Merge tag 'v3.10.13' into lsk/v3.10/topic/kvm
authorChristoffer Dall <christoffer.dall@linaro.org>
Thu, 2 Oct 2014 15:10:08 +0000 (17:10 +0200)
committerChristoffer Dall <christoffer.dall@linaro.org>
Thu, 2 Oct 2014 15:10:08 +0000 (17:10 +0200)
This is the 3.10.13 stable release

809 files changed:
Documentation/DocBook/media_api.tmpl
Documentation/hwmon/k10temp
Documentation/i2c/busses/i2c-piix4
Documentation/parisc/registers
MAINTAINERS
Makefile
arch/Kconfig
arch/arc/include/asm/ptrace.h
arch/arc/include/asm/syscall.h
arch/arc/kernel/entry.S
arch/arc/lib/strchr-700.S
arch/arm/Kconfig
arch/arm/boot/compressed/atags_to_fdt.c
arch/arm/boot/dts/at91rm9200.dtsi
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9n12.dtsi
arch/arm/boot/dts/at91sam9n12ek.dts
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/imx23.dtsi
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/imx6dl.dtsi
arch/arm/boot/dts/imx6q.dtsi
arch/arm/boot/dts/sama5d3.dtsi
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/boot/dts/sun5i-a13.dtsi
arch/arm/include/asm/a.out-core.h [deleted file]
arch/arm/include/asm/elf.h
arch/arm/include/asm/kvm_asm.h
arch/arm/include/asm/mmu.h
arch/arm/include/asm/mmu_context.h
arch/arm/include/asm/page.h
arch/arm/include/asm/processor.h
arch/arm/include/asm/thread_info.h
arch/arm/include/asm/tlb.h
arch/arm/include/uapi/asm/Kbuild
arch/arm/include/uapi/asm/a.out.h [deleted file]
arch/arm/kernel/entry-armv.S
arch/arm/kernel/fiq.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/process.c
arch/arm/kernel/signal.c
arch/arm/kernel/signal.h [deleted file]
arch/arm/kernel/smp_tlb.c
arch/arm/kernel/smp_twd.c
arch/arm/kernel/traps.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/kvm/coproc.c
arch/arm/kvm/coproc.h
arch/arm/kvm/coproc_a15.c
arch/arm/kvm/interrupts.S
arch/arm/kvm/interrupts_head.S
arch/arm/mach-davinci/board-dm355-leopard.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/board-neuros-osd2.c
arch/arm/mach-footbridge/dc21285.c
arch/arm/mach-s3c24xx/clock-s3c2410.c
arch/arm/mach-s3c24xx/clock-s3c2440.c
arch/arm/mach-shmobile/setup-emev2.c
arch/arm/mach-shmobile/setup-r8a73a4.c
arch/arm/mach-versatile/include/mach/platform.h
arch/arm/mach-versatile/pci.c
arch/arm/mm/Kconfig
arch/arm/mm/context.c
arch/arm/mm/init.c
arch/arm/mm/mmu.c
arch/arm/mm/proc-v7-2level.S
arch/arm/mm/proc-v7-3level.S
arch/arm/mm/proc-v7.S
arch/arm/plat-samsung/include/plat/clock.h
arch/arm/xen/enlighten.c
arch/arm64/include/asm/tlb.h
arch/c6x/mm/init.c
arch/ia64/include/asm/tlb.h
arch/m68k/emu/natfeat.c
arch/m68k/include/asm/div64.h
arch/microblaze/Kconfig
arch/mips/Kconfig
arch/mips/ath79/clock.c
arch/mips/cavium-octeon/setup.c
arch/mips/include/asm/io.h
arch/parisc/include/asm/parisc-device.h
arch/parisc/include/asm/special_insns.h
arch/parisc/include/asm/tlbflush.h
arch/parisc/kernel/cache.c
arch/parisc/kernel/inventory.c
arch/parisc/lib/memcpy.c
arch/powerpc/Kconfig
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/include/asm/module.h
arch/powerpc/include/asm/page.h
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/smp.h
arch/powerpc/include/asm/switch_to.h
arch/powerpc/kernel/align.c
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/hw_breakpoint.c
arch/powerpc/kernel/lparcfg.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/tm.S
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/vmlinux.lds.S
arch/powerpc/kvm/book3s_xics.c
arch/powerpc/mm/numa.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/perf/power8-pmu.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/pseries/setup.c
arch/s390/Kconfig
arch/s390/include/asm/bitops.h
arch/s390/include/asm/tlb.h
arch/s390/kernel/setup.c
arch/s390/kvm/kvm-s390.c
arch/s390/mm/init.c
arch/s390/oprofile/init.c
arch/sh/include/asm/tlb.h
arch/sparc/kernel/asm-offsets.c
arch/sparc/mm/hypersparc.S
arch/sparc/mm/swift.S
arch/sparc/mm/tsunami.S
arch/sparc/mm/viking.S
arch/um/include/asm/tlb.h
arch/um/include/shared/os.h
arch/um/kernel/Makefile
arch/um/kernel/maccess.c [new file with mode: 0644]
arch/um/os-Linux/process.c
arch/x86/boot/compressed/eboot.c
arch/x86/ia32/ia32_signal.c
arch/x86/include/asm/bootparam_utils.h
arch/x86/include/asm/checksum_32.h
arch/x86/include/asm/mce.h
arch/x86/include/asm/mmu_context.h
arch/x86/include/asm/xor_avx.h
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/amd_nb.c
arch/x86/kernel/cpu/mtrr/generic.c
arch/x86/kernel/cpu/mtrr/main.c
arch/x86/kernel/cpu/perf_event_intel_uncore.c
arch/x86/kernel/early-quirks.c
arch/x86/kernel/head_64.S
arch/x86/kernel/i387.c
arch/x86/kernel/signal.c
arch/x86/kernel/sys_x86_64.c
arch/x86/kvm/vmx.c
arch/x86/lib/csum-wrappers_64.c
arch/x86/mm/init.c
arch/x86/mm/mmap.c
arch/x86/xen/setup.c
arch/x86/xen/smp.c
arch/x86/xen/time.c
arch/xtensa/kernel/head.S
arch/xtensa/kernel/setup.c
block/cfq-iosched.c
block/deadline-iosched.c
block/elevator.c
block/genhd.c
block/noop-iosched.c
crypto/algapi.c
crypto/api.c
drivers/acpi/Makefile
drivers/acpi/acpi_cmos_rtc.c [new file with mode: 0644]
drivers/acpi/acpi_lpss.c
drivers/acpi/acpi_memhotplug.c
drivers/acpi/acpica/hwxfsleep.c
drivers/acpi/battery.c
drivers/acpi/device_pm.c
drivers/acpi/ec.c
drivers/acpi/glue.c
drivers/acpi/internal.h
drivers/acpi/proc.c
drivers/acpi/scan.c
drivers/acpi/video.c
drivers/ata/Kconfig
drivers/ata/ahci.c
drivers/ata/ata_piix.c
drivers/ata/libahci.c
drivers/ata/libata-pmp.c
drivers/ata/libata-zpodd.c
drivers/ata/sata_fsl.c
drivers/ata/sata_highbank.c
drivers/ata/sata_inic162x.c
drivers/base/memory.c
drivers/base/regmap/regcache-rbtree.c
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap.c
drivers/block/nbd.c
drivers/block/rbd.c
drivers/block/xen-blkback/blkback.c
drivers/block/xen-blkfront.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/cdrom/cdrom.c
drivers/char/agp/parisc-agp.c
drivers/char/hw_random/bcm2835-rng.c
drivers/char/virtio_console.c
drivers/clk/clk-wm831x.c
drivers/clocksource/dw_apb_timer_of.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_conservative.c
drivers/cpufreq/cpufreq_governor.c
drivers/cpufreq/cpufreq_governor.h
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/loongson2_cpufreq.c
drivers/cpuidle/coupled.c
drivers/cpuidle/governors/menu.c
drivers/crypto/caam/caamhash.c
drivers/dma/pl330.c
drivers/edac/amd64_edac.c
drivers/edac/edac_mc.c
drivers/edac/edac_mc_sysfs.c
drivers/edac/i5100_edac.c
drivers/firewire/core-cdev.c
drivers/firewire/ohci.c
drivers/gpu/drm/ast/ast_ttm.c
drivers/gpu/drm/cirrus/cirrus_ttm.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/mgag200/mgag200_drv.h
drivers/gpu/drm/mgag200/mgag200_main.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/mgag200/mgag200_ttm.c
drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/include/subdev/mc.h
drivers/gpu/drm/nouveau/core/subdev/mc/base.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/vm/base.c
drivers/gpu/drm/nouveau/nv17_fence.c
drivers/gpu/drm/nouveau/nv50_fence.c
drivers/gpu/drm/radeon/atom.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_object.h
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/radeon_sa.c
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
drivers/hid/hid-apple.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-ntrig.c
drivers/hid/hid-picolcd_cir.c
drivers/hid/hid-picolcd_core.c
drivers/hid/hid-picolcd_fb.c
drivers/hid/hid-pl.c
drivers/hid/hid-sensor-hub.c
drivers/hid/hid-speedlink.c
drivers/hid/hidraw.c
drivers/hid/usbhid/hid-quirks.c
drivers/hv/hv_balloon.c
drivers/hv/ring_buffer.c
drivers/hv/vmbus_drv.c
drivers/hwmon/Kconfig
drivers/hwmon/adt7470.c
drivers/hwmon/k10temp.c
drivers/hwmon/max6697.c
drivers/hwmon/nct6775.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-piix4.c
drivers/iio/inkern.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/infiniband/ulp/isert/ib_isert.h
drivers/input/mouse/bcm5974.c
drivers/iommu/amd_iommu.c
drivers/iommu/intel-iommu.c
drivers/leds/leds-wm831x-status.c
drivers/macintosh/windfarm_rm31.c
drivers/md/bcache/bcache.h
drivers/md/bcache/btree.c
drivers/md/bcache/closure.c
drivers/md/bcache/io.c
drivers/md/bcache/journal.c
drivers/md/bcache/request.c
drivers/md/bcache/super.c
drivers/md/dm-ioctl.c
drivers/md/dm-mpath.c
drivers/md/dm-verity.c
drivers/md/dm.c
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/md/raid5.h
drivers/media/common/siano/smsdvb-main.c
drivers/media/dvb-core/dmxdev.c
drivers/media/dvb-frontends/mb86a20s.c
drivers/media/pci/saa7134/saa7134-alsa.c
drivers/media/platform/coda.c
drivers/media/platform/exynos-gsc/gsc-core.c
drivers/media/platform/exynos-gsc/gsc-core.h
drivers/media/platform/exynos-gsc/gsc-m2m.c
drivers/media/platform/exynos4-is/media-dev.c
drivers/media/platform/s5p-g2d/g2d.c
drivers/media/usb/em28xx/em28xx-i2c.c
drivers/media/usb/hdpvr/hdpvr-core.c
drivers/misc/hpilo.c
drivers/misc/mei/hw-me.c
drivers/misc/mei/init.c
drivers/mmc/host/tmio_mmc_dma.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/nand_base.c
drivers/mtd/ubi/wl.c
drivers/net/arcnet/arcnet.c
drivers/net/bonding/bond_main.c
drivers/net/can/usb/peak_usb/pcan_usb.c
drivers/net/dummy.c
drivers/net/ethernet/atheros/alx/main.c
drivers/net/ethernet/atheros/atl1c/atl1c.h
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/atheros/atl1e/atl1e_main.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/sfc/filter.c
drivers/net/ethernet/sfc/rx.c
drivers/net/ethernet/sun/sunvnet.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/ifb.c
drivers/net/macvlan.c
drivers/net/macvtap.c
drivers/net/tun.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/cdc_mbim.c
drivers/net/usb/smsc75xx.c
drivers/net/virtio_net.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ar9003_phy.h
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/calib.c
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/ath/wil6210/debugfs.c
drivers/net/wireless/b43/Kconfig
drivers/net/wireless/brcm80211/brcmsmac/dma.c
drivers/net/wireless/hostap/hostap_ioctl.c
drivers/net/wireless/iwlegacy/4965-mac.c
drivers/net/wireless/iwlegacy/common.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/dvm/main.c
drivers/net/wireless/iwlwifi/iwl-7000.c
drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h
drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/scan.c
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/cfp.c
drivers/net/wireless/mwifiex/join.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/sdio.c
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2x00queue.c
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/rtlwifi/ps.c
drivers/net/wireless/rtlwifi/ps.h
drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
drivers/net/wireless/rtlwifi/rtl8723ae/sw.c
drivers/net/wireless/rtlwifi/usb.c
drivers/net/wireless/zd1201.c
drivers/net/xen-netfront.c
drivers/of/address.c
drivers/of/base.c
drivers/of/fdt.c
drivers/parisc/iosapic.c
drivers/parisc/lba_pci.c
drivers/pci/hotplug/pciehp_pci.c
drivers/pci/iov.c
drivers/pci/pci-acpi.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/setup-bus.c
drivers/pci/xen-pcifront.c
drivers/pcmcia/at91_cf.c
drivers/pinctrl/pinctrl-at91.c
drivers/platform/olpc/olpc-ec.c
drivers/power/charger-manager.c
drivers/rapidio/switches/idt_gen2.c
drivers/rtc/rtc-max77686.c
drivers/rtc/rtc-rv3029c2.c
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_scsi.c
drivers/scsi/Kconfig
drivers/scsi/aacraid/src.c
drivers/scsi/isci/task.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/mpt2sas/mpt2sas_base.c
drivers/scsi/mpt2sas/mpt2sas_base.h
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/mpt3sas/Makefile
drivers/scsi/mpt3sas/mpt3sas_scsih.c
drivers/scsi/nsp32.c
drivers/scsi/osd/osd_uld.c
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm80xx_hwi.c
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/scsi.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/scsi/virtio_scsi.c
drivers/spi/spi-davinci.c
drivers/staging/android/logger.c
drivers/staging/comedi/comedi_fops.c
drivers/staging/comedi/drivers.c
drivers/staging/comedi/drivers/dt282x.c
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/imx-drm/imx-drm-core.c
drivers/staging/line6/pcm.c
drivers/staging/zcache/zcache-main.c
drivers/staging/zram/zram_drv.c
drivers/staging/zram/zram_drv.h
drivers/staging/zram/zram_sysfs.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target.h
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_core.h
drivers/target/iscsi/iscsi_target_erl0.c
drivers/target/iscsi/iscsi_target_erl1.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_util.c
drivers/target/iscsi/iscsi_target_util.h
drivers/target/target_core_alua.c
drivers/target/target_core_pr.c
drivers/target/target_core_spc.c
drivers/tty/hvc/hvsi_lib.c
drivers/tty/serial/8250/8250_gsc.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/arc_uart.c
drivers/tty/serial/mxs-auart.c
drivers/tty/serial/pch_uart.c
drivers/tty/tty_io.c
drivers/tty/tty_port.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/config.c
drivers/usb/core/hub.c
drivers/usb/core/hub.h
drivers/usb/core/port.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/f_acm.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/udc-core.c
drivers/usb/gadget/uvc_queue.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-mxc.c
drivers/usb/host/ehci-omap.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/phy/phy-fsl-usb.h
drivers/usb/phy/phy-fsm-usb.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/keyspan.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb_wwan.c
drivers/usb/storage/unusual_devs.h
drivers/usb/wusbcore/wa-xfer.c
drivers/vhost/net.c
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_ring.c
drivers/xen/events.c
drivers/xen/evtchn.c
drivers/xen/grant-table.c
fs/bio.c
fs/block_dev.c
fs/btrfs/ctree.c
fs/btrfs/extent-tree.c
fs/btrfs/ioctl.c
fs/btrfs/scrub.c
fs/btrfs/send.c
fs/btrfs/tree-log.c
fs/btrfs/ulist.c
fs/ceph/ioctl.c
fs/ceph/xattr.c
fs/cifs/cifs_unicode.h
fs/cifs/cifsencrypt.c
fs/cifs/cifsglob.h
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/readdir.c
fs/cifs/sess.c
fs/cifs/smb2misc.c
fs/debugfs/inode.c
fs/exec.c
fs/ext3/namei.c
fs/ext4/balloc.c
fs/ext4/ext4_jbd2.c
fs/ext4/extents.c
fs/ext4/file.c
fs/ext4/ialloc.c
fs/ext4/inline.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/mballoc.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/ext4/super.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/hpfs/map.c
fs/hpfs/super.c
fs/isofs/inode.c
fs/jbd2/journal.c
fs/jbd2/transaction.c
fs/jfs/jfs_dtree.c
fs/lockd/clntlock.c
fs/lockd/clntproc.c
fs/lockd/svclock.c
fs/namespace.c
fs/nfs/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/vfs.c
fs/nilfs2/segbuf.c
fs/notify/fanotify/fanotify_user.c
fs/ocfs2/extent_map.c
fs/ocfs2/xattr.c
fs/proc/root.c
fs/proc/task_mmu.c
fs/reiserfs/procfs.c
fs/reiserfs/super.c
fs/super.c
fs/ubifs/super.c
include/acpi/acpi_bus.h
include/asm-generic/tlb.h
include/linux/ceph/decode.h
include/linux/cgroup.h
include/linux/compat.h
include/linux/cpu_cooling.h
include/linux/edac.h
include/linux/elevator.h
include/linux/firewire.h
include/linux/ftrace_event.h
include/linux/hid.h
include/linux/hugetlb.h
include/linux/if_vlan.h
include/linux/iio/iio.h
include/linux/ipv6.h
include/linux/mm_types.h
include/linux/nbd.h
include/linux/pci_ids.h
include/linux/rculist.h
include/linux/regmap.h
include/linux/signal.h
include/linux/sunrpc/sched.h
include/linux/syscalls.h
include/linux/tick.h
include/linux/usb/hcd.h
include/linux/user_namespace.h
include/linux/virtio.h
include/linux/wait.h
include/media/v4l2-ctrls.h
include/net/addrconf.h
include/net/genetlink.h
include/net/ip_tunnels.h
include/net/mac80211.h
include/net/ndisc.h
include/net/sch_generic.h
include/net/udp.h
include/target/iscsi/iscsi_transport.h
include/uapi/linux/firewire-cdev.h
include/uapi/linux/icmpv6.h
include/uapi/linux/if_pppox.h
include/uapi/linux/pkt_sched.h
ipc/msg.c
kernel/cgroup.c
kernel/cpuset.c
kernel/events/core.c
kernel/events/uprobes.c
kernel/fork.c
kernel/futex.c
kernel/hrtimer.c
kernel/irq/manage.c
kernel/module.c
kernel/pid.c
kernel/power/autosleep.c
kernel/power/qos.c
kernel/printk.c
kernel/sched/fair.c
kernel/time/tick-broadcast.c
kernel/time/tick-common.c
kernel/time/tick-sched.c
kernel/time/timer_list.c
kernel/timer.c
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_events.c
kernel/trace/trace_events_filter.c
kernel/trace/trace_irqsoff.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_syscalls.c
kernel/trace/trace_uprobe.c
kernel/user_namespace.c
kernel/workqueue.c
lib/Kconfig.debug
mm/huge_memory.c
mm/hugetlb.c
mm/memcontrol.c
mm/memory.c
mm/mempolicy.c
mm/mmap.c
mm/page_alloc.c
mm/slab.c
mm/slab.h
net/8021q/vlan_core.c
net/8021q/vlan_dev.c
net/9p/trans_common.c
net/bridge/br_fdb.c
net/bridge/br_multicast.c
net/bridge/br_netlink.c
net/bridge/br_vlan.c
net/ceph/auth_none.c
net/ceph/osd_client.c
net/ceph/osdmap.c
net/core/dev.c
net/core/flow_dissector.c
net/core/neighbour.c
net/core/rtnetlink.c
net/core/scm.c
net/core/sysctl_net_core.c
net/ipv4/devinet.c
net/ipv4/fib_trie.c
net/ipv4/ip_gre.c
net/ipv4/ip_input.c
net/ipv4/ip_tunnel.c
net/ipv4/ip_vti.c
net/ipv4/ipip.c
net/ipv4/raw.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_cubic.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv6/addrconf.c
net/ipv6/addrlabel.c
net/ipv6/icmp.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_output.c
net/ipv6/ip6mr.c
net/ipv6/mcast.c
net/ipv6/ndisc.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/key/af_key.c
net/l2tp/l2tp_ppp.c
net/mac80211/cfg.c
net/mac80211/ibss.c
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/pm.c
net/mac80211/rc80211_minstrel.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rx.c
net/netlink/genetlink.c
net/nfc/llcp.h
net/nfc/llcp_sock.c
net/packet/af_packet.c
net/sched/sch_api.c
net/sched/sch_atm.c
net/sched/sch_cbq.c
net/sched/sch_generic.c
net/sched/sch_htb.c
net/sched/sch_qfq.c
net/sunrpc/auth_gss/gss_rpc_upcall.c
net/sunrpc/auth_gss/gss_rpc_xdr.c
net/sunrpc/clnt.c
net/sunrpc/netns.h
net/sunrpc/rpcb_clnt.c
net/sunrpc/svcauth_unix.c
net/sunrpc/svcsock.c
net/sunrpc/xdr.c
net/sunrpc/xprtrdma/svc_rdma_marshal.c
net/tipc/socket.c
net/wireless/core.c
net/wireless/nl80211.c
net/x25/af_x25.c
sound/arm/pxa2xx-pcm-lib.c
sound/core/compress_offload.c
sound/core/seq/oss/seq_oss_init.c
sound/core/seq/oss/seq_oss_midi.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/pci/asihpi/asihpi.c
sound/pci/atiixp.c
sound/pci/atiixp_modem.c
sound/pci/hda/hda_auto_parser.c
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_local.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/soc/atmel/atmel-pcm-dma.c
sound/soc/codecs/cs42l52.c
sound/soc/codecs/max98088.c
sound/soc/codecs/mc13783.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/sgtl5000.h
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8962.c
sound/soc/s6000/s6000-pcm.c
sound/soc/soc-dapm.c
sound/soc/tegra/tegra20_ac97.c
sound/soc/tegra/tegra20_spdif.c
sound/soc/tegra/tegra30_i2s.c
sound/usb/6fire/comm.c
sound/usb/6fire/comm.h
sound/usb/6fire/midi.c
sound/usb/6fire/midi.h
sound/usb/6fire/pcm.c
sound/usb/6fire/pcm.h
sound/usb/endpoint.c
sound/usb/misc/ua101.c
sound/usb/mixer.c
sound/usb/usx2y/usbusx2yaudio.c
tools/hv/hv_kvp_daemon.c
tools/perf/config/utilities.mak

index 6a8b7158697f9ae58b33e82d2f7becd772a6c4aa..9c92bb879b6dc7b1468e247ae0dbb026ad519f2f 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-       "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+       "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
 <!ENTITY % media-entities SYSTEM "./media-entities.tmpl"> %media-entities;
 <!ENTITY media-indices SYSTEM "./media-indices.tmpl">
 
index 90956b6180254915e9ff17bb968729c20e043369..4dfdc8f836334e97881a6a92373d7702ad2111a8 100644 (file)
@@ -12,6 +12,7 @@ Supported chips:
 * AMD Family 12h processors: "Llano" (E2/A4/A6/A8-Series)
 * AMD Family 14h processors: "Brazos" (C/E/G/Z-Series)
 * AMD Family 15h processors: "Bulldozer" (FX-Series), "Trinity"
+* AMD Family 16h processors: "Kabini"
 
   Prefix: 'k10temp'
   Addresses scanned: PCI space
index 1e6634f54c5019b45b6d663b6fd7cd7db9b23530..a370b2047cf3025b5a0c318af15c670a76bc41e3 100644 (file)
@@ -13,7 +13,7 @@ Supported adapters:
   * AMD SP5100 (SB700 derivative found on some server mainboards)
     Datasheet: Publicly available at the AMD website
     http://support.amd.com/us/Embedded_TechDocs/44413.pdf
-  * AMD Hudson-2
+  * AMD Hudson-2, CZ
     Datasheet: Not publicly available
   * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge
     Datasheet: Publicly available at the SMSC website http://www.smsc.com
index dd3caddd1ad9859914defe892c359e864690acac..10c7d1730f5d8ccd0e7ace717627a2b1efe837b4 100644 (file)
@@ -77,6 +77,14 @@ PSW default E value          0
 Shadow Registers               used by interruption handler code
 TOC enable bit                 1
 
+=========================================================================
+
+The PA-RISC architecture defines 7 registers as "shadow registers".
+Those are used in RETURN FROM INTERRUPTION AND RESTORE instruction to reduce
+the state save and restore time by eliminating the need for general register
+(GR) saves and restores in interruption handlers.
+Shadow registers are the GRs 1, 8, 9, 16, 17, 24, and 25.
+
 =========================================================================
 Register usage notes, originally from John Marvin, with some additional
 notes from Randolph Chung.
index ad7e322ad17b8bb985c73617407792fdc92eb33d..48c748080c96ee5bb52e26d6a2b4bd2ab001c62d 100644 (file)
@@ -7667,6 +7667,7 @@ STABLE BRANCH
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     stable@vger.kernel.org
 S:     Supported
+F:     Documentation/stable_kernel_rules.txt
 
 STAGING SUBSYSTEM
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
index e5e3ba0851913723cc205987f0840c9e20c5a877..25d38b79b3e0be909f0a45643addd4f4ecadde19 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 3
 PATCHLEVEL = 10
-SUBLEVEL = 0
+SUBLEVEL = 13
 EXTRAVERSION =
-NAME = Unicycling Gorilla
+NAME = TOSSUG Baby Fish
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index a4429bcd609ec8a3761e064d200d0646c3cae5f1..00e3702ec79b2f8affb37248f29a06a5807ecafd 100644 (file)
@@ -404,6 +404,12 @@ config CLONE_BACKWARDS2
        help
          Architecture has the first two arguments of clone(2) swapped.
 
+config CLONE_BACKWARDS3
+       bool
+       help
+         Architecture has tls passed as the 3rd argument of clone(2),
+         not the 5th one.
+
 config ODD_RT_SIGACTION
        bool
        help
index 6179de7e07c21ca4875017adc1107c0e7b0b46c4..2046a89a57cf018b481c68651232e675b58ff9f1 100644 (file)
@@ -52,12 +52,14 @@ struct pt_regs {
 
        /*to distinguish bet excp, syscall, irq */
        union {
+               struct {
 #ifdef CONFIG_CPU_BIG_ENDIAN
                /* so that assembly code is same for LE/BE */
                unsigned long orig_r8:16, event:16;
 #else
                unsigned long event:16, orig_r8:16;
 #endif
+               };
                long orig_r8_word;
        };
 };
index 33ab3048e9b20a6447475ec417b3fc10a91a309a..29de098043064a20112dd7ffd02f86059261ae44 100644 (file)
@@ -18,7 +18,7 @@ static inline long
 syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 {
        if (user_mode(regs) && in_syscall(regs))
-               return regs->orig_r8;
+               return regs->r8;
        else
                return -1;
 }
@@ -26,8 +26,7 @@ syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 static inline void
 syscall_rollback(struct task_struct *task, struct pt_regs *regs)
 {
-       /* XXX: I can't fathom how pt_regs->r8 will be clobbered ? */
-       regs->r8 = regs->orig_r8;
+       regs->r0 = regs->orig_r0;
 }
 
 static inline long
index 0c6d664d4a8379512c32c7b52d8fbd0d321cf70e..6dbe359c760dde2625c1cef0b35f8db460f8bdeb 100644 (file)
@@ -498,7 +498,7 @@ tracesys_exit:
 trap_with_param:
 
        ; stop_pc info by gdb needs this info
-       stw orig_r8_IS_BRKPT, [sp, PT_orig_r8]
+       st  orig_r8_IS_BRKPT, [sp, PT_orig_r8]
 
        mov r0, r12
        lr  r1, [efa]
@@ -723,7 +723,7 @@ not_exception:
        ; things to what they were, before returning from L2 context
        ;----------------------------------------------------------------
 
-       ldw  r9, [sp, PT_orig_r8]      ; get orig_r8 to make sure it is
+       ld   r9, [sp, PT_orig_r8]      ; get orig_r8 to make sure it is
        brne r9, orig_r8_IS_IRQ2, 149f ; infact a L2 ISR ret path
 
        ld r9, [sp, PT_status32]       ; get statu32_l2 (saved in pt_regs)
index 99c10475d477c73957353e5e9df751718289b5ac..9c548c7cf0014e1ce9c0823026039d60365b6192 100644 (file)
@@ -39,9 +39,18 @@ ARC_ENTRY strchr
        ld.a    r2,[r0,4]
        sub     r12,r6,r7
        bic     r12,r12,r6
+#ifdef __LITTLE_ENDIAN__
        and     r7,r12,r4
        breq    r7,0,.Loop ; For speed, we want this branch to be unaligned.
        b       .Lfound_char ; Likewise this one.
+#else
+       and     r12,r12,r4
+       breq    r12,0,.Loop ; For speed, we want this branch to be unaligned.
+       lsr_s   r12,r12,7
+       bic     r2,r7,r6
+       b.d     .Lfound_char_b
+       and_s   r2,r2,r12
+#endif
 ; /* We require this code address to be unaligned for speed...  */
 .Laligned:
        ld_s    r2,[r0]
@@ -95,6 +104,7 @@ ARC_ENTRY strchr
        lsr     r7,r7,7
 
        bic     r2,r7,r6
+.Lfound_char_b:
        norm    r2,r2
        sub_s   r0,r0,4
        asr_s   r2,r2,3
index 136f263ed47b79d010cf4ca06e7b1e2a07e4fd73..18a9f5ef643ad2253f6e7863c2a24f049663bc4a 100644 (file)
@@ -19,7 +19,6 @@ config ARM
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
        select HARDIRQS_SW_RESEND
-       select HAVE_AOUT
        select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
        select HAVE_ARCH_KGDB
        select HAVE_ARCH_SECCOMP_FILTER
@@ -213,7 +212,8 @@ config VECTORS_BASE
        default DRAM_BASE if REMAP_VECTORS_TO_RAM
        default 0x00000000
        help
-         The base address of exception vectors.
+         The base address of exception vectors.  This must be two pages
+         in size.
 
 config ARM_PATCH_PHYS_VIRT
        bool "Patch physical to virtual translations at runtime" if EMBEDDED
index aabc02a68482a912545ab67221070ad2ccf51e11..d1153c8a765a05c23d62e7a25d9197186902a3ea 100644 (file)
@@ -53,6 +53,17 @@ static const void *getprop(const void *fdt, const char *node_path,
        return fdt_getprop(fdt, offset, property, len);
 }
 
+static uint32_t get_cell_size(const void *fdt)
+{
+       int len;
+       uint32_t cell_size = 1;
+       const uint32_t *size_len =  getprop(fdt, "/", "#size-cells", &len);
+
+       if (size_len)
+               cell_size = fdt32_to_cpu(*size_len);
+       return cell_size;
+}
+
 static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline)
 {
        char cmdline[COMMAND_LINE_SIZE];
@@ -95,9 +106,11 @@ static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline)
 int atags_to_fdt(void *atag_list, void *fdt, int total_space)
 {
        struct tag *atag = atag_list;
-       uint32_t mem_reg_property[2 * NR_BANKS];
+       /* In the case of 64 bits memory size, need to reserve 2 cells for
+        * address and size for each bank */
+       uint32_t mem_reg_property[2 * 2 * NR_BANKS];
        int memcount = 0;
-       int ret;
+       int ret, memsize;
 
        /* make sure we've got an aligned pointer */
        if ((u32)atag_list & 0x3)
@@ -137,8 +150,25 @@ int atags_to_fdt(void *atag_list, void *fdt, int total_space)
                                continue;
                        if (!atag->u.mem.size)
                                continue;
-                       mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start);
-                       mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size);
+                       memsize = get_cell_size(fdt);
+
+                       if (memsize == 2) {
+                               /* if memsize is 2, that means that
+                                * each data needs 2 cells of 32 bits,
+                                * so the data are 64 bits */
+                               uint64_t *mem_reg_prop64 =
+                                       (uint64_t *)mem_reg_property;
+                               mem_reg_prop64[memcount++] =
+                                       cpu_to_fdt64(atag->u.mem.start);
+                               mem_reg_prop64[memcount++] =
+                                       cpu_to_fdt64(atag->u.mem.size);
+                       } else {
+                               mem_reg_property[memcount++] =
+                                       cpu_to_fdt32(atag->u.mem.start);
+                               mem_reg_property[memcount++] =
+                                       cpu_to_fdt32(atag->u.mem.size);
+                       }
+
                } else if (atag->hdr.tag == ATAG_INITRD2) {
                        uint32_t initrd_start, initrd_size;
                        initrd_start = atag->u.initrd.start;
@@ -150,8 +180,10 @@ int atags_to_fdt(void *atag_list, void *fdt, int total_space)
                }
        }
 
-       if (memcount)
-               setprop(fdt, "/memory", "reg", mem_reg_property, 4*memcount);
+       if (memcount) {
+               setprop(fdt, "/memory", "reg", mem_reg_property,
+                       4 * memcount * memsize);
+       }
 
        return fdt_pack(fdt);
 }
index 5d3ed5aafc699b071f6a1044ed9cb4948d6ee726..0af879a4eafacc035e9c52ab3bfd34d038ddb382 100644 (file)
                ssc2 = &ssc2;
        };
        cpus {
-               cpu@0 {
+               #address-cells = <0>;
+               #size-cells = <0>;
+
+               cpu {
                        compatible = "arm,arm920t";
+                       device_type = "cpu";
                };
        };
 
index 84c4bef2d7268760a6d927bd8ed2fdf7d547ea59..0dbdb846f90ac518235f1cda74d797eec983d92a 100644 (file)
                ssc0 = &ssc0;
        };
        cpus {
-               cpu@0 {
-                       compatible = "arm,arm926ejs";
+               #address-cells = <0>;
+               #size-cells = <0>;
+
+               cpu {
+                       compatible = "arm,arm926ej-s";
+                       device_type = "cpu";
                };
        };
 
                                        };
                                };
 
+                               i2c_gpio0 {
+                                       pinctrl_i2c_gpio0: i2c_gpio0-0 {
+                                               atmel,pins =
+                                                       <0 23 0x0 0x3   /* PA23 gpio I2C_SDA pin */
+                                                        0 24 0x0 0x3>; /* PA24 gpio I2C_SCL pin */
+                                       };
+                               };
+
                                pioA: gpio@fffff400 {
                                        compatible = "atmel,at91rm9200-gpio";
                                        reg = <0xfffff400 0x200>;
                i2c-gpio,delay-us = <2>;        /* ~100 kHz */
                #address-cells = <1>;
                #size-cells = <0>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_i2c_gpio0>;
                status = "disabled";
        };
 };
index 94b58ab2cc08be9c841ff1cdd3e4553ca8ec40a4..fcd38f89904e3dd9b4d71a2c7903a7ca61fb8ad3 100644 (file)
                ssc1 = &ssc1;
        };
        cpus {
-               cpu@0 {
-                       compatible = "arm,arm926ejs";
+               #address-cells = <0>;
+               #size-cells = <0>;
+
+               cpu {
+                       compatible = "arm,arm926ej-s";
+                       device_type = "cpu";
                };
        };
 
index bf18a735c37d8b879a603e711dd25bde7e2980ac..479a0622cdb8fa0c3994f5aa26982b9fc022f47b 100644 (file)
                ssc1 = &ssc1;
        };
        cpus {
-               cpu@0 {
-                       compatible = "arm,arm926ejs";
+               #address-cells = <0>;
+               #size-cells = <0>;
+
+               cpu {
+                       compatible = "arm,arm926ej-s";
+                       device_type = "cpu";
                };
        };
 
index 8d25f889928eccd3c7a3440dd9522e4f1d34e37c..a92ec78349a2d256f6b64a1bfcdf2957b6652602 100644 (file)
                ssc0 = &ssc0;
        };
        cpus {
-               cpu@0 {
-                       compatible = "arm,arm926ejs";
+               #address-cells = <0>;
+               #size-cells = <0>;
+
+               cpu {
+                       compatible = "arm,arm926ej-s";
+                       device_type = "cpu";
                };
        };
 
index d30e48bd1e9d0f6a4c15d585c1d574092c475ce4..28ba79893877c9a00012a6579c7a2ff4e0c5b292 100644 (file)
        compatible = "atmel,at91sam9n12ek", "atmel,at91sam9n12", "atmel,at91sam9";
 
        chosen {
-               bootargs = "mem=128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
+               bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
        };
 
        memory {
-               reg = <0x20000000 0x10000000>;
+               reg = <0x20000000 0x8000000>;
        };
 
        clocks {
index 1145ac330fb7c091647ce7425179402260d7de95..2b2b6923d16b66df30e9a1722664196e9e3029bb 100644 (file)
                ssc0 = &ssc0;
        };
        cpus {
-               cpu@0 {
-                       compatible = "arm,arm926ejs";
+               #address-cells = <0>;
+               #size-cells = <0>;
+
+               cpu {
+                       compatible = "arm,arm926ej-s";
+                       device_type = "cpu";
                };
        };
 
                        };
 
                        rtc@fffffeb0 {
-                               compatible = "atmel,at91rm9200-rtc";
+                               compatible = "atmel,at91sam9x5-rtc";
                                reg = <0xfffffeb0 0x40>;
                                interrupts = <1 4 7>;
                                status = "disabled";
index 73fd7d0887b52f4505d908902fd99aaf0fe941c8..587ceef81e45a5eeb6cb6da0ff5f643f29892669 100644 (file)
        };
 
        cpus {
-               cpu@0 {
-                       compatible = "arm,arm926ejs";
+               #address-cells = <0>;
+               #size-cells = <0>;
+
+               cpu {
+                       compatible = "arm,arm926ej-s";
+                       device_type = "cpu";
                };
        };
 
index 600f7cb51f3e58ae78f88649f3b52b12c170e5d1..4c10a1968c0e3a6d8d4331c7f26af13d0f6a4f97 100644 (file)
        };
 
        cpus {
-               cpu@0 {
-                       compatible = "arm,arm926ejs";
+               #address-cells = <0>;
+               #size-cells = <0>;
+
+               cpu {
+                       compatible = "arm,arm926ej-s";
+                       device_type = "cpu";
                };
        };
 
index 5bcdf3a90bb39f36493409f28da7b98fef1259f4..62dc78126795fbc03d3ad339fedc2406a2edc624 100644 (file)
 
                cpu@0 {
                        compatible = "arm,cortex-a9";
+                       device_type = "cpu";
                        reg = <0>;
                        next-level-cache = <&L2>;
                };
 
                cpu@1 {
                        compatible = "arm,cortex-a9";
+                       device_type = "cpu";
                        reg = <1>;
                        next-level-cache = <&L2>;
                };
index 21e675848bd1e75a0568af6fae28f0264da05887..dc54a72a3bcdaeae9cc88cfd3c6b2feb8e1dbe5c 100644 (file)
@@ -18,6 +18,7 @@
 
                cpu@0 {
                        compatible = "arm,cortex-a9";
+                       device_type = "cpu";
                        reg = <0>;
                        next-level-cache = <&L2>;
                        operating-points = <
 
                cpu@1 {
                        compatible = "arm,cortex-a9";
+                       device_type = "cpu";
                        reg = <1>;
                        next-level-cache = <&L2>;
                };
 
                cpu@2 {
                        compatible = "arm,cortex-a9";
+                       device_type = "cpu";
                        reg = <2>;
                        next-level-cache = <&L2>;
                };
 
                cpu@3 {
                        compatible = "arm,cortex-a9";
+                       device_type = "cpu";
                        reg = <3>;
                        next-level-cache = <&L2>;
                };
index 5000e0d428496d8105f6157f4ba54b4603796657..642775d7ca673de429d7aa2d713387ae96937a90 100644 (file)
                ssc1 = &ssc1;
        };
        cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
                cpu@0 {
+                       device_type = "cpu";
                        compatible = "arm,cortex-a5";
+                       reg = <0x0>;
                };
        };
 
index e7ef619a70a2531440400086cdac4ee6ae3b71eb..06ef8b625dba03328870441b3923d18a86fece01 100644 (file)
        interrupt-parent = <&intc>;
 
        cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
                cpu@0 {
+                       device_type = "cpu";
                        compatible = "arm,cortex-a8";
+                       reg = <0x0>;
                };
        };
 
index 31fa38f8cc9851788e1aea09f1c5853eb397ae7e..d2852547b572f02d05f7481d96aca3cbe69189fc 100644 (file)
        interrupt-parent = <&intc>;
 
        cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
                cpu@0 {
+                       device_type = "cpu";
                        compatible = "arm,cortex-a8";
+                       reg = <0x0>;
                };
        };
 
diff --git a/arch/arm/include/asm/a.out-core.h b/arch/arm/include/asm/a.out-core.h
deleted file mode 100644 (file)
index 92f10cb..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/* a.out coredump register dumper
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#ifndef _ASM_A_OUT_CORE_H
-#define _ASM_A_OUT_CORE_H
-
-#ifdef __KERNEL__
-
-#include <linux/user.h>
-#include <linux/elfcore.h>
-
-/*
- * fill in the user structure for an a.out core dump
- */
-static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
-{
-       struct task_struct *tsk = current;
-
-       dump->magic = CMAGIC;
-       dump->start_code = tsk->mm->start_code;
-       dump->start_stack = regs->ARM_sp & ~(PAGE_SIZE - 1);
-
-       dump->u_tsize = (tsk->mm->end_code - tsk->mm->start_code) >> PAGE_SHIFT;
-       dump->u_dsize = (tsk->mm->brk - tsk->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       dump->u_ssize = 0;
-
-       memset(dump->u_debugreg, 0, sizeof(dump->u_debugreg));
-
-       if (dump->start_stack < 0x04000000)
-               dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT;
-
-       dump->regs = *regs;
-       dump->u_fpvalid = dump_fpu (regs, &dump->u_fp);
-}
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_A_OUT_CORE_H */
index e110a672e160f908e2f04d83bc2df5960e5e7aad..f4b46d39b9cfb12756050a992262367ce575f90b 100644 (file)
@@ -128,4 +128,10 @@ struct mm_struct;
 extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
 
+#ifdef CONFIG_MMU
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+int arch_setup_additional_pages(struct linux_binprm *, int);
+#endif
+
 #endif
index 18d50322a9e2fd147c361717097dba4d1a2ba35d..4bb08e3e52bc0160d5951646aa356b59e88d12d6 100644 (file)
 #define c5_AIFSR       15      /* Auxilary Instrunction Fault Status R */
 #define c6_DFAR                16      /* Data Fault Address Register */
 #define c6_IFAR                17      /* Instruction Fault Address Register */
-#define c9_L2CTLR      18      /* Cortex A15 L2 Control Register */
-#define c10_PRRR       19      /* Primary Region Remap Register */
-#define c10_NMRR       20      /* Normal Memory Remap Register */
-#define c12_VBAR       21      /* Vector Base Address Register */
-#define c13_CID                22      /* Context ID Register */
-#define c13_TID_URW    23      /* Thread ID, User R/W */
-#define c13_TID_URO    24      /* Thread ID, User R/O */
-#define c13_TID_PRIV   25      /* Thread ID, Privileged */
-#define c14_CNTKCTL    26      /* Timer Control Register (PL1) */
-#define NR_CP15_REGS   27      /* Number of regs (incl. invalid) */
+#define c7_PAR         18      /* Physical Address Register */
+#define c7_PAR_high    19      /* PAR top 32 bits */
+#define c9_L2CTLR      20      /* Cortex A15 L2 Control Register */
+#define c10_PRRR       21      /* Primary Region Remap Register */
+#define c10_NMRR       22      /* Normal Memory Remap Register */
+#define c12_VBAR       23      /* Vector Base Address Register */
+#define c13_CID                24      /* Context ID Register */
+#define c13_TID_URW    25      /* Thread ID, User R/W */
+#define c13_TID_URO    26      /* Thread ID, User R/O */
+#define c13_TID_PRIV   27      /* Thread ID, Privileged */
+#define c14_CNTKCTL    28      /* Timer Control Register (PL1) */
+#define NR_CP15_REGS   29      /* Number of regs (incl. invalid) */
 
 #define ARM_EXCEPTION_RESET      0
 #define ARM_EXCEPTION_UNDEFINED   1
index e3d55547e75592a9eb98fa1704ee8df9e872c2c5..6f18da09668b5f324ad8c32e6fd6058e5b837e2a 100644 (file)
@@ -6,8 +6,11 @@
 typedef struct {
 #ifdef CONFIG_CPU_HAS_ASID
        atomic64_t      id;
+#else
+       int             switch_pending;
 #endif
        unsigned int    vmalloc_seq;
+       unsigned long   sigpage;
 } mm_context_t;
 
 #ifdef CONFIG_CPU_HAS_ASID
index a7b85e0d0cc154a90a2efadca763cc60d95e82d8..e0b10f19d679d5915de6a49a23e9fc141e68d527 100644 (file)
@@ -27,7 +27,15 @@ void __check_vmalloc_seq(struct mm_struct *mm);
 void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk);
 #define init_new_context(tsk,mm)       ({ atomic64_set(&mm->context.id, 0); 0; })
 
-DECLARE_PER_CPU(atomic64_t, active_asids);
+#ifdef CONFIG_ARM_ERRATA_798181
+void a15_erratum_get_cpumask(int this_cpu, struct mm_struct *mm,
+                            cpumask_t *mask);
+#else  /* !CONFIG_ARM_ERRATA_798181 */
+static inline void a15_erratum_get_cpumask(int this_cpu, struct mm_struct *mm,
+                                          cpumask_t *mask)
+{
+}
+#endif /* CONFIG_ARM_ERRATA_798181 */
 
 #else  /* !CONFIG_CPU_HAS_ASID */
 
@@ -47,7 +55,7 @@ static inline void check_and_switch_context(struct mm_struct *mm,
                 * on non-ASID CPUs, the old mm will remain valid until the
                 * finish_arch_post_lock_switch() call.
                 */
-               set_ti_thread_flag(task_thread_info(tsk), TIF_SWITCH_MM);
+               mm->context.switch_pending = 1;
        else
                cpu_switch_mm(mm->pgd, mm);
 }
@@ -56,9 +64,21 @@ static inline void check_and_switch_context(struct mm_struct *mm,
        finish_arch_post_lock_switch
 static inline void finish_arch_post_lock_switch(void)
 {
-       if (test_and_clear_thread_flag(TIF_SWITCH_MM)) {
-               struct mm_struct *mm = current->mm;
-               cpu_switch_mm(mm->pgd, mm);
+       struct mm_struct *mm = current->mm;
+
+       if (mm && mm->context.switch_pending) {
+               /*
+                * Preemption must be disabled during cpu_switch_mm() as we
+                * have some stateful cache flush implementations. Check
+                * switch_pending again in case we were preempted and the
+                * switch to this mm was already done.
+                */
+               preempt_disable();
+               if (mm->context.switch_pending) {
+                       mm->context.switch_pending = 0;
+                       cpu_switch_mm(mm->pgd, mm);
+               }
+               preempt_enable_no_resched();
        }
 }
 
index 812a4944e78343469a2216327a746f37ce01b98c..cbdc7a21f869fcce44573119edb99c26d710c1a9 100644 (file)
@@ -142,7 +142,9 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from,
 #define clear_page(page)       memset((void *)(page), 0, PAGE_SIZE)
 extern void copy_page(void *to, const void *from);
 
+#ifdef CONFIG_KUSER_HELPERS
 #define __HAVE_ARCH_GATE_AREA 1
+#endif
 
 #ifdef CONFIG_ARM_LPAE
 #include <asm/pgtable-3level-types.h>
index 06e7d509eaac218864cc9d089ce9e6f4177c22f9..413f3876341cd6fd2e7bc4b1c6a71873cadaa887 100644 (file)
@@ -54,7 +54,6 @@ struct thread_struct {
 
 #define start_thread(regs,pc,sp)                                       \
 ({                                                                     \
-       unsigned long *stack = (unsigned long *)sp;                     \
        memset(regs->uregs, 0, sizeof(regs->uregs));                    \
        if (current->personality & ADDR_LIMIT_32BIT)                    \
                regs->ARM_cpsr = USR_MODE;                              \
@@ -65,9 +64,6 @@ struct thread_struct {
        regs->ARM_cpsr |= PSR_ENDSTATE;                                 \
        regs->ARM_pc = pc & ~1;         /* pc */                        \
        regs->ARM_sp = sp;              /* sp */                        \
-       regs->ARM_r2 = stack[2];        /* r2 (envp) */                 \
-       regs->ARM_r1 = stack[1];        /* r1 (argv) */                 \
-       regs->ARM_r0 = stack[0];        /* r0 (argc) */                 \
        nommu_start_thread(regs);                                       \
 })
 
index 1995d1a840609f3df26114e2ca3eed388a0d5f8e..f00b5692cd9d20a27d866a9d186673763966eb3b 100644 (file)
@@ -156,7 +156,6 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 #define TIF_USING_IWMMXT       17
 #define TIF_MEMDIE             18      /* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK    20
-#define TIF_SWITCH_MM          22      /* deferred switch_mm */
 
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
index bdf2b8458ec1d3bb0366ff6ce8aa6623e234aa02..aa9b4ac3fdf6dba0137f12daf725a5067137acf6 100644 (file)
@@ -43,6 +43,7 @@ struct mmu_gather {
        struct mm_struct        *mm;
        unsigned int            fullmm;
        struct vm_area_struct   *vma;
+       unsigned long           start, end;
        unsigned long           range_start;
        unsigned long           range_end;
        unsigned int            nr;
@@ -107,10 +108,12 @@ static inline void tlb_flush_mmu(struct mmu_gather *tlb)
 }
 
 static inline void
-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int fullmm)
+tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
 {
        tlb->mm = mm;
-       tlb->fullmm = fullmm;
+       tlb->fullmm = !(start | (end+1));
+       tlb->start = start;
+       tlb->end = end;
        tlb->vma = NULL;
        tlb->max = ARRAY_SIZE(tlb->local);
        tlb->pages = tlb->local;
index 47bcb2d254af8e4fdb3bacee96131d88a0e4f37e..18d76fd5a2afb2bf27b91980f29c77094e6638c0 100644 (file)
@@ -1,7 +1,6 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
-header-y += a.out.h
 header-y += byteorder.h
 header-y += fcntl.h
 header-y += hwcap.h
diff --git a/arch/arm/include/uapi/asm/a.out.h b/arch/arm/include/uapi/asm/a.out.h
deleted file mode 100644 (file)
index 083894b..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef __ARM_A_OUT_H__
-#define __ARM_A_OUT_H__
-
-#include <linux/personality.h>
-#include <linux/types.h>
-
-struct exec
-{
-  __u32 a_info;                /* Use macros N_MAGIC, etc for access */
-  __u32 a_text;                /* length of text, in bytes */
-  __u32 a_data;                /* length of data, in bytes */
-  __u32 a_bss;         /* length of uninitialized data area for file, in bytes */
-  __u32 a_syms;                /* length of symbol table data in file, in bytes */
-  __u32 a_entry;       /* start address */
-  __u32 a_trsize;      /* length of relocation info for text, in bytes */
-  __u32 a_drsize;      /* length of relocation info for data, in bytes */
-};
-
-/*
- * This is always the same
- */
-#define N_TXTADDR(a)   (0x00008000)
-
-#define N_TRSIZE(a)    ((a).a_trsize)
-#define N_DRSIZE(a)    ((a).a_drsize)
-#define N_SYMSIZE(a)   ((a).a_syms)
-
-#define M_ARM 103
-
-#ifndef LIBRARY_START_TEXT
-#define LIBRARY_START_TEXT     (0x00c00000)
-#endif
-
-#endif /* __A_OUT_GNU_H__ */
index 582b405befc527202f69ccbbc349c77d8d06caf8..d43c7e54ec6cafd568eb48c337d96c5bc4afa714 100644 (file)
@@ -741,6 +741,18 @@ ENDPROC(__switch_to)
 #endif
        .endm
 
+       .macro  kuser_pad, sym, size
+       .if     (. - \sym) & 3
+       .rept   4 - (. - \sym) & 3
+       .byte   0
+       .endr
+       .endif
+       .rept   (\size - (. - \sym)) / 4
+       .word   0xe7fddef1
+       .endr
+       .endm
+
+#ifdef CONFIG_KUSER_HELPERS
        .align  5
        .globl  __kuser_helper_start
 __kuser_helper_start:
@@ -831,18 +843,13 @@ kuser_cmpxchg64_fixup:
 #error "incoherent kernel configuration"
 #endif
 
-       /* pad to next slot */
-       .rept   (16 - (. - __kuser_cmpxchg64)/4)
-       .word   0
-       .endr
-
-       .align  5
+       kuser_pad __kuser_cmpxchg64, 64
 
 __kuser_memory_barrier:                                @ 0xffff0fa0
        smp_dmb arm
        usr_ret lr
 
-       .align  5
+       kuser_pad __kuser_memory_barrier, 32
 
 __kuser_cmpxchg:                               @ 0xffff0fc0
 
@@ -915,13 +922,14 @@ kuser_cmpxchg32_fixup:
 
 #endif
 
-       .align  5
+       kuser_pad __kuser_cmpxchg, 32
 
 __kuser_get_tls:                               @ 0xffff0fe0
        ldr     r0, [pc, #(16 - 8)]     @ read TLS, set in kuser_get_tls_init
        usr_ret lr
        mrc     p15, 0, r0, c13, c0, 3  @ 0xffff0fe8 hardware TLS code
-       .rep    4
+       kuser_pad __kuser_get_tls, 16
+       .rep    3
        .word   0                       @ 0xffff0ff0 software TLS value, then
        .endr                           @ pad up to __kuser_helper_version
 
@@ -931,14 +939,16 @@ __kuser_helper_version:                           @ 0xffff0ffc
        .globl  __kuser_helper_end
 __kuser_helper_end:
 
+#endif
+
  THUMB(        .thumb  )
 
 /*
  * Vector stubs.
  *
- * This code is copied to 0xffff0200 so we can use branches in the
- * vectors, rather than ldr's.  Note that this code must not
- * exceed 0x300 bytes.
+ * This code is copied to 0xffff1000 so we can use branches in the
+ * vectors, rather than ldr's.  Note that this code must not exceed
+ * a page size.
  *
  * Common stub entry macro:
  *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
@@ -985,8 +995,17 @@ ENDPROC(vector_\name)
 1:
        .endm
 
-       .globl  __stubs_start
+       .section .stubs, "ax", %progbits
 __stubs_start:
+       @ This must be the first word
+       .word   vector_swi
+
+vector_rst:
+ ARM(  swi     SYS_ERROR0      )
+ THUMB(        svc     #0              )
+ THUMB(        nop                     )
+       b       vector_und
+
 /*
  * Interrupt dispatcher
  */
@@ -1080,6 +1099,16 @@ __stubs_start:
 
        .align  5
 
+/*=============================================================================
+ * Address exception handler
+ *-----------------------------------------------------------------------------
+ * These aren't too critical.
+ * (they're not supposed to happen, and won't happen in 32-bit data mode).
+ */
+
+vector_addrexcptn:
+       b       vector_addrexcptn
+
 /*=============================================================================
  * Undefined FIQs
  *-----------------------------------------------------------------------------
@@ -1093,45 +1122,19 @@ __stubs_start:
 vector_fiq:
        subs    pc, lr, #4
 
-/*=============================================================================
- * Address exception handler
- *-----------------------------------------------------------------------------
- * These aren't too critical.
- * (they're not supposed to happen, and won't happen in 32-bit data mode).
- */
-
-vector_addrexcptn:
-       b       vector_addrexcptn
-
-/*
- * We group all the following data together to optimise
- * for CPUs with separate I & D caches.
- */
-       .align  5
-
-.LCvswi:
-       .word   vector_swi
-
-       .globl  __stubs_end
-__stubs_end:
-
-       .equ    stubs_offset, __vectors_start + 0x200 - __stubs_start
+       .globl  vector_fiq_offset
+       .equ    vector_fiq_offset, vector_fiq
 
-       .globl  __vectors_start
+       .section .vectors, "ax", %progbits
 __vectors_start:
- ARM(  swi     SYS_ERROR0      )
- THUMB(        svc     #0              )
- THUMB(        nop                     )
-       W(b)    vector_und + stubs_offset
-       W(ldr)  pc, .LCvswi + stubs_offset
-       W(b)    vector_pabt + stubs_offset
-       W(b)    vector_dabt + stubs_offset
-       W(b)    vector_addrexcptn + stubs_offset
-       W(b)    vector_irq + stubs_offset
-       W(b)    vector_fiq + stubs_offset
-
-       .globl  __vectors_end
-__vectors_end:
+       W(b)    vector_rst
+       W(b)    vector_und
+       W(ldr)  pc, __vectors_start + 0x1000
+       W(b)    vector_pabt
+       W(b)    vector_dabt
+       W(b)    vector_addrexcptn
+       W(b)    vector_irq
+       W(b)    vector_fiq
 
        .data
 
index 2adda11f712fe02fa2fdaa63e944e17199bd3748..25442f451148ee107ad8db89de891c8ff42b3bc0 100644 (file)
 #include <asm/irq.h>
 #include <asm/traps.h>
 
+#define FIQ_OFFSET ({                                  \
+               extern void *vector_fiq_offset;         \
+               (unsigned)&vector_fiq_offset;           \
+       })
+
 static unsigned long no_fiq_insn;
 
 /* Default reacquire function
@@ -80,13 +85,16 @@ int show_fiq_list(struct seq_file *p, int prec)
 void set_fiq_handler(void *start, unsigned int length)
 {
 #if defined(CONFIG_CPU_USE_DOMAINS)
-       memcpy((void *)0xffff001c, start, length);
+       void *base = (void *)0xffff0000;
 #else
-       memcpy(vectors_page + 0x1c, start, length);
+       void *base = vectors_page;
 #endif
-       flush_icache_range(0xffff001c, 0xffff001c + length);
+       unsigned offset = FIQ_OFFSET;
+
+       memcpy(base + offset, start, length);
+       flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length);
        if (!vectors_high())
-               flush_icache_range(0x1c, 0x1c + length);
+               flush_icache_range(offset, offset + length);
 }
 
 int claim_fiq(struct fiq_handler *f)
@@ -144,6 +152,7 @@ EXPORT_SYMBOL(disable_fiq);
 
 void __init init_FIQ(int start)
 {
-       no_fiq_insn = *(unsigned long *)0xffff001c;
+       unsigned offset = FIQ_OFFSET;
+       no_fiq_insn = *(unsigned long *)(0xffff0000 + offset);
        fiq_start = start;
 }
index 8c3094d0f7b78426e367e2cf3ed538e54d686cbd..e19edc6f2d15a3e893a40dac8531baeabb7aad9b 100644 (file)
@@ -53,7 +53,12 @@ armpmu_map_cache_event(const unsigned (*cache_map)
 static int
 armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
 {
-       int mapping = (*event_map)[config];
+       int mapping;
+
+       if (config >= PERF_COUNT_HW_MAX)
+               return -ENOENT;
+
+       mapping = (*event_map)[config];
        return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
 }
 
@@ -253,6 +258,9 @@ validate_event(struct pmu_hw_events *hw_events,
        struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
        struct pmu *leader_pmu = event->group_leader->pmu;
 
+       if (is_software_event(event))
+               return 1;
+
        if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF)
                return 1;
 
@@ -569,6 +577,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
                return;
        }
 
+       perf_callchain_store(entry, regs->ARM_pc);
        tail = (struct frame_tail __user *)regs->ARM_fp - 1;
 
        while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
index 6e8931ccf13ed048f0b93880476a3911b3a9b587..5bc2615268d4938cf1a49c70fd0c79af1a82f4ff 100644 (file)
@@ -433,10 +433,11 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
 }
 
 #ifdef CONFIG_MMU
+#ifdef CONFIG_KUSER_HELPERS
 /*
  * The vectors page is always readable from user space for the
- * atomic helpers and the signal restart code. Insert it into the
- * gate_vma so that it is visible through ptrace and /proc/<pid>/mem.
+ * atomic helpers. Insert it into the gate_vma so that it is visible
+ * through ptrace and /proc/<pid>/mem.
  */
 static struct vm_area_struct gate_vma = {
        .vm_start       = 0xffff0000,
@@ -465,9 +466,48 @@ int in_gate_area_no_mm(unsigned long addr)
 {
        return in_gate_area(NULL, addr);
 }
+#define is_gate_vma(vma)       ((vma) = &gate_vma)
+#else
+#define is_gate_vma(vma)       0
+#endif
 
 const char *arch_vma_name(struct vm_area_struct *vma)
 {
-       return (vma == &gate_vma) ? "[vectors]" : NULL;
+       return is_gate_vma(vma) ? "[vectors]" :
+               (vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage) ?
+                "[sigpage]" : NULL;
+}
+
+static struct page *signal_page;
+extern struct page *get_signal_page(void);
+
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+       struct mm_struct *mm = current->mm;
+       unsigned long addr;
+       int ret;
+
+       if (!signal_page)
+               signal_page = get_signal_page();
+       if (!signal_page)
+               return -ENOMEM;
+
+       down_write(&mm->mmap_sem);
+       addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
+       if (IS_ERR_VALUE(addr)) {
+               ret = addr;
+               goto up_fail;
+       }
+
+       ret = install_special_mapping(mm, addr, PAGE_SIZE,
+               VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
+               &signal_page);
+
+       if (ret == 0)
+               mm->context.sigpage = addr;
+
+ up_fail:
+       up_write(&mm->mmap_sem);
+       return ret;
 }
 #endif
index 296786bdbb737870d8fa99479127f9bc5bd8c271..5a42c12767af0cce01c38bd54ca17ffd98df5d1b 100644 (file)
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/errno.h>
+#include <linux/random.h>
 #include <linux/signal.h>
 #include <linux/personality.h>
 #include <linux/uaccess.h>
 
 #include <asm/elf.h>
 #include <asm/cacheflush.h>
+#include <asm/traps.h>
 #include <asm/ucontext.h>
 #include <asm/unistd.h>
 #include <asm/vfp.h>
 
-#include "signal.h"
-
 /*
  * For ARM syscalls, we encode the syscall number into the instruction.
  */
 #define SWI_THUMB_SIGRETURN    (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE))
 #define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))
 
-const unsigned long sigreturn_codes[7] = {
+static const unsigned long sigreturn_codes[7] = {
        MOV_R7_NR_SIGRETURN,    SWI_SYS_SIGRETURN,    SWI_THUMB_SIGRETURN,
        MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
 };
 
+static unsigned long signal_return_offset;
+
 #ifdef CONFIG_CRUNCH
 static int preserve_crunch_context(struct crunch_sigframe __user *frame)
 {
@@ -396,13 +398,19 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
                    __put_user(sigreturn_codes[idx+1], rc+1))
                        return 1;
 
+#ifdef CONFIG_MMU
                if (cpsr & MODE32_BIT) {
+                       struct mm_struct *mm = current->mm;
                        /*
-                        * 32-bit code can use the new high-page
-                        * signal return code support.
+                        * 32-bit code can use the signal return page
+                        * except when the MPU has protected the vectors
+                        * page from PL0
                         */
-                       retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb;
-               } else {
+                       retcode = mm->context.sigpage + signal_return_offset +
+                                 (idx << 2) + thumb;
+               } else
+#endif
+               {
                        /*
                         * Ensure that the instruction cache sees
                         * the return code written onto the stack.
@@ -603,3 +611,33 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
        } while (thread_flags & _TIF_WORK_MASK);
        return 0;
 }
+
+struct page *get_signal_page(void)
+{
+       unsigned long ptr;
+       unsigned offset;
+       struct page *page;
+       void *addr;
+
+       page = alloc_pages(GFP_KERNEL, 0);
+
+       if (!page)
+               return NULL;
+
+       addr = page_address(page);
+
+       /* Give the signal return code some randomness */
+       offset = 0x200 + (get_random_int() & 0x7fc);
+       signal_return_offset = offset;
+
+       /*
+        * Copy signal return handlers into the vector page, and
+        * set sigreturn to be a pointer to these.
+        */
+       memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes));
+
+       ptr = (unsigned long)addr + offset;
+       flush_icache_range(ptr, ptr + sizeof(sigreturn_codes));
+
+       return page;
+}
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h
deleted file mode 100644 (file)
index 5ff067b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- *  linux/arch/arm/kernel/signal.h
- *
- *  Copyright (C) 2005-2009 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#define KERN_SIGRETURN_CODE    (CONFIG_VECTORS_BASE + 0x00000500)
-
-extern const unsigned long sigreturn_codes[7];
index 9a52a07aa40ee3c017c55b5b5cce3b92ae7c599c..a98b62dca2faf9bbce7fbcb786d4c325513f7231 100644 (file)
@@ -103,7 +103,7 @@ static void broadcast_tlb_a15_erratum(void)
 
 static void broadcast_tlb_mm_a15_erratum(struct mm_struct *mm)
 {
-       int cpu, this_cpu;
+       int this_cpu;
        cpumask_t mask = { CPU_BITS_NONE };
 
        if (!erratum_a15_798181())
@@ -111,21 +111,7 @@ static void broadcast_tlb_mm_a15_erratum(struct mm_struct *mm)
 
        dummy_flush_tlb_a15_erratum();
        this_cpu = get_cpu();
-       for_each_online_cpu(cpu) {
-               if (cpu == this_cpu)
-                       continue;
-               /*
-                * We only need to send an IPI if the other CPUs are running
-                * the same ASID as the one being invalidated. There is no
-                * need for locking around the active_asids check since the
-                * switch_mm() function has at least one dmb() (as required by
-                * this workaround) in case a context switch happens on
-                * another CPU after the condition below.
-                */
-               if (atomic64_read(&mm->context.id) ==
-                   atomic64_read(&per_cpu(active_asids, cpu)))
-                       cpumask_set_cpu(cpu, &mask);
-       }
+       a15_erratum_get_cpumask(this_cpu, mm, &mask);
        smp_call_function_many(&mask, ipi_flush_tlb_a15_erratum, NULL, 1);
        put_cpu();
 }
index 90525d9d290b9c25e3b40d5bdeedfc6a6f524cf6..f6fd1d4398c6febcca070a90985d3585af9a6939 100644 (file)
@@ -120,7 +120,7 @@ static int twd_rate_change(struct notifier_block *nb,
         * changing cpu.
         */
        if (flags == POST_RATE_CHANGE)
-               smp_call_function(twd_update_frequency,
+               on_each_cpu(twd_update_frequency,
                                  (void *)&cnd->new_rate, 1);
 
        return NOTIFY_OK;
index 18b32e8e4497f4c1966f43ac6fbb4963315fb968..6b9567e19bdc17e1bb416cb880dc8bbbf3a6996e 100644 (file)
@@ -35,8 +35,6 @@
 #include <asm/tls.h>
 #include <asm/system_misc.h>
 
-#include "signal.h"
-
 static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
 
 void *vectors_page;
@@ -800,47 +798,55 @@ void __init trap_init(void)
        return;
 }
 
-static void __init kuser_get_tls_init(unsigned long vectors)
+#ifdef CONFIG_KUSER_HELPERS
+static void __init kuser_init(void *vectors)
 {
+       extern char __kuser_helper_start[], __kuser_helper_end[];
+       int kuser_sz = __kuser_helper_end - __kuser_helper_start;
+
+       memcpy(vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
+
        /*
         * vectors + 0xfe0 = __kuser_get_tls
         * vectors + 0xfe8 = hardware TLS instruction at 0xffff0fe8
         */
        if (tls_emu || has_tls_reg)
-               memcpy((void *)vectors + 0xfe0, (void *)vectors + 0xfe8, 4);
+               memcpy(vectors + 0xfe0, vectors + 0xfe8, 4);
 }
+#else
+static void __init kuser_init(void *vectors)
+{
+}
+#endif
 
 void __init early_trap_init(void *vectors_base)
 {
        unsigned long vectors = (unsigned long)vectors_base;
        extern char __stubs_start[], __stubs_end[];
        extern char __vectors_start[], __vectors_end[];
-       extern char __kuser_helper_start[], __kuser_helper_end[];
-       int kuser_sz = __kuser_helper_end - __kuser_helper_start;
+       unsigned i;
 
        vectors_page = vectors_base;
 
+       /*
+        * Poison the vectors page with an undefined instruction.  This
+        * instruction is chosen to be undefined for both ARM and Thumb
+        * ISAs.  The Thumb version is an undefined instruction with a
+        * branch back to the undefined instruction.
+        */
+       for (i = 0; i < PAGE_SIZE / sizeof(u32); i++)
+               ((u32 *)vectors_base)[i] = 0xe7fddef1;
+
        /*
         * Copy the vectors, stubs and kuser helpers (in entry-armv.S)
         * into the vector page, mapped at 0xffff0000, and ensure these
         * are visible to the instruction stream.
         */
        memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
-       memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
-       memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
+       memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start);
 
-       /*
-        * Do processor specific fixups for the kuser helpers
-        */
-       kuser_get_tls_init(vectors);
-
-       /*
-        * Copy signal return handlers into the vector page, and
-        * set sigreturn to be a pointer to these.
-        */
-       memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
-              sigreturn_codes, sizeof(sigreturn_codes));
+       kuser_init(vectors_base);
 
-       flush_icache_range(vectors, vectors + PAGE_SIZE);
+       flush_icache_range(vectors, vectors + PAGE_SIZE * 2);
        modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
 }
index a871b8e00fca7d67141859bbb2415dadabbc1ad5..33f2ea32f5a03602d5fc3c52d1b4d4e108a84ed6 100644 (file)
@@ -152,6 +152,23 @@ SECTIONS
        . = ALIGN(PAGE_SIZE);
        __init_begin = .;
 #endif
+       /*
+        * The vectors and stubs are relocatable code, and the
+        * only thing that matters is their relative offsets
+        */
+       __vectors_start = .;
+       .vectors 0 : AT(__vectors_start) {
+               *(.vectors)
+       }
+       . = __vectors_start + SIZEOF(.vectors);
+       __vectors_end = .;
+
+       __stubs_start = .;
+       .stubs 0x1000 : AT(__stubs_start) {
+               *(.stubs)
+       }
+       . = __stubs_start + SIZEOF(.stubs);
+       __stubs_end = .;
 
        INIT_TEXT_SECTION(8)
        .exit.text : {
index 8eea97be1ed52e8ea42d463f166fdc3e69261682..db9cf692d4dded3e2a6cc7e5622ba90ee5bef2e8 100644 (file)
@@ -146,7 +146,11 @@ static bool pm_fake(struct kvm_vcpu *vcpu,
 #define access_pmintenclr pm_fake
 
 /* Architected CP15 registers.
- * Important: Must be sorted ascending by CRn, CRM, Op1, Op2
+ * CRn denotes the primary register number, but is copied to the CRm in the
+ * user space API for 64-bit register access in line with the terminology used
+ * in the ARM ARM.
+ * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
+ *            registers preceding 32-bit ones.
  */
 static const struct coproc_reg cp15_regs[] = {
        /* CSSELR: swapped by interrupt.S. */
@@ -154,8 +158,8 @@ static const struct coproc_reg cp15_regs[] = {
                        NULL, reset_unknown, c0_CSSELR },
 
        /* TTBR0/TTBR1: swapped by interrupt.S. */
-       { CRm( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
-       { CRm( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
+       { CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
+       { CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
 
        /* TTBCR: swapped by interrupt.S. */
        { CRn( 2), CRm( 0), Op1( 0), Op2( 2), is32,
@@ -180,6 +184,10 @@ static const struct coproc_reg cp15_regs[] = {
                        NULL, reset_unknown, c6_DFAR },
        { CRn( 6), CRm( 0), Op1( 0), Op2( 2), is32,
                        NULL, reset_unknown, c6_IFAR },
+
+       /* PAR swapped by interrupt.S */
+       { CRm64( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR },
+
        /*
         * DC{C,I,CI}SW operations:
         */
@@ -395,12 +403,13 @@ static bool index_to_params(u64 id, struct coproc_params *params)
                              | KVM_REG_ARM_OPC1_MASK))
                        return false;
                params->is_64bit = true;
-               params->CRm = ((id & KVM_REG_ARM_CRM_MASK)
+               /* CRm to CRn: see cp15_to_index for details */
+               params->CRn = ((id & KVM_REG_ARM_CRM_MASK)
                               >> KVM_REG_ARM_CRM_SHIFT);
                params->Op1 = ((id & KVM_REG_ARM_OPC1_MASK)
                               >> KVM_REG_ARM_OPC1_SHIFT);
                params->Op2 = 0;
-               params->CRn = 0;
+               params->CRm = 0;
                return true;
        default:
                return false;
@@ -894,7 +903,14 @@ static u64 cp15_to_index(const struct coproc_reg *reg)
        if (reg->is_64) {
                val |= KVM_REG_SIZE_U64;
                val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
-               val |= (reg->CRm << KVM_REG_ARM_CRM_SHIFT);
+               /*
+                * CRn always denotes the primary coproc. reg. nr. for the
+                * in-kernel representation, but the user space API uses the
+                * CRm for the encoding, because it is modelled after the
+                * MRRC/MCRR instructions: see the ARM ARM rev. c page
+                * B3-1445
+                */
+               val |= (reg->CRn << KVM_REG_ARM_CRM_SHIFT);
        } else {
                val |= KVM_REG_SIZE_U32;
                val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
index b7301d3e479921f4d8983a172c88ec6edababd81..0461d5c8d3de4f99c3ecfef669340ec6fa8e0411 100644 (file)
@@ -135,6 +135,8 @@ static inline int cmp_reg(const struct coproc_reg *i1,
                return -1;
        if (i1->CRn != i2->CRn)
                return i1->CRn - i2->CRn;
+       if (i1->is_64 != i2->is_64)
+               return i2->is_64 - i1->is_64;
        if (i1->CRm != i2->CRm)
                return i1->CRm - i2->CRm;
        if (i1->Op1 != i2->Op1)
@@ -145,6 +147,7 @@ static inline int cmp_reg(const struct coproc_reg *i1,
 
 #define CRn(_x)                .CRn = _x
 #define CRm(_x)        .CRm = _x
+#define CRm64(_x)       .CRn = _x, .CRm = 0
 #define Op1(_x)        .Op1 = _x
 #define Op2(_x)        .Op2 = _x
 #define is64           .is_64 = true
index 685063a6d0cf655296aaec9713d08f19b53fa260..cf93472b9dd60daf3da620cf3a44a9ff65a6eac6 100644 (file)
@@ -114,7 +114,11 @@ static bool access_l2ectlr(struct kvm_vcpu *vcpu,
 
 /*
  * A15-specific CP15 registers.
- * Important: Must be sorted ascending by CRn, CRM, Op1, Op2
+ * CRn denotes the primary register number, but is copied to the CRm in the
+ * user space API for 64-bit register access in line with the terminology used
+ * in the ARM ARM.
+ * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
+ *            registers preceding 32-bit ones.
  */
 static const struct coproc_reg a15_regs[] = {
        /* MPIDR: we use VMPIDR for guest access. */
index f7793df62f5834ab60abb19528d2e31f9a756a11..16cd4ba5d7fd6d0ff0781da759712167cbc17508 100644 (file)
@@ -49,6 +49,7 @@ __kvm_hyp_code_start:
 ENTRY(__kvm_tlb_flush_vmid_ipa)
        push    {r2, r3}
 
+       dsb     ishst
        add     r0, r0, #KVM_VTTBR
        ldrd    r2, r3, [r0]
        mcrr    p15, 6, r2, r3, c2      @ Write VTTBR
@@ -291,6 +292,7 @@ THUMB(      orr     r2, r2, #PSR_T_BIT      )
        ldr     r2, =BSYM(panic)
        msr     ELR_hyp, r2
        ldr     r0, =\panic_str
+       clrex                           @ Clear exclusive monitor
        eret
 .endm
 
@@ -414,6 +416,10 @@ guest_trap:
        mrcne   p15, 4, r2, c6, c0, 4   @ HPFAR
        bne     3f
 
+       /* Preserve PAR */
+       mrrc    p15, 0, r0, r1, c7      @ PAR
+       push    {r0, r1}
+
        /* Resolve IPA using the xFAR */
        mcr     p15, 0, r2, c7, c8, 0   @ ATS1CPR
        isb
@@ -424,13 +430,20 @@ guest_trap:
        lsl     r2, r2, #4
        orr     r2, r2, r1, lsl #24
 
+       /* Restore PAR */
+       pop     {r0, r1}
+       mcrr    p15, 0, r0, r1, c7      @ PAR
+
 3:     load_vcpu                       @ Load VCPU pointer to r0
        str     r2, [r0, #VCPU_HPFAR]
 
 1:     mov     r1, #ARM_EXCEPTION_HVC
        b       __kvm_vcpu_return
 
-4:     pop     {r0, r1, r2}            @ Failed translation, return to guest
+4:     pop     {r0, r1}                @ Failed translation, return to guest
+       mcrr    p15, 0, r0, r1, c7      @ PAR
+       clrex
+       pop     {r0, r1, r2}
        eret
 
 /*
@@ -456,6 +469,7 @@ switch_to_guest_vfp:
 
        pop     {r3-r7}
        pop     {r0-r2}
+       clrex
        eret
 #endif
 
index 3c8f2f0b4c5e105c765b281241415066ce1470d2..2b44b95a86ddf6e77d60b6d28ef1de954d3236c6 100644 (file)
@@ -302,11 +302,14 @@ vcpu      .req    r0              @ vcpu pointer always in r0
        .endif
 
        mrc     p15, 0, r2, c14, c1, 0  @ CNTKCTL
+       mrrc    p15, 0, r4, r5, c7      @ PAR
 
        .if \store_to_vcpu == 0
-       push    {r2}
+       push    {r2,r4-r5}
        .else
        str     r2, [vcpu, #CP15_OFFSET(c14_CNTKCTL)]
+       add     r12, vcpu, #CP15_OFFSET(c7_PAR)
+       strd    r4, r5, [r12]
        .endif
 .endm
 
@@ -319,12 +322,15 @@ vcpu      .req    r0              @ vcpu pointer always in r0
  */
 .macro write_cp15_state read_from_vcpu
        .if \read_from_vcpu == 0
-       pop     {r2}
+       pop     {r2,r4-r5}
        .else
        ldr     r2, [vcpu, #CP15_OFFSET(c14_CNTKCTL)]
+       add     r12, vcpu, #CP15_OFFSET(c7_PAR)
+       ldrd    r4, r5, [r12]
        .endif
 
        mcr     p15, 0, r2, c14, c1, 0  @ CNTKCTL
+       mcrr    p15, 0, r4, r5, c7      @ PAR
 
        .if \read_from_vcpu == 0
        pop     {r2-r12}
index dff4ddc5ef81312590cd3a2cdb1ad4b40e3741ab..139e42da25f061baa0128c7615723da54e068592 100644 (file)
@@ -75,6 +75,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
        .parts                  = davinci_nand_partitions,
        .nr_parts               = ARRAY_SIZE(davinci_nand_partitions),
        .ecc_mode               = NAND_ECC_HW_SYNDROME,
+       .ecc_bits               = 4,
        .bbt_options            = NAND_BBT_USE_FLASH,
 };
 
index a33686a6fbb226f9b880c2268a87beeb6b6f98e9..fa4bfaf952d886abcc94fd20bbb46285bd4cada6 100644 (file)
@@ -153,6 +153,7 @@ static struct davinci_nand_pdata davinci_evm_nandflash_data = {
        .parts          = davinci_evm_nandflash_partition,
        .nr_parts       = ARRAY_SIZE(davinci_evm_nandflash_partition),
        .ecc_mode       = NAND_ECC_HW,
+       .ecc_bits       = 1,
        .bbt_options    = NAND_BBT_USE_FLASH,
        .timing         = &davinci_evm_nandflash_timing,
 };
index fbb8e5ab1dc19bbd56e3508a5505929bb6c71406..0c005e876cac6fbd226c1700cfe47818b80dc6ee 100644 (file)
@@ -90,6 +90,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
        .parts                  = davinci_nand_partitions,
        .nr_parts               = ARRAY_SIZE(davinci_nand_partitions),
        .ecc_mode               = NAND_ECC_HW,
+       .ecc_bits               = 1,
        .options                = 0,
 };
 
index 2bc112adf565495aed9505bfc23a401e53341d52..808233b60e3d0047e257227d50d49955c816228d 100644 (file)
@@ -88,6 +88,7 @@ static struct davinci_nand_pdata davinci_ntosd2_nandflash_data = {
        .parts          = davinci_ntosd2_nandflash_partition,
        .nr_parts       = ARRAY_SIZE(davinci_ntosd2_nandflash_partition),
        .ecc_mode       = NAND_ECC_HW,
+       .ecc_bits       = 1,
        .bbt_options    = NAND_BBT_USE_FLASH,
 };
 
index a7cd2cf5e08de32c2ceafc508559d3201919dcc4..3490a24f969e4a0b450ef146cee72f37e1cb6c9f 100644 (file)
@@ -276,8 +276,6 @@ int __init dc21285_setup(int nr, struct pci_sys_data *sys)
 
        sys->mem_offset  = DC21285_PCI_MEM;
 
-       pci_ioremap_io(0, DC21285_PCI_IO);
-
        pci_add_resource_offset(&sys->resources, &res[0], sys->mem_offset);
        pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
 
index 34fffdf6fc1dc4b7f699418976e0b3d943c512a6..564553694b543d24df4eca3fa6a305c59520ce79 100644 (file)
@@ -119,66 +119,101 @@ static struct clk init_clocks_off[] = {
        }
 };
 
-static struct clk init_clocks[] = {
-       {
-               .name           = "lcd",
-               .parent         = &clk_h,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_LCDC,
-       }, {
-               .name           = "gpio",
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_GPIO,
-       }, {
-               .name           = "usb-host",
-               .parent         = &clk_h,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_USBH,
-       }, {
-               .name           = "usb-device",
-               .parent         = &clk_h,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_USBD,
-       }, {
-               .name           = "timers",
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_PWMT,
-       }, {
-               .name           = "uart",
-               .devname        = "s3c2410-uart.0",
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_UART0,
-       }, {
-               .name           = "uart",
-               .devname        = "s3c2410-uart.1",
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_UART1,
-       }, {
-               .name           = "uart",
-               .devname        = "s3c2410-uart.2",
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_UART2,
-       }, {
-               .name           = "rtc",
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_RTC,
-       }, {
-               .name           = "watchdog",
-               .parent         = &clk_p,
-               .ctrlbit        = 0,
-       }, {
-               .name           = "usb-bus-host",
-               .parent         = &clk_usb_bus,
-       }, {
-               .name           = "usb-bus-gadget",
-               .parent         = &clk_usb_bus,
-       },
+static struct clk clk_lcd = {
+       .name           = "lcd",
+       .parent         = &clk_h,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_LCDC,
+};
+
+static struct clk clk_gpio = {
+       .name           = "gpio",
+       .parent         = &clk_p,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_GPIO,
+};
+
+static struct clk clk_usb_host = {
+       .name           = "usb-host",
+       .parent         = &clk_h,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_USBH,
+};
+
+static struct clk clk_usb_device = {
+       .name           = "usb-device",
+       .parent         = &clk_h,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_USBD,
+};
+
+static struct clk clk_timers = {
+       .name           = "timers",
+       .parent         = &clk_p,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_PWMT,
+};
+
+struct clk s3c24xx_clk_uart0 = {
+       .name           = "uart",
+       .devname        = "s3c2410-uart.0",
+       .parent         = &clk_p,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_UART0,
+};
+
+struct clk s3c24xx_clk_uart1 = {
+       .name           = "uart",
+       .devname        = "s3c2410-uart.1",
+       .parent         = &clk_p,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_UART1,
+};
+
+struct clk s3c24xx_clk_uart2 = {
+       .name           = "uart",
+       .devname        = "s3c2410-uart.2",
+       .parent         = &clk_p,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_UART2,
+};
+
+static struct clk clk_rtc = {
+       .name           = "rtc",
+       .parent         = &clk_p,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_RTC,
+};
+
+static struct clk clk_watchdog = {
+       .name           = "watchdog",
+       .parent         = &clk_p,
+       .ctrlbit        = 0,
+};
+
+static struct clk clk_usb_bus_host = {
+       .name           = "usb-bus-host",
+       .parent         = &clk_usb_bus,
+};
+
+static struct clk clk_usb_bus_gadget = {
+       .name           = "usb-bus-gadget",
+       .parent         = &clk_usb_bus,
+};
+
+static struct clk *init_clocks[] = {
+       &clk_lcd,
+       &clk_gpio,
+       &clk_usb_host,
+       &clk_usb_device,
+       &clk_timers,
+       &s3c24xx_clk_uart0,
+       &s3c24xx_clk_uart1,
+       &s3c24xx_clk_uart2,
+       &clk_rtc,
+       &clk_watchdog,
+       &clk_usb_bus_host,
+       &clk_usb_bus_gadget,
 };
 
 /* s3c2410_baseclk_add()
@@ -195,7 +230,6 @@ int __init s3c2410_baseclk_add(void)
 {
        unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
        unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
-       struct clk *clkp;
        struct clk *xtal;
        int ret;
        int ptr;
@@ -207,8 +241,9 @@ int __init s3c2410_baseclk_add(void)
 
        /* register clocks from clock array */
 
-       clkp = init_clocks;
-       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++) {
+               struct clk *clkp = init_clocks[ptr];
+
                /* ensure that we note the clock state */
 
                clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
index 1069b56808265b5efaf9877b9ed6a1b7dc5ea833..aaf006d1d6dc9ec6111ae080e3e4f15350615561 100644 (file)
@@ -166,6 +166,9 @@ static struct clk_lookup s3c2440_clk_lookup[] = {
        CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
        CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
        CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n),
+       CLKDEV_INIT("s3c2440-uart.0", "uart", &s3c24xx_clk_uart0),
+       CLKDEV_INIT("s3c2440-uart.1", "uart", &s3c24xx_clk_uart1),
+       CLKDEV_INIT("s3c2440-uart.2", "uart", &s3c24xx_clk_uart2),
        CLKDEV_INIT("s3c2440-camif", "camera", &s3c2440_clk_cam_upll),
 };
 
index 899a86c31ec92213520793c4c757628a5d4b0504..1ccddd228112abbbef7d28c173155f87e4c1eb21 100644 (file)
@@ -287,14 +287,14 @@ static struct gpio_em_config gio3_config = {
 static struct resource gio3_resources[] = {
        [0] = {
                .name   = "GIO_096",
-               .start  = 0xe0050100,
-               .end    = 0xe005012b,
+               .start  = 0xe0050180,
+               .end    = 0xe00501ab,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
                .name   = "GIO_096",
-               .start  = 0xe0050140,
-               .end    = 0xe005015f,
+               .start  = 0xe00501c0,
+               .end    = 0xe00501df,
                .flags  = IORESOURCE_MEM,
        },
        [2] = {
index c5a75a7a508fd6f47d2acedd9ace315e599b00f5..7f45c2edbca9a457564524ee1b988cd4f9599c4b 100644 (file)
@@ -62,7 +62,7 @@ enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFB3 };
 static const struct plat_sci_port scif[] = {
        SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */
        SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */
-       SCIFB_DATA(SCIFB0, 0xe6c50000, gic_spi(145)), /* SCIFB0 */
+       SCIFB_DATA(SCIFB0, 0xe6c20000, gic_spi(148)), /* SCIFB0 */
        SCIFB_DATA(SCIFB1, 0xe6c30000, gic_spi(149)), /* SCIFB1 */
        SCIFB_DATA(SCIFB2, 0xe6ce0000, gic_spi(150)), /* SCIFB2 */
        SCIFB_DATA(SCIFB3, 0xe6cf0000, gic_spi(151)), /* SCIFB3 */
index ec087407b163a4a5a22144c4a5a92ebaed570335..6f938ccb0c546fbc24c4ec19c656799811d84106 100644 (file)
 /* PCI space */
 #define VERSATILE_PCI_BASE             0x41000000      /* PCI Interface */
 #define VERSATILE_PCI_CFG_BASE        0x42000000
+#define VERSATILE_PCI_IO_BASE          0x43000000
 #define VERSATILE_PCI_MEM_BASE0        0x44000000
 #define VERSATILE_PCI_MEM_BASE1        0x50000000
 #define VERSATILE_PCI_MEM_BASE2        0x60000000
 /* Sizes of above maps */
 #define VERSATILE_PCI_BASE_SIZE               0x01000000
 #define VERSATILE_PCI_CFG_BASE_SIZE    0x02000000
+#define VERSATILE_PCI_IO_BASE_SIZE     0x01000000
 #define VERSATILE_PCI_MEM_BASE0_SIZE   0x0c000000      /* 32Mb */
 #define VERSATILE_PCI_MEM_BASE1_SIZE   0x10000000      /* 256Mb */
 #define VERSATILE_PCI_MEM_BASE2_SIZE   0x10000000      /* 256Mb */
index e92e5e0705bc945321779c6b6023e57adf9ff582..c97be4ea76d216d4dbbeb856ed200fbb0cd9e458 100644 (file)
@@ -43,9 +43,9 @@
 #define PCI_IMAP0              __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x0)
 #define PCI_IMAP1              __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x4)
 #define PCI_IMAP2              __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x8)
-#define PCI_SMAP0              __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x10)
-#define PCI_SMAP1              __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x14)
-#define PCI_SMAP2              __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x18)
+#define PCI_SMAP0              __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x14)
+#define PCI_SMAP1              __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x18)
+#define PCI_SMAP2              __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x1c)
 #define PCI_SELFID             __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0xc)
 
 #define DEVICE_ID_OFFSET               0x00
@@ -170,8 +170,8 @@ static struct pci_ops pci_versatile_ops = {
        .write  = versatile_write_config,
 };
 
-static struct resource io_mem = {
-       .name   = "PCI I/O space",
+static struct resource unused_mem = {
+       .name   = "PCI unused",
        .start  = VERSATILE_PCI_MEM_BASE0,
        .end    = VERSATILE_PCI_MEM_BASE0+VERSATILE_PCI_MEM_BASE0_SIZE-1,
        .flags  = IORESOURCE_MEM,
@@ -195,9 +195,9 @@ static int __init pci_versatile_setup_resources(struct pci_sys_data *sys)
 {
        int ret = 0;
 
-       ret = request_resource(&iomem_resource, &io_mem);
+       ret = request_resource(&iomem_resource, &unused_mem);
        if (ret) {
-               printk(KERN_ERR "PCI: unable to allocate I/O "
+               printk(KERN_ERR "PCI: unable to allocate unused "
                       "memory region (%d)\n", ret);
                goto out;
        }
@@ -205,7 +205,7 @@ static int __init pci_versatile_setup_resources(struct pci_sys_data *sys)
        if (ret) {
                printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
                       "memory region (%d)\n", ret);
-               goto release_io_mem;
+               goto release_unused_mem;
        }
        ret = request_resource(&iomem_resource, &pre_mem);
        if (ret) {
@@ -225,8 +225,8 @@ static int __init pci_versatile_setup_resources(struct pci_sys_data *sys)
 
  release_non_mem:
        release_resource(&non_mem);
- release_io_mem:
-       release_resource(&io_mem);
+ release_unused_mem:
+       release_resource(&unused_mem);
  out:
        return ret;
 }
@@ -246,7 +246,7 @@ int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
                goto out;
        }
 
-       ret = pci_ioremap_io(0, VERSATILE_PCI_MEM_BASE0);
+       ret = pci_ioremap_io(0, VERSATILE_PCI_IO_BASE);
        if (ret)
                goto out;
 
@@ -294,6 +294,19 @@ int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
        __raw_writel(PHYS_OFFSET, local_pci_cfg_base + PCI_BASE_ADDRESS_1);
        __raw_writel(PHYS_OFFSET, local_pci_cfg_base + PCI_BASE_ADDRESS_2);
 
+       /*
+        * For many years the kernel and QEMU were symbiotically buggy
+        * in that they both assumed the same broken IRQ mapping.
+        * QEMU therefore attempts to auto-detect old broken kernels
+        * so that they still work on newer QEMU as they did on old
+        * QEMU. Since we now use the correct (ie matching-hardware)
+        * IRQ mapping we write a definitely different value to a
+        * PCI_INTERRUPT_LINE register to tell QEMU that we expect
+        * real hardware behaviour and it need not be backwards
+        * compatible for us. This write is harmless on real hardware.
+        */
+       __raw_writel(0, VERSATILE_PCI_VIRT_BASE+PCI_INTERRUPT_LINE);
+
        /*
         * Do not to map Versatile FPGA PCI device into memory space
         */
@@ -327,13 +340,13 @@ static int __init versatile_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
-       /* slot,  pin,  irq
-        *  24     1     IRQ_SIC_PCI0
-        *  25     1     IRQ_SIC_PCI1
-        *  26     1     IRQ_SIC_PCI2
-        *  27     1     IRQ_SIC_PCI3
+       /*
+        * Slot INTA    INTB    INTC    INTD
+        * 31   PCI1    PCI2    PCI3    PCI0
+        * 30   PCI0    PCI1    PCI2    PCI3
+        * 29   PCI3    PCI0    PCI1    PCI2
         */
-       irq = IRQ_SIC_PCI0 + ((slot - 24 + pin - 1) & 3);
+       irq = IRQ_SIC_PCI0 + ((slot + 2 + pin - 1) & 3);
 
        return irq;
 }
index 35955b54944c1c5ed39bf051667b337aeaa7dee3..08c9fe917d1fec0c681ba2ab8ea4897dcd026e29 100644 (file)
@@ -411,24 +411,28 @@ config CPU_32v3
        select CPU_USE_DOMAINS if MMU
        select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
        select TLS_REG_EMUL if SMP || !MMU
+       select NEED_KUSER_HELPERS
 
 config CPU_32v4
        bool
        select CPU_USE_DOMAINS if MMU
        select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
        select TLS_REG_EMUL if SMP || !MMU
+       select NEED_KUSER_HELPERS
 
 config CPU_32v4T
        bool
        select CPU_USE_DOMAINS if MMU
        select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
        select TLS_REG_EMUL if SMP || !MMU
+       select NEED_KUSER_HELPERS
 
 config CPU_32v5
        bool
        select CPU_USE_DOMAINS if MMU
        select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
        select TLS_REG_EMUL if SMP || !MMU
+       select NEED_KUSER_HELPERS
 
 config CPU_32v6
        bool
@@ -756,6 +760,7 @@ config CPU_BPREDICT_DISABLE
 
 config TLS_REG_EMUL
        bool
+       select NEED_KUSER_HELPERS
        help
          An SMP system using a pre-ARMv6 processor (there are apparently
          a few prototypes like that in existence) and therefore access to
@@ -763,11 +768,43 @@ config TLS_REG_EMUL
 
 config NEEDS_SYSCALL_FOR_CMPXCHG
        bool
+       select NEED_KUSER_HELPERS
        help
          SMP on a pre-ARMv6 processor?  Well OK then.
          Forget about fast user space cmpxchg support.
          It is just not possible.
 
+config NEED_KUSER_HELPERS
+       bool
+
+config KUSER_HELPERS
+       bool "Enable kuser helpers in vector page" if !NEED_KUSER_HELPERS
+       default y
+       help
+         Warning: disabling this option may break user programs.
+
+         Provide kuser helpers in the vector page.  The kernel provides
+         helper code to userspace in read only form at a fixed location
+         in the high vector page to allow userspace to be independent of
+         the CPU type fitted to the system.  This permits binaries to be
+         run on ARMv4 through to ARMv7 without modification.
+
+         See Documentation/arm/kernel_user_helpers.txt for details.
+
+         However, the fixed address nature of these helpers can be used
+         by ROP (return orientated programming) authors when creating
+         exploits.
+
+         If all of the binaries and libraries which run on your platform
+         are built specifically for your platform, and make no use of
+         these helpers, then you can turn this option off to hinder
+         such exploits. However, in that case, if a binary or library
+         relying on those helpers is run, it will receive a SIGILL signal,
+         which will terminate the program.
+
+         Say N here only if you are absolutely certain that you do not
+         need these helpers; otherwise, the safe option is to say Y.
+
 config DMA_CACHE_RWFO
        bool "Enable read/write for ownership DMA cache maintenance"
        depends on CPU_V6K && SMP
index 2ac37372ef52f4ba4db642d39bef349798f1785a..eeab06ebd06e5d6eeefc75d14c91c4c740946965 100644 (file)
  * non 64-bit operations.
  */
 #define ASID_FIRST_VERSION     (1ULL << ASID_BITS)
-#define NUM_USER_ASIDS         (ASID_FIRST_VERSION - 1)
-
-#define ASID_TO_IDX(asid)      ((asid & ~ASID_MASK) - 1)
-#define IDX_TO_ASID(idx)       ((idx + 1) & ~ASID_MASK)
+#define NUM_USER_ASIDS         ASID_FIRST_VERSION
 
 static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
 static atomic64_t asid_generation = ATOMIC64_INIT(ASID_FIRST_VERSION);
 static DECLARE_BITMAP(asid_map, NUM_USER_ASIDS);
 
-DEFINE_PER_CPU(atomic64_t, active_asids);
+static DEFINE_PER_CPU(atomic64_t, active_asids);
 static DEFINE_PER_CPU(u64, reserved_asids);
 static cpumask_t tlb_flush_pending;
 
+#ifdef CONFIG_ARM_ERRATA_798181
+void a15_erratum_get_cpumask(int this_cpu, struct mm_struct *mm,
+                            cpumask_t *mask)
+{
+       int cpu;
+       unsigned long flags;
+       u64 context_id, asid;
+
+       raw_spin_lock_irqsave(&cpu_asid_lock, flags);
+       context_id = mm->context.id.counter;
+       for_each_online_cpu(cpu) {
+               if (cpu == this_cpu)
+                       continue;
+               /*
+                * We only need to send an IPI if the other CPUs are
+                * running the same ASID as the one being invalidated.
+                */
+               asid = per_cpu(active_asids, cpu).counter;
+               if (asid == 0)
+                       asid = per_cpu(reserved_asids, cpu);
+               if (context_id == asid)
+                       cpumask_set_cpu(cpu, mask);
+       }
+       raw_spin_unlock_irqrestore(&cpu_asid_lock, flags);
+}
+#endif
+
 #ifdef CONFIG_ARM_LPAE
 static void cpu_set_reserved_ttbr0(void)
 {
@@ -128,7 +152,16 @@ static void flush_context(unsigned int cpu)
                        asid = 0;
                } else {
                        asid = atomic64_xchg(&per_cpu(active_asids, i), 0);
-                       __set_bit(ASID_TO_IDX(asid), asid_map);
+                       /*
+                        * If this CPU has already been through a
+                        * rollover, but hasn't run another task in
+                        * the meantime, we must preserve its reserved
+                        * ASID, as this is the only trace we have of
+                        * the process it is still running.
+                        */
+                       if (asid == 0)
+                               asid = per_cpu(reserved_asids, i);
+                       __set_bit(asid & ~ASID_MASK, asid_map);
                }
                per_cpu(reserved_asids, i) = asid;
        }
@@ -167,17 +200,19 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu)
                /*
                 * Allocate a free ASID. If we can't find one, take a
                 * note of the currently active ASIDs and mark the TLBs
-                * as requiring flushes.
+                * as requiring flushes. We always count from ASID #1,
+                * as we reserve ASID #0 to switch via TTBR0 and indicate
+                * rollover events.
                 */
-               asid = find_first_zero_bit(asid_map, NUM_USER_ASIDS);
+               asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1);
                if (asid == NUM_USER_ASIDS) {
                        generation = atomic64_add_return(ASID_FIRST_VERSION,
                                                         &asid_generation);
                        flush_context(cpu);
-                       asid = find_first_zero_bit(asid_map, NUM_USER_ASIDS);
+                       asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1);
                }
                __set_bit(asid, asid_map);
-               asid = generation | IDX_TO_ASID(asid);
+               asid |= generation;
                cpumask_clear(mm_cpumask(mm));
        }
 
index afeaef7a8ffc36f4c5b3544f5addef809cf4984e..c12ae661d4ab6406c95dd1adbcc92415e5980985 100644 (file)
@@ -600,7 +600,7 @@ void __init mem_init(void)
 
 #ifdef CONFIG_SA1111
        /* now that our DMA memory is actually so designated, we can free it */
-       free_reserved_area(__va(PHYS_PFN_OFFSET), swapper_pg_dir, 0, NULL);
+       free_reserved_area(__va(PHYS_OFFSET), swapper_pg_dir, 0, NULL);
 #endif
 
        free_highpages();
index 4d409e6a552df67f11ea8bb81b1930e830c3dcde..daf336fe0be89250dc82343d81681ee746abc5d9 100644 (file)
@@ -1175,7 +1175,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
        /*
         * Allocate the vector page early.
         */
-       vectors = early_alloc(PAGE_SIZE);
+       vectors = early_alloc(PAGE_SIZE * 2);
 
        early_trap_init(vectors);
 
@@ -1220,15 +1220,27 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
        map.pfn = __phys_to_pfn(virt_to_phys(vectors));
        map.virtual = 0xffff0000;
        map.length = PAGE_SIZE;
+#ifdef CONFIG_KUSER_HELPERS
        map.type = MT_HIGH_VECTORS;
+#else
+       map.type = MT_LOW_VECTORS;
+#endif
        create_mapping(&map);
 
        if (!vectors_high()) {
                map.virtual = 0;
+               map.length = PAGE_SIZE * 2;
                map.type = MT_LOW_VECTORS;
                create_mapping(&map);
        }
 
+       /* Now create a kernel read-only mapping */
+       map.pfn += 1;
+       map.virtual = 0xffff0000 + PAGE_SIZE;
+       map.length = PAGE_SIZE;
+       map.type = MT_LOW_VECTORS;
+       create_mapping(&map);
+
        /*
         * Ask the machine support to map in the statically mapped devices.
         */
index 9704097c450e13300be619e73015c65b7bd08c4a..b3997c70af322eee2fffcbf802721c7c86612d33 100644 (file)
@@ -110,7 +110,7 @@ ENTRY(cpu_v7_set_pte_ext)
  ARM(  str     r3, [r0, #2048]! )
  THUMB(        add     r0, r0, #2048 )
  THUMB(        str     r3, [r0] )
-       ALT_SMP(mov     pc,lr)
+       ALT_SMP(W(nop))
        ALT_UP (mcr     p15, 0, r0, c7, c10, 1)         @ flush_pte
 #endif
        mov     pc, lr
index 363027e811d6f5c803d7616c318d4aeab7bfb3e9..6ba4bd9118f28163a0d4d0b36686f403f47f8d45 100644 (file)
@@ -73,7 +73,7 @@ ENTRY(cpu_v7_set_pte_ext)
        tst     r3, #1 << (55 - 32)             @ L_PTE_DIRTY
        orreq   r2, #L_PTE_RDONLY
 1:     strd    r2, r3, [r0]
-       ALT_SMP(mov     pc, lr)
+       ALT_SMP(W(nop))
        ALT_UP (mcr     p15, 0, r0, c7, c10, 1)         @ flush_pte
 #endif
        mov     pc, lr
index e35fec34453ea13d57e2f1902a07bc99e21ba731..5fbccee5f644e66c2d1ffcfc309463942fe148a7 100644 (file)
@@ -75,13 +75,14 @@ ENTRY(cpu_v7_do_idle)
 ENDPROC(cpu_v7_do_idle)
 
 ENTRY(cpu_v7_dcache_clean_area)
-       ALT_SMP(mov     pc, lr)                 @ MP extensions imply L1 PTW
-       ALT_UP(W(nop))
-       dcache_line_size r2, r3
-1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
+       ALT_SMP(W(nop))                 @ MP extensions imply L1 PTW
+       ALT_UP_B(1f)
+       mov     pc, lr
+1:     dcache_line_size r2, r3
+2:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
        add     r0, r0, r2
        subs    r1, r1, r2
-       bhi     1b
+       bhi     2b
        dsb
        mov     pc, lr
 ENDPROC(cpu_v7_dcache_clean_area)
index a62753dc15baf144ecfc2ea7efe53bfc6f13a9fe..df45d6edc98d9e723242f3890e1ea4df124d8888 100644 (file)
@@ -83,6 +83,11 @@ extern struct clk clk_ext;
 extern struct clksrc_clk clk_epllref;
 extern struct clksrc_clk clk_esysclk;
 
+/* S3C24XX UART clocks */
+extern struct clk s3c24xx_clk_uart0;
+extern struct clk s3c24xx_clk_uart1;
+extern struct clk s3c24xx_clk_uart2;
+
 /* S3C64XX specific clocks */
 extern struct clk clk_h2;
 extern struct clk clk_27m;
index 13609e01f4b786293219f2c9e865837c9262f76e..81edd31bb4ac62c78bd26507fd2fee1d78c68b6f 100644 (file)
@@ -170,6 +170,7 @@ static void __init xen_percpu_init(void *unused)
        per_cpu(xen_vcpu, cpu) = vcpup;
 
        enable_percpu_irq(xen_events_irq, 0);
+       put_cpu();
 }
 
 static void xen_restart(char str, const char *cmd)
@@ -272,12 +273,15 @@ core_initcall(xen_guest_init);
 
 static int __init xen_pm_init(void)
 {
+       if (!xen_domain())
+               return -ENODEV;
+
        pm_power_off = xen_power_off;
        arm_pm_restart = xen_restart;
 
        return 0;
 }
-subsys_initcall(xen_pm_init);
+late_initcall(xen_pm_init);
 
 static irqreturn_t xen_arm_callback(int irq, void *arg)
 {
index 46b3beb4b773c85cd381f72301b8f2e9dfdc7a97..717031a762c27966aabc7786f6d2a900034b0b08 100644 (file)
@@ -35,6 +35,7 @@ struct mmu_gather {
        struct mm_struct        *mm;
        unsigned int            fullmm;
        struct vm_area_struct   *vma;
+       unsigned long           start, end;
        unsigned long           range_start;
        unsigned long           range_end;
        unsigned int            nr;
@@ -97,10 +98,12 @@ static inline void tlb_flush_mmu(struct mmu_gather *tlb)
 }
 
 static inline void
-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int fullmm)
+tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
 {
        tlb->mm = mm;
-       tlb->fullmm = fullmm;
+       tlb->fullmm = !(start | (end+1));
+       tlb->start = start;
+       tlb->end = end;
        tlb->vma = NULL;
        tlb->max = ARRAY_SIZE(tlb->local);
        tlb->pages = tlb->local;
index a9fcd89b251b6ebd25eef44ce010cc8cf2f7c8a9..b74ccb5a769054f7e77ef42c586f20709a0329b2 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/initrd.h>
 
 #include <asm/sections.h>
+#include <asm/uaccess.h>
 
 /*
  * ZERO_PAGE is a special page that is used for zero-initialized
index ef3a9de01954511a352fa5b24285136789425e21..bc5efc7c3f3f8ead3608780ba5e2f5b9e212e20c 100644 (file)
@@ -22,7 +22,7 @@
  * unmapping a portion of the virtual address space, these hooks are called according to
  * the following template:
  *
- *     tlb <- tlb_gather_mmu(mm, full_mm_flush);       // start unmap for address space MM
+ *     tlb <- tlb_gather_mmu(mm, start, end);          // start unmap for address space MM
  *     {
  *       for each vma that needs a shootdown do {
  *         tlb_start_vma(tlb, vma);
@@ -58,6 +58,7 @@ struct mmu_gather {
        unsigned int            max;
        unsigned char           fullmm;         /* non-zero means full mm flush */
        unsigned char           need_flush;     /* really unmapped some PTEs? */
+       unsigned long           start, end;
        unsigned long           start_addr;
        unsigned long           end_addr;
        struct page             **pages;
@@ -155,13 +156,15 @@ static inline void __tlb_alloc_page(struct mmu_gather *tlb)
 
 
 static inline void
-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush)
+tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
 {
        tlb->mm = mm;
        tlb->max = ARRAY_SIZE(tlb->local);
        tlb->pages = tlb->local;
        tlb->nr = 0;
-       tlb->fullmm = full_mm_flush;
+       tlb->fullmm = !(start | (end+1));
+       tlb->start = start;
+       tlb->end = end;
        tlb->start_addr = ~0UL;
 }
 
index 2291a7d69d49a27c541a4746492d7be01ba17727..fa277aecfb78f1256dae50e30b0d873afbb72949 100644 (file)
 #include <asm/machdep.h>
 #include <asm/natfeat.h>
 
+extern long nf_get_id2(const char *feature_name);
+
 asm("\n"
-"      .global nf_get_id,nf_call\n"
-"nf_get_id:\n"
+"      .global nf_get_id2,nf_call\n"
+"nf_get_id2:\n"
 "      .short  0x7300\n"
 "      rts\n"
 "nf_call:\n"
@@ -29,12 +31,25 @@ asm("\n"
 "1:    moveq.l #0,%d0\n"
 "      rts\n"
 "      .section __ex_table,\"a\"\n"
-"      .long   nf_get_id,1b\n"
+"      .long   nf_get_id2,1b\n"
 "      .long   nf_call,1b\n"
 "      .previous");
-EXPORT_SYMBOL_GPL(nf_get_id);
 EXPORT_SYMBOL_GPL(nf_call);
 
+long nf_get_id(const char *feature_name)
+{
+       /* feature_name may be in vmalloc()ed memory, so make a copy */
+       char name_copy[32];
+       size_t n;
+
+       n = strlcpy(name_copy, feature_name, sizeof(name_copy));
+       if (n >= sizeof(name_copy))
+               return 0;
+
+       return nf_get_id2(name_copy);
+}
+EXPORT_SYMBOL_GPL(nf_get_id);
+
 void nfprint(const char *fmt, ...)
 {
        static char buf[256];
index 444ea8a09e9f3386434e89d502c41d1f4107302e..ef881cfbbca90987bf0e93c9271537317c15886c 100644 (file)
                unsigned long long n64;                         \
        } __n;                                                  \
        unsigned long __rem, __upper;                           \
+       unsigned long __base = (base);                          \
                                                                \
        __n.n64 = (n);                                          \
        if ((__upper = __n.n32[0])) {                           \
                asm ("divul.l %2,%1:%0"                         \
-                       : "=d" (__n.n32[0]), "=d" (__upper)     \
-                       : "d" (base), "0" (__n.n32[0]));        \
+                    : "=d" (__n.n32[0]), "=d" (__upper)        \
+                    : "d" (__base), "0" (__n.n32[0]));         \
        }                                                       \
        asm ("divu.l %2,%1:%0"                                  \
-               : "=d" (__n.n32[1]), "=d" (__rem)               \
-               : "d" (base), "1" (__upper), "0" (__n.n32[1])); \
+            : "=d" (__n.n32[1]), "=d" (__rem)                  \
+            : "d" (__base), "1" (__upper), "0" (__n.n32[1]));  \
        (n) = __n.n64;                                          \
        __rem;                                                  \
 })
index d22a4ecffff422f542e96f81527b45a4e3f9c6c2..4fab52294d9874b5b07558682ec5160a470c1092 100644 (file)
@@ -28,7 +28,7 @@ config MICROBLAZE
        select GENERIC_CLOCKEVENTS
        select GENERIC_IDLE_POLL_SETUP
        select MODULES_USE_ELF_RELA
-       select CLONE_BACKWARDS
+       select CLONE_BACKWARDS3
 
 config SWAP
        def_bool n
index 7a58ab933b206a397c56b65f6a608fc4f9a1d8eb..e53e2b40d695ffcc329d820741b0160c650953bd 100644 (file)
@@ -27,6 +27,7 @@ config MIPS
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
+       select GENERIC_PCI_IOMAP
        select HAVE_ARCH_JUMP_LABEL
        select ARCH_WANT_IPC_PARSE_VERSION
        select IRQ_FORCED_THREADING
@@ -2412,7 +2413,6 @@ config PCI
        bool "Support for PCI controller"
        depends on HW_HAS_PCI
        select PCI_DOMAINS
-       select GENERIC_PCI_IOMAP
        select NO_GENERIC_PCI_IOPORT_MAP
        help
          Find out whether you have a PCI motherboard. PCI is the name of a
index 765ef30e3e1c470d0d4ed69740718113b838daf8..733017b3dfe76ee98bcd67007861c135cd145503 100644 (file)
@@ -164,7 +164,7 @@ static void __init ar933x_clocks_init(void)
                ath79_ahb_clk.rate = freq / t;
        }
 
-       ath79_wdt_clk.rate = ath79_ref_clk.rate;
+       ath79_wdt_clk.rate = ath79_ahb_clk.rate;
        ath79_uart_clk.rate = ath79_ref_clk.rate;
 }
 
index 01b1b3f94feb77b115f6911771236961ff3e151c..2a75ff249e7156cec2e424f79e2caedf6163c78e 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright (C) 2008, 2009 Wind River Systems
  *   written by Ralf Baechle <ralf@linux-mips.org>
  */
+#include <linux/compiler.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/console.h>
@@ -712,7 +713,7 @@ void __init prom_init(void)
        if (cvmx_read_csr(CVMX_L2D_FUS3) & (3ull << 34)) {
                pr_info("Skipping L2 locking due to reduced L2 cache size\n");
        } else {
-               uint32_t ebase = read_c0_ebase() & 0x3ffff000;
+               uint32_t __maybe_unused ebase = read_c0_ebase() & 0x3ffff000;
 #ifdef CONFIG_CAVIUM_OCTEON_LOCK_L2_TLB
                /* TLB refill */
                cvmx_l2c_lock_mem_region(ebase, 0x100);
@@ -996,7 +997,7 @@ void __init plat_mem_setup(void)
        cvmx_bootmem_unlock();
        /* Add the memory region for the kernel. */
        kernel_start = (unsigned long) _text;
-       kernel_size = ALIGN(_end - _text, 0x100000);
+       kernel_size = _end - _text;
 
        /* Adjust for physical offset. */
        kernel_start &= ~0xffffffff80000000ULL;
index b7e59853fd33b05df930c3fb795aa03a9a6de23e..b84e1fb3fabf86bdbd81868b73418debf385eb22 100644 (file)
@@ -170,6 +170,11 @@ static inline void * isa_bus_to_virt(unsigned long address)
 extern void __iomem * __ioremap(phys_t offset, phys_t size, unsigned long flags);
 extern void __iounmap(const volatile void __iomem *addr);
 
+#ifndef CONFIG_PCI
+struct pci_dev;
+static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {}
+#endif
+
 static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
        unsigned long flags)
 {
index 9afdad6c2ffb81db7f8ffb68dd003bd3b5cd4980..eaf4dc1c729440688a169bd11fe81b250b8c776f 100644 (file)
@@ -23,6 +23,7 @@ struct parisc_device {
        /* generic info returned from pdc_pat_cell_module() */
        unsigned long   mod_info;       /* PAT specific - Misc Module info */
        unsigned long   pmod_loc;       /* physical Module location */
+       unsigned long   mod0;
 #endif
        u64             dma_mask;       /* DMA mask for I/O */
        struct device   dev;
@@ -61,4 +62,6 @@ parisc_get_drvdata(struct parisc_device *d)
 
 extern struct bus_type parisc_bus_type;
 
+int iosapic_serial_irq(struct parisc_device *dev);
+
 #endif /*_ASM_PARISC_PARISC_DEVICE_H_*/
index d306b75bc77f00323ce26a14558ddd0e98d9e127..e1509308899f6084a785143ac7460c3186353220 100644 (file)
@@ -32,9 +32,12 @@ static inline void set_eiem(unsigned long val)
        cr;                             \
 })
 
-#define mtsp(gr, cr) \
-       __asm__ __volatile__("mtsp %0,%1" \
+#define mtsp(val, cr) \
+       { if (__builtin_constant_p(val) && ((val) == 0)) \
+        __asm__ __volatile__("mtsp %%r0,%0" : : "i" (cr) : "memory"); \
+       else \
+        __asm__ __volatile__("mtsp %0,%1" \
                : /* no outputs */ \
-               : "r" (gr), "i" (cr) : "memory")
+               : "r" (val), "i" (cr) : "memory"); }
 
 #endif /* __PARISC_SPECIAL_INSNS_H */
index 5273da991e062c841ac40efdb0f3174a4df8cde3..9d086a599fa05f56a13cbd6b214b466ad4b43a12 100644 (file)
@@ -63,13 +63,14 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
 static inline void flush_tlb_page(struct vm_area_struct *vma,
        unsigned long addr)
 {
-       unsigned long flags;
+       unsigned long flags, sid;
 
        /* For one page, it's not worth testing the split_tlb variable */
 
        mb();
-       mtsp(vma->vm_mm->context,1);
+       sid = vma->vm_mm->context;
        purge_tlb_start(flags);
+       mtsp(sid, 1);
        pdtlb(addr);
        pitlb(addr);
        purge_tlb_end(flags);
index 65fb4cbc3a0ffd88f7f100870e8b0c952de573e7..c035673209f732f0850aaa4dc98d2d49eee3b74c 100644 (file)
@@ -71,18 +71,27 @@ flush_cache_all_local(void)
 }
 EXPORT_SYMBOL(flush_cache_all_local);
 
+/* Virtual address of pfn.  */
+#define pfn_va(pfn)    __va(PFN_PHYS(pfn))
+
 void
 update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
 {
-       struct page *page = pte_page(*ptep);
+       unsigned long pfn = pte_pfn(*ptep);
+       struct page *page;
 
-       if (pfn_valid(page_to_pfn(page)) && page_mapping(page) &&
-           test_bit(PG_dcache_dirty, &page->flags)) {
+       /* We don't have pte special.  As a result, we can be called with
+          an invalid pfn and we don't need to flush the kernel dcache page.
+          This occurs with FireGL card in C8000.  */
+       if (!pfn_valid(pfn))
+               return;
 
-               flush_kernel_dcache_page(page);
+       page = pfn_to_page(pfn);
+       if (page_mapping(page) && test_bit(PG_dcache_dirty, &page->flags)) {
+               flush_kernel_dcache_page_addr(pfn_va(pfn));
                clear_bit(PG_dcache_dirty, &page->flags);
        } else if (parisc_requires_coherency())
-               flush_kernel_dcache_page(page);
+               flush_kernel_dcache_page_addr(pfn_va(pfn));
 }
 
 void
@@ -440,8 +449,8 @@ void __flush_tlb_range(unsigned long sid, unsigned long start,
        else {
                unsigned long flags;
 
-               mtsp(sid, 1);
                purge_tlb_start(flags);
+               mtsp(sid, 1);
                if (split_tlb) {
                        while (npages--) {
                                pdtlb(start);
@@ -495,44 +504,42 @@ static inline pte_t *get_ptep(pgd_t *pgd, unsigned long addr)
 
 void flush_cache_mm(struct mm_struct *mm)
 {
+       struct vm_area_struct *vma;
+       pgd_t *pgd;
+
        /* Flushing the whole cache on each cpu takes forever on
           rp3440, etc.  So, avoid it if the mm isn't too big.  */
-       if (mm_total_size(mm) < parisc_cache_flush_threshold) {
-               struct vm_area_struct *vma;
-
-               if (mm->context == mfsp(3)) {
-                       for (vma = mm->mmap; vma; vma = vma->vm_next) {
-                               flush_user_dcache_range_asm(vma->vm_start,
-                                       vma->vm_end);
-                               if (vma->vm_flags & VM_EXEC)
-                                       flush_user_icache_range_asm(
-                                         vma->vm_start, vma->vm_end);
-                       }
-               } else {
-                       pgd_t *pgd = mm->pgd;
-
-                       for (vma = mm->mmap; vma; vma = vma->vm_next) {
-                               unsigned long addr;
-
-                               for (addr = vma->vm_start; addr < vma->vm_end;
-                                    addr += PAGE_SIZE) {
-                                       pte_t *ptep = get_ptep(pgd, addr);
-                                       if (ptep != NULL) {
-                                               pte_t pte = *ptep;
-                                               __flush_cache_page(vma, addr,
-                                                 page_to_phys(pte_page(pte)));
-                                       }
-                               }
-                       }
+       if (mm_total_size(mm) >= parisc_cache_flush_threshold) {
+               flush_cache_all();
+               return;
+       }
+
+       if (mm->context == mfsp(3)) {
+               for (vma = mm->mmap; vma; vma = vma->vm_next) {
+                       flush_user_dcache_range_asm(vma->vm_start, vma->vm_end);
+                       if ((vma->vm_flags & VM_EXEC) == 0)
+                               continue;
+                       flush_user_icache_range_asm(vma->vm_start, vma->vm_end);
                }
                return;
        }
 
-#ifdef CONFIG_SMP
-       flush_cache_all();
-#else
-       flush_cache_all_local();
-#endif
+       pgd = mm->pgd;
+       for (vma = mm->mmap; vma; vma = vma->vm_next) {
+               unsigned long addr;
+
+               for (addr = vma->vm_start; addr < vma->vm_end;
+                    addr += PAGE_SIZE) {
+                       unsigned long pfn;
+                       pte_t *ptep = get_ptep(pgd, addr);
+                       if (!ptep)
+                               continue;
+                       pfn = pte_pfn(*ptep);
+                       if (!pfn_valid(pfn))
+                               continue;
+                       __flush_cache_page(vma, addr, PFN_PHYS(pfn));
+               }
+       }
 }
 
 void
@@ -556,33 +563,32 @@ flush_user_icache_range(unsigned long start, unsigned long end)
 void flush_cache_range(struct vm_area_struct *vma,
                unsigned long start, unsigned long end)
 {
+       unsigned long addr;
+       pgd_t *pgd;
+
        BUG_ON(!vma->vm_mm->context);
 
-       if ((end - start) < parisc_cache_flush_threshold) {
-               if (vma->vm_mm->context == mfsp(3)) {
-                       flush_user_dcache_range_asm(start, end);
-                       if (vma->vm_flags & VM_EXEC)
-                               flush_user_icache_range_asm(start, end);
-               } else {
-                       unsigned long addr;
-                       pgd_t *pgd = vma->vm_mm->pgd;
-
-                       for (addr = start & PAGE_MASK; addr < end;
-                            addr += PAGE_SIZE) {
-                               pte_t *ptep = get_ptep(pgd, addr);
-                               if (ptep != NULL) {
-                                       pte_t pte = *ptep;
-                                       flush_cache_page(vma,
-                                          addr, pte_pfn(pte));
-                               }
-                       }
-               }
-       } else {
-#ifdef CONFIG_SMP
+       if ((end - start) >= parisc_cache_flush_threshold) {
                flush_cache_all();
-#else
-               flush_cache_all_local();
-#endif
+               return;
+       }
+
+       if (vma->vm_mm->context == mfsp(3)) {
+               flush_user_dcache_range_asm(start, end);
+               if (vma->vm_flags & VM_EXEC)
+                       flush_user_icache_range_asm(start, end);
+               return;
+       }
+
+       pgd = vma->vm_mm->pgd;
+       for (addr = start & PAGE_MASK; addr < end; addr += PAGE_SIZE) {
+               unsigned long pfn;
+               pte_t *ptep = get_ptep(pgd, addr);
+               if (!ptep)
+                       continue;
+               pfn = pte_pfn(*ptep);
+               if (pfn_valid(pfn))
+                       __flush_cache_page(vma, addr, PFN_PHYS(pfn));
        }
 }
 
@@ -591,9 +597,10 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
 {
        BUG_ON(!vma->vm_mm->context);
 
-       flush_tlb_page(vma, vmaddr);
-       __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn)));
-
+       if (pfn_valid(pfn)) {
+               flush_tlb_page(vma, vmaddr);
+               __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
+       }
 }
 
 #ifdef CONFIG_PARISC_TMPALIAS
index 3295ef4a185d06327c84b806276f31ac4c7cdaab..f0b6722fc706169b37a407a1fad6b063984722e8 100644 (file)
@@ -211,6 +211,7 @@ pat_query_module(ulong pcell_loc, ulong mod_index)
        /* REVISIT: who is the consumer of this? not sure yet... */
        dev->mod_info = pa_pdc_cell->mod_info;  /* pass to PAT_GET_ENTITY() */
        dev->pmod_loc = pa_pdc_cell->mod_location;
+       dev->mod0 = pa_pdc_cell->mod[0];
 
        register_parisc_device(dev);    /* advertise device */
 
index a49cc812df8a10c0c079a83d85c29e526626b73c..ac4370b1ca4019f5eaf85f910097bf1cc69c0611 100644 (file)
@@ -2,6 +2,7 @@
  *    Optimized memory copy routines.
  *
  *    Copyright (C) 2004 Randolph Chung <tausq@debian.org>
+ *    Copyright (C) 2013 Helge Deller <deller@gmx.de>
  *
  *    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
@@ -153,17 +154,21 @@ static inline void prefetch_dst(const void *addr)
 #define prefetch_dst(addr) do { } while(0)
 #endif
 
+#define PA_MEMCPY_OK           0
+#define PA_MEMCPY_LOAD_ERROR   1
+#define PA_MEMCPY_STORE_ERROR  2
+
 /* Copy from a not-aligned src to an aligned dst, using shifts. Handles 4 words
  * per loop.  This code is derived from glibc. 
  */
-static inline unsigned long copy_dstaligned(unsigned long dst, unsigned long src, unsigned long len, unsigned long o_dst, unsigned long o_src, unsigned long o_len)
+static inline unsigned long copy_dstaligned(unsigned long dst,
+                                       unsigned long src, unsigned long len)
 {
        /* gcc complains that a2 and a3 may be uninitialized, but actually
         * they cannot be.  Initialize a2/a3 to shut gcc up.
         */
        register unsigned int a0, a1, a2 = 0, a3 = 0;
        int sh_1, sh_2;
-       struct exception_data *d;
 
        /* prefetch_src((const void *)src); */
 
@@ -197,7 +202,7 @@ static inline unsigned long copy_dstaligned(unsigned long dst, unsigned long src
                        goto do2;
                case 0:
                        if (len == 0)
-                               return 0;
+                               return PA_MEMCPY_OK;
                        /* a3 = ((unsigned int *) src)[0];
                           a0 = ((unsigned int *) src)[1]; */
                        ldw(s_space, 0, src, a3, cda_ldw_exc);
@@ -256,42 +261,35 @@ do0:
        preserve_branch(handle_load_error);
        preserve_branch(handle_store_error);
 
-       return 0;
+       return PA_MEMCPY_OK;
 
 handle_load_error:
        __asm__ __volatile__ ("cda_ldw_exc:\n");
-       d = &__get_cpu_var(exception_data);
-       DPRINTF("cda_ldw_exc: o_len=%lu fault_addr=%lu o_src=%lu ret=%lu\n",
-               o_len, d->fault_addr, o_src, o_len - d->fault_addr + o_src);
-       return o_len * 4 - d->fault_addr + o_src;
+       return PA_MEMCPY_LOAD_ERROR;
 
 handle_store_error:
        __asm__ __volatile__ ("cda_stw_exc:\n");
-       d = &__get_cpu_var(exception_data);
-       DPRINTF("cda_stw_exc: o_len=%lu fault_addr=%lu o_dst=%lu ret=%lu\n",
-               o_len, d->fault_addr, o_dst, o_len - d->fault_addr + o_dst);
-       return o_len * 4 - d->fault_addr + o_dst;
+       return PA_MEMCPY_STORE_ERROR;
 }
 
 
-/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
-static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
+/* Returns PA_MEMCPY_OK, PA_MEMCPY_LOAD_ERROR or PA_MEMCPY_STORE_ERROR.
+ * In case of an access fault the faulty address can be read from the per_cpu
+ * exception data struct. */
+static unsigned long pa_memcpy_internal(void *dstp, const void *srcp,
+                                       unsigned long len)
 {
        register unsigned long src, dst, t1, t2, t3;
        register unsigned char *pcs, *pcd;
        register unsigned int *pws, *pwd;
        register double *pds, *pdd;
-       unsigned long ret = 0;
-       unsigned long o_dst, o_src, o_len;
-       struct exception_data *d;
+       unsigned long ret;
 
        src = (unsigned long)srcp;
        dst = (unsigned long)dstp;
        pcs = (unsigned char *)srcp;
        pcd = (unsigned char *)dstp;
 
-       o_dst = dst; o_src = src; o_len = len;
-
        /* prefetch_src((const void *)srcp); */
 
        if (len < THRESHOLD)
@@ -401,7 +399,7 @@ byte_copy:
                len--;
        }
 
-       return 0;
+       return PA_MEMCPY_OK;
 
 unaligned_copy:
        /* possibly we are aligned on a word, but not on a double... */
@@ -438,8 +436,7 @@ unaligned_copy:
                src = (unsigned long)pcs;
        }
 
-       ret = copy_dstaligned(dst, src, len / sizeof(unsigned int), 
-               o_dst, o_src, o_len);
+       ret = copy_dstaligned(dst, src, len / sizeof(unsigned int));
        if (ret)
                return ret;
 
@@ -454,17 +451,41 @@ unaligned_copy:
 
 handle_load_error:
        __asm__ __volatile__ ("pmc_load_exc:\n");
-       d = &__get_cpu_var(exception_data);
-       DPRINTF("pmc_load_exc: o_len=%lu fault_addr=%lu o_src=%lu ret=%lu\n",
-               o_len, d->fault_addr, o_src, o_len - d->fault_addr + o_src);
-       return o_len - d->fault_addr + o_src;
+       return PA_MEMCPY_LOAD_ERROR;
 
 handle_store_error:
        __asm__ __volatile__ ("pmc_store_exc:\n");
+       return PA_MEMCPY_STORE_ERROR;
+}
+
+
+/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
+static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
+{
+       unsigned long ret, fault_addr, reference;
+       struct exception_data *d;
+
+       ret = pa_memcpy_internal(dstp, srcp, len);
+       if (likely(ret == PA_MEMCPY_OK))
+               return 0;
+
+       /* if a load or store fault occured we can get the faulty addr */
        d = &__get_cpu_var(exception_data);
-       DPRINTF("pmc_store_exc: o_len=%lu fault_addr=%lu o_dst=%lu ret=%lu\n",
-               o_len, d->fault_addr, o_dst, o_len - d->fault_addr + o_dst);
-       return o_len - d->fault_addr + o_dst;
+       fault_addr = d->fault_addr;
+
+       /* error in load or store? */
+       if (ret == PA_MEMCPY_LOAD_ERROR)
+               reference = (unsigned long) srcp;
+       else
+               reference = (unsigned long) dstp;
+
+       DPRINTF("pa_memcpy: fault type = %lu, len=%lu fault_addr=%lu ref=%lu\n",
+               ret, len, fault_addr, reference);
+
+       if (fault_addr >= reference)
+               return len - (fault_addr - reference);
+       else
+               return len;
 }
 
 #ifdef __KERNEL__
index c33e3ad2c8fd52c9e0c31dfc272faf3d34902f37..fe404e77246ed47e87bd47d2b9e88b7192dcfed4 100644 (file)
@@ -572,7 +572,7 @@ config SCHED_SMT
 config PPC_DENORMALISATION
        bool "PowerPC denormalisation exception handling"
        depends on PPC_BOOK3S_64
-       default "n"
+       default "y" if PPC_POWERNV
        ---help---
          Add support for handling denormalisation of single precision
          values.  Useful for bare metal only.  If unsure say Y here.
@@ -986,6 +986,7 @@ config RELOCATABLE
          must live at a different physical address than the primary
          kernel.
 
+# This value must have zeroes in the bottom 60 bits otherwise lots will break
 config PAGE_OFFSET
        hex
        default "0xc000000000000000"
index 46793b58a761d549d7bf69814530c128352f26a5..07ca627e52c0b25ed45fb61128b3dc2210a4f541 100644 (file)
@@ -358,12 +358,12 @@ label##_relon_pSeries:                                    \
        /* No guest interrupts come through here */     \
        SET_SCRATCH0(r13);              /* save r13 */  \
        EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \
-                                      EXC_STD, KVMTEST_PR, vec)
+                                      EXC_STD, NOTEST, vec)
 
 #define STD_RELON_EXCEPTION_PSERIES_OOL(vec, label)            \
        .globl label##_relon_pSeries;                           \
 label##_relon_pSeries:                                         \
-       EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_PR, vec);        \
+       EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, vec);            \
        EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, EXC_STD)
 
 #define STD_RELON_EXCEPTION_HV(loc, vec, label)                \
@@ -374,12 +374,12 @@ label##_relon_hv:                                 \
        /* No guest interrupts come through here */     \
        SET_SCRATCH0(r13);      /* save r13 */          \
        EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \
-                                      EXC_HV, KVMTEST, vec)
+                                      EXC_HV, NOTEST, vec)
 
 #define STD_RELON_EXCEPTION_HV_OOL(vec, label)                 \
        .globl label##_relon_hv;                                \
 label##_relon_hv:                                              \
-       EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST, vec);           \
+       EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, vec);            \
        EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, EXC_HV)
 
 /* This associate vector numbers with bits in paca->irq_happened */
index c1df590ec4440a96f81b97f6048ad79a7f326179..49fa55bfbac4fba38f26368cbbdcdf1513aa590c 100644 (file)
@@ -82,10 +82,9 @@ struct exception_table_entry;
 void sort_ex_table(struct exception_table_entry *start,
                   struct exception_table_entry *finish);
 
-#ifdef CONFIG_MODVERSIONS
+#if defined(CONFIG_MODVERSIONS) && defined(CONFIG_PPC64)
 #define ARCH_RELOCATES_KCRCTAB
-
-extern const unsigned long reloc_start[];
+#define reloc_start PHYSICAL_START
 #endif
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_MODULE_H */
index 988c812aab5b15c3c3dc5698dc935376d0243192..b9f426212d3ab3afff006938089cf609fe3c785a 100644 (file)
@@ -211,9 +211,19 @@ extern long long virt_phys_offset;
 #define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + VIRT_PHYS_OFFSET))
 #define __pa(x) ((unsigned long)(x) - VIRT_PHYS_OFFSET)
 #else
+#ifdef CONFIG_PPC64
+/*
+ * gcc miscompiles (unsigned long)(&static_var) - PAGE_OFFSET
+ * with -mcmodel=medium, so we use & and | instead of - and + on 64-bit.
+ */
+#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) | PAGE_OFFSET))
+#define __pa(x) ((unsigned long)(x) & 0x0fffffffffffffffUL)
+
+#else /* 32-bit, non book E */
 #define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + PAGE_OFFSET - MEMORY_START))
 #define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + MEMORY_START)
 #endif
+#endif
 
 /*
  * Unfortunately the PLT is in the BSS in the PPC32 ELF ABI,
index 14a658363698ee1d58e0b400b33b3bbc13475dda..419e7125cce275ea3c875e2b9efecc666987e060 100644 (file)
@@ -247,6 +247,10 @@ struct thread_struct {
        unsigned long   tm_orig_msr;    /* Thread's MSR on ctx switch */
        struct pt_regs  ckpt_regs;      /* Checkpointed registers */
 
+       unsigned long   tm_tar;
+       unsigned long   tm_ppr;
+       unsigned long   tm_dscr;
+
        /*
         * Transactional FP and VSX 0-31 register set.
         * NOTE: the sense of these is the opposite of the integer ckpt_regs!
index 4a9e408644fe6ae0403d49821d48516092e51640..e1fb161252efd6dff6be0ff647674fd5dcbe63d2 100644 (file)
 #define SPRN_HRMOR     0x139   /* Real mode offset register */
 #define SPRN_HSRR0     0x13A   /* Hypervisor Save/Restore 0 */
 #define SPRN_HSRR1     0x13B   /* Hypervisor Save/Restore 1 */
+/* HFSCR and FSCR bit numbers are the same */
+#define FSCR_TAR_LG    8       /* Enable Target Address Register */
+#define FSCR_EBB_LG    7       /* Enable Event Based Branching */
+#define FSCR_TM_LG     5       /* Enable Transactional Memory */
+#define FSCR_PM_LG     4       /* Enable prob/priv access to PMU SPRs */
+#define FSCR_BHRB_LG   3       /* Enable Branch History Rolling Buffer*/
+#define FSCR_DSCR_LG   2       /* Enable Data Stream Control Register */
+#define FSCR_VECVSX_LG 1       /* Enable VMX/VSX  */
+#define FSCR_FP_LG     0       /* Enable Floating Point */
 #define SPRN_FSCR      0x099   /* Facility Status & Control Register */
-#define   FSCR_TAR     (1 << (63-55)) /* Enable Target Address Register */
-#define   FSCR_EBB     (1 << (63-56)) /* Enable Event Based Branching */
-#define   FSCR_DSCR    (1 << (63-61)) /* Enable Data Stream Control Register */
+#define   FSCR_TAR     __MASK(FSCR_TAR_LG)
+#define   FSCR_EBB     __MASK(FSCR_EBB_LG)
+#define   FSCR_DSCR    __MASK(FSCR_DSCR_LG)
 #define SPRN_HFSCR     0xbe    /* HV=1 Facility Status & Control Register */
-#define   HFSCR_TAR    (1 << (63-55)) /* Enable Target Address Register */
-#define   HFSCR_EBB    (1 << (63-56)) /* Enable Event Based Branching */
-#define   HFSCR_TM     (1 << (63-58)) /* Enable Transactional Memory */
-#define   HFSCR_PM     (1 << (63-60)) /* Enable prob/priv access to PMU SPRs */
-#define   HFSCR_BHRB   (1 << (63-59)) /* Enable Branch History Rolling Buffer*/
-#define   HFSCR_DSCR   (1 << (63-61)) /* Enable Data Stream Control Register */
-#define   HFSCR_VECVSX (1 << (63-62)) /* Enable VMX/VSX  */
-#define   HFSCR_FP     (1 << (63-63)) /* Enable Floating Point */
+#define   HFSCR_TAR    __MASK(FSCR_TAR_LG)
+#define   HFSCR_EBB    __MASK(FSCR_EBB_LG)
+#define   HFSCR_TM     __MASK(FSCR_TM_LG)
+#define   HFSCR_PM     __MASK(FSCR_PM_LG)
+#define   HFSCR_BHRB   __MASK(FSCR_BHRB_LG)
+#define   HFSCR_DSCR   __MASK(FSCR_DSCR_LG)
+#define   HFSCR_VECVSX __MASK(FSCR_VECVSX_LG)
+#define   HFSCR_FP     __MASK(FSCR_FP_LG)
 #define SPRN_TAR       0x32f   /* Target Address Register */
 #define SPRN_LPCR      0x13E   /* LPAR Control Register */
 #define   LPCR_VPM0    (1ul << (63-0))
 #define   MMCR0_TRIGGER        0x00002000UL /* TRIGGER enable */
 #define   MMCR0_PMAO   0x00000080UL /* performance monitor alert has occurred, set to 0 after handling exception */
 #define   MMCR0_SHRFC  0x00000040UL /* SHRre freeze conditions between threads */
+#define   MMCR0_FC56   0x00000010UL /* freeze counters 5 and 6 */
 #define   MMCR0_FCTI   0x00000008UL /* freeze counters in tags inactive mode */
 #define   MMCR0_FCTA   0x00000004UL /* freeze counters in tags active mode */
 #define   MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */
index ffbaabebcdca71eb1130ccaf12cfcf36c82501c4..48cfc858abd6dfa70c4c95172a5e4003fa62c53d 100644 (file)
@@ -145,6 +145,10 @@ extern void __cpu_die(unsigned int cpu);
 #define smp_setup_cpu_maps()
 static inline void inhibit_secondary_onlining(void) {}
 static inline void uninhibit_secondary_onlining(void) {}
+static inline const struct cpumask *cpu_sibling_mask(int cpu)
+{
+       return cpumask_of(cpu);
+}
 
 #endif /* CONFIG_SMP */
 
index 200d763a0a6708b16674eaa92df29a3fcf57fce9..685ecc86aa8bb18e67c57d59a27a240f93353c64 100644 (file)
@@ -15,6 +15,15 @@ extern struct task_struct *__switch_to(struct task_struct *,
 struct thread_struct;
 extern struct task_struct *_switch(struct thread_struct *prev,
                                   struct thread_struct *next);
+#ifdef CONFIG_PPC_BOOK3S_64
+static inline void save_tar(struct thread_struct *prev)
+{
+       if (cpu_has_feature(CPU_FTR_ARCH_207S))
+               prev->tar = mfspr(SPRN_TAR);
+}
+#else
+static inline void save_tar(struct thread_struct *prev) {}
+#endif
 
 extern void giveup_fpu(struct task_struct *);
 extern void load_up_fpu(void);
index ee5b690a0bedff7f4e9e6f485e9dc3c31df31a8a..52e5758ea3689825923ff04d7dc6f602f98dda98 100644 (file)
@@ -764,6 +764,16 @@ int fix_alignment(struct pt_regs *regs)
        nb = aligninfo[instr].len;
        flags = aligninfo[instr].flags;
 
+       /* ldbrx/stdbrx overlap lfs/stfs in the DSISR unfortunately */
+       if (IS_XFORM(instruction) && ((instruction >> 1) & 0x3ff) == 532) {
+               nb = 8;
+               flags = LD+SW;
+       } else if (IS_XFORM(instruction) &&
+                  ((instruction >> 1) & 0x3ff) == 660) {
+               nb = 8;
+               flags = ST+SW;
+       }
+
        /* Byteswap little endian loads and stores */
        swiz = 0;
        if (regs->msr & MSR_LE) {
index 6f16ffafa6f01542d54ccc684c3f8d5d7d6add5c..302886b77de2337819b907b4c90ccc446cc6d2a9 100644 (file)
@@ -139,6 +139,9 @@ int main(void)
        DEFINE(THREAD_TM_TFHAR, offsetof(struct thread_struct, tm_tfhar));
        DEFINE(THREAD_TM_TEXASR, offsetof(struct thread_struct, tm_texasr));
        DEFINE(THREAD_TM_TFIAR, offsetof(struct thread_struct, tm_tfiar));
+       DEFINE(THREAD_TM_TAR, offsetof(struct thread_struct, tm_tar));
+       DEFINE(THREAD_TM_PPR, offsetof(struct thread_struct, tm_ppr));
+       DEFINE(THREAD_TM_DSCR, offsetof(struct thread_struct, tm_dscr));
        DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs));
        DEFINE(THREAD_TRANSACT_VR0, offsetof(struct thread_struct,
                                         transact_vr[0]));
index 8741c854e03d50800cba18ad091f3d843c6a0111..38847767012dbf495e6f052484363d717627c605 100644 (file)
@@ -449,15 +449,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
 
 #ifdef CONFIG_PPC_BOOK3S_64
 BEGIN_FTR_SECTION
-       /*
-        * Back up the TAR across context switches.  Note that the TAR is not
-        * available for use in the kernel.  (To provide this, the TAR should
-        * be backed up/restored on exception entry/exit instead, and be in
-        * pt_regs.  FIXME, this should be in pt_regs anyway (for debug).)
-        */
-       mfspr   r0,SPRN_TAR
-       std     r0,THREAD_TAR(r3)
-
        /* Event based branch registers */
        mfspr   r0, SPRN_BESCR
        std     r0, THREAD_BESCR(r3)
@@ -584,9 +575,34 @@ BEGIN_FTR_SECTION
        ld      r7,DSCR_DEFAULT@toc(2)
        ld      r0,THREAD_DSCR(r4)
        cmpwi   r6,0
+       li      r8, FSCR_DSCR
        bne     1f
        ld      r0,0(r7)
-1:     cmpd    r0,r25
+       b       3f
+1:
+  BEGIN_FTR_SECTION_NESTED(70)
+       mfspr   r6, SPRN_FSCR
+       or      r6, r6, r8
+       mtspr   SPRN_FSCR, r6
+    BEGIN_FTR_SECTION_NESTED(69)
+       mfspr   r6, SPRN_HFSCR
+       or      r6, r6, r8
+       mtspr   SPRN_HFSCR, r6
+    END_FTR_SECTION_NESTED(CPU_FTR_HVMODE, CPU_FTR_HVMODE, 69)
+       b       4f
+  END_FTR_SECTION_NESTED(CPU_FTR_ARCH_207S, CPU_FTR_ARCH_207S, 70)
+3:
+  BEGIN_FTR_SECTION_NESTED(70)
+       mfspr   r6, SPRN_FSCR
+       andc    r6, r6, r8
+       mtspr   SPRN_FSCR, r6
+    BEGIN_FTR_SECTION_NESTED(69)
+       mfspr   r6, SPRN_HFSCR
+       andc    r6, r6, r8
+       mtspr   SPRN_HFSCR, r6
+    END_FTR_SECTION_NESTED(CPU_FTR_HVMODE, CPU_FTR_HVMODE, 69)
+  END_FTR_SECTION_NESTED(CPU_FTR_ARCH_207S, CPU_FTR_ARCH_207S, 70)
+4:     cmpd    r0,r25
        beq     2f
        mtspr   SPRN_DSCR,r0
 2:
index 40e4a17c8ba0f249e2b65d85d4014fe7aa47f7a7..902ca3c6b4b6496d8e606623187c9f1da1500f2a 100644 (file)
@@ -341,10 +341,17 @@ vsx_unavailable_pSeries_1:
        EXCEPTION_PROLOG_0(PACA_EXGEN)
        b       vsx_unavailable_pSeries
 
+facility_unavailable_trampoline:
        . = 0xf60
        SET_SCRATCH0(r13)
        EXCEPTION_PROLOG_0(PACA_EXGEN)
-       b       tm_unavailable_pSeries
+       b       facility_unavailable_pSeries
+
+hv_facility_unavailable_trampoline:
+       . = 0xf80
+       SET_SCRATCH0(r13)
+       EXCEPTION_PROLOG_0(PACA_EXGEN)
+       b       facility_unavailable_hv
 
 #ifdef CONFIG_CBE_RAS
        STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error)
@@ -522,8 +529,10 @@ denorm_done:
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf20)
        STD_EXCEPTION_PSERIES_OOL(0xf40, vsx_unavailable)
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf40)
-       STD_EXCEPTION_PSERIES_OOL(0xf60, tm_unavailable)
+       STD_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable)
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf60)
+       STD_EXCEPTION_HV_OOL(0xf82, facility_unavailable)
+       KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xf82)
 
 /*
  * An interrupt came in while soft-disabled. We set paca->irq_happened, then:
@@ -793,14 +802,10 @@ system_call_relon_pSeries:
        STD_RELON_EXCEPTION_PSERIES(0x4d00, 0xd00, single_step)
 
        . = 0x4e00
-       SET_SCRATCH0(r13)
-       EXCEPTION_PROLOG_0(PACA_EXGEN)
-       b       h_data_storage_relon_hv
+       b       .       /* Can't happen, see v2.07 Book III-S section 6.5 */
 
        . = 0x4e20
-       SET_SCRATCH0(r13)
-       EXCEPTION_PROLOG_0(PACA_EXGEN)
-       b       h_instr_storage_relon_hv
+       b       .       /* Can't happen, see v2.07 Book III-S section 6.5 */
 
        . = 0x4e40
        SET_SCRATCH0(r13)
@@ -808,9 +813,7 @@ system_call_relon_pSeries:
        b       emulation_assist_relon_hv
 
        . = 0x4e60
-       SET_SCRATCH0(r13)
-       EXCEPTION_PROLOG_0(PACA_EXGEN)
-       b       hmi_exception_relon_hv
+       b       .       /* Can't happen, see v2.07 Book III-S section 6.5 */
 
        . = 0x4e80
        SET_SCRATCH0(r13)
@@ -835,11 +838,17 @@ vsx_unavailable_relon_pSeries_1:
        EXCEPTION_PROLOG_0(PACA_EXGEN)
        b       vsx_unavailable_relon_pSeries
 
-tm_unavailable_relon_pSeries_1:
+facility_unavailable_relon_trampoline:
        . = 0x4f60
        SET_SCRATCH0(r13)
        EXCEPTION_PROLOG_0(PACA_EXGEN)
-       b       tm_unavailable_relon_pSeries
+       b       facility_unavailable_relon_pSeries
+
+hv_facility_unavailable_relon_trampoline:
+       . = 0x4f80
+       SET_SCRATCH0(r13)
+       EXCEPTION_PROLOG_0(PACA_EXGEN)
+       b       hv_facility_unavailable_relon_hv
 
        STD_RELON_EXCEPTION_PSERIES(0x5300, 0x1300, instruction_breakpoint)
 #ifdef CONFIG_PPC_DENORMALISATION
@@ -1165,36 +1174,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
        bl      .vsx_unavailable_exception
        b       .ret_from_except
 
-       .align  7
-       .globl tm_unavailable_common
-tm_unavailable_common:
-       EXCEPTION_PROLOG_COMMON(0xf60, PACA_EXGEN)
-       bl      .save_nvgprs
-       DISABLE_INTS
-       addi    r3,r1,STACK_FRAME_OVERHEAD
-       bl      .tm_unavailable_exception
-       b       .ret_from_except
+       STD_EXCEPTION_COMMON(0xf60, facility_unavailable, .facility_unavailable_exception)
+       STD_EXCEPTION_COMMON(0xf80, hv_facility_unavailable, .facility_unavailable_exception)
 
        .align  7
        .globl  __end_handlers
 __end_handlers:
 
        /* Equivalents to the above handlers for relocation-on interrupt vectors */
-       STD_RELON_EXCEPTION_HV_OOL(0xe00, h_data_storage)
-       KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe00)
-       STD_RELON_EXCEPTION_HV_OOL(0xe20, h_instr_storage)
-       KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe20)
        STD_RELON_EXCEPTION_HV_OOL(0xe40, emulation_assist)
-       KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe40)
-       STD_RELON_EXCEPTION_HV_OOL(0xe60, hmi_exception)
-       KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe60)
        MASKABLE_RELON_EXCEPTION_HV_OOL(0xe80, h_doorbell)
-       KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe80)
 
        STD_RELON_EXCEPTION_PSERIES_OOL(0xf00, performance_monitor)
        STD_RELON_EXCEPTION_PSERIES_OOL(0xf20, altivec_unavailable)
        STD_RELON_EXCEPTION_PSERIES_OOL(0xf40, vsx_unavailable)
-       STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, tm_unavailable)
+       STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable)
+       STD_RELON_EXCEPTION_HV_OOL(0xf80, hv_facility_unavailable)
 
 #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
index a949bdfc9623b5bd9bbfca9dfdc0ec2b37214417..f0b47d1a6b0ebd92dddd3ed49275e40a361c72ea 100644 (file)
@@ -176,7 +176,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
                length_max = 512 ; /* 64 doublewords */
                /* DAWR region can't cross 512 boundary */
                if ((bp->attr.bp_addr >> 10) != 
-                   ((bp->attr.bp_addr + bp->attr.bp_len) >> 10))
+                   ((bp->attr.bp_addr + bp->attr.bp_len - 1) >> 10))
                        return -EINVAL;
        }
        if (info->len >
@@ -250,6 +250,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
         * we still need to single-step the instruction, but we don't
         * generate an event.
         */
+       info->type &= ~HW_BRK_TYPE_EXTRANEOUS_IRQ;
        if (!((bp->attr.bp_addr <= dar) &&
              (dar - bp->attr.bp_addr < bp->attr.bp_len)))
                info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ;
index d92f3871e9cf959b583cf35b03de95929fc253ed..e2a0a162299b480b76b2a20ed26eb1dc69c01d16 100644 (file)
 #include <asm/vdso_datapage.h>
 #include <asm/vio.h>
 #include <asm/mmu.h>
+#include <asm/machdep.h>
 
+
+/*
+ * This isn't a module but we expose that to userspace
+ * via /proc so leave the definitions here
+ */
 #define MODULE_VERS "1.9"
 #define MODULE_NAME "lparcfg"
 
@@ -418,7 +424,8 @@ static void parse_em_data(struct seq_file *m)
 {
        unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
 
-       if (plpar_hcall(H_GET_EM_PARMS, retbuf) == H_SUCCESS)
+       if (firmware_has_feature(FW_FEATURE_LPAR) &&
+           plpar_hcall(H_GET_EM_PARMS, retbuf) == H_SUCCESS)
                seq_printf(m, "power_mode_data=%016lx\n", retbuf[0]);
 }
 
@@ -677,7 +684,6 @@ static int lparcfg_open(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations lparcfg_fops = {
-       .owner          = THIS_MODULE,
        .read           = seq_read,
        .write          = lparcfg_write,
        .open           = lparcfg_open,
@@ -699,14 +705,4 @@ static int __init lparcfg_init(void)
        }
        return 0;
 }
-
-static void __exit lparcfg_cleanup(void)
-{
-       remove_proc_subtree("powerpc/lparcfg", NULL);
-}
-
-module_init(lparcfg_init);
-module_exit(lparcfg_cleanup);
-MODULE_DESCRIPTION("Interface for LPAR configuration data");
-MODULE_AUTHOR("Dave Engebretsen");
-MODULE_LICENSE("GPL");
+machine_device_initcall(pseries, lparcfg_init);
index 076d1242507a7fdcf32c374b66b3b005eb4e0db9..7baa27b7abbeb94596e4151135ddef3bd1c0b47d 100644 (file)
@@ -600,6 +600,16 @@ struct task_struct *__switch_to(struct task_struct *prev,
        struct ppc64_tlb_batch *batch;
 #endif
 
+       /* Back up the TAR across context switches.
+        * Note that the TAR is not available for use in the kernel.  (To
+        * provide this, the TAR should be backed up/restored on exception
+        * entry/exit instead, and be in pt_regs.  FIXME, this should be in
+        * pt_regs anyway (for debug).)
+        * Save the TAR here before we do treclaim/trecheckpoint as these
+        * will change the TAR.
+        */
+       save_tar(&prev->thread);
+
        __switch_to_tm(prev);
 
 #ifdef CONFIG_SMP
index 98c2fc198712aabe3f90055e24d653df604be78e..64f7bd5b1b0f59bcf23fa47c22eb012a5a440b16 100644 (file)
@@ -1449,7 +1449,9 @@ static long ppc_set_hwdebug(struct task_struct *child,
         */
        if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE) {
                len = bp_info->addr2 - bp_info->addr;
-       } else if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) {
+       } else if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT)
+               len = 1;
+       else {
                ptrace_put_breakpoints(child);
                return -EINVAL;
        }
index e379d3fd16948cff85732eb5287dfc49557e9edc..389fb8077cc9cea25746b12497673dd573d35c56 100644 (file)
@@ -76,7 +76,7 @@
 #endif
 
 int boot_cpuid = 0;
-int __initdata spinning_secondaries;
+int spinning_secondaries;
 u64 ppc64_pft_size;
 
 /* Pick defaults since we might want to patch instructions
index 201385c3a1ae186f9de8102d0f5a8d645c36a6d4..0f83122e6676cf8dd8692d3e64f72a2c961f34bb 100644 (file)
@@ -407,7 +407,8 @@ inline unsigned long copy_transact_fpr_from_user(struct task_struct *task,
  * altivec/spe instructions at some point.
  */
 static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
-               int sigret, int ctx_has_vsx_region)
+                         struct mcontext __user *tm_frame, int sigret,
+                         int ctx_has_vsx_region)
 {
        unsigned long msr = regs->msr;
 
@@ -475,6 +476,12 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
 
        if (__put_user(msr, &frame->mc_gregs[PT_MSR]))
                return 1;
+       /* We need to write 0 the MSR top 32 bits in the tm frame so that we
+        * can check it on the restore to see if TM is active
+        */
+       if (tm_frame && __put_user(0, &tm_frame->mc_gregs[PT_MSR]))
+               return 1;
+
        if (sigret) {
                /* Set up the sigreturn trampoline: li r0,sigret; sc */
                if (__put_user(0x38000000UL + sigret, &frame->tramp[0])
@@ -747,7 +754,7 @@ static long restore_tm_user_regs(struct pt_regs *regs,
                                 struct mcontext __user *tm_sr)
 {
        long err;
-       unsigned long msr;
+       unsigned long msr, msr_hi;
 #ifdef CONFIG_VSX
        int i;
 #endif
@@ -852,8 +859,11 @@ static long restore_tm_user_regs(struct pt_regs *regs,
        tm_enable();
        /* This loads the checkpointed FP/VEC state, if used */
        tm_recheckpoint(&current->thread, msr);
-       /* The task has moved into TM state S, so ensure MSR reflects this */
-       regs->msr = (regs->msr & ~MSR_TS_MASK) | MSR_TS_S;
+       /* Get the top half of the MSR */
+       if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR]))
+               return 1;
+       /* Pull in MSR TM from user context */
+       regs->msr = (regs->msr & ~MSR_TS_MASK) | ((msr_hi<<32) & MSR_TS_MASK);
 
        /* This loads the speculative FP/VEC state, if used */
        if (msr & MSR_FP) {
@@ -952,6 +962,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
 {
        struct rt_sigframe __user *rt_sf;
        struct mcontext __user *frame;
+       struct mcontext __user *tm_frame = NULL;
        void __user *addr;
        unsigned long newsp = 0;
        int sigret;
@@ -985,23 +996,24 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
        }
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       tm_frame = &rt_sf->uc_transact.uc_mcontext;
        if (MSR_TM_ACTIVE(regs->msr)) {
-               if (save_tm_user_regs(regs, &rt_sf->uc.uc_mcontext,
-                                     &rt_sf->uc_transact.uc_mcontext, sigret))
+               if (save_tm_user_regs(regs, frame, tm_frame, sigret))
                        goto badframe;
        }
        else
 #endif
-               if (save_user_regs(regs, frame, sigret, 1))
+       {
+               if (save_user_regs(regs, frame, tm_frame, sigret, 1))
                        goto badframe;
+       }
        regs->link = tramp;
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        if (MSR_TM_ACTIVE(regs->msr)) {
                if (__put_user((unsigned long)&rt_sf->uc_transact,
                               &rt_sf->uc.uc_link)
-                   || __put_user(to_user_ptr(&rt_sf->uc_transact.uc_mcontext),
-                                 &rt_sf->uc_transact.uc_regs))
+                   || __put_user((unsigned long)tm_frame, &rt_sf->uc_transact.uc_regs))
                        goto badframe;
        }
        else
@@ -1170,7 +1182,7 @@ long sys_swapcontext(struct ucontext __user *old_ctx,
                mctx = (struct mcontext __user *)
                        ((unsigned long) &old_ctx->uc_mcontext & ~0xfUL);
                if (!access_ok(VERIFY_WRITE, old_ctx, ctx_size)
-                   || save_user_regs(regs, mctx, 0, ctx_has_vsx_region)
+                   || save_user_regs(regs, mctx, NULL, 0, ctx_has_vsx_region)
                    || put_sigset_t(&old_ctx->uc_sigmask, &current->blocked)
                    || __put_user(to_user_ptr(mctx), &old_ctx->uc_regs))
                        return -EFAULT;
@@ -1233,7 +1245,7 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
                if (__get_user(msr_hi, &mcp->mc_gregs[PT_MSR]))
                        goto bad;
 
-               if (MSR_TM_SUSPENDED(msr_hi<<32)) {
+               if (MSR_TM_ACTIVE(msr_hi<<32)) {
                        /* We only recheckpoint on return if we're
                         * transaction.
                         */
@@ -1392,6 +1404,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
 {
        struct sigcontext __user *sc;
        struct sigframe __user *frame;
+       struct mcontext __user *tm_mctx = NULL;
        unsigned long newsp = 0;
        int sigret;
        unsigned long tramp;
@@ -1425,6 +1438,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
        }
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       tm_mctx = &frame->mctx_transact;
        if (MSR_TM_ACTIVE(regs->msr)) {
                if (save_tm_user_regs(regs, &frame->mctx, &frame->mctx_transact,
                                      sigret))
@@ -1432,8 +1446,10 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
        }
        else
 #endif
-               if (save_user_regs(regs, &frame->mctx, sigret, 1))
+       {
+               if (save_user_regs(regs, &frame->mctx, tm_mctx, sigret, 1))
                        goto badframe;
+       }
 
        regs->link = tramp;
 
@@ -1481,16 +1497,22 @@ badframe:
 long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
                       struct pt_regs *regs)
 {
+       struct sigframe __user *sf;
        struct sigcontext __user *sc;
        struct sigcontext sigctx;
        struct mcontext __user *sr;
        void __user *addr;
        sigset_t set;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       struct mcontext __user *mcp, *tm_mcp;
+       unsigned long msr_hi;
+#endif
 
        /* Always make any pending restarted system calls return -EINTR */
        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
-       sc = (struct sigcontext __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
+       sf = (struct sigframe __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
+       sc = &sf->sctx;
        addr = sc;
        if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
                goto badframe;
@@ -1507,11 +1529,25 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
 #endif
        set_current_blocked(&set);
 
-       sr = (struct mcontext __user *)from_user_ptr(sigctx.regs);
-       addr = sr;
-       if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
-           || restore_user_regs(regs, sr, 1))
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       mcp = (struct mcontext __user *)&sf->mctx;
+       tm_mcp = (struct mcontext __user *)&sf->mctx_transact;
+       if (__get_user(msr_hi, &tm_mcp->mc_gregs[PT_MSR]))
                goto badframe;
+       if (MSR_TM_ACTIVE(msr_hi<<32)) {
+               if (!cpu_has_feature(CPU_FTR_TM))
+                       goto badframe;
+               if (restore_tm_user_regs(regs, mcp, tm_mcp))
+                       goto badframe;
+       } else
+#endif
+       {
+               sr = (struct mcontext __user *)from_user_ptr(sigctx.regs);
+               addr = sr;
+               if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
+                   || restore_user_regs(regs, sr, 1))
+                       goto badframe;
+       }
 
        set_thread_flag(TIF_RESTOREALL);
        return 0;
index 345947367ec00a4fa440e162005864d9708eae6a..887e99d85bc270eefeb949d30dcf4d45fd3d3647 100644 (file)
@@ -410,6 +410,10 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
 
        /* get MSR separately, transfer the LE bit if doing signal return */
        err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
+       /* pull in MSR TM from user context */
+       regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr & MSR_TS_MASK);
+
+       /* pull in MSR LE from user context */
        regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE);
 
        /* The following non-GPR non-FPR non-VR state is also checkpointed: */
@@ -505,8 +509,6 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
        tm_enable();
        /* This loads the checkpointed FP/VEC state, if used */
        tm_recheckpoint(&current->thread, msr);
-       /* The task has moved into TM state S, so ensure MSR reflects this: */
-       regs->msr = (regs->msr & ~MSR_TS_MASK) | __MASK(33);
 
        /* This loads the speculative FP/VEC state, if used */
        if (msr & MSR_FP) {
@@ -654,7 +656,7 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        if (__get_user(msr, &uc->uc_mcontext.gp_regs[PT_MSR]))
                goto badframe;
-       if (MSR_TM_SUSPENDED(msr)) {
+       if (MSR_TM_ACTIVE(msr)) {
                /* We recheckpoint on return. */
                struct ucontext __user *uc_transact;
                if (__get_user(uc_transact, &uc->uc_link))
index 2da67e7a16d58650e10a0b6113b705bd88a6f2d3..1edd6c2a168d45f88fc2b138e1a61a734289ed64 100644 (file)
@@ -224,6 +224,16 @@ dont_backup_fp:
        std     r5, _CCR(r7)
        std     r6, _XER(r7)
 
+
+       /* ******************** TAR, PPR, DSCR ********** */
+       mfspr   r3, SPRN_TAR
+       mfspr   r4, SPRN_PPR
+       mfspr   r5, SPRN_DSCR
+
+       std     r3, THREAD_TM_TAR(r12)
+       std     r4, THREAD_TM_PPR(r12)
+       std     r5, THREAD_TM_DSCR(r12)
+
        /* MSR and flags:  We don't change CRs, and we don't need to alter
         * MSR.
         */
@@ -338,6 +348,16 @@ dont_restore_fp:
        mtmsr   r6                              /* FP/Vec off again! */
 
 restore_gprs:
+
+       /* ******************** TAR, PPR, DSCR ********** */
+       ld      r4, THREAD_TM_TAR(r3)
+       ld      r5, THREAD_TM_PPR(r3)
+       ld      r6, THREAD_TM_DSCR(r3)
+
+       mtspr   SPRN_TAR,       r4
+       mtspr   SPRN_PPR,       r5
+       mtspr   SPRN_DSCR,      r6
+
        /* ******************** CR,LR,CCR,MSR ********** */
        ld      r3, _CTR(r7)
        ld      r4, _LINK(r7)
index c0e5caf8ccc72c0f7624b1e7dc9c3f7ecfe4b242..88929b1f4f77b11b68812ed699ef50df1b99c812 100644 (file)
@@ -44,9 +44,7 @@
 #include <asm/machdep.h>
 #include <asm/rtas.h>
 #include <asm/pmc.h>
-#ifdef CONFIG_PPC32
 #include <asm/reg.h>
-#endif
 #ifdef CONFIG_PMAC_BACKLIGHT
 #include <asm/backlight.h>
 #endif
@@ -1282,26 +1280,63 @@ void vsx_unavailable_exception(struct pt_regs *regs)
        die("Unrecoverable VSX Unavailable Exception", regs, SIGABRT);
 }
 
-void tm_unavailable_exception(struct pt_regs *regs)
+#ifdef CONFIG_PPC64
+void facility_unavailable_exception(struct pt_regs *regs)
 {
+       static char *facility_strings[] = {
+               [FSCR_FP_LG] = "FPU",
+               [FSCR_VECVSX_LG] = "VMX/VSX",
+               [FSCR_DSCR_LG] = "DSCR",
+               [FSCR_PM_LG] = "PMU SPRs",
+               [FSCR_BHRB_LG] = "BHRB",
+               [FSCR_TM_LG] = "TM",
+               [FSCR_EBB_LG] = "EBB",
+               [FSCR_TAR_LG] = "TAR",
+       };
+       char *facility = "unknown";
+       u64 value;
+       u8 status;
+       bool hv;
+
+       hv = (regs->trap == 0xf80);
+       if (hv)
+               value = mfspr(SPRN_HFSCR);
+       else
+               value = mfspr(SPRN_FSCR);
+
+       status = value >> 56;
+       if (status == FSCR_DSCR_LG) {
+               /* User is acessing the DSCR.  Set the inherit bit and allow
+                * the user to set it directly in future by setting via the
+                * H/FSCR DSCR bit.
+                */
+               current->thread.dscr_inherit = 1;
+               if (hv)
+                       mtspr(SPRN_HFSCR, value | HFSCR_DSCR);
+               else
+                       mtspr(SPRN_FSCR,  value | FSCR_DSCR);
+               return;
+       }
+
+       if ((status < ARRAY_SIZE(facility_strings)) &&
+           facility_strings[status])
+               facility = facility_strings[status];
+
        /* We restore the interrupt state now */
        if (!arch_irq_disabled_regs(regs))
                local_irq_enable();
 
-       /* Currently we never expect a TMU exception.  Catch
-        * this and kill the process!
-        */
-       printk(KERN_EMERG "Unexpected TM unavailable exception at %lx "
-              "(msr %lx)\n",
-              regs->nip, regs->msr);
+       pr_err("%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n",
+              hv ? "Hypervisor " : "", facility, regs->nip, regs->msr);
 
        if (user_mode(regs)) {
                _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
                return;
        }
 
-       die("Unexpected TM unavailable exception", regs, SIGABRT);
+       die("Unexpected facility unavailable exception", regs, SIGABRT);
 }
+#endif
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 
index 654e479802f2098afb74c0fea0bb0b68e25707f5..f096e72262f41d121398f8fa27d5286bd8641bf4 100644 (file)
@@ -38,9 +38,6 @@ jiffies = jiffies_64 + 4;
 #endif
 SECTIONS
 {
-       . = 0;
-       reloc_start = .;
-
        . = KERNELBASE;
 
 /*
index 94c1dd46b83d54e98a96c6af3b2e682072f027e6..a3a5cb8ee7eac2baa68cfb809e6a4eebce5457a9 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/hvcall.h>
 #include <asm/xics.h>
 #include <asm/debug.h>
+#include <asm/time.h>
 
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
index 88c0425dc0a88f41f61c38b4d01888ec468a937c..cafad4017765650463ba60dd0e11ea29d5179bcb 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
+#include <asm/cputhreads.h>
 #include <asm/sparsemem.h>
 #include <asm/prom.h>
 #include <asm/smp.h>
@@ -1319,7 +1320,8 @@ static int update_cpu_associativity_changes_mask(void)
                        }
                }
                if (changed) {
-                       cpumask_set_cpu(cpu, changes);
+                       cpumask_or(changes, changes, cpu_sibling_mask(cpu));
+                       cpu = cpu_last_thread_sibling(cpu);
                }
        }
 
@@ -1427,17 +1429,15 @@ static int update_cpu_topology(void *data)
        if (!data)
                return -EINVAL;
 
-       cpu = get_cpu();
+       cpu = smp_processor_id();
 
        for (update = data; update; update = update->next) {
                if (cpu != update->cpu)
                        continue;
 
-               unregister_cpu_under_node(update->cpu, update->old_nid);
                unmap_cpu_from_node(update->cpu);
                map_cpu_to_node(update->cpu, update->new_nid);
                vdso_getcpu_init();
-               register_cpu_under_node(update->cpu, update->new_nid);
        }
 
        return 0;
@@ -1449,12 +1449,12 @@ static int update_cpu_topology(void *data)
  */
 int arch_update_cpu_topology(void)
 {
-       unsigned int cpu, changed = 0;
+       unsigned int cpu, sibling, changed = 0;
        struct topology_update_data *updates, *ud;
        unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0};
        cpumask_t updated_cpus;
        struct device *dev;
-       int weight, i = 0;
+       int weight, new_nid, i = 0;
 
        weight = cpumask_weight(&cpu_associativity_changes_mask);
        if (!weight)
@@ -1467,24 +1467,54 @@ int arch_update_cpu_topology(void)
        cpumask_clear(&updated_cpus);
 
        for_each_cpu(cpu, &cpu_associativity_changes_mask) {
-               ud = &updates[i++];
-               ud->cpu = cpu;
-               vphn_get_associativity(cpu, associativity);
-               ud->new_nid = associativity_to_nid(associativity);
-
-               if (ud->new_nid < 0 || !node_online(ud->new_nid))
-                       ud->new_nid = first_online_node;
+               /*
+                * If siblings aren't flagged for changes, updates list
+                * will be too short. Skip on this update and set for next
+                * update.
+                */
+               if (!cpumask_subset(cpu_sibling_mask(cpu),
+                                       &cpu_associativity_changes_mask)) {
+                       pr_info("Sibling bits not set for associativity "
+                                       "change, cpu%d\n", cpu);
+                       cpumask_or(&cpu_associativity_changes_mask,
+                                       &cpu_associativity_changes_mask,
+                                       cpu_sibling_mask(cpu));
+                       cpu = cpu_last_thread_sibling(cpu);
+                       continue;
+               }
 
-               ud->old_nid = numa_cpu_lookup_table[cpu];
-               cpumask_set_cpu(cpu, &updated_cpus);
+               /* Use associativity from first thread for all siblings */
+               vphn_get_associativity(cpu, associativity);
+               new_nid = associativity_to_nid(associativity);
+               if (new_nid < 0 || !node_online(new_nid))
+                       new_nid = first_online_node;
+
+               if (new_nid == numa_cpu_lookup_table[cpu]) {
+                       cpumask_andnot(&cpu_associativity_changes_mask,
+                                       &cpu_associativity_changes_mask,
+                                       cpu_sibling_mask(cpu));
+                       cpu = cpu_last_thread_sibling(cpu);
+                       continue;
+               }
 
-               if (i < weight)
-                       ud->next = &updates[i];
+               for_each_cpu(sibling, cpu_sibling_mask(cpu)) {
+                       ud = &updates[i++];
+                       ud->cpu = sibling;
+                       ud->new_nid = new_nid;
+                       ud->old_nid = numa_cpu_lookup_table[sibling];
+                       cpumask_set_cpu(sibling, &updated_cpus);
+                       if (i < weight)
+                               ud->next = &updates[i];
+               }
+               cpu = cpu_last_thread_sibling(cpu);
        }
 
        stop_machine(update_cpu_topology, &updates[0], &updated_cpus);
 
        for (ud = &updates[0]; ud; ud = ud->next) {
+               unregister_cpu_under_node(ud->cpu, ud->old_nid);
+               register_cpu_under_node(ud->cpu, ud->new_nid);
+
                dev = get_cpu_device(ud->cpu);
                if (dev)
                        kobject_uevent(&dev->kobj, KOBJ_CHANGE);
index 29c6482890c88c89f8fbb159d5561b591b47c09f..d3ee2e50a3a6fbc44bac15c9fb5ec4dfff889867 100644 (file)
@@ -75,6 +75,8 @@ static unsigned int freeze_events_kernel = MMCR0_FCS;
 
 #define MMCR0_FCHV             0
 #define MMCR0_PMCjCE           MMCR0_PMCnCE
+#define MMCR0_FC56             0
+#define MMCR0_PMAO             0
 
 #define SPRN_MMCRA             SPRN_MMCR2
 #define MMCRA_SAMPLE_ENABLE    0
@@ -852,7 +854,7 @@ static void write_mmcr0(struct cpu_hw_events *cpuhw, unsigned long mmcr0)
 static void power_pmu_disable(struct pmu *pmu)
 {
        struct cpu_hw_events *cpuhw;
-       unsigned long flags;
+       unsigned long flags, val;
 
        if (!ppmu)
                return;
@@ -860,9 +862,6 @@ static void power_pmu_disable(struct pmu *pmu)
        cpuhw = &__get_cpu_var(cpu_hw_events);
 
        if (!cpuhw->disabled) {
-               cpuhw->disabled = 1;
-               cpuhw->n_added = 0;
-
                /*
                 * Check if we ever enabled the PMU on this cpu.
                 */
@@ -871,6 +870,21 @@ static void power_pmu_disable(struct pmu *pmu)
                        cpuhw->pmcs_enabled = 1;
                }
 
+               /*
+                * Set the 'freeze counters' bit, clear PMAO/FC56.
+                */
+               val  = mfspr(SPRN_MMCR0);
+               val |= MMCR0_FC;
+               val &= ~(MMCR0_PMAO | MMCR0_FC56);
+
+               /*
+                * The barrier is to make sure the mtspr has been
+                * executed and the PMU has frozen the events etc.
+                * before we return.
+                */
+               write_mmcr0(cpuhw, val);
+               mb();
+
                /*
                 * Disable instruction sampling if it was enabled
                 */
@@ -880,14 +894,8 @@ static void power_pmu_disable(struct pmu *pmu)
                        mb();
                }
 
-               /*
-                * Set the 'freeze counters' bit.
-                * The barrier is to make sure the mtspr has been
-                * executed and the PMU has frozen the events
-                * before we return.
-                */
-               write_mmcr0(cpuhw, mfspr(SPRN_MMCR0) | MMCR0_FC);
-               mb();
+               cpuhw->disabled = 1;
+               cpuhw->n_added = 0;
        }
        local_irq_restore(flags);
 }
@@ -911,12 +919,18 @@ static void power_pmu_enable(struct pmu *pmu)
 
        if (!ppmu)
                return;
+
        local_irq_save(flags);
+
        cpuhw = &__get_cpu_var(cpu_hw_events);
-       if (!cpuhw->disabled) {
-               local_irq_restore(flags);
-               return;
+       if (!cpuhw->disabled)
+               goto out;
+
+       if (cpuhw->n_events == 0) {
+               ppc_set_pmu_inuse(0);
+               goto out;
        }
+
        cpuhw->disabled = 0;
 
        /*
@@ -928,8 +942,6 @@ static void power_pmu_enable(struct pmu *pmu)
        if (!cpuhw->n_added) {
                mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE);
                mtspr(SPRN_MMCR1, cpuhw->mmcr[1]);
-               if (cpuhw->n_events == 0)
-                       ppc_set_pmu_inuse(0);
                goto out_enable;
        }
 
index f7d1c4fff30308c5febe047665ff95486a9f8412..d59f5b2d4c2f6922cebaecf41b3d99b80a925b69 100644 (file)
 #define EVENT_IS_MARKED                (EVENT_MARKED_MASK << EVENT_MARKED_SHIFT)
 #define EVENT_PSEL_MASK                0xff    /* PMCxSEL value */
 
+#define EVENT_VALID_MASK       \
+       ((EVENT_THRESH_MASK    << EVENT_THRESH_SHIFT)           |       \
+        (EVENT_SAMPLE_MASK    << EVENT_SAMPLE_SHIFT)           |       \
+        (EVENT_CACHE_SEL_MASK << EVENT_CACHE_SEL_SHIFT)        |       \
+        (EVENT_PMC_MASK       << EVENT_PMC_SHIFT)              |       \
+        (EVENT_UNIT_MASK      << EVENT_UNIT_SHIFT)             |       \
+        (EVENT_COMBINE_MASK   << EVENT_COMBINE_SHIFT)          |       \
+        (EVENT_MARKED_MASK    << EVENT_MARKED_SHIFT)           |       \
+         EVENT_PSEL_MASK)
+
 /* MMCRA IFM bits - POWER8 */
 #define        POWER8_MMCRA_IFM1               0x0000000040000000UL
 #define        POWER8_MMCRA_IFM2               0x0000000080000000UL
@@ -212,6 +222,9 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long
 
        mask = value = 0;
 
+       if (event & ~EVENT_VALID_MASK)
+               return -1;
+
        pmc   = (event >> EVENT_PMC_SHIFT)       & EVENT_PMC_MASK;
        unit  = (event >> EVENT_UNIT_SHIFT)      & EVENT_UNIT_MASK;
        cache = (event >> EVENT_CACHE_SEL_SHIFT) & EVENT_CACHE_SEL_MASK;
@@ -378,6 +391,10 @@ static int power8_compute_mmcr(u64 event[], int n_ev,
        if (pmc_inuse & 0x7c)
                mmcr[0] |= MMCR0_PMCjCE;
 
+       /* If we're not using PMC 5 or 6, freeze them */
+       if (!(pmc_inuse & 0x60))
+               mmcr[0] |= MMCR0_FC56;
+
        mmcr[1] = mmcr1;
        mmcr[2] = mmcra;
 
index 9c9d15e4cdf2700f803471667f83720430844c68..7816beff1db8625b5ca97c892f0a106b01af45ee 100644 (file)
@@ -441,6 +441,17 @@ static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev
        set_iommu_table_base(&pdev->dev, &pe->tce32_table);
 }
 
+static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus)
+{
+       struct pci_dev *dev;
+
+       list_for_each_entry(dev, &bus->devices, bus_list) {
+               set_iommu_table_base(&dev->dev, &pe->tce32_table);
+               if (dev->subordinate)
+                       pnv_ioda_setup_bus_dma(pe, dev->subordinate);
+       }
+}
+
 static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl,
                                         u64 *startp, u64 *endp)
 {
@@ -596,6 +607,11 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
        }
        iommu_init_table(tbl, phb->hose->node);
 
+       if (pe->pdev)
+               set_iommu_table_base(&pe->pdev->dev, tbl);
+       else
+               pnv_ioda_setup_bus_dma(pe, pe->pbus);
+
        return;
  fail:
        /* XXX Failure: Try to fallback to 64-bit only ? */
@@ -667,6 +683,11 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
        }
        iommu_init_table(tbl, phb->hose->node);
 
+       if (pe->pdev)
+               set_iommu_table_base(&pe->pdev->dev, tbl);
+       else
+               pnv_ioda_setup_bus_dma(pe, pe->pbus);
+
        return;
 fail:
        if (pe->tce32_seg >= 0)
index 3afad933593ac6afabad03554acd59a49d22d683..995cc0457c7615855735502a9913ff734e187622 100644 (file)
@@ -354,7 +354,7 @@ static int alloc_dispatch_log_kmem_cache(void)
 }
 early_initcall(alloc_dispatch_log_kmem_cache);
 
-static void pSeries_idle(void)
+static void pseries_lpar_idle(void)
 {
        /* This would call on the cpuidle framework, and the back-end pseries
         * driver to  go to idle states
@@ -362,10 +362,22 @@ static void pSeries_idle(void)
        if (cpuidle_idle_call()) {
                /* On error, execute default handler
                 * to go into low thread priority and possibly
-                * low power mode.
+                * low power mode by cedeing processor to hypervisor
                 */
-               HMT_low();
-               HMT_very_low();
+
+               /* Indicate to hypervisor that we are idle. */
+               get_lppaca()->idle = 1;
+
+               /*
+                * Yield the processor to the hypervisor.  We return if
+                * an external interrupt occurs (which are driven prior
+                * to returning here) or if a prod occurs from another
+                * processor. When returning here, external interrupts
+                * are enabled.
+                */
+               cede_processor();
+
+               get_lppaca()->idle = 0;
        }
 }
 
@@ -456,15 +468,14 @@ static void __init pSeries_setup_arch(void)
 
        pSeries_nvram_init();
 
-       if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
+       if (firmware_has_feature(FW_FEATURE_LPAR)) {
                vpa_init(boot_cpuid);
-               ppc_md.power_save = pSeries_idle;
-       }
-
-       if (firmware_has_feature(FW_FEATURE_LPAR))
+               ppc_md.power_save = pseries_lpar_idle;
                ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
-       else
+       } else {
+               /* No special idle routine */
                ppc_md.enable_pmcs = power4_enable_pmcs;
+       }
 
        ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare;
 
index da183c5a103ce1df1da3617bbde788011f0351d3..97dcbea97a1cca2eff1b7988cf5e761d910797d4 100644 (file)
@@ -227,11 +227,12 @@ config MARCH_Z196
          not work on older machines.
 
 config MARCH_ZEC12
-       bool "IBM zEC12"
+       bool "IBM zBC12 and zEC12"
        select HAVE_MARCH_ZEC12_FEATURES if 64BIT
        help
-         Select this to enable optimizations for IBM zEC12 (2827 series). The
-         kernel will be slightly faster but will not work on older machines.
+         Select this to enable optimizations for IBM zBC12 and zEC12 (2828 and
+         2827 series). The kernel will be slightly faster but will not work on
+         older machines.
 
 endchoice
 
index 4d8604e311f3aaf6b1799bd78760bcc52a5befab..7d46767587337c3874bd61c43e01a0a72f965303 100644 (file)
@@ -693,7 +693,7 @@ static inline int find_next_bit_left(const unsigned long *addr,
        size -= offset;
        p = addr + offset / BITS_PER_LONG;
        if (bit) {
-               set = __flo_word(0, *p & (~0UL << bit));
+               set = __flo_word(0, *p & (~0UL >> bit));
                if (set >= size)
                        return size + offset;
                if (set < BITS_PER_LONG)
index b75d7d686684975278e1881a9aaf74590a6949ed..6d6d92b4ea113fbc692cf4dda3cac36d803128fc 100644 (file)
@@ -32,6 +32,7 @@ struct mmu_gather {
        struct mm_struct *mm;
        struct mmu_table_batch *batch;
        unsigned int fullmm;
+       unsigned long start, end;
 };
 
 struct mmu_table_batch {
@@ -48,10 +49,13 @@ extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
 
 static inline void tlb_gather_mmu(struct mmu_gather *tlb,
                                  struct mm_struct *mm,
-                                 unsigned int full_mm_flush)
+                                 unsigned long start,
+                                 unsigned long end)
 {
        tlb->mm = mm;
-       tlb->fullmm = full_mm_flush;
+       tlb->start = start;
+       tlb->end = end;
+       tlb->fullmm = !(start | (end+1));
        tlb->batch = NULL;
        if (tlb->fullmm)
                __tlb_flush_mm(mm);
index 0a49095104c910f238cd9b28a9c79cf7a9958efc..8ad9413148bf20b01eafc9dff8a4fdc09fa01d3a 100644 (file)
@@ -998,6 +998,7 @@ static void __init setup_hwcaps(void)
                strcpy(elf_platform, "z196");
                break;
        case 0x2827:
+       case 0x2828:
                strcpy(elf_platform, "zEC12");
                break;
        }
index c1c7c683fa26d591af0eeac242ee898f88cb9dc2..698fb826e149d9c8c32f629fdb9d982c07c197db 100644 (file)
@@ -622,14 +622,25 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
                kvm_s390_deliver_pending_interrupts(vcpu);
 
        vcpu->arch.sie_block->icptcode = 0;
-       preempt_disable();
-       kvm_guest_enter();
-       preempt_enable();
        VCPU_EVENT(vcpu, 6, "entering sie flags %x",
                   atomic_read(&vcpu->arch.sie_block->cpuflags));
        trace_kvm_s390_sie_enter(vcpu,
                                 atomic_read(&vcpu->arch.sie_block->cpuflags));
+
+       /*
+        * As PF_VCPU will be used in fault handler, between guest_enter
+        * and guest_exit should be no uaccess.
+        */
+       preempt_disable();
+       kvm_guest_enter();
+       preempt_enable();
        rc = sie64a(vcpu->arch.sie_block, vcpu->run->s.regs.gprs);
+       kvm_guest_exit();
+
+       VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
+                  vcpu->arch.sie_block->icptcode);
+       trace_kvm_s390_sie_exit(vcpu, vcpu->arch.sie_block->icptcode);
+
        if (rc) {
                if (kvm_is_ucontrol(vcpu->kvm)) {
                        rc = SIE_INTERCEPT_UCONTROL;
@@ -639,10 +650,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
                        rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
                }
        }
-       VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
-                  vcpu->arch.sie_block->icptcode);
-       trace_kvm_s390_sie_exit(vcpu, vcpu->arch.sie_block->icptcode);
-       kvm_guest_exit();
 
        memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16);
        return rc;
index 89ebae4008f2ff6ec46a40e10327b2302f668705..eba15f18fd38b331de68410a29c303d4429985c3 100644 (file)
@@ -69,6 +69,7 @@ static void __init setup_zero_pages(void)
                order = 2;
                break;
        case 0x2827:    /* zEC12 */
+       case 0x2828:    /* zEC12 */
        default:
                order = 5;
                break;
index ffeb17ce7f313d914a38de3ee21dad5867991b9d..930783d2c99beb305b2346a220f414d98a4ba406 100644 (file)
@@ -440,7 +440,7 @@ static int oprofile_hwsampler_init(struct oprofile_operations *ops)
                switch (id.machine) {
                case 0x2097: case 0x2098: ops->cpu_type = "s390/z10"; break;
                case 0x2817: case 0x2818: ops->cpu_type = "s390/z196"; break;
-               case 0x2827:              ops->cpu_type = "s390/zEC12"; break;
+               case 0x2827: case 0x2828: ops->cpu_type = "s390/zEC12"; break;
                default: return -ENODEV;
                }
        }
index e61d43d9f689c0ef61bc0e1e5e43b3826b66a760..362192ed12fef1789d2c23d21c654f19632006a0 100644 (file)
@@ -36,10 +36,12 @@ static inline void init_tlb_gather(struct mmu_gather *tlb)
 }
 
 static inline void
-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush)
+tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
 {
        tlb->mm = mm;
-       tlb->fullmm = full_mm_flush;
+       tlb->start = start;
+       tlb->end = end;
+       tlb->fullmm = !(start | (end+1));
 
        init_tlb_gather(tlb);
 }
index 961b87f99e694959a9575d5b8aaef0cc37de026b..f76389a3234229a4a99e61ae55a8c70476b5798b 100644 (file)
@@ -49,6 +49,8 @@ int foo(void)
        DEFINE(AOFF_task_thread, offsetof(struct task_struct, thread));
        BLANK();
        DEFINE(AOFF_mm_context, offsetof(struct mm_struct, context));
+       BLANK();
+       DEFINE(VMA_VM_MM,    offsetof(struct vm_area_struct, vm_mm));
 
        /* DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); */
        return 0;
index 44aad32eeb4e604ff1f17730f218285f80659807..969f96450f690a8bc06c159bfc0045479f55a006 100644 (file)
@@ -74,7 +74,7 @@ hypersparc_flush_cache_mm_out:
 
        /* The things we do for performance... */
 hypersparc_flush_cache_range:
-       ld      [%o0 + 0x0], %o0                /* XXX vma->vm_mm, GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
 #ifndef CONFIG_SMP
        ld      [%o0 + AOFF_mm_context], %g1
        cmp     %g1, -1
@@ -163,7 +163,7 @@ hypersparc_flush_cache_range_out:
         */
        /* Verified, my ass... */
 hypersparc_flush_cache_page:
-       ld      [%o0 + 0x0], %o0                /* XXX vma->vm_mm, GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
        ld      [%o0 + AOFF_mm_context], %g2
 #ifndef CONFIG_SMP
        cmp     %g2, -1
@@ -284,7 +284,7 @@ hypersparc_flush_tlb_mm_out:
         sta    %g5, [%g1] ASI_M_MMUREGS
 
 hypersparc_flush_tlb_range:
-       ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
        mov     SRMMU_CTX_REG, %g1
        ld      [%o0 + AOFF_mm_context], %o3
        lda     [%g1] ASI_M_MMUREGS, %g5
@@ -307,7 +307,7 @@ hypersparc_flush_tlb_range_out:
         sta    %g5, [%g1] ASI_M_MMUREGS
 
 hypersparc_flush_tlb_page:
-       ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
        mov     SRMMU_CTX_REG, %g1
        ld      [%o0 + AOFF_mm_context], %o3
        andn    %o1, (PAGE_SIZE - 1), %o1
index c801c3953a00abec66285477c823d944a14040f3..5d2b88d394243157f895c35c330ac51305868e79 100644 (file)
@@ -105,7 +105,7 @@ swift_flush_cache_mm_out:
 
        .globl  swift_flush_cache_range
 swift_flush_cache_range:
-       ld      [%o0 + 0x0], %o0                /* XXX vma->vm_mm, GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
        sub     %o2, %o1, %o2
        sethi   %hi(4096), %o3
        cmp     %o2, %o3
@@ -116,7 +116,7 @@ swift_flush_cache_range:
 
        .globl  swift_flush_cache_page
 swift_flush_cache_page:
-       ld      [%o0 + 0x0], %o0                /* XXX vma->vm_mm, GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
 70:
        ld      [%o0 + AOFF_mm_context], %g2
        cmp     %g2, -1
@@ -219,7 +219,7 @@ swift_flush_sig_insns:
        .globl  swift_flush_tlb_range
        .globl  swift_flush_tlb_all
 swift_flush_tlb_range:
-       ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
 swift_flush_tlb_mm:
        ld      [%o0 + AOFF_mm_context], %g2
        cmp     %g2, -1
@@ -233,7 +233,7 @@ swift_flush_tlb_all_out:
 
        .globl  swift_flush_tlb_page
 swift_flush_tlb_page:
-       ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
        mov     SRMMU_CTX_REG, %g1
        ld      [%o0 + AOFF_mm_context], %o3
        andn    %o1, (PAGE_SIZE - 1), %o1
index 4e55e8f76648a27da7ff666b0fae21590e182651..bf10a345fa8b7857a9e080ef4baa44998ea36d55 100644 (file)
@@ -24,7 +24,7 @@
        /* Sliiick... */
 tsunami_flush_cache_page:
 tsunami_flush_cache_range:
-       ld      [%o0 + 0x0], %o0        /* XXX vma->vm_mm, GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
 tsunami_flush_cache_mm:
        ld      [%o0 + AOFF_mm_context], %g2
        cmp     %g2, -1
@@ -46,7 +46,7 @@ tsunami_flush_sig_insns:
 
        /* More slick stuff... */
 tsunami_flush_tlb_range:
-       ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
 tsunami_flush_tlb_mm:
        ld      [%o0 + AOFF_mm_context], %g2
        cmp     %g2, -1
@@ -65,7 +65,7 @@ tsunami_flush_tlb_out:
 
        /* This one can be done in a fine grained manner... */
 tsunami_flush_tlb_page:
-       ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
        mov     SRMMU_CTX_REG, %g1
        ld      [%o0 + AOFF_mm_context], %o3
        andn    %o1, (PAGE_SIZE - 1), %o1
index bf8ee0613ae7efdb1bb6d6897bb42a11b7621b4b..852257fcc82b83c508bb738b31490d8694cef2dc 100644 (file)
@@ -108,7 +108,7 @@ viking_mxcc_flush_page:
 viking_flush_cache_page:
 viking_flush_cache_range:
 #ifndef CONFIG_SMP
-       ld      [%o0 + 0x0], %o0                /* XXX vma->vm_mm, GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
 #endif
 viking_flush_cache_mm:
 #ifndef CONFIG_SMP
@@ -148,7 +148,7 @@ viking_flush_tlb_mm:
 #endif
 
 viking_flush_tlb_range:
-       ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
        mov     SRMMU_CTX_REG, %g1
        ld      [%o0 + AOFF_mm_context], %o3
        lda     [%g1] ASI_M_MMUREGS, %g5
@@ -173,7 +173,7 @@ viking_flush_tlb_range:
 #endif
 
 viking_flush_tlb_page:
-       ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
        mov     SRMMU_CTX_REG, %g1
        ld      [%o0 + AOFF_mm_context], %o3
        lda     [%g1] ASI_M_MMUREGS, %g5
@@ -239,7 +239,7 @@ sun4dsmp_flush_tlb_range:
        tst     %g5
        bne     3f
         mov    SRMMU_CTX_REG, %g1
-       ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
        ld      [%o0 + AOFF_mm_context], %o3
        lda     [%g1] ASI_M_MMUREGS, %g5
        sethi   %hi(~((1 << SRMMU_PGDIR_SHIFT) - 1)), %o4
@@ -265,7 +265,7 @@ sun4dsmp_flush_tlb_page:
        tst     %g5
        bne     2f
         mov    SRMMU_CTX_REG, %g1
-       ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
+       ld      [%o0 + VMA_VM_MM], %o0
        ld      [%o0 + AOFF_mm_context], %o3
        lda     [%g1] ASI_M_MMUREGS, %g5
        and     %o1, PAGE_MASK, %o1
index 4febacd1a8a1a3dee2c24e3b3447081e7ca94ebb..29b0301c18aab26f2a613d397da9856a8d1eec3b 100644 (file)
@@ -45,10 +45,12 @@ static inline void init_tlb_gather(struct mmu_gather *tlb)
 }
 
 static inline void
-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush)
+tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
 {
        tlb->mm = mm;
-       tlb->fullmm = full_mm_flush;
+       tlb->start = start;
+       tlb->end = end;
+       tlb->fullmm = !(start | (end+1));
 
        init_tlb_gather(tlb);
 }
index 95feaa47a2fbb369512daeb67ffdc19554f837ad..c70a234a3f8c7d4a31938963ef01ba167526d78d 100644 (file)
@@ -200,6 +200,7 @@ extern int os_unmap_memory(void *addr, int len);
 extern int os_drop_memory(void *addr, int length);
 extern int can_drop_memory(void);
 extern void os_flush_stdout(void);
+extern int os_mincore(void *addr, unsigned long len);
 
 /* execvp.c */
 extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
index babe21826e3ed80e2cae8d1956c53b69adb45705..d8b78a03855c6a1ad4c7ada6c96938f5e62ee02a 100644 (file)
@@ -13,7 +13,7 @@ clean-files :=
 obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \
        physmem.o process.o ptrace.o reboot.o sigio.o \
        signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o \
-       um_arch.o umid.o skas/
+       um_arch.o umid.o maccess.o skas/
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
 obj-$(CONFIG_GPROF)    += gprof_syms.o
diff --git a/arch/um/kernel/maccess.c b/arch/um/kernel/maccess.c
new file mode 100644 (file)
index 0000000..1f3d5c4
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 Richard Weinberger <richrd@nod.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/uaccess.h>
+#include <linux/kernel.h>
+#include <os.h>
+
+long probe_kernel_read(void *dst, const void *src, size_t size)
+{
+       void *psrc = (void *)rounddown((unsigned long)src, PAGE_SIZE);
+
+       if ((unsigned long)src < PAGE_SIZE || size <= 0)
+               return -EFAULT;
+
+       if (os_mincore(psrc, size + src - psrc) <= 0)
+               return -EFAULT;
+
+       return __probe_kernel_read(dst, src, size);
+}
index b8f34c9e53ae9fc820f81e215253ec2bc70f9ffc..67b9c8f5a89e95c261faea9a136f933cf7a46e05 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
 #include <signal.h>
@@ -232,6 +233,57 @@ out:
        return ok;
 }
 
+static int os_page_mincore(void *addr)
+{
+       char vec[2];
+       int ret;
+
+       ret = mincore(addr, UM_KERN_PAGE_SIZE, vec);
+       if (ret < 0) {
+               if (errno == ENOMEM || errno == EINVAL)
+                       return 0;
+               else
+                       return -errno;
+       }
+
+       return vec[0] & 1;
+}
+
+int os_mincore(void *addr, unsigned long len)
+{
+       char *vec;
+       int ret, i;
+
+       if (len <= UM_KERN_PAGE_SIZE)
+               return os_page_mincore(addr);
+
+       vec = calloc(1, (len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE);
+       if (!vec)
+               return -ENOMEM;
+
+       ret = mincore(addr, UM_KERN_PAGE_SIZE, vec);
+       if (ret < 0) {
+               if (errno == ENOMEM || errno == EINVAL)
+                       ret = 0;
+               else
+                       ret = -errno;
+
+               goto out;
+       }
+
+       for (i = 0; i < ((len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE); i++) {
+               if (!(vec[i] & 1)) {
+                       ret = 0;
+                       goto out;
+               }
+       }
+
+       ret = 1;
+out:
+       free(vec);
+       return ret;
+}
+
 void init_new_thread_signals(void)
 {
        set_handler(SIGSEGV);
index c205035a6b96b836ef683ddf8592dbc9c82200e6..d606463aa6d63bfdab5641e6bd7e6b68545e32d9 100644 (file)
@@ -992,18 +992,20 @@ static efi_status_t exit_boot(struct boot_params *boot_params,
        efi_memory_desc_t *mem_map;
        efi_status_t status;
        __u32 desc_version;
+       bool called_exit = false;
        u8 nr_entries;
        int i;
 
        size = sizeof(*mem_map) * 32;
 
 again:
-       size += sizeof(*mem_map);
+       size += sizeof(*mem_map) * 2;
        _size = size;
        status = low_alloc(size, 1, (unsigned long *)&mem_map);
        if (status != EFI_SUCCESS)
                return status;
 
+get_map:
        status = efi_call_phys5(sys_table->boottime->get_memory_map, &size,
                                mem_map, &key, &desc_size, &desc_version);
        if (status == EFI_BUFFER_TOO_SMALL) {
@@ -1029,8 +1031,20 @@ again:
        /* Might as well exit boot services now */
        status = efi_call_phys2(sys_table->boottime->exit_boot_services,
                                handle, key);
-       if (status != EFI_SUCCESS)
-               goto free_mem_map;
+       if (status != EFI_SUCCESS) {
+               /*
+                * ExitBootServices() will fail if any of the event
+                * handlers change the memory map. In which case, we
+                * must be prepared to retry, but only once so that
+                * we're guaranteed to exit on repeated failures instead
+                * of spinning forever.
+                */
+               if (called_exit)
+                       goto free_mem_map;
+
+               called_exit = true;
+               goto get_map;
+       }
 
        /* Historic? */
        boot_params->alt_mem_k = 32 * 1024;
index cf1a471a18a2f7dc1178810fc80d8c3b6462c46a..10adb41f162ea772061ec0ce4b395482dcfa0a1c 100644 (file)
@@ -459,7 +459,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
                else
                        put_user_ex(0, &frame->uc.uc_flags);
                put_user_ex(0, &frame->uc.uc_link);
-               err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp);
+               compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp);
 
                if (ksig->ka.sa.sa_flags & SA_RESTORER)
                        restorer = ksig->ka.sa.sa_restorer;
index 653668d140f994e543ad52e46d0c8402d5fe9259..4a8cb8d7cbd5d2b0febd4333931b459e75f1ea1d 100644 (file)
@@ -35,9 +35,9 @@ static void sanitize_boot_params(struct boot_params *boot_params)
         */
        if (boot_params->sentinel) {
                /* fields in boot_params are left uninitialized, clear them */
-               memset(&boot_params->olpc_ofw_header, 0,
+               memset(&boot_params->ext_ramdisk_image, 0,
                       (char *)&boot_params->efi_info -
-                       (char *)&boot_params->olpc_ofw_header);
+                       (char *)&boot_params->ext_ramdisk_image);
                memset(&boot_params->kbd_status, 0,
                       (char *)&boot_params->hdr -
                       (char *)&boot_params->kbd_status);
index 46fc474fd81960e7f1c345dd926fefd316cd2f04..f50de69517384b712c1266a3c98626b888d6953a 100644 (file)
@@ -49,9 +49,15 @@ static inline __wsum csum_partial_copy_from_user(const void __user *src,
                                                 int len, __wsum sum,
                                                 int *err_ptr)
 {
+       __wsum ret;
+
        might_sleep();
-       return csum_partial_copy_generic((__force void *)src, dst,
-                                        len, sum, err_ptr, NULL);
+       stac();
+       ret = csum_partial_copy_generic((__force void *)src, dst,
+                                       len, sum, err_ptr, NULL);
+       clac();
+
+       return ret;
 }
 
 /*
@@ -176,10 +182,16 @@ static inline __wsum csum_and_copy_to_user(const void *src,
                                           int len, __wsum sum,
                                           int *err_ptr)
 {
+       __wsum ret;
+
        might_sleep();
-       if (access_ok(VERIFY_WRITE, dst, len))
-               return csum_partial_copy_generic(src, (__force void *)dst,
-                                                len, sum, NULL, err_ptr);
+       if (access_ok(VERIFY_WRITE, dst, len)) {
+               stac();
+               ret = csum_partial_copy_generic(src, (__force void *)dst,
+                                               len, sum, NULL, err_ptr);
+               clac();
+               return ret;
+       }
 
        if (len)
                *err_ptr = -EFAULT;
index fa5f71e021d5363735caeaa3fbb834600d4bc5f2..e6833c655e594ef118978d6ba65cc69ec69b6256 100644 (file)
 #define MCI_STATUS_PCC   (1ULL<<57)  /* processor context corrupt */
 #define MCI_STATUS_S    (1ULL<<56)  /* Signaled machine check */
 #define MCI_STATUS_AR   (1ULL<<55)  /* Action required */
-#define MCACOD           0xffff     /* MCA Error Code */
+
+/*
+ * Note that the full MCACOD field of IA32_MCi_STATUS MSR is
+ * bits 15:0.  But bit 12 is the 'F' bit, defined for corrected
+ * errors to indicate that errors are being filtered by hardware.
+ * We should mask out bit 12 when looking for specific signatures
+ * of uncorrected errors - so the F bit is deliberately skipped
+ * in this #define.
+ */
+#define MCACOD           0xefff     /* MCA Error Code */
 
 /* Architecturally defined codes from SDM Vol. 3B Chapter 15 */
 #define MCACOD_SCRUB   0x00C0  /* 0xC0-0xCF Memory Scrubbing */
-#define MCACOD_SCRUBMSK        0xfff0
+#define MCACOD_SCRUBMSK        0xeff0  /* Skip bit 12 ('F' bit) */
 #define MCACOD_L3WB    0x017A  /* L3 Explicit Writeback */
 #define MCACOD_DATA    0x0134  /* Data Load */
 #define MCACOD_INSTR   0x0150  /* Instruction Fetch */
index cdbf36776106addf6eec8770b50d156b448b5185..be12c534fd592e84fd81ca0b3b6c5182ecb2f6fe 100644 (file)
@@ -45,22 +45,28 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                /* Re-load page tables */
                load_cr3(next->pgd);
 
-               /* stop flush ipis for the previous mm */
+               /* Stop flush ipis for the previous mm */
                cpumask_clear_cpu(cpu, mm_cpumask(prev));
 
-               /*
-                * load the LDT, if the LDT is different:
-                */
+               /* Load the LDT, if the LDT is different: */
                if (unlikely(prev->context.ldt != next->context.ldt))
                        load_LDT_nolock(&next->context);
        }
 #ifdef CONFIG_SMP
-       else {
+         else {
                this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK);
                BUG_ON(this_cpu_read(cpu_tlbstate.active_mm) != next);
 
-               if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next))) {
-                       /* We were in lazy tlb mode and leave_mm disabled
+               if (!cpumask_test_cpu(cpu, mm_cpumask(next))) {
+                       /*
+                        * On established mms, the mm_cpumask is only changed
+                        * from irq context, from ptep_clear_flush() while in
+                        * lazy tlb mode, and here. Irqs are blocked during
+                        * schedule, protecting us from simultaneous changes.
+                        */
+                       cpumask_set_cpu(cpu, mm_cpumask(next));
+                       /*
+                        * We were in lazy tlb mode and leave_mm disabled
                         * tlb flush IPI delivery. We must reload CR3
                         * to make sure to use no freed page tables.
                         */
index 7ea79c5fa1f217ff3c8aaf0afba935411fe61c6e..492b29802f571b0363a22fe686f708c8235c317a 100644 (file)
@@ -167,12 +167,12 @@ static struct xor_block_template xor_block_avx = {
 
 #define AVX_XOR_SPEED \
 do { \
-       if (cpu_has_avx) \
+       if (cpu_has_avx && cpu_has_osxsave) \
                xor_speed(&xor_block_avx); \
 } while (0)
 
 #define AVX_SELECT(FASTEST) \
-       (cpu_has_avx ? &xor_block_avx : FASTEST)
+       (cpu_has_avx && cpu_has_osxsave ? &xor_block_avx : FASTEST)
 
 #else
 
index b44577bc97449c14af7988e18a14b4b9c31cc262..ec94e11807dc43bded4cead2c22350d907b6a68c 100644 (file)
@@ -48,9 +48,20 @@ int acpi_suspend_lowlevel(void)
 #ifndef CONFIG_64BIT
        native_store_gdt((struct desc_ptr *)&header->pmode_gdt);
 
+       /*
+        * We have to check that we can write back the value, and not
+        * just read it.  At least on 90 nm Pentium M (Family 6, Model
+        * 13), reading an invalid MSR is not guaranteed to trap, see
+        * Erratum X4 in "Intel Pentium M Processor on 90 nm Process
+        * with 2-MB L2 Cache and Intel® Processor A100 and A110 on 90
+        * nm process with 512-KB L2 Cache Specification Update".
+        */
        if (!rdmsr_safe(MSR_EFER,
                        &header->pmode_efer_low,
-                       &header->pmode_efer_high))
+                       &header->pmode_efer_high) &&
+           !wrmsr_safe(MSR_EFER,
+                       header->pmode_efer_low,
+                       header->pmode_efer_high))
                header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_EFER);
 #endif /* !CONFIG_64BIT */
 
@@ -61,7 +72,10 @@ int acpi_suspend_lowlevel(void)
        }
        if (!rdmsr_safe(MSR_IA32_MISC_ENABLE,
                        &header->pmode_misc_en_low,
-                       &header->pmode_misc_en_high))
+                       &header->pmode_misc_en_high) &&
+           !wrmsr_safe(MSR_IA32_MISC_ENABLE,
+                       header->pmode_misc_en_low,
+                       header->pmode_misc_en_high))
                header->pmode_behavior |=
                        (1 << WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE);
        header->realmode_flags = acpi_realmode_flags;
index 3048ded1b5983a9a3e7f511fc30066f672721383..59554dca96ec8945c1d7f514a1281e06c6e7e771 100644 (file)
@@ -20,6 +20,7 @@ const struct pci_device_id amd_nb_misc_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
        {}
 };
@@ -27,6 +28,7 @@ EXPORT_SYMBOL(amd_nb_misc_ids);
 
 static const struct pci_device_id amd_nb_link_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F4) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
        {}
 };
@@ -81,12 +83,19 @@ int amd_cache_northbridges(void)
                        next_northbridge(misc, amd_nb_misc_ids);
                node_to_amd_nb(i)->link = link =
                        next_northbridge(link, amd_nb_link_ids);
-        }
+       }
 
+       /* GART present only on Fam15h upto model 0fh */
        if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10 ||
-           boot_cpu_data.x86 == 0x15)
+           (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model < 0x10))
                amd_northbridges.flags |= AMD_NB_GART;
 
+       /*
+        * Check for L3 cache presence.
+        */
+       if (!cpuid_edx(0x80000006))
+               return 0;
+
        /*
         * Some CPU families support L3 Cache Index Disable. There are some
         * limitations because of E382 and E388 on family 0x10.
index fa72a39e5d463a248a5b5a4a18f7860a1cbb8a77..3982357de5b0a9a3d498b6413a0ee5371cb731d4 100644 (file)
@@ -510,8 +510,9 @@ generic_get_free_region(unsigned long base, unsigned long size, int replace_reg)
 static void generic_get_mtrr(unsigned int reg, unsigned long *base,
                             unsigned long *size, mtrr_type *type)
 {
-       unsigned int mask_lo, mask_hi, base_lo, base_hi;
-       unsigned int tmp, hi;
+       u32 mask_lo, mask_hi, base_lo, base_hi;
+       unsigned int hi;
+       u64 tmp, mask;
 
        /*
         * get_mtrr doesn't need to update mtrr_state, also it could be called
@@ -532,18 +533,18 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,
        rdmsr(MTRRphysBase_MSR(reg), base_lo, base_hi);
 
        /* Work out the shifted address mask: */
-       tmp = mask_hi << (32 - PAGE_SHIFT) | mask_lo >> PAGE_SHIFT;
-       mask_lo = size_or_mask | tmp;
+       tmp = (u64)mask_hi << (32 - PAGE_SHIFT) | mask_lo >> PAGE_SHIFT;
+       mask = size_or_mask | tmp;
 
        /* Expand tmp with high bits to all 1s: */
-       hi = fls(tmp);
+       hi = fls64(tmp);
        if (hi > 0) {
-               tmp |= ~((1<<(hi - 1)) - 1);
+               tmp |= ~((1ULL<<(hi - 1)) - 1);
 
-               if (tmp != mask_lo) {
+               if (tmp != mask) {
                        printk(KERN_WARNING "mtrr: your BIOS has configured an incorrect mask, fixing it.\n");
                        add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
-                       mask_lo = tmp;
+                       mask = tmp;
                }
        }
 
@@ -551,8 +552,8 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,
         * This works correctly if size is a power of two, i.e. a
         * contiguous range:
         */
-       *size = -mask_lo;
-       *base = base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
+       *size = -mask;
+       *base = (u64)base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
        *type = base_lo & 0xff;
 
 out_put_cpu:
index 726bf963c2276569c39c67377b64fd7a74fb539e..ca22b73aaa25f8c4d512a62161bf6af92ec0807f 100644 (file)
@@ -305,7 +305,8 @@ int mtrr_add_page(unsigned long base, unsigned long size,
                return -EINVAL;
        }
 
-       if (base & size_or_mask || size & size_or_mask) {
+       if ((base | (base + size - 1)) >>
+           (boot_cpu_data.x86_phys_bits - PAGE_SHIFT)) {
                pr_warning("mtrr: base or size exceeds the MTRR width\n");
                return -EINVAL;
        }
@@ -583,6 +584,7 @@ static struct syscore_ops mtrr_syscore_ops = {
 
 int __initdata changed_by_mtrr_cleanup;
 
+#define SIZE_OR_MASK_BITS(n)  (~((1ULL << ((n) - PAGE_SHIFT)) - 1))
 /**
  * mtrr_bp_init - initialize mtrrs on the boot CPU
  *
@@ -600,7 +602,7 @@ void __init mtrr_bp_init(void)
 
        if (cpu_has_mtrr) {
                mtrr_if = &generic_mtrr_ops;
-               size_or_mask = 0xff000000;                      /* 36 bits */
+               size_or_mask = SIZE_OR_MASK_BITS(36);
                size_and_mask = 0x00f00000;
                phys_addr = 36;
 
@@ -619,7 +621,7 @@ void __init mtrr_bp_init(void)
                             boot_cpu_data.x86_mask == 0x4))
                                phys_addr = 36;
 
-                       size_or_mask = ~((1ULL << (phys_addr - PAGE_SHIFT)) - 1);
+                       size_or_mask = SIZE_OR_MASK_BITS(phys_addr);
                        size_and_mask = ~size_or_mask & 0xfffff00000ULL;
                } else if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR &&
                           boot_cpu_data.x86 == 6) {
@@ -627,7 +629,7 @@ void __init mtrr_bp_init(void)
                         * VIA C* family have Intel style MTRRs,
                         * but don't support PAE
                         */
-                       size_or_mask = 0xfff00000;              /* 32 bits */
+                       size_or_mask = SIZE_OR_MASK_BITS(32);
                        size_and_mask = 0;
                        phys_addr = 32;
                }
@@ -637,21 +639,21 @@ void __init mtrr_bp_init(void)
                        if (cpu_has_k6_mtrr) {
                                /* Pre-Athlon (K6) AMD CPU MTRRs */
                                mtrr_if = mtrr_ops[X86_VENDOR_AMD];
-                               size_or_mask = 0xfff00000;      /* 32 bits */
+                               size_or_mask = SIZE_OR_MASK_BITS(32);
                                size_and_mask = 0;
                        }
                        break;
                case X86_VENDOR_CENTAUR:
                        if (cpu_has_centaur_mcr) {
                                mtrr_if = mtrr_ops[X86_VENDOR_CENTAUR];
-                               size_or_mask = 0xfff00000;      /* 32 bits */
+                               size_or_mask = SIZE_OR_MASK_BITS(32);
                                size_and_mask = 0;
                        }
                        break;
                case X86_VENDOR_CYRIX:
                        if (cpu_has_cyrix_arr) {
                                mtrr_if = mtrr_ops[X86_VENDOR_CYRIX];
-                               size_or_mask = 0xfff00000;      /* 32 bits */
+                               size_or_mask = SIZE_OR_MASK_BITS(32);
                                size_and_mask = 0;
                        }
                        break;
index 52441a2af5380d1d44bbee24001b81ea63d53362..8aac56bda7dc3b37b8eac0620d3fc7990f50cf95 100644 (file)
@@ -314,8 +314,8 @@ static struct uncore_event_desc snbep_uncore_imc_events[] = {
 static struct uncore_event_desc snbep_uncore_qpi_events[] = {
        INTEL_UNCORE_EVENT_DESC(clockticks,       "event=0x14"),
        INTEL_UNCORE_EVENT_DESC(txl_flits_active, "event=0x00,umask=0x06"),
-       INTEL_UNCORE_EVENT_DESC(drs_data,         "event=0x02,umask=0x08"),
-       INTEL_UNCORE_EVENT_DESC(ncb_data,         "event=0x03,umask=0x04"),
+       INTEL_UNCORE_EVENT_DESC(drs_data,         "event=0x102,umask=0x08"),
+       INTEL_UNCORE_EVENT_DESC(ncb_data,         "event=0x103,umask=0x04"),
        { /* end: all zeroes */ },
 };
 
index 94ab6b90dd3fabdaf2856a5d7fc2abfd4ed2af88..63bdb29b25497edfb0a97ec7cfb9aa5b746d200a 100644 (file)
@@ -196,15 +196,23 @@ static void __init ati_bugs_contd(int num, int slot, int func)
 static void __init intel_remapping_check(int num, int slot, int func)
 {
        u8 revision;
+       u16 device;
 
+       device = read_pci_config_16(num, slot, func, PCI_DEVICE_ID);
        revision = read_pci_config_byte(num, slot, func, PCI_REVISION_ID);
 
        /*
-        * Revision 0x13 of this chipset supports irq remapping
-        * but has an erratum that breaks its behavior, flag it as such
+        * Revision 13 of all triggering devices id in this quirk have
+        * a problem draining interrupts when irq remapping is enabled,
+        * and should be flagged as broken.  Additionally revisions 0x12
+        * and 0x22 of device id 0x3405 has this problem.
         */
        if (revision == 0x13)
                set_irq_remapping_broken();
+       else if ((device == 0x3405) &&
+           ((revision == 0x12) ||
+            (revision == 0x22)))
+               set_irq_remapping_broken();
 
 }
 
@@ -239,6 +247,8 @@ static struct chipset early_qrk[] __initdata = {
          PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd },
        { PCI_VENDOR_ID_INTEL, 0x3403, PCI_CLASS_BRIDGE_HOST,
          PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check },
+       { PCI_VENDOR_ID_INTEL, 0x3405, PCI_CLASS_BRIDGE_HOST,
+         PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check },
        { PCI_VENDOR_ID_INTEL, 0x3406, PCI_CLASS_BRIDGE_HOST,
          PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check },
        {}
index 321d65ebaffe255bbb1dc1bc6aaf2ac217d55aaf..a8368608ab41b30edb83029978651c8ef4bc3650 100644 (file)
@@ -513,7 +513,7 @@ ENTRY(phys_base)
 #include "../../x86/xen/xen-head.S"
        
        .section .bss, "aw", @nobits
-       .align L1_CACHE_BYTES
+       .align PAGE_SIZE
 ENTRY(idt_table)
        .skip IDT_ENTRIES * 16
 
index cb339097b9ea0cf4f57b2b406fa308a489cee881..f7ea30dce23893a936265e791c1f3c6b04285c3f 100644 (file)
@@ -116,7 +116,7 @@ static void __cpuinit mxcsr_feature_mask_init(void)
 
        if (cpu_has_fxsr) {
                memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct));
-               asm volatile("fxsave %0" : : "m" (fx_scratch));
+               asm volatile("fxsave %0" : "+m" (fx_scratch));
                mask = fx_scratch.mxcsr_mask;
                if (mask == 0)
                        mask = 0x0000ffbf;
index 69562992e457456eaa4a861de85f6faf4eba8278..087ab2af381abb99089748672f5eb7f122a7f5c3 100644 (file)
@@ -364,7 +364,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
                else
                        put_user_ex(0, &frame->uc.uc_flags);
                put_user_ex(0, &frame->uc.uc_link);
-               err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
+               save_altstack_ex(&frame->uc.uc_stack, regs->sp);
 
                /* Set up to return from userspace.  */
                restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn);
@@ -429,7 +429,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
                else
                        put_user_ex(0, &frame->uc.uc_flags);
                put_user_ex(0, &frame->uc.uc_link);
-               err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
+               save_altstack_ex(&frame->uc.uc_stack, regs->sp);
 
                /* Set up to return from userspace.  If provided, use a stub
                   already in userspace.  */
@@ -496,7 +496,7 @@ static int x32_setup_rt_frame(struct ksignal *ksig,
                else
                        put_user_ex(0, &frame->uc.uc_flags);
                put_user_ex(0, &frame->uc.uc_link);
-               err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp);
+               compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp);
                put_user_ex(0, &frame->uc.uc__pad0);
 
                if (ksig->ka.sa.sa_flags & SA_RESTORER) {
index dbded5aedb818d511a46967ccb1d26d77233110f..30277e27431acde9a9320e0b1be4470bddb40e3a 100644 (file)
@@ -101,7 +101,7 @@ static void find_start_end(unsigned long flags, unsigned long *begin,
                                *begin = new_begin;
                }
        } else {
-               *begin = TASK_UNMAPPED_BASE;
+               *begin = current->mm->mmap_legacy_base;
                *end = TASK_SIZE;
        }
 }
index 260a9193955538b4fea743045b2f964b2736b24e..5402c94ab76835aa6a00f0d503b8992a899b28b6 100644 (file)
@@ -3399,15 +3399,22 @@ static void vmx_get_segment(struct kvm_vcpu *vcpu,
        var->limit = vmx_read_guest_seg_limit(vmx, seg);
        var->selector = vmx_read_guest_seg_selector(vmx, seg);
        ar = vmx_read_guest_seg_ar(vmx, seg);
+       var->unusable = (ar >> 16) & 1;
        var->type = ar & 15;
        var->s = (ar >> 4) & 1;
        var->dpl = (ar >> 5) & 3;
-       var->present = (ar >> 7) & 1;
+       /*
+        * Some userspaces do not preserve unusable property. Since usable
+        * segment has to be present according to VMX spec we can use present
+        * property to amend userspace bug by making unusable segment always
+        * nonpresent. vmx_segment_access_rights() already marks nonpresent
+        * segment as unusable.
+        */
+       var->present = !var->unusable;
        var->avl = (ar >> 12) & 1;
        var->l = (ar >> 13) & 1;
        var->db = (ar >> 14) & 1;
        var->g = (ar >> 15) & 1;
-       var->unusable = (ar >> 16) & 1;
 }
 
 static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
index 25b7ae8d058ad8b756987ed7dc8d22382a956519..7609e0e421ece96f6671cc7d2310e0c59402ac1b 100644 (file)
@@ -6,6 +6,7 @@
  */
 #include <asm/checksum.h>
 #include <linux/module.h>
+#include <asm/smap.h>
 
 /**
  * csum_partial_copy_from_user - Copy and checksum from user space.
@@ -52,8 +53,10 @@ csum_partial_copy_from_user(const void __user *src, void *dst,
                        len -= 2;
                }
        }
+       stac();
        isum = csum_partial_copy_generic((__force const void *)src,
                                dst, len, isum, errp, NULL);
+       clac();
        if (unlikely(*errp))
                goto out_err;
 
@@ -82,6 +85,8 @@ __wsum
 csum_partial_copy_to_user(const void *src, void __user *dst,
                          int len, __wsum isum, int *errp)
 {
+       __wsum ret;
+
        might_sleep();
 
        if (unlikely(!access_ok(VERIFY_WRITE, dst, len))) {
@@ -105,8 +110,11 @@ csum_partial_copy_to_user(const void *src, void __user *dst,
        }
 
        *errp = 0;
-       return csum_partial_copy_generic(src, (void __force *)dst,
-                                        len, isum, NULL, errp);
+       stac();
+       ret = csum_partial_copy_generic(src, (void __force *)dst,
+                                       len, isum, NULL, errp);
+       clac();
+       return ret;
 }
 EXPORT_SYMBOL(csum_partial_copy_to_user);
 
index 1f34e9219775b2251c72cbb3234fef0ebec600f3..7a5bf1b76e2fe82d7d7d72d08d732f5d9cd1746b 100644 (file)
@@ -78,8 +78,8 @@ __ref void *alloc_low_pages(unsigned int num)
        return __va(pfn << PAGE_SHIFT);
 }
 
-/* need 4 4k for initial PMD_SIZE, 4k for 0-ISA_END_ADDRESS */
-#define INIT_PGT_BUF_SIZE      (5 * PAGE_SIZE)
+/* need 3 4k for initial PMD_SIZE,  3 4k for 0-ISA_END_ADDRESS */
+#define INIT_PGT_BUF_SIZE      (6 * PAGE_SIZE)
 RESERVE_BRK(early_pgt_alloc, INIT_PGT_BUF_SIZE);
 void  __init early_alloc_pgt_buf(void)
 {
index 845df6835f9ff5fc216ab01857100d41eba77fbf..5c1ae28825cd2119d58349886d8476b8645d0337 100644 (file)
@@ -112,12 +112,14 @@ static unsigned long mmap_legacy_base(void)
  */
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
+       mm->mmap_legacy_base = mmap_legacy_base();
+       mm->mmap_base = mmap_base();
+
        if (mmap_is_legacy()) {
-               mm->mmap_base = mmap_legacy_base();
+               mm->mmap_base = mm->mmap_legacy_base;
                mm->get_unmapped_area = arch_get_unmapped_area;
                mm->unmap_area = arch_unmap_area;
        } else {
-               mm->mmap_base = mmap_base();
                mm->get_unmapped_area = arch_get_unmapped_area_topdown;
                mm->unmap_area = arch_unmap_area_topdown;
        }
index 94eac5c85cdc9eea7b32ac1d07d94252cac3087e..0a9fb7a0b4521970c50d558595906bfca7724e50 100644 (file)
@@ -313,6 +313,17 @@ static void xen_align_and_add_e820_region(u64 start, u64 size, int type)
        e820_add_region(start, end - start, type);
 }
 
+void xen_ignore_unusable(struct e820entry *list, size_t map_size)
+{
+       struct e820entry *entry;
+       unsigned int i;
+
+       for (i = 0, entry = list; i < map_size; i++, entry++) {
+               if (entry->type == E820_UNUSABLE)
+                       entry->type = E820_RAM;
+       }
+}
+
 /**
  * machine_specific_memory_setup - Hook for machine specific memory setup.
  **/
@@ -353,6 +364,17 @@ char * __init xen_memory_setup(void)
        }
        BUG_ON(rc);
 
+       /*
+        * Xen won't allow a 1:1 mapping to be created to UNUSABLE
+        * regions, so if we're using the machine memory map leave the
+        * region as RAM as it is in the pseudo-physical map.
+        *
+        * UNUSABLE regions in domUs are not handled and will need
+        * a patch in the future.
+        */
+       if (xen_initial_domain())
+               xen_ignore_unusable(map, memmap.nr_entries);
+
        /* Make sure the Xen-supplied memory map is well-ordered. */
        sanitize_e820_map(map, memmap.nr_entries, &memmap.nr_entries);
 
index d99cae8147d1243b84faa111bcd74b447e5ff7ec..a1e58e19d0ccea2005ff34d7d5c8acdc49100679 100644 (file)
@@ -667,8 +667,15 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
 static int __cpuinit xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
        int rc;
-       rc = native_cpu_up(cpu, tidle);
-       WARN_ON (xen_smp_intr_init(cpu));
+       /*
+        * xen_smp_intr_init() needs to run before native_cpu_up()
+        * so that IPI vectors are set up on the booting CPU before
+        * it is marked online in native_cpu_up().
+       */
+       rc = xen_smp_intr_init(cpu);
+       WARN_ON(rc);
+       if (!rc)
+               rc =  native_cpu_up(cpu, tidle);
        return rc;
 }
 
index 3d88bfdf9e1c092a23e9d4be143630a074a92926..13e8935e2eabe8b0c55f6f1abd4f8b1a1bb64974 100644 (file)
@@ -36,9 +36,8 @@ static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate);
 /* snapshots of runstate info */
 static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate_snapshot);
 
-/* unused ns of stolen and blocked time */
+/* unused ns of stolen time */
 static DEFINE_PER_CPU(u64, xen_residual_stolen);
-static DEFINE_PER_CPU(u64, xen_residual_blocked);
 
 /* return an consistent snapshot of 64-bit time/counter value */
 static u64 get64(const u64 *p)
@@ -115,7 +114,7 @@ static void do_stolen_accounting(void)
 {
        struct vcpu_runstate_info state;
        struct vcpu_runstate_info *snap;
-       s64 blocked, runnable, offline, stolen;
+       s64 runnable, offline, stolen;
        cputime_t ticks;
 
        get_runstate_snapshot(&state);
@@ -125,7 +124,6 @@ static void do_stolen_accounting(void)
        snap = &__get_cpu_var(xen_runstate_snapshot);
 
        /* work out how much time the VCPU has not been runn*ing*  */
-       blocked = state.time[RUNSTATE_blocked] - snap->time[RUNSTATE_blocked];
        runnable = state.time[RUNSTATE_runnable] - snap->time[RUNSTATE_runnable];
        offline = state.time[RUNSTATE_offline] - snap->time[RUNSTATE_offline];
 
@@ -141,17 +139,6 @@ static void do_stolen_accounting(void)
        ticks = iter_div_u64_rem(stolen, NS_PER_TICK, &stolen);
        __this_cpu_write(xen_residual_stolen, stolen);
        account_steal_ticks(ticks);
-
-       /* Add the appropriate number of ticks of blocked time,
-          including any left-overs from last time. */
-       blocked += __this_cpu_read(xen_residual_blocked);
-
-       if (blocked < 0)
-               blocked = 0;
-
-       ticks = iter_div_u64_rem(blocked, NS_PER_TICK, &blocked);
-       __this_cpu_write(xen_residual_blocked, blocked);
-       account_idle_ticks(ticks);
 }
 
 /* Get the TSC speed from Xen */
index ef12c0e6fa257e907ce7202b4202fce05adbf6ad..7d740ebbe198ec77a8011601f4172ebc809b9be8 100644 (file)
@@ -68,6 +68,15 @@ _SetupMMU:
 
 #ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
        initialize_mmu
+#if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
+       rsr     a2, excsave1
+       movi    a3, 0x08000000
+       bgeu    a2, a3, 1f
+       movi    a3, 0xd0000000
+       add     a2, a2, a3
+       wsr     a2, excsave1
+1:
+#endif
 #endif
        .end    no-absolute-literals
 
index 8f4484acbb08a1d93afa8fec882d7d7608317d40..ea9afb6904d7c2144b8e504fe0b3bc38547776bf 100644 (file)
@@ -152,8 +152,8 @@ static int __init parse_tag_initrd(const bp_tag_t* tag)
 {
        meminfo_t* mi;
        mi = (meminfo_t*)(tag->data);
-       initrd_start = (void*)(mi->start);
-       initrd_end = (void*)(mi->end);
+       initrd_start = __va(mi->start);
+       initrd_end = __va(mi->end);
 
        return 0;
 }
@@ -164,7 +164,7 @@ __tagtable(BP_TAG_INITRD, parse_tag_initrd);
 
 static int __init parse_tag_fdt(const bp_tag_t *tag)
 {
-       dtb_start = (void *)(tag->data[0]);
+       dtb_start = __va(tag->data[0]);
        return 0;
 }
 
index d5cd3131c57a36645bcf049e28ab9a46ab5ea559..d5bbdcfd0dab5f56fa76f9ca08dc979fe16d1a35 100644 (file)
@@ -4347,18 +4347,28 @@ static void cfq_exit_queue(struct elevator_queue *e)
        kfree(cfqd);
 }
 
-static int cfq_init_queue(struct request_queue *q)
+static int cfq_init_queue(struct request_queue *q, struct elevator_type *e)
 {
        struct cfq_data *cfqd;
        struct blkcg_gq *blkg __maybe_unused;
        int i, ret;
+       struct elevator_queue *eq;
+
+       eq = elevator_alloc(q, e);
+       if (!eq)
+               return -ENOMEM;
 
        cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node);
-       if (!cfqd)
+       if (!cfqd) {
+               kobject_put(&eq->kobj);
                return -ENOMEM;
+       }
+       eq->elevator_data = cfqd;
 
        cfqd->queue = q;
-       q->elevator->elevator_data = cfqd;
+       spin_lock_irq(q->queue_lock);
+       q->elevator = eq;
+       spin_unlock_irq(q->queue_lock);
 
        /* Init root service tree */
        cfqd->grp_service_tree = CFQ_RB_ROOT;
@@ -4433,6 +4443,7 @@ static int cfq_init_queue(struct request_queue *q)
 
 out_free:
        kfree(cfqd);
+       kobject_put(&eq->kobj);
        return ret;
 }
 
index ba19a3afab7929cf3ff0857683ccaef40a007a77..20614a33236220d0e79d99a2cfaf99822327bc57 100644 (file)
@@ -337,13 +337,21 @@ static void deadline_exit_queue(struct elevator_queue *e)
 /*
  * initialize elevator private data (deadline_data).
  */
-static int deadline_init_queue(struct request_queue *q)
+static int deadline_init_queue(struct request_queue *q, struct elevator_type *e)
 {
        struct deadline_data *dd;
+       struct elevator_queue *eq;
+
+       eq = elevator_alloc(q, e);
+       if (!eq)
+               return -ENOMEM;
 
        dd = kmalloc_node(sizeof(*dd), GFP_KERNEL | __GFP_ZERO, q->node);
-       if (!dd)
+       if (!dd) {
+               kobject_put(&eq->kobj);
                return -ENOMEM;
+       }
+       eq->elevator_data = dd;
 
        INIT_LIST_HEAD(&dd->fifo_list[READ]);
        INIT_LIST_HEAD(&dd->fifo_list[WRITE]);
@@ -355,7 +363,9 @@ static int deadline_init_queue(struct request_queue *q)
        dd->front_merges = 1;
        dd->fifo_batch = fifo_batch;
 
-       q->elevator->elevator_data = dd;
+       spin_lock_irq(q->queue_lock);
+       q->elevator = eq;
+       spin_unlock_irq(q->queue_lock);
        return 0;
 }
 
index eba5b04c29b135bdc6b84ac80690d380d59dd8a5..668394d185885bc3fcc878697878a4cb07be899e 100644 (file)
@@ -150,7 +150,7 @@ void __init load_default_elevator_module(void)
 
 static struct kobj_type elv_ktype;
 
-static struct elevator_queue *elevator_alloc(struct request_queue *q,
+struct elevator_queue *elevator_alloc(struct request_queue *q,
                                  struct elevator_type *e)
 {
        struct elevator_queue *eq;
@@ -170,6 +170,7 @@ err:
        elevator_put(e);
        return NULL;
 }
+EXPORT_SYMBOL(elevator_alloc);
 
 static void elevator_release(struct kobject *kobj)
 {
@@ -221,16 +222,7 @@ int elevator_init(struct request_queue *q, char *name)
                }
        }
 
-       q->elevator = elevator_alloc(q, e);
-       if (!q->elevator)
-               return -ENOMEM;
-
-       err = e->ops.elevator_init_fn(q);
-       if (err) {
-               kobject_put(&q->elevator->kobj);
-               return err;
-       }
-
+       err = e->ops.elevator_init_fn(q, e);
        return 0;
 }
 EXPORT_SYMBOL(elevator_init);
@@ -935,16 +927,9 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
        spin_unlock_irq(q->queue_lock);
 
        /* allocate, init and register new elevator */
-       err = -ENOMEM;
-       q->elevator = elevator_alloc(q, new_e);
-       if (!q->elevator)
-               goto fail_init;
-
-       err = new_e->ops.elevator_init_fn(q);
-       if (err) {
-               kobject_put(&q->elevator->kobj);
+       err = new_e->ops.elevator_init_fn(q, new_e);
+       if (err)
                goto fail_init;
-       }
 
        if (registered) {
                err = elv_register_queue(q);
index 20625eed55116555216cb594c49e4a0c36049675..cdeb5277dfd402ddeefa300d888d8e07b81b8ad9 100644 (file)
@@ -512,7 +512,7 @@ static void register_disk(struct gendisk *disk)
 
        ddev->parent = disk->driverfs_dev;
 
-       dev_set_name(ddev, disk->disk_name);
+       dev_set_name(ddev, "%s", disk->disk_name);
 
        /* delay uevents, until we scanned partition table */
        dev_set_uevent_suppress(ddev, 1);
index 5d1bf70e33d5a04a5fc994c8a8cb0c9ecdbf0900..3de89d4690f3bf3e0d9abec1976a379b5dc171e5 100644 (file)
@@ -59,16 +59,27 @@ noop_latter_request(struct request_queue *q, struct request *rq)
        return list_entry(rq->queuelist.next, struct request, queuelist);
 }
 
-static int noop_init_queue(struct request_queue *q)
+static int noop_init_queue(struct request_queue *q, struct elevator_type *e)
 {
        struct noop_data *nd;
+       struct elevator_queue *eq;
+
+       eq = elevator_alloc(q, e);
+       if (!eq)
+               return -ENOMEM;
 
        nd = kmalloc_node(sizeof(*nd), GFP_KERNEL, q->node);
-       if (!nd)
+       if (!nd) {
+               kobject_put(&eq->kobj);
                return -ENOMEM;
+       }
+       eq->elevator_data = nd;
 
        INIT_LIST_HEAD(&nd->queue);
-       q->elevator->elevator_data = nd;
+
+       spin_lock_irq(q->queue_lock);
+       q->elevator = eq;
+       spin_unlock_irq(q->queue_lock);
        return 0;
 }
 
index 6149a6e09643f0c9b975ac339dd904dd58421262..7a1ae87f1683459711c0b0c6badd1d76ddd9c9f1 100644 (file)
@@ -495,7 +495,8 @@ static struct crypto_template *__crypto_lookup_template(const char *name)
 
 struct crypto_template *crypto_lookup_template(const char *name)
 {
-       return try_then_request_module(__crypto_lookup_template(name), name);
+       return try_then_request_module(__crypto_lookup_template(name), "%s",
+                                      name);
 }
 EXPORT_SYMBOL_GPL(crypto_lookup_template);
 
index 3b6180336d3d54b9011bb8f90d15a220cf06b642..37c4c7213de070c9fbda60db25e92f1283cdcb6e 100644 (file)
@@ -34,6 +34,8 @@ EXPORT_SYMBOL_GPL(crypto_alg_sem);
 BLOCKING_NOTIFIER_HEAD(crypto_chain);
 EXPORT_SYMBOL_GPL(crypto_chain);
 
+static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg);
+
 struct crypto_alg *crypto_mod_get(struct crypto_alg *alg)
 {
        return try_module_get(alg->cra_module) ? crypto_alg_get(alg) : NULL;
@@ -144,8 +146,11 @@ static struct crypto_alg *crypto_larval_add(const char *name, u32 type,
        }
        up_write(&crypto_alg_sem);
 
-       if (alg != &larval->alg)
+       if (alg != &larval->alg) {
                kfree(larval);
+               if (crypto_is_larval(alg))
+                       alg = crypto_larval_wait(alg);
+       }
 
        return alg;
 }
index 536562c626a2fab4bb20c128abcf27f4404ca23f..97c949abfabbc591570e78e298988c790dd9d42e 100644 (file)
@@ -43,6 +43,7 @@ acpi-y                                += acpi_platform.o
 acpi-y                         += power.o
 acpi-y                         += event.o
 acpi-y                         += sysfs.o
+acpi-$(CONFIG_X86)             += acpi_cmos_rtc.o
 acpi-$(CONFIG_DEBUG_FS)                += debugfs.o
 acpi-$(CONFIG_ACPI_NUMA)       += numa.o
 acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
diff --git a/drivers/acpi/acpi_cmos_rtc.c b/drivers/acpi/acpi_cmos_rtc.c
new file mode 100644 (file)
index 0000000..84190ed
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * ACPI support for CMOS RTC Address Space access
+ *
+ * Copyright (C) 2013, Intel Corporation
+ * Authors: Lan Tianyu <tianyu.lan@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm-generic/rtc.h>
+
+#include "internal.h"
+
+#define PREFIX "ACPI: "
+
+ACPI_MODULE_NAME("cmos rtc");
+
+static const struct acpi_device_id acpi_cmos_rtc_ids[] = {
+       { "PNP0B00" },
+       { "PNP0B01" },
+       { "PNP0B02" },
+       {}
+};
+
+static acpi_status
+acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address,
+                     u32 bits, u64 *value64,
+                     void *handler_context, void *region_context)
+{
+       int i;
+       u8 *value = (u8 *)&value64;
+
+       if (address > 0xff || !value64)
+               return AE_BAD_PARAMETER;
+
+       if (function != ACPI_WRITE && function != ACPI_READ)
+               return AE_BAD_PARAMETER;
+
+       spin_lock_irq(&rtc_lock);
+
+       for (i = 0; i < DIV_ROUND_UP(bits, 8); ++i, ++address, ++value)
+               if (function == ACPI_READ)
+                       *value = CMOS_READ(address);
+               else
+                       CMOS_WRITE(*value, address);
+
+       spin_unlock_irq(&rtc_lock);
+
+       return AE_OK;
+}
+
+static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev,
+               const struct acpi_device_id *id)
+{
+       acpi_status status;
+
+       status = acpi_install_address_space_handler(adev->handle,
+                       ACPI_ADR_SPACE_CMOS,
+                       &acpi_cmos_rtc_space_handler,
+                       NULL, NULL);
+       if (ACPI_FAILURE(status)) {
+               pr_err(PREFIX "Error installing CMOS-RTC region handler\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void acpi_remove_cmos_rtc_space_handler(struct acpi_device *adev)
+{
+       if (ACPI_FAILURE(acpi_remove_address_space_handler(adev->handle,
+                       ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler)))
+               pr_err(PREFIX "Error removing CMOS-RTC region handler\n");
+}
+
+static struct acpi_scan_handler cmos_rtc_handler = {
+       .ids = acpi_cmos_rtc_ids,
+       .attach = acpi_install_cmos_rtc_space_handler,
+       .detach = acpi_remove_cmos_rtc_space_handler,
+};
+
+void __init acpi_cmos_rtc_init(void)
+{
+       acpi_scan_add_handler(&cmos_rtc_handler);
+}
index cab13f2fc28e3033aaed24adbbf618199473bb28..7c451cb26254f6158f8c87f7fcacda91ccce4c56 100644 (file)
@@ -155,12 +155,13 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
                        pdata->mmio_size = resource_size(&rentry->res);
                        pdata->mmio_base = ioremap(rentry->res.start,
                                                   pdata->mmio_size);
-                       pdata->dev_desc = dev_desc;
                        break;
                }
 
        acpi_dev_free_resource_list(&resource_list);
 
+       pdata->dev_desc = dev_desc;
+
        if (dev_desc->clk_required) {
                ret = register_device_clock(adev, pdata);
                if (ret) {
index 5e6301e949206adb9f9b512a4b44b9d093e588df..2cf0244d0ee9aa441001e4fbde5f094051313c7b 100644 (file)
@@ -283,6 +283,7 @@ static int acpi_memory_device_add(struct acpi_device *device,
        /* Get the range from the _CRS */
        result = acpi_memory_get_device_resources(mem_device);
        if (result) {
+               device->driver_data = NULL;
                kfree(mem_device);
                return result;
        }
index 35eebdac0f9d1e02976d382376005abbe4a870a5..09b06e2feff8073e8ae998befe35f8d20cf38c93 100644 (file)
@@ -240,12 +240,14 @@ static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id)
            &acpi_sleep_dispatch[function_id];
 
 #if (!ACPI_REDUCED_HARDWARE)
-
        /*
         * If the Hardware Reduced flag is set (from the FADT), we must
-        * use the extended sleep registers
+        * use the extended sleep registers (FADT). Note: As per the ACPI
+        * specification, these extended registers are to be used for HW-reduced
+        * platforms only. They are not general-purpose replacements for the
+        * legacy PM register sleep support.
         */
-       if (acpi_gbl_reduced_hardware || acpi_gbl_FADT.sleep_control.address) {
+       if (acpi_gbl_reduced_hardware) {
                status = sleep_functions->extended_function(sleep_state);
        } else {
                /* Legacy sleep */
index e7100459ac4ad0ab8432e3912841fa0da2988245..95332717e4f5e0f0617fddfd2314e725c4b65a08 100644 (file)
@@ -117,6 +117,7 @@ struct acpi_battery {
        struct acpi_device *device;
        struct notifier_block pm_nb;
        unsigned long update_time;
+       int revision;
        int rate_now;
        int capacity_now;
        int voltage_now;
@@ -359,6 +360,7 @@ static struct acpi_offsets info_offsets[] = {
 };
 
 static struct acpi_offsets extended_info_offsets[] = {
+       {offsetof(struct acpi_battery, revision), 0},
        {offsetof(struct acpi_battery, power_unit), 0},
        {offsetof(struct acpi_battery, design_capacity), 0},
        {offsetof(struct acpi_battery, full_charge_capacity), 0},
index 31c217a42839dce40ee2039cd38f36d935bda543..553527c2532b789de12c864eb653cf020ffba9b0 100644 (file)
@@ -324,14 +324,27 @@ int acpi_bus_update_power(acpi_handle handle, int *state_p)
        if (result)
                return result;
 
-       if (state == ACPI_STATE_UNKNOWN)
+       if (state == ACPI_STATE_UNKNOWN) {
                state = ACPI_STATE_D0;
-
-       result = acpi_device_set_power(device, state);
-       if (!result && state_p)
+               result = acpi_device_set_power(device, state);
+               if (result)
+                       return result;
+       } else {
+               if (device->power.flags.power_resources) {
+                       /*
+                        * We don't need to really switch the state, bu we need
+                        * to update the power resources' reference counters.
+                        */
+                       result = acpi_power_transition(device, state);
+                       if (result)
+                               return result;
+               }
+               device->power.state = state;
+       }
+       if (state_p)
                *state_p = state;
 
-       return result;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(acpi_bus_update_power);
 
index edc00818c80321086ff3938f5df3cf2afae04d61..45af90a1ec1b037e49f6ab1193da905462de71e6 100644 (file)
@@ -983,6 +983,14 @@ static struct dmi_system_id __initdata ec_dmi_table[] = {
        ec_enlarge_storm_threshold, "CLEVO hardware", {
        DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
        DMI_MATCH(DMI_PRODUCT_NAME, "M720T/M730T"),}, NULL},
+       {
+       ec_skip_dsdt_scan, "HP Folio 13", {
+       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+       DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13"),}, NULL},
+       {
+       ec_validate_ecdt, "ASUS hardware", {
+       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer Inc."),
+       DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),}, NULL},
        {},
 };
 
index 40a84cc6740c6c6522afc6bac6d5d5d2178a86bd..238412077c8394ee42ce66af4609697c670d6405 100644 (file)
@@ -78,32 +78,99 @@ static struct acpi_bus_type *acpi_get_bus_type(struct device *dev)
        return ret;
 }
 
-static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used,
-                                     void *addr_p, void **ret_p)
+static acpi_status acpi_dev_present(acpi_handle handle, u32 lvl_not_used,
+                                 void *not_used, void **ret_p)
 {
-       unsigned long long addr;
-       acpi_status status;
+       struct acpi_device *adev = NULL;
 
-       status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr);
-       if (ACPI_SUCCESS(status) && addr == *((u64 *)addr_p)) {
+       acpi_bus_get_device(handle, &adev);
+       if (adev) {
                *ret_p = handle;
                return AE_CTRL_TERMINATE;
        }
        return AE_OK;
 }
 
-acpi_handle acpi_get_child(acpi_handle parent, u64 address)
+static bool acpi_extra_checks_passed(acpi_handle handle, bool is_bridge)
 {
-       void *ret = NULL;
+       unsigned long long sta;
+       acpi_status status;
 
-       if (!parent)
-               return NULL;
+       status = acpi_bus_get_status_handle(handle, &sta);
+       if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED))
+               return false;
+
+       if (is_bridge) {
+               void *test = NULL;
+
+               /* Check if this object has at least one child device. */
+               acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+                                   acpi_dev_present, NULL, NULL, &test);
+               return !!test;
+       }
+       return true;
+}
+
+struct find_child_context {
+       u64 addr;
+       bool is_bridge;
+       acpi_handle ret;
+       bool ret_checked;
+};
+
+static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used,
+                                void *data, void **not_used)
+{
+       struct find_child_context *context = data;
+       unsigned long long addr;
+       acpi_status status;
 
-       acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, NULL,
-                           do_acpi_find_child, &address, &ret);
-       return (acpi_handle)ret;
+       status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr);
+       if (ACPI_FAILURE(status) || addr != context->addr)
+               return AE_OK;
+
+       if (!context->ret) {
+               /* This is the first matching object.  Save its handle. */
+               context->ret = handle;
+               return AE_OK;
+       }
+       /*
+        * There is more than one matching object with the same _ADR value.
+        * That really is unexpected, so we are kind of beyond the scope of the
+        * spec here.  We have to choose which one to return, though.
+        *
+        * First, check if the previously found object is good enough and return
+        * its handle if so.  Second, check the same for the object that we've
+        * just found.
+        */
+       if (!context->ret_checked) {
+               if (acpi_extra_checks_passed(context->ret, context->is_bridge))
+                       return AE_CTRL_TERMINATE;
+               else
+                       context->ret_checked = true;
+       }
+       if (acpi_extra_checks_passed(handle, context->is_bridge)) {
+               context->ret = handle;
+               return AE_CTRL_TERMINATE;
+       }
+       return AE_OK;
+}
+
+acpi_handle acpi_find_child(acpi_handle parent, u64 addr, bool is_bridge)
+{
+       if (parent) {
+               struct find_child_context context = {
+                       .addr = addr,
+                       .is_bridge = is_bridge,
+               };
+
+               acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, do_find_child,
+                                   NULL, &context, NULL);
+               return context.ret;
+       }
+       return NULL;
 }
-EXPORT_SYMBOL(acpi_get_child);
+EXPORT_SYMBOL_GPL(acpi_find_child);
 
 static int acpi_bind_one(struct device *dev, acpi_handle handle)
 {
index c610a76d92c4b4bdf5deafae76252110460d5ed2..63a08549bfa28db0d76a9cc89d2162f50ace768a 100644 (file)
@@ -50,6 +50,11 @@ void acpi_memory_hotplug_init(void);
 #else
 static inline void acpi_memory_hotplug_init(void) {}
 #endif
+#ifdef CONFIG_X86
+void acpi_cmos_rtc_init(void);
+#else
+static inline void acpi_cmos_rtc_init(void) {}
+#endif
 
 void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
                                    const char *name);
index aa1227a7e3f23e349ed5050680d4fef8c135cfc8..04a13784dd20a4a7e42b15b98eedcff90cb67299 100644 (file)
@@ -311,6 +311,8 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
                           dev->pnp.bus_id,
                           (u32) dev->wakeup.sleep_state);
 
+               mutex_lock(&dev->physical_node_lock);
+
                if (!dev->physical_node_count) {
                        seq_printf(seq, "%c%-8s\n",
                                dev->wakeup.flags.run_wake ? '*' : ' ',
@@ -338,6 +340,8 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
                                put_device(ldev);
                        }
                }
+
+               mutex_unlock(&dev->physical_node_lock);
        }
        mutex_unlock(&acpi_device_lock);
        return 0;
@@ -347,12 +351,16 @@ static void physical_device_enable_wakeup(struct acpi_device *adev)
 {
        struct acpi_device_physical_node *entry;
 
+       mutex_lock(&adev->physical_node_lock);
+
        list_for_each_entry(entry,
                &adev->physical_node_list, node)
                if (entry->dev && device_can_wakeup(entry->dev)) {
                        bool enable = !device_may_wakeup(entry->dev);
                        device_set_wakeup_enable(entry->dev, enable);
                }
+
+       mutex_unlock(&adev->physical_node_lock);
 }
 
 static ssize_t
index 27da63061e11ae88c628242e0eed71fc0e1d7588..af658b2ff2799de30d575e107a8309d292ca7adf 100644 (file)
@@ -237,10 +237,12 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source)
 
        mutex_lock(&acpi_scan_lock);
 
-       acpi_bus_get_device(handle, &device);
-       if (device) {
-               dev_warn(&device->dev, "Attempt to re-insert\n");
-               goto out;
+       if (ost_source != ACPI_NOTIFY_BUS_CHECK) {
+               acpi_bus_get_device(handle, &device);
+               if (device) {
+                       dev_warn(&device->dev, "Attempt to re-insert\n");
+                       goto out;
+               }
        }
        acpi_evaluate_hotplug_ost(handle, ost_source,
                                  ACPI_OST_SC_INSERT_IN_PROGRESS, NULL);
@@ -1890,6 +1892,9 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
        if (acpi_bus_get_device(handle, &device))
                return AE_CTRL_DEPTH;
 
+       if (device->handler)
+               return AE_OK;
+
        ret = acpi_scan_attach_handler(device);
        if (ret)
                return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
@@ -2040,6 +2045,7 @@ int __init acpi_scan_init(void)
        acpi_pci_link_init();
        acpi_platform_init();
        acpi_lpss_init();
+       acpi_cmos_rtc_init();
        acpi_container_init();
        acpi_memory_hotplug_init();
        acpi_dock_init();
index 440eadf2d32cdd270a75e9023f9ef31a1d9ae794..0e4b96b62c75f0bf1a79eb72405ce14eed07a5a0 100644 (file)
@@ -448,6 +448,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
                DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"),
                },
        },
+       {
+        .callback = video_ignore_initial_backlight,
+        .ident = "Fujitsu E753",
+        .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "FUJITSU"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E753"),
+               },
+       },
        {
         .callback = video_ignore_initial_backlight,
         .ident = "HP Pavilion dm4",
index a5a3ebcbdd2cf6295028f62d0fe1d3bb21397633..78eabff2fe46fe5839b02d0bc4d1a4f7767abc80 100644 (file)
@@ -107,7 +107,7 @@ config SATA_FSL
          If unsure, say N.
 
 config SATA_INIC162X
-       tristate "Initio 162x SATA support"
+       tristate "Initio 162x SATA support (Very Experimental)"
        depends on PCI
        help
          This option enables support for Initio 162x Serial ATA.
index 2b50dfdf1cfc3ea3a6e468e3776e64958fd38e5e..b112625482ca88db10127cddafb8dce8fe4dd084 100644 (file)
@@ -291,6 +291,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */
        { PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
        { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */
+       { PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */
 
        /* JMicron 360/1/3/5/6, match class to avoid IDE function */
        { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -310,6 +311,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
 
        /* AMD */
        { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
+       { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */
        /* AMD is using RAID class only for ahci controllers */
        { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
          PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
index 9a8a674e8fac9df8ac2c6d08515ce88e6b213fc8..b92913a528b61d418c28379b07f46567f3067514 100644 (file)
@@ -330,7 +330,7 @@ static const struct pci_device_id piix_pci_tbl[] = {
        /* SATA Controller IDE (Wellsburg) */
        { 0x8086, 0x8d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
        /* SATA Controller IDE (Wellsburg) */
-       { 0x8086, 0x8d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+       { 0x8086, 0x8d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
        /* SATA Controller IDE (Wellsburg) */
        { 0x8086, 0x8d60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
        /* SATA Controller IDE (Wellsburg) */
@@ -338,6 +338,8 @@ static const struct pci_device_id piix_pci_tbl[] = {
        /* SATA Controller IDE (BayTrail) */
        { 0x8086, 0x0F20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt },
        { 0x8086, 0x0F21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt },
+       /* SATA Controller IDE (Coleto Creek) */
+       { 0x8086, 0x23a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 
        { }     /* terminate list */
 };
index a70ff154f586753d6c096b858ae5dbee0ad869c3..7b9bdd822c6205d90f6ad40ac931c2d743a3e550 100644 (file)
@@ -1560,8 +1560,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
                u32 fbs = readl(port_mmio + PORT_FBS);
                int pmp = fbs >> PORT_FBS_DWE_OFFSET;
 
-               if ((fbs & PORT_FBS_SDE) && (pmp < ap->nr_pmp_links) &&
-                   ata_link_online(&ap->pmp_link[pmp])) {
+               if ((fbs & PORT_FBS_SDE) && (pmp < ap->nr_pmp_links)) {
                        link = &ap->pmp_link[pmp];
                        fbs_need_dec = true;
                }
index 61c59ee45ce9275af707d68a5328d276863c57df..20fd337a57314a2928c9208bf706ffabed0c4dd5 100644 (file)
@@ -289,24 +289,24 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
 
        /* Disable sending Early R_OK.
         * With "cached read" HDD testing and multiple ports busy on a SATA
-        * host controller, 3726 PMP will very rarely drop a deferred
+        * host controller, 3x26 PMP will very rarely drop a deferred
         * R_OK that was intended for the host. Symptom will be all
         * 5 drives under test will timeout, get reset, and recover.
         */
-       if (vendor == 0x1095 && devid == 0x3726) {
+       if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {
                u32 reg;
 
                err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, &reg);
                if (err_mask) {
                        rc = -EIO;
-                       reason = "failed to read Sil3726 Private Register";
+                       reason = "failed to read Sil3x26 Private Register";
                        goto fail;
                }
                reg &= ~0x1;
                err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg);
                if (err_mask) {
                        rc = -EIO;
-                       reason = "failed to write Sil3726 Private Register";
+                       reason = "failed to write Sil3x26 Private Register";
                        goto fail;
                }
        }
@@ -383,15 +383,19 @@ static void sata_pmp_quirks(struct ata_port *ap)
        u16 devid = sata_pmp_gscr_devid(gscr);
        struct ata_link *link;
 
-       if (vendor == 0x1095 && devid == 0x3726) {
-               /* sil3726 quirks */
+       if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {
+               /* sil3x26 quirks */
                ata_for_each_link(link, ap, EDGE) {
                        /* link reports offline after LPM */
                        link->flags |= ATA_LFLAG_NO_LPM;
 
-                       /* Class code report is unreliable. */
+                       /*
+                        * Class code report is unreliable and SRST times
+                        * out under certain configurations.
+                        */
                        if (link->pmp < 5)
-                               link->flags |= ATA_LFLAG_ASSUME_ATA;
+                               link->flags |= ATA_LFLAG_NO_SRST |
+                                              ATA_LFLAG_ASSUME_ATA;
 
                        /* port 5 is for SEMB device and it doesn't like SRST */
                        if (link->pmp == 5)
@@ -399,20 +403,17 @@ static void sata_pmp_quirks(struct ata_port *ap)
                                               ATA_LFLAG_ASSUME_SEMB;
                }
        } else if (vendor == 0x1095 && devid == 0x4723) {
-               /* sil4723 quirks */
-               ata_for_each_link(link, ap, EDGE) {
-                       /* link reports offline after LPM */
-                       link->flags |= ATA_LFLAG_NO_LPM;
-
-                       /* class code report is unreliable */
-                       if (link->pmp < 2)
-                               link->flags |= ATA_LFLAG_ASSUME_ATA;
-
-                       /* the config device at port 2 locks up on SRST */
-                       if (link->pmp == 2)
-                               link->flags |= ATA_LFLAG_NO_SRST |
-                                              ATA_LFLAG_ASSUME_ATA;
-               }
+               /*
+                * sil4723 quirks
+                *
+                * Link reports offline after LPM.  Class code report is
+                * unreliable.  SIMG PMPs never got SRST reliable and the
+                * config device at port 2 locks up on SRST.
+                */
+               ata_for_each_link(link, ap, EDGE)
+                       link->flags |= ATA_LFLAG_NO_LPM |
+                                      ATA_LFLAG_NO_SRST |
+                                      ATA_LFLAG_ASSUME_ATA;
        } else if (vendor == 0x1095 && devid == 0x4726) {
                /* sil4726 quirks */
                ata_for_each_link(link, ap, EDGE) {
index 90b159b740b3fd1f9153f371a84fa803c17ee4d6..cd8daf47188b0a635cd697a5ed406c0c92e02ab6 100644 (file)
@@ -32,13 +32,14 @@ struct zpodd {
 
 static int eject_tray(struct ata_device *dev)
 {
-       struct ata_taskfile tf = {};
+       struct ata_taskfile tf;
        const char cdb[] = {  GPCMD_START_STOP_UNIT,
                0, 0, 0,
                0x02,     /* LoEj */
                0, 0, 0, 0, 0, 0, 0,
        };
 
+       ata_tf_init(dev, &tf);
        tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
        tf.command = ATA_CMD_PACKET;
        tf.protocol = ATAPI_PROT_NODATA;
@@ -52,8 +53,7 @@ static enum odd_mech_type zpodd_get_mech_type(struct ata_device *dev)
        char buf[16];
        unsigned int ret;
        struct rm_feature_desc *desc = (void *)(buf + 8);
-       struct ata_taskfile tf = {};
-
+       struct ata_taskfile tf;
        char cdb[] = {  GPCMD_GET_CONFIGURATION,
                        2,      /* only 1 feature descriptor requested */
                        0, 3,   /* 3, removable medium feature */
@@ -62,6 +62,7 @@ static enum odd_mech_type zpodd_get_mech_type(struct ata_device *dev)
                        0, 0, 0,
        };
 
+       ata_tf_init(dev, &tf);
        tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
        tf.command = ATA_CMD_PACKET;
        tf.protocol = ATAPI_PROT_PIO;
index d40e403e82dd259a34ab6a155a88619ba3b3542a..8401061b4040b7fd3e2e13cfbee9cd51c87b2ce7 100644 (file)
@@ -293,6 +293,7 @@ static void fsl_sata_set_irq_coalescing(struct ata_host *host,
 {
        struct sata_fsl_host_priv *host_priv = host->private_data;
        void __iomem *hcr_base = host_priv->hcr_base;
+       unsigned long flags;
 
        if (count > ICC_MAX_INT_COUNT_THRESHOLD)
                count = ICC_MAX_INT_COUNT_THRESHOLD;
@@ -305,12 +306,12 @@ static void fsl_sata_set_irq_coalescing(struct ata_host *host,
                        (count > ICC_MIN_INT_COUNT_THRESHOLD))
                ticks = ICC_SAFE_INT_TICKS;
 
-       spin_lock(&host->lock);
+       spin_lock_irqsave(&host->lock, flags);
        iowrite32((count << 24 | ticks), hcr_base + ICC);
 
        intr_coalescing_count = count;
        intr_coalescing_ticks = ticks;
-       spin_unlock(&host->lock);
+       spin_unlock_irqrestore(&host->lock, flags);
 
        DPRINTK("interrupt coalescing, count = 0x%x, ticks = %x\n",
                        intr_coalescing_count, intr_coalescing_ticks);
index b20aa96b958d2428e4cd776cedfc57eee56ba3d8..c846fd3c5c091e1999b295f49c58a97faa4fa204 100644 (file)
@@ -196,10 +196,26 @@ static int highbank_initialize_phys(struct device *dev, void __iomem *addr)
        return 0;
 }
 
+/*
+ * The Calxeda SATA phy intermittently fails to bring up a link with Gen3
+ * Retrying the phy hard reset can work around the issue, but the drive
+ * may fail again. In less than 150 out of 15000 test runs, it took more
+ * than 10 tries for the link to be established (but never more than 35).
+ * Triple the maximum observed retry count to provide plenty of margin for
+ * rare events and to guarantee that the link is established.
+ *
+ * Also, the default 2 second time-out on a failed drive is too long in
+ * this situation. The uboot implementation of the same driver function
+ * uses a much shorter time-out period and never experiences a time out
+ * issue. Reducing the time-out to 500ms improves the responsiveness.
+ * The other timing constants were kept the same as the stock AHCI driver.
+ * This change was also tested 15000 times on 24 drives and none of them
+ * experienced a time out.
+ */
 static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
                                unsigned long deadline)
 {
-       const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+       static const unsigned long timing[] = { 5, 100, 500};
        struct ata_port *ap = link->ap;
        struct ahci_port_priv *pp = ap->private_data;
        u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
@@ -207,7 +223,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
        bool online;
        u32 sstatus;
        int rc;
-       int retry = 10;
+       int retry = 100;
 
        ahci_stop_engine(ap);
 
index 1e6827c89429d4bd79b422745d23faf6d8407d9f..74456fa8483fd8f699ed3c7b91bf6e6ec956d653 100644 (file)
@@ -6,6 +6,18 @@
  *
  * This file is released under GPL v2.
  *
+ * **** WARNING ****
+ *
+ * This driver never worked properly and unfortunately data corruption is
+ * relatively common.  There isn't anyone working on the driver and there's
+ * no support from the vendor.  Do not use this driver in any production
+ * environment.
+ *
+ * http://thread.gmane.org/gmane.linux.debian.devel.bugs.rc/378525/focus=54491
+ * https://bugzilla.kernel.org/show_bug.cgi?id=60565
+ *
+ * *****************
+ *
  * This controller is eccentric and easily locks up if something isn't
  * right.  Documentation is available at initio's website but it only
  * documents registers (not programming model).
@@ -807,6 +819,8 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        ata_print_version_once(&pdev->dev, DRV_VERSION);
 
+       dev_alert(&pdev->dev, "inic162x support is broken with common data corruption issues and will be disabled by default, contact linux-ide@vger.kernel.org if in production use\n");
+
        /* alloc host */
        host = ata_host_alloc_pinfo(&pdev->dev, ppi, NR_PORTS);
        hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
index 14f8a6954da0a11f1250b75b050318a9c63a4cb2..86abbff912ecc0687e1b4ac93701af8cfcded1b5 100644 (file)
@@ -152,6 +152,8 @@ static ssize_t show_mem_removable(struct device *dev,
                container_of(dev, struct memory_block, dev);
 
        for (i = 0; i < sections_per_block; i++) {
+               if (!present_section_nr(mem->start_section_nr + i))
+                       continue;
                pfn = section_nr_to_pfn(mem->start_section_nr + i);
                ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
        }
index 02f490bad30f791f627db78584ca75b691bc6eb7..bb8c3bbc78128ba51e77455df0587fa58aa6d19f 100644 (file)
@@ -362,7 +362,7 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
                rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL);
                if (!rbnode)
                        return -ENOMEM;
-               rbnode->blklen = sizeof(*rbnode);
+               rbnode->blklen = 1;
                rbnode->base_reg = reg;
                rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,
                                        GFP_KERNEL);
index 507ee2da0f6ee9b6455ab967f2dcf76a49c57b02..46283fd3c4c0dfb680e7ffe5d7320f6bf6ec581e 100644 (file)
@@ -644,7 +644,8 @@ static int regcache_sync_block_raw(struct regmap *map, void *block,
                }
        }
 
-       return regcache_sync_block_raw_flush(map, &data, base, regtmp);
+       return regcache_sync_block_raw_flush(map, &data, base, regtmp +
+                       map->reg_stride);
 }
 
 int regcache_sync_block(struct regmap *map, void *block,
index a941dcfe7590119f7f1cc1b4a69574ea3d47b9b6..d0c81d1f409c07bf2bb4eac3f34469a7b9626dd9 100644 (file)
@@ -1717,7 +1717,7 @@ int regmap_async_complete(struct regmap *map)
        int ret;
 
        /* Nothing to do with no async support */
-       if (!map->bus->async_write)
+       if (!map->bus || !map->bus->async_write)
                return 0;
 
        trace_regmap_async_complete_start(map->dev);
index 037288e7874d625676f5fa9e95a9920ac91551f5..cf1576d5436369d345465db37cd8368a80eff605 100644 (file)
@@ -623,8 +623,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
                if (!nbd->sock)
                        return -EINVAL;
 
+               nbd->disconnect = 1;
+
                nbd_send_req(nbd, &sreq);
-                return 0;
+               return 0;
        }
  
        case NBD_CLEAR_SOCK: {
@@ -654,6 +656,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
                                nbd->sock = SOCKET_I(inode);
                                if (max_part > 0)
                                        bdev->bd_invalidated = 1;
+                               nbd->disconnect = 0; /* we're connected now */
                                return 0;
                        } else {
                                fput(file);
@@ -714,7 +717,8 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
                else
                        blk_queue_flush(nbd->disk->queue, 0);
 
-               thread = kthread_create(nbd_thread, nbd, nbd->disk->disk_name);
+               thread = kthread_create(nbd_thread, nbd, "%s",
+                                       nbd->disk->disk_name);
                if (IS_ERR(thread)) {
                        mutex_lock(&nbd->tx_lock);
                        return PTR_ERR(thread);
@@ -742,6 +746,8 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
                set_capacity(nbd->disk, 0);
                if (max_part > 0)
                        ioctl_by_bdev(bdev, BLKRRPART, 0);
+               if (nbd->disconnect) /* user requested, ignore socket errors */
+                       return 0;
                return nbd->harderror;
        }
 
index aff789d6fccd35b7f0a0c3314e5c04951c6c774c..8c7421af8f1572e11c67f34daa5a9f2dfd9001e9 100644 (file)
@@ -1565,11 +1565,12 @@ rbd_img_obj_request_read_callback(struct rbd_obj_request *obj_request)
                obj_request, obj_request->img_request, obj_request->result,
                xferred, length);
        /*
-        * ENOENT means a hole in the image.  We zero-fill the
-        * entire length of the request.  A short read also implies
-        * zero-fill to the end of the request.  Either way we
-        * update the xferred count to indicate the whole request
-        * was satisfied.
+        * ENOENT means a hole in the image.  We zero-fill the entire
+        * length of the request.  A short read also implies zero-fill
+        * to the end of the request.  An error requires the whole
+        * length of the request to be reported finished with an error
+        * to the block layer.  In each case we update the xferred
+        * count to indicate the whole request was satisfied.
         */
        rbd_assert(obj_request->type != OBJ_REQUEST_NODATA);
        if (obj_request->result == -ENOENT) {
@@ -1578,14 +1579,13 @@ rbd_img_obj_request_read_callback(struct rbd_obj_request *obj_request)
                else
                        zero_pages(obj_request->pages, 0, length);
                obj_request->result = 0;
-               obj_request->xferred = length;
        } else if (xferred < length && !obj_request->result) {
                if (obj_request->type == OBJ_REQUEST_BIO)
                        zero_bio_chain(obj_request->bio_list, xferred);
                else
                        zero_pages(obj_request->pages, xferred, length);
-               obj_request->xferred = length;
        }
+       obj_request->xferred = length;
        obj_request_done_set(obj_request);
 }
 
index dd5b2fed97e9ae2b7665f13ec3c42db6ee6fb462..d81dfca755d15f2ad655596ed607fbe2f2fd891a 100644 (file)
@@ -647,7 +647,18 @@ static int dispatch_discard_io(struct xen_blkif *blkif,
        int status = BLKIF_RSP_OKAY;
        struct block_device *bdev = blkif->vbd.bdev;
        unsigned long secure;
+       struct phys_req preq;
+
+       preq.sector_number = req->u.discard.sector_number;
+       preq.nr_sects      = req->u.discard.nr_sectors;
 
+       err = xen_vbd_translate(&preq, blkif, WRITE);
+       if (err) {
+               pr_warn(DRV_PFX "access denied: DISCARD [%llu->%llu] on dev=%04x\n",
+                       preq.sector_number,
+                       preq.sector_number + preq.nr_sects, blkif->vbd.pdevice);
+               goto fail_response;
+       }
        blkif->st_ds_req++;
 
        xen_blkif_get(blkif);
@@ -658,7 +669,7 @@ static int dispatch_discard_io(struct xen_blkif *blkif,
        err = blkdev_issue_discard(bdev, req->u.discard.sector_number,
                                   req->u.discard.nr_sectors,
                                   GFP_KERNEL, secure);
-
+fail_response:
        if (err == -EOPNOTSUPP) {
                pr_debug(DRV_PFX "discard op failed, not supported\n");
                status = BLKIF_RSP_EOPNOTSUPP;
index d89ef86220f4a55a247083d36d5f8dd3ce74e0d5..69b45fc9727680e796951e1afe6f5de0b21350bb 100644 (file)
@@ -75,6 +75,7 @@ struct blk_shadow {
        struct blkif_request req;
        struct request *request;
        struct grant *grants_used[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+       struct scatterlist sg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 };
 
 static DEFINE_MUTEX(blkfront_mutex);
@@ -98,7 +99,6 @@ struct blkfront_info
        enum blkif_state connected;
        int ring_ref;
        struct blkif_front_ring ring;
-       struct scatterlist sg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
        unsigned int evtchn, irq;
        struct request_queue *rq;
        struct work_struct work;
@@ -422,11 +422,11 @@ static int blkif_queue_request(struct request *req)
                        ring_req->u.discard.flag = 0;
        } else {
                ring_req->u.rw.nr_segments = blk_rq_map_sg(req->q, req,
-                                                          info->sg);
+                                                          info->shadow[id].sg);
                BUG_ON(ring_req->u.rw.nr_segments >
                       BLKIF_MAX_SEGMENTS_PER_REQUEST);
 
-               for_each_sg(info->sg, sg, ring_req->u.rw.nr_segments, i) {
+               for_each_sg(info->shadow[id].sg, sg, ring_req->u.rw.nr_segments, i) {
                        fsect = sg->offset >> 9;
                        lsect = fsect + (sg->length >> 9) - 1;
 
@@ -867,12 +867,12 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,
                             struct blkif_response *bret)
 {
        int i = 0;
-       struct bio_vec *bvec;
-       struct req_iterator iter;
-       unsigned long flags;
+       struct scatterlist *sg;
        char *bvec_data;
        void *shared_data;
-       unsigned int offset = 0;
+       int nseg;
+
+       nseg = s->req.u.rw.nr_segments;
 
        if (bret->operation == BLKIF_OP_READ) {
                /*
@@ -881,19 +881,16 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,
                 * than PAGE_SIZE, we have to keep track of the current offset,
                 * to be sure we are copying the data from the right shared page.
                 */
-               rq_for_each_segment(bvec, s->request, iter) {
-                       BUG_ON((bvec->bv_offset + bvec->bv_len) > PAGE_SIZE);
-                       if (bvec->bv_offset < offset)
-                               i++;
-                       BUG_ON(i >= s->req.u.rw.nr_segments);
+               for_each_sg(s->sg, sg, nseg, i) {
+                       BUG_ON(sg->offset + sg->length > PAGE_SIZE);
                        shared_data = kmap_atomic(
                                pfn_to_page(s->grants_used[i]->pfn));
-                       bvec_data = bvec_kmap_irq(bvec, &flags);
-                       memcpy(bvec_data, shared_data + bvec->bv_offset,
-                               bvec->bv_len);
-                       bvec_kunmap_irq(bvec_data, &flags);
+                       bvec_data = kmap_atomic(sg_page(sg));
+                       memcpy(bvec_data   + sg->offset,
+                              shared_data + sg->offset,
+                              sg->length);
+                       kunmap_atomic(bvec_data);
                        kunmap_atomic(shared_data);
-                       offset = bvec->bv_offset + bvec->bv_len;
                }
        }
        /* Add the persistent grant into the list of free grants */
@@ -1022,7 +1019,7 @@ static int setup_blkring(struct xenbus_device *dev,
                         struct blkfront_info *info)
 {
        struct blkif_sring *sring;
-       int err;
+       int err, i;
 
        info->ring_ref = GRANT_INVALID_REF;
 
@@ -1034,7 +1031,8 @@ static int setup_blkring(struct xenbus_device *dev,
        SHARED_RING_INIT(sring);
        FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);
 
-       sg_init_table(info->sg, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+       for (i = 0; i < BLK_RING_SIZE; i++)
+               sg_init_table(info->shadow[i].sg, BLKIF_MAX_SEGMENTS_PER_REQUEST);
 
        /* Allocate memory for grants */
        err = fill_grant_buffer(info, BLK_RING_SIZE *
index 11f467c00d0ac836a1c6509bffd31e49b891a844..a12b923bbaca91f14b923e0b271b00ebc1be8d28 100644 (file)
@@ -91,6 +91,10 @@ static struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x0489, 0xe04e) },
        { USB_DEVICE(0x0489, 0xe056) },
        { USB_DEVICE(0x0489, 0xe04d) },
+       { USB_DEVICE(0x04c5, 0x1330) },
+       { USB_DEVICE(0x13d3, 0x3402) },
+       { USB_DEVICE(0x0cf3, 0x3121) },
+       { USB_DEVICE(0x0cf3, 0xe003) },
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE02C) },
@@ -128,6 +132,10 @@ static struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
 
        /* Atheros AR5BBU22 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
@@ -193,24 +201,44 @@ error:
 
 static int ath3k_get_state(struct usb_device *udev, unsigned char *state)
 {
-       int pipe = 0;
+       int ret, pipe = 0;
+       char *buf;
+
+       buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
 
        pipe = usb_rcvctrlpipe(udev, 0);
-       return usb_control_msg(udev, pipe, ATH3K_GETSTATE,
-                       USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
-                       state, 0x01, USB_CTRL_SET_TIMEOUT);
+       ret = usb_control_msg(udev, pipe, ATH3K_GETSTATE,
+                             USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
+                             buf, sizeof(*buf), USB_CTRL_SET_TIMEOUT);
+
+       *state = *buf;
+       kfree(buf);
+
+       return ret;
 }
 
 static int ath3k_get_version(struct usb_device *udev,
                        struct ath3k_version *version)
 {
-       int pipe = 0;
+       int ret, pipe = 0;
+       struct ath3k_version *buf;
+       const int size = sizeof(*buf);
+
+       buf = kmalloc(size, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
 
        pipe = usb_rcvctrlpipe(udev, 0);
-       return usb_control_msg(udev, pipe, ATH3K_GETVERSION,
-                       USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, version,
-                       sizeof(struct ath3k_version),
-                       USB_CTRL_SET_TIMEOUT);
+       ret = usb_control_msg(udev, pipe, ATH3K_GETVERSION,
+                             USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
+                             buf, size, USB_CTRL_SET_TIMEOUT);
+
+       memcpy(version, buf, size);
+       kfree(buf);
+
+       return ret;
 }
 
 static int ath3k_load_fwfile(struct usb_device *udev,
index 7a7e5f8ecadcffef990eaea6c2fafdcf94ff4c4b..d0b3d900d452d3422a84ebff8957b09bb6177f4c 100644 (file)
@@ -57,6 +57,9 @@ static struct usb_device_id btusb_table[] = {
        /* Apple-specific (Broadcom) devices */
        { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) },
 
+       /* MediaTek MT76x0E */
+       { USB_DEVICE(0x0e8d, 0x763f) },
+
        /* Broadcom SoftSailing reporting vendor specific */
        { USB_DEVICE(0x0a5c, 0x21e1) },
 
@@ -151,6 +154,10 @@ static struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
@@ -1092,7 +1099,7 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev,
        if (IS_ERR(skb)) {
                BT_ERR("%s sending Intel patch command (0x%4.4x) failed (%ld)",
                       hdev->name, cmd->opcode, PTR_ERR(skb));
-               return -PTR_ERR(skb);
+               return PTR_ERR(skb);
        }
 
        /* It ensures that the returned event matches the event data read from
@@ -1144,7 +1151,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
        if (IS_ERR(skb)) {
                BT_ERR("%s sending initial HCI reset command failed (%ld)",
                       hdev->name, PTR_ERR(skb));
-               return -PTR_ERR(skb);
+               return PTR_ERR(skb);
        }
        kfree_skb(skb);
 
@@ -1158,7 +1165,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
        if (IS_ERR(skb)) {
                BT_ERR("%s reading Intel fw version command failed (%ld)",
                       hdev->name, PTR_ERR(skb));
-               return -PTR_ERR(skb);
+               return PTR_ERR(skb);
        }
 
        if (skb->len != sizeof(*ver)) {
@@ -1216,7 +1223,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
                BT_ERR("%s entering Intel manufacturer mode failed (%ld)",
                       hdev->name, PTR_ERR(skb));
                release_firmware(fw);
-               return -PTR_ERR(skb);
+               return PTR_ERR(skb);
        }
 
        if (skb->data[0]) {
@@ -1273,7 +1280,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
        if (IS_ERR(skb)) {
                BT_ERR("%s exiting Intel manufacturer mode failed (%ld)",
                       hdev->name, PTR_ERR(skb));
-               return -PTR_ERR(skb);
+               return PTR_ERR(skb);
        }
        kfree_skb(skb);
 
@@ -1289,7 +1296,7 @@ exit_mfg_disable:
        if (IS_ERR(skb)) {
                BT_ERR("%s exiting Intel manufacturer mode failed (%ld)",
                       hdev->name, PTR_ERR(skb));
-               return -PTR_ERR(skb);
+               return PTR_ERR(skb);
        }
        kfree_skb(skb);
 
@@ -1307,7 +1314,7 @@ exit_mfg_deactivate:
        if (IS_ERR(skb)) {
                BT_ERR("%s exiting Intel manufacturer mode failed (%ld)",
                       hdev->name, PTR_ERR(skb));
-               return -PTR_ERR(skb);
+               return PTR_ERR(skb);
        }
        kfree_skb(skb);
 
index d620b44957454a80fcf444d10cb967e66fb9d7d5..8a3aff724d989c331f5de1596f3064cbbe72c271 100644 (file)
@@ -2882,7 +2882,7 @@ static noinline int mmc_ioctl_cdrom_read_data(struct cdrom_device_info *cdi,
        if (lba < 0)
                return -EINVAL;
 
-       cgc->buffer = kmalloc(blocksize, GFP_KERNEL);
+       cgc->buffer = kzalloc(blocksize, GFP_KERNEL);
        if (cgc->buffer == NULL)
                return -ENOMEM;
 
index 94821ab01c6d6ae1803201c27217c69a30357329..9576fad5d71cb7575adce4699754d3ceed2ae85c 100644 (file)
@@ -129,7 +129,8 @@ parisc_agp_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
        off_t j, io_pg_start;
        int io_pg_count;
 
-       if (type != 0 || mem->type != 0) {
+       if (type != mem->type ||
+               agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
                return -EINVAL;
        }
 
@@ -175,7 +176,8 @@ parisc_agp_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
        struct _parisc_agp_info *info = &parisc_agp_info;
        int i, io_pg_start, io_pg_count;
 
-       if (type != 0 || mem->type != 0) {
+       if (type != mem->type ||
+               agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
                return -EINVAL;
        }
 
index eb7f14725ebd2c7896b8a924d4527c1bc30730d4..43577ca780e304e7c6d25d919da70927bb8ffeb5 100644 (file)
@@ -110,4 +110,4 @@ module_platform_driver(bcm2835_rng_driver);
 
 MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
 MODULE_DESCRIPTION("BCM2835 Random Number Generator (RNG) driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
index 1b456fe9b87a12f98e8a6d691487c252271cb3e6..fc45567ad3acef079db496c9a2f495e19e5b5bba 100644 (file)
@@ -272,9 +272,12 @@ static struct port *find_port_by_devt_in_portdev(struct ports_device *portdev,
        unsigned long flags;
 
        spin_lock_irqsave(&portdev->ports_lock, flags);
-       list_for_each_entry(port, &portdev->ports, list)
-               if (port->cdev->dev == dev)
+       list_for_each_entry(port, &portdev->ports, list) {
+               if (port->cdev->dev == dev) {
+                       kref_get(&port->kref);
                        goto out;
+               }
+       }
        port = NULL;
 out:
        spin_unlock_irqrestore(&portdev->ports_lock, flags);
@@ -746,6 +749,10 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
 
        port = filp->private_data;
 
+       /* Port is hot-unplugged. */
+       if (!port->guest_connected)
+               return -ENODEV;
+
        if (!port_has_data(port)) {
                /*
                 * If nothing's connected on the host just return 0 in
@@ -762,7 +769,7 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
                if (ret < 0)
                        return ret;
        }
-       /* Port got hot-unplugged. */
+       /* Port got hot-unplugged while we were waiting above. */
        if (!port->guest_connected)
                return -ENODEV;
        /*
@@ -932,13 +939,25 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe,
        if (is_rproc_serial(port->out_vq->vdev))
                return -EINVAL;
 
+       /*
+        * pipe->nrbufs == 0 means there are no data to transfer,
+        * so this returns just 0 for no data.
+        */
+       pipe_lock(pipe);
+       if (!pipe->nrbufs) {
+               ret = 0;
+               goto error_out;
+       }
+
        ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK);
        if (ret < 0)
-               return ret;
+               goto error_out;
 
        buf = alloc_buf(port->out_vq, 0, pipe->nrbufs);
-       if (!buf)
-               return -ENOMEM;
+       if (!buf) {
+               ret = -ENOMEM;
+               goto error_out;
+       }
 
        sgl.n = 0;
        sgl.len = 0;
@@ -946,12 +965,17 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe,
        sgl.sg = buf->sg;
        sg_init_table(sgl.sg, sgl.size);
        ret = __splice_from_pipe(pipe, &sd, pipe_to_sg);
+       pipe_unlock(pipe);
        if (likely(ret > 0))
                ret = __send_to_port(port, buf->sg, sgl.n, sgl.len, buf, true);
 
        if (unlikely(ret <= 0))
                free_buf(buf, true);
        return ret;
+
+error_out:
+       pipe_unlock(pipe);
+       return ret;
 }
 
 static unsigned int port_fops_poll(struct file *filp, poll_table *wait)
@@ -1019,14 +1043,14 @@ static int port_fops_open(struct inode *inode, struct file *filp)
        struct port *port;
        int ret;
 
+       /* We get the port with a kref here */
        port = find_port_by_devt(cdev->dev);
+       if (!port) {
+               /* Port was unplugged before we could proceed */
+               return -ENXIO;
+       }
        filp->private_data = port;
 
-       /* Prevent against a port getting hot-unplugged at the same time */
-       spin_lock_irq(&port->portdev->ports_lock);
-       kref_get(&port->kref);
-       spin_unlock_irq(&port->portdev->ports_lock);
-
        /*
         * Don't allow opening of console port devices -- that's done
         * via /dev/hvc
@@ -1498,14 +1522,6 @@ static void remove_port(struct kref *kref)
 
        port = container_of(kref, struct port, kref);
 
-       sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
-       device_destroy(pdrvdata.class, port->dev->devt);
-       cdev_del(port->cdev);
-
-       kfree(port->name);
-
-       debugfs_remove(port->debugfs_file);
-
        kfree(port);
 }
 
@@ -1539,12 +1555,14 @@ static void unplug_port(struct port *port)
        spin_unlock_irq(&port->portdev->ports_lock);
 
        if (port->guest_connected) {
+               /* Let the app know the port is going down. */
+               send_sigio_to_port(port);
+
+               /* Do this after sigio is actually sent */
                port->guest_connected = false;
                port->host_connected = false;
-               wake_up_interruptible(&port->waitqueue);
 
-               /* Let the app know the port is going down. */
-               send_sigio_to_port(port);
+               wake_up_interruptible(&port->waitqueue);
        }
 
        if (is_console_port(port)) {
@@ -1563,6 +1581,14 @@ static void unplug_port(struct port *port)
         */
        port->portdev = NULL;
 
+       sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
+       device_destroy(pdrvdata.class, port->dev->devt);
+       cdev_del(port->cdev);
+
+       kfree(port->name);
+
+       debugfs_remove(port->debugfs_file);
+
        /*
         * Locks around here are not necessary - a port can't be
         * opened after we removed the port struct from ports_list
index 16ed06808554aa5aa92651342e3b2e88c32784a6..917a3ab482f9ac4831c91b48b4a5a6401fb6fc4c 100644 (file)
@@ -360,6 +360,8 @@ static int wm831x_clk_probe(struct platform_device *pdev)
        if (!clkdata)
                return -ENOMEM;
 
+       clkdata->wm831x = wm831x;
+
        /* XTAL_ENA can only be set via OTP/InstantConfig so just read once */
        ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
        if (ret < 0) {
index ab09ed3742ee6c585ed6a607ce2adfbd7d0a5929..6b02eddc5f5069ff80f226fdad83ca447041f892 100644 (file)
@@ -44,7 +44,7 @@ static void add_clockevent(struct device_node *event_timer)
        u32 irq, rate;
 
        irq = irq_of_parse_and_map(event_timer, 0);
-       if (irq == NO_IRQ)
+       if (irq == 0)
                panic("No IRQ for clock event timer");
 
        timer_get_base_and_rate(event_timer, &iobase, &rate);
index 2d53f47d1747360b8968c7c308c0f975777ef9ab..648554742a998aec1f2c0fdfea26adb597a8d7db 100644 (file)
@@ -1075,14 +1075,11 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif
                                __func__, cpu_dev->id, cpu);
        }
 
-       if ((cpus == 1) && (cpufreq_driver->target))
-               __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
-
-       pr_debug("%s: removing link, cpu: %d\n", __func__, cpu);
-       cpufreq_cpu_put(data);
-
        /* If cpu is last user of policy, free policy */
        if (cpus == 1) {
+               if (cpufreq_driver->target)
+                       __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
+
                lock_policy_rwsem_read(cpu);
                kobj = &data->kobj;
                cmp = &data->kobj_unregister;
@@ -1103,9 +1100,13 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif
                free_cpumask_var(data->related_cpus);
                free_cpumask_var(data->cpus);
                kfree(data);
-       } else if (cpufreq_driver->target) {
-               __cpufreq_governor(data, CPUFREQ_GOV_START);
-               __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
+       } else {
+               pr_debug("%s: removing link, cpu: %d\n", __func__, cpu);
+               cpufreq_cpu_put(data);
+               if (cpufreq_driver->target) {
+                       __cpufreq_governor(data, CPUFREQ_GOV_START);
+                       __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
+               }
        }
 
        per_cpu(cpufreq_policy_cpu, cpu) = -1;
@@ -1837,13 +1838,15 @@ static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb,
        if (dev) {
                switch (action) {
                case CPU_ONLINE:
+               case CPU_ONLINE_FROZEN:
                        cpufreq_add_dev(dev, NULL);
                        break;
                case CPU_DOWN_PREPARE:
-               case CPU_UP_CANCELED_FROZEN:
+               case CPU_DOWN_PREPARE_FROZEN:
                        __cpufreq_remove_dev(dev, NULL);
                        break;
                case CPU_DOWN_FAILED:
+               case CPU_DOWN_FAILED_FROZEN:
                        cpufreq_add_dev(dev, NULL);
                        break;
                }
index 0ceb2eff5a7e7044adfcf37a5522b131017d6088..f97cb3d8c5a232a60f319e04da5c0616624925d4 100644 (file)
@@ -221,8 +221,8 @@ static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf,
        return count;
 }
 
-static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
-               size_t count)
+static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
+               const char *buf, size_t count)
 {
        struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
        unsigned int input, j;
@@ -235,10 +235,10 @@ static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
        if (input > 1)
                input = 1;
 
-       if (input == cs_tuners->ignore_nice) /* nothing to do */
+       if (input == cs_tuners->ignore_nice_load) /* nothing to do */
                return count;
 
-       cs_tuners->ignore_nice = input;
+       cs_tuners->ignore_nice_load = input;
 
        /* we need to re-evaluate prev_cpu_idle */
        for_each_online_cpu(j) {
@@ -246,7 +246,7 @@ static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
                dbs_info = &per_cpu(cs_cpu_dbs_info, j);
                dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
                                        &dbs_info->cdbs.prev_cpu_wall, 0);
-               if (cs_tuners->ignore_nice)
+               if (cs_tuners->ignore_nice_load)
                        dbs_info->cdbs.prev_cpu_nice =
                                kcpustat_cpu(j).cpustat[CPUTIME_NICE];
        }
@@ -279,7 +279,7 @@ show_store_one(cs, sampling_rate);
 show_store_one(cs, sampling_down_factor);
 show_store_one(cs, up_threshold);
 show_store_one(cs, down_threshold);
-show_store_one(cs, ignore_nice);
+show_store_one(cs, ignore_nice_load);
 show_store_one(cs, freq_step);
 declare_show_sampling_rate_min(cs);
 
@@ -287,7 +287,7 @@ gov_sys_pol_attr_rw(sampling_rate);
 gov_sys_pol_attr_rw(sampling_down_factor);
 gov_sys_pol_attr_rw(up_threshold);
 gov_sys_pol_attr_rw(down_threshold);
-gov_sys_pol_attr_rw(ignore_nice);
+gov_sys_pol_attr_rw(ignore_nice_load);
 gov_sys_pol_attr_rw(freq_step);
 gov_sys_pol_attr_ro(sampling_rate_min);
 
@@ -297,7 +297,7 @@ static struct attribute *dbs_attributes_gov_sys[] = {
        &sampling_down_factor_gov_sys.attr,
        &up_threshold_gov_sys.attr,
        &down_threshold_gov_sys.attr,
-       &ignore_nice_gov_sys.attr,
+       &ignore_nice_load_gov_sys.attr,
        &freq_step_gov_sys.attr,
        NULL
 };
@@ -313,7 +313,7 @@ static struct attribute *dbs_attributes_gov_pol[] = {
        &sampling_down_factor_gov_pol.attr,
        &up_threshold_gov_pol.attr,
        &down_threshold_gov_pol.attr,
-       &ignore_nice_gov_pol.attr,
+       &ignore_nice_load_gov_pol.attr,
        &freq_step_gov_pol.attr,
        NULL
 };
@@ -338,7 +338,7 @@ static int cs_init(struct dbs_data *dbs_data)
        tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD;
        tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD;
        tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
-       tuners->ignore_nice = 0;
+       tuners->ignore_nice_load = 0;
        tuners->freq_step = DEF_FREQUENCY_STEP;
 
        dbs_data->tuners = tuners;
index dc9b72e25c1ab66c429fb65e9cb1d410ef4ee908..a86ff72141f3b88eced5bddc34f787bb894f4b10 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/tick.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
-#include <linux/cpu.h>
 
 #include "cpufreq_governor.h"
 
@@ -92,9 +91,9 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
        unsigned int j;
 
        if (dbs_data->cdata->governor == GOV_ONDEMAND)
-               ignore_nice = od_tuners->ignore_nice;
+               ignore_nice = od_tuners->ignore_nice_load;
        else
-               ignore_nice = cs_tuners->ignore_nice;
+               ignore_nice = cs_tuners->ignore_nice_load;
 
        policy = cdbs->cur_policy;
 
@@ -181,10 +180,8 @@ void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
        if (!all_cpus) {
                __gov_queue_work(smp_processor_id(), dbs_data, delay);
        } else {
-               get_online_cpus();
                for_each_cpu(i, policy->cpus)
                        __gov_queue_work(i, dbs_data, delay);
-               put_online_cpus();
        }
 }
 EXPORT_SYMBOL_GPL(gov_queue_work);
@@ -339,12 +336,12 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                cs_tuners = dbs_data->tuners;
                cs_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu);
                sampling_rate = cs_tuners->sampling_rate;
-               ignore_nice = cs_tuners->ignore_nice;
+               ignore_nice = cs_tuners->ignore_nice_load;
        } else {
                od_tuners = dbs_data->tuners;
                od_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu);
                sampling_rate = od_tuners->sampling_rate;
-               ignore_nice = od_tuners->ignore_nice;
+               ignore_nice = od_tuners->ignore_nice_load;
                od_ops = dbs_data->cdata->gov_ops;
                io_busy = od_tuners->io_is_busy;
        }
index e16a96130cb3491d30f376728144cdca92e441cd..0d9e6befe1d54a7bc88e1bc2d785b46bb04b4fd6 100644 (file)
@@ -165,7 +165,7 @@ struct cs_cpu_dbs_info_s {
 
 /* Per policy Governers sysfs tunables */
 struct od_dbs_tuners {
-       unsigned int ignore_nice;
+       unsigned int ignore_nice_load;
        unsigned int sampling_rate;
        unsigned int sampling_down_factor;
        unsigned int up_threshold;
@@ -175,7 +175,7 @@ struct od_dbs_tuners {
 };
 
 struct cs_dbs_tuners {
-       unsigned int ignore_nice;
+       unsigned int ignore_nice_load;
        unsigned int sampling_rate;
        unsigned int sampling_down_factor;
        unsigned int up_threshold;
index 93eb5cbcc1f639bf1ec52479a169a49deecd72f5..c087347d66884f03a4f1b2a94bf4fcbaceeda7a0 100644 (file)
@@ -403,8 +403,8 @@ static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
        return count;
 }
 
-static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
-               size_t count)
+static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
+               const char *buf, size_t count)
 {
        struct od_dbs_tuners *od_tuners = dbs_data->tuners;
        unsigned int input;
@@ -419,10 +419,10 @@ static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
        if (input > 1)
                input = 1;
 
-       if (input == od_tuners->ignore_nice) { /* nothing to do */
+       if (input == od_tuners->ignore_nice_load) { /* nothing to do */
                return count;
        }
-       od_tuners->ignore_nice = input;
+       od_tuners->ignore_nice_load = input;
 
        /* we need to re-evaluate prev_cpu_idle */
        for_each_online_cpu(j) {
@@ -430,7 +430,7 @@ static ssize_t store_ignore_nice(struct dbs_data *dbs_data, const char *buf,
                dbs_info = &per_cpu(od_cpu_dbs_info, j);
                dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
                        &dbs_info->cdbs.prev_cpu_wall, od_tuners->io_is_busy);
-               if (od_tuners->ignore_nice)
+               if (od_tuners->ignore_nice_load)
                        dbs_info->cdbs.prev_cpu_nice =
                                kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 
@@ -461,7 +461,7 @@ show_store_one(od, sampling_rate);
 show_store_one(od, io_is_busy);
 show_store_one(od, up_threshold);
 show_store_one(od, sampling_down_factor);
-show_store_one(od, ignore_nice);
+show_store_one(od, ignore_nice_load);
 show_store_one(od, powersave_bias);
 declare_show_sampling_rate_min(od);
 
@@ -469,7 +469,7 @@ gov_sys_pol_attr_rw(sampling_rate);
 gov_sys_pol_attr_rw(io_is_busy);
 gov_sys_pol_attr_rw(up_threshold);
 gov_sys_pol_attr_rw(sampling_down_factor);
-gov_sys_pol_attr_rw(ignore_nice);
+gov_sys_pol_attr_rw(ignore_nice_load);
 gov_sys_pol_attr_rw(powersave_bias);
 gov_sys_pol_attr_ro(sampling_rate_min);
 
@@ -478,7 +478,7 @@ static struct attribute *dbs_attributes_gov_sys[] = {
        &sampling_rate_gov_sys.attr,
        &up_threshold_gov_sys.attr,
        &sampling_down_factor_gov_sys.attr,
-       &ignore_nice_gov_sys.attr,
+       &ignore_nice_load_gov_sys.attr,
        &powersave_bias_gov_sys.attr,
        &io_is_busy_gov_sys.attr,
        NULL
@@ -494,7 +494,7 @@ static struct attribute *dbs_attributes_gov_pol[] = {
        &sampling_rate_gov_pol.attr,
        &up_threshold_gov_pol.attr,
        &sampling_down_factor_gov_pol.attr,
-       &ignore_nice_gov_pol.attr,
+       &ignore_nice_load_gov_pol.attr,
        &powersave_bias_gov_pol.attr,
        &io_is_busy_gov_pol.attr,
        NULL
@@ -544,7 +544,7 @@ static int od_init(struct dbs_data *dbs_data)
        }
 
        tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
-       tuners->ignore_nice = 0;
+       tuners->ignore_nice_load = 0;
        tuners->powersave_bias = default_powersave_bias;
        tuners->io_is_busy = should_io_be_busy();
 
index fb65decffa28128ded8817441b2e5eff8ecad8e3..bfd6273fd873531d864f3b4e104d37018a5d8dda 100644 (file)
@@ -349,16 +349,15 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
                cpufreq_update_policy(cpu);
                break;
        case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
                cpufreq_stats_free_sysfs(cpu);
                break;
        case CPU_DEAD:
-               cpufreq_stats_free_table(cpu);
-               break;
-       case CPU_UP_CANCELED_FROZEN:
-               cpufreq_stats_free_sysfs(cpu);
+       case CPU_DEAD_FROZEN:
                cpufreq_stats_free_table(cpu);
                break;
        }
index 07f2840ad80596b529488f40808e10c70782f498..6d6a0b48eb75442683221d4b8ac7c4164ed1f300 100644 (file)
@@ -103,10 +103,10 @@ struct pstate_adjust_policy {
 static struct pstate_adjust_policy default_policy = {
        .sample_rate_ms = 10,
        .deadband = 0,
-       .setpoint = 109,
-       .p_gain_pct = 17,
+       .setpoint = 97,
+       .p_gain_pct = 20,
        .d_gain_pct = 0,
-       .i_gain_pct = 4,
+       .i_gain_pct = 0,
 };
 
 struct perf_limits {
@@ -468,12 +468,12 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
 static inline int intel_pstate_get_scaled_busy(struct cpudata *cpu)
 {
        int32_t busy_scaled;
-       int32_t core_busy, turbo_pstate, current_pstate;
+       int32_t core_busy, max_pstate, current_pstate;
 
        core_busy = int_tofp(cpu->samples[cpu->sample_ptr].core_pct_busy);
-       turbo_pstate = int_tofp(cpu->pstate.turbo_pstate);
+       max_pstate = int_tofp(cpu->pstate.max_pstate);
        current_pstate = int_tofp(cpu->pstate.current_pstate);
-       busy_scaled = mul_fp(core_busy, div_fp(turbo_pstate, current_pstate));
+       busy_scaled = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
 
        return fp_toint(busy_scaled);
 }
index d53912768946b96c1c27b017dbaeb7a10e7c2feb..f92b02ae20be5d792353385ed072bc6dad4cbd21 100644 (file)
@@ -118,11 +118,6 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
                clk_put(cpuclk);
                return -EINVAL;
        }
-       ret = clk_set_rate(cpuclk, rate);
-       if (ret) {
-               clk_put(cpuclk);
-               return ret;
-       }
 
        /* clock table init */
        for (i = 2;
@@ -130,6 +125,12 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
             i++)
                loongson2_clockmod_table[i].frequency = (rate * i) / 8;
 
+       ret = clk_set_rate(cpuclk, rate);
+       if (ret) {
+               clk_put(cpuclk);
+               return ret;
+       }
+
        policy->cur = loongson2_cpufreq_get(policy->cpu);
 
        cpufreq_frequency_table_get_attr(&loongson2_clockmod_table[0],
index 2a297f86dbad25be5f17e0f41029e92dd23afeaf..fe853903fe10bec9ef57016e82dc6c8f8bf9ed11 100644 (file)
@@ -106,6 +106,7 @@ struct cpuidle_coupled {
        cpumask_t coupled_cpus;
        int requested_state[NR_CPUS];
        atomic_t ready_waiting_counts;
+       atomic_t abort_barrier;
        int online_count;
        int refcnt;
        int prevent;
@@ -122,12 +123,19 @@ static DEFINE_MUTEX(cpuidle_coupled_lock);
 static DEFINE_PER_CPU(struct call_single_data, cpuidle_coupled_poke_cb);
 
 /*
- * The cpuidle_coupled_poked_mask mask is used to avoid calling
+ * The cpuidle_coupled_poke_pending mask is used to avoid calling
  * __smp_call_function_single with the per cpu call_single_data struct already
  * in use.  This prevents a deadlock where two cpus are waiting for each others
  * call_single_data struct to be available
  */
-static cpumask_t cpuidle_coupled_poked_mask;
+static cpumask_t cpuidle_coupled_poke_pending;
+
+/*
+ * The cpuidle_coupled_poked mask is used to ensure that each cpu has been poked
+ * once to minimize entering the ready loop with a poke pending, which would
+ * require aborting and retrying.
+ */
+static cpumask_t cpuidle_coupled_poked;
 
 /**
  * cpuidle_coupled_parallel_barrier - synchronize all online coupled cpus
@@ -291,10 +299,11 @@ static inline int cpuidle_coupled_get_state(struct cpuidle_device *dev,
        return state;
 }
 
-static void cpuidle_coupled_poked(void *info)
+static void cpuidle_coupled_handle_poke(void *info)
 {
        int cpu = (unsigned long)info;
-       cpumask_clear_cpu(cpu, &cpuidle_coupled_poked_mask);
+       cpumask_set_cpu(cpu, &cpuidle_coupled_poked);
+       cpumask_clear_cpu(cpu, &cpuidle_coupled_poke_pending);
 }
 
 /**
@@ -313,7 +322,7 @@ static void cpuidle_coupled_poke(int cpu)
 {
        struct call_single_data *csd = &per_cpu(cpuidle_coupled_poke_cb, cpu);
 
-       if (!cpumask_test_and_set_cpu(cpu, &cpuidle_coupled_poked_mask))
+       if (!cpumask_test_and_set_cpu(cpu, &cpuidle_coupled_poke_pending))
                __smp_call_function_single(cpu, csd, 0);
 }
 
@@ -340,30 +349,19 @@ static void cpuidle_coupled_poke_others(int this_cpu,
  * @coupled: the struct coupled that contains the current cpu
  * @next_state: the index in drv->states of the requested state for this cpu
  *
- * Updates the requested idle state for the specified cpuidle device,
- * poking all coupled cpus out of idle if necessary to let them see the new
- * state.
+ * Updates the requested idle state for the specified cpuidle device.
+ * Returns the number of waiting cpus.
  */
-static void cpuidle_coupled_set_waiting(int cpu,
+static int cpuidle_coupled_set_waiting(int cpu,
                struct cpuidle_coupled *coupled, int next_state)
 {
-       int w;
-
        coupled->requested_state[cpu] = next_state;
 
        /*
-        * If this is the last cpu to enter the waiting state, poke
-        * all the other cpus out of their waiting state so they can
-        * enter a deeper state.  This can race with one of the cpus
-        * exiting the waiting state due to an interrupt and
-        * decrementing waiting_count, see comment below.
-        *
         * The atomic_inc_return provides a write barrier to order the write
         * to requested_state with the later write that increments ready_count.
         */
-       w = atomic_inc_return(&coupled->ready_waiting_counts) & WAITING_MASK;
-       if (w == coupled->online_count)
-               cpuidle_coupled_poke_others(cpu, coupled);
+       return atomic_inc_return(&coupled->ready_waiting_counts) & WAITING_MASK;
 }
 
 /**
@@ -410,19 +408,33 @@ static void cpuidle_coupled_set_done(int cpu, struct cpuidle_coupled *coupled)
  * been processed and the poke bit has been cleared.
  *
  * Other interrupts may also be processed while interrupts are enabled, so
- * need_resched() must be tested after turning interrupts off again to make sure
+ * need_resched() must be tested after this function returns to make sure
  * the interrupt didn't schedule work that should take the cpu out of idle.
  *
- * Returns 0 if need_resched was false, -EINTR if need_resched was true.
+ * Returns 0 if no poke was pending, 1 if a poke was cleared.
  */
 static int cpuidle_coupled_clear_pokes(int cpu)
 {
+       if (!cpumask_test_cpu(cpu, &cpuidle_coupled_poke_pending))
+               return 0;
+
        local_irq_enable();
-       while (cpumask_test_cpu(cpu, &cpuidle_coupled_poked_mask))
+       while (cpumask_test_cpu(cpu, &cpuidle_coupled_poke_pending))
                cpu_relax();
        local_irq_disable();
 
-       return need_resched() ? -EINTR : 0;
+       return 1;
+}
+
+static bool cpuidle_coupled_any_pokes_pending(struct cpuidle_coupled *coupled)
+{
+       cpumask_t cpus;
+       int ret;
+
+       cpumask_and(&cpus, cpu_online_mask, &coupled->coupled_cpus);
+       ret = cpumask_and(&cpus, &cpuidle_coupled_poke_pending, &cpus);
+
+       return ret;
 }
 
 /**
@@ -449,12 +461,14 @@ int cpuidle_enter_state_coupled(struct cpuidle_device *dev,
 {
        int entered_state = -1;
        struct cpuidle_coupled *coupled = dev->coupled;
+       int w;
 
        if (!coupled)
                return -EINVAL;
 
        while (coupled->prevent) {
-               if (cpuidle_coupled_clear_pokes(dev->cpu)) {
+               cpuidle_coupled_clear_pokes(dev->cpu);
+               if (need_resched()) {
                        local_irq_enable();
                        return entered_state;
                }
@@ -465,15 +479,37 @@ int cpuidle_enter_state_coupled(struct cpuidle_device *dev,
        /* Read barrier ensures online_count is read after prevent is cleared */
        smp_rmb();
 
-       cpuidle_coupled_set_waiting(dev->cpu, coupled, next_state);
+reset:
+       cpumask_clear_cpu(dev->cpu, &cpuidle_coupled_poked);
+
+       w = cpuidle_coupled_set_waiting(dev->cpu, coupled, next_state);
+       /*
+        * If this is the last cpu to enter the waiting state, poke
+        * all the other cpus out of their waiting state so they can
+        * enter a deeper state.  This can race with one of the cpus
+        * exiting the waiting state due to an interrupt and
+        * decrementing waiting_count, see comment below.
+        */
+       if (w == coupled->online_count) {
+               cpumask_set_cpu(dev->cpu, &cpuidle_coupled_poked);
+               cpuidle_coupled_poke_others(dev->cpu, coupled);
+       }
 
 retry:
        /*
         * Wait for all coupled cpus to be idle, using the deepest state
-        * allowed for a single cpu.
+        * allowed for a single cpu.  If this was not the poking cpu, wait
+        * for at least one poke before leaving to avoid a race where
+        * two cpus could arrive at the waiting loop at the same time,
+        * but the first of the two to arrive could skip the loop without
+        * processing the pokes from the last to arrive.
         */
-       while (!cpuidle_coupled_cpus_waiting(coupled)) {
-               if (cpuidle_coupled_clear_pokes(dev->cpu)) {
+       while (!cpuidle_coupled_cpus_waiting(coupled) ||
+                       !cpumask_test_cpu(dev->cpu, &cpuidle_coupled_poked)) {
+               if (cpuidle_coupled_clear_pokes(dev->cpu))
+                       continue;
+
+               if (need_resched()) {
                        cpuidle_coupled_set_not_waiting(dev->cpu, coupled);
                        goto out;
                }
@@ -487,11 +523,18 @@ retry:
                        dev->safe_state_index);
        }
 
-       if (cpuidle_coupled_clear_pokes(dev->cpu)) {
+       cpuidle_coupled_clear_pokes(dev->cpu);
+       if (need_resched()) {
                cpuidle_coupled_set_not_waiting(dev->cpu, coupled);
                goto out;
        }
 
+       /*
+        * Make sure final poke status for this cpu is visible before setting
+        * cpu as ready.
+        */
+       smp_wmb();
+
        /*
         * All coupled cpus are probably idle.  There is a small chance that
         * one of the other cpus just became active.  Increment the ready count,
@@ -511,6 +554,28 @@ retry:
                cpu_relax();
        }
 
+       /*
+        * Make sure read of all cpus ready is done before reading pending pokes
+        */
+       smp_rmb();
+
+       /*
+        * There is a small chance that a cpu left and reentered idle after this
+        * cpu saw that all cpus were waiting.  The cpu that reentered idle will
+        * have sent this cpu a poke, which will still be pending after the
+        * ready loop.  The pending interrupt may be lost by the interrupt
+        * controller when entering the deep idle state.  It's not possible to
+        * clear a pending interrupt without turning interrupts on and handling
+        * it, and it's too late to turn on interrupts here, so reset the
+        * coupled idle state of all cpus and retry.
+        */
+       if (cpuidle_coupled_any_pokes_pending(coupled)) {
+               cpuidle_coupled_set_done(dev->cpu, coupled);
+               /* Wait for all cpus to see the pending pokes */
+               cpuidle_coupled_parallel_barrier(dev, &coupled->abort_barrier);
+               goto reset;
+       }
+
        /* all cpus have acked the coupled state */
        next_state = cpuidle_coupled_get_state(dev, coupled);
 
@@ -596,7 +661,7 @@ have_coupled:
        coupled->refcnt++;
 
        csd = &per_cpu(cpuidle_coupled_poke_cb, dev->cpu);
-       csd->func = cpuidle_coupled_poked;
+       csd->func = cpuidle_coupled_handle_poke;
        csd->info = (void *)(unsigned long)dev->cpu;
 
        return 0;
index fe343a06b7da3278ba68c9c15c261ea14afde685..bc580b67a65298a8bf65e699d562dfd6f237b697 100644 (file)
 #define MAX_INTERESTING 50000
 #define STDDEV_THRESH 400
 
-/* 60 * 60 > STDDEV_THRESH * INTERVALS = 400 * 8 */
-#define MAX_DEVIATION 60
-
-static DEFINE_PER_CPU(struct hrtimer, menu_hrtimer);
-static DEFINE_PER_CPU(int, hrtimer_status);
-/* menu hrtimer mode */
-enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT, MENU_HRTIMER_GENERAL};
 
 /*
  * Concepts and ideas behind the menu governor
@@ -116,13 +109,6 @@ enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT, MENU_HRTIMER_GENERAL};
  *
  */
 
-/*
- * The C-state residency is so long that is is worthwhile to exit
- * from the shallow C-state and re-enter into a deeper C-state.
- */
-static unsigned int perfect_cstate_ms __read_mostly = 30;
-module_param(perfect_cstate_ms, uint, 0000);
-
 struct menu_device {
        int             last_state_idx;
        int             needs_update;
@@ -205,52 +191,17 @@ static u64 div_round64(u64 dividend, u32 divisor)
        return div_u64(dividend + (divisor / 2), divisor);
 }
 
-/* Cancel the hrtimer if it is not triggered yet */
-void menu_hrtimer_cancel(void)
-{
-       int cpu = smp_processor_id();
-       struct hrtimer *hrtmr = &per_cpu(menu_hrtimer, cpu);
-
-       /* The timer is still not time out*/
-       if (per_cpu(hrtimer_status, cpu)) {
-               hrtimer_cancel(hrtmr);
-               per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP;
-       }
-}
-EXPORT_SYMBOL_GPL(menu_hrtimer_cancel);
-
-/* Call back for hrtimer is triggered */
-static enum hrtimer_restart menu_hrtimer_notify(struct hrtimer *hrtimer)
-{
-       int cpu = smp_processor_id();
-       struct menu_device *data = &per_cpu(menu_devices, cpu);
-
-       /* In general case, the expected residency is much larger than
-        *  deepest C-state target residency, but prediction logic still
-        *  predicts a small predicted residency, so the prediction
-        *  history is totally broken if the timer is triggered.
-        *  So reset the correction factor.
-        */
-       if (per_cpu(hrtimer_status, cpu) == MENU_HRTIMER_GENERAL)
-               data->correction_factor[data->bucket] = RESOLUTION * DECAY;
-
-       per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP;
-
-       return HRTIMER_NORESTART;
-}
-
 /*
  * Try detecting repeating patterns by keeping track of the last 8
  * intervals, and checking if the standard deviation of that set
  * of points is below a threshold. If it is... then use the
  * average of these 8 points as the estimated value.
  */
-static u32 get_typical_interval(struct menu_device *data)
+static void get_typical_interval(struct menu_device *data)
 {
        int i = 0, divisor = 0;
        uint64_t max = 0, avg = 0, stddev = 0;
        int64_t thresh = LLONG_MAX; /* Discard outliers above this value. */
-       unsigned int ret = 0;
 
 again:
 
@@ -291,16 +242,13 @@ again:
        if (((avg > stddev * 6) && (divisor * 4 >= INTERVALS * 3))
                                                        || stddev <= 20) {
                data->predicted_us = avg;
-               ret = 1;
-               return ret;
+               return;
 
        } else if ((divisor * 4) > INTERVALS * 3) {
                /* Exclude the max interval */
                thresh = max - 1;
                goto again;
        }
-
-       return ret;
 }
 
 /**
@@ -315,9 +263,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
        int i;
        int multiplier;
        struct timespec t;
-       int repeat = 0, low_predicted = 0;
-       int cpu = smp_processor_id();
-       struct hrtimer *hrtmr = &per_cpu(menu_hrtimer, cpu);
 
        if (data->needs_update) {
                menu_update(drv, dev);
@@ -352,7 +297,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
        data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket],
                                         RESOLUTION * DECAY);
 
-       repeat = get_typical_interval(data);
+       get_typical_interval(data);
 
        /*
         * We want to default to C1 (hlt), not to busy polling
@@ -373,10 +318,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 
                if (s->disabled || su->disable)
                        continue;
-               if (s->target_residency > data->predicted_us) {
-                       low_predicted = 1;
+               if (s->target_residency > data->predicted_us)
                        continue;
-               }
                if (s->exit_latency > latency_req)
                        continue;
                if (s->exit_latency * multiplier > data->predicted_us)
@@ -386,44 +329,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
                data->exit_us = s->exit_latency;
        }
 
-       /* not deepest C-state chosen for low predicted residency */
-       if (low_predicted) {
-               unsigned int timer_us = 0;
-               unsigned int perfect_us = 0;
-
-               /*
-                * Set a timer to detect whether this sleep is much
-                * longer than repeat mode predicted.  If the timer
-                * triggers, the code will evaluate whether to put
-                * the CPU into a deeper C-state.
-                * The timer is cancelled on CPU wakeup.
-                */
-               timer_us = 2 * (data->predicted_us + MAX_DEVIATION);
-
-               perfect_us = perfect_cstate_ms * 1000;
-
-               if (repeat && (4 * timer_us < data->expected_us)) {
-                       RCU_NONIDLE(hrtimer_start(hrtmr,
-                               ns_to_ktime(1000 * timer_us),
-                               HRTIMER_MODE_REL_PINNED));
-                       /* In repeat case, menu hrtimer is started */
-                       per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_REPEAT;
-               } else if (perfect_us < data->expected_us) {
-                       /*
-                        * The next timer is long. This could be because
-                        * we did not make a useful prediction.
-                        * In that case, it makes sense to re-enter
-                        * into a deeper C-state after some time.
-                        */
-                       RCU_NONIDLE(hrtimer_start(hrtmr,
-                               ns_to_ktime(1000 * timer_us),
-                               HRTIMER_MODE_REL_PINNED));
-                       /* In general case, menu hrtimer is started */
-                       per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_GENERAL;
-               }
-
-       }
-
        return data->last_state_idx;
 }
 
@@ -514,9 +419,6 @@ static int menu_enable_device(struct cpuidle_driver *drv,
                                struct cpuidle_device *dev)
 {
        struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
-       struct hrtimer *t = &per_cpu(menu_hrtimer, dev->cpu);
-       hrtimer_init(t, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       t->function = menu_hrtimer_notify;
 
        memset(data, 0, sizeof(struct menu_device));
 
index 5996521a1caff11068e9b2e1e417cdf729f474df..84573b4d6f92809d5cd98fa968f6dd1a617482d3 100644 (file)
@@ -429,7 +429,7 @@ static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
        dma_addr_t src_dma, dst_dma;
        int ret = 0;
 
-       desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
+       desc = kmalloc(CAAM_CMD_SZ * 8 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
        if (!desc) {
                dev_err(jrdev, "unable to allocate key input memory\n");
                return -ENOMEM;
index a17553f7c02809325b06830d6eb1e36a4c95e435..4c2f465be3399b3c2f0dba993220978b08b6694b 100644 (file)
@@ -2485,10 +2485,10 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
        struct dma_pl330_chan *pch = to_pchan(chan);
        unsigned long flags;
 
-       spin_lock_irqsave(&pch->lock, flags);
-
        tasklet_kill(&pch->task);
 
+       spin_lock_irqsave(&pch->lock, flags);
+
        pl330_release_channel(pch->pl330_chid);
        pch->pl330_chid = NULL;
 
@@ -2527,6 +2527,10 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx)
        /* Assign cookies to all nodes */
        while (!list_empty(&last->node)) {
                desc = list_entry(last->node.next, struct dma_pl330_desc, node);
+               if (pch->cyclic) {
+                       desc->txd.callback = last->txd.callback;
+                       desc->txd.callback_param = last->txd.callback_param;
+               }
 
                dma_cookie_assign(&desc->txd);
 
@@ -2710,45 +2714,82 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
                size_t period_len, enum dma_transfer_direction direction,
                unsigned long flags, void *context)
 {
-       struct dma_pl330_desc *desc;
+       struct dma_pl330_desc *desc = NULL, *first = NULL;
        struct dma_pl330_chan *pch = to_pchan(chan);
+       struct dma_pl330_dmac *pdmac = pch->dmac;
+       unsigned int i;
        dma_addr_t dst;
        dma_addr_t src;
 
-       desc = pl330_get_desc(pch);
-       if (!desc) {
-               dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
-                       __func__, __LINE__);
+       if (len % period_len != 0)
                return NULL;
-       }
 
-       switch (direction) {
-       case DMA_MEM_TO_DEV:
-               desc->rqcfg.src_inc = 1;
-               desc->rqcfg.dst_inc = 0;
-               desc->req.rqtype = MEMTODEV;
-               src = dma_addr;
-               dst = pch->fifo_addr;
-               break;
-       case DMA_DEV_TO_MEM:
-               desc->rqcfg.src_inc = 0;
-               desc->rqcfg.dst_inc = 1;
-               desc->req.rqtype = DEVTOMEM;
-               src = pch->fifo_addr;
-               dst = dma_addr;
-               break;
-       default:
+       if (!is_slave_direction(direction)) {
                dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
                __func__, __LINE__);
                return NULL;
        }
 
-       desc->rqcfg.brst_size = pch->burst_sz;
-       desc->rqcfg.brst_len = 1;
+       for (i = 0; i < len / period_len; i++) {
+               desc = pl330_get_desc(pch);
+               if (!desc) {
+                       dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
+                               __func__, __LINE__);
 
-       pch->cyclic = true;
+                       if (!first)
+                               return NULL;
 
-       fill_px(&desc->px, dst, src, period_len);
+                       spin_lock_irqsave(&pdmac->pool_lock, flags);
+
+                       while (!list_empty(&first->node)) {
+                               desc = list_entry(first->node.next,
+                                               struct dma_pl330_desc, node);
+                               list_move_tail(&desc->node, &pdmac->desc_pool);
+                       }
+
+                       list_move_tail(&first->node, &pdmac->desc_pool);
+
+                       spin_unlock_irqrestore(&pdmac->pool_lock, flags);
+
+                       return NULL;
+               }
+
+               switch (direction) {
+               case DMA_MEM_TO_DEV:
+                       desc->rqcfg.src_inc = 1;
+                       desc->rqcfg.dst_inc = 0;
+                       desc->req.rqtype = MEMTODEV;
+                       src = dma_addr;
+                       dst = pch->fifo_addr;
+                       break;
+               case DMA_DEV_TO_MEM:
+                       desc->rqcfg.src_inc = 0;
+                       desc->rqcfg.dst_inc = 1;
+                       desc->req.rqtype = DEVTOMEM;
+                       src = pch->fifo_addr;
+                       dst = dma_addr;
+                       break;
+               default:
+                       break;
+               }
+
+               desc->rqcfg.brst_size = pch->burst_sz;
+               desc->rqcfg.brst_len = 1;
+               fill_px(&desc->px, dst, src, period_len);
+
+               if (!first)
+                       first = desc;
+               else
+                       list_add_tail(&desc->node, &first->node);
+
+               dma_addr += period_len;
+       }
+
+       if (!desc)
+               return NULL;
+
+       pch->cyclic = true;
+       desc->txd.flags = flags;
 
        return &desc->txd;
 }
index 8b6a0343c2208121cf858c6a22aea1816f427f16..8b3d90143514d79eee35dafec8d726174b30fd38 100644 (file)
@@ -2470,8 +2470,15 @@ static int amd64_init_one_instance(struct pci_dev *F2)
        layers[0].size = pvt->csels[0].b_cnt;
        layers[0].is_virt_csrow = true;
        layers[1].type = EDAC_MC_LAYER_CHANNEL;
-       layers[1].size = pvt->channel_count;
+
+       /*
+        * Always allocate two channels since we can have setups with DIMMs on
+        * only one channel. Also, this simplifies handling later for the price
+        * of a couple of KBs tops.
+        */
+       layers[1].size = 2;
        layers[1].is_virt_csrow = false;
+
        mci = edac_mc_alloc(nid, ARRAY_SIZE(layers), layers, 0);
        if (!mci)
                goto err_siblings;
index 27e86d93826280a62744a559332bf0cd9bc03b3b..89e109022d78a27cf506d995c1c16de2feffea0f 100644 (file)
@@ -48,6 +48,8 @@ static LIST_HEAD(mc_devices);
  */
 static void const *edac_mc_owner;
 
+static struct bus_type mc_bus[EDAC_MAX_MCS];
+
 unsigned edac_dimm_info_location(struct dimm_info *dimm, char *buf,
                                 unsigned len)
 {
@@ -723,6 +725,11 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
        int ret = -EINVAL;
        edac_dbg(0, "\n");
 
+       if (mci->mc_idx >= EDAC_MAX_MCS) {
+               pr_warn_once("Too many memory controllers: %d\n", mci->mc_idx);
+               return -ENODEV;
+       }
+
 #ifdef CONFIG_EDAC_DEBUG
        if (edac_debug_level >= 3)
                edac_mc_dump_mci(mci);
@@ -762,6 +769,8 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
        /* set load time so that error rate can be tracked */
        mci->start_time = jiffies;
 
+       mci->bus = &mc_bus[mci->mc_idx];
+
        if (edac_create_sysfs_mci_device(mci)) {
                edac_mc_printk(mci, KERN_WARNING,
                        "failed to create sysfs device\n");
index 67610a6ebf875765682cb50bec4226b42f956fc3..c4d700a577d2fc00ce0eb6b9b7dda74d0d26c689 100644 (file)
@@ -370,7 +370,7 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
                return -ENODEV;
 
        csrow->dev.type = &csrow_attr_type;
-       csrow->dev.bus = &mci->bus;
+       csrow->dev.bus = mci->bus;
        device_initialize(&csrow->dev);
        csrow->dev.parent = &mci->dev;
        csrow->mci = mci;
@@ -605,7 +605,7 @@ static int edac_create_dimm_object(struct mem_ctl_info *mci,
        dimm->mci = mci;
 
        dimm->dev.type = &dimm_attr_type;
-       dimm->dev.bus = &mci->bus;
+       dimm->dev.bus = mci->bus;
        device_initialize(&dimm->dev);
 
        dimm->dev.parent = &mci->dev;
@@ -975,11 +975,13 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
         * The memory controller needs its own bus, in order to avoid
         * namespace conflicts at /sys/bus/edac.
         */
-       mci->bus.name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx);
-       if (!mci->bus.name)
+       mci->bus->name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx);
+       if (!mci->bus->name)
                return -ENOMEM;
-       edac_dbg(0, "creating bus %s\n", mci->bus.name);
-       err = bus_register(&mci->bus);
+
+       edac_dbg(0, "creating bus %s\n", mci->bus->name);
+
+       err = bus_register(mci->bus);
        if (err < 0)
                return err;
 
@@ -988,7 +990,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
        device_initialize(&mci->dev);
 
        mci->dev.parent = mci_pdev;
-       mci->dev.bus = &mci->bus;
+       mci->dev.bus = mci->bus;
        dev_set_name(&mci->dev, "mc%d", mci->mc_idx);
        dev_set_drvdata(&mci->dev, mci);
        pm_runtime_forbid(&mci->dev);
@@ -997,8 +999,8 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
        err = device_add(&mci->dev);
        if (err < 0) {
                edac_dbg(1, "failure: create device %s\n", dev_name(&mci->dev));
-               bus_unregister(&mci->bus);
-               kfree(mci->bus.name);
+               bus_unregister(mci->bus);
+               kfree(mci->bus->name);
                return err;
        }
 
@@ -1064,8 +1066,8 @@ fail:
        }
 fail2:
        device_unregister(&mci->dev);
-       bus_unregister(&mci->bus);
-       kfree(mci->bus.name);
+       bus_unregister(mci->bus);
+       kfree(mci->bus->name);
        return err;
 }
 
@@ -1098,8 +1100,8 @@ void edac_unregister_sysfs(struct mem_ctl_info *mci)
 {
        edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev));
        device_unregister(&mci->dev);
-       bus_unregister(&mci->bus);
-       kfree(mci->bus.name);
+       bus_unregister(mci->bus);
+       kfree(mci->bus->name);
 }
 
 static void mc_attr_release(struct device *dev)
index 1b635178cc44ff31b8ed224560ebdf86851165f0..157b934e8ce3a528468e45a735ab41dee6043cea 100644 (file)
@@ -974,7 +974,7 @@ static int i5100_setup_debugfs(struct mem_ctl_info *mci)
        if (!i5100_debugfs)
                return -ENODEV;
 
-       priv->debugfs = debugfs_create_dir(mci->bus.name, i5100_debugfs);
+       priv->debugfs = debugfs_create_dir(mci->bus->name, i5100_debugfs);
 
        if (!priv->debugfs)
                return -ENOMEM;
index 7ef316fdc4d964cc8d1f87bd7be0cb9995223612..ac1b43a0428531273c4fdaefd56a0b83f1545ce2 100644 (file)
@@ -54,6 +54,7 @@
 #define FW_CDEV_KERNEL_VERSION                 5
 #define FW_CDEV_VERSION_EVENT_REQUEST2         4
 #define FW_CDEV_VERSION_ALLOCATE_REGION_END    4
+#define FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW        5
 
 struct client {
        u32 version;
@@ -1005,6 +1006,8 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg)
                        a->channel, a->speed, a->header_size, cb, client);
        if (IS_ERR(context))
                return PTR_ERR(context);
+       if (client->version < FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW)
+               context->drop_overflow_headers = true;
 
        /* We only support one context at this time. */
        spin_lock_irq(&client->lock);
index 9e1db6490b9a3bb497b7911d94c42d9fc6190be7..afb701ec90cabd50ceb03b1298beba38e97717b4 100644 (file)
@@ -2749,8 +2749,11 @@ static void copy_iso_headers(struct iso_context *ctx, const u32 *dma_hdr)
 {
        u32 *ctx_hdr;
 
-       if (ctx->header_length + ctx->base.header_size > PAGE_SIZE)
+       if (ctx->header_length + ctx->base.header_size > PAGE_SIZE) {
+               if (ctx->base.drop_overflow_headers)
+                       return;
                flush_iso_completions(ctx);
+       }
 
        ctx_hdr = ctx->header + ctx->header_length;
        ctx->last_timestamp = (u16)le32_to_cpu((__force __le32)dma_hdr[0]);
@@ -2910,8 +2913,11 @@ static int handle_it_packet(struct context *context,
 
        sync_it_packet_for_cpu(context, d);
 
-       if (ctx->header_length + 4 > PAGE_SIZE)
+       if (ctx->header_length + 4 > PAGE_SIZE) {
+               if (ctx->base.drop_overflow_headers)
+                       return 1;
                flush_iso_completions(ctx);
+       }
 
        ctx_hdr = ctx->header + ctx->header_length;
        ctx->last_timestamp = le16_to_cpu(last->res_count);
index 09da3393c527188f85a5e5f42316c502788e1a93..d5902e21d4a3b4af541bda94ae7c8dfbb63dd935 100644 (file)
@@ -348,6 +348,7 @@ int ast_bo_create(struct drm_device *dev, int size, int align,
 
        astbo->gem.driver_private = NULL;
        astbo->bo.bdev = &ast->ttm.bdev;
+       astbo->bo.bdev->dev_mapping = dev->dev_mapping;
 
        ast_ttm_placement(astbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
 
index 2ed8cfc740c9fa1845d86edcd876644b69302f82..c18faff826515a7550129e143a20e2b8845e43bd 100644 (file)
@@ -353,6 +353,7 @@ int cirrus_bo_create(struct drm_device *dev, int size, int align,
 
        cirrusbo->gem.driver_private = NULL;
        cirrusbo->bo.bdev = &cirrus->ttm.bdev;
+       cirrusbo->bo.bdev->dev_mapping = dev->dev_mapping;
 
        cirrus_ttm_placement(cirrusbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
 
index 9e62bbedb5ad45faa2b7193fad0bd8886ee76b00..0cb9b5d8e30a3900e4d964a5056c31f76a66e7a7 100644 (file)
@@ -125,6 +125,9 @@ static struct edid_quirk {
 
        /* ViewSonic VA2026w */
        { "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING },
+
+       /* Medion MD 30217 PG */
+       { "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 },
 };
 
 /*
index cf919e36e8ae4aa4282d11f48f4470cf929ebc59..239ef30f4a628d82c0c8f4af7f734f6385ce50fc 100644 (file)
@@ -453,25 +453,21 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
        spin_lock(&dev->object_name_lock);
        if (!obj->name) {
                ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_NOWAIT);
-               obj->name = ret;
-               args->name = (uint64_t) obj->name;
-               spin_unlock(&dev->object_name_lock);
-               idr_preload_end();
-
                if (ret < 0)
                        goto err;
-               ret = 0;
+
+               obj->name = ret;
 
                /* Allocate a reference for the name table.  */
                drm_gem_object_reference(obj);
-       } else {
-               args->name = (uint64_t) obj->name;
-               spin_unlock(&dev->object_name_lock);
-               idr_preload_end();
-               ret = 0;
        }
 
+       args->name = (uint64_t) obj->name;
+       ret = 0;
+
 err:
+       spin_unlock(&dev->object_name_lock);
+       idr_preload_end();
        drm_gem_object_unreference_unlocked(obj);
        return ret;
 }
index 8bcce7866d368e12df7c86edb17ff235ba58f4a7..f92da0a32f0d30d02fe8afeb09f5272a16b8a060 100644 (file)
@@ -708,7 +708,10 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
        /* Subtract time delta from raw timestamp to get final
         * vblank_time timestamp for end of vblank.
         */
-       etime = ktime_sub_ns(etime, delta_ns);
+       if (delta_ns < 0)
+               etime = ktime_add_ns(etime, -delta_ns);
+       else
+               etime = ktime_sub_ns(etime, delta_ns);
        *vblank_time = ktime_to_timeval(etime);
 
        DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
index 3b315ba85a3e4891de200b9bd88d5c3ccb1b8aa3..17d9b0b6afc5442424fcc31d7a8c6f84f9c006b3 100644 (file)
@@ -1511,6 +1511,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        dev_priv->dev = dev;
        dev_priv->info = info;
 
+       spin_lock_init(&dev_priv->irq_lock);
+       spin_lock_init(&dev_priv->gpu_error.lock);
+       spin_lock_init(&dev_priv->rps.lock);
+       spin_lock_init(&dev_priv->gt_lock);
+       mutex_init(&dev_priv->dpio_lock);
+       mutex_init(&dev_priv->rps.hw_lock);
+       mutex_init(&dev_priv->modeset_restore_lock);
+
        i915_dump_device_info(dev_priv);
 
        if (i915_get_bridge_dev(dev)) {
@@ -1601,6 +1609,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        intel_detect_pch(dev);
 
        intel_irq_init(dev);
+       intel_pm_init(dev);
+       intel_gt_sanitize(dev);
        intel_gt_init(dev);
 
        /* Try to make sure MCHBAR is enabled before poking at it */
@@ -1626,14 +1636,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (!IS_I945G(dev) && !IS_I945GM(dev))
                pci_enable_msi(dev->pdev);
 
-       spin_lock_init(&dev_priv->irq_lock);
-       spin_lock_init(&dev_priv->gpu_error.lock);
-       spin_lock_init(&dev_priv->rps.lock);
-       mutex_init(&dev_priv->dpio_lock);
-
-       mutex_init(&dev_priv->rps.hw_lock);
-       mutex_init(&dev_priv->modeset_restore_lock);
-
        dev_priv->num_plane = 1;
        if (IS_VALLEYVIEW(dev))
                dev_priv->num_plane = 2;
index a2e4953b8e8d5771d6edd95bcaf7f3198674f6b4..bc6cd3117ac3b6110ee02ede8e32ff7be10d8ed1 100644 (file)
@@ -685,7 +685,7 @@ static int i915_drm_thaw(struct drm_device *dev)
 {
        int error = 0;
 
-       intel_gt_reset(dev);
+       intel_gt_sanitize(dev);
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
                mutex_lock(&dev->struct_mutex);
@@ -711,7 +711,7 @@ int i915_resume(struct drm_device *dev)
 
        pci_set_master(dev->pdev);
 
-       intel_gt_reset(dev);
+       intel_gt_sanitize(dev);
 
        /*
         * Platforms with opregion should have sane BIOS, older ones (gen3 and
@@ -1247,21 +1247,21 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
 
 #define __i915_read(x, y) \
 u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
+       unsigned long irqflags; \
        u##x val = 0; \
+       spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
        if (IS_GEN5(dev_priv->dev)) \
                ilk_dummy_write(dev_priv); \
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
-               unsigned long irqflags; \
-               spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
                if (dev_priv->forcewake_count == 0) \
                        dev_priv->gt.force_wake_get(dev_priv); \
                val = read##y(dev_priv->regs + reg); \
                if (dev_priv->forcewake_count == 0) \
                        dev_priv->gt.force_wake_put(dev_priv); \
-               spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
        } else { \
                val = read##y(dev_priv->regs + reg); \
        } \
+       spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
        trace_i915_reg_rw(false, reg, val, sizeof(val)); \
        return val; \
 }
@@ -1274,8 +1274,10 @@ __i915_read(64, q)
 
 #define __i915_write(x, y) \
 void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
+       unsigned long irqflags; \
        u32 __fifo_ret = 0; \
        trace_i915_reg_rw(true, reg, val, sizeof(val)); \
+       spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
                __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
        } \
@@ -1287,6 +1289,7 @@ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
                gen6_gt_check_fifodbg(dev_priv); \
        } \
        hsw_unclaimed_reg_check(dev_priv, reg); \
+       spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
 }
 __i915_write(8, b)
 __i915_write(16, w)
index 9669a0b8b440384394f1d30cc2890add8525a8f7..47d8b68c500412eaa08ba273f7ab82bc8fa38973 100644 (file)
@@ -491,6 +491,7 @@ enum intel_sbi_destination {
 #define QUIRK_PIPEA_FORCE (1<<0)
 #define QUIRK_LVDS_SSC_DISABLE (1<<1)
 #define QUIRK_INVERT_BRIGHTNESS (1<<2)
+#define QUIRK_NO_PCH_PWM_ENABLE (1<<3)
 
 struct intel_fbdev;
 struct intel_fbc_work;
@@ -1474,9 +1475,10 @@ void i915_hangcheck_elapsed(unsigned long data);
 void i915_handle_error(struct drm_device *dev, bool wedged);
 
 extern void intel_irq_init(struct drm_device *dev);
+extern void intel_pm_init(struct drm_device *dev);
 extern void intel_hpd_init(struct drm_device *dev);
 extern void intel_gt_init(struct drm_device *dev);
-extern void intel_gt_reset(struct drm_device *dev);
+extern void intel_gt_sanitize(struct drm_device *dev);
 
 void i915_error_state_free(struct kref *error_ref);
 
index 9e35dafc580724da0f48db14c441f57db951b45d..0a30088178b05c9452d0d1bc63184eb7d8cf51d1 100644 (file)
@@ -1160,7 +1160,8 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj,
        /* Manually manage the write flush as we may have not yet
         * retired the buffer.
         */
-       if (obj->last_write_seqno &&
+       if (ret == 0 &&
+           obj->last_write_seqno &&
            i915_seqno_passed(seqno, obj->last_write_seqno)) {
                obj->last_write_seqno = 0;
                obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
@@ -1880,6 +1881,10 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
        u32 seqno = intel_ring_get_seqno(ring);
 
        BUG_ON(ring == NULL);
+       if (obj->ring != ring && obj->last_write_seqno) {
+               /* Keep the seqno relative to the current ring */
+               obj->last_write_seqno = seqno;
+       }
        obj->ring = ring;
 
        /* Add a reference if we're newly entering the active list. */
@@ -2133,7 +2138,17 @@ void i915_gem_restore_fences(struct drm_device *dev)
 
        for (i = 0; i < dev_priv->num_fence_regs; i++) {
                struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
-               i915_gem_write_fence(dev, i, reg->obj);
+
+               /*
+                * Commit delayed tiling changes if we have an object still
+                * attached to the fence, otherwise just clear the fence.
+                */
+               if (reg->obj) {
+                       i915_gem_object_update_fence(reg->obj, reg,
+                                                    reg->obj->tiling_mode);
+               } else {
+                       i915_gem_write_fence(dev, i, NULL);
+               }
        }
 }
 
@@ -2533,7 +2548,6 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
        drm_i915_private_t *dev_priv = dev->dev_private;
        int fence_reg;
        int fence_pitch_shift;
-       uint64_t val;
 
        if (INTEL_INFO(dev)->gen >= 6) {
                fence_reg = FENCE_REG_SANDYBRIDGE_0;
@@ -2543,8 +2557,23 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
                fence_pitch_shift = I965_FENCE_PITCH_SHIFT;
        }
 
+       fence_reg += reg * 8;
+
+       /* To w/a incoherency with non-atomic 64-bit register updates,
+        * we split the 64-bit update into two 32-bit writes. In order
+        * for a partial fence not to be evaluated between writes, we
+        * precede the update with write to turn off the fence register,
+        * and only enable the fence as the last step.
+        *
+        * For extra levels of paranoia, we make sure each step lands
+        * before applying the next step.
+        */
+       I915_WRITE(fence_reg, 0);
+       POSTING_READ(fence_reg);
+
        if (obj) {
                u32 size = obj->gtt_space->size;
+               uint64_t val;
 
                val = (uint64_t)((obj->gtt_offset + size - 4096) &
                                 0xfffff000) << 32;
@@ -2553,12 +2582,16 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
                if (obj->tiling_mode == I915_TILING_Y)
                        val |= 1 << I965_FENCE_TILING_Y_SHIFT;
                val |= I965_FENCE_REG_VALID;
-       } else
-               val = 0;
 
-       fence_reg += reg * 8;
-       I915_WRITE64(fence_reg, val);
-       POSTING_READ(fence_reg);
+               I915_WRITE(fence_reg + 4, val >> 32);
+               POSTING_READ(fence_reg + 4);
+
+               I915_WRITE(fence_reg + 0, val);
+               POSTING_READ(fence_reg);
+       } else {
+               I915_WRITE(fence_reg + 4, 0);
+               POSTING_READ(fence_reg + 4);
+       }
 }
 
 static void i915_write_fence_reg(struct drm_device *dev, int reg,
@@ -2653,6 +2686,10 @@ static void i915_gem_write_fence(struct drm_device *dev, int reg,
        if (i915_gem_object_needs_mb(dev_priv->fence_regs[reg].obj))
                mb();
 
+       WARN(obj && (!obj->stride || !obj->tiling_mode),
+            "bogus fence setup with stride: 0x%x, tiling mode: %i\n",
+            obj->stride, obj->tiling_mode);
+
        switch (INTEL_INFO(dev)->gen) {
        case 7:
        case 6:
@@ -2712,6 +2749,7 @@ static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
                fence->obj = NULL;
                list_del_init(&fence->lru_list);
        }
+       obj->fence_dirty = false;
 }
 
 static int
@@ -2841,7 +2879,6 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj)
                return 0;
 
        i915_gem_object_update_fence(obj, reg, enable);
-       obj->fence_dirty = false;
 
        return 0;
 }
@@ -4456,7 +4493,7 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
        list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list)
                if (obj->pages_pin_count == 0)
                        cnt += obj->base.size >> PAGE_SHIFT;
-       list_for_each_entry(obj, &dev_priv->mm.inactive_list, gtt_list)
+       list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list)
                if (obj->pin_count == 0 && obj->pages_pin_count == 0)
                        cnt += obj->base.size >> PAGE_SHIFT;
 
index a1e8ecb6adf65ac01bce50c5a79694518c405602..3bc8a58a8d5fea89da2ee2a71d7f31f1b05c7f01 100644 (file)
@@ -113,7 +113,7 @@ static int get_context_size(struct drm_device *dev)
        case 7:
                reg = I915_READ(GEN7_CXT_SIZE);
                if (IS_HASWELL(dev))
-                       ret = HSW_CXT_TOTAL_SIZE(reg) * 64;
+                       ret = HSW_CXT_TOTAL_SIZE;
                else
                        ret = GEN7_CXT_TOTAL_SIZE(reg) * 64;
                break;
index 0aa2ef0d2ae01b3d8e796a23f63ee119b657fbdc..e5e328691e3a67ac2bc9b4aee39aae60fdf003ad 100644 (file)
@@ -70,15 +70,6 @@ static const u32 hpd_status_gen4[] = {
        [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
 };
 
-static const u32 hpd_status_i965[] = {
-        [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
-        [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I965,
-        [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I965,
-        [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS,
-        [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS,
-        [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
-};
-
 static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */
        [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
        [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915,
@@ -2952,13 +2943,13 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
                        u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
                        u32 hotplug_trigger = hotplug_status & (IS_G4X(dev) ?
                                                                  HOTPLUG_INT_STATUS_G4X :
-                                                                 HOTPLUG_INT_STATUS_I965);
+                                                                 HOTPLUG_INT_STATUS_I915);
 
                        DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
                                  hotplug_status);
                        if (hotplug_trigger) {
                                if (hotplug_irq_storm_detect(dev, hotplug_trigger,
-                                                           IS_G4X(dev) ? hpd_status_gen4 : hpd_status_i965))
+                                                           IS_G4X(dev) ? hpd_status_gen4 : hpd_status_i915))
                                        i915_hpd_irq_setup(dev);
                                queue_work(dev_priv->wq,
                                           &dev_priv->hotplug_work);
index 2d6b62e42daf324478ea64bc49e6e722330c3e2b..a365780aeb1eebf06be30adfa7bbe5d666f6fd88 100644 (file)
                                        will not assert AGPBUSY# and will only
                                        be delivered when out of C3. */
 #define   INSTPM_FORCE_ORDERING                                (1<<7) /* GEN6+ */
+#define   INSTPM_TLB_INVALIDATE        (1<<9)
+#define   INSTPM_SYNC_FLUSH    (1<<5)
 #define ACTHD          0x020c8
 #define FW_BLC         0x020d8
 #define FW_BLC2                0x020dc
                                         GEN7_CXT_EXTENDED_SIZE(ctx_reg) + \
                                         GEN7_CXT_GT1_SIZE(ctx_reg) + \
                                         GEN7_CXT_VFSTATE_SIZE(ctx_reg))
-#define HSW_CXT_POWER_SIZE(ctx_reg)    ((ctx_reg >> 26) & 0x3f)
-#define HSW_CXT_RING_SIZE(ctx_reg)     ((ctx_reg >> 23) & 0x7)
-#define HSW_CXT_RENDER_SIZE(ctx_reg)   ((ctx_reg >> 15) & 0xff)
-#define HSW_CXT_TOTAL_SIZE(ctx_reg)    (HSW_CXT_POWER_SIZE(ctx_reg) + \
-                                        HSW_CXT_RING_SIZE(ctx_reg) + \
-                                        HSW_CXT_RENDER_SIZE(ctx_reg) + \
-                                        GEN7_CXT_VFSTATE_SIZE(ctx_reg))
-
+/* Haswell does have the CXT_SIZE register however it does not appear to be
+ * valid. Now, docs explain in dwords what is in the context object. The full
+ * size is 70720 bytes, however, the power context and execlist context will
+ * never be saved (power context is stored elsewhere, and execlists don't work
+ * on HSW) - so the final size is 66944 bytes, which rounds to 17 pages.
+ */
+#define HSW_CXT_TOTAL_SIZE             (17 * PAGE_SIZE)
 
 /*
  * Overlay regs
 /* SDVO is different across gen3/4 */
 #define   SDVOC_HOTPLUG_INT_STATUS_G4X         (1 << 3)
 #define   SDVOB_HOTPLUG_INT_STATUS_G4X         (1 << 2)
+/*
+ * Bspec seems to be seriously misleaded about the SDVO hpd bits on i965g/gm,
+ * since reality corrobates that they're the same as on gen3. But keep these
+ * bits here (and the comment!) to help any other lost wanderers back onto the
+ * right tracks.
+ */
 #define   SDVOC_HOTPLUG_INT_STATUS_I965                (3 << 4)
 #define   SDVOB_HOTPLUG_INT_STATUS_I965                (3 << 2)
 #define   SDVOC_HOTPLUG_INT_STATUS_I915                (1 << 7)
                                                 PORTC_HOTPLUG_INT_STATUS | \
                                                 PORTD_HOTPLUG_INT_STATUS)
 
-#define HOTPLUG_INT_STATUS_I965                        (CRT_HOTPLUG_INT_STATUS | \
-                                                SDVOB_HOTPLUG_INT_STATUS_I965 | \
-                                                SDVOC_HOTPLUG_INT_STATUS_I965 | \
-                                                PORTB_HOTPLUG_INT_STATUS | \
-                                                PORTC_HOTPLUG_INT_STATUS | \
-                                                PORTD_HOTPLUG_INT_STATUS)
-
 #define HOTPLUG_INT_STATUS_I915                        (CRT_HOTPLUG_INT_STATUS | \
                                                 SDVOB_HOTPLUG_INT_STATUS_I915 | \
                                                 SDVOC_HOTPLUG_INT_STATUS_I915 | \
 #define EDP_LINK_TRAIN_600MV_0DB_IVB           (0x30 <<22)
 #define EDP_LINK_TRAIN_600MV_3_5DB_IVB         (0x36 <<22)
 #define EDP_LINK_TRAIN_800MV_0DB_IVB           (0x38 <<22)
-#define EDP_LINK_TRAIN_800MV_3_5DB_IVB         (0x33 <<22)
+#define EDP_LINK_TRAIN_800MV_3_5DB_IVB         (0x3e <<22)
 
 /* legacy values */
 #define EDP_LINK_TRAIN_500MV_0DB_IVB           (0x00 <<22)
index fb961bb81903c95550289845a846bd0308c448d7..16e674af4d5709fe7a8cd07d5cece488d7103b3c 100644 (file)
@@ -684,7 +684,7 @@ static void intel_ddi_mode_set(struct drm_encoder *encoder,
                struct intel_digital_port *intel_dig_port =
                        enc_to_dig_port(encoder);
 
-               intel_dp->DP = intel_dig_port->port_reversal |
+               intel_dp->DP = intel_dig_port->saved_port_bits |
                               DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
                switch (intel_dp->lane_count) {
                case 1:
@@ -1324,7 +1324,8 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
                 * enabling the port.
                 */
                I915_WRITE(DDI_BUF_CTL(port),
-                          intel_dig_port->port_reversal | DDI_BUF_CTL_ENABLE);
+                          intel_dig_port->saved_port_bits |
+                          DDI_BUF_CTL_ENABLE);
        } else if (type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
@@ -1543,8 +1544,9 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
        intel_encoder->get_hw_state = intel_ddi_get_hw_state;
 
        intel_dig_port->port = port;
-       intel_dig_port->port_reversal = I915_READ(DDI_BUF_CTL(port)) &
-                                       DDI_BUF_PORT_REVERSAL;
+       intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) &
+                                         (DDI_BUF_PORT_REVERSAL |
+                                          DDI_A_4_LANES);
        if (hdmi_connector)
                intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port);
        intel_dig_port->dp.output_reg = DDI_BUF_CTL(port);
index 56746dcac40f116fe58c25e648ee9887a0f63a39..eea5982657a86745d313b113f956ff2f60ce256a 100644 (file)
@@ -4333,7 +4333,8 @@ static void vlv_update_pll(struct intel_crtc *crtc)
 
 static void i9xx_update_pll(struct intel_crtc *crtc,
                            intel_clock_t *reduced_clock,
-                           int num_connectors)
+                           int num_connectors,
+                           bool needs_tv_clock)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4391,7 +4392,7 @@ static void i9xx_update_pll(struct intel_crtc *crtc,
        if (INTEL_INFO(dev)->gen >= 4)
                dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
 
-       if (is_sdvo && intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_TVOUT))
+       if (is_sdvo && needs_tv_clock)
                dpll |= PLL_REF_INPUT_TVCLKINBC;
        else if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_TVOUT))
                /* XXX: just matching BIOS for now */
@@ -4716,7 +4717,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
        else
                i9xx_update_pll(intel_crtc,
                                has_reduced_clock ? &reduced_clock : NULL,
-                               num_connectors);
+                               num_connectors,
+                               is_sdvo && is_tv);
 
        /* Set up the display plane register */
        dspcntr = DISPPLANE_GAMMA_ENABLE;
@@ -8146,15 +8148,20 @@ static void intel_set_config_restore_state(struct drm_device *dev,
 }
 
 static bool
-is_crtc_connector_off(struct drm_crtc *crtc, struct drm_connector *connectors,
-                     int num_connectors)
+is_crtc_connector_off(struct drm_mode_set *set)
 {
        int i;
 
-       for (i = 0; i < num_connectors; i++)
-               if (connectors[i].encoder &&
-                   connectors[i].encoder->crtc == crtc &&
-                   connectors[i].dpms != DRM_MODE_DPMS_ON)
+       if (set->num_connectors == 0)
+               return false;
+
+       if (WARN_ON(set->connectors == NULL))
+               return false;
+
+       for (i = 0; i < set->num_connectors; i++)
+               if (set->connectors[i]->encoder &&
+                   set->connectors[i]->encoder->crtc == set->crtc &&
+                   set->connectors[i]->dpms != DRM_MODE_DPMS_ON)
                        return true;
 
        return false;
@@ -8167,10 +8174,8 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
 
        /* We should be able to check here if the fb has the same properties
         * and then just flip_or_move it */
-       if (set->connectors != NULL &&
-           is_crtc_connector_off(set->crtc, *set->connectors,
-                                 set->num_connectors)) {
-                       config->mode_changed = true;
+       if (is_crtc_connector_off(set)) {
+               config->mode_changed = true;
        } else if (set->crtc->fb != set->fb) {
                /* If we have no fb then treat it as a full mode set */
                if (set->crtc->fb == NULL) {
@@ -8914,6 +8919,17 @@ static void quirk_invert_brightness(struct drm_device *dev)
        DRM_INFO("applying inverted panel brightness quirk\n");
 }
 
+/*
+ * Some machines (Dell XPS13) suffer broken backlight controls if
+ * BLM_PCH_PWM_ENABLE is set.
+ */
+static void quirk_no_pcm_pwm_enable(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       dev_priv->quirks |= QUIRK_NO_PCH_PWM_ENABLE;
+       DRM_INFO("applying no-PCH_PWM_ENABLE quirk\n");
+}
+
 struct intel_quirk {
        int device;
        int subsystem_vendor;
@@ -8983,6 +8999,11 @@ static struct intel_quirk intel_quirks[] = {
 
        /* Acer Aspire 4736Z */
        { 0x2a42, 0x1025, 0x0260, quirk_invert_brightness },
+
+       /* Dell XPS13 HD Sandy Bridge */
+       { 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable },
+       /* Dell XPS13 HD and XPS13 FHD Ivy Bridge */
+       { 0x0166, 0x1028, 0x058b, quirk_no_pcm_pwm_enable },
 };
 
 static void intel_init_quirks(struct drm_device *dev)
index 624a9e6b8d718ebe64a3aa41019137b673b3b296..7cd55843e73ec576b376be092830f1b95c6a8ebc 100644 (file)
@@ -426,7 +426,7 @@ struct intel_dp {
 struct intel_digital_port {
        struct intel_encoder base;
        enum port port;
-       u32 port_reversal;
+       u32 saved_port_bits;
        struct intel_dp dp;
        struct intel_hdmi hdmi;
 };
index eb5e6e95f3c7ee72e14e9eed3c5cd8167bc7a449..33cb87f7983eca312eee74d3bee596f096405be9 100644 (file)
@@ -354,7 +354,8 @@ void intel_panel_enable_backlight(struct drm_device *dev,
                POSTING_READ(reg);
                I915_WRITE(reg, tmp | BLM_PWM_ENABLE);
 
-               if (HAS_PCH_SPLIT(dev)) {
+               if (HAS_PCH_SPLIT(dev) &&
+                   !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) {
                        tmp = I915_READ(BLC_PWM_PCH_CTL1);
                        tmp |= BLM_PCH_PWM_ENABLE;
                        tmp &= ~BLM_PCH_OVERRIDE_ENABLE;
index aa01128ff192cc6c5860c881a9aa8a71cb756fd7..94ad6bc08260fd2161182e7201fc1f75aa08ed56 100644 (file)
@@ -4486,7 +4486,7 @@ static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
        gen6_gt_check_fifodbg(dev_priv);
 }
 
-void intel_gt_reset(struct drm_device *dev)
+void intel_gt_sanitize(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -4497,26 +4497,61 @@ void intel_gt_reset(struct drm_device *dev)
                if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
                        __gen6_gt_force_wake_mt_reset(dev_priv);
        }
+
+       /* BIOS often leaves RC6 enabled, but disable it for hw init */
+       if (INTEL_INFO(dev)->gen >= 6)
+               intel_disable_gt_powersave(dev);
 }
 
 void intel_gt_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       spin_lock_init(&dev_priv->gt_lock);
-
-       intel_gt_reset(dev);
-
        if (IS_VALLEYVIEW(dev)) {
                dev_priv->gt.force_wake_get = vlv_force_wake_get;
                dev_priv->gt.force_wake_put = vlv_force_wake_put;
-       } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
+       } else if (IS_HASWELL(dev)) {
                dev_priv->gt.force_wake_get = __gen6_gt_force_wake_mt_get;
                dev_priv->gt.force_wake_put = __gen6_gt_force_wake_mt_put;
+       } else if (IS_IVYBRIDGE(dev)) {
+               u32 ecobus;
+
+               /* IVB configs may use multi-threaded forcewake */
+
+               /* A small trick here - if the bios hasn't configured
+                * MT forcewake, and if the device is in RC6, then
+                * force_wake_mt_get will not wake the device and the
+                * ECOBUS read will return zero. Which will be
+                * (correctly) interpreted by the test below as MT
+                * forcewake being disabled.
+                */
+               mutex_lock(&dev->struct_mutex);
+               __gen6_gt_force_wake_mt_get(dev_priv);
+               ecobus = I915_READ_NOTRACE(ECOBUS);
+               __gen6_gt_force_wake_mt_put(dev_priv);
+               mutex_unlock(&dev->struct_mutex);
+
+               if (ecobus & FORCEWAKE_MT_ENABLE) {
+                       dev_priv->gt.force_wake_get =
+                                               __gen6_gt_force_wake_mt_get;
+                       dev_priv->gt.force_wake_put =
+                                               __gen6_gt_force_wake_mt_put;
+               } else {
+                       DRM_INFO("No MT forcewake available on Ivybridge, this can result in issues\n");
+                       DRM_INFO("when using vblank-synced partial screen updates.\n");
+                       dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get;
+                       dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put;
+               }
        } else if (IS_GEN6(dev)) {
                dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get;
                dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put;
        }
+}
+
+void intel_pm_init(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
        INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
                          intel_gen6_powersave_work);
 }
index 1d5d613eb6be4d21affe491af19a3eaba99325ee..48fe23e8d180967ffd25e5e2fbb553d818587f0c 100644 (file)
@@ -490,9 +490,6 @@ cleanup_pipe_control(struct intel_ring_buffer *ring)
        struct pipe_control *pc = ring->private;
        struct drm_i915_gem_object *obj;
 
-       if (!ring->private)
-               return;
-
        obj = pc->obj;
 
        kunmap(sg_page(obj->pages->sgl));
@@ -500,7 +497,6 @@ cleanup_pipe_control(struct intel_ring_buffer *ring)
        drm_gem_object_unreference(&obj->base);
 
        kfree(pc);
-       ring->private = NULL;
 }
 
 static int init_render_ring(struct intel_ring_buffer *ring)
@@ -571,7 +567,10 @@ static void render_ring_cleanup(struct intel_ring_buffer *ring)
        if (HAS_BROKEN_CS_TLB(dev))
                drm_gem_object_unreference(to_gem_object(ring->private));
 
-       cleanup_pipe_control(ring);
+       if (INTEL_INFO(dev)->gen >= 5)
+               cleanup_pipe_control(ring);
+
+       ring->private = NULL;
 }
 
 static void
@@ -908,6 +907,18 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
 
        I915_WRITE(mmio, (u32)ring->status_page.gfx_addr);
        POSTING_READ(mmio);
+
+       /* Flush the TLB for this page */
+       if (INTEL_INFO(dev)->gen >= 6) {
+               u32 reg = RING_INSTPM(ring->mmio_base);
+               I915_WRITE(reg,
+                          _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
+                                             INSTPM_SYNC_FLUSH));
+               if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0,
+                            1000))
+                       DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
+                                 ring->name);
+       }
 }
 
 static int
index bf29b2f4d68d0b951cd7fcb5e5a74a2d8a0ce3e2..988911afcc8bab0f17369f27bac17c0bb5b0f56e 100644 (file)
@@ -198,7 +198,8 @@ struct mga_device {
                struct ttm_bo_device bdev;
        } ttm;
 
-       u32 reg_1e24; /* SE model number */
+       /* SE model number stored in reg 0x1e24 */
+       u32 unique_rev_id;
 };
 
 
index 99059237da38e68d16cebd77be77269526214f97..dafe049fb1aeb7646024ca5d3056dd4c144aeeda 100644 (file)
@@ -176,7 +176,7 @@ static int mgag200_device_init(struct drm_device *dev,
 
        /* stash G200 SE model number for later use */
        if (IS_G200_SE(mdev))
-               mdev->reg_1e24 = RREG32(0x1e24);
+               mdev->unique_rev_id = RREG32(0x1e24);
 
        ret = mga_vram_init(mdev);
        if (ret)
index ee66badc8bb63b4b49e61744a40ad213e6330954..99e07b688ea8bddb5ee3104394feb422505fdd77 100644 (file)
@@ -1008,7 +1008,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
 
 
        if (IS_G200_SE(mdev)) {
-               if (mdev->reg_1e24 >= 0x02) {
+               if (mdev->unique_rev_id >= 0x02) {
                        u8 hi_pri_lvl;
                        u32 bpp;
                        u32 mb;
@@ -1038,7 +1038,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
                        WREG8(MGAREG_CRTCEXT_DATA, hi_pri_lvl);
                } else {
                        WREG8(MGAREG_CRTCEXT_INDEX, 0x06);
-                       if (mdev->reg_1e24 >= 0x01)
+                       if (mdev->unique_rev_id >= 0x01)
                                WREG8(MGAREG_CRTCEXT_DATA, 0x03);
                        else
                                WREG8(MGAREG_CRTCEXT_DATA, 0x04);
@@ -1410,6 +1410,32 @@ static int mga_vga_get_modes(struct drm_connector *connector)
        return ret;
 }
 
+static uint32_t mga_vga_calculate_mode_bandwidth(struct drm_display_mode *mode,
+                                                       int bits_per_pixel)
+{
+       uint32_t total_area, divisor;
+       int64_t active_area, pixels_per_second, bandwidth;
+       uint64_t bytes_per_pixel = (bits_per_pixel + 7) / 8;
+
+       divisor = 1024;
+
+       if (!mode->htotal || !mode->vtotal || !mode->clock)
+               return 0;
+
+       active_area = mode->hdisplay * mode->vdisplay;
+       total_area = mode->htotal * mode->vtotal;
+
+       pixels_per_second = active_area * mode->clock * 1000;
+       do_div(pixels_per_second, total_area);
+
+       bandwidth = pixels_per_second * bytes_per_pixel * 100;
+       do_div(bandwidth, divisor);
+
+       return (uint32_t)(bandwidth);
+}
+
+#define MODE_BANDWIDTH MODE_BAD
+
 static int mga_vga_mode_valid(struct drm_connector *connector,
                                 struct drm_display_mode *mode)
 {
@@ -1421,7 +1447,45 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
        int bpp = 32;
        int i = 0;
 
-       /* FIXME: Add bandwidth and g200se limitations */
+       if (IS_G200_SE(mdev)) {
+               if (mdev->unique_rev_id == 0x01) {
+                       if (mode->hdisplay > 1600)
+                               return MODE_VIRTUAL_X;
+                       if (mode->vdisplay > 1200)
+                               return MODE_VIRTUAL_Y;
+                       if (mga_vga_calculate_mode_bandwidth(mode, bpp)
+                               > (24400 * 1024))
+                               return MODE_BANDWIDTH;
+               } else if (mdev->unique_rev_id >= 0x02) {
+                       if (mode->hdisplay > 1920)
+                               return MODE_VIRTUAL_X;
+                       if (mode->vdisplay > 1200)
+                               return MODE_VIRTUAL_Y;
+                       if (mga_vga_calculate_mode_bandwidth(mode, bpp)
+                               > (30100 * 1024))
+                               return MODE_BANDWIDTH;
+               }
+       } else if (mdev->type == G200_WB) {
+               if (mode->hdisplay > 1280)
+                       return MODE_VIRTUAL_X;
+               if (mode->vdisplay > 1024)
+                       return MODE_VIRTUAL_Y;
+               if (mga_vga_calculate_mode_bandwidth(mode,
+                       bpp > (31877 * 1024)))
+                       return MODE_BANDWIDTH;
+       } else if (mdev->type == G200_EV &&
+               (mga_vga_calculate_mode_bandwidth(mode, bpp)
+                       > (32700 * 1024))) {
+               return MODE_BANDWIDTH;
+       } else if (mode->type == G200_EH &&
+               (mga_vga_calculate_mode_bandwidth(mode, bpp)
+                       > (37500 * 1024))) {
+               return MODE_BANDWIDTH;
+       } else if (mode->type == G200_ER &&
+               (mga_vga_calculate_mode_bandwidth(mode,
+                       bpp) > (55000 * 1024))) {
+               return MODE_BANDWIDTH;
+       }
 
        if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 ||
            mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 ||
index 401c9891d3a8b7cfdf37ed4f40e1a5c5e79b050f..d2cb32f3c05b28e90ed38c1f1180c8e4adab5109 100644 (file)
@@ -347,6 +347,7 @@ int mgag200_bo_create(struct drm_device *dev, int size, int align,
 
        mgabo->gem.driver_private = NULL;
        mgabo->bo.bdev = &mdev->ttm.bdev;
+       mgabo->bo.bdev->dev_mapping = dev->dev_mapping;
 
        mgag200_ttm_placement(mgabo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
 
index f065fc248adfc9bba86beb476bd2545e884cc476..db8c6fd462784a8ebf8257ba4ab0965fa608348f 100644 (file)
@@ -55,6 +55,10 @@ nva3_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
        nv_wr32(priv, 0x61c510 + soff, 0x00000000);
        nv_mask(priv, 0x61c500 + soff, 0x00000001, 0x00000001);
 
+       nv_mask(priv, 0x61c5d0 + soff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */
+       nv_mask(priv, 0x61c568 + soff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */
+       nv_mask(priv, 0x61c578 + soff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */
+
        /* ??? */
        nv_mask(priv, 0x61733c, 0x00100000, 0x00100000); /* RESETF */
        nv_mask(priv, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */
index 6a38402fa56c95cd01a98ba89d01e71dccf92fb3..5680d3eb11ca7b51e57439149e39c0262a4a5ff3 100644 (file)
@@ -1107,6 +1107,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head)
        u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
        u32 hval, hreg = 0x614200 + (head * 0x800);
        u32 oval, oreg;
+       u32 mask;
        u32 conf = exec_clkcmp(priv, head, 0xff, pclk, &outp);
        if (conf != ~0) {
                if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) {
@@ -1133,6 +1134,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head)
                        oreg = 0x614280 + (ffs(outp.or) - 1) * 0x800;
                        oval = 0x00000000;
                        hval = 0x00000000;
+                       mask = 0xffffffff;
                } else
                if (!outp.location) {
                        if (outp.type == DCB_OUTPUT_DP)
@@ -1140,14 +1142,16 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head)
                        oreg = 0x614300 + (ffs(outp.or) - 1) * 0x800;
                        oval = (conf & 0x0100) ? 0x00000101 : 0x00000000;
                        hval = 0x00000000;
+                       mask = 0x00000707;
                } else {
                        oreg = 0x614380 + (ffs(outp.or) - 1) * 0x800;
                        oval = 0x00000001;
                        hval = 0x00000001;
+                       mask = 0x00000707;
                }
 
                nv_mask(priv, hreg, 0x0000000f, hval);
-               nv_mask(priv, oreg, 0x00000707, oval);
+               nv_mask(priv, oreg, mask, oval);
        }
 }
 
index d5502267c30f71162ad901fdbedfa6a375cb54eb..9d2cd200625084608b9a6ecb8e866a9dd7cecf2f 100644 (file)
@@ -20,8 +20,8 @@ nouveau_mc(void *obj)
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC];
 }
 
-#define nouveau_mc_create(p,e,o,d)                                             \
-       nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_mc_create(p,e,o,m,d)                                           \
+       nouveau_mc_create_((p), (e), (o), (m), sizeof(**d), (void **)d)
 #define nouveau_mc_destroy(p) ({                                               \
        struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc));        \
 })
@@ -33,7 +33,8 @@ nouveau_mc(void *obj)
 })
 
 int  nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *,
-                       struct nouveau_oclass *, int, void **);
+                       struct nouveau_oclass *, const struct nouveau_mc_intr *,
+                       int, void **);
 void _nouveau_mc_dtor(struct nouveau_object *);
 int  _nouveau_mc_init(struct nouveau_object *);
 int  _nouveau_mc_fini(struct nouveau_object *, bool);
index 1c0330b8c9a43919861a42781f6691bec3cbf51f..ec9cd6f10f910aac9f56c4acbc4d9e09d393c85a 100644 (file)
@@ -80,7 +80,9 @@ _nouveau_mc_dtor(struct nouveau_object *object)
 
 int
 nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
-                  struct nouveau_oclass *oclass, int length, void **pobject)
+                  struct nouveau_oclass *oclass,
+                  const struct nouveau_mc_intr *intr_map,
+                  int length, void **pobject)
 {
        struct nouveau_device *device = nv_device(parent);
        struct nouveau_mc *pmc;
@@ -92,6 +94,8 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
+       pmc->intr_map = intr_map;
+
        ret = request_irq(device->pdev->irq, nouveau_mc_intr,
                          IRQF_SHARED, "nouveau", pmc);
        if (ret < 0)
index 8c769715227bd65a6b814b0585e047b169ad1bb8..64aa4edb0d9d958d60daf543fcd7d98209da10fb 100644 (file)
@@ -50,12 +50,11 @@ nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv04_mc_intr;
        return 0;
 }
 
index 51919371810fdf25c924f6e765ede4c0c682e829..d9891782bf28ea69a906a50714110914af9cb8ba 100644 (file)
@@ -36,12 +36,11 @@ nv44_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv44_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv04_mc_intr;
        return 0;
 }
 
index d796924f99309764ca1799f0183aa0c955b7bdc2..732d8100344b2f470f320c880cc7c71f0b2aa886 100644 (file)
@@ -52,12 +52,11 @@ nv50_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv50_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv50_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv50_mc_intr;
        return 0;
 }
 
index e82fd21b504154e8b28ed3dcca7fb7c1647a4394..0d57b4d3e001a9f2d141f745bed505ae7670badd 100644 (file)
@@ -54,12 +54,11 @@ nv98_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv98_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv98_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv98_mc_intr;
        return 0;
 }
 
index 737bd4b682e1c8eae4880a78b65ac0535117294b..4c97cd2e7b56f184eed4553763107c312d5cb575 100644 (file)
@@ -56,12 +56,11 @@ nvc0_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvc0_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nvc0_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nvc0_mc_intr;
        return 0;
 }
 
index 77c67fc970e64f187d0b37d533fd3bef3cc8139c..e66fb77131bc8eae5d49cdbed348bc37e90275fe 100644 (file)
@@ -362,7 +362,7 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length,
        vm->fpde = offset >> (vmm->pgt_bits + 12);
        vm->lpde = (offset + length - 1) >> (vmm->pgt_bits + 12);
 
-       vm->pgt  = kcalloc(vm->lpde - vm->fpde + 1, sizeof(*vm->pgt), GFP_KERNEL);
+       vm->pgt  = vzalloc((vm->lpde - vm->fpde + 1) * sizeof(*vm->pgt));
        if (!vm->pgt) {
                kfree(vm);
                return -ENOMEM;
@@ -371,7 +371,7 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length,
        ret = nouveau_mm_init(&vm->mm, mm_offset >> 12, mm_length >> 12,
                              block >> 12);
        if (ret) {
-               kfree(vm->pgt);
+               vfree(vm->pgt);
                kfree(vm);
                return ret;
        }
@@ -446,7 +446,7 @@ nouveau_vm_del(struct nouveau_vm *vm)
        }
 
        nouveau_mm_fini(&vm->mm);
-       kfree(vm->pgt);
+       vfree(vm->pgt);
        kfree(vm);
 }
 
index 8e47a9bae8c301e1ac205a0140ef650ed9d7aa5f..22aa9963ea6fd46b36f28b457fa7cfeecac0372b 100644 (file)
@@ -76,7 +76,7 @@ nv17_fence_context_new(struct nouveau_channel *chan)
        struct ttm_mem_reg *mem = &priv->bo->bo.mem;
        struct nouveau_object *object;
        u32 start = mem->start * PAGE_SIZE;
-       u32 limit = mem->start + mem->size - 1;
+       u32 limit = start + mem->size - 1;
        int ret = 0;
 
        fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
index f9701e567db89793136c52e02bf11d59baba4ce4..0ee363840035b1e67bd3e6c6b8bb63afbf4d8ea3 100644 (file)
@@ -39,6 +39,8 @@ nv50_fence_context_new(struct nouveau_channel *chan)
        struct nv10_fence_chan *fctx;
        struct ttm_mem_reg *mem = &priv->bo->bo.mem;
        struct nouveau_object *object;
+       u32 start = mem->start * PAGE_SIZE;
+       u32 limit = start + mem->size - 1;
        int ret, i;
 
        fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
@@ -51,26 +53,28 @@ nv50_fence_context_new(struct nouveau_channel *chan)
        fctx->base.sync = nv17_fence_sync;
 
        ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
-                                NvSema, 0x0002,
+                                NvSema, 0x003d,
                                 &(struct nv_dma_class) {
                                        .flags = NV_DMA_TARGET_VRAM |
                                                 NV_DMA_ACCESS_RDWR,
-                                       .start = mem->start * PAGE_SIZE,
-                                       .limit = mem->size - 1,
+                                       .start = start,
+                                       .limit = limit,
                                 }, sizeof(struct nv_dma_class),
                                 &object);
 
        /* dma objects for display sync channel semaphore blocks */
        for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) {
                struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
+               u32 start = bo->bo.mem.start * PAGE_SIZE;
+               u32 limit = start + bo->bo.mem.size - 1;
 
                ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
                                         NvEvoSema0 + i, 0x003d,
                                         &(struct nv_dma_class) {
                                                .flags = NV_DMA_TARGET_VRAM |
                                                         NV_DMA_ACCESS_RDWR,
-                                               .start = bo->bo.offset,
-                                               .limit = bo->bo.offset + 0xfff,
+                                               .start = start,
+                                               .limit = limit,
                                         }, sizeof(struct nv_dma_class),
                                         &object);
        }
index fb441a790f3dc5a56fa6c65bf4384f2d098906fb..15da7ef344a4e55fa11d604c21269e97ab361386 100644 (file)
@@ -1222,12 +1222,17 @@ int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
        int r;
 
        mutex_lock(&ctx->mutex);
+       /* reset data block */
+       ctx->data_block = 0;
        /* reset reg block */
        ctx->reg_block = 0;
        /* reset fb window */
        ctx->fb_base = 0;
        /* reset io mode */
        ctx->io_mode = ATOM_IO_MM;
+       /* reset divmul */
+       ctx->divmul[0] = 0;
+       ctx->divmul[1] = 0;
        r = atom_execute_table_locked(ctx, index, params);
        mutex_unlock(&ctx->mutex);
        return r;
index 064023bed480fb84eae64d505465601499ac4dfc..32501f6ec991169917af2446db4acbd37f8fbba0 100644 (file)
@@ -44,6 +44,41 @@ static char *pre_emph_names[] = {
 };
 
 /***** radeon AUX functions *****/
+
+/* Atom needs data in little endian format
+ * so swap as appropriate when copying data to
+ * or from atom. Note that atom operates on
+ * dw units.
+ */
+static void radeon_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le)
+{
+#ifdef __BIG_ENDIAN
+       u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */
+       u32 *dst32, *src32;
+       int i;
+
+       memcpy(src_tmp, src, num_bytes);
+       src32 = (u32 *)src_tmp;
+       dst32 = (u32 *)dst_tmp;
+       if (to_le) {
+               for (i = 0; i < ((num_bytes + 3) / 4); i++)
+                       dst32[i] = cpu_to_le32(src32[i]);
+               memcpy(dst, dst_tmp, num_bytes);
+       } else {
+               u8 dws = num_bytes & ~3;
+               for (i = 0; i < ((num_bytes + 3) / 4); i++)
+                       dst32[i] = le32_to_cpu(src32[i]);
+               memcpy(dst, dst_tmp, dws);
+               if (num_bytes % 4) {
+                       for (i = 0; i < (num_bytes % 4); i++)
+                               dst[dws+i] = dst_tmp[dws+i];
+               }
+       }
+#else
+       memcpy(dst, src, num_bytes);
+#endif
+}
+
 union aux_channel_transaction {
        PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1;
        PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2;
@@ -65,10 +100,10 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
 
        base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1);
 
-       memcpy(base, send, send_bytes);
+       radeon_copy_swap(base, send, send_bytes, true);
 
-       args.v1.lpAuxRequest = 0 + 4;
-       args.v1.lpDataOut = 16 + 4;
+       args.v1.lpAuxRequest = cpu_to_le16((u16)(0 + 4));
+       args.v1.lpDataOut = cpu_to_le16((u16)(16 + 4));
        args.v1.ucDataOutLen = 0;
        args.v1.ucChannelID = chan->rec.i2c_id;
        args.v1.ucDelay = delay / 10;
@@ -102,7 +137,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
                recv_bytes = recv_size;
 
        if (recv && recv_size)
-               memcpy(recv, base + 16, recv_bytes);
+               radeon_copy_swap(recv, base + 16, recv_bytes, false);
 
        return recv_bytes;
 }
index 8406c8251fbfd074078fa79cb0e3f3806fb49779..4120d355cadd7fc0870709655ed7c6e081c68340 100644 (file)
@@ -186,6 +186,13 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
        u8 backlight_level;
        char bl_name[16];
 
+       /* Mac laptops with multiple GPUs use the gmux driver for backlight
+        * so don't register a backlight device
+        */
+       if ((rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
+           (rdev->pdev->device == 0x6741))
+               return;
+
        if (!radeon_encoder->enc_priv)
                return;
 
index 0f89ce3d02b90d7640c47a9b42f137001c76bcaf..687b421f75c35d0c64bc4c42a0d784db6dc962d2 100644 (file)
@@ -4681,6 +4681,8 @@ static int evergreen_startup(struct radeon_device *rdev)
        /* enable pcie gen2 link */
        evergreen_pcie_gen2_enable(rdev);
 
+       evergreen_mc_program(rdev);
+
        if (ASIC_IS_DCE5(rdev)) {
                if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
                        r = ni_init_microcode(rdev);
@@ -4708,7 +4710,6 @@ static int evergreen_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       evergreen_mc_program(rdev);
        if (rdev->flags & RADEON_IS_AGP) {
                evergreen_agp_enable(rdev);
        } else {
@@ -4854,10 +4855,10 @@ int evergreen_resume(struct radeon_device *rdev)
 int evergreen_suspend(struct radeon_device *rdev)
 {
        r600_audio_fini(rdev);
+       r600_uvd_stop(rdev);
        radeon_uvd_suspend(rdev);
        r700_cp_stop(rdev);
        r600_dma_stop(rdev);
-       r600_uvd_rbc_stop(rdev);
        evergreen_irq_suspend(rdev);
        radeon_wb_disable(rdev);
        evergreen_pcie_gart_disable(rdev);
@@ -4988,6 +4989,7 @@ void evergreen_fini(struct radeon_device *rdev)
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
        evergreen_pcie_gart_fini(rdev);
+       r600_uvd_stop(rdev);
        radeon_uvd_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
index ed7c8a7680929e5589fe84daa70f36d2e3bce74a..bb9ea3641312af1a8da0aff84486a124c629704a 100644 (file)
@@ -128,14 +128,7 @@ static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        uint32_t offset = dig->afmt->offset;
        uint8_t *frame = buffer + 3;
-
-       /* Our header values (type, version, length) should be alright, Intel
-        * is using the same. Checksum function also seems to be OK, it works
-        * fine for audio infoframe. However calculated value is always lower
-        * by 2 in comparison to fglrx. It breaks displaying anything in case
-        * of TVs that strictly check the checksum. Hack it manually here to
-        * workaround this issue. */
-       frame[0x0] += 2;
+       uint8_t *header = buffer;
 
        WREG32(AFMT_AVI_INFO0 + offset,
                frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
@@ -144,7 +137,7 @@ static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
        WREG32(AFMT_AVI_INFO2 + offset,
                frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
        WREG32(AFMT_AVI_INFO3 + offset,
-               frame[0xC] | (frame[0xD] << 8));
+               frame[0xC] | (frame[0xD] << 8) | (header[1] << 24));
 }
 
 static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 clock)
@@ -164,9 +157,9 @@ static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 clock)
         * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
         * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
         */
+       WREG32(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL(radeon_crtc->crtc_id));
        WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
        WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
-       WREG32(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL(radeon_crtc->crtc_id));
 }
 
 
@@ -184,6 +177,9 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
        uint32_t offset;
        ssize_t err;
 
+       if (!dig || !dig->afmt)
+               return;
+
        /* Silent, r600_hdmi_enable will raise WARN for us */
        if (!dig->afmt->enabled)
                return;
@@ -287,6 +283,9 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 
+       if (!dig || !dig->afmt)
+               return;
+
        /* Silent, r600_hdmi_enable will raise WARN for us */
        if (enable && dig->afmt->enabled)
                return;
index 84583302b08162058d3ce0c2bfed31ddf1b2b44e..3bf43a16adcc3af5f5955d485bd0b7af77a10f2b 100644 (file)
@@ -1929,6 +1929,8 @@ static int cayman_startup(struct radeon_device *rdev)
        /* enable pcie gen2 link */
        evergreen_pcie_gen2_enable(rdev);
 
+       evergreen_mc_program(rdev);
+
        if (rdev->flags & RADEON_IS_IGP) {
                if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
                        r = ni_init_microcode(rdev);
@@ -1957,7 +1959,6 @@ static int cayman_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       evergreen_mc_program(rdev);
        r = cayman_pcie_gart_enable(rdev);
        if (r)
                return r;
@@ -2133,7 +2134,7 @@ int cayman_suspend(struct radeon_device *rdev)
        radeon_vm_manager_fini(rdev);
        cayman_cp_enable(rdev, false);
        cayman_dma_stop(rdev);
-       r600_uvd_rbc_stop(rdev);
+       r600_uvd_stop(rdev);
        radeon_uvd_suspend(rdev);
        evergreen_irq_suspend(rdev);
        radeon_wb_disable(rdev);
@@ -2265,6 +2266,7 @@ void cayman_fini(struct radeon_device *rdev)
        radeon_vm_manager_fini(rdev);
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
+       r600_uvd_stop(rdev);
        radeon_uvd_fini(rdev);
        cayman_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
index 6948eb88c2b7848cad2ff436e0df835bdd8d7999..f19620b472f537053c73a4dfb232135b1f6f76fc 100644 (file)
@@ -2675,12 +2675,29 @@ int r600_uvd_rbc_start(struct radeon_device *rdev)
        return 0;
 }
 
-void r600_uvd_rbc_stop(struct radeon_device *rdev)
+void r600_uvd_stop(struct radeon_device *rdev)
 {
        struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
 
        /* force RBC into idle state */
        WREG32(UVD_RBC_RB_CNTL, 0x11010101);
+
+       /* Stall UMC and register bus before resetting VCPU */
+       WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
+       WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
+       mdelay(1);
+
+       /* put VCPU into reset */
+       WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
+       mdelay(5);
+
+       /* disable VCPU clock */
+       WREG32(UVD_VCPU_CNTL, 0x0);
+
+       /* Unstall UMC and register bus */
+       WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
+       WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
+
        ring->ready = false;
 }
 
@@ -2700,6 +2717,11 @@ int r600_uvd_init(struct radeon_device *rdev)
        /* disable interupt */
        WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1));
 
+       /* Stall UMC and register bus before resetting VCPU */
+       WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
+       WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
+       mdelay(1);
+
        /* put LMI, VCPU, RBC etc... into reset */
        WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET |
               LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET |
@@ -2729,10 +2751,6 @@ int r600_uvd_init(struct radeon_device *rdev)
        WREG32(UVD_MPC_SET_ALU, 0);
        WREG32(UVD_MPC_SET_MUX, 0x88);
 
-       /* Stall UMC */
-       WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
-       WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
-
        /* take all subblocks out of reset, except VCPU */
        WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
        mdelay(5);
@@ -2986,7 +3004,7 @@ void r600_uvd_fence_emit(struct radeon_device *rdev,
                         struct radeon_fence *fence)
 {
        struct radeon_ring *ring = &rdev->ring[fence->ring];
-       uint32_t addr = rdev->fence_drv[fence->ring].gpu_addr;
+       uint64_t addr = rdev->fence_drv[fence->ring].gpu_addr;
 
        radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0));
        radeon_ring_write(ring, fence->seq);
@@ -3206,6 +3224,8 @@ static int r600_startup(struct radeon_device *rdev)
        /* enable pcie gen2 link */
        r600_pcie_gen2_enable(rdev);
 
+       r600_mc_program(rdev);
+
        if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
                r = r600_init_microcode(rdev);
                if (r) {
@@ -3218,7 +3238,6 @@ static int r600_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r600_mc_program(rdev);
        if (rdev->flags & RADEON_IS_AGP) {
                r600_agp_enable(rdev);
        } else {
index 456750a0daa5c98409e040d6c3ed4731e533a0a1..b9b1139da356bcf37f55f6de0e422d896570aa88 100644 (file)
@@ -133,14 +133,7 @@ static void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        uint32_t offset = dig->afmt->offset;
        uint8_t *frame = buffer + 3;
-
-       /* Our header values (type, version, length) should be alright, Intel
-        * is using the same. Checksum function also seems to be OK, it works
-        * fine for audio infoframe. However calculated value is always lower
-        * by 2 in comparison to fglrx. It breaks displaying anything in case
-        * of TVs that strictly check the checksum. Hack it manually here to
-        * workaround this issue. */
-       frame[0x0] += 2;
+       uint8_t *header = buffer;
 
        WREG32(HDMI0_AVI_INFO0 + offset,
                frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
@@ -149,7 +142,7 @@ static void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
        WREG32(HDMI0_AVI_INFO2 + offset,
                frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
        WREG32(HDMI0_AVI_INFO3 + offset,
-               frame[0xC] | (frame[0xD] << 8));
+               frame[0xC] | (frame[0xD] << 8) | (header[1] << 24));
 }
 
 /*
@@ -249,9 +242,15 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
                /* according to the reg specs, this should DCE3.2 only, but in
                 * practice it seems to cover DCE3.0 as well.
                 */
-               WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
-               WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
-               WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
+               if (dig->dig_encoder == 0) {
+                       WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
+                       WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
+                       WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
+               } else {
+                       WREG32(DCCG_AUDIO_DTO1_PHASE, base_rate * 100);
+                       WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100);
+                       WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
+               }
        } else {
                /* according to the reg specs, this should be DCE2.0 and DCE3.0 */
                WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) |
@@ -273,6 +272,9 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
        uint32_t offset;
        ssize_t err;
 
+       if (!dig || !dig->afmt)
+               return;
+
        /* Silent, r600_hdmi_enable will raise WARN for us */
        if (!dig->afmt->enabled)
                return;
@@ -455,6 +457,9 @@ void r600_hdmi_enable(struct drm_encoder *encoder, bool enable)
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        u32 hdmi = HDMI0_ERROR_ACK;
 
+       if (!dig || !dig->afmt)
+               return;
+
        /* Silent, r600_hdmi_enable will raise WARN for us */
        if (enable && dig->afmt->enabled)
                return;
index 142ce6cc69f5e3564299102ceaa2982adce628e7..d4ff48ce1d8b452524cf03aaf9c936eaf243f9bb 100644 (file)
@@ -408,6 +408,7 @@ struct radeon_sa_manager {
        uint64_t                gpu_addr;
        void                    *cpu_ptr;
        uint32_t                domain;
+       uint32_t                align;
 };
 
 struct radeon_sa_bo;
@@ -1144,6 +1145,7 @@ struct radeon_uvd {
        struct radeon_bo        *vcpu_bo;
        void                    *cpu_addr;
        uint64_t                gpu_addr;
+       void                    *saved_bo;
        atomic_t                handles[RADEON_MAX_UVD_HANDLES];
        struct drm_file         *filp[RADEON_MAX_UVD_HANDLES];
        struct delayed_work     idle_work;
@@ -1762,7 +1764,7 @@ void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
                WREG32(reg, tmp_);                              \
        } while (0)
 #define WREG32_AND(reg, and) WREG32_P(reg, 0, and)
-#define WREG32_OR(reg, or) WREG32_P(reg, or, ~or)
+#define WREG32_OR(reg, or) WREG32_P(reg, or, ~(or))
 #define WREG32_PLL_P(reg, val, mask)                           \
        do {                                                    \
                uint32_t tmp_ = RREG32_PLL(reg);                \
index a2802b47ee958e230d754f105214070f91ef1f23..de36c472242377b50f74fcb07e38a3a1bf27d2ca 100644 (file)
@@ -986,8 +986,8 @@ static struct radeon_asic r600_asic = {
                .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .dma = &r600_copy_dma,
                .dma_ring_index = R600_RING_TYPE_DMA_INDEX,
-               .copy = &r600_copy_dma,
-               .copy_ring_index = R600_RING_TYPE_DMA_INDEX,
+               .copy = &r600_copy_blit,
+               .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX,
        },
        .surface = {
                .set_reg = r600_set_surface_reg,
@@ -1074,8 +1074,8 @@ static struct radeon_asic rs780_asic = {
                .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .dma = &r600_copy_dma,
                .dma_ring_index = R600_RING_TYPE_DMA_INDEX,
-               .copy = &r600_copy_dma,
-               .copy_ring_index = R600_RING_TYPE_DMA_INDEX,
+               .copy = &r600_copy_blit,
+               .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX,
        },
        .surface = {
                .set_reg = r600_set_surface_reg,
index a72759ede7538390a9360c0764670fcf161018c7..34223fc3d8280a2ffc5b96e3df2ece4bdba800be 100644 (file)
@@ -399,7 +399,7 @@ uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev);
 /* uvd */
 int r600_uvd_init(struct radeon_device *rdev);
 int r600_uvd_rbc_start(struct radeon_device *rdev);
-void r600_uvd_rbc_stop(struct radeon_device *rdev);
+void r600_uvd_stop(struct radeon_device *rdev);
 int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
 void r600_uvd_fence_emit(struct radeon_device *rdev,
                         struct radeon_fence *fence);
index 78edadc9e86b22b8ec64d5877f4b98365cafcffd..68ce360560190af6505856452658e450d3f6878a 100644 (file)
@@ -147,7 +147,7 @@ static uint16_t combios_get_table_offset(struct drm_device *dev,
                                         enum radeon_combios_table_offset table)
 {
        struct radeon_device *rdev = dev->dev_private;
-       int rev;
+       int rev, size;
        uint16_t offset = 0, check_offset;
 
        if (!rdev->bios)
@@ -156,174 +156,106 @@ static uint16_t combios_get_table_offset(struct drm_device *dev,
        switch (table) {
                /* absolute offset tables */
        case COMBIOS_ASIC_INIT_1_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0xc);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0xc;
                break;
        case COMBIOS_BIOS_SUPPORT_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x14);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x14;
                break;
        case COMBIOS_DAC_PROGRAMMING_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x2a);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x2a;
                break;
        case COMBIOS_MAX_COLOR_DEPTH_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x2c);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x2c;
                break;
        case COMBIOS_CRTC_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x2e);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x2e;
                break;
        case COMBIOS_PLL_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x30);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x30;
                break;
        case COMBIOS_TV_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x32);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x32;
                break;
        case COMBIOS_DFP_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x34);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x34;
                break;
        case COMBIOS_HW_CONFIG_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x36);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x36;
                break;
        case COMBIOS_MULTIMEDIA_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x38);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x38;
                break;
        case COMBIOS_TV_STD_PATCH_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x3e);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x3e;
                break;
        case COMBIOS_LCD_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x40);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x40;
                break;
        case COMBIOS_MOBILE_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x42);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x42;
                break;
        case COMBIOS_PLL_INIT_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x46);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x46;
                break;
        case COMBIOS_MEM_CONFIG_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x48);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x48;
                break;
        case COMBIOS_SAVE_MASK_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x4a);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x4a;
                break;
        case COMBIOS_HARDCODED_EDID_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x4c);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x4c;
                break;
        case COMBIOS_ASIC_INIT_2_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x4e);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x4e;
                break;
        case COMBIOS_CONNECTOR_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x50);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x50;
                break;
        case COMBIOS_DYN_CLK_1_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x52);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x52;
                break;
        case COMBIOS_RESERVED_MEM_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x54);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x54;
                break;
        case COMBIOS_EXT_TMDS_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x58);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x58;
                break;
        case COMBIOS_MEM_CLK_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x5a);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x5a;
                break;
        case COMBIOS_EXT_DAC_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x5c);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x5c;
                break;
        case COMBIOS_MISC_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x5e);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x5e;
                break;
        case COMBIOS_CRT_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x60);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x60;
                break;
        case COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x62);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x62;
                break;
        case COMBIOS_COMPONENT_VIDEO_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x64);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x64;
                break;
        case COMBIOS_FAN_SPEED_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x66);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x66;
                break;
        case COMBIOS_OVERDRIVE_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x68);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x68;
                break;
        case COMBIOS_OEM_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x6a);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x6a;
                break;
        case COMBIOS_DYN_CLK_2_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x6c);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x6c;
                break;
        case COMBIOS_POWER_CONNECTOR_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x6e);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x6e;
                break;
        case COMBIOS_I2C_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x70);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x70;
                break;
                /* relative offset tables */
        case COMBIOS_ASIC_INIT_3_TABLE: /* offset from misc info */
@@ -439,11 +371,16 @@ static uint16_t combios_get_table_offset(struct drm_device *dev,
                }
                break;
        default:
+               check_offset = 0;
                break;
        }
 
-       return offset;
+       size = RBIOS8(rdev->bios_header_start + 0x6);
+       /* check absolute offset tables */
+       if (table < COMBIOS_ASIC_INIT_3_TABLE && check_offset && check_offset < size)
+               offset = RBIOS16(rdev->bios_header_start + check_offset);
 
+       return offset;
 }
 
 bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
@@ -965,16 +902,22 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
                        dac = RBIOS8(dac_info + 0x3) & 0xf;
                        p_dac->ps2_pdac_adj = (bg << 8) | (dac);
                }
-               /* if the values are all zeros, use the table */
-               if (p_dac->ps2_pdac_adj)
+               /* if the values are zeros, use the table */
+               if ((dac == 0) || (bg == 0))
+                       found = 0;
+               else
                        found = 1;
        }
 
        /* quirks */
+       /* Radeon 7000 (RV100) */
+       if (((dev->pdev->device == 0x5159) &&
+           (dev->pdev->subsystem_vendor == 0x174B) &&
+           (dev->pdev->subsystem_device == 0x7c28)) ||
        /* Radeon 9100 (R200) */
-       if ((dev->pdev->device == 0x514D) &&
+          ((dev->pdev->device == 0x514D) &&
            (dev->pdev->subsystem_vendor == 0x174B) &&
-           (dev->pdev->subsystem_device == 0x7149)) {
+           (dev->pdev->subsystem_device == 0x7149))) {
                /* vbios value is bad, use the default */
                found = 0;
        }
index 43ec4a401f077809371e0360f22aa7f10c21af3b..5ce190b8bd1f148ff0fb7deac9ba873d1ef2422d 100644 (file)
@@ -467,6 +467,7 @@ int radeon_vm_manager_init(struct radeon_device *rdev)
                size *= 2;
                r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager,
                                              RADEON_GPU_PAGE_ALIGN(size),
+                                             RADEON_GPU_PAGE_SIZE,
                                              RADEON_GEM_DOMAIN_VRAM);
                if (r) {
                        dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n",
index 5a99d433fc35d52f57aa11649b1847ce7c7e7321..1fe12ab5c5ea9a133d7cf379f06cf37345c9349d 100644 (file)
@@ -241,9 +241,6 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
 {
        int r = 0;
 
-       INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
-       INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi);
-
        spin_lock_init(&rdev->irq.lock);
        r = drm_vblank_init(rdev->ddev, rdev->num_crtc);
        if (r) {
@@ -265,6 +262,10 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
                rdev->irq.installed = false;
                return r;
        }
+
+       INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
+       INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi);
+
        DRM_INFO("radeon: irq initialized.\n");
        return 0;
 }
@@ -284,8 +285,8 @@ void radeon_irq_kms_fini(struct radeon_device *rdev)
                rdev->irq.installed = false;
                if (rdev->msi_enabled)
                        pci_disable_msi(rdev->pdev);
+               flush_work(&rdev->hotplug_work);
        }
-       flush_work(&rdev->hotplug_work);
 }
 
 /**
index e2cb80a96b5113b0e0d3b3dfa42eeeef04d75d42..2943823946080b5ca76cd00184345bad05f937e6 100644 (file)
@@ -158,7 +158,7 @@ static inline void * radeon_sa_bo_cpu_addr(struct radeon_sa_bo *sa_bo)
 
 extern int radeon_sa_bo_manager_init(struct radeon_device *rdev,
                                     struct radeon_sa_manager *sa_manager,
-                                    unsigned size, u32 domain);
+                                    unsigned size, u32 align, u32 domain);
 extern void radeon_sa_bo_manager_fini(struct radeon_device *rdev,
                                      struct radeon_sa_manager *sa_manager);
 extern int radeon_sa_bo_manager_start(struct radeon_device *rdev,
index 82434018cbe81c3cd989de7f6586f88df57ddce1..83f6295a0e5e00247e55dd7f8045227b380fc22c 100644 (file)
@@ -224,6 +224,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
        }
        r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo,
                                      RADEON_IB_POOL_SIZE*64*1024,
+                                     RADEON_GPU_PAGE_SIZE,
                                      RADEON_GEM_DOMAIN_GTT);
        if (r) {
                return r;
index 0abe5a9431bb0a6abecd239919ac64bb68f32d5f..f0bac68254b79a5dd31cfdc14ce80a98bca91065 100644 (file)
@@ -49,7 +49,7 @@ static void radeon_sa_bo_try_free(struct radeon_sa_manager *sa_manager);
 
 int radeon_sa_bo_manager_init(struct radeon_device *rdev,
                              struct radeon_sa_manager *sa_manager,
-                             unsigned size, u32 domain)
+                             unsigned size, u32 align, u32 domain)
 {
        int i, r;
 
@@ -57,13 +57,14 @@ int radeon_sa_bo_manager_init(struct radeon_device *rdev,
        sa_manager->bo = NULL;
        sa_manager->size = size;
        sa_manager->domain = domain;
+       sa_manager->align = align;
        sa_manager->hole = &sa_manager->olist;
        INIT_LIST_HEAD(&sa_manager->olist);
        for (i = 0; i < RADEON_NUM_RINGS; ++i) {
                INIT_LIST_HEAD(&sa_manager->flist[i]);
        }
 
-       r = radeon_bo_create(rdev, size, RADEON_GPU_PAGE_SIZE, true,
+       r = radeon_bo_create(rdev, size, align, true,
                             domain, NULL, &sa_manager->bo);
        if (r) {
                dev_err(rdev->dev, "(%d) failed to allocate bo for manager\n", r);
@@ -317,7 +318,7 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
        unsigned tries[RADEON_NUM_RINGS];
        int i, r;
 
-       BUG_ON(align > RADEON_GPU_PAGE_SIZE);
+       BUG_ON(align > sa_manager->align);
        BUG_ON(size > sa_manager->size);
 
        *sa_bo = kmalloc(sizeof(struct radeon_sa_bo), GFP_KERNEL);
index cad735dd02c6f95260a92b268a446d1fbebe3be5..f3ccf6d4addb7577067da9670b2eecc7664c3312 100644 (file)
@@ -123,16 +123,29 @@ int radeon_uvd_init(struct radeon_device *rdev)
                return r;
        }
 
-       r = radeon_uvd_resume(rdev);
-       if (r)
+       r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
+       if (r) {
+               radeon_bo_unref(&rdev->uvd.vcpu_bo);
+               dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r);
                return r;
+       }
 
-       memset(rdev->uvd.cpu_addr, 0, bo_size);
-       memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size);
+       r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM,
+                         &rdev->uvd.gpu_addr);
+       if (r) {
+               radeon_bo_unreserve(rdev->uvd.vcpu_bo);
+               radeon_bo_unref(&rdev->uvd.vcpu_bo);
+               dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r);
+               return r;
+       }
 
-       r = radeon_uvd_suspend(rdev);
-       if (r)
+       r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
+       if (r) {
+               dev_err(rdev->dev, "(%d) UVD map failed\n", r);
                return r;
+       }
+
+       radeon_bo_unreserve(rdev->uvd.vcpu_bo);
 
        for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
                atomic_set(&rdev->uvd.handles[i], 0);
@@ -143,71 +156,74 @@ int radeon_uvd_init(struct radeon_device *rdev)
 }
 
 void radeon_uvd_fini(struct radeon_device *rdev)
-{
-       radeon_uvd_suspend(rdev);
-       radeon_bo_unref(&rdev->uvd.vcpu_bo);
-}
-
-int radeon_uvd_suspend(struct radeon_device *rdev)
 {
        int r;
 
        if (rdev->uvd.vcpu_bo == NULL)
-               return 0;
+               return;
 
        r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
        if (!r) {
                radeon_bo_kunmap(rdev->uvd.vcpu_bo);
                radeon_bo_unpin(rdev->uvd.vcpu_bo);
-               rdev->uvd.cpu_addr = NULL;
-               if (!radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_CPU, NULL)) {
-                       radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
-               }
                radeon_bo_unreserve(rdev->uvd.vcpu_bo);
-
-               if (rdev->uvd.cpu_addr) {
-                       radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
-               } else {
-                       rdev->fence_drv[R600_RING_TYPE_UVD_INDEX].cpu_addr = NULL;
-               }
        }
-       return r;
+
+       radeon_bo_unref(&rdev->uvd.vcpu_bo);
+
+       release_firmware(rdev->uvd_fw);
+}
+
+int radeon_uvd_suspend(struct radeon_device *rdev)
+{
+       unsigned size;
+       void *ptr;
+       int i;
+
+       if (rdev->uvd.vcpu_bo == NULL)
+               return 0;
+
+       for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
+               if (atomic_read(&rdev->uvd.handles[i]))
+                       break;
+
+       if (i == RADEON_MAX_UVD_HANDLES)
+               return 0;
+
+       size = radeon_bo_size(rdev->uvd.vcpu_bo);
+       size -= rdev->uvd_fw->size;
+
+       ptr = rdev->uvd.cpu_addr;
+       ptr += rdev->uvd_fw->size;
+
+       rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
+       memcpy(rdev->uvd.saved_bo, ptr, size);
+
+       return 0;
 }
 
 int radeon_uvd_resume(struct radeon_device *rdev)
 {
-       int r;
+       unsigned size;
+       void *ptr;
 
        if (rdev->uvd.vcpu_bo == NULL)
                return -EINVAL;
 
-       r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
-       if (r) {
-               radeon_bo_unref(&rdev->uvd.vcpu_bo);
-               dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r);
-               return r;
-       }
-
-       /* Have been pin in cpu unmap unpin */
-       radeon_bo_kunmap(rdev->uvd.vcpu_bo);
-       radeon_bo_unpin(rdev->uvd.vcpu_bo);
+       memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size);
 
-       r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM,
-                         &rdev->uvd.gpu_addr);
-       if (r) {
-               radeon_bo_unreserve(rdev->uvd.vcpu_bo);
-               radeon_bo_unref(&rdev->uvd.vcpu_bo);
-               dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r);
-               return r;
-       }
+       size = radeon_bo_size(rdev->uvd.vcpu_bo);
+       size -= rdev->uvd_fw->size;
 
-       r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
-       if (r) {
-               dev_err(rdev->dev, "(%d) UVD map failed\n", r);
-               return r;
-       }
+       ptr = rdev->uvd.cpu_addr;
+       ptr += rdev->uvd_fw->size;
 
-       radeon_bo_unreserve(rdev->uvd.vcpu_bo);
+       if (rdev->uvd.saved_bo != NULL) {
+               memcpy(ptr, rdev->uvd.saved_bo, size);
+               kfree(rdev->uvd.saved_bo);
+               rdev->uvd.saved_bo = NULL;
+       } else
+               memset(ptr, 0, size);
 
        return 0;
 }
@@ -222,8 +238,8 @@ void radeon_uvd_free_handles(struct radeon_device *rdev, struct drm_file *filp)
 {
        int i, r;
        for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
-               if (rdev->uvd.filp[i] == filp) {
-                       uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
+               uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
+               if (handle != 0 && rdev->uvd.filp[i] == filp) {
                        struct radeon_fence *fence;
 
                        r = radeon_uvd_get_destroy_msg(rdev,
@@ -343,6 +359,14 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
                return -EINVAL;
        }
 
+       if (bo->tbo.sync_obj) {
+               r = radeon_fence_wait(bo->tbo.sync_obj, false);
+               if (r) {
+                       DRM_ERROR("Failed waiting for UVD message (%d)!\n", r);
+                       return r;
+               }
+       }
+
        r = radeon_bo_kmap(bo, &ptr);
        if (r)
                return r;
index 4a62ad2e539944ffaefc73b7169733bfefff86ff..f5e92cfcc140984bd63e1a892fa88277bb7530c3 100644 (file)
@@ -744,10 +744,10 @@ static void rv770_init_golden_registers(struct radeon_device *rdev)
                                                 (const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers));
                radeon_program_register_sequence(rdev,
                                                 rv730_golden_registers,
-                                                (const u32)ARRAY_SIZE(rv770_golden_registers));
+                                                (const u32)ARRAY_SIZE(rv730_golden_registers));
                radeon_program_register_sequence(rdev,
                                                 rv730_mgcg_init,
-                                                (const u32)ARRAY_SIZE(rv770_mgcg_init));
+                                                (const u32)ARRAY_SIZE(rv730_mgcg_init));
                break;
        case CHIP_RV710:
                radeon_program_register_sequence(rdev,
@@ -758,18 +758,18 @@ static void rv770_init_golden_registers(struct radeon_device *rdev)
                                                 (const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers));
                radeon_program_register_sequence(rdev,
                                                 rv710_golden_registers,
-                                                (const u32)ARRAY_SIZE(rv770_golden_registers));
+                                                (const u32)ARRAY_SIZE(rv710_golden_registers));
                radeon_program_register_sequence(rdev,
                                                 rv710_mgcg_init,
-                                                (const u32)ARRAY_SIZE(rv770_mgcg_init));
+                                                (const u32)ARRAY_SIZE(rv710_mgcg_init));
                break;
        case CHIP_RV740:
                radeon_program_register_sequence(rdev,
                                                 rv740_golden_registers,
-                                                (const u32)ARRAY_SIZE(rv770_golden_registers));
+                                                (const u32)ARRAY_SIZE(rv740_golden_registers));
                radeon_program_register_sequence(rdev,
                                                 rv740_mgcg_init,
-                                                (const u32)ARRAY_SIZE(rv770_mgcg_init));
+                                                (const u32)ARRAY_SIZE(rv740_mgcg_init));
                break;
        default:
                break;
@@ -1829,6 +1829,8 @@ static int rv770_startup(struct radeon_device *rdev)
        /* enable pcie gen2 link */
        rv770_pcie_gen2_enable(rdev);
 
+       rv770_mc_program(rdev);
+
        if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
                r = r600_init_microcode(rdev);
                if (r) {
@@ -1841,7 +1843,6 @@ static int rv770_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       rv770_mc_program(rdev);
        if (rdev->flags & RADEON_IS_AGP) {
                rv770_agp_enable(rdev);
        } else {
@@ -1983,6 +1984,7 @@ int rv770_resume(struct radeon_device *rdev)
 int rv770_suspend(struct radeon_device *rdev)
 {
        r600_audio_fini(rdev);
+       r600_uvd_stop(rdev);
        radeon_uvd_suspend(rdev);
        r700_cp_stop(rdev);
        r600_dma_stop(rdev);
@@ -2098,6 +2100,7 @@ void rv770_fini(struct radeon_device *rdev)
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
        rv770_pcie_gart_fini(rdev);
+       r600_uvd_stop(rdev);
        radeon_uvd_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
index a1b0da6b580859dfede1703ee822e8cab28fe91f..1a96a16b9996aa3011b26212727d570b09bb0e94 100644 (file)
@@ -5270,6 +5270,8 @@ static int si_startup(struct radeon_device *rdev)
        struct radeon_ring *ring;
        int r;
 
+       si_mc_program(rdev);
+
        if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
            !rdev->rlc_fw || !rdev->mc_fw) {
                r = si_init_microcode(rdev);
@@ -5289,7 +5291,6 @@ static int si_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       si_mc_program(rdev);
        r = si_pcie_gart_enable(rdev);
        if (r)
                return r;
@@ -5473,7 +5474,7 @@ int si_suspend(struct radeon_device *rdev)
        si_cp_enable(rdev, false);
        cayman_dma_stop(rdev);
        if (rdev->has_uvd) {
-               r600_uvd_rbc_stop(rdev);
+               r600_uvd_stop(rdev);
                radeon_uvd_suspend(rdev);
        }
        si_irq_suspend(rdev);
@@ -5613,8 +5614,10 @@ void si_fini(struct radeon_device *rdev)
        radeon_vm_manager_fini(rdev);
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
-       if (rdev->has_uvd)
+       if (rdev->has_uvd) {
+               r600_uvd_stop(rdev);
                radeon_uvd_fini(rdev);
+       }
        si_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
index 3751730764a5e2e64e69c76ae958cf9ab3045dde..1a0bf07fe54b8c41dd16ab274c48ca6cc6043d32 100644 (file)
@@ -29,7 +29,9 @@
 #include <drm/drmP.h>
 #include <drm/ttm/ttm_bo_driver.h>
 
-#define VMW_PPN_SIZE sizeof(unsigned long)
+#define VMW_PPN_SIZE (sizeof(unsigned long))
+/* A future safe maximum remap size. */
+#define VMW_PPN_PER_REMAP ((31 * 1024) / VMW_PPN_SIZE)
 
 static int vmw_gmr2_bind(struct vmw_private *dev_priv,
                         struct page *pages[],
@@ -38,43 +40,61 @@ static int vmw_gmr2_bind(struct vmw_private *dev_priv,
 {
        SVGAFifoCmdDefineGMR2 define_cmd;
        SVGAFifoCmdRemapGMR2 remap_cmd;
-       uint32_t define_size = sizeof(define_cmd) + 4;
-       uint32_t remap_size = VMW_PPN_SIZE * num_pages + sizeof(remap_cmd) + 4;
        uint32_t *cmd;
        uint32_t *cmd_orig;
+       uint32_t define_size = sizeof(define_cmd) + sizeof(*cmd);
+       uint32_t remap_num = num_pages / VMW_PPN_PER_REMAP + ((num_pages % VMW_PPN_PER_REMAP) > 0);
+       uint32_t remap_size = VMW_PPN_SIZE * num_pages + (sizeof(remap_cmd) + sizeof(*cmd)) * remap_num;
+       uint32_t remap_pos = 0;
+       uint32_t cmd_size = define_size + remap_size;
        uint32_t i;
 
-       cmd_orig = cmd = vmw_fifo_reserve(dev_priv, define_size + remap_size);
+       cmd_orig = cmd = vmw_fifo_reserve(dev_priv, cmd_size);
        if (unlikely(cmd == NULL))
                return -ENOMEM;
 
        define_cmd.gmrId = gmr_id;
        define_cmd.numPages = num_pages;
 
+       *cmd++ = SVGA_CMD_DEFINE_GMR2;
+       memcpy(cmd, &define_cmd, sizeof(define_cmd));
+       cmd += sizeof(define_cmd) / sizeof(*cmd);
+
+       /*
+        * Need to split the command if there are too many
+        * pages that goes into the gmr.
+        */
+
        remap_cmd.gmrId = gmr_id;
        remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ?
                SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32;
-       remap_cmd.offsetPages = 0;
-       remap_cmd.numPages = num_pages;
 
-       *cmd++ = SVGA_CMD_DEFINE_GMR2;
-       memcpy(cmd, &define_cmd, sizeof(define_cmd));
-       cmd += sizeof(define_cmd) / sizeof(uint32);
+       while (num_pages > 0) {
+               unsigned long nr = min(num_pages, (unsigned long)VMW_PPN_PER_REMAP);
+
+               remap_cmd.offsetPages = remap_pos;
+               remap_cmd.numPages = nr;
 
-       *cmd++ = SVGA_CMD_REMAP_GMR2;
-       memcpy(cmd, &remap_cmd, sizeof(remap_cmd));
-       cmd += sizeof(remap_cmd) / sizeof(uint32);
+               *cmd++ = SVGA_CMD_REMAP_GMR2;
+               memcpy(cmd, &remap_cmd, sizeof(remap_cmd));
+               cmd += sizeof(remap_cmd) / sizeof(*cmd);
 
-       for (i = 0; i < num_pages; ++i) {
-               if (VMW_PPN_SIZE <= 4)
-                       *cmd = page_to_pfn(*pages++);
-               else
-                       *((uint64_t *)cmd) = page_to_pfn(*pages++);
+               for (i = 0; i < nr; ++i) {
+                       if (VMW_PPN_SIZE <= 4)
+                               *cmd = page_to_pfn(*pages++);
+                       else
+                               *((uint64_t *)cmd) = page_to_pfn(*pages++);
 
-               cmd += VMW_PPN_SIZE / sizeof(*cmd);
+                       cmd += VMW_PPN_SIZE / sizeof(*cmd);
+               }
+
+               num_pages -= nr;
+               remap_pos += nr;
        }
 
-       vmw_fifo_commit(dev_priv, define_size + remap_size);
+       BUG_ON(cmd != cmd_orig + cmd_size / sizeof(*cmd));
+
+       vmw_fifo_commit(dev_priv, cmd_size);
 
        return 0;
 }
index feae88b53fcd7597bc477aeef4dae7182f8f05ed..c7710b5c69afbf009d0e9f2d727668e6cdae5045 100644 (file)
@@ -524,6 +524,12 @@ static const struct hid_device_id apple_devices[] = {
                .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
                .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI),
+               .driver_data = APPLE_HAS_FN },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO),
+               .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS),
+               .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
index 264f550999406f7b924be6634917e3826e80a161..ed626e01514bcdd3818a3225146079f3a2eabb6c 100644 (file)
@@ -63,6 +63,8 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type,
        struct hid_report_enum *report_enum = device->report_enum + type;
        struct hid_report *report;
 
+       if (id >= HID_MAX_IDS)
+               return NULL;
        if (report_enum->report_id_hash[id])
                return report_enum->report_id_hash[id];
 
@@ -404,8 +406,10 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
 
        case HID_GLOBAL_ITEM_TAG_REPORT_ID:
                parser->global.report_id = item_udata(item);
-               if (parser->global.report_id == 0) {
-                       hid_err(parser->device, "report_id 0 is invalid\n");
+               if (parser->global.report_id == 0 ||
+                   parser->global.report_id >= HID_MAX_IDS) {
+                       hid_err(parser->device, "report_id %u is invalid\n",
+                               parser->global.report_id);
                        return -1;
                }
                return 0;
@@ -575,7 +579,7 @@ static void hid_close_report(struct hid_device *device)
        for (i = 0; i < HID_REPORT_TYPES; i++) {
                struct hid_report_enum *report_enum = device->report_enum + i;
 
-               for (j = 0; j < 256; j++) {
+               for (j = 0; j < HID_MAX_IDS; j++) {
                        struct hid_report *report = report_enum->report_id_hash[j];
                        if (report)
                                hid_free_report(report);
@@ -1152,7 +1156,12 @@ EXPORT_SYMBOL_GPL(hid_output_report);
 
 int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
 {
-       unsigned size = field->report_size;
+       unsigned size;
+
+       if (!field)
+               return -1;
+
+       size = field->report_size;
 
        hid_dump_input(field->report->device, field->usage + offset, value);
 
@@ -1547,6 +1556,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
@@ -2179,6 +2191,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
        { }
index 38535c9243d532b36d8cd321638fd4f2aeabb9c4..ca0219f98c650b12608bc7469e3fe5ce032aea5f 100644 (file)
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS   0x023b
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI  0x0255
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO   0x0256
+#define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI   0x0290
+#define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO    0x0291
+#define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS    0x0292
 #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY   0x030a
 #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY    0x030b
 #define USB_DEVICE_ID_APPLE_IRCONTROL  0x8240
 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16   0x0012
 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17   0x0013
 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18   0x0014
+#define USB_DEVICE_ID_NTRIG_DUOSENSE 0x1500
 
 #define USB_VENDOR_ID_ONTRAK           0x0a07
 #define USB_DEVICE_ID_ONTRAK_ADU100    0x0064
index 945b8158ec4c7f556d6c9db8753762ac958276c1..ac5e93528dfaec1ab8a5193de65dd59ae5f9e357 100644 (file)
@@ -340,7 +340,7 @@ static int hidinput_get_battery_property(struct power_supply *psy,
 {
        struct hid_device *dev = container_of(psy, struct hid_device, battery);
        int ret = 0;
-       __u8 buf[2] = {};
+       __u8 *buf;
 
        switch (prop) {
        case POWER_SUPPLY_PROP_PRESENT:
@@ -349,13 +349,20 @@ static int hidinput_get_battery_property(struct power_supply *psy,
                break;
 
        case POWER_SUPPLY_PROP_CAPACITY:
+
+               buf = kmalloc(2 * sizeof(__u8), GFP_KERNEL);
+               if (!buf) {
+                       ret = -ENOMEM;
+                       break;
+               }
                ret = dev->hid_get_raw_report(dev, dev->battery_report_id,
-                                             buf, sizeof(buf),
+                                             buf, 2,
                                              dev->battery_report_type);
 
                if (ret != 2) {
                        if (ret >= 0)
                                ret = -EINVAL;
+                       kfree(buf);
                        break;
                }
 
@@ -364,6 +371,7 @@ static int hidinput_get_battery_property(struct power_supply *psy,
                    buf[1] <= dev->battery_max)
                        val->intval = (100 * (buf[1] - dev->battery_min)) /
                                (dev->battery_max - dev->battery_min);
+               kfree(buf);
                break;
 
        case POWER_SUPPLY_PROP_MODEL_NAME:
index ef95102515e4d499143dd02a831481902d674b1e..5482156ab4debd2bfea4e7e47c36f9df7f0de678 100644 (file)
@@ -115,7 +115,8 @@ static inline int ntrig_get_mode(struct hid_device *hdev)
        struct hid_report *report = hdev->report_enum[HID_FEATURE_REPORT].
                                    report_id_hash[0x0d];
 
-       if (!report)
+       if (!report || report->maxfield < 1 ||
+           report->field[0]->report_count < 1)
                return -EINVAL;
 
        hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
index e346038f0f111eaf1b47571552df952d10537760..59d5eb1e742c98b8721f14a100528b587c25e3ef 100644 (file)
@@ -145,6 +145,7 @@ void picolcd_exit_cir(struct picolcd_data *data)
        struct rc_dev *rdev = data->rc_dev;
 
        data->rc_dev = NULL;
-       rc_unregister_device(rdev);
+       if (rdev)
+               rc_unregister_device(rdev);
 }
 
index b48092d0e1394a73f4c4ef66a21bc490f4b686f0..acbb021065ece8287c9d3ea433c860afc0711855 100644 (file)
@@ -290,7 +290,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev,
                buf += 10;
                cnt -= 10;
        }
-       if (!report)
+       if (!report || report->maxfield != 1)
                return -EINVAL;
 
        while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r'))
index 591f6b22aa947190a9e728b650caa40090cc9595..c930ab8554eac830dd8d615e86c01926bb716be0 100644 (file)
@@ -593,10 +593,14 @@ err_nomem:
 void picolcd_exit_framebuffer(struct picolcd_data *data)
 {
        struct fb_info *info = data->fb_info;
-       struct picolcd_fb_data *fbdata = info->par;
+       struct picolcd_fb_data *fbdata;
        unsigned long flags;
 
+       if (!info)
+               return;
+
        device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate);
+       fbdata = info->par;
 
        /* disconnect framebuffer from HID dev */
        spin_lock_irqsave(&fbdata->lock, flags);
index d29112fa5cd51a86b4c29c31398874cc5a726e3d..2dcd7d98dbd6d1f333f3082be4974c42a5df3c45 100644 (file)
@@ -132,8 +132,14 @@ static int plff_init(struct hid_device *hid)
                        strong = &report->field[0]->value[2];
                        weak = &report->field[0]->value[3];
                        debug("detected single-field device");
-               } else if (report->maxfield >= 4 && report->field[0]->maxusage == 1 &&
-                               report->field[0]->usage[0].hid == (HID_UP_LED | 0x43)) {
+               } else if (report->field[0]->maxusage == 1 &&
+                          report->field[0]->usage[0].hid ==
+                               (HID_UP_LED | 0x43) &&
+                          report->maxfield >= 4 &&
+                          report->field[0]->report_count >= 1 &&
+                          report->field[1]->report_count >= 1 &&
+                          report->field[2]->report_count >= 1 &&
+                          report->field[3]->report_count >= 1) {
                        report->field[0]->value[0] = 0x00;
                        report->field[1]->value[0] = 0x00;
                        strong = &report->field[2]->value[0];
index ca74981073271effdddc72ba1f173acea27ebbf9..aa34755ca205eb6955cb10b01b2a6b01bc1a3dd1 100644 (file)
@@ -221,7 +221,8 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
 
        mutex_lock(&data->mutex);
        report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
-       if (!report || (field_index >=  report->maxfield)) {
+       if (!report || (field_index >=  report->maxfield) ||
+           report->field[field_index]->report_count < 1) {
                ret = -EINVAL;
                goto done_proc;
        }
index a2f587d004e1e6afccadcd424a2ac5af202a74b6..7112f3e832ee22cd39f725f5f1100bb47f966643 100644 (file)
@@ -3,7 +3,7 @@
  *  Fixes "jumpy" cursor and removes nonexistent keyboard LEDS from
  *  the HID descriptor.
  *
- *  Copyright (c) 2011 Stefan Kriwanek <mail@stefankriwanek.de>
+ *  Copyright (c) 2011, 2013 Stefan Kriwanek <dev@stefankriwanek.de>
  */
 
 /*
@@ -46,8 +46,13 @@ static int speedlink_event(struct hid_device *hdev, struct hid_field *field,
                struct hid_usage *usage, __s32 value)
 {
        /* No other conditions due to usage_table. */
-       /* Fix "jumpy" cursor (invalid events sent by device). */
-       if (value == 256)
+
+       /* This fixes the "jumpy" cursor occuring due to invalid events sent
+        * by the device. Some devices only send them with value==+256, others
+        * don't. However, catching abs(value)>=256 is restrictive enough not
+        * to interfere with devices that were bug-free (has been tested).
+        */
+       if (abs(value) >= 256)
                return 1;
        /* Drop useless distance 0 events (on button clicks etc.) as well */
        if (value == 0)
index a7451632ceb46bad87845c444fc1897973e94ef9..612a655bc9f04cf2ad4b02b4b1e9ebd98164364d 100644 (file)
@@ -113,7 +113,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
        __u8 *buf;
        int ret = 0;
 
-       if (!hidraw_table[minor]) {
+       if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
                ret = -ENODEV;
                goto out;
        }
@@ -261,7 +261,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
        }
 
        mutex_lock(&minors_lock);
-       if (!hidraw_table[minor]) {
+       if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
                err = -ENODEV;
                goto out_unlock;
        }
@@ -302,39 +302,38 @@ static int hidraw_fasync(int fd, struct file *file, int on)
        return fasync_helper(fd, file, on, &list->fasync);
 }
 
+static void drop_ref(struct hidraw *hidraw, int exists_bit)
+{
+       if (exists_bit) {
+               hid_hw_close(hidraw->hid);
+               hidraw->exist = 0;
+               if (hidraw->open)
+                       wake_up_interruptible(&hidraw->wait);
+       } else {
+               --hidraw->open;
+       }
+
+       if (!hidraw->open && !hidraw->exist) {
+               device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
+               hidraw_table[hidraw->minor] = NULL;
+               kfree(hidraw);
+       }
+}
+
 static int hidraw_release(struct inode * inode, struct file * file)
 {
        unsigned int minor = iminor(inode);
-       struct hidraw *dev;
        struct hidraw_list *list = file->private_data;
-       int ret;
-       int i;
 
        mutex_lock(&minors_lock);
-       if (!hidraw_table[minor]) {
-               ret = -ENODEV;
-               goto unlock;
-       }
 
        list_del(&list->node);
-       dev = hidraw_table[minor];
-       if (!--dev->open) {
-               if (list->hidraw->exist) {
-                       hid_hw_power(dev->hid, PM_HINT_NORMAL);
-                       hid_hw_close(dev->hid);
-               } else {
-                       kfree(list->hidraw);
-               }
-       }
-
-       for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i)
-               kfree(list->buffer[i].value);
        kfree(list);
-       ret = 0;
-unlock:
-       mutex_unlock(&minors_lock);
 
-       return ret;
+       drop_ref(hidraw_table[minor], 0);
+
+       mutex_unlock(&minors_lock);
+       return 0;
 }
 
 static long hidraw_ioctl(struct file *file, unsigned int cmd,
@@ -539,18 +538,9 @@ void hidraw_disconnect(struct hid_device *hid)
        struct hidraw *hidraw = hid->hidraw;
 
        mutex_lock(&minors_lock);
-       hidraw->exist = 0;
-
-       device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
 
-       hidraw_table[hidraw->minor] = NULL;
+       drop_ref(hidraw, 1);
 
-       if (hidraw->open) {
-               hid_hw_close(hid);
-               wake_up_interruptible(&hidraw->wait);
-       } else {
-               kfree(hidraw);
-       }
        mutex_unlock(&minors_lock);
 }
 EXPORT_SYMBOL_GPL(hidraw_disconnect);
index 19b8360f2330ddec85856e09605a1ce69e32d880..07345521f4210f4988627cff4421beedc96d1c06 100644 (file)
@@ -109,6 +109,8 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS },
+
        { 0, 0 }
 };
 
index 4c605c70ebf9ed858d014d94383ebfab86851b1f..deb5c25305aff4622ceb8f84a1598902e484a6ce 100644 (file)
@@ -562,7 +562,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
                                struct hv_hotadd_state *has)
 {
        int ret = 0;
-       int i, nid, t;
+       int i, nid;
        unsigned long start_pfn;
        unsigned long processed_pfn;
        unsigned long total_pfn = pfn_count;
@@ -607,14 +607,11 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
 
                /*
                 * Wait for the memory block to be onlined.
+                * Since the hot add has succeeded, it is ok to
+                * proceed even if the pages in the hot added region
+                * have not been "onlined" within the allowed time.
                 */
-               t = wait_for_completion_timeout(&dm_device.ol_waitevent, 5*HZ);
-               if (t == 0) {
-                       pr_info("hot_add memory timedout\n");
-                       has->ha_end_pfn -= HA_CHUNK;
-                       has->covered_end_pfn -=  processed_pfn;
-                       break;
-               }
+               wait_for_completion_timeout(&dm_device.ol_waitevent, 5*HZ);
 
        }
 
@@ -978,6 +975,14 @@ static void post_status(struct hv_dynmem_device *dm)
                                dm->num_pages_ballooned +
                                compute_balloon_floor();
 
+       /*
+        * If our transaction ID is no longer current, just don't
+        * send the status. This can happen if we were interrupted
+        * after we picked our transaction ID.
+        */
+       if (status.hdr.trans_id != atomic_read(&trans_id))
+               return;
+
        vmbus_sendpacket(dm->dev->channel, &status,
                                sizeof(struct dm_status),
                                (unsigned long)NULL,
index d6fbb5772b8d62ff371d968bde11779a3a47302b..791f45dfc85dd9abc1847059650f7b6467001a0e 100644 (file)
@@ -32,7 +32,7 @@
 void hv_begin_read(struct hv_ring_buffer_info *rbi)
 {
        rbi->ring_buffer->interrupt_mask = 1;
-       smp_mb();
+       mb();
 }
 
 u32 hv_end_read(struct hv_ring_buffer_info *rbi)
@@ -41,7 +41,7 @@ u32 hv_end_read(struct hv_ring_buffer_info *rbi)
        u32 write;
 
        rbi->ring_buffer->interrupt_mask = 0;
-       smp_mb();
+       mb();
 
        /*
         * Now check to see if the ring buffer is still empty.
@@ -71,7 +71,7 @@ u32 hv_end_read(struct hv_ring_buffer_info *rbi)
 
 static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi)
 {
-       smp_mb();
+       mb();
        if (rbi->ring_buffer->interrupt_mask)
                return false;
 
@@ -442,7 +442,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
                                             sizeof(u64));
 
        /* Issue a full memory barrier before updating the write index */
-       smp_mb();
+       mb();
 
        /* Now, update the write location */
        hv_set_next_write_location(outring_info, next_write_location);
@@ -549,7 +549,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer,
        /* Make sure all reads are done before we update the read index since */
        /* the writer may start writing to the read area once the read index */
        /*is updated */
-       smp_mb();
+       mb();
 
        /* Update the read index */
        hv_set_next_read_location(inring_info, next_read_location);
index bf421e0efa1ebca57d834ff6599014b049dc6a19..4004e54ef05dab7c32330df8f268c1f4e3f5aff7 100644 (file)
@@ -434,7 +434,7 @@ static void vmbus_on_msg_dpc(unsigned long data)
                 * will not deliver any more messages since there is
                 * no empty slot
                 */
-               smp_mb();
+               mb();
 
                if (msg->header.message_flags.msg_pending) {
                        /*
index 0428e8a74b19253c1ab5da323d9026fe3e9a23c7..df064e8cd9dc2f5b861175d18133a6b35b61daf3 100644 (file)
@@ -296,8 +296,8 @@ config SENSORS_K10TEMP
          If you say yes here you get support for the temperature
          sensor(s) inside your CPU. Supported are later revisions of
          the AMD Family 10h and all revisions of the AMD Family 11h,
-         12h (Llano), 14h (Brazos) and 15h (Bulldozer/Trinity)
-         microarchitectures.
+         12h (Llano), 14h (Brazos), 15h (Bulldozer/Trinity) and
+         16h (Kabini) microarchitectures.
 
          This driver can also be built as a module.  If so, the module
          will be called k10temp.
index b83bf4bb95eba3489e861d7f2d51e24e6a42d15f..58637355c1f66c1ed876f9363ab84d7ae989def7 100644 (file)
@@ -215,7 +215,7 @@ static inline int adt7470_write_word_data(struct i2c_client *client, u8 reg,
                                          u16 value)
 {
        return i2c_smbus_write_byte_data(client, reg, value & 0xFF)
-              && i2c_smbus_write_byte_data(client, reg + 1, value >> 8);
+              || i2c_smbus_write_byte_data(client, reg + 1, value >> 8);
 }
 
 static void adt7470_init_client(struct i2c_client *client)
index e3b037c73a7eef2ce54249a99564e12d63690a26..e633856370cf403247d5a44152f776fc39e56241 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * k10temp.c - AMD Family 10h/11h/12h/14h/15h processor hardware monitoring
+ * k10temp.c - AMD Family 10h/11h/12h/14h/15h/16h processor hardware monitoring
  *
  * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
  *
@@ -211,6 +211,7 @@ static DEFINE_PCI_DEVICE_TABLE(k10temp_id_table) = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
        {}
 };
 MODULE_DEVICE_TABLE(pci, k10temp_id_table);
index 328fb0353c171a1b879af1040185afa1be109ea4..a41b5f3fc5069596d7c9a0c0c164dcefefc7e621 100644 (file)
@@ -605,12 +605,12 @@ static int max6697_init_chip(struct i2c_client *client)
                if (ret < 0)
                        return ret;
                ret = i2c_smbus_write_byte_data(client, MAX6581_REG_IDEALITY,
-                                               pdata->ideality_mask >> 1);
+                                               pdata->ideality_value);
                if (ret < 0)
                        return ret;
                ret = i2c_smbus_write_byte_data(client,
                                                MAX6581_REG_IDEALITY_SELECT,
-                                               pdata->ideality_value);
+                                               pdata->ideality_mask >> 1);
                if (ret < 0)
                        return ret;
        }
index 04638aee90398f44e73a620e3a3cffc9631b8d40..99cec18254203c5ebfa59ba0b1cbfdecabf77aac 100644 (file)
@@ -199,7 +199,7 @@ static const s8 NCT6775_ALARM_BITS[] = {
        0, 1, 2, 3, 8, 21, 20, 16,      /* in0.. in7 */
        17, -1, -1, -1, -1, -1, -1,     /* in8..in14 */
        -1,                             /* unused */
-       6, 7, 11, 10, 23,               /* fan1..fan5 */
+       6, 7, 11, -1, -1,               /* fan1..fan5 */
        -1, -1, -1,                     /* unused */
        4, 5, 13, -1, -1, -1,           /* temp1..temp6 */
        12, -1 };                       /* intrusion0, intrusion1 */
@@ -625,6 +625,7 @@ struct nct6775_data {
        u8 has_fan_min;         /* some fans don't have min register */
        bool has_fan_div;
 
+       u8 num_temp_alarms;     /* 2 or 3 */
        u8 temp_fixed_num;      /* 3 or 6 */
        u8 temp_type[NUM_TEMP_FIXED];
        s8 temp_offset[NUM_TEMP_FIXED];
@@ -1193,6 +1194,42 @@ show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
                       (unsigned int)((data->alarms >> nr) & 0x01));
 }
 
+static int find_temp_source(struct nct6775_data *data, int index, int count)
+{
+       int source = data->temp_src[index];
+       int nr;
+
+       for (nr = 0; nr < count; nr++) {
+               int src;
+
+               src = nct6775_read_value(data,
+                                        data->REG_TEMP_SOURCE[nr]) & 0x1f;
+               if (src == source)
+                       return nr;
+       }
+       return -1;
+}
+
+static ssize_t
+show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+       struct nct6775_data *data = nct6775_update_device(dev);
+       unsigned int alarm = 0;
+       int nr;
+
+       /*
+        * For temperatures, there is no fixed mapping from registers to alarm
+        * bits. Alarm bits are determined by the temperature source mapping.
+        */
+       nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
+       if (nr >= 0) {
+               int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
+               alarm = (data->alarms >> bit) & 0x01;
+       }
+       return sprintf(buf, "%u\n", alarm);
+}
+
 static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in_reg, NULL, 0, 0);
 static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in_reg, NULL, 1, 0);
 static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in_reg, NULL, 2, 0);
@@ -1874,22 +1911,18 @@ static struct sensor_device_attribute sda_temp_type[] = {
 };
 
 static struct sensor_device_attribute sda_temp_alarm[] = {
-       SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL,
-                   TEMP_ALARM_BASE),
-       SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL,
-                   TEMP_ALARM_BASE + 1),
-       SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL,
-                   TEMP_ALARM_BASE + 2),
-       SENSOR_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL,
-                   TEMP_ALARM_BASE + 3),
-       SENSOR_ATTR(temp5_alarm, S_IRUGO, show_alarm, NULL,
-                   TEMP_ALARM_BASE + 4),
-       SENSOR_ATTR(temp6_alarm, S_IRUGO, show_alarm, NULL,
-                   TEMP_ALARM_BASE + 5),
+       SENSOR_ATTR(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0),
+       SENSOR_ATTR(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 1),
+       SENSOR_ATTR(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 2),
+       SENSOR_ATTR(temp4_alarm, S_IRUGO, show_temp_alarm, NULL, 3),
+       SENSOR_ATTR(temp5_alarm, S_IRUGO, show_temp_alarm, NULL, 4),
+       SENSOR_ATTR(temp6_alarm, S_IRUGO, show_temp_alarm, NULL, 5),
+       SENSOR_ATTR(temp7_alarm, S_IRUGO, show_temp_alarm, NULL, 6),
+       SENSOR_ATTR(temp8_alarm, S_IRUGO, show_temp_alarm, NULL, 7),
+       SENSOR_ATTR(temp9_alarm, S_IRUGO, show_temp_alarm, NULL, 8),
+       SENSOR_ATTR(temp10_alarm, S_IRUGO, show_temp_alarm, NULL, 9),
 };
 
-#define NUM_TEMP_ALARM ARRAY_SIZE(sda_temp_alarm)
-
 static ssize_t
 show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -3215,13 +3248,11 @@ static void nct6775_device_remove_files(struct device *dev)
                device_remove_file(dev, &sda_temp_max[i].dev_attr);
                device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
                device_remove_file(dev, &sda_temp_crit[i].dev_attr);
+               device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
                if (!(data->have_temp_fixed & (1 << i)))
                        continue;
                device_remove_file(dev, &sda_temp_type[i].dev_attr);
                device_remove_file(dev, &sda_temp_offset[i].dev_attr);
-               if (i >= NUM_TEMP_ALARM)
-                       continue;
-               device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
        }
 
        device_remove_file(dev, &sda_caseopen[0].dev_attr);
@@ -3419,6 +3450,7 @@ static int nct6775_probe(struct platform_device *pdev)
                data->auto_pwm_num = 6;
                data->has_fan_div = true;
                data->temp_fixed_num = 3;
+               data->num_temp_alarms = 3;
 
                data->ALARM_BITS = NCT6775_ALARM_BITS;
 
@@ -3483,6 +3515,7 @@ static int nct6775_probe(struct platform_device *pdev)
                data->auto_pwm_num = 4;
                data->has_fan_div = false;
                data->temp_fixed_num = 3;
+               data->num_temp_alarms = 3;
 
                data->ALARM_BITS = NCT6776_ALARM_BITS;
 
@@ -3547,6 +3580,7 @@ static int nct6775_probe(struct platform_device *pdev)
                data->auto_pwm_num = 4;
                data->has_fan_div = false;
                data->temp_fixed_num = 6;
+               data->num_temp_alarms = 2;
 
                data->ALARM_BITS = NCT6779_ALARM_BITS;
 
@@ -3843,10 +3877,12 @@ static int nct6775_probe(struct platform_device *pdev)
                                                 &sda_fan_input[i].dev_attr);
                        if (err)
                                goto exit_remove;
-                       err = device_create_file(dev,
-                                                &sda_fan_alarm[i].dev_attr);
-                       if (err)
-                               goto exit_remove;
+                       if (data->ALARM_BITS[FAN_ALARM_BASE + i] >= 0) {
+                               err = device_create_file(dev,
+                                               &sda_fan_alarm[i].dev_attr);
+                               if (err)
+                                       goto exit_remove;
+                       }
                        if (data->kind != nct6776 &&
                            data->kind != nct6779) {
                                err = device_create_file(dev,
@@ -3897,6 +3933,12 @@ static int nct6775_probe(struct platform_device *pdev)
                        if (err)
                                goto exit_remove;
                }
+               if (find_temp_source(data, i, data->num_temp_alarms) >= 0) {
+                       err = device_create_file(dev,
+                                                &sda_temp_alarm[i].dev_attr);
+                       if (err)
+                               goto exit_remove;
+               }
                if (!(data->have_temp_fixed & (1 << i)))
                        continue;
                err = device_create_file(dev, &sda_temp_type[i].dev_attr);
@@ -3905,12 +3947,6 @@ static int nct6775_probe(struct platform_device *pdev)
                err = device_create_file(dev, &sda_temp_offset[i].dev_attr);
                if (err)
                        goto exit_remove;
-               if (i >= NUM_TEMP_ALARM ||
-                   data->ALARM_BITS[TEMP_ALARM_BASE + i] < 0)
-                       continue;
-               err = device_create_file(dev, &sda_temp_alarm[i].dev_attr);
-               if (err)
-                       goto exit_remove;
        }
 
        for (i = 0; i < ARRAY_SIZE(sda_caseopen); i++) {
index 631736e2e7ed94297a0f871615d6d5b6c9e6acd3..4faf02b3657d6f834c7b8d9860a8640da8580b4a 100644 (file)
@@ -150,6 +150,7 @@ config I2C_PIIX4
            ATI SB700/SP5100
            ATI SB800
            AMD Hudson-2
+           AMD CZ
            Serverworks OSB4
            Serverworks CSB5
            Serverworks CSB6
index 2039f230482db0565c0e4357bc9ae8f38a34757f..6d8094d44987b236cef49e0731d09627497ab2af 100644 (file)
@@ -494,7 +494,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
         * based on this empirical measurement and a lot of previous frobbing.
         */
        i2c->cmd_err = 0;
-       if (msg->len < 8) {
+       if (0) {        /* disable PIO mode until a proper fix is made */
                ret = mxs_i2c_pio_setup_xfer(adap, msg, flags);
                if (ret)
                        mxs_i2c_reset(i2c);
index 39ab78c1a02cc3a4f056a0294432ef01fbbfd165..d05ad590af29b5163e0920a8d7868a31d8ec0529 100644 (file)
@@ -22,7 +22,7 @@
        Intel PIIX4, 440MX
        Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100
        ATI IXP200, IXP300, IXP400, SB600, SB700/SP5100, SB800
-       AMD Hudson-2
+       AMD Hudson-2, CZ
        SMSC Victory66
 
    Note: we assume there can only be one device, with one or more
@@ -522,6 +522,7 @@ static DEFINE_PCI_DEVICE_TABLE(piix4_ids) = {
        { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS) },
        { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x790b) },
        { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
                     PCI_DEVICE_ID_SERVERWORKS_OSB4) },
        { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
index 98ddc323add011fe84e45abc4f8902ce9e7f09af..0cf5f8e06cfcc6b6bc8c059871e153a391cbd122 100644 (file)
@@ -451,7 +451,7 @@ static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan,
        int ret;
 
        ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_OFFSET);
-       if (ret == 0)
+       if (ret >= 0)
                raw64 += offset;
 
        scale_type = iio_channel_read(chan, &scale_val, &scale_val2,
index 41712f096515675ee70273c99856e8d888a06ea9..5849dc0726b9d457e09c313a41fce4c8910bdee8 100644 (file)
@@ -388,6 +388,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
        init_waitqueue_head(&isert_conn->conn_wait_comp_err);
        kref_init(&isert_conn->conn_kref);
        kref_get(&isert_conn->conn_kref);
+       mutex_init(&isert_conn->conn_mutex);
 
        cma_id->context = isert_conn;
        isert_conn->conn_cm_id = cma_id;
@@ -540,15 +541,32 @@ isert_disconnect_work(struct work_struct *work)
                                struct isert_conn, conn_logout_work);
 
        pr_debug("isert_disconnect_work(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
-
+       mutex_lock(&isert_conn->conn_mutex);
        isert_conn->state = ISER_CONN_DOWN;
 
        if (isert_conn->post_recv_buf_count == 0 &&
            atomic_read(&isert_conn->post_send_buf_count) == 0) {
                pr_debug("Calling wake_up(&isert_conn->conn_wait);\n");
-               wake_up(&isert_conn->conn_wait);
+               mutex_unlock(&isert_conn->conn_mutex);
+               goto wake_up;
+       }
+       if (!isert_conn->conn_cm_id) {
+               mutex_unlock(&isert_conn->conn_mutex);
+               isert_put_conn(isert_conn);
+               return;
+       }
+       if (!isert_conn->logout_posted) {
+               pr_debug("Calling rdma_disconnect for !logout_posted from"
+                        " isert_disconnect_work\n");
+               rdma_disconnect(isert_conn->conn_cm_id);
+               mutex_unlock(&isert_conn->conn_mutex);
+               iscsit_cause_connection_reinstatement(isert_conn->conn, 0);
+               goto wake_up;
        }
+       mutex_unlock(&isert_conn->conn_mutex);
 
+wake_up:
+       wake_up(&isert_conn->conn_wait);
        isert_put_conn(isert_conn);
 }
 
@@ -934,16 +952,11 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
        }
 
 sequence_cmd:
-       rc = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
+       rc = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
 
        if (!rc && dump_payload == false && unsol_data)
                iscsit_set_unsoliticed_dataout(cmd);
 
-       if (rc == CMDSN_ERROR_CANNOT_RECOVER)
-               return iscsit_add_reject_from_cmd(
-                          ISCSI_REASON_PROTOCOL_ERROR,
-                          1, 0, (unsigned char *)hdr, cmd);
-
        return 0;
 }
 
@@ -1184,14 +1197,12 @@ isert_put_cmd(struct isert_cmd *isert_cmd)
 {
        struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd;
        struct isert_conn *isert_conn = isert_cmd->conn;
-       struct iscsi_conn *conn;
+       struct iscsi_conn *conn = isert_conn->conn;
 
        pr_debug("Entering isert_put_cmd: %p\n", isert_cmd);
 
        switch (cmd->iscsi_opcode) {
        case ISCSI_OP_SCSI_CMD:
-               conn = isert_conn->conn;
-
                spin_lock_bh(&conn->cmd_lock);
                if (!list_empty(&cmd->i_conn_node))
                        list_del(&cmd->i_conn_node);
@@ -1201,16 +1212,18 @@ isert_put_cmd(struct isert_cmd *isert_cmd)
                        iscsit_stop_dataout_timer(cmd);
 
                isert_unmap_cmd(isert_cmd, isert_conn);
-               /*
-                * Fall-through
-                */
+               transport_generic_free_cmd(&cmd->se_cmd, 0);
+               break;
        case ISCSI_OP_SCSI_TMFUNC:
+               spin_lock_bh(&conn->cmd_lock);
+               if (!list_empty(&cmd->i_conn_node))
+                       list_del(&cmd->i_conn_node);
+               spin_unlock_bh(&conn->cmd_lock);
+
                transport_generic_free_cmd(&cmd->se_cmd, 0);
                break;
        case ISCSI_OP_REJECT:
        case ISCSI_OP_NOOP_OUT:
-               conn = isert_conn->conn;
-
                spin_lock_bh(&conn->cmd_lock);
                if (!list_empty(&cmd->i_conn_node))
                        list_del(&cmd->i_conn_node);
@@ -1222,6 +1235,9 @@ isert_put_cmd(struct isert_cmd *isert_cmd)
                 * associated cmd->se_cmd needs to be released.
                 */
                if (cmd->se_cmd.se_tfo != NULL) {
+                       pr_debug("Calling transport_generic_free_cmd from"
+                                " isert_put_cmd for 0x%02x\n",
+                                cmd->iscsi_opcode);
                        transport_generic_free_cmd(&cmd->se_cmd, 0);
                        break;
                }
@@ -1318,8 +1334,8 @@ isert_do_control_comp(struct work_struct *work)
                atomic_dec(&isert_conn->post_send_buf_count);
 
                cmd->i_state = ISTATE_SENT_STATUS;
-               complete(&cmd->reject_comp);
                isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev);
+               break;
        case ISTATE_SEND_LOGOUTRSP:
                pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n");
                /*
@@ -1345,7 +1361,8 @@ isert_response_completion(struct iser_tx_desc *tx_desc,
        struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd;
 
        if (cmd->i_state == ISTATE_SEND_TASKMGTRSP ||
-           cmd->i_state == ISTATE_SEND_LOGOUTRSP) {
+           cmd->i_state == ISTATE_SEND_LOGOUTRSP ||
+           cmd->i_state == ISTATE_SEND_REJECT) {
                isert_unmap_tx_desc(tx_desc, ib_dev);
 
                INIT_WORK(&isert_cmd->comp_work, isert_do_control_comp);
@@ -1419,7 +1436,11 @@ isert_cq_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn)
                pr_debug("isert_cq_comp_err >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
                pr_debug("Calling wake_up from isert_cq_comp_err\n");
 
-               isert_conn->state = ISER_CONN_TERMINATING;
+               mutex_lock(&isert_conn->conn_mutex);
+               if (isert_conn->state != ISER_CONN_DOWN)
+                       isert_conn->state = ISER_CONN_TERMINATING;
+               mutex_unlock(&isert_conn->conn_mutex);
+
                wake_up(&isert_conn->conn_wait_comp_err);
        }
 }
@@ -1637,11 +1658,25 @@ isert_put_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
                                struct isert_cmd, iscsi_cmd);
        struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
        struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr;
+       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1];
+       struct iscsi_reject *hdr =
+               (struct iscsi_reject *)&isert_cmd->tx_desc.iscsi_header;
 
        isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc);
-       iscsit_build_reject(cmd, conn, (struct iscsi_reject *)
-                               &isert_cmd->tx_desc.iscsi_header);
+       iscsit_build_reject(cmd, conn, hdr);
        isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc);
+
+       hton24(hdr->dlength, ISCSI_HDR_LEN);
+       isert_cmd->sense_buf_dma = ib_dma_map_single(ib_dev,
+                       (void *)cmd->buf_ptr, ISCSI_HDR_LEN,
+                       DMA_TO_DEVICE);
+       isert_cmd->sense_buf_len = ISCSI_HDR_LEN;
+       tx_dsg->addr    = isert_cmd->sense_buf_dma;
+       tx_dsg->length  = ISCSI_HDR_LEN;
+       tx_dsg->lkey    = isert_conn->conn_mr->lkey;
+       isert_cmd->tx_desc.num_sge = 2;
+
        isert_init_send_wr(isert_cmd, send_wr);
 
        pr_debug("Posting Reject IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n");
@@ -2175,6 +2210,17 @@ isert_free_np(struct iscsi_np *np)
        kfree(isert_np);
 }
 
+static int isert_check_state(struct isert_conn *isert_conn, int state)
+{
+       int ret;
+
+       mutex_lock(&isert_conn->conn_mutex);
+       ret = (isert_conn->state == state);
+       mutex_unlock(&isert_conn->conn_mutex);
+
+       return ret;
+}
+
 static void isert_free_conn(struct iscsi_conn *conn)
 {
        struct isert_conn *isert_conn = conn->context;
@@ -2184,26 +2230,43 @@ static void isert_free_conn(struct iscsi_conn *conn)
         * Decrement post_send_buf_count for special case when called
         * from isert_do_control_comp() -> iscsit_logout_post_handler()
         */
+       mutex_lock(&isert_conn->conn_mutex);
        if (isert_conn->logout_posted)
                atomic_dec(&isert_conn->post_send_buf_count);
 
-       if (isert_conn->conn_cm_id)
+       if (isert_conn->conn_cm_id && isert_conn->state != ISER_CONN_DOWN) {
+               pr_debug("Calling rdma_disconnect from isert_free_conn\n");
                rdma_disconnect(isert_conn->conn_cm_id);
+       }
        /*
         * Only wait for conn_wait_comp_err if the isert_conn made it
         * into full feature phase..
         */
-       if (isert_conn->state > ISER_CONN_INIT) {
+       if (isert_conn->state == ISER_CONN_UP) {
                pr_debug("isert_free_conn: Before wait_event comp_err %d\n",
                         isert_conn->state);
+               mutex_unlock(&isert_conn->conn_mutex);
+
                wait_event(isert_conn->conn_wait_comp_err,
-                          isert_conn->state == ISER_CONN_TERMINATING);
-               pr_debug("isert_free_conn: After wait_event #1 >>>>>>>>>>>>\n");
+                         (isert_check_state(isert_conn, ISER_CONN_TERMINATING)));
+
+               wait_event(isert_conn->conn_wait,
+                         (isert_check_state(isert_conn, ISER_CONN_DOWN)));
+
+               isert_put_conn(isert_conn);
+               return;
+       }
+       if (isert_conn->state == ISER_CONN_INIT) {
+               mutex_unlock(&isert_conn->conn_mutex);
+               isert_put_conn(isert_conn);
+               return;
        }
+       pr_debug("isert_free_conn: wait_event conn_wait %d\n",
+                isert_conn->state);
+       mutex_unlock(&isert_conn->conn_mutex);
 
-       pr_debug("isert_free_conn: wait_event conn_wait %d\n", isert_conn->state);
-       wait_event(isert_conn->conn_wait, isert_conn->state == ISER_CONN_DOWN);
-       pr_debug("isert_free_conn: After wait_event #2 >>>>>>>>>>>>>>>>>>>>\n");
+       wait_event(isert_conn->conn_wait,
+                 (isert_check_state(isert_conn, ISER_CONN_DOWN)));
 
        isert_put_conn(isert_conn);
 }
index b104f4c2cd3852979521d02b514c6b7fa2a198fb..5795c82a23061c35c54395e231889c57eccbae91 100644 (file)
@@ -102,6 +102,7 @@ struct isert_conn {
        struct ib_qp            *conn_qp;
        struct isert_device     *conn_device;
        struct work_struct      conn_logout_work;
+       struct mutex            conn_mutex;
        wait_queue_head_t       conn_wait;
        wait_queue_head_t       conn_wait_comp_err;
        struct kref             conn_kref;
index 2baff1b79a5596eb33eaaaa31577c193d80f099e..a73f9618b0adbbc0641c77a13254580e9d64ab0e 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI  0x0259
 #define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO   0x025a
 #define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS   0x025b
+/* MacbookAir6,2 (unibody, June 2013) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI   0x0290
+#define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO    0x0291
+#define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS    0x0292
 
 #define BCM5974_DEVICE(prod) {                                 \
        .match_flags = (USB_DEVICE_ID_MATCH_DEVICE |            \
@@ -145,6 +149,10 @@ static const struct usb_device_id bcm5974_table[] = {
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
+       /* MacbookAir6,2 */
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_ISO),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_JIS),
        /* Terminating entry */
        {}
 };
@@ -172,15 +180,18 @@ struct bt_data {
 /* trackpad header types */
 enum tp_type {
        TYPE1,                  /* plain trackpad */
-       TYPE2                   /* button integrated in trackpad */
+       TYPE2,                  /* button integrated in trackpad */
+       TYPE3                   /* additional header fields since June 2013 */
 };
 
 /* trackpad finger data offsets, le16-aligned */
 #define FINGER_TYPE1           (13 * sizeof(__le16))
 #define FINGER_TYPE2           (15 * sizeof(__le16))
+#define FINGER_TYPE3           (19 * sizeof(__le16))
 
 /* trackpad button data offsets */
 #define BUTTON_TYPE2           15
+#define BUTTON_TYPE3           23
 
 /* list of device capability bits */
 #define HAS_INTEGRATED_BUTTON  1
@@ -400,6 +411,19 @@ static const struct bcm5974_config bcm5974_config_table[] = {
                { SN_COORD, -150, 6730 },
                { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
        },
+       {
+               USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI,
+               USB_DEVICE_ID_APPLE_WELLSPRING8_ISO,
+               USB_DEVICE_ID_APPLE_WELLSPRING8_JIS,
+               HAS_INTEGRATED_BUTTON,
+               0, sizeof(struct bt_data),
+               0x83, TYPE3, FINGER_TYPE3, FINGER_TYPE3 + SIZEOF_ALL_FINGERS,
+               { SN_PRESSURE, 0, 300 },
+               { SN_WIDTH, 0, 2048 },
+               { SN_COORD, -4620, 5140 },
+               { SN_COORD, -150, 6600 },
+               { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
+       },
        {}
 };
 
@@ -557,6 +581,9 @@ static int report_tp_state(struct bcm5974 *dev, int size)
                input_report_key(input, BTN_LEFT, ibt);
        }
 
+       if (c->tp_type == TYPE3)
+               input_report_key(input, BTN_LEFT, dev->tp_data[BUTTON_TYPE3]);
+
        input_sync(input);
 
        return 0;
@@ -572,9 +599,14 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 
 static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
 {
-       char *data = kmalloc(8, GFP_KERNEL);
        int retval = 0, size;
+       char *data;
+
+       /* Type 3 does not require a mode switch */
+       if (dev->cfg.tp_type == TYPE3)
+               return 0;
 
+       data = kmalloc(8, GFP_KERNEL);
        if (!data) {
                dev_err(&dev->intf->dev, "out of memory\n");
                retval = -ENOMEM;
index 21d02b0d907c1ada17aa3b1d0e13352cd2e4cbf3..a3c338942f101cbf9310b6b5c36b29bc5f0dc5e5 100644 (file)
@@ -1484,6 +1484,10 @@ static unsigned long iommu_unmap_page(struct protection_domain *dom,
 
                        /* Large PTE found which maps this address */
                        unmap_size = PTE_PAGE_SIZE(*pte);
+
+                       /* Only unmap from the first pte in the page */
+                       if ((unmap_size - 1) & bus_addr)
+                               break;
                        count      = PAGE_SIZE_PTE_COUNT(unmap_size);
                        for (i = 0; i < count; i++)
                                pte[i] = 0ULL;
@@ -1493,7 +1497,7 @@ static unsigned long iommu_unmap_page(struct protection_domain *dom,
                unmapped += unmap_size;
        }
 
-       BUG_ON(!is_power_of_2(unmapped));
+       BUG_ON(unmapped && !is_power_of_2(unmapped));
 
        return unmapped;
 }
index b4f0e28dfa41d6bbff0314783360d455dd6c45ef..fa004b112a89941509cfe855a0f55d7a44c963a3 100644 (file)
@@ -890,56 +890,54 @@ static int dma_pte_clear_range(struct dmar_domain *domain,
        return order;
 }
 
+static void dma_pte_free_level(struct dmar_domain *domain, int level,
+                              struct dma_pte *pte, unsigned long pfn,
+                              unsigned long start_pfn, unsigned long last_pfn)
+{
+       pfn = max(start_pfn, pfn);
+       pte = &pte[pfn_level_offset(pfn, level)];
+
+       do {
+               unsigned long level_pfn;
+               struct dma_pte *level_pte;
+
+               if (!dma_pte_present(pte) || dma_pte_superpage(pte))
+                       goto next;
+
+               level_pfn = pfn & level_mask(level - 1);
+               level_pte = phys_to_virt(dma_pte_addr(pte));
+
+               if (level > 2)
+                       dma_pte_free_level(domain, level - 1, level_pte,
+                                          level_pfn, start_pfn, last_pfn);
+
+               /* If range covers entire pagetable, free it */
+               if (!(start_pfn > level_pfn ||
+                     last_pfn < level_pfn + level_size(level))) {
+                       dma_clear_pte(pte);
+                       domain_flush_cache(domain, pte, sizeof(*pte));
+                       free_pgtable_page(level_pte);
+               }
+next:
+               pfn += level_size(level);
+       } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
+}
+
 /* free page table pages. last level pte should already be cleared */
 static void dma_pte_free_pagetable(struct dmar_domain *domain,
                                   unsigned long start_pfn,
                                   unsigned long last_pfn)
 {
        int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
-       struct dma_pte *first_pte, *pte;
-       int total = agaw_to_level(domain->agaw);
-       int level;
-       unsigned long tmp;
-       int large_page = 2;
 
        BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
        BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
        BUG_ON(start_pfn > last_pfn);
 
        /* We don't need lock here; nobody else touches the iova range */
-       level = 2;
-       while (level <= total) {
-               tmp = align_to_level(start_pfn, level);
-
-               /* If we can't even clear one PTE at this level, we're done */
-               if (tmp + level_size(level) - 1 > last_pfn)
-                       return;
-
-               do {
-                       large_page = level;
-                       first_pte = pte = dma_pfn_level_pte(domain, tmp, level, &large_page);
-                       if (large_page > level)
-                               level = large_page + 1;
-                       if (!pte) {
-                               tmp = align_to_level(tmp + 1, level + 1);
-                               continue;
-                       }
-                       do {
-                               if (dma_pte_present(pte)) {
-                                       free_pgtable_page(phys_to_virt(dma_pte_addr(pte)));
-                                       dma_clear_pte(pte);
-                               }
-                               pte++;
-                               tmp += level_size(level);
-                       } while (!first_pte_in_page(pte) &&
-                                tmp + level_size(level) - 1 <= last_pfn);
+       dma_pte_free_level(domain, agaw_to_level(domain->agaw),
+                          domain->pgd, 0, start_pfn, last_pfn);
 
-                       domain_flush_cache(domain, first_pte,
-                                          (void *)pte - (void *)first_pte);
-                       
-               } while (tmp && tmp + level_size(level) - 1 <= last_pfn);
-               level++;
-       }
        /* free pgd */
        if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
                free_pgtable_page(domain->pgd);
index 6bd5c679d877fd2dcf4e447b781ec6d3363f2546..b7d83d6838f3f11f0e673e8b50a501edb6e3c2cc 100644 (file)
@@ -230,9 +230,9 @@ static int wm831x_status_probe(struct platform_device *pdev)
        int id = pdev->id % ARRAY_SIZE(chip_pdata->status);
        int ret;
 
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       res = platform_get_resource(pdev, IORESOURCE_REG, 0);
        if (res == NULL) {
-               dev_err(&pdev->dev, "No I/O resource\n");
+               dev_err(&pdev->dev, "No register resource\n");
                ret = -EINVAL;
                goto err;
        }
index 0b9a79b2f48aaded2397762ce500b032f25f77e1..82fc86a90c1a436d94ab8500334b62f4cce47dbc 100644 (file)
@@ -439,15 +439,15 @@ static void backside_setup_pid(void)
 
 /* Slots fan */
 static const struct wf_pid_param slots_param = {
-       .interval       = 5,
-       .history_len    = 2,
-       .gd             = 30 << 20,
-       .gp             = 5 << 20,
-       .gr             = 0,
-       .itarget        = 40 << 16,
-       .additive       = 1,
-       .min            = 300,
-       .max            = 4000,
+       .interval       = 1,
+       .history_len    = 20,
+       .gd             = 0,
+       .gp             = 0,
+       .gr             = 0x00100000,
+       .itarget        = 3200000,
+       .additive       = 0,
+       .min            = 20,
+       .max            = 100,
 };
 
 static void slots_fan_tick(void)
index d3e15b42a4ab97655d989c3fe8240b09613acdc4..c42b14b2304cceb0c5dde84660f63de6b57daca2 100644 (file)
@@ -437,6 +437,7 @@ struct bcache_device {
 
        /* If nonzero, we're detaching/unregistering from cache set */
        atomic_t                detaching;
+       int                     flush_done;
 
        atomic_long_t           sectors_dirty;
        unsigned long           sectors_dirty_gc;
index 7a5658f04e62092610b2144faab12ae5fa3976a0..833c590806ba6b4bcd39e2cf453e245b3d4ae373 100644 (file)
@@ -326,10 +326,25 @@ static void do_btree_write(struct btree *b)
        i->csum         = btree_csum_set(b, i);
 
        btree_bio_init(b);
-       b->bio->bi_rw   = REQ_META|WRITE_SYNC;
+       b->bio->bi_rw   = REQ_META|WRITE_SYNC|REQ_FUA;
        b->bio->bi_size = set_blocks(i, b->c) * block_bytes(b->c);
        bch_bio_map(b->bio, i);
 
+       /*
+        * If we're appending to a leaf node, we don't technically need FUA -
+        * this write just needs to be persisted before the next journal write,
+        * which will be marked FLUSH|FUA.
+        *
+        * Similarly if we're writing a new btree root - the pointer is going to
+        * be in the next journal entry.
+        *
+        * But if we're writing a new btree node (that isn't a root) or
+        * appending to a non leaf btree node, we need either FUA or a flush
+        * when we write the parent with the new pointer. FUA is cheaper than a
+        * flush, and writes appending to leaf nodes aren't blocking anything so
+        * just make all btree node writes FUA to keep things sane.
+        */
+
        bkey_copy(&k.key, &b->key);
        SET_PTR_OFFSET(&k.key, 0, PTR_OFFSET(&k.key, 0) + bset_offset(b, i));
 
@@ -1419,8 +1434,10 @@ static void btree_gc_start(struct cache_set *c)
        for_each_cache(ca, c, i)
                for_each_bucket(b, ca) {
                        b->gc_gen = b->gen;
-                       if (!atomic_read(&b->pin))
+                       if (!atomic_read(&b->pin)) {
                                SET_GC_MARK(b, GC_MARK_RECLAIMABLE);
+                               SET_GC_SECTORS_USED(b, 0);
+                       }
                }
 
        for (d = c->devices;
@@ -2140,6 +2157,9 @@ int bch_btree_insert(struct btree_op *op, struct cache_set *c)
 void bch_btree_set_root(struct btree *b)
 {
        unsigned i;
+       struct closure cl;
+
+       closure_init_stack(&cl);
 
        BUG_ON(!b->written);
 
@@ -2153,8 +2173,9 @@ void bch_btree_set_root(struct btree *b)
        b->c->root = b;
        __bkey_put(b->c, &b->key);
 
-       bch_journal_meta(b->c, NULL);
+       bch_journal_meta(b->c, &cl);
        pr_debug("%s for %pf", pbtree(b), __builtin_return_address(0));
+       closure_sync(&cl);
 }
 
 /* Cache lookup */
index bd05a9a8c7cf933e028be5eefbd1cd178681e495..9aba2017f0d1685ac5858ccf716c1f829681c853 100644 (file)
@@ -66,16 +66,18 @@ static inline void closure_put_after_sub(struct closure *cl, int flags)
                } else {
                        struct closure *parent = cl->parent;
                        struct closure_waitlist *wait = closure_waitlist(cl);
+                       closure_fn *destructor = cl->fn;
 
                        closure_debug_destroy(cl);
 
+                       smp_mb();
                        atomic_set(&cl->remaining, -1);
 
                        if (wait)
                                closure_wake_up(wait);
 
-                       if (cl->fn)
-                               cl->fn(cl);
+                       if (destructor)
+                               destructor(cl);
 
                        if (parent)
                                closure_put(parent);
index 48efd4dea645bde1b12cf69927e9f628fd1ae077..d285cd49104c895e75220040007be1d5bf96ad50 100644 (file)
@@ -97,6 +97,8 @@ struct bio *bch_bio_split(struct bio *bio, int sectors,
 
        if (bio->bi_rw & REQ_DISCARD) {
                ret = bio_alloc_bioset(gfp, 1, bs);
+               if (!ret)
+                       return NULL;
                idx = 0;
                goto out;
        }
index 8c8dfdcd9d4cc9bc4a3d0799b98401855b280bcc..b49abb246bb69f61e4d865843d597e55dc8409c4 100644 (file)
@@ -182,9 +182,14 @@ bsearch:
                pr_debug("starting binary search, l %u r %u", l, r);
 
                while (l + 1 < r) {
+                       seq = list_entry(list->prev, struct journal_replay,
+                                        list)->j.seq;
+
                        m = (l + r) >> 1;
+                       read_bucket(m);
 
-                       if (read_bucket(m))
+                       if (seq != list_entry(list->prev, struct journal_replay,
+                                             list)->j.seq)
                                l = m;
                        else
                                r = m;
@@ -617,7 +622,7 @@ static void journal_write_unlocked(struct closure *cl)
                bio_reset(bio);
                bio->bi_sector  = PTR_OFFSET(k, i);
                bio->bi_bdev    = ca->bdev;
-               bio->bi_rw      = REQ_WRITE|REQ_SYNC|REQ_META|REQ_FLUSH;
+               bio->bi_rw      = REQ_WRITE|REQ_SYNC|REQ_META|REQ_FLUSH|REQ_FUA;
                bio->bi_size    = sectors << 9;
 
                bio->bi_end_io  = journal_write_endio;
index e5ff12e52d5b277bea9cc4fa4aa5eb5bdf23540a..afb9a998a737d205024bf06d755756686f5d3b19 100644 (file)
@@ -489,6 +489,12 @@ static void bch_insert_data_loop(struct closure *cl)
                bch_queue_gc(op->c);
        }
 
+       /*
+        * Journal writes are marked REQ_FLUSH; if the original write was a
+        * flush, it'll wait on the journal write.
+        */
+       bio->bi_rw &= ~(REQ_FLUSH|REQ_FUA);
+
        do {
                unsigned i;
                struct bkey *k;
@@ -716,7 +722,7 @@ static struct search *search_alloc(struct bio *bio, struct bcache_device *d)
        s->task                 = current;
        s->orig_bio             = bio;
        s->write                = (bio->bi_rw & REQ_WRITE) != 0;
-       s->op.flush_journal     = (bio->bi_rw & REQ_FLUSH) != 0;
+       s->op.flush_journal     = (bio->bi_rw & (REQ_FLUSH|REQ_FUA)) != 0;
        s->op.skip              = (bio->bi_rw & REQ_DISCARD) != 0;
        s->recoverable          = 1;
        s->start_time           = jiffies;
@@ -1047,9 +1053,20 @@ static void request_write(struct cached_dev *dc, struct search *s)
                trace_bcache_writethrough(s->orig_bio);
                closure_bio_submit(bio, cl, s->d);
        } else {
-               s->op.cache_bio = bio;
                trace_bcache_writeback(s->orig_bio);
                bch_writeback_add(dc, bio_sectors(bio));
+
+               if (s->op.flush_journal) {
+                       /* Also need to send a flush to the backing device */
+                       s->op.cache_bio = bio_clone_bioset(bio, GFP_NOIO,
+                                                          dc->disk.bio_split);
+
+                       bio->bi_size = 0;
+                       bio->bi_vcnt = 0;
+                       closure_bio_submit(bio, cl, s->d);
+               } else {
+                       s->op.cache_bio = bio;
+               }
        }
 out:
        closure_call(&s->op.cl, bch_insert_data, NULL, cl);
index f88e2b653a3fc9c82a7b308c8988cd10eda0c96b..b4713cea1913dea2e7759d6c56c5df6859bf8b65 100644 (file)
@@ -704,7 +704,8 @@ static void bcache_device_detach(struct bcache_device *d)
                atomic_set(&d->detaching, 0);
        }
 
-       bcache_device_unlink(d);
+       if (!d->flush_done)
+               bcache_device_unlink(d);
 
        d->c->devices[d->id] = NULL;
        closure_put(&d->c->caching);
@@ -781,6 +782,8 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size)
        set_bit(QUEUE_FLAG_NONROT,      &d->disk->queue->queue_flags);
        set_bit(QUEUE_FLAG_DISCARD,     &d->disk->queue->queue_flags);
 
+       blk_queue_flush(q, REQ_FLUSH|REQ_FUA);
+
        return 0;
 }
 
@@ -1014,6 +1017,14 @@ static void cached_dev_flush(struct closure *cl)
        struct cached_dev *dc = container_of(cl, struct cached_dev, disk.cl);
        struct bcache_device *d = &dc->disk;
 
+       mutex_lock(&bch_register_lock);
+       d->flush_done = 1;
+
+       if (d->c)
+               bcache_device_unlink(d);
+
+       mutex_unlock(&bch_register_lock);
+
        bch_cache_accounting_destroy(&dc->accounting);
        kobject_del(&d->kobj);
 
@@ -1303,18 +1314,22 @@ static void cache_set_flush(struct closure *cl)
 static void __cache_set_unregister(struct closure *cl)
 {
        struct cache_set *c = container_of(cl, struct cache_set, caching);
-       struct cached_dev *dc, *t;
+       struct cached_dev *dc;
        size_t i;
 
        mutex_lock(&bch_register_lock);
 
-       if (test_bit(CACHE_SET_UNREGISTERING, &c->flags))
-               list_for_each_entry_safe(dc, t, &c->cached_devs, list)
-                       bch_cached_dev_detach(dc);
-
        for (i = 0; i < c->nr_uuids; i++)
-               if (c->devices[i] && UUID_FLASH_ONLY(&c->uuids[i]))
-                       bcache_device_stop(c->devices[i]);
+               if (c->devices[i]) {
+                       if (!UUID_FLASH_ONLY(&c->uuids[i]) &&
+                           test_bit(CACHE_SET_UNREGISTERING, &c->flags)) {
+                               dc = container_of(c->devices[i],
+                                                 struct cached_dev, disk);
+                               bch_cached_dev_detach(dc);
+                       } else {
+                               bcache_device_stop(c->devices[i]);
+                       }
+               }
 
        mutex_unlock(&bch_register_lock);
 
index aa04f02246421f503c63f267d1f0604454ddaecf..81a79b739e9738457190152e9d6f4ccafbe1dbe5 100644 (file)
@@ -1644,7 +1644,10 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
        }
 
        if (!dmi) {
+               unsigned noio_flag;
+               noio_flag = memalloc_noio_save();
                dmi = __vmalloc(param_kernel->data_size, GFP_NOIO | __GFP_REPEAT | __GFP_HIGH, PAGE_KERNEL);
+               memalloc_noio_restore(noio_flag);
                if (dmi)
                        *param_flags |= DM_PARAMS_VMALLOC;
        }
index bdf26f5bd326011595f8b9801cc2e408af6842cc..5adede17ddf6de2ffa7724aa8c72dae623f17611 100644 (file)
@@ -1561,7 +1561,6 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
        unsigned long flags;
        int r;
 
-again:
        bdev = NULL;
        mode = 0;
        r = 0;
@@ -1579,7 +1578,7 @@ again:
        }
 
        if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
-               r = -EAGAIN;
+               r = -ENOTCONN;
        else if (!bdev)
                r = -EIO;
 
@@ -1591,11 +1590,8 @@ again:
        if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
                r = scsi_verify_blk_ioctl(NULL, cmd);
 
-       if (r == -EAGAIN && !fatal_signal_pending(current)) {
+       if (r == -ENOTCONN && !fatal_signal_pending(current))
                queue_work(kmultipathd, &m->process_queued_ios);
-               msleep(10);
-               goto again;
-       }
 
        return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
 }
index b948fd864d457e9ce857d1d04fd74bf8997e0aee..0d2e812d424bff13aeb2ae7905d6ff026ffec581 100644 (file)
@@ -831,9 +831,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
        for (i = v->levels - 1; i >= 0; i--) {
                sector_t s;
                v->hash_level_block[i] = hash_position;
-               s = verity_position_at_level(v, v->data_blocks, i);
-               s = (s >> v->hash_per_block_bits) +
-                   !!(s & ((1 << v->hash_per_block_bits) - 1));
+               s = (v->data_blocks + ((sector_t)1 << ((i + 1) * v->hash_per_block_bits)) - 1)
+                                       >> ((i + 1) * v->hash_per_block_bits);
                if (hash_position + s < hash_position) {
                        ti->error = "Hash device offset overflow";
                        r = -E2BIG;
index d5370a94b2c1308ece53dd50ca5f9a5011b25fc7..33f20103d8d566d4a2dbb556acd22fcbd7b628f7 100644 (file)
@@ -386,10 +386,12 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
                        unsigned int cmd, unsigned long arg)
 {
        struct mapped_device *md = bdev->bd_disk->private_data;
-       struct dm_table *map = dm_get_live_table(md);
+       struct dm_table *map;
        struct dm_target *tgt;
        int r = -ENOTTY;
 
+retry:
+       map = dm_get_live_table(md);
        if (!map || !dm_table_get_size(map))
                goto out;
 
@@ -410,6 +412,11 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
 out:
        dm_table_put(map);
 
+       if (r == -ENOTCONN) {
+               msleep(10);
+               goto retry;
+       }
+
        return r;
 }
 
index 9b82377a833bd6572b628c79426ca153781fd712..51f0345a4ba43f3f692bea2785d641d257f1d4d5 100644 (file)
@@ -7697,20 +7697,6 @@ static int remove_and_add_spares(struct mddev *mddev,
                        continue;
 
                rdev->recovery_offset = 0;
-               if (rdev->saved_raid_disk >= 0 && mddev->in_sync) {
-                       spin_lock_irq(&mddev->write_lock);
-                       if (mddev->in_sync)
-                               /* OK, this device, which is in_sync,
-                                * will definitely be noticed before
-                                * the next write, so recovery isn't
-                                * needed.
-                                */
-                               rdev->recovery_offset = mddev->recovery_cp;
-                       spin_unlock_irq(&mddev->write_lock);
-               }
-               if (mddev->ro && rdev->recovery_offset != MaxSector)
-                       /* not safe to add this disk now */
-                       continue;
                if (mddev->pers->
                    hot_add_disk(mddev, rdev) == 0) {
                        if (sysfs_link_rdev(mddev, rdev))
index 6e17f8181c4b923eb4044838d5bfc9dbb6d625fd..6f4824426e86944013e61ac9a5e6e92c01661c8b 100644 (file)
@@ -1848,6 +1848,36 @@ static int process_checks(struct r1bio *r1_bio)
        int i;
        int vcnt;
 
+       /* Fix variable parts of all bios */
+       vcnt = (r1_bio->sectors + PAGE_SIZE / 512 - 1) >> (PAGE_SHIFT - 9);
+       for (i = 0; i < conf->raid_disks * 2; i++) {
+               int j;
+               int size;
+               struct bio *b = r1_bio->bios[i];
+               if (b->bi_end_io != end_sync_read)
+                       continue;
+               /* fixup the bio for reuse */
+               bio_reset(b);
+               b->bi_vcnt = vcnt;
+               b->bi_size = r1_bio->sectors << 9;
+               b->bi_sector = r1_bio->sector +
+                       conf->mirrors[i].rdev->data_offset;
+               b->bi_bdev = conf->mirrors[i].rdev->bdev;
+               b->bi_end_io = end_sync_read;
+               b->bi_private = r1_bio;
+
+               size = b->bi_size;
+               for (j = 0; j < vcnt ; j++) {
+                       struct bio_vec *bi;
+                       bi = &b->bi_io_vec[j];
+                       bi->bv_offset = 0;
+                       if (size > PAGE_SIZE)
+                               bi->bv_len = PAGE_SIZE;
+                       else
+                               bi->bv_len = size;
+                       size -= PAGE_SIZE;
+               }
+       }
        for (primary = 0; primary < conf->raid_disks * 2; primary++)
                if (r1_bio->bios[primary]->bi_end_io == end_sync_read &&
                    test_bit(BIO_UPTODATE, &r1_bio->bios[primary]->bi_flags)) {
@@ -1856,12 +1886,10 @@ static int process_checks(struct r1bio *r1_bio)
                        break;
                }
        r1_bio->read_disk = primary;
-       vcnt = (r1_bio->sectors + PAGE_SIZE / 512 - 1) >> (PAGE_SHIFT - 9);
        for (i = 0; i < conf->raid_disks * 2; i++) {
                int j;
                struct bio *pbio = r1_bio->bios[primary];
                struct bio *sbio = r1_bio->bios[i];
-               int size;
 
                if (sbio->bi_end_io != end_sync_read)
                        continue;
@@ -1887,27 +1915,6 @@ static int process_checks(struct r1bio *r1_bio)
                        rdev_dec_pending(conf->mirrors[i].rdev, mddev);
                        continue;
                }
-               /* fixup the bio for reuse */
-               bio_reset(sbio);
-               sbio->bi_vcnt = vcnt;
-               sbio->bi_size = r1_bio->sectors << 9;
-               sbio->bi_sector = r1_bio->sector +
-                       conf->mirrors[i].rdev->data_offset;
-               sbio->bi_bdev = conf->mirrors[i].rdev->bdev;
-               sbio->bi_end_io = end_sync_read;
-               sbio->bi_private = r1_bio;
-
-               size = sbio->bi_size;
-               for (j = 0; j < vcnt ; j++) {
-                       struct bio_vec *bi;
-                       bi = &sbio->bi_io_vec[j];
-                       bi->bv_offset = 0;
-                       if (size > PAGE_SIZE)
-                               bi->bv_len = PAGE_SIZE;
-                       else
-                               bi->bv_len = size;
-                       size -= PAGE_SIZE;
-               }
 
                bio_copy_data(sbio, pbio);
        }
index 6ddae2501b9ae0fb2eb7119a4bf5467d9b6a90b2..081bb33453535d87226c66b303ea4fc2d19fae67 100644 (file)
@@ -2075,11 +2075,17 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
                         * both 'first' and 'i', so we just compare them.
                         * All vec entries are PAGE_SIZE;
                         */
-                       for (j = 0; j < vcnt; j++)
+                       int sectors = r10_bio->sectors;
+                       for (j = 0; j < vcnt; j++) {
+                               int len = PAGE_SIZE;
+                               if (sectors < (len / 512))
+                                       len = sectors * 512;
                                if (memcmp(page_address(fbio->bi_io_vec[j].bv_page),
                                           page_address(tbio->bi_io_vec[j].bv_page),
-                                          fbio->bi_io_vec[j].bv_len))
+                                          len))
                                        break;
+                               sectors -= len/512;
+                       }
                        if (j == vcnt)
                                continue;
                        atomic64_add(r10_bio->sectors, &mddev->resync_mismatches);
@@ -2262,12 +2268,18 @@ static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio)
        d = r10_bio->devs[1].devnum;
        wbio = r10_bio->devs[1].bio;
        wbio2 = r10_bio->devs[1].repl_bio;
+       /* Need to test wbio2->bi_end_io before we call
+        * generic_make_request as if the former is NULL,
+        * the latter is free to free wbio2.
+        */
+       if (wbio2 && !wbio2->bi_end_io)
+               wbio2 = NULL;
        if (wbio->bi_end_io) {
                atomic_inc(&conf->mirrors[d].rdev->nr_pending);
                md_sync_acct(conf->mirrors[d].rdev->bdev, bio_sectors(wbio));
                generic_make_request(wbio);
        }
-       if (wbio2 && wbio2->bi_end_io) {
+       if (wbio2) {
                atomic_inc(&conf->mirrors[d].replacement->nr_pending);
                md_sync_acct(conf->mirrors[d].replacement->bdev,
                             bio_sectors(wbio2));
@@ -2909,14 +2921,13 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
         */
        if (mddev->bitmap == NULL &&
            mddev->recovery_cp == MaxSector &&
+           mddev->reshape_position == MaxSector &&
+           !test_bit(MD_RECOVERY_SYNC, &mddev->recovery) &&
            !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
+           !test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
            conf->fullsync == 0) {
                *skipped = 1;
-               max_sector = mddev->dev_sectors;
-               if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ||
-                   test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
-                       max_sector = mddev->resync_max_sectors;
-               return max_sector - sector_nr;
+               return mddev->dev_sectors - sector_nr;
        }
 
  skipped:
@@ -3386,6 +3397,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
 
                if (bio->bi_end_io == end_sync_read) {
                        md_sync_acct(bio->bi_bdev, nr_sectors);
+                       set_bit(BIO_UPTODATE, &bio->bi_flags);
                        generic_make_request(bio);
                }
        }
@@ -3532,7 +3544,7 @@ static struct r10conf *setup_conf(struct mddev *mddev)
 
        /* FIXME calc properly */
        conf->mirrors = kzalloc(sizeof(struct raid10_info)*(mddev->raid_disks +
-                                                           max(0,mddev->delta_disks)),
+                                                           max(0,-mddev->delta_disks)),
                                GFP_KERNEL);
        if (!conf->mirrors)
                goto out;
@@ -3691,7 +3703,7 @@ static int run(struct mddev *mddev)
                    conf->geo.far_offset == 0)
                        goto out_free_conf;
                if (conf->prev.far_copies != 1 &&
-                   conf->geo.far_offset == 0)
+                   conf->prev.far_offset == 0)
                        goto out_free_conf;
        }
 
index 05e4a105b9c706bb91bf4490ef2ce5f724601477..a35b846af4f8d82615b3ed5ed480295453bedaa3 100644 (file)
@@ -3462,6 +3462,7 @@ static void handle_stripe(struct stripe_head *sh)
                    test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
                        set_bit(STRIPE_SYNCING, &sh->state);
                        clear_bit(STRIPE_INSYNC, &sh->state);
+                       clear_bit(STRIPE_REPLACED, &sh->state);
                }
                spin_unlock(&sh->stripe_lock);
        }
@@ -3607,19 +3608,23 @@ static void handle_stripe(struct stripe_head *sh)
                        handle_parity_checks5(conf, sh, &s, disks);
        }
 
-       if (s.replacing && s.locked == 0
-           && !test_bit(STRIPE_INSYNC, &sh->state)) {
+       if ((s.replacing || s.syncing) && s.locked == 0
+           && !test_bit(STRIPE_COMPUTE_RUN, &sh->state)
+           && !test_bit(STRIPE_REPLACED, &sh->state)) {
                /* Write out to replacement devices where possible */
                for (i = 0; i < conf->raid_disks; i++)
-                       if (test_bit(R5_UPTODATE, &sh->dev[i].flags) &&
-                           test_bit(R5_NeedReplace, &sh->dev[i].flags)) {
+                       if (test_bit(R5_NeedReplace, &sh->dev[i].flags)) {
+                               WARN_ON(!test_bit(R5_UPTODATE, &sh->dev[i].flags));
                                set_bit(R5_WantReplace, &sh->dev[i].flags);
                                set_bit(R5_LOCKED, &sh->dev[i].flags);
                                s.locked++;
                        }
-               set_bit(STRIPE_INSYNC, &sh->state);
+               if (s.replacing)
+                       set_bit(STRIPE_INSYNC, &sh->state);
+               set_bit(STRIPE_REPLACED, &sh->state);
        }
        if ((s.syncing || s.replacing) && s.locked == 0 &&
+           !test_bit(STRIPE_COMPUTE_RUN, &sh->state) &&
            test_bit(STRIPE_INSYNC, &sh->state)) {
                md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
                clear_bit(STRIPE_SYNCING, &sh->state);
index b0b663b119a8f324ba7fa3b58953b42c81030fa4..70c49329ca9a23fbbad73061477ac0a0cfe80e6e 100644 (file)
@@ -306,6 +306,7 @@ enum {
        STRIPE_SYNC_REQUESTED,
        STRIPE_SYNCING,
        STRIPE_INSYNC,
+       STRIPE_REPLACED,
        STRIPE_PREREAD_ACTIVE,
        STRIPE_DELAYED,
        STRIPE_DEGRADED,
index 297f1b2f9a3219398087b12b8a7344e335e4423f..8df1aea5fbffdcbe6e900651f296e5e28bf059f5 100644 (file)
@@ -275,7 +275,8 @@ static void smsdvb_update_per_slices(struct smsdvb_client_t *client,
 
        /* Legacy PER/BER */
        tmp = p->ets_packets * 65535;
-       do_div(tmp, p->ts_packets + p->ets_packets);
+       if (p->ts_packets + p->ets_packets)
+               do_div(tmp, p->ts_packets + p->ets_packets);
        client->legacy_per = tmp;
 }
 
index a1a3a5159d71f1ffc3ab244232bf68b6877d5f50..0b4616b8719594560a70a1dfb977a206de5eba4b 100644 (file)
@@ -377,10 +377,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
                ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2,
                                              buffer2_len);
        }
-       if (ret < 0) {
-               dvb_ringbuffer_flush(&dmxdevfilter->buffer);
+       if (ret < 0)
                dmxdevfilter->buffer.error = ret;
-       }
        if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
                dmxdevfilter->state = DMXDEV_STATE_DONE;
        spin_unlock(&dmxdevfilter->dev->lock);
@@ -416,10 +414,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
        ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
        if (ret == buffer1_len)
                ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
-       if (ret < 0) {
-               dvb_ringbuffer_flush(buffer);
+       if (ret < 0)
                buffer->error = ret;
-       }
        spin_unlock(&dmxdevfilter->dev->lock);
        wake_up(&buffer->queue);
        return 0;
index 856374bd3676e2a3c3bfc9deab4d6ec23684c1f8..2c7217fb1415fae76c897d8b5cc31c06c253883d 100644 (file)
@@ -157,7 +157,6 @@ static struct regdata mb86a20s_init2[] = {
        { 0x45, 0x04 },                         /* CN symbol 4 */
        { 0x48, 0x04 },                         /* CN manual mode */
 
-       { 0x50, 0xd5 }, { 0x51, 0x01 },         /* Serial */
        { 0x50, 0xd6 }, { 0x51, 0x1f },
        { 0x50, 0xd2 }, { 0x51, 0x03 },
        { 0x50, 0xd7 }, { 0x51, 0xbf },
@@ -1860,16 +1859,15 @@ static int mb86a20s_initfe(struct dvb_frontend *fe)
        dev_dbg(&state->i2c->dev, "%s: IF=%d, IF reg=0x%06llx\n",
                __func__, state->if_freq, (long long)pll);
 
-       if (!state->config->is_serial) {
+       if (!state->config->is_serial)
                regD5 &= ~1;
 
-               rc = mb86a20s_writereg(state, 0x50, 0xd5);
-               if (rc < 0)
-                       goto err;
-               rc = mb86a20s_writereg(state, 0x51, regD5);
-               if (rc < 0)
-                       goto err;
-       }
+       rc = mb86a20s_writereg(state, 0x50, 0xd5);
+       if (rc < 0)
+               goto err;
+       rc = mb86a20s_writereg(state, 0x51, regD5);
+       if (rc < 0)
+               goto err;
 
        rc = mb86a20s_writeregdata(state, mb86a20s_init2);
        if (rc < 0)
index 10460fd3ce3994c5865e11e4f990407b2b583c47..dbcdfbf8aed0bdeae1f5d6ffff71bbe7a4e7d9da 100644 (file)
@@ -172,7 +172,9 @@ static void saa7134_irq_alsa_done(struct saa7134_dev *dev,
                dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count,
                        dev->dmasound.bufsize, dev->dmasound.blocks);
                spin_unlock(&dev->slock);
+               snd_pcm_stream_lock(dev->dmasound.substream);
                snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN);
+               snd_pcm_stream_unlock(dev->dmasound.substream);
                return;
        }
 
index 9d1481a60bd97d5ce60e8387365a7e22cbc50016..c504f70d4e90e5a83aa9d12134e1adfc9d612f22 100644 (file)
@@ -1933,7 +1933,7 @@ MODULE_DEVICE_TABLE(platform, coda_platform_ids);
 
 #ifdef CONFIG_OF
 static const struct of_device_id coda_dt_ids[] = {
-       { .compatible = "fsl,imx27-vpu", .data = &coda_platform_ids[CODA_IMX27] },
+       { .compatible = "fsl,imx27-vpu", .data = &coda_devdata[CODA_IMX27] },
        { .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] },
        { /* sentinel */ }
 };
index 33b5ffc8d66dfe136e2cd0df4129963b6c60ad79..f45b940d60721df6e57c85c69683f334e946c17c 100644 (file)
@@ -1122,10 +1122,14 @@ static int gsc_probe(struct platform_device *pdev)
                goto err_clk;
        }
 
-       ret = gsc_register_m2m_device(gsc);
+       ret = v4l2_device_register(dev, &gsc->v4l2_dev);
        if (ret)
                goto err_clk;
 
+       ret = gsc_register_m2m_device(gsc);
+       if (ret)
+               goto err_v4l2;
+
        platform_set_drvdata(pdev, gsc);
        pm_runtime_enable(dev);
        ret = pm_runtime_get_sync(&pdev->dev);
@@ -1147,6 +1151,8 @@ err_pm:
        pm_runtime_put(dev);
 err_m2m:
        gsc_unregister_m2m_device(gsc);
+err_v4l2:
+       v4l2_device_unregister(&gsc->v4l2_dev);
 err_clk:
        gsc_clk_put(gsc);
        return ret;
@@ -1157,6 +1163,7 @@ static int gsc_remove(struct platform_device *pdev)
        struct gsc_dev *gsc = platform_get_drvdata(pdev);
 
        gsc_unregister_m2m_device(gsc);
+       v4l2_device_unregister(&gsc->v4l2_dev);
 
        vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx);
        pm_runtime_disable(&pdev->dev);
index cc19bba09bd173720b2e8fc7b35813ea409da703..76435d3bf62d8a735c277c66724995ca78b8ab03 100644 (file)
@@ -343,6 +343,7 @@ struct gsc_dev {
        unsigned long                   state;
        struct vb2_alloc_ctx            *alloc_ctx;
        struct video_device             vdev;
+       struct v4l2_device              v4l2_dev;
 };
 
 /**
index 40a73f7d20daaefa006fa7afdef47e6ca529ef04..e576ff2de3de033cfc888d2afea783d72dfd93bb 100644 (file)
@@ -751,6 +751,7 @@ int gsc_register_m2m_device(struct gsc_dev *gsc)
        gsc->vdev.release       = video_device_release_empty;
        gsc->vdev.lock          = &gsc->lock;
        gsc->vdev.vfl_dir       = VFL_DIR_M2M;
+       gsc->vdev.v4l2_dev      = &gsc->v4l2_dev;
        snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m",
                                        GSC_MODULE_NAME, gsc->id);
 
index 15ef8f28239b797df583fa910720847cd4e14947..b5b480befcc3126d394289b3dfa71c60c4c44922 100644 (file)
@@ -1441,9 +1441,9 @@ static int fimc_md_probe(struct platform_device *pdev)
 err_unlock:
        mutex_unlock(&fmd->media_dev.graph_mutex);
 err_clk:
-       media_device_unregister(&fmd->media_dev);
        fimc_md_put_clocks(fmd);
        fimc_md_unregister_entities(fmd);
+       media_device_unregister(&fmd->media_dev);
 err_md:
        v4l2_device_unregister(&fmd->v4l2_dev);
        return ret;
index 553d87e5ceab41b9d2d081c6fc55dbe4b17db1ed..fd6289d60cde2c8a25450f6cb6d24c18923f0e81 100644 (file)
@@ -784,6 +784,7 @@ static int g2d_probe(struct platform_device *pdev)
        }
        *vfd = g2d_videodev;
        vfd->lock = &dev->mutex;
+       vfd->v4l2_dev = &dev->v4l2_dev;
        ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
        if (ret) {
                v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
index 4851cc2e4a4d3227b59df97c8020298b41796c77..c4ff9739a7ae8cb099b21637dc23723e5e170d1b 100644 (file)
@@ -726,7 +726,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus,
 
        *eedata = data;
        *eedata_len = len;
-       dev_config = (void *)eedata;
+       dev_config = (void *)*eedata;
 
        switch (le16_to_cpu(dev_config->chip_conf) >> 4 & 0x3) {
        case 0:
index 8247c19d62603cd4fbf977f010e28ea92ba6b045..77d7b7fbdc7e1ba0a62ca7dceb7e4cc903c28744 100644 (file)
@@ -311,6 +311,11 @@ static int hdpvr_probe(struct usb_interface *interface,
 
        dev->workqueue = 0;
 
+       /* init video transfer queues first of all */
+       /* to prevent oops in hdpvr_delete() on error paths */
+       INIT_LIST_HEAD(&dev->free_buff_list);
+       INIT_LIST_HEAD(&dev->rec_buff_list);
+
        /* register v4l2_device early so it can be used for printks */
        if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) {
                dev_err(&interface->dev, "v4l2_device_register failed\n");
@@ -333,10 +338,6 @@ static int hdpvr_probe(struct usb_interface *interface,
        if (!dev->workqueue)
                goto error;
 
-       /* init video transfer queues */
-       INIT_LIST_HEAD(&dev->free_buff_list);
-       INIT_LIST_HEAD(&dev->rec_buff_list);
-
        dev->options = hdpvr_default_options;
 
        if (default_video_input < HDPVR_VIDEO_INPUTS)
@@ -413,7 +414,7 @@ static int hdpvr_probe(struct usb_interface *interface,
                                    video_nr[atomic_inc_return(&dev_nr)]);
        if (retval < 0) {
                v4l2_err(&dev->v4l2_dev, "registering videodev failed\n");
-               goto error;
+               goto reg_fail;
        }
 
        /* let the user know what node this device is now attached to */
index 621c7a3733901abc6cf7da5170f1380a3a376ab9..b83e3ca12a419349690d1ab2a790124f2c1e0e93 100644 (file)
@@ -759,7 +759,7 @@ static int ilo_probe(struct pci_dev *pdev,
 
        /* Ignore subsystem_device = 0x1979 (set by BIOS)  */
        if (pdev->subsystem_device == 0x1979)
-               goto out;
+               return 0;
 
        if (max_ccb > MAX_CCB)
                max_ccb = MAX_CCB;
@@ -899,7 +899,7 @@ static void __exit ilo_exit(void)
        class_destroy(ilo_class);
 }
 
-MODULE_VERSION("1.4");
+MODULE_VERSION("1.4.1");
 MODULE_ALIAS(ILO_NAME);
 MODULE_DESCRIPTION(ILO_NAME);
 MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");
index 822170f00348df63b2a180aa157f08a0496ca27e..1bf3f8b5ce3a13d35e67a9772cc812ae5a3b7e1f 100644 (file)
@@ -176,16 +176,14 @@ static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
        struct mei_me_hw *hw = to_me_hw(dev);
        u32 hcsr = mei_hcsr_read(hw);
 
-       dev_dbg(&dev->pdev->dev, "before reset HCSR = 0x%08x.\n", hcsr);
-
-       hcsr |= (H_RST | H_IG);
+       hcsr |= H_RST | H_IG | H_IS;
 
        if (intr_enable)
                hcsr |= H_IE;
        else
-               hcsr |= ~H_IE;
+               hcsr &= ~H_IE;
 
-       mei_hcsr_set(hw, hcsr);
+       mei_me_reg_write(hw, H_CSR, hcsr);
 
        if (dev->dev_state == MEI_DEV_POWER_DOWN)
                mei_me_hw_reset_release(dev);
@@ -238,14 +236,18 @@ static int mei_me_hw_ready_wait(struct mei_device *dev)
        if (mei_me_hw_is_ready(dev))
                return 0;
 
+       dev->recvd_hw_ready = false;
        mutex_unlock(&dev->device_lock);
        err = wait_event_interruptible_timeout(dev->wait_hw_ready,
-                       dev->recvd_hw_ready, MEI_INTEROP_TIMEOUT);
+                       dev->recvd_hw_ready,
+                       mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
        mutex_lock(&dev->device_lock);
        if (!err && !dev->recvd_hw_ready) {
+               if (!err)
+                       err = -ETIMEDOUT;
                dev_err(&dev->pdev->dev,
-                       "wait hw ready failed. status = 0x%x\n", err);
-               return -ETIMEDOUT;
+                       "wait hw ready failed. status = %d\n", err);
+               return err;
        }
 
        dev->recvd_hw_ready = false;
@@ -482,7 +484,9 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
        /* check if ME wants a reset */
        if (!mei_hw_is_ready(dev) &&
            dev->dev_state != MEI_DEV_RESETTING &&
-           dev->dev_state != MEI_DEV_INITIALIZING) {
+           dev->dev_state != MEI_DEV_INITIALIZING &&
+           dev->dev_state != MEI_DEV_POWER_DOWN &&
+           dev->dev_state != MEI_DEV_POWER_UP) {
                dev_dbg(&dev->pdev->dev, "FW not ready.\n");
                mei_reset(dev, 1);
                mutex_unlock(&dev->device_lock);
index f580d30bb7842c564e81dba6b4406b1b01bfdee1..6eec689ba97ef71e95f1c27bd280d9c948bc50c8 100644 (file)
@@ -143,7 +143,8 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 
        dev->hbm_state = MEI_HBM_IDLE;
 
-       if (dev->dev_state != MEI_DEV_INITIALIZING) {
+       if (dev->dev_state != MEI_DEV_INITIALIZING &&
+           dev->dev_state != MEI_DEV_POWER_UP) {
                if (dev->dev_state != MEI_DEV_DISABLED &&
                    dev->dev_state != MEI_DEV_POWER_DOWN)
                        dev->dev_state = MEI_DEV_RESETTING;
index fff9286048594fa7dad59922ea382af76901450b..491e9ecc92c2501c9adcd4cc545eed85942e6754 100644 (file)
@@ -104,6 +104,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
 pio:
        if (!desc) {
                /* DMA failed, fall back to PIO */
+               tmio_mmc_enable_dma(host, false);
                if (ret >= 0)
                        ret = -EIO;
                host->chan_rx = NULL;
@@ -116,7 +117,6 @@ pio:
                }
                dev_warn(&host->pdev->dev,
                         "DMA failed: %d, falling back to PIO\n", ret);
-               tmio_mmc_enable_dma(host, false);
        }
 
        dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__,
@@ -185,6 +185,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
 pio:
        if (!desc) {
                /* DMA failed, fall back to PIO */
+               tmio_mmc_enable_dma(host, false);
                if (ret >= 0)
                        ret = -EIO;
                host->chan_tx = NULL;
@@ -197,7 +198,6 @@ pio:
                }
                dev_warn(&host->pdev->dev,
                         "DMA failed: %d, falling back to PIO\n", ret);
-               tmio_mmc_enable_dma(host, false);
        }
 
        dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d\n", __func__,
index a60f6c17f57b62acd19528b62a7d1b329df12913..50543f1662150ade806e9967190c60426a9ab029 100644 (file)
@@ -95,7 +95,7 @@ config MTD_NAND_OMAP2
 
 config MTD_NAND_OMAP_BCH
        depends on MTD_NAND && MTD_NAND_OMAP2 && ARCH_OMAP3
-       bool "Enable support for hardware BCH error correction"
+       tristate "Enable support for hardware BCH error correction"
        default n
        select BCH
        select BCH_CONST_PARAMS
index dfcd0a565c5b3e8f66d9b24077ae3701f132ee36..fb8c4deaac2717fe921c3b654276b2d19a4eaff7 100644 (file)
@@ -2793,7 +2793,9 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
 
        if (!chip->select_chip)
                chip->select_chip = nand_select_chip;
-       if (!chip->read_byte)
+
+       /* If called twice, pointers that depend on busw may need to be reset */
+       if (!chip->read_byte || chip->read_byte == nand_read_byte)
                chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
        if (!chip->read_word)
                chip->read_word = nand_read_word;
@@ -2801,9 +2803,9 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
                chip->block_bad = nand_block_bad;
        if (!chip->block_markbad)
                chip->block_markbad = nand_default_block_markbad;
-       if (!chip->write_buf)
+       if (!chip->write_buf || chip->write_buf == nand_write_buf)
                chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
-       if (!chip->read_buf)
+       if (!chip->read_buf || chip->read_buf == nand_read_buf)
                chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
        if (!chip->scan_bbt)
                chip->scan_bbt = nand_default_bbt;
index 5df49d3cb5c7c05e7644bd9e534950b070336d5b..c95bfb183c62b185f2f6cc17b5d84245bdd2d13d 100644 (file)
@@ -1069,6 +1069,9 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
                if (!(e2->ec - e1->ec >= UBI_WL_THRESHOLD)) {
                        dbg_wl("no WL needed: min used EC %d, max free EC %d",
                               e1->ec, e2->ec);
+
+                       /* Give the unused PEB back */
+                       wl_tree_add(e2, &ubi->free);
                        goto out_cancel;
                }
                self_check_in_wl_tree(ubi, e1, &ubi->used);
index a746ba272f04b5e3b77a4e45f65809a398c73585..a956053608f9f6a9fdb94c877917150e6a25680e 100644 (file)
@@ -1007,7 +1007,7 @@ static void arcnet_rx(struct net_device *dev, int bufnum)
 
        soft = &pkt.soft.rfc1201;
 
-       lp->hw.copy_from_card(dev, bufnum, 0, &pkt, sizeof(ARC_HDR_SIZE));
+       lp->hw.copy_from_card(dev, bufnum, 0, &pkt, ARC_HDR_SIZE);
        if (pkt.hard.offset[0]) {
                ofs = pkt.hard.offset[0];
                length = 256 - ofs;
index f975696135265a68a5946d7f784d4688f4ad0d30..666cf3a49b6d1418f5329ac038945b48cdcf31ed 100644 (file)
@@ -3770,11 +3770,17 @@ static int bond_neigh_init(struct neighbour *n)
  * The bonding ndo_neigh_setup is called at init time beofre any
  * slave exists. So we must declare proxy setup function which will
  * be used at run time to resolve the actual slave neigh param setup.
+ *
+ * It's also called by master devices (such as vlans) to setup their
+ * underlying devices. In that case - do nothing, we're already set up from
+ * our init.
  */
 static int bond_neigh_setup(struct net_device *dev,
                            struct neigh_parms *parms)
 {
-       parms->neigh_setup   = bond_neigh_init;
+       /* modify only our neigh_parms */
+       if (parms->dev == dev)
+               parms->neigh_setup = bond_neigh_init;
 
        return 0;
 }
index 25723d8ee20130b19ad95b885a99e5c1ba019517..925ab8ec9329b5bbfadb6e94faa12de0b7f91ceb 100644 (file)
@@ -649,7 +649,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
                if ((mc->ptr + rec_len) > mc->end)
                        goto decode_failed;
 
-               memcpy(cf->data, mc->ptr, rec_len);
+               memcpy(cf->data, mc->ptr, cf->can_dlc);
                mc->ptr += rec_len;
        }
 
index 42aa54af684271d1a69ffd1852f1b2222bfbcd6d..b710c6b2d65962db616017a6572cf75e425d69a1 100644 (file)
@@ -185,6 +185,8 @@ static int __init dummy_init_module(void)
 
        rtnl_lock();
        err = __rtnl_link_register(&dummy_link_ops);
+       if (err < 0)
+               goto out;
 
        for (i = 0; i < numdummies && !err; i++) {
                err = dummy_init_one();
@@ -192,6 +194,8 @@ static int __init dummy_init_module(void)
        }
        if (err < 0)
                __rtnl_link_unregister(&dummy_link_ops);
+
+out:
        rtnl_unlock();
 
        return err;
index 418de8b13165a767a0da5b98138055b6cf20bafb..d30085c2b45494727895e6c6f69ab5be1e07f57b 100644 (file)
@@ -1303,6 +1303,8 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        SET_NETDEV_DEV(netdev, &pdev->dev);
        alx = netdev_priv(netdev);
+       spin_lock_init(&alx->hw.mdio_lock);
+       spin_lock_init(&alx->irq_lock);
        alx->dev = netdev;
        alx->hw.pdev = pdev;
        alx->msg_enable = NETIF_MSG_LINK | NETIF_MSG_HW | NETIF_MSG_IFUP |
@@ -1385,9 +1387,6 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        INIT_WORK(&alx->link_check_wk, alx_link_check);
        INIT_WORK(&alx->reset_wk, alx_reset);
-       spin_lock_init(&alx->hw.mdio_lock);
-       spin_lock_init(&alx->irq_lock);
-
        netif_carrier_off(netdev);
 
        err = register_netdev(netdev);
index b2bf324631dc89f7902f9d7322c549331daa1c78..0f0556526ba90bff7f764c4005d6f6e850220dd7 100644 (file)
@@ -520,6 +520,9 @@ struct atl1c_adapter {
        struct net_device   *netdev;
        struct pci_dev      *pdev;
        struct napi_struct  napi;
+       struct page         *rx_page;
+       unsigned int        rx_page_offset;
+       unsigned int        rx_frag_size;
        struct atl1c_hw        hw;
        struct atl1c_hw_stats  hw_stats;
        struct mii_if_info  mii;    /* MII interface info */
index 0ba900762b138d87a3547a0a6d810bcfb151429d..11cdf1d430414598e9017d57fe8a93bdca0221a7 100644 (file)
@@ -481,10 +481,15 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p)
 static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter,
                                struct net_device *dev)
 {
+       unsigned int head_size;
        int mtu = dev->mtu;
 
        adapter->rx_buffer_len = mtu > AT_RX_BUF_SIZE ?
                roundup(mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN, 8) : AT_RX_BUF_SIZE;
+
+       head_size = SKB_DATA_ALIGN(adapter->rx_buffer_len + NET_SKB_PAD) +
+                   SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+       adapter->rx_frag_size = roundup_pow_of_two(head_size);
 }
 
 static netdev_features_t atl1c_fix_features(struct net_device *netdev,
@@ -952,6 +957,10 @@ static void atl1c_free_ring_resources(struct atl1c_adapter *adapter)
                kfree(adapter->tpd_ring[0].buffer_info);
                adapter->tpd_ring[0].buffer_info = NULL;
        }
+       if (adapter->rx_page) {
+               put_page(adapter->rx_page);
+               adapter->rx_page = NULL;
+       }
 }
 
 /**
@@ -1639,6 +1648,35 @@ static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter,
        skb_checksum_none_assert(skb);
 }
 
+static struct sk_buff *atl1c_alloc_skb(struct atl1c_adapter *adapter)
+{
+       struct sk_buff *skb;
+       struct page *page;
+
+       if (adapter->rx_frag_size > PAGE_SIZE)
+               return netdev_alloc_skb(adapter->netdev,
+                                       adapter->rx_buffer_len);
+
+       page = adapter->rx_page;
+       if (!page) {
+               adapter->rx_page = page = alloc_page(GFP_ATOMIC);
+               if (unlikely(!page))
+                       return NULL;
+               adapter->rx_page_offset = 0;
+       }
+
+       skb = build_skb(page_address(page) + adapter->rx_page_offset,
+                       adapter->rx_frag_size);
+       if (likely(skb)) {
+               adapter->rx_page_offset += adapter->rx_frag_size;
+               if (adapter->rx_page_offset >= PAGE_SIZE)
+                       adapter->rx_page = NULL;
+               else
+                       get_page(page);
+       }
+       return skb;
+}
+
 static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter)
 {
        struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring;
@@ -1660,7 +1698,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter)
        while (next_info->flags & ATL1C_BUFFER_FREE) {
                rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use);
 
-               skb = netdev_alloc_skb(adapter->netdev, adapter->rx_buffer_len);
+               skb = atl1c_alloc_skb(adapter);
                if (unlikely(!skb)) {
                        if (netif_msg_rx_err(adapter))
                                dev_warn(&pdev->dev, "alloc rx buffer failed\n");
index 0688bb82b442e9cd55d5ce6da9d1a9f064295403..c23bb02e3ed0eeec91e22367a789c00d91901cc8 100644 (file)
@@ -1665,8 +1665,8 @@ check_sum:
        return 0;
 }
 
-static void atl1e_tx_map(struct atl1e_adapter *adapter,
-                     struct sk_buff *skb, struct atl1e_tpd_desc *tpd)
+static int atl1e_tx_map(struct atl1e_adapter *adapter,
+                       struct sk_buff *skb, struct atl1e_tpd_desc *tpd)
 {
        struct atl1e_tpd_desc *use_tpd = NULL;
        struct atl1e_tx_buffer *tx_buffer = NULL;
@@ -1677,6 +1677,8 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
        u16 nr_frags;
        u16 f;
        int segment;
+       int ring_start = adapter->tx_ring.next_to_use;
+       int ring_end;
 
        nr_frags = skb_shinfo(skb)->nr_frags;
        segment = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
@@ -1689,6 +1691,9 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
                tx_buffer->length = map_len;
                tx_buffer->dma = pci_map_single(adapter->pdev,
                                        skb->data, hdr_len, PCI_DMA_TODEVICE);
+               if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma))
+                       return -ENOSPC;
+
                ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE);
                mapped_len += map_len;
                use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
@@ -1715,6 +1720,22 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
                tx_buffer->dma =
                        pci_map_single(adapter->pdev, skb->data + mapped_len,
                                        map_len, PCI_DMA_TODEVICE);
+
+               if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) {
+                       /* We need to unwind the mappings we've done */
+                       ring_end = adapter->tx_ring.next_to_use;
+                       adapter->tx_ring.next_to_use = ring_start;
+                       while (adapter->tx_ring.next_to_use != ring_end) {
+                               tpd = atl1e_get_tpd(adapter);
+                               tx_buffer = atl1e_get_tx_buffer(adapter, tpd);
+                               pci_unmap_single(adapter->pdev, tx_buffer->dma,
+                                                tx_buffer->length, PCI_DMA_TODEVICE);
+                       }
+                       /* Reset the tx rings next pointer */
+                       adapter->tx_ring.next_to_use = ring_start;
+                       return -ENOSPC;
+               }
+
                ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE);
                mapped_len  += map_len;
                use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
@@ -1750,6 +1771,23 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
                                                          (i * MAX_TX_BUF_LEN),
                                                          tx_buffer->length,
                                                          DMA_TO_DEVICE);
+
+                       if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) {
+                               /* We need to unwind the mappings we've done */
+                               ring_end = adapter->tx_ring.next_to_use;
+                               adapter->tx_ring.next_to_use = ring_start;
+                               while (adapter->tx_ring.next_to_use != ring_end) {
+                                       tpd = atl1e_get_tpd(adapter);
+                                       tx_buffer = atl1e_get_tx_buffer(adapter, tpd);
+                                       dma_unmap_page(&adapter->pdev->dev, tx_buffer->dma,
+                                                      tx_buffer->length, DMA_TO_DEVICE);
+                               }
+
+                               /* Reset the ring next to use pointer */
+                               adapter->tx_ring.next_to_use = ring_start;
+                               return -ENOSPC;
+                       }
+
                        ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_PAGE);
                        use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
                        use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
@@ -1767,6 +1805,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter,
        /* The last buffer info contain the skb address,
           so it will be free after unmap */
        tx_buffer->skb = skb;
+       return 0;
 }
 
 static void atl1e_tx_queue(struct atl1e_adapter *adapter, u16 count,
@@ -1834,10 +1873,15 @@ static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb,
                return NETDEV_TX_OK;
        }
 
-       atl1e_tx_map(adapter, skb, tpd);
+       if (atl1e_tx_map(adapter, skb, tpd)) {
+               dev_kfree_skb_any(skb);
+               goto out;
+       }
+
        atl1e_tx_queue(adapter, tpd_req, tpd);
 
        netdev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
+out:
        spin_unlock_irqrestore(&adapter->tx_lock, flags);
        return NETDEV_TX_OK;
 }
index a13463e8a2c3401ac4f02715dc44857ed330b5e5..0877a052e3ee4f889fbdea221fc2be1e157a2ae7 100644 (file)
@@ -3003,6 +3003,19 @@ static bool tg3_phy_power_bug(struct tg3 *tp)
        return false;
 }
 
+static bool tg3_phy_led_bug(struct tg3 *tp)
+{
+       switch (tg3_asic_rev(tp)) {
+       case ASIC_REV_5719:
+               if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) &&
+                   !tp->pci_fn)
+                       return true;
+               return false;
+       }
+
+       return false;
+}
+
 static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
 {
        u32 val;
@@ -3050,8 +3063,9 @@ static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
                }
                return;
        } else if (do_low_power) {
-               tg3_writephy(tp, MII_TG3_EXT_CTRL,
-                            MII_TG3_EXT_CTRL_FORCE_LED_OFF);
+               if (!tg3_phy_led_bug(tp))
+                       tg3_writephy(tp, MII_TG3_EXT_CTRL,
+                                    MII_TG3_EXT_CTRL_FORCE_LED_OFF);
 
                val = MII_TG3_AUXCTL_PCTL_100TX_LPWR |
                      MII_TG3_AUXCTL_PCTL_SPR_ISOLATE |
index c89aa41dd44873f02fbea97c6af3f3cd6132dcbd..b4e0dc832c69509981a86a2728f1f5127532d974 100644 (file)
@@ -1070,7 +1070,7 @@ static void macb_configure_dma(struct macb *bp)
 static void macb_configure_caps(struct macb *bp)
 {
        if (macb_is_gem(bp)) {
-               if (GEM_BF(IRQCOR, gem_readl(bp, DCFG1)) == 0)
+               if (GEM_BFEXT(IRQCOR, gem_readl(bp, DCFG1)) == 0)
                        bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
        }
 }
index a0b4be51f0d1d09781a216d0ffe13ecc57805129..7371626c56a1462afba10760aa3b1a87c13671ec 100644 (file)
@@ -782,16 +782,22 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
 
        if (vlan_tx_tag_present(skb))
                vlan_tag = be_get_tx_vlan_tag(adapter, skb);
-       else if (qnq_async_evt_rcvd(adapter) && adapter->pvid)
-               vlan_tag = adapter->pvid;
+
+       if (qnq_async_evt_rcvd(adapter) && adapter->pvid) {
+               if (!vlan_tag)
+                       vlan_tag = adapter->pvid;
+               /* f/w workaround to set skip_hw_vlan = 1, informs the F/W to
+                * skip VLAN insertion
+                */
+               if (skip_hw_vlan)
+                       *skip_hw_vlan = true;
+       }
 
        if (vlan_tag) {
                skb = __vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
                if (unlikely(!skb))
                        return skb;
                skb->vlan_tci = 0;
-               if (skip_hw_vlan)
-                       *skip_hw_vlan = true;
        }
 
        /* Insert the outer VLAN, if any */
@@ -2555,8 +2561,8 @@ static int be_close(struct net_device *netdev)
        /* Wait for all pending tx completions to arrive so that
         * all tx skbs are freed.
         */
-       be_tx_compl_clean(adapter);
        netif_tx_disable(netdev);
+       be_tx_compl_clean(adapter);
 
        be_rx_qs_destroy(adapter);
 
index ac780770863dfb3a338f3dfe4550f5bd87d2e66e..7a77f37a7cbcbd6b7b5b87dd78e9e50b677e778c 100644 (file)
@@ -108,9 +108,8 @@ s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
 
        /* Enable arbiter */
        reg &= ~IXGBE_DPMCS_ARBDIS;
-       /* Enable DFP and Recycle mode */
-       reg |= (IXGBE_DPMCS_TDPAC | IXGBE_DPMCS_TRM);
        reg |= IXGBE_DPMCS_TSOEF;
+
        /* Configure Max TSO packet size 34KB including payload and headers */
        reg |= (0x4 << IXGBE_DPMCS_MTSOS_SHIFT);
 
index c96678555233c4afc1336c012c17c3b0da943060..254f255204f96c7d4662ca9a244d31f4dc05a324 100644 (file)
 #define      MVNETA_GMAC_FORCE_LINK_PASS         BIT(1)
 #define      MVNETA_GMAC_CONFIG_MII_SPEED        BIT(5)
 #define      MVNETA_GMAC_CONFIG_GMII_SPEED       BIT(6)
+#define      MVNETA_GMAC_AN_SPEED_EN             BIT(7)
 #define      MVNETA_GMAC_CONFIG_FULL_DUPLEX      BIT(12)
+#define      MVNETA_GMAC_AN_DUPLEX_EN            BIT(13)
 #define MVNETA_MIB_COUNTERS_BASE                 0x3080
 #define      MVNETA_MIB_LATE_COLLISION           0x7c
 #define MVNETA_DA_FILT_SPEC_MCAST                0x3400
@@ -911,6 +913,13 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
        /* Assign port SDMA configuration */
        mvreg_write(pp, MVNETA_SDMA_CONFIG, val);
 
+       /* Disable PHY polling in hardware, since we're using the
+        * kernel phylib to do this.
+        */
+       val = mvreg_read(pp, MVNETA_UNIT_CONTROL);
+       val &= ~MVNETA_PHY_POLLING_ENABLE;
+       mvreg_write(pp, MVNETA_UNIT_CONTROL, val);
+
        mvneta_set_ucast_table(pp, -1);
        mvneta_set_special_mcast_table(pp, -1);
        mvneta_set_other_mcast_table(pp, -1);
@@ -2288,7 +2297,9 @@ static void mvneta_adjust_link(struct net_device *ndev)
                        val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
                        val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED |
                                 MVNETA_GMAC_CONFIG_GMII_SPEED |
-                                MVNETA_GMAC_CONFIG_FULL_DUPLEX);
+                                MVNETA_GMAC_CONFIG_FULL_DUPLEX |
+                                MVNETA_GMAC_AN_SPEED_EN |
+                                MVNETA_GMAC_AN_DUPLEX_EN);
 
                        if (phydev->duplex)
                                val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX;
index 2c97901c6a6d2ff79231e294c5fd1d5622255263..593177d47711a3802f6166fb7b7eba021e42d938 100644 (file)
@@ -840,16 +840,7 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
                           MLX4_CMD_NATIVE);
 
        if (!err && dev->caps.function != slave) {
-               /* if config MAC in DB use it */
-               if (priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac)
-                       def_mac = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac;
-               else {
-                       /* set slave default_mac address */
-                       MLX4_GET(def_mac, outbox->buf, QUERY_PORT_MAC_OFFSET);
-                       def_mac += slave << 8;
-                       priv->mfunc.master.vf_admin[slave].vport[vhcr->in_modifier].mac = def_mac;
-               }
-
+               def_mac = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac;
                MLX4_PUT(outbox->buf, def_mac, QUERY_PORT_MAC_OFFSET);
 
                /* get port type - currently only eth is enabled */
index 8a434997a0df38a5266e40d7238b55956499458c..1b195fc7f4112c390ce28114132b329a9e2526ee 100644 (file)
@@ -371,7 +371,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 
        dev->caps.sqp_demux = (mlx4_is_master(dev)) ? MLX4_MAX_NUM_SLAVES : 0;
 
-       if (!enable_64b_cqe_eqe) {
+       if (!enable_64b_cqe_eqe && !mlx4_is_slave(dev)) {
                if (dev_cap->flags &
                    (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) {
                        mlx4_warn(dev, "64B EQEs/CQEs supported by the device but not enabled\n");
index 03523459c4061627d1fad51f751082298eec2147..9095ff930f2979168f3f716f220fa63661ebba3e 100644 (file)
@@ -478,7 +478,7 @@ rx_status_loop:
 
        while (1) {
                u32 status, len;
-               dma_addr_t mapping;
+               dma_addr_t mapping, new_mapping;
                struct sk_buff *skb, *new_skb;
                struct cp_desc *desc;
                const unsigned buflen = cp->rx_buf_sz;
@@ -520,6 +520,14 @@ rx_status_loop:
                        goto rx_next;
                }
 
+               new_mapping = dma_map_single(&cp->pdev->dev, new_skb->data, buflen,
+                                        PCI_DMA_FROMDEVICE);
+               if (dma_mapping_error(&cp->pdev->dev, new_mapping)) {
+                       dev->stats.rx_dropped++;
+                       kfree_skb(new_skb);
+                       goto rx_next;
+               }
+
                dma_unmap_single(&cp->pdev->dev, mapping,
                                 buflen, PCI_DMA_FROMDEVICE);
 
@@ -531,12 +539,11 @@ rx_status_loop:
 
                skb_put(skb, len);
 
-               mapping = dma_map_single(&cp->pdev->dev, new_skb->data, buflen,
-                                        PCI_DMA_FROMDEVICE);
                cp->rx_skb[rx_tail] = new_skb;
 
                cp_rx_skb(cp, skb, desc);
                rx++;
+               mapping = new_mapping;
 
 rx_next:
                cp->rx_ring[rx_tail].opts2 = 0;
@@ -716,6 +723,22 @@ static inline u32 cp_tx_vlan_tag(struct sk_buff *skb)
                TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
 }
 
+static void unwind_tx_frag_mapping(struct cp_private *cp, struct sk_buff *skb,
+                                  int first, int entry_last)
+{
+       int frag, index;
+       struct cp_desc *txd;
+       skb_frag_t *this_frag;
+       for (frag = 0; frag+first < entry_last; frag++) {
+               index = first+frag;
+               cp->tx_skb[index] = NULL;
+               txd = &cp->tx_ring[index];
+               this_frag = &skb_shinfo(skb)->frags[frag];
+               dma_unmap_single(&cp->pdev->dev, le64_to_cpu(txd->addr),
+                                skb_frag_size(this_frag), PCI_DMA_TODEVICE);
+       }
+}
+
 static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
                                        struct net_device *dev)
 {
@@ -749,6 +772,9 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 
                len = skb->len;
                mapping = dma_map_single(&cp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE);
+               if (dma_mapping_error(&cp->pdev->dev, mapping))
+                       goto out_dma_error;
+
                txd->opts2 = opts2;
                txd->addr = cpu_to_le64(mapping);
                wmb();
@@ -786,6 +812,9 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
                first_len = skb_headlen(skb);
                first_mapping = dma_map_single(&cp->pdev->dev, skb->data,
                                               first_len, PCI_DMA_TODEVICE);
+               if (dma_mapping_error(&cp->pdev->dev, first_mapping))
+                       goto out_dma_error;
+
                cp->tx_skb[entry] = skb;
                entry = NEXT_TX(entry);
 
@@ -799,6 +828,11 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
                        mapping = dma_map_single(&cp->pdev->dev,
                                                 skb_frag_address(this_frag),
                                                 len, PCI_DMA_TODEVICE);
+                       if (dma_mapping_error(&cp->pdev->dev, mapping)) {
+                               unwind_tx_frag_mapping(cp, skb, first_entry, entry);
+                               goto out_dma_error;
+                       }
+
                        eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
 
                        ctrl = eor | len | DescOwn;
@@ -859,11 +893,16 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
        if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
                netif_stop_queue(dev);
 
+out_unlock:
        spin_unlock_irqrestore(&cp->lock, intr_flags);
 
        cpw8(TxPoll, NormalTxPoll);
 
        return NETDEV_TX_OK;
+out_dma_error:
+       kfree_skb(skb);
+       cp->dev->stats.tx_dropped++;
+       goto out_unlock;
 }
 
 /* Set or clear the multicast filter for this adaptor.
@@ -1054,6 +1093,10 @@ static int cp_refill_rx(struct cp_private *cp)
 
                mapping = dma_map_single(&cp->pdev->dev, skb->data,
                                         cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
+               if (dma_mapping_error(&cp->pdev->dev, mapping)) {
+                       kfree_skb(skb);
+                       goto err_out;
+               }
                cp->rx_skb[i] = skb;
 
                cp->rx_ring[i].opts2 = 0;
index 2397f0e8d3ebf7e50c75e13cfeccc9b3c24237fa..a52046581a6c384db0dd6c12c6df8d10d0b26fae 100644 (file)
@@ -675,7 +675,7 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
                BUILD_BUG_ON(EFX_FILTER_INDEX_UC_DEF != 0);
                BUILD_BUG_ON(EFX_FILTER_INDEX_MC_DEF !=
                             EFX_FILTER_MC_DEF - EFX_FILTER_UC_DEF);
-               rep_index = spec->type - EFX_FILTER_INDEX_UC_DEF;
+               rep_index = spec->type - EFX_FILTER_UC_DEF;
                ins_index = rep_index;
 
                spin_lock_bh(&state->lock);
@@ -1196,7 +1196,9 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
        EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + 4 * ip->ihl + 4);
        ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
 
-       efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT, 0, rxq_index);
+       efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT,
+                          efx->rx_scatter ? EFX_FILTER_FLAG_RX_SCATTER : 0,
+                          rxq_index);
        rc = efx_filter_set_ipv4_full(&spec, ip->protocol,
                                      ip->daddr, ports[1], ip->saddr, ports[0]);
        if (rc)
index a7dfe36cabf4b7855291237c0ed5ec5caec28519..5173eaac5bca148351447fadd6f4f1a482657e51 100644 (file)
@@ -282,9 +282,9 @@ static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
 }
 
 /* Recycle the pages that are used by buffers that have just been received. */
-static void efx_recycle_rx_buffers(struct efx_channel *channel,
-                                  struct efx_rx_buffer *rx_buf,
-                                  unsigned int n_frags)
+static void efx_recycle_rx_pages(struct efx_channel *channel,
+                                struct efx_rx_buffer *rx_buf,
+                                unsigned int n_frags)
 {
        struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
 
@@ -294,6 +294,20 @@ static void efx_recycle_rx_buffers(struct efx_channel *channel,
        } while (--n_frags);
 }
 
+static void efx_discard_rx_packet(struct efx_channel *channel,
+                                 struct efx_rx_buffer *rx_buf,
+                                 unsigned int n_frags)
+{
+       struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
+
+       efx_recycle_rx_pages(channel, rx_buf, n_frags);
+
+       do {
+               efx_free_rx_buffer(rx_buf);
+               rx_buf = efx_rx_buf_next(rx_queue, rx_buf);
+       } while (--n_frags);
+}
+
 /**
  * efx_fast_push_rx_descriptors - push new RX descriptors quickly
  * @rx_queue:          RX descriptor queue
@@ -533,8 +547,7 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
         */
        if (unlikely(rx_buf->flags & EFX_RX_PKT_DISCARD)) {
                efx_rx_flush_packet(channel);
-               put_page(rx_buf->page);
-               efx_recycle_rx_buffers(channel, rx_buf, n_frags);
+               efx_discard_rx_packet(channel, rx_buf, n_frags);
                return;
        }
 
@@ -570,9 +583,9 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
                efx_sync_rx_buffer(efx, rx_buf, rx_buf->len);
        }
 
-       /* All fragments have been DMA-synced, so recycle buffers and pages. */
+       /* All fragments have been DMA-synced, so recycle pages. */
        rx_buf = efx_rx_buffer(rx_queue, index);
-       efx_recycle_rx_buffers(channel, rx_buf, n_frags);
+       efx_recycle_rx_pages(channel, rx_buf, n_frags);
 
        /* Pipeline receives so that we give time for packet headers to be
         * prefetched into cache.
index 1df0ff3839e8f44e4125588009d20a74d41773f3..3df56840a3b9282c7ab308682d448bba6dac53f4 100644 (file)
@@ -1239,6 +1239,8 @@ static int vnet_port_remove(struct vio_dev *vdev)
                dev_set_drvdata(&vdev->dev, NULL);
 
                kfree(port);
+
+               unregister_netdev(vp->dev);
        }
        return 0;
 }
index 4dccead586bee57a076be015478809ea82e7157e..23a0fff0df52eaf6cc3a9992e9ec45350a1c9084 100644 (file)
@@ -431,8 +431,8 @@ static int netvsc_probe(struct hv_device *dev,
        net->netdev_ops = &device_ops;
 
        /* TODO: Add GSO and Checksum offload */
-       net->hw_features = NETIF_F_SG;
-       net->features = NETIF_F_SG | NETIF_F_HW_VLAN_CTAG_TX;
+       net->hw_features = 0;
+       net->features = NETIF_F_HW_VLAN_CTAG_TX;
 
        SET_ETHTOOL_OPS(net, &ethtool_ops);
        SET_NETDEV_DEV(net, &dev->device);
index dc9f6a45515dacaa76fabb419ed82daa89d9a3d3..a3bed28197d29bf9722b6c586f311827d357b501 100644 (file)
@@ -291,11 +291,17 @@ static int __init ifb_init_module(void)
 
        rtnl_lock();
        err = __rtnl_link_register(&ifb_link_ops);
+       if (err < 0)
+               goto out;
 
-       for (i = 0; i < numifbs && !err; i++)
+       for (i = 0; i < numifbs && !err; i++) {
                err = ifb_init_one(i);
+               cond_resched();
+       }
        if (err)
                __rtnl_link_unregister(&ifb_link_ops);
+
+out:
        rtnl_unlock();
 
        return err;
index 6e91931a1c2ca914dfe0049db288189467e9c674..06eba6e480c97a7b37476ba45d129f3e43d91057 100644 (file)
@@ -727,6 +727,10 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
                        return -EADDRNOTAVAIL;
        }
 
+       if (data && data[IFLA_MACVLAN_FLAGS] &&
+           nla_get_u16(data[IFLA_MACVLAN_FLAGS]) & ~MACVLAN_FLAG_NOPROMISC)
+               return -EINVAL;
+
        if (data && data[IFLA_MACVLAN_MODE]) {
                switch (nla_get_u32(data[IFLA_MACVLAN_MODE])) {
                case MACVLAN_MODE_PRIVATE:
index b6dd6a75919a69216964b2743ff14c60de460e20..523d6b2426a80037f7312d5c491d4fa760f2ce69 100644 (file)
@@ -633,6 +633,28 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
        return 0;
 }
 
+static unsigned long iov_pages(const struct iovec *iv, int offset,
+                              unsigned long nr_segs)
+{
+       unsigned long seg, base;
+       int pages = 0, len, size;
+
+       while (nr_segs && (offset >= iv->iov_len)) {
+               offset -= iv->iov_len;
+               ++iv;
+               --nr_segs;
+       }
+
+       for (seg = 0; seg < nr_segs; seg++) {
+               base = (unsigned long)iv[seg].iov_base + offset;
+               len = iv[seg].iov_len - offset;
+               size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
+               pages += size;
+               offset = 0;
+       }
+
+       return pages;
+}
 
 /* Get packet from user space buffer */
 static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
@@ -647,6 +669,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
        int vnet_hdr_len = 0;
        int copylen = 0;
        bool zerocopy = false;
+       size_t linear;
 
        if (q->flags & IFF_VNET_HDR) {
                vnet_hdr_len = q->vnet_hdr_sz;
@@ -678,42 +701,35 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
        if (unlikely(count > UIO_MAXIOV))
                goto err;
 
-       if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY))
-               zerocopy = true;
+       if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) {
+               copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN;
+               linear = copylen;
+               if (iov_pages(iv, vnet_hdr_len + copylen, count)
+                   <= MAX_SKB_FRAGS)
+                       zerocopy = true;
+       }
 
-       if (zerocopy) {
-               /* Userspace may produce vectors with count greater than
-                * MAX_SKB_FRAGS, so we need to linearize parts of the skb
-                * to let the rest of data to be fit in the frags.
-                */
-               if (count > MAX_SKB_FRAGS) {
-                       copylen = iov_length(iv, count - MAX_SKB_FRAGS);
-                       if (copylen < vnet_hdr_len)
-                               copylen = 0;
-                       else
-                               copylen -= vnet_hdr_len;
-               }
-               /* There are 256 bytes to be copied in skb, so there is enough
-                * room for skb expand head in case it is used.
-                * The rest buffer is mapped from userspace.
-                */
-               if (copylen < vnet_hdr.hdr_len)
-                       copylen = vnet_hdr.hdr_len;
-               if (!copylen)
-                       copylen = GOODCOPY_LEN;
-       } else
+       if (!zerocopy) {
                copylen = len;
+               linear = vnet_hdr.hdr_len;
+       }
 
        skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen,
-                               vnet_hdr.hdr_len, noblock, &err);
+                               linear, noblock, &err);
        if (!skb)
                goto err;
 
        if (zerocopy)
                err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count);
-       else
+       else {
                err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len,
                                                   len);
+               if (!err && m && m->msg_control) {
+                       struct ubuf_info *uarg = m->msg_control;
+                       uarg->callback(uarg, false);
+               }
+       }
+
        if (err)
                goto err_kfree;
 
index 9c61f8734a40c09e950505184e39232ead9fa938..7b54f4f052d085a106dba118ad6c4d1c6e41eacb 100644 (file)
@@ -1037,6 +1037,29 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
        return 0;
 }
 
+static unsigned long iov_pages(const struct iovec *iv, int offset,
+                              unsigned long nr_segs)
+{
+       unsigned long seg, base;
+       int pages = 0, len, size;
+
+       while (nr_segs && (offset >= iv->iov_len)) {
+               offset -= iv->iov_len;
+               ++iv;
+               --nr_segs;
+       }
+
+       for (seg = 0; seg < nr_segs; seg++) {
+               base = (unsigned long)iv[seg].iov_base + offset;
+               len = iv[seg].iov_len - offset;
+               size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
+               pages += size;
+               offset = 0;
+       }
+
+       return pages;
+}
+
 /* Get packet from user space buffer */
 static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
                            void *msg_control, const struct iovec *iv,
@@ -1044,7 +1067,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
 {
        struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) };
        struct sk_buff *skb;
-       size_t len = total_len, align = NET_SKB_PAD;
+       size_t len = total_len, align = NET_SKB_PAD, linear;
        struct virtio_net_hdr gso = { 0 };
        int offset = 0;
        int copylen;
@@ -1053,8 +1076,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
        u32 rxhash;
 
        if (!(tun->flags & TUN_NO_PI)) {
-               if ((len -= sizeof(pi)) > total_len)
+               if (len < sizeof(pi))
                        return -EINVAL;
+               len -= sizeof(pi);
 
                if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi)))
                        return -EFAULT;
@@ -1062,8 +1086,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
        }
 
        if (tun->flags & TUN_VNET_HDR) {
-               if ((len -= tun->vnet_hdr_sz) > total_len)
+               if (len < tun->vnet_hdr_sz)
                        return -EINVAL;
+               len -= tun->vnet_hdr_sz;
 
                if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso)))
                        return -EFAULT;
@@ -1084,34 +1109,23 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
                        return -EINVAL;
        }
 
-       if (msg_control)
-               zerocopy = true;
-
-       if (zerocopy) {
-               /* Userspace may produce vectors with count greater than
-                * MAX_SKB_FRAGS, so we need to linearize parts of the skb
-                * to let the rest of data to be fit in the frags.
-                */
-               if (count > MAX_SKB_FRAGS) {
-                       copylen = iov_length(iv, count - MAX_SKB_FRAGS);
-                       if (copylen < offset)
-                               copylen = 0;
-                       else
-                               copylen -= offset;
-               } else
-                               copylen = 0;
-               /* There are 256 bytes to be copied in skb, so there is enough
-                * room for skb expand head in case it is used.
+       if (msg_control) {
+               /* There are 256 bytes to be copied in skb, so there is
+                * enough room for skb expand head in case it is used.
                 * The rest of the buffer is mapped from userspace.
                 */
-               if (copylen < gso.hdr_len)
-                       copylen = gso.hdr_len;
-               if (!copylen)
-                       copylen = GOODCOPY_LEN;
-       } else
+               copylen = gso.hdr_len ? gso.hdr_len : GOODCOPY_LEN;
+               linear = copylen;
+               if (iov_pages(iv, offset + copylen, count) <= MAX_SKB_FRAGS)
+                       zerocopy = true;
+       }
+
+       if (!zerocopy) {
                copylen = len;
+               linear = gso.hdr_len;
+       }
 
-       skb = tun_alloc_skb(tfile, align, copylen, gso.hdr_len, noblock);
+       skb = tun_alloc_skb(tfile, align, copylen, linear, noblock);
        if (IS_ERR(skb)) {
                if (PTR_ERR(skb) != -EAGAIN)
                        tun->dev->stats.rx_dropped++;
@@ -1120,8 +1134,13 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
 
        if (zerocopy)
                err = zerocopy_sg_from_iovec(skb, iv, offset, count);
-       else
+       else {
                err = skb_copy_datagram_from_iovec(skb, 0, iv, offset, len);
+               if (!err && msg_control) {
+                       struct ubuf_info *uarg = msg_control;
+                       uarg->callback(uarg, false);
+               }
+       }
 
        if (err) {
                tun->dev->stats.rx_dropped++;
index bd8758fa38c140cf93dd3c8b623a3d9b61a279fe..cea1f3d0311b12bdbfb18d2011a774c9e7e200ab 100644 (file)
@@ -1029,10 +1029,10 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
        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;
+                             NETIF_F_RXCSUM;
 
        dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-                                NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO;
+                                NETIF_F_RXCSUM;
 
        /* Enable checksum offload */
        *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP |
@@ -1173,7 +1173,6 @@ ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
        if (((skb->len + 8) % frame_size) == 0)
                tx_hdr2 |= 0x80008000;  /* Enable padding */
 
-       skb_linearize(skb);
        headroom = skb_headroom(skb);
        tailroom = skb_tailroom(skb);
 
@@ -1317,10 +1316,10 @@ static int ax88179_reset(struct usbnet *dev)
                          1, 1, tmp);
 
        dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-                             NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO;
+                             NETIF_F_RXCSUM;
 
        dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-                                NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO;
+                                NETIF_F_RXCSUM;
 
        /* Enable checksum offload */
        *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP |
index 872819851aef814f23d850a126e6ccd9ea1f5db4..25ba7eca9a13bdaa7950627111b2eab88a292447 100644 (file)
@@ -400,6 +400,10 @@ static const struct usb_device_id mbim_devs[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68a2, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
          .driver_info = (unsigned long)&cdc_mbim_info_zlp,
        },
+       /* HP hs2434 Mobile Broadband Module needs ZLPs */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x3f0, 0x4b1d, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+         .driver_info = (unsigned long)&cdc_mbim_info_zlp,
+       },
        { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
          .driver_info = (unsigned long)&cdc_mbim_info,
        },
index 75409748c77470da8cc5bcc7390e9f4c5a94ea6a..66ebbacf066f6692ba21d2fa07538535827074b9 100644 (file)
@@ -45,7 +45,6 @@
 #define EEPROM_MAC_OFFSET              (0x01)
 #define DEFAULT_TX_CSUM_ENABLE         (true)
 #define DEFAULT_RX_CSUM_ENABLE         (true)
-#define DEFAULT_TSO_ENABLE             (true)
 #define SMSC75XX_INTERNAL_PHY_ID       (1)
 #define SMSC75XX_TX_OVERHEAD           (8)
 #define MAX_RX_FIFO_SIZE               (20 * 1024)
@@ -1410,17 +1409,14 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
 
        INIT_WORK(&pdata->set_multicast, smsc75xx_deferred_multicast_write);
 
-       if (DEFAULT_TX_CSUM_ENABLE) {
+       if (DEFAULT_TX_CSUM_ENABLE)
                dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-               if (DEFAULT_TSO_ENABLE)
-                       dev->net->features |= NETIF_F_SG |
-                               NETIF_F_TSO | NETIF_F_TSO6;
-       }
+
        if (DEFAULT_RX_CSUM_ENABLE)
                dev->net->features |= NETIF_F_RXCSUM;
 
        dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-               NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_RXCSUM;
+                               NETIF_F_RXCSUM;
 
        ret = smsc75xx_wait_ready(dev, 0);
        if (ret < 0) {
@@ -2200,8 +2196,6 @@ static struct sk_buff *smsc75xx_tx_fixup(struct usbnet *dev,
 {
        u32 tx_cmd_a, tx_cmd_b;
 
-       skb_linearize(skb);
-
        if (skb_headroom(skb) < SMSC75XX_TX_OVERHEAD) {
                struct sk_buff *skb2 =
                        skb_copy_expand(skb, SMSC75XX_TX_OVERHEAD, 0, flags);
index c9e00387d9996e3c5b0660a57bf296e4ff15f3d5..42d670a468f89462a4e31ebde531c6a0e9c3b644 100644 (file)
@@ -602,7 +602,7 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
                container_of(napi, struct receive_queue, napi);
        struct virtnet_info *vi = rq->vq->vdev->priv;
        void *buf;
-       unsigned int len, received = 0;
+       unsigned int r, len, received = 0;
 
 again:
        while (received < budget &&
@@ -619,8 +619,9 @@ again:
 
        /* Out of packets? */
        if (received < budget) {
+               r = virtqueue_enable_cb_prepare(rq->vq);
                napi_complete(napi);
-               if (unlikely(!virtqueue_enable_cb(rq->vq)) &&
+               if (unlikely(virtqueue_poll(rq->vq, r)) &&
                    napi_schedule_prep(napi)) {
                        virtqueue_disable_cb(rq->vq);
                        __napi_schedule(napi);
index 57325f356d4f125421bfa297a4beb2302c5f194b..054489fdf54a2e04bf9cc8d447b6b7af07a29de7 100644 (file)
@@ -1090,7 +1090,7 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
        iph->daddr      = dst;
        iph->saddr      = fl4.saddr;
        iph->ttl        = ttl ? : ip4_dst_hoplimit(&rt->dst);
-       tunnel_ip_select_ident(skb, old_iph, &rt->dst);
+       __ip_select_ident(iph, &rt->dst, (skb_shinfo(skb)->gso_segs ?: 1) - 1);
 
        nf_reset(skb);
 
index e6b92ff265fd6e878274a2d0b35660a5bfa9a1c5..25b8bbbe74fe347f6f0f17fcc129ebd100f88301 100644 (file)
@@ -3563,14 +3563,18 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
 {
        struct ath9k_hw_capabilities *pCap = &ah->caps;
        int chain;
-       u32 regval;
+       u32 regval, value;
        static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = {
                        AR_PHY_SWITCH_CHAIN_0,
                        AR_PHY_SWITCH_CHAIN_1,
                        AR_PHY_SWITCH_CHAIN_2,
        };
 
-       u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
+       if (AR_SREV_9485(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0))
+               ath9k_hw_cfg_output(ah, AR9300_EXT_LNA_CTL_GPIO_AR9485,
+                                   AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED);
+
+       value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
 
        if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
                REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
index e1714d7c9eeb50d0c546a9ea01ad213a8bd51215..3457ca5382f4aa2b7e18ca81d9d072e1244b735d 100644 (file)
@@ -1076,6 +1076,10 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
                 * is_on == 0 means MRC CCK is OFF (more noise imm)
                 */
                bool is_on = param ? 1 : 0;
+
+               if (ah->caps.rx_chainmask == 1)
+                       break;
+
                REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
                              AR_PHY_MRC_CCK_ENABLE, is_on);
                REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
index e71774196c01bbf7fa6f3a33b1789556fc63ae9a..5013c731f9f6de2bb79a9a4d86f4fd0323ef7a88 100644 (file)
 
 #define AR_PHY_CCA_NOM_VAL_9330_2GHZ          -118
 
+#define AR9300_EXT_LNA_CTL_GPIO_AR9485 9
+
 /*
  * AGC Field Definitions
  */
index 42b03dc39d1423561dff8fb08f95be67f54ea5bb..4ebd9fd8a0a47a78425f69f37c53938923528782 100644 (file)
@@ -79,10 +79,6 @@ struct ath_config {
                       sizeof(struct ath_buf_state));           \
        } while (0)
 
-#define ATH_RXBUF_RESET(_bf) do {              \
-               (_bf)->bf_stale = false;        \
-       } while (0)
-
 /**
  * enum buffer_type - Buffer type flags
  *
@@ -316,6 +312,7 @@ struct ath_rx {
        struct ath_descdma rxdma;
        struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
 
+       struct ath_buf *buf_hold;
        struct sk_buff *frag;
 
        u32 ampdu_ref;
index 7304e7585009c03ec1faeaa7d013e5ded4eea5d3..5e8219a91e252b3d4a9ac2f5fda599caf4ae9ae8 100644 (file)
@@ -387,7 +387,6 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
 
        if (!caldata) {
                chan->noisefloor = nf;
-               ah->noise = ath9k_hw_getchan_noise(ah, chan);
                return false;
        }
 
index f5dda84176c3d4ae8277c069df06fa3bbc11922d..75a6376ed2897caa567934712af9f23e2e4a6c55 100644 (file)
@@ -1289,7 +1289,9 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
 
        usb_set_intfdata(interface, NULL);
 
-       if (!unplugged && (hif_dev->flags & HIF_USB_START))
+       /* If firmware was loaded we should drop it
+        * go back to first stage bootloader. */
+       if (!unplugged && (hif_dev->flags & HIF_USB_READY))
                ath9k_hif_usb_reboot(udev);
 
        kfree(hif_dev);
index a47f5e05fc04835d6b747b8ba4553c91d6614178..3b202ffb3257109dce3ed2ae7eb42275ada8878e 100644 (file)
@@ -846,6 +846,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
        if (error != 0)
                goto err_rx;
 
+       ath9k_hw_disable(priv->ah);
 #ifdef CONFIG_MAC80211_LEDS
        /* must be initialized before ieee80211_register_hw */
        priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw,
index 6bd0e92ea2aaee7144aaa4c74fae7a8ff43a42c0..417a089cd7e1056adc01834d1dff8a4255a4b4ee 100644 (file)
@@ -448,6 +448,7 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv,
        struct ieee80211_conf *cur_conf = &priv->hw->conf;
        bool txok;
        int slot;
+       int hdrlen, padsize;
 
        slot = strip_drv_header(priv, skb);
        if (slot < 0) {
@@ -504,6 +505,15 @@ send_mac80211:
 
        ath9k_htc_tx_clear_slot(priv, slot);
 
+       /* Remove padding before handing frame back to mac80211 */
+       hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+
+       padsize = hdrlen & 3;
+       if (padsize && skb->len > hdrlen + padsize) {
+               memmove(skb->data + padsize, skb->data, hdrlen);
+               skb_pull(skb, padsize);
+       }
+
        /* Send status to mac80211 */
        ieee80211_tx_status(priv->hw, skb);
 }
index 15dfefcf2d0fca7ef80f3eb64752c47c0bea5d45..b1d5037bff7fc0ac804d0cdc08647940d249b789 100644 (file)
@@ -1872,7 +1872,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
        ah->caldata = caldata;
        if (caldata && (chan->channel != caldata->channel ||
-                       chan->channelFlags != caldata->channelFlags)) {
+                       chan->channelFlags != caldata->channelFlags ||
+                       chan->chanmode != caldata->chanmode)) {
                /* Operating channel changed, reset channel calibration data */
                memset(caldata, 0, sizeof(*caldata));
                ath9k_init_nfcal_hist_buffer(ah, chan);
index 2ba494567777f35ea359a1beb883ecb0be471a74..bd126c25a727cb3b8192150c483117ad0a0dc31b 100644 (file)
@@ -767,7 +767,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
                IEEE80211_HW_PS_NULLFUNC_STACK |
                IEEE80211_HW_SPECTRUM_MGMT |
                IEEE80211_HW_REPORTS_TX_ACK_STATUS |
-               IEEE80211_HW_SUPPORTS_RC_TABLE;
+               IEEE80211_HW_SUPPORTS_RC_TABLE |
+               IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
 
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
                 hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
index 5092ecae7706ab7140bcf7d3f88f830be176cc38..e33a659e224b6049fab4c6936fd225963766cfef 100644 (file)
@@ -173,8 +173,7 @@ static void ath_restart_work(struct ath_softc *sc)
 {
        ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
 
-       if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9485(sc->sc_ah) ||
-           AR_SREV_9550(sc->sc_ah))
+       if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9330(sc->sc_ah))
                ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
                                     msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
 
@@ -1211,13 +1210,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
                ath_update_survey_stats(sc);
                spin_unlock_irqrestore(&common->cc_lock, flags);
 
-               /*
-                * Preserve the current channel values, before updating
-                * the same channel
-                */
-               if (ah->curchan && (old_pos == pos))
-                       ath9k_hw_getnf(ah, ah->curchan);
-
                ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
                                          curchan, channel_type);
 
index 8be2b5d8c155c91c0daafca2e7caa634a89f19e5..f53dbd1133ce51ecae9319e42082e1049970a882 100644 (file)
@@ -42,8 +42,6 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
        struct ath_desc *ds;
        struct sk_buff *skb;
 
-       ATH_RXBUF_RESET(bf);
-
        ds = bf->bf_desc;
        ds->ds_link = 0; /* link to null */
        ds->ds_data = bf->bf_buf_addr;
@@ -70,6 +68,14 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
        sc->rx.rxlink = &ds->ds_link;
 }
 
+static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_buf *bf)
+{
+       if (sc->rx.buf_hold)
+               ath_rx_buf_link(sc, sc->rx.buf_hold);
+
+       sc->rx.buf_hold = bf;
+}
+
 static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
 {
        /* XXX block beacon interrupts */
@@ -117,7 +123,6 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc,
 
        skb = bf->bf_mpdu;
 
-       ATH_RXBUF_RESET(bf);
        memset(skb->data, 0, ah->caps.rx_status_len);
        dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
                                ah->caps.rx_status_len, DMA_TO_DEVICE);
@@ -432,6 +437,7 @@ int ath_startrecv(struct ath_softc *sc)
        if (list_empty(&sc->rx.rxbuf))
                goto start_recv;
 
+       sc->rx.buf_hold = NULL;
        sc->rx.rxlink = NULL;
        list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
                ath_rx_buf_link(sc, bf);
@@ -677,6 +683,9 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
        }
 
        bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
+       if (bf == sc->rx.buf_hold)
+               return NULL;
+
        ds = bf->bf_desc;
 
        /*
@@ -1378,7 +1387,7 @@ requeue:
                if (edma) {
                        ath_rx_edma_buf_link(sc, qtype);
                } else {
-                       ath_rx_buf_link(sc, bf);
+                       ath_rx_buf_relink(sc, bf);
                        ath9k_hw_rxena(ah);
                }
        } while (1);
index 83ab6be3fe6d502178b3253943bdd0097f4f8cbe..e752f5d4995d49c9053a4c9a4a07183adb86e084 100644 (file)
@@ -2387,6 +2387,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
        for (acno = 0, ac = &an->ac[acno];
             acno < IEEE80211_NUM_ACS; acno++, ac++) {
                ac->sched    = false;
+               ac->clear_ps_filter = true;
                ac->txq = sc->tx.txq_map[acno];
                INIT_LIST_HEAD(&ac->tid_q);
        }
index e9010a481dfdf475d61f567bb0f5f11f2e44dded..0686375a97b9ee319219dd09ad6b5ed77f321b68 100644 (file)
@@ -1857,7 +1857,8 @@ void *carl9170_alloc(size_t priv_size)
                     IEEE80211_HW_SUPPORTS_PS |
                     IEEE80211_HW_PS_NULLFUNC_STACK |
                     IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC |
-                    IEEE80211_HW_SIGNAL_DBM;
+                    IEEE80211_HW_SIGNAL_DBM |
+                    IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
 
        if (!modparam_noht) {
                /*
index 727b1f53e6adac700cc744b5450ffc49979cb6f4..d57e5be32ee020a1bfbbf4c0868e83311ffbbf9d 100644 (file)
@@ -145,7 +145,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix,
                                   le16_to_cpu(hdr.type), hdr.flags);
                        if (len <= MAX_MBOXITEM_SIZE) {
                                int n = 0;
-                               unsigned char printbuf[16 * 3 + 2];
+                               char printbuf[16 * 3 + 2];
                                unsigned char databuf[MAX_MBOXITEM_SIZE];
                                void __iomem *src = wmi_buffer(wil, d.addr) +
                                        sizeof(struct wil6210_mbox_hdr);
@@ -416,7 +416,7 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data)
                seq_printf(s, "  SKB = %p\n", skb);
 
                if (skb) {
-                       unsigned char printbuf[16 * 3 + 2];
+                       char printbuf[16 * 3 + 2];
                        int i = 0;
                        int len = skb_headlen(skb);
                        void *p = skb->data;
index 078e6f3477a9dfb3aa9a1fd67c7cb0fd4c8fa8cb..13f91ac9499e66673176b1fe72101f61d3d0fce2 100644 (file)
@@ -28,7 +28,7 @@ config B43
 
 config B43_BCMA
        bool "Support for BCMA bus"
-       depends on B43 && BCMA
+       depends on B43 && (BCMA = y || BCMA = B43)
        default y
 
 config B43_BCMA_EXTRA
@@ -39,7 +39,7 @@ config B43_BCMA_EXTRA
 
 config B43_SSB
        bool
-       depends on B43 && SSB
+       depends on B43 && (SSB = y || SSB = B43)
        default y
 
 # Auto-select SSB PCI-HOST support, if possible
index 1860c572b3c476a88527418725848a62f7f9e45a..4fb9635d3919d29a5c927d55086946d1afe18269 100644 (file)
@@ -1015,9 +1015,10 @@ static bool dma64_txidle(struct dma_info *di)
 
 /*
  * post receive buffers
- *  return false is refill failed completely and ring is empty this will stall
- *  the rx dma and user might want to call rxfill again asap. This unlikely
- *  happens on memory-rich NIC, but often on memory-constrained dongle
+ *  Return false if refill failed completely or dma mapping failed. The ring
+ *  is empty, which will stall the rx dma and user might want to call rxfill
+ *  again asap. This is unlikely to happen on a memory-rich NIC, but often on
+ *  memory-constrained dongle.
  */
 bool dma_rxfill(struct dma_pub *pub)
 {
@@ -1078,6 +1079,8 @@ bool dma_rxfill(struct dma_pub *pub)
 
                pa = dma_map_single(di->dmadev, p->data, di->rxbufsize,
                                    DMA_FROM_DEVICE);
+               if (dma_mapping_error(di->dmadev, pa))
+                       return false;
 
                /* save the free packet pointer */
                di->rxp[rxout] = p;
@@ -1284,7 +1287,11 @@ static void dma_txenq(struct dma_info *di, struct sk_buff *p)
 
        /* get physical address of buffer start */
        pa = dma_map_single(di->dmadev, data, len, DMA_TO_DEVICE);
-
+       /* if mapping failed, free skb */
+       if (dma_mapping_error(di->dmadev, pa)) {
+               brcmu_pkt_buf_free_skb(p);
+               return;
+       }
        /* With a DMA segment list, Descriptor table is filled
         * using the segment list instead of looping over
         * buffers in multi-chain DMA. Therefore, EOF for SGLIST
index ac074731335a5ed1b7ef393dfd15ae6c87299d03..e5090309824e53c04d1961c0fd6993e80c5aa61e 100644 (file)
@@ -523,9 +523,9 @@ static int prism2_ioctl_giwaplist(struct net_device *dev,
 
        data->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_AP, 1);
 
-       memcpy(extra, &addr, sizeof(struct sockaddr) * data->length);
+       memcpy(extra, addr, sizeof(struct sockaddr) * data->length);
        data->flags = 1; /* has quality information */
-       memcpy(extra + sizeof(struct sockaddr) * data->length, &qual,
+       memcpy(extra + sizeof(struct sockaddr) * data->length, qual,
               sizeof(struct iw_quality) * data->length);
 
        kfree(addr);
index 9a95045c97b6b4fe6041f457a1999ecfb7926d12..a8eff95ee677bdabcc978b6277b2e23f00e74c0d 100644 (file)
@@ -4442,13 +4442,13 @@ il4965_irq_tasklet(struct il_priv *il)
                 * is killed. Hence update the killswitch state here. The
                 * rfkill handler will care about restarting if needed.
                 */
-               if (!test_bit(S_ALIVE, &il->status)) {
-                       if (hw_rf_kill)
-                               set_bit(S_RFKILL, &il->status);
-                       else
-                               clear_bit(S_RFKILL, &il->status);
-                       wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill);
+               if (hw_rf_kill) {
+                       set_bit(S_RFKILL, &il->status);
+               } else {
+                       clear_bit(S_RFKILL, &il->status);
+                       il_force_reset(il, true);
                }
+               wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill);
 
                handled |= CSR_INT_BIT_RF_KILL;
        }
@@ -5316,6 +5316,9 @@ il4965_alive_start(struct il_priv *il)
 
        il->active_rate = RATES_MASK;
 
+       il_power_update_mode(il, true);
+       D_INFO("Updated power mode\n");
+
        if (il_is_associated(il)) {
                struct il_rxon_cmd *active_rxon =
                    (struct il_rxon_cmd *)&il->active;
@@ -5346,9 +5349,6 @@ il4965_alive_start(struct il_priv *il)
        D_INFO("ALIVE processing complete.\n");
        wake_up(&il->wait_command_queue);
 
-       il_power_update_mode(il, true);
-       D_INFO("Updated power mode\n");
-
        return;
 
 restart:
index e9a3cbc409ae1d239fb7ff9c4a43436e9994f26d..9c9ebadc22e20d312f590e4acb39547416cd2371 100644 (file)
@@ -4660,6 +4660,7 @@ il_force_reset(struct il_priv *il, bool external)
 
        return 0;
 }
+EXPORT_SYMBOL(il_force_reset);
 
 int
 il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
index cab23af0be9e604051e0c2a5d4b8b0a87073a7ca..e04f3da1ccb32655b1582bc39339f259e5892702 100644 (file)
@@ -1059,7 +1059,10 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+       if (!test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+               return;
+
+       if (ctx->vif)
                ieee80211_chswitch_done(ctx->vif, is_success);
 }
 
index 74d7572e709125160f0a0db02b8e337d23d96cc5..a8afc7bee545a7f429192aa18d846a6994adc6e6 100644 (file)
@@ -758,7 +758,7 @@ int iwl_alive_start(struct iwl_priv *priv)
                                         BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
                if (ret)
                        return ret;
-       } else {
+       } else if (priv->cfg->bt_params) {
                /*
                 * default is 2-wire BT coexexistence support
                 */
index 50263e87fe156509d4e1c0328cb12f5bdec993a8..dc94d44d95cd0904ad9da862d3aae6d6f8238976 100644 (file)
 #include "iwl-agn-hw.h"
 
 /* Highest firmware API version supported */
-#define IWL7260_UCODE_API_MAX  6
-#define IWL3160_UCODE_API_MAX  6
+#define IWL7260_UCODE_API_MAX  7
+#define IWL3160_UCODE_API_MAX  7
 
 /* Oldest version we won't warn about */
-#define IWL7260_UCODE_API_OK   6
-#define IWL3160_UCODE_API_OK   6
+#define IWL7260_UCODE_API_OK   7
+#define IWL3160_UCODE_API_OK   7
 
 /* Lowest firmware API version supported */
-#define IWL7260_UCODE_API_MIN  6
-#define IWL3160_UCODE_API_MIN  6
+#define IWL7260_UCODE_API_MIN  7
+#define IWL3160_UCODE_API_MIN  7
 
 /* NVM versions */
 #define IWL7260_NVM_VERSION            0x0a1d
index 51e015d1dfb297cfeb6169afcc2db2ae57dc6a8d..6f8b2c16ae171965253c0d7e0e149ab3ff0d52f6 100644 (file)
@@ -75,13 +75,15 @@ enum iwl_d3_wakeup_flags {
  * struct iwl_d3_manager_config - D3 manager configuration command
  * @min_sleep_time: minimum sleep time (in usec)
  * @wakeup_flags: wakeup flags, see &enum iwl_d3_wakeup_flags
+ * @wakeup_host_timer: force wakeup after this many seconds
  *
  * The structure is used for the D3_CONFIG_CMD command.
  */
 struct iwl_d3_manager_config {
        __le32 min_sleep_time;
        __le32 wakeup_flags;
-} __packed; /* D3_MANAGER_CONFIG_CMD_S_VER_3 */
+       __le32 wakeup_host_timer;
+} __packed; /* D3_MANAGER_CONFIG_CMD_S_VER_4 */
 
 
 /* TODO: OFFLOADS_QUERY_API_S_VER_1 */
index d68640ea41d42e3ea0612d1fa562de1b00ba50e6..98b1feb43d388f70bc4aadf0f4434cc714744d05 100644 (file)
 #define MAC_INDEX_MIN_DRIVER   0
 #define NUM_MAC_INDEX_DRIVER   MAC_INDEX_AUX
 
-#define AC_NUM 4 /* Number of access categories */
+enum iwl_ac {
+       AC_BK,
+       AC_BE,
+       AC_VI,
+       AC_VO,
+       AC_NUM,
+};
 
 /**
  * enum iwl_mac_protection_flags - MAC context flags
index b60d14151721da3cb141b9b74ac0e3aee2d43a92..365095a0c3b3101e3c87b76036dbd82b352b9deb 100644 (file)
@@ -69,7 +69,6 @@
 /* Scan Commands, Responses, Notifications */
 
 /* Masks for iwl_scan_channel.type flags */
-#define SCAN_CHANNEL_TYPE_PASSIVE      0
 #define SCAN_CHANNEL_TYPE_ACTIVE       BIT(0)
 #define SCAN_CHANNEL_NARROW_BAND       BIT(22)
 
index b2cc3d98e0f7aa2e89b744b17cd706ed20268cc6..d8e858cc8dd9a71338863f1288264cc755e8536b 100644 (file)
@@ -193,14 +193,11 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
 u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
                                struct ieee80211_vif *vif)
 {
-       u32 qmask, ac;
+       u32 qmask = 0, ac;
 
        if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
                return BIT(IWL_MVM_OFFCHANNEL_QUEUE);
 
-       qmask = (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) ?
-               BIT(vif->cab_queue) : 0;
-
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
                if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
                        qmask |= BIT(vif->hw_queue[ac]);
@@ -362,7 +359,7 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
                break;
        case NL80211_IFTYPE_AP:
                iwl_trans_ac_txq_enable(mvm->trans, vif->cab_queue,
-                                       IWL_MVM_TX_FIFO_VO);
+                                       IWL_MVM_TX_FIFO_MCAST);
                /* fall through */
        default:
                for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
@@ -550,6 +547,10 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
                cmd->ac[i].fifos_mask = BIT(iwl_mvm_ac_to_tx_fifo[i]);
        }
 
+       /* in AP mode, the MCAST FIFO takes the EDCA params from VO */
+       if (vif->type == NL80211_IFTYPE_AP)
+               cmd->ac[AC_VO].fifos_mask |= BIT(IWL_MVM_TX_FIFO_MCAST);
+
        if (vif->bss_conf.qos)
                cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
 
index a5eb8c82f16a806fea43738629e738cdeaaba0b6..f7545e06ce2ac041cc9bc50192113c9f22f42d7d 100644 (file)
@@ -243,7 +243,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
        if (ret)
                return ret;
 
-       return ieee80211_register_hw(mvm->hw);
+       ret = ieee80211_register_hw(mvm->hw);
+       if (ret)
+               iwl_mvm_leds_exit(mvm);
+
+       return ret;
 }
 
 static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
@@ -987,6 +991,21 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
        mutex_lock(&mvm->mutex);
        if (old_state == IEEE80211_STA_NOTEXIST &&
            new_state == IEEE80211_STA_NONE) {
+               /*
+                * Firmware bug - it'll crash if the beacon interval is less
+                * than 16. We can't avoid connecting at all, so refuse the
+                * station state change, this will cause mac80211 to abandon
+                * attempts to connect to this AP, and eventually wpa_s will
+                * blacklist the AP...
+                */
+               if (vif->type == NL80211_IFTYPE_STATION &&
+                   vif->bss_conf.beacon_int < 16) {
+                       IWL_ERR(mvm,
+                               "AP %pM beacon interval is %d, refusing due to firmware bug!\n",
+                               sta->addr, vif->bss_conf.beacon_int);
+                       ret = -EINVAL;
+                       goto out_unlock;
+               }
                ret = iwl_mvm_add_sta(mvm, vif, sta);
        } else if (old_state == IEEE80211_STA_NONE &&
                   new_state == IEEE80211_STA_AUTH) {
@@ -1015,6 +1034,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
        } else {
                ret = -EIO;
        }
+ out_unlock:
        mutex_unlock(&mvm->mutex);
 
        return ret;
index 9f46b23801bc84187b6aba6ed4b89ca7149eafc6..80862319c42aa1ab7e5b679e1d667731cc2bfb58 100644 (file)
@@ -88,6 +88,7 @@ enum iwl_mvm_tx_fifo {
        IWL_MVM_TX_FIFO_BE,
        IWL_MVM_TX_FIFO_VI,
        IWL_MVM_TX_FIFO_VO,
+       IWL_MVM_TX_FIFO_MCAST = 5,
 };
 
 extern struct ieee80211_ops iwl_mvm_hw_ops;
index 2476e43799d5e6d5bfd182e62b30b3cbe77020a9..8e1f6c095a9ecade2e9b275ed076374158d136e9 100644 (file)
@@ -137,8 +137,8 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd,
 {
        int fw_idx, req_idx;
 
-       fw_idx = 0;
-       for (req_idx = req->n_ssids - 1; req_idx > 0; req_idx--) {
+       for (req_idx = req->n_ssids - 1, fw_idx = 0; req_idx > 0;
+            req_idx--, fw_idx++) {
                cmd->direct_scan[fw_idx].id = WLAN_EID_SSID;
                cmd->direct_scan[fw_idx].len = req->ssids[req_idx].ssid_len;
                memcpy(cmd->direct_scan[fw_idx].ssid,
@@ -176,19 +176,12 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd,
        struct iwl_scan_channel *chan = (struct iwl_scan_channel *)
                (cmd->data + le16_to_cpu(cmd->tx_cmd.len));
        int i;
-       __le32 chan_type_value;
-
-       if (req->n_ssids > 0)
-               chan_type_value = cpu_to_le32(BIT(req->n_ssids + 1) - 1);
-       else
-               chan_type_value = SCAN_CHANNEL_TYPE_PASSIVE;
 
        for (i = 0; i < cmd->channel_count; i++) {
                chan->channel = cpu_to_le16(req->channels[i]->hw_value);
+               chan->type = cpu_to_le32(BIT(req->n_ssids) - 1);
                if (req->channels[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-                       chan->type = SCAN_CHANNEL_TYPE_PASSIVE;
-               else
-                       chan->type = chan_type_value;
+                       chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE);
                chan->active_dwell = cpu_to_le16(active_dwell);
                chan->passive_dwell = cpu_to_le16(passive_dwell);
                chan->iteration_count = cpu_to_le16(1);
index 5c664ed54400ed65c5232c9092c62dceaeadfdcd..68f0bbe1f381f4b09303450b9520e3d107963a2d 100644 (file)
@@ -226,9 +226,6 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
                if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
                        mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]);
 
-       if (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE)
-               mvm_sta->tfd_queue_msk |= BIT(vif->cab_queue);
-
        /* for HW restart - need to reset the seq_number etc... */
        memset(mvm_sta->tid_data, 0, sizeof(mvm_sta->tid_data));
 
@@ -621,8 +618,12 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
        cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
        cmd.sta_id = mvm_sta->sta_id;
        cmd.add_modify = STA_MODE_MODIFY;
-       cmd.add_immediate_ba_tid = (u8) tid;
-       cmd.add_immediate_ba_ssn = cpu_to_le16(ssn);
+       if (start) {
+               cmd.add_immediate_ba_tid = (u8) tid;
+               cmd.add_immediate_ba_ssn = cpu_to_le16(ssn);
+       } else {
+               cmd.remove_immediate_ba_tid = (u8) tid;
+       }
        cmd.modify_mask = start ? STA_MODIFY_ADD_BA_TID :
                                  STA_MODIFY_REMOVE_BA_TID;
 
@@ -894,6 +895,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
        struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
        u16 txq_id;
+       enum iwl_mvm_agg_state old_state;
 
        /*
         * First set the agg state to OFF to avoid calling
@@ -903,13 +905,17 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        txq_id = tid_data->txq_id;
        IWL_DEBUG_TX_QUEUES(mvm, "Flush AGG: sta %d tid %d q %d state %d\n",
                            mvmsta->sta_id, tid, txq_id, tid_data->state);
+       old_state = tid_data->state;
        tid_data->state = IWL_AGG_OFF;
        spin_unlock_bh(&mvmsta->lock);
 
-       if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true))
-               IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
+       if (old_state >= IWL_AGG_ON) {
+               if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true))
+                       IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
+
+               iwl_trans_txq_disable(mvm->trans, tid_data->txq_id);
+       }
 
-       iwl_trans_txq_disable(mvm->trans, tid_data->txq_id);
        mvm->queue_to_mac80211[tid_data->txq_id] =
                                IWL_INVALID_MAC80211_QUEUE;
 
@@ -1287,17 +1293,11 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
        struct iwl_mvm_add_sta_cmd cmd = {
                .add_modify = STA_MODE_MODIFY,
                .sta_id = mvmsta->sta_id,
-               .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT,
-               .sleep_state_flags = cpu_to_le16(STA_SLEEP_STATE_AWAKE),
+               .station_flags_msk = cpu_to_le32(STA_FLG_PS),
                .mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),
        };
        int ret;
 
-       /*
-        * Same modify mask for sleep_tx_count and sleep_state_flags but this
-        * should be fine since if we set the STA as "awake", then
-        * sleep_tx_count is not relevant.
-        */
        ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd);
        if (ret)
                IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret);
index 48c1891e3df6b00ce3417b7609f9c240ae36f2e4..a2e6112e91e9b5dd0da9dba0c4bbeb846f21a404 100644 (file)
@@ -175,7 +175,7 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
         * table is controlled by LINK_QUALITY commands
         */
 
-       if (ieee80211_is_data(fc)) {
+       if (ieee80211_is_data(fc) && sta) {
                tx_cmd->initial_rate_index = 0;
                tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
                return;
@@ -610,8 +610,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
                    !(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) {
+               /* W/A FW bug: seq_ctl is wrong when the status isn't success */
+               if (status != TX_STATUS_SUCCESS) {
                        struct ieee80211_hdr *hdr = (void *)skb->data;
                        seq_ctl = le16_to_cpu(hdr->seq_ctrl);
                }
index 8cb53ec2b77bc6534faf95efaf64377e80ceb798..5283b5552e6fb7a5be03da79f0504e00198c5770 100644 (file)
@@ -129,6 +129,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
        {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */
        {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */
        {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x423C, 0x1326, iwl5150_abg_cfg)}, /* Half Mini Card */
 
        {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */
        {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */
index 50ba0a468f94baa59dede7d4c50c8a3a2f960b35..aeb70e13137abdc8eb99c7f539336cc2e830d667 100644 (file)
@@ -1481,16 +1481,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
        spin_lock_init(&trans_pcie->reg_lock);
        init_waitqueue_head(&trans_pcie->ucode_write_waitq);
 
-       /* W/A - seems to solve weird behavior. We need to remove this if we
-        * don't want to stay in L1 all the time. This wastes a lot of power */
-       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
-                              PCIE_LINK_STATE_CLKPM);
-
        if (pci_enable_device(pdev)) {
                err = -ENODEV;
                goto out_no_pci;
        }
 
+       /* W/A - seems to solve weird behavior. We need to remove this if we
+        * don't want to stay in L1 all the time. This wastes a lot of power */
+       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+                              PCIE_LINK_STATE_CLKPM);
+
        pci_set_master(pdev);
 
        err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
index c5e30294c5acc746730d2b60c857addeba4f3a36..48acfc6201914ae49823077cea5e78706004ce44 100644 (file)
@@ -576,10 +576,16 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
 
        spin_lock_bh(&txq->lock);
        while (q->write_ptr != q->read_ptr) {
+               IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n",
+                                  txq_id, q->read_ptr);
                iwl_pcie_txq_free_tfd(trans, txq);
                q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
        }
+       txq->active = false;
        spin_unlock_bh(&txq->lock);
+
+       /* just in case - this queue may have been stopped */
+       iwl_wake_queue(trans, txq);
 }
 
 /*
@@ -927,6 +933,12 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
 
        spin_lock_bh(&txq->lock);
 
+       if (!txq->active) {
+               IWL_DEBUG_TX_QUEUES(trans, "Q %d inactive - ignoring idx %d\n",
+                                   txq_id, ssn);
+               goto out;
+       }
+
        if (txq->q.read_ptr == tfd_num)
                goto out;
 
@@ -1103,6 +1115,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
                       (fifo << SCD_QUEUE_STTS_REG_POS_TXF) |
                       (1 << SCD_QUEUE_STTS_REG_POS_WSL) |
                       SCD_QUEUE_STTS_REG_MSK);
+       trans_pcie->txq[txq_id].active = true;
        IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d on FIFO %d WrPtr: %d\n",
                            txq_id, fifo, ssn & 0xff);
 }
index e42b266a023a2c0df18e7cd85fd7dbbb3cf07d45..e7f7cdfafd51f4f36a89d36c8ff8897a71dce838 100644 (file)
@@ -1668,9 +1668,9 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
        int ret;
 
-       if (priv->bss_mode != NL80211_IFTYPE_STATION) {
+       if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) {
                wiphy_err(wiphy,
-                         "%s: reject infra assoc request in non-STA mode\n",
+                         "%s: reject infra assoc request in non-STA role\n",
                          dev->name);
                return -EINVAL;
        }
index 988552dece75d49ab3af4628dec68bd6a9627030..5178c4630d89310e17a5db810977fa5aad8ca525 100644 (file)
@@ -415,7 +415,8 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
        u32 k = 0;
        struct mwifiex_adapter *adapter = priv->adapter;
 
-       if (priv->bss_mode == NL80211_IFTYPE_STATION) {
+       if (priv->bss_mode == NL80211_IFTYPE_STATION ||
+           priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
                switch (adapter->config_bands) {
                case BAND_B:
                        dev_dbg(adapter->dev, "info: infra band=%d "
index 6bcb66e6e97c8c1a43a139ba6970ddc0b15f701e..96bda6ca316dda9d7bd48d0de6db8c2b7fb3d437 100644 (file)
@@ -1290,8 +1290,10 @@ int mwifiex_associate(struct mwifiex_private *priv,
 {
        u8 current_bssid[ETH_ALEN];
 
-       /* Return error if the adapter or table entry is not marked as infra */
-       if ((priv->bss_mode != NL80211_IFTYPE_STATION) ||
+       /* Return error if the adapter is not STA role or table entry
+        * is not marked as infra.
+        */
+       if ((GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) ||
            (bss_desc->bss_mode != NL80211_IFTYPE_STATION))
                return -1;
 
index 2eb88ea9acf7f66f51e8e7544f52642586fe627e..c4a2e775fe1a1a206395ec8f126d331e12fa64fb 100644 (file)
@@ -363,20 +363,6 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
                dev_err(adapter->dev, "cannot create default STA interface\n");
                goto err_add_intf;
        }
-
-       /* Create AP interface by default */
-       if (!mwifiex_add_virtual_intf(adapter->wiphy, "uap%d",
-                                     NL80211_IFTYPE_AP, NULL, NULL)) {
-               dev_err(adapter->dev, "cannot create default AP interface\n");
-               goto err_add_intf;
-       }
-
-       /* Create P2P interface by default */
-       if (!mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d",
-                                     NL80211_IFTYPE_P2P_CLIENT, NULL, NULL)) {
-               dev_err(adapter->dev, "cannot create default P2P interface\n");
-               goto err_add_intf;
-       }
        rtnl_unlock();
 
        mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
index 363ba31b58bf057fbd305007a70aba9ffea82978..139c9581aecca2617ee1c69fcad4e3e10ab733c5 100644 (file)
@@ -1441,8 +1441,8 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
        /* Allocate buffer and copy payload */
        blk_size = MWIFIEX_SDIO_BLOCK_SIZE;
        buf_block_len = (pkt_len + blk_size - 1) / blk_size;
-       *(u16 *) &payload[0] = (u16) pkt_len;
-       *(u16 *) &payload[2] = type;
+       *(__le16 *)&payload[0] = cpu_to_le16((u16)pkt_len);
+       *(__le16 *)&payload[2] = cpu_to_le16(type);
 
        /*
         * This is SDIO specific header
index 72f32e5caa4d1931b8719891c150f1b30304425e..7e66a903cfeecdfae806f197aef1759ac979bfc3 100644 (file)
@@ -2392,7 +2392,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
        rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
 
        rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
-       if (info->default_power1 > power_bound)
+       if (info->default_power2 > power_bound)
                rt2x00_set_field8(&rfcsr, RFCSR50_TX, power_bound);
        else
                rt2x00_set_field8(&rfcsr, RFCSR50_TX, info->default_power2);
@@ -5912,7 +5912,8 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
            IEEE80211_HW_SUPPORTS_PS |
            IEEE80211_HW_PS_NULLFUNC_STACK |
            IEEE80211_HW_AMPDU_AGGREGATION |
-           IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+           IEEE80211_HW_REPORTS_TX_ACK_STATUS |
+           IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
 
        /*
         * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices
@@ -6056,8 +6057,8 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
                default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
 
                for (i = 14; i < spec->num_channels; i++) {
-                       info[i].default_power1 = default_power1[i];
-                       info[i].default_power2 = default_power2[i];
+                       info[i].default_power1 = default_power1[i - 14];
+                       info[i].default_power2 = default_power2[i - 14];
                }
        }
 
index 2c12311467a99cd634c7b204eaccc36eb75d2aaa..d955741e48ff1c46d1beefba25077eb89fdbf4ed 100644 (file)
@@ -936,13 +936,8 @@ void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index)
        spin_unlock_irqrestore(&queue->index_lock, irqflags);
 }
 
-void rt2x00queue_pause_queue(struct data_queue *queue)
+void rt2x00queue_pause_queue_nocheck(struct data_queue *queue)
 {
-       if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
-           !test_bit(QUEUE_STARTED, &queue->flags) ||
-           test_and_set_bit(QUEUE_PAUSED, &queue->flags))
-               return;
-
        switch (queue->qid) {
        case QID_AC_VO:
        case QID_AC_VI:
@@ -958,6 +953,15 @@ void rt2x00queue_pause_queue(struct data_queue *queue)
                break;
        }
 }
+void rt2x00queue_pause_queue(struct data_queue *queue)
+{
+       if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
+           !test_bit(QUEUE_STARTED, &queue->flags) ||
+           test_and_set_bit(QUEUE_PAUSED, &queue->flags))
+               return;
+
+       rt2x00queue_pause_queue_nocheck(queue);
+}
 EXPORT_SYMBOL_GPL(rt2x00queue_pause_queue);
 
 void rt2x00queue_unpause_queue(struct data_queue *queue)
@@ -1019,7 +1023,7 @@ void rt2x00queue_stop_queue(struct data_queue *queue)
                return;
        }
 
-       rt2x00queue_pause_queue(queue);
+       rt2x00queue_pause_queue_nocheck(queue);
 
        queue->rt2x00dev->ops->lib->stop_queue(queue);
 
index 0dc8180e251bf0c1ff33e917db2f94bf15d7c927..883a54c8c5bcdbf56693db076835e1c09af28542 100644 (file)
@@ -2825,7 +2825,8 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
                tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
                for (i = 14; i < spec->num_channels; i++) {
                        info[i].max_power = MAX_TXPOWER;
-                       info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+                       info[i].default_power1 =
+                                       TXPOWER_FROM_DEV(tx_power[i - 14]);
                }
        }
 
index 377e09bb0b812cb9c269678a3b6f55696140e48d..2bbca183f94ac77740137e6c581fad040f65522a 100644 (file)
@@ -2167,7 +2167,8 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
                tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
                for (i = 14; i < spec->num_channels; i++) {
                        info[i].max_power = MAX_TXPOWER;
-                       info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+                       info[i].default_power1 =
+                                       TXPOWER_FROM_DEV(tx_power[i - 14]);
                }
        }
 
index c97e9d327331c8b25624327ec4d672c7289f4492..e70b4ffaf97f06de385e5e4bfc861e1b411c2a82 100644 (file)
@@ -1008,19 +1008,6 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
        return;
 }
 
-static void rtl_lps_change_work_callback(struct work_struct *work)
-{
-       struct rtl_works *rtlworks =
-           container_of(work, struct rtl_works, lps_change_work);
-       struct ieee80211_hw *hw = rtlworks->hw;
-       struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-       if (rtlpriv->enter_ps)
-               rtl_lps_enter(hw);
-       else
-               rtl_lps_leave(hw);
-}
-
 static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw)
 {
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
index 884bceae38a91d2b9ce4e07cf70c5c040e844df4..71e917db83383ba6a9b393f9278f2b37bc9a3bf1 100644 (file)
@@ -611,6 +611,18 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
                        MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40));
 }
 
+void rtl_lps_change_work_callback(struct work_struct *work)
+{
+       struct rtl_works *rtlworks =
+           container_of(work, struct rtl_works, lps_change_work);
+       struct ieee80211_hw *hw = rtlworks->hw;
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       if (rtlpriv->enter_ps)
+               rtl_lps_enter(hw);
+       else
+               rtl_lps_leave(hw);
+}
 
 void rtl_swlps_wq_callback(void *data)
 {
index 4d682b753f503df0f61b5e58b98e871f58c31029..88bd76ea88f7621dd92cb4ff495ee22e9dc53912 100644 (file)
@@ -49,5 +49,6 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw);
 void rtl_swlps_rf_sleep(struct ieee80211_hw *hw);
 void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
 void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len);
+void rtl_lps_change_work_callback(struct work_struct *work);
 
 #endif
index 953f1a0f853238289620eaedbaf5f80bdc77d3d9..2119313a737bab21e9c304627b2acb56d2a3ab43 100644 (file)
@@ -104,7 +104,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
                        tx_agc[RF90_PATH_A] = 0x10101010;
                        tx_agc[RF90_PATH_B] = 0x10101010;
                } else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
-                          TXHIGHPWRLEVEL_LEVEL1) {
+                          TXHIGHPWRLEVEL_LEVEL2) {
                        tx_agc[RF90_PATH_A] = 0x00000000;
                        tx_agc[RF90_PATH_B] = 0x00000000;
                } else{
index 826f085c29dd5d9155ff0ab1e4ea2a8b2832f70c..2bd5985262171bfdfa81de5494a4ef9640d72cc5 100644 (file)
@@ -359,6 +359,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
        {RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/
        {RTL_USB_DEVICE(0x20f4, 0x624d, rtl92cu_hal_cfg)}, /*TRENDNet*/
+       {RTL_USB_DEVICE(0x2357, 0x0100, rtl92cu_hal_cfg)}, /*TP-Link WN8200ND*/
        {RTL_USB_DEVICE(0x7392, 0x7822, rtl92cu_hal_cfg)}, /*Edimax -Edimax*/
        {}
 };
index e4c4cdc3eb67f6d992c29b026d98f244400e696b..d9ee2efffe5ffb1284335352eed2e13ab8e4df96 100644 (file)
@@ -251,7 +251,7 @@ static struct rtl_hal_cfg rtl8723ae_hal_cfg = {
        .bar_id = 2,
        .write_readback = true,
        .name = "rtl8723ae_pci",
-       .fw_name = "rtlwifi/rtl8723aefw.bin",
+       .fw_name = "rtlwifi/rtl8723fw.bin",
        .ops = &rtl8723ae_hal_ops,
        .mod_params = &rtl8723ae_mod_params,
        .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
@@ -353,8 +353,8 @@ MODULE_AUTHOR("Realtek WlanFAE      <wlanfae@realtek.com>");
 MODULE_AUTHOR("Larry Finger    <Larry.Finger@lwfinger.net>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Realtek 8723E 802.11n PCI wireless");
-MODULE_FIRMWARE("rtlwifi/rtl8723aefw.bin");
-MODULE_FIRMWARE("rtlwifi/rtl8723aefw_B.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8723fw.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8723fw_B.bin");
 
 module_param_named(swenc, rtl8723ae_mod_params.sw_crypto, bool, 0444);
 module_param_named(debug, rtl8723ae_mod_params.debug, int, 0444);
index a3532e0778710ff5975a3c3fec4e21299e45e301..1feebdc92f41d3b1d5ab818eecf631528920affc 100644 (file)
@@ -1070,6 +1070,8 @@ int rtl_usb_probe(struct usb_interface *intf,
        spin_lock_init(&rtlpriv->locks.usb_lock);
        INIT_WORK(&rtlpriv->works.fill_h2c_cmd,
                  rtl_fill_h2c_cmd_work_callback);
+       INIT_WORK(&rtlpriv->works.lps_change_work,
+                 rtl_lps_change_work_callback);
 
        rtlpriv->usb_data_index = 0;
        init_completion(&rtlpriv->firmware_loading_complete);
index 4941f201d6c8dc5a4b62446a9153a4384a3cb4f4..b8ba1f925e75521a2886b42a8a3d95dac69c0aa9 100644 (file)
@@ -98,10 +98,12 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw)
                goto exit;
 
        err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4,
-           USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT);
+           USB_DIR_IN | 0x40, 0, 0, buf, sizeof(ret), ZD1201_FW_TIMEOUT);
        if (err < 0)
                goto exit;
 
+       memcpy(&ret, buf, sizeof(ret));
+
        if (ret & 0x80) {
                err = -EIO;
                goto exit;
index 1db101415069726fc59d26443f773fc0432f52a6..0c01b8e33fe1870373fa8f0f18c703c6cc9d7a4f 100644 (file)
@@ -276,8 +276,7 @@ no_skb:
                        break;
                }
 
-               __skb_fill_page_desc(skb, 0, page, 0, 0);
-               skb_shinfo(skb)->nr_frags = 1;
+               skb_add_rx_frag(skb, 0, page, 0, 0, PAGE_SIZE);
                __skb_queue_tail(&np->rx_batch, skb);
        }
 
@@ -822,7 +821,6 @@ static RING_IDX xennet_fill_frags(struct netfront_info *np,
                                  struct sk_buff_head *list)
 {
        struct skb_shared_info *shinfo = skb_shinfo(skb);
-       int nr_frags = shinfo->nr_frags;
        RING_IDX cons = np->rx.rsp_cons;
        struct sk_buff *nskb;
 
@@ -831,19 +829,21 @@ static RING_IDX xennet_fill_frags(struct netfront_info *np,
                        RING_GET_RESPONSE(&np->rx, ++cons);
                skb_frag_t *nfrag = &skb_shinfo(nskb)->frags[0];
 
-               __skb_fill_page_desc(skb, nr_frags,
-                                    skb_frag_page(nfrag),
-                                    rx->offset, rx->status);
+               if (shinfo->nr_frags == MAX_SKB_FRAGS) {
+                       unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
 
-               skb->data_len += rx->status;
+                       BUG_ON(pull_to <= skb_headlen(skb));
+                       __pskb_pull_tail(skb, pull_to - skb_headlen(skb));
+               }
+               BUG_ON(shinfo->nr_frags >= MAX_SKB_FRAGS);
+
+               skb_add_rx_frag(skb, shinfo->nr_frags, skb_frag_page(nfrag),
+                               rx->offset, rx->status, PAGE_SIZE);
 
                skb_shinfo(nskb)->nr_frags = 0;
                kfree_skb(nskb);
-
-               nr_frags++;
        }
 
-       shinfo->nr_frags = nr_frags;
        return cons;
 }
 
@@ -929,7 +929,8 @@ static int handle_incoming_queue(struct net_device *dev,
        while ((skb = __skb_dequeue(rxq)) != NULL) {
                int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
 
-               __pskb_pull_tail(skb, pull_to - skb_headlen(skb));
+               if (pull_to > skb_headlen(skb))
+                       __pskb_pull_tail(skb, pull_to - skb_headlen(skb));
 
                /* Ethernet work: Delayed to here as it peeks the header. */
                skb->protocol = eth_type_trans(skb, dev);
@@ -1015,16 +1016,10 @@ err:
                skb_shinfo(skb)->frags[0].page_offset = rx->offset;
                skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status);
                skb->data_len = rx->status;
+               skb->len += rx->status;
 
                i = xennet_fill_frags(np, skb, &tmpq);
 
-               /*
-                 * Truesize is the actual allocation size, even if the
-                 * allocation is only partially used.
-                 */
-               skb->truesize += PAGE_SIZE * skb_shinfo(skb)->nr_frags;
-               skb->len += skb->data_len;
-
                if (rx->flags & XEN_NETRXF_csum_blank)
                        skb->ip_summed = CHECKSUM_PARTIAL;
                else if (rx->flags & XEN_NETRXF_data_validated)
index 04da786c84d2451b79be8bcbcb61c469030f977e..7c8221d363292df921cd5341facfa48bfd06d1e3 100644 (file)
@@ -106,8 +106,12 @@ static unsigned int of_bus_default_get_flags(const __be32 *addr)
 
 static int of_bus_pci_match(struct device_node *np)
 {
-       /* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */
-       return !strcmp(np->type, "pci") || !strcmp(np->type, "vci");
+       /*
+        * "vci" is for the /chaos bridge on 1st-gen PCI powermacs
+        * "ht" is hypertransport
+        */
+       return !strcmp(np->type, "pci") || !strcmp(np->type, "vci") ||
+               !strcmp(np->type, "ht");
 }
 
 static void of_bus_pci_count_cells(struct device_node *np,
index ffb84d506030f5e7cd1aa7ae9e45791ecc12d53f..fad95c811bec66e067f48e335073f56ce20f35d7 100644 (file)
@@ -1639,6 +1639,7 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
                ap = dt_alloc(sizeof(*ap) + len + 1, 4);
                if (!ap)
                        continue;
+               memset(ap, 0, sizeof(*ap) + len + 1);
                ap->alias = start;
                of_alias_add(ap, np, id, start, len);
        }
index 10c08e82054b2fa3a650acfd094f4c4c1c2272d9..4911158cba8a154b80aaeac44ef39a05741d93df 100644 (file)
@@ -337,6 +337,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
        /* Allocate memory for the expanded device tree */
        mem = dt_alloc(size + 4, __alignof__(struct device_node));
 
+       memset((void *)mem, 0, size);
+
        ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);
 
        pr_debug("  unflattening %p...\n", mem);
index e79e006eb9abc4eab4722aa483d2c6fb38a8c455..9ee04b4b68bf39569acd6dd360c62a6cb4e4b76e 100644 (file)
@@ -811,18 +811,28 @@ int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
        return pcidev->irq;
 }
 
-static struct iosapic_info *first_isi = NULL;
+static struct iosapic_info *iosapic_list;
 
 #ifdef CONFIG_64BIT
-int iosapic_serial_irq(int num)
+int iosapic_serial_irq(struct parisc_device *dev)
 {
-       struct iosapic_info *isi = first_isi;
-       struct irt_entry *irte = NULL;  /* only used if PAT PDC */
+       struct iosapic_info *isi;
+       struct irt_entry *irte;
        struct vector_info *vi;
-       int isi_line;   /* line used by device */
+       int cnt;
+       int intin;
+
+       intin = (dev->mod_info >> 24) & 15;
 
        /* lookup IRT entry for isi/slot/pin set */
-       irte = &irt_cell[num];
+       for (cnt = 0; cnt < irt_num_entry; cnt++) {
+               irte = &irt_cell[cnt];
+               if (COMPARE_IRTE_ADDR(irte, dev->mod0) &&
+                   irte->dest_iosapic_intin == intin)
+                       break;
+       }
+       if (cnt >= irt_num_entry)
+               return 0; /* no irq found, force polling */
 
        DBG_IRT("iosapic_serial_irq(): irte %p %x %x %x %x %x %x %x %x\n",
                irte,
@@ -834,11 +844,17 @@ int iosapic_serial_irq(int num)
                irte->src_seg_id,
                irte->dest_iosapic_intin,
                (u32) irte->dest_iosapic_addr);
-       isi_line = irte->dest_iosapic_intin;
+
+       /* search for iosapic */
+       for (isi = iosapic_list; isi; isi = isi->isi_next)
+               if (isi->isi_hpa == dev->mod0)
+                       break;
+       if (!isi)
+               return 0; /* no iosapic found, force polling */
 
        /* get vector info for this input line */
-       vi = isi->isi_vector + isi_line;
-       DBG_IRT("iosapic_serial_irq:  line %d vi 0x%p\n", isi_line, vi);
+       vi = isi->isi_vector + intin;
+       DBG_IRT("iosapic_serial_irq:  line %d vi 0x%p\n", iosapic_intin, vi);
 
        /* If this IRQ line has already been setup, skip it */
        if (vi->irte)
@@ -941,8 +957,8 @@ void *iosapic_register(unsigned long hpa)
                vip->irqline = (unsigned char) cnt;
                vip->iosapic = isi;
        }
-       if (!first_isi)
-               first_isi = isi;
+       isi->isi_next = iosapic_list;
+       iosapic_list = isi;
        return isi;
 }
 
index 1f05913ae677e2724c78729a324a01ac1d2afbbd..19f6f70c67d398f8d585618901de98797ebbfcef 100644 (file)
@@ -613,6 +613,54 @@ truncate_pat_collision(struct resource *root, struct resource *new)
        return 0;       /* truncation successful */
 }
 
+/*
+ * extend_lmmio_len: extend lmmio range to maximum length
+ *
+ * This is needed at least on C8000 systems to get the ATI FireGL card
+ * working. On other systems we will currently not extend the lmmio space.
+ */
+static unsigned long
+extend_lmmio_len(unsigned long start, unsigned long end, unsigned long lba_len)
+{
+       struct resource *tmp;
+
+       pr_debug("LMMIO mismatch: PAT length = 0x%lx, MASK register = 0x%lx\n",
+               end - start, lba_len);
+
+       lba_len = min(lba_len+1, 256UL*1024*1024); /* limit to 256 MB */
+
+       pr_debug("LBA: lmmio_space [0x%lx-0x%lx] - original\n", start, end);
+
+       if (boot_cpu_data.cpu_type < mako) {
+               pr_info("LBA: Not a C8000 system - not extending LMMIO range.\n");
+               return end;
+       }
+
+       end += lba_len;
+       if (end < start) /* fix overflow */
+               end = -1ULL;
+
+       pr_debug("LBA: lmmio_space [0x%lx-0x%lx] - current\n", start, end);
+
+       /* first overlap */
+       for (tmp = iomem_resource.child; tmp; tmp = tmp->sibling) {
+               pr_debug("LBA: testing %pR\n", tmp);
+               if (tmp->start == start)
+                       continue; /* ignore ourself */
+               if (tmp->end < start)
+                       continue;
+               if (tmp->start > end)
+                       continue;
+               if (end >= tmp->start)
+                       end = tmp->start - 1;
+       }
+
+       pr_info("LBA: lmmio_space [0x%lx-0x%lx] - new\n", start, end);
+
+       /* return new end */
+       return end;
+}
+
 #else
 #define truncate_pat_collision(r,n)  (0)
 #endif
@@ -994,6 +1042,14 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
                case PAT_LMMIO:
                        /* used to fix up pre-initialized MEM BARs */
                        if (!lba_dev->hba.lmmio_space.flags) {
+                               unsigned long lba_len;
+
+                               lba_len = ~READ_REG32(lba_dev->hba.base_addr
+                                               + LBA_LMMIO_MASK);
+                               if ((p->end - p->start) != lba_len)
+                                       p->end = extend_lmmio_len(p->start,
+                                               p->end, lba_len);
+
                                sprintf(lba_dev->hba.lmmio_name,
                                                "PCI%02x LMMIO",
                                                (int)lba_dev->hba.bus_num.start);
index aac7a40e4a4ac9205441d9c6918a080531117571..0e0d0f7f63fdd83aa551549d38b174cdca8d034d 100644 (file)
@@ -92,7 +92,14 @@ int pciehp_unconfigure_device(struct slot *p_slot)
        if (ret)
                presence = 0;
 
-       list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) {
+       /*
+        * Stopping an SR-IOV PF device removes all the associated VFs,
+        * which will update the bus->devices list and confuse the
+        * iterator.  Therefore, iterate in reverse so we remove the VFs
+        * first, then the PF.  We do the same in pci_stop_bus_device().
+        */
+       list_for_each_entry_safe_reverse(dev, temp, &parent->devices,
+                                        bus_list) {
                pci_dev_get(dev);
                if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
                        pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl);
index c93071d428f5d6d6cb038d5cb614e4117c5fd8aa..a971a6f6268d83f3ec67e1519caaa0455c83a205 100644 (file)
@@ -92,6 +92,8 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
        pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_DID, &virtfn->device);
        pci_setup_device(virtfn);
        virtfn->dev.parent = dev->dev.parent;
+       virtfn->physfn = pci_dev_get(dev);
+       virtfn->is_virtfn = 1;
 
        for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
                res = dev->resource + PCI_IOV_RESOURCES + i;
@@ -113,9 +115,6 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
        pci_device_add(virtfn, virtfn->bus);
        mutex_unlock(&iov->dev->sriov->lock);
 
-       virtfn->physfn = pci_dev_get(dev);
-       virtfn->is_virtfn = 1;
-
        rc = pci_bus_add_device(virtfn);
        sprintf(buf, "virtfn%u", id);
        rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf);
index e4b1fb2c0f5d83029e0a62ffa4aaef36f4559da3..336b3f94a19a2fe67e25ce65a3e189da9a5af7cc 100644 (file)
@@ -317,13 +317,20 @@ void acpi_pci_remove_bus(struct pci_bus *bus)
 /* ACPI bus type */
 static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
 {
-       struct pci_dev * pci_dev;
-       u64     addr;
+       struct pci_dev *pci_dev = to_pci_dev(dev);
+       bool is_bridge;
+       u64 addr;
 
-       pci_dev = to_pci_dev(dev);
+       /*
+        * pci_is_bridge() is not suitable here, because pci_dev->subordinate
+        * is set only after acpi_pci_find_device() has been called for the
+        * given device.
+        */
+       is_bridge = pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE
+                       || pci_dev->hdr_type == PCI_HEADER_TYPE_CARDBUS;
        /* Please ref to ACPI spec for the syntax of _ADR */
        addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
-       *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
+       *handle = acpi_find_child(ACPI_HANDLE(dev->parent), addr, is_bridge);
        if (!*handle)
                return -ENODEV;
        return 0;
index 70f10fa3c1b216ab88e04471c171d8404f107770..ea37072e8bf2d5789d03b57f0c703e91ec45f5ab 100644 (file)
@@ -1703,12 +1703,16 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
        bridge->dev.release = pci_release_bus_bridge_dev;
        dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
        error = pcibios_root_bridge_prepare(bridge);
-       if (error)
-               goto bridge_dev_reg_err;
+       if (error) {
+               kfree(bridge);
+               goto err_out;
+       }
 
        error = device_register(&bridge->dev);
-       if (error)
-               goto bridge_dev_reg_err;
+       if (error) {
+               put_device(&bridge->dev);
+               goto err_out;
+       }
        b->bridge = get_device(&bridge->dev);
        device_enable_async_suspend(b->bridge);
        pci_set_bus_of_node(b);
@@ -1764,8 +1768,6 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 class_dev_reg_err:
        put_device(&bridge->dev);
        device_unregister(&bridge->dev);
-bridge_dev_reg_err:
-       kfree(bridge);
 err_out:
        kfree(b);
        return NULL;
index 7d68aeebf56b1a53d447bd0e152643d85d06ea44..df4655c5c13886f3b7ef8502997c95b65bb3f5a1 100644 (file)
@@ -1022,6 +1022,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk_amd_ide_mode);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE, quirk_amd_ide_mode);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE, quirk_amd_ide_mode);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x7900, quirk_amd_ide_mode);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, 0x7900, quirk_amd_ide_mode);
 
 /*
  *     Serverworks CSB5 IDE does not fully support native mode
index d254e237953382bb99768c7cca79b65c3b9aded8..64a7de22d9afe0edb548b3b20f96d7c288e53273 100644 (file)
@@ -300,6 +300,47 @@ static void assign_requested_resources_sorted(struct list_head *head,
        }
 }
 
+static unsigned long pci_fail_res_type_mask(struct list_head *fail_head)
+{
+       struct pci_dev_resource *fail_res;
+       unsigned long mask = 0;
+
+       /* check failed type */
+       list_for_each_entry(fail_res, fail_head, list)
+               mask |= fail_res->flags;
+
+       /*
+        * one pref failed resource will set IORESOURCE_MEM,
+        * as we can allocate pref in non-pref range.
+        * Will release all assigned non-pref sibling resources
+        * according to that bit.
+        */
+       return mask & (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH);
+}
+
+static bool pci_need_to_release(unsigned long mask, struct resource *res)
+{
+       if (res->flags & IORESOURCE_IO)
+               return !!(mask & IORESOURCE_IO);
+
+       /* check pref at first */
+       if (res->flags & IORESOURCE_PREFETCH) {
+               if (mask & IORESOURCE_PREFETCH)
+                       return true;
+               /* count pref if its parent is non-pref */
+               else if ((mask & IORESOURCE_MEM) &&
+                        !(res->parent->flags & IORESOURCE_PREFETCH))
+                       return true;
+               else
+                       return false;
+       }
+
+       if (res->flags & IORESOURCE_MEM)
+               return !!(mask & IORESOURCE_MEM);
+
+       return false;   /* should not get here */
+}
+
 static void __assign_resources_sorted(struct list_head *head,
                                 struct list_head *realloc_head,
                                 struct list_head *fail_head)
@@ -312,11 +353,24 @@ static void __assign_resources_sorted(struct list_head *head,
         *  if could do that, could get out early.
         *  if could not do that, we still try to assign requested at first,
         *    then try to reassign add_size for some resources.
+        *
+        * Separate three resource type checking if we need to release
+        * assigned resource after requested + add_size try.
+        *      1. if there is io port assign fail, will release assigned
+        *         io port.
+        *      2. if there is pref mmio assign fail, release assigned
+        *         pref mmio.
+        *         if assigned pref mmio's parent is non-pref mmio and there
+        *         is non-pref mmio assign fail, will release that assigned
+        *         pref mmio.
+        *      3. if there is non-pref mmio assign fail or pref mmio
+        *         assigned fail, will release assigned non-pref mmio.
         */
        LIST_HEAD(save_head);
        LIST_HEAD(local_fail_head);
        struct pci_dev_resource *save_res;
-       struct pci_dev_resource *dev_res;
+       struct pci_dev_resource *dev_res, *tmp_res;
+       unsigned long fail_type;
 
        /* Check if optional add_size is there */
        if (!realloc_head || list_empty(realloc_head))
@@ -348,6 +402,19 @@ static void __assign_resources_sorted(struct list_head *head,
                return;
        }
 
+       /* check failed type */
+       fail_type = pci_fail_res_type_mask(&local_fail_head);
+       /* remove not need to be released assigned res from head list etc */
+       list_for_each_entry_safe(dev_res, tmp_res, head, list)
+               if (dev_res->res->parent &&
+                   !pci_need_to_release(fail_type, dev_res->res)) {
+                       /* remove it from realloc_head list */
+                       remove_from_list(realloc_head, dev_res->res);
+                       remove_from_list(&save_head, dev_res->res);
+                       list_del(&dev_res->list);
+                       kfree(dev_res);
+               }
+
        free_list(&local_fail_head);
        /* Release assigned resource */
        list_for_each_entry(dev_res, head, list)
index 966abc6054d7b625c18a5eeb854dc065b40d43c1..f7197a790341a0c1de8b4a7dfa2c22377cfdf5c5 100644 (file)
@@ -678,10 +678,9 @@ static int pcifront_connect_and_init_dma(struct pcifront_device *pdev)
        if (!pcifront_dev) {
                dev_info(&pdev->xdev->dev, "Installing PCI frontend\n");
                pcifront_dev = pdev;
-       } else {
-               dev_err(&pdev->xdev->dev, "PCI frontend already installed!\n");
+       } else
                err = -EEXIST;
-       }
+
        spin_unlock(&pcifront_dev_lock);
 
        if (!err && !swiotlb_nr_tbl()) {
@@ -848,7 +847,7 @@ static int pcifront_try_connect(struct pcifront_device *pdev)
                goto out;
 
        err = pcifront_connect_and_init_dma(pdev);
-       if (err) {
+       if (err && err != -EEXIST) {
                xenbus_dev_fatal(pdev->xdev, err,
                                 "Error setting up PCI Frontend");
                goto out;
index 01463c781847d6b2bccd3afd03eca62b0239cd0b..1b2c6317c772cea305a8412a51b5a38b9265b208 100644 (file)
@@ -100,9 +100,9 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
                int vcc = gpio_is_valid(cf->board->vcc_pin);
 
                *sp = SS_DETECT | SS_3VCARD;
-               if (!rdy || gpio_get_value(rdy))
+               if (!rdy || gpio_get_value(cf->board->irq_pin))
                        *sp |= SS_READY;
-               if (!vcc || gpio_get_value(vcc))
+               if (!vcc || gpio_get_value(cf->board->vcc_pin))
                        *sp |= SS_POWERON;
        } else
                *sp = 0;
index 5d7529ed5392d843cb80371cd47b45fb32e9a7b2..314e5e8e91224b7dc79e9bce71d0fb6b92fc9700 100644 (file)
@@ -325,7 +325,7 @@ static void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask)
 
 static unsigned at91_mux_get_pullup(void __iomem *pio, unsigned pin)
 {
-       return (readl_relaxed(pio + PIO_PUSR) >> pin) & 0x1;
+       return !((readl_relaxed(pio + PIO_PUSR) >> pin) & 0x1);
 }
 
 static void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on)
@@ -445,7 +445,7 @@ static void at91_mux_pio3_set_debounce(void __iomem *pio, unsigned mask,
 
 static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin)
 {
-       return (__raw_readl(pio + PIO_PPDSR) >> pin) & 0x1;
+       return !((__raw_readl(pio + PIO_PPDSR) >> pin) & 0x1);
 }
 
 static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is_on)
index 0f9f8596b300a0d06d525547159bf4d038ba1505..f9119525f5570c2d041d563c0eefbc9a01e32c20 100644 (file)
@@ -330,7 +330,7 @@ static int __init olpc_ec_init_module(void)
        return platform_driver_register(&olpc_ec_plat_driver);
 }
 
-module_init(olpc_ec_init_module);
+arch_initcall(olpc_ec_init_module);
 
 MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
 MODULE_LICENSE("GPL");
index fefc39fe42bef0e600a47d5e2aade039e6a96d83..98de1ddce4586920593d0e51b7f87971d63feae1 100644 (file)
@@ -450,7 +450,7 @@ static void uevent_notify(struct charger_manager *cm, const char *event)
        strncpy(env_str, event, UEVENT_BUF_SIZE);
        kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE);
 
-       dev_info(cm->dev, event);
+       dev_info(cm->dev, "%s", event);
 }
 
 /**
index 809b7a3336baa40e654f296feeaa8ebb5067411e..5d3b0f014d350f580c1387c3dcd4af621ddc9282 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/rio_drv.h>
 #include <linux/rio_ids.h>
 #include <linux/delay.h>
+
+#include <asm/page.h>
 #include "../rio.h"
 
 #define LOCAL_RTE_CONF_DESTID_SEL      0x010070
index 771812d62e6bd3a961742db477e660771ee593f1..3bb9401f1caed17323eb9bf7afc3a40b77a72561 100644 (file)
@@ -240,9 +240,9 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        }
 
        alrm->pending = 0;
-       ret = regmap_read(info->max77686->regmap, MAX77686_REG_STATUS1, &val);
+       ret = regmap_read(info->max77686->regmap, MAX77686_REG_STATUS2, &val);
        if (ret < 0) {
-               dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n",
+               dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n",
                                __func__, __LINE__, ret);
                goto out;
        }
index 5032c24ec15938d2341927960de9e52a077b9773..9100a3401de12cf2ae72d30a659d2385b259ce8c 100644 (file)
@@ -310,7 +310,7 @@ static int rv3029c2_rtc_i2c_set_alarm(struct i2c_client *client,
                dev_dbg(&client->dev, "alarm IRQ armed\n");
        } else {
                /* disable AIE irq */
-               ret = rv3029c2_rtc_i2c_alarm_set_irq(client, 1);
+               ret = rv3029c2_rtc_i2c_alarm_set_irq(client, 0);
                if (ret)
                        return ret;
 
index f6adde44f226e1352c327a3b27696f09f7a7b501..3743ac931231fdb0a595ba8ef4736345918c9b02 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Module interface and handling of zfcp data structures.
  *
- * Copyright IBM Corp. 2002, 2010
+ * Copyright IBM Corp. 2002, 2013
  */
 
 /*
@@ -23,6 +23,7 @@
  *            Christof Schmitt
  *            Martin Petermann
  *            Sven Schuetz
+ *            Steffen Maier
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -415,6 +416,8 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
        adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN;
        adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
 
+       adapter->stat_read_buf_num = FSF_STATUS_READS_RECOM;
+
        if (!zfcp_scsi_adapter_register(adapter))
                return adapter;
 
index 4133ab6e20f1ab5ccfe058b49f125770e6c289e2..8e8f3533d2a1d67558e5ff93fac4fb0e96d5b678 100644 (file)
@@ -102,10 +102,13 @@ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
 
        if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
                zfcp_erp_action_dismiss(&port->erp_action);
-       else
-               shost_for_each_device(sdev, port->adapter->scsi_host)
+       else {
+               spin_lock(port->adapter->scsi_host->host_lock);
+               __shost_for_each_device(sdev, port->adapter->scsi_host)
                        if (sdev_to_zfcp(sdev)->port == port)
                                zfcp_erp_action_dismiss_lun(sdev);
+               spin_unlock(port->adapter->scsi_host->host_lock);
+       }
 }
 
 static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
@@ -592,9 +595,11 @@ static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear,
 {
        struct scsi_device *sdev;
 
-       shost_for_each_device(sdev, port->adapter->scsi_host)
+       spin_lock(port->adapter->scsi_host->host_lock);
+       __shost_for_each_device(sdev, port->adapter->scsi_host)
                if (sdev_to_zfcp(sdev)->port == port)
                        _zfcp_erp_lun_reopen(sdev, clear, id, 0);
+       spin_unlock(port->adapter->scsi_host->host_lock);
 }
 
 static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
@@ -1435,8 +1440,10 @@ void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask)
                atomic_set_mask(common_mask, &port->status);
        read_unlock_irqrestore(&adapter->port_list_lock, flags);
 
-       shost_for_each_device(sdev, adapter->scsi_host)
+       spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, adapter->scsi_host)
                atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status);
+       spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
 }
 
 /**
@@ -1470,11 +1477,13 @@ void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask)
        }
        read_unlock_irqrestore(&adapter->port_list_lock, flags);
 
-       shost_for_each_device(sdev, adapter->scsi_host) {
+       spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, adapter->scsi_host) {
                atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status);
                if (clear_counter)
                        atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
        }
+       spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
 }
 
 /**
@@ -1488,16 +1497,19 @@ void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask)
 {
        struct scsi_device *sdev;
        u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+       unsigned long flags;
 
        atomic_set_mask(mask, &port->status);
 
        if (!common_mask)
                return;
 
-       shost_for_each_device(sdev, port->adapter->scsi_host)
+       spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, port->adapter->scsi_host)
                if (sdev_to_zfcp(sdev)->port == port)
                        atomic_set_mask(common_mask,
                                        &sdev_to_zfcp(sdev)->status);
+       spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
 }
 
 /**
@@ -1512,6 +1524,7 @@ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask)
        struct scsi_device *sdev;
        u32 common_mask = mask & ZFCP_COMMON_FLAGS;
        u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
+       unsigned long flags;
 
        atomic_clear_mask(mask, &port->status);
 
@@ -1521,13 +1534,15 @@ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask)
        if (clear_counter)
                atomic_set(&port->erp_counter, 0);
 
-       shost_for_each_device(sdev, port->adapter->scsi_host)
+       spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, port->adapter->scsi_host)
                if (sdev_to_zfcp(sdev)->port == port) {
                        atomic_clear_mask(common_mask,
                                          &sdev_to_zfcp(sdev)->status);
                        if (clear_counter)
                                atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
                }
+       spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
 }
 
 /**
index c7e148f33b2a8afbcd319689434b707a835e0645..9152999a0707591259c4aa7498b19ee5ee6717d2 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Implementation of FSF commands.
  *
- * Copyright IBM Corp. 2002, 2010
+ * Copyright IBM Corp. 2002, 2013
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -483,12 +483,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
 
        fc_host_port_name(shost) = nsp->fl_wwpn;
        fc_host_node_name(shost) = nsp->fl_wwnn;
-       fc_host_port_id(shost) = ntoh24(bottom->s_id);
-       fc_host_speed(shost) =
-               zfcp_fsf_convert_portspeed(bottom->fc_link_speed);
        fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
 
-       adapter->hydra_version = bottom->adapter_type;
        adapter->timer_ticks = bottom->timer_interval & ZFCP_FSF_TIMER_INT_MASK;
        adapter->stat_read_buf_num = max(bottom->status_read_buf_num,
                                         (u16)FSF_STATUS_READS_RECOM);
@@ -496,6 +492,19 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
        if (fc_host_permanent_port_name(shost) == -1)
                fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
 
+       zfcp_scsi_set_prot(adapter);
+
+       /* no error return above here, otherwise must fix call chains */
+       /* do not evaluate invalid fields */
+       if (req->qtcb->header.fsf_status == FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE)
+               return 0;
+
+       fc_host_port_id(shost) = ntoh24(bottom->s_id);
+       fc_host_speed(shost) =
+               zfcp_fsf_convert_portspeed(bottom->fc_link_speed);
+
+       adapter->hydra_version = bottom->adapter_type;
+
        switch (bottom->fc_topology) {
        case FSF_TOPO_P2P:
                adapter->peer_d_id = ntoh24(bottom->peer_d_id);
@@ -517,8 +526,6 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
                return -EIO;
        }
 
-       zfcp_scsi_set_prot(adapter);
-
        return 0;
 }
 
@@ -563,8 +570,14 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
                fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
                adapter->hydra_version = 0;
 
+               /* avoids adapter shutdown to be able to recognize
+                * events such as LINK UP */
+               atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
+                               &adapter->status);
                zfcp_fsf_link_down_info_eval(req,
                        &qtcb->header.fsf_status_qual.link_down_info);
+               if (zfcp_fsf_exchange_config_evaluate(req))
+                       return;
                break;
        default:
                zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3");
index 665e3cfaaf85d5b14859465163a3867073f2c5f5..de0598eaacd226ed2824ff94412069ed855a6420 100644 (file)
@@ -224,11 +224,9 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
 
 static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
 {
-       spin_lock_irq(&qdio->req_q_lock);
        if (atomic_read(&qdio->req_q_free) ||
            !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
                return 1;
-       spin_unlock_irq(&qdio->req_q_lock);
        return 0;
 }
 
@@ -246,9 +244,8 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
 {
        long ret;
 
-       spin_unlock_irq(&qdio->req_q_lock);
-       ret = wait_event_interruptible_timeout(qdio->req_q_wq,
-                              zfcp_qdio_sbal_check(qdio), 5 * HZ);
+       ret = wait_event_interruptible_lock_irq_timeout(qdio->req_q_wq,
+                      zfcp_qdio_sbal_check(qdio), qdio->req_q_lock, 5 * HZ);
 
        if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
                return -EIO;
@@ -262,7 +259,6 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
                zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1");
        }
 
-       spin_lock_irq(&qdio->req_q_lock);
        return -EIO;
 }
 
index 7b31e3f403f9060b2af3955e8f306538206ff486..7b353647cb9087894ded09ec8b51234023adce85 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Interface to Linux SCSI midlayer.
  *
- * Copyright IBM Corp. 2002, 2010
+ * Copyright IBM Corp. 2002, 2013
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -311,8 +311,12 @@ static struct scsi_host_template zfcp_scsi_host_template = {
        .proc_name               = "zfcp",
        .can_queue               = 4096,
        .this_id                 = -1,
-       .sg_tablesize            = 1, /* adjusted later */
-       .max_sectors             = 8, /* adjusted later */
+       .sg_tablesize            = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
+                                    * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2),
+                                  /* GCD, adjusted later */
+       .max_sectors             = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
+                                    * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2) * 8,
+                                  /* GCD, adjusted later */
        .dma_boundary            = ZFCP_QDIO_SBALE_LEN - 1,
        .cmd_per_lun             = 1,
        .use_clustering          = 1,
index 86af29f53bbebefec7d58ca0c595c3852e6fdf79..1348fa47d1277d8bb3230f0782d4b419da9ebba6 100644 (file)
@@ -1353,7 +1353,6 @@ config SCSI_LPFC
        tristate "Emulex LightPulse Fibre Channel Support"
        depends on PCI && SCSI
        select SCSI_FC_ATTRS
-       select GENERIC_CSUM
        select CRC_T10DIF
        help
           This lpfc driver supports the Emulex LightPulse
index 0f56d8d7524ff783709fef8797508ea8ce0bcbcb..7e17107643d48a2066b1b00dbb954d35c75db0ef 100644 (file)
@@ -93,6 +93,9 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
                        int send_it = 0;
                        extern int aac_sync_mode;
 
+                       src_writel(dev, MUnit.ODR_C, bellbits);
+                       src_readl(dev, MUnit.ODR_C);
+
                        if (!aac_sync_mode) {
                                src_writel(dev, MUnit.ODR_C, bellbits);
                                src_readl(dev, MUnit.ODR_C);
index 9bb020ac089cddf6b665e8a52f728c95621ece34..0d30ca849e8f71502c9ecddfa9aa539e4e59af0f 100644 (file)
@@ -491,6 +491,7 @@ int isci_task_abort_task(struct sas_task *task)
        struct isci_tmf           tmf;
        int                       ret = TMF_RESP_FUNC_FAILED;
        unsigned long             flags;
+       int                       target_done_already = 0;
 
        /* Get the isci_request reference from the task.  Note that
         * this check does not depend on the pending request list
@@ -505,9 +506,11 @@ int isci_task_abort_task(struct sas_task *task)
        /* If task is already done, the request isn't valid */
        if (!(task->task_state_flags & SAS_TASK_STATE_DONE) &&
            (task->task_state_flags & SAS_TASK_AT_INITIATOR) &&
-           old_request)
+           old_request) {
                idev = isci_get_device(task->dev->lldd_dev);
-
+               target_done_already = test_bit(IREQ_COMPLETE_IN_TARGET,
+                                              &old_request->flags);
+       }
        spin_unlock(&task->task_state_lock);
        spin_unlock_irqrestore(&ihost->scic_lock, flags);
 
@@ -561,7 +564,7 @@ int isci_task_abort_task(struct sas_task *task)
 
        if (task->task_proto == SAS_PROTOCOL_SMP ||
            sas_protocol_ata(task->task_proto) ||
-           test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags) ||
+           target_done_already ||
            test_bit(IDEV_GONE, &idev->flags)) {
 
                spin_unlock_irqrestore(&ihost->scic_lock, flags);
index 3a9ddae86f1f8e2d5e33474a7f0f3510ec413c65..9b60dc129a5391c5f6a17c391794d546c46b4d8f 100644 (file)
@@ -3508,11 +3508,21 @@ static int megasas_init_fw(struct megasas_instance *instance)
                break;
        }
 
-       /*
-        * We expect the FW state to be READY
-        */
-       if (megasas_transition_to_ready(instance, 0))
-               goto fail_ready_state;
+       if (megasas_transition_to_ready(instance, 0)) {
+               atomic_set(&instance->fw_reset_no_pci_access, 1);
+               instance->instancet->adp_reset
+                       (instance, instance->reg_set);
+               atomic_set(&instance->fw_reset_no_pci_access, 0);
+               dev_info(&instance->pdev->dev,
+                       "megasas: FW restarted successfully from %s!\n",
+                       __func__);
+
+               /*waitting for about 30 second before retry*/
+               ssleep(30);
+
+               if (megasas_transition_to_ready(instance, 0))
+                       goto fail_ready_state;
+       }
 
        /* Check if MSI-X is supported while in ready state */
        msix_enable = (instance->instancet->read_fw_status_reg(reg_set) &
@@ -4852,10 +4862,12 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
                                    sense, sense_handle);
        }
 
-       for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) {
-               dma_free_coherent(&instance->pdev->dev,
-                                   kern_sge32[i].length,
-                                   kbuff_arr[i], kern_sge32[i].phys_addr);
+       for (i = 0; i < ioc->sge_count; i++) {
+               if (kbuff_arr[i])
+                       dma_free_coherent(&instance->pdev->dev,
+                                         kern_sge32[i].length,
+                                         kbuff_arr[i],
+                                         kern_sge32[i].phys_addr);
        }
 
        megasas_return_cmd(instance, cmd);
index bcb23d28b3e830f700e415acc36c453381abca9f..c76b18bbacb8b9e6097695222c59cb4895ac707a 100644 (file)
@@ -80,10 +80,6 @@ static int msix_disable = -1;
 module_param(msix_disable, int, 0);
 MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
 
-static int missing_delay[2] = {-1, -1};
-module_param_array(missing_delay, int, NULL, 0);
-MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
-
 static int mpt2sas_fwfault_debug;
 MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
        "and halt firmware - (default=0)");
@@ -2199,7 +2195,7 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
 }
 
 /**
- * _base_update_missing_delay - change the missing delay timers
+ * mpt2sas_base_update_missing_delay - change the missing delay timers
  * @ioc: per adapter object
  * @device_missing_delay: amount of time till device is reported missing
  * @io_missing_delay: interval IO is returned when there is a missing device
@@ -2210,8 +2206,8 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
  * delay, as well as the io missing delay. This should be called at driver
  * load time.
  */
-static void
-_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
+void
+mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
        u16 device_missing_delay, u8 io_missing_delay)
 {
        u16 dmd, dmd_new, dmd_orignal;
@@ -4407,9 +4403,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
        if (r)
                goto out_free_resources;
 
-       if (missing_delay[0] != -1 && missing_delay[1] != -1)
-               _base_update_missing_delay(ioc, missing_delay[0],
-                   missing_delay[1]);
        ioc->non_operational_loop = 0;
 
        return 0;
index 4caaac13682f3c04a0a4ccfbfd3944faf21466ba..11301974628ba465d04f5b4cc7205338ad2c261a 100644 (file)
@@ -1055,6 +1055,9 @@ void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_ty
 
 void mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc);
 
+void mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
+       u16 device_missing_delay, u8 io_missing_delay);
+
 int mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc);
 
 /* scsih shared API */
index c6bdc92672298acabb6da842ba840710894ca6ab..8dbe500c935d3d4ccd0c372359e09a1f070da666 100644 (file)
@@ -101,6 +101,10 @@ static ushort max_sectors = 0xFFFF;
 module_param(max_sectors, ushort, 0);
 MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 32767  default=32767");
 
+static int missing_delay[2] = {-1, -1};
+module_param_array(missing_delay, int, NULL, 0);
+MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
+
 /* scsi-mid layer global parmeter is max_report_luns, which is 511 */
 #define MPT2SAS_MAX_LUN (16895)
 static int max_lun = MPT2SAS_MAX_LUN;
@@ -3994,11 +3998,7 @@ _scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
                        else
                                mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
                } else
-/* MPI Revision I (UNIT = 0xA) - removed MPI2_SCSIIO_CONTROL_UNTAGGED */
-/*                     mpi_control |= MPI2_SCSIIO_CONTROL_UNTAGGED;
- */
-                       mpi_control |= (0x500);
-
+                       mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
        } else
                mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
        /* Make sure Device is not raid volume.
@@ -7303,7 +7303,9 @@ _firmware_event_work(struct work_struct *work)
        case MPT2SAS_PORT_ENABLE_COMPLETE:
                ioc->start_scan = 0;
 
-
+               if (missing_delay[0] != -1 && missing_delay[1] != -1)
+                       mpt2sas_base_update_missing_delay(ioc, missing_delay[0],
+                               missing_delay[1]);
 
                dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "port enable: complete "
                    "from worker thread\n", ioc->name));
index 4c1d2e7a11768a027063b546c408f0852cc98447..efb0c4c2e31000fd6f8e96777570c0d1086d1dae 100644 (file)
@@ -1,5 +1,5 @@
 # mpt3sas makefile
-obj-m += mpt3sas.o
+obj-$(CONFIG_SCSI_MPT3SAS) += mpt3sas.o
 mpt3sas-y +=  mpt3sas_base.o     \
                mpt3sas_config.o \
                mpt3sas_scsih.o      \
index dcbf7c880cb282502b4e0b55f77d317f3f0b4496..f8c4b8564251d80ebab899544bc98dd7ba1b0e30 100644 (file)
@@ -1273,6 +1273,7 @@ _scsih_slave_alloc(struct scsi_device *sdev)
        struct MPT3SAS_DEVICE *sas_device_priv_data;
        struct scsi_target *starget;
        struct _raid_device *raid_device;
+       struct _sas_device *sas_device;
        unsigned long flags;
 
        sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
@@ -1301,6 +1302,19 @@ _scsih_slave_alloc(struct scsi_device *sdev)
                spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
        }
 
+       if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+                                       sas_target_priv_data->sas_address);
+               if (sas_device && (sas_device->starget == NULL)) {
+                       sdev_printk(KERN_INFO, sdev,
+                       "%s : sas_device->starget set to starget @ %d\n",
+                               __func__, __LINE__);
+                       sas_device->starget = starget;
+               }
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       }
+
        return 0;
 }
 
@@ -6392,7 +6406,7 @@ _scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
            handle))) {
                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
                    MPI2_IOCSTATUS_MASK;
-               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
                        break;
                handle = le16_to_cpu(sas_device_pg0.DevHandle);
                device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
@@ -6494,7 +6508,7 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
            &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
                    MPI2_IOCSTATUS_MASK;
-               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
                        break;
                handle = le16_to_cpu(volume_pg1.DevHandle);
 
@@ -6518,7 +6532,7 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
                    phys_disk_num))) {
                        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
                            MPI2_IOCSTATUS_MASK;
-                       if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                       if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
                                break;
                        phys_disk_num = pd_pg0.PhysDiskNum;
                        handle = le16_to_cpu(pd_pg0.DevHandle);
@@ -6597,7 +6611,7 @@ _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc)
 
                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
                    MPI2_IOCSTATUS_MASK;
-               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
                        break;
 
                handle = le16_to_cpu(expander_pg0.DevHandle);
@@ -6742,8 +6756,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
            MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
                    MPI2_IOCSTATUS_MASK;
-               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
-                       break;
                if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
                        pr_info(MPT3SAS_FMT "\tbreak from expander scan: " \
                            "ioc_status(0x%04x), loginfo(0x%08x)\n",
@@ -6787,8 +6799,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
            phys_disk_num))) {
                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
                    MPI2_IOCSTATUS_MASK;
-               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
-                       break;
                if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
                        pr_info(MPT3SAS_FMT "\tbreak from phys disk scan: "\
                            "ioc_status(0x%04x), loginfo(0x%08x)\n",
@@ -6854,8 +6864,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
            &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
                    MPI2_IOCSTATUS_MASK;
-               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
-                       break;
                if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
                        pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \
                            "ioc_status(0x%04x), loginfo(0x%08x)\n",
@@ -6914,8 +6922,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
            handle))) {
                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
                    MPI2_IOCSTATUS_MASK;
-               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
-                       break;
                if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
                        pr_info(MPT3SAS_FMT "\tbreak from end device scan:"\
                            " ioc_status(0x%04x), loginfo(0x%08x)\n",
index 1e3879dcbdcc70d2d3b8e02d6aa341458a044843..0665f9cfdb02d7fb5c4fc415f969ee309c37690e 100644 (file)
@@ -2899,7 +2899,7 @@ static void nsp32_do_bus_reset(nsp32_hw_data *data)
         * reset SCSI bus
         */
        nsp32_write1(base, SCSI_BUS_CONTROL, BUSCTL_RST);
-       udelay(RESET_HOLD_TIME);
+       mdelay(RESET_HOLD_TIME / 1000);
        nsp32_write1(base, SCSI_BUS_CONTROL, 0);
        for(i = 0; i < 5; i++) {
                intrdat = nsp32_read2(base, IRQ_STATUS); /* dummy read */
index 0fab6b5c7b8293da875bce94b5bdca9a9c97e41a..9d86947d67fe25802b5e172fdd60cd2b08486e8e 100644 (file)
@@ -485,7 +485,7 @@ static int osd_probe(struct device *dev)
        oud->class_dev.class = &osd_uld_class;
        oud->class_dev.parent = dev;
        oud->class_dev.release = __remove;
-       error = dev_set_name(&oud->class_dev, disk->disk_name);
+       error = dev_set_name(&oud->class_dev, "%s", disk->disk_name);
        if (error) {
                OSD_ERR("dev_set_name failed => %d\n", error);
                goto err_put_cdev;
index 69dd49c05f1e1069b2aea0544734f52ea5126abb..ce3f129d39bf8961601aa71789d7147f2d193b05 100644 (file)
@@ -221,7 +221,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
        pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_interrupt          = 0x01;
        for (i = 0; i < PM8001_MAX_INB_NUM; i++) {
                pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt  =
-                       PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30);
+                       PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30);
                pm8001_ha->inbnd_q_tbl[i].upper_base_addr       =
                        pm8001_ha->memoryMap.region[IB + i].phys_addr_hi;
                pm8001_ha->inbnd_q_tbl[i].lower_base_addr       =
@@ -247,7 +247,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
        }
        for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) {
                pm8001_ha->outbnd_q_tbl[i].element_size_cnt     =
-                       PM8001_MPI_QUEUE | (64 << 16) | (0x01<<30);
+                       PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30);
                pm8001_ha->outbnd_q_tbl[i].upper_base_addr      =
                        pm8001_ha->memoryMap.region[OB + i].phys_addr_hi;
                pm8001_ha->outbnd_q_tbl[i].lower_base_addr      =
index 302514d8157b78ffdce87ef3b32db4cbf4aaa7aa..e1c48961ceac046b93e615547b78eef966aaa25e 100644 (file)
@@ -275,7 +275,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
 
        for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) {
                pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt  =
-                       PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30);
+                       PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30);
                pm8001_ha->inbnd_q_tbl[i].upper_base_addr       =
                        pm8001_ha->memoryMap.region[IB + i].phys_addr_hi;
                pm8001_ha->inbnd_q_tbl[i].lower_base_addr       =
@@ -301,7 +301,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
        }
        for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
                pm8001_ha->outbnd_q_tbl[i].element_size_cnt     =
-                       PM8001_MPI_QUEUE | (64 << 16) | (0x01<<30);
+                       PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30);
                pm8001_ha->outbnd_q_tbl[i].upper_base_addr      =
                        pm8001_ha->memoryMap.region[OB + i].phys_addr_hi;
                pm8001_ha->outbnd_q_tbl[i].lower_base_addr      =
index 15e4080b347cd1ed69c9b905125d2001332d3ae9..51cd27a50309022775a41b914ec5c1c2a652d53b 100644 (file)
@@ -419,6 +419,8 @@ qla2x00_start_scsi(srb_t *sp)
                            __constant_cpu_to_le16(CF_SIMPLE_TAG);
                        break;
                }
+       } else {
+               cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG);
        }
 
        /* Load SCSI command packet. */
@@ -1308,11 +1310,11 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
                    fcp_cmnd->task_attribute = TSK_ORDERED;
                    break;
                default:
-                   fcp_cmnd->task_attribute = 0;
+                   fcp_cmnd->task_attribute = TSK_SIMPLE;
                    break;
                }
        } else {
-               fcp_cmnd->task_attribute = 0;
+               fcp_cmnd->task_attribute = TSK_SIMPLE;
        }
 
        cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */
@@ -1527,7 +1529,12 @@ qla24xx_start_scsi(srb_t *sp)
                case ORDERED_QUEUE_TAG:
                        cmd_pkt->task = TSK_ORDERED;
                        break;
+               default:
+                   cmd_pkt->task = TSK_SIMPLE;
+                   break;
                }
+       } else {
+               cmd_pkt->task = TSK_SIMPLE;
        }
 
        /* Load SCSI command packet. */
index 2c0d0ec8150b62d62d8ca3ca9ecc777a950a7c0a..eaa808e6ba91c78f13748a6ab3977c9c174c20f9 100644 (file)
@@ -1031,6 +1031,9 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf,
 {
        int i, result;
 
+       if (sdev->skip_vpd_pages)
+               goto fail;
+
        /* Ask for all the pages supported by this device */
        result = scsi_vpd_inquiry(sdev, buf, 0, buf_len);
        if (result)
@@ -1070,8 +1073,8 @@ EXPORT_SYMBOL_GPL(scsi_get_vpd_page);
  * @opcode:    opcode for command to look up
  *
  * Uses the REPORT SUPPORTED OPERATION CODES to look up the given
- * opcode. Returns 0 if RSOC fails or if the command opcode is
- * unsupported. Returns 1 if the device claims to support the command.
+ * opcode. Returns -EINVAL if RSOC fails, 0 if the command opcode is
+ * unsupported and 1 if the device claims to support the command.
  */
 int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
                       unsigned int len, unsigned char opcode)
@@ -1081,7 +1084,7 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
        int result;
 
        if (sdev->no_report_opcodes || sdev->scsi_level < SCSI_SPC_3)
-               return 0;
+               return -EINVAL;
 
        memset(cmd, 0, 16);
        cmd[0] = MAINTENANCE_IN;
@@ -1097,7 +1100,7 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
        if (result && scsi_sense_valid(&sshdr) &&
            sshdr.sense_key == ILLEGAL_REQUEST &&
            (sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00)
-               return 0;
+               return -EINVAL;
 
        if ((buffer[1] & 3) == 3) /* Command supported */
                return 1;
index c1c555242d0d715d46c051955deacea4a819d634..c39863441337cd8982472af8e0ba4e68b60a49c6 100644 (file)
@@ -142,7 +142,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
        char *buffer_data;
        struct scsi_mode_data data;
        struct scsi_sense_hdr sshdr;
-       const char *temp = "temporary ";
+       static const char temp[] = "temporary ";
        int len;
 
        if (sdp->type != TYPE_DISK)
@@ -442,8 +442,10 @@ sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr,
 
        if (max == 0)
                sdp->no_write_same = 1;
-       else if (max <= SD_MAX_WS16_BLOCKS)
+       else if (max <= SD_MAX_WS16_BLOCKS) {
+               sdp->no_write_same = 0;
                sdkp->max_ws_blocks = max;
+       }
 
        sd_config_write_same(sdkp);
 
@@ -740,7 +742,6 @@ static void sd_config_write_same(struct scsi_disk *sdkp)
 {
        struct request_queue *q = sdkp->disk->queue;
        unsigned int logical_block_size = sdkp->device->sector_size;
-       unsigned int blocks = 0;
 
        if (sdkp->device->no_write_same) {
                sdkp->max_ws_blocks = 0;
@@ -752,18 +753,20 @@ static void sd_config_write_same(struct scsi_disk *sdkp)
         * blocks per I/O unless the device explicitly advertises a
         * bigger limit.
         */
-       if (sdkp->max_ws_blocks == 0)
-               sdkp->max_ws_blocks = SD_MAX_WS10_BLOCKS;
-
-       if (sdkp->ws16 || sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS)
-               blocks = min_not_zero(sdkp->max_ws_blocks,
-                                     (u32)SD_MAX_WS16_BLOCKS);
-       else
-               blocks = min_not_zero(sdkp->max_ws_blocks,
-                                     (u32)SD_MAX_WS10_BLOCKS);
+       if (sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS)
+               sdkp->max_ws_blocks = min_not_zero(sdkp->max_ws_blocks,
+                                                  (u32)SD_MAX_WS16_BLOCKS);
+       else if (sdkp->ws16 || sdkp->ws10 || sdkp->device->no_report_opcodes)
+               sdkp->max_ws_blocks = min_not_zero(sdkp->max_ws_blocks,
+                                                  (u32)SD_MAX_WS10_BLOCKS);
+       else {
+               sdkp->device->no_write_same = 1;
+               sdkp->max_ws_blocks = 0;
+       }
 
 out:
-       blk_queue_max_write_same_sectors(q, blocks * (logical_block_size >> 9));
+       blk_queue_max_write_same_sectors(q, sdkp->max_ws_blocks *
+                                        (logical_block_size >> 9));
 }
 
 /**
@@ -825,10 +828,17 @@ static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
 
 static void sd_unprep_fn(struct request_queue *q, struct request *rq)
 {
+       struct scsi_cmnd *SCpnt = rq->special;
+
        if (rq->cmd_flags & REQ_DISCARD) {
                free_page((unsigned long)rq->buffer);
                rq->buffer = NULL;
        }
+       if (SCpnt->cmnd != rq->cmd) {
+               mempool_free(SCpnt->cmnd, sd_cdb_pool);
+               SCpnt->cmnd = NULL;
+               SCpnt->cmd_len = 0;
+       }
 }
 
 /**
@@ -1707,21 +1717,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
        if (rq_data_dir(SCpnt->request) == READ && scsi_prot_sg_count(SCpnt))
                sd_dif_complete(SCpnt, good_bytes);
 
-       if (scsi_host_dif_capable(sdkp->device->host, sdkp->protection_type)
-           == SD_DIF_TYPE2_PROTECTION && SCpnt->cmnd != SCpnt->request->cmd) {
-
-               /* We have to print a failed command here as the
-                * extended CDB gets freed before scsi_io_completion()
-                * is called.
-                */
-               if (result)
-                       scsi_print_command(SCpnt);
-
-               mempool_free(SCpnt->cmnd, sd_cdb_pool);
-               SCpnt->cmnd = NULL;
-               SCpnt->cmd_len = 0;
-       }
-
        return good_bytes;
 }
 
@@ -2414,14 +2409,9 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
                        }
                }
 
-               if (modepage == 0x3F) {
-                       sd_printk(KERN_ERR, sdkp, "No Caching mode page "
-                                 "present\n");
-                       goto defaults;
-               } else if ((buffer[offset] & 0x3f) != modepage) {
-                       sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
-                       goto defaults;
-               }
+               sd_printk(KERN_ERR, sdkp, "No Caching mode page found\n");
+               goto defaults;
+
        Page_found:
                if (modepage == 8) {
                        sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);
@@ -2635,9 +2625,24 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp)
 
 static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
 {
-       if (scsi_report_opcode(sdkp->device, buffer, SD_BUF_SIZE,
-                              WRITE_SAME_16))
+       struct scsi_device *sdev = sdkp->device;
+
+       if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) {
+               sdev->no_report_opcodes = 1;
+
+               /* Disable WRITE SAME if REPORT SUPPORTED OPERATION
+                * CODES is unsupported and the device has an ATA
+                * Information VPD page (SAT).
+                */
+               if (!scsi_get_vpd_page(sdev, 0x89, buffer, SD_BUF_SIZE))
+                       sdev->no_write_same = 1;
+       }
+
+       if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16) == 1)
                sdkp->ws16 = 1;
+
+       if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME) == 1)
+               sdkp->ws10 = 1;
 }
 
 static int sd_try_extended_inquiry(struct scsi_device *sdp)
index 2386aeb41fe8d74826908d3dca71eb3f97a59ac8..7a049de220512777dd8d1cb43e665a9c351023d5 100644 (file)
@@ -84,6 +84,7 @@ struct scsi_disk {
        unsigned        lbpws : 1;
        unsigned        lbpws10 : 1;
        unsigned        lbpvpd : 1;
+       unsigned        ws10 : 1;
        unsigned        ws16 : 1;
 };
 #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
index 2168258fb2c3a2cf5374a3592a302062d75bb305..74b88efde6ad408123de6a9b96ec37460195fe82 100644 (file)
@@ -751,7 +751,7 @@ static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity)
 
                vscsi->affinity_hint_set = true;
        } else {
-               for (i = 0; i < vscsi->num_queues - VIRTIO_SCSI_VQ_BASE; i++)
+               for (i = 0; i < vscsi->num_queues; i++)
                        virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1);
 
                vscsi->affinity_hint_set = false;
index 50b13c9b1ab691fd5defcae44b98dc4bfccb5557..df0aacc6fc3b496f47eda7f96f0cb58954f844a9 100644 (file)
@@ -610,7 +610,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
                else
                        buf = (void *)t->tx_buf;
                t->tx_dma = dma_map_single(&spi->dev, buf,
-                               t->len, DMA_FROM_DEVICE);
+                               t->len, DMA_TO_DEVICE);
                if (!t->tx_dma) {
                        ret = -EFAULT;
                        goto err_tx_map;
index 9bd874789ce5fc93906a78f62a68e542541bd288..34519ea14b5429e0e3ac91125d472dbe0f1d234c 100644 (file)
@@ -469,7 +469,7 @@ static ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
                         unsigned long nr_segs, loff_t ppos)
 {
        struct logger_log *log = file_get_log(iocb->ki_filp);
-       size_t orig = log->w_off;
+       size_t orig;
        struct logger_entry header;
        struct timespec now;
        ssize_t ret = 0;
@@ -490,6 +490,8 @@ static ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
 
        mutex_lock(&log->mutex);
 
+       orig = log->w_off;
+
        /*
         * Fix up any readers, pulling them forward to the first readable
         * entry after (what will be) the new write offset. We do this now
index 924c54c9c31fad595d1cdf9331db17d8c40413f4..0ae406a475073cbcf9366256a226c4b3d8c3ce60 100644 (file)
@@ -1401,22 +1401,19 @@ static int do_cmd_ioctl(struct comedi_device *dev,
                DPRINTK("subdevice busy\n");
                return -EBUSY;
        }
-       s->busy = file;
 
        /* make sure channel/gain list isn't too long */
        if (cmd.chanlist_len > s->len_chanlist) {
                DPRINTK("channel/gain list too long %u > %d\n",
                        cmd.chanlist_len, s->len_chanlist);
-               ret = -EINVAL;
-               goto cleanup;
+               return -EINVAL;
        }
 
        /* make sure channel/gain list isn't too short */
        if (cmd.chanlist_len < 1) {
                DPRINTK("channel/gain list too short %u < 1\n",
                        cmd.chanlist_len);
-               ret = -EINVAL;
-               goto cleanup;
+               return -EINVAL;
        }
 
        async->cmd = cmd;
@@ -1426,8 +1423,7 @@ static int do_cmd_ioctl(struct comedi_device *dev,
            kmalloc(async->cmd.chanlist_len * sizeof(int), GFP_KERNEL);
        if (!async->cmd.chanlist) {
                DPRINTK("allocation failed\n");
-               ret = -ENOMEM;
-               goto cleanup;
+               return -ENOMEM;
        }
 
        if (copy_from_user(async->cmd.chanlist, user_chanlist,
@@ -1479,6 +1475,9 @@ static int do_cmd_ioctl(struct comedi_device *dev,
 
        comedi_set_subdevice_runflags(s, ~0, SRF_USER | SRF_RUNNING);
 
+       /* set s->busy _after_ setting SRF_RUNNING flag to avoid race with
+        * comedi_read() or comedi_write() */
+       s->busy = file;
        ret = s->do_cmd(dev, s);
        if (ret == 0)
                return 0;
@@ -1693,6 +1692,7 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg,
                           void *file)
 {
        struct comedi_subdevice *s;
+       int ret;
 
        if (arg >= dev->n_subdevices)
                return -EINVAL;
@@ -1709,7 +1709,11 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg,
        if (s->busy != file)
                return -EBUSY;
 
-       return do_cancel(dev, s);
+       ret = do_cancel(dev, s);
+       if (comedi_get_subdevice_runflags(s) & SRF_USER)
+               wake_up_interruptible(&s->async->wait_head);
+
+       return ret;
 }
 
 /*
@@ -2041,11 +2045,13 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
 
                if (!comedi_is_subdevice_running(s)) {
                        if (count == 0) {
+                               mutex_lock(&dev->mutex);
                                if (comedi_is_subdevice_in_error(s))
                                        retval = -EPIPE;
                                else
                                        retval = 0;
                                do_become_nonbusy(dev, s);
+                               mutex_unlock(&dev->mutex);
                        }
                        break;
                }
@@ -2144,11 +2150,13 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
 
                if (n == 0) {
                        if (!comedi_is_subdevice_running(s)) {
+                               mutex_lock(&dev->mutex);
                                do_become_nonbusy(dev, s);
                                if (comedi_is_subdevice_in_error(s))
                                        retval = -EPIPE;
                                else
                                        retval = 0;
+                               mutex_unlock(&dev->mutex);
                                break;
                        }
                        if (file->f_flags & O_NONBLOCK) {
@@ -2186,9 +2194,11 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
                buf += n;
                break;          /* makes device work like a pipe */
        }
-       if (comedi_is_subdevice_idle(s) &&
-           async->buf_read_count - async->buf_write_count == 0) {
-               do_become_nonbusy(dev, s);
+       if (comedi_is_subdevice_idle(s)) {
+               mutex_lock(&dev->mutex);
+               if (async->buf_read_count - async->buf_write_count == 0)
+                       do_become_nonbusy(dev, s);
+               mutex_unlock(&dev->mutex);
        }
        set_current_state(TASK_RUNNING);
        remove_wait_queue(&async->wait_head, &wait);
index 06d190f8fd34a5c81e0cccf97419f3e50b12fef4..4a2b04277304e478ddf4e3e55a58642481eb876a 100644 (file)
@@ -464,7 +464,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                ret = comedi_device_postconfig(dev);
        if (ret < 0) {
                comedi_device_detach(dev);
-               module_put(dev->driver->module);
+               module_put(driv->module);
        }
        /* On success, the driver module count has been incremented. */
        return ret;
index 90f2de9bc402d614ea965a587f3ec287a636e511..f4c1e998cbe9b259eac0f4117f255562bbbb1dcc 100644 (file)
@@ -269,8 +269,9 @@ struct dt282x_private {
                        }                                       \
                        udelay(5);                              \
                }                                               \
-               if (_i)                                         \
+               if (_i) {                                       \
                        b                                       \
+               }                                               \
        } while (0)
 
 static int prep_ai_dma(struct comedi_device *dev, int chan, int size);
index 163c638e4095f3b893668bb5d83e8e2110b76afb..972a0723afaccc617cdc4a68142dbc5c57070c8e 100644 (file)
@@ -234,7 +234,6 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
 {
        struct mxs_lradc *lradc = iio_priv(iio_dev);
        int ret;
-       unsigned long mask;
 
        if (m != IIO_CHAN_INFO_RAW)
                return -EINVAL;
@@ -243,12 +242,6 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
        if (chan->channel > LRADC_MAX_TOTAL_CHANS)
                return -EINVAL;
 
-       /* Validate the channel if it doesn't intersect with reserved chans. */
-       bitmap_set(&mask, chan->channel, 1);
-       ret = iio_validate_scan_mask_onehot(iio_dev, &mask);
-       if (ret)
-               return -EINVAL;
-
        /*
         * See if there is no buffered operation in progess. If there is, simply
         * bail out. This can be improved to support both buffered and raw IO at
@@ -661,12 +654,13 @@ static int mxs_lradc_trigger_init(struct iio_dev *iio)
 {
        int ret;
        struct iio_trigger *trig;
+       struct mxs_lradc *lradc = iio_priv(iio);
 
        trig = iio_trigger_alloc("%s-dev%i", iio->name, iio->id);
        if (trig == NULL)
                return -ENOMEM;
 
-       trig->dev.parent = iio->dev.parent;
+       trig->dev.parent = lradc->dev;
        iio_trigger_set_drvdata(trig, iio);
        trig->ops = &mxs_lradc_trigger_ops;
 
@@ -676,15 +670,17 @@ static int mxs_lradc_trigger_init(struct iio_dev *iio)
                return ret;
        }
 
-       iio->trig = trig;
+       lradc->trig = trig;
 
        return 0;
 }
 
 static void mxs_lradc_trigger_remove(struct iio_dev *iio)
 {
-       iio_trigger_unregister(iio->trig);
-       iio_trigger_free(iio->trig);
+       struct mxs_lradc *lradc = iio_priv(iio);
+
+       iio_trigger_unregister(lradc->trig);
+       iio_trigger_free(lradc->trig);
 }
 
 static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
index 64553058b67ee8c81229028e3e64bdc233100df2..a532ca5685261e0e9a233dd8a95cf4c7647a1b4e 100644 (file)
@@ -681,6 +681,7 @@ found:
 
        return i;
 }
+EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id);
 
 /*
  * imx_drm_remove_encoder - remove an encoder
index 02f77d74809f3d15572c82ad44b79ebac2dc33b0..a7856bad3cc61e3e88b80871346fcde4a3a53ccf 100644 (file)
@@ -385,8 +385,11 @@ static int snd_line6_pcm_free(struct snd_device *device)
 */
 static void pcm_disconnect_substream(struct snd_pcm_substream *substream)
 {
-       if (substream->runtime && snd_pcm_running(substream))
+       if (substream->runtime && snd_pcm_running(substream)) {
+               snd_pcm_stream_lock_irq(substream);
                snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
+               snd_pcm_stream_unlock_irq(substream);
+       }
 }
 
 /*
index dcceed29d31ae415818d1fceecc6518cbc017845..81972fa47bebab17ad635a4d855d5cd691f5daad 100644 (file)
@@ -1811,10 +1811,12 @@ static int zcache_comp_init(void)
 #else
        if (*zcache_comp_name != '\0') {
                ret = crypto_has_comp(zcache_comp_name, 0, 0);
-               if (!ret)
+               if (!ret) {
                        pr_info("zcache: %s not supported\n",
                                        zcache_comp_name);
-               goto out;
+                       ret = 1;
+                       goto out;
+               }
        }
        if (!ret)
                strcpy(zcache_comp_name, "lzo");
index e34e3fe0ae2e61f12f7c167ba74588d663dee09a..a333d44d0cffbeaa1412155a197f88f43ed063c9 100644 (file)
@@ -272,8 +272,6 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 
        if (page_zero_filled(uncmem)) {
                kunmap_atomic(user_mem);
-               if (is_partial_io(bvec))
-                       kfree(uncmem);
                zram->stats.pages_zero++;
                zram_set_flag(meta, index, ZRAM_ZERO);
                ret = 0;
@@ -422,13 +420,20 @@ out:
  */
 static inline int valid_io_request(struct zram *zram, struct bio *bio)
 {
-       if (unlikely(
-               (bio->bi_sector >= (zram->disksize >> SECTOR_SHIFT)) ||
-               (bio->bi_sector & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1)) ||
-               (bio->bi_size & (ZRAM_LOGICAL_BLOCK_SIZE - 1)))) {
+       u64 start, end, bound;
 
+       /* unaligned request */
+       if (unlikely(bio->bi_sector & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1)))
+               return 0;
+       if (unlikely(bio->bi_size & (ZRAM_LOGICAL_BLOCK_SIZE - 1)))
+               return 0;
+
+       start = bio->bi_sector;
+       end = start + (bio->bi_size >> SECTOR_SHIFT);
+       bound = zram->disksize >> SECTOR_SHIFT;
+       /* out of range range */
+       if (unlikely(start >= bound || end > bound || start > end))
                return 0;
-       }
 
        /* I/O request is valid */
        return 1;
@@ -582,7 +587,9 @@ static void zram_slot_free_notify(struct block_device *bdev,
        struct zram *zram;
 
        zram = bdev->bd_disk->private_data;
+       down_write(&zram->lock);
        zram_free_page(zram, index);
+       up_write(&zram->lock);
        zram_stat64_inc(zram, &zram->stats.notify_free);
 }
 
@@ -593,7 +600,7 @@ static const struct block_device_operations zram_devops = {
 
 static int create_device(struct zram *zram, int device_id)
 {
-       int ret = 0;
+       int ret = -ENOMEM;
 
        init_rwsem(&zram->lock);
        init_rwsem(&zram->init_lock);
@@ -603,7 +610,6 @@ static int create_device(struct zram *zram, int device_id)
        if (!zram->queue) {
                pr_err("Error allocating disk queue for device %d\n",
                        device_id);
-               ret = -ENOMEM;
                goto out;
        }
 
@@ -613,11 +619,9 @@ static int create_device(struct zram *zram, int device_id)
         /* gendisk structure */
        zram->disk = alloc_disk(1);
        if (!zram->disk) {
-               blk_cleanup_queue(zram->queue);
                pr_warn("Error allocating disk structure for device %d\n",
                        device_id);
-               ret = -ENOMEM;
-               goto out;
+               goto out_free_queue;
        }
 
        zram->disk->major = zram_major;
@@ -646,11 +650,17 @@ static int create_device(struct zram *zram, int device_id)
                                &zram_disk_attr_group);
        if (ret < 0) {
                pr_warn("Error creating sysfs group");
-               goto out;
+               goto out_free_disk;
        }
 
        zram->init_done = 0;
+       return 0;
 
+out_free_disk:
+       del_gendisk(zram->disk);
+       put_disk(zram->disk);
+out_free_queue:
+       blk_cleanup_queue(zram->queue);
 out:
        return ret;
 }
@@ -727,8 +737,10 @@ static void __exit zram_exit(void)
        for (i = 0; i < num_devices; i++) {
                zram = &zram_devices[i];
 
+               get_disk(zram->disk);
                destroy_device(zram);
                zram_reset_device(zram);
+               put_disk(zram->disk);
        }
 
        unregister_blkdev(zram_major, "zram");
index 2d1a3f1e8edbdff9dc049d50339ffebcb6056d0d..d542eee81357582cf95bd4e296bb1610c2a7d7f8 100644 (file)
@@ -93,8 +93,9 @@ struct zram_meta {
 struct zram {
        struct zram_meta *meta;
        spinlock_t stat64_lock; /* protect 64-bit stats */
-       struct rw_semaphore lock; /* protect compression buffers and table
-                                  * against concurrent read and writes */
+       struct rw_semaphore lock; /* protect compression buffers, table,
+                                  * 32bit stat counters against concurrent
+                                  * notifications, reads and writes */
        struct request_queue *queue;
        struct gendisk *disk;
        int init_done;
index e6a929d452f72cda5b9953e1b9b0a1b3c15cb13d..dc76a3dba1b8d918f42d59cdc1cf1c6ae39de79d 100644 (file)
@@ -188,8 +188,10 @@ static ssize_t mem_used_total_show(struct device *dev,
        struct zram *zram = dev_to_zram(dev);
        struct zram_meta *meta = zram->meta;
 
+       down_read(&zram->init_lock);
        if (zram->init_done)
                val = zs_get_total_size_bytes(meta->mem_pool);
+       up_read(&zram->init_lock);
 
        return sprintf(buf, "%llu\n", val);
 }
index d7705e5824fb2d39205d55846d560df2a8a03270..4c1b8dbdcb36566574144c5d59d43a6ed16a2d07 100644 (file)
@@ -628,25 +628,18 @@ static void __exit iscsi_target_cleanup_module(void)
 }
 
 static int iscsit_add_reject(
+       struct iscsi_conn *conn,
        u8 reason,
-       int fail_conn,
-       unsigned char *buf,
-       struct iscsi_conn *conn)
+       unsigned char *buf)
 {
        struct iscsi_cmd *cmd;
-       struct iscsi_reject *hdr;
-       int ret;
 
        cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
        if (!cmd)
                return -1;
 
        cmd->iscsi_opcode = ISCSI_OP_REJECT;
-       if (fail_conn)
-               cmd->cmd_flags |= ICF_REJECT_FAIL_CONN;
-
-       hdr     = (struct iscsi_reject *) cmd->pdu;
-       hdr->reason = reason;
+       cmd->reject_reason = reason;
 
        cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
        if (!cmd->buf_ptr) {
@@ -662,23 +655,16 @@ static int iscsit_add_reject(
        cmd->i_state = ISTATE_SEND_REJECT;
        iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
 
-       ret = wait_for_completion_interruptible(&cmd->reject_comp);
-       if (ret != 0)
-               return -1;
-
-       return (!fail_conn) ? 0 : -1;
+       return -1;
 }
 
-int iscsit_add_reject_from_cmd(
+static int iscsit_add_reject_from_cmd(
+       struct iscsi_cmd *cmd,
        u8 reason,
-       int fail_conn,
-       int add_to_conn,
-       unsigned char *buf,
-       struct iscsi_cmd *cmd)
+       bool add_to_conn,
+       unsigned char *buf)
 {
        struct iscsi_conn *conn;
-       struct iscsi_reject *hdr;
-       int ret;
 
        if (!cmd->conn) {
                pr_err("cmd->conn is NULL for ITT: 0x%08x\n",
@@ -688,11 +674,7 @@ int iscsit_add_reject_from_cmd(
        conn = cmd->conn;
 
        cmd->iscsi_opcode = ISCSI_OP_REJECT;
-       if (fail_conn)
-               cmd->cmd_flags |= ICF_REJECT_FAIL_CONN;
-
-       hdr     = (struct iscsi_reject *) cmd->pdu;
-       hdr->reason = reason;
+       cmd->reject_reason = reason;
 
        cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
        if (!cmd->buf_ptr) {
@@ -709,8 +691,6 @@ int iscsit_add_reject_from_cmd(
 
        cmd->i_state = ISTATE_SEND_REJECT;
        iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
-
-       ret = wait_for_completion_interruptible(&cmd->reject_comp);
        /*
         * Perform the kref_put now if se_cmd has already been setup by
         * scsit_setup_scsi_cmd()
@@ -719,12 +699,19 @@ int iscsit_add_reject_from_cmd(
                pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n");
                target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
        }
-       if (ret != 0)
-               return -1;
+       return -1;
+}
 
-       return (!fail_conn) ? 0 : -1;
+static int iscsit_add_reject_cmd(struct iscsi_cmd *cmd, u8 reason,
+                                unsigned char *buf)
+{
+       return iscsit_add_reject_from_cmd(cmd, reason, true, buf);
+}
+
+int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8 reason, unsigned char *buf)
+{
+       return iscsit_add_reject_from_cmd(cmd, reason, false, buf);
 }
-EXPORT_SYMBOL(iscsit_add_reject_from_cmd);
 
 /*
  * Map some portion of the allocated scatterlist to an iovec, suitable for
@@ -844,8 +831,8 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
            !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) {
                pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL"
                                " not set. Bad iSCSI Initiator.\n");
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
        }
 
        if (((hdr->flags & ISCSI_FLAG_CMD_READ) ||
@@ -865,8 +852,8 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
                        " set when Expected Data Transfer Length is 0 for"
                        " CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
        }
 done:
 
@@ -875,62 +862,62 @@ done:
                pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE"
                        " MUST be set if Expected Data Transfer Length is not 0."
                        " Bad iSCSI Initiator\n");
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
        }
 
        if ((hdr->flags & ISCSI_FLAG_CMD_READ) &&
            (hdr->flags & ISCSI_FLAG_CMD_WRITE)) {
                pr_err("Bidirectional operations not supported!\n");
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
        }
 
        if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
                pr_err("Illegally set Immediate Bit in iSCSI Initiator"
                                " Scsi Command PDU.\n");
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
        }
 
        if (payload_length && !conn->sess->sess_ops->ImmediateData) {
                pr_err("ImmediateData=No but DataSegmentLength=%u,"
                        " protocol error.\n", payload_length);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
 
-       if ((be32_to_cpu(hdr->data_length )== payload_length) &&
+       if ((be32_to_cpu(hdr->data_length== payload_length) &&
            (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))) {
                pr_err("Expected Data Transfer Length and Length of"
                        " Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL"
                        " bit is not set protocol error\n");
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
 
        if (payload_length > be32_to_cpu(hdr->data_length)) {
                pr_err("DataSegmentLength: %u is greater than"
                        " EDTL: %u, protocol error.\n", payload_length,
                                hdr->data_length);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
 
        if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
                pr_err("DataSegmentLength: %u is greater than"
                        " MaxXmitDataSegmentLength: %u, protocol error.\n",
                        payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
 
        if (payload_length > conn->sess->sess_ops->FirstBurstLength) {
                pr_err("DataSegmentLength: %u is greater than"
                        " FirstBurstLength: %u, protocol error.\n",
                        payload_length, conn->sess->sess_ops->FirstBurstLength);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
        }
 
        data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE :
@@ -985,9 +972,8 @@ done:
 
                dr = iscsit_allocate_datain_req();
                if (!dr)
-                       return iscsit_add_reject_from_cmd(
-                                       ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                       1, 1, buf, cmd);
+                       return iscsit_add_reject_cmd(cmd,
+                                       ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
 
                iscsit_attach_datain_req(cmd, dr);
        }
@@ -1015,18 +1001,16 @@ done:
        cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb);
        if (cmd->sense_reason) {
                if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) {
-                       return iscsit_add_reject_from_cmd(
-                                       ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                       1, 1, buf, cmd);
+                       return iscsit_add_reject_cmd(cmd,
+                                       ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
                }
 
                goto attach_cmd;
        }
 
        if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) {
-               return iscsit_add_reject_from_cmd(
-                       ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                       1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                               ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
        }
 
 attach_cmd:
@@ -1068,17 +1052,13 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
         * be acknowledged. (See below)
         */
        if (!cmd->immediate_data) {
-               cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
-               if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
-                       if (!cmd->sense_reason)
-                               return 0;
-
+               cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
+                                       (unsigned char *)hdr, hdr->cmdsn);
+               if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
+                       return -1;
+               else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
                        target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
                        return 0;
-               } else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) {
-                       return iscsit_add_reject_from_cmd(
-                               ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 0, (unsigned char *)hdr, cmd);
                }
        }
 
@@ -1103,7 +1083,9 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
         * iscsit_check_received_cmdsn() in iscsit_get_immediate_data() below.
         */
        if (cmd->sense_reason) {
-               target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
+               if (cmd->reject_reason)
+                       return 0;
+
                return 1;
        }
        /*
@@ -1111,10 +1093,8 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
         * the backend memory allocation.
         */
        cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd);
-       if (cmd->sense_reason) {
-               target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
+       if (cmd->sense_reason)
                return 1;
-       }
 
        return 0;
 }
@@ -1124,6 +1104,7 @@ static int
 iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,
                          bool dump_payload)
 {
+       struct iscsi_conn *conn = cmd->conn;
        int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
        /*
         * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes.
@@ -1140,20 +1121,21 @@ after_immediate_data:
                 * DataCRC, check against ExpCmdSN/MaxCmdSN if
                 * Immediate Bit is not set.
                 */
-               cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd, hdr->cmdsn);
+               cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd,
+                                       (unsigned char *)hdr, hdr->cmdsn);
+               if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
+                       return -1;
 
-               if (cmd->sense_reason) {
-                       if (iscsit_dump_data_payload(cmd->conn,
-                                       cmd->first_burst_len, 1) < 0)
-                               return -1;
+               if (cmd->sense_reason || cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
+                       int rc;
+
+                       rc = iscsit_dump_data_payload(cmd->conn,
+                                                     cmd->first_burst_len, 1);
+                       target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
+                       return rc;
                } else if (cmd->unsolicited_data)
                        iscsit_set_unsoliticed_dataout(cmd);
 
-               if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
-                       return iscsit_add_reject_from_cmd(
-                               ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 0, (unsigned char *)hdr, cmd);
-
        } else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) {
                /*
                 * Immediate Data failed DataCRC and ERL>=1,
@@ -1184,15 +1166,14 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
 
        rc = iscsit_setup_scsi_cmd(conn, cmd, buf);
        if (rc < 0)
-               return rc;
+               return 0;
        /*
         * Allocation iovecs needed for struct socket operations for
         * traditional iSCSI block I/O.
         */
        if (iscsit_allocate_iovecs(cmd) < 0) {
-               return iscsit_add_reject_from_cmd(
-                               ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                               1, 0, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                               ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
        }
        immed_data = cmd->immediate_data;
 
@@ -1283,8 +1264,8 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
 
        if (!payload_length) {
                pr_err("DataOUT payload is ZERO, protocol error.\n");
-               return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buf, conn);
+               return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                        buf);
        }
 
        /* iSCSI write */
@@ -1301,8 +1282,8 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
                pr_err("DataSegmentLength: %u is greater than"
                        " MaxXmitDataSegmentLength: %u\n", payload_length,
                        conn->conn_ops->MaxXmitDataSegmentLength);
-               return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buf, conn);
+               return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                        buf);
        }
 
        cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt,
@@ -1325,8 +1306,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
        if (cmd->data_direction != DMA_TO_DEVICE) {
                pr_err("Command ITT: 0x%08x received DataOUT for a"
                        " NON-WRITE command.\n", cmd->init_task_tag);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 0, buf, cmd);
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
        se_cmd = &cmd->se_cmd;
        iscsit_mod_dataout_timer(cmd);
@@ -1335,8 +1315,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
                pr_err("DataOut Offset: %u, Length %u greater than"
                        " iSCSI Command EDTL %u, protocol error.\n",
                        hdr->offset, payload_length, cmd->se_cmd.data_length);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 0, buf, cmd);
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID, buf);
        }
 
        if (cmd->unsolicited_data) {
@@ -1528,7 +1507,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
 
        rc = iscsit_check_dataout_hdr(conn, buf, &cmd);
        if (rc < 0)
-               return rc;
+               return 0;
        else if (!cmd)
                return 0;
 
@@ -1557,8 +1536,12 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
                pr_err("NOPOUT ITT is reserved, but Immediate Bit is"
                        " not set, protocol error.\n");
-               return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buf, conn);
+               if (!cmd)
+                       return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                                (unsigned char *)hdr);
+
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
+                                        (unsigned char *)hdr);
        }
 
        if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
@@ -1566,8 +1549,12 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                        " greater than MaxXmitDataSegmentLength: %u, protocol"
                        " error.\n", payload_length,
                        conn->conn_ops->MaxXmitDataSegmentLength);
-               return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buf, conn);
+               if (!cmd)
+                       return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                                (unsigned char *)hdr);
+
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
+                                        (unsigned char *)hdr);
        }
 
        pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x,"
@@ -1584,9 +1571,9 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
         */
        if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
                if (!cmd)
-                       return iscsit_add_reject(
+                       return iscsit_reject_cmd(cmd,
                                        ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                       1, buf, conn);
+                                       (unsigned char *)hdr);
 
                cmd->iscsi_opcode       = ISCSI_OP_NOOP_OUT;
                cmd->i_state            = ISTATE_SEND_NOPIN;
@@ -1700,15 +1687,14 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                        return 0;
                }
 
-               cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
+               cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
+                               (unsigned char *)hdr, hdr->cmdsn);
                if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
                        ret = 0;
                        goto ping_out;
                }
                if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
-                       return iscsit_add_reject_from_cmd(
-                                       ISCSI_REASON_PROTOCOL_ERROR,
-                                       1, 0, buf, cmd);
+                       return -1;
 
                return 0;
        }
@@ -1757,8 +1743,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        struct se_tmr_req *se_tmr;
        struct iscsi_tmr_req *tmr_req;
        struct iscsi_tm *hdr;
-       int out_of_order_cmdsn = 0;
-       int ret;
+       int out_of_order_cmdsn = 0, ret;
+       bool sess_ref = false;
        u8 function;
 
        hdr                     = (struct iscsi_tm *) buf;
@@ -1782,8 +1768,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                pr_err("Task Management Request TASK_REASSIGN not"
                        " issued as immediate command, bad iSCSI Initiator"
                                "implementation\n");
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                                       1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
        if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
            be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG)
@@ -1795,9 +1781,9 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        if (!cmd->tmr_req) {
                pr_err("Unable to allocate memory for"
                        " Task Management command!\n");
-               return iscsit_add_reject_from_cmd(
-                       ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                       1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+                                            buf);
        }
 
        /*
@@ -1814,6 +1800,9 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                                      conn->sess->se_sess, 0, DMA_NONE,
                                      MSG_SIMPLE_TAG, cmd->sense_buffer + 2);
 
+               target_get_sess_cmd(conn->sess->se_sess, &cmd->se_cmd, true);
+               sess_ref = true;
+
                switch (function) {
                case ISCSI_TM_FUNC_ABORT_TASK:
                        tcm_function = TMR_ABORT_TASK;
@@ -1839,17 +1828,15 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                default:
                        pr_err("Unknown iSCSI TMR Function:"
                               " 0x%02x\n", function);
-                       return iscsit_add_reject_from_cmd(
-                               ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                               1, 1, buf, cmd);
+                       return iscsit_add_reject_cmd(cmd,
+                               ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
                }
 
                ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req,
                                         tcm_function, GFP_KERNEL);
                if (ret < 0)
-                       return iscsit_add_reject_from_cmd(
-                               ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                               1, 1, buf, cmd);
+                       return iscsit_add_reject_cmd(cmd,
+                               ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
 
                cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req;
        }
@@ -1908,9 +1895,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                        break;
 
                if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0)
-                       return iscsit_add_reject_from_cmd(
-                                       ISCSI_REASON_BOOKMARK_INVALID, 1, 1,
-                                       buf, cmd);
+                       return iscsit_add_reject_cmd(cmd,
+                                       ISCSI_REASON_BOOKMARK_INVALID, buf);
                break;
        default:
                pr_err("Unknown TMR function: 0x%02x, protocol"
@@ -1928,15 +1914,13 @@ attach:
        spin_unlock_bh(&conn->cmd_lock);
 
        if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
-               int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
+               int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
                if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP)
                        out_of_order_cmdsn = 1;
                else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
                        return 0;
                else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
-                       return iscsit_add_reject_from_cmd(
-                                       ISCSI_REASON_PROTOCOL_ERROR,
-                                       1, 0, buf, cmd);
+                       return -1;
        }
        iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
 
@@ -1956,6 +1940,11 @@ attach:
         * For connection recovery, this is also the default action for
         * TMR TASK_REASSIGN.
         */
+       if (sess_ref) {
+               pr_debug("Handle TMR, using sess_ref=true check\n");
+               target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
+       }
+
        iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
        return 0;
 }
@@ -1981,8 +1970,7 @@ static int iscsit_handle_text_cmd(
                pr_err("Unable to accept text parameter length: %u"
                        "greater than MaxXmitDataSegmentLength %u.\n",
                       payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
-               return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buf, conn);
+               return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
 
        pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x,"
@@ -2084,8 +2072,8 @@ static int iscsit_handle_text_cmd(
 
        cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
        if (!cmd)
-               return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                       1, buf, conn);
+               return iscsit_add_reject(conn,
+                                        ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
 
        cmd->iscsi_opcode       = ISCSI_OP_TEXT;
        cmd->i_state            = ISTATE_SEND_TEXTRSP;
@@ -2103,11 +2091,10 @@ static int iscsit_handle_text_cmd(
        iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
 
        if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
-               cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
+               cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
+                               (unsigned char *)hdr, hdr->cmdsn);
                if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
-                       return iscsit_add_reject_from_cmd(
-                                       ISCSI_REASON_PROTOCOL_ERROR,
-                                       1, 0, buf, cmd);
+                       return -1;
 
                return 0;
        }
@@ -2292,14 +2279,11 @@ iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                if (ret < 0)
                        return ret;
        } else {
-               cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
-               if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
+               cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
+               if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
                        logout_remove = 0;
-               } else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) {
-                       return iscsit_add_reject_from_cmd(
-                               ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 0, buf, cmd);
-               }
+               else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
+                       return -1;
        }
 
        return logout_remove;
@@ -2323,8 +2307,8 @@ static int iscsit_handle_snack(
        if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
                pr_err("Initiator sent SNACK request while in"
                        " ErrorRecoveryLevel=0.\n");
-               return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buf, conn);
+               return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                        buf);
        }
        /*
         * SNACK_DATA and SNACK_R2T are both 0,  so check which function to
@@ -2348,13 +2332,13 @@ static int iscsit_handle_snack(
        case ISCSI_FLAG_SNACK_TYPE_RDATA:
                /* FIXME: Support R-Data SNACK */
                pr_err("R-Data SNACK Not Supported.\n");
-               return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buf, conn);
+               return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                        buf);
        default:
                pr_err("Unknown SNACK type 0x%02x, protocol"
                        " error.\n", hdr->flags & 0x0f);
-               return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buf, conn);
+               return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                        buf);
        }
 
        return 0;
@@ -2426,14 +2410,14 @@ static int iscsit_handle_immediate_data(
                                pr_err("Unable to recover from"
                                        " Immediate Data digest failure while"
                                        " in ERL=0.\n");
-                               iscsit_add_reject_from_cmd(
+                               iscsit_reject_cmd(cmd,
                                                ISCSI_REASON_DATA_DIGEST_ERROR,
-                                               1, 0, (unsigned char *)hdr, cmd);
+                                               (unsigned char *)hdr);
                                return IMMEDIATE_DATA_CANNOT_RECOVER;
                        } else {
-                               iscsit_add_reject_from_cmd(
+                               iscsit_reject_cmd(cmd,
                                                ISCSI_REASON_DATA_DIGEST_ERROR,
-                                               0, 0, (unsigned char *)hdr, cmd);
+                                               (unsigned char *)hdr);
                                return IMMEDIATE_DATA_ERL1_CRC_FAILURE;
                        }
                } else {
@@ -3533,6 +3517,7 @@ iscsit_build_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
                    struct iscsi_reject *hdr)
 {
        hdr->opcode             = ISCSI_OP_REJECT;
+       hdr->reason             = cmd->reject_reason;
        hdr->flags              |= ISCSI_FLAG_CMD_FINAL;
        hton24(hdr->dlength, ISCSI_HDR_LEN);
        hdr->ffffffff           = cpu_to_be32(0xffffffff);
@@ -3806,18 +3791,11 @@ check_rsp_state:
        case ISTATE_SEND_STATUS_RECOVERY:
        case ISTATE_SEND_TEXTRSP:
        case ISTATE_SEND_TASKMGTRSP:
+       case ISTATE_SEND_REJECT:
                spin_lock_bh(&cmd->istate_lock);
                cmd->i_state = ISTATE_SENT_STATUS;
                spin_unlock_bh(&cmd->istate_lock);
                break;
-       case ISTATE_SEND_REJECT:
-               if (cmd->cmd_flags & ICF_REJECT_FAIL_CONN) {
-                       cmd->cmd_flags &= ~ICF_REJECT_FAIL_CONN;
-                       complete(&cmd->reject_comp);
-                       goto err;
-               }
-               complete(&cmd->reject_comp);
-               break;
        default:
                pr_err("Unknown Opcode: 0x%02x ITT:"
                       " 0x%08x, i_state: %d on CID: %hu\n",
@@ -3922,8 +3900,7 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
        case ISCSI_OP_SCSI_CMD:
                cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
                if (!cmd)
-                       return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                               1, buf, conn);
+                       goto reject;
 
                ret = iscsit_handle_scsi_cmd(conn, cmd, buf);
                break;
@@ -3935,16 +3912,14 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
                if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
                        cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
                        if (!cmd)
-                               return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                               1, buf, conn);
+                               goto reject;
                }
                ret = iscsit_handle_nop_out(conn, cmd, buf);
                break;
        case ISCSI_OP_SCSI_TMFUNC:
                cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
                if (!cmd)
-                       return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                               1, buf, conn);
+                       goto reject;
 
                ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf);
                break;
@@ -3954,8 +3929,7 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
        case ISCSI_OP_LOGOUT:
                cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
                if (!cmd)
-                       return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                               1, buf, conn);
+                       goto reject;
 
                ret = iscsit_handle_logout_cmd(conn, cmd, buf);
                if (ret > 0)
@@ -3987,6 +3961,8 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
        }
 
        return ret;
+reject:
+       return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
 }
 
 int iscsi_target_rx_thread(void *arg)
@@ -4086,8 +4062,8 @@ restart:
                    (!(opcode & ISCSI_OP_LOGOUT)))) {
                        pr_err("Received illegal iSCSI Opcode: 0x%02x"
                        " while in Discovery Session, rejecting.\n", opcode);
-                       iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buffer, conn);
+                       iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                         buffer);
                        goto transport_err;
                }
 
index a0050b2f294ea9248dd5a001805d60834ca5172b..2c437cb8ca00eedfd05f6ff8747f42acc5195375 100644 (file)
@@ -15,7 +15,7 @@ extern struct iscsi_np *iscsit_add_np(struct __kernel_sockaddr_storage *,
 extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *,
                                struct iscsi_portal_group *);
 extern int iscsit_del_np(struct iscsi_np *);
-extern int iscsit_add_reject_from_cmd(u8, int, int, unsigned char *, struct iscsi_cmd *);
+extern int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8, unsigned char *);
 extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *);
 extern int iscsit_logout_closesession(struct iscsi_cmd *, struct iscsi_conn *);
 extern int iscsit_logout_closeconnection(struct iscsi_cmd *, struct iscsi_conn *);
index 8d8b3ff68490be34fd78382f256bdd5dedda87f2..421344da8b5151e48508aca058b7f18e7d7d5ac6 100644 (file)
@@ -474,7 +474,7 @@ static ssize_t __iscsi_##prefix##_store_##name(                             \
        if (!capable(CAP_SYS_ADMIN))                                    \
                return -EPERM;                                          \
                                                                        \
-       snprintf(auth->name, PAGE_SIZE, "%s", page);                    \
+       snprintf(auth->name, sizeof(auth->name), "%s", page);           \
        if (!strncmp("NULL", auth->name, 4))                            \
                auth->naf_flags &= ~flags;                              \
        else                                                            \
index 60ec4b92be034f502216dd5e8d14de4e9c4f6c43..8907dcdc0db9ea75195dbd012d358a70d3f55999 100644 (file)
@@ -132,7 +132,6 @@ enum cmd_flags_table {
        ICF_CONTIG_MEMORY                       = 0x00000020,
        ICF_ATTACHED_TO_RQUEUE                  = 0x00000040,
        ICF_OOO_CMDSN                           = 0x00000080,
-       ICF_REJECT_FAIL_CONN                    = 0x00000100,
 };
 
 /* struct iscsi_cmd->i_state */
@@ -366,6 +365,8 @@ struct iscsi_cmd {
        u8                      maxcmdsn_inc;
        /* Immediate Unsolicited Dataout */
        u8                      unsolicited_data;
+       /* Reject reason code */
+       u8                      reject_reason;
        /* CID contained in logout PDU when opcode == ISCSI_INIT_LOGOUT_CMND */
        u16                     logout_cid;
        /* Command flags */
@@ -446,7 +447,6 @@ struct iscsi_cmd {
        struct list_head        datain_list;
        /* R2T List */
        struct list_head        cmd_r2t_list;
-       struct completion       reject_comp;
        /* Timer for DataOUT */
        struct timer_list       dataout_timer;
        /* Iovecs for SCSI data payload RX/TX w/ kernel level sockets */
index dcb199da06b9678d8dbd5fd1446dc0493edae003..08bd87833321c09b14938c210b14e76d2f24a618 100644 (file)
@@ -746,13 +746,12 @@ int iscsit_check_post_dataout(
                if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
                        pr_err("Unable to recover from DataOUT CRC"
                                " failure while ERL=0, closing session.\n");
-                       iscsit_add_reject_from_cmd(ISCSI_REASON_DATA_DIGEST_ERROR,
-                                       1, 0, buf, cmd);
+                       iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR,
+                                         buf);
                        return DATAOUT_CANNOT_RECOVER;
                }
 
-               iscsit_add_reject_from_cmd(ISCSI_REASON_DATA_DIGEST_ERROR,
-                               0, 0, buf, cmd);
+               iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR, buf);
                return iscsit_dataout_post_crc_failed(cmd, buf);
        }
 }
@@ -909,6 +908,7 @@ void iscsit_cause_connection_reinstatement(struct iscsi_conn *conn, int sleep)
        wait_for_completion(&conn->conn_wait_comp);
        complete(&conn->conn_post_wait_comp);
 }
+EXPORT_SYMBOL(iscsit_cause_connection_reinstatement);
 
 void iscsit_fall_back_to_erl0(struct iscsi_session *sess)
 {
index 40d9dbca987b25a811ca0fb75c9c0277f65933a8..586c268679a450aa9b382d9d42b23ca5dfe0cf35 100644 (file)
@@ -162,9 +162,8 @@ static int iscsit_handle_r2t_snack(
                        " protocol error.\n", cmd->init_task_tag, begrun,
                        (begrun + runlength), cmd->acked_data_sn);
 
-                       return iscsit_add_reject_from_cmd(
-                                       ISCSI_REASON_PROTOCOL_ERROR,
-                                       1, 0, buf, cmd);
+                       return iscsit_reject_cmd(cmd,
+                                       ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
 
        if (runlength) {
@@ -173,8 +172,8 @@ static int iscsit_handle_r2t_snack(
                        " with BegRun: 0x%08x, RunLength: 0x%08x, exceeds"
                        " current R2TSN: 0x%08x, protocol error.\n",
                        cmd->init_task_tag, begrun, runlength, cmd->r2t_sn);
-                       return iscsit_add_reject_from_cmd(
-                               ISCSI_REASON_BOOKMARK_INVALID, 1, 0, buf, cmd);
+                       return iscsit_reject_cmd(cmd,
+                                       ISCSI_REASON_BOOKMARK_INVALID, buf);
                }
                last_r2tsn = (begrun + runlength);
        } else
@@ -433,8 +432,7 @@ static int iscsit_handle_recovery_datain(
                        " protocol error.\n", cmd->init_task_tag, begrun,
                        (begrun + runlength), cmd->acked_data_sn);
 
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 0, buf, cmd);
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
 
        /*
@@ -445,14 +443,14 @@ static int iscsit_handle_recovery_datain(
                pr_err("Initiator requesting BegRun: 0x%08x, RunLength"
                        ": 0x%08x greater than maximum DataSN: 0x%08x.\n",
                                begrun, runlength, (cmd->data_sn - 1));
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 0, buf, cmd);
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID,
+                                        buf);
        }
 
        dr = iscsit_allocate_datain_req();
        if (!dr)
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                               1, 0, buf, cmd);
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+                                        buf);
 
        dr->data_sn = dr->begrun = begrun;
        dr->runlength = runlength;
@@ -1090,7 +1088,7 @@ int iscsit_handle_ooo_cmdsn(
 
        ooo_cmdsn = iscsit_allocate_ooo_cmdsn();
        if (!ooo_cmdsn)
-               return CMDSN_ERROR_CANNOT_RECOVER;
+               return -ENOMEM;
 
        ooo_cmdsn->cmd                  = cmd;
        ooo_cmdsn->batch_count          = (batch) ?
@@ -1101,10 +1099,10 @@ int iscsit_handle_ooo_cmdsn(
 
        if (iscsit_attach_ooo_cmdsn(sess, ooo_cmdsn) < 0) {
                kmem_cache_free(lio_ooo_cache, ooo_cmdsn);
-               return CMDSN_ERROR_CANNOT_RECOVER;
+               return -ENOMEM;
        }
 
-       return CMDSN_HIGHER_THAN_EXP;
+       return 0;
 }
 
 static int iscsit_set_dataout_timeout_values(
index 3402241be87cd401b500da10a398cb734e62bf8b..bc788c52b6cc861d9c2dfd3753b723c70f09b7b0 100644 (file)
@@ -1163,12 +1163,11 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
                if (np->np_thread_state == ISCSI_NP_THREAD_RESET) {
                        spin_unlock_bh(&np->np_thread_lock);
                        complete(&np->np_restart_comp);
-                       if (ret == -ENODEV) {
-                               iscsit_put_transport(conn->conn_transport);
-                               kfree(conn);
-                               conn = NULL;
+                       iscsit_put_transport(conn->conn_transport);
+                       kfree(conn);
+                       conn = NULL;
+                       if (ret == -ENODEV)
                                goto out;
-                       }
                        /* Get another socket */
                        return 1;
                }
index 08a3bacef0c599ee72ba13e04d28a0c765783a97..96e7fdbba9fc8efec4c1b9dce2fcd20953c043a3 100644 (file)
@@ -178,7 +178,6 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask)
        INIT_LIST_HEAD(&cmd->i_conn_node);
        INIT_LIST_HEAD(&cmd->datain_list);
        INIT_LIST_HEAD(&cmd->cmd_r2t_list);
-       init_completion(&cmd->reject_comp);
        spin_lock_init(&cmd->datain_lock);
        spin_lock_init(&cmd->dataout_timeout_lock);
        spin_lock_init(&cmd->istate_lock);
@@ -284,13 +283,12 @@ static inline int iscsit_check_received_cmdsn(struct iscsi_session *sess, u32 cm
  * Commands may be received out of order if MC/S is in use.
  * Ensure they are executed in CmdSN order.
  */
-int iscsit_sequence_cmd(
-       struct iscsi_conn *conn,
-       struct iscsi_cmd *cmd,
-       __be32 cmdsn)
+int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+                       unsigned char *buf, __be32 cmdsn)
 {
-       int ret;
-       int cmdsn_ret;
+       int ret, cmdsn_ret;
+       bool reject = false;
+       u8 reason = ISCSI_REASON_BOOKMARK_NO_RESOURCES;
 
        mutex_lock(&conn->sess->cmdsn_mutex);
 
@@ -300,9 +298,19 @@ int iscsit_sequence_cmd(
                ret = iscsit_execute_cmd(cmd, 0);
                if ((ret >= 0) && !list_empty(&conn->sess->sess_ooo_cmdsn_list))
                        iscsit_execute_ooo_cmdsns(conn->sess);
+               else if (ret < 0) {
+                       reject = true;
+                       ret = CMDSN_ERROR_CANNOT_RECOVER;
+               }
                break;
        case CMDSN_HIGHER_THAN_EXP:
                ret = iscsit_handle_ooo_cmdsn(conn->sess, cmd, be32_to_cpu(cmdsn));
+               if (ret < 0) {
+                       reject = true;
+                       ret = CMDSN_ERROR_CANNOT_RECOVER;
+                       break;
+               }
+               ret = CMDSN_HIGHER_THAN_EXP;
                break;
        case CMDSN_LOWER_THAN_EXP:
                cmd->i_state = ISTATE_REMOVE;
@@ -310,11 +318,16 @@ int iscsit_sequence_cmd(
                ret = cmdsn_ret;
                break;
        default:
+               reason = ISCSI_REASON_PROTOCOL_ERROR;
+               reject = true;
                ret = cmdsn_ret;
                break;
        }
        mutex_unlock(&conn->sess->cmdsn_mutex);
 
+       if (reject)
+               iscsit_reject_cmd(cmd, reason, buf);
+
        return ret;
 }
 EXPORT_SYMBOL(iscsit_sequence_cmd);
index a4422659d04944f58c85670bfd08c646c1bcf5ff..e4fc34a02f57b0d7ed88354a315efa87f41ed500 100644 (file)
@@ -13,7 +13,8 @@ extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t);
 extern struct iscsi_seq *iscsit_get_seq_holder_for_datain(struct iscsi_cmd *, u32);
 extern struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsi_cmd *);
 extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32);
-int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, __be32 cmdsn);
+extern int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+                              unsigned char * ,__be32 cmdsn);
 extern int iscsit_check_unsolicited_dataout(struct iscsi_cmd *, unsigned char *);
 extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, itt_t);
 extern struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *,
index cbe48ab417459de02ec06660934ec8b3ff8804c0..f608fbc14a27b6b8564d02614b46a2c13e35ee18 100644 (file)
@@ -730,7 +730,7 @@ static int core_alua_write_tpg_metadata(
        if (ret < 0)
                pr_err("Error writing ALUA metadata file: %s\n", path);
        fput(file);
-       return ret ? -EIO : 0;
+       return (ret < 0) ? -EIO : 0;
 }
 
 /*
index 3240f2cc81efe0b65d2369c5cdadd9d3d22d3df4..04a74938bb43e580f68a22b8745517762ad8970c 100644 (file)
@@ -1987,7 +1987,7 @@ static int __core_scsi3_write_aptpl_to_file(
                pr_debug("Error writing APTPL metadata file: %s\n", path);
        fput(file);
 
-       return ret ? -EIO : 0;
+       return (ret < 0) ? -EIO : 0;
 }
 
 static int
index 4cb667d720a74e18584199454ce0b7af548fe802..9fabbf7214cd70cc3d4ad3e1bfa74f7ac516cdd0 100644 (file)
@@ -97,9 +97,12 @@ spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf)
 
        buf[7] = 0x2; /* CmdQue=1 */
 
-       snprintf(&buf[8], 8, "LIO-ORG");
-       snprintf(&buf[16], 16, "%s", dev->t10_wwn.model);
-       snprintf(&buf[32], 4, "%s", dev->t10_wwn.revision);
+       memcpy(&buf[8], "LIO-ORG ", 8);
+       memset(&buf[16], 0x20, 16);
+       memcpy(&buf[16], dev->t10_wwn.model,
+              min_t(size_t, strlen(dev->t10_wwn.model), 16));
+       memcpy(&buf[32], dev->t10_wwn.revision,
+              min_t(size_t, strlen(dev->t10_wwn.revision), 4));
        buf[4] = 31; /* Set additional length to 31 */
 
        return 0;
index 3396eb9d57a374770f22dd956d06fa3382196f66..ac2767100df56d3ef071f565ddfc7f4063432ca7 100644 (file)
@@ -341,8 +341,8 @@ void hvsilib_establish(struct hvsi_priv *pv)
 
        pr_devel("HVSI@%x:   ... waiting handshake\n", pv->termno);
 
-       /* Try for up to 200s */
-       for (timeout = 0; timeout < 20; timeout++) {
+       /* Try for up to 400ms */
+       for (timeout = 0; timeout < 40; timeout++) {
                if (pv->established)
                        goto established;
                if (!hvsi_get_packet(pv))
index bb91b4713ebdb8c7ba8849cba643d046c5bc9973..2e3ea1a70d7b90768f33f26a39f098eed7df2c12 100644 (file)
@@ -31,9 +31,8 @@ static int __init serial_init_chip(struct parisc_device *dev)
        int err;
 
 #ifdef CONFIG_64BIT
-       extern int iosapic_serial_irq(int cellnum);
        if (!dev->irq && (dev->id.sversion == 0xad))
-               dev->irq = iosapic_serial_irq(dev->mod_index-1);
+               dev->irq = iosapic_serial_irq(dev);
 #endif
 
        if (!dev->irq) {
index 26e3a97ab157ed16d23825c1a62bec4d53cd81b9..c52948b368d81a1dbd6ea274ffa3058f1128ea37 100644 (file)
@@ -4797,10 +4797,6 @@ 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 cbf1d155b7b2a8c80ef782443edbf77c0e7f5595..22f280aa4f2c521b5829a6ea5e72b8c05f2265d9 100644 (file)
@@ -773,6 +773,6 @@ module_init(arc_serial_init);
 module_exit(arc_serial_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("plat-arcfpga/uart");
+MODULE_ALIAS("platform:" DRIVER_NAME);
 MODULE_AUTHOR("Vineet Gupta");
 MODULE_DESCRIPTION("ARC(Synopsys) On-Chip(fpga) serial driver");
index 4f5f161896a139852e46f93f30239be979838bda..f85b8e6d0346fc472fbc835b0451a706ce46aab3 100644 (file)
@@ -678,11 +678,18 @@ static void mxs_auart_settermios(struct uart_port *u,
 
 static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
 {
-       u32 istatus, istat;
+       u32 istat;
        struct mxs_auart_port *s = context;
        u32 stat = readl(s->port.membase + AUART_STAT);
 
-       istatus = istat = readl(s->port.membase + AUART_INTR);
+       istat = readl(s->port.membase + AUART_INTR);
+
+       /* ack irq */
+       writel(istat & (AUART_INTR_RTIS
+               | AUART_INTR_TXIS
+               | AUART_INTR_RXIS
+               | AUART_INTR_CTSMIS),
+                       s->port.membase + AUART_INTR_CLR);
 
        if (istat & AUART_INTR_CTSMIS) {
                uart_handle_cts_change(&s->port, stat & AUART_STAT_CTS);
@@ -702,12 +709,6 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
                istat &= ~AUART_INTR_TXIS;
        }
 
-       writel(istatus & (AUART_INTR_RTIS
-               | AUART_INTR_TXIS
-               | AUART_INTR_RXIS
-               | AUART_INTR_CTSMIS),
-                       s->port.membase + AUART_INTR_CLR);
-
        return IRQ_HANDLED;
 }
 
@@ -850,7 +851,7 @@ auart_console_write(struct console *co, const char *str, unsigned int count)
        struct mxs_auart_port *s;
        struct uart_port *port;
        unsigned int old_ctrl0, old_ctrl2;
-       unsigned int to = 1000;
+       unsigned int to = 20000;
 
        if (co->index >= MXS_AUART_PORTS || co->index < 0)
                return;
@@ -871,18 +872,23 @@ auart_console_write(struct console *co, const char *str, unsigned int count)
 
        uart_console_write(port, str, count, mxs_auart_console_putchar);
 
-       /*
-        * Finally, wait for transmitter to become empty
-        * and restore the TCR
-        */
+       /* Finally, wait for transmitter to become empty ... */
        while (readl(port->membase + AUART_STAT) & AUART_STAT_BUSY) {
+               udelay(1);
                if (!to--)
                        break;
-               udelay(1);
        }
 
-       writel(old_ctrl0, port->membase + AUART_CTRL0);
-       writel(old_ctrl2, port->membase + AUART_CTRL2);
+       /*
+        * ... and restore the TCR if we waited long enough for the transmitter
+        * to be idle. This might keep the transmitter enabled although it is
+        * unused, but that is better than to disable it while it is still
+        * transmitting.
+        */
+       if (!(readl(port->membase + AUART_STAT) & AUART_STAT_BUSY)) {
+               writel(old_ctrl0, port->membase + AUART_CTRL0);
+               writel(old_ctrl2, port->membase + AUART_CTRL2);
+       }
 
        clk_disable(s->clk);
 }
index 21a7e179edf36a2ef476553159000e7eef81c913..572d48189de910c632ed12e93b4f603bceb55172 100644 (file)
@@ -217,6 +217,7 @@ enum {
 #define FRI2_64_UARTCLK  64000000 /*  64.0000 MHz */
 #define FRI2_48_UARTCLK  48000000 /*  48.0000 MHz */
 #define NTC1_UARTCLK     64000000 /*  64.0000 MHz */
+#define MINNOW_UARTCLK   50000000 /*  50.0000 MHz */
 
 struct pch_uart_buffer {
        unsigned char *buf;
@@ -398,6 +399,10 @@ static int pch_uart_get_uartclk(void)
                    strstr(cmp, "nanoETXexpress-TT")))
                return NTC1_UARTCLK;
 
+       cmp = dmi_get_system_info(DMI_BOARD_NAME);
+       if (cmp && strstr(cmp, "MinnowBoard"))
+               return MINNOW_UARTCLK;
+
        return DEFAULT_UARTCLK;
 }
 
index 6464029e4860968945840c252ad632b556f9f947..59d26ef538d864e4396e8f76bd560b68908e8b13 100644 (file)
@@ -850,7 +850,8 @@ void disassociate_ctty(int on_exit)
                        struct pid *tty_pgrp = tty_get_pgrp(tty);
                        if (tty_pgrp) {
                                kill_pgrp(tty_pgrp, SIGHUP, on_exit);
-                               kill_pgrp(tty_pgrp, SIGCONT, on_exit);
+                               if (!on_exit)
+                                       kill_pgrp(tty_pgrp, SIGCONT, on_exit);
                                put_pid(tty_pgrp);
                        }
                }
@@ -1618,6 +1619,8 @@ static void release_tty(struct tty_struct *tty, int idx)
        tty_free_termios(tty);
        tty_driver_remove_tty(tty->driver, tty);
        tty->port->itty = NULL;
+       if (tty->link)
+               tty->link->port->itty = NULL;
        cancel_work_sync(&tty->port->buf.work);
 
        if (tty->link)
index 121aeb9393e1172e75fe5972a7c4b8ab4640557f..f597e88a705d1fa8e65cf36ae98a61f84f20b9a3 100644 (file)
@@ -256,10 +256,9 @@ void tty_port_tty_hangup(struct tty_port *port, bool check_clocal)
 {
        struct tty_struct *tty = tty_port_tty_get(port);
 
-       if (tty && (!check_clocal || !C_CLOCAL(tty))) {
+       if (tty && (!check_clocal || !C_CLOCAL(tty)))
                tty_hangup(tty);
-               tty_kref_put(tty);
-       }
+       tty_kref_put(tty);
 }
 EXPORT_SYMBOL_GPL(tty_port_tty_hangup);
 
index 8a230f0ef77c77b9acef90b86ab902e9cd4999eb..d3318a0df8ee503f4f5ee553cda3ff1391298be4 100644 (file)
@@ -209,6 +209,7 @@ skip_error:
 static void wdm_int_callback(struct urb *urb)
 {
        int rv = 0;
+       int responding;
        int status = urb->status;
        struct wdm_device *desc;
        struct usb_cdc_notification *dr;
@@ -262,8 +263,8 @@ static void wdm_int_callback(struct urb *urb)
 
        spin_lock(&desc->iuspin);
        clear_bit(WDM_READ, &desc->flags);
-       set_bit(WDM_RESPONDING, &desc->flags);
-       if (!test_bit(WDM_DISCONNECTING, &desc->flags)
+       responding = test_and_set_bit(WDM_RESPONDING, &desc->flags);
+       if (!responding && !test_bit(WDM_DISCONNECTING, &desc->flags)
                && !test_bit(WDM_SUSPENDING, &desc->flags)) {
                rv = usb_submit_urb(desc->response, GFP_ATOMIC);
                dev_dbg(&desc->intf->dev, "%s: usb_submit_urb %d",
@@ -685,16 +686,20 @@ static void wdm_rxwork(struct work_struct *work)
 {
        struct wdm_device *desc = container_of(work, struct wdm_device, rxwork);
        unsigned long flags;
-       int rv;
+       int rv = 0;
+       int responding;
 
        spin_lock_irqsave(&desc->iuspin, flags);
        if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
                spin_unlock_irqrestore(&desc->iuspin, flags);
        } else {
+               responding = test_and_set_bit(WDM_RESPONDING, &desc->flags);
                spin_unlock_irqrestore(&desc->iuspin, flags);
-               rv = usb_submit_urb(desc->response, GFP_KERNEL);
+               if (!responding)
+                       rv = usb_submit_urb(desc->response, GFP_KERNEL);
                if (rv < 0 && rv != -EPERM) {
                        spin_lock_irqsave(&desc->iuspin, flags);
+                       clear_bit(WDM_RESPONDING, &desc->flags);
                        if (!test_bit(WDM_DISCONNECTING, &desc->flags))
                                schedule_work(&desc->rxwork);
                        spin_unlock_irqrestore(&desc->iuspin, flags);
index 7199adccf44488dc487641de2a085361bdaa0041..a6b2cabe7930eff53504448ab36d48b8786f3f98 100644 (file)
@@ -424,7 +424,8 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
 
        memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
        if (config->desc.bDescriptorType != USB_DT_CONFIG ||
-           config->desc.bLength < USB_DT_CONFIG_SIZE) {
+           config->desc.bLength < USB_DT_CONFIG_SIZE ||
+           config->desc.bLength > size) {
                dev_err(ddev, "invalid descriptor for config index %d: "
                    "type = 0x%X, length = %d\n", cfgidx,
                    config->desc.bDescriptorType, config->desc.bLength);
index feef9351463d99845a379ee3cdd1cb32b6772a4c..6cf2ae0aa1f731625eeb91d4a3325f983a53375c 100644 (file)
@@ -668,6 +668,15 @@ resubmit:
 static inline int
 hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt)
 {
+       /* Need to clear both directions for control ep */
+       if (((devinfo >> 11) & USB_ENDPOINT_XFERTYPE_MASK) ==
+                       USB_ENDPOINT_XFER_CONTROL) {
+               int status = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
+                               HUB_CLEAR_TT_BUFFER, USB_RT_PORT,
+                               devinfo ^ 0x8000, tt, NULL, 0, 1000);
+               if (status)
+                       return status;
+       }
        return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
                               HUB_CLEAR_TT_BUFFER, USB_RT_PORT, devinfo,
                               tt, NULL, 0, 1000);
@@ -2846,6 +2855,15 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev)
                                USB_CTRL_SET_TIMEOUT);
 }
 
+/* Count of wakeup-enabled devices at or below udev */
+static unsigned wakeup_enabled_descendants(struct usb_device *udev)
+{
+       struct usb_hub *hub = usb_hub_to_struct_hub(udev);
+
+       return udev->do_remote_wakeup +
+                       (hub ? hub->wakeup_enabled_descendants : 0);
+}
+
 /*
  * usb_port_suspend - suspend a usb device's upstream port
  * @udev: device that's no longer in active use, not a root hub
@@ -2886,8 +2904,8 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev)
  * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
  * timer, no SRP, no requests through sysfs.
  *
- * If Runtime PM isn't enabled or used, non-SuperSpeed devices really get
- * suspended only when their bus goes into global suspend (i.e., the root
+ * If Runtime PM isn't enabled or used, non-SuperSpeed devices may not get
+ * suspended until their bus goes into global suspend (i.e., the root
  * hub is suspended).  Nevertheless, we change @udev->state to
  * USB_STATE_SUSPENDED as this is the device's "logical" state.  The actual
  * upstream port setting is stored in @udev->port_is_suspended.
@@ -2898,7 +2916,6 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 {
        struct usb_hub  *hub = usb_hub_to_struct_hub(udev->parent);
        struct usb_port *port_dev = hub->ports[udev->portnum - 1];
-       enum pm_qos_flags_status pm_qos_stat;
        int             port1 = udev->portnum;
        int             status;
        bool            really_suspend = true;
@@ -2936,7 +2953,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
                                        status);
                        /* bail if autosuspend is requested */
                        if (PMSG_IS_AUTO(msg))
-                               return status;
+                               goto err_wakeup;
                }
        }
 
@@ -2945,28 +2962,36 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
                usb_set_usb2_hardware_lpm(udev, 0);
 
        if (usb_disable_ltm(udev)) {
-               dev_err(&udev->dev, "%s Failed to disable LTM before suspend\n.",
-                               __func__);
-               return -ENOMEM;
+               dev_err(&udev->dev, "Failed to disable LTM before suspend\n.");
+               status = -ENOMEM;
+               if (PMSG_IS_AUTO(msg))
+                       goto err_ltm;
        }
        if (usb_unlocked_disable_lpm(udev)) {
-               dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.",
-                               __func__);
-               return -ENOMEM;
+               dev_err(&udev->dev, "Failed to disable LPM before suspend\n.");
+               status = -ENOMEM;
+               if (PMSG_IS_AUTO(msg))
+                       goto err_lpm3;
        }
 
        /* see 7.1.7.6 */
        if (hub_is_superspeed(hub->hdev))
                status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3);
-       else if (PMSG_IS_AUTO(msg))
-               status = set_port_feature(hub->hdev, port1,
-                                               USB_PORT_FEAT_SUSPEND);
+
        /*
         * For system suspend, we do not need to enable the suspend feature
         * on individual USB-2 ports.  The devices will automatically go
         * into suspend a few ms after the root hub stops sending packets.
         * The USB 2.0 spec calls this "global suspend".
+        *
+        * However, many USB hubs have a bug: They don't relay wakeup requests
+        * from a downstream port if the port's suspend feature isn't on.
+        * Therefore we will turn on the suspend feature if udev or any of its
+        * descendants is enabled for remote wakeup.
         */
+       else if (PMSG_IS_AUTO(msg) || wakeup_enabled_descendants(udev) > 0)
+               status = set_port_feature(hub->hdev, port1,
+                               USB_PORT_FEAT_SUSPEND);
        else {
                really_suspend = false;
                status = 0;
@@ -2974,54 +2999,49 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
        if (status) {
                dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
                                port1, status);
-               /* paranoia:  "should not happen" */
-               if (udev->do_remote_wakeup) {
-                       if (!hub_is_superspeed(hub->hdev)) {
-                               (void) usb_control_msg(udev,
-                                               usb_sndctrlpipe(udev, 0),
-                                               USB_REQ_CLEAR_FEATURE,
-                                               USB_RECIP_DEVICE,
-                                               USB_DEVICE_REMOTE_WAKEUP, 0,
-                                               NULL, 0,
-                                               USB_CTRL_SET_TIMEOUT);
-                       } else
-                               (void) usb_disable_function_remotewakeup(udev);
-
-               }
 
+               /* Try to enable USB3 LPM and LTM again */
+               usb_unlocked_enable_lpm(udev);
+ err_lpm3:
+               usb_enable_ltm(udev);
+ err_ltm:
                /* Try to enable USB2 hardware LPM again */
                if (udev->usb2_hw_lpm_capable == 1)
                        usb_set_usb2_hardware_lpm(udev, 1);
 
-               /* Try to enable USB3 LTM and LPM again */
-               usb_enable_ltm(udev);
-               usb_unlocked_enable_lpm(udev);
+               if (udev->do_remote_wakeup) {
+                       if (udev->speed < USB_SPEED_SUPER)
+                               usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                                               USB_REQ_CLEAR_FEATURE,
+                                               USB_RECIP_DEVICE,
+                                               USB_DEVICE_REMOTE_WAKEUP, 0,
+                                               NULL, 0, USB_CTRL_SET_TIMEOUT);
+                       else
+                               usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                                               USB_REQ_CLEAR_FEATURE,
+                                               USB_RECIP_INTERFACE,
+                                               USB_INTRF_FUNC_SUSPEND, 0,
+                                               NULL, 0, USB_CTRL_SET_TIMEOUT);
+               }
+ err_wakeup:
 
                /* System sleep transitions should never fail */
                if (!PMSG_IS_AUTO(msg))
                        status = 0;
        } else {
-               /* device has up to 10 msec to fully suspend */
                dev_dbg(&udev->dev, "usb %ssuspend, wakeup %d\n",
                                (PMSG_IS_AUTO(msg) ? "auto-" : ""),
                                udev->do_remote_wakeup);
-               usb_set_device_state(udev, USB_STATE_SUSPENDED);
                if (really_suspend) {
                        udev->port_is_suspended = 1;
+
+                       /* device has up to 10 msec to fully suspend */
                        msleep(10);
                }
+               usb_set_device_state(udev, USB_STATE_SUSPENDED);
        }
 
-       /*
-        * Check whether current status meets the requirement of
-        * usb port power off mechanism
-        */
-       pm_qos_stat = dev_pm_qos_flags(&port_dev->dev,
-                       PM_QOS_FLAG_NO_POWER_OFF);
-       if (!udev->do_remote_wakeup
-                       && pm_qos_stat != PM_QOS_FLAGS_ALL
-                       && udev->persist_enabled
-                       && !status) {
+       if (status == 0 && !udev->do_remote_wakeup && udev->persist_enabled) {
                pm_runtime_put_sync(&port_dev->dev);
                port_dev->did_runtime_put = true;
        }
@@ -3291,7 +3311,11 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
        unsigned                port1;
        int                     status;
 
-       /* Warn if children aren't already suspended */
+       /*
+        * Warn if children aren't already suspended.
+        * Also, add up the number of wakeup-enabled descendants.
+        */
+       hub->wakeup_enabled_descendants = 0;
        for (port1 = 1; port1 <= hdev->maxchild; port1++) {
                struct usb_device       *udev;
 
@@ -3301,6 +3325,9 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
                        if (PMSG_IS_AUTO(msg))
                                return -EBUSY;
                }
+               if (udev)
+                       hub->wakeup_enabled_descendants +=
+                                       wakeup_enabled_descendants(udev);
        }
 
        if (hdev->do_remote_wakeup && hub->quirk_check_port_auto_suspend) {
@@ -4764,7 +4791,8 @@ static void hub_events(void)
                                        hub->ports[i - 1]->child;
 
                                dev_dbg(hub_dev, "warm reset port %d\n", i);
-                               if (!udev) {
+                               if (!udev || !(portstatus &
+                                               USB_PORT_STAT_CONNECTION)) {
                                        status = hub_port_reset(hub, i,
                                                        NULL, HUB_BH_RESET_TIME,
                                                        true);
@@ -4774,8 +4802,8 @@ static void hub_events(void)
                                        usb_lock_device(udev);
                                        status = usb_reset_device(udev);
                                        usb_unlock_device(udev);
+                                       connect_change = 0;
                                }
-                               connect_change = 0;
                        }
 
                        if (connect_change)
index 80ab9ee070171a795a93758a271f96767156e68f..f608b39beaf090c531cb3f244a3aed482fd0ee1a 100644 (file)
@@ -59,6 +59,9 @@ struct usb_hub {
        struct usb_tt           tt;             /* Transaction Translator */
 
        unsigned                mA_per_port;    /* current for each child */
+#ifdef CONFIG_PM
+       unsigned                wakeup_enabled_descendants;
+#endif
 
        unsigned                limited_power:1;
        unsigned                quiescing:1;
index b8bad294eeb8d168d58a30e92875cb55c1dbbe81..ef07b3596d06c7cf434f4d0e6ecb9227e59852d1 100644 (file)
@@ -89,22 +89,19 @@ static int usb_port_runtime_resume(struct device *dev)
        retval = usb_hub_set_port_power(hdev, port1, true);
        if (port_dev->child && !retval) {
                /*
-                * Wait for usb hub port to be reconnected in order to make
-                * the resume procedure successful.
+                * Attempt to wait for usb hub port to be reconnected in order
+                * to make the resume procedure successful.  The device may have
+                * disconnected while the port was powered off, so ignore the
+                * return status.
                 */
                retval = hub_port_debounce_be_connected(hub, port1);
-               if (retval < 0) {
+               if (retval < 0)
                        dev_dbg(&port_dev->dev, "can't get reconnection after setting port  power on, status %d\n",
                                        retval);
-                       goto out;
-               }
                usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);
-
-               /* Set return value to 0 if debounce successful */
                retval = 0;
        }
 
-out:
        clear_bit(port1, hub->busy_bits);
        usb_autopm_put_interface(intf);
        return retval;
index a63598895077ff8c984c0ed473d5ee90afa52086..5b44cd47da5b28b30046bead355aa54eda3eec0f 100644 (file)
@@ -78,6 +78,12 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x04d8, 0x000c), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
 
+       /* CarrolTouch 4000U */
+       { USB_DEVICE(0x04e7, 0x0009), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* CarrolTouch 4500U */
+       { USB_DEVICE(0x04e7, 0x0030), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Samsung Android phone modem - ID conflict with SPH-I500 */
        { USB_DEVICE(0x04e8, 0x6601), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
index c35d49d39b7615f83e7e71a9f009643e33c8d760..358375e0b291098d8be40d65bdfbbff7f97f0826 100644 (file)
@@ -450,7 +450,7 @@ static int dwc3_probe(struct platform_device *pdev)
        }
 
        if (IS_ERR(dwc->usb3_phy)) {
-               ret = PTR_ERR(dwc->usb2_phy);
+               ret = PTR_ERR(dwc->usb3_phy);
 
                /*
                 * if -ENXIO is returned, it means PHY layer wasn't
index b69d322e3cab51c4bcdb784d8f0e3eeda66028e2..27dad993b00706ef5a14a257c40bd353ca6ee560 100644 (file)
@@ -759,8 +759,8 @@ struct dwc3 {
 
 struct dwc3_event_type {
        u32     is_devspec:1;
-       u32     type:6;
-       u32     reserved8_31:25;
+       u32     type:7;
+       u32     reserved8_31:24;
 } __packed;
 
 #define DWC3_DEPEVT_XFERCOMPLETE       0x01
index b5e5b35df49c8ff49ca5817ced0838e79dad9ccf..14d28d6184f641816a0c0e10c0fe01fdcabb26b0 100644 (file)
@@ -1508,6 +1508,15 @@ static int dwc3_gadget_start(struct usb_gadget *g,
        int                     irq;
        u32                     reg;
 
+       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+       ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
+                       IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
+       if (ret) {
+               dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+                               irq, ret);
+               goto err0;
+       }
+
        spin_lock_irqsave(&dwc->lock, flags);
 
        if (dwc->gadget_driver) {
@@ -1515,7 +1524,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
                                dwc->gadget.name,
                                dwc->gadget_driver->driver.name);
                ret = -EBUSY;
-               goto err0;
+               goto err1;
        }
 
        dwc->gadget_driver      = driver;
@@ -1551,41 +1560,38 @@ static int dwc3_gadget_start(struct usb_gadget *g,
        ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
        if (ret) {
                dev_err(dwc->dev, "failed to enable %s\n", dep->name);
-               goto err0;
+               goto err2;
        }
 
        dep = dwc->eps[1];
        ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
        if (ret) {
                dev_err(dwc->dev, "failed to enable %s\n", dep->name);
-               goto err1;
+               goto err3;
        }
 
        /* begin to receive SETUP packets */
        dwc->ep0state = EP0_SETUP_PHASE;
        dwc3_ep0_out_start(dwc);
 
-       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-       ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
-                       IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
-       if (ret) {
-               dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
-                               irq, ret);
-               goto err1;
-       }
-
        dwc3_gadget_enable_irq(dwc);
 
        spin_unlock_irqrestore(&dwc->lock, flags);
 
        return 0;
 
-err1:
+err3:
        __dwc3_gadget_ep_disable(dwc->eps[0]);
 
-err0:
+err2:
+       dwc->gadget_driver = NULL;
+
+err1:
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       free_irq(irq, dwc);
+
+err0:
        return ret;
 }
 
@@ -1599,9 +1605,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
        spin_lock_irqsave(&dwc->lock, flags);
 
        dwc3_gadget_disable_irq(dwc);
-       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-       free_irq(irq, dwc);
-
        __dwc3_gadget_ep_disable(dwc->eps[0]);
        __dwc3_gadget_ep_disable(dwc->eps[1]);
 
@@ -1609,6 +1612,9 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
 
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+       free_irq(irq, dwc);
+
        return 0;
 }
 
index 4b7e33e5d9c624a452ee4917d3511f085717ffaf..ab1065afbbd0c0cac55788dad3b805f9a240b2a9 100644 (file)
@@ -285,6 +285,7 @@ static struct usb_string acm_string_defs[] = {
        [ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)",
        [ACM_DATA_IDX].s = "CDC ACM Data",
        [ACM_IAD_IDX ].s = "CDC Serial",
+       {  } /* end of list */
 };
 
 static struct usb_gadget_strings acm_string_table = {
index 97666e8b1b9554ce54b1b6309a537eb456e406d5..c35a9ecc576bb9a7e25724571e4c4841d0227720 100644 (file)
@@ -413,6 +413,7 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
 /* Caller must hold fsg->lock */
 static void wakeup_thread(struct fsg_common *common)
 {
+       smp_wmb();      /* ensure the write of bh->state is complete */
        /* Tell the main thread that something has happened */
        common->thread_wakeup_needed = 1;
        if (common->thread_task)
@@ -632,6 +633,7 @@ static int sleep_thread(struct fsg_common *common)
        }
        __set_current_state(TASK_RUNNING);
        common->thread_wakeup_needed = 0;
+       smp_rmb();      /* ensure the latest bh->state is visible */
        return rc;
 }
 
index ffd8fa5411015f823bc5701777e20cd928848f56..5514822114a575edc5dca1cf992d00ce4e0d74d0 100644 (file)
@@ -105,7 +105,7 @@ void usb_gadget_set_state(struct usb_gadget *gadget,
                enum usb_device_state state)
 {
        gadget->state = state;
-       sysfs_notify(&gadget->dev.kobj, NULL, "status");
+       sysfs_notify(&gadget->dev.kobj, NULL, "state");
 }
 EXPORT_SYMBOL_GPL(usb_gadget_set_state);
 
index 7ce27e35550b7e50c887764b53f6907e4fc5864d..de456a5a5e0a52ed6fcac1ca97ce64b5c3f0a336 100644 (file)
@@ -177,12 +177,16 @@ static int uvc_queue_buffer(struct uvc_video_queue *queue,
 
        mutex_lock(&queue->mutex);
        ret = vb2_qbuf(&queue->queue, buf);
+       if (ret < 0)
+               goto done;
+
        spin_lock_irqsave(&queue->irqlock, flags);
        ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
        queue->flags &= ~UVC_QUEUE_PAUSED;
        spin_unlock_irqrestore(&queue->irqlock, flags);
-       mutex_unlock(&queue->mutex);
 
+done:
+       mutex_unlock(&queue->mutex);
        return ret;
 }
 
index 9ab4a4d9768a5a3ed3fa791746e01977445ba840..ca6289b4b7ade64a5387dec6f8bb2ba025e7f0cf 100644 (file)
@@ -858,6 +858,7 @@ static int ehci_hub_control (
                                ehci->reset_done[wIndex] = jiffies
                                                + msecs_to_jiffies(20);
                                usb_hcd_start_port_resume(&hcd->self, wIndex);
+                               set_bit(wIndex, &ehci->resuming_ports);
                                /* check the port again */
                                mod_timer(&ehci_to_hcd(ehci)->rh_timer,
                                                ehci->reset_done[wIndex]);
index c369767b00e26de940eb6e8eca2e1ebe00b7e975..ec128bc72debe16079bbb0f8a4e0b94b0a0bd3e2 100644 (file)
@@ -184,7 +184,7 @@ static int ehci_mxc_drv_remove(struct platform_device *pdev)
        if (pdata && pdata->exit)
                pdata->exit(pdev);
 
-       if (pdata->otg)
+       if (pdata && pdata->otg)
                usb_phy_shutdown(pdata->otg);
 
        clk_disable_unprepare(priv->usbclk);
index 16d7150e855722be6bc143c504d31120adf53f83..dda408f2c6e93942d64a9d7a88b3b00f7c0d3a67 100644 (file)
@@ -187,6 +187,12 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
                }
 
                omap->phy[i] = phy;
+
+               if (pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_PHY) {
+                       usb_phy_init(omap->phy[i]);
+                       /* bring PHY out of suspend */
+                       usb_phy_set_suspend(omap->phy[i], 0);
+               }
        }
 
        pm_runtime_enable(dev);
@@ -211,13 +217,14 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
        }
 
        /*
-        * Bring PHYs out of reset.
+        * Bring PHYs out of reset for non PHY modes.
         * Even though HSIC mode is a PHY-less mode, the reset
         * line exists between the chips and can be modelled
         * as a PHY device for reset control.
         */
        for (i = 0; i < omap->nports; i++) {
-               if (!omap->phy[i])
+               if (!omap->phy[i] ||
+                    pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_PHY)
                        continue;
 
                usb_phy_init(omap->phy[i]);
index f80d0330d548d36564e9332d60392c9671360263..8e3c878f38cf57e64cb24c25a992b59e184ce322 100644 (file)
@@ -1391,21 +1391,20 @@ iso_stream_schedule (
 
                /* Behind the scheduling threshold? */
                if (unlikely(start < next)) {
+                       unsigned now2 = (now - base) & (mod - 1);
 
                        /* USB_ISO_ASAP: Round up to the first available slot */
                        if (urb->transfer_flags & URB_ISO_ASAP)
                                start += (next - start + period - 1) & -period;
 
                        /*
-                        * Not ASAP: Use the next slot in the stream.  If
-                        * the entire URB falls before the threshold, fail.
+                        * Not ASAP: Use the next slot in the stream,
+                        * no matter what.
                         */
-                       else if (start + span - period < next) {
-                               ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n",
+                       else if (start + span - period < now2) {
+                               ehci_dbg(ehci, "iso underrun %p (%u+%u < %u)\n",
                                                urb, start + base,
-                                               span - period, next + base);
-                               status = -EXDEV;
-                               goto fail;
+                                               span - period, now2 + base);
                        }
                }
 
index 951514ef446dfa5c5dbaff1fd299c5e4f121dd8c..ef6782bd1fa9f5ea39781b7cc0e6517003289362 100644 (file)
@@ -371,7 +371,7 @@ static struct pci_driver ohci_pci_driver = {
        .remove =       usb_hcd_pci_remove,
        .shutdown =     usb_hcd_pci_shutdown,
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
        .driver =       {
                .pm =   &usb_hcd_pci_pm_ops
        },
index fbf75e57628b72e0b7a74237d8a9610826b2ab93..f2e57a1112c93c2c1291df41782c5ba97057af75 100644 (file)
@@ -369,6 +369,10 @@ static struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci
                ctx->size += CTX_SIZE(xhci->hcc_params);
 
        ctx->bytes = dma_pool_alloc(xhci->device_pool, flags, &ctx->dma);
+       if (!ctx->bytes) {
+               kfree(ctx);
+               return NULL;
+       }
        memset(ctx->bytes, 0, ctx->size);
        return ctx;
 }
index cc24e39b97d5b8b2bdf7faada7f7767b4f8013c2..f00cb203faea569b2e87e79e8371455a7abd77b4 100644 (file)
@@ -93,7 +93,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
                        pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) {
-               xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
                xhci->quirks |= XHCI_EP_LIMIT_QUIRK;
                xhci->limit_active_eps = 64;
                xhci->quirks |= XHCI_SW_BW_CHECKING;
index df90fe51b4aa2d406b8b2f8bfa591c410df89a35..6e70ce976769e148962dd5f032997e4493b5fbb6 100644 (file)
@@ -24,7 +24,7 @@ static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
         * here that the generic code does not try to make a pci_dev from our
         * dev struct in order to setup MSI
         */
-       xhci->quirks |= XHCI_BROKEN_MSI;
+       xhci->quirks |= XHCI_PLAT;
 }
 
 /* called during probe() after chip reset completes */
@@ -179,6 +179,7 @@ static int xhci_plat_remove(struct platform_device *dev)
 
        usb_remove_hcd(hcd);
        iounmap(hcd->regs);
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
        kfree(xhci);
 
index 1969c001b3f9a8bacbe926dfc4777c95206101a1..cc3bfc5d590df6b1182b87d2620e03fa1e72fe3f 100644 (file)
@@ -434,7 +434,7 @@ static void ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
 
        /* A ring has pending URBs if its TD list is not empty */
        if (!(ep->ep_state & EP_HAS_STREAMS)) {
-               if (!(list_empty(&ep->ring->td_list)))
+               if (ep->ring && !(list_empty(&ep->ring->td_list)))
                        xhci_ring_ep_doorbell(xhci, slot_id, ep_index, 0);
                return;
        }
index d8f640b12dd9d950e842892858a617b7fa97247e..f4a49c45299cf4335b20fe425b44c3f84b7f3c4b 100644 (file)
@@ -342,9 +342,14 @@ static void xhci_msix_sync_irqs(struct xhci_hcd *xhci)
 static int xhci_try_enable_msi(struct usb_hcd *hcd)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-       struct pci_dev  *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
+       struct pci_dev  *pdev;
        int ret;
 
+       /* The xhci platform device has set up IRQs through usb_add_hcd. */
+       if (xhci->quirks & XHCI_PLAT)
+               return 0;
+
+       pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
        /*
         * Some Fresco Logic host controllers advertise MSI, but fail to
         * generate interrupts.  Don't even try to enable MSI.
@@ -1171,9 +1176,6 @@ static int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
        }
 
        xhci = hcd_to_xhci(hcd);
-       if (xhci->xhc_state & XHCI_STATE_HALTED)
-               return -ENODEV;
-
        if (check_virt_dev) {
                if (!udev->slot_id || !xhci->devs[udev->slot_id]) {
                        printk(KERN_DEBUG "xHCI %s called with unaddressed "
@@ -1189,6 +1191,9 @@ static int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
                }
        }
 
+       if (xhci->xhc_state & XHCI_STATE_HALTED)
+               return -ENODEV;
+
        return 1;
 }
 
@@ -3506,10 +3511,21 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
        struct xhci_virt_device *virt_dev;
+       struct device *dev = hcd->self.controller;
        unsigned long flags;
        u32 state;
        int i, ret;
 
+#ifndef CONFIG_USB_DEFAULT_PERSIST
+       /*
+        * We called pm_runtime_get_noresume when the device was attached.
+        * Decrement the counter here to allow controller to runtime suspend
+        * if no devices remain.
+        */
+       if (xhci->quirks & XHCI_RESET_ON_RESUME)
+               pm_runtime_put_noidle(dev);
+#endif
+
        ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
        /* If the host is halted due to driver unload, we still need to free the
         * device.
@@ -3581,6 +3597,7 @@ static int xhci_reserve_host_control_ep_resources(struct xhci_hcd *xhci)
 int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+       struct device *dev = hcd->self.controller;
        unsigned long flags;
        int timeleft;
        int ret;
@@ -3633,6 +3650,16 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
                goto disable_slot;
        }
        udev->slot_id = xhci->slot_id;
+
+#ifndef CONFIG_USB_DEFAULT_PERSIST
+       /*
+        * If resetting upon resume, we can't put the controller into runtime
+        * suspend if there is a device attached.
+        */
+       if (xhci->quirks & XHCI_RESET_ON_RESUME)
+               pm_runtime_get_noresume(dev);
+#endif
+
        /* Is this a LS or FS device under a HS hub? */
        /* Hub or peripherial? */
        return 1;
@@ -4697,6 +4724,13 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
 
        get_quirks(dev, xhci);
 
+       /* In xhci controllers which follow xhci 1.0 spec gives a spurious
+        * success event after a short transfer. This quirk will ignore such
+        * spurious event.
+        */
+       if (xhci->hci_version > 0x96)
+               xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
+
        /* Make sure the HC is halted. */
        retval = xhci_halt(xhci);
        if (retval)
index 77600cefcaf1df6ed3209a41c2a00dcdbb31b4dc..3638f1d779e68be74c2a0686ac703212b657034b 100644 (file)
@@ -1516,6 +1516,7 @@ struct xhci_hcd {
 #define XHCI_SPURIOUS_REBOOT   (1 << 13)
 #define XHCI_COMP_MODE_QUIRK   (1 << 14)
 #define XHCI_AVOID_BEI         (1 << 15)
+#define XHCI_PLAT              (1 << 16)
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;
        /* There are two roothubs to keep track of bus suspend info for */
index c21386ec5d35d142b7d0d84abe2e3f3cb5be7125..de98906f786d08ebac625b3cc8213de5d79cf68e 100644 (file)
@@ -3247,6 +3247,7 @@ static const struct usb_device_id sisusb_table[] = {
        { USB_DEVICE(0x0711, 0x0903) },
        { USB_DEVICE(0x0711, 0x0918) },
        { USB_DEVICE(0x0711, 0x0920) },
+       { USB_DEVICE(0x0711, 0x0950) },
        { USB_DEVICE(0x182d, 0x021c) },
        { USB_DEVICE(0x182d, 0x0269) },
        { }
index ca266280895dc2f150484f1dbb8873150588175b..e1859b8ef5679dc5c39a367c7e86979a2cfde5ec 100644 (file)
@@ -15,7 +15,7 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "otg_fsm.h"
+#include "phy-fsm-usb.h"
 #include <linux/usb/otg.h>
 #include <linux/ioctl.h>
 
index c520b3548e7cf59cd0058eda330cd2d7ac792197..7f4596606e18b41565ef338598298b6f36c64269 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
 
-#include "phy-otg-fsm.h"
+#include "phy-fsm-usb.h"
 
 /* Change USB protocol when there is a protocol change */
 static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
index 2c659553c07c01df5dc1a65be8341809939fc6f4..c90d960e091b24da139887a9daf868219c85fffd 100644 (file)
@@ -53,6 +53,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
        { USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
        { USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */
+       { USB_DEVICE(0x0846, 0x1100) }, /* NetGear Managed Switch M4100 series, M5300 series, M7100 series */
        { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
        { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */
        { USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */
@@ -118,6 +119,8 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */
        { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
        { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
+       { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */
+       { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */
        { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
@@ -148,6 +151,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
        { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
        { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
+       { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
        { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
        { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */
        { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */
index 7260ec66034715e7a065d0f5fe6441f49a37f6b4..b65e657c641da56a1545be79e22a13a9fdad653c 100644 (file)
@@ -735,9 +735,34 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID),
                .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
        { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
-       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) },
-       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_CT29B_PID) },
-       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_RTS01_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S03_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_59_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57A_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57B_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29A_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29B_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29F_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_62B_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S01_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_63_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29C_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_81B_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_82B_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K5D_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K4Y_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K5G_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S05_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_60_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_61_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_62_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_63B_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_64_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_65_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_92_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_92D_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_W5R_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_A5R_PID) },
+       { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_PW1_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) },
        { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
index 6dd79253205dd7ec54278ddb078f08346cdbb4f8..1b8af461b522c65a111983226ba1e704f012ac8c 100644 (file)
 /*
  * RT Systems programming cables for various ham radios
  */
-#define RTSYSTEMS_VID                  0x2100  /* Vendor ID */
-#define RTSYSTEMS_SERIAL_VX7_PID       0x9e52  /* Serial converter for VX-7 Radios using FT232RL */
-#define RTSYSTEMS_CT29B_PID            0x9e54  /* CT29B Radio Cable */
-#define RTSYSTEMS_RTS01_PID            0x9e57  /* USB-RTS01 Radio Cable */
-
+#define RTSYSTEMS_VID          0x2100  /* Vendor ID */
+#define RTSYSTEMS_USB_S03_PID  0x9001  /* RTS-03 USB to Serial Adapter */
+#define RTSYSTEMS_USB_59_PID   0x9e50  /* USB-59 USB to 8 pin plug */
+#define RTSYSTEMS_USB_57A_PID  0x9e51  /* USB-57A USB to 4pin 3.5mm plug */
+#define RTSYSTEMS_USB_57B_PID  0x9e52  /* USB-57B USB to extended 4pin 3.5mm plug */
+#define RTSYSTEMS_USB_29A_PID  0x9e53  /* USB-29A USB to 3.5mm stereo plug */
+#define RTSYSTEMS_USB_29B_PID  0x9e54  /* USB-29B USB to 6 pin mini din */
+#define RTSYSTEMS_USB_29F_PID  0x9e55  /* USB-29F USB to 6 pin modular plug */
+#define RTSYSTEMS_USB_62B_PID  0x9e56  /* USB-62B USB to 8 pin mini din plug*/
+#define RTSYSTEMS_USB_S01_PID  0x9e57  /* USB-RTS01 USB to 3.5 mm stereo plug*/
+#define RTSYSTEMS_USB_63_PID   0x9e58  /* USB-63 USB to 9 pin female*/
+#define RTSYSTEMS_USB_29C_PID  0x9e59  /* USB-29C USB to 4 pin modular plug*/
+#define RTSYSTEMS_USB_81B_PID  0x9e5A  /* USB-81 USB to 8 pin mini din plug*/
+#define RTSYSTEMS_USB_82B_PID  0x9e5B  /* USB-82 USB to 2.5 mm stereo plug*/
+#define RTSYSTEMS_USB_K5D_PID  0x9e5C  /* USB-K5D USB to 8 pin modular plug*/
+#define RTSYSTEMS_USB_K4Y_PID  0x9e5D  /* USB-K4Y USB to 2.5/3.5 mm plugs*/
+#define RTSYSTEMS_USB_K5G_PID  0x9e5E  /* USB-K5G USB to 8 pin modular plug*/
+#define RTSYSTEMS_USB_S05_PID  0x9e5F  /* USB-RTS05 USB to 2.5 mm stereo plug*/
+#define RTSYSTEMS_USB_60_PID   0x9e60  /* USB-60 USB to 6 pin din*/
+#define RTSYSTEMS_USB_61_PID   0x9e61  /* USB-61 USB to 6 pin mini din*/
+#define RTSYSTEMS_USB_62_PID   0x9e62  /* USB-62 USB to 8 pin mini din*/
+#define RTSYSTEMS_USB_63B_PID  0x9e63  /* USB-63 USB to 9 pin female*/
+#define RTSYSTEMS_USB_64_PID   0x9e64  /* USB-64 USB to 9 pin male*/
+#define RTSYSTEMS_USB_65_PID   0x9e65  /* USB-65 USB to 9 pin female null modem*/
+#define RTSYSTEMS_USB_92_PID   0x9e66  /* USB-92 USB to 12 pin plug*/
+#define RTSYSTEMS_USB_92D_PID  0x9e67  /* USB-92D USB to 12 pin plug data*/
+#define RTSYSTEMS_USB_W5R_PID  0x9e68  /* USB-W5R USB to 8 pin modular plug*/
+#define RTSYSTEMS_USB_A5R_PID  0x9e69  /* USB-A5R USB to 8 pin modular plug*/
+#define RTSYSTEMS_USB_PW1_PID  0x9e6A  /* USB-PW1 USB to 8 pin modular plug*/
 
 /*
  * Physik Instrumente
index 3549d073df229617690f90d29b6c2e1f77648b64..07fbdf0e7ab66d50e9c29aa61f4238c52b8ce339 100644 (file)
@@ -2315,7 +2315,7 @@ static int keyspan_startup(struct usb_serial *serial)
        if (d_details == NULL) {
                dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
                    __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
-               return 1;
+               return -ENODEV;
        }
 
        /* Setup private data for serial driver */
index f27c621a9297f3c896b84c9ea700d6285ef6b94f..0f16bf6ea71c1707fa6ec5d64bd9242eeac9cdfa 100644 (file)
@@ -90,6 +90,7 @@ struct urbtracker {
        struct list_head        urblist_entry;
        struct kref             ref_count;
        struct urb              *urb;
+       struct usb_ctrlrequest  *setup;
 };
 
 enum mos7715_pp_modes {
@@ -271,6 +272,7 @@ static void destroy_urbtracker(struct kref *kref)
        struct mos7715_parport *mos_parport = urbtrack->mos_parport;
 
        usb_free_urb(urbtrack->urb);
+       kfree(urbtrack->setup);
        kfree(urbtrack);
        kref_put(&mos_parport->ref_count, destroy_mos_parport);
 }
@@ -355,7 +357,6 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
        struct urbtracker *urbtrack;
        int ret_val;
        unsigned long flags;
-       struct usb_ctrlrequest setup;
        struct usb_serial *serial = mos_parport->serial;
        struct usb_device *usbdev = serial->dev;
 
@@ -373,14 +374,20 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
                kfree(urbtrack);
                return -ENOMEM;
        }
-       setup.bRequestType = (__u8)0x40;
-       setup.bRequest = (__u8)0x0e;
-       setup.wValue = get_reg_value(reg, dummy);
-       setup.wIndex = get_reg_index(reg);
-       setup.wLength = 0;
+       urbtrack->setup = kmalloc(sizeof(*urbtrack->setup), GFP_ATOMIC);
+       if (!urbtrack->setup) {
+               usb_free_urb(urbtrack->urb);
+               kfree(urbtrack);
+               return -ENOMEM;
+       }
+       urbtrack->setup->bRequestType = (__u8)0x40;
+       urbtrack->setup->bRequest = (__u8)0x0e;
+       urbtrack->setup->wValue = cpu_to_le16(get_reg_value(reg, dummy));
+       urbtrack->setup->wIndex = cpu_to_le16(get_reg_index(reg));
+       urbtrack->setup->wLength = 0;
        usb_fill_control_urb(urbtrack->urb, usbdev,
                             usb_sndctrlpipe(usbdev, 0),
-                            (unsigned char *)&setup,
+                            (unsigned char *)urbtrack->setup,
                             NULL, 0, async_complete, urbtrack);
        kref_init(&urbtrack->ref_count);
        INIT_LIST_HEAD(&urbtrack->urblist_entry);
index 7e998081e1cd9b42651143e7f01e63286410393d..2c1749da1f7e1b49254ae33142dac30790ea99e0 100644 (file)
 #define LED_ON_MS      500
 #define LED_OFF_MS     500
 
-static int device_type;
+enum mos7840_flag {
+       MOS7840_FLAG_CTRL_BUSY,
+       MOS7840_FLAG_LED_BUSY,
+};
 
 static const struct usb_device_id id_table[] = {
        {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
@@ -238,9 +241,12 @@ struct moschip_port {
 
        /* For device(s) with LED indicator */
        bool has_led;
-       bool led_flag;
        struct timer_list led_timer1;   /* Timer for LED on */
        struct timer_list led_timer2;   /* Timer for LED off */
+       struct urb *led_urb;
+       struct usb_ctrlrequest *led_dr;
+
+       unsigned long flags;
 };
 
 /*
@@ -467,10 +473,10 @@ static void mos7840_control_callback(struct urb *urb)
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
                dev_dbg(dev, "%s - urb shutting down with status: %d\n", __func__, status);
-               return;
+               goto out;
        default:
                dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status);
-               return;
+               goto out;
        }
 
        dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length);
@@ -483,6 +489,8 @@ static void mos7840_control_callback(struct urb *urb)
                mos7840_handle_new_msr(mos7840_port, regval);
        else if (mos7840_port->MsrLsr == 1)
                mos7840_handle_new_lsr(mos7840_port, regval);
+out:
+       clear_bit_unlock(MOS7840_FLAG_CTRL_BUSY, &mos7840_port->flags);
 }
 
 static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
@@ -493,6 +501,9 @@ static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
        unsigned char *buffer = mcs->ctrl_buf;
        int ret;
 
+       if (test_and_set_bit_lock(MOS7840_FLAG_CTRL_BUSY, &mcs->flags))
+               return -EBUSY;
+
        dr->bRequestType = MCS_RD_RTYPE;
        dr->bRequest = MCS_RDREQ;
        dr->wValue = cpu_to_le16(Wval); /* 0 */
@@ -504,6 +515,9 @@ static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
                             mos7840_control_callback, mcs);
        mcs->control_urb->transfer_buffer_length = 2;
        ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC);
+       if (ret)
+               clear_bit_unlock(MOS7840_FLAG_CTRL_BUSY, &mcs->flags);
+
        return ret;
 }
 
@@ -530,7 +544,7 @@ static void mos7840_set_led_async(struct moschip_port *mcs, __u16 wval,
                                __u16 reg)
 {
        struct usb_device *dev = mcs->port->serial->dev;
-       struct usb_ctrlrequest *dr = mcs->dr;
+       struct usb_ctrlrequest *dr = mcs->led_dr;
 
        dr->bRequestType = MCS_WR_RTYPE;
        dr->bRequest = MCS_WRREQ;
@@ -538,10 +552,10 @@ static void mos7840_set_led_async(struct moschip_port *mcs, __u16 wval,
        dr->wIndex = cpu_to_le16(reg);
        dr->wLength = cpu_to_le16(0);
 
-       usb_fill_control_urb(mcs->control_urb, dev, usb_sndctrlpipe(dev, 0),
+       usb_fill_control_urb(mcs->led_urb, dev, usb_sndctrlpipe(dev, 0),
                (unsigned char *)dr, NULL, 0, mos7840_set_led_callback, NULL);
 
-       usb_submit_urb(mcs->control_urb, GFP_ATOMIC);
+       usb_submit_urb(mcs->led_urb, GFP_ATOMIC);
 }
 
 static void mos7840_set_led_sync(struct usb_serial_port *port, __u16 reg,
@@ -567,7 +581,19 @@ static void mos7840_led_flag_off(unsigned long arg)
 {
        struct moschip_port *mcs = (struct moschip_port *) arg;
 
-       mcs->led_flag = false;
+       clear_bit_unlock(MOS7840_FLAG_LED_BUSY, &mcs->flags);
+}
+
+static void mos7840_led_activity(struct usb_serial_port *port)
+{
+       struct moschip_port *mos7840_port = usb_get_serial_port_data(port);
+
+       if (test_and_set_bit_lock(MOS7840_FLAG_LED_BUSY, &mos7840_port->flags))
+               return;
+
+       mos7840_set_led_async(mos7840_port, 0x0301, MODEM_CONTROL_REGISTER);
+       mod_timer(&mos7840_port->led_timer1,
+                               jiffies + msecs_to_jiffies(LED_ON_MS));
 }
 
 /*****************************************************************************
@@ -767,14 +793,8 @@ static void mos7840_bulk_in_callback(struct urb *urb)
                return;
        }
 
-       /* Turn on LED */
-       if (mos7840_port->has_led && !mos7840_port->led_flag) {
-               mos7840_port->led_flag = true;
-               mos7840_set_led_async(mos7840_port, 0x0301,
-                                       MODEM_CONTROL_REGISTER);
-               mod_timer(&mos7840_port->led_timer1,
-                               jiffies + msecs_to_jiffies(LED_ON_MS));
-       }
+       if (mos7840_port->has_led)
+               mos7840_led_activity(port);
 
        mos7840_port->read_urb_busy = true;
        retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
@@ -825,18 +845,6 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
 /************************************************************************/
 /*       D R I V E R  T T Y  I N T E R F A C E  F U N C T I O N S       */
 /************************************************************************/
-#ifdef MCSSerialProbe
-static int mos7840_serial_probe(struct usb_serial *serial,
-                               const struct usb_device_id *id)
-{
-
-       /*need to implement the mode_reg reading and updating\
-          structures usb_serial_ device_type\
-          (i.e num_ports, num_bulkin,bulkout etc) */
-       /* Also we can update the changes  attach */
-       return 1;
-}
-#endif
 
 /*****************************************************************************
  * mos7840_open
@@ -914,20 +922,20 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
        status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
        if (status < 0) {
                dev_dbg(&port->dev, "Reading Spreg failed\n");
-               return -1;
+               goto err;
        }
        Data |= 0x80;
        status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
        if (status < 0) {
                dev_dbg(&port->dev, "writing Spreg failed\n");
-               return -1;
+               goto err;
        }
 
        Data &= ~0x80;
        status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
        if (status < 0) {
                dev_dbg(&port->dev, "writing Spreg failed\n");
-               return -1;
+               goto err;
        }
        /* End of block to be checked */
 
@@ -936,7 +944,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
                                                                        &Data);
        if (status < 0) {
                dev_dbg(&port->dev, "Reading Controlreg failed\n");
-               return -1;
+               goto err;
        }
        Data |= 0x08;           /* Driver done bit */
        Data |= 0x20;           /* rx_disable */
@@ -944,7 +952,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
                                mos7840_port->ControlRegOffset, Data);
        if (status < 0) {
                dev_dbg(&port->dev, "writing Controlreg failed\n");
-               return -1;
+               goto err;
        }
        /* do register settings here */
        /* Set all regs to the device default values. */
@@ -955,21 +963,21 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
        status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
        if (status < 0) {
                dev_dbg(&port->dev, "disabling interrupts failed\n");
-               return -1;
+               goto err;
        }
        /* Set FIFO_CONTROL_REGISTER to the default value */
        Data = 0x00;
        status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
        if (status < 0) {
                dev_dbg(&port->dev, "Writing FIFO_CONTROL_REGISTER  failed\n");
-               return -1;
+               goto err;
        }
 
        Data = 0xcf;
        status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
        if (status < 0) {
                dev_dbg(&port->dev, "Writing FIFO_CONTROL_REGISTER  failed\n");
-               return -1;
+               goto err;
        }
 
        Data = 0x03;
@@ -1114,6 +1122,15 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
        /* mos7840_change_port_settings(mos7840_port,old_termios); */
 
        return 0;
+err:
+       for (j = 0; j < NUM_URBS; ++j) {
+               urb = mos7840_port->write_urb_pool[j];
+               if (!urb)
+                       continue;
+               kfree(urb->transfer_buffer);
+               usb_free_urb(urb);
+       }
+       return status;
 }
 
 /*****************************************************************************
@@ -1458,13 +1475,8 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
        data1 = urb->transfer_buffer;
        dev_dbg(&port->dev, "bulkout endpoint is %d\n", port->bulk_out_endpointAddress);
 
-       /* Turn on LED */
-       if (mos7840_port->has_led && !mos7840_port->led_flag) {
-               mos7840_port->led_flag = true;
-               mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0301);
-               mod_timer(&mos7840_port->led_timer1,
-                               jiffies + msecs_to_jiffies(LED_ON_MS));
-       }
+       if (mos7840_port->has_led)
+               mos7840_led_activity(port);
 
        /* send it down the pipe */
        status = usb_submit_urb(urb, GFP_ATOMIC);
@@ -2193,38 +2205,48 @@ static int mos7810_check(struct usb_serial *serial)
        return 0;
 }
 
-static int mos7840_calc_num_ports(struct usb_serial *serial)
+static int mos7840_probe(struct usb_serial *serial,
+                               const struct usb_device_id *id)
 {
-       __u16 data = 0x00;
+       u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
        u8 *buf;
-       int mos7840_num_ports;
+       int device_type;
+
+       if (product == MOSCHIP_DEVICE_ID_7810 ||
+               product == MOSCHIP_DEVICE_ID_7820) {
+               device_type = product;
+               goto out;
+       }
 
        buf = kzalloc(VENDOR_READ_LENGTH, GFP_KERNEL);
-       if (buf) {
-               usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+       if (!buf)
+               return -ENOMEM;
+
+       usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
                        MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, buf,
                        VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
-               data = *buf;
-               kfree(buf);
-       }
 
-       if (serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7810 ||
-               serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7820) {
-               device_type = serial->dev->descriptor.idProduct;
-       } else {
-               /* For a MCS7840 device GPIO0 must be set to 1 */
-               if ((data & 0x01) == 1)
-                       device_type = MOSCHIP_DEVICE_ID_7840;
-               else if (mos7810_check(serial))
-                       device_type = MOSCHIP_DEVICE_ID_7810;
-               else
-                       device_type = MOSCHIP_DEVICE_ID_7820;
-       }
+       /* For a MCS7840 device GPIO0 must be set to 1 */
+       if (buf[0] & 0x01)
+               device_type = MOSCHIP_DEVICE_ID_7840;
+       else if (mos7810_check(serial))
+               device_type = MOSCHIP_DEVICE_ID_7810;
+       else
+               device_type = MOSCHIP_DEVICE_ID_7820;
+
+       kfree(buf);
+out:
+       usb_set_serial_data(serial, (void *)(unsigned long)device_type);
+
+       return 0;
+}
+
+static int mos7840_calc_num_ports(struct usb_serial *serial)
+{
+       int device_type = (unsigned long)usb_get_serial_data(serial);
+       int mos7840_num_ports;
 
        mos7840_num_ports = (device_type >> 4) & 0x000F;
-       serial->num_bulk_in = mos7840_num_ports;
-       serial->num_bulk_out = mos7840_num_ports;
-       serial->num_ports = mos7840_num_ports;
 
        return mos7840_num_ports;
 }
@@ -2232,6 +2254,7 @@ static int mos7840_calc_num_ports(struct usb_serial *serial)
 static int mos7840_port_probe(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
+       int device_type = (unsigned long)usb_get_serial_data(serial);
        struct moschip_port *mos7840_port;
        int status;
        int pnum;
@@ -2409,6 +2432,14 @@ static int mos7840_port_probe(struct usb_serial_port *port)
        if (device_type == MOSCHIP_DEVICE_ID_7810) {
                mos7840_port->has_led = true;
 
+               mos7840_port->led_urb = usb_alloc_urb(0, GFP_KERNEL);
+               mos7840_port->led_dr = kmalloc(sizeof(*mos7840_port->led_dr),
+                                                               GFP_KERNEL);
+               if (!mos7840_port->led_urb || !mos7840_port->led_dr) {
+                       status = -ENOMEM;
+                       goto error;
+               }
+
                init_timer(&mos7840_port->led_timer1);
                mos7840_port->led_timer1.function = mos7840_led_off;
                mos7840_port->led_timer1.expires =
@@ -2421,8 +2452,6 @@ static int mos7840_port_probe(struct usb_serial_port *port)
                        jiffies + msecs_to_jiffies(LED_OFF_MS);
                mos7840_port->led_timer2.data = (unsigned long)mos7840_port;
 
-               mos7840_port->led_flag = false;
-
                /* Turn off LED */
                mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);
        }
@@ -2444,6 +2473,8 @@ out:
        }
        return 0;
 error:
+       kfree(mos7840_port->led_dr);
+       usb_free_urb(mos7840_port->led_urb);
        kfree(mos7840_port->dr);
        kfree(mos7840_port->ctrl_buf);
        usb_free_urb(mos7840_port->control_urb);
@@ -2464,6 +2495,10 @@ static int mos7840_port_remove(struct usb_serial_port *port)
 
                del_timer_sync(&mos7840_port->led_timer1);
                del_timer_sync(&mos7840_port->led_timer2);
+
+               usb_kill_urb(mos7840_port->led_urb);
+               usb_free_urb(mos7840_port->led_urb);
+               kfree(mos7840_port->led_dr);
        }
        usb_kill_urb(mos7840_port->control_urb);
        usb_free_urb(mos7840_port->control_urb);
@@ -2490,9 +2525,7 @@ static struct usb_serial_driver moschip7840_4port_device = {
        .throttle = mos7840_throttle,
        .unthrottle = mos7840_unthrottle,
        .calc_num_ports = mos7840_calc_num_ports,
-#ifdef MCSSerialProbe
-       .probe = mos7840_serial_probe,
-#endif
+       .probe = mos7840_probe,
        .ioctl = mos7840_ioctl,
        .set_termios = mos7840_set_termios,
        .break_ctl = mos7840_break,
index bd4323ddae1aa19002b92998d52d00b9bd13a7cf..1cf6f125f5f078624b41bd1256686d35f28ee4b7 100644 (file)
@@ -159,8 +159,6 @@ static void option_instat_callback(struct urb *urb);
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED        0x9000
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED        0x9001
 #define NOVATELWIRELESS_PRODUCT_E362           0x9010
-#define NOVATELWIRELESS_PRODUCT_G1             0xA001
-#define NOVATELWIRELESS_PRODUCT_G1_M           0xA002
 #define NOVATELWIRELESS_PRODUCT_G2             0xA010
 #define NOVATELWIRELESS_PRODUCT_MC551          0xB001
 
@@ -343,17 +341,12 @@ static void option_instat_callback(struct urb *urb);
 #define OLIVETTI_VENDOR_ID                     0x0b3c
 #define OLIVETTI_PRODUCT_OLICARD100            0xc000
 #define OLIVETTI_PRODUCT_OLICARD145            0xc003
+#define OLIVETTI_PRODUCT_OLICARD200            0xc005
 
 /* Celot products */
 #define CELOT_VENDOR_ID                                0x211f
 #define CELOT_PRODUCT_CT680M                   0x6801
 
-/* ONDA Communication vendor id */
-#define ONDA_VENDOR_ID       0x1ee8
-
-/* ONDA MT825UP HSDPA 14.2 modem */
-#define ONDA_MT825UP         0x000b
-
 /* Samsung products */
 #define SAMSUNG_VENDOR_ID                       0x04e8
 #define SAMSUNG_PRODUCT_GT_B3730                0x6889
@@ -446,7 +439,8 @@ static void option_instat_callback(struct urb *urb);
 
 /* Hyundai Petatel Inc. products */
 #define PETATEL_VENDOR_ID                      0x1ff4
-#define PETATEL_PRODUCT_NP10T                  0x600e
+#define PETATEL_PRODUCT_NP10T_600A             0x600a
+#define PETATEL_PRODUCT_NP10T_600E             0x600e
 
 /* TP-LINK Incorporated products */
 #define TPLINK_VENDOR_ID                       0x2357
@@ -730,8 +724,6 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC547) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED) },
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1) },
-       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1_M) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) },
        /* Novatel Ovation MC551 a.k.a. Verizon USB551L */
        { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
@@ -786,6 +778,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
+       { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },
@@ -821,7 +814,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0018, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0019, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0019, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0020, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0021, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
@@ -1260,8 +1254,8 @@ static const struct usb_device_id option_ids[] = {
 
        { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
        { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) },
+       { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200) },
        { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
-       { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
        { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
        { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) },
        { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM610) },
@@ -1333,9 +1327,12 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) },
        { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) },
        { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
-       { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) },
+       { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600A) },
+       { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600E) },
        { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE(TPLINK_VENDOR_ID, 0x9000),                                 /* TP-Link MA260 */
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) },
        { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x02, 0x01) },    /* D-Link DWM-156 (variant) */
        { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x00, 0x00) },    /* D-Link DWM-156 (variant) */
@@ -1343,6 +1340,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) },
        { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) },
        { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index bd794b43898cce03ef4ac6fb2c71ecc6563bc4c0..c65437cfd4a276a71ffe1e3bede20306c18fe75f 100644 (file)
@@ -35,7 +35,13 @@ static const struct usb_device_id id_table[] = {
        {DEVICE_G1K(0x04da, 0x250c)},   /* Panasonic Gobi QDL device */
        {DEVICE_G1K(0x413c, 0x8172)},   /* Dell Gobi Modem device */
        {DEVICE_G1K(0x413c, 0x8171)},   /* Dell Gobi QDL device */
-       {DEVICE_G1K(0x1410, 0xa001)},   /* Novatel Gobi Modem device */
+       {DEVICE_G1K(0x1410, 0xa001)},   /* Novatel/Verizon USB-1000 */
+       {DEVICE_G1K(0x1410, 0xa002)},   /* Novatel Gobi Modem device */
+       {DEVICE_G1K(0x1410, 0xa003)},   /* Novatel Gobi Modem device */
+       {DEVICE_G1K(0x1410, 0xa004)},   /* Novatel Gobi Modem device */
+       {DEVICE_G1K(0x1410, 0xa005)},   /* Novatel Gobi Modem device */
+       {DEVICE_G1K(0x1410, 0xa006)},   /* Novatel Gobi Modem device */
+       {DEVICE_G1K(0x1410, 0xa007)},   /* Novatel Gobi Modem device */
        {DEVICE_G1K(0x1410, 0xa008)},   /* Novatel Gobi QDL device */
        {DEVICE_G1K(0x0b05, 0x1776)},   /* Asus Gobi Modem device */
        {DEVICE_G1K(0x0b05, 0x1774)},   /* Asus Gobi QDL device */
index e581c2549a57658bc702c854e4924c3f3ae01a25..32bdd5eac59b68e8c04c432201ff804042bdfe5a 100644 (file)
@@ -371,7 +371,7 @@ static int ti_startup(struct usb_serial *serial)
        usb_set_serial_data(serial, tdev);
 
        /* determine device type */
-       if (usb_match_id(serial->interface, ti_id_table_3410))
+       if (serial->type == &ti_1port_device)
                tdev->td_is_3410 = 1;
        dev_dbg(&dev->dev, "%s - device type is %s\n", __func__,
                tdev->td_is_3410 ? "3410" : "5052");
@@ -1536,14 +1536,15 @@ static int ti_download_firmware(struct ti_device *tdev)
        char buf[32];
 
        /* try ID specific firmware first, then try generic firmware */
-       sprintf(buf, "ti_usb-v%04x-p%04x.fw", dev->descriptor.idVendor,
-           dev->descriptor.idProduct);
+       sprintf(buf, "ti_usb-v%04x-p%04x.fw",
+                       le16_to_cpu(dev->descriptor.idVendor),
+                       le16_to_cpu(dev->descriptor.idProduct));
        status = request_firmware(&fw_p, buf, &dev->dev);
 
        if (status != 0) {
                buf[0] = '\0';
-               if (dev->descriptor.idVendor == MTS_VENDOR_ID) {
-                       switch (dev->descriptor.idProduct) {
+               if (le16_to_cpu(dev->descriptor.idVendor) == MTS_VENDOR_ID) {
+                       switch (le16_to_cpu(dev->descriptor.idProduct)) {
                        case MTS_CDMA_PRODUCT_ID:
                                strcpy(buf, "mts_cdma.fw");
                                break;
index ece326ef63a0b64c831e5f541b7171b95a9761f6..db0cf536de186c0958582ce497a17426668edffa 100644 (file)
@@ -291,18 +291,18 @@ static void usb_wwan_indat_callback(struct urb *urb)
                        tty_flip_buffer_push(&port->port);
                } else
                        dev_dbg(dev, "%s: empty read urb received\n", __func__);
-
-               /* Resubmit urb so we continue receiving */
-               err = usb_submit_urb(urb, GFP_ATOMIC);
-               if (err) {
-                       if (err != -EPERM) {
-                               dev_err(dev, "%s: resubmit read urb failed. (%d)\n", __func__, err);
-                               /* busy also in error unless we are killed */
-                               usb_mark_last_busy(port->serial->dev);
-                       }
-               } else {
+       }
+       /* Resubmit urb so we continue receiving */
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+       if (err) {
+               if (err != -EPERM) {
+                       dev_err(dev, "%s: resubmit read urb failed. (%d)\n",
+                               __func__, err);
+                       /* busy also in error unless we are killed */
                        usb_mark_last_busy(port->serial->dev);
                }
+       } else {
+               usb_mark_last_busy(port->serial->dev);
        }
 }
 
index 1799335288bd5e60522a60def1c311f07df62286..c015f2c16729c5b4030fc829fae9a3cfb90acde6 100644 (file)
@@ -665,6 +665,13 @@ UNUSUAL_DEV(  0x054c, 0x016a, 0x0000, 0x9999,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_FIX_INQUIRY ),
 
+/* Submitted by Ren Bigcren <bigcren.ren@sonymobile.com> */
+UNUSUAL_DEV(  0x054c, 0x02a5, 0x0100, 0x0100,
+               "Sony Corp.",
+               "MicroVault Flash Drive",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NO_READ_CAPACITY_16 ),
+
 /* floppy reports multiple luns */
 UNUSUAL_DEV(  0x055d, 0x2020, 0x0000, 0x0210,
                "SAMSUNG",
index 6ef94bce8c0dc49a5e118c642dbcb4e6c2beddf3..028fc833743541a1755313eb67263595d165d630 100644 (file)
@@ -1110,6 +1110,12 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb)
        }
        spin_lock_irqsave(&xfer->lock, flags);
        rpipe = xfer->ep->hcpriv;
+       if (rpipe == NULL) {
+               pr_debug("%s: xfer id 0x%08X has no RPIPE.  %s",
+                       __func__, wa_xfer_id(xfer),
+                       "Probably already aborted.\n" );
+               goto out_unlock;
+       }
        /* Check the delayed list -> if there, release and complete */
        spin_lock_irqsave(&wa->xfer_list_lock, flags2);
        if (!list_empty(&xfer->list_node) && xfer->seg == NULL)
@@ -1493,8 +1499,7 @@ static void wa_xfer_result_cb(struct urb *urb)
                        break;
                }
                usb_status = xfer_result->bTransferStatus & 0x3f;
-               if (usb_status == WA_XFER_STATUS_ABORTED
-                   || usb_status == WA_XFER_STATUS_NOT_FOUND)
+               if (usb_status == WA_XFER_STATUS_NOT_FOUND)
                        /* taken care of already */
                        break;
                xfer_id = xfer_result->dwTransferID;
index f80d3dd41d8c6d420c8fb2d640a81739f2049674..d6a518ce4d6df38036069d2c8d93c2007673e116 100644 (file)
@@ -150,6 +150,11 @@ static void vhost_net_ubuf_put_and_wait(struct vhost_net_ubuf_ref *ubufs)
 {
        kref_put(&ubufs->kref, vhost_net_zerocopy_done_signal);
        wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount));
+}
+
+static void vhost_net_ubuf_put_wait_and_free(struct vhost_net_ubuf_ref *ubufs)
+{
+       vhost_net_ubuf_put_and_wait(ubufs);
        kfree(ubufs);
 }
 
@@ -302,6 +307,11 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)
        struct vhost_virtqueue *vq = ubufs->vq;
        int cnt = atomic_read(&ubufs->kref.refcount);
 
+       /* set len to mark this desc buffers done DMA */
+       vq->heads[ubuf->desc].len = success ?
+               VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN;
+       vhost_net_ubuf_put(ubufs);
+
        /*
         * Trigger polling thread if guest stopped submitting new buffers:
         * in this case, the refcount after decrement will eventually reach 1
@@ -312,10 +322,6 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)
         */
        if (cnt <= 2 || !(cnt % 16))
                vhost_poll_queue(&vq->poll);
-       /* set len to mark this desc buffers done DMA */
-       vq->heads[ubuf->desc].len = success ?
-               VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN;
-       vhost_net_ubuf_put(ubufs);
 }
 
 /* Expects to be always run from workqueue - which acts as
@@ -948,7 +954,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
        mutex_unlock(&vq->mutex);
 
        if (oldubufs) {
-               vhost_net_ubuf_put_and_wait(oldubufs);
+               vhost_net_ubuf_put_wait_and_free(oldubufs);
                mutex_lock(&vq->mutex);
                vhost_zerocopy_signal_used(n, vq);
                mutex_unlock(&vq->mutex);
@@ -966,7 +972,7 @@ err_used:
        rcu_assign_pointer(vq->private_data, oldsock);
        vhost_net_enable_vq(n, vq);
        if (ubufs)
-               vhost_net_ubuf_put_and_wait(ubufs);
+               vhost_net_ubuf_put_wait_and_free(ubufs);
 err_ubufs:
        fput(sock->file);
 err_vq:
index bd3ae324a1a261d5c735c552a915f9f5eeef86b1..71af7b5abe01780f3fcf99d5d621bfdbf8819b55 100644 (file)
@@ -191,7 +191,8 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num)
         * virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST);
         * is true, we *have* to do it in this order
         */
-       tell_host(vb, vb->deflate_vq);
+       if (vb->num_pfns != 0)
+               tell_host(vb, vb->deflate_vq);
        mutex_unlock(&vb->balloon_lock);
        release_pages_by_pfn(vb->pfns, vb->num_pfns);
 }
index 5217baf5528c0ef85dca9c4282cfb081f158a30c..37d58f84dc50accce2581a9f7b7bf1485d2df7d0 100644 (file)
@@ -607,19 +607,21 @@ void virtqueue_disable_cb(struct virtqueue *_vq)
 EXPORT_SYMBOL_GPL(virtqueue_disable_cb);
 
 /**
- * virtqueue_enable_cb - restart callbacks after disable_cb.
+ * virtqueue_enable_cb_prepare - restart callbacks after disable_cb
  * @vq: the struct virtqueue we're talking about.
  *
- * This re-enables callbacks; it returns "false" if there are pending
- * buffers in the queue, to detect a possible race between the driver
- * checking for more work, and enabling callbacks.
+ * This re-enables callbacks; it returns current queue state
+ * in an opaque unsigned value. This value should be later tested by
+ * virtqueue_poll, to detect a possible race between the driver checking for
+ * more work, and enabling callbacks.
  *
  * Caller must ensure we don't call this with other virtqueue
  * operations at the same time (except where noted).
  */
-bool virtqueue_enable_cb(struct virtqueue *_vq)
+unsigned virtqueue_enable_cb_prepare(struct virtqueue *_vq)
 {
        struct vring_virtqueue *vq = to_vvq(_vq);
+       u16 last_used_idx;
 
        START_USE(vq);
 
@@ -629,15 +631,45 @@ bool virtqueue_enable_cb(struct virtqueue *_vq)
         * either clear the flags bit or point the event index at the next
         * entry. Always do both to keep code simple. */
        vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
-       vring_used_event(&vq->vring) = vq->last_used_idx;
+       vring_used_event(&vq->vring) = last_used_idx = vq->last_used_idx;
+       END_USE(vq);
+       return last_used_idx;
+}
+EXPORT_SYMBOL_GPL(virtqueue_enable_cb_prepare);
+
+/**
+ * virtqueue_poll - query pending used buffers
+ * @vq: the struct virtqueue we're talking about.
+ * @last_used_idx: virtqueue state (from call to virtqueue_enable_cb_prepare).
+ *
+ * Returns "true" if there are pending used buffers in the queue.
+ *
+ * This does not need to be serialized.
+ */
+bool virtqueue_poll(struct virtqueue *_vq, unsigned last_used_idx)
+{
+       struct vring_virtqueue *vq = to_vvq(_vq);
+
        virtio_mb(vq->weak_barriers);
-       if (unlikely(more_used(vq))) {
-               END_USE(vq);
-               return false;
-       }
+       return (u16)last_used_idx != vq->vring.used->idx;
+}
+EXPORT_SYMBOL_GPL(virtqueue_poll);
 
-       END_USE(vq);
-       return true;
+/**
+ * virtqueue_enable_cb - restart callbacks after disable_cb.
+ * @vq: the struct virtqueue we're talking about.
+ *
+ * This re-enables callbacks; it returns "false" if there are pending
+ * buffers in the queue, to detect a possible race between the driver
+ * checking for more work, and enabling callbacks.
+ *
+ * Caller must ensure we don't call this with other virtqueue
+ * operations at the same time (except where noted).
+ */
+bool virtqueue_enable_cb(struct virtqueue *_vq)
+{
+       unsigned last_used_idx = virtqueue_enable_cb_prepare(_vq);
+       return !virtqueue_poll(_vq, last_used_idx);
 }
 EXPORT_SYMBOL_GPL(virtqueue_enable_cb);
 
index 6a6bbe4ede92c67afe4c88efd105839f14b3a240..1faa1305c043d5b7a81d3674b27187312d4dfe47 100644 (file)
@@ -346,7 +346,7 @@ static void init_evtchn_cpu_bindings(void)
 
        for_each_possible_cpu(i)
                memset(per_cpu(cpu_evtchn_mask, i),
-                      (i == 0) ? ~0 : 0, sizeof(*per_cpu(cpu_evtchn_mask, i)));
+                      (i == 0) ? ~0 : 0, NR_EVENT_CHANNELS/8);
 }
 
 static inline void clear_evtchn(int port)
@@ -1492,8 +1492,10 @@ void rebind_evtchn_irq(int evtchn, int irq)
 /* Rebind an evtchn so that it gets delivered to a specific cpu */
 static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
 {
+       struct shared_info *s = HYPERVISOR_shared_info;
        struct evtchn_bind_vcpu bind_vcpu;
        int evtchn = evtchn_from_irq(irq);
+       int masked;
 
        if (!VALID_EVTCHN(evtchn))
                return -1;
@@ -1509,6 +1511,12 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
        bind_vcpu.port = evtchn;
        bind_vcpu.vcpu = tcpu;
 
+       /*
+        * Mask the event while changing the VCPU binding to prevent
+        * it being delivered on an unexpected VCPU.
+        */
+       masked = sync_test_and_set_bit(evtchn, BM(s->evtchn_mask));
+
        /*
         * If this fails, it usually just indicates that we're dealing with a
         * virq or IPI channel, which don't actually need to be rebound. Ignore
@@ -1517,6 +1525,9 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
        if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
                bind_evtchn_to_cpu(evtchn, tcpu);
 
+       if (!masked)
+               unmask_evtchn(evtchn);
+
        return 0;
 }
 
index 45c8efaa6b3ea1035a1c560c403ad924f9d9e8ad..34924fb9d02ae1159baaf5c5bd864c3a564d8f35 100644 (file)
@@ -377,18 +377,12 @@ static long evtchn_ioctl(struct file *file,
                if (unbind.port >= NR_EVENT_CHANNELS)
                        break;
 
-               spin_lock_irq(&port_user_lock);
-
                rc = -ENOTCONN;
-               if (get_port_user(unbind.port) != u) {
-                       spin_unlock_irq(&port_user_lock);
+               if (get_port_user(unbind.port) != u)
                        break;
-               }
 
                disable_irq(irq_from_evtchn(unbind.port));
 
-               spin_unlock_irq(&port_user_lock);
-
                evtchn_unbind_from_user(u, unbind.port);
 
                rc = 0;
@@ -488,26 +482,15 @@ static int evtchn_release(struct inode *inode, struct file *filp)
        int i;
        struct per_user_data *u = filp->private_data;
 
-       spin_lock_irq(&port_user_lock);
-
-       free_page((unsigned long)u->ring);
-
        for (i = 0; i < NR_EVENT_CHANNELS; i++) {
                if (get_port_user(i) != u)
                        continue;
 
                disable_irq(irq_from_evtchn(i));
-       }
-
-       spin_unlock_irq(&port_user_lock);
-
-       for (i = 0; i < NR_EVENT_CHANNELS; i++) {
-               if (get_port_user(i) != u)
-                       continue;
-
                evtchn_unbind_from_user(get_port_user(i), i);
        }
 
+       free_page((unsigned long)u->ring);
        kfree(u->name);
        kfree(u);
 
index 04c1b2d9b77514ca89ef1cf74d6263f5ebb93a29..d5418c1be9aaae7c6876946d57c8ba5958949e6e 100644 (file)
@@ -729,9 +729,18 @@ void gnttab_request_free_callback(struct gnttab_free_callback *callback,
                                  void (*fn)(void *), void *arg, u16 count)
 {
        unsigned long flags;
+       struct gnttab_free_callback *cb;
+
        spin_lock_irqsave(&gnttab_list_lock, flags);
-       if (callback->next)
-               goto out;
+
+       /* Check if the callback is already on the list */
+       cb = gnttab_free_callback_list;
+       while (cb) {
+               if (cb == callback)
+                       goto out;
+               cb = cb->next;
+       }
+
        callback->fn = fn;
        callback->arg = arg;
        callback->count = count;
index 94bbc04dba77053bb47d3d8b793a3a8218f0a0d2..c5eae7251490e9b48553000f8e582cb6c0b9420f 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1045,12 +1045,22 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs,
 int bio_uncopy_user(struct bio *bio)
 {
        struct bio_map_data *bmd = bio->bi_private;
-       int ret = 0;
+       struct bio_vec *bvec;
+       int ret = 0, i;
 
-       if (!bio_flagged(bio, BIO_NULL_MAPPED))
-               ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs,
-                                    bmd->nr_sgvecs, bio_data_dir(bio) == READ,
-                                    0, bmd->is_our_pages);
+       if (!bio_flagged(bio, BIO_NULL_MAPPED)) {
+               /*
+                * if we're in a workqueue, the request is orphaned, so
+                * don't copy into a random user address space, just free.
+                */
+               if (current->mm)
+                       ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs,
+                                            bmd->nr_sgvecs, bio_data_dir(bio) == READ,
+                                            0, bmd->is_our_pages);
+               else if (bmd->is_our_pages)
+                       bio_for_each_segment_all(bvec, bio, i)
+                               __free_page(bvec->bv_page);
+       }
        bio_free_map_data(bmd);
        bio_put(bio);
        return ret;
index 2091db8cdd783a2287ce9165a7223cfe59cf5a2b..85f5c85ec91c050818495c49c1e4a2a669c14322 100644 (file)
@@ -58,17 +58,24 @@ static void bdev_inode_switch_bdi(struct inode *inode,
                        struct backing_dev_info *dst)
 {
        struct backing_dev_info *old = inode->i_data.backing_dev_info;
+       bool wakeup_bdi = false;
 
        if (unlikely(dst == old))               /* deadlock avoidance */
                return;
        bdi_lock_two(&old->wb, &dst->wb);
        spin_lock(&inode->i_lock);
        inode->i_data.backing_dev_info = dst;
-       if (inode->i_state & I_DIRTY)
+       if (inode->i_state & I_DIRTY) {
+               if (bdi_cap_writeback_dirty(dst) && !wb_has_dirty_io(&dst->wb))
+                       wakeup_bdi = true;
                list_move(&inode->i_wb_list, &dst->wb.b_dirty);
+       }
        spin_unlock(&inode->i_lock);
        spin_unlock(&old->wb.list_lock);
        spin_unlock(&dst->wb.list_lock);
+
+       if (wakeup_bdi)
+               bdi_wakeup_thread_delayed(dst);
 }
 
 /* Kill _all_ buffers and pagecache , dirty or not.. */
index 02fae7f7e42cb417a14fe0243805bcad4270b592..7fb054ba1b60124539643277d3204cc7e887ab0c 100644 (file)
@@ -1089,7 +1089,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
                btrfs_set_node_ptr_generation(parent, parent_slot,
                                              trans->transid);
                btrfs_mark_buffer_dirty(parent);
-               tree_mod_log_free_eb(root->fs_info, buf);
+               if (last_ref)
+                       tree_mod_log_free_eb(root->fs_info, buf);
                btrfs_free_tree_block(trans, root, buf, parent_start,
                                      last_ref);
        }
@@ -1161,8 +1162,8 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info,
  * time_seq).
  */
 static void
-__tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq,
-                     struct tree_mod_elem *first_tm)
+__tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
+                     u64 time_seq, struct tree_mod_elem *first_tm)
 {
        u32 n;
        struct rb_node *next;
@@ -1172,6 +1173,7 @@ __tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq,
        unsigned long p_size = sizeof(struct btrfs_key_ptr);
 
        n = btrfs_header_nritems(eb);
+       tree_mod_log_read_lock(fs_info);
        while (tm && tm->seq >= time_seq) {
                /*
                 * all the operations are recorded with the operator used for
@@ -1226,6 +1228,7 @@ __tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq,
                if (tm->index != first_tm->index)
                        break;
        }
+       tree_mod_log_read_unlock(fs_info);
        btrfs_set_header_nritems(eb, n);
 }
 
@@ -1274,7 +1277,7 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
 
        extent_buffer_get(eb_rewin);
        btrfs_tree_read_lock(eb_rewin);
-       __tree_mod_log_rewind(eb_rewin, time_seq, tm);
+       __tree_mod_log_rewind(fs_info, eb_rewin, time_seq, tm);
        WARN_ON(btrfs_header_nritems(eb_rewin) >
                BTRFS_NODEPTRS_PER_BLOCK(fs_info->tree_root));
 
@@ -1350,7 +1353,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
                btrfs_set_header_generation(eb, old_generation);
        }
        if (tm)
-               __tree_mod_log_rewind(eb, time_seq, tm);
+               __tree_mod_log_rewind(root->fs_info, eb, time_seq, tm);
        else
                WARN_ON(btrfs_header_level(eb) != 0);
        WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root));
index df472ab1b5acca7b411b05bcc414913bcebcc244..0b272d0683370ec8288fad1bb3e9aaf56839ad73 100644 (file)
@@ -7298,6 +7298,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
        int err = 0;
        int ret;
        int level;
+       bool root_dropped = false;
 
        path = btrfs_alloc_path();
        if (!path) {
@@ -7355,6 +7356,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
                while (1) {
                        btrfs_tree_lock(path->nodes[level]);
                        btrfs_set_lock_blocking(path->nodes[level]);
+                       path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
 
                        ret = btrfs_lookup_extent_info(trans, root,
                                                path->nodes[level]->start,
@@ -7370,6 +7372,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
                                break;
 
                        btrfs_tree_unlock(path->nodes[level]);
+                       path->locks[level] = 0;
                        WARN_ON(wc->refs[level] != 1);
                        level--;
                }
@@ -7471,12 +7474,22 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
                free_extent_buffer(root->commit_root);
                kfree(root);
        }
+       root_dropped = true;
 out_end_trans:
        btrfs_end_transaction_throttle(trans, tree_root);
 out_free:
        kfree(wc);
        btrfs_free_path(path);
 out:
+       /*
+        * So if we need to stop dropping the snapshot for whatever reason we
+        * need to make sure to add it back to the dead root list so that we
+        * keep trying to do the work later.  This also cleans up roots if we
+        * don't have it in the radix (like when we recover after a power fail
+        * or unmount) so we don't leak memory.
+        */
+       if (root_dropped == false)
+               btrfs_add_dead_root(root);
        if (err)
                btrfs_std_error(root->fs_info, err);
        return err;
index 0f81d67cdc8da651890df1a89c01df9188667d97..8dedf4019672fc9a9d27be23305949d934a9fb70 100644 (file)
@@ -3299,6 +3299,9 @@ static long btrfs_ioctl_dev_replace(struct btrfs_root *root, void __user *arg)
 
        switch (p->cmd) {
        case BTRFS_IOCTL_DEV_REPLACE_CMD_START:
+               if (root->fs_info->sb->s_flags & MS_RDONLY)
+                       return -EROFS;
+
                if (atomic_xchg(
                        &root->fs_info->mutually_exclusive_operation_running,
                        1)) {
index 79bd479317cb53cbea30a7021d81a891ed9ae20c..eb84c2db1acae77010410bd2300b0de173f4628e 100644 (file)
@@ -2501,7 +2501,7 @@ again:
                        ret = scrub_extent(sctx, extent_logical, extent_len,
                                           extent_physical, extent_dev, flags,
                                           generation, extent_mirror_num,
-                                          extent_physical);
+                                          extent_logical - logical + physical);
                        if (ret)
                                goto out;
 
index ff40f1c00ce315d59eaf4da6d20145351a000e51..ba9690b9ae2405d7e8b500eaadc0db6225676eb6 100644 (file)
@@ -4579,6 +4579,41 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
        send_root = BTRFS_I(file_inode(mnt_file))->root;
        fs_info = send_root->fs_info;
 
+       /*
+        * This is done when we lookup the root, it should already be complete
+        * by the time we get here.
+        */
+       WARN_ON(send_root->orphan_cleanup_state != ORPHAN_CLEANUP_DONE);
+
+       /*
+        * If we just created this root we need to make sure that the orphan
+        * cleanup has been done and committed since we search the commit root,
+        * so check its commit root transid with our otransid and if they match
+        * commit the transaction to make sure everything is updated.
+        */
+       down_read(&send_root->fs_info->extent_commit_sem);
+       if (btrfs_header_generation(send_root->commit_root) ==
+           btrfs_root_otransid(&send_root->root_item)) {
+               struct btrfs_trans_handle *trans;
+
+               up_read(&send_root->fs_info->extent_commit_sem);
+
+               trans = btrfs_attach_transaction_barrier(send_root);
+               if (IS_ERR(trans)) {
+                       if (PTR_ERR(trans) != -ENOENT) {
+                               ret = PTR_ERR(trans);
+                               goto out;
+                       }
+                       /* ENOENT means theres no transaction */
+               } else {
+                       ret = btrfs_commit_transaction(trans, send_root);
+                       if (ret)
+                               goto out;
+               }
+       } else {
+               up_read(&send_root->fs_info->extent_commit_sem);
+       }
+
        arg = memdup_user(arg_, sizeof(*arg));
        if (IS_ERR(arg)) {
                ret = PTR_ERR(arg);
index c276ac9a0ec338c86973a752d74b9e93d22cc9a8..cf68596b51fb62ca3c4b1c718ed21564f5b4d2b8 100644 (file)
@@ -3728,8 +3728,9 @@ next_slot:
        }
 
 log_extents:
+       btrfs_release_path(path);
+       btrfs_release_path(dst_path);
        if (fast_search) {
-               btrfs_release_path(dst_path);
                ret = btrfs_log_changed_extents(trans, root, inode, dst_path);
                if (ret) {
                        err = ret;
@@ -3746,8 +3747,6 @@ log_extents:
        }
 
        if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) {
-               btrfs_release_path(path);
-               btrfs_release_path(dst_path);
                ret = log_directory_changes(trans, root, inode, path, dst_path);
                if (ret) {
                        err = ret;
index 7b417e20efe26da50a83a1a695e62491d3077f85..b0a523b2c60ee8e73cd5165382892918ddad269e 100644 (file)
@@ -205,6 +205,10 @@ int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux,
                u64 new_alloced = ulist->nodes_alloced + 128;
                struct ulist_node *new_nodes;
                void *old = NULL;
+               int i;
+
+               for (i = 0; i < ulist->nnodes; i++)
+                       rb_erase(&ulist->nodes[i].rb_node, &ulist->root);
 
                /*
                 * if nodes_alloced == ULIST_SIZE no memory has been allocated
@@ -224,6 +228,17 @@ int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux,
 
                ulist->nodes = new_nodes;
                ulist->nodes_alloced = new_alloced;
+
+               /*
+                * krealloc actually uses memcpy, which does not copy rb_node
+                * pointers, so we have to do it ourselves.  Otherwise we may
+                * be bitten by crashes.
+                */
+               for (i = 0; i < ulist->nnodes; i++) {
+                       ret = ulist_rbtree_insert(ulist, &ulist->nodes[i]);
+                       if (ret < 0)
+                               return ret;
+               }
        }
        ulist->nodes[ulist->nnodes].val = val;
        ulist->nodes[ulist->nnodes].aux = aux;
index e0b4ef31d3c870c9e73fecad303e9f9957542385..a5ce62eb7806daf0722d1950f26015a11e67275c 100644 (file)
@@ -196,8 +196,10 @@ static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg)
        r = ceph_calc_file_object_mapping(&ci->i_layout, dl.file_offset, len,
                                          &dl.object_no, &dl.object_offset,
                                          &olen);
-       if (r < 0)
+       if (r < 0) {
+               up_read(&osdc->map_sem);
                return -EIO;
+       }
        dl.file_offset -= dl.object_offset;
        dl.object_size = ceph_file_layout_object_size(ci->i_layout);
        dl.block_size = ceph_file_layout_su(ci->i_layout);
index 9b6b2b6dd164c5fd047f691a68aac03fd8de69d5..be661d8f532adcea4b44d2b42aae52b788d4753e 100644 (file)
@@ -675,17 +675,18 @@ ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value,
        if (!ceph_is_valid_xattr(name))
                return -ENODATA;
 
-       spin_lock(&ci->i_ceph_lock);
-       dout("getxattr %p ver=%lld index_ver=%lld\n", inode,
-            ci->i_xattrs.version, ci->i_xattrs.index_version);
 
        /* let's see if a virtual xattr was requested */
        vxattr = ceph_match_vxattr(inode, name);
        if (vxattr && !(vxattr->exists_cb && !vxattr->exists_cb(ci))) {
                err = vxattr->getxattr_cb(ci, value, size);
-               goto out;
+               return err;
        }
 
+       spin_lock(&ci->i_ceph_lock);
+       dout("getxattr %p ver=%lld index_ver=%lld\n", inode,
+            ci->i_xattrs.version, ci->i_xattrs.index_version);
+
        if (__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 1) &&
            (ci->i_xattrs.index_version >= ci->i_xattrs.version)) {
                goto get_xattr;
index 4fb097468e214feb00b8602dd6dd658b20fafd88..fe8d6276410a5613230743f20312d4f283db2f4f 100644 (file)
@@ -327,14 +327,14 @@ UniToupper(register wchar_t uc)
 /*
  * UniStrupr:  Upper case a unicode string
  */
-static inline wchar_t *
-UniStrupr(register wchar_t *upin)
+static inline __le16 *
+UniStrupr(register __le16 *upin)
 {
-       register wchar_t *up;
+       register __le16 *up;
 
        up = upin;
        while (*up) {           /* For all characters */
-               *up = UniToupper(*up);
+               *up = cpu_to_le16(UniToupper(le16_to_cpu(*up)));
                up++;
        }
        return upin;            /* Return input pointer */
index 71436d1fca13bede14a8a25ac6a9ae126e80dede..5c807b23ca67e1e648362275558649ecbc3261f4 100644 (file)
@@ -389,7 +389,7 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
                if (blobptr + attrsize > blobend)
                        break;
                if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
-                       if (!attrsize)
+                       if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN)
                                break;
                        if (!ses->domainName) {
                                ses->domainName =
@@ -414,7 +414,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
        int rc = 0;
        int len;
        char nt_hash[CIFS_NTHASH_SIZE];
-       wchar_t *user;
+       __le16 *user;
        wchar_t *domain;
        wchar_t *server;
 
@@ -439,7 +439,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
                return rc;
        }
 
-       /* convert ses->user_name to unicode and uppercase */
+       /* convert ses->user_name to unicode */
        len = ses->user_name ? strlen(ses->user_name) : 0;
        user = kmalloc(2 + (len * 2), GFP_KERNEL);
        if (user == NULL) {
@@ -448,7 +448,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
        }
 
        if (len) {
-               len = cifs_strtoUTF16((__le16 *)user, ses->user_name, len, nls_cp);
+               len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp);
                UniStrupr(user);
        } else {
                memset(user, '\0', 2);
index 4f07f6fbe4944c5e6f8bdf12c30b4eaed9397976..ea3a0b3018a5f869bffdc536c7ad9a4ffd57f953 100644 (file)
@@ -44,6 +44,7 @@
 #define MAX_TREE_SIZE (2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1)
 #define MAX_SERVER_SIZE 15
 #define MAX_SHARE_SIZE 80
+#define CIFS_MAX_DOMAINNAME_LEN 256 /* max domain name length */
 #define MAX_USERNAME_SIZE 256  /* reasonable maximum for current servers */
 #define MAX_PASSWORD_SIZE 512  /* max for windows seems to be 256 wide chars */
 
index e3bc39bb9d12b224d7cda96e2e55b9babed68c0b..d05a30072023c563e48059b6ac0bddeda3f0a794 100644 (file)
@@ -377,6 +377,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
                try_to_freeze();
 
                /* we should try only the port we connected to before */
+               mutex_lock(&server->srv_mutex);
                rc = generic_ip_connect(server);
                if (rc) {
                        cifs_dbg(FYI, "reconnect error %d\n", rc);
@@ -388,6 +389,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
                                server->tcpStatus = CifsNeedNegotiate;
                        spin_unlock(&GlobalMid_Lock);
                }
+               mutex_unlock(&server->srv_mutex);
        } while (server->tcpStatus == CifsNeedReconnect);
 
        return rc;
@@ -1662,7 +1664,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (strnlen(string, 256) == 256) {
+                       if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
+                                       == CIFS_MAX_DOMAINNAME_LEN) {
                                printk(KERN_WARNING "CIFS: domain name too"
                                                    " long\n");
                                goto cifs_parse_mount_err;
@@ -2288,8 +2291,8 @@ cifs_put_smb_ses(struct cifs_ses *ses)
 
 #ifdef CONFIG_KEYS
 
-/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
-#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
+/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
+#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
 
 /* Populate username and pw fields from keyring if possible */
 static int
index 48b29d24c9f4d58e225d060b70da4fc2e5ea5e5e..c2934f8701daca59e8b9f04c5f8d7869d176e396 100644 (file)
@@ -553,11 +553,10 @@ cifs_relock_file(struct cifsFileInfo *cfile)
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
        int rc = 0;
 
-       /* we are going to update can_cache_brlcks here - need a write access */
-       down_write(&cinode->lock_sem);
+       down_read(&cinode->lock_sem);
        if (cinode->can_cache_brlcks) {
-               /* can cache locks - no need to push them */
-               up_write(&cinode->lock_sem);
+               /* can cache locks - no need to relock */
+               up_read(&cinode->lock_sem);
                return rc;
        }
 
@@ -568,7 +567,7 @@ cifs_relock_file(struct cifsFileInfo *cfile)
        else
                rc = tcon->ses->server->ops->push_mand_locks(cfile);
 
-       up_write(&cinode->lock_sem);
+       up_read(&cinode->lock_sem);
        return rc;
 }
 
index 20efd81266c643338bcd81b434edfe9fbcacc0ac..449b6cf09b09dbc15e90f311e09bc011a0157b44 100644 (file)
@@ -558,6 +558,11 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
                        fattr->cf_mode &= ~(S_IWUGO);
 
                fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
+               if (fattr->cf_nlink < 1) {
+                       cifs_dbg(1, "replacing bogus file nlink value %u\n",
+                               fattr->cf_nlink);
+                       fattr->cf_nlink = 1;
+               }
        }
 
        fattr->cf_uid = cifs_sb->mnt_uid;
index 770d5a9781c1ccc0a67d033aafd66d3e4473f929..036279c064ff423726d27f4a192ece0b3eb3f057 100644 (file)
@@ -111,6 +111,14 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
                        return;
        }
 
+       /*
+        * If we know that the inode will need to be revalidated immediately,
+        * then don't create a new dentry for it. We'll end up doing an on
+        * the wire call either way and this spares us an invalidation.
+        */
+       if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
+               return;
+
        dentry = d_alloc(parent, name);
        if (!dentry)
                return;
index f230571a7ab30d1c7d809eafbfdf9cb5724c2dd3..8edc9eb1ef7bdbd6a8b7b199157eb79c40f8b80f 100644 (file)
@@ -198,7 +198,7 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
                bytes_ret = 0;
        } else
                bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
-                                           256, nls_cp);
+                                           CIFS_MAX_DOMAINNAME_LEN, nls_cp);
        bcc_ptr += 2 * bytes_ret;
        bcc_ptr += 2;  /* account for null terminator */
 
@@ -256,8 +256,8 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
 
        /* copy domain */
        if (ses->domainName != NULL) {
-               strncpy(bcc_ptr, ses->domainName, 256);
-               bcc_ptr += strnlen(ses->domainName, 256);
+               strncpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
+               bcc_ptr += strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
        } /* else we will send a null domain name
             so the server will default to its own domain */
        *bcc_ptr = 0;
index 10383d8c015b12c4aa7bd936972e58bca97a648b..4f791e0e98d7b60f0ea86dcd0d0a78199b64160c 100644 (file)
@@ -413,96 +413,108 @@ cifs_ses_oplock_break(struct work_struct *work)
 }
 
 static bool
-smb2_is_valid_lease_break(char *buffer, struct TCP_Server_Info *server)
+smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp,
+                   struct smb2_lease_break_work *lw)
 {
-       struct smb2_lease_break *rsp = (struct smb2_lease_break *)buffer;
-       struct list_head *tmp, *tmp1, *tmp2;
-       struct cifs_ses *ses;
-       struct cifs_tcon *tcon;
-       struct cifsInodeInfo *cinode;
+       bool found;
+       __u8 lease_state;
+       struct list_head *tmp;
        struct cifsFileInfo *cfile;
        struct cifs_pending_open *open;
-       struct smb2_lease_break_work *lw;
-       bool found;
+       struct cifsInodeInfo *cinode;
        int ack_req = le32_to_cpu(rsp->Flags &
                                  SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
 
-       lw = kmalloc(sizeof(struct smb2_lease_break_work), GFP_KERNEL);
-       if (!lw)
-               return false;
+       lease_state = smb2_map_lease_to_oplock(rsp->NewLeaseState);
 
-       INIT_WORK(&lw->lease_break, cifs_ses_oplock_break);
-       lw->lease_state = rsp->NewLeaseState;
+       list_for_each(tmp, &tcon->openFileList) {
+               cfile = list_entry(tmp, struct cifsFileInfo, tlist);
+               cinode = CIFS_I(cfile->dentry->d_inode);
 
-       cifs_dbg(FYI, "Checking for lease break\n");
+               if (memcmp(cinode->lease_key, rsp->LeaseKey,
+                                                       SMB2_LEASE_KEY_SIZE))
+                       continue;
 
-       /* look up tcon based on tid & uid */
-       spin_lock(&cifs_tcp_ses_lock);
-       list_for_each(tmp, &server->smb_ses_list) {
-               ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
+               cifs_dbg(FYI, "found in the open list\n");
+               cifs_dbg(FYI, "lease key match, lease break 0x%d\n",
+                        le32_to_cpu(rsp->NewLeaseState));
 
-               spin_lock(&cifs_file_list_lock);
-               list_for_each(tmp1, &ses->tcon_list) {
-                       tcon = list_entry(tmp1, struct cifs_tcon, tcon_list);
+               smb2_set_oplock_level(cinode, lease_state);
 
-                       cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
-                       list_for_each(tmp2, &tcon->openFileList) {
-                               cfile = list_entry(tmp2, struct cifsFileInfo,
-                                                  tlist);
-                               cinode = CIFS_I(cfile->dentry->d_inode);
+               if (ack_req)
+                       cfile->oplock_break_cancelled = false;
+               else
+                       cfile->oplock_break_cancelled = true;
 
-                               if (memcmp(cinode->lease_key, rsp->LeaseKey,
-                                          SMB2_LEASE_KEY_SIZE))
-                                       continue;
+               queue_work(cifsiod_wq, &cfile->oplock_break);
+               kfree(lw);
+               return true;
+       }
 
-                               cifs_dbg(FYI, "found in the open list\n");
-                               cifs_dbg(FYI, "lease key match, lease break 0x%d\n",
-                                        le32_to_cpu(rsp->NewLeaseState));
+       found = false;
+       list_for_each_entry(open, &tcon->pending_opens, olist) {
+               if (memcmp(open->lease_key, rsp->LeaseKey,
+                          SMB2_LEASE_KEY_SIZE))
+                       continue;
+
+               if (!found && ack_req) {
+                       found = true;
+                       memcpy(lw->lease_key, open->lease_key,
+                              SMB2_LEASE_KEY_SIZE);
+                       lw->tlink = cifs_get_tlink(open->tlink);
+                       queue_work(cifsiod_wq, &lw->lease_break);
+               }
 
-                               smb2_set_oplock_level(cinode,
-                                 smb2_map_lease_to_oplock(rsp->NewLeaseState));
+               cifs_dbg(FYI, "found in the pending open list\n");
+               cifs_dbg(FYI, "lease key match, lease break 0x%d\n",
+                        le32_to_cpu(rsp->NewLeaseState));
 
-                               if (ack_req)
-                                       cfile->oplock_break_cancelled = false;
-                               else
-                                       cfile->oplock_break_cancelled = true;
+               open->oplock = lease_state;
+       }
+       return found;
+}
 
-                               queue_work(cifsiod_wq, &cfile->oplock_break);
+static bool
+smb2_is_valid_lease_break(char *buffer)
+{
+       struct smb2_lease_break *rsp = (struct smb2_lease_break *)buffer;
+       struct list_head *tmp, *tmp1, *tmp2;
+       struct TCP_Server_Info *server;
+       struct cifs_ses *ses;
+       struct cifs_tcon *tcon;
+       struct smb2_lease_break_work *lw;
 
-                               spin_unlock(&cifs_file_list_lock);
-                               spin_unlock(&cifs_tcp_ses_lock);
-                               return true;
-                       }
+       lw = kmalloc(sizeof(struct smb2_lease_break_work), GFP_KERNEL);
+       if (!lw)
+               return false;
 
-                       found = false;
-                       list_for_each_entry(open, &tcon->pending_opens, olist) {
-                               if (memcmp(open->lease_key, rsp->LeaseKey,
-                                          SMB2_LEASE_KEY_SIZE))
-                                       continue;
+       INIT_WORK(&lw->lease_break, cifs_ses_oplock_break);
+       lw->lease_state = rsp->NewLeaseState;
 
-                               if (!found && ack_req) {
-                                       found = true;
-                                       memcpy(lw->lease_key, open->lease_key,
-                                              SMB2_LEASE_KEY_SIZE);
-                                       lw->tlink = cifs_get_tlink(open->tlink);
-                                       queue_work(cifsiod_wq,
-                                                  &lw->lease_break);
-                               }
+       cifs_dbg(FYI, "Checking for lease break\n");
+
+       /* look up tcon based on tid & uid */
+       spin_lock(&cifs_tcp_ses_lock);
+       list_for_each(tmp, &cifs_tcp_ses_list) {
+               server = list_entry(tmp, struct TCP_Server_Info, tcp_ses_list);
 
-                               cifs_dbg(FYI, "found in the pending open list\n");
-                               cifs_dbg(FYI, "lease key match, lease break 0x%d\n",
-                                        le32_to_cpu(rsp->NewLeaseState));
+               list_for_each(tmp1, &server->smb_ses_list) {
+                       ses = list_entry(tmp1, struct cifs_ses, smb_ses_list);
 
-                               open->oplock =
-                                 smb2_map_lease_to_oplock(rsp->NewLeaseState);
-                       }
-                       if (found) {
-                               spin_unlock(&cifs_file_list_lock);
-                               spin_unlock(&cifs_tcp_ses_lock);
-                               return true;
+                       spin_lock(&cifs_file_list_lock);
+                       list_for_each(tmp2, &ses->tcon_list) {
+                               tcon = list_entry(tmp2, struct cifs_tcon,
+                                                 tcon_list);
+                               cifs_stats_inc(
+                                   &tcon->stats.cifs_stats.num_oplock_brks);
+                               if (smb2_tcon_has_lease(tcon, rsp, lw)) {
+                                       spin_unlock(&cifs_file_list_lock);
+                                       spin_unlock(&cifs_tcp_ses_lock);
+                                       return true;
+                               }
                        }
+                       spin_unlock(&cifs_file_list_lock);
                }
-               spin_unlock(&cifs_file_list_lock);
        }
        spin_unlock(&cifs_tcp_ses_lock);
        kfree(lw);
@@ -528,7 +540,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
        if (rsp->StructureSize !=
                                smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) {
                if (le16_to_cpu(rsp->StructureSize) == 44)
-                       return smb2_is_valid_lease_break(buffer, server);
+                       return smb2_is_valid_lease_break(buffer);
                else
                        return false;
        }
index 4888cb3fdef76037b7af5f9db898bdcb82ce48c2..c7c83ff0f752ce6a86d6e42a420e34ed996ae8ca 100644 (file)
@@ -533,8 +533,7 @@ EXPORT_SYMBOL_GPL(debugfs_remove);
  */
 void debugfs_remove_recursive(struct dentry *dentry)
 {
-       struct dentry *child;
-       struct dentry *parent;
+       struct dentry *child, *next, *parent;
 
        if (IS_ERR_OR_NULL(dentry))
                return;
@@ -544,61 +543,37 @@ void debugfs_remove_recursive(struct dentry *dentry)
                return;
 
        parent = dentry;
+ down:
        mutex_lock(&parent->d_inode->i_mutex);
+       list_for_each_entry_safe(child, next, &parent->d_subdirs, d_u.d_child) {
+               if (!debugfs_positive(child))
+                       continue;
 
-       while (1) {
-               /*
-                * When all dentries under "parent" has been removed,
-                * walk up the tree until we reach our starting point.
-                */
-               if (list_empty(&parent->d_subdirs)) {
-                       mutex_unlock(&parent->d_inode->i_mutex);
-                       if (parent == dentry)
-                               break;
-                       parent = parent->d_parent;
-                       mutex_lock(&parent->d_inode->i_mutex);
-               }
-               child = list_entry(parent->d_subdirs.next, struct dentry,
-                               d_u.d_child);
- next_sibling:
-
-               /*
-                * If "child" isn't empty, walk down the tree and
-                * remove all its descendants first.
-                */
+               /* perhaps simple_empty(child) makes more sense */
                if (!list_empty(&child->d_subdirs)) {
                        mutex_unlock(&parent->d_inode->i_mutex);
                        parent = child;
-                       mutex_lock(&parent->d_inode->i_mutex);
-                       continue;
+                       goto down;
                }
-               __debugfs_remove(child, parent);
-               if (parent->d_subdirs.next == &child->d_u.d_child) {
-                       /*
-                        * Try the next sibling.
-                        */
-                       if (child->d_u.d_child.next != &parent->d_subdirs) {
-                               child = list_entry(child->d_u.d_child.next,
-                                                  struct dentry,
-                                                  d_u.d_child);
-                               goto next_sibling;
-                       }
-
-                       /*
-                        * Avoid infinite loop if we fail to remove
-                        * one dentry.
-                        */
-                       mutex_unlock(&parent->d_inode->i_mutex);
-                       break;
-               }
-               simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+ up:
+               if (!__debugfs_remove(child, parent))
+                       simple_release_fs(&debugfs_mount, &debugfs_mount_count);
        }
 
-       parent = dentry->d_parent;
+       mutex_unlock(&parent->d_inode->i_mutex);
+       child = parent;
+       parent = parent->d_parent;
        mutex_lock(&parent->d_inode->i_mutex);
-       __debugfs_remove(dentry, parent);
+
+       if (child != dentry) {
+               next = list_entry(child->d_u.d_child.next, struct dentry,
+                                       d_u.d_child);
+               goto up;
+       }
+
+       if (!__debugfs_remove(child, parent))
+               simple_release_fs(&debugfs_mount, &debugfs_mount_count);
        mutex_unlock(&parent->d_inode->i_mutex);
-       simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 }
 EXPORT_SYMBOL_GPL(debugfs_remove_recursive);
 
index ffd7a813ad3d06ee1e1de4e996c72282c24e7039..1f446705636bed7b7dd1816778c302572369b910 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -607,7 +607,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
                return -ENOMEM;
 
        lru_add_drain();
-       tlb_gather_mmu(&tlb, mm, 0);
+       tlb_gather_mmu(&tlb, mm, old_start, old_end);
        if (new_end > old_start) {
                /*
                 * when the old and new regions overlap clear from new_end.
@@ -624,7 +624,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
                free_pgd_range(&tlb, old_start, old_end, new_end,
                        vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING);
        }
-       tlb_finish_mmu(&tlb, new_end, old_end);
+       tlb_finish_mmu(&tlb, old_start, old_end);
 
        /*
         * Shrink the vma to just the new range.  Always succeeds.
index 692de13e35963a86dbbbab1cb246a3f2b74ba202..cea8ecf3e76e47efb977127a95cb7b70a9d5f377 100644 (file)
@@ -576,11 +576,8 @@ static int htree_dirblock_to_tree(struct file *dir_file,
                if (!ext3_check_dir_entry("htree_dirblock_to_tree", dir, de, bh,
                                        (block<<EXT3_BLOCK_SIZE_BITS(dir->i_sb))
                                                +((char *)de - bh->b_data))) {
-                       /* On error, skip the f_pos to the next block. */
-                       dir_file->f_pos = (dir_file->f_pos |
-                                       (dir->i_sb->s_blocksize - 1)) + 1;
-                       brelse (bh);
-                       return count;
+                       /* silently ignore the rest of the block */
+                       break;
                }
                ext3fs_dirhash(de->name, de->name_len, hinfo);
                if ((hinfo->hash < start_hash) ||
index d0f13eada0ed5799295a5378642cd3786cf32595..3742e4c85723c0db580f915d13346d89fa39cde1 100644 (file)
@@ -38,8 +38,8 @@ ext4_group_t ext4_get_group_number(struct super_block *sb,
        ext4_group_t group;
 
        if (test_opt2(sb, STD_GROUP_SIZE))
-               group = (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) +
-                        block) >>
+               group = (block -
+                        le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) >>
                        (EXT4_BLOCK_SIZE_BITS(sb) + EXT4_CLUSTER_BITS(sb) + 3);
        else
                ext4_get_group_no_and_offset(sb, block, &group, NULL);
index 451eb404533095fc323218fe5ea0f3caa0af8b16..1c88061da526d4c42b02aee0d46419f7246ea8e5 100644 (file)
@@ -219,10 +219,10 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
        set_buffer_prio(bh);
        if (ext4_handle_valid(handle)) {
                err = jbd2_journal_dirty_metadata(handle, bh);
-               if (err) {
-                       /* Errors can only happen if there is a bug */
-                       handle->h_err = err;
-                       __ext4_journal_stop(where, line, handle);
+               /* Errors can only happen if there is a bug */
+               if (WARN_ON_ONCE(err)) {
+                       ext4_journal_abort_handle(where, line, __func__, bh,
+                                                 handle, err);
                }
        } else {
                if (inode)
index bc0f1910b9cfa7dd5aa93b9c5d889c6fbacd037d..dc1e030472269ed93f9d7bc153cf3a990b3cf1ba 100644 (file)
@@ -4386,9 +4386,20 @@ void ext4_ext_truncate(handle_t *handle, struct inode *inode)
 
        last_block = (inode->i_size + sb->s_blocksize - 1)
                        >> EXT4_BLOCK_SIZE_BITS(sb);
+retry:
        err = ext4_es_remove_extent(inode, last_block,
                                    EXT_MAX_BLOCKS - last_block);
+       if (err == -ENOMEM) {
+               cond_resched();
+               congestion_wait(BLK_RW_ASYNC, HZ/50);
+               goto retry;
+       }
+       if (err) {
+               ext4_std_error(inode->i_sb, err);
+               return;
+       }
        err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1);
+       ext4_std_error(inode->i_sb, err);
 }
 
 static void ext4_falloc_update_inode(struct inode *inode,
@@ -4659,7 +4670,7 @@ static int ext4_xattr_fiemap(struct inode *inode,
                error = ext4_get_inode_loc(inode, &iloc);
                if (error)
                        return error;
-               physical = iloc.bh->b_blocknr << blockbits;
+               physical = (__u64)iloc.bh->b_blocknr << blockbits;
                offset = EXT4_GOOD_OLD_INODE_SIZE +
                                EXT4_I(inode)->i_extra_isize;
                physical += offset;
@@ -4667,7 +4678,7 @@ static int ext4_xattr_fiemap(struct inode *inode,
                flags |= FIEMAP_EXTENT_DATA_INLINE;
                brelse(iloc.bh);
        } else { /* external block */
-               physical = EXT4_I(inode)->i_file_acl << blockbits;
+               physical = (__u64)EXT4_I(inode)->i_file_acl << blockbits;
                length = inode->i_sb->s_blocksize;
        }
 
index b1b4d51b5d86b4e54c179ddce5f5b574238b3629..b19f0a457f329c5fb0f6974f7afff8dc79f1e31c 100644 (file)
@@ -312,7 +312,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode,
        blkbits = inode->i_sb->s_blocksize_bits;
        startoff = *offset;
        lastoff = startoff;
-       endoff = (map->m_lblk + map->m_len) << blkbits;
+       endoff = (loff_t)(map->m_lblk + map->m_len) << blkbits;
 
        index = startoff >> PAGE_CACHE_SHIFT;
        end = endoff >> PAGE_CACHE_SHIFT;
@@ -457,7 +457,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize)
                ret = ext4_map_blocks(NULL, inode, &map, 0);
                if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) {
                        if (last != start)
-                               dataoff = last << blkbits;
+                               dataoff = (loff_t)last << blkbits;
                        break;
                }
 
@@ -468,7 +468,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize)
                ext4_es_find_delayed_extent_range(inode, last, last, &es);
                if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) {
                        if (last != start)
-                               dataoff = last << blkbits;
+                               dataoff = (loff_t)last << blkbits;
                        break;
                }
 
@@ -486,7 +486,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize)
                }
 
                last++;
-               dataoff = last << blkbits;
+               dataoff = (loff_t)last << blkbits;
        } while (last <= end);
 
        mutex_unlock(&inode->i_mutex);
@@ -540,7 +540,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize)
                ret = ext4_map_blocks(NULL, inode, &map, 0);
                if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) {
                        last += ret;
-                       holeoff = last << blkbits;
+                       holeoff = (loff_t)last << blkbits;
                        continue;
                }
 
@@ -551,7 +551,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize)
                ext4_es_find_delayed_extent_range(inode, last, last, &es);
                if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) {
                        last = es.es_lblk + es.es_len;
-                       holeoff = last << blkbits;
+                       holeoff = (loff_t)last << blkbits;
                        continue;
                }
 
@@ -566,7 +566,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize)
                                                              &map, &holeoff);
                        if (!unwritten) {
                                last += ret;
-                               holeoff = last << blkbits;
+                               holeoff = (loff_t)last << blkbits;
                                continue;
                        }
                }
index 00a818d67b54930c74dad44c6f73dcb3f01e6a19..3da3bf1b2cd0bcd9e17fd7aaba92058f0d4b9ff0 100644 (file)
@@ -734,11 +734,8 @@ repeat_in_this_group:
                ino = ext4_find_next_zero_bit((unsigned long *)
                                              inode_bitmap_bh->b_data,
                                              EXT4_INODES_PER_GROUP(sb), ino);
-               if (ino >= EXT4_INODES_PER_GROUP(sb)) {
-                       if (++group == ngroups)
-                               group = 0;
-                       continue;
-               }
+               if (ino >= EXT4_INODES_PER_GROUP(sb))
+                       goto next_group;
                if (group == 0 && (ino+1) < EXT4_FIRST_INO(sb)) {
                        ext4_error(sb, "reserved inode found cleared - "
                                   "inode=%lu", ino + 1);
@@ -768,6 +765,9 @@ repeat_in_this_group:
                        goto got; /* we grabbed the inode! */
                if (ino < EXT4_INODES_PER_GROUP(sb))
                        goto repeat_in_this_group;
+next_group:
+               if (++group == ngroups)
+                       group = 0;
        }
        err = -ENOSPC;
        goto out;
index 3e2bf873e8a8b42b1564c44505e0ec8cba1971e6..33331b4c21783b1e93169d9abef3e3e0441b5956 100644 (file)
@@ -1842,7 +1842,7 @@ int ext4_inline_data_fiemap(struct inode *inode,
        if (error)
                goto out;
 
-       physical = iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits;
+       physical = (__u64)iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits;
        physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data;
        physical += offsetof(struct ext4_inode, i_block);
        length = i_size_read(inode);
index d6382b89ecbde3077720ebc6a9bb56254883e2d7..904ca1a21dce85484563d5ec4b6681b9974b32d1 100644 (file)
@@ -1118,10 +1118,13 @@ static int ext4_write_end(struct file *file,
                }
        }
 
-       if (ext4_has_inline_data(inode))
-               copied = ext4_write_inline_data_end(inode, pos, len,
-                                                   copied, page);
-       else
+       if (ext4_has_inline_data(inode)) {
+               ret = ext4_write_inline_data_end(inode, pos, len,
+                                                copied, page);
+               if (ret < 0)
+                       goto errout;
+               copied = ret;
+       } else
                copied = block_write_end(file, mapping, pos,
                                         len, copied, page, fsdata);
 
@@ -4703,7 +4706,9 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
                ext4_journal_stop(handle);
        }
 
-       if (attr->ia_valid & ATTR_SIZE) {
+       if (attr->ia_valid & ATTR_SIZE && attr->ia_size != inode->i_size) {
+               handle_t *handle;
+               loff_t oldsize = inode->i_size;
 
                if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
                        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
@@ -4711,73 +4716,60 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
                        if (attr->ia_size > sbi->s_bitmap_maxbytes)
                                return -EFBIG;
                }
-       }
-
-       if (S_ISREG(inode->i_mode) &&
-           attr->ia_valid & ATTR_SIZE &&
-           (attr->ia_size < inode->i_size)) {
-               handle_t *handle;
-
-               handle = ext4_journal_start(inode, EXT4_HT_INODE, 3);
-               if (IS_ERR(handle)) {
-                       error = PTR_ERR(handle);
-                       goto err_out;
-               }
-               if (ext4_handle_valid(handle)) {
-                       error = ext4_orphan_add(handle, inode);
-                       orphan = 1;
-               }
-               EXT4_I(inode)->i_disksize = attr->ia_size;
-               rc = ext4_mark_inode_dirty(handle, inode);
-               if (!error)
-                       error = rc;
-               ext4_journal_stop(handle);
-
-               if (ext4_should_order_data(inode)) {
-                       error = ext4_begin_ordered_truncate(inode,
+               if (S_ISREG(inode->i_mode) &&
+                   (attr->ia_size < inode->i_size)) {
+                       if (ext4_should_order_data(inode)) {
+                               error = ext4_begin_ordered_truncate(inode,
                                                            attr->ia_size);
-                       if (error) {
-                               /* Do as much error cleanup as possible */
-                               handle = ext4_journal_start(inode,
-                                                           EXT4_HT_INODE, 3);
-                               if (IS_ERR(handle)) {
-                                       ext4_orphan_del(NULL, inode);
+                               if (error)
                                        goto err_out;
-                               }
-                               ext4_orphan_del(handle, inode);
-                               orphan = 0;
-                               ext4_journal_stop(handle);
+                       }
+                       handle = ext4_journal_start(inode, EXT4_HT_INODE, 3);
+                       if (IS_ERR(handle)) {
+                               error = PTR_ERR(handle);
+                               goto err_out;
+                       }
+                       if (ext4_handle_valid(handle)) {
+                               error = ext4_orphan_add(handle, inode);
+                               orphan = 1;
+                       }
+                       EXT4_I(inode)->i_disksize = attr->ia_size;
+                       rc = ext4_mark_inode_dirty(handle, inode);
+                       if (!error)
+                               error = rc;
+                       ext4_journal_stop(handle);
+                       if (error) {
+                               ext4_orphan_del(NULL, inode);
                                goto err_out;
                        }
                }
-       }
-
-       if (attr->ia_valid & ATTR_SIZE) {
-               if (attr->ia_size != inode->i_size) {
-                       loff_t oldsize = inode->i_size;
 
-                       i_size_write(inode, attr->ia_size);
-                       /*
-                        * Blocks are going to be removed from the inode. Wait
-                        * for dio in flight.  Temporarily disable
-                        * dioread_nolock to prevent livelock.
-                        */
-                       if (orphan) {
-                               if (!ext4_should_journal_data(inode)) {
-                                       ext4_inode_block_unlocked_dio(inode);
-                                       inode_dio_wait(inode);
-                                       ext4_inode_resume_unlocked_dio(inode);
-                               } else
-                                       ext4_wait_for_tail_page_commit(inode);
-                       }
-                       /*
-                        * Truncate pagecache after we've waited for commit
-                        * in data=journal mode to make pages freeable.
-                        */
-                       truncate_pagecache(inode, oldsize, inode->i_size);
+               i_size_write(inode, attr->ia_size);
+               /*
+                * Blocks are going to be removed from the inode. Wait
+                * for dio in flight.  Temporarily disable
+                * dioread_nolock to prevent livelock.
+                */
+               if (orphan) {
+                       if (!ext4_should_journal_data(inode)) {
+                               ext4_inode_block_unlocked_dio(inode);
+                               inode_dio_wait(inode);
+                               ext4_inode_resume_unlocked_dio(inode);
+                       } else
+                               ext4_wait_for_tail_page_commit(inode);
                }
-               ext4_truncate(inode);
+               /*
+                * Truncate pagecache after we've waited for commit
+                * in data=journal mode to make pages freeable.
+                */
+               truncate_pagecache(inode, oldsize, inode->i_size);
        }
+       /*
+        * We want to call ext4_truncate() even if attr->ia_size ==
+        * inode->i_size for cases like truncation of fallocated space
+        */
+       if (attr->ia_valid & ATTR_SIZE)
+               ext4_truncate(inode);
 
        if (!rc) {
                setattr_copy(inode, attr);
@@ -4805,7 +4797,7 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
                 struct kstat *stat)
 {
        struct inode *inode;
-       unsigned long delalloc_blocks;
+       unsigned long long delalloc_blocks;
 
        inode = dentry->d_inode;
        generic_fillattr(inode, stat);
@@ -4823,7 +4815,7 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
        delalloc_blocks = EXT4_C2B(EXT4_SB(inode->i_sb),
                                EXT4_I(inode)->i_reserved_data_blocks);
 
-       stat->blocks += (delalloc_blocks << inode->i_sb->s_blocksize_bits)>>9;
+       stat->blocks += delalloc_blocks << (inode->i_sb->s_blocksize_bits-9);
        return 0;
 }
 
index 9491ac0590f746b9abe56e484e7646022a0bd1c3..c0427e2f66481a13f3018b4630901688fdd6646e 100644 (file)
@@ -77,8 +77,10 @@ static void swap_inode_data(struct inode *inode1, struct inode *inode2)
        memswap(ei1->i_data, ei2->i_data, sizeof(ei1->i_data));
        memswap(&ei1->i_flags, &ei2->i_flags, sizeof(ei1->i_flags));
        memswap(&ei1->i_disksize, &ei2->i_disksize, sizeof(ei1->i_disksize));
-       memswap(&ei1->i_es_tree, &ei2->i_es_tree, sizeof(ei1->i_es_tree));
-       memswap(&ei1->i_es_lru_nr, &ei2->i_es_lru_nr, sizeof(ei1->i_es_lru_nr));
+       ext4_es_remove_extent(inode1, 0, EXT_MAX_BLOCKS);
+       ext4_es_remove_extent(inode2, 0, EXT_MAX_BLOCKS);
+       ext4_es_lru_del(inode1);
+       ext4_es_lru_del(inode2);
 
        isize = i_size_read(inode1);
        i_size_write(inode1, i_size_read(inode2));
index def84082a9a9b73deadc0d369c63a7ef981d8ea9..59c6750b894f702cbc08e873f8e971897eb2c0f8 100644 (file)
@@ -4735,11 +4735,16 @@ do_more:
                 * blocks being freed are metadata. these blocks shouldn't
                 * be used until this transaction is committed
                 */
+       retry:
                new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS);
                if (!new_entry) {
-                       ext4_mb_unload_buddy(&e4b);
-                       err = -ENOMEM;
-                       goto error_return;
+                       /*
+                        * We use a retry loop because
+                        * ext4_free_blocks() is not allowed to fail.
+                        */
+                       cond_resched();
+                       congestion_wait(BLK_RW_ASYNC, HZ/50);
+                       goto retry;
                }
                new_entry->efd_start_cluster = bit;
                new_entry->efd_group = block_group;
index 6653fc35ecb7dda920377a7d45ab8efef2091b2d..ab2f6dc44b3abf88b62902433f48a1aa78ba8561 100644 (file)
@@ -918,11 +918,8 @@ static int htree_dirblock_to_tree(struct file *dir_file,
                                bh->b_data, bh->b_size,
                                (block<<EXT4_BLOCK_SIZE_BITS(dir->i_sb))
                                         + ((char *)de - bh->b_data))) {
-                       /* On error, skip the f_pos to the next block. */
-                       dir_file->f_pos = (dir_file->f_pos |
-                                       (dir->i_sb->s_blocksize - 1)) + 1;
-                       brelse(bh);
-                       return count;
+                       /* silently ignore the rest of the block */
+                       break;
                }
                ext4fs_dirhash(de->name, de->name_len, hinfo);
                if ((hinfo->hash < start_hash) ||
index b27c96d01965b97a1998b8542d31d9639a0b0161..49d3c01eabf898042cafd7281195aaa1922816b9 100644 (file)
@@ -1656,12 +1656,10 @@ errout:
                err = err2;
 
        if (!err) {
-               ext4_fsblk_t first_block;
-               first_block = ext4_group_first_block_no(sb, 0);
                if (test_opt(sb, DEBUG))
                        printk(KERN_DEBUG "EXT4-fs: extended group to %llu "
                               "blocks\n", ext4_blocks_count(es));
-               update_backups(sb, EXT4_SB(sb)->s_sbh->b_blocknr - first_block,
+               update_backups(sb, EXT4_SB(sb)->s_sbh->b_blocknr,
                               (char *)es, sizeof(struct ext4_super_block), 0);
        }
        return err;
index 94cc84db7c9aae349b44be229e993ec906a0a25a..3f7c39e6d097fb949493c219409dfa2ee784819a 100644 (file)
@@ -1341,7 +1341,7 @@ static const struct mount_opts {
        {Opt_delalloc, EXT4_MOUNT_DELALLOC,
         MOPT_EXT4_ONLY | MOPT_SET | MOPT_EXPLICIT},
        {Opt_nodelalloc, EXT4_MOUNT_DELALLOC,
-        MOPT_EXT4_ONLY | MOPT_CLEAR | MOPT_EXPLICIT},
+        MOPT_EXT4_ONLY | MOPT_CLEAR},
        {Opt_journal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM,
         MOPT_EXT4_ONLY | MOPT_SET},
        {Opt_journal_async_commit, (EXT4_MOUNT_JOURNAL_ASYNC_COMMIT |
@@ -1684,12 +1684,6 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
 
        if (sbi->s_qf_names[GRPQUOTA])
                seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
-
-       if (test_opt(sb, USRQUOTA))
-               seq_puts(seq, ",usrquota");
-
-       if (test_opt(sb, GRPQUOTA))
-               seq_puts(seq, ",grpquota");
 #endif
 }
 
@@ -3451,7 +3445,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                }
                if (test_opt(sb, DIOREAD_NOLOCK)) {
                        ext4_msg(sb, KERN_ERR, "can't mount with "
-                                "both data=journal and delalloc");
+                                "both data=journal and dioread_nolock");
                        goto failed_mount;
                }
                if (test_opt(sb, DELALLOC))
@@ -3586,10 +3580,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb));
        sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
 
-       /* Do we have standard group size of blocksize * 8 blocks ? */
-       if (sbi->s_blocks_per_group == blocksize << 3)
-               set_opt2(sb, STD_GROUP_SIZE);
-
        for (i = 0; i < 4; i++)
                sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
        sbi->s_def_hash_version = es->s_def_hash_version;
@@ -3659,6 +3649,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                goto failed_mount;
        }
 
+       /* Do we have standard group size of clustersize * 8 blocks ? */
+       if (sbi->s_blocks_per_group == clustersize << 3)
+               set_opt2(sb, STD_GROUP_SIZE);
+
        /*
         * Test whether we have more sectors than will fit in sector_t,
         * and whether the max offset is addressable by the page cache.
@@ -4652,6 +4646,21 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                goto restore_opts;
        }
 
+       if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
+               if (test_opt2(sb, EXPLICIT_DELALLOC)) {
+                       ext4_msg(sb, KERN_ERR, "can't mount with "
+                                "both data=journal and delalloc");
+                       err = -EINVAL;
+                       goto restore_opts;
+               }
+               if (test_opt(sb, DIOREAD_NOLOCK)) {
+                       ext4_msg(sb, KERN_ERR, "can't mount with "
+                                "both data=journal and dioread_nolock");
+                       err = -EINVAL;
+                       goto restore_opts;
+               }
+       }
+
        if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
                ext4_abort(sb, "Abort forced by user");
 
@@ -5406,6 +5415,7 @@ static void __exit ext4_exit_fs(void)
        kset_unregister(ext4_kset);
        ext4_exit_system_zone();
        ext4_exit_pageio();
+       ext4_exit_es();
 }
 
 MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
index f3f783dc4f7509096235c7f8f6ed468fe51ddded..e67b13de2ebc463b9be8c3bea57304e3af561454 100644 (file)
@@ -1175,6 +1175,8 @@ static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
                        return -EIO;
                if (reclen > nbytes)
                        break;
+               if (memchr(dirent->name, '/', dirent->namelen) != NULL)
+                       return -EIO;
 
                over = filldir(dstbuf, dirent->name, dirent->namelen,
                               file->f_pos, dirent->ino, dirent->type);
@@ -1225,13 +1227,29 @@ static int fuse_direntplus_link(struct file *file,
                if (name.name[1] == '.' && name.len == 2)
                        return 0;
        }
+
+       if (invalid_nodeid(o->nodeid))
+               return -EIO;
+       if (!fuse_valid_type(o->attr.mode))
+               return -EIO;
+
        fc = get_fuse_conn(dir);
 
        name.hash = full_name_hash(name.name, name.len);
        dentry = d_lookup(parent, &name);
-       if (dentry && dentry->d_inode) {
+       if (dentry) {
                inode = dentry->d_inode;
-               if (get_node_id(inode) == o->nodeid) {
+               if (!inode) {
+                       d_drop(dentry);
+               } else if (get_node_id(inode) != o->nodeid ||
+                          ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
+                       err = d_invalidate(dentry);
+                       if (err)
+                               goto out;
+               } else if (is_bad_inode(inode)) {
+                       err = -EIO;
+                       goto out;
+               } else {
                        struct fuse_inode *fi;
                        fi = get_fuse_inode(inode);
                        spin_lock(&fc->lock);
@@ -1244,9 +1262,6 @@ static int fuse_direntplus_link(struct file *file,
                         */
                        goto found;
                }
-               err = d_invalidate(dentry);
-               if (err)
-                       goto out;
                dput(dentry);
                dentry = NULL;
        }
@@ -1261,10 +1276,19 @@ static int fuse_direntplus_link(struct file *file,
        if (!inode)
                goto out;
 
-       alias = d_materialise_unique(dentry, inode);
-       err = PTR_ERR(alias);
-       if (IS_ERR(alias))
-               goto out;
+       if (S_ISDIR(inode->i_mode)) {
+               mutex_lock(&fc->inst_mutex);
+               alias = fuse_d_add_directory(dentry, inode);
+               mutex_unlock(&fc->inst_mutex);
+               err = PTR_ERR(alias);
+               if (IS_ERR(alias)) {
+                       iput(inode);
+                       goto out;
+               }
+       } else {
+               alias = d_splice_alias(inode, dentry);
+       }
+
        if (alias) {
                dput(dentry);
                dentry = alias;
@@ -1301,6 +1325,8 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
                        return -EIO;
                if (reclen > nbytes)
                        break;
+               if (memchr(dirent->name, '/', dirent->namelen) != NULL)
+                       return -EIO;
 
                if (!over) {
                        /* We fill entries into dstbuf only as much as
@@ -1572,6 +1598,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
                    struct file *file)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
        struct fuse_req *req;
        struct fuse_setattr_in inarg;
        struct fuse_attr_out outarg;
@@ -1599,8 +1626,10 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
        if (IS_ERR(req))
                return PTR_ERR(req);
 
-       if (is_truncate)
+       if (is_truncate) {
                fuse_set_nowrite(inode);
+               set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
+       }
 
        memset(&inarg, 0, sizeof(inarg));
        memset(&outarg, 0, sizeof(outarg));
@@ -1662,12 +1691,14 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
                invalidate_inode_pages2(inode->i_mapping);
        }
 
+       clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
        return 0;
 
 error:
        if (is_truncate)
                fuse_release_nowrite(inode);
 
+       clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
        return err;
 }
 
@@ -1731,6 +1762,8 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
                fc->no_setxattr = 1;
                err = -EOPNOTSUPP;
        }
+       if (!err)
+               fuse_invalidate_attr(inode);
        return err;
 }
 
@@ -1860,6 +1893,8 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
                fc->no_removexattr = 1;
                err = -EOPNOTSUPP;
        }
+       if (!err)
+               fuse_invalidate_attr(inode);
        return err;
 }
 
index 35f2810331427b9c4b660cc6b83ec1b889d6910b..473e8453a7df9f429a7042c667d8d7df379c86fb 100644 (file)
@@ -630,7 +630,8 @@ static void fuse_read_update_size(struct inode *inode, loff_t size,
        struct fuse_inode *fi = get_fuse_inode(inode);
 
        spin_lock(&fc->lock);
-       if (attr_ver == fi->attr_version && size < inode->i_size) {
+       if (attr_ver == fi->attr_version && size < inode->i_size &&
+           !test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) {
                fi->attr_version = ++fc->attr_version;
                i_size_write(inode, size);
        }
@@ -1033,12 +1034,16 @@ static ssize_t fuse_perform_write(struct file *file,
 {
        struct inode *inode = mapping->host;
        struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
        int err = 0;
        ssize_t res = 0;
 
        if (is_bad_inode(inode))
                return -EIO;
 
+       if (inode->i_size < pos + iov_iter_count(ii))
+               set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
+
        do {
                struct fuse_req *req;
                ssize_t count;
@@ -1074,6 +1079,7 @@ static ssize_t fuse_perform_write(struct file *file,
        if (res > 0)
                fuse_write_update_size(inode, pos);
 
+       clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
        fuse_invalidate_attr(inode);
 
        return res > 0 ? res : err;
@@ -1530,7 +1536,6 @@ static int fuse_writepage_locked(struct page *page)
 
        inc_bdi_stat(mapping->backing_dev_info, BDI_WRITEBACK);
        inc_zone_page_state(tmp_page, NR_WRITEBACK_TEMP);
-       end_page_writeback(page);
 
        spin_lock(&fc->lock);
        list_add(&req->writepages_entry, &fi->writepages);
@@ -1538,6 +1543,8 @@ static int fuse_writepage_locked(struct page *page)
        fuse_flush_writepages(inode);
        spin_unlock(&fc->lock);
 
+       end_page_writeback(page);
+
        return 0;
 
 err_free:
index fde7249a3a9608c8c6e49be4316a1d155b7cdfba..5ced199b50bbb19a9dcd8fb42313de4afba26d6c 100644 (file)
@@ -115,6 +115,8 @@ struct fuse_inode {
 enum {
        /** Advise readdirplus  */
        FUSE_I_ADVISE_RDPLUS,
+       /** An operation changing file size is in progress  */
+       FUSE_I_SIZE_UNSTABLE,
 };
 
 struct fuse_conn;
index 9a0cdde14a088c43e12e5d5fc4ba84257ca98b46..b5718516825b9b20377cc855f3956dc9f709bd5f 100644 (file)
@@ -201,7 +201,8 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
        struct timespec old_mtime;
 
        spin_lock(&fc->lock);
-       if (attr_version != 0 && fi->attr_version > attr_version) {
+       if ((attr_version != 0 && fi->attr_version > attr_version) ||
+           test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) {
                spin_unlock(&fc->lock);
                return;
        }
index 4acb19d78359d4bec83f90b854680dc3962905cf..803d3da3a0feb4e64d9672c6aa137b6b7a800951 100644 (file)
@@ -17,7 +17,8 @@ __le32 *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,
                         struct quad_buffer_head *qbh, char *id)
 {
        secno sec;
-       if (hpfs_sb(s)->sb_chk) if (bmp_block * 16384 > hpfs_sb(s)->sb_fs_size) {
+       unsigned n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;
+       if (hpfs_sb(s)->sb_chk) if (bmp_block >= n_bands) {
                hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id);
                return NULL;
        }
index a0617e7069579c61baed047b3ba2992b294d6082..962e90c37aec64ec95773467f146951995c9adc1 100644 (file)
@@ -558,7 +558,13 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
        sbi->sb_cp_table = NULL;
        sbi->sb_c_bitmap = -1;
        sbi->sb_max_fwd_alloc = 0xffffff;
-       
+
+       if (sbi->sb_fs_size >= 0x80000000) {
+               hpfs_error(s, "invalid size in superblock: %08x",
+                       (unsigned)sbi->sb_fs_size);
+               goto bail4;
+       }
+
        /* Load bitmap directory */
        if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps))))
                goto bail4;
index d9b8aebdeb22b467eb9717996b823734f8446300..d3705490ff9ca378de6ba1f63d7d1515634d6d98 100644 (file)
@@ -125,8 +125,8 @@ static void destroy_inodecache(void)
 
 static int isofs_remount(struct super_block *sb, int *flags, char *data)
 {
-       /* we probably want a lot more here */
-       *flags |= MS_RDONLY;
+       if (!(*flags & MS_RDONLY))
+               return -EROFS;
        return 0;
 }
 
@@ -779,15 +779,6 @@ root_found:
         */
        s->s_maxbytes = 0x80000000000LL;
 
-       /*
-        * The CDROM is read-only, has no nodes (devices) on it, and since
-        * all of the files appear to be owned by root, we really do not want
-        * to allow suid.  (suid or devices will not show up unless we have
-        * Rock Ridge extensions)
-        */
-
-       s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
-
        /* Set this for reference. Its not currently used except on write
           which we don't have .. */
 
@@ -1546,6 +1537,9 @@ struct inode *isofs_iget(struct super_block *sb,
 static struct dentry *isofs_mount(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data)
 {
+       /* We don't support read-write mounts */
+       if (!(flags & MS_RDONLY))
+               return ERR_PTR(-EACCES);
        return mount_bdev(fs_type, flags, dev_name, data, isofs_fill_super);
 }
 
index 95457576e434b2624475bbdab2758974eefbd9d5..aaa1a3f33b0e951150203e4426c377af0d1605e2 100644 (file)
@@ -1318,6 +1318,7 @@ static int journal_reset(journal_t *journal)
 static void jbd2_write_superblock(journal_t *journal, int write_op)
 {
        struct buffer_head *bh = journal->j_sb_buffer;
+       journal_superblock_t *sb = journal->j_superblock;
        int ret;
 
        trace_jbd2_write_superblock(journal, write_op);
@@ -1339,6 +1340,7 @@ static void jbd2_write_superblock(journal_t *journal, int write_op)
                clear_buffer_write_io_error(bh);
                set_buffer_uptodate(bh);
        }
+       jbd2_superblock_csum_set(journal, sb);
        get_bh(bh);
        bh->b_end_io = end_buffer_write_sync;
        ret = submit_bh(write_op, bh);
@@ -1435,7 +1437,6 @@ void jbd2_journal_update_sb_errno(journal_t *journal)
        jbd_debug(1, "JBD2: updating superblock error (errno %d)\n",
                  journal->j_errno);
        sb->s_errno    = cpu_to_be32(journal->j_errno);
-       jbd2_superblock_csum_set(journal, sb);
        read_unlock(&journal->j_state_lock);
 
        jbd2_write_superblock(journal, WRITE_SYNC);
index 10f524c59ea88d48bf4f85f42e6fb2eca0d7a55b..e0c0bc275924a12bc6f7670ec665b56f23c848fa 100644 (file)
@@ -517,10 +517,10 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask)
                   &transaction->t_outstanding_credits);
        if (atomic_dec_and_test(&transaction->t_updates))
                wake_up(&journal->j_wait_updates);
+       tid = transaction->t_tid;
        spin_unlock(&transaction->t_handle_lock);
 
        jbd_debug(2, "restarting handle %p\n", handle);
-       tid = transaction->t_tid;
        need_to_start = !tid_geq(journal->j_commit_request, tid);
        read_unlock(&journal->j_state_lock);
        if (need_to_start)
index 0ddbeceafc626f9471042f09f7a74ada4514ad12..c450fdb3d78d21575440fb73bed5bb5e0ae911e8 100644 (file)
@@ -3047,6 +3047,14 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
                dir_index = (u32) filp->f_pos;
 
+               /*
+                * NFSv4 reserves cookies 1 and 2 for . and .. so we add
+                * the value we return to the vfs is one greater than the
+                * one we use internally.
+                */
+               if (dir_index)
+                       dir_index--;
+
                if (dir_index > 1) {
                        struct dir_table_slot dirtab_slot;
 
@@ -3086,7 +3094,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                        if (p->header.flag & BT_INTERNAL) {
                                jfs_err("jfs_readdir: bad index table");
                                DT_PUTPAGE(mp);
-                               filp->f_pos = -1;
+                               filp->f_pos = DIREND;
                                return 0;
                        }
                } else {
@@ -3094,7 +3102,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                                /*
                                 * self "."
                                 */
-                               filp->f_pos = 0;
+                               filp->f_pos = 1;
                                if (filldir(dirent, ".", 1, 0, ip->i_ino,
                                            DT_DIR))
                                        return 0;
@@ -3102,7 +3110,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                        /*
                         * parent ".."
                         */
-                       filp->f_pos = 1;
+                       filp->f_pos = 2;
                        if (filldir(dirent, "..", 2, 1, PARENT(ip), DT_DIR))
                                return 0;
 
@@ -3123,24 +3131,25 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                /*
                 * Legacy filesystem - OS/2 & Linux JFS < 0.3.6
                 *
-                * pn = index = 0:      First entry "."
-                * pn = 0; index = 1:   Second entry ".."
+                * pn = 0; index = 1:   First entry "."
+                * pn = 0; index = 2:   Second entry ".."
                 * pn > 0:              Real entries, pn=1 -> leftmost page
                 * pn = index = -1:     No more entries
                 */
                dtpos = filp->f_pos;
-               if (dtpos == 0) {
+               if (dtpos < 2) {
                        /* build "." entry */
 
+                       filp->f_pos = 1;
                        if (filldir(dirent, ".", 1, filp->f_pos, ip->i_ino,
                                    DT_DIR))
                                return 0;
-                       dtoffset->index = 1;
+                       dtoffset->index = 2;
                        filp->f_pos = dtpos;
                }
 
                if (dtoffset->pn == 0) {
-                       if (dtoffset->index == 1) {
+                       if (dtoffset->index == 2) {
                                /* build ".." entry */
 
                                if (filldir(dirent, "..", 2, filp->f_pos,
@@ -3233,6 +3242,12 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                                        }
                                        jfs_dirent->position = unique_pos++;
                                }
+                               /*
+                                * We add 1 to the index because we may
+                                * use a value of 2 internally, and NFSv4
+                                * doesn't like that.
+                                */
+                               jfs_dirent->position++;
                        } else {
                                jfs_dirent->position = dtpos;
                                len = min(d_namleft, DTLHDRDATALEN_LEGACY);
index 01bfe76627516d836241b249bdeac7b0a02b0f97..41e491b8e5d7e40164e0e51d90534c9d8660a94e 100644 (file)
@@ -64,12 +64,17 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)
                                   nlm_init->protocol, nlm_version,
                                   nlm_init->hostname, nlm_init->noresvport,
                                   nlm_init->net);
-       if (host == NULL) {
-               lockd_down(nlm_init->net);
-               return ERR_PTR(-ENOLCK);
-       }
+       if (host == NULL)
+               goto out_nohost;
+       if (host->h_rpcclnt == NULL && nlm_bind_host(host) == NULL)
+               goto out_nobind;
 
        return host;
+out_nobind:
+       nlmclnt_release_host(host);
+out_nohost:
+       lockd_down(nlm_init->net);
+       return ERR_PTR(-ENOLCK);
 }
 EXPORT_SYMBOL_GPL(nlmclnt_init);
 
index 9760ecb9b60f6ae39471ea09fd8f286ca0285da7..acd3947163497b802544a632aa02512c37b88d9d 100644 (file)
@@ -125,14 +125,15 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
 {
        struct nlm_args *argp = &req->a_args;
        struct nlm_lock *lock = &argp->lock;
+       char *nodename = req->a_host->h_rpcclnt->cl_nodename;
 
        nlmclnt_next_cookie(&argp->cookie);
        memcpy(&lock->fh, NFS_FH(file_inode(fl->fl_file)), sizeof(struct nfs_fh));
-       lock->caller  = utsname()->nodename;
+       lock->caller  = nodename;
        lock->oh.data = req->a_owner;
        lock->oh.len  = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s",
                                (unsigned int)fl->fl_u.nfs_fl.owner->pid,
-                               utsname()->nodename);
+                               nodename);
        lock->svid = fl->fl_u.nfs_fl.owner->pid;
        lock->fl.fl_start = fl->fl_start;
        lock->fl.fl_end = fl->fl_end;
index e703318c41dface91c09b100a3c88bacd63f6751..8ebd3f551e0c861e15f8f9e1c946daad202dc883 100644 (file)
@@ -939,6 +939,7 @@ nlmsvc_retry_blocked(void)
        unsigned long   timeout = MAX_SCHEDULE_TIMEOUT;
        struct nlm_block *block;
 
+       spin_lock(&nlm_blocked_lock);
        while (!list_empty(&nlm_blocked) && !kthread_should_stop()) {
                block = list_entry(nlm_blocked.next, struct nlm_block, b_list);
 
@@ -948,6 +949,7 @@ nlmsvc_retry_blocked(void)
                        timeout = block->b_when - jiffies;
                        break;
                }
+               spin_unlock(&nlm_blocked_lock);
 
                dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
                        block, block->b_when);
@@ -957,7 +959,9 @@ nlmsvc_retry_blocked(void)
                        retry_deferred_block(block);
                } else
                        nlmsvc_grant_blocked(block);
+               spin_lock(&nlm_blocked_lock);
        }
+       spin_unlock(&nlm_blocked_lock);
 
        return timeout;
 }
index 7b1ca9ba0b0a70213915f6d7bce688184ab7a56f..a45ba4f267fe6e834909f122dd166cdd608dcce5 100644 (file)
@@ -1429,7 +1429,7 @@ struct vfsmount *collect_mounts(struct path *path)
                         CL_COPY_ALL | CL_PRIVATE);
        namespace_unlock();
        if (IS_ERR(tree))
-               return NULL;
+               return ERR_CAST(tree);
        return &tree->mnt;
 }
 
index 1fab140764c42756867f064a81b61903b8858a91..2c37442ed9369c7bccdba4f75797dcea314357b7 100644 (file)
@@ -228,19 +228,8 @@ static int nfs41_setup_state_renewal(struct nfs_client *clp)
        return status;
 }
 
-/*
- * Back channel returns NFS4ERR_DELAY for new requests when
- * NFS4_SESSION_DRAINING is set so there is no work to be done when draining
- * is ended.
- */
-static void nfs4_end_drain_session(struct nfs_client *clp)
+static void nfs4_end_drain_slot_table(struct nfs4_slot_table *tbl)
 {
-       struct nfs4_session *ses = clp->cl_session;
-       struct nfs4_slot_table *tbl;
-
-       if (ses == NULL)
-               return;
-       tbl = &ses->fc_slot_table;
        if (test_and_clear_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state)) {
                spin_lock(&tbl->slot_tbl_lock);
                nfs41_wake_slot_table(tbl);
@@ -248,6 +237,16 @@ static void nfs4_end_drain_session(struct nfs_client *clp)
        }
 }
 
+static void nfs4_end_drain_session(struct nfs_client *clp)
+{
+       struct nfs4_session *ses = clp->cl_session;
+
+       if (ses != NULL) {
+               nfs4_end_drain_slot_table(&ses->bc_slot_table);
+               nfs4_end_drain_slot_table(&ses->fc_slot_table);
+       }
+}
+
 /*
  * Signal state manager thread if session fore channel is drained
  */
index 6cd86e0fe450a2b4ed36e447b946970cceaca95b..582321a978b0cbba31fd26d92bc9d8ec93ad4502 100644 (file)
@@ -162,8 +162,8 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
         */
        memcpy(p, argp->p, avail);
        /* step to next page */
-       argp->p = page_address(argp->pagelist[0]);
        argp->pagelist++;
+       argp->p = page_address(argp->pagelist[0]);
        if (argp->pagelen < PAGE_SIZE) {
                argp->end = argp->p + (argp->pagelen>>2);
                argp->pagelen = 0;
index 84ce601d80632ba1dd090cd319766cecbe4cac98..baf149a85263bfc87785e9a1581f57026bee2afe 100644 (file)
@@ -802,9 +802,10 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
                        flags = O_WRONLY|O_LARGEFILE;
        }
        *filp = dentry_open(&path, flags, current_cred());
-       if (IS_ERR(*filp))
+       if (IS_ERR(*filp)) {
                host_err = PTR_ERR(*filp);
-       else {
+               *filp = NULL;
+       } else {
                host_err = ima_file_check(*filp, may_flags);
 
                if (may_flags & NFSD_MAY_64BIT_COOKIE)
index dc9a913784ab94127fba6e4503d12a0708069f41..2d8be51f90dc9257bf74cad77b719d17f781c739 100644 (file)
@@ -345,8 +345,7 @@ static void nilfs_end_bio_write(struct bio *bio, int err)
 
        if (err == -EOPNOTSUPP) {
                set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
-               bio_put(bio);
-               /* to be detected by submit_seg_bio() */
+               /* to be detected by nilfs_segbuf_submit_bio() */
        }
 
        if (!uptodate)
@@ -377,12 +376,12 @@ static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer *segbuf,
        bio->bi_private = segbuf;
        bio_get(bio);
        submit_bio(mode, bio);
+       segbuf->sb_nbio++;
        if (bio_flagged(bio, BIO_EOPNOTSUPP)) {
                bio_put(bio);
                err = -EOPNOTSUPP;
                goto failed;
        }
-       segbuf->sb_nbio++;
        bio_put(bio);
 
        wi->bio = NULL;
index 6c80083a984fc192ebc73bad2a2edc86b4c25e11..77cc85dd0db01f1ead504e96e8f521d11eeb8af4 100644 (file)
@@ -122,6 +122,7 @@ static int fill_event_metadata(struct fsnotify_group *group,
        metadata->event_len = FAN_EVENT_METADATA_LEN;
        metadata->metadata_len = FAN_EVENT_METADATA_LEN;
        metadata->vers = FANOTIFY_METADATA_VERSION;
+       metadata->reserved = 0;
        metadata->mask = event->mask & FAN_ALL_OUTGOING_EVENTS;
        metadata->pid = pid_vnr(event->tgid);
        if (unlikely(event->mask & FAN_Q_OVERFLOW))
index 2487116d0d3312981834aa3667fd708dc7aa05ab..8460647266822fe6140b00d46a9130058171e92e 100644 (file)
@@ -781,7 +781,6 @@ int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
        cpos = map_start >> osb->s_clustersize_bits;
        mapping_end = ocfs2_clusters_for_bytes(inode->i_sb,
                                               map_start + map_len);
-       mapping_end -= cpos;
        is_last = 0;
        while (cpos < mapping_end && !is_last) {
                u32 fe_flags;
index 2e3ea308c14430640fe3a28f35d5149fc3d7cdf0..5b8d944361058ff48ca83f536ab803a87f660112 100644 (file)
@@ -6499,6 +6499,16 @@ static int ocfs2_reflink_xattr_inline(struct ocfs2_xattr_reflink *args)
        }
 
        new_oi = OCFS2_I(args->new_inode);
+       /*
+        * Adjust extent record count to reserve space for extended attribute.
+        * Inline data count had been adjusted in ocfs2_duplicate_inline_data().
+        */
+       if (!(new_oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) &&
+           !(ocfs2_inode_is_fast_symlink(args->new_inode))) {
+               struct ocfs2_extent_list *el = &new_di->id2.i_list;
+               le16_add_cpu(&el->l_count, -(inline_size /
+                                       sizeof(struct ocfs2_extent_rec)));
+       }
        spin_lock(&new_oi->ip_lock);
        new_oi->ip_dyn_features |= OCFS2_HAS_XATTR_FL | OCFS2_INLINE_XATTR_FL;
        new_di->i_dyn_features = cpu_to_le16(new_oi->ip_dyn_features);
index 41a6ea93f486ff81b6b112821339a66f0b020324..04ec276c7bab9dfcfd65a4bc5e61bb15ac413a2f 100644 (file)
@@ -110,7 +110,8 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
                ns = task_active_pid_ns(current);
                options = data;
 
-               if (!current_user_ns()->may_mount_proc)
+               if (!current_user_ns()->may_mount_proc ||
+                   !ns_capable(ns->user_ns, CAP_SYS_ADMIN))
                        return ERR_PTR(-EPERM);
        }
 
index 3e636d864d5666aa2b7a58a5f61af214e6d30832..65fc60a07c47ba7fb13879f130c4c9c93046c18f 100644 (file)
@@ -792,14 +792,14 @@ typedef struct {
 } pagemap_entry_t;
 
 struct pagemapread {
-       int pos, len;
+       int pos, len;           /* units: PM_ENTRY_BYTES, not bytes */
        pagemap_entry_t *buffer;
 };
 
 #define PAGEMAP_WALK_SIZE      (PMD_SIZE)
 #define PAGEMAP_WALK_MASK      (PMD_MASK)
 
-#define PM_ENTRY_BYTES      sizeof(u64)
+#define PM_ENTRY_BYTES      sizeof(pagemap_entry_t)
 #define PM_STATUS_BITS      3
 #define PM_STATUS_OFFSET    (64 - PM_STATUS_BITS)
 #define PM_STATUS_MASK      (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET)
@@ -1038,8 +1038,8 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
        if (!count)
                goto out_task;
 
-       pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
-       pm.buffer = kmalloc(pm.len, GFP_TEMPORARY);
+       pm.len = (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
+       pm.buffer = kmalloc(pm.len * PM_ENTRY_BYTES, GFP_TEMPORARY);
        ret = -ENOMEM;
        if (!pm.buffer)
                goto out_task;
index 33532f79b4f714923ec951fa5fb75d1758fbfda3..1d48974c25dd47f54c2c3d2a9501d04244a72d1b 100644 (file)
 /*
  * LOCKING:
  *
- * We rely on new Alexander Viro's super-block locking.
+ * These guys are evicted from procfs as the very first step in ->kill_sb().
  *
  */
 
-static int show_version(struct seq_file *m, struct super_block *sb)
+static int show_version(struct seq_file *m, void *unused)
 {
+       struct super_block *sb = m->private;
        char *format;
 
        if (REISERFS_SB(sb)->s_properties & (1 << REISERFS_3_6)) {
@@ -66,8 +67,9 @@ static int show_version(struct seq_file *m, struct super_block *sb)
 #define DJP( x ) le32_to_cpu( jp -> x )
 #define JF( x ) ( r -> s_journal -> x )
 
-static int show_super(struct seq_file *m, struct super_block *sb)
+static int show_super(struct seq_file *m, void *unused)
 {
+       struct super_block *sb = m->private;
        struct reiserfs_sb_info *r = REISERFS_SB(sb);
 
        seq_printf(m, "state: \t%s\n"
@@ -128,8 +130,9 @@ static int show_super(struct seq_file *m, struct super_block *sb)
        return 0;
 }
 
-static int show_per_level(struct seq_file *m, struct super_block *sb)
+static int show_per_level(struct seq_file *m, void *unused)
 {
+       struct super_block *sb = m->private;
        struct reiserfs_sb_info *r = REISERFS_SB(sb);
        int level;
 
@@ -186,8 +189,9 @@ static int show_per_level(struct seq_file *m, struct super_block *sb)
        return 0;
 }
 
-static int show_bitmap(struct seq_file *m, struct super_block *sb)
+static int show_bitmap(struct seq_file *m, void *unused)
 {
+       struct super_block *sb = m->private;
        struct reiserfs_sb_info *r = REISERFS_SB(sb);
 
        seq_printf(m, "free_block: %lu\n"
@@ -218,8 +222,9 @@ static int show_bitmap(struct seq_file *m, struct super_block *sb)
        return 0;
 }
 
-static int show_on_disk_super(struct seq_file *m, struct super_block *sb)
+static int show_on_disk_super(struct seq_file *m, void *unused)
 {
+       struct super_block *sb = m->private;
        struct reiserfs_sb_info *sb_info = REISERFS_SB(sb);
        struct reiserfs_super_block *rs = sb_info->s_rs;
        int hash_code = DFL(s_hash_function_code);
@@ -261,8 +266,9 @@ static int show_on_disk_super(struct seq_file *m, struct super_block *sb)
        return 0;
 }
 
-static int show_oidmap(struct seq_file *m, struct super_block *sb)
+static int show_oidmap(struct seq_file *m, void *unused)
 {
+       struct super_block *sb = m->private;
        struct reiserfs_sb_info *sb_info = REISERFS_SB(sb);
        struct reiserfs_super_block *rs = sb_info->s_rs;
        unsigned int mapsize = le16_to_cpu(rs->s_v1.s_oid_cursize);
@@ -291,8 +297,9 @@ static int show_oidmap(struct seq_file *m, struct super_block *sb)
        return 0;
 }
 
-static int show_journal(struct seq_file *m, struct super_block *sb)
+static int show_journal(struct seq_file *m, void *unused)
 {
+       struct super_block *sb = m->private;
        struct reiserfs_sb_info *r = REISERFS_SB(sb);
        struct reiserfs_super_block *rs = r->s_rs;
        struct journal_params *jp = &rs->s_v1.s_journal;
@@ -383,92 +390,24 @@ static int show_journal(struct seq_file *m, struct super_block *sb)
        return 0;
 }
 
-/* iterator */
-static int test_sb(struct super_block *sb, void *data)
-{
-       return data == sb;
-}
-
-static int set_sb(struct super_block *sb, void *data)
-{
-       return -ENOENT;
-}
-
-struct reiserfs_seq_private {
-       struct super_block *sb;
-       int (*show) (struct seq_file *, struct super_block *);
-};
-
-static void *r_start(struct seq_file *m, loff_t * pos)
-{
-       struct reiserfs_seq_private *priv = m->private;
-       loff_t l = *pos;
-
-       if (l)
-               return NULL;
-
-       if (IS_ERR(sget(&reiserfs_fs_type, test_sb, set_sb, 0, priv->sb)))
-               return NULL;
-
-       up_write(&priv->sb->s_umount);
-       return priv->sb;
-}
-
-static void *r_next(struct seq_file *m, void *v, loff_t * pos)
-{
-       ++*pos;
-       if (v)
-               deactivate_super(v);
-       return NULL;
-}
-
-static void r_stop(struct seq_file *m, void *v)
-{
-       if (v)
-               deactivate_super(v);
-}
-
-static int r_show(struct seq_file *m, void *v)
-{
-       struct reiserfs_seq_private *priv = m->private;
-       return priv->show(m, v);
-}
-
-static const struct seq_operations r_ops = {
-       .start = r_start,
-       .next = r_next,
-       .stop = r_stop,
-       .show = r_show,
-};
-
 static int r_open(struct inode *inode, struct file *file)
 {
-       struct reiserfs_seq_private *priv;
-       int ret = seq_open_private(file, &r_ops,
-                                  sizeof(struct reiserfs_seq_private));
-
-       if (!ret) {
-               struct seq_file *m = file->private_data;
-               priv = m->private;
-               priv->sb = proc_get_parent_data(inode);
-               priv->show = PDE_DATA(inode);
-       }
-       return ret;
+       return single_open(file, PDE_DATA(inode),
+                               proc_get_parent_data(inode));
 }
 
 static const struct file_operations r_file_operations = {
        .open = r_open,
        .read = seq_read,
        .llseek = seq_lseek,
-       .release = seq_release_private,
-       .owner = THIS_MODULE,
+       .release = single_release,
 };
 
 static struct proc_dir_entry *proc_info_root = NULL;
 static const char proc_info_root_name[] = "fs/reiserfs";
 
 static void add_file(struct super_block *sb, char *name,
-                    int (*func) (struct seq_file *, struct super_block *))
+                    int (*func) (struct seq_file *, void *))
 {
        proc_create_data(name, 0, REISERFS_SB(sb)->procdir,
                         &r_file_operations, func);
index f8a23c3078f87d5eda59c30d55cea7ecc94b9273..e2e202a07b317cff5c84d8b51e3b66efafd689ea 100644 (file)
@@ -499,6 +499,7 @@ int remove_save_link(struct inode *inode, int truncate)
 static void reiserfs_kill_sb(struct super_block *s)
 {
        if (REISERFS_SB(s)) {
+               reiserfs_proc_info_done(s);
                /*
                 * Force any pending inode evictions to occur now. Any
                 * inodes to be removed that have extended attributes
@@ -554,8 +555,6 @@ static void reiserfs_put_super(struct super_block *s)
                                 REISERFS_SB(s)->reserved_blocks);
        }
 
-       reiserfs_proc_info_done(s);
-
        reiserfs_write_unlock(s);
        mutex_destroy(&REISERFS_SB(s)->lock);
        kfree(s->s_fs_info);
index 7465d4364208a2e751d2d3a7c8a8c1cc10d2d7c3..68307c029228c51efc0e7967c90c39edd1a85113 100644 (file)
@@ -336,19 +336,19 @@ EXPORT_SYMBOL(deactivate_super);
  *     and want to turn it into a full-blown active reference.  grab_super()
  *     is called with sb_lock held and drops it.  Returns 1 in case of
  *     success, 0 if we had failed (superblock contents was already dead or
- *     dying when grab_super() had been called).
+ *     dying when grab_super() had been called).  Note that this is only
+ *     called for superblocks not in rundown mode (== ones still on ->fs_supers
+ *     of their type), so increment of ->s_count is OK here.
  */
 static int grab_super(struct super_block *s) __releases(sb_lock)
 {
-       if (atomic_inc_not_zero(&s->s_active)) {
-               spin_unlock(&sb_lock);
-               return 1;
-       }
-       /* it's going away */
        s->s_count++;
        spin_unlock(&sb_lock);
-       /* wait for it to die */
        down_write(&s->s_umount);
+       if ((s->s_flags & MS_BORN) && atomic_inc_not_zero(&s->s_active)) {
+               put_super(s);
+               return 1;
+       }
        up_write(&s->s_umount);
        put_super(s);
        return 0;
@@ -463,11 +463,6 @@ retry:
                                destroy_super(s);
                                s = NULL;
                        }
-                       down_write(&old->s_umount);
-                       if (unlikely(!(old->s_flags & MS_BORN))) {
-                               deactivate_locked_super(old);
-                               goto retry;
-                       }
                        return old;
                }
        }
@@ -660,10 +655,10 @@ restart:
                if (hlist_unhashed(&sb->s_instances))
                        continue;
                if (sb->s_bdev == bdev) {
-                       if (grab_super(sb)) /* drops sb_lock */
-                               return sb;
-                       else
+                       if (!grab_super(sb))
                                goto restart;
+                       up_write(&sb->s_umount);
+                       return sb;
                }
        }
        spin_unlock(&sb_lock);
index f21acf0ef01f9535b7d3a576361c387593414747..879b9976c12bf9ab7cc841a1930e0c9b3df41446 100644 (file)
@@ -1412,7 +1412,7 @@ static int mount_ubifs(struct ubifs_info *c)
 
        ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"%s",
                  c->vi.ubi_num, c->vi.vol_id, c->vi.name,
-                 c->ro_mount ? ", R/O mode" : NULL);
+                 c->ro_mount ? ", R/O mode" : "");
        x = (long long)c->main_lebs * c->leb_size;
        y = (long long)c->log_lebs * c->leb_size + c->max_bud_bytes;
        ubifs_msg("LEB size: %d bytes (%d KiB), min./max. I/O unit sizes: %d bytes/%d bytes",
index c13c919ab99e9803b2ebe18d36eb93ab98bf6076..f45b2a7800c49870c278ef74d43b84636c3636fb 100644 (file)
@@ -455,7 +455,11 @@ struct acpi_pci_root {
 };
 
 /* helper */
-acpi_handle acpi_get_child(acpi_handle, u64);
+acpi_handle acpi_find_child(acpi_handle, u64, bool);
+static inline acpi_handle acpi_get_child(acpi_handle handle, u64 addr)
+{
+       return acpi_find_child(handle, addr, false);
+}
 int acpi_is_root_bridge(acpi_handle);
 struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);
 #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)ACPI_HANDLE(dev))
index 13821c339a4151912b88f2e4de04cbf99653a612..5672d7ea1fa066175b33c8f4c19457fcdc0614ed 100644 (file)
@@ -112,7 +112,7 @@ struct mmu_gather {
 
 #define HAVE_GENERIC_MMU_GATHER
 
-void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm);
+void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end);
 void tlb_flush_mmu(struct mmu_gather *tlb);
 void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start,
                                                        unsigned long end);
index 379f71508995f1bd65a740c2c558792ca9061ff0..0442c3d800f0f9c8a9268a93715cfe2bc18c639b 100644 (file)
@@ -160,11 +160,6 @@ static inline void ceph_decode_timespec(struct timespec *ts,
 static inline void ceph_encode_timespec(struct ceph_timespec *tv,
                                        const struct timespec *ts)
 {
-       BUG_ON(ts->tv_sec < 0);
-       BUG_ON(ts->tv_sec > (__kernel_time_t)U32_MAX);
-       BUG_ON(ts->tv_nsec < 0);
-       BUG_ON(ts->tv_nsec > (long)U32_MAX);
-
        tv->tv_sec = cpu_to_le32((u32)ts->tv_sec);
        tv->tv_nsec = cpu_to_le32((u32)ts->tv_nsec);
 }
index 8bda1294c035b24912a3da178ebc2c8e1cd5f827..8852d370c720373b5d92025fc39d46a5ec59e7b7 100644 (file)
@@ -646,22 +646,60 @@ static inline struct cgroup_subsys_state *cgroup_subsys_state(
        return cgrp->subsys[subsys_id];
 }
 
-/*
- * function to get the cgroup_subsys_state which allows for extra
- * rcu_dereference_check() conditions, such as locks used during the
- * cgroup_subsys::attach() methods.
+/**
+ * task_css_set_check - obtain a task's css_set with extra access conditions
+ * @task: the task to obtain css_set for
+ * @__c: extra condition expression to be passed to rcu_dereference_check()
+ *
+ * A task's css_set is RCU protected, initialized and exited while holding
+ * task_lock(), and can only be modified while holding both cgroup_mutex
+ * and task_lock() while the task is alive.  This macro verifies that the
+ * caller is inside proper critical section and returns @task's css_set.
+ *
+ * The caller can also specify additional allowed conditions via @__c, such
+ * as locks used during the cgroup_subsys::attach() methods.
  */
 #ifdef CONFIG_PROVE_RCU
 extern struct mutex cgroup_mutex;
-#define task_subsys_state_check(task, subsys_id, __c)                  \
-       rcu_dereference_check((task)->cgroups->subsys[(subsys_id)],     \
-                             lockdep_is_held(&(task)->alloc_lock) ||   \
-                             lockdep_is_held(&cgroup_mutex) || (__c))
+#define task_css_set_check(task, __c)                                  \
+       rcu_dereference_check((task)->cgroups,                          \
+               lockdep_is_held(&(task)->alloc_lock) ||                 \
+               lockdep_is_held(&cgroup_mutex) || (__c))
 #else
-#define task_subsys_state_check(task, subsys_id, __c)                  \
-       rcu_dereference((task)->cgroups->subsys[(subsys_id)])
+#define task_css_set_check(task, __c)                                  \
+       rcu_dereference((task)->cgroups)
 #endif
 
+/**
+ * task_subsys_state_check - obtain css for (task, subsys) w/ extra access conds
+ * @task: the target task
+ * @subsys_id: the target subsystem ID
+ * @__c: extra condition expression to be passed to rcu_dereference_check()
+ *
+ * Return the cgroup_subsys_state for the (@task, @subsys_id) pair.  The
+ * synchronization rules are the same as task_css_set_check().
+ */
+#define task_subsys_state_check(task, subsys_id, __c)                  \
+       task_css_set_check((task), (__c))->subsys[(subsys_id)]
+
+/**
+ * task_css_set - obtain a task's css_set
+ * @task: the task to obtain css_set for
+ *
+ * See task_css_set_check().
+ */
+static inline struct css_set *task_css_set(struct task_struct *task)
+{
+       return task_css_set_check(task, false);
+}
+
+/**
+ * task_subsys_state - obtain css for (task, subsys)
+ * @task: the target task
+ * @subsys_id: the target subsystem ID
+ *
+ * See task_subsys_state_check().
+ */
 static inline struct cgroup_subsys_state *
 task_subsys_state(struct task_struct *task, int subsys_id)
 {
index 7f0c1dd0907904a831ab0f65fdcbb0d67a068b50..ec1aee4aec9ca4b205c1d677623088d65e19f8f3 100644 (file)
@@ -669,6 +669,13 @@ asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr,
 
 int compat_restore_altstack(const compat_stack_t __user *uss);
 int __compat_save_altstack(compat_stack_t __user *, unsigned long);
+#define compat_save_altstack_ex(uss, sp) do { \
+       compat_stack_t __user *__uss = uss; \
+       struct task_struct *t = current; \
+       put_user_ex(ptr_to_compat((void __user *)t->sas_ss_sp), &__uss->ss_sp); \
+       put_user_ex(sas_ss_flags(sp), &__uss->ss_flags); \
+       put_user_ex(t->sas_ss_size, &__uss->ss_size); \
+} while (0);
 
 asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid,
                                                 struct compat_timespec __user *interval);
index 282e27028418adc27dcee1f8b7831cd36c4a80ec..a5d52eea82326010feac703f4f7f971801daf6ae 100644 (file)
@@ -41,7 +41,7 @@ cpufreq_cooling_register(const struct cpumask *clip_cpus);
  */
 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev);
 
-unsigned long cpufreq_cooling_get_level(unsigned int, unsigned int);
+unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq);
 #else /* !CONFIG_CPU_THERMAL */
 static inline struct thermal_cooling_device *
 cpufreq_cooling_register(const struct cpumask *clip_cpus)
@@ -54,7 +54,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
        return;
 }
 static inline
-unsigned long cpufreq_cooling_get_level(unsigned int, unsigned int)
+unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq)
 {
        return THERMAL_CSTATE_INVALID;
 }
index 0b763276f6199a255d304b572e0c414c90252056..5c6d7fbaf89e00dbed2d9cc418318980f7de3d2b 100644 (file)
@@ -622,7 +622,7 @@ struct edac_raw_error_desc {
  */
 struct mem_ctl_info {
        struct device                   dev;
-       struct bus_type                 bus;
+       struct bus_type                 *bus;
 
        struct list_head link;  /* for global list of mem_ctl_info structs */
 
@@ -742,4 +742,9 @@ struct mem_ctl_info {
 #endif
 };
 
+/*
+ * Maximum number of memory controllers in the coherent fabric.
+ */
+#define EDAC_MAX_MCS   16
+
 #endif
index acd0312d46fb13d0a2752ea49add626a1a9411d8..306dd8cd0b6f6136502cab1eefede59319f84ac2 100644 (file)
@@ -7,6 +7,7 @@
 #ifdef CONFIG_BLOCK
 
 struct io_cq;
+struct elevator_type;
 
 typedef int (elevator_merge_fn) (struct request_queue *, struct request **,
                                 struct bio *);
@@ -35,7 +36,8 @@ typedef void (elevator_put_req_fn) (struct request *);
 typedef void (elevator_activate_req_fn) (struct request_queue *, struct request *);
 typedef void (elevator_deactivate_req_fn) (struct request_queue *, struct request *);
 
-typedef int (elevator_init_fn) (struct request_queue *);
+typedef int (elevator_init_fn) (struct request_queue *,
+                               struct elevator_type *e);
 typedef void (elevator_exit_fn) (struct elevator_queue *);
 
 struct elevator_ops
@@ -155,6 +157,8 @@ extern int elevator_init(struct request_queue *, char *);
 extern void elevator_exit(struct elevator_queue *);
 extern int elevator_change(struct request_queue *, const char *);
 extern bool elv_rq_merge_ok(struct request *, struct bio *);
+extern struct elevator_queue *elevator_alloc(struct request_queue *,
+                                       struct elevator_type *);
 
 /*
  * Helper functions.
index 191501afd7fb040268496ea68a9e47e043bc906b..217e4b42b7c8392ebb69d1cc4109919dd67a1642 100644 (file)
@@ -434,6 +434,7 @@ struct fw_iso_context {
        int type;
        int channel;
        int speed;
+       bool drop_overflow_headers;
        size_t header_size;
        union {
                fw_iso_callback_t sc;
index 4372658c73ae5eddd3dd6570d4dfac8c5d8825c8..120d57a1c3a5dcb452a75d4fd21a6d338b128a0d 100644 (file)
@@ -78,6 +78,11 @@ struct trace_iterator {
        /* trace_seq for __print_flags() and __print_symbolic() etc. */
        struct trace_seq        tmp_seq;
 
+       cpumask_var_t           started;
+
+       /* it's true when current open file is snapshot */
+       bool                    snapshot;
+
        /* The below is zeroed out in pipe_read */
        struct trace_seq        seq;
        struct trace_entry      *ent;
@@ -90,10 +95,7 @@ struct trace_iterator {
        loff_t                  pos;
        long                    idx;
 
-       cpumask_var_t           started;
-
-       /* it's true when current open file is snapshot */
-       bool                    snapshot;
+       /* All new field here will be zeroed out in pipe_read */
 };
 
 enum trace_iter_flags {
@@ -332,7 +334,7 @@ extern int trace_define_field(struct ftrace_event_call *call, const char *type,
                              const char *name, int offset, int size,
                              int is_signed, int filter_type);
 extern int trace_add_event_call(struct ftrace_event_call *call);
-extern void trace_remove_event_call(struct ftrace_event_call *call);
+extern int trace_remove_event_call(struct ftrace_event_call *call);
 
 #define is_signed_type(type)   (((type)(-1)) < (type)1)
 
index 0c48991b0402d0d93110b8a4fa9cd42d615279c2..ff545cc33c3a75527f07cf3d867e76408994fbd7 100644 (file)
@@ -393,10 +393,12 @@ struct hid_report {
        struct hid_device *device;                      /* associated device */
 };
 
+#define HID_MAX_IDS 256
+
 struct hid_report_enum {
        unsigned numbered;
        struct list_head report_list;
-       struct hid_report *report_id_hash[256];
+       struct hid_report *report_id_hash[HID_MAX_IDS];
 };
 
 #define HID_REPORT_TYPES 3
index 981546ad231c74f0900e25b825e56ee454dece2f..89d4fbf681e742abbcc81edd3576fbcb50e48172 100644 (file)
@@ -362,6 +362,17 @@ static inline int hstate_index(struct hstate *h)
        return h - hstates;
 }
 
+pgoff_t __basepage_index(struct page *page);
+
+/* Return page->index in PAGE_SIZE units */
+static inline pgoff_t basepage_index(struct page *page)
+{
+       if (!PageCompound(page))
+               return page->index;
+
+       return __basepage_index(page);
+}
+
 #else  /* CONFIG_HUGETLB_PAGE */
 struct hstate {};
 #define alloc_huge_page_node(h, nid) NULL
@@ -382,6 +393,11 @@ static inline unsigned int pages_per_huge_page(struct hstate *h)
 }
 #define hstate_index_to_shift(index) 0
 #define hstate_index(h) 0
+
+static inline pgoff_t basepage_index(struct page *page)
+{
+       return page->index;
+}
 #endif /* CONFIG_HUGETLB_PAGE */
 
 #endif /* _LINUX_HUGETLB_H */
index 637fa71de0c7541fc5011fc764fe23c391f6debc..0b3498800ba0f6b64a8108c54a19ef34c6a0233e 100644 (file)
@@ -79,9 +79,8 @@ static inline int is_vlan_dev(struct net_device *dev)
 }
 
 #define vlan_tx_tag_present(__skb)     ((__skb)->vlan_tci & VLAN_TAG_PRESENT)
-#define vlan_tx_nonzero_tag_present(__skb) \
-       (vlan_tx_tag_present(__skb) && ((__skb)->vlan_tci & VLAN_VID_MASK))
 #define vlan_tx_tag_get(__skb)         ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT)
+#define vlan_tx_tag_get_id(__skb)      ((__skb)->vlan_tci & VLAN_VID_MASK)
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 
index 8d171f42763261cc15f7944fd3f27f22fb003c1b..3d35b7023591facc722dc58a22e9acbb44302726 100644 (file)
@@ -211,8 +211,8 @@ struct iio_chan_spec {
 static inline bool iio_channel_has_info(const struct iio_chan_spec *chan,
        enum iio_chan_info_enum type)
 {
-       return (chan->info_mask_separate & type) |
-              (chan->info_mask_shared_by_type & type);
+       return (chan->info_mask_separate & BIT(type)) |
+              (chan->info_mask_shared_by_type & BIT(type));
 }
 
 #define IIO_ST(si, rb, sb, sh)                                         \
index 850e95bc766c8504d4fbc2c592c1327ef5994431..b8b7dc755752d8cfe6337ca92062b196cd19f073 100644 (file)
@@ -101,6 +101,7 @@ struct inet6_skb_parm {
 #define IP6SKB_FORWARDED       2
 #define IP6SKB_REROUTED                4
 #define IP6SKB_ROUTERALERT     8
+#define IP6SKB_FRAGMENTED      16
 };
 
 #define IP6CB(skb)     ((struct inet6_skb_parm*)((skb)->cb))
index ace9a5f01c64fe1a8ae9d97fe45765ddc375df58..4a189ba6b1284b1ff152ce3e5a7d52e8c5815948 100644 (file)
@@ -333,6 +333,7 @@ struct mm_struct {
        void (*unmap_area) (struct mm_struct *mm, unsigned long addr);
 #endif
        unsigned long mmap_base;                /* base of mmap area */
+       unsigned long mmap_legacy_base;         /* base of mmap area in bottom-up allocations */
        unsigned long task_size;                /* size of task vm space */
        unsigned long cached_hole_size;         /* if non-zero, the largest hole below free_area_cache */
        unsigned long free_area_cache;          /* first hole of size cached_hole_size or larger */
index 4871170a04a0b24b33e2a5221577fb22565d363b..ae4981ebd18eaacacafb0cf34b040f67c2c3b729 100644 (file)
@@ -41,6 +41,7 @@ struct nbd_device {
        u64 bytesize;
        pid_t pid; /* pid of nbd-client, if attached */
        int xmit_timeout;
+       int disconnect; /* a disconnect has been requested by user */
 };
 
 #endif
index c12916248469f577795d28e96c4f86be747fbf5b..6c7bb35ad6d112d978d99cfd9e8c0d3ae9e65e0b 100644 (file)
 #define PCI_DEVICE_ID_AMD_11H_NB_MISC  0x1303
 #define PCI_DEVICE_ID_AMD_11H_NB_LINK  0x1304
 #define PCI_DEVICE_ID_AMD_15H_M10H_F3  0x1403
+#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F3 0x141d
+#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F4 0x141e
 #define PCI_DEVICE_ID_AMD_15H_NB_F0    0x1600
 #define PCI_DEVICE_ID_AMD_15H_NB_F1    0x1601
 #define PCI_DEVICE_ID_AMD_15H_NB_F2    0x1602
index f4b1001a4676b48bfb04e74d3051813c90875752..4106721c4e5e39d3d0a08d44f5d50909da6c9b86 100644 (file)
@@ -267,8 +267,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
  */
 #define list_first_or_null_rcu(ptr, type, member) \
        ({struct list_head *__ptr = (ptr); \
-         struct list_head __rcu *__next = list_next_rcu(__ptr); \
-         likely(__ptr != __next) ? container_of(__next, type, member) : NULL; \
+         struct list_head *__next = ACCESS_ONCE(__ptr->next); \
+         likely(__ptr != __next) ? \
+               list_entry_rcu(__next, type, member) : NULL; \
        })
 
 /**
index 02d84e24b7c2083ff1a4ddf13a1b2ac7ad663261..98c470ced989c1122cf5f06f370fe1d9c502407f 100644 (file)
@@ -15,6 +15,8 @@
 
 #include <linux/list.h>
 #include <linux/rbtree.h>
+#include <linux/err.h>
+#include <linux/bug.h>
 
 struct module;
 struct device;
index d897484730c0e0853c45785c5d070538252b2049..2ac423bdb6766f7aa4f50f87093374ce59ea49f7 100644 (file)
@@ -434,6 +434,14 @@ void signals_init(void);
 int restore_altstack(const stack_t __user *);
 int __save_altstack(stack_t __user *, unsigned long);
 
+#define save_altstack_ex(uss, sp) do { \
+       stack_t __user *__uss = uss; \
+       struct task_struct *t = current; \
+       put_user_ex((void __user *)t->sas_ss_sp, &__uss->ss_sp); \
+       put_user_ex(sas_ss_flags(sp), &__uss->ss_flags); \
+       put_user_ex(t->sas_ss_size, &__uss->ss_size); \
+} while (0);
+
 #ifdef CONFIG_PROC_FS
 struct seq_file;
 extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
index 84ca436b76c21986436d1a569add79ab1702a1f1..9faf0f49199f625ab74942d2ea5e0ccb40f40a29 100644 (file)
@@ -130,6 +130,7 @@ struct rpc_task_setup {
 #define RPC_TASK_SOFTCONN      0x0400          /* Fail if can't connect */
 #define RPC_TASK_SENT          0x0800          /* message was sent */
 #define RPC_TASK_TIMEOUT       0x1000          /* fail with ETIMEDOUT on timeout */
+#define RPC_TASK_NOCONNECT     0x2000          /* return ENOTCONN if not connected */
 
 #define RPC_IS_ASYNC(t)                ((t)->tk_flags & RPC_TASK_ASYNC)
 #define RPC_IS_SWAPPER(t)      ((t)->tk_flags & RPC_TASK_SWAPPER)
index 4147d700a293623b63615b987c797f14d380a7a1..84662ecc7b51468233175959ddd5c04bd0efac0d 100644 (file)
@@ -802,9 +802,14 @@ asmlinkage long sys_vfork(void);
 asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, int,
               int __user *);
 #else
+#ifdef CONFIG_CLONE_BACKWARDS3
+asmlinkage long sys_clone(unsigned long, unsigned long, int, int __user *,
+                         int __user *, int);
+#else
 asmlinkage long sys_clone(unsigned long, unsigned long, int __user *,
               int __user *, int);
 #endif
+#endif
 
 asmlinkage long sys_execve(const char __user *filename,
                const char __user *const __user *argv,
index 9180f4b85e6deedd827fa071add91940c3ac48e5..62bd8b72873c0bed1702d41a2a8982831d01564b 100644 (file)
@@ -174,10 +174,4 @@ static inline void tick_nohz_task_switch(struct task_struct *tsk) { }
 #endif
 
 
-# ifdef CONFIG_CPU_IDLE_GOV_MENU
-extern void menu_hrtimer_cancel(void);
-# else
-static inline void menu_hrtimer_cancel(void) {}
-# endif /* CONFIG_CPU_IDLE_GOV_MENU */
-
 #endif
index f5f5c7dfda90ebe2656176c058672b75854c3176..0fdff28d5015dcf551f7c935594d80975311d8da 100644 (file)
@@ -410,7 +410,7 @@ extern int usb_hcd_pci_probe(struct pci_dev *dev,
 extern void usb_hcd_pci_remove(struct pci_dev *dev);
 extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 extern const struct dev_pm_ops usb_hcd_pci_pm_ops;
 #endif
 #endif /* CONFIG_PCI */
index b6b215f13b453091ff2be0fae11b37a5a51c0c84..14105c26a83618da5d91ae09331fb83ba8f8ad6b 100644 (file)
@@ -23,6 +23,7 @@ struct user_namespace {
        struct uid_gid_map      projid_map;
        atomic_t                count;
        struct user_namespace   *parent;
+       int                     level;
        kuid_t                  owner;
        kgid_t                  group;
        unsigned int            proc_inum;
index 9ff8645b7e0be05cee6dbbcf7498690425a1f3f4..72398eea6e86e6a1b736b05fc310f021d204bdb6 100644 (file)
@@ -70,6 +70,10 @@ void virtqueue_disable_cb(struct virtqueue *vq);
 
 bool virtqueue_enable_cb(struct virtqueue *vq);
 
+unsigned virtqueue_enable_cb_prepare(struct virtqueue *vq);
+
+bool virtqueue_poll(struct virtqueue *vq, unsigned);
+
 bool virtqueue_enable_cb_delayed(struct virtqueue *vq);
 
 void *virtqueue_detach_unused_buf(struct virtqueue *vq);
index 1133695eb0671d7aeb7f9140bf2b6adc3bc7483d..c8e5760222342669081979e1ed36623dedde59ff 100644 (file)
@@ -805,6 +805,63 @@ do {                                                                       \
        __ret;                                                          \
 })
 
+#define __wait_event_interruptible_lock_irq_timeout(wq, condition,     \
+                                                   lock, ret)          \
+do {                                                                   \
+       DEFINE_WAIT(__wait);                                            \
+                                                                       \
+       for (;;) {                                                      \
+               prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);      \
+               if (condition)                                          \
+                       break;                                          \
+               if (signal_pending(current)) {                          \
+                       ret = -ERESTARTSYS;                             \
+                       break;                                          \
+               }                                                       \
+               spin_unlock_irq(&lock);                                 \
+               ret = schedule_timeout(ret);                            \
+               spin_lock_irq(&lock);                                   \
+               if (!ret)                                               \
+                       break;                                          \
+       }                                                               \
+       finish_wait(&wq, &__wait);                                      \
+} while (0)
+
+/**
+ * wait_event_interruptible_lock_irq_timeout - sleep until a condition gets true or a timeout elapses.
+ *             The condition is checked under the lock. This is expected
+ *             to be called with the lock taken.
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ * @lock: a locked spinlock_t, which will be released before schedule()
+ *       and reacquired afterwards.
+ * @timeout: timeout, in jiffies
+ *
+ * The process is put to sleep (TASK_INTERRUPTIBLE) until the
+ * @condition evaluates to true or signal is received. The @condition is
+ * checked each time the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * This is supposed to be called while holding the lock. The lock is
+ * dropped before going to sleep and is reacquired afterwards.
+ *
+ * The function returns 0 if the @timeout elapsed, -ERESTARTSYS if it
+ * was interrupted by a signal, and the remaining jiffies otherwise
+ * if the condition evaluated to true before the timeout elapsed.
+ */
+#define wait_event_interruptible_lock_irq_timeout(wq, condition, lock, \
+                                                 timeout)              \
+({                                                                     \
+       int __ret = timeout;                                            \
+                                                                       \
+       if (!(condition))                                               \
+               __wait_event_interruptible_lock_irq_timeout(            \
+                                       wq, condition, lock, __ret);    \
+       __ret;                                                          \
+})
+
 
 /*
  * These are the old interfaces to sleep waiting for an event.
index 7343a27fe81966372c3ee8dc72241f2822891543..47ada23345a195973c3942681566244d50c7f34d 100644 (file)
@@ -22,6 +22,7 @@
 #define _V4L2_CTRLS_H
 
 #include <linux/list.h>
+#include <linux/mutex.h>
 #include <linux/videodev2.h>
 
 /* forward references */
index 21f702704f2444272e1554c87112594d40acd421..01b1a1ad77d2130723dde6afeee80e4c20e50833 100644 (file)
@@ -86,6 +86,9 @@ extern int                    ipv6_dev_get_saddr(struct net *net,
                                               const struct in6_addr *daddr,
                                               unsigned int srcprefs,
                                               struct in6_addr *saddr);
+extern int                     __ipv6_get_lladdr(struct inet6_dev *idev,
+                                                 struct in6_addr *addr,
+                                                 unsigned char banned_flags);
 extern int                     ipv6_get_lladdr(struct net_device *dev,
                                                struct in6_addr *addr,
                                                unsigned char banned_flags);
index 93024a47e0e21f6926a7eed247683324d2497736..8e0b6c856a1302227812acbc10cb5e6b1f230bf7 100644 (file)
@@ -61,6 +61,7 @@ struct genl_family {
        struct list_head        ops_list;       /* private */
        struct list_head        family_list;    /* private */
        struct list_head        mcast_groups;   /* private */
+       struct module           *module;
 };
 
 /**
@@ -121,9 +122,24 @@ struct genl_ops {
        struct list_head        ops_list;
 };
 
-extern int genl_register_family(struct genl_family *family);
-extern int genl_register_family_with_ops(struct genl_family *family,
+extern int __genl_register_family(struct genl_family *family);
+
+static inline int genl_register_family(struct genl_family *family)
+{
+       family->module = THIS_MODULE;
+       return __genl_register_family(family);
+}
+
+extern int __genl_register_family_with_ops(struct genl_family *family,
        struct genl_ops *ops, size_t n_ops);
+
+static inline int genl_register_family_with_ops(struct genl_family *family,
+       struct genl_ops *ops, size_t n_ops)
+{
+       family->module = THIS_MODULE;
+       return __genl_register_family_with_ops(family, ops, n_ops);
+}
+
 extern int genl_unregister_family(struct genl_family *family);
 extern int genl_register_ops(struct genl_family *, struct genl_ops *ops);
 extern int genl_unregister_ops(struct genl_family *, struct genl_ops *ops);
index 09b1360e10bf0de6c78cbb8cdf6156b5ccdc8061..a9942e1faefb64f2effcedfd50beb23d27cff13b 100644 (file)
@@ -141,20 +141,6 @@ static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph,
        return INET_ECN_encapsulate(tos, inner);
 }
 
-static inline void tunnel_ip_select_ident(struct sk_buff *skb,
-                                         const struct iphdr  *old_iph,
-                                         struct dst_entry *dst)
-{
-       struct iphdr *iph = ip_hdr(skb);
-
-       /* Use inner packet iph-id if possible. */
-       if (skb->protocol == htons(ETH_P_IP) && old_iph->id)
-               iph->id = old_iph->id;
-       else
-               __ip_select_ident(iph, dst,
-                                 (skb_shinfo(skb)->gso_segs ?: 1) - 1);
-}
-
 static inline void iptunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        int err;
index 885898a40d13530504ad41e489b9d58a6b233366..4e50d367443148a8170dbdf73b6bc4414bba39e3 100644 (file)
@@ -1484,6 +1484,7 @@ enum ieee80211_hw_flags {
        IEEE80211_HW_SUPPORTS_RC_TABLE                  = 1<<24,
        IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF              = 1<<25,
        IEEE80211_HW_TIMING_BEACON_ONLY                 = 1<<26,
+       IEEE80211_HW_SUPPORTS_HT_CCK_RATES              = 1<<27,
 };
 
 /**
index 745bf741e029c50d8a464374ec5cc4bae855c655..5043f8b080532435ceab264c72a5060a79fc798d 100644 (file)
@@ -119,7 +119,7 @@ extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
  * if RFC 3831 IPv6-over-Fibre Channel is ever implemented it may
  * also need a pad of 2.
  */
-static int ndisc_addr_option_pad(unsigned short type)
+static inline int ndisc_addr_option_pad(unsigned short type)
 {
        switch (type) {
        case ARPHRD_INFINIBAND: return 2;
index e7f4e21cc3e17ec53ac8c5021daa74401766decb..63ed1d1dd9e79c34b232840c72e45a91a26fd631 100644 (file)
@@ -682,13 +682,19 @@ struct psched_ratecfg {
        u64     rate_bps;
        u32     mult;
        u16     overhead;
+       u8      linklayer;
        u8      shift;
 };
 
 static inline u64 psched_l2t_ns(const struct psched_ratecfg *r,
                                unsigned int len)
 {
-       return ((u64)(len + r->overhead) * r->mult) >> r->shift;
+       len += r->overhead;
+
+       if (unlikely(r->linklayer == TC_LINKLAYER_ATM))
+               return ((u64)(DIV_ROUND_UP(len,48)*53) * r->mult) >> r->shift;
+
+       return ((u64)len * r->mult) >> r->shift;
 }
 
 extern void psched_ratecfg_precompute(struct psched_ratecfg *r, const struct tc_ratespec *conf);
@@ -699,6 +705,7 @@ static inline void psched_ratecfg_getrate(struct tc_ratespec *res,
        memset(res, 0, sizeof(*res));
        res->rate = r->rate_bps >> 3;
        res->overhead = r->overhead;
+       res->linklayer = (r->linklayer & TC_LINKLAYER_MASK);
 }
 
 #endif
index 065f379c6503a489a901dfca0f26312911ada0f4..ad99eedc616890beabd23f620b340844eee76384 100644 (file)
@@ -181,6 +181,7 @@ extern int udp_get_port(struct sock *sk, unsigned short snum,
 extern void udp_err(struct sk_buff *, u32);
 extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk,
                            struct msghdr *msg, size_t len);
+extern int udp_push_pending_frames(struct sock *sk);
 extern void udp_flush_pending_frames(struct sock *sk);
 extern int udp_rcv(struct sk_buff *skb);
 extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
index 23a87d0cd72c22ed876463bc997d5190ccb635d0..c5aade52386314c82f555a7e92589ed51ae04f13 100644 (file)
@@ -34,8 +34,6 @@ extern void iscsit_put_transport(struct iscsit_transport *);
 /*
  * From iscsi_target.c
  */
-extern int iscsit_add_reject_from_cmd(u8, int, int, unsigned char *,
-                               struct iscsi_cmd *);
 extern int iscsit_setup_scsi_cmd(struct iscsi_conn *, struct iscsi_cmd *,
                                unsigned char *);
 extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *);
@@ -66,6 +64,10 @@ extern int iscsit_logout_post_handler(struct iscsi_cmd *, struct iscsi_conn *);
  * From iscsi_target_device.c
  */
 extern void iscsit_increment_maxcmdsn(struct iscsi_cmd *, struct iscsi_session *);
+/*
+ * From iscsi_target_erl0.c
+ */
+extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int);
 /*
  * From iscsi_target_erl1.c
  */
@@ -80,4 +82,5 @@ extern int iscsit_tmr_post_handler(struct iscsi_cmd *, struct iscsi_conn *);
  * From iscsi_target_util.c
  */
 extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t);
-extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *, __be32);
+extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *,
+                              unsigned char *, __be32);
index d500369534972c2dede7208ba69d7815e389f299..1db453e4b550ebc84b10ca27f32dd4fdc2ecffd7 100644 (file)
@@ -215,8 +215,8 @@ struct fw_cdev_event_request2 {
  * with the %FW_CDEV_ISO_INTERRUPT bit set, when explicitly requested with
  * %FW_CDEV_IOC_FLUSH_ISO, or when there have been so many completed packets
  * without the interrupt bit set that the kernel's internal buffer for @header
- * is about to overflow.  (In the last case, kernels with ABI version < 5 drop
- * header data up to the next interrupt packet.)
+ * is about to overflow.  (In the last case, ABI versions < 5 drop header data
+ * up to the next interrupt packet.)
  *
  * Isochronous transmit events (context type %FW_CDEV_ISO_CONTEXT_TRANSMIT):
  *
index e0133c73c30409fd29b1a9ada5ccb6a9118fb2f5..590beda78ea0ffcaa9c72321c9ba1ea893d0e4d3 100644 (file)
@@ -115,6 +115,8 @@ struct icmp6hdr {
 #define ICMPV6_NOT_NEIGHBOUR           2
 #define ICMPV6_ADDR_UNREACH            3
 #define ICMPV6_PORT_UNREACH            4
+#define ICMPV6_POLICY_FAIL             5
+#define ICMPV6_REJECT_ROUTE            6
 
 /*
  *     Codes for Time Exceeded
index 0b46fd57c8f6ff28f356598c5ffbe6a67f3496f2..e36a4aecd3117ebdaf46c17ac115e5d0a29bcede 100644 (file)
@@ -135,11 +135,11 @@ struct pppoe_tag {
 
 struct pppoe_hdr {
 #if defined(__LITTLE_ENDIAN_BITFIELD)
-       __u8 ver : 4;
        __u8 type : 4;
+       __u8 ver : 4;
 #elif defined(__BIG_ENDIAN_BITFIELD)
-       __u8 type : 4;
        __u8 ver : 4;
+       __u8 type : 4;
 #else
 #error "Please fix <asm/byteorder.h>"
 #endif
index dbd71b0c7d8c93edbc80ae50ad7223db3665f00a..09d62b9228ffa061de1b5cb8ee80e20ef470db5c 100644 (file)
@@ -73,9 +73,17 @@ struct tc_estimator {
 #define TC_H_ROOT      (0xFFFFFFFFU)
 #define TC_H_INGRESS    (0xFFFFFFF1U)
 
+/* Need to corrospond to iproute2 tc/tc_core.h "enum link_layer" */
+enum tc_link_layer {
+       TC_LINKLAYER_UNAWARE, /* Indicate unaware old iproute2 util */
+       TC_LINKLAYER_ETHERNET,
+       TC_LINKLAYER_ATM,
+};
+#define TC_LINKLAYER_MASK 0x0F /* limit use to lower 4 bits */
+
 struct tc_ratespec {
        unsigned char   cell_log;
-       unsigned char   __reserved;
+       __u8            linklayer; /* lower 4 bits */
        unsigned short  overhead;
        short           cell_align;
        unsigned short  mpu;
index d0c6d967b390a888b913812d772db2c9bf366810..f8fbe2c095ceb5eda82fbaefcda6832e35621844 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -795,7 +795,7 @@ static inline void free_copy(struct msg_msg *copy)
 
 static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode)
 {
-       struct msg_msg *msg;
+       struct msg_msg *msg, *found = NULL;
        long count = 0;
 
        list_for_each_entry(msg, &msq->q_messages, m_list) {
@@ -804,6 +804,7 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode)
                                               *msgtyp, mode)) {
                        if (mode == SEARCH_LESSEQUAL && msg->m_type != 1) {
                                *msgtyp = msg->m_type - 1;
+                               found = msg;
                        } else if (mode == SEARCH_NUMBER) {
                                if (*msgtyp == count)
                                        return msg;
@@ -813,7 +814,7 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode)
                }
        }
 
-       return ERR_PTR(-EAGAIN);
+       return found ?: ERR_PTR(-EAGAIN);
 }
 
 
index a7c9e6ddb9797a886e96bbff7c75fb8ed9670c68..2e9b387971d1760452027c052bd0a32edde90a83 100644 (file)
@@ -2769,13 +2769,17 @@ static void cgroup_cfts_commit(struct cgroup_subsys *ss,
 {
        LIST_HEAD(pending);
        struct cgroup *cgrp, *n;
+       struct super_block *sb = ss->root->sb;
 
        /* %NULL @cfts indicates abort and don't bother if @ss isn't attached */
-       if (cfts && ss->root != &rootnode) {
+       if (cfts && ss->root != &rootnode &&
+           atomic_inc_not_zero(&sb->s_active)) {
                list_for_each_entry(cgrp, &ss->root->allcg_list, allcg_node) {
                        dget(cgrp->dentry);
                        list_add_tail(&cgrp->cft_q_node, &pending);
                }
+       } else {
+               sb = NULL;
        }
 
        mutex_unlock(&cgroup_mutex);
@@ -2798,6 +2802,9 @@ static void cgroup_cfts_commit(struct cgroup_subsys *ss,
                dput(cgrp->dentry);
        }
 
+       if (sb)
+               deactivate_super(sb);
+
        mutex_unlock(&cgroup_cft_mutex);
 }
 
@@ -3726,6 +3733,23 @@ static int cgroup_write_notify_on_release(struct cgroup *cgrp,
        return 0;
 }
 
+/*
+ * When dput() is called asynchronously, if umount has been done and
+ * then deactivate_super() in cgroup_free_fn() kills the superblock,
+ * there's a small window that vfs will see the root dentry with non-zero
+ * refcnt and trigger BUG().
+ *
+ * That's why we hold a reference before dput() and drop it right after.
+ */
+static void cgroup_dput(struct cgroup *cgrp)
+{
+       struct super_block *sb = cgrp->root->sb;
+
+       atomic_inc(&sb->s_active);
+       dput(cgrp->dentry);
+       deactivate_super(sb);
+}
+
 /*
  * Unregister event and free resources.
  *
@@ -3746,7 +3770,7 @@ static void cgroup_event_remove(struct work_struct *work)
 
        eventfd_ctx_put(event->eventfd);
        kfree(event);
-       dput(cgrp->dentry);
+       cgroup_dput(cgrp);
 }
 
 /*
@@ -4031,12 +4055,8 @@ static void css_dput_fn(struct work_struct *work)
 {
        struct cgroup_subsys_state *css =
                container_of(work, struct cgroup_subsys_state, dput_work);
-       struct dentry *dentry = css->cgroup->dentry;
-       struct super_block *sb = dentry->d_sb;
 
-       atomic_inc(&sb->s_active);
-       dput(dentry);
-       deactivate_super(sb);
+       cgroup_dput(css->cgroup);
 }
 
 static void init_cgroup_css(struct cgroup_subsys_state *css,
index 64b3f791bbe595905b00e9cf8ecbee763cbacf7d..6948e9476b4242a95e86981d182e3d1928b68c11 100644 (file)
@@ -1502,11 +1502,13 @@ static int cpuset_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val)
 {
        struct cpuset *cs = cgroup_cs(cgrp);
        cpuset_filetype_t type = cft->private;
-       int retval = -ENODEV;
+       int retval = 0;
 
        mutex_lock(&cpuset_mutex);
-       if (!is_cpuset_online(cs))
+       if (!is_cpuset_online(cs)) {
+               retval = -ENODEV;
                goto out_unlock;
+       }
 
        switch (type) {
        case FILE_CPU_EXCLUSIVE:
index b391907d53520cb4a126bc8e3e0a2d5a64ade54d..e76e4959908c57fbdf49c4c68f5efa94105ea19d 100644 (file)
@@ -761,8 +761,18 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags)
 {
        struct perf_event_context *ctx;
 
-       rcu_read_lock();
 retry:
+       /*
+        * One of the few rules of preemptible RCU is that one cannot do
+        * rcu_read_unlock() while holding a scheduler (or nested) lock when
+        * part of the read side critical section was preemptible -- see
+        * rcu_read_unlock_special().
+        *
+        * Since ctx->lock nests under rq->lock we must ensure the entire read
+        * side critical section is non-preemptible.
+        */
+       preempt_disable();
+       rcu_read_lock();
        ctx = rcu_dereference(task->perf_event_ctxp[ctxn]);
        if (ctx) {
                /*
@@ -778,6 +788,8 @@ retry:
                raw_spin_lock_irqsave(&ctx->lock, *flags);
                if (ctx != rcu_dereference(task->perf_event_ctxp[ctxn])) {
                        raw_spin_unlock_irqrestore(&ctx->lock, *flags);
+                       rcu_read_unlock();
+                       preempt_enable();
                        goto retry;
                }
 
@@ -787,6 +799,7 @@ retry:
                }
        }
        rcu_read_unlock();
+       preempt_enable();
        return ctx;
 }
 
@@ -1761,7 +1774,16 @@ static int __perf_event_enable(void *info)
        struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
        int err;
 
-       if (WARN_ON_ONCE(!ctx->is_active))
+       /*
+        * There's a time window between 'ctx->is_active' check
+        * in perf_event_enable function and this place having:
+        *   - IRQs on
+        *   - ctx->lock unlocked
+        *
+        * where the task could be killed and 'ctx' deactivated
+        * by perf_event_exit_task.
+        */
+       if (!ctx->is_active)
                return -EINVAL;
 
        raw_spin_lock(&ctx->lock);
@@ -7228,7 +7250,7 @@ inherit_task_group(struct perf_event *event, struct task_struct *parent,
                 * child.
                 */
 
-               child_ctx = alloc_perf_context(event->pmu, child);
+               child_ctx = alloc_perf_context(parent_ctx->pmu, child);
                if (!child_ctx)
                        return -ENOMEM;
 
index f3569747d6295043ca3c8a853361a48c2ecf2869..ad8e1bdca70e4c702ff5c6e86255dc74a8b98259 100644 (file)
@@ -1682,12 +1682,10 @@ static bool handle_trampoline(struct pt_regs *regs)
                tmp = ri;
                ri = ri->next;
                kfree(tmp);
+               utask->depth--;
 
                if (!chained)
                        break;
-
-               utask->depth--;
-
                BUG_ON(!ri);
        }
 
index 987b28a1f01b6c6ce5d554eb22d9c89e1cde1e7b..80d92e987f21542281c26973a7d40474a78b51d0 100644 (file)
@@ -1171,10 +1171,11 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                return ERR_PTR(-EINVAL);
 
        /*
-        * If the new process will be in a different pid namespace
-        * don't allow the creation of threads.
+        * If the new process will be in a different pid namespace don't
+        * allow it to share a thread group or signal handlers with the
+        * forking task.
         */
-       if ((clone_flags & (CLONE_VM|CLONE_NEWPID)) &&
+       if ((clone_flags & (CLONE_SIGHAND | CLONE_NEWPID)) &&
            (task_active_pid_ns(current) != current->nsproxy->pid_ns))
                return ERR_PTR(-EINVAL);
 
@@ -1675,6 +1676,12 @@ SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags,
                 int __user *, parent_tidptr,
                 int __user *, child_tidptr,
                 int, tls_val)
+#elif defined(CONFIG_CLONE_BACKWARDS3)
+SYSCALL_DEFINE6(clone, unsigned long, clone_flags, unsigned long, newsp,
+               int, stack_size,
+               int __user *, parent_tidptr,
+               int __user *, child_tidptr,
+               int, tls_val)
 #else
 SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
                 int __user *, parent_tidptr,
index b26dcfc02c9489b3ca00bfd076f2208bb4964366..49dacfb4574563b61551a436a21a2fc33053e47f 100644 (file)
@@ -61,6 +61,7 @@
 #include <linux/nsproxy.h>
 #include <linux/ptrace.h>
 #include <linux/sched/rt.h>
+#include <linux/hugetlb.h>
 
 #include <asm/futex.h>
 
@@ -365,7 +366,7 @@ again:
        } else {
                key->both.offset |= FUT_OFF_INODE; /* inode-based key */
                key->shared.inode = page_head->mapping->host;
-               key->shared.pgoff = page_head->index;
+               key->shared.pgoff = basepage_index(page);
        }
 
        get_futex_key_refs(key);
index fd4b13b131f8db23fb17055caf5d33e23bec7b50..2288fbdada160f3c144d3c5bb9e008e6c142faf3 100644 (file)
@@ -721,17 +721,20 @@ static int hrtimer_switch_to_hres(void)
        return 1;
 }
 
+static void clock_was_set_work(struct work_struct *work)
+{
+       clock_was_set();
+}
+
+static DECLARE_WORK(hrtimer_work, clock_was_set_work);
+
 /*
- * Called from timekeeping code to reprogramm the hrtimer interrupt
- * device. If called from the timer interrupt context we defer it to
- * softirq context.
+ * Called from timekeeping and resume code to reprogramm the hrtimer
+ * interrupt device on all cpus.
  */
 void clock_was_set_delayed(void)
 {
-       struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
-
-       cpu_base->clock_was_set = 1;
-       __raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+       schedule_work(&hrtimer_work);
 }
 
 #else
@@ -780,8 +783,10 @@ void hrtimers_resume(void)
        WARN_ONCE(!irqs_disabled(),
                  KERN_INFO "hrtimers_resume() called with IRQs enabled!");
 
+       /* Retrigger on the local CPU */
        retrigger_next_event(NULL);
-       timerfd_clock_was_set();
+       /* And schedule a retrigger for all others */
+       clock_was_set_delayed();
 }
 
 static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer)
@@ -1432,13 +1437,6 @@ void hrtimer_peek_ahead_timers(void)
 
 static void run_hrtimer_softirq(struct softirq_action *h)
 {
-       struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
-
-       if (cpu_base->clock_was_set) {
-               cpu_base->clock_was_set = 0;
-               clock_was_set();
-       }
-
        hrtimer_peek_ahead_timers();
 }
 
index fa17855ca65a235bd5c1f9a7daa042b57722b924..dc4db3228dcdefe7e1d9aca246fe4c3e93952fdc 100644 (file)
@@ -555,9 +555,9 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)
                return 0;
 
        if (irq_settings_can_request(desc)) {
-               if (desc->action)
-                       if (irqflags & desc->action->flags & IRQF_SHARED)
-                               canrequest =1;
+               if (!desc->action ||
+                   irqflags & desc->action->flags & IRQF_SHARED)
+                       canrequest = 1;
        }
        irq_put_desc_unlock(desc, flags);
        return canrequest;
index cab4bce49c23dbe3779d02db8259dda28b7b4258..fa53db8aadeb2dea6320d1987f0f775e35e480a4 100644 (file)
@@ -2927,7 +2927,6 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
 {
        /* Module within temporary copy. */
        struct module *mod;
-       Elf_Shdr *pcpusec;
        int err;
 
        mod = setup_load_info(info, flags);
@@ -2942,17 +2941,10 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
        err = module_frob_arch_sections(info->hdr, info->sechdrs,
                                        info->secstrings, mod);
        if (err < 0)
-               goto out;
+               return ERR_PTR(err);
 
-       pcpusec = &info->sechdrs[info->index.pcpu];
-       if (pcpusec->sh_size) {
-               /* We have a special allocation for this section. */
-               err = percpu_modalloc(mod,
-                                     pcpusec->sh_size, pcpusec->sh_addralign);
-               if (err)
-                       goto out;
-               pcpusec->sh_flags &= ~(unsigned long)SHF_ALLOC;
-       }
+       /* We will do a special allocation for per-cpu sections later. */
+       info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC;
 
        /* Determine total sizes, and put offsets in sh_entsize.  For now
           this is done generically; there doesn't appear to be any
@@ -2963,17 +2955,22 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
        /* Allocate and move to the final place */
        err = move_module(mod, info);
        if (err)
-               goto free_percpu;
+               return ERR_PTR(err);
 
        /* Module has been copied to its final place now: return it. */
        mod = (void *)info->sechdrs[info->index.mod].sh_addr;
        kmemleak_load_module(mod, info);
        return mod;
+}
 
-free_percpu:
-       percpu_modfree(mod);
-out:
-       return ERR_PTR(err);
+static int alloc_module_percpu(struct module *mod, struct load_info *info)
+{
+       Elf_Shdr *pcpusec = &info->sechdrs[info->index.pcpu];
+       if (!pcpusec->sh_size)
+               return 0;
+
+       /* We have a special allocation for this section. */
+       return percpu_modalloc(mod, pcpusec->sh_size, pcpusec->sh_addralign);
 }
 
 /* mod is no longer valid after this! */
@@ -3237,6 +3234,11 @@ static int load_module(struct load_info *info, const char __user *uargs,
        }
 #endif
 
+       /* To avoid stressing percpu allocator, do this once we're unique. */
+       err = alloc_module_percpu(mod, info);
+       if (err)
+               goto unlink_mod;
+
        /* Now module is in final location, initialize linked lists, etc. */
        err = module_unload_init(mod);
        if (err)
index 0db3e791a06d48594606bc4789bc8fbe0fd5a4f0..0eb6d8e8b1da7ffd3d5a750698395d0889190b73 100644 (file)
@@ -264,6 +264,7 @@ void free_pid(struct pid *pid)
                struct pid_namespace *ns = upid->ns;
                hlist_del_rcu(&upid->pid_chain);
                switch(--ns->nr_hashed) {
+               case 2:
                case 1:
                        /* When all that is left in the pid namespace
                         * is the reaper wake up the reaper.  The reaper
index c6422ffeda9a9c304a750b9321d555278b6a39d3..9012ecf7b814f9b476abff1ddd40ea508a12f9e1 100644 (file)
@@ -32,7 +32,8 @@ static void try_to_suspend(struct work_struct *work)
 
        mutex_lock(&autosleep_lock);
 
-       if (!pm_save_wakeup_count(initial_count)) {
+       if (!pm_save_wakeup_count(initial_count) ||
+               system_state != SYSTEM_RUNNING) {
                mutex_unlock(&autosleep_lock);
                goto out;
        }
index 587dddeebf15610da6f93c35874381ea5156365a..25cf89bc659e0d58b9a1b6819698076ea2362d04 100644 (file)
@@ -293,6 +293,15 @@ int pm_qos_request_active(struct pm_qos_request *req)
 }
 EXPORT_SYMBOL_GPL(pm_qos_request_active);
 
+static void __pm_qos_update_request(struct pm_qos_request *req,
+                          s32 new_value)
+{
+       if (new_value != req->node.prio)
+               pm_qos_update_target(
+                       pm_qos_array[req->pm_qos_class]->constraints,
+                       &req->node, PM_QOS_UPDATE_REQ, new_value);
+}
+
 /**
  * pm_qos_work_fn - the timeout handler of pm_qos_update_request_timeout
  * @work: work struct for the delayed work (timeout)
@@ -305,7 +314,7 @@ static void pm_qos_work_fn(struct work_struct *work)
                                                  struct pm_qos_request,
                                                  work);
 
-       pm_qos_update_request(req, PM_QOS_DEFAULT_VALUE);
+       __pm_qos_update_request(req, PM_QOS_DEFAULT_VALUE);
 }
 
 /**
@@ -365,6 +374,8 @@ void pm_qos_update_request(struct pm_qos_request *req,
                pm_qos_update_target(
                        pm_qos_array[req->pm_qos_class]->constraints,
                        &req->node, PM_QOS_UPDATE_REQ, new_value);
+
+       __pm_qos_update_request(req, new_value);
 }
 EXPORT_SYMBOL_GPL(pm_qos_update_request);
 
index 8212c1aef125f2d4290cbe0e55564d7e9a5a57de..d37d45c90ae6fc863a257f75751976a4bfe2f9ef 100644 (file)
@@ -1369,9 +1369,9 @@ static int console_trylock_for_printk(unsigned int cpu)
                }
        }
        logbuf_cpu = UINT_MAX;
+       raw_spin_unlock(&logbuf_lock);
        if (wake)
                up(&console_sem);
-       raw_spin_unlock(&logbuf_lock);
        return retval;
 }
 
index c61a614465c8ebf13b5f71aabf23a78c9e8533a6..03b73bea33d667b8575606ce022cced5b18be7f5 100644 (file)
@@ -1984,6 +1984,7 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued)
         */
        update_entity_load_avg(curr, 1);
        update_cfs_rq_blocked_load(cfs_rq, 1);
+       update_cfs_shares(cfs_rq);
 
 #ifdef CONFIG_SCHED_HRTICK
        /*
index 20d6fba70652094324c13ef6f8e2fcf9bba26a50..297b90b5277eec05e106a7d6d98c761e8c62e895 100644 (file)
@@ -29,6 +29,7 @@
 
 static struct tick_device tick_broadcast_device;
 static cpumask_var_t tick_broadcast_mask;
+static cpumask_var_t tick_broadcast_on;
 static cpumask_var_t tmpmask;
 static DEFINE_RAW_SPINLOCK(tick_broadcast_lock);
 static int tick_broadcast_force;
@@ -123,8 +124,9 @@ static void tick_device_setup_broadcast_func(struct clock_event_device *dev)
  */
 int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
 {
+       struct clock_event_device *bc = tick_broadcast_device.evtdev;
        unsigned long flags;
-       int ret = 0;
+       int ret;
 
        raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
 
@@ -138,20 +140,59 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
                dev->event_handler = tick_handle_periodic;
                tick_device_setup_broadcast_func(dev);
                cpumask_set_cpu(cpu, tick_broadcast_mask);
-               tick_broadcast_start_periodic(tick_broadcast_device.evtdev);
+               tick_broadcast_start_periodic(bc);
                ret = 1;
        } else {
                /*
-                * When the new device is not affected by the stop
-                * feature and the cpu is marked in the broadcast mask
-                * then clear the broadcast bit.
+                * Clear the broadcast bit for this cpu if the
+                * device is not power state affected.
                 */
-               if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) {
-                       int cpu = smp_processor_id();
+               if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
                        cpumask_clear_cpu(cpu, tick_broadcast_mask);
-                       tick_broadcast_clear_oneshot(cpu);
-               } else {
+               else
                        tick_device_setup_broadcast_func(dev);
+
+               /*
+                * Clear the broadcast bit if the CPU is not in
+                * periodic broadcast on state.
+                */
+               if (!cpumask_test_cpu(cpu, tick_broadcast_on))
+                       cpumask_clear_cpu(cpu, tick_broadcast_mask);
+
+               switch (tick_broadcast_device.mode) {
+               case TICKDEV_MODE_ONESHOT:
+                       /*
+                        * If the system is in oneshot mode we can
+                        * unconditionally clear the oneshot mask bit,
+                        * because the CPU is running and therefore
+                        * not in an idle state which causes the power
+                        * state affected device to stop. Let the
+                        * caller initialize the device.
+                        */
+                       tick_broadcast_clear_oneshot(cpu);
+                       ret = 0;
+                       break;
+
+               case TICKDEV_MODE_PERIODIC:
+                       /*
+                        * If the system is in periodic mode, check
+                        * whether the broadcast device can be
+                        * switched off now.
+                        */
+                       if (cpumask_empty(tick_broadcast_mask) && bc)
+                               clockevents_shutdown(bc);
+                       /*
+                        * If we kept the cpu in the broadcast mask,
+                        * tell the caller to leave the per cpu device
+                        * in shutdown state. The periodic interrupt
+                        * is delivered by the broadcast device.
+                        */
+                       ret = cpumask_test_cpu(cpu, tick_broadcast_mask);
+                       break;
+               default:
+                       /* Nothing to do */
+                       ret = 0;
+                       break;
                }
        }
        raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
@@ -281,6 +322,7 @@ static void tick_do_broadcast_on_off(unsigned long *reason)
        switch (*reason) {
        case CLOCK_EVT_NOTIFY_BROADCAST_ON:
        case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
+               cpumask_set_cpu(cpu, tick_broadcast_on);
                if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_mask)) {
                        if (tick_broadcast_device.mode ==
                            TICKDEV_MODE_PERIODIC)
@@ -290,8 +332,12 @@ static void tick_do_broadcast_on_off(unsigned long *reason)
                        tick_broadcast_force = 1;
                break;
        case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
-               if (!tick_broadcast_force &&
-                   cpumask_test_and_clear_cpu(cpu, tick_broadcast_mask)) {
+               if (tick_broadcast_force)
+                       break;
+               cpumask_clear_cpu(cpu, tick_broadcast_on);
+               if (!tick_device_is_functional(dev))
+                       break;
+               if (cpumask_test_and_clear_cpu(cpu, tick_broadcast_mask)) {
                        if (tick_broadcast_device.mode ==
                            TICKDEV_MODE_PERIODIC)
                                tick_setup_periodic(dev, 0);
@@ -349,6 +395,7 @@ void tick_shutdown_broadcast(unsigned int *cpup)
 
        bc = tick_broadcast_device.evtdev;
        cpumask_clear_cpu(cpu, tick_broadcast_mask);
+       cpumask_clear_cpu(cpu, tick_broadcast_on);
 
        if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) {
                if (bc && cpumask_empty(tick_broadcast_mask))
@@ -475,7 +522,15 @@ void tick_check_oneshot_broadcast(int cpu)
        if (cpumask_test_cpu(cpu, tick_broadcast_oneshot_mask)) {
                struct tick_device *td = &per_cpu(tick_cpu_device, cpu);
 
-               clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_ONESHOT);
+               /*
+                * We might be in the middle of switching over from
+                * periodic to oneshot. If the CPU has not yet
+                * switched over, leave the device alone.
+                */
+               if (td->mode == TICKDEV_MODE_ONESHOT) {
+                       clockevents_set_mode(td->evtdev,
+                                            CLOCK_EVT_MODE_ONESHOT);
+               }
        }
 }
 
@@ -792,6 +847,7 @@ bool tick_broadcast_oneshot_available(void)
 void __init tick_broadcast_init(void)
 {
        zalloc_cpumask_var(&tick_broadcast_mask, GFP_NOWAIT);
+       zalloc_cpumask_var(&tick_broadcast_on, GFP_NOWAIT);
        zalloc_cpumask_var(&tmpmask, GFP_NOWAIT);
 #ifdef CONFIG_TICK_ONESHOT
        zalloc_cpumask_var(&tick_broadcast_oneshot_mask, GFP_NOWAIT);
index 5d3fb100bc065285a9673e9f2cbe786ad734505d..7ce5e5a4a4c5b0199efb2255d892acbcdc9cfac0 100644 (file)
@@ -194,7 +194,8 @@ static void tick_setup_device(struct tick_device *td,
         * When global broadcasting is active, check if the current
         * device is registered as a placeholder for broadcast mode.
         * This allows us to handle this x86 misfeature in a generic
-        * way.
+        * way. This function also returns !=0 when we keep the
+        * current active broadcast state for this CPU.
         */
        if (tick_device_uses_broadcast(newdev, cpu))
                return;
index 0cf1c14531817eacb61eae48f6f76a45a0cc8027..4251374578bc96a762d336cfb8ecc08cde699dd1 100644 (file)
@@ -832,13 +832,10 @@ void tick_nohz_irq_exit(void)
 {
        struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
 
-       if (ts->inidle) {
-               /* Cancel the timer because CPU already waken up from the C-states*/
-               menu_hrtimer_cancel();
+       if (ts->inidle)
                __tick_nohz_idle_enter(ts);
-       } else {
+       else
                tick_nohz_full_stop_tick(ts);
-       }
 }
 
 /**
@@ -936,8 +933,6 @@ void tick_nohz_idle_exit(void)
 
        ts->inidle = 0;
 
-       /* Cancel the timer because CPU already waken up from the C-states*/
-       menu_hrtimer_cancel();
        if (ts->idle_active || ts->tick_stopped)
                now = ktime_get();
 
index 3bdf28323012639c9cc60b43f3add4ff257cbe91..61ed862cdd376222dedfa317301f3d6c3dbd3404 100644 (file)
@@ -265,10 +265,9 @@ static inline void timer_list_header(struct seq_file *m, u64 now)
 static int timer_list_show(struct seq_file *m, void *v)
 {
        struct timer_list_iter *iter = v;
-       u64 now = ktime_to_ns(ktime_get());
 
        if (iter->cpu == -1 && !iter->second_pass)
-               timer_list_header(m, now);
+               timer_list_header(m, iter->now);
        else if (!iter->second_pass)
                print_cpu(m, iter->cpu, iter->now);
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
@@ -298,33 +297,41 @@ void sysrq_timer_list_show(void)
        return;
 }
 
-static void *timer_list_start(struct seq_file *file, loff_t *offset)
+static void *move_iter(struct timer_list_iter *iter, loff_t offset)
 {
-       struct timer_list_iter *iter = file->private;
-
-       if (!*offset) {
-               iter->cpu = -1;
-               iter->now = ktime_to_ns(ktime_get());
-       } else if (iter->cpu >= nr_cpu_ids) {
+       for (; offset; offset--) {
+               iter->cpu = cpumask_next(iter->cpu, cpu_online_mask);
+               if (iter->cpu >= nr_cpu_ids) {
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
-               if (!iter->second_pass) {
-                       iter->cpu = -1;
-                       iter->second_pass = true;
-               } else
-                       return NULL;
+                       if (!iter->second_pass) {
+                               iter->cpu = -1;
+                               iter->second_pass = true;
+                       } else
+                               return NULL;
 #else
-               return NULL;
+                       return NULL;
 #endif
+               }
        }
        return iter;
 }
 
+static void *timer_list_start(struct seq_file *file, loff_t *offset)
+{
+       struct timer_list_iter *iter = file->private;
+
+       if (!*offset)
+               iter->now = ktime_to_ns(ktime_get());
+       iter->cpu = -1;
+       iter->second_pass = false;
+       return move_iter(iter, *offset);
+}
+
 static void *timer_list_next(struct seq_file *file, void *v, loff_t *offset)
 {
        struct timer_list_iter *iter = file->private;
-       iter->cpu = cpumask_next(iter->cpu, cpu_online_mask);
        ++*offset;
-       return timer_list_start(file, offset);
+       return move_iter(iter, 1);
 }
 
 static void timer_list_stop(struct seq_file *seq, void *v)
index 15ffdb3f1948b9468c2c04527beb8190b0d79d45..15bc1b41021dae203b7d3c43293b5edd54cff4cb 100644 (file)
@@ -149,9 +149,11 @@ static unsigned long round_jiffies_common(unsigned long j, int cpu,
        /* now that we have rounded, subtract the extra skew again */
        j -= cpu * 3;
 
-       if (j <= jiffies) /* rounding ate our timeout entirely; */
-               return original;
-       return j;
+       /*
+        * Make sure j is still in the future. Otherwise return the
+        * unmodified value.
+        */
+       return time_is_after_jiffies(j) ? j : original;
 }
 
 /**
index 6c508ff33c6206df8e028e1eab43e913565f927e..f23449d0650e1acdddb7a957a894b6d2416f9530 100644 (file)
@@ -1416,12 +1416,22 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable,
  * the hashes are freed with call_rcu_sched().
  */
 static int
-ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
+ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs)
 {
        struct ftrace_hash *filter_hash;
        struct ftrace_hash *notrace_hash;
        int ret;
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+       /*
+        * There's a small race when adding ops that the ftrace handler
+        * that wants regs, may be called without them. We can not
+        * allow that handler to be called if regs is NULL.
+        */
+       if (regs == NULL && (ops->flags & FTRACE_OPS_FL_SAVE_REGS))
+               return 0;
+#endif
+
        filter_hash = rcu_dereference_raw_notrace(ops->filter_hash);
        notrace_hash = rcu_dereference_raw_notrace(ops->notrace_hash);
 
@@ -2134,12 +2144,57 @@ static cycle_t          ftrace_update_time;
 static unsigned long   ftrace_update_cnt;
 unsigned long          ftrace_update_tot_cnt;
 
-static int ops_traces_mod(struct ftrace_ops *ops)
+static inline int ops_traces_mod(struct ftrace_ops *ops)
 {
-       struct ftrace_hash *hash;
+       /*
+        * Filter_hash being empty will default to trace module.
+        * But notrace hash requires a test of individual module functions.
+        */
+       return ftrace_hash_empty(ops->filter_hash) &&
+               ftrace_hash_empty(ops->notrace_hash);
+}
+
+/*
+ * Check if the current ops references the record.
+ *
+ * If the ops traces all functions, then it was already accounted for.
+ * If the ops does not trace the current record function, skip it.
+ * If the ops ignores the function via notrace filter, skip it.
+ */
+static inline bool
+ops_references_rec(struct ftrace_ops *ops, struct dyn_ftrace *rec)
+{
+       /* If ops isn't enabled, ignore it */
+       if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
+               return 0;
+
+       /* If ops traces all mods, we already accounted for it */
+       if (ops_traces_mod(ops))
+               return 0;
 
-       hash = ops->filter_hash;
-       return ftrace_hash_empty(hash);
+       /* The function must be in the filter */
+       if (!ftrace_hash_empty(ops->filter_hash) &&
+           !ftrace_lookup_ip(ops->filter_hash, rec->ip))
+               return 0;
+
+       /* If in notrace hash, we ignore it too */
+       if (ftrace_lookup_ip(ops->notrace_hash, rec->ip))
+               return 0;
+
+       return 1;
+}
+
+static int referenced_filters(struct dyn_ftrace *rec)
+{
+       struct ftrace_ops *ops;
+       int cnt = 0;
+
+       for (ops = ftrace_ops_list; ops != &ftrace_list_end; ops = ops->next) {
+               if (ops_references_rec(ops, rec))
+                   cnt++;
+       }
+
+       return cnt;
 }
 
 static int ftrace_update_code(struct module *mod)
@@ -2148,6 +2203,7 @@ static int ftrace_update_code(struct module *mod)
        struct dyn_ftrace *p;
        cycle_t start, stop;
        unsigned long ref = 0;
+       bool test = false;
        int i;
 
        /*
@@ -2161,9 +2217,12 @@ static int ftrace_update_code(struct module *mod)
 
                for (ops = ftrace_ops_list;
                     ops != &ftrace_list_end; ops = ops->next) {
-                       if (ops->flags & FTRACE_OPS_FL_ENABLED &&
-                           ops_traces_mod(ops))
-                               ref++;
+                       if (ops->flags & FTRACE_OPS_FL_ENABLED) {
+                               if (ops_traces_mod(ops))
+                                       ref++;
+                               else
+                                       test = true;
+                       }
                }
        }
 
@@ -2173,12 +2232,16 @@ static int ftrace_update_code(struct module *mod)
        for (pg = ftrace_new_pgs; pg; pg = pg->next) {
 
                for (i = 0; i < pg->index; i++) {
+                       int cnt = ref;
+
                        /* If something went wrong, bail without enabling anything */
                        if (unlikely(ftrace_disabled))
                                return -1;
 
                        p = &pg->records[i];
-                       p->flags = ref;
+                       if (test)
+                               cnt += referenced_filters(p);
+                       p->flags = cnt;
 
                        /*
                         * Do the initial record conversion from mcount jump
@@ -2198,7 +2261,7 @@ static int ftrace_update_code(struct module *mod)
                         * conversion puts the module to the correct state, thus
                         * passing the ftrace_make_call check.
                         */
-                       if (ftrace_start_up && ref) {
+                       if (ftrace_start_up && cnt) {
                                int failed = __ftrace_replace_code(p, 1);
                                if (failed)
                                        ftrace_bug(failed, p->ip);
@@ -4188,7 +4251,7 @@ static inline void ftrace_startup_enable(int command) { }
 # define ftrace_shutdown_sysctl()      do { } while (0)
 
 static inline int
-ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
+ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs)
 {
        return 1;
 }
@@ -4211,7 +4274,7 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,
        do_for_each_ftrace_op(op, ftrace_control_list) {
                if (!(op->flags & FTRACE_OPS_FL_STUB) &&
                    !ftrace_function_local_disabled(op) &&
-                   ftrace_ops_test(op, ip))
+                   ftrace_ops_test(op, ip, regs))
                        op->func(ip, parent_ip, op, regs);
        } while_for_each_ftrace_op(op);
        trace_recursion_clear(TRACE_CONTROL_BIT);
@@ -4244,7 +4307,7 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
         */
        preempt_disable_notrace();
        do_for_each_ftrace_op(op, ftrace_ops_list) {
-               if (ftrace_ops_test(op, ip))
+               if (ftrace_ops_test(op, ip, regs))
                        op->func(ip, parent_ip, op, regs);
        } while_for_each_ftrace_op(op);
        preempt_enable_notrace();
index e71a8be4a6ee9decd1429eb13159885f8c567469..0582a01a81e36c98ecfc2574b804075ea26c1273 100644 (file)
@@ -193,6 +193,37 @@ static struct trace_array  global_trace;
 
 LIST_HEAD(ftrace_trace_arrays);
 
+int trace_array_get(struct trace_array *this_tr)
+{
+       struct trace_array *tr;
+       int ret = -ENODEV;
+
+       mutex_lock(&trace_types_lock);
+       list_for_each_entry(tr, &ftrace_trace_arrays, list) {
+               if (tr == this_tr) {
+                       tr->ref++;
+                       ret = 0;
+                       break;
+               }
+       }
+       mutex_unlock(&trace_types_lock);
+
+       return ret;
+}
+
+static void __trace_array_put(struct trace_array *this_tr)
+{
+       WARN_ON(!this_tr->ref);
+       this_tr->ref--;
+}
+
+void trace_array_put(struct trace_array *this_tr)
+{
+       mutex_lock(&trace_types_lock);
+       __trace_array_put(this_tr);
+       mutex_unlock(&trace_types_lock);
+}
+
 int filter_current_check_discard(struct ring_buffer *buffer,
                                 struct ftrace_event_call *call, void *rec,
                                 struct ring_buffer_event *event)
@@ -201,23 +232,43 @@ int filter_current_check_discard(struct ring_buffer *buffer,
 }
 EXPORT_SYMBOL_GPL(filter_current_check_discard);
 
-cycle_t ftrace_now(int cpu)
+cycle_t buffer_ftrace_now(struct trace_buffer *buf, int cpu)
 {
        u64 ts;
 
        /* Early boot up does not have a buffer yet */
-       if (!global_trace.trace_buffer.buffer)
+       if (!buf->buffer)
                return trace_clock_local();
 
-       ts = ring_buffer_time_stamp(global_trace.trace_buffer.buffer, cpu);
-       ring_buffer_normalize_time_stamp(global_trace.trace_buffer.buffer, cpu, &ts);
+       ts = ring_buffer_time_stamp(buf->buffer, cpu);
+       ring_buffer_normalize_time_stamp(buf->buffer, cpu, &ts);
 
        return ts;
 }
 
+cycle_t ftrace_now(int cpu)
+{
+       return buffer_ftrace_now(&global_trace.trace_buffer, cpu);
+}
+
+/**
+ * tracing_is_enabled - Show if global_trace has been disabled
+ *
+ * Shows if the global trace has been enabled or not. It uses the
+ * mirror flag "buffer_disabled" to be used in fast paths such as for
+ * the irqsoff tracer. But it may be inaccurate due to races. If you
+ * need to know the accurate state, use tracing_is_on() which is a little
+ * slower, but accurate.
+ */
 int tracing_is_enabled(void)
 {
-       return tracing_is_on();
+       /*
+        * For quick access (irqsoff uses this in fast path), just
+        * return the mirror variable of the state of the ring buffer.
+        * It's a little racy, but we don't really care.
+        */
+       smp_rmb();
+       return !global_trace.buffer_disabled;
 }
 
 /*
@@ -240,7 +291,7 @@ static struct tracer                *trace_types __read_mostly;
 /*
  * trace_types_lock is used to protect the trace_types list.
  */
-static DEFINE_MUTEX(trace_types_lock);
+DEFINE_MUTEX(trace_types_lock);
 
 /*
  * serialize the access of the ring buffer
@@ -330,6 +381,23 @@ unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK |
        TRACE_ITER_GRAPH_TIME | TRACE_ITER_RECORD_CMD | TRACE_ITER_OVERWRITE |
        TRACE_ITER_IRQ_INFO | TRACE_ITER_MARKERS | TRACE_ITER_FUNCTION;
 
+void tracer_tracing_on(struct trace_array *tr)
+{
+       if (tr->trace_buffer.buffer)
+               ring_buffer_record_on(tr->trace_buffer.buffer);
+       /*
+        * This flag is looked at when buffers haven't been allocated
+        * yet, or by some tracers (like irqsoff), that just want to
+        * know if the ring buffer has been disabled, but it can handle
+        * races of where it gets disabled but we still do a record.
+        * As the check is in the fast path of the tracers, it is more
+        * important to be fast than accurate.
+        */
+       tr->buffer_disabled = 0;
+       /* Make the flag seen by readers */
+       smp_wmb();
+}
+
 /**
  * tracing_on - enable tracing buffers
  *
@@ -338,15 +406,7 @@ unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK |
  */
 void tracing_on(void)
 {
-       if (global_trace.trace_buffer.buffer)
-               ring_buffer_record_on(global_trace.trace_buffer.buffer);
-       /*
-        * This flag is only looked at when buffers haven't been
-        * allocated yet. We don't really care about the race
-        * between setting this flag and actually turning
-        * on the buffer.
-        */
-       global_trace.buffer_disabled = 0;
+       tracer_tracing_on(&global_trace);
 }
 EXPORT_SYMBOL_GPL(tracing_on);
 
@@ -540,6 +600,23 @@ void tracing_snapshot_alloc(void)
 EXPORT_SYMBOL_GPL(tracing_snapshot_alloc);
 #endif /* CONFIG_TRACER_SNAPSHOT */
 
+void tracer_tracing_off(struct trace_array *tr)
+{
+       if (tr->trace_buffer.buffer)
+               ring_buffer_record_off(tr->trace_buffer.buffer);
+       /*
+        * This flag is looked at when buffers haven't been allocated
+        * yet, or by some tracers (like irqsoff), that just want to
+        * know if the ring buffer has been disabled, but it can handle
+        * races of where it gets disabled but we still do a record.
+        * As the check is in the fast path of the tracers, it is more
+        * important to be fast than accurate.
+        */
+       tr->buffer_disabled = 1;
+       /* Make the flag seen by readers */
+       smp_wmb();
+}
+
 /**
  * tracing_off - turn off tracing buffers
  *
@@ -550,26 +627,29 @@ EXPORT_SYMBOL_GPL(tracing_snapshot_alloc);
  */
 void tracing_off(void)
 {
-       if (global_trace.trace_buffer.buffer)
-               ring_buffer_record_off(global_trace.trace_buffer.buffer);
-       /*
-        * This flag is only looked at when buffers haven't been
-        * allocated yet. We don't really care about the race
-        * between setting this flag and actually turning
-        * on the buffer.
-        */
-       global_trace.buffer_disabled = 1;
+       tracer_tracing_off(&global_trace);
 }
 EXPORT_SYMBOL_GPL(tracing_off);
 
+/**
+ * tracer_tracing_is_on - show real state of ring buffer enabled
+ * @tr : the trace array to know if ring buffer is enabled
+ *
+ * Shows real state of the ring buffer if it is enabled or not.
+ */
+int tracer_tracing_is_on(struct trace_array *tr)
+{
+       if (tr->trace_buffer.buffer)
+               return ring_buffer_record_is_on(tr->trace_buffer.buffer);
+       return !tr->buffer_disabled;
+}
+
 /**
  * tracing_is_on - show state of ring buffers enabled
  */
 int tracing_is_on(void)
 {
-       if (global_trace.trace_buffer.buffer)
-               return ring_buffer_record_is_on(global_trace.trace_buffer.buffer);
-       return !global_trace.buffer_disabled;
+       return tracer_tracing_is_on(&global_trace);
 }
 EXPORT_SYMBOL_GPL(tracing_is_on);
 
@@ -1119,7 +1199,7 @@ void tracing_reset_online_cpus(struct trace_buffer *buf)
        /* Make sure all commits have finished */
        synchronize_sched();
 
-       buf->time_start = ftrace_now(buf->cpu);
+       buf->time_start = buffer_ftrace_now(buf, buf->cpu);
 
        for_each_online_cpu(cpu)
                ring_buffer_reset_cpu(buffer, cpu);
@@ -1127,23 +1207,17 @@ void tracing_reset_online_cpus(struct trace_buffer *buf)
        ring_buffer_record_enable(buffer);
 }
 
-void tracing_reset_current(int cpu)
-{
-       tracing_reset(&global_trace.trace_buffer, cpu);
-}
-
+/* Must have trace_types_lock held */
 void tracing_reset_all_online_cpus(void)
 {
        struct trace_array *tr;
 
-       mutex_lock(&trace_types_lock);
        list_for_each_entry(tr, &ftrace_trace_arrays, list) {
                tracing_reset_online_cpus(&tr->trace_buffer);
 #ifdef CONFIG_TRACER_MAX_TRACE
                tracing_reset_online_cpus(&tr->max_buffer);
 #endif
        }
-       mutex_unlock(&trace_types_lock);
 }
 
 #define SAVED_CMDLINES 128
@@ -2760,6 +2834,17 @@ static int s_show(struct seq_file *m, void *v)
        return 0;
 }
 
+/*
+ * Should be used after trace_array_get(), trace_types_lock
+ * ensures that i_cdev was already initialized.
+ */
+static inline int tracing_get_cpu(struct inode *inode)
+{
+       if (inode->i_cdev) /* See trace_create_cpu_file() */
+               return (long)inode->i_cdev - 1;
+       return RING_BUFFER_ALL_CPUS;
+}
+
 static const struct seq_operations tracer_seq_ops = {
        .start          = s_start,
        .next           = s_next,
@@ -2770,8 +2855,7 @@ static const struct seq_operations tracer_seq_ops = {
 static struct trace_iterator *
 __tracing_open(struct inode *inode, struct file *file, bool snapshot)
 {
-       struct trace_cpu *tc = inode->i_private;
-       struct trace_array *tr = tc->tr;
+       struct trace_array *tr = inode->i_private;
        struct trace_iterator *iter;
        int cpu;
 
@@ -2812,8 +2896,8 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
                iter->trace_buffer = &tr->trace_buffer;
        iter->snapshot = snapshot;
        iter->pos = -1;
+       iter->cpu_file = tracing_get_cpu(inode);
        mutex_init(&iter->mutex);
-       iter->cpu_file = tc->cpu;
 
        /* Notify the tracer early; before we stop tracing. */
        if (iter->trace && iter->trace->open)
@@ -2850,8 +2934,6 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
                tracing_iter_reset(iter, cpu);
        }
 
-       tr->ref++;
-
        mutex_unlock(&trace_types_lock);
 
        return iter;
@@ -2874,24 +2956,41 @@ int tracing_open_generic(struct inode *inode, struct file *filp)
        return 0;
 }
 
+/*
+ * Open and update trace_array ref count.
+ * Must have the current trace_array passed to it.
+ */
+int tracing_open_generic_tr(struct inode *inode, struct file *filp)
+{
+       struct trace_array *tr = inode->i_private;
+
+       if (tracing_disabled)
+               return -ENODEV;
+
+       if (trace_array_get(tr) < 0)
+               return -ENODEV;
+
+       filp->private_data = inode->i_private;
+
+       return 0;
+}
+
 static int tracing_release(struct inode *inode, struct file *file)
 {
+       struct trace_array *tr = inode->i_private;
        struct seq_file *m = file->private_data;
        struct trace_iterator *iter;
-       struct trace_array *tr;
        int cpu;
 
-       if (!(file->f_mode & FMODE_READ))
+       if (!(file->f_mode & FMODE_READ)) {
+               trace_array_put(tr);
                return 0;
+       }
 
+       /* Writes do not use seq_file */
        iter = m->private;
-       tr = iter->tr;
-
        mutex_lock(&trace_types_lock);
 
-       WARN_ON(!tr->ref);
-       tr->ref--;
-
        for_each_tracing_cpu(cpu) {
                if (iter->buffer_iter[cpu])
                        ring_buffer_read_finish(iter->buffer_iter[cpu]);
@@ -2903,6 +3002,9 @@ static int tracing_release(struct inode *inode, struct file *file)
        if (!iter->snapshot)
                /* reenable tracing if it was previously enabled */
                tracing_start_tr(tr);
+
+       __trace_array_put(tr);
+
        mutex_unlock(&trace_types_lock);
 
        mutex_destroy(&iter->mutex);
@@ -2910,24 +3012,44 @@ static int tracing_release(struct inode *inode, struct file *file)
        kfree(iter->trace);
        kfree(iter->buffer_iter);
        seq_release_private(inode, file);
+
+       return 0;
+}
+
+static int tracing_release_generic_tr(struct inode *inode, struct file *file)
+{
+       struct trace_array *tr = inode->i_private;
+
+       trace_array_put(tr);
        return 0;
 }
 
+static int tracing_single_release_tr(struct inode *inode, struct file *file)
+{
+       struct trace_array *tr = inode->i_private;
+
+       trace_array_put(tr);
+
+       return single_release(inode, file);
+}
+
 static int tracing_open(struct inode *inode, struct file *file)
 {
+       struct trace_array *tr = inode->i_private;
        struct trace_iterator *iter;
        int ret = 0;
 
+       if (trace_array_get(tr) < 0)
+               return -ENODEV;
+
        /* If this file was open for write, then erase contents */
-       if ((file->f_mode & FMODE_WRITE) &&
-           (file->f_flags & O_TRUNC)) {
-               struct trace_cpu *tc = inode->i_private;
-               struct trace_array *tr = tc->tr;
+       if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
+               int cpu = tracing_get_cpu(inode);
 
-               if (tc->cpu == RING_BUFFER_ALL_CPUS)
+               if (cpu == RING_BUFFER_ALL_CPUS)
                        tracing_reset_online_cpus(&tr->trace_buffer);
                else
-                       tracing_reset(&tr->trace_buffer, tc->cpu);
+                       tracing_reset(&tr->trace_buffer, cpu);
        }
 
        if (file->f_mode & FMODE_READ) {
@@ -2937,6 +3059,10 @@ static int tracing_open(struct inode *inode, struct file *file)
                else if (trace_flags & TRACE_ITER_LATENCY_FMT)
                        iter->iter_flags |= TRACE_FILE_LAT_FMT;
        }
+
+       if (ret < 0)
+               trace_array_put(tr);
+
        return ret;
 }
 
@@ -3293,17 +3419,27 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
 
 static int tracing_trace_options_open(struct inode *inode, struct file *file)
 {
+       struct trace_array *tr = inode->i_private;
+       int ret;
+
        if (tracing_disabled)
                return -ENODEV;
 
-       return single_open(file, tracing_trace_options_show, inode->i_private);
+       if (trace_array_get(tr) < 0)
+               return -ENODEV;
+
+       ret = single_open(file, tracing_trace_options_show, inode->i_private);
+       if (ret < 0)
+               trace_array_put(tr);
+
+       return ret;
 }
 
 static const struct file_operations tracing_iter_fops = {
        .open           = tracing_trace_options_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = single_release,
+       .release        = tracing_single_release_tr,
        .write          = tracing_trace_options_write,
 };
 
@@ -3783,20 +3919,23 @@ tracing_max_lat_write(struct file *filp, const char __user *ubuf,
 
 static int tracing_open_pipe(struct inode *inode, struct file *filp)
 {
-       struct trace_cpu *tc = inode->i_private;
-       struct trace_array *tr = tc->tr;
+       struct trace_array *tr = inode->i_private;
        struct trace_iterator *iter;
        int ret = 0;
 
        if (tracing_disabled)
                return -ENODEV;
 
+       if (trace_array_get(tr) < 0)
+               return -ENODEV;
+
        mutex_lock(&trace_types_lock);
 
        /* create a buffer to store the information to pass to userspace */
        iter = kzalloc(sizeof(*iter), GFP_KERNEL);
        if (!iter) {
                ret = -ENOMEM;
+               __trace_array_put(tr);
                goto out;
        }
 
@@ -3826,9 +3965,9 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
        if (trace_clocks[tr->clock_id].in_ns)
                iter->iter_flags |= TRACE_FILE_TIME_IN_NS;
 
-       iter->cpu_file = tc->cpu;
-       iter->tr = tc->tr;
-       iter->trace_buffer = &tc->tr->trace_buffer;
+       iter->tr = tr;
+       iter->trace_buffer = &tr->trace_buffer;
+       iter->cpu_file = tracing_get_cpu(inode);
        mutex_init(&iter->mutex);
        filp->private_data = iter;
 
@@ -3843,6 +3982,7 @@ out:
 fail:
        kfree(iter->trace);
        kfree(iter);
+       __trace_array_put(tr);
        mutex_unlock(&trace_types_lock);
        return ret;
 }
@@ -3850,6 +3990,7 @@ fail:
 static int tracing_release_pipe(struct inode *inode, struct file *file)
 {
        struct trace_iterator *iter = file->private_data;
+       struct trace_array *tr = inode->i_private;
 
        mutex_lock(&trace_types_lock);
 
@@ -3863,6 +4004,8 @@ static int tracing_release_pipe(struct inode *inode, struct file *file)
        kfree(iter->trace);
        kfree(iter);
 
+       trace_array_put(tr);
+
        return 0;
 }
 
@@ -3939,7 +4082,7 @@ static int tracing_wait_pipe(struct file *filp)
                 *
                 * iter->pos will be 0 if we haven't read anything.
                 */
-               if (!tracing_is_enabled() && iter->pos)
+               if (!tracing_is_on() && iter->pos)
                        break;
        }
 
@@ -4000,6 +4143,7 @@ waitagain:
        memset(&iter->seq, 0,
               sizeof(struct trace_iterator) -
               offsetof(struct trace_iterator, seq));
+       cpumask_clear(iter->started);
        iter->pos = -1;
 
        trace_event_read_lock();
@@ -4200,15 +4344,16 @@ static ssize_t
 tracing_entries_read(struct file *filp, char __user *ubuf,
                     size_t cnt, loff_t *ppos)
 {
-       struct trace_cpu *tc = filp->private_data;
-       struct trace_array *tr = tc->tr;
+       struct inode *inode = file_inode(filp);
+       struct trace_array *tr = inode->i_private;
+       int cpu = tracing_get_cpu(inode);
        char buf[64];
        int r = 0;
        ssize_t ret;
 
        mutex_lock(&trace_types_lock);
 
-       if (tc->cpu == RING_BUFFER_ALL_CPUS) {
+       if (cpu == RING_BUFFER_ALL_CPUS) {
                int cpu, buf_size_same;
                unsigned long size;
 
@@ -4235,7 +4380,7 @@ tracing_entries_read(struct file *filp, char __user *ubuf,
                } else
                        r = sprintf(buf, "X\n");
        } else
-               r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->trace_buffer.data, tc->cpu)->entries >> 10);
+               r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->trace_buffer.data, cpu)->entries >> 10);
 
        mutex_unlock(&trace_types_lock);
 
@@ -4247,7 +4392,8 @@ static ssize_t
 tracing_entries_write(struct file *filp, const char __user *ubuf,
                      size_t cnt, loff_t *ppos)
 {
-       struct trace_cpu *tc = filp->private_data;
+       struct inode *inode = file_inode(filp);
+       struct trace_array *tr = inode->i_private;
        unsigned long val;
        int ret;
 
@@ -4261,8 +4407,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
 
        /* value is in KB */
        val <<= 10;
-
-       ret = tracing_resize_ring_buffer(tc->tr, val, tc->cpu);
+       ret = tracing_resize_ring_buffer(tr, val, tracing_get_cpu(inode));
        if (ret < 0)
                return ret;
 
@@ -4316,10 +4461,12 @@ tracing_free_buffer_release(struct inode *inode, struct file *filp)
 
        /* disable tracing ? */
        if (trace_flags & TRACE_ITER_STOP_ON_FREE)
-               tracing_off();
+               tracer_tracing_off(tr);
        /* resize the ring buffer to 0 */
        tracing_resize_ring_buffer(tr, 0, RING_BUFFER_ALL_CPUS);
 
+       trace_array_put(tr);
+
        return 0;
 }
 
@@ -4328,6 +4475,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
                                        size_t cnt, loff_t *fpos)
 {
        unsigned long addr = (unsigned long)ubuf;
+       struct trace_array *tr = filp->private_data;
        struct ring_buffer_event *event;
        struct ring_buffer *buffer;
        struct print_entry *entry;
@@ -4387,7 +4535,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
 
        local_save_flags(irq_flags);
        size = sizeof(*entry) + cnt + 2; /* possible \n added */
-       buffer = global_trace.trace_buffer.buffer;
+       buffer = tr->trace_buffer.buffer;
        event = trace_buffer_lock_reserve(buffer, TRACE_PRINT, size,
                                          irq_flags, preempt_count());
        if (!event) {
@@ -4478,12 +4626,12 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
         * New clock may not be consistent with the previous clock.
         * Reset the buffer so that it doesn't have incomparable timestamps.
         */
-       tracing_reset_online_cpus(&global_trace.trace_buffer);
+       tracing_reset_online_cpus(&tr->trace_buffer);
 
 #ifdef CONFIG_TRACER_MAX_TRACE
        if (tr->flags & TRACE_ARRAY_FL_GLOBAL && tr->max_buffer.buffer)
                ring_buffer_set_clock(tr->max_buffer.buffer, trace_clocks[i].func);
-       tracing_reset_online_cpus(&global_trace.max_buffer);
+       tracing_reset_online_cpus(&tr->max_buffer);
 #endif
 
        mutex_unlock(&trace_types_lock);
@@ -4495,10 +4643,20 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
 
 static int tracing_clock_open(struct inode *inode, struct file *file)
 {
+       struct trace_array *tr = inode->i_private;
+       int ret;
+
        if (tracing_disabled)
                return -ENODEV;
 
-       return single_open(file, tracing_clock_show, inode->i_private);
+       if (trace_array_get(tr))
+               return -ENODEV;
+
+       ret = single_open(file, tracing_clock_show, inode->i_private);
+       if (ret < 0)
+               trace_array_put(tr);
+
+       return ret;
 }
 
 struct ftrace_buffer_info {
@@ -4510,31 +4668,40 @@ struct ftrace_buffer_info {
 #ifdef CONFIG_TRACER_SNAPSHOT
 static int tracing_snapshot_open(struct inode *inode, struct file *file)
 {
-       struct trace_cpu *tc = inode->i_private;
+       struct trace_array *tr = inode->i_private;
        struct trace_iterator *iter;
        struct seq_file *m;
        int ret = 0;
 
+       if (trace_array_get(tr) < 0)
+               return -ENODEV;
+
        if (file->f_mode & FMODE_READ) {
                iter = __tracing_open(inode, file, true);
                if (IS_ERR(iter))
                        ret = PTR_ERR(iter);
        } else {
                /* Writes still need the seq_file to hold the private data */
+               ret = -ENOMEM;
                m = kzalloc(sizeof(*m), GFP_KERNEL);
                if (!m)
-                       return -ENOMEM;
+                       goto out;
                iter = kzalloc(sizeof(*iter), GFP_KERNEL);
                if (!iter) {
                        kfree(m);
-                       return -ENOMEM;
+                       goto out;
                }
-               iter->tr = tc->tr;
-               iter->trace_buffer = &tc->tr->max_buffer;
-               iter->cpu_file = tc->cpu;
+               ret = 0;
+
+               iter->tr = tr;
+               iter->trace_buffer = &tr->max_buffer;
+               iter->cpu_file = tracing_get_cpu(inode);
                m->private = iter;
                file->private_data = m;
        }
+out:
+       if (ret < 0)
+               trace_array_put(tr);
 
        return ret;
 }
@@ -4616,9 +4783,12 @@ out:
 static int tracing_snapshot_release(struct inode *inode, struct file *file)
 {
        struct seq_file *m = file->private_data;
+       int ret;
+
+       ret = tracing_release(inode, file);
 
        if (file->f_mode & FMODE_READ)
-               return tracing_release(inode, file);
+               return ret;
 
        /* If write only, the seq_file is just a stub */
        if (m)
@@ -4684,34 +4854,38 @@ static const struct file_operations tracing_pipe_fops = {
 };
 
 static const struct file_operations tracing_entries_fops = {
-       .open           = tracing_open_generic,
+       .open           = tracing_open_generic_tr,
        .read           = tracing_entries_read,
        .write          = tracing_entries_write,
        .llseek         = generic_file_llseek,
+       .release        = tracing_release_generic_tr,
 };
 
 static const struct file_operations tracing_total_entries_fops = {
-       .open           = tracing_open_generic,
+       .open           = tracing_open_generic_tr,
        .read           = tracing_total_entries_read,
        .llseek         = generic_file_llseek,
+       .release        = tracing_release_generic_tr,
 };
 
 static const struct file_operations tracing_free_buffer_fops = {
+       .open           = tracing_open_generic_tr,
        .write          = tracing_free_buffer_write,
        .release        = tracing_free_buffer_release,
 };
 
 static const struct file_operations tracing_mark_fops = {
-       .open           = tracing_open_generic,
+       .open           = tracing_open_generic_tr,
        .write          = tracing_mark_write,
        .llseek         = generic_file_llseek,
+       .release        = tracing_release_generic_tr,
 };
 
 static const struct file_operations trace_clock_fops = {
        .open           = tracing_clock_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = single_release,
+       .release        = tracing_single_release_tr,
        .write          = tracing_clock_write,
 };
 
@@ -4736,23 +4910,26 @@ static const struct file_operations snapshot_raw_fops = {
 
 static int tracing_buffers_open(struct inode *inode, struct file *filp)
 {
-       struct trace_cpu *tc = inode->i_private;
-       struct trace_array *tr = tc->tr;
+       struct trace_array *tr = inode->i_private;
        struct ftrace_buffer_info *info;
+       int ret;
 
        if (tracing_disabled)
                return -ENODEV;
 
+       if (trace_array_get(tr) < 0)
+               return -ENODEV;
+
        info = kzalloc(sizeof(*info), GFP_KERNEL);
-       if (!info)
+       if (!info) {
+               trace_array_put(tr);
                return -ENOMEM;
+       }
 
        mutex_lock(&trace_types_lock);
 
-       tr->ref++;
-
        info->iter.tr           = tr;
-       info->iter.cpu_file     = tc->cpu;
+       info->iter.cpu_file     = tracing_get_cpu(inode);
        info->iter.trace        = tr->current_trace;
        info->iter.trace_buffer = &tr->trace_buffer;
        info->spare             = NULL;
@@ -4763,7 +4940,11 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)
 
        mutex_unlock(&trace_types_lock);
 
-       return nonseekable_open(inode, filp);
+       ret = nonseekable_open(inode, filp);
+       if (ret < 0)
+               trace_array_put(tr);
+
+       return ret;
 }
 
 static unsigned int
@@ -4863,8 +5044,7 @@ static int tracing_buffers_release(struct inode *inode, struct file *file)
 
        mutex_lock(&trace_types_lock);
 
-       WARN_ON(!iter->tr->ref);
-       iter->tr->ref--;
+       __trace_array_put(iter->tr);
 
        if (info->spare)
                ring_buffer_free_read_page(iter->trace_buffer->buffer, info->spare);
@@ -5066,14 +5246,14 @@ static ssize_t
 tracing_stats_read(struct file *filp, char __user *ubuf,
                   size_t count, loff_t *ppos)
 {
-       struct trace_cpu *tc = filp->private_data;
-       struct trace_array *tr = tc->tr;
+       struct inode *inode = file_inode(filp);
+       struct trace_array *tr = inode->i_private;
        struct trace_buffer *trace_buf = &tr->trace_buffer;
+       int cpu = tracing_get_cpu(inode);
        struct trace_seq *s;
        unsigned long cnt;
        unsigned long long t;
        unsigned long usec_rem;
-       int cpu = tc->cpu;
 
        s = kmalloc(sizeof(*s), GFP_KERNEL);
        if (!s)
@@ -5126,9 +5306,10 @@ tracing_stats_read(struct file *filp, char __user *ubuf,
 }
 
 static const struct file_operations tracing_stats_fops = {
-       .open           = tracing_open_generic,
+       .open           = tracing_open_generic_tr,
        .read           = tracing_stats_read,
        .llseek         = generic_file_llseek,
+       .release        = tracing_release_generic_tr,
 };
 
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -5317,10 +5498,20 @@ static struct dentry *tracing_dentry_percpu(struct trace_array *tr, int cpu)
        return tr->percpu_dir;
 }
 
+static struct dentry *
+trace_create_cpu_file(const char *name, umode_t mode, struct dentry *parent,
+                     void *data, long cpu, const struct file_operations *fops)
+{
+       struct dentry *ret = trace_create_file(name, mode, parent, data, fops);
+
+       if (ret) /* See tracing_get_cpu() */
+               ret->d_inode->i_cdev = (void *)(cpu + 1);
+       return ret;
+}
+
 static void
 tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
 {
-       struct trace_array_cpu *data = per_cpu_ptr(tr->trace_buffer.data, cpu);
        struct dentry *d_percpu = tracing_dentry_percpu(tr, cpu);
        struct dentry *d_cpu;
        char cpu_dir[30]; /* 30 characters should be more than enough */
@@ -5336,28 +5527,28 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
        }
 
        /* per cpu trace_pipe */
-       trace_create_file("trace_pipe", 0444, d_cpu,
-                       (void *)&data->trace_cpu, &tracing_pipe_fops);
+       trace_create_cpu_file("trace_pipe", 0444, d_cpu,
+                               tr, cpu, &tracing_pipe_fops);
 
        /* per cpu trace */
-       trace_create_file("trace", 0644, d_cpu,
-                       (void *)&data->trace_cpu, &tracing_fops);
+       trace_create_cpu_file("trace", 0644, d_cpu,
+                               tr, cpu, &tracing_fops);
 
-       trace_create_file("trace_pipe_raw", 0444, d_cpu,
-                       (void *)&data->trace_cpu, &tracing_buffers_fops);
+       trace_create_cpu_file("trace_pipe_raw", 0444, d_cpu,
+                               tr, cpu, &tracing_buffers_fops);
 
-       trace_create_file("stats", 0444, d_cpu,
-                       (void *)&data->trace_cpu, &tracing_stats_fops);
+       trace_create_cpu_file("stats", 0444, d_cpu,
+                               tr, cpu, &tracing_stats_fops);
 
-       trace_create_file("buffer_size_kb", 0444, d_cpu,
-                       (void *)&data->trace_cpu, &tracing_entries_fops);
+       trace_create_cpu_file("buffer_size_kb", 0444, d_cpu,
+                               tr, cpu, &tracing_entries_fops);
 
 #ifdef CONFIG_TRACER_SNAPSHOT
-       trace_create_file("snapshot", 0644, d_cpu,
-                         (void *)&data->trace_cpu, &snapshot_fops);
+       trace_create_cpu_file("snapshot", 0644, d_cpu,
+                               tr, cpu, &snapshot_fops);
 
-       trace_create_file("snapshot_raw", 0444, d_cpu,
-                       (void *)&data->trace_cpu, &snapshot_raw_fops);
+       trace_create_cpu_file("snapshot_raw", 0444, d_cpu,
+                               tr, cpu, &snapshot_raw_fops);
 #endif
 }
 
@@ -5612,15 +5803,10 @@ rb_simple_read(struct file *filp, char __user *ubuf,
               size_t cnt, loff_t *ppos)
 {
        struct trace_array *tr = filp->private_data;
-       struct ring_buffer *buffer = tr->trace_buffer.buffer;
        char buf[64];
        int r;
 
-       if (buffer)
-               r = ring_buffer_record_is_on(buffer);
-       else
-               r = 0;
-
+       r = tracer_tracing_is_on(tr);
        r = sprintf(buf, "%d\n", r);
 
        return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
@@ -5642,11 +5828,11 @@ rb_simple_write(struct file *filp, const char __user *ubuf,
        if (buffer) {
                mutex_lock(&trace_types_lock);
                if (val) {
-                       ring_buffer_record_on(buffer);
+                       tracer_tracing_on(tr);
                        if (tr->current_trace->start)
                                tr->current_trace->start(tr);
                } else {
-                       ring_buffer_record_off(buffer);
+                       tracer_tracing_off(tr);
                        if (tr->current_trace->stop)
                                tr->current_trace->stop(tr);
                }
@@ -5659,9 +5845,10 @@ rb_simple_write(struct file *filp, const char __user *ubuf,
 }
 
 static const struct file_operations rb_simple_fops = {
-       .open           = tracing_open_generic,
+       .open           = tracing_open_generic_tr,
        .read           = rb_simple_read,
        .write          = rb_simple_write,
+       .release        = tracing_release_generic_tr,
        .llseek         = default_llseek,
 };
 
@@ -5775,8 +5962,10 @@ static int new_instance_create(const char *name)
                goto out_free_tr;
 
        ret = event_trace_add_tracer(tr->dir, tr);
-       if (ret)
+       if (ret) {
+               debugfs_remove_recursive(tr->dir);
                goto out_free_tr;
+       }
 
        init_tracer_debugfs(tr, tr->dir);
 
@@ -5922,13 +6111,13 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer)
                          tr, &tracing_iter_fops);
 
        trace_create_file("trace", 0644, d_tracer,
-                       (void *)&tr->trace_cpu, &tracing_fops);
+                         tr, &tracing_fops);
 
        trace_create_file("trace_pipe", 0444, d_tracer,
-                       (void *)&tr->trace_cpu, &tracing_pipe_fops);
+                         tr, &tracing_pipe_fops);
 
        trace_create_file("buffer_size_kb", 0644, d_tracer,
-                       (void *)&tr->trace_cpu, &tracing_entries_fops);
+                         tr, &tracing_entries_fops);
 
        trace_create_file("buffer_total_size_kb", 0444, d_tracer,
                          tr, &tracing_total_entries_fops);
@@ -5943,11 +6132,11 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer)
                          &trace_clock_fops);
 
        trace_create_file("tracing_on", 0644, d_tracer,
-                           tr, &rb_simple_fops);
+                         tr, &rb_simple_fops);
 
 #ifdef CONFIG_TRACER_SNAPSHOT
        trace_create_file("snapshot", 0644, d_tracer,
-                         (void *)&tr->trace_cpu, &snapshot_fops);
+                         tr, &snapshot_fops);
 #endif
 
        for_each_tracing_cpu(cpu)
index 20572ed88c5c3b791bef107aab7fbc1f3b0b44d1..51b44483eb78b87f21c263a4868288284bc10b74 100644 (file)
@@ -224,6 +224,11 @@ enum {
 
 extern struct list_head ftrace_trace_arrays;
 
+extern struct mutex trace_types_lock;
+
+extern int trace_array_get(struct trace_array *tr);
+extern void trace_array_put(struct trace_array *tr);
+
 /*
  * The global tracer (top) should be the first trace array added,
  * but we check the flag anyway.
index 27963e2bf4bfe141d0884bbe9f05b0d74a7fcc47..3d18aadef493e835ad9bcaaee95aea88f8edbaf0 100644 (file)
@@ -41,6 +41,23 @@ static LIST_HEAD(ftrace_common_fields);
 static struct kmem_cache *field_cachep;
 static struct kmem_cache *file_cachep;
 
+#define SYSTEM_FL_FREE_NAME            (1 << 31)
+
+static inline int system_refcount(struct event_subsystem *system)
+{
+       return system->ref_count & ~SYSTEM_FL_FREE_NAME;
+}
+
+static int system_refcount_inc(struct event_subsystem *system)
+{
+       return (system->ref_count++) & ~SYSTEM_FL_FREE_NAME;
+}
+
+static int system_refcount_dec(struct event_subsystem *system)
+{
+       return (--system->ref_count) & ~SYSTEM_FL_FREE_NAME;
+}
+
 /* Double loops, do not use break, only goto's work */
 #define do_for_each_event_file(tr, file)                       \
        list_for_each_entry(tr, &ftrace_trace_arrays, list) {   \
@@ -97,7 +114,7 @@ static int __trace_define_field(struct list_head *head, const char *type,
 
        field = kmem_cache_alloc(field_cachep, GFP_TRACE);
        if (!field)
-               goto err;
+               return -ENOMEM;
 
        field->name = name;
        field->type = type;
@@ -114,11 +131,6 @@ static int __trace_define_field(struct list_head *head, const char *type,
        list_add(&field->link, head);
 
        return 0;
-
-err:
-       kmem_cache_free(field_cachep, field);
-
-       return -ENOMEM;
 }
 
 int trace_define_field(struct ftrace_event_call *call, const char *type,
@@ -349,8 +361,8 @@ static void __put_system(struct event_subsystem *system)
 {
        struct event_filter *filter = system->filter;
 
-       WARN_ON_ONCE(system->ref_count == 0);
-       if (--system->ref_count)
+       WARN_ON_ONCE(system_refcount(system) == 0);
+       if (system_refcount_dec(system))
                return;
 
        list_del(&system->list);
@@ -359,13 +371,15 @@ static void __put_system(struct event_subsystem *system)
                kfree(filter->filter_string);
                kfree(filter);
        }
+       if (system->ref_count & SYSTEM_FL_FREE_NAME)
+               kfree(system->name);
        kfree(system);
 }
 
 static void __get_system(struct event_subsystem *system)
 {
-       WARN_ON_ONCE(system->ref_count == 0);
-       system->ref_count++;
+       WARN_ON_ONCE(system_refcount(system) == 0);
+       system_refcount_inc(system);
 }
 
 static void __get_system_dir(struct ftrace_subsystem_dir *dir)
@@ -379,7 +393,7 @@ static void __put_system_dir(struct ftrace_subsystem_dir *dir)
 {
        WARN_ON_ONCE(dir->ref_count == 0);
        /* If the subsystem is about to be freed, the dir must be too */
-       WARN_ON_ONCE(dir->subsystem->ref_count == 1 && dir->ref_count != 1);
+       WARN_ON_ONCE(system_refcount(dir->subsystem) == 1 && dir->ref_count != 1);
 
        __put_system(dir->subsystem);
        if (!--dir->ref_count)
@@ -393,17 +407,55 @@ static void put_system(struct ftrace_subsystem_dir *dir)
        mutex_unlock(&event_mutex);
 }
 
+static void remove_subsystem(struct ftrace_subsystem_dir *dir)
+{
+       if (!dir)
+               return;
+
+       if (!--dir->nr_events) {
+               debugfs_remove_recursive(dir->entry);
+               list_del(&dir->list);
+               __put_system_dir(dir);
+       }
+}
+
+static void *event_file_data(struct file *filp)
+{
+       return ACCESS_ONCE(file_inode(filp)->i_private);
+}
+
+static void remove_event_file_dir(struct ftrace_event_file *file)
+{
+       struct dentry *dir = file->dir;
+       struct dentry *child;
+
+       if (dir) {
+               spin_lock(&dir->d_lock);        /* probably unneeded */
+               list_for_each_entry(child, &dir->d_subdirs, d_u.d_child) {
+                       if (child->d_inode)     /* probably unneeded */
+                               child->d_inode->i_private = NULL;
+               }
+               spin_unlock(&dir->d_lock);
+
+               debugfs_remove_recursive(dir);
+       }
+
+       list_del(&file->list);
+       remove_subsystem(file->system);
+       kmem_cache_free(file_cachep, file);
+}
+
 /*
  * __ftrace_set_clr_event(NULL, NULL, NULL, set) will set/unset all events.
  */
-static int __ftrace_set_clr_event(struct trace_array *tr, const char *match,
-                                 const char *sub, const char *event, int set)
+static int
+__ftrace_set_clr_event_nolock(struct trace_array *tr, const char *match,
+                             const char *sub, const char *event, int set)
 {
        struct ftrace_event_file *file;
        struct ftrace_event_call *call;
        int ret = -EINVAL;
 
-       mutex_lock(&event_mutex);
        list_for_each_entry(file, &tr->events, list) {
 
                call = file->event_call;
@@ -429,6 +481,17 @@ static int __ftrace_set_clr_event(struct trace_array *tr, const char *match,
 
                ret = 0;
        }
+
+       return ret;
+}
+
+static int __ftrace_set_clr_event(struct trace_array *tr, const char *match,
+                                 const char *sub, const char *event, int set)
+{
+       int ret;
+
+       mutex_lock(&event_mutex);
+       ret = __ftrace_set_clr_event_nolock(tr, match, sub, event, set);
        mutex_unlock(&event_mutex);
 
        return ret;
@@ -623,13 +686,23 @@ static ssize_t
 event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
                  loff_t *ppos)
 {
-       struct ftrace_event_file *file = filp->private_data;
+       struct ftrace_event_file *file;
+       unsigned long flags;
        char *buf;
 
-       if (file->flags & FTRACE_EVENT_FL_ENABLED) {
-               if (file->flags & FTRACE_EVENT_FL_SOFT_DISABLED)
+       mutex_lock(&event_mutex);
+       file = event_file_data(filp);
+       if (likely(file))
+               flags = file->flags;
+       mutex_unlock(&event_mutex);
+
+       if (!file)
+               return -ENODEV;
+
+       if (flags & FTRACE_EVENT_FL_ENABLED) {
+               if (flags & FTRACE_EVENT_FL_SOFT_DISABLED)
                        buf = "0*\n";
-               else if (file->flags & FTRACE_EVENT_FL_SOFT_MODE)
+               else if (flags & FTRACE_EVENT_FL_SOFT_MODE)
                        buf = "1*\n";
                else
                        buf = "1\n";
@@ -643,13 +716,10 @@ static ssize_t
 event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
                   loff_t *ppos)
 {
-       struct ftrace_event_file *file = filp->private_data;
+       struct ftrace_event_file *file;
        unsigned long val;
        int ret;
 
-       if (!file)
-               return -EINVAL;
-
        ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
        if (ret)
                return ret;
@@ -661,8 +731,11 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
        switch (val) {
        case 0:
        case 1:
+               ret = -ENODEV;
                mutex_lock(&event_mutex);
-               ret = ftrace_event_enable_disable(file, val);
+               file = event_file_data(filp);
+               if (likely(file))
+                       ret = ftrace_event_enable_disable(file, val);
                mutex_unlock(&event_mutex);
                break;
 
@@ -769,7 +842,7 @@ enum {
 
 static void *f_next(struct seq_file *m, void *v, loff_t *pos)
 {
-       struct ftrace_event_call *call = m->private;
+       struct ftrace_event_call *call = event_file_data(m->private);
        struct ftrace_event_field *field;
        struct list_head *common_head = &ftrace_common_fields;
        struct list_head *head = trace_get_fields(call);
@@ -813,6 +886,11 @@ static void *f_start(struct seq_file *m, loff_t *pos)
        loff_t l = 0;
        void *p;
 
+       /* ->stop() is called even if ->start() fails */
+       mutex_lock(&event_mutex);
+       if (!event_file_data(m->private))
+               return ERR_PTR(-ENODEV);
+
        /* Start by showing the header */
        if (!*pos)
                return (void *)FORMAT_HEADER;
@@ -827,7 +905,7 @@ static void *f_start(struct seq_file *m, loff_t *pos)
 
 static int f_show(struct seq_file *m, void *v)
 {
-       struct ftrace_event_call *call = m->private;
+       struct ftrace_event_call *call = event_file_data(m->private);
        struct ftrace_event_field *field;
        const char *array_descriptor;
 
@@ -878,6 +956,7 @@ static int f_show(struct seq_file *m, void *v)
 
 static void f_stop(struct seq_file *m, void *p)
 {
+       mutex_unlock(&event_mutex);
 }
 
 static const struct seq_operations trace_format_seq_ops = {
@@ -889,7 +968,6 @@ static const struct seq_operations trace_format_seq_ops = {
 
 static int trace_format_open(struct inode *inode, struct file *file)
 {
-       struct ftrace_event_call *call = inode->i_private;
        struct seq_file *m;
        int ret;
 
@@ -898,7 +976,7 @@ static int trace_format_open(struct inode *inode, struct file *file)
                return ret;
 
        m = file->private_data;
-       m->private = call;
+       m->private = file;
 
        return 0;
 }
@@ -906,19 +984,22 @@ static int trace_format_open(struct inode *inode, struct file *file)
 static ssize_t
 event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 {
-       struct ftrace_event_call *call = filp->private_data;
+       int id = (long)event_file_data(filp);
        struct trace_seq *s;
        int r;
 
        if (*ppos)
                return 0;
 
+       if (unlikely(!id))
+               return -ENODEV;
+
        s = kmalloc(sizeof(*s), GFP_KERNEL);
        if (!s)
                return -ENOMEM;
 
        trace_seq_init(s);
-       trace_seq_printf(s, "%d\n", call->event.type);
+       trace_seq_printf(s, "%d\n", id);
 
        r = simple_read_from_buffer(ubuf, cnt, ppos,
                                    s->buffer, s->len);
@@ -930,21 +1011,28 @@ static ssize_t
 event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
                  loff_t *ppos)
 {
-       struct ftrace_event_call *call = filp->private_data;
+       struct ftrace_event_call *call;
        struct trace_seq *s;
-       int r;
+       int r = -ENODEV;
 
        if (*ppos)
                return 0;
 
        s = kmalloc(sizeof(*s), GFP_KERNEL);
+
        if (!s)
                return -ENOMEM;
 
        trace_seq_init(s);
 
-       print_event_filter(call, s);
-       r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
+       mutex_lock(&event_mutex);
+       call = event_file_data(filp);
+       if (call)
+               print_event_filter(call, s);
+       mutex_unlock(&event_mutex);
+
+       if (call)
+               r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
 
        kfree(s);
 
@@ -955,9 +1043,9 @@ static ssize_t
 event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
                   loff_t *ppos)
 {
-       struct ftrace_event_call *call = filp->private_data;
+       struct ftrace_event_call *call;
        char *buf;
-       int err;
+       int err = -ENODEV;
 
        if (cnt >= PAGE_SIZE)
                return -EINVAL;
@@ -972,7 +1060,12 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
        }
        buf[cnt] = '\0';
 
-       err = apply_event_filter(call, buf);
+       mutex_lock(&event_mutex);
+       call = event_file_data(filp);
+       if (call)
+               err = apply_event_filter(call, buf);
+       mutex_unlock(&event_mutex);
+
        free_page((unsigned long) buf);
        if (err < 0)
                return err;
@@ -992,6 +1085,7 @@ static int subsystem_open(struct inode *inode, struct file *filp)
        int ret;
 
        /* Make sure the system still exists */
+       mutex_lock(&trace_types_lock);
        mutex_lock(&event_mutex);
        list_for_each_entry(tr, &ftrace_trace_arrays, list) {
                list_for_each_entry(dir, &tr->systems, list) {
@@ -1007,6 +1101,7 @@ static int subsystem_open(struct inode *inode, struct file *filp)
        }
  exit_loop:
        mutex_unlock(&event_mutex);
+       mutex_unlock(&trace_types_lock);
 
        if (!system)
                return -ENODEV;
@@ -1014,9 +1109,17 @@ static int subsystem_open(struct inode *inode, struct file *filp)
        /* Some versions of gcc think dir can be uninitialized here */
        WARN_ON(!dir);
 
+       /* Still need to increment the ref count of the system */
+       if (trace_array_get(tr) < 0) {
+               put_system(dir);
+               return -ENODEV;
+       }
+
        ret = tracing_open_generic(inode, filp);
-       if (ret < 0)
+       if (ret < 0) {
+               trace_array_put(tr);
                put_system(dir);
+       }
 
        return ret;
 }
@@ -1027,16 +1130,23 @@ static int system_tr_open(struct inode *inode, struct file *filp)
        struct trace_array *tr = inode->i_private;
        int ret;
 
+       if (trace_array_get(tr) < 0)
+               return -ENODEV;
+
        /* Make a temporary dir that has no system but points to tr */
        dir = kzalloc(sizeof(*dir), GFP_KERNEL);
-       if (!dir)
+       if (!dir) {
+               trace_array_put(tr);
                return -ENOMEM;
+       }
 
        dir->tr = tr;
 
        ret = tracing_open_generic(inode, filp);
-       if (ret < 0)
+       if (ret < 0) {
+               trace_array_put(tr);
                kfree(dir);
+       }
 
        filp->private_data = dir;
 
@@ -1047,6 +1157,8 @@ static int subsystem_release(struct inode *inode, struct file *file)
 {
        struct ftrace_subsystem_dir *dir = file->private_data;
 
+       trace_array_put(dir->tr);
+
        /*
         * If dir->subsystem is NULL, then this is a temporary
         * descriptor that was made for a trace_array to enable
@@ -1143,6 +1255,7 @@ show_header(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 
 static int ftrace_event_avail_open(struct inode *inode, struct file *file);
 static int ftrace_event_set_open(struct inode *inode, struct file *file);
+static int ftrace_event_release(struct inode *inode, struct file *file);
 
 static const struct seq_operations show_event_seq_ops = {
        .start = t_start,
@@ -1170,7 +1283,7 @@ static const struct file_operations ftrace_set_event_fops = {
        .read = seq_read,
        .write = ftrace_event_write,
        .llseek = seq_lseek,
-       .release = seq_release,
+       .release = ftrace_event_release,
 };
 
 static const struct file_operations ftrace_enable_fops = {
@@ -1188,7 +1301,6 @@ static const struct file_operations ftrace_event_format_fops = {
 };
 
 static const struct file_operations ftrace_event_id_fops = {
-       .open = tracing_open_generic,
        .read = event_id_read,
        .llseek = default_llseek,
 };
@@ -1247,6 +1359,15 @@ ftrace_event_open(struct inode *inode, struct file *file,
        return ret;
 }
 
+static int ftrace_event_release(struct inode *inode, struct file *file)
+{
+       struct trace_array *tr = inode->i_private;
+
+       trace_array_put(tr);
+
+       return seq_release(inode, file);
+}
+
 static int
 ftrace_event_avail_open(struct inode *inode, struct file *file)
 {
@@ -1260,12 +1381,19 @@ ftrace_event_set_open(struct inode *inode, struct file *file)
 {
        const struct seq_operations *seq_ops = &show_set_event_seq_ops;
        struct trace_array *tr = inode->i_private;
+       int ret;
+
+       if (trace_array_get(tr) < 0)
+               return -ENODEV;
 
        if ((file->f_mode & FMODE_WRITE) &&
            (file->f_flags & O_TRUNC))
                ftrace_clear_events(tr);
 
-       return ftrace_event_open(inode, file, seq_ops);
+       ret = ftrace_event_open(inode, file, seq_ops);
+       if (ret < 0)
+               trace_array_put(tr);
+       return ret;
 }
 
 static struct event_subsystem *
@@ -1279,7 +1407,15 @@ create_new_subsystem(const char *name)
                return NULL;
 
        system->ref_count = 1;
-       system->name = name;
+
+       /* Only allocate if dynamic (kprobes and modules) */
+       if (!core_kernel_data((unsigned long)name)) {
+               system->ref_count |= SYSTEM_FL_FREE_NAME;
+               system->name = kstrdup(name, GFP_KERNEL);
+               if (!system->name)
+                       goto out_free;
+       } else
+               system->name = name;
 
        system->filter = NULL;
 
@@ -1292,6 +1428,8 @@ create_new_subsystem(const char *name)
        return system;
 
  out_free:
+       if (system->ref_count & SYSTEM_FL_FREE_NAME)
+               kfree(system->name);
        kfree(system);
        return NULL;
 }
@@ -1410,8 +1548,8 @@ event_create_dir(struct dentry *parent,
 
 #ifdef CONFIG_PERF_EVENTS
        if (call->event.type && call->class->reg)
-               trace_create_file("id", 0444, file->dir, call,
-                                 id);
+               trace_create_file("id", 0444, file->dir,
+                                 (void *)(long)call->event.type, id);
 #endif
 
        /*
@@ -1436,33 +1574,16 @@ event_create_dir(struct dentry *parent,
        return 0;
 }
 
-static void remove_subsystem(struct ftrace_subsystem_dir *dir)
-{
-       if (!dir)
-               return;
-
-       if (!--dir->nr_events) {
-               debugfs_remove_recursive(dir->entry);
-               list_del(&dir->list);
-               __put_system_dir(dir);
-       }
-}
-
 static void remove_event_from_tracers(struct ftrace_event_call *call)
 {
        struct ftrace_event_file *file;
        struct trace_array *tr;
 
        do_for_each_event_file_safe(tr, file) {
-
                if (file->event_call != call)
                        continue;
 
-               list_del(&file->list);
-               debugfs_remove_recursive(file->dir);
-               remove_subsystem(file->system);
-               kmem_cache_free(file_cachep, file);
-
+               remove_event_file_dir(file);
                /*
                 * The do_for_each_event_file_safe() is
                 * a double loop. After finding the call for this
@@ -1591,6 +1712,7 @@ static void __add_event_to_tracers(struct ftrace_event_call *call,
 int trace_add_event_call(struct ftrace_event_call *call)
 {
        int ret;
+       mutex_lock(&trace_types_lock);
        mutex_lock(&event_mutex);
 
        ret = __register_event(call, NULL);
@@ -1598,11 +1720,13 @@ int trace_add_event_call(struct ftrace_event_call *call)
                __add_event_to_tracers(call, NULL);
 
        mutex_unlock(&event_mutex);
+       mutex_unlock(&trace_types_lock);
        return ret;
 }
 
 /*
- * Must be called under locking both of event_mutex and trace_event_sem.
+ * Must be called under locking of trace_types_lock, event_mutex and
+ * trace_event_sem.
  */
 static void __trace_remove_event_call(struct ftrace_event_call *call)
 {
@@ -1611,14 +1735,47 @@ static void __trace_remove_event_call(struct ftrace_event_call *call)
        destroy_preds(call);
 }
 
+static int probe_remove_event_call(struct ftrace_event_call *call)
+{
+       struct trace_array *tr;
+       struct ftrace_event_file *file;
+
+#ifdef CONFIG_PERF_EVENTS
+       if (call->perf_refcount)
+               return -EBUSY;
+#endif
+       do_for_each_event_file(tr, file) {
+               if (file->event_call != call)
+                       continue;
+               /*
+                * We can't rely on ftrace_event_enable_disable(enable => 0)
+                * we are going to do, FTRACE_EVENT_FL_SOFT_MODE can suppress
+                * TRACE_REG_UNREGISTER.
+                */
+               if (file->flags & FTRACE_EVENT_FL_ENABLED)
+                       return -EBUSY;
+               break;
+       } while_for_each_event_file();
+
+       __trace_remove_event_call(call);
+
+       return 0;
+}
+
 /* Remove an event_call */
-void trace_remove_event_call(struct ftrace_event_call *call)
+int trace_remove_event_call(struct ftrace_event_call *call)
 {
+       int ret;
+
+       mutex_lock(&trace_types_lock);
        mutex_lock(&event_mutex);
        down_write(&trace_event_sem);
-       __trace_remove_event_call(call);
+       ret = probe_remove_event_call(call);
        up_write(&trace_event_sem);
        mutex_unlock(&event_mutex);
+       mutex_unlock(&trace_types_lock);
+
+       return ret;
 }
 
 #define for_each_event(event, start, end)                      \
@@ -1762,6 +1919,7 @@ static int trace_module_notify(struct notifier_block *self,
 {
        struct module *mod = data;
 
+       mutex_lock(&trace_types_lock);
        mutex_lock(&event_mutex);
        switch (val) {
        case MODULE_STATE_COMING:
@@ -1772,6 +1930,7 @@ static int trace_module_notify(struct notifier_block *self,
                break;
        }
        mutex_unlock(&event_mutex);
+       mutex_unlock(&trace_types_lock);
 
        return 0;
 }
@@ -2188,12 +2347,8 @@ __trace_remove_event_dirs(struct trace_array *tr)
 {
        struct ftrace_event_file *file, *next;
 
-       list_for_each_entry_safe(file, next, &tr->events, list) {
-               list_del(&file->list);
-               debugfs_remove_recursive(file->dir);
-               remove_subsystem(file->system);
-               kmem_cache_free(file_cachep, file);
-       }
+       list_for_each_entry_safe(file, next, &tr->events, list)
+               remove_event_file_dir(file);
 }
 
 static void
@@ -2329,11 +2484,11 @@ early_event_add_tracer(struct dentry *parent, struct trace_array *tr)
 
 int event_trace_del_tracer(struct trace_array *tr)
 {
-       /* Disable any running events */
-       __ftrace_set_clr_event(tr, NULL, NULL, NULL, 0);
-
        mutex_lock(&event_mutex);
 
+       /* Disable any running events */
+       __ftrace_set_clr_event_nolock(tr, NULL, NULL, NULL, 0);
+
        down_write(&trace_event_sem);
        __trace_remove_event_dirs(tr);
        debugfs_remove_recursive(tr->event_dir);
index e1b653f7e1ca101f0861351d610b5c8297a4b3ca..0a1edc694d67c7f488a04e5bdb15f9594e14606c 100644 (file)
@@ -631,17 +631,15 @@ static void append_filter_err(struct filter_parse_state *ps,
        free_page((unsigned long) buf);
 }
 
+/* caller must hold event_mutex */
 void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s)
 {
-       struct event_filter *filter;
+       struct event_filter *filter = call->filter;
 
-       mutex_lock(&event_mutex);
-       filter = call->filter;
        if (filter && filter->filter_string)
                trace_seq_printf(s, "%s\n", filter->filter_string);
        else
                trace_seq_printf(s, "none\n");
-       mutex_unlock(&event_mutex);
 }
 
 void print_subsystem_event_filter(struct event_subsystem *system,
@@ -1835,23 +1833,22 @@ static int create_system_filter(struct event_subsystem *system,
        return err;
 }
 
+/* caller must hold event_mutex */
 int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
 {
        struct event_filter *filter;
-       int err = 0;
-
-       mutex_lock(&event_mutex);
+       int err;
 
        if (!strcmp(strstrip(filter_string), "0")) {
                filter_disable(call);
                filter = call->filter;
                if (!filter)
-                       goto out_unlock;
+                       return 0;
                RCU_INIT_POINTER(call->filter, NULL);
                /* Make sure the filter is not being used */
                synchronize_sched();
                __free_filter(filter);
-               goto out_unlock;
+               return 0;
        }
 
        err = create_filter(call, filter_string, true, &filter);
@@ -1878,8 +1875,6 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
                        __free_filter(tmp);
                }
        }
-out_unlock:
-       mutex_unlock(&event_mutex);
 
        return err;
 }
index b19d065a28cb44b303d74d1a2ec6b13a04ec734f..2aefbee93a6d574a0ea082632788a1d5c7791474 100644 (file)
@@ -373,7 +373,7 @@ start_critical_timing(unsigned long ip, unsigned long parent_ip)
        struct trace_array_cpu *data;
        unsigned long flags;
 
-       if (likely(!tracer_enabled))
+       if (!tracer_enabled || !tracing_is_enabled())
                return;
 
        cpu = raw_smp_processor_id();
@@ -416,7 +416,7 @@ stop_critical_timing(unsigned long ip, unsigned long parent_ip)
        else
                return;
 
-       if (!tracer_enabled)
+       if (!tracer_enabled || !tracing_is_enabled())
                return;
 
        data = per_cpu_ptr(tr->trace_buffer.data, cpu);
index 9f46e98ba8f22a712962ccc68e17b34f166439ba..64abc8ca928b3da7d0b78ab3811695b49f2e8c1c 100644 (file)
@@ -90,7 +90,7 @@ static __kprobes bool trace_probe_is_on_module(struct trace_probe *tp)
 }
 
 static int register_probe_event(struct trace_probe *tp);
-static void unregister_probe_event(struct trace_probe *tp);
+static int unregister_probe_event(struct trace_probe *tp);
 
 static DEFINE_MUTEX(probe_lock);
 static LIST_HEAD(probe_list);
@@ -281,6 +281,8 @@ trace_probe_file_index(struct trace_probe *tp, struct ftrace_event_file *file)
 static int
 disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
 {
+       struct ftrace_event_file **old = NULL;
+       int wait = 0;
        int ret = 0;
 
        mutex_lock(&probe_enable_lock);
@@ -314,10 +316,7 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
                }
 
                rcu_assign_pointer(tp->files, new);
-
-               /* Make sure the probe is done with old files */
-               synchronize_sched();
-               kfree(old);
+               wait = 1;
        } else
                tp->flags &= ~TP_FLAG_PROFILE;
 
@@ -326,11 +325,25 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
                        disable_kretprobe(&tp->rp);
                else
                        disable_kprobe(&tp->rp.kp);
+               wait = 1;
        }
 
  out_unlock:
        mutex_unlock(&probe_enable_lock);
 
+       if (wait) {
+               /*
+                * Synchronize with kprobe_trace_func/kretprobe_trace_func
+                * to ensure disabled (all running handlers are finished).
+                * This is not only for kfree(), but also the caller,
+                * trace_remove_event_call() supposes it for releasing
+                * event_call related objects, which will be accessed in
+                * the kprobe_trace_func/kretprobe_trace_func.
+                */
+               synchronize_sched();
+               kfree(old);     /* Ignored if link == NULL */
+       }
+
        return ret;
 }
 
@@ -398,9 +411,12 @@ static int unregister_trace_probe(struct trace_probe *tp)
        if (trace_probe_is_enabled(tp))
                return -EBUSY;
 
+       /* Will fail if probe is being used by ftrace or perf */
+       if (unregister_probe_event(tp))
+               return -EBUSY;
+
        __unregister_trace_probe(tp);
        list_del(&tp->list);
-       unregister_probe_event(tp);
 
        return 0;
 }
@@ -679,7 +695,9 @@ static int release_all_trace_probes(void)
        /* TODO: Use batch unregistration */
        while (!list_empty(&probe_list)) {
                tp = list_entry(probe_list.next, struct trace_probe, list);
-               unregister_trace_probe(tp);
+               ret = unregister_trace_probe(tp);
+               if (ret)
+                       goto end;
                free_trace_probe(tp);
        }
 
@@ -1312,11 +1330,15 @@ static int register_probe_event(struct trace_probe *tp)
        return ret;
 }
 
-static void unregister_probe_event(struct trace_probe *tp)
+static int unregister_probe_event(struct trace_probe *tp)
 {
+       int ret;
+
        /* tp->event is unregistered in trace_remove_event_call() */
-       trace_remove_event_call(&tp->call);
-       kfree(tp->call.print_fmt);
+       ret = trace_remove_event_call(&tp->call);
+       if (!ret)
+               kfree(tp->call.print_fmt);
+       return ret;
 }
 
 /* Make a debugfs interface for controlling probe points */
index 8f2ac73c7a5fd9a6c8412b7b96e1cc0473651d62..322e16461072575e6d8439208891b5730bd41438 100644 (file)
@@ -306,6 +306,8 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id)
        struct syscall_metadata *sys_data;
        struct ring_buffer_event *event;
        struct ring_buffer *buffer;
+       unsigned long irq_flags;
+       int pc;
        int syscall_nr;
        int size;
 
@@ -321,9 +323,12 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id)
 
        size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args;
 
+       local_save_flags(irq_flags);
+       pc = preempt_count();
+
        buffer = tr->trace_buffer.buffer;
        event = trace_buffer_lock_reserve(buffer,
-                       sys_data->enter_event->event.type, size, 0, 0);
+                       sys_data->enter_event->event.type, size, irq_flags, pc);
        if (!event)
                return;
 
@@ -333,7 +338,8 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id)
 
        if (!filter_current_check_discard(buffer, sys_data->enter_event,
                                          entry, event))
-               trace_current_buffer_unlock_commit(buffer, event, 0, 0);
+               trace_current_buffer_unlock_commit(buffer, event,
+                                                  irq_flags, pc);
 }
 
 static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret)
@@ -343,6 +349,8 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret)
        struct syscall_metadata *sys_data;
        struct ring_buffer_event *event;
        struct ring_buffer *buffer;
+       unsigned long irq_flags;
+       int pc;
        int syscall_nr;
 
        syscall_nr = trace_get_syscall_nr(current, regs);
@@ -355,9 +363,13 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret)
        if (!sys_data)
                return;
 
+       local_save_flags(irq_flags);
+       pc = preempt_count();
+
        buffer = tr->trace_buffer.buffer;
        event = trace_buffer_lock_reserve(buffer,
-                       sys_data->exit_event->event.type, sizeof(*entry), 0, 0);
+                       sys_data->exit_event->event.type, sizeof(*entry),
+                       irq_flags, pc);
        if (!event)
                return;
 
@@ -367,7 +379,8 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret)
 
        if (!filter_current_check_discard(buffer, sys_data->exit_event,
                                          entry, event))
-               trace_current_buffer_unlock_commit(buffer, event, 0, 0);
+               trace_current_buffer_unlock_commit(buffer, event,
+                                                  irq_flags, pc);
 }
 
 static int reg_event_syscall_enter(struct ftrace_event_file *file,
index 32494fb0ee640eef4548ac380cd158eab7415083..6fd72b768522465174b98ea4c44f5b83a5e6dc30 100644 (file)
@@ -70,7 +70,7 @@ struct trace_uprobe {
        (sizeof(struct probe_arg) * (n)))
 
 static int register_uprobe_event(struct trace_uprobe *tu);
-static void unregister_uprobe_event(struct trace_uprobe *tu);
+static int unregister_uprobe_event(struct trace_uprobe *tu);
 
 static DEFINE_MUTEX(uprobe_lock);
 static LIST_HEAD(uprobe_list);
@@ -164,11 +164,17 @@ static struct trace_uprobe *find_probe_event(const char *event, const char *grou
 }
 
 /* Unregister a trace_uprobe and probe_event: call with locking uprobe_lock */
-static void unregister_trace_uprobe(struct trace_uprobe *tu)
+static int unregister_trace_uprobe(struct trace_uprobe *tu)
 {
+       int ret;
+
+       ret = unregister_uprobe_event(tu);
+       if (ret)
+               return ret;
+
        list_del(&tu->list);
-       unregister_uprobe_event(tu);
        free_trace_uprobe(tu);
+       return 0;
 }
 
 /* Register a trace_uprobe and probe_event */
@@ -181,9 +187,12 @@ static int register_trace_uprobe(struct trace_uprobe *tu)
 
        /* register as an event */
        old_tp = find_probe_event(tu->call.name, tu->call.class->system);
-       if (old_tp)
+       if (old_tp) {
                /* delete old event */
-               unregister_trace_uprobe(old_tp);
+               ret = unregister_trace_uprobe(old_tp);
+               if (ret)
+                       goto end;
+       }
 
        ret = register_uprobe_event(tu);
        if (ret) {
@@ -256,6 +265,8 @@ static int create_trace_uprobe(int argc, char **argv)
                group = UPROBE_EVENT_SYSTEM;
 
        if (is_delete) {
+               int ret;
+
                if (!event) {
                        pr_info("Delete command needs an event name.\n");
                        return -EINVAL;
@@ -269,9 +280,9 @@ static int create_trace_uprobe(int argc, char **argv)
                        return -ENOENT;
                }
                /* delete an event */
-               unregister_trace_uprobe(tu);
+               ret = unregister_trace_uprobe(tu);
                mutex_unlock(&uprobe_lock);
-               return 0;
+               return ret;
        }
 
        if (argc < 2) {
@@ -283,8 +294,10 @@ static int create_trace_uprobe(int argc, char **argv)
                return -EINVAL;
        }
        arg = strchr(argv[1], ':');
-       if (!arg)
+       if (!arg) {
+               ret = -EINVAL;
                goto fail_address_parse;
+       }
 
        *arg++ = '\0';
        filename = argv[1];
@@ -406,16 +419,20 @@ fail_address_parse:
        return ret;
 }
 
-static void cleanup_all_probes(void)
+static int cleanup_all_probes(void)
 {
        struct trace_uprobe *tu;
+       int ret = 0;
 
        mutex_lock(&uprobe_lock);
        while (!list_empty(&uprobe_list)) {
                tu = list_entry(uprobe_list.next, struct trace_uprobe, list);
-               unregister_trace_uprobe(tu);
+               ret = unregister_trace_uprobe(tu);
+               if (ret)
+                       break;
        }
        mutex_unlock(&uprobe_lock);
+       return ret;
 }
 
 /* Probes listing interfaces */
@@ -460,8 +477,13 @@ static const struct seq_operations probes_seq_op = {
 
 static int probes_open(struct inode *inode, struct file *file)
 {
-       if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC))
-               cleanup_all_probes();
+       int ret;
+
+       if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
+               ret = cleanup_all_probes();
+               if (ret)
+                       return ret;
+       }
 
        return seq_open(file, &probes_seq_op);
 }
@@ -968,12 +990,17 @@ static int register_uprobe_event(struct trace_uprobe *tu)
        return ret;
 }
 
-static void unregister_uprobe_event(struct trace_uprobe *tu)
+static int unregister_uprobe_event(struct trace_uprobe *tu)
 {
+       int ret;
+
        /* tu->event is unregistered in trace_remove_event_call() */
-       trace_remove_event_call(&tu->call);
+       ret = trace_remove_event_call(&tu->call);
+       if (ret)
+               return ret;
        kfree(tu->call.print_fmt);
        tu->call.print_fmt = NULL;
+       return 0;
 }
 
 /* Make a trace interface for controling probe points */
index d8c30db06c5b75456098fe2f1a26785e9a9110ee..9064b919a4066fe9fca676581479e9162de56717 100644 (file)
@@ -62,6 +62,9 @@ int create_user_ns(struct cred *new)
        kgid_t group = new->egid;
        int ret;
 
+       if (parent_ns->level > 32)
+               return -EUSERS;
+
        /*
         * Verify that we can not violate the policy of which files
         * may be accessed that is specified by the root directory,
@@ -92,6 +95,7 @@ int create_user_ns(struct cred *new)
        atomic_set(&ns->count, 1);
        /* Leave the new->user_ns reference with the new user namespace. */
        ns->parent = parent_ns;
+       ns->level = parent_ns->level + 1;
        ns->owner = owner;
        ns->group = group;
 
@@ -105,16 +109,21 @@ int create_user_ns(struct cred *new)
 int unshare_userns(unsigned long unshare_flags, struct cred **new_cred)
 {
        struct cred *cred;
+       int err = -ENOMEM;
 
        if (!(unshare_flags & CLONE_NEWUSER))
                return 0;
 
        cred = prepare_creds();
-       if (!cred)
-               return -ENOMEM;
+       if (cred) {
+               err = create_user_ns(cred);
+               if (err)
+                       put_cred(cred);
+               else
+                       *new_cred = cred;
+       }
 
-       *new_cred = cred;
-       return create_user_ns(cred);
+       return err;
 }
 
 void free_user_ns(struct user_namespace *ns)
index ee8e29a2320c7c76d67df8f4816af52cd9da5f68..e52d002d389319564fc59df7b7ff5ec6f80ece9a 100644 (file)
@@ -2188,6 +2188,15 @@ __acquires(&pool->lock)
                dump_stack();
        }
 
+       /*
+        * The following prevents a kworker from hogging CPU on !PREEMPT
+        * kernels, where a requeueing work item waiting for something to
+        * happen could deadlock with stop_machine as such work item could
+        * indefinitely requeue itself while all other CPUs are trapped in
+        * stop_machine.
+        */
+       cond_resched();
+
        spin_lock_irq(&pool->lock);
 
        /* clear cpu intensive status */
@@ -3398,6 +3407,12 @@ static void copy_workqueue_attrs(struct workqueue_attrs *to,
 {
        to->nice = from->nice;
        cpumask_copy(to->cpumask, from->cpumask);
+       /*
+        * Unlike hash and equality test, this function doesn't ignore
+        * ->no_numa as it is used for both pool and wq attrs.  Instead,
+        * get_unbound_pool() explicitly clears ->no_numa after copying.
+        */
+       to->no_numa = from->no_numa;
 }
 
 /* hash value of the content of @attr */
@@ -3565,6 +3580,12 @@ static struct worker_pool *get_unbound_pool(const struct workqueue_attrs *attrs)
        lockdep_set_subclass(&pool->lock, 1);   /* see put_pwq() */
        copy_workqueue_attrs(pool->attrs, attrs);
 
+       /*
+        * no_numa isn't a worker_pool attribute, always clear it.  See
+        * 'struct workqueue_attrs' comments for detail.
+        */
+       pool->attrs->no_numa = false;
+
        /* if cpumask is contained inside a NUMA node, we belong to that node */
        if (wq_numa_enabled) {
                for_each_node(node) {
index 566cf2bc08eaac44813dd9a1d1ac0d816a072237..74fdc5cf4adc44cc755e2dab5018a61df288e078 100644 (file)
@@ -1272,7 +1272,7 @@ config FAULT_INJECTION_STACKTRACE_FILTER
        depends on FAULT_INJECTION_DEBUG_FS && STACKTRACE_SUPPORT
        depends on !X86_64
        select STACKTRACE
-       select FRAME_POINTER if !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND
+       select FRAME_POINTER if !MIPS && !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND
        help
          Provide stacktrace filter for fault-injection capabilities
 
index 362c329b83fe7441b4d2119c1e164a54c58fc860..b92d0ce428b1dda83fc8ea30311506c7a1dfdcd7 100644 (file)
@@ -2286,6 +2286,8 @@ static void collapse_huge_page(struct mm_struct *mm,
                goto out;
 
        vma = find_vma(mm, address);
+       if (!vma)
+               goto out;
        hstart = (vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK;
        hend = vma->vm_end & HPAGE_PMD_MASK;
        if (address < hstart || address + HPAGE_PMD_SIZE > hend)
index a7482d1d213142edad7327b5d5e8f64541ac403f..de608bbc8389b553042cfe74c8065a5181166091 100644 (file)
@@ -690,6 +690,23 @@ int PageHuge(struct page *page)
 }
 EXPORT_SYMBOL_GPL(PageHuge);
 
+pgoff_t __basepage_index(struct page *page)
+{
+       struct page *page_head = compound_head(page);
+       pgoff_t index = page_index(page_head);
+       unsigned long compound_idx;
+
+       if (!PageHuge(page_head))
+               return page_index(page);
+
+       if (compound_order(page_head) >= MAX_ORDER)
+               compound_idx = page_to_pfn(page) - page_to_pfn(page_head);
+       else
+               compound_idx = page - page_head;
+
+       return (index << compound_order(page_head)) + compound_idx;
+}
+
 static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid)
 {
        struct page *page;
@@ -2484,7 +2501,7 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
 
        mm = vma->vm_mm;
 
-       tlb_gather_mmu(&tlb, mm, 0);
+       tlb_gather_mmu(&tlb, mm, start, end);
        __unmap_hugepage_range(&tlb, vma, start, end, ref_page);
        tlb_finish_mmu(&tlb, start, end);
 }
index 194721839cf5d303a0de2b4df611b700db895043..905ce72c8c4e596b5234dc1cb2277dd94ce3a60a 100644 (file)
@@ -3186,11 +3186,11 @@ int memcg_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s,
        if (!s->memcg_params)
                return -ENOMEM;
 
-       INIT_WORK(&s->memcg_params->destroy,
-                       kmem_cache_destroy_work_func);
        if (memcg) {
                s->memcg_params->memcg = memcg;
                s->memcg_params->root_cache = root_cache;
+               INIT_WORK(&s->memcg_params->destroy,
+                               kmem_cache_destroy_work_func);
        } else
                s->memcg_params->is_root_cache = true;
 
@@ -5584,7 +5584,13 @@ static int compare_thresholds(const void *a, const void *b)
        const struct mem_cgroup_threshold *_a = a;
        const struct mem_cgroup_threshold *_b = b;
 
-       return _a->threshold - _b->threshold;
+       if (_a->threshold > _b->threshold)
+               return 1;
+
+       if (_a->threshold < _b->threshold)
+               return -1;
+
+       return 0;
 }
 
 static int mem_cgroup_oom_notify_cb(struct mem_cgroup *memcg)
@@ -6296,16 +6302,6 @@ mem_cgroup_css_online(struct cgroup *cont)
 
        error = memcg_init_kmem(memcg, &mem_cgroup_subsys);
        mutex_unlock(&memcg_create_mutex);
-       if (error) {
-               /*
-                * We call put now because our (and parent's) refcnts
-                * are already in place. mem_cgroup_put() will internally
-                * call __mem_cgroup_free, so return directly
-                */
-               mem_cgroup_put(memcg);
-               if (parent->use_hierarchy)
-                       mem_cgroup_put(parent);
-       }
        return error;
 }
 
index 61a262b08e53efa2f69c1387e488bea6f87bb0f9..5a35443c01ad4845a9dc32b947e02fb65ea29200 100644 (file)
@@ -211,14 +211,15 @@ static int tlb_next_batch(struct mmu_gather *tlb)
  *     tear-down from @mm. The @fullmm argument is used when @mm is without
  *     users and we're going to destroy the full address space (exit/execve).
  */
-void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm)
+void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
 {
        tlb->mm = mm;
 
-       tlb->fullmm     = fullmm;
+       /* Is it from 0 to ~0? */
+       tlb->fullmm     = !(start | (end+1));
        tlb->need_flush_all = 0;
-       tlb->start      = -1UL;
-       tlb->end        = 0;
+       tlb->start      = start;
+       tlb->end        = end;
        tlb->need_flush = 0;
        tlb->local.next = NULL;
        tlb->local.nr   = 0;
@@ -258,8 +259,6 @@ void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long e
 {
        struct mmu_gather_batch *batch, *next;
 
-       tlb->start = start;
-       tlb->end   = end;
        tlb_flush_mmu(tlb);
 
        /* keep the page table cache within bounds */
@@ -1203,13 +1202,23 @@ again:
         * and page-free while holding it.
         */
        if (force_flush) {
+               unsigned long old_end;
+
                force_flush = 0;
 
-#ifdef HAVE_GENERIC_MMU_GATHER
-               tlb->start = addr;
-               tlb->end = end;
-#endif
+               /*
+                * Flush the TLB just for the previous segment,
+                * then update the range to be the remaining
+                * TLB range.
+                */
+               old_end = tlb->end;
+               tlb->end = addr;
+
                tlb_flush_mmu(tlb);
+
+               tlb->start = addr;
+               tlb->end = old_end;
+
                if (addr != end)
                        goto again;
        }
@@ -1396,7 +1405,7 @@ void zap_page_range(struct vm_area_struct *vma, unsigned long start,
        unsigned long end = start + size;
 
        lru_add_drain();
-       tlb_gather_mmu(&tlb, mm, 0);
+       tlb_gather_mmu(&tlb, mm, start, end);
        update_hiwater_rss(mm);
        mmu_notifier_invalidate_range_start(mm, start, end);
        for ( ; vma && vma->vm_start < end; vma = vma->vm_next)
@@ -1422,7 +1431,7 @@ static void zap_page_range_single(struct vm_area_struct *vma, unsigned long addr
        unsigned long end = address + size;
 
        lru_add_drain();
-       tlb_gather_mmu(&tlb, mm, 0);
+       tlb_gather_mmu(&tlb, mm, address, end);
        update_hiwater_rss(mm);
        mmu_notifier_invalidate_range_start(mm, address, end);
        unmap_single_vma(&tlb, vma, address, end, details);
index 74310017296ee02317b79a2c28b25ef303fc7720..4baf12e534d19031d28ddc5eba5335f72de54099 100644 (file)
@@ -732,7 +732,10 @@ static int mbind_range(struct mm_struct *mm, unsigned long start,
                if (prev) {
                        vma = prev;
                        next = vma->vm_next;
-                       continue;
+                       if (mpol_equal(vma_policy(vma), new_pol))
+                               continue;
+                       /* vma_merge() joined vma && vma->next, case 8 */
+                       goto replace;
                }
                if (vma->vm_start != vmstart) {
                        err = split_vma(vma->vm_mm, vma, vmstart, 1);
@@ -744,6 +747,7 @@ static int mbind_range(struct mm_struct *mm, unsigned long start,
                        if (err)
                                goto out;
                }
+ replace:
                err = vma_replace_policy(vma, new_pol);
                if (err)
                        goto out;
index f681e1842fadc1ccd8d7188a7ca1688c73548111..8d25fdc653be6d144869a52f0fe9ede2e00f5a58 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -865,7 +865,7 @@ again:                      remove_next = 1 + (end > next->vm_end);
                if (next->anon_vma)
                        anon_vma_merge(vma, next);
                mm->map_count--;
-               vma_set_policy(vma, vma_policy(next));
+               mpol_put(vma_policy(next));
                kmem_cache_free(vm_area_cachep, next);
                /*
                 * In mprotect's case 6 (see comments on vma_merge),
@@ -2356,7 +2356,7 @@ static void unmap_region(struct mm_struct *mm,
        struct mmu_gather tlb;
 
        lru_add_drain();
-       tlb_gather_mmu(&tlb, mm, 0);
+       tlb_gather_mmu(&tlb, mm, start, end);
        update_hiwater_rss(mm);
        unmap_vmas(&tlb, vma, start, end);
        free_pgtables(&tlb, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS,
@@ -2735,7 +2735,7 @@ void exit_mmap(struct mm_struct *mm)
 
        lru_add_drain();
        flush_cache_mm(mm);
-       tlb_gather_mmu(&tlb, mm, 1);
+       tlb_gather_mmu(&tlb, mm, 0, -1);
        /* update_hiwater_rss(mm) here? but nobody should be looking */
        /* Use -1 here to ensure all VMAs in the mm are unmapped */
        unmap_vmas(&tlb, vma, 0, -1);
index c3edb624fccf30c303ccff94cf139e090b416d7e..2ee0fd313f036e8bab7af2b4d6e0ae6a8ce93378 100644 (file)
@@ -6142,6 +6142,10 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
                list_del(&page->lru);
                rmv_page_order(page);
                zone->free_area[order].nr_free--;
+#ifdef CONFIG_HIGHMEM
+               if (PageHighMem(page))
+                       totalhigh_pages -= 1 << order;
+#endif
                for (i = 0; i < (1 << order); i++)
                        SetPageReserved((page+i));
                pfn += (1 << order);
index 8ccd296c6d9c7586fca85fc89bfd9f7a4023e220..bd88411595b9ba1df48332a7e89d64847cd7de6e 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -565,7 +565,7 @@ static void init_node_lock_keys(int q)
        if (slab_state < UP)
                return;
 
-       for (i = 1; i < PAGE_SHIFT + MAX_ORDER; i++) {
+       for (i = 1; i <= KMALLOC_SHIFT_HIGH; i++) {
                struct kmem_cache_node *n;
                struct kmem_cache *cache = kmalloc_caches[i];
 
index f96b49e4704efb1d362ef10c6eacef81afb9e6a0..4d6d836247dd95c3eb5e4d3e39295a80eb000a81 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -162,6 +162,8 @@ static inline const char *cache_name(struct kmem_cache *s)
 
 static inline struct kmem_cache *cache_from_memcg(struct kmem_cache *s, int idx)
 {
+       if (!s->memcg_params)
+               return NULL;
        return s->memcg_params->memcg_caches[idx];
 }
 
index 8a15eaadc4bd655c9969b0b19197a424d79aaa36..4a78c4de9f200831c75e5c87bad683bbf669bbfb 100644 (file)
@@ -9,7 +9,7 @@ bool vlan_do_receive(struct sk_buff **skbp)
 {
        struct sk_buff *skb = *skbp;
        __be16 vlan_proto = skb->vlan_proto;
-       u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK;
+       u16 vlan_id = vlan_tx_tag_get_id(skb);
        struct net_device *vlan_dev;
        struct vlan_pcpu_stats *rx_stats;
 
index 3a8c8fd63c88e2c204a8f1ac3b6dc4eb3f15cc63..1cd3d2a406f5a268113d0d802f03578f2a3cbe20 100644 (file)
@@ -73,6 +73,8 @@ vlan_dev_get_egress_qos_mask(struct net_device *dev, struct sk_buff *skb)
 {
        struct vlan_priority_tci_mapping *mp;
 
+       smp_rmb(); /* coupled with smp_wmb() in vlan_dev_set_egress_priority() */
+
        mp = vlan_dev_priv(dev)->egress_priority_map[(skb->priority & 0xF)];
        while (mp) {
                if (mp->priority == skb->priority) {
@@ -249,6 +251,11 @@ int vlan_dev_set_egress_priority(const struct net_device *dev,
        np->next = mp;
        np->priority = skb_prio;
        np->vlan_qos = vlan_qos;
+       /* Before inserting this element in hash table, make sure all its fields
+        * are committed to memory.
+        * coupled with smp_rmb() in vlan_dev_get_egress_qos_mask()
+        */
+       smp_wmb();
        vlan->egress_priority_map[skb_prio & 0xF] = np;
        if (vlan_qos)
                vlan->nr_egress_mappings++;
index de8df957867def380831cc9a3589386f82a78aae..2ee3879161b1769f456501044a08c8ebfda420a0 100644 (file)
  */
 void p9_release_pages(struct page **pages, int nr_pages)
 {
-       int i = 0;
-       while (pages[i] && nr_pages--) {
-               put_page(pages[i]);
-               i++;
-       }
+       int i;
+
+       for (i = 0; i < nr_pages; i++)
+               if (pages[i])
+                       put_page(pages[i]);
 }
 EXPORT_SYMBOL(p9_release_pages);
 
index ebfa4443c69b3cd62b1bcbf94190a579bfb0115b..84dd783abe5cd56ebc6c872f855f74c420c2328e 100644 (file)
@@ -161,7 +161,7 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
        if (!pv)
                return;
 
-       for_each_set_bit_from(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+       for_each_set_bit_from(vid, pv->vlan_bitmap, VLAN_N_VID) {
                f = __br_fdb_get(br, br->dev->dev_addr, vid);
                if (f && f->is_local && !f->dst)
                        fdb_delete(br, f);
@@ -725,7 +725,7 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                /* VID was specified, so use it. */
                err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
        } else {
-               if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
+               if (!pv || bitmap_empty(pv->vlan_bitmap, VLAN_N_VID)) {
                        err = __br_fdb_add(ndm, p, addr, nlh_flags, 0);
                        goto out;
                }
@@ -734,7 +734,7 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                 * specify a VLAN.  To be nice, add/update entry for every
                 * vlan on this port.
                 */
-               for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+               for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
                        err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
                        if (err)
                                goto out;
@@ -812,7 +812,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
 
                err = __br_fdb_delete(p, addr, vid);
        } else {
-               if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
+               if (!pv || bitmap_empty(pv->vlan_bitmap, VLAN_N_VID)) {
                        err = __br_fdb_delete(p, addr, 0);
                        goto out;
                }
@@ -822,7 +822,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
                 * vlan on this port.
                 */
                err = -ENOENT;
-               for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+               for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
                        err &= __br_fdb_delete(p, addr, vid);
                }
        }
index d6448e35e02712682953d3d617aeac3b5f40737e..d82058f6fc791e8cf19dd7d3fe6c22964a7ac2d3 100644 (file)
@@ -1185,7 +1185,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
                max_delay = msecs_to_jiffies(ntohs(mld->mld_maxdelay));
                if (max_delay)
                        group = &mld->mld_mca;
-       } else if (skb->len >= sizeof(*mld2q)) {
+       } else {
                if (!pskb_may_pull(skb, sizeof(*mld2q))) {
                        err = -EINVAL;
                        goto out;
@@ -1193,7 +1193,8 @@ static int br_ip6_multicast_query(struct net_bridge *br,
                mld2q = (struct mld2_query *)icmp6_hdr(skb);
                if (!mld2q->mld2q_nsrcs)
                        group = &mld2q->mld2q_mca;
-               max_delay = mld2q->mld2q_mrc ? MLDV2_MRC(ntohs(mld2q->mld2q_mrc)) : 1;
+
+               max_delay = max(msecs_to_jiffies(MLDV2_MRC(ntohs(mld2q->mld2q_mrc))), 1UL);
        }
 
        if (!group)
index 8e3abf564798a9044feb2c6e668fda46f30f2dae..f66a03453a8e7ee203c9a106f2bdc58afad13c67 100644 (file)
@@ -128,7 +128,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
                else
                        pv = br_get_vlan_info(br);
 
-               if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN))
+               if (!pv || bitmap_empty(pv->vlan_bitmap, VLAN_N_VID))
                        goto done;
 
                af = nla_nest_start(skb, IFLA_AF_SPEC);
@@ -136,7 +136,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
                        goto nla_put_failure;
 
                pvid = br_get_pvid(pv);
-               for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+               for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
                        vinfo.vid = vid;
                        vinfo.flags = 0;
                        if (vid == pvid)
index bd58b45f5f901fd4c6a3ad00abe068baeba8d898..9a9ffe7e4019741d75456e3b9afdba21c44785b3 100644 (file)
@@ -108,7 +108,7 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid)
 
        clear_bit(vid, v->vlan_bitmap);
        v->num_vlans--;
-       if (bitmap_empty(v->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
+       if (bitmap_empty(v->vlan_bitmap, VLAN_N_VID)) {
                if (v->port_idx)
                        rcu_assign_pointer(v->parent.port->vlan_info, NULL);
                else
@@ -122,7 +122,7 @@ static void __vlan_flush(struct net_port_vlans *v)
 {
        smp_wmb();
        v->pvid = 0;
-       bitmap_zero(v->vlan_bitmap, BR_VLAN_BITMAP_LEN);
+       bitmap_zero(v->vlan_bitmap, VLAN_N_VID);
        if (v->port_idx)
                rcu_assign_pointer(v->parent.port->vlan_info, NULL);
        else
index 925ca583c09c8eae2fbaebbd73603e9194132f97..8c93fa8d81bc45b2d4bf1e9e1fd1eb3b96e3de53 100644 (file)
@@ -39,6 +39,11 @@ static int should_authenticate(struct ceph_auth_client *ac)
        return xi->starting;
 }
 
+static int build_request(struct ceph_auth_client *ac, void *buf, void *end)
+{
+       return 0;
+}
+
 /*
  * the generic auth code decode the global_id, and we carry no actual
  * authenticate state, so nothing happens here.
@@ -106,6 +111,7 @@ static const struct ceph_auth_client_ops ceph_auth_none_ops = {
        .destroy = destroy,
        .is_authenticated = is_authenticated,
        .should_authenticate = should_authenticate,
+       .build_request = build_request,
        .handle_reply = handle_reply,
        .create_authorizer = ceph_auth_none_create_authorizer,
        .destroy_authorizer = ceph_auth_none_destroy_authorizer,
index 3a246a6cab473496e58275cbb367485acbbda4d8..46ec7672cccc972ccf7d9d6712c08d76e4444d98 100644 (file)
@@ -2130,6 +2130,8 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc,
                        dout("osdc_start_request failed map, "
                                " will retry %lld\n", req->r_tid);
                        rc = 0;
+               } else {
+                       __unregister_request(osdc, req);
                }
                goto out_unlock;
        }
index 603ddd92db1965e16fac61a420c4cdb5c8330bbb..dbd9a4792427455e0a2dfdd7d2249c4abcbbb798 100644 (file)
@@ -1129,7 +1129,7 @@ static int *calc_pg_raw(struct ceph_osdmap *osdmap, struct ceph_pg pgid,
 
        /* pg_temp? */
        pgid.seed = ceph_stable_mod(pgid.seed, pool->pg_num,
-                                   pool->pgp_num_mask);
+                                   pool->pg_num_mask);
        pg = __lookup_pg_mapping(&osdmap->pg_temp, pgid);
        if (pg) {
                *num = pg->len;
index faebb398fb46ad93a1d09b051f8662bcf203eaab..7ddbb31b10d3f47c164a18fc3e9f22ea9947b9ed 100644 (file)
@@ -3513,8 +3513,15 @@ ncls:
                }
        }
 
-       if (vlan_tx_nonzero_tag_present(skb))
-               skb->pkt_type = PACKET_OTHERHOST;
+       if (unlikely(vlan_tx_tag_present(skb))) {
+               if (vlan_tx_tag_get_id(skb))
+                       skb->pkt_type = PACKET_OTHERHOST;
+               /* Note: we might in the future use prio bits
+                * and set skb->priority like in vlan_do_receive()
+                * For the time being, just ignore Priority Code Point
+                */
+               skb->vlan_tci = 0;
+       }
 
        /* deliver only exact match when indicated */
        null_or_dev = deliver_exact ? skb->dev : NULL;
index 00ee068efc1c2374bc0195d9458eca00392359c6..c99cc371bbd78a63a25c04fe2735aa27259336d3 100644 (file)
@@ -345,14 +345,9 @@ u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
                if (new_index < 0)
                        new_index = skb_tx_hash(dev, skb);
 
-               if (queue_index != new_index && sk) {
-                       struct dst_entry *dst =
-                                   rcu_dereference_check(sk->sk_dst_cache, 1);
-
-                       if (dst && skb_dst(skb) == dst)
-                               sk_tx_queue_set(sk, queue_index);
-
-               }
+               if (queue_index != new_index && sk &&
+                   rcu_access_pointer(sk->sk_dst_cache))
+                       sk_tx_queue_set(sk, queue_index);
 
                queue_index = new_index;
        }
index 5c56b217b999d114ea7954a9e6060a77d906ceff..0034b611fa5e7497cdca5a77eb60b0807e4b4104 100644 (file)
@@ -231,7 +231,7 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
                                   we must kill timers etc. and move
                                   it to safe state.
                                 */
-                               skb_queue_purge(&n->arp_queue);
+                               __skb_queue_purge(&n->arp_queue);
                                n->arp_queue_len_bytes = 0;
                                n->output = neigh_blackhole;
                                if (n->nud_state & NUD_VALID)
@@ -286,7 +286,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device
        if (!n)
                goto out_entries;
 
-       skb_queue_head_init(&n->arp_queue);
+       __skb_queue_head_init(&n->arp_queue);
        rwlock_init(&n->lock);
        seqlock_init(&n->ha_lock);
        n->updated        = n->used = now;
@@ -708,7 +708,9 @@ void neigh_destroy(struct neighbour *neigh)
        if (neigh_del_timer(neigh))
                pr_warn("Impossible event\n");
 
-       skb_queue_purge(&neigh->arp_queue);
+       write_lock_bh(&neigh->lock);
+       __skb_queue_purge(&neigh->arp_queue);
+       write_unlock_bh(&neigh->lock);
        neigh->arp_queue_len_bytes = 0;
 
        if (dev->netdev_ops->ndo_neigh_destroy)
@@ -858,7 +860,7 @@ static void neigh_invalidate(struct neighbour *neigh)
                neigh->ops->error_report(neigh, skb);
                write_lock(&neigh->lock);
        }
-       skb_queue_purge(&neigh->arp_queue);
+       __skb_queue_purge(&neigh->arp_queue);
        neigh->arp_queue_len_bytes = 0;
 }
 
@@ -1210,7 +1212,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
 
                        write_lock_bh(&neigh->lock);
                }
-               skb_queue_purge(&neigh->arp_queue);
+               __skb_queue_purge(&neigh->arp_queue);
                neigh->arp_queue_len_bytes = 0;
        }
 out:
@@ -1443,16 +1445,18 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
                atomic_set(&p->refcnt, 1);
                p->reachable_time =
                                neigh_rand_reach_time(p->base_reachable_time);
+               dev_hold(dev);
+               p->dev = dev;
+               write_pnet(&p->net, hold_net(net));
+               p->sysctl_table = NULL;
 
                if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
+                       release_net(net);
+                       dev_put(dev);
                        kfree(p);
                        return NULL;
                }
 
-               dev_hold(dev);
-               p->dev = dev;
-               write_pnet(&p->net, hold_net(net));
-               p->sysctl_table = NULL;
                write_lock_bh(&tbl->lock);
                p->next         = tbl->parms.next;
                tbl->parms.next = p;
index a08bd2b7fe3f06901d6c75e82df5e51e1aa2234f..fd01eca52a13b956fb764cdcbf11bc95c6b57b22 100644 (file)
@@ -2142,7 +2142,7 @@ int ndo_dflt_fdb_del(struct ndmsg *ndm,
        /* If aging addresses are supported device will need to
         * implement its own handler for this.
         */
-       if (ndm->ndm_state & NUD_PERMANENT) {
+       if (!(ndm->ndm_state & NUD_PERMANENT)) {
                pr_info("%s: FDB only supports static addresses\n", dev->name);
                return -EINVAL;
        }
@@ -2374,7 +2374,7 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
        struct nlattr *extfilt;
        u32 filter_mask = 0;
 
-       extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct rtgenmsg),
+       extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg),
                                  IFLA_EXT_MASK);
        if (extfilt)
                filter_mask = nla_get_u32(extfilt);
index 03795d0147f2995e09495c98dcf3c94cb3d5511f..b4da80b1cc07d28eafec50a6185d6d2a2ece61af 100644 (file)
@@ -54,7 +54,7 @@ static __inline__ int scm_check_creds(struct ucred *creds)
                return -EINVAL;
 
        if ((creds->pid == task_tgid_vnr(current) ||
-            ns_capable(current->nsproxy->pid_ns->user_ns, CAP_SYS_ADMIN)) &&
+            ns_capable(task_active_pid_ns(current)->user_ns, CAP_SYS_ADMIN)) &&
            ((uid_eq(uid, cred->uid)   || uid_eq(uid, cred->euid) ||
              uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) &&
            ((gid_eq(gid, cred->gid)   || gid_eq(gid, cred->egid) ||
index cfdb46ab3a7f866dd77957abc2f202d673c99bd5..2ff093b7c45e794de0fd96ffbbe35f0d927bf66b 100644 (file)
@@ -20,7 +20,9 @@
 #include <net/sock.h>
 #include <net/net_ratelimit.h>
 
+static int zero = 0;
 static int one = 1;
+static int ushort_max = USHRT_MAX;
 
 #ifdef CONFIG_RPS
 static int rps_sock_flow_sysctl(ctl_table *table, int write,
@@ -204,7 +206,9 @@ static struct ctl_table netns_core_table[] = {
                .data           = &init_net.core.sysctl_somaxconn,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec
+               .extra1         = &zero,
+               .extra2         = &ushort_max,
+               .proc_handler   = proc_dointvec_minmax
        },
        { }
 };
index dfc39d4d48b7471fc83035746026fa14d1dcf497..9e38217c393168768200745511cf99c9e6fd2032 100644 (file)
@@ -771,7 +771,7 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh,
                ci = nla_data(tb[IFA_CACHEINFO]);
                if (!ci->ifa_valid || ci->ifa_prefered > ci->ifa_valid) {
                        err = -EINVAL;
-                       goto errout;
+                       goto errout_free;
                }
                *pvalid_lft = ci->ifa_valid;
                *pprefered_lft = ci->ifa_prefered;
@@ -779,6 +779,8 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh,
 
        return ifa;
 
+errout_free:
+       inet_free_ifa(ifa);
 errout:
        return ERR_PTR(err);
 }
index 49616fed9340265b203c7b1fbf10390f92c38020..6e8a13da6cbd68c8f7894a3b458f1e5f1b683eb5 100644 (file)
@@ -71,7 +71,6 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/slab.h>
-#include <linux/prefetch.h>
 #include <linux/export.h>
 #include <net/net_namespace.h>
 #include <net/ip.h>
@@ -1761,10 +1760,8 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct rt_trie_node *c)
                        if (!c)
                                continue;
 
-                       if (IS_LEAF(c)) {
-                               prefetch(rcu_dereference_rtnl(p->child[idx]));
+                       if (IS_LEAF(c))
                                return (struct leaf *) c;
-                       }
 
                        /* Rescan start scanning in new node */
                        p = (struct tnode *) c;
index 2a83591492dd6f3e8b7470c3e9b897dad7625a49..c52fee0976dab2677222cdbed8158106f43c46f2 100644 (file)
@@ -503,10 +503,11 @@ static int ipgre_tunnel_ioctl(struct net_device *dev,
 
        if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
                return -EFAULT;
-       if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
-           p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) ||
-           ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING))) {
-               return -EINVAL;
+       if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
+               if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
+                   p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) ||
+                   ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)))
+                       return -EINVAL;
        }
        p.i_flags = gre_flags_to_tnl_flags(p.i_flags);
        p.o_flags = gre_flags_to_tnl_flags(p.o_flags);
@@ -571,7 +572,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
        if (daddr)
                memcpy(&iph->daddr, daddr, 4);
        if (iph->daddr)
-               return t->hlen;
+               return t->hlen + sizeof(*iph);
 
        return -(t->hlen + sizeof(*iph));
 }
index 3da817b89e9bf5376a3603028fb548dac2d58715..15e3e683adece394b02347eeed1d05afe5a62d01 100644 (file)
@@ -190,10 +190,7 @@ static int ip_local_deliver_finish(struct sk_buff *skb)
 {
        struct net *net = dev_net(skb->dev);
 
-       __skb_pull(skb, ip_hdrlen(skb));
-
-       /* Point into the IP datagram, just past the header. */
-       skb_reset_transport_header(skb);
+       __skb_pull(skb, skb_network_header_len(skb));
 
        rcu_read_lock();
        {
@@ -437,6 +434,8 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
                goto drop;
        }
 
+       skb->transport_header = skb->network_header + iph->ihl*4;
+
        /* Remove any debris in the socket control block */
        memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
 
index 7fa8f08fa7ae08220bfdb3a9bd4ab7077a1c5a9e..b7a4c21c06ecddcd489b0ad51747fda11b2da960 100644 (file)
@@ -486,6 +486,53 @@ drop:
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_rcv);
 
+static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
+                           struct rtable *rt, __be16 df)
+{
+       struct ip_tunnel *tunnel = netdev_priv(dev);
+       int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len;
+       int mtu;
+
+       if (df)
+               mtu = dst_mtu(&rt->dst) - dev->hard_header_len
+                                       - sizeof(struct iphdr) - tunnel->hlen;
+       else
+               mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
+
+       if (skb_dst(skb))
+               skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
+
+       if (skb->protocol == htons(ETH_P_IP)) {
+               if (!skb_is_gso(skb) &&
+                   (df & htons(IP_DF)) && mtu < pkt_size) {
+                       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
+                       return -E2BIG;
+               }
+       }
+#if IS_ENABLED(CONFIG_IPV6)
+       else if (skb->protocol == htons(ETH_P_IPV6)) {
+               struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
+
+               if (rt6 && mtu < dst_mtu(skb_dst(skb)) &&
+                          mtu >= IPV6_MIN_MTU) {
+                       if ((tunnel->parms.iph.daddr &&
+                           !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
+                           rt6->rt6i_dst.plen == 128) {
+                               rt6->rt6i_flags |= RTF_MODIFIED;
+                               dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
+                       }
+               }
+
+               if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU &&
+                                       mtu < pkt_size) {
+                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+                       return -E2BIG;
+               }
+       }
+#endif
+       return 0;
+}
+
 void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
                    const struct iphdr *tnl_params)
 {
@@ -499,7 +546,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        struct net_device *tdev;        /* Device to other host */
        unsigned int max_headroom;      /* The extra header space needed */
        __be32 dst;
-       int mtu;
 
        inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
 
@@ -579,50 +625,11 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
                goto tx_error;
        }
 
-       df = tnl_params->frag_off;
 
-       if (df)
-               mtu = dst_mtu(&rt->dst) - dev->hard_header_len
-                                       - sizeof(struct iphdr);
-       else
-               mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
-
-       if (skb_dst(skb))
-               skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
-
-       if (skb->protocol == htons(ETH_P_IP)) {
-               df |= (inner_iph->frag_off&htons(IP_DF));
-
-               if (!skb_is_gso(skb) &&
-                   (inner_iph->frag_off&htons(IP_DF)) &&
-                    mtu < ntohs(inner_iph->tot_len)) {
-                       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
-                       ip_rt_put(rt);
-                       goto tx_error;
-               }
-       }
-#if IS_ENABLED(CONFIG_IPV6)
-       else if (skb->protocol == htons(ETH_P_IPV6)) {
-               struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
-
-               if (rt6 && mtu < dst_mtu(skb_dst(skb)) &&
-                   mtu >= IPV6_MIN_MTU) {
-                       if ((tunnel->parms.iph.daddr &&
-                           !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
-                           rt6->rt6i_dst.plen == 128) {
-                               rt6->rt6i_flags |= RTF_MODIFIED;
-                               dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
-                       }
-               }
-
-               if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU &&
-                   mtu < skb->len) {
-                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
-                       ip_rt_put(rt);
-                       goto tx_error;
-               }
+       if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off)) {
+               ip_rt_put(rt);
+               goto tx_error;
        }
-#endif
 
        if (tunnel->err_count > 0) {
                if (time_before(jiffies,
@@ -646,6 +653,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
                        ttl = ip4_dst_hoplimit(&rt->dst);
        }
 
+       df = tnl_params->frag_off;
+       if (skb->protocol == htons(ETH_P_IP))
+               df |= (inner_iph->frag_off&htons(IP_DF));
+
        max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct iphdr)
                                               + rt->dst.header_len;
        if (max_headroom > dev->needed_headroom) {
@@ -675,7 +686,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        iph->daddr      =       fl4.daddr;
        iph->saddr      =       fl4.saddr;
        iph->ttl        =       ttl;
-       tunnel_ip_select_ident(skb, inner_iph, &rt->dst);
+       __ip_select_ident(iph, &rt->dst, (skb_shinfo(skb)->gso_segs ?: 1) - 1);
 
        iptunnel_xmit(skb, dev);
        return;
index c118f6b576bbb50c6fa909bffa1f40930a7c2750..17cc0ffa8c0d0ea2a3732b76b63be1f85c896778 100644 (file)
@@ -606,17 +606,10 @@ static int __net_init vti_fb_tunnel_init(struct net_device *dev)
        struct iphdr *iph = &tunnel->parms.iph;
        struct vti_net *ipn = net_generic(dev_net(dev), vti_net_id);
 
-       tunnel->dev = dev;
-       strcpy(tunnel->parms.name, dev->name);
-
        iph->version            = 4;
        iph->protocol           = IPPROTO_IPIP;
        iph->ihl                = 5;
 
-       dev->tstats = alloc_percpu(struct pcpu_tstats);
-       if (!dev->tstats)
-               return -ENOMEM;
-
        dev_hold(dev);
        rcu_assign_pointer(ipn->tunnels_wc[0], tunnel);
        return 0;
index 77bfcce64fe568b3a162a9d36324061553275a5e..7cfc45624b6d080954562ec913f738082508312e 100644 (file)
@@ -240,11 +240,13 @@ ipip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
                return -EFAULT;
 
-       if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP ||
-                       p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
-               return -EINVAL;
-       if (p.i_key || p.o_key || p.i_flags || p.o_flags)
-               return -EINVAL;
+       if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
+               if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP ||
+                   p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
+                       return -EINVAL;
+       }
+
+       p.i_key = p.o_key = p.i_flags = p.o_flags = 0;
        if (p.iph.ttl)
                p.iph.frag_off |= htons(IP_DF);
 
index dd44e0ab600cafe76ac50f74aaff5c6d429ea534..61e60d67adca9d24729cd06d33b02f91552b3515 100644 (file)
@@ -571,7 +571,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
                           RT_SCOPE_UNIVERSE,
                           inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
-                          inet_sk_flowi_flags(sk) | FLOWI_FLAG_CAN_SLEEP,
+                          inet_sk_flowi_flags(sk) | FLOWI_FLAG_CAN_SLEEP |
+                           (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
                           daddr, saddr, 0, 0);
 
        if (!inet->hdrincl) {
index fa2f63fc453b936b1660b79146b67edf17ae687a..3f25e75ae692e909592bdfaf0ce0a60cd0ee5697 100644 (file)
@@ -36,6 +36,8 @@ static int tcp_adv_win_scale_min = -31;
 static int tcp_adv_win_scale_max = 31;
 static int ip_ttl_min = 1;
 static int ip_ttl_max = 255;
+static int tcp_syn_retries_min = 1;
+static int tcp_syn_retries_max = MAX_TCP_SYNCNT;
 static int ip_ping_group_range_min[] = { 0, 0 };
 static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX };
 
@@ -331,7 +333,9 @@ static struct ctl_table ipv4_table[] = {
                .data           = &sysctl_tcp_syn_retries,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &tcp_syn_retries_min,
+               .extra2         = &tcp_syn_retries_max
        },
        {
                .procname       = "tcp_synack_retries",
index ab450c099aa49a3d4b68ca531e7f5426a8eabaf1..2005561861ad0382b34bff9ab308d2f2c2a1e0c6 100644 (file)
@@ -1117,6 +1117,13 @@ new_segment:
                                if (!skb)
                                        goto wait_for_memory;
 
+                               /*
+                                * All packets are restored as if they have
+                                * already been sent.
+                                */
+                               if (tp->repair)
+                                       TCP_SKB_CB(skb)->when = tcp_time_stamp;
+
                                /*
                                 * Check whether we can use HW checksum.
                                 */
index a9077f441cb27b693d8ad1d710e4dba67aa93ebb..b6ae92a51f58607f7c32be2d0762a49380205012 100644 (file)
@@ -206,8 +206,8 @@ static u32 cubic_root(u64 a)
  */
 static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
 {
-       u64 offs;
-       u32 delta, t, bic_target, max_cnt;
+       u32 delta, bic_target, max_cnt;
+       u64 offs, t;
 
        ca->ack_cnt++;  /* count the number of ACKs */
 
@@ -250,9 +250,11 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
         * if the cwnd < 1 million packets !!!
         */
 
+       t = (s32)(tcp_time_stamp - ca->epoch_start);
+       t += msecs_to_jiffies(ca->delay_min >> 3);
        /* change the unit from HZ to bictcp_HZ */
-       t = ((tcp_time_stamp + msecs_to_jiffies(ca->delay_min>>3)
-             - ca->epoch_start) << BICTCP_HZ) / HZ;
+       t <<= BICTCP_HZ;
+       do_div(t, HZ);
 
        if (t < ca->bic_K)              /* t - K */
                offs = ca->bic_K - t;
@@ -414,7 +416,7 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)
                return;
 
        /* Discard delay samples right after fast recovery */
-       if ((s32)(tcp_time_stamp - ca->epoch_start) < HZ)
+       if (ca->epoch_start && (s32)(tcp_time_stamp - ca->epoch_start) < HZ)
                return;
 
        delay = (rtt_us << 3) / USEC_PER_MSEC;
index 9c6225780bd5aafdb175a762d45c704e82416582..4b75aad14b04a0c2dbf899d9d7993cf125002240 100644 (file)
@@ -3598,7 +3598,10 @@ static bool tcp_parse_aligned_timestamp(struct tcp_sock *tp, const struct tcphdr
                ++ptr;
                tp->rx_opt.rcv_tsval = ntohl(*ptr);
                ++ptr;
-               tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->tsoffset;
+               if (*ptr)
+                       tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->tsoffset;
+               else
+                       tp->rx_opt.rcv_tsecr = 0;
                return true;
        }
        return false;
@@ -3623,7 +3626,7 @@ static bool tcp_fast_parse_options(const struct sk_buff *skb,
        }
 
        tcp_parse_options(skb, &tp->rx_opt, 1, NULL);
-       if (tp->rx_opt.saw_tstamp)
+       if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
                tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 
        return true;
@@ -5376,7 +5379,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
        int saved_clamp = tp->rx_opt.mss_clamp;
 
        tcp_parse_options(skb, &tp->rx_opt, 0, &foc);
-       if (tp->rx_opt.saw_tstamp)
+       if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
                tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 
        if (th->ack) {
index ec335fabd5cc12daba8addf5de86adc90abbd561..0145ce7e609881704e78718c1383870856fce326 100644 (file)
@@ -2664,7 +2664,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
        int tcp_header_size;
        int mss;
 
-       skb = alloc_skb(MAX_TCP_HEADER + 15, sk_gfp_atomic(sk, GFP_ATOMIC));
+       skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC);
        if (unlikely(!skb)) {
                dst_release(dst);
                return NULL;
@@ -2808,6 +2808,8 @@ void tcp_connect_init(struct sock *sk)
 
        if (likely(!tp->repair))
                tp->rcv_nxt = 0;
+       else
+               tp->rcv_tstamp = tcp_time_stamp;
        tp->rcv_wup = tp->rcv_nxt;
        tp->copied_seq = tp->rcv_nxt;
 
index 0bf5d399a03c1c0eaedeedd4a6a9db4ee2af68e6..93b731d5322102daa74b7f59767aaafc414cf826 100644 (file)
@@ -799,7 +799,7 @@ send:
 /*
  * Push out all pending data as one UDP datagram. Socket is locked.
  */
-static int udp_push_pending_frames(struct sock *sk)
+int udp_push_pending_frames(struct sock *sk)
 {
        struct udp_sock  *up = udp_sk(sk);
        struct inet_sock *inet = inet_sk(sk);
@@ -818,6 +818,7 @@ out:
        up->pending = 0;
        return err;
 }
+EXPORT_SYMBOL(udp_push_pending_frames);
 
 int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                size_t len)
index 4ab4c38958c6857afd7cfe998fc8866a0da00382..d3057f9b04a1a63f22f9927feb28e6a59329759e 100644 (file)
@@ -1124,12 +1124,10 @@ retry:
        if (ifp->flags & IFA_F_OPTIMISTIC)
                addr_flags |= IFA_F_OPTIMISTIC;
 
-       ift = !max_addresses ||
-             ipv6_count_addresses(idev) < max_addresses ?
-               ipv6_add_addr(idev, &addr, tmp_plen,
-                             ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK,
-                             addr_flags) : NULL;
-       if (IS_ERR_OR_NULL(ift)) {
+       ift = ipv6_add_addr(idev, &addr, tmp_plen,
+                           ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK,
+                           addr_flags);
+       if (IS_ERR(ift)) {
                in6_ifa_put(ifp);
                in6_dev_put(idev);
                pr_info("%s: retry temporary address regeneration\n", __func__);
@@ -1448,6 +1446,23 @@ try_nextdev:
 }
 EXPORT_SYMBOL(ipv6_dev_get_saddr);
 
+int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
+                     unsigned char banned_flags)
+{
+       struct inet6_ifaddr *ifp;
+       int err = -EADDRNOTAVAIL;
+
+       list_for_each_entry(ifp, &idev->addr_list, if_list) {
+               if (ifp->scope == IFA_LINK &&
+                   !(ifp->flags & banned_flags)) {
+                       *addr = ifp->addr;
+                       err = 0;
+                       break;
+               }
+       }
+       return err;
+}
+
 int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
                    unsigned char banned_flags)
 {
@@ -1457,17 +1472,8 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
        rcu_read_lock();
        idev = __in6_dev_get(dev);
        if (idev) {
-               struct inet6_ifaddr *ifp;
-
                read_lock_bh(&idev->lock);
-               list_for_each_entry(ifp, &idev->addr_list, if_list) {
-                       if (ifp->scope == IFA_LINK &&
-                           !(ifp->flags & banned_flags)) {
-                               *addr = ifp->addr;
-                               err = 0;
-                               break;
-                       }
-               }
+               err = __ipv6_get_lladdr(idev, addr, banned_flags);
                read_unlock_bh(&idev->lock);
        }
        rcu_read_unlock();
index f083a583a05cfac719a1df3fd4dc0e58e30f431f..b30ad3741b46732ee2c38bc851fa759ac02ff698 100644 (file)
@@ -251,38 +251,36 @@ static struct ip6addrlbl_entry *ip6addrlbl_alloc(struct net *net,
 /* add a label */
 static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace)
 {
+       struct hlist_node *n;
+       struct ip6addrlbl_entry *last = NULL, *p = NULL;
        int ret = 0;
 
-       ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n",
-                       __func__,
-                       newp, replace);
+       ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", __func__, newp,
+                 replace);
 
-       if (hlist_empty(&ip6addrlbl_table.head)) {
-               hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head);
-       } else {
-               struct hlist_node *n;
-               struct ip6addrlbl_entry *p = NULL;
-               hlist_for_each_entry_safe(p, n,
-                                         &ip6addrlbl_table.head, list) {
-                       if (p->prefixlen == newp->prefixlen &&
-                           net_eq(ip6addrlbl_net(p), ip6addrlbl_net(newp)) &&
-                           p->ifindex == newp->ifindex &&
-                           ipv6_addr_equal(&p->prefix, &newp->prefix)) {
-                               if (!replace) {
-                                       ret = -EEXIST;
-                                       goto out;
-                               }
-                               hlist_replace_rcu(&p->list, &newp->list);
-                               ip6addrlbl_put(p);
-                               goto out;
-                       } else if ((p->prefixlen == newp->prefixlen && !p->ifindex) ||
-                                  (p->prefixlen < newp->prefixlen)) {
-                               hlist_add_before_rcu(&newp->list, &p->list);
+       hlist_for_each_entry_safe(p, n, &ip6addrlbl_table.head, list) {
+               if (p->prefixlen == newp->prefixlen &&
+                   net_eq(ip6addrlbl_net(p), ip6addrlbl_net(newp)) &&
+                   p->ifindex == newp->ifindex &&
+                   ipv6_addr_equal(&p->prefix, &newp->prefix)) {
+                       if (!replace) {
+                               ret = -EEXIST;
                                goto out;
                        }
+                       hlist_replace_rcu(&p->list, &newp->list);
+                       ip6addrlbl_put(p);
+                       goto out;
+               } else if ((p->prefixlen == newp->prefixlen && !p->ifindex) ||
+                          (p->prefixlen < newp->prefixlen)) {
+                       hlist_add_before_rcu(&newp->list, &p->list);
+                       goto out;
                }
-               hlist_add_after_rcu(&p->list, &newp->list);
+               last = p;
        }
+       if (last)
+               hlist_add_after_rcu(&last->list, &newp->list);
+       else
+               hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head);
 out:
        if (!ret)
                ip6addrlbl_table.seq++;
index b4ff0a42b8c70248faf1b7298c1bec2cc79368ee..70e704d4900732a4f20492ccdd5723abf18db11c 100644 (file)
@@ -931,6 +931,14 @@ static const struct icmp6_err {
                .err    = ECONNREFUSED,
                .fatal  = 1,
        },
+       {       /* POLICY_FAIL */
+               .err    = EACCES,
+               .fatal  = 1,
+       },
+       {       /* REJECT_ROUTE */
+               .err    = EACCES,
+               .fatal  = 1,
+       },
 };
 
 int icmpv6_err_convert(u8 type, u8 code, int *err)
@@ -942,7 +950,7 @@ int icmpv6_err_convert(u8 type, u8 code, int *err)
        switch (type) {
        case ICMPV6_DEST_UNREACH:
                fatal = 1;
-               if (code <= ICMPV6_PORT_UNREACH) {
+               if (code < ARRAY_SIZE(tab_unreach)) {
                        *err  = tab_unreach[code].err;
                        fatal = tab_unreach[code].fatal;
                }
index 192dd1a0e18810f01923b43ef5f4a75c5b5d8d35..2221ff6a308bceb6f66e447265db1d590fe3f9d4 100644 (file)
@@ -632,6 +632,12 @@ insert_above:
        return ln;
 }
 
+static inline bool rt6_qualify_for_ecmp(struct rt6_info *rt)
+{
+       return (rt->rt6i_flags & (RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC)) ==
+              RTF_GATEWAY;
+}
+
 /*
  *     Insert routing information in a node.
  */
@@ -646,6 +652,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
        int add = (!info->nlh ||
                   (info->nlh->nlmsg_flags & NLM_F_CREATE));
        int found = 0;
+       bool rt_can_ecmp = rt6_qualify_for_ecmp(rt);
 
        ins = &fn->leaf;
 
@@ -691,9 +698,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
                         * To avoid long list, we only had siblings if the
                         * route have a gateway.
                         */
-                       if (rt->rt6i_flags & RTF_GATEWAY &&
-                           !(rt->rt6i_flags & RTF_EXPIRES) &&
-                           !(iter->rt6i_flags & RTF_EXPIRES))
+                       if (rt_can_ecmp &&
+                           rt6_qualify_for_ecmp(iter))
                                rt->rt6i_nsiblings++;
                }
 
@@ -715,7 +721,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
                /* Find the first route that have the same metric */
                sibling = fn->leaf;
                while (sibling) {
-                       if (sibling->rt6i_metric == rt->rt6i_metric) {
+                       if (sibling->rt6i_metric == rt->rt6i_metric &&
+                           rt6_qualify_for_ecmp(sibling)) {
                                list_add_tail(&rt->rt6i_siblings,
                                              &sibling->rt6i_siblings);
                                break;
@@ -986,14 +993,22 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root,
 
                        if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) {
 #ifdef CONFIG_IPV6_SUBTREES
-                               if (fn->subtree)
-                                       fn = fib6_lookup_1(fn->subtree, args + 1);
+                               if (fn->subtree) {
+                                       struct fib6_node *sfn;
+                                       sfn = fib6_lookup_1(fn->subtree,
+                                                           args + 1);
+                                       if (!sfn)
+                                               goto backtrack;
+                                       fn = sfn;
+                               }
 #endif
-                               if (!fn || fn->fn_flags & RTN_RTINFO)
+                               if (fn->fn_flags & RTN_RTINFO)
                                        return fn;
                        }
                }
-
+#ifdef CONFIG_IPV6_SUBTREES
+backtrack:
+#endif
                if (fn->fn_flags & RTN_ROOT)
                        break;
 
index d5d20cde8d92808387e171fb25b2fa701a06f275..6e3ddf806ec20abcfd4952dfe97d2b521138e055 100644 (file)
@@ -1098,11 +1098,12 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src,
        return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL;
 }
 
-static void ip6_append_data_mtu(int *mtu,
+static void ip6_append_data_mtu(unsigned int *mtu,
                                int *maxfraglen,
                                unsigned int fragheaderlen,
                                struct sk_buff *skb,
-                               struct rt6_info *rt)
+                               struct rt6_info *rt,
+                               bool pmtuprobe)
 {
        if (!(rt->dst.flags & DST_XFRM_TUNNEL)) {
                if (skb == NULL) {
@@ -1114,7 +1115,9 @@ static void ip6_append_data_mtu(int *mtu,
                         * this fragment is not first, the headers
                         * space is regarded as data space.
                         */
-                       *mtu = dst_mtu(rt->dst.path);
+                       *mtu = min(*mtu, pmtuprobe ?
+                                  rt->dst.dev->mtu :
+                                  dst_mtu(rt->dst.path));
                }
                *maxfraglen = ((*mtu - fragheaderlen) & ~7)
                              + fragheaderlen - sizeof(struct frag_hdr);
@@ -1131,11 +1134,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct inet_cork *cork;
        struct sk_buff *skb, *skb_prev = NULL;
-       unsigned int maxfraglen, fragheaderlen;
+       unsigned int maxfraglen, fragheaderlen, mtu;
        int exthdrlen;
        int dst_exthdrlen;
        int hh_len;
-       int mtu;
        int copy;
        int err;
        int offset = 0;
@@ -1292,7 +1294,9 @@ alloc_new_skb:
                        /* update mtu and maxfraglen if necessary */
                        if (skb == NULL || skb_prev == NULL)
                                ip6_append_data_mtu(&mtu, &maxfraglen,
-                                                   fragheaderlen, skb, rt);
+                                                   fragheaderlen, skb, rt,
+                                                   np->pmtudisc ==
+                                                   IPV6_PMTUDISC_PROBE);
 
                        skb_prev = skb;
 
index 241fb8ad9fcf28e2982f32e23ff9b7403ceef24a..4b421249532f272e0a6a9e91488e462d0a6f54ab 100644 (file)
@@ -259,10 +259,12 @@ static void __net_exit ip6mr_rules_exit(struct net *net)
 {
        struct mr6_table *mrt, *next;
 
+       rtnl_lock();
        list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
                list_del(&mrt->list);
                ip6mr_free_table(mrt);
        }
+       rtnl_unlock();
        fib_rules_unregister(net->ipv6.mr6_rules_ops);
 }
 #else
@@ -289,7 +291,10 @@ static int __net_init ip6mr_rules_init(struct net *net)
 
 static void __net_exit ip6mr_rules_exit(struct net *net)
 {
+       rtnl_lock();
        ip6mr_free_table(net->ipv6.mrt6);
+       net->ipv6.mrt6 = NULL;
+       rtnl_unlock();
 }
 #endif
 
index bfa6cc36ef2ab33e6e2894e03bb07c50f56a5804..c3998c2bbc5a3f5fafe37476b21cbbcb18584807 100644 (file)
@@ -1343,8 +1343,9 @@ static void ip6_mc_hdr(struct sock *sk, struct sk_buff *skb,
        hdr->daddr = *daddr;
 }
 
-static struct sk_buff *mld_newpack(struct net_device *dev, int size)
+static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size)
 {
+       struct net_device *dev = idev->dev;
        struct net *net = dev_net(dev);
        struct sock *sk = net->ipv6.igmp_sk;
        struct sk_buff *skb;
@@ -1369,7 +1370,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
 
        skb_reserve(skb, hlen);
 
-       if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) {
+       if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) {
                /* <draft-ietf-magma-mld-source-05.txt>:
                 * use unspecified address as the source address
                 * when a valid link-local address is not available.
@@ -1465,7 +1466,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc,
        struct mld2_grec *pgr;
 
        if (!skb)
-               skb = mld_newpack(dev, dev->mtu);
+               skb = mld_newpack(pmc->idev, dev->mtu);
        if (!skb)
                return NULL;
        pgr = (struct mld2_grec *)skb_put(skb, sizeof(struct mld2_grec));
@@ -1485,7 +1486,8 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc,
 static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc,
        int type, int gdeleted, int sdeleted)
 {
-       struct net_device *dev = pmc->idev->dev;
+       struct inet6_dev *idev = pmc->idev;
+       struct net_device *dev = idev->dev;
        struct mld2_report *pmr;
        struct mld2_grec *pgr = NULL;
        struct ip6_sf_list *psf, *psf_next, *psf_prev, **psf_list;
@@ -1514,7 +1516,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc,
                    AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) {
                        if (skb)
                                mld_sendpack(skb);
-                       skb = mld_newpack(dev, dev->mtu);
+                       skb = mld_newpack(idev, dev->mtu);
                }
        }
        first = 1;
@@ -1541,7 +1543,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc,
                                pgr->grec_nsrcs = htons(scount);
                        if (skb)
                                mld_sendpack(skb);
-                       skb = mld_newpack(dev, dev->mtu);
+                       skb = mld_newpack(idev, dev->mtu);
                        first = 1;
                        scount = 0;
                }
@@ -1596,8 +1598,8 @@ static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc)
        struct sk_buff *skb = NULL;
        int type;
 
+       read_lock_bh(&idev->lock);
        if (!pmc) {
-               read_lock_bh(&idev->lock);
                for (pmc=idev->mc_list; pmc; pmc=pmc->next) {
                        if (pmc->mca_flags & MAF_NOREPORT)
                                continue;
@@ -1609,7 +1611,6 @@ static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc)
                        skb = add_grec(skb, pmc, type, 0, 0);
                        spin_unlock_bh(&pmc->mca_lock);
                }
-               read_unlock_bh(&idev->lock);
        } else {
                spin_lock_bh(&pmc->mca_lock);
                if (pmc->mca_sfcount[MCAST_EXCLUDE])
@@ -1619,6 +1620,7 @@ static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc)
                skb = add_grec(skb, pmc, type, 0, 0);
                spin_unlock_bh(&pmc->mca_lock);
        }
+       read_unlock_bh(&idev->lock);
        if (skb)
                mld_sendpack(skb);
 }
index ca4ffcc287f1ebbd3cdb5011660f385479d597d3..060a0449acaa960433f0fd561329b66bf0f31056 100644 (file)
@@ -372,14 +372,11 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
        int tlen = dev->needed_tailroom;
        struct sock *sk = dev_net(dev)->ipv6.ndisc_sk;
        struct sk_buff *skb;
-       int err;
 
-       skb = sock_alloc_send_skb(sk,
-                                 hlen + sizeof(struct ipv6hdr) + len + tlen,
-                                 1, &err);
+       skb = alloc_skb(hlen + sizeof(struct ipv6hdr) + len + tlen, GFP_ATOMIC);
        if (!skb) {
-               ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb, err=%d\n",
-                         __func__, err);
+               ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb\n",
+                         __func__);
                return NULL;
        }
 
@@ -389,6 +386,11 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
        skb_reserve(skb, hlen + sizeof(struct ipv6hdr));
        skb_reset_transport_header(skb);
 
+       /* Manually assign socket ownership as we avoid calling
+        * sock_alloc_send_pskb() to bypass wmem buffer limits
+        */
+       skb_set_owner_w(skb, sk);
+
        return skb;
 }
 
index 790d9f4b8b0b21c1d4dd4577ee6a472bd96fd729..1aeb473b2cc695d8d2b0a3696972ec9228455d14 100644 (file)
@@ -490,6 +490,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
        ipv6_hdr(head)->payload_len = htons(payload_len);
        ipv6_change_dsfield(ipv6_hdr(head), 0xff, ecn);
        IP6CB(head)->nhoff = nhoff;
+       IP6CB(head)->flags |= IP6SKB_FRAGMENTED;
 
        /* Yes, and fold redundant checksum back. 8) */
        if (head->ip_summed == CHECKSUM_COMPLETE)
@@ -524,6 +525,9 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
        struct net *net = dev_net(skb_dst(skb)->dev);
        int evicted;
 
+       if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED)
+               goto fail_hdr;
+
        IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS);
 
        /* Jumbo payload inhibits frag. header */
@@ -544,6 +548,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
                                 ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMOKS);
 
                IP6CB(skb)->nhoff = (u8 *)fhdr - skb_network_header(skb);
+               IP6CB(skb)->flags |= IP6SKB_FRAGMENTED;
                return 1;
        }
 
index ad0aa6b0b86ae02f80b6b2184588605a3d5d7a6c..bacce6c086447e6feba8211c15d65018b62a48e8 100644 (file)
 #include <linux/sysctl.h>
 #endif
 
+enum rt6_nud_state {
+       RT6_NUD_FAIL_HARD = -2,
+       RT6_NUD_FAIL_SOFT = -1,
+       RT6_NUD_SUCCEED = 1
+};
+
 static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
                                    const struct in6_addr *dest);
 static struct dst_entry        *ip6_dst_check(struct dst_entry *dst, u32 cookie);
@@ -527,26 +533,29 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif)
        return 0;
 }
 
-static inline bool rt6_check_neigh(struct rt6_info *rt)
+static inline enum rt6_nud_state rt6_check_neigh(struct rt6_info *rt)
 {
        struct neighbour *neigh;
-       bool ret = false;
+       enum rt6_nud_state ret = RT6_NUD_FAIL_HARD;
 
        if (rt->rt6i_flags & RTF_NONEXTHOP ||
            !(rt->rt6i_flags & RTF_GATEWAY))
-               return true;
+               return RT6_NUD_SUCCEED;
 
        rcu_read_lock_bh();
        neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway);
        if (neigh) {
                read_lock(&neigh->lock);
                if (neigh->nud_state & NUD_VALID)
-                       ret = true;
+                       ret = RT6_NUD_SUCCEED;
 #ifdef CONFIG_IPV6_ROUTER_PREF
                else if (!(neigh->nud_state & NUD_FAILED))
-                       ret = true;
+                       ret = RT6_NUD_SUCCEED;
 #endif
                read_unlock(&neigh->lock);
+       } else {
+               ret = IS_ENABLED(CONFIG_IPV6_ROUTER_PREF) ?
+                     RT6_NUD_SUCCEED : RT6_NUD_FAIL_SOFT;
        }
        rcu_read_unlock_bh();
 
@@ -560,43 +569,52 @@ static int rt6_score_route(struct rt6_info *rt, int oif,
 
        m = rt6_check_dev(rt, oif);
        if (!m && (strict & RT6_LOOKUP_F_IFACE))
-               return -1;
+               return RT6_NUD_FAIL_HARD;
 #ifdef CONFIG_IPV6_ROUTER_PREF
        m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
 #endif
-       if (!rt6_check_neigh(rt) && (strict & RT6_LOOKUP_F_REACHABLE))
-               return -1;
+       if (strict & RT6_LOOKUP_F_REACHABLE) {
+               int n = rt6_check_neigh(rt);
+               if (n < 0)
+                       return n;
+       }
        return m;
 }
 
 static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict,
-                                  int *mpri, struct rt6_info *match)
+                                  int *mpri, struct rt6_info *match,
+                                  bool *do_rr)
 {
        int m;
+       bool match_do_rr = false;
 
        if (rt6_check_expired(rt))
                goto out;
 
        m = rt6_score_route(rt, oif, strict);
-       if (m < 0)
+       if (m == RT6_NUD_FAIL_SOFT && !IS_ENABLED(CONFIG_IPV6_ROUTER_PREF)) {
+               match_do_rr = true;
+               m = 0; /* lowest valid score */
+       } else if (m < 0) {
                goto out;
+       }
+
+       if (strict & RT6_LOOKUP_F_REACHABLE)
+               rt6_probe(rt);
 
        if (m > *mpri) {
-               if (strict & RT6_LOOKUP_F_REACHABLE)
-                       rt6_probe(match);
+               *do_rr = match_do_rr;
                *mpri = m;
                match = rt;
-       } else if (strict & RT6_LOOKUP_F_REACHABLE) {
-               rt6_probe(rt);
        }
-
 out:
        return match;
 }
 
 static struct rt6_info *find_rr_leaf(struct fib6_node *fn,
                                     struct rt6_info *rr_head,
-                                    u32 metric, int oif, int strict)
+                                    u32 metric, int oif, int strict,
+                                    bool *do_rr)
 {
        struct rt6_info *rt, *match;
        int mpri = -1;
@@ -604,10 +622,10 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn,
        match = NULL;
        for (rt = rr_head; rt && rt->rt6i_metric == metric;
             rt = rt->dst.rt6_next)
-               match = find_match(rt, oif, strict, &mpri, match);
+               match = find_match(rt, oif, strict, &mpri, match, do_rr);
        for (rt = fn->leaf; rt && rt != rr_head && rt->rt6i_metric == metric;
             rt = rt->dst.rt6_next)
-               match = find_match(rt, oif, strict, &mpri, match);
+               match = find_match(rt, oif, strict, &mpri, match, do_rr);
 
        return match;
 }
@@ -616,15 +634,16 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict)
 {
        struct rt6_info *match, *rt0;
        struct net *net;
+       bool do_rr = false;
 
        rt0 = fn->rr_ptr;
        if (!rt0)
                fn->rr_ptr = rt0 = fn->leaf;
 
-       match = find_rr_leaf(fn, rt0, rt0->rt6i_metric, oif, strict);
+       match = find_rr_leaf(fn, rt0, rt0->rt6i_metric, oif, strict,
+                            &do_rr);
 
-       if (!match &&
-           (strict & RT6_LOOKUP_F_REACHABLE)) {
+       if (do_rr) {
                struct rt6_info *next = rt0->dst.rt6_next;
 
                /* no entries matched; do round-robin */
@@ -1074,10 +1093,13 @@ static void ip6_link_failure(struct sk_buff *skb)
 
        rt = (struct rt6_info *) skb_dst(skb);
        if (rt) {
-               if (rt->rt6i_flags & RTF_CACHE)
-                       rt6_update_expires(rt, 0);
-               else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT))
+               if (rt->rt6i_flags & RTF_CACHE) {
+                       dst_hold(&rt->dst);
+                       if (ip6_del_rt(rt))
+                               dst_free(&rt->dst);
+               } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) {
                        rt->rt6i_node->fn_sernum = -1;
+               }
        }
 }
 
index 335363478bbfa037e5a4ddc8c3020cc4eeae0a15..60df36d1539046d494bb7c94d7259a7fe317e221 100644 (file)
@@ -589,7 +589,7 @@ static int ipip6_rcv(struct sk_buff *skb)
                                tunnel->dev->stats.rx_errors++;
                                goto out;
                        }
-               } else {
+               } else if (!(tunnel->dev->flags&IFF_POINTOPOINT)) {
                        if (is_spoofed_6rd(tunnel, iph->saddr,
                                           &ipv6_hdr(skb)->saddr) ||
                            is_spoofed_6rd(tunnel, iph->daddr,
index 0a17ed9eaf390c4b84a6264c03697f60af9281a1..66c718854e5aa28543fe7352c6546e718b25e7fc 100644 (file)
@@ -1426,7 +1426,7 @@ ipv6_pktoptions:
                if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim)
                        np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit;
                if (np->rxopt.bits.rxtclass)
-                       np->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(skb));
+                       np->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(opt_skb));
                if (ipv6_opt_accepted(sk, opt_skb)) {
                        skb_set_owner_r(opt_skb, sk);
                        opt_skb = xchg(&np->pktoptions, opt_skb);
index 42923b14dfa618ce83ba969c126611fe2ad4a828..e7b28f9bb02bd79cb4eb1131cd6115bd369f873d 100644 (file)
@@ -955,11 +955,16 @@ static int udp_v6_push_pending_frames(struct sock *sk)
        struct udphdr *uh;
        struct udp_sock  *up = udp_sk(sk);
        struct inet_sock *inet = inet_sk(sk);
-       struct flowi6 *fl6 = &inet->cork.fl.u.ip6;
+       struct flowi6 *fl6;
        int err = 0;
        int is_udplite = IS_UDPLITE(sk);
        __wsum csum = 0;
 
+       if (up->pending == AF_INET)
+               return udp_push_pending_frames(sk);
+
+       fl6 = &inet->cork.fl.u.ip6;
+
        /* Grab the skbuff where UDP header space exists. */
        if ((skb = skb_peek(&sk->sk_write_queue)) == NULL)
                goto out;
index 9da862070dd84fe596f77582c82af6eec8ad660c..ab8bd2cabfa090a4fa50524e7a76064891e535d6 100644 (file)
@@ -2081,6 +2081,7 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, const struct xfrm_policy *
                        pol->sadb_x_policy_type = IPSEC_POLICY_NONE;
        }
        pol->sadb_x_policy_dir = dir+1;
+       pol->sadb_x_policy_reserved = 0;
        pol->sadb_x_policy_id = xp->index;
        pol->sadb_x_policy_priority = xp->priority;
 
@@ -3137,7 +3138,9 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
        pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
        pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
        pol->sadb_x_policy_dir = XFRM_POLICY_OUT + 1;
+       pol->sadb_x_policy_reserved = 0;
        pol->sadb_x_policy_id = xp->index;
+       pol->sadb_x_policy_priority = xp->priority;
 
        /* Set sadb_comb's. */
        if (x->id.proto == IPPROTO_AH)
@@ -3525,6 +3528,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
        pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
        pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
        pol->sadb_x_policy_dir = dir + 1;
+       pol->sadb_x_policy_reserved = 0;
        pol->sadb_x_policy_id = 0;
        pol->sadb_x_policy_priority = 0;
 
index 8dec6876dc508265084cc80314e69d6b9d25aa25..5ebee2ded9e9a8f40d2a282600b47f6cb088a910 100644 (file)
@@ -1793,7 +1793,8 @@ static const struct proto_ops pppol2tp_ops = {
 
 static const struct pppox_proto pppol2tp_proto = {
        .create         = pppol2tp_create,
-       .ioctl          = pppol2tp_ioctl
+       .ioctl          = pppol2tp_ioctl,
+       .owner          = THIS_MODULE,
 };
 
 #ifdef CONFIG_L2TP_V3
index 4fdb306e42e0c1724f7a843b6cc77239d6b065bb..ae36f8e11ae4f9d60d98c052ecb9fdc26be6c7a9 100644 (file)
@@ -652,6 +652,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
                        if (sta->sdata->dev != dev)
                                continue;
 
+                       sinfo.filled = 0;
+                       sta_set_sinfo(sta, &sinfo);
                        i = 0;
                        ADD_STA_STATS(sta);
                }
index 170f9a7fa3190afee4148bb4caf0c817a53b7991..3052672e37f74f16eca01fcc05eea73442584cc0 100644 (file)
@@ -1166,6 +1166,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
        clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
                                                BSS_CHANGED_IBSS);
+       ieee80211_vif_release_channel(sdata);
        synchronize_rcu();
        kfree(presp);
 
index 98d20c0f6fed8829c1881e16b274c2bf97c589c4..514e90f470bf654abf6f6279cf8dbc16284e0ef9 100644 (file)
@@ -1717,6 +1717,15 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
 
        ASSERT_RTNL();
 
+       /*
+        * Close all AP_VLAN interfaces first, as otherwise they
+        * might be closed while the AP interface they belong to
+        * is closed, causing unregister_netdevice_many() to crash.
+        */
+       list_for_each_entry(sdata, &local->interfaces, list)
+               if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+                       dev_close(sdata->dev);
+
        /*
         * Close all AP_VLAN interfaces first, as otherwise they
         * might be closed while the AP interface they belong to
index 741448b308257c3a6f01c3d09ca36d7ddaa31ca3..5b4328dcbe4ecb443ae26f31b186bc389c51dd0e 100644 (file)
 #include "led.h"
 
 #define IEEE80211_AUTH_TIMEOUT         (HZ / 5)
+#define IEEE80211_AUTH_TIMEOUT_LONG    (HZ / 2)
 #define IEEE80211_AUTH_TIMEOUT_SHORT   (HZ / 10)
 #define IEEE80211_AUTH_MAX_TRIES       3
 #define IEEE80211_AUTH_WAIT_ASSOC      (HZ * 5)
 #define IEEE80211_ASSOC_TIMEOUT                (HZ / 5)
+#define IEEE80211_ASSOC_TIMEOUT_LONG   (HZ / 2)
 #define IEEE80211_ASSOC_TIMEOUT_SHORT  (HZ / 10)
 #define IEEE80211_ASSOC_MAX_TRIES      3
 
@@ -237,8 +239,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
                             struct ieee80211_channel *channel,
                             const struct ieee80211_ht_operation *ht_oper,
                             const struct ieee80211_vht_operation *vht_oper,
-                            struct cfg80211_chan_def *chandef, bool verbose)
+                            struct cfg80211_chan_def *chandef, bool tracking)
 {
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct cfg80211_chan_def vht_chandef;
        u32 ht_cfreq, ret;
 
@@ -257,7 +260,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
        ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
                                                  channel->band);
        /* check that channel matches the right operating channel */
-       if (channel->center_freq != ht_cfreq) {
+       if (!tracking && channel->center_freq != ht_cfreq) {
                /*
                 * It's possible that some APs are confused here;
                 * Netgear WNDR3700 sometimes reports 4 higher than
@@ -265,11 +268,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
                 * since we look at probe response/beacon data here
                 * it should be OK.
                 */
-               if (verbose)
-                       sdata_info(sdata,
-                                  "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
-                                  channel->center_freq, ht_cfreq,
-                                  ht_oper->primary_chan, channel->band);
+               sdata_info(sdata,
+                          "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
+                          channel->center_freq, ht_cfreq,
+                          ht_oper->primary_chan, channel->band);
                ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
                goto out;
        }
@@ -323,7 +325,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
                                channel->band);
                break;
        default:
-               if (verbose)
+               if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
                        sdata_info(sdata,
                                   "AP VHT operation IE has invalid channel width (%d), disable VHT\n",
                                   vht_oper->chan_width);
@@ -332,7 +334,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
        }
 
        if (!cfg80211_chandef_valid(&vht_chandef)) {
-               if (verbose)
+               if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
                        sdata_info(sdata,
                                   "AP VHT information is invalid, disable VHT\n");
                ret = IEEE80211_STA_DISABLE_VHT;
@@ -345,7 +347,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
        }
 
        if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) {
-               if (verbose)
+               if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
                        sdata_info(sdata,
                                   "AP VHT information doesn't match HT, disable VHT\n");
                ret = IEEE80211_STA_DISABLE_VHT;
@@ -361,18 +363,27 @@ out:
        if (ret & IEEE80211_STA_DISABLE_VHT)
                vht_chandef = *chandef;
 
+       /*
+        * Ignore the DISABLED flag when we're already connected and only
+        * tracking the APs beacon for bandwidth changes - otherwise we
+        * might get disconnected here if we connect to an AP, update our
+        * regulatory information based on the AP's country IE and the
+        * information we have is wrong/outdated and disables the channel
+        * that we're actually using for the connection to the AP.
+        */
        while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
-                                       IEEE80211_CHAN_DISABLED)) {
+                                       tracking ? 0 :
+                                                  IEEE80211_CHAN_DISABLED)) {
                if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
                        ret = IEEE80211_STA_DISABLE_HT |
                              IEEE80211_STA_DISABLE_VHT;
-                       goto out;
+                       break;
                }
 
                ret |= chandef_downgrade(chandef);
        }
 
-       if (chandef->width != vht_chandef.width && verbose)
+       if (chandef->width != vht_chandef.width && !tracking)
                sdata_info(sdata,
                           "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n");
 
@@ -412,7 +423,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
 
        /* calculate new channel (type) based on HT/VHT operation IEs */
        flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper,
-                                            vht_oper, &chandef, false);
+                                            vht_oper, &chandef, true);
 
        /*
         * Downgrade the new channel if we associated with restricted
@@ -3461,10 +3472,13 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
 
        if (tx_flags == 0) {
                auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
-               ifmgd->auth_data->timeout_started = true;
+               auth_data->timeout_started = true;
                run_again(ifmgd, auth_data->timeout);
        } else {
-               auth_data->timeout_started = false;
+               auth_data->timeout =
+                       round_jiffies_up(jiffies + IEEE80211_AUTH_TIMEOUT_LONG);
+               auth_data->timeout_started = true;
+               run_again(ifmgd, auth_data->timeout);
        }
 
        return 0;
@@ -3501,7 +3515,11 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
                assoc_data->timeout_started = true;
                run_again(&sdata->u.mgd, assoc_data->timeout);
        } else {
-               assoc_data->timeout_started = false;
+               assoc_data->timeout =
+                       round_jiffies_up(jiffies +
+                                        IEEE80211_ASSOC_TIMEOUT_LONG);
+               assoc_data->timeout_started = true;
+               run_again(&sdata->u.mgd, assoc_data->timeout);
        }
 
        return 0;
@@ -3906,7 +3924,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
        ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
                                                     cbss->channel,
                                                     ht_oper, vht_oper,
-                                                    &chandef, true);
+                                                    &chandef, false);
 
        sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
                                      local->rx_chains);
index 7fc5d0d8149a53f2a20377499841657dd9a97c7c..340126204343a063902bb205675cc14bea743a4c 100644 (file)
@@ -99,10 +99,13 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
        }
        mutex_unlock(&local->sta_mtx);
 
-       /* remove all interfaces */
+       /* remove all interfaces that were created in the driver */
        list_for_each_entry(sdata, &local->interfaces, list) {
-               if (!ieee80211_sdata_running(sdata))
+               if (!ieee80211_sdata_running(sdata) ||
+                   sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+                   sdata->vif.type == NL80211_IFTYPE_MONITOR)
                        continue;
+
                drv_remove_interface(local, sdata);
        }
 
index ac7ef5414bdede030d289a81946eaabc7b5d7a88..e6512e2ffd200223cd5cb75090802a98f544bb7d 100644 (file)
@@ -290,7 +290,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
        struct minstrel_rate *msr, *mr;
        unsigned int ndx;
        bool mrr_capable;
-       bool prev_sample = mi->prev_sample;
+       bool prev_sample;
        int delta;
        int sampling_ratio;
 
@@ -314,6 +314,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
                        (mi->sample_count + mi->sample_deferred / 2);
 
        /* delta < 0: no sampling required */
+       prev_sample = mi->prev_sample;
        mi->prev_sample = false;
        if (delta < 0 || (!mrr_capable && prev_sample))
                return;
index 5b2d3012b9830aef8d9101c26ba761402993b382..f3bbea1eb9e73eb9b7bbcd6b9e33faadb0b1fac5 100644 (file)
@@ -804,10 +804,18 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
 
        sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
        info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
+       rate->count = 1;
+
+       if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
+               int idx = sample_idx % ARRAY_SIZE(mp->cck_rates);
+               rate->idx = mp->cck_rates[idx];
+               rate->flags = 0;
+               return;
+       }
+
        rate->idx = sample_idx % MCS_GROUP_RATES +
                    (sample_group->streams - 1) * MCS_GROUP_RATES;
        rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
-       rate->count = 1;
 }
 
 static void
@@ -820,6 +828,9 @@ minstrel_ht_update_cck(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
        if (sband->band != IEEE80211_BAND_2GHZ)
                return;
 
+       if (!(mp->hw->flags & IEEE80211_HW_SUPPORTS_HT_CCK_RATES))
+               return;
+
        mi->cck_supported = 0;
        mi->cck_supported_short = 0;
        for (i = 0; i < 4; i++) {
index 8e29526202568f0223401659f4301500d5f9d424..83f6d29202aa3f146f47e95bba8e08f27f1848e1 100644 (file)
@@ -932,8 +932,14 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
 
-       /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
-       if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
+       /*
+        * Drop duplicate 802.11 retransmissions
+        * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")
+        */
+       if (rx->skb->len >= 24 && rx->sta &&
+           !ieee80211_is_ctl(hdr->frame_control) &&
+           !ieee80211_is_qos_nullfunc(hdr->frame_control) &&
+           !is_multicast_ether_addr(hdr->addr1)) {
                if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
                             rx->sta->last_seq_ctrl[rx->seqno_idx] ==
                             hdr->seq_ctrl)) {
index 2fd6dbea327a8b39d2ec0ed10b927d74bcdab408..393f17eea1a2f148a4c48a423c1611553473019c 100644 (file)
@@ -364,7 +364,7 @@ int genl_unregister_ops(struct genl_family *family, struct genl_ops *ops)
 EXPORT_SYMBOL(genl_unregister_ops);
 
 /**
- * genl_register_family - register a generic netlink family
+ * __genl_register_family - register a generic netlink family
  * @family: generic netlink family
  *
  * Registers the specified family after validating it first. Only one
@@ -374,7 +374,7 @@ EXPORT_SYMBOL(genl_unregister_ops);
  *
  * Return 0 on success or a negative error code.
  */
-int genl_register_family(struct genl_family *family)
+int __genl_register_family(struct genl_family *family)
 {
        int err = -EINVAL;
 
@@ -430,10 +430,10 @@ errout_locked:
 errout:
        return err;
 }
-EXPORT_SYMBOL(genl_register_family);
+EXPORT_SYMBOL(__genl_register_family);
 
 /**
- * genl_register_family_with_ops - register a generic netlink family
+ * __genl_register_family_with_ops - register a generic netlink family
  * @family: generic netlink family
  * @ops: operations to be registered
  * @n_ops: number of elements to register
@@ -457,12 +457,12 @@ EXPORT_SYMBOL(genl_register_family);
  *
  * Return 0 on success or a negative error code.
  */
-int genl_register_family_with_ops(struct genl_family *family,
+int __genl_register_family_with_ops(struct genl_family *family,
        struct genl_ops *ops, size_t n_ops)
 {
        int err, i;
 
-       err = genl_register_family(family);
+       err = __genl_register_family(family);
        if (err)
                return err;
 
@@ -476,7 +476,7 @@ err_out:
        genl_unregister_family(family);
        return err;
 }
-EXPORT_SYMBOL(genl_register_family_with_ops);
+EXPORT_SYMBOL(__genl_register_family_with_ops);
 
 /**
  * genl_unregister_family - unregister generic netlink family
@@ -544,6 +544,30 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
 }
 EXPORT_SYMBOL(genlmsg_put);
 
+static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+       struct genl_ops *ops = cb->data;
+       int rc;
+
+       genl_lock();
+       rc = ops->dumpit(skb, cb);
+       genl_unlock();
+       return rc;
+}
+
+static int genl_lock_done(struct netlink_callback *cb)
+{
+       struct genl_ops *ops = cb->data;
+       int rc = 0;
+
+       if (ops->done) {
+               genl_lock();
+               rc = ops->done(cb);
+               genl_unlock();
+       }
+       return rc;
+}
+
 static int genl_family_rcv_msg(struct genl_family *family,
                               struct sk_buff *skb,
                               struct nlmsghdr *nlh)
@@ -572,15 +596,34 @@ static int genl_family_rcv_msg(struct genl_family *family,
                return -EPERM;
 
        if (nlh->nlmsg_flags & NLM_F_DUMP) {
-               struct netlink_dump_control c = {
-                       .dump = ops->dumpit,
-                       .done = ops->done,
-               };
+               int rc;
 
                if (ops->dumpit == NULL)
                        return -EOPNOTSUPP;
 
-               return netlink_dump_start(net->genl_sock, skb, nlh, &c);
+               if (!family->parallel_ops) {
+                       struct netlink_dump_control c = {
+                               .module = family->module,
+                               .data = ops,
+                               .dump = genl_lock_dumpit,
+                               .done = genl_lock_done,
+                       };
+
+                       genl_unlock();
+                       rc = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
+                       genl_lock();
+
+               } else {
+                       struct netlink_dump_control c = {
+                               .module = family->module,
+                               .dump = ops->dumpit,
+                               .done = ops->done,
+                       };
+
+                       rc = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
+               }
+
+               return rc;
        }
 
        if (ops->doit == NULL)
@@ -877,8 +920,10 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
 #ifdef CONFIG_MODULES
                if (res == NULL) {
                        genl_unlock();
+                       up_read(&cb_lock);
                        request_module("net-pf-%d-proto-%d-family-%s",
                                       PF_NETLINK, NETLINK_GENERIC, name);
+                       down_read(&cb_lock);
                        genl_lock();
                        res = genl_family_find_byname(name);
                }
index ff8c434f7df89d5df8fd37281c06c315f35a6b18..f924dd209b311040ba21f4fda736980af14fdb77 100644 (file)
@@ -19,6 +19,7 @@
 
 enum llcp_state {
        LLCP_CONNECTED = 1, /* wait_for_packet() wants that */
+       LLCP_CONNECTING,
        LLCP_CLOSED,
        LLCP_BOUND,
        LLCP_LISTEN,
index 380253eccb74a87c3ca01f98daacd79c0a9deeea..7522c3708723d710f8edfcf7b1a7fc7d30eed5a9 100644 (file)
@@ -571,7 +571,7 @@ static unsigned int llcp_sock_poll(struct file *file, struct socket *sock,
        if (sk->sk_shutdown == SHUTDOWN_MASK)
                mask |= POLLHUP;
 
-       if (sock_writeable(sk))
+       if (sock_writeable(sk) && sk->sk_state == LLCP_CONNECTED)
                mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
        else
                set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
@@ -722,14 +722,16 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
        if (ret)
                goto sock_unlink;
 
+       sk->sk_state = LLCP_CONNECTING;
+
        ret = sock_wait_state(sk, LLCP_CONNECTED,
                              sock_sndtimeo(sk, flags & O_NONBLOCK));
-       if (ret)
+       if (ret && ret != -EINPROGRESS)
                goto sock_unlink;
 
        release_sock(sk);
 
-       return 0;
+       return ret;
 
 sock_unlink:
        nfc_llcp_put_ssap(local, llcp_sock->ssap);
index 20a1bd0e6549dcd5c55592c9138c4e99556f3816..a6895ab597c280ed3e05b732e5c8ca0cc8a54fec 100644 (file)
@@ -3259,9 +3259,11 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
 
                if (po->tp_version == TPACKET_V3) {
                        lv = sizeof(struct tpacket_stats_v3);
+                       st.stats3.tp_packets += st.stats3.tp_drops;
                        data = &st.stats3;
                } else {
                        lv = sizeof(struct tpacket_stats);
+                       st.stats1.tp_packets += st.stats1.tp_drops;
                        data = &st.stats1;
                }
 
index 281c1bded1f60f94934e406c9cafe076e4e2706d..51b968d3febb477be1e4183c8a94258c97fdcd18 100644 (file)
@@ -285,6 +285,45 @@ static struct Qdisc_ops *qdisc_lookup_ops(struct nlattr *kind)
        return q;
 }
 
+/* The linklayer setting were not transferred from iproute2, in older
+ * versions, and the rate tables lookup systems have been dropped in
+ * the kernel. To keep backward compatible with older iproute2 tc
+ * utils, we detect the linklayer setting by detecting if the rate
+ * table were modified.
+ *
+ * For linklayer ATM table entries, the rate table will be aligned to
+ * 48 bytes, thus some table entries will contain the same value.  The
+ * mpu (min packet unit) is also encoded into the old rate table, thus
+ * starting from the mpu, we find low and high table entries for
+ * mapping this cell.  If these entries contain the same value, when
+ * the rate tables have been modified for linklayer ATM.
+ *
+ * This is done by rounding mpu to the nearest 48 bytes cell/entry,
+ * and then roundup to the next cell, calc the table entry one below,
+ * and compare.
+ */
+static __u8 __detect_linklayer(struct tc_ratespec *r, __u32 *rtab)
+{
+       int low       = roundup(r->mpu, 48);
+       int high      = roundup(low+1, 48);
+       int cell_low  = low >> r->cell_log;
+       int cell_high = (high >> r->cell_log) - 1;
+
+       /* rtab is too inaccurate at rates > 100Mbit/s */
+       if ((r->rate > (100000000/8)) || (rtab[0] == 0)) {
+               pr_debug("TC linklayer: Giving up ATM detection\n");
+               return TC_LINKLAYER_ETHERNET;
+       }
+
+       if ((cell_high > cell_low) && (cell_high < 256)
+           && (rtab[cell_low] == rtab[cell_high])) {
+               pr_debug("TC linklayer: Detected ATM, low(%d)=high(%d)=%u\n",
+                        cell_low, cell_high, rtab[cell_high]);
+               return TC_LINKLAYER_ATM;
+       }
+       return TC_LINKLAYER_ETHERNET;
+}
+
 static struct qdisc_rate_table *qdisc_rtab_list;
 
 struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *tab)
@@ -308,6 +347,8 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *ta
                rtab->rate = *r;
                rtab->refcnt = 1;
                memcpy(rtab->data, nla_data(tab), 1024);
+               if (r->linklayer == TC_LINKLAYER_UNAWARE)
+                       r->linklayer = __detect_linklayer(r, rtab->data);
                rtab->next = qdisc_rtab_list;
                qdisc_rtab_list = rtab;
        }
index ca8e0a57d945dabeb51147f338cef363672040d5..1f9c31411f1998dec927fccf05362f09408558b4 100644 (file)
@@ -605,6 +605,7 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
                struct sockaddr_atmpvc pvc;
                int state;
 
+               memset(&pvc, 0, sizeof(pvc));
                pvc.sap_family = AF_ATMPVC;
                pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1;
                pvc.sap_addr.vpi = flow->vcc->vpi;
index 1bc210ffcba2a524750b3382d444a87db2c08c2c..8ec15988b5f39fcb590ae6e5e0c495282853c134 100644 (file)
@@ -1465,6 +1465,7 @@ static int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl)
        unsigned char *b = skb_tail_pointer(skb);
        struct tc_cbq_wrropt opt;
 
+       memset(&opt, 0, sizeof(opt));
        opt.flags = 0;
        opt.allot = cl->allot;
        opt.priority = cl->priority + 1;
index 20224086cc28abc30a63ef95964253fd2a55f183..a7f838b45dc8546acd88cde01da0c20326419f21 100644 (file)
@@ -908,6 +908,7 @@ void psched_ratecfg_precompute(struct psched_ratecfg *r,
        memset(r, 0, sizeof(*r));
        r->overhead = conf->overhead;
        r->rate_bps = (u64)conf->rate << 3;
+       r->linklayer = (conf->linklayer & TC_LINKLAYER_MASK);
        r->mult = 1;
        /*
         * Calibrate mult, shift so that token counting is accurate
index adaedd79389ccd0775a824c9e3c61aef2ea5355e..910667cbc1e353290880e1f0b0350dabba5c3122 100644 (file)
@@ -87,7 +87,7 @@ struct htb_class {
        unsigned int children;
        struct htb_class *parent;       /* parent class */
 
-       int prio;               /* these two are used only by leaves... */
+       u32 prio;               /* these two are used only by leaves... */
        int quantum;            /* but stored for parent-to-leaf return */
 
        union {
@@ -1312,6 +1312,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
        struct htb_sched *q = qdisc_priv(sch);
        struct htb_class *cl = (struct htb_class *)*arg, *parent;
        struct nlattr *opt = tca[TCA_OPTIONS];
+       struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
        struct nlattr *tb[TCA_HTB_MAX + 1];
        struct tc_htb_opt *hopt;
 
@@ -1333,6 +1334,18 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
        if (!hopt->rate.rate || !hopt->ceil.rate)
                goto failure;
 
+       /* Keeping backward compatible with rate_table based iproute2 tc */
+       if (hopt->rate.linklayer == TC_LINKLAYER_UNAWARE) {
+               rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]);
+               if (rtab)
+                       qdisc_put_rtab(rtab);
+       }
+       if (hopt->ceil.linklayer == TC_LINKLAYER_UNAWARE) {
+               ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]);
+               if (ctab)
+                       qdisc_put_rtab(ctab);
+       }
+
        if (!cl) {              /* new class */
                struct Qdisc *new_q;
                int prio;
index d51852bba01c981c9f9834dad82cfbcfec904508..57922524f0c754b7595654b12fe7704929a503bc 100644 (file)
 
 #define FRAC_BITS              30      /* fixed point arithmetic */
 #define ONE_FP                 (1UL << FRAC_BITS)
-#define IWSUM                  (ONE_FP/QFQ_MAX_WSUM)
 
 #define QFQ_MTU_SHIFT          16      /* to support TSO/GSO */
 #define QFQ_MIN_LMAX           512     /* see qfq_slot_insert */
@@ -189,6 +188,7 @@ struct qfq_sched {
        struct qfq_aggregate    *in_serv_agg;   /* Aggregate being served. */
        u32                     num_active_agg; /* Num. of active aggregates */
        u32                     wsum;           /* weight sum */
+       u32                     iwsum;          /* inverse weight sum */
 
        unsigned long bitmaps[QFQ_MAX_STATE];       /* Group bitmaps. */
        struct qfq_group groups[QFQ_MAX_INDEX + 1]; /* The groups. */
@@ -314,6 +314,7 @@ static void qfq_update_agg(struct qfq_sched *q, struct qfq_aggregate *agg,
 
        q->wsum +=
                (int) agg->class_weight * (new_num_classes - agg->num_classes);
+       q->iwsum = ONE_FP / q->wsum;
 
        agg->num_classes = new_num_classes;
 }
@@ -340,6 +341,10 @@ static void qfq_destroy_agg(struct qfq_sched *q, struct qfq_aggregate *agg)
 {
        if (!hlist_unhashed(&agg->nonfull_next))
                hlist_del_init(&agg->nonfull_next);
+       q->wsum -= agg->class_weight;
+       if (q->wsum != 0)
+               q->iwsum = ONE_FP / q->wsum;
+
        if (q->in_serv_agg == agg)
                q->in_serv_agg = qfq_choose_next_agg(q);
        kfree(agg);
@@ -827,38 +832,60 @@ static void qfq_make_eligible(struct qfq_sched *q)
        }
 }
 
-
 /*
- * The index of the slot in which the aggregate is to be inserted must
- * not be higher than QFQ_MAX_SLOTS-2. There is a '-2' and not a '-1'
- * because the start time of the group may be moved backward by one
- * slot after the aggregate has been inserted, and this would cause
- * non-empty slots to be right-shifted by one position.
+ * The index of the slot in which the input aggregate agg is to be
+ * inserted must not be higher than QFQ_MAX_SLOTS-2. There is a '-2'
+ * and not a '-1' because the start time of the group may be moved
+ * backward by one slot after the aggregate has been inserted, and
+ * this would cause non-empty slots to be right-shifted by one
+ * position.
+ *
+ * QFQ+ fully satisfies this bound to the slot index if the parameters
+ * of the classes are not changed dynamically, and if QFQ+ never
+ * happens to postpone the service of agg unjustly, i.e., it never
+ * happens that the aggregate becomes backlogged and eligible, or just
+ * eligible, while an aggregate with a higher approximated finish time
+ * is being served. In particular, in this case QFQ+ guarantees that
+ * the timestamps of agg are low enough that the slot index is never
+ * higher than 2. Unfortunately, QFQ+ cannot provide the same
+ * guarantee if it happens to unjustly postpone the service of agg, or
+ * if the parameters of some class are changed.
+ *
+ * As for the first event, i.e., an out-of-order service, the
+ * upper bound to the slot index guaranteed by QFQ+ grows to
+ * 2 +
+ * QFQ_MAX_AGG_CLASSES * ((1<<QFQ_MTU_SHIFT)/QFQ_MIN_LMAX) *
+ * (current_max_weight/current_wsum) <= 2 + 8 * 128 * 1.
  *
- * If the weight and lmax (max_pkt_size) of the classes do not change,
- * then QFQ+ does meet the above contraint according to the current
- * values of its parameters. In fact, if the weight and lmax of the
- * classes do not change, then, from the theory, QFQ+ guarantees that
- * the slot index is never higher than
- * 2 + QFQ_MAX_AGG_CLASSES * ((1<<QFQ_MTU_SHIFT)/QFQ_MIN_LMAX) *
- * (QFQ_MAX_WEIGHT/QFQ_MAX_WSUM) = 2 + 8 * 128 * (1 / 64) = 18
+ * The following function deals with this problem by backward-shifting
+ * the timestamps of agg, if needed, so as to guarantee that the slot
+ * index is never higher than QFQ_MAX_SLOTS-2. This backward-shift may
+ * cause the service of other aggregates to be postponed, yet the
+ * worst-case guarantees of these aggregates are not violated.  In
+ * fact, in case of no out-of-order service, the timestamps of agg
+ * would have been even lower than they are after the backward shift,
+ * because QFQ+ would have guaranteed a maximum value equal to 2 for
+ * the slot index, and 2 < QFQ_MAX_SLOTS-2. Hence the aggregates whose
+ * service is postponed because of the backward-shift would have
+ * however waited for the service of agg before being served.
  *
- * When the weight of a class is increased or the lmax of the class is
- * decreased, a new aggregate with smaller slot size than the original
- * parent aggregate of the class may happen to be activated. The
- * activation of this aggregate should be properly delayed to when the
- * service of the class has finished in the ideal system tracked by
- * QFQ+. If the activation of the aggregate is not delayed to this
- * reference time instant, then this aggregate may be unjustly served
- * before other aggregates waiting for service. This may cause the
- * above bound to the slot index to be violated for some of these
- * unlucky aggregates.
+ * The other event that may cause the slot index to be higher than 2
+ * for agg is a recent change of the parameters of some class. If the
+ * weight of a class is increased or the lmax (max_pkt_size) of the
+ * class is decreased, then a new aggregate with smaller slot size
+ * than the original parent aggregate of the class may happen to be
+ * activated. The activation of this aggregate should be properly
+ * delayed to when the service of the class has finished in the ideal
+ * system tracked by QFQ+. If the activation of the aggregate is not
+ * delayed to this reference time instant, then this aggregate may be
+ * unjustly served before other aggregates waiting for service. This
+ * may cause the above bound to the slot index to be violated for some
+ * of these unlucky aggregates.
  *
  * Instead of delaying the activation of the new aggregate, which is
- * quite complex, the following inaccurate but simple solution is used:
- * if the slot index is higher than QFQ_MAX_SLOTS-2, then the
- * timestamps of the aggregate are shifted backward so as to let the
- * slot index become equal to QFQ_MAX_SLOTS-2.
+ * quite complex, the above-discussed capping of the slot index is
+ * used to handle also the consequences of a change of the parameters
+ * of a class.
  */
 static void qfq_slot_insert(struct qfq_group *grp, struct qfq_aggregate *agg,
                            u64 roundedS)
@@ -1077,7 +1104,7 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch)
        else
                in_serv_agg->budget -= len;
 
-       q->V += (u64)len * IWSUM;
+       q->V += (u64)len * q->iwsum;
        pr_debug("qfq dequeue: len %u F %lld now %lld\n",
                 len, (unsigned long long) in_serv_agg->F,
                 (unsigned long long) q->V);
index d304f41260f2d8be4822631be5deb86612b63860..af7ffd447fee2af42a642c3e608536a8459ecbe5 100644 (file)
@@ -120,7 +120,7 @@ static int gssp_rpc_create(struct net *net, struct rpc_clnt **_clnt)
        if (IS_ERR(clnt)) {
                dprintk("RPC:       failed to create AF_LOCAL gssproxy "
                                "client (errno %ld).\n", PTR_ERR(clnt));
-               result = -PTR_ERR(clnt);
+               result = PTR_ERR(clnt);
                *_clnt = NULL;
                goto out;
        }
@@ -328,7 +328,6 @@ 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);
 }
 
index 357f613df7ff49d3460e37d3f338cb89c7029a69..3c85d1c8a0288db543fdb5cbec9d9ef5bd0f2f22 100644 (file)
@@ -430,7 +430,7 @@ static int dummy_enc_nameattr_array(struct xdr_stream *xdr,
 static int dummy_dec_nameattr_array(struct xdr_stream *xdr,
                                    struct gssx_name_attr_array *naa)
 {
-       struct gssx_name_attr dummy;
+       struct gssx_name_attr dummy = { .attr = {.len = 0} };
        u32 count, i;
        __be32 *p;
 
@@ -493,12 +493,13 @@ static int gssx_enc_name(struct xdr_stream *xdr,
        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;
+       struct xdr_netobj dummy_netobj = { .len = 0 };
+       struct gssx_name_attr_array dummy_name_attr_array = { .count = 0 };
+       struct gssx_option_array dummy_option_array = { .count = 0 };
        int err;
 
        /* name->display_name */
index 5a750b9c36404b34a3b41bd0e2d38628f881a5f2..426f8fcc4c6ce0c7a66d00571dfbea394c948983 100644 (file)
@@ -1644,6 +1644,10 @@ call_connect(struct rpc_task *task)
                task->tk_action = call_connect_status;
                if (task->tk_status < 0)
                        return;
+               if (task->tk_flags & RPC_TASK_NOCONNECT) {
+                       rpc_exit(task, -ENOTCONN);
+                       return;
+               }
                xprt_connect(task);
        }
 }
index 74d948f5d5a1d399d13061ee5c910c2cacc6f720..779742cfc1ffe3178fc0c320b6d0832e0f420d64 100644 (file)
@@ -23,6 +23,7 @@ struct sunrpc_net {
        struct rpc_clnt *rpcb_local_clnt4;
        spinlock_t rpcb_clnt_lock;
        unsigned int rpcb_users;
+       unsigned int rpcb_is_af_local : 1;
 
        struct mutex gssp_lock;
        wait_queue_head_t gssp_wq;
index 3df764dc330cbdb398e7dbbd5c6558d894bfc386..1891a1022c17e9d7d4c1686ff30c2ef13ebbf7b8 100644 (file)
@@ -204,13 +204,15 @@ void rpcb_put_local(struct net *net)
 }
 
 static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt,
-                       struct rpc_clnt *clnt4)
+                       struct rpc_clnt *clnt4,
+                       bool is_af_local)
 {
        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 
        /* Protected by rpcb_create_local_mutex */
        sn->rpcb_local_clnt = clnt;
        sn->rpcb_local_clnt4 = clnt4;
+       sn->rpcb_is_af_local = is_af_local ? 1 : 0;
        smp_wmb(); 
        sn->rpcb_users = 1;
        dprintk("RPC:       created new rpcb local clients (rpcb_local_clnt: "
@@ -238,6 +240,14 @@ static int rpcb_create_local_unix(struct net *net)
                .program        = &rpcb_program,
                .version        = RPCBVERS_2,
                .authflavor     = RPC_AUTH_NULL,
+               /*
+                * We turn off the idle timeout to prevent the kernel
+                * from automatically disconnecting the socket.
+                * Otherwise, we'd have to cache the mount namespace
+                * of the caller and somehow pass that to the socket
+                * reconnect code.
+                */
+               .flags          = RPC_CLNT_CREATE_NO_IDLE_TIMEOUT,
        };
        struct rpc_clnt *clnt, *clnt4;
        int result = 0;
@@ -263,7 +273,7 @@ static int rpcb_create_local_unix(struct net *net)
                clnt4 = NULL;
        }
 
-       rpcb_set_local(net, clnt, clnt4);
+       rpcb_set_local(net, clnt, clnt4, true);
 
 out:
        return result;
@@ -315,7 +325,7 @@ static int rpcb_create_local_net(struct net *net)
                clnt4 = NULL;
        }
 
-       rpcb_set_local(net, clnt, clnt4);
+       rpcb_set_local(net, clnt, clnt4, false);
 
 out:
        return result;
@@ -376,13 +386,16 @@ static struct rpc_clnt *rpcb_create(struct net *net, const char *hostname,
        return rpc_create(&args);
 }
 
-static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg)
+static int rpcb_register_call(struct sunrpc_net *sn, struct rpc_clnt *clnt, struct rpc_message *msg, bool is_set)
 {
-       int result, error = 0;
+       int flags = RPC_TASK_NOCONNECT;
+       int error, result = 0;
 
+       if (is_set || !sn->rpcb_is_af_local)
+               flags = RPC_TASK_SOFTCONN;
        msg->rpc_resp = &result;
 
-       error = rpc_call_sync(clnt, msg, RPC_TASK_SOFTCONN);
+       error = rpc_call_sync(clnt, msg, flags);
        if (error < 0) {
                dprintk("RPC:       failed to contact local rpcbind "
                                "server (errno %d).\n", -error);
@@ -439,16 +452,19 @@ int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, unsigned short
                .rpc_argp       = &map,
        };
        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+       bool is_set = false;
 
        dprintk("RPC:       %sregistering (%u, %u, %d, %u) with local "
                        "rpcbind\n", (port ? "" : "un"),
                        prog, vers, prot, port);
 
        msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET];
-       if (port)
+       if (port != 0) {
                msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET];
+               is_set = true;
+       }
 
-       return rpcb_register_call(sn->rpcb_local_clnt, &msg);
+       return rpcb_register_call(sn, sn->rpcb_local_clnt, &msg, is_set);
 }
 
 /*
@@ -461,6 +477,7 @@ static int rpcb_register_inet4(struct sunrpc_net *sn,
        const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
        struct rpcbind_args *map = msg->rpc_argp;
        unsigned short port = ntohs(sin->sin_port);
+       bool is_set = false;
        int result;
 
        map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL);
@@ -471,10 +488,12 @@ static int rpcb_register_inet4(struct sunrpc_net *sn,
                        map->r_addr, map->r_netid);
 
        msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
-       if (port)
+       if (port != 0) {
                msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
+               is_set = true;
+       }
 
-       result = rpcb_register_call(sn->rpcb_local_clnt4, msg);
+       result = rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, is_set);
        kfree(map->r_addr);
        return result;
 }
@@ -489,6 +508,7 @@ static int rpcb_register_inet6(struct sunrpc_net *sn,
        const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap;
        struct rpcbind_args *map = msg->rpc_argp;
        unsigned short port = ntohs(sin6->sin6_port);
+       bool is_set = false;
        int result;
 
        map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL);
@@ -499,10 +519,12 @@ static int rpcb_register_inet6(struct sunrpc_net *sn,
                        map->r_addr, map->r_netid);
 
        msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
-       if (port)
+       if (port != 0) {
                msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
+               is_set = true;
+       }
 
-       result = rpcb_register_call(sn->rpcb_local_clnt4, msg);
+       result = rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, is_set);
        kfree(map->r_addr);
        return result;
 }
@@ -519,7 +541,7 @@ static int rpcb_unregister_all_protofamilies(struct sunrpc_net *sn,
        map->r_addr = "";
        msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
 
-       return rpcb_register_call(sn->rpcb_local_clnt4, msg);
+       return rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, false);
 }
 
 /**
index 06bdf5a1082c850030650fc3957f47ef75ebda8a..1583c8a4eb7f6d7e9a945b7876604352407d2c48 100644 (file)
@@ -493,8 +493,6 @@ static int unix_gid_parse(struct cache_detail *cd,
        if (rv)
                return -EINVAL;
        uid = make_kuid(&init_user_ns, id);
-       if (!uid_valid(uid))
-               return -EINVAL;
        ug.uid = uid;
 
        expiry = get_expiry(&mesg);
index 0f679df7d072794094ece1aa48988e834395d849..305374d4fb985ec4942040447f91e8d8277ea10d 100644 (file)
@@ -917,7 +917,10 @@ static void svc_tcp_clear_pages(struct svc_sock *svsk)
        len = svsk->sk_datalen;
        npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
        for (i = 0; i < npages; i++) {
-               BUG_ON(svsk->sk_pages[i] == NULL);
+               if (svsk->sk_pages[i] == NULL) {
+                       WARN_ON_ONCE(1);
+                       continue;
+               }
                put_page(svsk->sk_pages[i]);
                svsk->sk_pages[i] = NULL;
        }
@@ -1092,8 +1095,10 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
                goto err_noclose;
        }
 
-       if (svc_sock_reclen(svsk) < 8)
+       if (svsk->sk_datalen < 8) {
+               svsk->sk_datalen = 0;
                goto err_delete; /* client is nuts. */
+       }
 
        rqstp->rq_arg.len = svsk->sk_datalen;
        rqstp->rq_arg.page_base = 0;
index 75edcfad6e264f299fac566f16bb1cfd82615d2a..1504bb11e4f351d1a79835fa990ac8f22751faf3 100644 (file)
@@ -207,10 +207,13 @@ _shift_data_right_pages(struct page **pages, size_t pgto_base,
                pgfrom_base -= copy;
 
                vto = kmap_atomic(*pgto);
-               vfrom = kmap_atomic(*pgfrom);
-               memmove(vto + pgto_base, vfrom + pgfrom_base, copy);
+               if (*pgto != *pgfrom) {
+                       vfrom = kmap_atomic(*pgfrom);
+                       memcpy(vto + pgto_base, vfrom + pgfrom_base, copy);
+                       kunmap_atomic(vfrom);
+               } else
+                       memmove(vto + pgto_base, vto + pgfrom_base, copy);
                flush_dcache_page(*pgto);
-               kunmap_atomic(vfrom);
                kunmap_atomic(vto);
 
        } while ((len -= copy) != 0);
index 8d2edddf48cf13c6d283bd8784e61c7601f23fc7..65b146297f5acfa8f5ab08e4d6f1ae0df865b4f6 100644 (file)
@@ -98,6 +98,7 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch,
  */
 static u32 *decode_write_list(u32 *va, u32 *vaend)
 {
+       unsigned long start, end;
        int nchunks;
 
        struct rpcrdma_write_array *ary =
@@ -113,9 +114,12 @@ static u32 *decode_write_list(u32 *va, u32 *vaend)
                return NULL;
        }
        nchunks = ntohl(ary->wc_nchunks);
-       if (((unsigned long)&ary->wc_array[0] +
-            (sizeof(struct rpcrdma_write_chunk) * nchunks)) >
-           (unsigned long)vaend) {
+
+       start = (unsigned long)&ary->wc_array[0];
+       end = (unsigned long)vaend;
+       if (nchunks < 0 ||
+           nchunks > (SIZE_MAX - start) / sizeof(struct rpcrdma_write_chunk) ||
+           (start + (sizeof(struct rpcrdma_write_chunk) * nchunks)) > end) {
                dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n",
                        ary, nchunks, vaend);
                return NULL;
@@ -129,6 +133,7 @@ static u32 *decode_write_list(u32 *va, u32 *vaend)
 
 static u32 *decode_reply_array(u32 *va, u32 *vaend)
 {
+       unsigned long start, end;
        int nchunks;
        struct rpcrdma_write_array *ary =
                (struct rpcrdma_write_array *)va;
@@ -143,9 +148,12 @@ static u32 *decode_reply_array(u32 *va, u32 *vaend)
                return NULL;
        }
        nchunks = ntohl(ary->wc_nchunks);
-       if (((unsigned long)&ary->wc_array[0] +
-            (sizeof(struct rpcrdma_write_chunk) * nchunks)) >
-           (unsigned long)vaend) {
+
+       start = (unsigned long)&ary->wc_array[0];
+       end = (unsigned long)vaend;
+       if (nchunks < 0 ||
+           nchunks > (SIZE_MAX - start) / sizeof(struct rpcrdma_write_chunk) ||
+           (start + (sizeof(struct rpcrdma_write_chunk) * nchunks)) > end) {
                dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n",
                        ary, nchunks, vaend);
                return NULL;
index 515ce38e4f4c7286023f32f4c8c692af2787ec80..7e26ad416af1aa786b6fa969260d794f1592ebb5 100644 (file)
@@ -1179,7 +1179,7 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
                /* Accept only ACK or NACK message */
                if (unlikely(msg_errcode(msg))) {
                        sock->state = SS_DISCONNECTING;
-                       sk->sk_err = -ECONNREFUSED;
+                       sk->sk_err = ECONNREFUSED;
                        retval = TIPC_OK;
                        break;
                }
@@ -1190,7 +1190,7 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
                res = auto_connect(sock, msg);
                if (res) {
                        sock->state = SS_DISCONNECTING;
-                       sk->sk_err = res;
+                       sk->sk_err = -res;
                        retval = TIPC_OK;
                        break;
                }
index 73405e00c800fd62ff703c9c030e31da70c69858..64fcbae020d200fbea388028aeec70f93d2a2b1f 100644 (file)
@@ -876,6 +876,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
                cfg80211_leave_mesh(rdev, dev);
                break;
        case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_P2P_GO:
                cfg80211_stop_ap(rdev, dev);
                break;
        default:
index b14b7e3cb6e65a76517752872753b53264baa7b4..448c034184e275619732d23c01a01f83aad44ba7 100644 (file)
@@ -471,10 +471,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
                        goto out_unlock;
                }
                *rdev = wiphy_to_dev((*wdev)->wiphy);
-               cb->args[0] = (*rdev)->wiphy_idx;
+               /* 0 is the first index - add 1 to parse only once */
+               cb->args[0] = (*rdev)->wiphy_idx + 1;
                cb->args[1] = (*wdev)->identifier;
        } else {
-               struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0]);
+               /* subtract the 1 again here */
+               struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
                struct wireless_dev *tmp;
 
                if (!wiphy) {
@@ -6588,12 +6590,14 @@ EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb);
 
 void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
 {
+       struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
        void *hdr = ((void **)skb->cb)[1];
        struct nlattr *data = ((void **)skb->cb)[2];
 
        nla_nest_end(skb, data);
        genlmsg_end(skb, hdr);
-       genlmsg_multicast(skb, 0, nl80211_testmode_mcgrp.id, gfp);
+       genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), skb, 0,
+                               nl80211_testmode_mcgrp.id, gfp);
 }
 EXPORT_SYMBOL(cfg80211_testmode_event);
 #endif
@@ -10028,7 +10032,8 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
 
        genlmsg_end(msg, hdr);
 
-       genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
+       genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+                               nl80211_mlme_mcgrp.id, gfp);
        return;
 
  nla_put_failure:
index 37ca9694aabea14efd6308b59ced2e153ac30ae5..22c88d2e6846fbb7023ed02bb6ce3e7c423c9e66 100644 (file)
@@ -1583,11 +1583,11 @@ out_cud_release:
        case SIOCX25CALLACCPTAPPRV: {
                rc = -EINVAL;
                lock_sock(sk);
-               if (sk->sk_state != TCP_CLOSE)
-                       break;
-               clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags);
+               if (sk->sk_state == TCP_CLOSE) {
+                       clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags);
+                       rc = 0;
+               }
                release_sock(sk);
-               rc = 0;
                break;
        }
 
@@ -1595,14 +1595,15 @@ out_cud_release:
                rc = -EINVAL;
                lock_sock(sk);
                if (sk->sk_state != TCP_ESTABLISHED)
-                       break;
+                       goto out_sendcallaccpt_release;
                /* must call accptapprv above */
                if (test_bit(X25_ACCPT_APPRV_FLAG, &x25->flags))
-                       break;
+                       goto out_sendcallaccpt_release;
                x25_write_internal(sk, X25_CALL_ACCEPTED);
                x25->state = X25_STATE_3;
-               release_sock(sk);
                rc = 0;
+out_sendcallaccpt_release:
+               release_sock(sk);
                break;
        }
 
index 76e0d56950751a8a60074d5a9a7df6232a1ee472..823359ed95e16a0969ee6c28843a4777387d3561 100644 (file)
@@ -166,7 +166,9 @@ void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
        } else {
                printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
                        rtd->params->name, dma_ch, dcsr);
+               snd_pcm_stream_lock(substream);
                snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+               snd_pcm_stream_unlock(substream);
        }
 }
 EXPORT_SYMBOL(pxa2xx_pcm_dma_irq);
index 99db892d7299056568e5432bdd660ea14d3143c6..98969541cbcc9c62ff81afb9818d2399dd6e7eb0 100644 (file)
@@ -743,7 +743,7 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
        mutex_lock(&stream->device->lock);
        switch (_IOC_NR(cmd)) {
        case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
-               put_user(SNDRV_COMPRESS_VERSION,
+               retval = put_user(SNDRV_COMPRESS_VERSION,
                                (int __user *)arg) ? -EFAULT : 0;
                break;
        case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
index e3cb46fef2c76b4cca8d67a52f212deb41598caf..b3f39b5ed74234ff92d31162fc3af067a523c1ba 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/export.h>
 #include <linux/moduleparam.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
 
 /*
  * common variables
@@ -60,6 +61,14 @@ static void free_devinfo(void *private);
 #define call_ctl(type,rec) snd_seq_kernel_client_ctl(system_client, type, rec)
 
 
+/* call snd_seq_oss_midi_lookup_ports() asynchronously */
+static void async_call_lookup_ports(struct work_struct *work)
+{
+       snd_seq_oss_midi_lookup_ports(system_client);
+}
+
+static DECLARE_WORK(async_lookup_work, async_call_lookup_ports);
+
 /*
  * create sequencer client for OSS sequencer
  */
@@ -85,9 +94,6 @@ snd_seq_oss_create_client(void)
        system_client = rc;
        debug_printk(("new client = %d\n", rc));
 
-       /* look up midi devices */
-       snd_seq_oss_midi_lookup_ports(system_client);
-
        /* create annoucement receiver port */
        memset(port, 0, sizeof(*port));
        strcpy(port->name, "Receiver");
@@ -115,6 +121,9 @@ snd_seq_oss_create_client(void)
        }
        rc = 0;
 
+       /* look up midi devices */
+       schedule_work(&async_lookup_work);
+
  __error:
        kfree(port);
        return rc;
@@ -160,6 +169,7 @@ receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic
 int
 snd_seq_oss_delete_client(void)
 {
+       cancel_work_sync(&async_lookup_work);
        if (system_client >= 0)
                snd_seq_delete_kernel_client(system_client);
 
index 677dc84590c79ae49dca0fb569fe4c98a44c068c..862d84893ee871c0467f5baf4667d769d6f7203e 100644 (file)
@@ -72,7 +72,7 @@ static int send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev,
  * look up the existing ports
  * this looks a very exhausting job.
  */
-int __init
+int
 snd_seq_oss_midi_lookup_ports(int client)
 {
        struct snd_seq_client_info *clinfo;
index b41ed8661b237abd41676cf2bed810686028e046..e427dbf7636814a1677db21ed22450b2e889527f 100644 (file)
@@ -173,11 +173,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids);
 
 #endif /* CONFIG_PNP */
 
-#ifdef OPTi93X
-#define DEV_NAME "opti93x"
-#else
-#define DEV_NAME "opti92x"
-#endif
+#define DEV_NAME KBUILD_MODNAME
 
 static char * snd_opti9xx_names[] = {
        "unknown",
@@ -1168,7 +1164,7 @@ static int snd_opti9xx_pnp_resume(struct pnp_card_link *pcard)
 
 static struct pnp_card_driver opti9xx_pnpc_driver = {
        .flags          = PNP_DRIVER_RES_DISABLE,
-       .name           = "opti9xx",
+       .name           = DEV_NAME,
        .id_table       = snd_opti9xx_pnpids,
        .probe          = snd_opti9xx_pnp_probe,
        .remove         = snd_opti9xx_pnp_remove,
index fbc17203613c05f874e765ae30df13f12add9324..a471d821c608b52326eba083f9e291a3bb33e818 100644 (file)
@@ -769,7 +769,10 @@ static void snd_card_asihpi_timer_function(unsigned long data)
                                                s->number);
                                ds->drained_count++;
                                if (ds->drained_count > 20) {
+                                       unsigned long flags;
+                                       snd_pcm_stream_lock_irqsave(s, flags);
                                        snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN);
+                                       snd_pcm_stream_unlock_irqrestore(s, flags);
                                        continue;
                                }
                        } else {
index 6e78c6789858394b16c7c4543d4c30874602c978..819430ac6b3b5238a1cf25c45198f2776664b16a 100644 (file)
@@ -689,7 +689,9 @@ static void snd_atiixp_xrun_dma(struct atiixp *chip, struct atiixp_dma *dma)
        if (! dma->substream || ! dma->running)
                return;
        snd_printdd("atiixp: XRUN detected (DMA %d)\n", dma->ops->type);
+       snd_pcm_stream_lock(dma->substream);
        snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN);
+       snd_pcm_stream_unlock(dma->substream);
 }
 
 /*
index d0bec7ba3b0d8f3eb610807525e071ed53c4e220..57f41820263f6203864d3558dd128c8a16fd5c17 100644 (file)
@@ -638,7 +638,9 @@ static void snd_atiixp_xrun_dma(struct atiixp_modem *chip,
        if (! dma->substream || ! dma->running)
                return;
        snd_printdd("atiixp-modem: XRUN detected (DMA %d)\n", dma->ops->type);
+       snd_pcm_stream_lock(dma->substream);
        snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN);
+       snd_pcm_stream_unlock(dma->substream);
 }
 
 /*
index 7c11d46b84d3b3b0fd26b8bca560f6fb3017a8fc..48a9d004d6d938ac5365b52a83c6b67b7b18dcaa 100644 (file)
@@ -860,7 +860,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
                }
        }
        if (id < 0 && quirk) {
-               for (q = quirk; q->subvendor; q++) {
+               for (q = quirk; q->subvendor || q->subdevice; q++) {
                        unsigned int vendorid =
                                q->subdevice | (q->subvendor << 16);
                        unsigned int mask = 0xffff0000 | q->subdevice_mask;
index 4b1524a861f38e2aee10d8bd39bf3352d82ed0b8..ad22decad02b6fc1360d18e537c08296a5be0455 100644 (file)
@@ -519,7 +519,7 @@ static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
 }
 
 #define nid_has_mute(codec, nid, dir) \
-       check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
+       check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))
 #define nid_has_volume(codec, nid, dir) \
        check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
 
@@ -621,7 +621,7 @@ static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
                if (enable)
                        val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
        }
-       if (caps & AC_AMPCAP_MUTE) {
+       if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
                if (!enable)
                        val |= HDA_AMP_MUTE;
        }
@@ -645,7 +645,7 @@ static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
 {
        unsigned int mask = 0xff;
 
-       if (caps & AC_AMPCAP_MUTE) {
+       if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
                if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL))
                        mask &= ~0x80;
        }
@@ -840,7 +840,7 @@ static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
                                const char *pfx, const char *dir,
                                const char *sfx, int cidx, unsigned long val)
 {
-       char name[32];
+       char name[44];
        snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
        if (!add_control(spec, type, name, cidx, val))
                return -ENOMEM;
index de18722c487346858783fa5d5e9f9fd574b70b39..624e6c044a44f756b2b213f49fe0bc118a273899 100644 (file)
@@ -3335,6 +3335,7 @@ static struct snd_pci_quirk msi_black_list[] = {
        SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
        SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
        SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
+       SND_PCI_QUIRK(0x1179, 0xfb44, "Toshiba Satellite C870", 0), /* AMD Hudson */
        SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */
        SND_PCI_QUIRK(0xa0a0, 0x0575, "Aopen MZ915-M", 0), /* ICH6 */
        {}
index e0bf7534fa1f410c28986e5cb0d0be4ee03e1442..2e7493ef8ee0643b1ee51b759198c233d23af6a5 100644 (file)
@@ -562,6 +562,14 @@ static inline unsigned int get_wcaps_channels(u32 wcaps)
        return chans;
 }
 
+static inline void snd_hda_override_wcaps(struct hda_codec *codec,
+                                         hda_nid_t nid, u32 val)
+{
+       if (nid >= codec->start_nid &&
+           nid < codec->start_nid + codec->num_nodes)
+               codec->wcaps[nid - codec->start_nid] = val;
+}
+
 u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
 int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
                              unsigned int caps);
@@ -667,7 +675,7 @@ snd_hda_check_power_state(struct hda_codec *codec, hda_nid_t nid,
        if (state & AC_PWRST_ERROR)
                return true;
        state = (state >> 4) & 0x0f;
-       return (state != target_state);
+       return (state == target_state);
 }
 
 unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
index 977b0d878dae44de0e1a5c8d0de67df31da3e437..d97f0d61a15b5779bd10a17ef3d90a184673c008 100644 (file)
@@ -2112,6 +2112,9 @@ static void ad_vmaster_eapd_hook(void *private_data, int enabled)
 {
        struct hda_codec *codec = private_data;
        struct ad198x_spec *spec = codec->spec;
+
+       if (!spec->eapd_nid)
+               return;
        snd_hda_codec_update_cache(codec, spec->eapd_nid, 0,
                                   AC_VERB_SET_EAPD_BTLENABLE,
                                   enabled ? 0x02 : 0x00);
@@ -3601,13 +3604,16 @@ static void ad1884_fixup_hp_eapd(struct hda_codec *codec,
 {
        struct ad198x_spec *spec = codec->spec;
 
-       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
+               spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
+               break;
+       case HDA_FIXUP_ACT_PROBE:
                if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
                        spec->eapd_nid = spec->gen.autocfg.line_out_pins[0];
                else
                        spec->eapd_nid = spec->gen.autocfg.speaker_pins[0];
-               if (spec->eapd_nid)
-                       spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
+               break;
        }
 }
 
index e12f7a030c58efae2c5a93829ec6bfce1fb17ac7..b5375ed022d773e2c6ec10cb928a1d2d102dc766 100644 (file)
@@ -67,6 +67,8 @@ struct hdmi_spec_per_pin {
        struct delayed_work work;
        struct snd_kcontrol *eld_ctl;
        int repoll_count;
+       bool setup; /* the stream has been set up by prepare callback */
+       int channels; /* current number of channels */
        bool non_pcm;
        bool chmap_set;         /* channel-map override by ALSA API? */
        unsigned char chmap[8]; /* ALSA API channel-map */
@@ -551,6 +553,17 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels)
                }
        }
 
+       if (!ca) {
+               /* if there was no match, select the regular ALSA channel
+                * allocation with the matching number of channels */
+               for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+                       if (channels == channel_allocations[i].channels) {
+                               ca = channel_allocations[i].ca_index;
+                               break;
+                       }
+               }
+       }
+
        snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf));
        snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
                    ca, channels, buf);
@@ -868,18 +881,19 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
        return true;
 }
 
-static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx,
-                                      bool non_pcm,
-                                      struct snd_pcm_substream *substream)
+static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
+                                      struct hdmi_spec_per_pin *per_pin,
+                                      bool non_pcm)
 {
-       struct hdmi_spec *spec = codec->spec;
-       struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
        hda_nid_t pin_nid = per_pin->pin_nid;
-       int channels = substream->runtime->channels;
+       int channels = per_pin->channels;
        struct hdmi_eld *eld;
        int ca;
        union audio_infoframe ai;
 
+       if (!channels)
+               return;
+
        eld = &per_pin->sink_eld;
        if (!eld->monitor_present)
                return;
@@ -1146,7 +1160,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
        per_cvt->assigned = 1;
        hinfo->nid = per_cvt->cvt_nid;
 
-       snd_hda_codec_write(codec, per_pin->pin_nid, 0,
+       snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
                            AC_VERB_SET_CONNECT_SEL,
                            mux_idx);
        snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid);
@@ -1263,6 +1277,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
                eld_changed = true;
        }
        if (update_eld) {
+               bool old_eld_valid = pin_eld->eld_valid;
                pin_eld->eld_valid = eld->eld_valid;
                eld_changed = pin_eld->eld_size != eld->eld_size ||
                              memcmp(pin_eld->eld_buffer, eld->eld_buffer,
@@ -1272,6 +1287,18 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
                               eld->eld_size);
                pin_eld->eld_size = eld->eld_size;
                pin_eld->info = eld->info;
+
+               /* Haswell-specific workaround: re-setup when the transcoder is
+                * changed during the stream playback
+                */
+               if (codec->vendor_id == 0x80862807 &&
+                   eld->eld_valid && !old_eld_valid && per_pin->setup) {
+                       snd_hda_codec_write(codec, pin_nid, 0,
+                                           AC_VERB_SET_AMP_GAIN_MUTE,
+                                           AMP_OUT_UNMUTE);
+                       hdmi_setup_audio_infoframe(codec, per_pin,
+                                                  per_pin->non_pcm);
+               }
        }
        mutex_unlock(&pin_eld->lock);
 
@@ -1444,14 +1471,17 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
        hda_nid_t cvt_nid = hinfo->nid;
        struct hdmi_spec *spec = codec->spec;
        int pin_idx = hinfo_to_pin_index(spec, hinfo);
-       hda_nid_t pin_nid = get_pin(spec, pin_idx)->pin_nid;
+       struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
+       hda_nid_t pin_nid = per_pin->pin_nid;
        bool non_pcm;
 
        non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
+       per_pin->channels = substream->runtime->channels;
+       per_pin->setup = true;
 
        hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels);
 
-       hdmi_setup_audio_infoframe(codec, pin_idx, non_pcm, substream);
+       hdmi_setup_audio_infoframe(codec, per_pin, non_pcm);
 
        return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);
 }
@@ -1491,6 +1521,9 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
                snd_hda_spdif_ctls_unassign(codec, pin_idx);
                per_pin->chmap_set = false;
                memset(per_pin->chmap, 0, sizeof(per_pin->chmap));
+
+               per_pin->setup = false;
+               per_pin->channels = 0;
        }
 
        return 0;
@@ -1626,8 +1659,7 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
        per_pin->chmap_set = true;
        memcpy(per_pin->chmap, chmap, sizeof(chmap));
        if (prepared)
-               hdmi_setup_audio_infoframe(codec, pin_idx, per_pin->non_pcm,
-                                          substream);
+               hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
 
        return 0;
 }
@@ -1715,6 +1747,9 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
                struct snd_pcm_chmap *chmap;
                struct snd_kcontrol *kctl;
                int i;
+
+               if (!codec->pcm_info[pin_idx].pcm)
+                       break;
                err = snd_pcm_add_chmap_ctls(codec->pcm_info[pin_idx].pcm,
                                             SNDRV_PCM_STREAM_PLAYBACK,
                                             NULL, 0, pin_idx, &chmap);
@@ -2536,6 +2571,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
 { .id = 0x10de0043, .name = "GPU 43 HDMI/DP",  .patch = patch_generic_hdmi },
 { .id = 0x10de0044, .name = "GPU 44 HDMI/DP",  .patch = patch_generic_hdmi },
 { .id = 0x10de0051, .name = "GPU 51 HDMI/DP",  .patch = patch_generic_hdmi },
+{ .id = 0x10de0060, .name = "GPU 60 HDMI/DP",  .patch = patch_generic_hdmi },
 { .id = 0x10de0067, .name = "MCP67 HDMI",      .patch = patch_nvhdmi_2ch },
 { .id = 0x10de8001, .name = "MCP73 HDMI",      .patch = patch_nvhdmi_2ch },
 { .id = 0x11069f80, .name = "VX900 HDMI/DP",   .patch = patch_via_hdmi },
@@ -2588,6 +2624,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0042");
 MODULE_ALIAS("snd-hda-codec-id:10de0043");
 MODULE_ALIAS("snd-hda-codec-id:10de0044");
 MODULE_ALIAS("snd-hda-codec-id:10de0051");
+MODULE_ALIAS("snd-hda-codec-id:10de0060");
 MODULE_ALIAS("snd-hda-codec-id:10de0067");
 MODULE_ALIAS("snd-hda-codec-id:10de8001");
 MODULE_ALIAS("snd-hda-codec-id:11069f80");
index 403010c9e82ea610125c82811e7f1f4ea3d27aac..458cf89b16436fc6c779948ff4db0bd7c28c2bfe 100644 (file)
@@ -1027,6 +1027,7 @@ enum {
        ALC880_FIXUP_GPIO2,
        ALC880_FIXUP_MEDION_RIM,
        ALC880_FIXUP_LG,
+       ALC880_FIXUP_LG_LW25,
        ALC880_FIXUP_W810,
        ALC880_FIXUP_EAPD_COEF,
        ALC880_FIXUP_TCL_S700,
@@ -1085,6 +1086,14 @@ static const struct hda_fixup alc880_fixups[] = {
                        { }
                }
        },
+       [ALC880_FIXUP_LG_LW25] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x1a, 0x0181344f }, /* line-in */
+                       { 0x1b, 0x0321403f }, /* headphone */
+                       { }
+               }
+       },
        [ALC880_FIXUP_W810] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -1337,6 +1346,7 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG),
        SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG),
        SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG),
+       SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_FIXUP_LG_LW25),
        SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700),
 
        /* Below is the copied entries from alc880_quirks.c.
@@ -3495,9 +3505,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05f8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05f9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05fb, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
        SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -4194,9 +4207,11 @@ static const struct hda_fixup alc662_fixups[] = {
 
 static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
+       SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
+       SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
index 1d9d6427e0bf7cd3f09bc3a83fb1e0b08ad64848..dc4833f47a2bd6339505ddb2202eb8271f4f51d1 100644 (file)
@@ -417,9 +417,11 @@ static void stac_update_outputs(struct hda_codec *codec)
                        val &= ~spec->eapd_mask;
                else
                        val |= spec->eapd_mask;
-               if (spec->gpio_data != val)
+               if (spec->gpio_data != val) {
+                       spec->gpio_data = val;
                        stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir,
                                      val);
+               }
        }
 }
 
@@ -2813,6 +2815,7 @@ static const struct hda_pintbl ecs202_pin_configs[] = {
 
 /* codec SSIDs for Intel Mac sharing the same PCI SSID 8384:7680 */
 static const struct snd_pci_quirk stac922x_intel_mac_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x0000, 0x0100, "Mac Mini", STAC_INTEL_MAC_V3),
        SND_PCI_QUIRK(0x106b, 0x0800, "Mac", STAC_INTEL_MAC_V1),
        SND_PCI_QUIRK(0x106b, 0x0600, "Mac", STAC_INTEL_MAC_V2),
        SND_PCI_QUIRK(0x106b, 0x0700, "Mac", STAC_INTEL_MAC_V2),
@@ -3227,7 +3230,7 @@ static const struct hda_fixup stac927x_fixups[] = {
                        /* configure the analog microphone on some laptops */
                        { 0x0c, 0x90a79130 },
                        /* correct the front output jack as a hp out */
-                       { 0x0f, 0x0227011f },
+                       { 0x0f, 0x0221101f },
                        /* correct the front input jack as a mic */
                        { 0x0e, 0x02a79130 },
                        {}
@@ -3608,20 +3611,18 @@ static int stac_parse_auto_config(struct hda_codec *codec)
 static int stac_init(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
-       unsigned int gpio;
        int i;
 
        /* override some hints */
        stac_store_hints(codec);
 
        /* set up GPIO */
-       gpio = spec->gpio_data;
        /* turn on EAPD statically when spec->eapd_switch isn't set.
         * otherwise, unsol event will turn it on/off dynamically
         */
        if (!spec->eapd_switch)
-               gpio |= spec->eapd_mask;
-       stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, gpio);
+               spec->gpio_data |= spec->eapd_mask;
+       stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
 
        snd_hda_gen_init(codec);
 
@@ -3921,6 +3922,7 @@ static void stac_setup_gpio(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
 
+       spec->gpio_mask |= spec->eapd_mask;
        if (spec->gpio_led) {
                if (!spec->vref_mute_led_nid) {
                        spec->gpio_mask |= spec->gpio_led;
index e5245544eb52bbecaaf0ff3e60b6f4f25d80d3c3..aed19c3f8466d1224fa403055f0d76cc428fecf8 100644 (file)
@@ -910,6 +910,8 @@ static const struct hda_verb vt1708S_init_verbs[] = {
 static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
                               int offset, int num_steps, int step_size)
 {
+       snd_hda_override_wcaps(codec, pin,
+                              get_wcaps(codec, pin) | AC_WCAP_IN_AMP);
        snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
                                  (offset << AC_AMPCAP_OFFSET_SHIFT) |
                                  (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |
index 1d38fd0bc4e26bd49772d7e030efb7e283e5687f..d12826526798fc47620e4cb613df9e95da8a8f7c 100644 (file)
@@ -81,7 +81,9 @@ static void atmel_pcm_dma_irq(u32 ssc_sr,
 
                /* stop RX and capture: will be enabled again at restart */
                ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_disable);
+               snd_pcm_stream_lock(substream);
                snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+               snd_pcm_stream_unlock(substream);
 
                /* now drain RHR and read status to remove xrun condition */
                ssc_readx(prtd->ssc->regs, SSC_RHR);
index 987f728718c52cad7ee2a5f1c5dd8dc2fc6d3f02..ee25f325d65c15ecc5adfa85f54e5acc2b8bf348 100644 (file)
@@ -451,7 +451,7 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
        SOC_ENUM("Beep Pitch", beep_pitch_enum),
        SOC_ENUM("Beep on Time", beep_ontime_enum),
        SOC_ENUM("Beep off Time", beep_offtime_enum),
-       SOC_SINGLE_TLV("Beep Volume", CS42L52_BEEP_VOL, 0, 0x1f, 0x07, hl_tlv),
+       SOC_SINGLE_SX_TLV("Beep Volume", CS42L52_BEEP_VOL, 0, 0x07, 0x1f, hl_tlv),
        SOC_SINGLE("Beep Mixer Switch", CS42L52_BEEP_TONE_CTL, 5, 1, 1),
        SOC_ENUM("Beep Treble Corner Freq", beep_treble_enum),
        SOC_ENUM("Beep Bass Corner Freq", beep_bass_enum),
index 3eeada57e87de68b43394e3440805de03932d890..566a367c94fa0ce71ac04f86686923ed63ece58d 100644 (file)
@@ -1612,7 +1612,7 @@ static int max98088_dai2_digital_mute(struct snd_soc_dai *codec_dai, int mute)
 
 static void max98088_sync_cache(struct snd_soc_codec *codec)
 {
-       u16 *reg_cache = codec->reg_cache;
+       u8 *reg_cache = codec->reg_cache;
        int i;
 
        if (!codec->cache_sync)
index 5402dfbbb7162f668d8841a83ad3c04db5d2516f..8a8d9364e87f09e437a8839331e44455fda33194 100644 (file)
@@ -126,6 +126,10 @@ static int mc13783_write(struct snd_soc_codec *codec,
 
        ret = mc13xxx_reg_write(priv->mc13xxx, reg, value);
 
+       /* include errata fix for spi audio problems */
+       if (reg == MC13783_AUDIO_CODEC || reg == MC13783_AUDIO_DAC)
+               ret = mc13xxx_reg_write(priv->mc13xxx, reg, value);
+
        mc13xxx_unlock(priv->mc13xxx);
 
        return ret;
index 92bbfec9b107a0ec5ee55205b9272ce9e67caa74..ea479388fb5c55d80fbffbd77e586b330b6ba0da 100644 (file)
@@ -37,7 +37,7 @@
 static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET] =  {
        [SGTL5000_CHIP_CLK_CTRL] = 0x0008,
        [SGTL5000_CHIP_I2S_CTRL] = 0x0010,
-       [SGTL5000_CHIP_SSS_CTRL] = 0x0008,
+       [SGTL5000_CHIP_SSS_CTRL] = 0x0010,
        [SGTL5000_CHIP_DAC_VOL] = 0x3c3c,
        [SGTL5000_CHIP_PAD_STRENGTH] = 0x015f,
        [SGTL5000_CHIP_ANA_HP_CTRL] = 0x1818,
index 8a9f43534b79569bb69c0ce0b012a74489ca815d..d3a68bbfea007e358d47b5557df78d5c3a045535 100644 (file)
 #define SGTL5000_PLL_INT_DIV_MASK              0xf800
 #define SGTL5000_PLL_INT_DIV_SHIFT             11
 #define SGTL5000_PLL_INT_DIV_WIDTH             5
-#define SGTL5000_PLL_FRAC_DIV_MASK             0x0700
+#define SGTL5000_PLL_FRAC_DIV_MASK             0x07ff
 #define SGTL5000_PLL_FRAC_DIV_SHIFT            0
 #define SGTL5000_PLL_FRAC_DIV_WIDTH            11
 
index 0a4ffdd1d2a70eb19c22445365d0acc5cc854dee..5e5af898f7f837164c4b1df775fafda5bb1cfafa 100644 (file)
@@ -857,9 +857,9 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
        if (pll_div.k) {
                reg |= 0x20;
 
-               snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f);
-               snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff);
-               snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0x1ff);
+               snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 16) & 0xff);
+               snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 8) & 0xff);
+               snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0xff);
        }
        snd_soc_write(codec, WM8960_PLL1, reg);
 
index e9710280e5e18b882242f8d5b4cb61a2492e8eae..730dd0c0f0ab70ad62ed4865a1c305d9a71870cb 100644 (file)
@@ -1600,7 +1600,6 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
                            struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       u16 *reg_cache = codec->reg_cache;
        int ret;
 
        /* Apply the update (if any) */
@@ -1609,16 +1608,19 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
                return 0;
 
        /* If the left PGA is enabled hit that VU bit... */
-       if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTL_PGA_ENA)
-               return snd_soc_write(codec, WM8962_HPOUTL_VOLUME,
-                                    reg_cache[WM8962_HPOUTL_VOLUME]);
+       ret = snd_soc_read(codec, WM8962_PWR_MGMT_2);
+       if (ret & WM8962_HPOUTL_PGA_ENA) {
+               snd_soc_write(codec, WM8962_HPOUTL_VOLUME,
+                             snd_soc_read(codec, WM8962_HPOUTL_VOLUME));
+               return 1;
+       }
 
        /* ...otherwise the right.  The VU is stereo. */
-       if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTR_PGA_ENA)
-               return snd_soc_write(codec, WM8962_HPOUTR_VOLUME,
-                                    reg_cache[WM8962_HPOUTR_VOLUME]);
+       if (ret & WM8962_HPOUTR_PGA_ENA)
+               snd_soc_write(codec, WM8962_HPOUTR_VOLUME,
+                             snd_soc_read(codec, WM8962_HPOUTR_VOLUME));
 
-       return 0;
+       return 1;
 }
 
 /* The VU bits for the speakers are in a different register to the mute
@@ -3374,7 +3376,6 @@ static int wm8962_probe(struct snd_soc_codec *codec)
        int ret;
        struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
        struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
-       u16 *reg_cache = codec->reg_cache;
        int i, trigger, irq_pol;
        bool dmicclk, dmicdat;
 
@@ -3432,8 +3433,9 @@ static int wm8962_probe(struct snd_soc_codec *codec)
 
                /* Put the speakers into mono mode? */
                if (pdata->spk_mono)
-                       reg_cache[WM8962_CLASS_D_CONTROL_2]
-                               |= WM8962_SPK_MONO;
+                       snd_soc_update_bits(codec, WM8962_CLASS_D_CONTROL_2,
+                               WM8962_SPK_MONO_MASK, WM8962_SPK_MONO);
+
 
                /* Micbias setup, detection enable and detection
                 * threasholds. */
index 1358c7de2521b7c296aaf2b031f78cf662523c96..d0740a762963d867bf75cce29d20c15c0a4b5097 100644 (file)
@@ -128,7 +128,9 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)
                    substream->runtime &&
                    snd_pcm_running(substream)) {
                        dev_dbg(pcm->dev, "xrun\n");
+                       snd_pcm_stream_lock(substream);
                        snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+                       snd_pcm_stream_unlock(substream);
                        ret = IRQ_HANDLED;
                }
 
index c7051c457b75c0f09acdd9cd1e39ef62eda22f0f..360638362e98e528eae5b2ba796868340726d3db 100644 (file)
@@ -682,13 +682,14 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
                return -EINVAL;
        }
 
-       path = list_first_entry(&w->sources, struct snd_soc_dapm_path,
-                               list_sink);
-       if (!path) {
+       if (list_empty(&w->sources)) {
                dev_err(dapm->dev, "ASoC: mux %s has no paths\n", w->name);
                return -EINVAL;
        }
 
+       path = list_first_entry(&w->sources, struct snd_soc_dapm_path,
+                               list_sink);
+
        ret = dapm_create_or_share_mixmux_kcontrol(w, 0, path);
        if (ret < 0)
                return ret;
index 2f70ea7f6618ae04dc8f125925638d4e9f90c147..05676c022a165d3bc8ebb920c4fe51b1014a7811 100644 (file)
@@ -399,9 +399,9 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
        ac97->capture_dma_data.slave_id = of_dma[1];
 
        ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1;
-       ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       ac97->capture_dma_data.maxburst = 4;
-       ac97->capture_dma_data.slave_id = of_dma[0];
+       ac97->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       ac97->playback_dma_data.maxburst = 4;
+       ac97->playback_dma_data.slave_id = of_dma[1];
 
        ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component,
                                         &tegra20_ac97_dai, 1);
index 5eaa12cdc6ebd3bfcbd502beb1aff881c111d406..551b3c93ce932c77e9e05de4bcf01f5af63d1c94 100644 (file)
@@ -323,8 +323,8 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev)
        }
 
        spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT;
-       spdif->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       spdif->capture_dma_data.maxburst = 4;
+       spdif->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       spdif->playback_dma_data.maxburst = 4;
        spdif->playback_dma_data.slave_id = dmareq->start;
 
        pm_runtime_enable(&pdev->dev);
index 31d092d83c71e5981cc36adee0ca0655e308bde1..a5432b10eaca16d681ed8a2baa7755a021ac82cf 100644 (file)
@@ -228,7 +228,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
                reg = TEGRA30_I2S_CIF_RX_CTRL;
        } else {
                val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
-               reg = TEGRA30_I2S_CIF_RX_CTRL;
+               reg = TEGRA30_I2S_CIF_TX_CTRL;
        }
 
        regmap_write(i2s->regmap, reg, val);
index 9e6e3ffd86bbbc4212e72eb3d0c7cd69e6d44c8e..23452ee617e11a5d304fffbd0da3e7bea805e0dc 100644 (file)
@@ -110,19 +110,37 @@ static int usb6fire_comm_send_buffer(u8 *buffer, struct usb_device *dev)
 static int usb6fire_comm_write8(struct comm_runtime *rt, u8 request,
                u8 reg, u8 value)
 {
-       u8 buffer[13]; /* 13: maximum length of message */
+       u8 *buffer;
+       int ret;
+
+       /* 13: maximum length of message */
+       buffer = kmalloc(13, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
 
        usb6fire_comm_init_buffer(buffer, 0x00, request, reg, value, 0x00);
-       return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+       ret = usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+
+       kfree(buffer);
+       return ret;
 }
 
 static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request,
                u8 reg, u8 vl, u8 vh)
 {
-       u8 buffer[13]; /* 13: maximum length of message */
+       u8 *buffer;
+       int ret;
+
+       /* 13: maximum length of message */
+       buffer = kmalloc(13, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
 
        usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl, vh);
-       return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+       ret = usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+
+       kfree(buffer);
+       return ret;
 }
 
 int usb6fire_comm_init(struct sfire_chip *chip)
@@ -135,6 +153,12 @@ int usb6fire_comm_init(struct sfire_chip *chip)
        if (!rt)
                return -ENOMEM;
 
+       rt->receiver_buffer = kzalloc(COMM_RECEIVER_BUFSIZE, GFP_KERNEL);
+       if (!rt->receiver_buffer) {
+               kfree(rt);
+               return -ENOMEM;
+       }
+
        urb = &rt->receiver;
        rt->serial = 1;
        rt->chip = chip;
@@ -153,6 +177,7 @@ int usb6fire_comm_init(struct sfire_chip *chip)
        urb->interval = 1;
        ret = usb_submit_urb(urb, GFP_KERNEL);
        if (ret < 0) {
+               kfree(rt->receiver_buffer);
                kfree(rt);
                snd_printk(KERN_ERR PREFIX "cannot create comm data receiver.");
                return ret;
@@ -171,6 +196,9 @@ void usb6fire_comm_abort(struct sfire_chip *chip)
 
 void usb6fire_comm_destroy(struct sfire_chip *chip)
 {
-       kfree(chip->comm);
+       struct comm_runtime *rt = chip->comm;
+
+       kfree(rt->receiver_buffer);
+       kfree(rt);
        chip->comm = NULL;
 }
index 6a0840b0dcff2be78366119126e5842aa4ab325f..780d5ed8e5d8a39ff9bec150d9840fcbbef713d8 100644 (file)
@@ -24,7 +24,7 @@ struct comm_runtime {
        struct sfire_chip *chip;
 
        struct urb receiver;
-       u8 receiver_buffer[COMM_RECEIVER_BUFSIZE];
+       u8 *receiver_buffer;
 
        u8 serial; /* urb serial */
 
index 26722423330dd283b62d3fd4c5b77409913372cb..f3dd7266c391c7f17dae6220ed094f548a1d4507 100644 (file)
 #include "chip.h"
 #include "comm.h"
 
+enum {
+       MIDI_BUFSIZE = 64
+};
+
 static void usb6fire_midi_out_handler(struct urb *urb)
 {
        struct midi_runtime *rt = urb->context;
@@ -156,6 +160,12 @@ int usb6fire_midi_init(struct sfire_chip *chip)
        if (!rt)
                return -ENOMEM;
 
+       rt->out_buffer = kzalloc(MIDI_BUFSIZE, GFP_KERNEL);
+       if (!rt->out_buffer) {
+               kfree(rt);
+               return -ENOMEM;
+       }
+
        rt->chip = chip;
        rt->in_received = usb6fire_midi_in_received;
        rt->out_buffer[0] = 0x80; /* 'send midi' command */
@@ -169,6 +179,7 @@ int usb6fire_midi_init(struct sfire_chip *chip)
 
        ret = snd_rawmidi_new(chip->card, "6FireUSB", 0, 1, 1, &rt->instance);
        if (ret < 0) {
+               kfree(rt->out_buffer);
                kfree(rt);
                snd_printk(KERN_ERR PREFIX "unable to create midi.\n");
                return ret;
@@ -197,6 +208,9 @@ void usb6fire_midi_abort(struct sfire_chip *chip)
 
 void usb6fire_midi_destroy(struct sfire_chip *chip)
 {
-       kfree(chip->midi);
+       struct midi_runtime *rt = chip->midi;
+
+       kfree(rt->out_buffer);
+       kfree(rt);
        chip->midi = NULL;
 }
index c321006e5430ac763e593ecee6314c6cee8fd2d6..84851b9f55592f2ddc4b35781e1efa20cac5cd02 100644 (file)
 
 #include "common.h"
 
-enum {
-       MIDI_BUFSIZE = 64
-};
-
 struct midi_runtime {
        struct sfire_chip *chip;
        struct snd_rawmidi *instance;
@@ -32,7 +28,7 @@ struct midi_runtime {
        struct snd_rawmidi_substream *out;
        struct urb out_urb;
        u8 out_serial; /* serial number of out packet */
-       u8 out_buffer[MIDI_BUFSIZE];
+       u8 *out_buffer;
        int buffer_offset;
 
        void (*in_received)(struct midi_runtime *rt, u8 *data, int length);
index 40dd50a80f55de653ffc30c2c4a4960c4d868025..25f9e61ad883cfcd4ce1f220a9f8b2ede0282257 100644 (file)
@@ -543,7 +543,7 @@ static snd_pcm_uframes_t usb6fire_pcm_pointer(
        snd_pcm_uframes_t ret;
 
        if (rt->panic || !sub)
-               return SNDRV_PCM_STATE_XRUN;
+               return SNDRV_PCM_POS_XRUN;
 
        spin_lock_irqsave(&sub->lock, flags);
        ret = sub->dma_off;
@@ -580,6 +580,33 @@ static void usb6fire_pcm_init_urb(struct pcm_urb *urb,
        urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB;
 }
 
+static int usb6fire_pcm_buffers_init(struct pcm_runtime *rt)
+{
+       int i;
+
+       for (i = 0; i < PCM_N_URBS; i++) {
+               rt->out_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB
+                               * PCM_MAX_PACKET_SIZE, GFP_KERNEL);
+               if (!rt->out_urbs[i].buffer)
+                       return -ENOMEM;
+               rt->in_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB
+                               * PCM_MAX_PACKET_SIZE, GFP_KERNEL);
+               if (!rt->in_urbs[i].buffer)
+                       return -ENOMEM;
+       }
+       return 0;
+}
+
+static void usb6fire_pcm_buffers_destroy(struct pcm_runtime *rt)
+{
+       int i;
+
+       for (i = 0; i < PCM_N_URBS; i++) {
+               kfree(rt->out_urbs[i].buffer);
+               kfree(rt->in_urbs[i].buffer);
+       }
+}
+
 int usb6fire_pcm_init(struct sfire_chip *chip)
 {
        int i;
@@ -591,6 +618,13 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
        if (!rt)
                return -ENOMEM;
 
+       ret = usb6fire_pcm_buffers_init(rt);
+       if (ret) {
+               usb6fire_pcm_buffers_destroy(rt);
+               kfree(rt);
+               return ret;
+       }
+
        rt->chip = chip;
        rt->stream_state = STREAM_DISABLED;
        rt->rate = ARRAY_SIZE(rates);
@@ -612,6 +646,7 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
 
        ret = snd_pcm_new(chip->card, "DMX6FireUSB", 0, 1, 1, &pcm);
        if (ret < 0) {
+               usb6fire_pcm_buffers_destroy(rt);
                kfree(rt);
                snd_printk(KERN_ERR PREFIX "cannot create pcm instance.\n");
                return ret;
@@ -627,6 +662,7 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
                        snd_dma_continuous_data(GFP_KERNEL),
                        MAX_BUFSIZE, MAX_BUFSIZE);
        if (ret) {
+               usb6fire_pcm_buffers_destroy(rt);
                kfree(rt);
                snd_printk(KERN_ERR PREFIX
                                "error preallocating pcm buffers.\n");
@@ -641,17 +677,25 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
 void usb6fire_pcm_abort(struct sfire_chip *chip)
 {
        struct pcm_runtime *rt = chip->pcm;
+       unsigned long flags;
        int i;
 
        if (rt) {
                rt->panic = true;
 
-               if (rt->playback.instance)
+               if (rt->playback.instance) {
+                       snd_pcm_stream_lock_irqsave(rt->playback.instance, flags);
                        snd_pcm_stop(rt->playback.instance,
                                        SNDRV_PCM_STATE_XRUN);
-               if (rt->capture.instance)
+                       snd_pcm_stream_unlock_irqrestore(rt->playback.instance, flags);
+               }
+
+               if (rt->capture.instance) {
+                       snd_pcm_stream_lock_irqsave(rt->capture.instance, flags);
                        snd_pcm_stop(rt->capture.instance,
                                        SNDRV_PCM_STATE_XRUN);
+                       snd_pcm_stream_unlock_irqrestore(rt->capture.instance, flags);
+               }
 
                for (i = 0; i < PCM_N_URBS; i++) {
                        usb_poison_urb(&rt->in_urbs[i].instance);
@@ -663,6 +707,9 @@ void usb6fire_pcm_abort(struct sfire_chip *chip)
 
 void usb6fire_pcm_destroy(struct sfire_chip *chip)
 {
-       kfree(chip->pcm);
+       struct pcm_runtime *rt = chip->pcm;
+
+       usb6fire_pcm_buffers_destroy(rt);
+       kfree(rt);
        chip->pcm = NULL;
 }
index 9b01133ee3fe9c22d3f51557430f011846e5bc8a..f5779d6182c638b02253af7bc9ab73dfed7e1916 100644 (file)
@@ -32,7 +32,7 @@ struct pcm_urb {
        struct urb instance;
        struct usb_iso_packet_descriptor packets[PCM_N_PACKETS_PER_URB];
        /* END DO NOT SEPARATE */
-       u8 buffer[PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE];
+       u8 *buffer;
 
        struct pcm_urb *peer;
 };
index 7a444b5501d91d28a4e7e8fb5e044c2b4e7ea41b..659950e5b94f6b411577a84821f1a1c4d93b4593 100644 (file)
@@ -591,17 +591,16 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
        ep->stride = frame_bits >> 3;
        ep->silence_value = pcm_format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0;
 
-       /* calculate max. frequency */
-       if (ep->maxpacksize) {
+       /* assume max. frequency is 25% higher than nominal */
+       ep->freqmax = ep->freqn + (ep->freqn >> 2);
+       maxsize = ((ep->freqmax + 0xffff) * (frame_bits >> 3))
+                               >> (16 - ep->datainterval);
+       /* but wMaxPacketSize might reduce this */
+       if (ep->maxpacksize && ep->maxpacksize < maxsize) {
                /* whatever fits into a max. size packet */
                maxsize = ep->maxpacksize;
                ep->freqmax = (maxsize / (frame_bits >> 3))
                                << (16 - ep->datainterval);
-       } else {
-               /* no max. packet size: just take 25% higher than nominal */
-               ep->freqmax = ep->freqn + (ep->freqn >> 2);
-               maxsize = ((ep->freqmax + 0xffff) * (frame_bits >> 3))
-                               >> (16 - ep->datainterval);
        }
 
        if (ep->fill_max)
index 6ad617b947321b438d3ae1b1071364109747d379..76d832908fe0c9f1713fe4fb1397d7d07c081499 100644 (file)
@@ -613,14 +613,24 @@ static int start_usb_playback(struct ua101 *ua)
 
 static void abort_alsa_capture(struct ua101 *ua)
 {
-       if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states))
+       unsigned long flags;
+
+       if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states)) {
+               snd_pcm_stream_lock_irqsave(ua->capture.substream, flags);
                snd_pcm_stop(ua->capture.substream, SNDRV_PCM_STATE_XRUN);
+               snd_pcm_stream_unlock_irqrestore(ua->capture.substream, flags);
+       }
 }
 
 static void abort_alsa_playback(struct ua101 *ua)
 {
-       if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states))
+       unsigned long flags;
+
+       if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) {
+               snd_pcm_stream_lock_irqsave(ua->playback.substream, flags);
                snd_pcm_stop(ua->playback.substream, SNDRV_PCM_STATE_XRUN);
+               snd_pcm_stream_unlock_irqrestore(ua->playback.substream, flags);
+       }
 }
 
 static int set_stream_hw(struct ua101 *ua, struct snd_pcm_substream *substream,
index d5438083fd6a8072c20275778f1f3b9fa0a42517..95558ef4a7a09c72ed52c4706348d765a40c4314 100644 (file)
@@ -888,6 +888,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
        case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */
        case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */
        case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */
+       case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */
        case USB_ID(0x046d, 0x0991):
        /* Most audio usb devices lie about volume resolution.
         * Most Logitech webcams have res = 384.
index b37653247ef4e035b096153253b69ca0fd1e9a8b..0ce903375eaff1f7069f8427e6fa839c474a6552 100644 (file)
@@ -273,7 +273,11 @@ static void usX2Y_clients_stop(struct usX2Ydev *usX2Y)
                struct snd_usX2Y_substream *subs = usX2Y->subs[s];
                if (subs) {
                        if (atomic_read(&subs->state) >= state_PRERUNNING) {
+                               unsigned long flags;
+
+                               snd_pcm_stream_lock_irqsave(subs->pcm_substream, flags);
                                snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
+                               snd_pcm_stream_unlock_irqrestore(subs->pcm_substream, flags);
                        }
                        for (u = 0; u < NRURBS; u++) {
                                struct urb *urb = subs->urb[u];
index 5a1f6489d185a10f20616de81c6d145f3ff01b86..274e17867a3aa6dd13bd4ef0dc7bb843dd70d0c1 100644 (file)
@@ -1016,9 +1016,10 @@ kvp_get_ip_info(int family, char *if_name, int op,
 
                                if (sn_offset == 0)
                                        strcpy(sn_str, cidr_mask);
-                               else
+                               else {
+                                       strcat((char *)ip_buffer->sub_net, ";");
                                        strcat(sn_str, cidr_mask);
-                               strcat((char *)ip_buffer->sub_net, ";");
+                               }
                                sn_offset += strlen(sn_str) + 1;
                        }
 
index 8ef3bd30a5492afa002c928b4483e03ac16db790..3e897198d1f78d0f9b6e5b5848fff0308fd16f04 100644 (file)
@@ -173,7 +173,7 @@ _ge-abspath = $(if $(is-executable),$(1))
 # Usage: absolute-executable-path-or-empty = $(call get-executable-or-default,variable,default)
 #
 define get-executable-or-default
-$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2),$(1)))
+$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2)))
 endef
 _ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2)))
 _gea_warn = $(warning The path '$(1)' is not executable.)