]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 23 Feb 2009 22:38:20 +0000 (14:38 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 23 Feb 2009 22:38:20 +0000 (14:38 -0800)
* git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6:
  crypto: ahash - Fix digest size in /proc/crypto

377 files changed:
CREDITS
Documentation/ABI/testing/sysfs-firmware-memmap
Documentation/DocBook/Makefile
Documentation/DocBook/device-drivers.tmpl [new file with mode: 0644]
Documentation/DocBook/kernel-api.tmpl
Documentation/PCI/PCIEBUS-HOWTO.txt
Documentation/cgroups/cgroups.txt
Documentation/cgroups/cpusets.txt
Documentation/driver-model/device.txt
Documentation/filesystems/sysfs.txt
Documentation/hwmon/hpfall.c [new file with mode: 0644]
Documentation/hwmon/lis3lv02d
Documentation/kernel-parameters.txt
Documentation/tracers/mmiotrace.txt
MAINTAINERS
Makefile
README
arch/alpha/kernel/process.c
arch/alpha/kernel/smp.c
arch/arm/configs/at91sam9260ek_defconfig
arch/arm/configs/at91sam9261ek_defconfig
arch/arm/configs/at91sam9263ek_defconfig
arch/arm/configs/at91sam9rlek_defconfig
arch/arm/configs/qil-a9260_defconfig
arch/arm/kernel/elf.c
arch/arm/mach-at91/at91cap9_devices.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/gpio.c
arch/arm/mach-at91/include/mach/board.h
arch/arm/mach-ep93xx/include/mach/gesbc9312.h [deleted file]
arch/arm/mach-ep93xx/include/mach/hardware.h
arch/arm/mach-kirkwood/irq.c
arch/arm/mach-mv78xx0/irq.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-orion5x/irq.c
arch/arm/mm/mmu.c
arch/arm/plat-orion/gpio.c
arch/arm/plat-orion/include/plat/gpio.h
arch/avr32/mach-at32ap/include/mach/board.h
arch/ia64/Kconfig
arch/ia64/configs/xen_domu_defconfig [new file with mode: 0644]
arch/ia64/include/asm/kvm.h
arch/ia64/include/asm/mmzone.h
arch/ia64/include/asm/sn/bte.h
arch/ia64/kernel/smpboot.c
arch/ia64/kvm/kvm-ia64.c
arch/ia64/kvm/process.c
arch/ia64/mm/numa.c
arch/ia64/sn/kernel/bte.c
arch/ia64/xen/Kconfig
arch/ia64/xen/xen_pv_ops.c
arch/m68k/atari/ataints.c
arch/m68k/atari/atakeyb.c
arch/m68k/atari/config.c
arch/m68k/atari/debug.c
arch/m68k/atari/time.c
arch/m68k/include/asm/atarihw.h
arch/m68k/include/asm/atariints.h
arch/mn10300/Kconfig
arch/mn10300/unit-asb2305/pci.c
arch/powerpc/include/asm/pgtable-4k.h
arch/powerpc/include/asm/pgtable-64k.h
arch/powerpc/include/asm/pgtable-ppc32.h
arch/powerpc/kernel/align.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/mm/numa.c
arch/powerpc/platforms/ps3/mm.c
arch/s390/include/asm/cputime.h
arch/s390/include/asm/setup.h
arch/s390/kernel/setup.c
arch/s390/kvm/kvm-s390.c
arch/um/drivers/vde_user.c
arch/x86/Kconfig.debug
arch/x86/include/asm/kvm.h
arch/x86/include/asm/mmzone_32.h
arch/x86/include/asm/mmzone_64.h
arch/x86/include/asm/page.h
arch/x86/include/asm/paravirt.h
arch/x86/kernel/acpi/wakeup_64.S
arch/x86/kernel/apic.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/cpu/cpufreq/powernow-k8.c
arch/x86/kernel/cpu/mcheck/mce_64.c
arch/x86/kernel/cpu/mcheck/mce_amd_64.c
arch/x86/kernel/cpu/mcheck/mce_intel_64.c
arch/x86/kernel/hpet.c
arch/x86/kernel/olpc.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/process_32.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/time_64.c
arch/x86/kernel/traps.c
arch/x86/kernel/vmiclock_32.c
arch/x86/kvm/i8254.c
arch/x86/kvm/irq.c
arch/x86/kvm/irq.h
arch/x86/kvm/lapic.c
arch/x86/kvm/lapic.h
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mach-default/setup.c
arch/x86/mach-voyager/setup.c
arch/x86/mm/ioremap.c
arch/x86/mm/numa_64.c
arch/x86/mm/pageattr.c
arch/x86/mm/pat.c
block/blk-timeout.c
block/blktrace.c
block/bsg.c
block/genhd.c
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/battery.c
drivers/acpi/ec.c
drivers/ata/libata-sff.c
drivers/ata/pata_via.c
drivers/ata/sata_nv.c
drivers/atm/lanai.c
drivers/base/base.h
drivers/base/dd.c
drivers/base/power/main.c
drivers/base/sys.c
drivers/block/aoe/aoe.h
drivers/block/aoe/aoenet.c
drivers/block/ataflop.c
drivers/block/cciss.c
drivers/block/floppy.c
drivers/block/paride/pg.c
drivers/char/scc.h
drivers/char/sx.c
drivers/dma/dmaengine.c
drivers/dma/dw_dmac.c
drivers/dma/dw_dmac_regs.h
drivers/firmware/memmap.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/drm_gem.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_tiling.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_fb.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/radeon/radeon_cp.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hidraw.c
drivers/hwmon/f71882fg.c
drivers/hwmon/hp_accel.c
drivers/hwmon/lis3lv02d.c
drivers/hwmon/lis3lv02d.h
drivers/hwmon/vt1211.c
drivers/hwmon/w83627ehf.c
drivers/isdn/sc/shmem.c
drivers/md/dm-io.c
drivers/md/dm-kcopyd.c
drivers/md/md.c
drivers/media/common/tuners/tuner-simple.c
drivers/media/dvb/dvb-core/dmxdev.c
drivers/media/dvb/dvb-core/dvb_demux.c
drivers/media/radio/radio-si470x.c
drivers/media/video/gspca/gspca.c
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/mfd/htc-egpio.c
drivers/mfd/pcf50633-core.c
drivers/mfd/sm501.c
drivers/mfd/twl4030-core.c
drivers/mfd/wm8350-core.c
drivers/mfd/wm8350-regmap.c
drivers/mmc/card/block.c
drivers/mmc/card/mmc_test.c
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/s3cmci.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mtd/nand/atmel_nand.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/atl1c/Makefile [new file with mode: 0644]
drivers/net/atl1c/atl1c.h [new file with mode: 0644]
drivers/net/atl1c/atl1c_ethtool.c [new file with mode: 0644]
drivers/net/atl1c/atl1c_hw.c [new file with mode: 0644]
drivers/net/atl1c/atl1c_hw.h [new file with mode: 0644]
drivers/net/atl1c/atl1c_main.c [new file with mode: 0644]
drivers/net/cxgb3/cxgb3_main.c
drivers/net/cxgb3/t3_hw.c
drivers/net/forcedeth.c
drivers/net/mv643xx_eth.c
drivers/net/smsc911x.c
drivers/net/smsc9420.c
drivers/net/smsc9420.h
drivers/net/sundance.c
drivers/net/sungem.c
drivers/net/sunlance.c
drivers/net/tg3.c
drivers/net/veth.c
drivers/net/wimax/i2400m/i2400m.h
drivers/parport/parport_atari.c
drivers/pci/intel-iommu.c
drivers/pci/msi.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/rom.c
drivers/platform/x86/Kconfig
drivers/platform/x86/fujitsu-laptop.c
drivers/s390/char/sclp.c
drivers/s390/char/sclp_cmd.c
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ibmvscsi/ibmvfc.h
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/libiscsi.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_devtbl.h
drivers/scsi/qla2xxx/qla_fw.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_sup.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/scsi_scan.c
drivers/scsi/sg.c
drivers/serial/8250.c
drivers/serial/8250_pci.c
drivers/serial/atmel_serial.c
drivers/serial/jsm/jsm_driver.c
drivers/spi/spi_gpio.c
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd.h
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/uhci-hcd.c
drivers/usb/host/whci/asl.c
drivers/usb/host/whci/pzl.c
drivers/video/Kconfig
drivers/video/atafb.c
drivers/video/aty/aty128fb.c
drivers/watchdog/Kconfig
drivers/watchdog/at91rm9200_wdt.c
drivers/watchdog/at91sam9_wdt.c
drivers/watchdog/iTCO_vendor_support.c
drivers/watchdog/iTCO_wdt.c
drivers/xen/manage.c
fs/bio.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/file.c
fs/btrfs/inode-map.c
fs/btrfs/inode.c
fs/btrfs/locking.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/buffer.c
fs/cifs/CHANGES
fs/cifs/cifsfs.h
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/inode.c
fs/cifs/readdir.c
fs/cifs/sess.c
fs/compat_ioctl.c
fs/ext4/ext4.h
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/migrate.c
fs/ext4/super.c
fs/jbd2/journal.c
fs/jbd2/transaction.c
fs/namespace.c
fs/notify/inotify/inotify.c
fs/ocfs2/journal.h
fs/seq_file.c
fs/super.c
fs/timerfd.c
fs/xfs/linux-2.6/xfs_buf.c
include/asm-frv/pgtable.h
include/drm/drmP.h
include/drm/drm_crtc.h
include/drm/drm_crtc_helper.h
include/linux/bio.h
include/linux/blktrace_api.h
include/linux/device.h
include/linux/dmaengine.h
include/linux/firmware-map.h
include/linux/fs.h
include/linux/if_vlan.h
include/linux/jbd2.h
include/linux/kvm.h
include/linux/kvm_host.h
include/linux/mm.h
include/linux/mmzone.h
include/linux/pci_ids.h
include/linux/pm.h
include/linux/seq_file.h
include/linux/serial_core.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/spi/spi_bitbang.h
include/linux/timerfd.h
include/linux/vmalloc.h
include/net/sock.h
init/do_mounts.c
init/do_mounts_md.c
kernel/Makefile
kernel/cgroup.c
kernel/futex.c
kernel/kexec.c
kernel/posix-cpu-timers.c
kernel/power/Makefile
kernel/power/console.c
kernel/power/disk.c
kernel/power/main.c
kernel/power/swap.c
kernel/power/user.c
kernel/printk.c
kernel/sched.c
kernel/trace/Kconfig
kernel/trace/ftrace.c
kernel/trace/trace_mmiotrace.c
kernel/trace/trace_selftest.c
lib/Kconfig.debug
mm/mlock.c
mm/page-writeback.c
mm/page_alloc.c
mm/page_io.c
mm/swapfile.c
mm/util.c
mm/vmalloc.c
mm/vmscan.c
net/core/net_namespace.c
net/core/skbuff.c
net/core/sock.c
net/ipv4/cipso_ipv4.c
net/ipv4/tcp_output.c
scripts/bootgraph.pl
scripts/markup_oops.pl
scripts/mod/file2alias.c
scripts/package/mkspec
scripts/setlocalversion
scripts/tags.sh
security/selinux/netlabel.c
sound/core/jack.c
sound/oss/dmasound/dmasound_atari.c
sound/pci/hda/hda_intel.c
sound/pci/oxygen/virtuoso.c
sound/usb/usbaudio.c
sound/usb/usbmidi.c
virt/kvm/iommu.c
virt/kvm/kvm_main.c

diff --git a/CREDITS b/CREDITS
index 2b39168c06aabe35bc35c10753cb42438e65eaed..5e0736722afd547659c491ad2ee503e57336435d 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2166,7 +2166,6 @@ D: Initial implementation of VC's, pty's and select()
 
 N: Pavel Machek
 E: pavel@ucw.cz
-E: pavel@suse.cz
 D: Softcursor for vga, hypertech cdrom support, vcsa bugfix, nbd
 D: sun4/330 port, capabilities for elf, speedup for rm on ext2, USB,
 D: work on suspend-to-ram/disk, killing duplicates from ioctl32
index 0d99ee6ae02ec786aef9ed6373bc91d1f5d1fb19..eca0d65087dc4239352add5f2167a85ae7a179e8 100644 (file)
@@ -1,6 +1,6 @@
 What:          /sys/firmware/memmap/
 Date:          June 2008
-Contact:       Bernhard Walle <bwalle@suse.de>
+Contact:       Bernhard Walle <bernhard.walle@gmx.de>
 Description:
                On all platforms, the firmware provides a memory map which the
                kernel reads. The resources from that memory map are registered
index dc3154e49279b6f95935df1665b6f25ad0d4c1a1..1462ed86d40aec28e0d54e947c93ad43f22333ae 100644 (file)
@@ -6,7 +6,7 @@
 # To add a new book the only step required is to add the book to the
 # list of DOCBOOKS.
 
-DOCBOOKS := z8530book.xml mcabook.xml \
+DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
            kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
            procfs-guide.xml writing_usb_driver.xml networking.xml \
            kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
new file mode 100644 (file)
index 0000000..94a20fe
--- /dev/null
@@ -0,0 +1,418 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+       "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="LinuxDriversAPI">
+ <bookinfo>
+  <title>Linux Device Drivers</title>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="Basics">
+     <title>Driver Basics</title>
+     <sect1><title>Driver Entry and Exit points</title>
+!Iinclude/linux/init.h
+     </sect1>
+
+     <sect1><title>Atomic and pointer manipulation</title>
+!Iarch/x86/include/asm/atomic_32.h
+!Iarch/x86/include/asm/unaligned.h
+     </sect1>
+
+     <sect1><title>Delaying, scheduling, and timer routines</title>
+!Iinclude/linux/sched.h
+!Ekernel/sched.c
+!Ekernel/timer.c
+     </sect1>
+     <sect1><title>High-resolution timers</title>
+!Iinclude/linux/ktime.h
+!Iinclude/linux/hrtimer.h
+!Ekernel/hrtimer.c
+     </sect1>
+     <sect1><title>Workqueues and Kevents</title>
+!Ekernel/workqueue.c
+     </sect1>
+     <sect1><title>Internal Functions</title>
+!Ikernel/exit.c
+!Ikernel/signal.c
+!Iinclude/linux/kthread.h
+!Ekernel/kthread.c
+     </sect1>
+
+     <sect1><title>Kernel objects manipulation</title>
+<!--
+X!Iinclude/linux/kobject.h
+-->
+!Elib/kobject.c
+     </sect1>
+
+     <sect1><title>Kernel utility functions</title>
+!Iinclude/linux/kernel.h
+!Ekernel/printk.c
+!Ekernel/panic.c
+!Ekernel/sys.c
+!Ekernel/rcupdate.c
+     </sect1>
+
+     <sect1><title>Device Resource Management</title>
+!Edrivers/base/devres.c
+     </sect1>
+
+  </chapter>
+
+  <chapter id="devdrivers">
+     <title>Device drivers infrastructure</title>
+     <sect1><title>Device Drivers Base</title>
+<!--
+X!Iinclude/linux/device.h
+-->
+!Edrivers/base/driver.c
+!Edrivers/base/core.c
+!Edrivers/base/class.c
+!Edrivers/base/firmware_class.c
+!Edrivers/base/transport_class.c
+<!-- Cannot be included, because
+     attribute_container_add_class_device_adapter
+ and attribute_container_classdev_to_container
+     exceed allowed 44 characters maximum
+X!Edrivers/base/attribute_container.c
+-->
+!Edrivers/base/sys.c
+<!--
+X!Edrivers/base/interface.c
+-->
+!Edrivers/base/platform.c
+!Edrivers/base/bus.c
+     </sect1>
+     <sect1><title>Device Drivers Power Management</title>
+!Edrivers/base/power/main.c
+     </sect1>
+     <sect1><title>Device Drivers ACPI Support</title>
+<!-- Internal functions only
+X!Edrivers/acpi/sleep/main.c
+X!Edrivers/acpi/sleep/wakeup.c
+X!Edrivers/acpi/motherboard.c
+X!Edrivers/acpi/bus.c
+-->
+!Edrivers/acpi/scan.c
+!Idrivers/acpi/scan.c
+<!-- No correct structured comments
+X!Edrivers/acpi/pci_bind.c
+-->
+     </sect1>
+     <sect1><title>Device drivers PnP support</title>
+!Idrivers/pnp/core.c
+<!-- No correct structured comments
+X!Edrivers/pnp/system.c
+ -->
+!Edrivers/pnp/card.c
+!Idrivers/pnp/driver.c
+!Edrivers/pnp/manager.c
+!Edrivers/pnp/support.c
+     </sect1>
+     <sect1><title>Userspace IO devices</title>
+!Edrivers/uio/uio.c
+!Iinclude/linux/uio_driver.h
+     </sect1>
+  </chapter>
+
+  <chapter id="parportdev">
+     <title>Parallel Port Devices</title>
+!Iinclude/linux/parport.h
+!Edrivers/parport/ieee1284.c
+!Edrivers/parport/share.c
+!Idrivers/parport/daisy.c
+  </chapter>
+
+  <chapter id="message_devices">
+       <title>Message-based devices</title>
+     <sect1><title>Fusion message devices</title>
+!Edrivers/message/fusion/mptbase.c
+!Idrivers/message/fusion/mptbase.c
+!Edrivers/message/fusion/mptscsih.c
+!Idrivers/message/fusion/mptscsih.c
+!Idrivers/message/fusion/mptctl.c
+!Idrivers/message/fusion/mptspi.c
+!Idrivers/message/fusion/mptfc.c
+!Idrivers/message/fusion/mptlan.c
+     </sect1>
+     <sect1><title>I2O message devices</title>
+!Iinclude/linux/i2o.h
+!Idrivers/message/i2o/core.h
+!Edrivers/message/i2o/iop.c
+!Idrivers/message/i2o/iop.c
+!Idrivers/message/i2o/config-osm.c
+!Edrivers/message/i2o/exec-osm.c
+!Idrivers/message/i2o/exec-osm.c
+!Idrivers/message/i2o/bus-osm.c
+!Edrivers/message/i2o/device.c
+!Idrivers/message/i2o/device.c
+!Idrivers/message/i2o/driver.c
+!Idrivers/message/i2o/pci.c
+!Idrivers/message/i2o/i2o_block.c
+!Idrivers/message/i2o/i2o_scsi.c
+!Idrivers/message/i2o/i2o_proc.c
+     </sect1>
+  </chapter>
+
+  <chapter id="snddev">
+     <title>Sound Devices</title>
+!Iinclude/sound/core.h
+!Esound/sound_core.c
+!Iinclude/sound/pcm.h
+!Esound/core/pcm.c
+!Esound/core/device.c
+!Esound/core/info.c
+!Esound/core/rawmidi.c
+!Esound/core/sound.c
+!Esound/core/memory.c
+!Esound/core/pcm_memory.c
+!Esound/core/init.c
+!Esound/core/isadma.c
+!Esound/core/control.c
+!Esound/core/pcm_lib.c
+!Esound/core/hwdep.c
+!Esound/core/pcm_native.c
+!Esound/core/memalloc.c
+<!-- FIXME: Removed for now since no structured comments in source
+X!Isound/sound_firmware.c
+-->
+  </chapter>
+
+  <chapter id="uart16x50">
+     <title>16x50 UART Driver</title>
+!Iinclude/linux/serial_core.h
+!Edrivers/serial/serial_core.c
+!Edrivers/serial/8250.c
+  </chapter>
+
+  <chapter id="fbdev">
+     <title>Frame Buffer Library</title>
+
+     <para>
+       The frame buffer drivers depend heavily on four data structures.
+       These structures are declared in include/linux/fb.h.  They are
+       fb_info, fb_var_screeninfo, fb_fix_screeninfo and fb_monospecs.
+       The last three can be made available to and from userland.
+     </para>
+
+     <para>
+       fb_info defines the current state of a particular video card.
+       Inside fb_info, there exists a fb_ops structure which is a
+       collection of needed functions to make fbdev and fbcon work.
+       fb_info is only visible to the kernel.
+     </para>
+
+     <para>
+       fb_var_screeninfo is used to describe the features of a video card
+       that are user defined.  With fb_var_screeninfo, things such as
+       depth and the resolution may be defined.
+     </para>
+
+     <para>
+       The next structure is fb_fix_screeninfo. This defines the
+       properties of a card that are created when a mode is set and can't
+       be changed otherwise.  A good example of this is the start of the
+       frame buffer memory.  This "locks" the address of the frame buffer
+       memory, so that it cannot be changed or moved.
+     </para>
+
+     <para>
+       The last structure is fb_monospecs. In the old API, there was
+       little importance for fb_monospecs. This allowed for forbidden things
+       such as setting a mode of 800x600 on a fix frequency monitor. With
+       the new API, fb_monospecs prevents such things, and if used
+       correctly, can prevent a monitor from being cooked.  fb_monospecs
+       will not be useful until kernels 2.5.x.
+     </para>
+
+     <sect1><title>Frame Buffer Memory</title>
+!Edrivers/video/fbmem.c
+     </sect1>
+<!--
+     <sect1><title>Frame Buffer Console</title>
+X!Edrivers/video/console/fbcon.c
+     </sect1>
+-->
+     <sect1><title>Frame Buffer Colormap</title>
+!Edrivers/video/fbcmap.c
+     </sect1>
+<!-- FIXME:
+  drivers/video/fbgen.c has no docs, which stuffs up the sgml.  Comment
+  out until somebody adds docs.  KAO
+     <sect1><title>Frame Buffer Generic Functions</title>
+X!Idrivers/video/fbgen.c
+     </sect1>
+KAO -->
+     <sect1><title>Frame Buffer Video Mode Database</title>
+!Idrivers/video/modedb.c
+!Edrivers/video/modedb.c
+     </sect1>
+     <sect1><title>Frame Buffer Macintosh Video Mode Database</title>
+!Edrivers/video/macmodes.c
+     </sect1>
+     <sect1><title>Frame Buffer Fonts</title>
+        <para>
+           Refer to the file drivers/video/console/fonts.c for more information.
+        </para>
+<!-- FIXME: Removed for now since no structured comments in source
+X!Idrivers/video/console/fonts.c
+-->
+     </sect1>
+  </chapter>
+
+  <chapter id="input_subsystem">
+     <title>Input Subsystem</title>
+!Iinclude/linux/input.h
+!Edrivers/input/input.c
+!Edrivers/input/ff-core.c
+!Edrivers/input/ff-memless.c
+  </chapter>
+
+  <chapter id="spi">
+      <title>Serial Peripheral Interface (SPI)</title>
+  <para>
+       SPI is the "Serial Peripheral Interface", widely used with
+       embedded systems because it is a simple and efficient
+       interface:  basically a multiplexed shift register.
+       Its three signal wires hold a clock (SCK, often in the range
+       of 1-20 MHz), a "Master Out, Slave In" (MOSI) data line, and
+       a "Master In, Slave Out" (MISO) data line.
+       SPI is a full duplex protocol; for each bit shifted out the
+       MOSI line (one per clock) another is shifted in on the MISO line.
+       Those bits are assembled into words of various sizes on the
+       way to and from system memory.
+       An additional chipselect line is usually active-low (nCS);
+       four signals are normally used for each peripheral, plus
+       sometimes an interrupt.
+  </para>
+  <para>
+       The SPI bus facilities listed here provide a generalized
+       interface to declare SPI busses and devices, manage them
+       according to the standard Linux driver model, and perform
+       input/output operations.
+       At this time, only "master" side interfaces are supported,
+       where Linux talks to SPI peripherals and does not implement
+       such a peripheral itself.
+       (Interfaces to support implementing SPI slaves would
+       necessarily look different.)
+  </para>
+  <para>
+       The programming interface is structured around two kinds of driver,
+       and two kinds of device.
+       A "Controller Driver" abstracts the controller hardware, which may
+       be as simple as a set of GPIO pins or as complex as a pair of FIFOs
+       connected to dual DMA engines on the other side of the SPI shift
+       register (maximizing throughput).  Such drivers bridge between
+       whatever bus they sit on (often the platform bus) and SPI, and
+       expose the SPI side of their device as a
+       <structname>struct spi_master</structname>.
+       SPI devices are children of that master, represented as a
+       <structname>struct spi_device</structname> and manufactured from
+       <structname>struct spi_board_info</structname> descriptors which
+       are usually provided by board-specific initialization code.
+       A <structname>struct spi_driver</structname> is called a
+       "Protocol Driver", and is bound to a spi_device using normal
+       driver model calls.
+  </para>
+  <para>
+       The I/O model is a set of queued messages.  Protocol drivers
+       submit one or more <structname>struct spi_message</structname>
+       objects, which are processed and completed asynchronously.
+       (There are synchronous wrappers, however.)  Messages are
+       built from one or more <structname>struct spi_transfer</structname>
+       objects, each of which wraps a full duplex SPI transfer.
+       A variety of protocol tweaking options are needed, because
+       different chips adopt very different policies for how they
+       use the bits transferred with SPI.
+  </para>
+!Iinclude/linux/spi/spi.h
+!Fdrivers/spi/spi.c spi_register_board_info
+!Edrivers/spi/spi.c
+  </chapter>
+
+  <chapter id="i2c">
+     <title>I<superscript>2</superscript>C and SMBus Subsystem</title>
+
+     <para>
+       I<superscript>2</superscript>C (or without fancy typography, "I2C")
+       is an acronym for the "Inter-IC" bus, a simple bus protocol which is
+       widely used where low data rate communications suffice.
+       Since it's also a licensed trademark, some vendors use another
+       name (such as "Two-Wire Interface", TWI) for the same bus.
+       I2C only needs two signals (SCL for clock, SDA for data), conserving
+       board real estate and minimizing signal quality issues.
+       Most I2C devices use seven bit addresses, and bus speeds of up
+       to 400 kHz; there's a high speed extension (3.4 MHz) that's not yet
+       found wide use.
+       I2C is a multi-master bus; open drain signaling is used to
+       arbitrate between masters, as well as to handshake and to
+       synchronize clocks from slower clients.
+     </para>
+
+     <para>
+       The Linux I2C programming interfaces support only the master
+       side of bus interactions, not the slave side.
+       The programming interface is structured around two kinds of driver,
+       and two kinds of device.
+       An I2C "Adapter Driver" abstracts the controller hardware; it binds
+       to a physical device (perhaps a PCI device or platform_device) and
+       exposes a <structname>struct i2c_adapter</structname> representing
+       each I2C bus segment it manages.
+       On each I2C bus segment will be I2C devices represented by a
+       <structname>struct i2c_client</structname>.  Those devices will
+       be bound to a <structname>struct i2c_driver</structname>,
+       which should follow the standard Linux driver model.
+       (At this writing, a legacy model is more widely used.)
+       There are functions to perform various I2C protocol operations; at
+       this writing all such functions are usable only from task context.
+     </para>
+
+     <para>
+       The System Management Bus (SMBus) is a sibling protocol.  Most SMBus
+       systems are also I2C conformant.  The electrical constraints are
+       tighter for SMBus, and it standardizes particular protocol messages
+       and idioms.  Controllers that support I2C can also support most
+       SMBus operations, but SMBus controllers don't support all the protocol
+       options that an I2C controller will.
+       There are functions to perform various SMBus protocol operations,
+       either using I2C primitives or by issuing SMBus commands to
+       i2c_adapter devices which don't support those I2C operations.
+     </para>
+
+!Iinclude/linux/i2c.h
+!Fdrivers/i2c/i2c-boardinfo.c i2c_register_board_info
+!Edrivers/i2c/i2c-core.c
+  </chapter>
+
+</book>
index 5818ff75786abf9a853706794f1f33f6238786cb..bc962cda650485aea9cddcced9823ef39a3252b6 100644 (file)
 
 <toc></toc>
 
-  <chapter id="Basics">
-     <title>Driver Basics</title>
-     <sect1><title>Driver Entry and Exit points</title>
-!Iinclude/linux/init.h
-     </sect1>
-
-     <sect1><title>Atomic and pointer manipulation</title>
-!Iarch/x86/include/asm/atomic_32.h
-!Iarch/x86/include/asm/unaligned.h
-     </sect1>
-
-     <sect1><title>Delaying, scheduling, and timer routines</title>
-!Iinclude/linux/sched.h
-!Ekernel/sched.c
-!Ekernel/timer.c
-     </sect1>
-     <sect1><title>High-resolution timers</title>
-!Iinclude/linux/ktime.h
-!Iinclude/linux/hrtimer.h
-!Ekernel/hrtimer.c
-     </sect1>
-     <sect1><title>Workqueues and Kevents</title>
-!Ekernel/workqueue.c
-     </sect1>
-     <sect1><title>Internal Functions</title>
-!Ikernel/exit.c
-!Ikernel/signal.c
-!Iinclude/linux/kthread.h
-!Ekernel/kthread.c
-     </sect1>
-
-     <sect1><title>Kernel objects manipulation</title>
-<!--
-X!Iinclude/linux/kobject.h
--->
-!Elib/kobject.c
-     </sect1>
-
-     <sect1><title>Kernel utility functions</title>
-!Iinclude/linux/kernel.h
-!Ekernel/printk.c
-!Ekernel/panic.c
-!Ekernel/sys.c
-!Ekernel/rcupdate.c
-     </sect1>
-
-     <sect1><title>Device Resource Management</title>
-!Edrivers/base/devres.c
-     </sect1>
-
-  </chapter>
-
   <chapter id="adt">
      <title>Data Types</title>
      <sect1><title>Doubly Linked Lists</title>
@@ -298,62 +246,6 @@ X!Earch/x86/kernel/mca_32.c
 !Ikernel/acct.c
   </chapter>
 
-  <chapter id="devdrivers">
-     <title>Device drivers infrastructure</title>
-     <sect1><title>Device Drivers Base</title>
-<!--
-X!Iinclude/linux/device.h
--->
-!Edrivers/base/driver.c
-!Edrivers/base/core.c
-!Edrivers/base/class.c
-!Edrivers/base/firmware_class.c
-!Edrivers/base/transport_class.c
-<!-- Cannot be included, because
-     attribute_container_add_class_device_adapter
- and attribute_container_classdev_to_container
-     exceed allowed 44 characters maximum
-X!Edrivers/base/attribute_container.c
--->
-!Edrivers/base/sys.c
-<!--
-X!Edrivers/base/interface.c
--->
-!Edrivers/base/platform.c
-!Edrivers/base/bus.c
-     </sect1>
-     <sect1><title>Device Drivers Power Management</title>
-!Edrivers/base/power/main.c
-     </sect1>
-     <sect1><title>Device Drivers ACPI Support</title>
-<!-- Internal functions only
-X!Edrivers/acpi/sleep/main.c
-X!Edrivers/acpi/sleep/wakeup.c
-X!Edrivers/acpi/motherboard.c
-X!Edrivers/acpi/bus.c
--->
-!Edrivers/acpi/scan.c
-!Idrivers/acpi/scan.c
-<!-- No correct structured comments
-X!Edrivers/acpi/pci_bind.c
--->
-     </sect1>
-     <sect1><title>Device drivers PnP support</title>
-!Idrivers/pnp/core.c
-<!-- No correct structured comments
-X!Edrivers/pnp/system.c
- -->
-!Edrivers/pnp/card.c
-!Idrivers/pnp/driver.c
-!Edrivers/pnp/manager.c
-!Edrivers/pnp/support.c
-     </sect1>
-     <sect1><title>Userspace IO devices</title>
-!Edrivers/uio/uio.c
-!Iinclude/linux/uio_driver.h
-     </sect1>
-  </chapter>
-
   <chapter id="blkdev">
      <title>Block Devices</title>
 !Eblock/blk-core.c
@@ -381,275 +273,6 @@ X!Edrivers/pnp/system.c
 !Edrivers/char/misc.c
   </chapter>
 
-  <chapter id="parportdev">
-     <title>Parallel Port Devices</title>
-!Iinclude/linux/parport.h
-!Edrivers/parport/ieee1284.c
-!Edrivers/parport/share.c
-!Idrivers/parport/daisy.c
-  </chapter>
-
-  <chapter id="message_devices">
-       <title>Message-based devices</title>
-     <sect1><title>Fusion message devices</title>
-!Edrivers/message/fusion/mptbase.c
-!Idrivers/message/fusion/mptbase.c
-!Edrivers/message/fusion/mptscsih.c
-!Idrivers/message/fusion/mptscsih.c
-!Idrivers/message/fusion/mptctl.c
-!Idrivers/message/fusion/mptspi.c
-!Idrivers/message/fusion/mptfc.c
-!Idrivers/message/fusion/mptlan.c
-     </sect1>
-     <sect1><title>I2O message devices</title>
-!Iinclude/linux/i2o.h
-!Idrivers/message/i2o/core.h
-!Edrivers/message/i2o/iop.c
-!Idrivers/message/i2o/iop.c
-!Idrivers/message/i2o/config-osm.c
-!Edrivers/message/i2o/exec-osm.c
-!Idrivers/message/i2o/exec-osm.c
-!Idrivers/message/i2o/bus-osm.c
-!Edrivers/message/i2o/device.c
-!Idrivers/message/i2o/device.c
-!Idrivers/message/i2o/driver.c
-!Idrivers/message/i2o/pci.c
-!Idrivers/message/i2o/i2o_block.c
-!Idrivers/message/i2o/i2o_scsi.c
-!Idrivers/message/i2o/i2o_proc.c
-     </sect1>
-  </chapter>
-
-  <chapter id="snddev">
-     <title>Sound Devices</title>
-!Iinclude/sound/core.h
-!Esound/sound_core.c
-!Iinclude/sound/pcm.h
-!Esound/core/pcm.c
-!Esound/core/device.c
-!Esound/core/info.c
-!Esound/core/rawmidi.c
-!Esound/core/sound.c
-!Esound/core/memory.c
-!Esound/core/pcm_memory.c
-!Esound/core/init.c
-!Esound/core/isadma.c
-!Esound/core/control.c
-!Esound/core/pcm_lib.c
-!Esound/core/hwdep.c
-!Esound/core/pcm_native.c
-!Esound/core/memalloc.c
-<!-- FIXME: Removed for now since no structured comments in source
-X!Isound/sound_firmware.c
--->
-  </chapter>
-
-  <chapter id="uart16x50">
-     <title>16x50 UART Driver</title>
-!Iinclude/linux/serial_core.h
-!Edrivers/serial/serial_core.c
-!Edrivers/serial/8250.c
-  </chapter>
-
-  <chapter id="fbdev">
-     <title>Frame Buffer Library</title>
-
-     <para>
-       The frame buffer drivers depend heavily on four data structures.  
-       These structures are declared in include/linux/fb.h.  They are 
-       fb_info, fb_var_screeninfo, fb_fix_screeninfo and fb_monospecs. 
-       The last three can be made available to and from userland. 
-     </para>
-
-     <para>
-       fb_info defines the current state of a particular video card. 
-       Inside fb_info, there exists a fb_ops structure which is a 
-       collection of needed functions to make fbdev and fbcon work.
-       fb_info is only visible to the kernel.
-     </para>
-
-     <para>
-       fb_var_screeninfo is used to describe the features of a video card 
-       that are user defined.  With fb_var_screeninfo, things such as
-       depth and the resolution may be defined.
-     </para>
-
-     <para>
-       The next structure is fb_fix_screeninfo. This defines the 
-       properties of a card that are created when a mode is set and can't 
-       be changed otherwise.  A good example of this is the start of the 
-       frame buffer memory.  This "locks" the address of the frame buffer
-       memory, so that it cannot be changed or moved.
-     </para>
-
-     <para>
-       The last structure is fb_monospecs. In the old API, there was 
-       little importance for fb_monospecs. This allowed for forbidden things 
-       such as setting a mode of 800x600 on a fix frequency monitor. With 
-       the new API, fb_monospecs prevents such things, and if used 
-       correctly, can prevent a monitor from being cooked.  fb_monospecs
-       will not be useful until kernels 2.5.x.
-     </para>
-
-     <sect1><title>Frame Buffer Memory</title>
-!Edrivers/video/fbmem.c
-     </sect1>
-<!--
-     <sect1><title>Frame Buffer Console</title>
-X!Edrivers/video/console/fbcon.c
-     </sect1>
--->
-     <sect1><title>Frame Buffer Colormap</title>
-!Edrivers/video/fbcmap.c
-     </sect1>
-<!-- FIXME:
-  drivers/video/fbgen.c has no docs, which stuffs up the sgml.  Comment
-  out until somebody adds docs.  KAO
-     <sect1><title>Frame Buffer Generic Functions</title>
-X!Idrivers/video/fbgen.c
-     </sect1>
-KAO -->
-     <sect1><title>Frame Buffer Video Mode Database</title>
-!Idrivers/video/modedb.c
-!Edrivers/video/modedb.c
-     </sect1>
-     <sect1><title>Frame Buffer Macintosh Video Mode Database</title>
-!Edrivers/video/macmodes.c
-     </sect1>
-     <sect1><title>Frame Buffer Fonts</title>
-        <para>
-           Refer to the file drivers/video/console/fonts.c for more information.
-        </para>
-<!-- FIXME: Removed for now since no structured comments in source
-X!Idrivers/video/console/fonts.c
--->
-     </sect1>
-  </chapter>
-
-  <chapter id="input_subsystem">
-     <title>Input Subsystem</title>
-!Iinclude/linux/input.h
-!Edrivers/input/input.c
-!Edrivers/input/ff-core.c
-!Edrivers/input/ff-memless.c
-  </chapter>
-
-  <chapter id="spi">
-      <title>Serial Peripheral Interface (SPI)</title>
-  <para>
-       SPI is the "Serial Peripheral Interface", widely used with
-       embedded systems because it is a simple and efficient
-       interface:  basically a multiplexed shift register.
-       Its three signal wires hold a clock (SCK, often in the range
-       of 1-20 MHz), a "Master Out, Slave In" (MOSI) data line, and
-       a "Master In, Slave Out" (MISO) data line.
-       SPI is a full duplex protocol; for each bit shifted out the
-       MOSI line (one per clock) another is shifted in on the MISO line.
-       Those bits are assembled into words of various sizes on the
-       way to and from system memory.
-       An additional chipselect line is usually active-low (nCS);
-       four signals are normally used for each peripheral, plus
-       sometimes an interrupt.
-  </para>
-  <para>
-       The SPI bus facilities listed here provide a generalized
-       interface to declare SPI busses and devices, manage them
-       according to the standard Linux driver model, and perform
-       input/output operations.
-       At this time, only "master" side interfaces are supported,
-       where Linux talks to SPI peripherals and does not implement
-       such a peripheral itself.
-       (Interfaces to support implementing SPI slaves would
-       necessarily look different.)
-  </para>
-  <para>
-       The programming interface is structured around two kinds of driver,
-       and two kinds of device.
-       A "Controller Driver" abstracts the controller hardware, which may
-       be as simple as a set of GPIO pins or as complex as a pair of FIFOs
-       connected to dual DMA engines on the other side of the SPI shift
-       register (maximizing throughput).  Such drivers bridge between
-       whatever bus they sit on (often the platform bus) and SPI, and
-       expose the SPI side of their device as a
-       <structname>struct spi_master</structname>.
-       SPI devices are children of that master, represented as a
-       <structname>struct spi_device</structname> and manufactured from
-       <structname>struct spi_board_info</structname> descriptors which
-       are usually provided by board-specific initialization code.
-       A <structname>struct spi_driver</structname> is called a
-       "Protocol Driver", and is bound to a spi_device using normal
-       driver model calls.
-  </para>
-  <para>
-       The I/O model is a set of queued messages.  Protocol drivers
-       submit one or more <structname>struct spi_message</structname>
-       objects, which are processed and completed asynchronously.
-       (There are synchronous wrappers, however.)  Messages are
-       built from one or more <structname>struct spi_transfer</structname>
-       objects, each of which wraps a full duplex SPI transfer.
-       A variety of protocol tweaking options are needed, because
-       different chips adopt very different policies for how they
-       use the bits transferred with SPI.
-  </para>
-!Iinclude/linux/spi/spi.h
-!Fdrivers/spi/spi.c spi_register_board_info
-!Edrivers/spi/spi.c
-  </chapter>
-
-  <chapter id="i2c">
-     <title>I<superscript>2</superscript>C and SMBus Subsystem</title>
-
-     <para>
-       I<superscript>2</superscript>C (or without fancy typography, "I2C")
-       is an acronym for the "Inter-IC" bus, a simple bus protocol which is
-       widely used where low data rate communications suffice.
-       Since it's also a licensed trademark, some vendors use another
-       name (such as "Two-Wire Interface", TWI) for the same bus.
-       I2C only needs two signals (SCL for clock, SDA for data), conserving
-       board real estate and minimizing signal quality issues.
-       Most I2C devices use seven bit addresses, and bus speeds of up
-       to 400 kHz; there's a high speed extension (3.4 MHz) that's not yet
-       found wide use.
-       I2C is a multi-master bus; open drain signaling is used to
-       arbitrate between masters, as well as to handshake and to
-       synchronize clocks from slower clients.
-     </para>
-
-     <para>
-       The Linux I2C programming interfaces support only the master
-       side of bus interactions, not the slave side.
-       The programming interface is structured around two kinds of driver,
-       and two kinds of device.
-       An I2C "Adapter Driver" abstracts the controller hardware; it binds
-       to a physical device (perhaps a PCI device or platform_device) and
-       exposes a <structname>struct i2c_adapter</structname> representing
-       each I2C bus segment it manages.
-       On each I2C bus segment will be I2C devices represented by a
-       <structname>struct i2c_client</structname>.  Those devices will
-       be bound to a <structname>struct i2c_driver</structname>,
-       which should follow the standard Linux driver model.
-       (At this writing, a legacy model is more widely used.)
-       There are functions to perform various I2C protocol operations; at
-       this writing all such functions are usable only from task context.
-     </para>
-
-     <para>
-       The System Management Bus (SMBus) is a sibling protocol.  Most SMBus
-       systems are also I2C conformant.  The electrical constraints are
-       tighter for SMBus, and it standardizes particular protocol messages
-       and idioms.  Controllers that support I2C can also support most
-       SMBus operations, but SMBus controllers don't support all the protocol
-       options that an I2C controller will.
-       There are functions to perform various SMBus protocol operations,
-       either using I2C primitives or by issuing SMBus commands to
-       i2c_adapter devices which don't support those I2C operations.
-     </para>
-
-!Iinclude/linux/i2c.h
-!Fdrivers/i2c/i2c-boardinfo.c i2c_register_board_info
-!Edrivers/i2c/i2c-core.c
-  </chapter>
-
   <chapter id="clk">
      <title>Clock Framework</title>
 
index 9a07e38631b0a0d1ed7956db151b667402725419..6bd5f372adec010d18bf0b15d6d5f62d185a4f18 100644 (file)
@@ -93,7 +93,7 @@ the PCI Express Port Bus driver from loading a service driver.
 
 int pcie_port_service_register(struct pcie_port_service_driver *new)
 
-This API replaces the Linux Driver Model's pci_module_init API. A
+This API replaces the Linux Driver Model's pci_register_driver API. A
 service driver should always calls pcie_port_service_register at
 module init. Note that after service driver being loaded, calls
 such as pci_enable_device(dev) and pci_set_master(dev) are no longer
index d9e5d6f41b927c09ce0c98e8dfd6a448bddee236..93feb8444489686b1a9874da9c964f388d5ed316 100644 (file)
@@ -252,10 +252,8 @@ cgroup file system directories.
 When a task is moved from one cgroup to another, it gets a new
 css_set pointer - if there's an already existing css_set with the
 desired collection of cgroups then that group is reused, else a new
-css_set is allocated. Note that the current implementation uses a
-linear search to locate an appropriate existing css_set, so isn't
-very efficient. A future version will use a hash table for better
-performance.
+css_set is allocated. The appropriate existing css_set is located by
+looking into a hash table.
 
 To allow access from a cgroup to the css_sets (and hence tasks)
 that comprise it, a set of cg_cgroup_link objects form a lattice;
index 5c86c258c7913dd9c97da4a3e4f7a0dd666745bc..0611e9528c7c236c3dbdeb3038e762664614dec5 100644 (file)
@@ -142,7 +142,7 @@ into the rest of the kernel, none in performance critical paths:
  - in fork and exit, to attach and detach a task from its cpuset.
  - in sched_setaffinity, to mask the requested CPUs by what's
    allowed in that tasks cpuset.
- - in sched.c migrate_all_tasks(), to keep migrating tasks within
+ - in sched.c migrate_live_tasks(), to keep migrating tasks within
    the CPUs allowed by their cpuset, if possible.
  - in the mbind and set_mempolicy system calls, to mask the requested
    Memory Nodes by what's allowed in that tasks cpuset.
@@ -175,6 +175,10 @@ files describing that cpuset:
  - mem_exclusive flag: is memory placement exclusive?
  - mem_hardwall flag:  is memory allocation hardwalled
  - memory_pressure: measure of how much paging pressure in cpuset
+ - memory_spread_page flag: if set, spread page cache evenly on allowed nodes
+ - memory_spread_slab flag: if set, spread slab cache evenly on allowed nodes
+ - sched_load_balance flag: if set, load balance within CPUs on that cpuset
+ - sched_relax_domain_level: the searching range when migrating tasks
 
 In addition, the root cpuset only has the following file:
  - memory_pressure_enabled flag: compute memory_pressure?
@@ -252,7 +256,7 @@ is causing.
 
 This is useful both on tightly managed systems running a wide mix of
 submitted jobs, which may choose to terminate or re-prioritize jobs that
-are trying to use more memory than allowed on the nodes assigned them,
+are trying to use more memory than allowed on the nodes assigned to them,
 and with tightly coupled, long running, massively parallel scientific
 computing jobs that will dramatically fail to meet required performance
 goals if they start to use more memory than allowed to them.
@@ -378,7 +382,7 @@ as cpusets and sched_setaffinity.
 The algorithmic cost of load balancing and its impact on key shared
 kernel data structures such as the task list increases more than
 linearly with the number of CPUs being balanced.  So the scheduler
-has support to  partition the systems CPUs into a number of sched
+has support to partition the systems CPUs into a number of sched
 domains such that it only load balances within each sched domain.
 Each sched domain covers some subset of the CPUs in the system;
 no two sched domains overlap; some CPUs might not be in any sched
@@ -485,17 +489,22 @@ of CPUs allowed to a cpuset having 'sched_load_balance' enabled.
 The internal kernel cpuset to scheduler interface passes from the
 cpuset code to the scheduler code a partition of the load balanced
 CPUs in the system. This partition is a set of subsets (represented
-as an array of cpumask_t) of CPUs, pairwise disjoint, that cover all
-the CPUs that must be load balanced.
-
-Whenever the 'sched_load_balance' flag changes, or CPUs come or go
-from a cpuset with this flag enabled, or a cpuset with this flag
-enabled is removed, the cpuset code builds a new such partition and
-passes it to the scheduler sched domain setup code, to have the sched
-domains rebuilt as necessary.
+as an array of struct cpumask) of CPUs, pairwise disjoint, that cover
+all the CPUs that must be load balanced.
+
+The cpuset code builds a new such partition and passes it to the
+scheduler sched domain setup code, to have the sched domains rebuilt
+as necessary, whenever:
+ - the 'sched_load_balance' flag of a cpuset with non-empty CPUs changes,
+ - or CPUs come or go from a cpuset with this flag enabled,
+ - or 'sched_relax_domain_level' value of a cpuset with non-empty CPUs
+   and with this flag enabled changes,
+ - or a cpuset with non-empty CPUs and with this flag enabled is removed,
+ - or a cpu is offlined/onlined.
 
 This partition exactly defines what sched domains the scheduler should
-setup - one sched domain for each element (cpumask_t) in the partition.
+setup - one sched domain for each element (struct cpumask) in the
+partition.
 
 The scheduler remembers the currently active sched domain partitions.
 When the scheduler routine partition_sched_domains() is invoked from
@@ -559,7 +568,7 @@ domain, the largest value among those is used.  Be careful, if one
 requests 0 and others are -1 then 0 is used.
 
 Note that modifying this file will have both good and bad effects,
-and whether it is acceptable or not will be depend on your situation.
+and whether it is acceptable or not depends on your situation.
 Don't modify this file if you are not sure.
 
 If your situation is:
@@ -600,19 +609,15 @@ to allocate a page of memory for that task.
 
 If a cpuset has its 'cpus' modified, then each task in that cpuset
 will have its allowed CPU placement changed immediately.  Similarly,
-if a tasks pid is written to a cpusets 'tasks' file, in either its
-current cpuset or another cpuset, then its allowed CPU placement is
-changed immediately.  If such a task had been bound to some subset
-of its cpuset using the sched_setaffinity() call, the task will be
-allowed to run on any CPU allowed in its new cpuset, negating the
-affect of the prior sched_setaffinity() call.
+if a tasks pid is written to another cpusets 'tasks' file, then its
+allowed CPU placement is changed immediately.  If such a task had been
+bound to some subset of its cpuset using the sched_setaffinity() call,
+the task will be allowed to run on any CPU allowed in its new cpuset,
+negating the effect of the prior sched_setaffinity() call.
 
 In summary, the memory placement of a task whose cpuset is changed is
 updated by the kernel, on the next allocation of a page for that task,
-but the processor placement is not updated, until that tasks pid is
-rewritten to the 'tasks' file of its cpuset.  This is done to avoid
-impacting the scheduler code in the kernel with a check for changes
-in a tasks processor placement.
+and the processor placement is updated immediately.
 
 Normally, once a page is allocated (given a physical page
 of main memory) then that page stays on whatever node it
@@ -681,10 +686,14 @@ and then start a subshell 'sh' in that cpuset:
   # The next line should display '/Charlie'
   cat /proc/self/cpuset
 
-In the future, a C library interface to cpusets will likely be
-available.  For now, the only way to query or modify cpusets is
-via the cpuset file system, using the various cd, mkdir, echo, cat,
-rmdir commands from the shell, or their equivalent from C.
+There are ways to query or modify cpusets:
+ - via the cpuset file system directly, using the various cd, mkdir, echo,
+   cat, rmdir commands from the shell, or their equivalent from C.
+ - via the C library libcpuset.
+ - via the C library libcgroup.
+   (http://sourceforge.net/proects/libcg/)
+ - via the python application cset.
+   (http://developer.novell.com/wiki/index.php/Cpuset)
 
 The sched_setaffinity calls can also be done at the shell prompt using
 SGI's runon or Robert Love's taskset.  The mbind and set_mempolicy
@@ -756,7 +765,7 @@ mount -t cpuset X /dev/cpuset
 
 is equivalent to
 
-mount -t cgroup -ocpuset X /dev/cpuset
+mount -t cgroup -ocpuset,noprefix X /dev/cpuset
 echo "/sbin/cpuset_release_agent" > /dev/cpuset/release_agent
 
 2.2 Adding/removing cpus
index a05ec50f8004dd65f29c87579612389f93660187..a7cbfff40d077047f76463377381b269b5d41fc4 100644 (file)
@@ -127,9 +127,11 @@ void unlock_device(struct device * dev);
 Attributes
 ~~~~~~~~~~
 struct device_attribute {
-        struct attribute        attr;
-        ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
-        ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
+       struct attribute        attr;
+       ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+                       char *buf);
+       ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+                        const char *buf, size_t count);
 };
 
 Attributes of devices can be exported via drivers using a simple
index 9e9c348275a96fd362acf9916d2789be8a08c4c8..7e81e37c0b1ec0ccbea30a92ffbf70f495ffdbd0 100644 (file)
@@ -2,8 +2,10 @@
 sysfs - _The_ filesystem for exporting kernel objects. 
 
 Patrick Mochel <mochel@osdl.org>
+Mike Murphy <mamurph@cs.clemson.edu>
 
-10 January 2003
+Revised:    22 February 2009
+Original:   10 January 2003
 
 
 What it is:
@@ -64,12 +66,13 @@ An attribute definition is simply:
 
 struct attribute {
         char                    * name;
+        struct module          *owner;
         mode_t                  mode;
 };
 
 
-int sysfs_create_file(struct kobject * kobj, struct attribute * attr);
-void sysfs_remove_file(struct kobject * kobj, struct attribute * attr);
+int sysfs_create_file(struct kobject * kobj, const struct attribute * attr);
+void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);
 
 
 A bare attribute contains no means to read or write the value of the
@@ -80,9 +83,11 @@ a specific object type.
 For example, the driver model defines struct device_attribute like:
 
 struct device_attribute {
-        struct attribute        attr;
-        ssize_t (*show)(struct device * dev, char * buf);
-        ssize_t (*store)(struct device * dev, const char * buf);
+       struct attribute        attr;
+       ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+                       char *buf);
+       ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+                        const char *buf, size_t count);
 };
 
 int device_create_file(struct device *, struct device_attribute *);
@@ -90,12 +95,8 @@ void device_remove_file(struct device *, struct device_attribute *);
 
 It also defines this helper for defining device attributes: 
 
-#define DEVICE_ATTR(_name, _mode, _show, _store)      \
-struct device_attribute dev_attr_##_name = {            \
-        .attr = {.name  = __stringify(_name) , .mode   = _mode },      \
-        .show   = _show,                                \
-        .store  = _store,                               \
-};
+#define DEVICE_ATTR(_name, _mode, _show, _store) \
+struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
 
 For example, declaring
 
@@ -107,9 +108,9 @@ static struct device_attribute dev_attr_foo = {
        .attr   = {
                .name = "foo",
                .mode = S_IWUSR | S_IRUGO,
+               .show = show_foo,
+               .store = store_foo,
        },
-       .show = show_foo,
-       .store = store_foo,
 };
 
 
@@ -161,10 +162,12 @@ To read or write attributes, show() or store() methods must be
 specified when declaring the attribute. The method types should be as
 simple as those defined for device attributes:
 
-        ssize_t (*show)(struct device * dev, char * buf);
-        ssize_t (*store)(struct device * dev, const char * buf);
+ssize_t (*show)(struct device * dev, struct device_attribute * attr,
+                char * buf);
+ssize_t (*store)(struct device * dev, struct device_attribute * attr,
+                 const char * buf);
 
-IOW, they should take only an object and a buffer as parameters. 
+IOW, they should take only an object, an attribute, and a buffer as parameters.
 
 
 sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the
@@ -299,14 +302,16 @@ The following interface layers currently exist in sysfs:
 Structure:
 
 struct device_attribute {
-        struct attribute        attr;
-        ssize_t (*show)(struct device * dev, char * buf);
-        ssize_t (*store)(struct device * dev, const char * buf);
+       struct attribute        attr;
+       ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+                       char *buf);
+       ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+                        const char *buf, size_t count);
 };
 
 Declaring:
 
-DEVICE_ATTR(_name, _str, _mode, _show, _store);
+DEVICE_ATTR(_name, _mode, _show, _store);
 
 Creation/Removal:
 
@@ -342,7 +347,8 @@ Structure:
 struct driver_attribute {
         struct attribute        attr;
         ssize_t (*show)(struct device_driver *, char * buf);
-        ssize_t (*store)(struct device_driver *, const char * buf);
+        ssize_t (*store)(struct device_driver *, const char * buf,
+                         size_t count);
 };
 
 Declaring:
diff --git a/Documentation/hwmon/hpfall.c b/Documentation/hwmon/hpfall.c
new file mode 100644 (file)
index 0000000..bbea1cc
--- /dev/null
@@ -0,0 +1,101 @@
+/* Disk protection for HP machines.
+ *
+ * Copyright 2008 Eric Piel
+ * Copyright 2009 Pavel Machek <pavel@suse.cz>
+ *
+ * GPLv2.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <signal.h>
+
+void write_int(char *path, int i)
+{
+       char buf[1024];
+       int fd = open(path, O_RDWR);
+       if (fd < 0) {
+               perror("open");
+               exit(1);
+       }
+       sprintf(buf, "%d", i);
+       if (write(fd, buf, strlen(buf)) != strlen(buf)) {
+               perror("write");
+               exit(1);
+       }
+       close(fd);
+}
+
+void set_led(int on)
+{
+       write_int("/sys/class/leds/hp::hddprotect/brightness", on);
+}
+
+void protect(int seconds)
+{
+       write_int("/sys/block/sda/device/unload_heads", seconds*1000);
+}
+
+int on_ac(void)
+{
+//     /sys/class/power_supply/AC0/online
+}
+
+int lid_open(void)
+{
+//     /proc/acpi/button/lid/LID/state
+}
+
+void ignore_me(void)
+{
+       protect(0);
+       set_led(0);
+
+}
+
+int main(int argc, char* argv[])
+{
+       int fd, ret;
+
+       fd = open("/dev/freefall", O_RDONLY);
+       if (fd < 0) {
+               perror("open");
+               return EXIT_FAILURE;
+       }
+
+       signal(SIGALRM, ignore_me);
+
+       for (;;) {
+              unsigned char count;
+
+               ret = read(fd, &count, sizeof(count));
+              alarm(0);
+              if ((ret == -1) && (errno == EINTR)) {
+                      /* Alarm expired, time to unpark the heads */
+                      continue;
+              }
+
+               if (ret != sizeof(count)) {
+                       perror("read");
+                       break;
+               }
+
+              protect(21);
+              set_led(1);
+              if (1 || on_ac() || lid_open()) {
+                      alarm(2);
+              } else {
+                      alarm(20);
+              }
+       }
+
+       close(fd);
+       return EXIT_SUCCESS;
+}
index 0fcfc4a7ccdc0c9b7934a42054d60139e3320a4a..287f8c902656db40353954b967b06503d517dc70 100644 (file)
@@ -33,6 +33,14 @@ rate - reports the sampling rate of the accelerometer device in HZ
 This driver also provides an absolute input class device, allowing
 the laptop to act as a pinball machine-esque joystick.
 
+Another feature of the driver is misc device called "freefall" that
+acts similar to /dev/rtc and reacts on free-fall interrupts received
+from the device. It supports blocking operations, poll/select and
+fasync operation modes. You must read 1 bytes from the device.  The
+result is number of free-fall interrupts since the last successful
+read (or 255 if number of interrupts would not fit).
+
+
 Axes orientation
 ----------------
 
index b182626739ea7e7fb5c4ca98ce02b8bc76b21608..319785b6dcb1d024892bca7f9eb6c8195d8bcf11 100644 (file)
@@ -134,7 +134,7 @@ and is between 256 and 4096 characters. It is defined in the file
 
        acpi=           [HW,ACPI,X86-64,i386]
                        Advanced Configuration and Power Interface
-                       Format: { force | off | ht | strict | noirq }
+                       Format: { force | off | ht | strict | noirq | rsdt }
                        force -- enable ACPI if default was off
                        off -- disable ACPI if default was on
                        noirq -- do not use ACPI for IRQ routing
index cde23b4a12a19a9306464ec1296cb4fee19eb9c0..5731c67abc558f4ac91d9f54d78bf88cacb8dad6 100644 (file)
@@ -78,12 +78,10 @@ to view your kernel log and look for "mmiotrace has lost events" warning. If
 events were lost, the trace is incomplete. You should enlarge the buffers and
 try again. Buffers are enlarged by first seeing how large the current buffers
 are:
-$ cat /debug/tracing/trace_entries
+$ cat /debug/tracing/buffer_size_kb
 gives you a number. Approximately double this number and write it back, for
 instance:
-$ echo 0 > /debug/tracing/tracing_enabled
-$ echo 128000 > /debug/tracing/trace_entries
-$ echo 1 > /debug/tracing/tracing_enabled
+$ echo 128000 > /debug/tracing/buffer_size_kb
 Then start again from the top.
 
 If you are doing a trace for a driver project, e.g. Nouveau, you should also
index db65b4e6d1324b65b58db7e70174d1ee9e1bfe93..59fd2d1d94a772a6262669ff8947b35b4bbd0f7a 100644 (file)
@@ -692,6 +692,13 @@ M: kernel@wantstofly.org
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
+ARM/NUVOTON W90X900 ARM ARCHITECTURE
+P:      Wan ZongShun
+M:      mcuos.com@gmail.com
+L:      linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W:      http://www.mcuos.com
+S:      Maintained
+
 ARPD SUPPORT
 P:     Jonathan Layes
 L:     netdev@vger.kernel.org
@@ -1905,10 +1912,10 @@ W:      http://gigaset307x.sourceforge.net/
 S:     Maintained
 
 HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
-P:     Robert Love
-M:     rlove@rlove.org
-M:     linux-kernel@vger.kernel.org
-W:     http://www.kernel.org/pub/linux/kernel/people/rml/hdaps/
+P:     Frank Seidel
+M:     frank@f-seidel.de
+L:     lm-sensors@lm-sensors.org
+W:     http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
 S:     Maintained
 
 GSPCA FINEPIX SUBDRIVER
@@ -2001,7 +2008,7 @@ S:        Maintained
 
 HIBERNATION (aka Software Suspend, aka swsusp)
 P:     Pavel Machek
-M:     pavel@suse.cz
+M:     pavel@ucw.cz
 P:     Rafael J. Wysocki
 M:     rjw@sisk.pl
 L:     linux-pm@lists.linux-foundation.org
@@ -3327,8 +3334,8 @@ P:        Jeremy Fitzhardinge
 M:     jeremy@xensource.com
 P:     Chris Wright
 M:     chrisw@sous-sol.org
-P:     Zachary Amsden
-M:     zach@vmware.com
+P:     Alok Kataria
+M:     akataria@vmware.com
 P:     Rusty Russell
 M:     rusty@rustcorp.com.au
 L:     virtualization@lists.osdl.org
@@ -4172,7 +4179,7 @@ SUSPEND TO RAM
 P:     Len Brown
 M:     len.brown@intel.com
 P:     Pavel Machek
-M:     pavel@suse.cz
+M:     pavel@ucw.cz
 P:     Rafael J. Wysocki
 M:     rjw@sisk.pl
 L:     linux-pm@lists.linux-foundation.org
@@ -4924,11 +4931,11 @@ L:      zd1211-devs@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 
 ZR36067 VIDEO FOR LINUX DRIVER
-P:     Ronald Bultje
-M:     rbultje@ronald.bitfreak.net
 L:     mjpeg-users@lists.sourceforge.net
+L:     linux-media@vger.kernel.org
 W:     http://mjpeg.sourceforge.net/driver-zoran/
-S:     Maintained
+T:     Mercurial http://linuxtv.org/hg/v4l-dvb
+S:     Odd Fixes
 
 ZS DECSTATION Z85C30 SERIAL DRIVER
 P:     Maciej W. Rozycki
index 22d758495ad29424f88361e9b1c782e1529bad94..df6ce3e8009091b4b6a4e96e131bd1f7adcea74d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 29
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc6
 NAME = Erotic Pickled Herring
 
 # *DOCUMENTATION*
@@ -389,6 +389,7 @@ PHONY += outputmakefile
 # output directory.
 outputmakefile:
 ifneq ($(KBUILD_SRC),)
+       $(Q)ln -fsn $(srctree) source
        $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
            $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
 endif
@@ -946,7 +947,6 @@ ifneq ($(KBUILD_SRC),)
            mkdir -p include2;                                          \
            ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm;     \
        fi
-       ln -fsn $(srctree) source
 endif
 
 # prepare2 creates a makefile if using a separate output directory
diff --git a/README b/README
index 90a07658ede14840346eee6610648bcf4ec79997..d6c6c742c1d78aea9f64e4307e36e06a2a0959da 100644 (file)
--- a/README
+++ b/README
@@ -188,7 +188,7 @@ CONFIGURING the kernel:
                           values to random values.
 
    You can find more information on using the Linux kernel config tools
-   in Documentation/kbuild/make-configs.txt.
+   in Documentation/kbuild/kconfig.txt.
 
        NOTES on "make config":
        - having unnecessary drivers will make the kernel bigger, and can
index f238370c907d9f4c86ecbed9da7332ccf08908c3..8d0097f10208dad922760de0a72756a55272c722 100644 (file)
@@ -93,8 +93,8 @@ common_shutdown_1(void *generic_ptr)
        if (cpuid != boot_cpuid) {
                flags |= 0x00040000UL; /* "remain halted" */
                *pflags = flags;
-               cpu_clear(cpuid, cpu_present_map);
-               cpu_clear(cpuid, cpu_possible_map);
+               set_cpu_present(cpuid, false);
+               set_cpu_possible(cpuid, false);
                halt();
        }
 #endif
@@ -120,8 +120,8 @@ common_shutdown_1(void *generic_ptr)
 
 #ifdef CONFIG_SMP
        /* Wait for the secondaries to halt. */
-       cpu_clear(boot_cpuid, cpu_present_map);
-       cpu_clear(boot_cpuid, cpu_possible_map);
+       set_cpu_present(boot_cpuid, false);
+       set_cpu_possible(boot_cpuid, false);
        while (cpus_weight(cpu_present_map))
                barrier();
 #endif
index 00f1dc3dfd5f215e5e1068c89c2376afed7f7830..b1fe5674c3a1fb286c3af38559a52009ce054478 100644 (file)
@@ -120,12 +120,12 @@ void __cpuinit
 smp_callin(void)
 {
        int cpuid = hard_smp_processor_id();
-       cpumask_t mask = cpu_online_map;
 
-       if (cpu_test_and_set(cpuid, mask)) {
+       if (cpu_online(cpuid)) {
                printk("??, cpu 0x%x already present??\n", cpuid);
                BUG();
        }
+       set_cpu_online(cpuid, true);
 
        /* Turn on machine checks.  */
        wrmces(7);
@@ -436,8 +436,8 @@ setup_smp(void)
                                ((char *)cpubase + i*hwrpb->processor_size);
                        if ((cpu->flags & 0x1cc) == 0x1cc) {
                                smp_num_probed++;
-                               cpu_set(i, cpu_possible_map);
-                               cpu_set(i, cpu_present_map);
+                               set_cpu_possible(i, true);
+                               set_cpu_present(i, true);
                                cpu->pal_revision = boot_cpu_palrev;
                        }
 
@@ -470,8 +470,8 @@ smp_prepare_cpus(unsigned int max_cpus)
 
        /* Nothing to do on a UP box, or when told not to.  */
        if (smp_num_probed == 1 || max_cpus == 0) {
-               cpu_possible_map = cpumask_of_cpu(boot_cpuid);
-               cpu_present_map = cpumask_of_cpu(boot_cpuid);
+               init_cpu_possible(cpumask_of(boot_cpuid));
+               init_cpu_present(cpumask_of(boot_cpuid));
                printk(KERN_INFO "SMP mode deactivated.\n");
                return;
        }
index e0ee7060f9aadf607f8830bda764f4df66f16b96..98e2f3de4bc5819420c7f538fdfd2937a682e692 100644 (file)
@@ -608,7 +608,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
-CONFIG_AT91SAM9_WATCHDOG=y
+CONFIG_AT91SAM9X_WATCHDOG=y
 
 #
 # USB-based Watchdog Cards
index 01d1ef97d8be0e4ed395a9f87653f5269cb2c4f6..149456142392b84d2a12d9cdd92b08d0595175c3 100644 (file)
@@ -700,7 +700,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
-CONFIG_AT91SAM9_WATCHDOG=y
+CONFIG_AT91SAM9X_WATCHDOG=y
 
 #
 # USB-based Watchdog Cards
index 036a126725c16ad5b284442591e1154f3628bb44..21599f3c6275bc98fafe4331490cc17e853fef92 100644 (file)
@@ -710,7 +710,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
-CONFIG_AT91SAM9_WATCHDOG=y
+CONFIG_AT91SAM9X_WATCHDOG=y
 
 #
 # USB-based Watchdog Cards
index 237a2a6a8517b17583b8dd01009f27594ba0b534..e2df81a3e804199da7b3701924df98db70ede1a8 100644 (file)
@@ -606,7 +606,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
-CONFIG_AT91SAM9_WATCHDOG=y
+CONFIG_AT91SAM9X_WATCHDOG=y
 
 #
 # Sonics Silicon Backplane
index cd1d717903ac5dec800e566f0bf7a6bf6bdb5a22..9b32d0eb89bac0a93e09000f1ab2897ecc10b5bd 100644 (file)
@@ -727,7 +727,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_AT91SAM9_WATCHDOG is not set
+# CONFIG_AT91SAM9X_WATCHDOG is not set
 
 #
 # USB-based Watchdog Cards
index 84849098c8e8139da19ae6b8d8fecd089539ee30..d4a0da1e48f40988bb7f92ce34664d86adb74a32 100644 (file)
@@ -74,9 +74,9 @@ EXPORT_SYMBOL(elf_set_personality);
  */
 int arm_elf_read_implies_exec(const struct elf32_hdr *x, int executable_stack)
 {
-       if (executable_stack != EXSTACK_ENABLE_X)
+       if (executable_stack != EXSTACK_DISABLE_X)
                return 1;
-       if (cpu_architecture() <= CPU_ARCH_ARMv6)
+       if (cpu_architecture() < CPU_ARCH_ARMv6)
                return 1;
        return 0;
 }
index 9eca2209cde630dd656491ef5c964461f2c8b5b2..412aa49ad2fb432ca1e98fa7876f3d78234eb16b 100644 (file)
@@ -697,7 +697,7 @@ static void __init at91_add_device_rtt(void)
  *  Watchdog
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE)
+#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
 static struct platform_device at91cap9_wdt_device = {
        .name           = "at91_wdt",
        .id             = -1,
index fdde1ea21b0729738ade6357b728a634ff505fc6..d74c9ac007e75c1d91642d711c7ef19c93b320e1 100644 (file)
@@ -643,7 +643,7 @@ static void __init at91_add_device_rtt(void)
  *  Watchdog
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE)
+#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
 static struct platform_device at91sam9260_wdt_device = {
        .name           = "at91_wdt",
        .id             = -1,
index 17289756f80ffe8c5eb6d34bd561ea2fe119a0f5..59fc48311fb07d11760382e85e5ff386986a93f6 100644 (file)
@@ -621,7 +621,7 @@ static void __init at91_add_device_rtt(void)
  *  Watchdog
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE)
+#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
 static struct platform_device at91sam9261_wdt_device = {
        .name           = "at91_wdt",
        .id             = -1,
index b753cb879d8e6ae5ee7621492709fae1895eaebd..134af97ff3403f1c309b4b6c962665c860fa796d 100644 (file)
@@ -854,7 +854,7 @@ static void __init at91_add_device_rtt(void)
  *  Watchdog
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE)
+#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
 static struct platform_device at91sam9263_wdt_device = {
        .name           = "at91_wdt",
        .id             = -1,
index 145324f4ec5671fca146f160196dc54b5cd0cfb6..728186515cdf2a2b3db5a99fce5564336be92218 100644 (file)
@@ -609,7 +609,7 @@ static void __init at91_add_device_rtt(void)
  *  Watchdog
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE)
+#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
 static struct platform_device at91sam9rl_wdt_device = {
        .name           = "at91_wdt",
        .id             = -1,
index 9b0447c3d59b15443539c44eb1cb3a23dedd3a3b..2f7d4977dce95b3c43c575d2696b30888af5e187 100644 (file)
@@ -490,7 +490,8 @@ postcore_initcall(at91_gpio_debugfs_init);
 
 /*--------------------------------------------------------------------------*/
 
-/* This lock class tells lockdep that GPIO irqs are in a different
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
  * category than their parents, so it won't report false recursion.
  */
 static struct lock_class_key gpio_lock_class;
@@ -509,9 +510,6 @@ void __init at91_gpio_irq_setup(void)
                unsigned        id = this->id;
                unsigned        i;
 
-               /* enable PIO controller's clock */
-               clk_enable(this->clock);
-
                __raw_writel(~0, this->regbase + PIO_IDR);
 
                for (i = 0, pin = this->chipbase; i < 32; i++, pin++) {
@@ -556,7 +554,14 @@ void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
                data->chipbase = PIN_BASE + i * 32;
                data->regbase = data->offset + (void __iomem *)AT91_VA_BASE_SYS;
 
-               /* AT91SAM9263_ID_PIOCDE groups PIOC, PIOD, PIOE */
+               /* enable PIO controller's clock */
+               clk_enable(data->clock);
+
+               /*
+                * Some processors share peripheral ID between multiple GPIO banks.
+                *  SAM9263 (PIOC, PIOD, PIOE)
+                *  CAP9 (PIOA, PIOB, PIOC, PIOD)
+                */
                if (last && last->id == data->id)
                        last->next = data;
        }
index fb51f0e0a83fb933b718c80960a46cd60b831ce8..0b3ae21b4565abb471fbedd59c15c96a3e4450f5 100644 (file)
@@ -93,6 +93,7 @@ struct atmel_nand_data {
        u8              enable_pin;     /* chip enable */
        u8              det_pin;        /* card detect */
        u8              rdy_pin;        /* ready/busy */
+       u8              rdy_pin_active_low;     /* rdy_pin value is inverted */
        u8              ale;            /* address line number connected to ALE */
        u8              cle;            /* address line number connected to CLE */
        u8              bus_width_16;   /* buswidth is 16 bit */
diff --git a/arch/arm/mach-ep93xx/include/mach/gesbc9312.h b/arch/arm/mach-ep93xx/include/mach/gesbc9312.h
deleted file mode 100644 (file)
index 21fe2b9..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/gesbc9312.h
- */
index 529807d182bf2c28a8b47350dec7c2eb942cb12d..2866297310b7c9e38f80a7992921481e7140d00b 100644 (file)
@@ -10,7 +10,6 @@
 
 #include "platform.h"
 
-#include "gesbc9312.h"
 #include "ts72xx.h"
 
 #endif
index efb86b700276bf965c611526e83d8973d20b7a90..06083b23bb446a6743a894afd0c605c5b2932274 100644 (file)
@@ -42,7 +42,7 @@ void __init kirkwood_init_irq(void)
        writel(0, GPIO_EDGE_CAUSE(32));
 
        for (i = IRQ_KIRKWOOD_GPIO_START; i < NR_IRQS; i++) {
-               set_irq_chip(i, &orion_gpio_irq_level_chip);
+               set_irq_chip(i, &orion_gpio_irq_chip);
                set_irq_handler(i, handle_level_irq);
                irq_desc[i].status |= IRQ_LEVEL;
                set_irq_flags(i, IRQF_VALID);
index e273418797b41cbaa309469fac12656aff97b986..30b7e4bcdbc7c7523affdb36f4884e819acf0420 100644 (file)
@@ -40,7 +40,7 @@ void __init mv78xx0_init_irq(void)
        writel(0, GPIO_EDGE_CAUSE(0));
 
        for (i = IRQ_MV78XX0_GPIO_START; i < NR_IRQS; i++) {
-               set_irq_chip(i, &orion_gpio_irq_level_chip);
+               set_irq_chip(i, &orion_gpio_irq_chip);
                set_irq_handler(i, handle_level_irq);
                irq_desc[i].status |= IRQ_LEVEL;
                set_irq_flags(i, IRQF_VALID);
index ad721e0cbf7a1ded6c54ab2212efb4a5da1f281e..ce4d46a4a8381d2bd2b0cff19f840ae16ac2c153 100644 (file)
@@ -565,7 +565,7 @@ u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val)
  *
  * Given a struct clk of a rate-selectable clksel clock, and a clock divisor,
  * find the corresponding register field value.  The return register value is
- * the value before left-shifting.  Returns 0xffffffff on error
+ * the value before left-shifting.  Returns ~0 on error
  */
 u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
 {
@@ -577,7 +577,7 @@ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
 
        clks = omap2_get_clksel_by_parent(clk, clk->parent);
        if (clks == NULL)
-               return 0;
+               return ~0;
 
        for (clkr = clks->rates; clkr->div; clkr++) {
                if ((clkr->flags & cpu_mask) && (clkr->div == div))
@@ -588,7 +588,7 @@ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
                printk(KERN_ERR "clock: Could not find divisor %d for "
                       "clock %s parent %s\n", div, clk->name,
                       clk->parent->name);
-               return 0;
+               return ~0;
        }
 
        return clkr->val;
@@ -708,7 +708,7 @@ static u32 omap2_clksel_get_src_field(void __iomem **src_addr,
                return 0;
 
        for (clkr = clks->rates; clkr->div; clkr++) {
-               if (clkr->flags & (cpu_mask | DEFAULT_RATE))
+               if (clkr->flags & cpu_mask && clkr->flags & DEFAULT_RATE)
                        break; /* Found the default rate for this platform */
        }
 
@@ -746,7 +746,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
                return -EINVAL;
 
        if (clk->usecount > 0)
-               _omap2_clk_disable(clk);
+               omap2_clk_disable(clk);
 
        /* Set new source value (previous dividers if any in effect) */
        reg_val = __raw_readl(src_addr) & ~field_mask;
@@ -759,11 +759,11 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
                wmb();
        }
 
-       if (clk->usecount > 0)
-               _omap2_clk_enable(clk);
-
        clk->parent = new_parent;
 
+       if (clk->usecount > 0)
+               omap2_clk_enable(clk);
+
        /* CLKSEL clocks follow their parents' rates, divided by a divisor */
        clk->rate = new_parent->rate;
 
index 0caae43301e54e472d82187680ed69fca4feda72..e03f7b45cb0d114ad0b0e343d424ba1122b03472 100644 (file)
@@ -44,7 +44,7 @@ void __init orion5x_init_irq(void)
         * User can use set_type() if he wants to use edge types handlers.
         */
        for (i = IRQ_ORION5X_GPIO_START; i < NR_IRQS; i++) {
-               set_irq_chip(i, &orion_gpio_irq_level_chip);
+               set_irq_chip(i, &orion_gpio_irq_chip);
                set_irq_handler(i, handle_level_irq);
                irq_desc[i].status |= IRQ_LEVEL;
                set_irq_flags(i, IRQF_VALID);
index 9b36c5cb5e9f68306c017cf63f94ab55ccc1ce3f..d4d082c5c2d4ad2be9f1eb331cce837fff3de325 100644 (file)
@@ -693,7 +693,8 @@ static void __init sanity_check_meminfo(void)
                 * Check whether this memory bank would entirely overlap
                 * the vmalloc area.
                 */
-               if (__va(bank->start) >= VMALLOC_MIN) {
+               if (__va(bank->start) >= VMALLOC_MIN ||
+                   __va(bank->start) < PAGE_OFFSET) {
                        printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx "
                               "(vmalloc region overlap).\n",
                               bank->start, bank->start + bank->size - 1);
index 967186425ca1073ecea837206ebe22c081335693..0d12c21647663d5191167569354bd3af1d7d84b5 100644 (file)
@@ -265,51 +265,36 @@ EXPORT_SYMBOL(orion_gpio_set_blink);
  *        polarity    LEVEL          mask
  *
  ****************************************************************************/
-static void gpio_irq_edge_ack(u32 irq)
-{
-       int pin = irq_to_gpio(irq);
-
-       writel(~(1 << (pin & 31)), GPIO_EDGE_CAUSE(pin));
-}
-
-static void gpio_irq_edge_mask(u32 irq)
-{
-       int pin = irq_to_gpio(irq);
-       u32 u;
-
-       u = readl(GPIO_EDGE_MASK(pin));
-       u &= ~(1 << (pin & 31));
-       writel(u, GPIO_EDGE_MASK(pin));
-}
 
-static void gpio_irq_edge_unmask(u32 irq)
+static void gpio_irq_ack(u32 irq)
 {
-       int pin = irq_to_gpio(irq);
-       u32 u;
-
-       u = readl(GPIO_EDGE_MASK(pin));
-       u |= 1 << (pin & 31);
-       writel(u, GPIO_EDGE_MASK(pin));
+       int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK;
+       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
+               int pin = irq_to_gpio(irq);
+               writel(~(1 << (pin & 31)), GPIO_EDGE_CAUSE(pin));
+       }
 }
 
-static void gpio_irq_level_mask(u32 irq)
+static void gpio_irq_mask(u32 irq)
 {
        int pin = irq_to_gpio(irq);
-       u32 u;
-
-       u = readl(GPIO_LEVEL_MASK(pin));
+       int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK;
+       u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ?
+               GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin);
+       u32 u = readl(reg);
        u &= ~(1 << (pin & 31));
-       writel(u, GPIO_LEVEL_MASK(pin));
+       writel(u, reg);
 }
 
-static void gpio_irq_level_unmask(u32 irq)
+static void gpio_irq_unmask(u32 irq)
 {
        int pin = irq_to_gpio(irq);
-       u32 u;
-
-       u = readl(GPIO_LEVEL_MASK(pin));
+       int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK;
+       u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ?
+               GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin);
+       u32 u = readl(reg);
        u |= 1 << (pin & 31);
-       writel(u, GPIO_LEVEL_MASK(pin));
+       writel(u, reg);
 }
 
 static int gpio_irq_set_type(u32 irq, u32 type)
@@ -331,9 +316,9 @@ static int gpio_irq_set_type(u32 irq, u32 type)
         * Set edge/level type.
         */
        if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
-               desc->chip = &orion_gpio_irq_edge_chip;
+               desc->handle_irq = handle_edge_irq;
        } else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
-               desc->chip = &orion_gpio_irq_level_chip;
+               desc->handle_irq = handle_level_irq;
        } else {
                printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
                return -EINVAL;
@@ -371,19 +356,11 @@ static int gpio_irq_set_type(u32 irq, u32 type)
        return 0;
 }
 
-struct irq_chip orion_gpio_irq_edge_chip = {
-       .name           = "orion_gpio_irq_edge",
-       .ack            = gpio_irq_edge_ack,
-       .mask           = gpio_irq_edge_mask,
-       .unmask         = gpio_irq_edge_unmask,
-       .set_type       = gpio_irq_set_type,
-};
-
-struct irq_chip orion_gpio_irq_level_chip = {
-       .name           = "orion_gpio_irq_level",
-       .mask           = gpio_irq_level_mask,
-       .mask_ack       = gpio_irq_level_mask,
-       .unmask         = gpio_irq_level_unmask,
+struct irq_chip orion_gpio_irq_chip = {
+       .name           = "orion_gpio",
+       .ack            = gpio_irq_ack,
+       .mask           = gpio_irq_mask,
+       .unmask         = gpio_irq_unmask,
        .set_type       = gpio_irq_set_type,
 };
 
index 54deaf274b5268a6983dae399f8285f4e4a92ea6..ec743e82c876cab82abd00a9c415c265258feea9 100644 (file)
@@ -31,8 +31,7 @@ void orion_gpio_set_blink(unsigned pin, int blink);
 /*
  * GPIO interrupt handling.
  */
-extern struct irq_chip orion_gpio_irq_edge_chip;
-extern struct irq_chip orion_gpio_irq_level_chip;
+extern struct irq_chip orion_gpio_irq_chip;
 void orion_gpio_irq_handler(int irqoff);
 
 
index aafaf7a78886951ed50017c6d414e6b5758cff05..cff8e84f78f21b64e580034a999cefc48d7536b1 100644 (file)
@@ -116,6 +116,7 @@ struct atmel_nand_data {
        int     enable_pin;     /* chip enable */
        int     det_pin;        /* card detect */
        int     rdy_pin;        /* ready/busy */
+       u8      rdy_pin_active_low;     /* rdy_pin value is inverted */
        u8      ale;            /* address line number connected to ALE */
        u8      cle;            /* address line number connected to CLE */
        u8      bus_width_16;   /* buswidth is 16 bit */
index 6183aeccecf1f9d564cc2bc2832943a235ed3871..4eb45c0124986279a35d33731a71fcdaf72d53aa 100644 (file)
@@ -221,7 +221,11 @@ config IA64_HP_SIM
 
 config IA64_XEN_GUEST
        bool "Xen guest"
+       select SWIOTLB
        depends on XEN
+       help
+         Build a kernel that runs on Xen guest domain. At this moment only
+         16KB page size in supported.
 
 endchoice
 
@@ -479,8 +483,7 @@ config HOLES_IN_ZONE
        default y if VIRTUAL_MEM_MAP
 
 config HAVE_ARCH_EARLY_PFN_TO_NID
-       def_bool y
-       depends on NEED_MULTIPLE_NODES
+       def_bool NUMA && SPARSEMEM
 
 config HAVE_ARCH_NODEDATA_EXTENSION
        def_bool y
diff --git a/arch/ia64/configs/xen_domu_defconfig b/arch/ia64/configs/xen_domu_defconfig
new file mode 100644 (file)
index 0000000..0bb0714
--- /dev/null
@@ -0,0 +1,1601 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc1
+# Fri Jan 16 11:49:59 2009
+#
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=20
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+# CONFIG_GROUP_SCHED is not set
+
+#
+# Control Group support
+#
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_FREEZER=y
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_ZONE_DMA=y
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HUGETLB_PAGE_SIZE_VARIABLE=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_DMI=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_PARAVIRT_GUEST=y
+CONFIG_PARAVIRT=y
+CONFIG_XEN=y
+CONFIG_XEN_XENCOMM=y
+CONFIG_NO_IDLE_HZ=y
+# CONFIG_IA64_GENERIC is not set
+# CONFIG_IA64_DIG is not set
+# CONFIG_IA64_DIG_VTD is not set
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_SGI_UV is not set
+# CONFIG_IA64_HP_SIM is not set
+CONFIG_IA64_XEN_GUEST=y
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_PGTABLE_3=y
+# CONFIG_PGTABLE_4 is not set
+CONFIG_HZ=250
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_IA64_L1_CACHE_SHIFT=7
+CONFIG_IA64_CYCLONE=y
+CONFIG_IOSAPIC=y
+CONFIG_FORCE_MAX_ZONEORDER=17
+# CONFIG_VIRT_CPU_ACCOUNTING is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=16
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_SCHED_SMT is not set
+CONFIG_PERMIT_BSP_REMOVE=y
+CONFIG_FORCE_CPEI_RETARGET=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_NR_QUICK=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_VIRTUAL_MEM_MAP=y
+CONFIG_HOLES_IN_ZONE=y
+# CONFIG_IA32_SUPPORT is not set
+# CONFIG_COMPAT_FOR_U64_ALIGNMENT is not set
+CONFIG_IA64_MCA_RECOVERY=y
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+# CONFIG_IA64_MC_ERR_INJECT is not set
+# CONFIG_IA64_ESI is not set
+# CONFIG_IA64_HP_AML_NFW is not set
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+CONFIG_DMIID=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management and ACPI options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_PROCFS=y
+CONFIG_ACPI_PROCFS_POWER=y
+CONFIG_ACPI_SYSFS_POWER=y
+CONFIG_ACPI_PROC_EVENT=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=m
+# CONFIG_ACPI_DOCK is not set
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=m
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+# CONFIG_ACPI_PCI_SLOT is not set
+CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_CONTAINER=m
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+CONFIG_HOTPLUG_PCI=m
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+CONFIG_HOTPLUG_PCI_ACPI=m
+# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+# CONFIG_PCCARD is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_PNP=y
+CONFIG_PNP_DEBUG_MESSAGES=y
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_XEN_BLKDEV_FRONTEND=y
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_TIMINGS=y
+CONFIG_IDE_ATAPI=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEACPI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_PLATFORM is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT8172 is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
+CONFIG_BLK_DEV_IDEDMA=y
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_STEX is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+CONFIG_SCSI_QLOGIC_1280=y
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID456 is not set
+CONFIG_MD_MULTIPATH=m
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
+# CONFIG_DM_UEVENT is not set
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=y
+CONFIG_FUSION_FC=y
+# CONFIG_FUSION_SAS is not set
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=y
+# CONFIG_FUSION_LOGGING is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_NET_SB1000 is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+CONFIG_E100=m
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_R6040 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+CONFIG_XEN_NETDEV_FRONTEND=y
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+CONFIG_NETCONSOLE=y
+# CONFIG_NETCONSOLE_DYNAMIC is not set
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+CONFIG_GAMEPORT=m
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_FM801 is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_SYNCLINK_GT is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_NR_UARTS=6
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_IRQ=y
+CONFIG_HVC_XEN=y
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_EFI_RTC=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+CONFIG_HPET=y
+CONFIG_HPET_MMAP=y
+# CONFIG_HANGCHECK_TIMER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=m
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_AGP=m
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_TOPSEED=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XENFS=y
+CONFIG_XEN_COMPAT_XENFS=y
+# CONFIG_STAGING is not set
+# CONFIG_MSPEC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=2048
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_HAVE_KVM=y
+CONFIG_VIRTUALIZATION=y
+# CONFIG_KVM is not set
+# CONFIG_VIRTIO_PCI is not set
+# CONFIG_VIRTIO_BALLOON is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_IRQ_PER_CPU=y
+# CONFIG_IOMMU_API is not set
index 68aa6da807c191fa74344c85b562b97f6d14694b..bfa86b6af7cd0774d652c99d800e822284f74c23 100644 (file)
 
 #include <linux/ioctl.h>
 
+/* Select x86 specific features in <linux/kvm.h> */
+#define __KVM_HAVE_IOAPIC
+#define __KVM_HAVE_DEVICE_ASSIGNMENT
+
 /* Architectural interrupt line count. */
 #define KVM_NR_INTERRUPTS 256
 
index 34efe88eb84948f042474988089fa6d1ef1f82f8..f2ca32069b3ff5e2b4f97925cabf6540f0d3dea7 100644 (file)
@@ -31,10 +31,6 @@ static inline int pfn_to_nid(unsigned long pfn)
 #endif
 }
 
-#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
-extern int early_pfn_to_nid(unsigned long pfn);
-#endif
-
 #ifdef CONFIG_IA64_DIG /* DIG systems are small */
 # define MAX_PHYSNODE_ID       8
 # define NR_NODE_MEMBLKS       (MAX_NUMNODES * 8)
index 5efecf06c9a42efef99870084a3748e9bd3dfc15..96798d2da7c272fe4e9417f5329702d8f4559042 100644 (file)
@@ -39,7 +39,7 @@
 /* BTE status register only supports 16 bits for length field */
 #define BTE_LEN_BITS (16)
 #define BTE_LEN_MASK ((1 << BTE_LEN_BITS) - 1)
-#define BTE_MAX_XFER ((1 << BTE_LEN_BITS) * L1_CACHE_BYTES)
+#define BTE_MAX_XFER (BTE_LEN_MASK << L1_CACHE_SHIFT)
 
 
 /* Define hardware */
index 11463994a7d540b63de364b80d3077a5f51f6445..52290547c85ba89edd5ba3fa1a98985891803361 100644 (file)
@@ -736,14 +736,15 @@ int __cpu_disable(void)
                        return -EBUSY;
        }
 
+       cpu_clear(cpu, cpu_online_map);
+
        if (migrate_platform_irqs(cpu)) {
                cpu_set(cpu, cpu_online_map);
-               return (-EBUSY);
+               return -EBUSY;
        }
 
        remove_siblinginfo(cpu);
        fixup_irqs();
-       cpu_clear(cpu, cpu_online_map);
        local_flush_tlb_all();
        cpu_clear(cpu, cpu_callin_map);
        return 0;
index 4e586f6110aa08c4d2df47f8aa16a053748f8268..28f982045f29c6c1623c2ac06e032e904efb0720 100644 (file)
@@ -1337,6 +1337,10 @@ static void kvm_release_vm_pages(struct kvm *kvm)
        }
 }
 
+void kvm_arch_sync_events(struct kvm *kvm)
+{
+}
+
 void kvm_arch_destroy_vm(struct kvm *kvm)
 {
        kvm_iommu_unmap_guest(kvm);
index 552d07724207e213b5949e2dd15c00bc31c74dd3..230eae482f3262a443e2ef9acf5111820937b574 100644 (file)
@@ -455,13 +455,18 @@ fpswa_ret_t vmm_fp_emulate(int fp_fault, void *bundle, unsigned long *ipsr,
        if (!vmm_fpswa_interface)
                return (fpswa_ret_t) {-1, 0, 0, 0};
 
-       /*
-        * Just let fpswa driver to use hardware fp registers.
-        * No fp register is valid in memory.
-        */
        memset(&fp_state, 0, sizeof(fp_state_t));
 
        /*
+        * compute fp_state.  only FP registers f6 - f11 are used by the
+        * vmm, so set those bits in the mask and set the low volatile
+        * pointer to point to these registers.
+        */
+       fp_state.bitmask_low64 = 0xfc0;  /* bit6..bit11 */
+
+       fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) &regs->f6;
+
+   /*
         * unsigned long (*EFI_FPSWA) (
         *      unsigned long    trap_type,
         *      void             *Bundle,
@@ -545,10 +550,6 @@ void reflect_interruption(u64 ifa, u64 isr, u64 iim,
                status = vmm_handle_fpu_swa(0, regs, isr);
                if (!status)
                        return ;
-               else if (-EAGAIN == status) {
-                       vcpu_decrement_iip(vcpu);
-                       return ;
-               }
                break;
        }
 
index b73bf1838e57750fb69f3ae27d6950bcc9dc46c8..3efea7d0a351c5159d5e843406e744fe0948a33d 100644 (file)
@@ -58,7 +58,7 @@ paddr_to_nid(unsigned long paddr)
  * SPARSEMEM to allocate the SPARSEMEM sectionmap on the NUMA node where
  * the section resides.
  */
-int early_pfn_to_nid(unsigned long pfn)
+int __meminit __early_pfn_to_nid(unsigned long pfn)
 {
        int i, section = pfn >> PFN_SECTION_SHIFT, ssec, esec;
 
@@ -70,7 +70,7 @@ int early_pfn_to_nid(unsigned long pfn)
                        return node_memblk[i].nid;
        }
 
-       return 0;
+       return -1;
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
index 9456d4034024aa97eed31518162e6ddb68e7a436..c6d6b62db66c99c05c4cc5ee8c84f19c4a768d5b 100644 (file)
@@ -97,9 +97,10 @@ bte_result_t bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
                return BTE_SUCCESS;
        }
 
-       BUG_ON((len & L1_CACHE_MASK) ||
-                (src & L1_CACHE_MASK) || (dest & L1_CACHE_MASK));
-       BUG_ON(!(len < ((BTE_LEN_MASK + 1) << L1_CACHE_SHIFT)));
+       BUG_ON(len & L1_CACHE_MASK);
+       BUG_ON(src & L1_CACHE_MASK);
+       BUG_ON(dest & L1_CACHE_MASK);
+       BUG_ON(len > BTE_MAX_XFER);
 
        /*
         * Start with interface corresponding to cpu number
index f1683a20275b8caad1e6ae92c982a483a2f524ad..515e0826803a8f6eb349153658a4b59fdd56a21a 100644 (file)
@@ -8,8 +8,7 @@ config XEN
        depends on PARAVIRT && MCKINLEY && IA64_PAGE_SIZE_16KB && EXPERIMENTAL
        select XEN_XENCOMM
        select NO_IDLE_HZ
-
-       # those are required to save/restore.
+       # followings are required to save/restore.
        select ARCH_SUSPEND_POSSIBLE
        select SUSPEND
        select PM_SLEEP
index 04cd12350455f33a2a563be95c0a3e9ad5e3ea02..936cff3c96e0215f413054d038950fc8ecc22973 100644 (file)
@@ -153,7 +153,7 @@ xen_post_smp_prepare_boot_cpu(void)
        xen_setup_vcpu_info_placement();
 }
 
-static const struct pv_init_ops xen_init_ops __initdata = {
+static const struct pv_init_ops xen_init_ops __initconst = {
        .banner = xen_banner,
 
        .reserve_memory = xen_reserve_memory,
@@ -337,7 +337,7 @@ xen_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
        HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op);
 }
 
-static const struct pv_iosapic_ops xen_iosapic_ops __initdata = {
+static const struct pv_iosapic_ops xen_iosapic_ops __initconst = {
        .pcat_compat_init = xen_pcat_compat_init,
        .__get_irq_chip = xen_iosapic_get_irq_chip,
 
index dba4afabb444a41bb7c294475825726e607f1881..39478dd08e67dd8a5d34a76fecc21bc511e1f4b2 100644 (file)
@@ -187,8 +187,8 @@ __asm__ (__ALIGN_STR "\n"                                              \
 "      jbra    ret_from_interrupt\n"                                      \
         : : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]),       \
             "n" (PT_OFF_SR), "n" (n),                                     \
-            "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &mfp.int_mk_a)      \
-                       : (n & 16 ? &tt_mfp.int_mk_b : &mfp.int_mk_b)),    \
+            "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &st_mfp.int_mk_a)   \
+                       : (n & 16 ? &tt_mfp.int_mk_b : &st_mfp.int_mk_b)), \
             "m" (preempt_count()), "di" (HARDIRQ_OFFSET)                  \
 );                                                                        \
        for (;;);                       /* fake noreturn */                \
@@ -366,14 +366,14 @@ void __init atari_init_IRQ(void)
        /* Initialize the MFP(s) */
 
 #ifdef ATARI_USE_SOFTWARE_EOI
-       mfp.vec_adr  = 0x48;    /* Software EOI-Mode */
+       st_mfp.vec_adr  = 0x48; /* Software EOI-Mode */
 #else
-       mfp.vec_adr  = 0x40;    /* Automatic EOI-Mode */
+       st_mfp.vec_adr  = 0x40; /* Automatic EOI-Mode */
 #endif
-       mfp.int_en_a = 0x00;    /* turn off MFP-Ints */
-       mfp.int_en_b = 0x00;
-       mfp.int_mk_a = 0xff;    /* no Masking */
-       mfp.int_mk_b = 0xff;
+       st_mfp.int_en_a = 0x00; /* turn off MFP-Ints */
+       st_mfp.int_en_b = 0x00;
+       st_mfp.int_mk_a = 0xff; /* no Masking */
+       st_mfp.int_mk_b = 0xff;
 
        if (ATARIHW_PRESENT(TT_MFP)) {
 #ifdef ATARI_USE_SOFTWARE_EOI
index a5f33c059979077ea17229a97c36fe692041cb23..4add96d13b1964db9b97aa6103005b5f803a75ed 100644 (file)
@@ -609,10 +609,10 @@ int atari_keyb_init(void)
                                 ACIA_RHTID : 0);
 
        /* make sure the interrupt line is up */
-       } while ((mfp.par_dt_reg & 0x10) == 0);
+       } while ((st_mfp.par_dt_reg & 0x10) == 0);
 
        /* enable ACIA Interrupts */
-       mfp.active_edge &= ~0x10;
+       st_mfp.active_edge &= ~0x10;
        atari_turnon_irq(IRQ_MFP_ACIA);
 
        ikbd_self_test = 1;
index 49c28cdbea5c5bf6cc89d00be99eee339900838c..ae2d96e5d618eba94ed0428468ca2e9f025e983f 100644 (file)
@@ -258,7 +258,7 @@ void __init config_atari(void)
                        printk("STND_SHIFTER ");
                }
        }
-       if (hwreg_present(&mfp.par_dt_reg)) {
+       if (hwreg_present(&st_mfp.par_dt_reg)) {
                ATARIHW_SET(ST_MFP);
                printk("ST_MFP ");
        }
index 702b15ccfab7b0f5c2bd53d3f73f18cdfa8ae50e..28efdc33c1aeab89afde05ff5249ba5bdf2f20ac 100644 (file)
@@ -34,9 +34,9 @@ static struct console atari_console_driver = {
 
 static inline void ata_mfp_out(char c)
 {
-       while (!(mfp.trn_stat & 0x80))  /* wait for tx buf empty */
+       while (!(st_mfp.trn_stat & 0x80))       /* wait for tx buf empty */
                barrier();
-       mfp.usart_dta = c;
+       st_mfp.usart_dta = c;
 }
 
 static void atari_mfp_console_write(struct console *co, const char *str,
@@ -91,7 +91,7 @@ static int ata_par_out(char c)
        /* This a some-seconds timeout in case no printer is connected */
        unsigned long i = loops_per_jiffy > 1 ? loops_per_jiffy : 10000000/HZ;
 
-       while ((mfp.par_dt_reg & 1) && --i) /* wait for BUSY == L */
+       while ((st_mfp.par_dt_reg & 1) && --i) /* wait for BUSY == L */
                ;
        if (!i)
                return 0;
@@ -131,9 +131,9 @@ static void atari_par_console_write(struct console *co, const char *str,
 #if 0
 int atari_mfp_console_wait_key(struct console *co)
 {
-       while (!(mfp.rcv_stat & 0x80))  /* wait for rx buf filled */
+       while (!(st_mfp.rcv_stat & 0x80))       /* wait for rx buf filled */
                barrier();
-       return mfp.usart_dta;
+       return st_mfp.usart_dta;
 }
 
 int atari_scc_console_wait_key(struct console *co)
@@ -175,12 +175,12 @@ static void __init atari_init_mfp_port(int cflag)
                baud = B9600;           /* use default 9600bps for non-implemented rates */
        baud -= B1200;                  /* baud_table[] starts at 1200bps */
 
-       mfp.trn_stat &= ~0x01;          /* disable TX */
-       mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
-       mfp.tim_ct_cd &= 0x70;          /* stop timer D */
-       mfp.tim_dt_d = baud_table[baud];
-       mfp.tim_ct_cd |= 0x01;          /* start timer D, 1:4 */
-       mfp.trn_stat |= 0x01;           /* enable TX */
+       st_mfp.trn_stat &= ~0x01;       /* disable TX */
+       st_mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
+       st_mfp.tim_ct_cd &= 0x70;       /* stop timer D */
+       st_mfp.tim_dt_d = baud_table[baud];
+       st_mfp.tim_ct_cd |= 0x01;       /* start timer D, 1:4 */
+       st_mfp.trn_stat |= 0x01;        /* enable TX */
 }
 
 #define SCC_WRITE(reg, val)                            \
index d076ff8d1b39138ba16b4483d2874a7d5b4bcaa9..a0531f34c617ca90df986902735e0b6ae5d26574 100644 (file)
@@ -27,9 +27,9 @@ void __init
 atari_sched_init(irq_handler_t timer_routine)
 {
     /* set Timer C data Register */
-    mfp.tim_dt_c = INT_TICKS;
+    st_mfp.tim_dt_c = INT_TICKS;
     /* start timer C, div = 1:100 */
-    mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60;
+    st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 15) | 0x60;
     /* install interrupt service routine for MFP Timer C */
     if (request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
                    "timer", timer_routine))
@@ -46,11 +46,11 @@ unsigned long atari_gettimeoffset (void)
   unsigned long ticks, offset = 0;
 
   /* read MFP timer C current value */
-  ticks = mfp.tim_dt_c;
+  ticks = st_mfp.tim_dt_c;
   /* The probability of underflow is less than 2% */
   if (ticks > INT_TICKS - INT_TICKS / 50)
     /* Check for pending timer interrupt */
-    if (mfp.int_pn_b & (1 << 5))
+    if (st_mfp.int_pn_b & (1 << 5))
       offset = TICK_SIZE;
 
   ticks = INT_TICKS - ticks;
index 1412b4ab202f1e753324e734d42dc92bbb635e7e..a714e1aa072a0e4bf4981894ed2c00b71ce7ca6c 100644 (file)
@@ -113,7 +113,7 @@ extern struct atari_hw_present atari_hw_present;
  * of nops on various machines. Somebody claimed that the tstb takes 600 ns.
  */
 #define        MFPDELAY() \
-       __asm__ __volatile__ ( "tstb %0" : : "m" (mfp.par_dt_reg) : "cc" );
+       __asm__ __volatile__ ( "tstb %0" : : "m" (st_mfp.par_dt_reg) : "cc" );
 
 /* Do cache push/invalidate for DMA read/write. This function obeys the
  * snooping on some machines (Medusa) and processors: The Medusa itself can
@@ -565,7 +565,7 @@ struct MFP
   u_char char_dummy23;
   u_char usart_dta;
  };
-# define mfp ((*(volatile struct MFP*)MFP_BAS))
+# define st_mfp ((*(volatile struct MFP*)MFP_BAS))
 
 /* TT's second MFP */
 
index 5748e99f4e260a2c3337a6bb4808dfc62ab8c774..f597892e43a00a6699219298dca76e6f081c9161 100644 (file)
@@ -113,7 +113,7 @@ static inline int get_mfp_bit( unsigned irq, int type )
 {      unsigned char   mask, *reg;
 
        mask = 1 << (irq & 7);
-       reg = (unsigned char *)&mfp.int_en_a + type*4 +
+       reg = (unsigned char *)&st_mfp.int_en_a + type*4 +
                  ((irq & 8) >> 2) + (((irq-8) & 16) << 3);
        return( *reg & mask );
 }
@@ -123,7 +123,7 @@ static inline void set_mfp_bit( unsigned irq, int type )
 {      unsigned char   mask, *reg;
 
        mask = 1 << (irq & 7);
-       reg = (unsigned char *)&mfp.int_en_a + type*4 +
+       reg = (unsigned char *)&st_mfp.int_en_a + type*4 +
                  ((irq & 8) >> 2) + (((irq-8) & 16) << 3);
        __asm__ __volatile__ ( "orb %0,%1"
                              : : "di" (mask), "m" (*reg) : "memory" );
@@ -134,7 +134,7 @@ static inline void clear_mfp_bit( unsigned irq, int type )
 {      unsigned char   mask, *reg;
 
        mask = ~(1 << (irq & 7));
-       reg = (unsigned char *)&mfp.int_en_a + type*4 +
+       reg = (unsigned char *)&st_mfp.int_en_a + type*4 +
                  ((irq & 8) >> 2) + (((irq-8) & 16) << 3);
        if (type == MFP_PENDING || type == MFP_SERVICE)
                __asm__ __volatile__ ( "moveb %0,%1"
index 9a9f433588792f5030796b2686193f4983c98ce9..41d16822e616b0f61062f04ba3d3560a579cb946 100644 (file)
@@ -7,6 +7,7 @@ mainmenu "Linux Kernel Configuration"
 
 config MN10300
        def_bool y
+       select HAVE_OPROFILE
 
 config AM33
        def_bool y
index 1a86425fec42302a9f6558c6e40279ddcc85e2f2..07dbbcda3b2e5dc57f71ee2ba376f6da83010d63 100644 (file)
@@ -173,7 +173,7 @@ static int pci_ampci_write_config_byte(struct pci_bus *bus, unsigned int devfn,
                BRIDGEREGB(where) = value;
        } else {
                if (bus->number == 0 &&
-                   (devfn == PCI_DEVFN(2, 0) && devfn == PCI_DEVFN(3, 0))
+                   (devfn == PCI_DEVFN(2, 0) || devfn == PCI_DEVFN(3, 0))
                    )
                        __pcidebug("<= %02x", bus, devfn, where, value);
                CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
index 6b18ba9d2d856fabc31e86dc9d6ebbb300aac63d..1dbca4e7de67d70b1d28ed52c370312f81c2e041 100644 (file)
@@ -60,7 +60,7 @@
 /* It should be preserving the high 48 bits and then specifically */
 /* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */
 #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | \
-                         _PAGE_HPTEFLAGS)
+                         _PAGE_HPTEFLAGS | _PAGE_SPECIAL)
 
 /* Bits to mask out from a PMD to get to the PTE page */
 #define PMD_MASKED_BITS                0
index 07b0d8f09cb60ecbad1a963193fa0cfec85a0155..7389003349a693a4f021f0144fc56d9d2e3fe4d2 100644 (file)
@@ -114,7 +114,7 @@ static inline struct subpage_prot_table *pgd_subpage_prot(pgd_t *pgd)
  * pgprot changes
  */
 #define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
-                         _PAGE_ACCESSED)
+                         _PAGE_ACCESSED | _PAGE_SPECIAL)
 
 /* Bits to mask out from a PMD to get to the PTE page */
 #define PMD_MASKED_BITS                0x1ff
index f69a4d97772904ea5c42beda4748a8d4cc085202..820b5f0a35ce309fcc1b2f662625d0205abfc8dc 100644 (file)
@@ -429,7 +429,8 @@ extern int icache_44x_need_flush;
 #define PMD_PAGE_SIZE(pmd)     bad_call_to_PMD_PAGE_SIZE()
 #endif
 
-#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | \
+                        _PAGE_SPECIAL)
 
 
 #define PAGE_PROT_BITS (_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \
index 5af4e9b2dbe2c6dcdde0213809f0d74673e19252..ada06924a423b312e1e404c65a3d446e92fb31ea 100644 (file)
@@ -646,11 +646,16 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg,
                       unsigned int areg, struct pt_regs *regs,
                       unsigned int flags, unsigned int length)
 {
-       char *ptr = (char *) &current->thread.TS_FPR(reg);
+       char *ptr;
        int ret = 0;
 
        flush_vsx_to_thread(current);
 
+       if (reg < 32)
+               ptr = (char *) &current->thread.TS_FPR(reg);
+       else
+               ptr = (char *) &current->thread.vr[reg - 32];
+
        if (flags & ST)
                ret = __copy_to_user(addr, ptr, length);
         else {
index 2822c8ccfaaf3ae036d6ce8da0fc16b4cf7c12a7..5f81256287f5967d1480e7abbbac2fbcab40ac9c 100644 (file)
@@ -125,6 +125,10 @@ static void kvmppc_free_vcpus(struct kvm *kvm)
        }
 }
 
+void kvm_arch_sync_events(struct kvm *kvm)
+{
+}
+
 void kvm_arch_destroy_vm(struct kvm *kvm)
 {
        kvmppc_free_vcpus(kvm);
index 7393bd76d698406f85a70b423113c8e163afacae..5ac08b8ab654f50391ebc8087c57a2b84c48aa52 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/notifier.h>
 #include <linux/lmb.h>
 #include <linux/of.h>
+#include <linux/pfn.h>
 #include <asm/sparsemem.h>
 #include <asm/prom.h>
 #include <asm/system.h>
@@ -882,7 +883,7 @@ static void mark_reserved_regions_for_nid(int nid)
                unsigned long physbase = lmb.reserved.region[i].base;
                unsigned long size = lmb.reserved.region[i].size;
                unsigned long start_pfn = physbase >> PAGE_SHIFT;
-               unsigned long end_pfn = ((physbase + size) >> PAGE_SHIFT);
+               unsigned long end_pfn = PFN_UP(physbase + size);
                struct node_active_region node_ar;
                unsigned long node_end_pfn = node->node_start_pfn +
                                             node->node_spanned_pages;
@@ -908,7 +909,7 @@ static void mark_reserved_regions_for_nid(int nid)
                         */
                        if (end_pfn > node_ar.end_pfn)
                                reserve_size = (node_ar.end_pfn << PAGE_SHIFT)
-                                       - (start_pfn << PAGE_SHIFT);
+                                       - physbase;
                        /*
                         * Only worry about *this* node, others may not
                         * yet have valid NODE_DATA().
index 67de6bf3db3d243a6d542dec9b9028d7f9fcf111..d281cc0bca712fd24553ca34b9477d5c8e47b68e 100644 (file)
@@ -328,7 +328,7 @@ static int __init ps3_mm_add_memory(void)
        return result;
 }
 
-core_initcall(ps3_mm_add_memory);
+device_initcall(ps3_mm_add_memory);
 
 /*============================================================================*/
 /* dma routines                                                               */
index 521726430afac81fcb19e870e4765a44fa85e528..95b0f7db3c69dcb076c7969ceacba1f5ab2f82b0 100644 (file)
@@ -145,7 +145,7 @@ cputime_to_timeval(const cputime_t cputime, struct timeval *value)
        value->tv_usec = rp.subreg.even / 4096;
        value->tv_sec = rp.subreg.odd;
 #else
-       value->tv_usec = cputime % 4096000000ULL;
+       value->tv_usec = (cputime % 4096000000ULL) / 4096;
        value->tv_sec = cputime / 4096000000ULL;
 #endif
 }
index 2bd9faeb3919a0a3b7fae325769c3042db144d44..e8bd6ac22c996e40378654d7bdad1b9824ac826f 100644 (file)
@@ -43,6 +43,8 @@ struct mem_chunk {
 
 extern struct mem_chunk memory_chunk[];
 extern unsigned long real_memory_size;
+extern int memory_end_set;
+extern unsigned long memory_end;
 
 void detect_memory_layout(struct mem_chunk chunk[]);
 
index d825f4950e4e2f721e89de76fc98fe3dad91971b..c5cfb6185eaca51eb5e9ee3667d1c4d06ee22a52 100644 (file)
@@ -82,7 +82,9 @@ char elf_platform[ELF_PLATFORM_SIZE];
 
 struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
 volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
-static unsigned long __initdata memory_end;
+
+int __initdata memory_end_set;
+unsigned long __initdata memory_end;
 
 /*
  * This is set up by the setup-routine at boot-time
@@ -281,6 +283,7 @@ void (*pm_power_off)(void) = machine_power_off;
 static int __init early_parse_mem(char *p)
 {
        memory_end = memparse(p, &p);
+       memory_end_set = 1;
        return 0;
 }
 early_param("mem", early_parse_mem);
@@ -508,8 +511,10 @@ static void __init setup_memory_end(void)
        int i;
 
 #if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
-       if (ipl_info.type == IPL_TYPE_FCP_DUMP)
+       if (ipl_info.type == IPL_TYPE_FCP_DUMP) {
                memory_end = ZFCPDUMP_HSA_SIZE;
+               memory_end_set = 1;
+       }
 #endif
        memory_size = 0;
        memory_end &= PAGE_MASK;
index be8497186b96d86472f1ae692c9c74e7c88515f4..0d33893e1e898448c05b7ec2573904a81850180b 100644 (file)
@@ -212,6 +212,10 @@ static void kvm_free_vcpus(struct kvm *kvm)
        }
 }
 
+void kvm_arch_sync_events(struct kvm *kvm)
+{
+}
+
 void kvm_arch_destroy_vm(struct kvm *kvm)
 {
        kvm_free_vcpus(kvm);
index 56533db25343129bcd60c152744966a2b84241cc..c5c43253e6ce4994778205e1853e2026f19a0cae 100644 (file)
@@ -78,7 +78,7 @@ void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init)
 {
        struct vde_open_args *args;
 
-       vpri->args = kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL);
+       vpri->args = uml_kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL);
        if (vpri->args == NULL) {
                printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args "
                       "allocation failed");
@@ -91,8 +91,8 @@ void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init)
        args->group = init->group;
        args->mode = init->mode ? init->mode : 0700;
 
-       args->port ?  printk(UM_KERN_INFO "port %d", args->port) :
-               printk(UM_KERN_INFO "undefined port");
+       args->port ?  printk("port %d", args->port) :
+               printk("undefined port");
 }
 
 int vde_user_read(void *conn, void *buf, int len)
index 10d6cc3fd052fd56c6817f2736e78a113bfa1046..e1983fa025d2a941f86c5ac6dc4012fc3b1d4e71 100644 (file)
@@ -174,28 +174,8 @@ config IOMMU_LEAK
          Add a simple leak tracer to the IOMMU code. This is useful when you
          are debugging a buggy device driver that leaks IOMMU mappings.
 
-config MMIOTRACE
-       bool "Memory mapped IO tracing"
-       depends on DEBUG_KERNEL && PCI
-       select TRACING
-       help
-         Mmiotrace traces Memory Mapped I/O access and is meant for
-         debugging and reverse engineering. It is called from the ioremap
-         implementation and works via page faults. Tracing is disabled by
-         default and can be enabled at run-time.
-
-         See Documentation/tracers/mmiotrace.txt.
-         If you are not helping to develop drivers, say N.
-
-config MMIOTRACE_TEST
-       tristate "Test module for mmiotrace"
-       depends on MMIOTRACE && m
-       help
-         This is a dumb module for testing mmiotrace. It is very dangerous
-         as it will write garbage to IO memory starting at a given address.
-         However, it should be safe to use on e.g. unused portion of VRAM.
-
-         Say N, unless you absolutely know what you are doing.
+config HAVE_MMIOTRACE_SUPPORT
+       def_bool y
 
 #
 # IO delay types:
index d2e3bf3608af549cb544fddc17c590c139c80733..886c9402ec4583fd94fc9f6eb44aa8bda088ab3a 100644 (file)
@@ -9,6 +9,13 @@
 #include <linux/types.h>
 #include <linux/ioctl.h>
 
+/* Select x86 specific features in <linux/kvm.h> */
+#define __KVM_HAVE_PIT
+#define __KVM_HAVE_IOAPIC
+#define __KVM_HAVE_DEVICE_ASSIGNMENT
+#define __KVM_HAVE_MSI
+#define __KVM_HAVE_USER_NMI
+
 /* Architectural interrupt line count. */
 #define KVM_NR_INTERRUPTS 256
 
index 07f1af494ca5c011801c9260a088d2dd34a4ae8e..105fb90a063527d761ed47350d553ecb755bd3cb 100644 (file)
@@ -32,8 +32,6 @@ static inline void get_memcfg_numa(void)
        get_memcfg_numa_flat();
 }
 
-extern int early_pfn_to_nid(unsigned long pfn);
-
 extern void resume_map_numa_kva(pgd_t *pgd);
 
 #else /* !CONFIG_NUMA */
index a5b3817d4b9e621e2615ddd16435b83011206548..a29f48c2a3229fc5a8a23599fdf51bcfb94c3dea 100644 (file)
@@ -40,8 +40,6 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
 #define node_end_pfn(nid)       (NODE_DATA(nid)->node_start_pfn +      \
                                 NODE_DATA(nid)->node_spanned_pages)
 
-extern int early_pfn_to_nid(unsigned long pfn);
-
 #ifdef CONFIG_NUMA_EMU
 #define FAKE_NODE_MIN_SIZE     (64 * 1024 * 1024)
 #define FAKE_NODE_MIN_HASH_MASK        (~(FAKE_NODE_MIN_SIZE - 1UL))
index e9873a2e86951d10c7a5576e3b908956d0e3e6f8..776579119a009feb1b2854a9ea18a68183d63243 100644 (file)
@@ -57,7 +57,6 @@ typedef struct { pgdval_t pgd; } pgd_t;
 typedef struct { pgprotval_t pgprot; } pgprot_t;
 
 extern int page_is_ram(unsigned long pagenr);
-extern int pagerange_is_ram(unsigned long start, unsigned long end);
 extern int devmem_is_allowed(unsigned long pagenr);
 extern void map_devmem(unsigned long pfn, unsigned long size,
                       pgprot_t vma_prot);
index c09a1412758431271633f1af7793d708d59a24f2..e299287e8e3396d95b3169c5a9e9a1086e662a1a 100644 (file)
@@ -1352,14 +1352,7 @@ static inline void arch_leave_lazy_cpu_mode(void)
        PVOP_VCALL0(pv_cpu_ops.lazy_mode.leave);
 }
 
-static inline void arch_flush_lazy_cpu_mode(void)
-{
-       if (unlikely(paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU)) {
-               arch_leave_lazy_cpu_mode();
-               arch_enter_lazy_cpu_mode();
-       }
-}
-
+void arch_flush_lazy_cpu_mode(void);
 
 #define  __HAVE_ARCH_ENTER_LAZY_MMU_MODE
 static inline void arch_enter_lazy_mmu_mode(void)
@@ -1372,13 +1365,7 @@ static inline void arch_leave_lazy_mmu_mode(void)
        PVOP_VCALL0(pv_mmu_ops.lazy_mode.leave);
 }
 
-static inline void arch_flush_lazy_mmu_mode(void)
-{
-       if (unlikely(paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU)) {
-               arch_leave_lazy_mmu_mode();
-               arch_enter_lazy_mmu_mode();
-       }
-}
+void arch_flush_lazy_mmu_mode(void);
 
 static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx,
                                unsigned long phys, pgprot_t flags)
index bcc293423a7026cb28e8c659b693d464a8cfe28e..96258d9dc9743c094e0d42af3ff6201d960a6abb 100644 (file)
@@ -13,7 +13,6 @@
         * Hooray, we are in Long 64-bit mode (but still running in low memory)
         */
 ENTRY(wakeup_long64)
-wakeup_long64:
        movq    saved_magic, %rax
        movq    $0x123456789abcdef0, %rdx
        cmpq    %rdx, %rax
@@ -34,16 +33,12 @@ wakeup_long64:
 
        movq    saved_rip, %rax
        jmp     *%rax
+ENDPROC(wakeup_long64)
 
 bogus_64_magic:
        jmp     bogus_64_magic
 
-       .align 2
-       .p2align 4,,15
-.globl do_suspend_lowlevel
-       .type   do_suspend_lowlevel,@function
-do_suspend_lowlevel:
-.LFB5:
+ENTRY(do_suspend_lowlevel)
        subq    $8, %rsp
        xorl    %eax, %eax
        call    save_processor_state
@@ -67,7 +62,7 @@ do_suspend_lowlevel:
        pushfq
        popq    pt_regs_flags(%rax)
 
-       movq    $.L97, saved_rip(%rip)
+       movq    $resume_point, saved_rip(%rip)
 
        movq    %rsp, saved_rsp
        movq    %rbp, saved_rbp
@@ -78,14 +73,12 @@ do_suspend_lowlevel:
        addq    $8, %rsp
        movl    $3, %edi
        xorl    %eax, %eax
-       jmp     acpi_enter_sleep_state
-.L97:
-       .p2align 4,,7
-.L99:
-       .align 4
-       movl    $24, %eax
-       movw    %ax, %ds
+       call    acpi_enter_sleep_state
+       /* in case something went wrong, restore the machine status and go on */
+       jmp     resume_point
 
+       .align 4
+resume_point:
        /* We don't restore %rax, it must be 0 anyway */
        movq    $saved_context, %rax
        movq    saved_context_cr4(%rax), %rbx
@@ -117,12 +110,9 @@ do_suspend_lowlevel:
        xorl    %eax, %eax
        addq    $8, %rsp
        jmp     restore_processor_state
-.LFE5:
-.Lfe5:
-       .size   do_suspend_lowlevel, .Lfe5-do_suspend_lowlevel
-       
+ENDPROC(do_suspend_lowlevel)
+
 .data
-ALIGN
 ENTRY(saved_rbp)       .quad   0
 ENTRY(saved_rsi)       .quad   0
 ENTRY(saved_rdi)       .quad   0
index 115449f869ee368f567cfd38bc8605a47944078c..570f36e44e59671d7bdc0722a2370f1e8633fbe4 100644 (file)
@@ -862,7 +862,7 @@ void clear_local_APIC(void)
        }
 
        /* lets not touch this if we didn't frob it */
-#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(X86_MCE_INTEL)
+#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL)
        if (maxlvt >= 5) {
                v = apic_read(APIC_LVTTHMR);
                apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED);
index 98807bb095adadf6e03003beffff4c640161f33a..266ec6c18b6c6b9aea5696d796c7dc565105286b 100644 (file)
@@ -1192,6 +1192,7 @@ static int suspend(int vetoable)
        device_suspend(PMSG_SUSPEND);
        local_irq_disable();
        device_power_down(PMSG_SUSPEND);
+       sysdev_suspend(PMSG_SUSPEND);
 
        local_irq_enable();
 
@@ -1208,6 +1209,7 @@ static int suspend(int vetoable)
        if (err != APM_SUCCESS)
                apm_error("suspend", err);
        err = (err == APM_SUCCESS) ? 0 : -EIO;
+       sysdev_resume();
        device_power_up(PMSG_RESUME);
        local_irq_enable();
        device_resume(PMSG_RESUME);
@@ -1228,6 +1230,7 @@ static void standby(void)
 
        local_irq_disable();
        device_power_down(PMSG_SUSPEND);
+       sysdev_suspend(PMSG_SUSPEND);
        local_irq_enable();
 
        err = set_system_power_state(APM_STATE_STANDBY);
@@ -1235,6 +1238,7 @@ static void standby(void)
                apm_error("standby", err);
 
        local_irq_disable();
+       sysdev_resume();
        device_power_up(PMSG_RESUME);
        local_irq_enable();
 }
index fb039cd345d861ce97e8b7585dc4f399483f8a13..6428aa17b40e794683b5359ed0589dc3dbfbf592 100644 (file)
@@ -1157,8 +1157,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
        data->cpu = pol->cpu;
        data->currpstate = HW_PSTATE_INVALID;
 
-       rc = powernow_k8_cpu_init_acpi(data);
-       if (rc) {
+       if (powernow_k8_cpu_init_acpi(data)) {
                /*
                 * Use the PSB BIOS structure. This is only availabe on
                 * an UP version, and is deprecated by AMD.
@@ -1176,17 +1175,20 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
                               "ACPI maintainers and complain to your BIOS "
                               "vendor.\n");
 #endif
-                       goto err_out;
+                       kfree(data);
+                       return -ENODEV;
                }
                if (pol->cpu != 0) {
                        printk(KERN_ERR FW_BUG PFX "No ACPI _PSS objects for "
                               "CPU other than CPU0. Complain to your BIOS "
                               "vendor.\n");
-                       goto err_out;
+                       kfree(data);
+                       return -ENODEV;
                }
                rc = find_psb_table(data);
                if (rc) {
-                       goto err_out;
+                       kfree(data);
+                       return -ENODEV;
                }
                /* Take a crude guess here.
                 * That guess was in microseconds, so multiply with 1000 */
index 1c838032fd3732fde9bff776cbb63a2821115d60..fe79985ce0f2f6fb4ae23f3bc92a791994ed9f62 100644 (file)
@@ -295,11 +295,11 @@ void do_machine_check(struct pt_regs * regs, long error_code)
                 * If we know that the error was in user space, send a
                 * SIGBUS.  Otherwise, panic if tolerance is low.
                 *
-                * do_exit() takes an awful lot of locks and has a slight
+                * force_sig() takes an awful lot of locks and has a slight
                 * risk of deadlocking.
                 */
                if (user_space) {
-                       do_exit(SIGBUS);
+                       force_sig(SIGBUS, current);
                } else if (panic_on_oops || tolerant < 2) {
                        mce_panic("Uncorrected machine check",
                                &panicm, mcestart);
@@ -490,7 +490,7 @@ static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
 
 }
 
-static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c)
+static void mce_cpu_features(struct cpuinfo_x86 *c)
 {
        switch (c->x86_vendor) {
        case X86_VENDOR_INTEL:
@@ -734,6 +734,7 @@ __setup("mce=", mcheck_enable);
 static int mce_resume(struct sys_device *dev)
 {
        mce_init(NULL);
+       mce_cpu_features(&current_cpu_data);
        return 0;
 }
 
index 8ae8c4ff094d1910ad77ca398192b4f362731e59..f2ee0ae29bd6e00b7755ab0573deae02e17ae592 100644 (file)
@@ -121,7 +121,7 @@ static long threshold_restart_bank(void *_tr)
 }
 
 /* cpu init entry point, called from mce.c with preempt off */
-void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
+void mce_amd_feature_init(struct cpuinfo_x86 *c)
 {
        unsigned int bank, block;
        unsigned int cpu = smp_processor_id();
index 4b48f251fd39ed540f99a2c91b6e7d66d93e1b56..f44c366243602b594566147a8447bfaa3d641013 100644 (file)
@@ -30,7 +30,7 @@ asmlinkage void smp_thermal_interrupt(void)
        irq_exit();
 }
 
-static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
+static void intel_init_thermal(struct cpuinfo_x86 *c)
 {
        u32 l, h;
        int tm2 = 0;
@@ -84,7 +84,7 @@ static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
        return;
 }
 
-void __cpuinit mce_intel_feature_init(struct cpuinfo_x86 *c)
+void mce_intel_feature_init(struct cpuinfo_x86 *c)
 {
        intel_init_thermal(c);
 }
index 388254f69a2ad13721f87797d7aa7790126655df..a00545fe5cdd1dae730fe18031b631bd1f57d8d5 100644 (file)
@@ -269,6 +269,8 @@ static void hpet_set_mode(enum clock_event_mode mode,
                now = hpet_readl(HPET_COUNTER);
                cmp = now + (unsigned long) delta;
                cfg = hpet_readl(HPET_Tn_CFG(timer));
+               /* Make sure we use edge triggered interrupts */
+               cfg &= ~HPET_TN_LEVEL;
                cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
                       HPET_TN_SETVAL | HPET_TN_32BIT;
                hpet_writel(cfg, HPET_Tn_CFG(timer));
index 7a13fac63a1f11ccd8cfe2cf72160117a0477cd2..4006c522adc780a0ce016b43b2d5a7ae93ca0f14 100644 (file)
@@ -203,7 +203,7 @@ static void __init platform_detect(void)
 static void __init platform_detect(void)
 {
        /* stopgap until OFW support is added to the kernel */
-       olpc_platform_info.boardrev = 0xc2;
+       olpc_platform_info.boardrev = olpc_board(0xc2);
 }
 #endif
 
index e4c8fb608873797c381f825cc874c5a4e0506e1b..c6520a4e85d4fe3479070d03867bfd65e50dd081 100644 (file)
@@ -268,6 +268,32 @@ enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
        return __get_cpu_var(paravirt_lazy_mode);
 }
 
+void arch_flush_lazy_mmu_mode(void)
+{
+       preempt_disable();
+
+       if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
+               WARN_ON(preempt_count() == 1);
+               arch_leave_lazy_mmu_mode();
+               arch_enter_lazy_mmu_mode();
+       }
+
+       preempt_enable();
+}
+
+void arch_flush_lazy_cpu_mode(void)
+{
+       preempt_disable();
+
+       if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU) {
+               WARN_ON(preempt_count() == 1);
+               arch_leave_lazy_cpu_mode();
+               arch_enter_lazy_cpu_mode();
+       }
+
+       preempt_enable();
+}
+
 struct pv_info pv_info = {
        .name = "bare hardware",
        .paravirt_enabled = 0,
index a546f55c77b4639f5e3f5773a1599d81cc53432d..bd4da2af08aec72ff1933eea7164a2b3d8f73139 100644 (file)
@@ -104,9 +104,6 @@ void cpu_idle(void)
                        check_pgt_cache();
                        rmb();
 
-                       if (rcu_pending(cpu))
-                               rcu_check_callbacks(cpu, 0);
-
                        if (cpu_is_offline(cpu))
                                play_dead();
 
index 0a5df5f82fb9579b1be4e824aa499ac561d9ba10..5a4c23d898926149e65b8cb5d826b7e868f4a527 100644 (file)
@@ -810,12 +810,16 @@ static void ptrace_bts_untrace(struct task_struct *child)
 
 static void ptrace_bts_detach(struct task_struct *child)
 {
-       if (unlikely(child->bts)) {
-               ds_release_bts(child->bts);
-               child->bts = NULL;
-
-               ptrace_bts_free_buffer(child);
-       }
+       /*
+        * Ptrace_detach() races with ptrace_untrace() in case
+        * the child dies and is reaped by another thread.
+        *
+        * We only do the memory accounting at this point and
+        * leave the buffer deallocation and the bts tracer
+        * release to ptrace_bts_untrace() which will be called
+        * later on with tasklist_lock held.
+        */
+       release_locked_buffer(child->bts_buffer, child->bts_size);
 }
 #else
 static inline void ptrace_bts_fork(struct task_struct *tsk) {}
index e6e695acd725739a645b5664f83a8356ff5b13a7..241ec3923f611bf03cb266362409924daabf1f6f 100644 (file)
@@ -115,7 +115,7 @@ unsigned long __init calibrate_cpu(void)
 
 static struct irqaction irq0 = {
        .handler        = timer_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING,
+       .flags          = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING | IRQF_TIMER,
        .mask           = CPU_MASK_NONE,
        .name           = "timer"
 };
index 7932338d7cb3112c7222121e513db0ca71190fa0..a9e7548e17906f885f28e4763128e749c7a76481 100644 (file)
@@ -99,6 +99,12 @@ static inline void preempt_conditional_sti(struct pt_regs *regs)
                local_irq_enable();
 }
 
+static inline void conditional_cli(struct pt_regs *regs)
+{
+       if (regs->flags & X86_EFLAGS_IF)
+               local_irq_disable();
+}
+
 static inline void preempt_conditional_cli(struct pt_regs *regs)
 {
        if (regs->flags & X86_EFLAGS_IF)
@@ -626,8 +632,10 @@ clear_dr7:
 
 #ifdef CONFIG_X86_32
 debug_vm86:
+       /* reenable preemption: handle_vm86_trap() might sleep */
+       dec_preempt_count();
        handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
-       preempt_conditional_cli(regs);
+       conditional_cli(regs);
        return;
 #endif
 
index c4c1f9e094027089373189f7e57cb7ede8149be9..e5b088fffa40f56f1418179efcd89ba480bcae6d 100644 (file)
@@ -202,7 +202,7 @@ static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id)
 static struct irqaction vmi_clock_action  = {
        .name           = "vmi-timer",
        .handler        = vmi_timer_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_NOBALANCING,
+       .flags          = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER,
        .mask           = CPU_MASK_ALL,
 };
 
@@ -283,10 +283,13 @@ void __devinit vmi_time_ap_init(void)
 #endif
 
 /** vmi clocksource */
+static struct clocksource clocksource_vmi;
 
 static cycle_t read_real_cycles(void)
 {
-       return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL);
+       cycle_t ret = (cycle_t)vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL);
+       return ret >= clocksource_vmi.cycle_last ?
+               ret : clocksource_vmi.cycle_last;
 }
 
 static struct clocksource clocksource_vmi = {
index e665d1c623ca04f45444daf5324e6c6d6477612d..72bd275a9b5cee632b393448e325f371610f860b 100644 (file)
@@ -207,7 +207,7 @@ static int __pit_timer_fn(struct kvm_kpit_state *ps)
        hrtimer_add_expires_ns(&pt->timer, pt->period);
        pt->scheduled = hrtimer_get_expires_ns(&pt->timer);
        if (pt->period)
-               ps->channels[0].count_load_time = hrtimer_get_expires(&pt->timer);
+               ps->channels[0].count_load_time = ktime_get();
 
        return (pt->period == 0 ? 0 : 1);
 }
index c019b8edcdb76bab269ceb48f8bc96e02fae7817..cf17ed52f6fbbe33563668604df0fa814f3cf493 100644 (file)
@@ -87,13 +87,6 @@ void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs);
 
-void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
-{
-       kvm_apic_timer_intr_post(vcpu, vec);
-       /* TODO: PIT, RTC etc. */
-}
-EXPORT_SYMBOL_GPL(kvm_timer_intr_post);
-
 void __kvm_migrate_timers(struct kvm_vcpu *vcpu)
 {
        __kvm_migrate_apic_timer(vcpu);
index 2bf32a03ceecf5837f6e30ef99b80067423632da..82579ee538d08b257f2a53a230cfb9cbf1a51986 100644 (file)
@@ -89,7 +89,6 @@ static inline int irqchip_in_kernel(struct kvm *kvm)
 
 void kvm_pic_reset(struct kvm_kpic_state *s);
 
-void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
 void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu);
 void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu);
 void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu);
index afac68c0815c78e712edc789821029d05b1d2d2f..f0b67f2cdd695a71c636ddfbe45b9ec9248b0748 100644 (file)
 #include "kvm_cache_regs.h"
 #include "irq.h"
 
+#ifndef CONFIG_X86_64
+#define mod_64(x, y) ((x) - (y) * div64_u64(x, y))
+#else
+#define mod_64(x, y) ((x) % (y))
+#endif
+
 #define PRId64 "d"
 #define PRIx64 "llx"
 #define PRIu64 "u"
@@ -511,52 +517,22 @@ static void apic_send_ipi(struct kvm_lapic *apic)
 
 static u32 apic_get_tmcct(struct kvm_lapic *apic)
 {
-       u64 counter_passed;
-       ktime_t passed, now;
+       ktime_t remaining;
+       s64 ns;
        u32 tmcct;
 
        ASSERT(apic != NULL);
 
-       now = apic->timer.dev.base->get_time();
-       tmcct = apic_get_reg(apic, APIC_TMICT);
-
        /* if initial count is 0, current count should also be 0 */
-       if (tmcct == 0)
+       if (apic_get_reg(apic, APIC_TMICT) == 0)
                return 0;
 
-       if (unlikely(ktime_to_ns(now) <=
-               ktime_to_ns(apic->timer.last_update))) {
-               /* Wrap around */
-               passed = ktime_add(( {
-                                   (ktime_t) {
-                                   .tv64 = KTIME_MAX -
-                                   (apic->timer.last_update).tv64}; }
-                                  ), now);
-               apic_debug("time elapsed\n");
-       } else
-               passed = ktime_sub(now, apic->timer.last_update);
-
-       counter_passed = div64_u64(ktime_to_ns(passed),
-                                  (APIC_BUS_CYCLE_NS * apic->timer.divide_count));
-
-       if (counter_passed > tmcct) {
-               if (unlikely(!apic_lvtt_period(apic))) {
-                       /* one-shot timers stick at 0 until reset */
-                       tmcct = 0;
-               } else {
-                       /*
-                        * periodic timers reset to APIC_TMICT when they
-                        * hit 0. The while loop simulates this happening N
-                        * times. (counter_passed %= tmcct) would also work,
-                        * but might be slower or not work on 32-bit??
-                        */
-                       while (counter_passed > tmcct)
-                               counter_passed -= tmcct;
-                       tmcct -= counter_passed;
-               }
-       } else {
-               tmcct -= counter_passed;
-       }
+       remaining = hrtimer_expires_remaining(&apic->timer.dev);
+       if (ktime_to_ns(remaining) < 0)
+               remaining = ktime_set(0, 0);
+
+       ns = mod_64(ktime_to_ns(remaining), apic->timer.period);
+       tmcct = div64_u64(ns, (APIC_BUS_CYCLE_NS * apic->timer.divide_count));
 
        return tmcct;
 }
@@ -653,8 +629,6 @@ static void start_apic_timer(struct kvm_lapic *apic)
 {
        ktime_t now = apic->timer.dev.base->get_time();
 
-       apic->timer.last_update = now;
-
        apic->timer.period = apic_get_reg(apic, APIC_TMICT) *
                    APIC_BUS_CYCLE_NS * apic->timer.divide_count;
        atomic_set(&apic->timer.pending, 0);
@@ -1110,16 +1084,6 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
        }
 }
 
-void kvm_apic_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
-{
-       struct kvm_lapic *apic = vcpu->arch.apic;
-
-       if (apic && apic_lvt_vector(apic, APIC_LVTT) == vec)
-               apic->timer.last_update = ktime_add_ns(
-                               apic->timer.last_update,
-                               apic->timer.period);
-}
-
 int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
 {
        int vector = kvm_apic_has_interrupt(vcpu);
index 81858881287e6962c4ab4863191f8e71cfef7a1b..45ab6ee71209f586596447c0b1ad02feca125698 100644 (file)
@@ -12,7 +12,6 @@ struct kvm_lapic {
                atomic_t pending;
                s64 period;     /* unit: ns */
                u32 divide_count;
-               ktime_t last_update;
                struct hrtimer dev;
        } timer;
        struct kvm_vcpu *vcpu;
@@ -42,7 +41,6 @@ void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data);
 void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu);
 int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
-void kvm_apic_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
 
 void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
 void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
index 83f11c7474a1d74ef996ca7245078e1b6dda7051..2d4477c7147372c28ed84f5a513ca553dc46979c 100644 (file)
@@ -1698,8 +1698,13 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
        if (largepage)
                spte |= PT_PAGE_SIZE_MASK;
        if (mt_mask) {
-               mt_mask = get_memory_type(vcpu, gfn) <<
-                         kvm_x86_ops->get_mt_mask_shift();
+               if (!kvm_is_mmio_pfn(pfn)) {
+                       mt_mask = get_memory_type(vcpu, gfn) <<
+                               kvm_x86_ops->get_mt_mask_shift();
+                       mt_mask |= VMX_EPT_IGMT_BIT;
+               } else
+                       mt_mask = MTRR_TYPE_UNCACHABLE <<
+                               kvm_x86_ops->get_mt_mask_shift();
                spte |= mt_mask;
        }
 
index 1452851ae2583b689f250a403ce6ee08075144c8..a9e769e4e2513b552d1a035884959a8a5280c84d 100644 (file)
@@ -1600,7 +1600,6 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu)
        /* Okay, we can deliver the interrupt: grab it and update PIC state. */
        intr_vector = kvm_cpu_get_interrupt(vcpu);
        svm_inject_irq(svm, intr_vector);
-       kvm_timer_intr_post(vcpu, intr_vector);
 out:
        update_cr8_intercept(vcpu);
 }
index 6259d7467648e1209456abff3666ad9a4e4a3cb4..7611af576829d820eba8de4a79d389e8baef7759 100644 (file)
@@ -903,6 +903,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
                data = vmcs_readl(GUEST_SYSENTER_ESP);
                break;
        default:
+               vmx_load_host_state(to_vmx(vcpu));
                msr = find_msr_entry(to_vmx(vcpu), msr_index);
                if (msr) {
                        data = msr->data;
@@ -3285,7 +3286,6 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
        }
        if (vcpu->arch.interrupt.pending) {
                vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
-               kvm_timer_intr_post(vcpu, vcpu->arch.interrupt.nr);
                if (kvm_cpu_has_interrupt(vcpu))
                        enable_irq_window(vcpu);
        }
@@ -3687,8 +3687,7 @@ static int __init vmx_init(void)
        if (vm_need_ept()) {
                bypass_guest_pf = 0;
                kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK |
-                       VMX_EPT_WRITABLE_MASK |
-                       VMX_EPT_IGMT_BIT);
+                       VMX_EPT_WRITABLE_MASK);
                kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull,
                                VMX_EPT_EXECUTABLE_MASK,
                                VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT);
index cc17546a2406af860329ea28d1ae85b7ebb4aa23..758b7a155ae9113559b5993b38abfc3cf603fe70 100644 (file)
@@ -967,7 +967,6 @@ int kvm_dev_ioctl_check_extension(long ext)
        case KVM_CAP_MMU_SHADOW_CACHE_CONTROL:
        case KVM_CAP_SET_TSS_ADDR:
        case KVM_CAP_EXT_CPUID:
-       case KVM_CAP_CLOCKSOURCE:
        case KVM_CAP_PIT:
        case KVM_CAP_NOP_IO_DELAY:
        case KVM_CAP_MP_STATE:
@@ -992,6 +991,9 @@ int kvm_dev_ioctl_check_extension(long ext)
        case KVM_CAP_IOMMU:
                r = iommu_found();
                break;
+       case KVM_CAP_CLOCKSOURCE:
+               r = boot_cpu_has(X86_FEATURE_CONSTANT_TSC);
+               break;
        default:
                r = 0;
                break;
@@ -4127,9 +4129,13 @@ static void kvm_free_vcpus(struct kvm *kvm)
 
 }
 
-void kvm_arch_destroy_vm(struct kvm *kvm)
+void kvm_arch_sync_events(struct kvm *kvm)
 {
        kvm_free_all_assigned_devices(kvm);
+}
+
+void kvm_arch_destroy_vm(struct kvm *kvm)
+{
        kvm_iommu_unmap_guest(kvm);
        kvm_free_pit(kvm);
        kfree(kvm->arch.vpic);
index a265a7c631901d111a9b907fa105754871a45e5b..50b5918711289a175287e0c8fb3b39f4c85a541e 100644 (file)
@@ -96,7 +96,7 @@ void __init trap_init_hook(void)
 
 static struct irqaction irq0  = {
        .handler = timer_interrupt,
-       .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL,
+       .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
        .mask = CPU_MASK_NONE,
        .name = "timer"
 };
index d914a7996a6684758f9ba1be29b6e012c88c21eb..8e5118371f0fac1cb3ff2e90d87e0c038c484aed 100644 (file)
@@ -56,7 +56,7 @@ void __init trap_init_hook(void)
 
 static struct irqaction irq0 = {
        .handler = timer_interrupt,
-       .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL,
+       .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
        .mask = CPU_MASK_NONE,
        .name = "timer"
 };
index af750ab973b6943840e9de53e4716819da06c4a2..f45d5e29a72edf4e15616d48c0d174f7905ac417 100644 (file)
@@ -134,25 +134,6 @@ int page_is_ram(unsigned long pagenr)
        return 0;
 }
 
-int pagerange_is_ram(unsigned long start, unsigned long end)
-{
-       int ram_page = 0, not_rampage = 0;
-       unsigned long page_nr;
-
-       for (page_nr = (start >> PAGE_SHIFT); page_nr < (end >> PAGE_SHIFT);
-            ++page_nr) {
-               if (page_is_ram(page_nr))
-                       ram_page = 1;
-               else
-                       not_rampage = 1;
-
-               if (ram_page == not_rampage)
-                       return -1;
-       }
-
-       return ram_page;
-}
-
 /*
  * Fix up the linear direct mapping of the kernel to avoid cache attribute
  * conflicts.
index 71a14f89f89e7367c72f2de85da6708acc83c069..f3516da035d141947d04ddfbd61bd56f74623fd3 100644 (file)
@@ -145,7 +145,7 @@ int __init compute_hash_shift(struct bootnode *nodes, int numnodes,
        return shift;
 }
 
-int early_pfn_to_nid(unsigned long pfn)
+int __meminit  __early_pfn_to_nid(unsigned long pfn)
 {
        return phys_to_nid(pfn << PAGE_SHIFT);
 }
index 84ba74820ad6436479a6456ec8d8e3a9a3c5c591..7be47d1a97e463590fe0565e72f36499d95949b5 100644 (file)
@@ -508,18 +508,13 @@ static int split_large_page(pte_t *kpte, unsigned long address)
 #endif
 
        /*
-        * Install the new, split up pagetable. Important details here:
+        * Install the new, split up pagetable.
         *
-        * On Intel the NX bit of all levels must be cleared to make a
-        * page executable. See section 4.13.2 of Intel 64 and IA-32
-        * Architectures Software Developer's Manual).
-        *
-        * Mark the entry present. The current mapping might be
-        * set to not present, which we preserved above.
+        * We use the standard kernel pagetable protections for the new
+        * pagetable protections, the actual ptes set above control the
+        * primary protection behavior:
         */
-       ref_prot = pte_pgprot(pte_mkexec(pte_clrhuge(*kpte)));
-       pgprot_val(ref_prot) |= _PAGE_PRESENT;
-       __set_pmd_pte(kpte, address, mk_pte(base, ref_prot));
+       __set_pmd_pte(kpte, address, mk_pte(base, __pgprot(_KERNPG_TABLE)));
        base = NULL;
 
 out_unlock:
@@ -575,7 +570,6 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)
                address = cpa->vaddr[cpa->curpage];
        else
                address = *cpa->vaddr;
-
 repeat:
        kpte = lookup_address(address, &level);
        if (!kpte)
@@ -812,6 +806,13 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
 
        vm_unmap_aliases();
 
+       /*
+        * If we're called with lazy mmu updates enabled, the
+        * in-memory pte state may be stale.  Flush pending updates to
+        * bring them up to date.
+        */
+       arch_flush_lazy_mmu_mode();
+
        cpa.vaddr = addr;
        cpa.numpages = numpages;
        cpa.mask_set = mask_set;
@@ -854,6 +855,13 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
        } else
                cpa_flush_all(cache);
 
+       /*
+        * If we've been called with lazy mmu updates enabled, then
+        * make sure that everything gets flushed out before we
+        * return.
+        */
+       arch_flush_lazy_mmu_mode();
+
 out:
        return ret;
 }
index 7b61036427df69d11a33044d60bc85102931e385..aebbf67a79d02326724e91065180675ecb525637 100644 (file)
@@ -211,6 +211,33 @@ chk_conflict(struct memtype *new, struct memtype *entry, unsigned long *type)
 static struct memtype *cached_entry;
 static u64 cached_start;
 
+static int pat_pagerange_is_ram(unsigned long start, unsigned long end)
+{
+       int ram_page = 0, not_rampage = 0;
+       unsigned long page_nr;
+
+       for (page_nr = (start >> PAGE_SHIFT); page_nr < (end >> PAGE_SHIFT);
+            ++page_nr) {
+               /*
+                * For legacy reasons, physical address range in the legacy ISA
+                * region is tracked as non-RAM. This will allow users of
+                * /dev/mem to map portions of legacy ISA region, even when
+                * some of those portions are listed(or not even listed) with
+                * different e820 types(RAM/reserved/..)
+                */
+               if (page_nr >= (ISA_END_ADDRESS >> PAGE_SHIFT) &&
+                   page_is_ram(page_nr))
+                       ram_page = 1;
+               else
+                       not_rampage = 1;
+
+               if (ram_page == not_rampage)
+                       return -1;
+       }
+
+       return ram_page;
+}
+
 /*
  * For RAM pages, mark the pages as non WB memory type using
  * PageNonWB (PG_arch_1). We allow only one set_memory_uc() or
@@ -336,20 +363,12 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
        if (new_type)
                *new_type = actual_type;
 
-       /*
-        * For legacy reasons, some parts of the physical address range in the
-        * legacy 1MB region is treated as non-RAM (even when listed as RAM in
-        * the e820 tables).  So we will track the memory attributes of this
-        * legacy 1MB region using the linear memtype_list always.
-        */
-       if (end >= ISA_END_ADDRESS) {
-               is_range_ram = pagerange_is_ram(start, end);
-               if (is_range_ram == 1)
-                       return reserve_ram_pages_type(start, end, req_type,
-                                                     new_type);
-               else if (is_range_ram < 0)
-                       return -EINVAL;
-       }
+       is_range_ram = pat_pagerange_is_ram(start, end);
+       if (is_range_ram == 1)
+               return reserve_ram_pages_type(start, end, req_type,
+                                             new_type);
+       else if (is_range_ram < 0)
+               return -EINVAL;
 
        new  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
        if (!new)
@@ -446,19 +465,11 @@ int free_memtype(u64 start, u64 end)
        if (is_ISA_range(start, end - 1))
                return 0;
 
-       /*
-        * For legacy reasons, some parts of the physical address range in the
-        * legacy 1MB region is treated as non-RAM (even when listed as RAM in
-        * the e820 tables).  So we will track the memory attributes of this
-        * legacy 1MB region using the linear memtype_list always.
-        */
-       if (end >= ISA_END_ADDRESS) {
-               is_range_ram = pagerange_is_ram(start, end);
-               if (is_range_ram == 1)
-                       return free_ram_pages_type(start, end);
-               else if (is_range_ram < 0)
-                       return -EINVAL;
-       }
+       is_range_ram = pat_pagerange_is_ram(start, end);
+       if (is_range_ram == 1)
+               return free_ram_pages_type(start, end);
+       else if (is_range_ram < 0)
+               return -EINVAL;
 
        spin_lock(&memtype_lock);
        list_for_each_entry(entry, &memtype_list, nd) {
@@ -626,17 +637,13 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
        unsigned long flags;
        unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK);
 
-       is_ram = pagerange_is_ram(paddr, paddr + size);
+       is_ram = pat_pagerange_is_ram(paddr, paddr + size);
 
-       if (is_ram != 0) {
-               /*
-                * For mapping RAM pages, drivers need to call
-                * set_memory_[uc|wc|wb] directly, for reserve and free, before
-                * setting up the PTE.
-                */
-               WARN_ON_ONCE(1);
-               return 0;
-       }
+       /*
+        * reserve_pfn_range() doesn't support RAM pages.
+        */
+       if (is_ram != 0)
+               return -EINVAL;
 
        ret = reserve_memtype(paddr, paddr + size, want_flags, &flags);
        if (ret)
@@ -693,7 +700,7 @@ static void free_pfn_range(u64 paddr, unsigned long size)
 {
        int is_ram;
 
-       is_ram = pagerange_is_ram(paddr, paddr + size);
+       is_ram = pat_pagerange_is_ram(paddr, paddr + size);
        if (is_ram == 0)
                free_memtype(paddr, paddr + size);
 }
index a09535377a94c0b84a59118533f5e4ddeaa1076d..bbbdc4b8ccf27a9d0d1f4a9648a930b89f8761a0 100644 (file)
@@ -209,12 +209,19 @@ void blk_abort_queue(struct request_queue *q)
 {
        unsigned long flags;
        struct request *rq, *tmp;
+       LIST_HEAD(list);
 
        spin_lock_irqsave(q->queue_lock, flags);
 
        elv_abort_queue(q);
 
-       list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list)
+       /*
+        * Splice entries to local list, to avoid deadlocking if entries
+        * get readded to the timeout list by error handling
+        */
+       list_splice_init(&q->timeout_list, &list);
+
+       list_for_each_entry_safe(rq, tmp, &list, timeout_list)
                blk_abort_request(rq);
 
        spin_unlock_irqrestore(q->queue_lock, flags);
index 39cc3bfe56e41055793a804e1461dad39045b264..7cf9d1ff45a015e0d8fe7be2546c6fb7f95f590e 100644 (file)
@@ -142,7 +142,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
 
        what |= ddir_act[rw & WRITE];
        what |= MASK_TC_BIT(rw, BARRIER);
-       what |= MASK_TC_BIT(rw, SYNC);
+       what |= MASK_TC_BIT(rw, SYNCIO);
        what |= MASK_TC_BIT(rw, AHEAD);
        what |= MASK_TC_BIT(rw, META);
        what |= MASK_TC_BIT(rw, DISCARD);
index d414bb5607e89f4e3a05466b2a488db5e79c98a3..0ce8806dd0c1a3786b6cd86ba8a90b743ca81b8d 100644 (file)
@@ -244,7 +244,8 @@ bsg_validate_sgv4_hdr(struct request_queue *q, struct sg_io_v4 *hdr, int *rw)
  * map sg_io_v4 to a request.
  */
 static struct request *
-bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm)
+bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
+           u8 *sense)
 {
        struct request_queue *q = bd->queue;
        struct request *rq, *next_rq = NULL;
@@ -306,6 +307,10 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm)
                if (ret)
                        goto out;
        }
+
+       rq->sense = sense;
+       rq->sense_len = 0;
+
        return rq;
 out:
        if (rq->cmd != rq->__cmd)
@@ -348,9 +353,6 @@ static void bsg_rq_end_io(struct request *rq, int uptodate)
 static void bsg_add_command(struct bsg_device *bd, struct request_queue *q,
                            struct bsg_command *bc, struct request *rq)
 {
-       rq->sense = bc->sense;
-       rq->sense_len = 0;
-
        /*
         * add bc command to busy queue and submit rq for io
         */
@@ -419,7 +421,7 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
 {
        int ret = 0;
 
-       dprintk("rq %p bio %p %u\n", rq, bio, rq->errors);
+       dprintk("rq %p bio %p 0x%x\n", rq, bio, rq->errors);
        /*
         * fill in all the output members
         */
@@ -635,7 +637,7 @@ static int __bsg_write(struct bsg_device *bd, const char __user *buf,
                /*
                 * get a request, fill in the blanks, and add to request queue
                 */
-               rq = bsg_map_hdr(bd, &bc->hdr, has_write_perm);
+               rq = bsg_map_hdr(bd, &bc->hdr, has_write_perm, bc->sense);
                if (IS_ERR(rq)) {
                        ret = PTR_ERR(rq);
                        rq = NULL;
@@ -922,11 +924,12 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                struct request *rq;
                struct bio *bio, *bidi_bio = NULL;
                struct sg_io_v4 hdr;
+               u8 sense[SCSI_SENSE_BUFFERSIZE];
 
                if (copy_from_user(&hdr, uarg, sizeof(hdr)))
                        return -EFAULT;
 
-               rq = bsg_map_hdr(bd, &hdr, file->f_mode & FMODE_WRITE);
+               rq = bsg_map_hdr(bd, &hdr, file->f_mode & FMODE_WRITE, sense);
                if (IS_ERR(rq))
                        return PTR_ERR(rq);
 
index 397960cf26afcd61fc7c2bba2365944c8485c767..e1eadcc9546a72ec0d1c76d933143767dd357536 100644 (file)
@@ -1087,6 +1087,14 @@ dev_t blk_lookup_devt(const char *name, int partno)
                if (strcmp(dev_name(dev), name))
                        continue;
 
+               if (partno < disk->minors) {
+                       /* We need to return the right devno, even
+                        * if the partition doesn't exist yet.
+                        */
+                       devt = MKDEV(MAJOR(dev->devt),
+                                    MINOR(dev->devt) + partno);
+                       break;
+               }
                part = disk_get_part(disk, partno);
                if (part) {
                        devt = part_devt(part);
index a7799a99f2d9a192b2b98ed5e0bdb5d5c9796f56..8a851d0f438458392f03fce3c8ded88957f96124 100644 (file)
@@ -254,13 +254,6 @@ config ACPI_PCI_SLOT
          help you correlate PCI bus addresses with the physical geography
          of your slots. If you are unsure, say N.
 
-config ACPI_SYSTEM
-       bool
-       default y
-       help
-         This driver will enable your system to shut down using ACPI, and
-         dump your ACPI DSDT table using /proc/acpi/dsdt.
-
 config X86_PM_TIMER
        bool "Power Management Timer Support" if EMBEDDED
        depends on X86
index 65d90c720b5a63995179235af6683577e112cc44..b130ea0d0759a3f95c8b81d3c203e4bdea1c5820 100644 (file)
@@ -52,7 +52,7 @@ obj-$(CONFIG_ACPI_PROCESSOR)  += processor.o
 obj-$(CONFIG_ACPI_CONTAINER)   += container.o
 obj-$(CONFIG_ACPI_THERMAL)     += thermal.o
 obj-y                          += power.o
-obj-$(CONFIG_ACPI_SYSTEM)      += system.o event.o
+obj-y                          += system.o event.o
 obj-$(CONFIG_ACPI_DEBUG)       += debug.o
 obj-$(CONFIG_ACPI_NUMA)                += numa.o
 obj-$(CONFIG_ACPI_HOTPLUG_MEMORY)      += acpi_memhotplug.o
index 65132f9204596eb9908b8e0424531ec682a8b731..69cbc57c2d1cd248e7431bb40661e9ea139efbb7 100644 (file)
@@ -138,6 +138,29 @@ static int acpi_battery_technology(struct acpi_battery *battery)
 
 static int acpi_battery_get_state(struct acpi_battery *battery);
 
+static int acpi_battery_is_charged(struct acpi_battery *battery)
+{
+       /* either charging or discharging */
+       if (battery->state != 0)
+               return 0;
+
+       /* battery not reporting charge */
+       if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
+           battery->capacity_now == 0)
+               return 0;
+
+       /* good batteries update full_charge as the batteries degrade */
+       if (battery->full_charge_capacity == battery->capacity_now)
+               return 1;
+
+       /* fallback to using design values for broken batteries */
+       if (battery->design_capacity == battery->capacity_now)
+               return 1;
+
+       /* we don't do any sort of metric based on percentages */
+       return 0;
+}
+
 static int acpi_battery_get_property(struct power_supply *psy,
                                     enum power_supply_property psp,
                                     union power_supply_propval *val)
@@ -155,7 +178,7 @@ static int acpi_battery_get_property(struct power_supply *psy,
                        val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
                else if (battery->state & 0x02)
                        val->intval = POWER_SUPPLY_STATUS_CHARGING;
-               else if (battery->state == 0)
+               else if (acpi_battery_is_charged(battery))
                        val->intval = POWER_SUPPLY_STATUS_FULL;
                else
                        val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
index 5c2f5d343be6185fc552c0181c194429fdccb027..2fe15060dcdc2c3a51dd9f3ef20171e0b4e50c8e 100644 (file)
@@ -120,6 +120,8 @@ static struct acpi_ec {
        spinlock_t curr_lock;
 } *boot_ec, *first_ec;
 
+static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
+
 /* --------------------------------------------------------------------------
                              Transaction Management
    -------------------------------------------------------------------------- */
@@ -259,6 +261,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
                clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
                acpi_disable_gpe(NULL, ec->gpe);
        }
+       if (EC_FLAGS_MSI)
+               udelay(ACPI_EC_DELAY);
        /* start transaction */
        spin_lock_irqsave(&ec->curr_lock, tmp);
        /* following two actions should be kept atomic */
@@ -967,6 +971,11 @@ int __init acpi_ec_ecdt_probe(void)
        /*
         * Generate a boot ec context
         */
+       if (dmi_name_in_vendors("Micro-Star") ||
+           dmi_name_in_vendors("Notebook")) {
+               pr_info(PREFIX "Enabling special treatment for EC from MSI.\n");
+               EC_FLAGS_MSI = 1;
+       }
        status = acpi_get_table(ACPI_SIG_ECDT, 1,
                                (struct acpi_table_header **)&ecdt_ptr);
        if (ACPI_SUCCESS(status)) {
index 0b299b0f81721bbe1446169b8fa5b51c86eecd2d..714cb046b594200a17d096768f0d8a45f89a835a 100644 (file)
@@ -773,18 +773,32 @@ unsigned int ata_sff_data_xfer32(struct ata_device *dev, unsigned char *buf,
        else
                iowrite32_rep(data_addr, buf, words);
 
+       /* Transfer trailing bytes, if any */
        if (unlikely(slop)) {
-               __le32 pad;
+               unsigned char pad[4];
+
+               /* Point buf to the tail of buffer */
+               buf += buflen - slop;
+
+               /*
+                * Use io*_rep() accessors here as well to avoid pointlessly
+                * swapping bytes to and fro on the big endian machines...
+                */
                if (rw == READ) {
-                       pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
-                       memcpy(buf + buflen - slop, &pad, slop);
+                       if (slop < 3)
+                               ioread16_rep(data_addr, pad, 1);
+                       else
+                               ioread32_rep(data_addr, pad, 1);
+                       memcpy(buf, pad, slop);
                } else {
-                       memcpy(&pad, buf + buflen - slop, slop);
-                       iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
+                       memcpy(pad, buf, slop);
+                       if (slop < 3)
+                               iowrite16_rep(data_addr, pad, 1);
+                       else
+                               iowrite32_rep(data_addr, pad, 1);
                }
-               words++;
        }
-       return words << 2;
+       return (buflen + 1) & ~1;
 }
 EXPORT_SYMBOL_GPL(ata_sff_data_xfer32);
 
index 79a6c9a0b721b5caacb43c9785bebb877d16c9d1..ba556d3e696368ecea761e4440f82434695318f9 100644 (file)
@@ -110,7 +110,8 @@ static const struct via_isa_bridge {
        { "vt8237s",    PCI_DEVICE_ID_VIA_8237S,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
        { "vt8251",     PCI_DEVICE_ID_VIA_8251,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
        { "cx700",      PCI_DEVICE_ID_VIA_CX700,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA },
-       { "vt6410",     PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES},
+       { "vt6410",     PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
+       { "vt6415",     PCI_DEVICE_ID_VIA_6415,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
        { "vt8237a",    PCI_DEVICE_ID_VIA_8237A,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
        { "vt8237",     PCI_DEVICE_ID_VIA_8237,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
        { "vt8235",     PCI_DEVICE_ID_VIA_8235,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
@@ -593,6 +594,7 @@ static int via_reinit_one(struct pci_dev *pdev)
 #endif
 
 static const struct pci_device_id via[] = {
+       { PCI_VDEVICE(VIA, 0x0415), },
        { PCI_VDEVICE(VIA, 0x0571), },
        { PCI_VDEVICE(VIA, 0x0581), },
        { PCI_VDEVICE(VIA, 0x1571), },
index 444af0415ca167b67f91adbf6ae24a5507c78987..55a8eed3f3a35cb9fa64b9e67800a40d72d5d062 100644 (file)
@@ -421,19 +421,21 @@ static struct ata_port_operations nv_generic_ops = {
        .hardreset              = ATA_OP_NULL,
 };
 
-/* OSDL bz3352 reports that nf2/3 controllers can't determine device
- * signature reliably.  Also, the following thread reports detection
- * failure on cold boot with the standard debouncing timing.
+/* nf2 is ripe with hardreset related problems.
+ *
+ * kernel bz#3352 reports nf2/3 controllers can't determine device
+ * signature reliably.  The following thread reports detection failure
+ * on cold boot with the standard debouncing timing.
  *
  * http://thread.gmane.org/gmane.linux.ide/34098
  *
- * Debounce with hotplug timing and request follow-up SRST.
+ * And bz#12176 reports that hardreset simply doesn't work on nf2.
+ * Give up on it and just don't do hardreset.
  */
 static struct ata_port_operations nv_nf2_ops = {
-       .inherits               = &nv_common_ops,
+       .inherits               = &nv_generic_ops,
        .freeze                 = nv_nf2_freeze,
        .thaw                   = nv_nf2_thaw,
-       .hardreset              = nv_noclassify_hardreset,
 };
 
 /* For initial probing after boot and hot plugging, hardreset mostly
index 144a49f152207402c044caca1c0c8dde47f10747..8733a2ea04c2b39a02fede69c6e4dbd69035cd3a 100644 (file)
@@ -901,7 +901,7 @@ static int __devinit eeprom_read(struct lanai_dev *lanai)
                clock_l(); udelay(5);
                for (i = 128; i != 0; i >>= 1) {   /* write command out */
                        tmp = (lanai->conf1 & ~CONFIG1_PROMDATA) |
-                           (data & i) ? CONFIG1_PROMDATA : 0;
+                           ((data & i) ? CONFIG1_PROMDATA : 0);
                        if (lanai->conf1 != tmp) {
                                set_config1(tmp);
                                udelay(5);      /* Let new data settle */
index 0a5f055dffbaa389fd8f4b2f0bfe81fe5a352241..9f50f1b545dc49de323135663628da1566797175 100644 (file)
@@ -88,8 +88,6 @@ extern void driver_detach(struct device_driver *drv);
 extern int driver_probe_device(struct device_driver *drv, struct device *dev);
 
 extern void sysdev_shutdown(void);
-extern int sysdev_suspend(pm_message_t state);
-extern int sysdev_resume(void);
 
 extern char *make_class_name(const char *name, struct kobject *kobj);
 
index 315bed8d5e7fc5e33d1ea10e9f4c084e03428036..1352312391032fcda76f672c5b43a76e5c6df6f0 100644 (file)
  */
 
 #include <linux/device.h>
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/kthread.h>
 #include <linux/wait.h>
+#include <linux/async.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -167,6 +169,21 @@ int driver_probe_done(void)
        return 0;
 }
 
+/**
+ * wait_for_device_probe
+ * Wait for device probing to be completed.
+ *
+ * Note: this function polls at 100 msec intervals.
+ */
+int wait_for_device_probe(void)
+{
+       /* wait for the known devices to complete their probing */
+       while (driver_probe_done() != 0)
+               msleep(100);
+       async_synchronize_full();
+       return 0;
+}
+
 /**
  * driver_probe_device - attempt to bind device & driver together
  * @drv: driver to bind a device to
index 670c9d6c140743a7fac01bcfada07254d4da5016..2d14f4ae6c01da28be636629db5e50b9205b5699 100644 (file)
@@ -333,7 +333,6 @@ static void dpm_power_up(pm_message_t state)
  */
 void device_power_up(pm_message_t state)
 {
-       sysdev_resume();
        dpm_power_up(state);
 }
 EXPORT_SYMBOL_GPL(device_power_up);
@@ -577,8 +576,6 @@ int device_power_down(pm_message_t state)
                }
                dev->power.status = DPM_OFF_IRQ;
        }
-       if (!error)
-               error = sysdev_suspend(state);
        if (error)
                dpm_power_up(resume_event(state));
        return error;
index c98c31ec2f752189e2481a278ed8e7f02cf01985..b428c8c4bc6464177ea32524341e85992346ce3b 100644 (file)
@@ -303,7 +303,6 @@ void sysdev_unregister(struct sys_device * sysdev)
  *     is guaranteed by virtue of the fact that child devices are registered
  *     after their parents.
  */
-
 void sysdev_shutdown(void)
 {
        struct sysdev_class * cls;
@@ -363,7 +362,6 @@ static void __sysdev_resume(struct sys_device *dev)
  *     This is only called by the device PM core, so we let them handle
  *     all synchronization.
  */
-
 int sysdev_suspend(pm_message_t state)
 {
        struct sysdev_class * cls;
@@ -432,7 +430,7 @@ aux_driver:
        }
        return ret;
 }
-
+EXPORT_SYMBOL_GPL(sysdev_suspend);
 
 /**
  *     sysdev_resume - Bring system devices back to life.
@@ -442,7 +440,6 @@ aux_driver:
  *
  *     Note: Interrupts are disabled when called.
  */
-
 int sysdev_resume(void)
 {
        struct sysdev_class * cls;
@@ -463,7 +460,7 @@ int sysdev_resume(void)
        }
        return 0;
 }
-
+EXPORT_SYMBOL_GPL(sysdev_resume);
 
 int __init system_bus_init(void)
 {
index c237527b1aa59880b272a13bc8d0a17d6206ca2a..5e41e6dd657b9a7326ba1347346c8147c428f3c2 100644 (file)
@@ -18,6 +18,7 @@
 enum {
        AOECMD_ATA,
        AOECMD_CFG,
+       AOECMD_VEND_MIN = 0xf0,
 
        AOEFL_RSP = (1<<3),
        AOEFL_ERR = (1<<2),
index 30de5b1c647e80b05007a22f1a4e0b79a38dcad4..c6099ba9a4b895ebabb5905255fd5a3f589145a8 100644 (file)
@@ -142,6 +142,8 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
                aoecmd_cfg_rsp(skb);
                break;
        default:
+               if (h->cmd >= AOECMD_VEND_MIN)
+                       break;  /* don't complain about vendor commands */
                printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd);
        }
 exit:
index 69e1df7dfa14a4447c6797a0b6f1f6d8c18993fb..4234c11c1e4cfe34592c9830eca7d2a68400b052 100644 (file)
@@ -1730,7 +1730,7 @@ static int __init fd_test_drive_present( int drive )
 
        timeout = jiffies + 2*HZ+HZ/2;
        while (time_before(jiffies, timeout))
-               if (!(mfp.par_dt_reg & 0x20))
+               if (!(st_mfp.par_dt_reg & 0x20))
                        break;
 
        status = FDC_READ( FDCREG_STATUS );
@@ -1747,7 +1747,7 @@ static int __init fd_test_drive_present( int drive )
                /* dummy seek command to make WP bit accessible */
                FDC_WRITE( FDCREG_DATA, 0 );
                FDC_WRITE( FDCREG_CMD, FDCCMD_SEEK );
-               while( mfp.par_dt_reg & 0x20 )
+               while( st_mfp.par_dt_reg & 0x20 )
                        ;
                status = FDC_READ( FDCREG_STATUS );
        }
index 01e69383d9c07ece3df6e56d23b4d3b2bf687475..d2cb67b61176674f7e8df4230f1d807db2190ee3 100644 (file)
@@ -3390,6 +3390,203 @@ static void free_hba(int i)
        kfree(p);
 }
 
+/* Send a message CDB to the firmware. */
+static __devinit int cciss_message(struct pci_dev *pdev, unsigned char opcode, unsigned char type)
+{
+       typedef struct {
+               CommandListHeader_struct CommandHeader;
+               RequestBlock_struct Request;
+               ErrDescriptor_struct ErrorDescriptor;
+       } Command;
+       static const size_t cmd_sz = sizeof(Command) + sizeof(ErrorInfo_struct);
+       Command *cmd;
+       dma_addr_t paddr64;
+       uint32_t paddr32, tag;
+       void __iomem *vaddr;
+       int i, err;
+
+       vaddr = ioremap_nocache(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+       if (vaddr == NULL)
+               return -ENOMEM;
+
+       /* The Inbound Post Queue only accepts 32-bit physical addresses for the
+          CCISS commands, so they must be allocated from the lower 4GiB of
+          memory. */
+       err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+       if (err) {
+               iounmap(vaddr);
+               return -ENOMEM;
+       }
+
+       cmd = pci_alloc_consistent(pdev, cmd_sz, &paddr64);
+       if (cmd == NULL) {
+               iounmap(vaddr);
+               return -ENOMEM;
+       }
+
+       /* This must fit, because of the 32-bit consistent DMA mask.  Also,
+          although there's no guarantee, we assume that the address is at
+          least 4-byte aligned (most likely, it's page-aligned). */
+       paddr32 = paddr64;
+
+       cmd->CommandHeader.ReplyQueue = 0;
+       cmd->CommandHeader.SGList = 0;
+       cmd->CommandHeader.SGTotal = 0;
+       cmd->CommandHeader.Tag.lower = paddr32;
+       cmd->CommandHeader.Tag.upper = 0;
+       memset(&cmd->CommandHeader.LUN.LunAddrBytes, 0, 8);
+
+       cmd->Request.CDBLen = 16;
+       cmd->Request.Type.Type = TYPE_MSG;
+       cmd->Request.Type.Attribute = ATTR_HEADOFQUEUE;
+       cmd->Request.Type.Direction = XFER_NONE;
+       cmd->Request.Timeout = 0; /* Don't time out */
+       cmd->Request.CDB[0] = opcode;
+       cmd->Request.CDB[1] = type;
+       memset(&cmd->Request.CDB[2], 0, 14); /* the rest of the CDB is reserved */
+
+       cmd->ErrorDescriptor.Addr.lower = paddr32 + sizeof(Command);
+       cmd->ErrorDescriptor.Addr.upper = 0;
+       cmd->ErrorDescriptor.Len = sizeof(ErrorInfo_struct);
+
+       writel(paddr32, vaddr + SA5_REQUEST_PORT_OFFSET);
+
+       for (i = 0; i < 10; i++) {
+               tag = readl(vaddr + SA5_REPLY_PORT_OFFSET);
+               if ((tag & ~3) == paddr32)
+                       break;
+               schedule_timeout_uninterruptible(HZ);
+       }
+
+       iounmap(vaddr);
+
+       /* we leak the DMA buffer here ... no choice since the controller could
+          still complete the command. */
+       if (i == 10) {
+               printk(KERN_ERR "cciss: controller message %02x:%02x timed out\n",
+                       opcode, type);
+               return -ETIMEDOUT;
+       }
+
+       pci_free_consistent(pdev, cmd_sz, cmd, paddr64);
+
+       if (tag & 2) {
+               printk(KERN_ERR "cciss: controller message %02x:%02x failed\n",
+                       opcode, type);
+               return -EIO;
+       }
+
+       printk(KERN_INFO "cciss: controller message %02x:%02x succeeded\n",
+               opcode, type);
+       return 0;
+}
+
+#define cciss_soft_reset_controller(p) cciss_message(p, 1, 0)
+#define cciss_noop(p) cciss_message(p, 3, 0)
+
+static __devinit int cciss_reset_msi(struct pci_dev *pdev)
+{
+/* the #defines are stolen from drivers/pci/msi.h. */
+#define msi_control_reg(base)          (base + PCI_MSI_FLAGS)
+#define PCI_MSIX_FLAGS_ENABLE          (1 << 15)
+
+       int pos;
+       u16 control = 0;
+
+       pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
+       if (pos) {
+               pci_read_config_word(pdev, msi_control_reg(pos), &control);
+               if (control & PCI_MSI_FLAGS_ENABLE) {
+                       printk(KERN_INFO "cciss: resetting MSI\n");
+                       pci_write_config_word(pdev, msi_control_reg(pos), control & ~PCI_MSI_FLAGS_ENABLE);
+               }
+       }
+
+       pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+       if (pos) {
+               pci_read_config_word(pdev, msi_control_reg(pos), &control);
+               if (control & PCI_MSIX_FLAGS_ENABLE) {
+                       printk(KERN_INFO "cciss: resetting MSI-X\n");
+                       pci_write_config_word(pdev, msi_control_reg(pos), control & ~PCI_MSIX_FLAGS_ENABLE);
+               }
+       }
+
+       return 0;
+}
+
+/* This does a hard reset of the controller using PCI power management
+ * states. */
+static __devinit int cciss_hard_reset_controller(struct pci_dev *pdev)
+{
+       u16 pmcsr, saved_config_space[32];
+       int i, pos;
+
+       printk(KERN_INFO "cciss: using PCI PM to reset controller\n");
+
+       /* This is very nearly the same thing as
+
+          pci_save_state(pci_dev);
+          pci_set_power_state(pci_dev, PCI_D3hot);
+          pci_set_power_state(pci_dev, PCI_D0);
+          pci_restore_state(pci_dev);
+
+          but we can't use these nice canned kernel routines on
+          kexec, because they also check the MSI/MSI-X state in PCI
+          configuration space and do the wrong thing when it is
+          set/cleared.  Also, the pci_save/restore_state functions
+          violate the ordering requirements for restoring the
+          configuration space from the CCISS document (see the
+          comment below).  So we roll our own .... */
+
+       for (i = 0; i < 32; i++)
+               pci_read_config_word(pdev, 2*i, &saved_config_space[i]);
+
+       pos = pci_find_capability(pdev, PCI_CAP_ID_PM);
+       if (pos == 0) {
+               printk(KERN_ERR "cciss_reset_controller: PCI PM not supported\n");
+               return -ENODEV;
+       }
+
+       /* Quoting from the Open CISS Specification: "The Power
+        * Management Control/Status Register (CSR) controls the power
+        * state of the device.  The normal operating state is D0,
+        * CSR=00h.  The software off state is D3, CSR=03h.  To reset
+        * the controller, place the interface device in D3 then to
+        * D0, this causes a secondary PCI reset which will reset the
+        * controller." */
+
+       /* enter the D3hot power management state */
+       pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr);
+       pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+       pmcsr |= PCI_D3hot;
+       pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+
+       schedule_timeout_uninterruptible(HZ >> 1);
+
+       /* enter the D0 power management state */
+       pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+       pmcsr |= PCI_D0;
+       pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+
+       schedule_timeout_uninterruptible(HZ >> 1);
+
+       /* Restore the PCI configuration space.  The Open CISS
+        * Specification says, "Restore the PCI Configuration
+        * Registers, offsets 00h through 60h. It is important to
+        * restore the command register, 16-bits at offset 04h,
+        * last. Do not restore the configuration status register,
+        * 16-bits at offset 06h."  Note that the offset is 2*i. */
+       for (i = 0; i < 32; i++) {
+               if (i == 2 || i == 3)
+                       continue;
+               pci_write_config_word(pdev, 2*i, saved_config_space[i]);
+       }
+       wmb();
+       pci_write_config_word(pdev, 4, saved_config_space[2]);
+
+       return 0;
+}
+
 /*
  *  This is it.  Find all the controllers and register them.  I really hate
  *  stealing all these major device numbers.
@@ -3404,6 +3601,24 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        int dac, return_code;
        InquiryData_struct *inq_buff = NULL;
 
+       if (reset_devices) {
+               /* Reset the controller with a PCI power-cycle */
+               if (cciss_hard_reset_controller(pdev) || cciss_reset_msi(pdev))
+                       return -ENODEV;
+
+               /* Some devices (notably the HP Smart Array 5i Controller)
+                  need a little pause here */
+               schedule_timeout_uninterruptible(30*HZ);
+
+               /* Now try to get the controller to respond to a no-op */
+               for (i=0; i<12; i++) {
+                       if (cciss_noop(pdev) == 0)
+                               break;
+                       else
+                               printk("cciss: no-op failed%s\n", (i < 11 ? "; re-trying" : ""));
+               }
+       }
+
        i = alloc_cciss_hba();
        if (i < 0)
                return -1;
index cf29cc4e6ab73d2d95e6d4778f576aae9c98b327..83d8ed39433d058f70896057e52fc4d1e4dc99f3 100644 (file)
@@ -558,6 +558,8 @@ static void process_fd_request(void);
 static void recalibrate_floppy(void);
 static void floppy_shutdown(unsigned long);
 
+static int floppy_request_regions(int);
+static void floppy_release_regions(int);
 static int floppy_grab_irq_and_dma(void);
 static void floppy_release_irq_and_dma(void);
 
@@ -4274,8 +4276,7 @@ static int __init floppy_init(void)
                FDCS->rawcmd = 2;
                if (user_reset_fdc(-1, FD_RESET_ALWAYS, 0)) {
                        /* free ioports reserved by floppy_grab_irq_and_dma() */
-                       release_region(FDCS->address + 2, 4);
-                       release_region(FDCS->address + 7, 1);
+                       floppy_release_regions(fdc);
                        FDCS->address = -1;
                        FDCS->version = FDC_NONE;
                        continue;
@@ -4284,8 +4285,7 @@ static int __init floppy_init(void)
                FDCS->version = get_fdc_version();
                if (FDCS->version == FDC_NONE) {
                        /* free ioports reserved by floppy_grab_irq_and_dma() */
-                       release_region(FDCS->address + 2, 4);
-                       release_region(FDCS->address + 7, 1);
+                       floppy_release_regions(fdc);
                        FDCS->address = -1;
                        continue;
                }
@@ -4358,6 +4358,47 @@ out_put_disk:
 
 static DEFINE_SPINLOCK(floppy_usage_lock);
 
+static const struct io_region {
+       int offset;
+       int size;
+} io_regions[] = {
+       { 2, 1 },
+       /* address + 3 is sometimes reserved by pnp bios for motherboard */
+       { 4, 2 },
+       /* address + 6 is reserved, and may be taken by IDE.
+        * Unfortunately, Adaptec doesn't know this :-(, */
+       { 7, 1 },
+};
+
+static void floppy_release_allocated_regions(int fdc, const struct io_region *p)
+{
+       while (p != io_regions) {
+               p--;
+               release_region(FDCS->address + p->offset, p->size);
+       }
+}
+
+#define ARRAY_END(X) (&((X)[ARRAY_SIZE(X)]))
+
+static int floppy_request_regions(int fdc)
+{
+       const struct io_region *p;
+
+       for (p = io_regions; p < ARRAY_END(io_regions); p++) {
+               if (!request_region(FDCS->address + p->offset, p->size, "floppy")) {
+                       DPRINT("Floppy io-port 0x%04lx in use\n", FDCS->address + p->offset);
+                       floppy_release_allocated_regions(fdc, p);
+                       return -EBUSY;
+               }
+       }
+       return 0;
+}
+
+static void floppy_release_regions(int fdc)
+{
+       floppy_release_allocated_regions(fdc, ARRAY_END(io_regions));
+}
+
 static int floppy_grab_irq_and_dma(void)
 {
        unsigned long flags;
@@ -4399,18 +4440,8 @@ static int floppy_grab_irq_and_dma(void)
 
        for (fdc = 0; fdc < N_FDC; fdc++) {
                if (FDCS->address != -1) {
-                       if (!request_region(FDCS->address + 2, 4, "floppy")) {
-                               DPRINT("Floppy io-port 0x%04lx in use\n",
-                                      FDCS->address + 2);
-                               goto cleanup1;
-                       }
-                       if (!request_region(FDCS->address + 7, 1, "floppy DIR")) {
-                               DPRINT("Floppy io-port 0x%04lx in use\n",
-                                      FDCS->address + 7);
-                               goto cleanup2;
-                       }
-                       /* address + 6 is reserved, and may be taken by IDE.
-                        * Unfortunately, Adaptec doesn't know this :-(, */
+                       if (floppy_request_regions(fdc))
+                               goto cleanup;
                }
        }
        for (fdc = 0; fdc < N_FDC; fdc++) {
@@ -4432,15 +4463,11 @@ static int floppy_grab_irq_and_dma(void)
        fdc = 0;
        irqdma_allocated = 1;
        return 0;
-cleanup2:
-       release_region(FDCS->address + 2, 4);
-cleanup1:
+cleanup:
        fd_free_irq();
        fd_free_dma();
-       while (--fdc >= 0) {
-               release_region(FDCS->address + 2, 4);
-               release_region(FDCS->address + 7, 1);
-       }
+       while (--fdc >= 0)
+               floppy_release_regions(fdc);
        spin_lock_irqsave(&floppy_usage_lock, flags);
        usage_count--;
        spin_unlock_irqrestore(&floppy_usage_lock, flags);
@@ -4501,10 +4528,8 @@ static void floppy_release_irq_and_dma(void)
 #endif
        old_fdc = fdc;
        for (fdc = 0; fdc < N_FDC; fdc++)
-               if (FDCS->address != -1) {
-                       release_region(FDCS->address + 2, 4);
-                       release_region(FDCS->address + 7, 1);
-               }
+               if (FDCS->address != -1)
+                       floppy_release_regions(fdc);
        fdc = old_fdc;
 }
 
index 9dfa27163001e9d31de36f5196be7db0f2334a2d..c397b3ddba9b8676293bf773edfa90b29cf3101d 100644 (file)
@@ -422,7 +422,7 @@ static void xs(char *buf, char *targ, int len)
 
        for (k = 0; k < len; k++) {
                char c = *buf++;
-               if (c != ' ' || c != l)
+               if (c != ' ' && c != l)
                        l = *targ++ = c;
        }
        if (l == ' ')
index 93998f5baff576d9a68dcbd4077aa1ad37be1c95..341b1142bea864228d0b42a00fb64824d2afc6ca 100644 (file)
@@ -387,7 +387,7 @@ struct scc_port {
 /* The SCC needs 3.5 PCLK cycles recovery time between to register
  * accesses. PCLK runs with 8 MHz on an Atari, so this delay is 3.5 *
  * 125 ns = 437.5 ns. This is too short for udelay().
- * 10/16/95: A tstb mfp.par_dt_reg takes 600ns (sure?) and thus should be
+ * 10/16/95: A tstb st_mfp.par_dt_reg takes 600ns (sure?) and thus should be
  * quite right
  */
 
index f146e90404fa984586513966ed3a87033e01a0b3..518f2a25d91ec6b1a208c6fe233c505a7395aa47 100644 (file)
@@ -1746,9 +1746,10 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
                sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc);
                break;
        case SXIO_DO_RAMTEST:
-               if (sx_initialized)     /* Already initialized: better not ramtest the board.  */
+               if (sx_initialized) {   /* Already initialized: better not ramtest the board.  */
                        rc = -EPERM;
                        break;
+               }
                if (IS_SX_BOARD(board)) {
                        rc = do_memtest(board, 0, 0x7000);
                        if (!rc)
@@ -1788,7 +1789,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
                                                nbytes - i : SX_CHUNK_SIZE)) {
                                        kfree(tmp);
                                        rc = -EFAULT;
-                                       break;
+                                       goto out;
                                }
                                memcpy_toio(board->base2 + offset + i, tmp,
                                                (i + SX_CHUNK_SIZE > nbytes) ?
index a58993011edb4bc369a39b6caed0a93f62dc44a8..280a9d263eb3c4271d1cff6e55448cae0a93b387 100644 (file)
@@ -518,6 +518,7 @@ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, v
                                       dma_chan_name(chan), err);
                        else
                                break;
+                       chan->private = NULL;
                        chan = NULL;
                }
        }
@@ -536,6 +537,7 @@ void dma_release_channel(struct dma_chan *chan)
        WARN_ONCE(chan->client_count != 1,
                  "chan reference count %d != 1\n", chan->client_count);
        dma_chan_put(chan);
+       chan->private = NULL;
        mutex_unlock(&dma_list_mutex);
 }
 EXPORT_SYMBOL_GPL(dma_release_channel);
index 6b702cc46b3d1c36d4a7bdd19228f7c253f35ca8..a97c07eef7ec92468c24150669e690033f310a4f 100644 (file)
@@ -560,7 +560,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                unsigned long flags)
 {
        struct dw_dma_chan      *dwc = to_dw_dma_chan(chan);
-       struct dw_dma_slave     *dws = dwc->dws;
+       struct dw_dma_slave     *dws = chan->private;
        struct dw_desc          *prev;
        struct dw_desc          *first;
        u32                     ctllo;
@@ -790,7 +790,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
        cfghi = DWC_CFGH_FIFO_MODE;
        cfglo = 0;
 
-       dws = dwc->dws;
+       dws = chan->private;
        if (dws) {
                /*
                 * We need controller-specific data to set up slave
@@ -866,7 +866,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
        spin_lock_bh(&dwc->lock);
        list_splice_init(&dwc->free_list, &list);
        dwc->descs_allocated = 0;
-       dwc->dws = NULL;
 
        /* Disable interrupts */
        channel_clear_bit(dw, MASK.XFER, dwc->mask);
index 00fdd187bb0cf7ddbb5188cc33097f9739ee4ea7..b252b202c5cf1888f65149d3e22deee3d9cfeef0 100644 (file)
@@ -139,8 +139,6 @@ struct dw_dma_chan {
        struct list_head        queue;
        struct list_head        free_list;
 
-       struct dw_dma_slave     *dws;
-
        unsigned int            descs_allocated;
 };
 
index 261b9aa3f248e6c2df0c67d5492b35586cf1bb96..05aa2d406ac64769ecfbb3f6827d5e7fb53915e3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/firmware/memmap.c
  *  Copyright (C) 2008 SUSE LINUX Products GmbH
- *  by Bernhard Walle <bwalle@suse.de>
+ *  by Bernhard Walle <bernhard.walle@gmx.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License v2.0 as published by
index 4be3acbaaf9a429ff3208d2be7622babe0ac6245..3a22eb9be3783ac890514980e4ea7939c0a38e31 100644 (file)
@@ -80,18 +80,17 @@ config DRM_I915
          XFree86 4.4 and above. If unsure, build this and i830 as modules and
          the X server will load the correct one.
 
-endchoice
-
 config DRM_I915_KMS
        bool "Enable modesetting on intel by default"
        depends on DRM_I915
        help
-       Choose this option if you want kernel modesetting enabled by default,
-       and you have a new enough userspace to support this. Running old
-       userspaces with this enabled will cause pain.  Note that this causes
-       the driver to bind to PCI devices, which precludes loading things
-       like intelfb.
+         Choose this option if you want kernel modesetting enabled by default,
+         and you have a new enough userspace to support this. Running old
+         userspaces with this enabled will cause pain.  Note that this causes
+         the driver to bind to PCI devices, which precludes loading things
+         like intelfb.
 
+endchoice
 
 config DRM_MGA
        tristate "Matrox g200/g400"
index bfce0992fefbcaa3c3b6848f3e440f88577b2af7..94a76887173444f0e8390014a0ff586eefbea8f8 100644 (file)
@@ -1741,9 +1741,8 @@ out:
  * RETURNS:
  * Zero on success, errno on failure.
  */
-void drm_fb_release(struct file *filp)
+void drm_fb_release(struct drm_file *priv)
 {
-       struct drm_file *priv = filp->private_data;
        struct drm_device *dev = priv->minor->dev;
        struct drm_framebuffer *fb, *tfb;
 
index 964c5eb1fada4266795056abbad038ac23463dd7..733028b4d45e413e9d1689cd73a5fdec0618a982 100644 (file)
@@ -512,8 +512,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
        if (drm_mode_equal(&saved_mode, &crtc->mode)) {
                if (saved_x != crtc->x || saved_y != crtc->y ||
                    depth_changed || bpp_changed) {
-                       crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
-                                                 old_fb);
+                       ret = !crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
+                                                        old_fb);
                        goto done;
                }
        }
@@ -552,7 +552,9 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
        /* Set up the DPLL and any encoders state that needs to adjust or depend
         * on the DPLL.
         */
-       crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
+       ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
+       if (!ret)
+           goto done;
 
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 
@@ -752,6 +754,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                        if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
                                                      set->x, set->y,
                                                      old_fb)) {
+                               DRM_ERROR("failed to set mode on crtc %p\n",
+                                         set->crtc);
                                ret = -EINVAL;
                                goto fail_set_mode;
                        }
@@ -765,7 +769,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                old_fb = set->crtc->fb;
                if (set->crtc->fb != set->fb)
                        set->crtc->fb = set->fb;
-               crtc_funcs->mode_set_base(set->crtc, set->x, set->y, old_fb);
+               ret = crtc_funcs->mode_set_base(set->crtc,
+                                               set->x, set->y, old_fb);
+               if (ret != 0)
+                   goto fail_set_mode;
        }
 
        kfree(save_encoders);
@@ -775,8 +782,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 fail_set_mode:
        set->crtc->enabled = save_enabled;
        count = 0;
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               if (!connector->encoder)
+                       continue;
+
                connector->encoder->crtc = save_crtcs[count++];
+       }
 fail_no_encoder:
        kfree(save_crtcs);
        count = 0;
index b06a53715853af03df4717108106a72c1effdba5..6c020fe5431ca5eea366e60fd9560f5096e6da58 100644 (file)
@@ -457,6 +457,9 @@ int drm_release(struct inode *inode, struct file *filp)
        if (dev->driver->driver_features & DRIVER_GEM)
                drm_gem_release(dev, file_priv);
 
+       if (dev->driver->driver_features & DRIVER_MODESET)
+               drm_fb_release(file_priv);
+
        mutex_lock(&dev->ctxlist_mutex);
        if (!list_empty(&dev->ctxlist)) {
                struct drm_ctx_list *pos, *n;
index 6915fb82d0b0ea6aaa4a5c82b1ac5cf61b572e74..88d3368ffddd946974ba9a42ac273810f9c68c21 100644 (file)
@@ -104,8 +104,8 @@ drm_gem_init(struct drm_device *dev)
 
        if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
                        DRM_FILE_PAGE_OFFSET_SIZE)) {
-               drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
                drm_ht_remove(&mm->offset_hash);
+               drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
                return -ENOMEM;
        }
 
@@ -295,35 +295,37 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
                return -EBADF;
 
 again:
-       if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0)
-               return -ENOMEM;
+       if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) {
+               ret = -ENOMEM;
+               goto err;
+       }
 
        spin_lock(&dev->object_name_lock);
-       if (obj->name) {
-               args->name = obj->name;
+       if (!obj->name) {
+               ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
+                                       &obj->name);
+               args->name = (uint64_t) obj->name;
                spin_unlock(&dev->object_name_lock);
-               return 0;
-       }
-       ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
-                                &obj->name);
-       spin_unlock(&dev->object_name_lock);
-       if (ret == -EAGAIN)
-               goto again;
 
-       if (ret != 0) {
-               mutex_lock(&dev->struct_mutex);
-               drm_gem_object_unreference(obj);
-               mutex_unlock(&dev->struct_mutex);
-               return ret;
-       }
+               if (ret == -EAGAIN)
+                       goto again;
 
-       /*
-        * Leave the reference from the lookup around as the
-        * name table now holds one
-        */
-       args->name = (uint64_t) obj->name;
+               if (ret != 0)
+                       goto err;
 
-       return 0;
+               /* 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);
+               ret = 0;
+       }
+
+err:
+       mutex_lock(&dev->struct_mutex);
+       drm_gem_object_unreference(obj);
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
 }
 
 /**
@@ -448,6 +450,7 @@ drm_gem_object_handle_free(struct kref *kref)
        spin_lock(&dev->object_name_lock);
        if (obj->name) {
                idr_remove(&dev->object_name_idr, obj->name);
+               obj->name = 0;
                spin_unlock(&dev->object_name_lock);
                /*
                 * The object name held a reference to this object, drop
@@ -460,6 +463,26 @@ drm_gem_object_handle_free(struct kref *kref)
 }
 EXPORT_SYMBOL(drm_gem_object_handle_free);
 
+void drm_gem_vm_open(struct vm_area_struct *vma)
+{
+       struct drm_gem_object *obj = vma->vm_private_data;
+
+       drm_gem_object_reference(obj);
+}
+EXPORT_SYMBOL(drm_gem_vm_open);
+
+void drm_gem_vm_close(struct vm_area_struct *vma)
+{
+       struct drm_gem_object *obj = vma->vm_private_data;
+       struct drm_device *dev = obj->dev;
+
+       mutex_lock(&dev->struct_mutex);
+       drm_gem_object_unreference(obj);
+       mutex_unlock(&dev->struct_mutex);
+}
+EXPORT_SYMBOL(drm_gem_vm_close);
+
+
 /**
  * drm_gem_mmap - memory map routine for GEM objects
  * @filp: DRM file pointer
@@ -521,6 +544,14 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 #endif
        vma->vm_page_prot = __pgprot(prot);
 
+       /* Take a ref for this mapping of the object, so that the fault
+        * handler can dereference the mmap offset's pointer to the object.
+        * This reference is cleaned up by the corresponding vm_close
+        * (which should happen whether the vma was created by this call, or
+        * by a vm_open due to mremap or partial unmap or whatever).
+        */
+       drm_gem_object_reference(obj);
+
        vma->vm_file = filp;    /* Needed for drm_vm_open() */
        drm_vm_open_locked(vma);
 
index 81f1cff56fd5e2ff02313849a2d9f4d412d22237..2d797ffe8137c43472f08a3019ecb2052d664ec6 100644 (file)
@@ -202,7 +202,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
                dev_priv->ring.map.flags = 0;
                dev_priv->ring.map.mtrr = 0;
 
-               drm_core_ioremap(&dev_priv->ring.map, dev);
+               drm_core_ioremap_wc(&dev_priv->ring.map, dev);
 
                if (dev_priv->ring.map.handle == NULL) {
                        i915_dma_cleanup(dev);
index aac12ee31a46e86540e7e2cba43d8cef273e27c2..0692622ee2b3dc3d75e47c086a344b1e0fd8bb3b 100644 (file)
@@ -27,6 +27,7 @@
  *
  */
 
+#include <linux/device.h>
 #include "drmP.h"
 #include "drm.h"
 #include "i915_drm.h"
@@ -66,6 +67,12 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
 
        i915_save_state(dev);
 
+       /* If KMS is active, we do the leavevt stuff here */
+       if (drm_core_check_feature(dev, DRIVER_MODESET) && i915_gem_idle(dev)) {
+               dev_err(&dev->pdev->dev, "GEM idle failed, aborting suspend\n");
+               return -EBUSY;
+       }
+
        intel_opregion_free(dev);
 
        if (state.event == PM_EVENT_SUSPEND) {
@@ -79,6 +86,9 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
 
 static int i915_resume(struct drm_device *dev)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret = 0;
+
        pci_set_power_state(dev->pdev, PCI_D0);
        pci_restore_state(dev->pdev);
        if (pci_enable_device(dev->pdev))
@@ -89,11 +99,24 @@ static int i915_resume(struct drm_device *dev)
 
        intel_opregion_init(dev);
 
-       return 0;
+       /* KMS EnterVT equivalent */
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               mutex_lock(&dev->struct_mutex);
+               dev_priv->mm.suspended = 0;
+
+               ret = i915_gem_init_ringbuffer(dev);
+               if (ret != 0)
+                       ret = -1;
+               mutex_unlock(&dev->struct_mutex);
+       }
+
+       return ret;
 }
 
 static struct vm_operations_struct i915_gem_vm_ops = {
        .fault = i915_gem_fault,
+       .open = drm_gem_vm_open,
+       .close = drm_gem_vm_close,
 };
 
 static struct drm_driver driver = {
index 7325363164f84cf26a2f39bc3312753d1c31f28b..17fa40858d26147b5ae6ca041adb5984c05ac06a 100644 (file)
@@ -184,6 +184,8 @@ typedef struct drm_i915_private {
        unsigned int lvds_dither:1;
        unsigned int lvds_vbt:1;
        unsigned int int_crt_support:1;
+       unsigned int lvds_use_ssc:1;
+       int lvds_ssc_freq;
 
        struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
        int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
@@ -616,6 +618,7 @@ int i915_gem_init_ringbuffer(struct drm_device *dev);
 void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
 int i915_gem_do_init(struct drm_device *dev, unsigned long start,
                     unsigned long end);
+int i915_gem_idle(struct drm_device *dev);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
                                      int write);
index 818576654092b341746ebb40a846e15ebfb4d5fc..25b337438ca737d4148bbc473f68483ece0d40bc 100644 (file)
 
 #define I915_GEM_GPU_DOMAINS   (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
 
-static void
-i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
-                                 uint32_t read_domains,
-                                 uint32_t write_domain);
 static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
 static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
 static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
@@ -607,8 +603,6 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        case -EAGAIN:
                return VM_FAULT_OOM;
        case -EFAULT:
-       case -EBUSY:
-               DRM_ERROR("can't insert pfn??  fault or busy...\n");
                return VM_FAULT_SIGBUS;
        default:
                return VM_FAULT_NOPAGE;
@@ -684,6 +678,30 @@ out_free_list:
        return ret;
 }
 
+static void
+i915_gem_free_mmap_offset(struct drm_gem_object *obj)
+{
+       struct drm_device *dev = obj->dev;
+       struct drm_i915_gem_object *obj_priv = obj->driver_private;
+       struct drm_gem_mm *mm = dev->mm_private;
+       struct drm_map_list *list;
+
+       list = &obj->map_list;
+       drm_ht_remove_item(&mm->offset_hash, &list->hash);
+
+       if (list->file_offset_node) {
+               drm_mm_put_block(list->file_offset_node);
+               list->file_offset_node = NULL;
+       }
+
+       if (list->map) {
+               drm_free(list->map, sizeof(struct drm_map), DRM_MEM_DRIVER);
+               list->map = NULL;
+       }
+
+       obj_priv->mmap_offset = 0;
+}
+
 /**
  * i915_gem_get_gtt_alignment - return required GTT alignment for an object
  * @obj: object to check
@@ -758,8 +776,11 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
 
        if (!obj_priv->mmap_offset) {
                ret = i915_gem_create_mmap_offset(obj);
-               if (ret)
+               if (ret) {
+                       drm_gem_object_unreference(obj);
+                       mutex_unlock(&dev->struct_mutex);
                        return ret;
+               }
        }
 
        args->offset = obj_priv->mmap_offset;
@@ -1996,30 +2017,28 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write)
  *             drm_agp_chipset_flush
  */
 static void
-i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
-                                 uint32_t read_domains,
-                                 uint32_t write_domain)
+i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj)
 {
        struct drm_device               *dev = obj->dev;
        struct drm_i915_gem_object      *obj_priv = obj->driver_private;
        uint32_t                        invalidate_domains = 0;
        uint32_t                        flush_domains = 0;
 
-       BUG_ON(read_domains & I915_GEM_DOMAIN_CPU);
-       BUG_ON(write_domain == I915_GEM_DOMAIN_CPU);
+       BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU);
+       BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU);
 
 #if WATCH_BUF
        DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n",
                 __func__, obj,
-                obj->read_domains, read_domains,
-                obj->write_domain, write_domain);
+                obj->read_domains, obj->pending_read_domains,
+                obj->write_domain, obj->pending_write_domain);
 #endif
        /*
         * If the object isn't moving to a new write domain,
         * let the object stay in multiple read domains
         */
-       if (write_domain == 0)
-               read_domains |= obj->read_domains;
+       if (obj->pending_write_domain == 0)
+               obj->pending_read_domains |= obj->read_domains;
        else
                obj_priv->dirty = 1;
 
@@ -2029,15 +2048,17 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
         * any read domains which differ from the old
         * write domain
         */
-       if (obj->write_domain && obj->write_domain != read_domains) {
+       if (obj->write_domain &&
+           obj->write_domain != obj->pending_read_domains) {
                flush_domains |= obj->write_domain;
-               invalidate_domains |= read_domains & ~obj->write_domain;
+               invalidate_domains |=
+                       obj->pending_read_domains & ~obj->write_domain;
        }
        /*
         * Invalidate any read caches which may have
         * stale data. That is, any new read domains.
         */
-       invalidate_domains |= read_domains & ~obj->read_domains;
+       invalidate_domains |= obj->pending_read_domains & ~obj->read_domains;
        if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) {
 #if WATCH_BUF
                DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n",
@@ -2046,9 +2067,15 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
                i915_gem_clflush_object(obj);
        }
 
-       if ((write_domain | flush_domains) != 0)
-               obj->write_domain = write_domain;
-       obj->read_domains = read_domains;
+       /* The actual obj->write_domain will be updated with
+        * pending_write_domain after we emit the accumulated flush for all
+        * of our domain changes in execbuffers (which clears objects'
+        * write_domains).  So if we have a current write domain that we
+        * aren't changing, set pending_write_domain to that.
+        */
+       if (flush_domains == 0 && obj->pending_write_domain == 0)
+               obj->pending_write_domain = obj->write_domain;
+       obj->read_domains = obj->pending_read_domains;
 
        dev->invalidate_domains |= invalidate_domains;
        dev->flush_domains |= flush_domains;
@@ -2251,6 +2278,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
                                  (int) reloc.offset,
                                  reloc.read_domains,
                                  reloc.write_domain);
+                       drm_gem_object_unreference(target_obj);
+                       i915_gem_object_unpin(obj);
                        return -EINVAL;
                }
 
@@ -2480,13 +2509,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
        if (dev_priv->mm.wedged) {
                DRM_ERROR("Execbuf while wedged\n");
                mutex_unlock(&dev->struct_mutex);
-               return -EIO;
+               ret = -EIO;
+               goto pre_mutex_err;
        }
 
        if (dev_priv->mm.suspended) {
                DRM_ERROR("Execbuf while VT-switched.\n");
                mutex_unlock(&dev->struct_mutex);
-               return -EBUSY;
+               ret = -EBUSY;
+               goto pre_mutex_err;
        }
 
        /* Look up object handles */
@@ -2554,9 +2585,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
                struct drm_gem_object *obj = object_list[i];
 
                /* Compute new gpu domains and update invalidate/flush */
-               i915_gem_object_set_to_gpu_domain(obj,
-                                                 obj->pending_read_domains,
-                                                 obj->pending_write_domain);
+               i915_gem_object_set_to_gpu_domain(obj);
        }
 
        i915_verify_inactive(dev, __FILE__, __LINE__);
@@ -2575,6 +2604,12 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
                        (void)i915_add_request(dev, dev->flush_domains);
        }
 
+       for (i = 0; i < args->buffer_count; i++) {
+               struct drm_gem_object *obj = object_list[i];
+
+               obj->write_domain = obj->pending_write_domain;
+       }
+
        i915_verify_inactive(dev, __FILE__, __LINE__);
 
 #if WATCH_COHERENCY
@@ -2632,15 +2667,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 
        i915_verify_inactive(dev, __FILE__, __LINE__);
 
-       /* Copy the new buffer offsets back to the user's exec list. */
-       ret = copy_to_user((struct drm_i915_relocation_entry __user *)
-                          (uintptr_t) args->buffers_ptr,
-                          exec_list,
-                          sizeof(*exec_list) * args->buffer_count);
-       if (ret)
-               DRM_ERROR("failed to copy %d exec entries "
-                         "back to user (%d)\n",
-                          args->buffer_count, ret);
 err:
        for (i = 0; i < pinned; i++)
                i915_gem_object_unpin(object_list[i]);
@@ -2650,6 +2676,18 @@ err:
 
        mutex_unlock(&dev->struct_mutex);
 
+       if (!ret) {
+               /* Copy the new buffer offsets back to the user's exec list. */
+               ret = copy_to_user((struct drm_i915_relocation_entry __user *)
+                                  (uintptr_t) args->buffers_ptr,
+                                  exec_list,
+                                  sizeof(*exec_list) * args->buffer_count);
+               if (ret)
+                       DRM_ERROR("failed to copy %d exec entries "
+                                 "back to user (%d)\n",
+                                 args->buffer_count, ret);
+       }
+
 pre_mutex_err:
        drm_free(object_list, sizeof(*object_list) * args->buffer_count,
                 DRM_MEM_DRIVER);
@@ -2753,6 +2791,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
        if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) {
                DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
                          args->handle);
+               drm_gem_object_unreference(obj);
                mutex_unlock(&dev->struct_mutex);
                return -EINVAL;
        }
@@ -2833,6 +2872,13 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
                return -EBADF;
        }
 
+       /* Update the active list for the hardware's current position.
+        * Otherwise this only updates on a delayed timer or when irqs are
+        * actually unmasked, and our working set ends up being larger than
+        * required.
+        */
+       i915_gem_retire_requests(dev);
+
        obj_priv = obj->driver_private;
        /* Don't count being on the flushing list against the object being
         * done.  Otherwise, a buffer left on the flushing list but not getting
@@ -2885,9 +2931,6 @@ int i915_gem_init_object(struct drm_gem_object *obj)
 void i915_gem_free_object(struct drm_gem_object *obj)
 {
        struct drm_device *dev = obj->dev;
-       struct drm_gem_mm *mm = dev->mm_private;
-       struct drm_map_list *list;
-       struct drm_map *map;
        struct drm_i915_gem_object *obj_priv = obj->driver_private;
 
        while (obj_priv->pin_count > 0)
@@ -2898,19 +2941,7 @@ void i915_gem_free_object(struct drm_gem_object *obj)
 
        i915_gem_object_unbind(obj);
 
-       list = &obj->map_list;
-       drm_ht_remove_item(&mm->offset_hash, &list->hash);
-
-       if (list->file_offset_node) {
-               drm_mm_put_block(list->file_offset_node);
-               list->file_offset_node = NULL;
-       }
-
-       map = list->map;
-       if (map) {
-               drm_free(map, sizeof(*map), DRM_MEM_DRIVER);
-               list->map = NULL;
-       }
+       i915_gem_free_mmap_offset(obj);
 
        drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
        drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
@@ -2949,7 +2980,7 @@ i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head)
        return 0;
 }
 
-static int
+int
 i915_gem_idle(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
@@ -3095,6 +3126,7 @@ i915_gem_init_hws(struct drm_device *dev)
        if (dev_priv->hw_status_page == NULL) {
                DRM_ERROR("Failed to map status page.\n");
                memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
+               i915_gem_object_unpin(obj);
                drm_gem_object_unreference(obj);
                return -EINVAL;
        }
@@ -3107,6 +3139,31 @@ i915_gem_init_hws(struct drm_device *dev)
        return 0;
 }
 
+static void
+i915_gem_cleanup_hws(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_gem_object *obj;
+       struct drm_i915_gem_object *obj_priv;
+
+       if (dev_priv->hws_obj == NULL)
+               return;
+
+       obj = dev_priv->hws_obj;
+       obj_priv = obj->driver_private;
+
+       kunmap(obj_priv->page_list[0]);
+       i915_gem_object_unpin(obj);
+       drm_gem_object_unreference(obj);
+       dev_priv->hws_obj = NULL;
+
+       memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
+       dev_priv->hw_status_page = NULL;
+
+       /* Write high address into HWS_PGA when disabling. */
+       I915_WRITE(HWS_PGA, 0x1ffff000);
+}
+
 int
 i915_gem_init_ringbuffer(struct drm_device *dev)
 {
@@ -3124,6 +3181,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
        obj = drm_gem_object_alloc(dev, 128 * 1024);
        if (obj == NULL) {
                DRM_ERROR("Failed to allocate ringbuffer\n");
+               i915_gem_cleanup_hws(dev);
                return -ENOMEM;
        }
        obj_priv = obj->driver_private;
@@ -3131,6 +3189,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
        ret = i915_gem_object_pin(obj, 4096);
        if (ret != 0) {
                drm_gem_object_unreference(obj);
+               i915_gem_cleanup_hws(dev);
                return ret;
        }
 
@@ -3148,7 +3207,9 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
        if (ring->map.handle == NULL) {
                DRM_ERROR("Failed to map ringbuffer.\n");
                memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
+               i915_gem_object_unpin(obj);
                drm_gem_object_unreference(obj);
+               i915_gem_cleanup_hws(dev);
                return -EINVAL;
        }
        ring->ring_obj = obj;
@@ -3228,20 +3289,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)
        dev_priv->ring.ring_obj = NULL;
        memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
 
-       if (dev_priv->hws_obj != NULL) {
-               struct drm_gem_object *obj = dev_priv->hws_obj;
-               struct drm_i915_gem_object *obj_priv = obj->driver_private;
-
-               kunmap(obj_priv->page_list[0]);
-               i915_gem_object_unpin(obj);
-               drm_gem_object_unreference(obj);
-               dev_priv->hws_obj = NULL;
-               memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
-               dev_priv->hw_status_page = NULL;
-
-               /* Write high address into HWS_PGA when disabling. */
-               I915_WRITE(HWS_PGA, 0x1ffff000);
-       }
+       i915_gem_cleanup_hws(dev);
 }
 
 int
index fa1685cba8402fdbd456be37f627bd21c170cca4..7fb4191ef934c2b9a9549a36737e075d6ee3fca7 100644 (file)
@@ -299,9 +299,8 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
        }
        obj_priv->stride = args->stride;
 
-       mutex_unlock(&dev->struct_mutex);
-
        drm_gem_object_unreference(obj);
+       mutex_unlock(&dev->struct_mutex);
 
        return 0;
 }
@@ -340,9 +339,8 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
                DRM_ERROR("unknown tiling mode\n");
        }
 
-       mutex_unlock(&dev->struct_mutex);
-
        drm_gem_object_unreference(obj);
+       mutex_unlock(&dev->struct_mutex);
 
        return 0;
 }
index 4ca82a0255255e09f82426bc23b2bc25da555f08..65be30dccc7767d8781cad444a317c43930a6064 100644 (file)
@@ -135,6 +135,14 @@ parse_general_features(struct drm_i915_private *dev_priv,
        if (general) {
                dev_priv->int_tv_support = general->int_tv_support;
                dev_priv->int_crt_support = general->int_crt_support;
+               dev_priv->lvds_use_ssc = general->enable_ssc;
+
+               if (dev_priv->lvds_use_ssc) {
+                 if (IS_I855(dev_priv->dev))
+                   dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48;
+                 else
+                   dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96;
+               }
        }
 }
 
index bbdd72909a113db3cf70411de682121d57ebba0a..65b635ce28c8c78da6563f21538d9d6434de23a9 100644 (file)
@@ -90,12 +90,12 @@ typedef struct {
 #define I9XX_DOT_MAX            400000
 #define I9XX_VCO_MIN           1400000
 #define I9XX_VCO_MAX           2800000
-#define I9XX_N_MIN                   3
-#define I9XX_N_MAX                   8
+#define I9XX_N_MIN                   1
+#define I9XX_N_MAX                   6
 #define I9XX_M_MIN                  70
 #define I9XX_M_MAX                 120
 #define I9XX_M1_MIN                 10
-#define I9XX_M1_MAX                 20
+#define I9XX_M1_MAX                 22
 #define I9XX_M2_MIN                  5
 #define I9XX_M2_MAX                  9
 #define I9XX_P_SDVO_DAC_MIN          5
@@ -189,9 +189,7 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
        return limit;
 }
 
-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
-
-static void i8xx_clock(int refclk, intel_clock_t *clock)
+static void intel_clock(int refclk, intel_clock_t *clock)
 {
        clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
        clock->p = clock->p1 * clock->p2;
@@ -199,25 +197,6 @@ static void i8xx_clock(int refclk, intel_clock_t *clock)
        clock->dot = clock->vco / clock->p;
 }
 
-/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */
-
-static void i9xx_clock(int refclk, intel_clock_t *clock)
-{
-       clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
-       clock->p = clock->p1 * clock->p2;
-       clock->vco = refclk * clock->m / (clock->n + 2);
-       clock->dot = clock->vco / clock->p;
-}
-
-static void intel_clock(struct drm_device *dev, int refclk,
-                       intel_clock_t *clock)
-{
-       if (IS_I9XX(dev))
-               i9xx_clock (refclk, clock);
-       else
-               i8xx_clock (refclk, clock);
-}
-
 /**
  * Returns whether any output on the specified pipe is of the specified type
  */
@@ -238,7 +217,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
     return false;
 }
 
-#define INTELPllInvalid(s)   { /* ErrorF (s) */; return false; }
+#define INTELPllInvalid(s)   do { DRM_DEBUG(s); return false; } while (0)
 /**
  * Returns whether the given set of divisors are valid for a given refclk with
  * the given connectors.
@@ -318,7 +297,7 @@ static bool intel_find_best_PLL(struct drm_crtc *crtc, int target,
                                     clock.p1 <= limit->p1.max; clock.p1++) {
                                        int this_err;
 
-                                       intel_clock(dev, refclk, &clock);
+                                       intel_clock(refclk, &clock);
 
                                        if (!intel_PLL_is_valid(crtc, &clock))
                                                continue;
@@ -343,7 +322,7 @@ intel_wait_for_vblank(struct drm_device *dev)
        udelay(20000);
 }
 
-static void
+static int
 intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                    struct drm_framebuffer *old_fb)
 {
@@ -361,11 +340,21 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
        int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
        u32 dspcntr, alignment;
+       int ret;
 
        /* no fb bound */
        if (!crtc->fb) {
                DRM_DEBUG("No FB bound\n");
-               return;
+               return 0;
+       }
+
+       switch (pipe) {
+       case 0:
+       case 1:
+               break;
+       default:
+               DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
+               return -EINVAL;
        }
 
        intel_fb = to_intel_framebuffer(crtc->fb);
@@ -377,28 +366,30 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                alignment = 64 * 1024;
                break;
        case I915_TILING_X:
-               if (IS_I9XX(dev))
-                       alignment = 1024 * 1024;
-               else
-                       alignment = 512 * 1024;
+               /* pin() will align the object as required by fence */
+               alignment = 0;
                break;
        case I915_TILING_Y:
                /* FIXME: Is this true? */
                DRM_ERROR("Y tiled not allowed for scan out buffers\n");
-               return;
+               return -EINVAL;
        default:
                BUG();
        }
 
-       if (i915_gem_object_pin(intel_fb->obj, alignment))
-               return;
-
-       i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1);
-
-       Start = obj_priv->gtt_offset;
-       Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+       mutex_lock(&dev->struct_mutex);
+       ret = i915_gem_object_pin(intel_fb->obj, alignment);
+       if (ret != 0) {
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
 
-       I915_WRITE(dspstride, crtc->fb->pitch);
+       ret = i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1);
+       if (ret != 0) {
+               i915_gem_object_unpin(intel_fb->obj);
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
 
        dspcntr = I915_READ(dspcntr_reg);
        /* Mask out pixel format bits in case we change it */
@@ -419,11 +410,17 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                break;
        default:
                DRM_ERROR("Unknown color depth\n");
-               return;
+               i915_gem_object_unpin(intel_fb->obj);
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
        }
        I915_WRITE(dspcntr_reg, dspcntr);
 
+       Start = obj_priv->gtt_offset;
+       Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+
        DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
+       I915_WRITE(dspstride, crtc->fb->pitch);
        if (IS_I965G(dev)) {
                I915_WRITE(dspbase, Offset);
                I915_READ(dspbase);
@@ -440,27 +437,24 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                intel_fb = to_intel_framebuffer(old_fb);
                i915_gem_object_unpin(intel_fb->obj);
        }
+       mutex_unlock(&dev->struct_mutex);
 
        if (!dev->primary->master)
-               return;
+               return 0;
 
        master_priv = dev->primary->master->driver_priv;
        if (!master_priv->sarea_priv)
-               return;
+               return 0;
 
-       switch (pipe) {
-       case 0:
-               master_priv->sarea_priv->pipeA_x = x;
-               master_priv->sarea_priv->pipeA_y = y;
-               break;
-       case 1:
+       if (pipe) {
                master_priv->sarea_priv->pipeB_x = x;
                master_priv->sarea_priv->pipeB_y = y;
-               break;
-       default:
-               DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
-               break;
+       } else {
+               master_priv->sarea_priv->pipeA_x = x;
+               master_priv->sarea_priv->pipeA_y = y;
        }
+
+       return 0;
 }
 
 
@@ -708,11 +702,11 @@ static int intel_panel_fitter_pipe (struct drm_device *dev)
        return 1;
 }
 
-static void intel_crtc_mode_set(struct drm_crtc *crtc,
-                               struct drm_display_mode *mode,
-                               struct drm_display_mode *adjusted_mode,
-                               int x, int y,
-                               struct drm_framebuffer *old_fb)
+static int intel_crtc_mode_set(struct drm_crtc *crtc,
+                              struct drm_display_mode *mode,
+                              struct drm_display_mode *adjusted_mode,
+                              int x, int y,
+                              struct drm_framebuffer *old_fb)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -732,13 +726,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
        int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
        int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
        int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
-       int refclk;
+       int refclk, num_outputs = 0;
        intel_clock_t clock;
        u32 dpll = 0, fp = 0, dspcntr, pipeconf;
        bool ok, is_sdvo = false, is_dvo = false;
        bool is_crt = false, is_lvds = false, is_tv = false;
        struct drm_mode_config *mode_config = &dev->mode_config;
        struct drm_connector *connector;
+       int ret;
 
        drm_vblank_pre_modeset(dev, pipe);
 
@@ -768,9 +763,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
                        is_crt = true;
                        break;
                }
+
+               num_outputs++;
        }
 
-       if (IS_I9XX(dev)) {
+       if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2) {
+               refclk = dev_priv->lvds_ssc_freq * 1000;
+               DRM_DEBUG("using SSC reference clock of %d MHz\n", refclk / 1000);
+       } else if (IS_I9XX(dev)) {
                refclk = 96000;
        } else {
                refclk = 48000;
@@ -779,7 +779,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
        ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock);
        if (!ok) {
                DRM_ERROR("Couldn't find PLL settings for mode!\n");
-               return;
+               return -EINVAL;
        }
 
        fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
@@ -829,11 +829,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
                }
        }
 
-       if (is_tv) {
+       if (is_sdvo && is_tv)
+               dpll |= PLL_REF_INPUT_TVCLKINBC;
+       else if (is_tv)
                /* XXX: just matching BIOS for now */
-/*     dpll |= PLL_REF_INPUT_TVCLKINBC; */
+               /*      dpll |= PLL_REF_INPUT_TVCLKINBC; */
                dpll |= 3;
-       }
+       else if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2)
+               dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
        else
                dpll |= PLL_REF_INPUT_DREFCLK;
 
@@ -950,9 +953,13 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
        I915_WRITE(dspcntr_reg, dspcntr);
 
        /* Flush the plane changes */
-       intel_pipe_set_base(crtc, x, y, old_fb);
+       ret = intel_pipe_set_base(crtc, x, y, old_fb);
+       if (ret != 0)
+           return ret;
 
        drm_vblank_post_modeset(dev, pipe);
+
+       return 0;
 }
 
 /** Loads the palette/gamma unit for the CRTC with the prepared values */
@@ -1001,6 +1008,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
                temp = CURSOR_MODE_DISABLE;
                addr = 0;
                bo = NULL;
+               mutex_lock(&dev->struct_mutex);
                goto finish;
        }
 
@@ -1023,18 +1031,19 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
        }
 
        /* we only need to pin inside GTT if cursor is non-phy */
+       mutex_lock(&dev->struct_mutex);
        if (!dev_priv->cursor_needs_physical) {
                ret = i915_gem_object_pin(bo, PAGE_SIZE);
                if (ret) {
                        DRM_ERROR("failed to pin cursor bo\n");
-                       goto fail;
+                       goto fail_locked;
                }
                addr = obj_priv->gtt_offset;
        } else {
                ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
                if (ret) {
                        DRM_ERROR("failed to attach phys object\n");
-                       goto fail;
+                       goto fail_locked;
                }
                addr = obj_priv->phys_obj->handle->busaddr;
        }
@@ -1054,10 +1063,9 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
                                i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
                } else
                        i915_gem_object_unpin(intel_crtc->cursor_bo);
-               mutex_lock(&dev->struct_mutex);
                drm_gem_object_unreference(intel_crtc->cursor_bo);
-               mutex_unlock(&dev->struct_mutex);
        }
+       mutex_unlock(&dev->struct_mutex);
 
        intel_crtc->cursor_addr = addr;
        intel_crtc->cursor_bo = bo;
@@ -1065,6 +1073,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
        return 0;
 fail:
        mutex_lock(&dev->struct_mutex);
+fail_locked:
        drm_gem_object_unreference(bo);
        mutex_unlock(&dev->struct_mutex);
        return ret;
@@ -1292,7 +1301,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
                }
 
                /* XXX: Handle the 100Mhz refclk */
-               i9xx_clock(96000, &clock);
+               intel_clock(96000, &clock);
        } else {
                bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
 
@@ -1304,9 +1313,9 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
                        if ((dpll & PLL_REF_INPUT_MASK) ==
                            PLLB_REF_INPUT_SPREADSPECTRUMIN) {
                                /* XXX: might not be 66MHz */
-                               i8xx_clock(66000, &clock);
+                               intel_clock(66000, &clock);
                        } else
-                               i8xx_clock(48000, &clock);
+                               intel_clock(48000, &clock);
                } else {
                        if (dpll & PLL_P1_DIVIDE_BY_TWO)
                                clock.p1 = 2;
@@ -1319,7 +1328,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
                        else
                                clock.p2 = 2;
 
-                       i8xx_clock(48000, &clock);
+                       intel_clock(48000, &clock);
                }
        }
 
@@ -1598,7 +1607,9 @@ intel_user_framebuffer_create(struct drm_device *dev,
 
        ret = intel_framebuffer_create(dev, mode_cmd, &fb, obj);
        if (ret) {
+               mutex_lock(&dev->struct_mutex);
                drm_gem_object_unreference(obj);
+               mutex_unlock(&dev->struct_mutex);
                return NULL;
        }
 
index afd1217b8a02cb4bfff4b7371baf2f842a4599fb..b7f0ebe9f810105b1d68a2446a5bab9921fa795c 100644 (file)
@@ -473,7 +473,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
        ret = intel_framebuffer_create(dev, &mode_cmd, &fb, fbo);
        if (ret) {
                DRM_ERROR("failed to allocate fb.\n");
-               goto out_unref;
+               goto out_unpin;
        }
 
        list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list);
@@ -484,7 +484,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
        info = framebuffer_alloc(sizeof(struct intelfb_par), device);
        if (!info) {
                ret = -ENOMEM;
-               goto out_unref;
+               goto out_unpin;
        }
 
        par = info->par;
@@ -513,7 +513,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
                                       size);
        if (!info->screen_base) {
                ret = -ENOSPC;
-               goto out_unref;
+               goto out_unpin;
        }
        info->screen_size = size;
 
@@ -608,6 +608,8 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
        mutex_unlock(&dev->struct_mutex);
        return 0;
 
+out_unpin:
+       i915_gem_object_unpin(fbo);
 out_unref:
        drm_gem_object_unreference(fbo);
        mutex_unlock(&dev->struct_mutex);
index 6d4f9126535443366debd7b0f769bcc9c2dceb31..0d211af98854c18debd6af4f1ea6a246af16871d 100644 (file)
@@ -481,8 +481,6 @@ void intel_lvds_init(struct drm_device *dev)
                if (dev_priv->panel_fixed_mode) {
                        dev_priv->panel_fixed_mode->type |=
                                DRM_MODE_TYPE_PREFERRED;
-                       drm_mode_probed_add(connector,
-                                           dev_priv->panel_fixed_mode);
                        goto out;
                }
        }
index a30508b639ba3ffa04d4a0812ddc9f2a4e880092..fbe6f3931b1b116cb022daa2238ee78d2e7c359c 100644 (file)
@@ -193,7 +193,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr,
 
 #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd}
 /** Mapping of command numbers to names, for debug output */
-const static struct _sdvo_cmd_name {
+static const struct _sdvo_cmd_name {
        u8 cmd;
        char *name;
 } sdvo_cmd_names[] = {
index fbb35dc56f5c15ee917a892b1ab2df9f45398d9b..56485d67369b8dcf913b28b17afa9bb3bd3b3de8 100644 (file)
@@ -411,7 +411,7 @@ struct tv_mode {
  * These values account for -1s required.
  */
 
-const static struct tv_mode tv_modes[] = {
+static const struct tv_mode tv_modes[] = {
        {
                .name           = "NTSC-M",
                .clock          = 107520,
index df4cf97e5d976cb1c5d445dc487b15d2c3333029..92965dbb3c147a7b46c3cf248466765f2d08f5e8 100644 (file)
@@ -557,8 +557,10 @@ static int radeon_do_engine_reset(struct drm_device * dev)
 }
 
 static void radeon_cp_init_ring_buffer(struct drm_device * dev,
-                                      drm_radeon_private_t * dev_priv)
+                                      drm_radeon_private_t *dev_priv,
+                                      struct drm_file *file_priv)
 {
+       struct drm_radeon_master_private *master_priv;
        u32 ring_start, cur_read_ptr;
        u32 tmp;
 
@@ -677,6 +679,14 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
        dev_priv->scratch[2] = 0;
        RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0);
 
+       /* reset sarea copies of these */
+       master_priv = file_priv->master->driver_priv;
+       if (master_priv->sarea_priv) {
+               master_priv->sarea_priv->last_frame = 0;
+               master_priv->sarea_priv->last_dispatch = 0;
+               master_priv->sarea_priv->last_clear = 0;
+       }
+
        radeon_do_wait_for_idle(dev_priv);
 
        /* Sync everything up */
@@ -1215,7 +1225,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
        }
 
        radeon_cp_load_microcode(dev_priv);
-       radeon_cp_init_ring_buffer(dev, dev_priv);
+       radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
 
        dev_priv->last_buf = 0;
 
@@ -1281,7 +1291,7 @@ static int radeon_do_cleanup_cp(struct drm_device * dev)
  *
  * Charl P. Botha <http://cpbotha.net>
  */
-static int radeon_do_resume_cp(struct drm_device * dev)
+static int radeon_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -1304,7 +1314,7 @@ static int radeon_do_resume_cp(struct drm_device * dev)
        }
 
        radeon_cp_load_microcode(dev_priv);
-       radeon_cp_init_ring_buffer(dev, dev_priv);
+       radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
 
        radeon_do_engine_reset(dev);
        radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
@@ -1479,8 +1489,7 @@ int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_pri
  */
 int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-
-       return radeon_do_resume_cp(dev);
+       return radeon_do_resume_cp(dev, file_priv);
 }
 
 int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
index 6cad69ed21c558c908b68fb9751a381a92cf0eae..1cc967448f4d5c760a8d75329c4e76bb82f4000f 100644 (file)
@@ -1300,7 +1300,13 @@ static const struct hid_device_id hid_blacklist[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
 
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
@@ -1605,6 +1611,7 @@ static const struct hid_device_id hid_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
        { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
        { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3) },
@@ -1612,10 +1619,6 @@ static const struct hid_device_id hid_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD5) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
        { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
@@ -1626,8 +1629,6 @@ static const struct hid_device_id hid_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT) },
        { HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
        { }
 };
 
index e899f510ebeb5c474c1e682f874559ea9f690e79..88511970508d71b8ceae437ae78726ca35563cc8 100644 (file)
 #define USB_VENDOR_ID_PLAYDOTCOM       0x0b43
 #define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII     0x0003
 
+#define USB_VENDOR_ID_POWERCOM         0x0d9f
+#define USB_DEVICE_ID_POWERCOM_UPS     0x0002
+
 #define USB_VENDOR_ID_SAITEK           0x06a3
 #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
 
index 732449628971185d7603728aaa4c764266342274..02b19db5442ebd1d1fce7c0716bb2a071f528e12 100644 (file)
@@ -267,8 +267,10 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
                default:
                        {
                                struct hid_device *hid = dev->hid;
-                               if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
-                                       return -EINVAL;
+                               if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) {
+                                       ret = -EINVAL;
+                                       break;
+                               }
 
                                if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
                                        int len;
@@ -277,8 +279,9 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
                                        len = strlen(hid->name) + 1;
                                        if (len > _IOC_SIZE(cmd))
                                                len = _IOC_SIZE(cmd);
-                                       return copy_to_user(user_arg, hid->name, len) ?
+                                       ret = copy_to_user(user_arg, hid->name, len) ?
                                                -EFAULT : len;
+                                       break;
                                }
 
                                if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
@@ -288,12 +291,13 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
                                        len = strlen(hid->phys) + 1;
                                        if (len > _IOC_SIZE(cmd))
                                                len = _IOC_SIZE(cmd);
-                                       return copy_to_user(user_arg, hid->phys, len) ?
+                                       ret = copy_to_user(user_arg, hid->phys, len) ?
                                                -EFAULT : len;
+                                       break;
                                }
                 }
 
-                       ret = -ENOTTY;
+               ret = -ENOTTY;
        }
        unlock_kernel();
        return ret;
index 609cafff86bc2ce23c364831f959c2dbcd310baf..5f81ddf7150871e67c7fe3ff1647df7e01c6c2c5 100644 (file)
@@ -1872,7 +1872,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
 
        devid = superio_inw(sioaddr, SIO_REG_MANID);
        if (devid != SIO_FINTEK_ID) {
-               printk(KERN_INFO DRVNAME ": Not a Fintek device\n");
+               pr_debug(DRVNAME ": Not a Fintek device\n");
                goto exit;
        }
 
@@ -1932,7 +1932,7 @@ static int __init f71882fg_device_add(unsigned short address,
        res.name = f71882fg_pdev->name;
        err = acpi_check_resource_conflict(&res);
        if (err)
-               return err;
+               goto exit_device_put;
 
        err = platform_device_add_resources(f71882fg_pdev, &res, 1);
        if (err) {
index abf4dfc8ec229c874b286acb4942278c50a138c1..29c83b5b96974bb88cbeb67d896ba46ee71469f2 100644 (file)
@@ -166,6 +166,18 @@ static struct axis_conversion lis3lv02d_axis_xy_swap_yz_inverted = {2, -1, -3};
        },                                              \
        .driver_data = &lis3lv02d_axis_##_axis          \
 }
+
+#define AXIS_DMI_MATCH2(_ident, _class1, _name1,       \
+                               _class2, _name2,        \
+                               _axis) {                \
+       .ident = _ident,                                \
+       .callback = lis3lv02d_dmi_matched,              \
+       .matches = {                                    \
+               DMI_MATCH(DMI_##_class1, _name1),       \
+               DMI_MATCH(DMI_##_class2, _name2),       \
+       },                                              \
+       .driver_data = &lis3lv02d_axis_##_axis          \
+}
 static struct dmi_system_id lis3lv02d_dmi_ids[] = {
        /* product names are truncated to match all kinds of a same model */
        AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
@@ -179,6 +191,16 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
        AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd),
        AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
        AXIS_DMI_MATCH("NC671xx", "HP Compaq 671", xy_swap_yz_inverted),
+       /* Intel-based HP Pavilion dv5 */
+       AXIS_DMI_MATCH2("HPDV5_I",
+                       PRODUCT_NAME, "HP Pavilion dv5",
+                       BOARD_NAME, "3603",
+                       x_inverted),
+       /* AMD-based HP Pavilion dv5 */
+       AXIS_DMI_MATCH2("HPDV5_A",
+                       PRODUCT_NAME, "HP Pavilion dv5",
+                       BOARD_NAME, "3600",
+                       y_inverted),
        { NULL, }
 /* Laptop models without axis info (yet):
  * "NC6910" "HP Compaq 6910"
@@ -213,9 +235,49 @@ static struct delayed_led_classdev hpled_led = {
        .set_brightness = hpled_set,
 };
 
+static acpi_status
+lis3lv02d_get_resource(struct acpi_resource *resource, void *context)
+{
+       if (resource->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
+               struct acpi_resource_extended_irq *irq;
+               u32 *device_irq = context;
+
+               irq = &resource->data.extended_irq;
+               *device_irq = irq->interrupts[0];
+       }
+
+       return AE_OK;
+}
+
+static void lis3lv02d_enum_resources(struct acpi_device *device)
+{
+       acpi_status status;
+
+       status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+                                       lis3lv02d_get_resource, &adev.irq);
+       if (ACPI_FAILURE(status))
+               printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
+}
+
+static s16 lis3lv02d_read_16(acpi_handle handle, int reg)
+{
+       u8 lo, hi;
+
+       adev.read(handle, reg - 1, &lo);
+       adev.read(handle, reg, &hi);
+       /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
+       return (s16)((hi << 8) | lo);
+}
+
+static s16 lis3lv02d_read_8(acpi_handle handle, int reg)
+{
+       s8 lo;
+       adev.read(handle, reg, &lo);
+       return lo;
+}
+
 static int lis3lv02d_add(struct acpi_device *device)
 {
-       u8 val;
        int ret;
 
        if (!device)
@@ -229,10 +291,22 @@ static int lis3lv02d_add(struct acpi_device *device)
        strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
        device->driver_data = &adev;
 
-       lis3lv02d_acpi_read(device->handle, WHO_AM_I, &val);
-       if ((val != LIS3LV02DL_ID) && (val != LIS302DL_ID)) {
+       lis3lv02d_acpi_read(device->handle, WHO_AM_I, &adev.whoami);
+       switch (adev.whoami) {
+       case LIS_DOUBLE_ID:
+               printk(KERN_INFO DRIVER_NAME ": 2-byte sensor found\n");
+               adev.read_data = lis3lv02d_read_16;
+               adev.mdps_max_val = 2048;
+               break;
+       case LIS_SINGLE_ID:
+               printk(KERN_INFO DRIVER_NAME ": 1-byte sensor found\n");
+               adev.read_data = lis3lv02d_read_8;
+               adev.mdps_max_val = 128;
+               break;
+       default:
                printk(KERN_ERR DRIVER_NAME
-                               ": Accelerometer chip not LIS3LV02D{L,Q}\n");
+                       ": unknown sensor type 0x%X\n", adev.whoami);
+               return -EINVAL;
        }
 
        /* If possible use a "standard" axes order */
@@ -247,6 +321,9 @@ static int lis3lv02d_add(struct acpi_device *device)
        if (ret)
                return ret;
 
+       /* obtain IRQ number of our device from ACPI */
+       lis3lv02d_enum_resources(adev.device);
+
        ret = lis3lv02d_init_device(&adev);
        if (ret) {
                flush_work(&hpled_led.work);
index 219d2d0d5a626713377ada0f311d190dca9048c6..8bb2158f0453c01f3c089ffaa88d8eea2927fd9d 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2007-2008 Yan Burman
  *  Copyright (C) 2008 Eric Piel
- *  Copyright (C) 2008 Pavel Machek
+ *  Copyright (C) 2008-2009 Pavel Machek
  *
  *  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
@@ -35,6 +35,7 @@
 #include <linux/poll.h>
 #include <linux/freezer.h>
 #include <linux/uaccess.h>
+#include <linux/miscdevice.h>
 #include <acpi/acpi_drivers.h>
 #include <asm/atomic.h>
 #include "lis3lv02d.h"
  * joystick.
  */
 
-/* Maximum value our axis may get for the input device (signed 12 bits) */
-#define MDPS_MAX_VAL 2048
+struct acpi_lis3lv02d adev = {
+       .misc_wait   = __WAIT_QUEUE_HEAD_INITIALIZER(adev.misc_wait),
+};
 
-struct acpi_lis3lv02d adev;
 EXPORT_SYMBOL_GPL(adev);
 
 static int lis3lv02d_add_fs(struct acpi_device *device);
 
-static s16 lis3lv02d_read_16(acpi_handle handle, int reg)
-{
-       u8 lo, hi;
-
-       adev.read(handle, reg, &lo);
-       adev.read(handle, reg + 1, &hi);
-       /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
-       return (s16)((hi << 8) | lo);
-}
-
 /**
  * lis3lv02d_get_axis - For the given axis, give the value converted
  * @axis:      1,2,3 - can also be negative
@@ -98,9 +89,9 @@ static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z)
 {
        int position[3];
 
-       position[0] = lis3lv02d_read_16(handle, OUTX_L);
-       position[1] = lis3lv02d_read_16(handle, OUTY_L);
-       position[2] = lis3lv02d_read_16(handle, OUTZ_L);
+       position[0] = adev.read_data(handle, OUTX);
+       position[1] = adev.read_data(handle, OUTY);
+       position[2] = adev.read_data(handle, OUTZ);
 
        *x = lis3lv02d_get_axis(adev.ac.x, position);
        *y = lis3lv02d_get_axis(adev.ac.y, position);
@@ -110,26 +101,13 @@ static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z)
 void lis3lv02d_poweroff(acpi_handle handle)
 {
        adev.is_on = 0;
-       /* disable X,Y,Z axis and power down */
-       adev.write(handle, CTRL_REG1, 0x00);
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
 
 void lis3lv02d_poweron(acpi_handle handle)
 {
-       u8 val;
-
        adev.is_on = 1;
        adev.init(handle);
-       adev.write(handle, FF_WU_CFG, 0);
-       /*
-        * BDU: LSB and MSB values are not updated until both have been read.
-        *      So the value read will always be correct.
-        * IEN: Interrupt for free-fall and DD, not for data-ready.
-        */
-       adev.read(handle, CTRL_REG2, &val);
-       val |= CTRL2_BDU | CTRL2_IEN;
-       adev.write(handle, CTRL_REG2, val);
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
 
@@ -162,6 +140,140 @@ static void lis3lv02d_decrease_use(struct acpi_lis3lv02d *dev)
        mutex_unlock(&dev->lock);
 }
 
+static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
+{
+       /*
+        * Be careful: on some HP laptops the bios force DD when on battery and
+        * the lid is closed. This leads to interrupts as soon as a little move
+        * is done.
+        */
+       atomic_inc(&adev.count);
+
+       wake_up_interruptible(&adev.misc_wait);
+       kill_fasync(&adev.async_queue, SIGIO, POLL_IN);
+       return IRQ_HANDLED;
+}
+
+static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
+{
+       int ret;
+
+       if (test_and_set_bit(0, &adev.misc_opened))
+               return -EBUSY; /* already open */
+
+       atomic_set(&adev.count, 0);
+
+       /*
+        * The sensor can generate interrupts for free-fall and direction
+        * detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
+        * the things simple and _fast_ we activate it only for free-fall, so
+        * no need to read register (very slow with ACPI). For the same reason,
+        * we forbid shared interrupts.
+        *
+        * IRQF_TRIGGER_RISING seems pointless on HP laptops because the
+        * io-apic is not configurable (and generates a warning) but I keep it
+        * in case of support for other hardware.
+        */
+       ret = request_irq(adev.irq, lis302dl_interrupt, IRQF_TRIGGER_RISING,
+                         DRIVER_NAME, &adev);
+
+       if (ret) {
+               clear_bit(0, &adev.misc_opened);
+               printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", adev.irq);
+               return -EBUSY;
+       }
+       lis3lv02d_increase_use(&adev);
+       printk("lis3: registered interrupt %d\n", adev.irq);
+       return 0;
+}
+
+static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
+{
+       fasync_helper(-1, file, 0, &adev.async_queue);
+       lis3lv02d_decrease_use(&adev);
+       free_irq(adev.irq, &adev);
+       clear_bit(0, &adev.misc_opened); /* release the device */
+       return 0;
+}
+
+static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
+                               size_t count, loff_t *pos)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       u32 data;
+       unsigned char byte_data;
+       ssize_t retval = 1;
+
+       if (count < 1)
+               return -EINVAL;
+
+       add_wait_queue(&adev.misc_wait, &wait);
+       while (true) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               data = atomic_xchg(&adev.count, 0);
+               if (data)
+                       break;
+
+               if (file->f_flags & O_NONBLOCK) {
+                       retval = -EAGAIN;
+                       goto out;
+               }
+
+               if (signal_pending(current)) {
+                       retval = -ERESTARTSYS;
+                       goto out;
+               }
+
+               schedule();
+       }
+
+       if (data < 255)
+               byte_data = data;
+       else
+               byte_data = 255;
+
+       /* make sure we are not going into copy_to_user() with
+        * TASK_INTERRUPTIBLE state */
+       set_current_state(TASK_RUNNING);
+       if (copy_to_user(buf, &byte_data, sizeof(byte_data)))
+               retval = -EFAULT;
+
+out:
+       __set_current_state(TASK_RUNNING);
+       remove_wait_queue(&adev.misc_wait, &wait);
+
+       return retval;
+}
+
+static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait)
+{
+       poll_wait(file, &adev.misc_wait, wait);
+       if (atomic_read(&adev.count))
+               return POLLIN | POLLRDNORM;
+       return 0;
+}
+
+static int lis3lv02d_misc_fasync(int fd, struct file *file, int on)
+{
+       return fasync_helper(fd, file, on, &adev.async_queue);
+}
+
+static const struct file_operations lis3lv02d_misc_fops = {
+       .owner   = THIS_MODULE,
+       .llseek  = no_llseek,
+       .read    = lis3lv02d_misc_read,
+       .open    = lis3lv02d_misc_open,
+       .release = lis3lv02d_misc_release,
+       .poll    = lis3lv02d_misc_poll,
+       .fasync  = lis3lv02d_misc_fasync,
+};
+
+static struct miscdevice lis3lv02d_misc_device = {
+       .minor   = MISC_DYNAMIC_MINOR,
+       .name    = "freefall",
+       .fops    = &lis3lv02d_misc_fops,
+};
+
 /**
  * lis3lv02d_joystick_kthread - Kthread polling function
  * @data: unused - here to conform to threadfn prototype
@@ -203,7 +315,6 @@ static void lis3lv02d_joystick_close(struct input_dev *input)
        lis3lv02d_decrease_use(&adev);
 }
 
-
 static inline void lis3lv02d_calibrate_joystick(void)
 {
        lis3lv02d_get_xyz(adev.device->handle, &adev.xcalib, &adev.ycalib, &adev.zcalib);
@@ -231,9 +342,9 @@ int lis3lv02d_joystick_enable(void)
        adev.idev->close      = lis3lv02d_joystick_close;
 
        set_bit(EV_ABS, adev.idev->evbit);
-       input_set_abs_params(adev.idev, ABS_X, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3);
-       input_set_abs_params(adev.idev, ABS_Y, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3);
-       input_set_abs_params(adev.idev, ABS_Z, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3);
+       input_set_abs_params(adev.idev, ABS_X, -adev.mdps_max_val, adev.mdps_max_val, 3, 3);
+       input_set_abs_params(adev.idev, ABS_Y, -adev.mdps_max_val, adev.mdps_max_val, 3, 3);
+       input_set_abs_params(adev.idev, ABS_Z, -adev.mdps_max_val, adev.mdps_max_val, 3, 3);
 
        err = input_register_device(adev.idev);
        if (err) {
@@ -250,6 +361,7 @@ void lis3lv02d_joystick_disable(void)
        if (!adev.idev)
                return;
 
+       misc_deregister(&lis3lv02d_misc_device);
        input_unregister_device(adev.idev);
        adev.idev = NULL;
 }
@@ -268,6 +380,19 @@ int lis3lv02d_init_device(struct acpi_lis3lv02d *dev)
        if (lis3lv02d_joystick_enable())
                printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n");
 
+       printk("lis3_init_device: irq %d\n", dev->irq);
+
+       /* if we did not get an IRQ from ACPI - we have nothing more to do */
+       if (!dev->irq) {
+               printk(KERN_ERR DRIVER_NAME
+                       ": No IRQ in ACPI. Disabling /dev/freefall\n");
+               goto out;
+       }
+
+       printk("lis3: registering device\n");
+       if (misc_register(&lis3lv02d_misc_device))
+               printk(KERN_ERR DRIVER_NAME ": misc_register failed\n");
+out:
        lis3lv02d_decrease_use(dev);
        return 0;
 }
@@ -351,6 +476,6 @@ int lis3lv02d_remove_fs(void)
 EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
 
 MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver");
-MODULE_AUTHOR("Yan Burman and Eric Piel");
+MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
 MODULE_LICENSE("GPL");
 
index 223f1c0763bba4decc69c85e74c990ba4472ba9d..75972bf372ff474a2fd1a43cdaf85db9ddddebd4 100644 (file)
 /*
  * The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to
  * be connected via SPI. There exists also several similar chips (such as LIS302DL or
- * LIS3L02DQ) but not in the HP laptops and they have slightly different registers.
+ * LIS3L02DQ) and they have slightly different registers, but we can provide a
+ * common interface for all of them.
  * They can also be connected via I²C.
  */
 
-#define LIS3LV02DL_ID  0x3A /* Also the LIS3LV02DQ */
-#define LIS302DL_ID    0x3B /* Also the LIS202DL! */
+/* 2-byte registers */
+#define LIS_DOUBLE_ID  0x3A /* LIS3LV02D[LQ] */
+/* 1-byte registers */
+#define LIS_SINGLE_ID  0x3B /* LIS[32]02DL and others */
 
 enum lis3lv02d_reg {
        WHO_AM_I        = 0x0F,
@@ -44,10 +47,13 @@ enum lis3lv02d_reg {
        STATUS_REG      = 0x27,
        OUTX_L          = 0x28,
        OUTX_H          = 0x29,
+       OUTX            = 0x29,
        OUTY_L          = 0x2A,
        OUTY_H          = 0x2B,
+       OUTY            = 0x2B,
        OUTZ_L          = 0x2C,
        OUTZ_H          = 0x2D,
+       OUTZ            = 0x2D,
        FF_WU_CFG       = 0x30,
        FF_WU_SRC       = 0x31,
        FF_WU_ACK       = 0x32,
@@ -159,6 +165,10 @@ struct acpi_lis3lv02d {
        acpi_status (*write) (acpi_handle handle, int reg, u8 val);
        acpi_status (*read) (acpi_handle handle, int reg, u8 *ret);
 
+       u8                      whoami;    /* 3Ah: 2-byte registries, 3Bh: 1-byte registries */
+       s16 (*read_data) (acpi_handle handle, int reg);
+       int                     mdps_max_val;
+
        struct input_dev        *idev;     /* input device */
        struct task_struct      *kthread;  /* kthread for input */
        struct mutex            lock;
@@ -170,6 +180,11 @@ struct acpi_lis3lv02d {
        unsigned char           is_on;     /* whether the device is on or off */
        unsigned char           usage;     /* usage counter */
        struct axis_conversion  ac;        /* hw -> logical axis */
+
+       u32                     irq;       /* IRQ number */
+       struct fasync_struct    *async_queue; /* queue for the misc device */
+       wait_queue_head_t       misc_wait; /* Wait queue for the misc device */
+       unsigned long           misc_opened; /* bit0: whether the device is open */
 };
 
 int lis3lv02d_init_device(struct acpi_lis3lv02d *dev);
index b0ce3785228101f6cf8ff388497e57e5b0f44f98..73f77a9b8b188fb15840beea34d5f2f07a8d8a4f 100644 (file)
@@ -1262,7 +1262,7 @@ static int __init vt1211_device_add(unsigned short address)
        res.name = pdev->name;
        err = acpi_check_resource_conflict(&res);
        if (err)
-               goto EXIT;
+               goto EXIT_DEV_PUT;
 
        err = platform_device_add_resources(pdev, &res, 1);
        if (err) {
index cb808d0153619838378bd70f1ea5bfc3ca1c5ad2..feae743ba99163c2475b0f51663c89fc7e7f1375 100644 (file)
@@ -1548,7 +1548,7 @@ static int __init sensors_w83627ehf_init(void)
 
        err = acpi_check_resource_conflict(&res);
        if (err)
-               goto exit;
+               goto exit_device_put;
 
        err = platform_device_add_resources(pdev, &res, 1);
        if (err) {
index 712220cef139469f93bd82ad5c97239c932d4841..7f16d75d2d89fa1137cad8651e765eb9b4a512e2 100644 (file)
@@ -54,7 +54,7 @@ void memcpy_toshmem(int card, void *dest, const void *src, size_t n)
        spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
        pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
                ((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
-       pr_debug("%s: copying %d bytes from %#lx to %#lx\n",
+       pr_debug("%s: copying %zu bytes from %#lx to %#lx\n",
                sc_adapter[card]->devicename, n,
                (unsigned long) src,
                sc_adapter[card]->rambase + ((unsigned long) dest %0x4000));
index a34338567a2a601c3cdbda72441d54299301f89a..f14813be4eff88ccdc082b62336690e20b0342cb 100644 (file)
@@ -328,7 +328,7 @@ static void dispatch_io(int rw, unsigned int num_regions,
        struct dpages old_pages = *dp;
 
        if (sync)
-               rw |= (1 << BIO_RW_SYNC);
+               rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
 
        /*
         * For multiple regions we need to be careful to rewind
index 3073618269ea3030e468541ea2af6f05dd2aac65..0a225da21272543c33b4992a9bf1c83b923b8bbf 100644 (file)
@@ -344,7 +344,7 @@ static int run_io_job(struct kcopyd_job *job)
 {
        int r;
        struct dm_io_request io_req = {
-               .bi_rw = job->rw | (1 << BIO_RW_SYNC),
+               .bi_rw = job->rw | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG),
                .mem.type = DM_IO_PAGE_LIST,
                .mem.ptr.pl = job->pages,
                .mem.offset = job->offset,
index 4495104f6c9f33297727891510e667db46ac29ac..03b4cd0a6344cf2e458a035325eb2ec7ffc8805a 100644 (file)
@@ -474,7 +474,7 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
         * causes ENOTSUPP, we allocate a spare bio...
         */
        struct bio *bio = bio_alloc(GFP_NOIO, 1);
-       int rw = (1<<BIO_RW) | (1<<BIO_RW_SYNC);
+       int rw = (1<<BIO_RW) | (1<<BIO_RW_SYNCIO) | (1<<BIO_RW_UNPLUG);
 
        bio->bi_bdev = rdev->bdev;
        bio->bi_sector = sector;
@@ -531,7 +531,7 @@ int sync_page_io(struct block_device *bdev, sector_t sector, int size,
        struct completion event;
        int ret;
 
-       rw |= (1 << BIO_RW_SYNC);
+       rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
 
        bio->bi_bdev = bdev;
        bio->bi_sector = sector;
index de7adaf5fa5b1d186c8c05b8c46925bea1c52d65..78412c9c424a13e492a59ad467368716755be6b2 100644 (file)
@@ -318,7 +318,6 @@ static int simple_std_setup(struct dvb_frontend *fe,
                            u8 *config, u8 *cb)
 {
        struct tuner_simple_priv *priv = fe->tuner_priv;
-       u8 tuneraddr;
        int rc;
 
        /* tv norm specific stuff for multi-norm tuners */
@@ -387,6 +386,7 @@ static int simple_std_setup(struct dvb_frontend *fe,
 
        case TUNER_PHILIPS_TUV1236D:
        {
+               struct tuner_i2c_props i2c = priv->i2c_props;
                /* 0x40 -> ATSC antenna input 1 */
                /* 0x48 -> ATSC antenna input 2 */
                /* 0x00 -> NTSC antenna input 1 */
@@ -398,17 +398,15 @@ static int simple_std_setup(struct dvb_frontend *fe,
                        buffer[1] = 0x04;
                }
                /* set to the correct mode (analog or digital) */
-               tuneraddr = priv->i2c_props.addr;
-               priv->i2c_props.addr = 0x0a;
-               rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[0], 2);
+               i2c.addr = 0x0a;
+               rc = tuner_i2c_xfer_send(&i2c, &buffer[0], 2);
                if (2 != rc)
                        tuner_warn("i2c i/o error: rc == %d "
                                   "(should be 2)\n", rc);
-               rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[2], 2);
+               rc = tuner_i2c_xfer_send(&i2c, &buffer[2], 2);
                if (2 != rc)
                        tuner_warn("i2c i/o error: rc == %d "
                                   "(should be 2)\n", rc);
-               priv->i2c_props.addr = tuneraddr;
                break;
        }
        }
index 0c733c66a44150d7abd6afdea0acbbd760fe385b..069d847ba887c39e2f1f83eafdf7c06a07b838a7 100644 (file)
@@ -364,16 +364,15 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
                                       enum dmx_success success)
 {
        struct dmxdev_filter *dmxdevfilter = filter->priv;
-       unsigned long flags;
        int ret;
 
        if (dmxdevfilter->buffer.error) {
                wake_up(&dmxdevfilter->buffer.queue);
                return 0;
        }
-       spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
+       spin_lock(&dmxdevfilter->dev->lock);
        if (dmxdevfilter->state != DMXDEV_STATE_GO) {
-               spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+               spin_unlock(&dmxdevfilter->dev->lock);
                return 0;
        }
        del_timer(&dmxdevfilter->timer);
@@ -392,7 +391,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
        }
        if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
                dmxdevfilter->state = DMXDEV_STATE_DONE;
-       spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+       spin_unlock(&dmxdevfilter->dev->lock);
        wake_up(&dmxdevfilter->buffer.queue);
        return 0;
 }
@@ -404,12 +403,11 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
 {
        struct dmxdev_filter *dmxdevfilter = feed->priv;
        struct dvb_ringbuffer *buffer;
-       unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
+       spin_lock(&dmxdevfilter->dev->lock);
        if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
-               spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+               spin_unlock(&dmxdevfilter->dev->lock);
                return 0;
        }
 
@@ -419,7 +417,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
        else
                buffer = &dmxdevfilter->dev->dvr_buffer;
        if (buffer->error) {
-               spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+               spin_unlock(&dmxdevfilter->dev->lock);
                wake_up(&buffer->queue);
                return 0;
        }
@@ -430,7 +428,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
                dvb_ringbuffer_flush(buffer);
                buffer->error = ret;
        }
-       spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+       spin_unlock(&dmxdevfilter->dev->lock);
        wake_up(&buffer->queue);
        return 0;
 }
index a2c1fd5d2f67b05b5b25da04cf6a8dc0d7e8da49..e2eca0b1fe7cfad6dc1215aa6d2bd1247497b93e 100644 (file)
@@ -399,9 +399,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
 void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
                              size_t count)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&demux->lock, flags);
+       spin_lock(&demux->lock);
 
        while (count--) {
                if (buf[0] == 0x47)
@@ -409,17 +407,16 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
                buf += 188;
        }
 
-       spin_unlock_irqrestore(&demux->lock, flags);
+       spin_unlock(&demux->lock);
 }
 
 EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
 
 void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
 {
-       unsigned long flags;
        int p = 0, i, j;
 
-       spin_lock_irqsave(&demux->lock, flags);
+       spin_lock(&demux->lock);
 
        if (demux->tsbufp) {
                i = demux->tsbufp;
@@ -452,18 +449,17 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
        }
 
 bailout:
-       spin_unlock_irqrestore(&demux->lock, flags);
+       spin_unlock(&demux->lock);
 }
 
 EXPORT_SYMBOL(dvb_dmx_swfilter);
 
 void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
 {
-       unsigned long flags;
        int p = 0, i, j;
        u8 tmppack[188];
 
-       spin_lock_irqsave(&demux->lock, flags);
+       spin_lock(&demux->lock);
 
        if (demux->tsbufp) {
                i = demux->tsbufp;
@@ -504,7 +500,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
        }
 
 bailout:
-       spin_unlock_irqrestore(&demux->lock, flags);
+       spin_unlock(&demux->lock);
 }
 
 EXPORT_SYMBOL(dvb_dmx_swfilter_204);
index 67cbce82cb913a0619f3a72fb8a4e519076cbf96..4dfed6aa2dbc54921e175a591f8a40668553b294 100644 (file)
  *             - blacklisted KWorld radio in hid-core.c and hid-ids.h
  * 2008-12-03  Mark Lord <mlord@pobox.com>
  *             - add support for DealExtreme USB Radio
+ * 2009-01-31  Bob Ross <pigiron@gmx.com>
+ *             - correction of stereo detection/setting
+ *             - correction of signal strength indicator scaling
+ * 2009-01-31  Rick Bronson <rick@efn.org>
+ *             Tobias Lorenz <tobias.lorenz@gmx.net>
+ *             - add LED status output
  *
  * ToDo:
  * - add firmware download/update support
  * - RDS support: interrupt mode, instead of polling
- * - add LED status output (check if that's not already done in firmware)
  */
 
 
@@ -881,6 +886,30 @@ static int si470x_rds_on(struct si470x_device *radio)
 
 
 
+/**************************************************************************
+ * General Driver Functions - LED_REPORT
+ **************************************************************************/
+
+/*
+ * si470x_set_led_state - sets the led state
+ */
+static int si470x_set_led_state(struct si470x_device *radio,
+               unsigned char led_state)
+{
+       unsigned char buf[LED_REPORT_SIZE];
+       int retval;
+
+       buf[0] = LED_REPORT;
+       buf[1] = LED_COMMAND;
+       buf[2] = led_state;
+
+       retval = si470x_set_report(radio, (void *) &buf, sizeof(buf));
+
+       return (retval < 0) ? -EINVAL : 0;
+}
+
+
+
 /**************************************************************************
  * RDS Driver Functions
  **************************************************************************/
@@ -1385,20 +1414,22 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
        };
 
        /* stereo indicator == stereo (instead of mono) */
-       if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 1)
-               tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
-       else
+       if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0)
                tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
+       else
+               tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
 
        /* mono/stereo selector */
-       if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 1)
-               tuner->audmode = V4L2_TUNER_MODE_MONO;
-       else
+       if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0)
                tuner->audmode = V4L2_TUNER_MODE_STEREO;
+       else
+               tuner->audmode = V4L2_TUNER_MODE_MONO;
 
        /* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */
-       tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI)
-                               * 0x0101;
+       /* measured in units of dbµV in 1 db increments (max at ~75 dbµV) */
+       tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI);
+       /* the ideal factor is 0xffff/75 = 873,8 */
+       tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10);
 
        /* automatic frequency control: -1: freq to low, 1 freq to high */
        /* AFCRL does only indicate that freq. differs, not if too low/high */
@@ -1632,6 +1663,9 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
        /* set initial frequency */
        si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
 
+       /* set led to connect state */
+       si470x_set_led_state(radio, BLINK_GREEN_LED);
+
        /* rds buffer allocation */
        radio->buf_size = rds_buf * 3;
        radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
@@ -1715,6 +1749,9 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
        cancel_delayed_work_sync(&radio->work);
        usb_set_intfdata(intf, NULL);
        if (radio->users == 0) {
+               /* set led to disconnect state */
+               si470x_set_led_state(radio, BLINK_ORANGE_LED);
+
                video_unregister_device(radio->videodev);
                kfree(radio->buffer);
                kfree(radio);
index 2ed24527ecd61cea70287dd668725445799ee4fa..65e4901f4db70a713a4b1d60c0400c4ec9f9250a 100644 (file)
@@ -422,6 +422,7 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
                if (urb == NULL)
                        break;
 
+               BUG_ON(!gspca_dev->dev);
                gspca_dev->urb[i] = NULL;
                if (!gspca_dev->present)
                        usb_kill_urb(urb);
@@ -1950,8 +1951,12 @@ void gspca_disconnect(struct usb_interface *intf)
 {
        struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
 
+       mutex_lock(&gspca_dev->usb_lock);
        gspca_dev->present = 0;
+       mutex_unlock(&gspca_dev->usb_lock);
 
+       destroy_urbs(gspca_dev);
+       gspca_dev->dev = NULL;
        usb_set_intfdata(intf, NULL);
 
        /* release the device */
index f6b3ef6e691be8465ab82b397b7c796bd27b0cf4..c13bd2aa0bea6180a98fe078be7449e6ea2e25ca 100644 (file)
@@ -393,7 +393,7 @@ static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo
                return 0;
        }
 
-       v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
+       v4l2_subdev_call(itv->sd_video, video, g_fmt, fmt);
        vbifmt->service_set = ivtv_get_service_set(vbifmt);
        return 0;
 }
@@ -1748,6 +1748,18 @@ static long ivtv_default(struct file *file, void *fh, int cmd, void *arg)
                break;
        }
 
+       case IVTV_IOC_DMA_FRAME:
+       case VIDEO_GET_PTS:
+       case VIDEO_GET_FRAME_COUNT:
+       case VIDEO_GET_EVENT:
+       case VIDEO_PLAY:
+       case VIDEO_STOP:
+       case VIDEO_FREEZE:
+       case VIDEO_CONTINUE:
+       case VIDEO_COMMAND:
+       case VIDEO_TRY_COMMAND:
+               return ivtv_decoder_ioctls(file, cmd, (void *)arg);
+
        default:
                return -EINVAL;
        }
@@ -1790,18 +1802,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
                ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
                return 0;
 
-       case IVTV_IOC_DMA_FRAME:
-       case VIDEO_GET_PTS:
-       case VIDEO_GET_FRAME_COUNT:
-       case VIDEO_GET_EVENT:
-       case VIDEO_PLAY:
-       case VIDEO_STOP:
-       case VIDEO_FREEZE:
-       case VIDEO_CONTINUE:
-       case VIDEO_COMMAND:
-       case VIDEO_TRY_COMMAND:
-               return ivtv_decoder_ioctls(filp, cmd, (void *)arg);
-
        default:
                break;
        }
index 1a4d04664d6dca96426c965b0ad80062f3042a95..aa266e1f69b255875ee5b98e67988b31019fcf18 100644 (file)
@@ -286,7 +286,7 @@ static int __init egpio_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
                goto fail;
-       ei->base_addr = ioremap_nocache(res->start, res->end - res->start);
+       ei->base_addr = ioremap_nocache(res->start, resource_size(res));
        if (!ei->base_addr)
                goto fail;
        pr_debug("EGPIO phys=%08x virt=%p\n", (u32)res->start, ei->base_addr);
@@ -307,7 +307,7 @@ static int __init egpio_probe(struct platform_device *pdev)
 
        ei->nchips = pdata->num_chips;
        ei->chip = kzalloc(sizeof(struct egpio_chip) * ei->nchips, GFP_KERNEL);
-       if (!ei) {
+       if (!ei->chip) {
                ret = -ENOMEM;
                goto fail;
        }
index ea9488e7ad6d60a7d8b80d90083d2cbe83d7beef..2e36057659e12acedd5d2be43268d692aaefe8e3 100644 (file)
@@ -678,6 +678,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client)
 
 static struct i2c_device_id pcf50633_id_table[] = {
        {"pcf50633", 0x73},
+       {/* end of list */}
 };
 
 static struct i2c_driver pcf50633_driver = {
index 0e5761f12634c02c493e4b346b29ec8722eb3f21..4c7b7962f6b8002b18ef57c0a6d4015bcf7c2fc1 100644 (file)
@@ -1050,7 +1050,7 @@ static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
        return gpiochip_add(gchip);
 }
 
-static int sm501_register_gpio(struct sm501_devdata *sm)
+static int __devinit sm501_register_gpio(struct sm501_devdata *sm)
 {
        struct sm501_gpio *gpio = &sm->gpio;
        resource_size_t iobase = sm->io_res->start + SM501_GPIO;
@@ -1321,7 +1321,7 @@ static unsigned int sm501_mem_local[] = {
  * Common init code for an SM501
 */
 
-static int sm501_init_dev(struct sm501_devdata *sm)
+static int __devinit sm501_init_dev(struct sm501_devdata *sm)
 {
        struct sm501_initdata *idata;
        struct sm501_platdata *pdata;
@@ -1397,7 +1397,7 @@ static int sm501_init_dev(struct sm501_devdata *sm)
        return 0;
 }
 
-static int sm501_plat_probe(struct platform_device *dev)
+static int __devinit sm501_plat_probe(struct platform_device *dev)
 {
        struct sm501_devdata *sm;
        int ret;
@@ -1586,8 +1586,8 @@ static struct sm501_platdata sm501_pci_platdata = {
        .gpio_base      = -1,
 };
 
-static int sm501_pci_probe(struct pci_dev *dev,
-                          const struct pci_device_id *id)
+static int __devinit sm501_pci_probe(struct pci_dev *dev,
+                                    const struct pci_device_id *id)
 {
        struct sm501_devdata *sm;
        int err;
@@ -1693,7 +1693,7 @@ static void sm501_dev_remove(struct sm501_devdata *sm)
        sm501_gpio_remove(sm);
 }
 
-static void sm501_pci_remove(struct pci_dev *dev)
+static void __devexit sm501_pci_remove(struct pci_dev *dev)
 {
        struct sm501_devdata *sm = pci_get_drvdata(dev);
 
@@ -1727,16 +1727,16 @@ static struct pci_device_id sm501_pci_tbl[] = {
 
 MODULE_DEVICE_TABLE(pci, sm501_pci_tbl);
 
-static struct pci_driver sm501_pci_drv = {
+static struct pci_driver sm501_pci_driver = {
        .name           = "sm501",
        .id_table       = sm501_pci_tbl,
        .probe          = sm501_pci_probe,
-       .remove         = sm501_pci_remove,
+       .remove         = __devexit_p(sm501_pci_remove),
 };
 
 MODULE_ALIAS("platform:sm501");
 
-static struct platform_driver sm501_plat_drv = {
+static struct platform_driver sm501_plat_driver = {
        .driver         = {
                .name   = "sm501",
                .owner  = THIS_MODULE,
@@ -1749,14 +1749,14 @@ static struct platform_driver sm501_plat_drv = {
 
 static int __init sm501_base_init(void)
 {
-       platform_driver_register(&sm501_plat_drv);
-       return pci_register_driver(&sm501_pci_drv);
+       platform_driver_register(&sm501_plat_driver);
+       return pci_register_driver(&sm501_pci_driver);
 }
 
 static void __exit sm501_base_exit(void)
 {
-       platform_driver_unregister(&sm501_plat_drv);
-       pci_unregister_driver(&sm501_pci_drv);
+       platform_driver_unregister(&sm501_plat_driver);
+       pci_unregister_driver(&sm501_pci_driver);
 }
 
 module_init(sm501_base_init);
index e7ab0035d3054fdfd159b48c9e548150758b986b..68826f1e36bccd057f938919083e6877731025c3 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c/twl4030.h>
 
-#ifdef CONFIG_ARM
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 #include <mach/cpu.h>
 #endif
 
index f92595c8f165b7223d66958f648ba183dbb5519e..84d5ea1ec17120e9c4d8d94b6a2c9376ac241449 100644 (file)
@@ -1111,7 +1111,7 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
        do {
                schedule_timeout_interruptible(1);
                reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
-       } while (tries-- && (reg & WM8350_AUXADC_POLL));
+       } while (--tries && (reg & WM8350_AUXADC_POLL));
 
        if (!tries)
                dev_err(wm8350->dev, "adc chn %d read timeout\n", channel);
@@ -1297,14 +1297,29 @@ static void wm8350_client_dev_register(struct wm8350 *wm8350,
 int wm8350_device_init(struct wm8350 *wm8350, int irq,
                       struct wm8350_platform_data *pdata)
 {
-       int ret = -EINVAL;
+       int ret;
        u16 id1, id2, mask_rev;
        u16 cust_id, mode, chip_rev;
 
        /* get WM8350 revision and config mode */
-       wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
-       wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2);
-       wm8350->read_dev(wm8350, WM8350_REVISION, sizeof(mask_rev), &mask_rev);
+       ret = wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
+       if (ret != 0) {
+               dev_err(wm8350->dev, "Failed to read ID: %d\n", ret);
+               goto err;
+       }
+
+       ret = wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2);
+       if (ret != 0) {
+               dev_err(wm8350->dev, "Failed to read ID: %d\n", ret);
+               goto err;
+       }
+
+       ret = wm8350->read_dev(wm8350, WM8350_REVISION, sizeof(mask_rev),
+                              &mask_rev);
+       if (ret != 0) {
+               dev_err(wm8350->dev, "Failed to read revision: %d\n", ret);
+               goto err;
+       }
 
        id1 = be16_to_cpu(id1);
        id2 = be16_to_cpu(id2);
@@ -1404,14 +1419,12 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
                return ret;
        }
 
-       if (pdata && pdata->init) {
-               ret = pdata->init(wm8350);
-               if (ret != 0) {
-                       dev_err(wm8350->dev, "Platform init() failed: %d\n",
-                               ret);
-                       goto err;
-               }
-       }
+       wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF);
+       wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK, 0xFFFF);
+       wm8350_reg_write(wm8350, WM8350_INT_STATUS_2_MASK, 0xFFFF);
+       wm8350_reg_write(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, 0xFFFF);
+       wm8350_reg_write(wm8350, WM8350_GPIO_INT_STATUS_MASK, 0xFFFF);
+       wm8350_reg_write(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK, 0xFFFF);
 
        mutex_init(&wm8350->auxadc_mutex);
        mutex_init(&wm8350->irq_mutex);
@@ -1430,6 +1443,15 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
        }
        wm8350->chip_irq = irq;
 
+       if (pdata && pdata->init) {
+               ret = pdata->init(wm8350);
+               if (ret != 0) {
+                       dev_err(wm8350->dev, "Platform init() failed: %d\n",
+                               ret);
+                       goto err;
+               }
+       }
+
        wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0x0);
 
        wm8350_client_dev_register(wm8350, "wm8350-codec",
index 68887b817d17e071a834fbbd71c4a86c44fc2796..9a4cc954cb7c72fcbfd4ef18e363e05795dab287 100644 (file)
@@ -3188,7 +3188,7 @@ const struct wm8350_reg_access wm8350_reg_io_map[] = {
        { 0x7CFF, 0x0C00, 0x7FFF }, /* R1   - ID */
        { 0x0000, 0x0000, 0x0000 }, /* R2 */
        { 0xBE3B, 0xBE3B, 0x8000 }, /* R3   - System Control 1 */
-       { 0xFCF7, 0xFCF7, 0xF800 }, /* R4   - System Control 2 */
+       { 0xFEF7, 0xFEF7, 0xF800 }, /* R4   - System Control 2 */
        { 0x80FF, 0x80FF, 0x8000 }, /* R5   - System Hibernate */
        { 0xFB0E, 0xFB0E, 0x0000 }, /* R6   - Interface Control */
        { 0x0000, 0x0000, 0x0000 }, /* R7 */
index 45b1f430685fca915aa12c7f28913fa4ed6a0733..513eb09a638f305d93f28aa2bdbfe967f70c32fc 100644 (file)
@@ -584,7 +584,7 @@ static int mmc_blk_probe(struct mmc_card *card)
        if (err)
                goto out;
 
-       string_get_size(get_capacity(md->disk) << 9, STRING_UNITS_2,
+       string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
                        cap_str, sizeof(cap_str));
        printk(KERN_INFO "%s: %s %s %s %s\n",
                md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
index b92b172074ee5a6f2b698a0292951b900dbd3008..b9f1e84897cc14fc2cbfa1e12adff95b4b93bb2e 100644 (file)
@@ -494,7 +494,7 @@ static int mmc_test_basic_read(struct mmc_test_card *test)
 
        sg_init_one(&sg, test->buffer, 512);
 
-       ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1);
+       ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 0);
        if (ret)
                return ret;
 
index 76bfe16c09b1e3e159a8016b479408a906c5bebd..2b1196e6142c1b951e47655d36ea185ac9466019 100644 (file)
@@ -1548,9 +1548,10 @@ static bool filter(struct dma_chan *chan, void *slave)
 {
        struct dw_dma_slave *dws = slave;
 
-       if (dws->dma_dev == chan->device->dev)
+       if (dws->dma_dev == chan->device->dev) {
+               chan->private = dws;
                return true;
-       else
+       else
                return false;
 }
 #endif
index db37490f67ec724d68732cd56054735d684a223e..a631c81dce1243bcb9bacefd26dcd3f0e439073d 100644 (file)
@@ -55,6 +55,7 @@
 #define VS30                   (1 << 25)
 #define SDVS18                 (0x5 << 9)
 #define SDVS30                 (0x6 << 9)
+#define SDVS33                 (0x7 << 9)
 #define SDVSCLR                        0xFFFFF1FF
 #define SDVSDET                        0x00000400
 #define AUTOIDLE               0x1
@@ -375,6 +376,32 @@ static void mmc_omap_report_irq(struct mmc_omap_host *host, u32 status)
 }
 #endif  /* CONFIG_MMC_DEBUG */
 
+/*
+ * MMC controller internal state machines reset
+ *
+ * Used to reset command or data internal state machines, using respectively
+ *  SRC or SRD bit of SYSCTL register
+ * Can be called from interrupt context
+ */
+static inline void mmc_omap_reset_controller_fsm(struct mmc_omap_host *host,
+               unsigned long bit)
+{
+       unsigned long i = 0;
+       unsigned long limit = (loops_per_jiffy *
+                               msecs_to_jiffies(MMC_TIMEOUT_MS));
+
+       OMAP_HSMMC_WRITE(host->base, SYSCTL,
+                        OMAP_HSMMC_READ(host->base, SYSCTL) | bit);
+
+       while ((OMAP_HSMMC_READ(host->base, SYSCTL) & bit) &&
+               (i++ < limit))
+               cpu_relax();
+
+       if (OMAP_HSMMC_READ(host->base, SYSCTL) & bit)
+               dev_err(mmc_dev(host->mmc),
+                       "Timeout waiting on controller reset in %s\n",
+                       __func__);
+}
 
 /*
  * MMC controller IRQ handler
@@ -403,21 +430,17 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                        (status & CMD_CRC)) {
                        if (host->cmd) {
                                if (status & CMD_TIMEOUT) {
-                                       OMAP_HSMMC_WRITE(host->base, SYSCTL,
-                                               OMAP_HSMMC_READ(host->base,
-                                                               SYSCTL) | SRC);
-                                       while (OMAP_HSMMC_READ(host->base,
-                                                       SYSCTL) & SRC)
-                                               ;
-
+                                       mmc_omap_reset_controller_fsm(host, SRC);
                                        host->cmd->error = -ETIMEDOUT;
                                } else {
                                        host->cmd->error = -EILSEQ;
                                }
                                end_cmd = 1;
                        }
-                       if (host->data)
+                       if (host->data) {
                                mmc_dma_cleanup(host);
+                               mmc_omap_reset_controller_fsm(host, SRD);
+                       }
                }
                if ((status & DATA_TIMEOUT) ||
                        (status & DATA_CRC)) {
@@ -426,12 +449,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                                        mmc_dma_cleanup(host);
                                else
                                        host->data->error = -EILSEQ;
-                               OMAP_HSMMC_WRITE(host->base, SYSCTL,
-                                       OMAP_HSMMC_READ(host->base,
-                                                       SYSCTL) | SRD);
-                               while (OMAP_HSMMC_READ(host->base,
-                                               SYSCTL) & SRD)
-                                       ;
+                               mmc_omap_reset_controller_fsm(host, SRD);
                                end_trans = 1;
                        }
                }
@@ -456,13 +474,20 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 }
 
 /*
- * Switch MMC operating voltage
+ * Switch MMC interface voltage ... only relevant for MMC1.
+ *
+ * MMC2 and MMC3 use fixed 1.8V levels, and maybe a transceiver.
+ * The MMC2 transceiver controls are used instead of DAT4..DAT7.
+ * Some chips, like eMMC ones, use internal transceivers.
  */
 static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
 {
        u32 reg_val = 0;
        int ret;
 
+       if (host->id != OMAP_MMC1_DEVID)
+               return 0;
+
        /* Disable the clocks */
        clk_disable(host->fclk);
        clk_disable(host->iclk);
@@ -485,19 +510,26 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
        OMAP_HSMMC_WRITE(host->base, HCTL,
                OMAP_HSMMC_READ(host->base, HCTL) & SDVSCLR);
        reg_val = OMAP_HSMMC_READ(host->base, HCTL);
+
        /*
         * If a MMC dual voltage card is detected, the set_ios fn calls
         * this fn with VDD bit set for 1.8V. Upon card removal from the
         * slot, omap_mmc_set_ios sets the VDD back to 3V on MMC_POWER_OFF.
         *
-        * Only MMC1 supports 3.0V.  MMC2 will not function if SDVS30 is
-        * set in HCTL.
+        * Cope with a bit of slop in the range ... per data sheets:
+        *  - "1.8V" for vdds_mmc1/vdds_mmc1a can be up to 2.45V max,
+        *    but recommended values are 1.71V to 1.89V
+        *  - "3.0V" for vdds_mmc1/vdds_mmc1a can be up to 3.5V max,
+        *    but recommended values are 2.7V to 3.3V
+        *
+        * Board setup code shouldn't permit anything very out-of-range.
+        * TWL4030-family VMMC1 and VSIM regulators are fine (avoiding the
+        * middle range) but VSIM can't power DAT4..DAT7 at more than 3V.
         */
-       if (host->id == OMAP_MMC1_DEVID && (((1 << vdd) == MMC_VDD_32_33) ||
-                               ((1 << vdd) == MMC_VDD_33_34)))
-               reg_val |= SDVS30;
-       if ((1 << vdd) == MMC_VDD_165_195)
+       if ((1 << vdd) <= MMC_VDD_23_24)
                reg_val |= SDVS18;
+       else
+               reg_val |= SDVS30;
 
        OMAP_HSMMC_WRITE(host->base, HCTL, reg_val);
 
@@ -517,16 +549,15 @@ static void mmc_omap_detect(struct work_struct *work)
 {
        struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
                                                mmc_carddetect_work);
+       struct omap_mmc_slot_data *slot = &mmc_slot(host);
+
+       host->carddetect = slot->card_detect(slot->card_detect_irq);
 
        sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
        if (host->carddetect) {
                mmc_detect_change(host->mmc, (HZ * 200) / 1000);
        } else {
-               OMAP_HSMMC_WRITE(host->base, SYSCTL,
-                       OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
-               while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
-                       ;
-
+               mmc_omap_reset_controller_fsm(host, SRD);
                mmc_detect_change(host->mmc, (HZ * 50) / 1000);
        }
 }
@@ -538,7 +569,6 @@ static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id)
 {
        struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id;
 
-       host->carddetect = mmc_slot(host).card_detect(irq);
        schedule_work(&host->mmc_carddetect_work);
 
        return IRQ_HANDLED;
@@ -757,10 +787,14 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        case MMC_POWER_OFF:
                mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
                /*
-                * Reset bus voltage to 3V if it got set to 1.8V earlier.
+                * Reset interface voltage to 3V if it's 1.8V now;
+                * only relevant on MMC-1, the others always use 1.8V.
+                *
                 * REVISIT: If we are able to detect cards after unplugging
                 * a 1.8V card, this code should not be needed.
                 */
+               if (host->id != OMAP_MMC1_DEVID)
+                       break;
                if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
                        int vdd = fls(host->mmc->ocr_avail) - 1;
                        if (omap_mmc_switch_opcond(host, vdd) != 0)
@@ -784,7 +818,9 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        }
 
        if (host->id == OMAP_MMC1_DEVID) {
-               /* Only MMC1 can operate at 3V/1.8V */
+               /* Only MMC1 can interface at 3V without some flavor
+                * of external transceiver; but they all handle 1.8V.
+                */
                if ((OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET) &&
                        (ios->vdd == DUAL_VOLT_OCR_BIT)) {
                                /*
@@ -1137,7 +1173,9 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
                                                " level suspend\n");
                        }
 
-                       if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
+                       if (host->id == OMAP_MMC1_DEVID
+                                       && !(OMAP_HSMMC_READ(host->base, HCTL)
+                                                       & SDVSDET)) {
                                OMAP_HSMMC_WRITE(host->base, HCTL,
                                        OMAP_HSMMC_READ(host->base, HCTL)
                                        & SDVSCLR);
index 35a98eec74149a916c1baf735bff1b6ceff0baa4..f4a67c65d301b4d5aacc52ac85c8e452d6c63fd7 100644 (file)
@@ -329,7 +329,7 @@ static void do_pio_write(struct s3cmci_host *host)
 
        to_ptr = host->base + host->sdidata;
 
-       while ((fifo = fifo_free(host))) {
+       while ((fifo = fifo_free(host)) > 3) {
                if (!host->pio_bytes) {
                        res = get_data_buffer(host, &host->pio_bytes,
                                                        &host->pio_ptr);
index f07255cb17ee7a9d50dd3beacecd9157f523f1f0..8cff5f5e7f86dfa6f743317910afb028db7ca2df 100644 (file)
@@ -144,8 +144,7 @@ static int jmicron_probe(struct sdhci_pci_chip *chip)
                          SDHCI_QUIRK_32BIT_DMA_SIZE |
                          SDHCI_QUIRK_32BIT_ADMA_SIZE |
                          SDHCI_QUIRK_RESET_AFTER_REQUEST |
-                         SDHCI_QUIRK_BROKEN_SMALL_PIO |
-                         SDHCI_QUIRK_FORCE_HIGHSPEED;
+                         SDHCI_QUIRK_BROKEN_SMALL_PIO;
        }
 
        /*
index 6b2d1f99af6728d9cd12d42ebe2c71e0adaf08fe..f52f3053ed9251a9d3c3b795997e0f6dbd3ffbf5 100644 (file)
@@ -1636,8 +1636,7 @@ int sdhci_add_host(struct sdhci_host *host)
        mmc->f_max = host->max_clk;
        mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
 
-       if ((caps & SDHCI_CAN_DO_HISPD) ||
-               (host->quirks & SDHCI_QUIRK_FORCE_HIGHSPEED))
+       if (caps & SDHCI_CAN_DO_HISPD)
                mmc->caps |= MMC_CAP_SD_HIGHSPEED;
 
        mmc->ocr_avail = 0;
@@ -1723,7 +1722,9 @@ int sdhci_add_host(struct sdhci_host *host)
 #endif
 
 #ifdef SDHCI_USE_LEDS_CLASS
-       host->led.name = mmc_hostname(mmc);
+       snprintf(host->led_name, sizeof(host->led_name),
+               "%s::", mmc_hostname(mmc));
+       host->led.name = host->led_name;
        host->led.brightness = LED_OFF;
        host->led.default_trigger = mmc_hostname(mmc);
        host->led.brightness_set = sdhci_led_control;
index 3efba236394164b195674905d4e978856494b477..ebb83657e27ab2b1257ab8ef54a3cb6de18d5abf 100644 (file)
@@ -208,8 +208,6 @@ struct sdhci_host {
 #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL                 (1<<12)
 /* Controller has an issue with buffer bits for small transfers */
 #define SDHCI_QUIRK_BROKEN_SMALL_PIO                   (1<<13)
-/* Controller supports high speed but doesn't have the caps bit set */
-#define SDHCI_QUIRK_FORCE_HIGHSPEED                    (1<<14)
 
        int                     irq;            /* Device IRQ */
        void __iomem *          ioaddr;         /* Mapped address */
@@ -222,6 +220,7 @@ struct sdhci_host {
 
 #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
        struct led_classdev     led;            /* LED control */
+       char   led_name[32];
 #endif
 
        spinlock_t              lock;           /* Mutex */
index c98c1570a40b1ef5f3f3931ab4e0512be0341406..47a33cec3793d4b3f1a8b512e3fcf95d5ca83aba 100644 (file)
@@ -139,7 +139,8 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
        struct nand_chip *nand_chip = mtd->priv;
        struct atmel_nand_host *host = nand_chip->priv;
 
-       return gpio_get_value(host->board->rdy_pin);
+       return gpio_get_value(host->board->rdy_pin) ^
+                !!host->board->rdy_pin_active_low;
 }
 
 /*
index 6bdfd47d679d9425d777ac68cc7b6b22d13e46f0..a2f185fd70725eb84c1e239afe7831c7a3ba828b 100644 (file)
@@ -2342,6 +2342,17 @@ config ATL1E
          To compile this driver as a module, choose M here.  The module
          will be called atl1e.
 
+config ATL1C
+       tristate "Atheros L1C Gigabit Ethernet support (EXPERIMENTAL)"
+       depends on PCI && EXPERIMENTAL
+       select CRC32
+       select MII
+       help
+         This driver supports the Atheros L1C gigabit ethernet adapter.
+
+         To compile this driver as a module, choose M here.  The module
+         will be called atl1c.
+
 config JME
        tristate "JMicron(R) PCI-Express Gigabit Ethernet support"
        depends on PCI
index a3c5c002f224343ad30343b0ffc485b358075c77..aca8492db65453fed3bae5a106497d597fb7c0c6 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_BONDING) += bonding/
 obj-$(CONFIG_ATL1) += atlx/
 obj-$(CONFIG_ATL2) += atlx/
 obj-$(CONFIG_ATL1E) += atl1e/
+obj-$(CONFIG_ATL1C) += atl1c/
 obj-$(CONFIG_GIANFAR) += gianfar_driver.o
 obj-$(CONFIG_TEHUTI) += tehuti.o
 obj-$(CONFIG_ENIC) += enic/
diff --git a/drivers/net/atl1c/Makefile b/drivers/net/atl1c/Makefile
new file mode 100644 (file)
index 0000000..c37d966
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ATL1C) += atl1c.o
+atl1c-objs := atl1c_main.o atl1c_hw.o atl1c_ethtool.o
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h
new file mode 100644 (file)
index 0000000..ac11b84
--- /dev/null
@@ -0,0 +1,606 @@
+/*
+ * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _ATL1C_H_
+#define _ATL1C_H_
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
+#include <linux/mii.h>
+#include <linux/io.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+#include <linux/tcp.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/workqueue.h>
+#include <net/checksum.h>
+#include <net/ip6_checksum.h>
+
+#include "atl1c_hw.h"
+
+/* Wake Up Filter Control */
+#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+#define AT_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */
+#define AT_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */
+#define AT_WUFC_MC   0x00000008 /* Multicast Wakeup Enable */
+#define AT_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
+
+#define AT_VLAN_TO_TAG(_vlan, _tag)       \
+       _tag =  ((((_vlan) >> 8) & 0xFF)  |\
+                (((_vlan) & 0xFF) << 8))
+
+#define AT_TAG_TO_VLAN(_tag, _vlan)     \
+       _vlan = ((((_tag) >> 8) & 0xFF) |\
+               (((_tag) & 0xFF) << 8))
+
+#define SPEED_0                   0xffff
+#define HALF_DUPLEX        1
+#define FULL_DUPLEX        2
+
+#define AT_RX_BUF_SIZE         (ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN)
+#define MAX_JUMBO_FRAME_SIZE   (9*1024)
+#define MAX_TX_OFFLOAD_THRESH  (9*1024)
+
+#define AT_MAX_RECEIVE_QUEUE    4
+#define AT_DEF_RECEIVE_QUEUE   1
+#define AT_MAX_TRANSMIT_QUEUE  2
+
+#define AT_DMA_HI_ADDR_MASK     0xffffffff00000000ULL
+#define AT_DMA_LO_ADDR_MASK     0x00000000ffffffffULL
+
+#define AT_TX_WATCHDOG  (5 * HZ)
+#define AT_MAX_INT_WORK                5
+#define AT_TWSI_EEPROM_TIMEOUT         100
+#define AT_HW_MAX_IDLE_DELAY   10
+#define AT_SUSPEND_LINK_TIMEOUT 28
+
+#define AT_ASPM_L0S_TIMER      6
+#define AT_ASPM_L1_TIMER       12
+
+#define ATL1C_PCIE_L0S_L1_DISABLE      0x01
+#define ATL1C_PCIE_PHY_RESET           0x02
+
+#define ATL1C_ASPM_L0s_ENABLE          0x0001
+#define ATL1C_ASPM_L1_ENABLE           0x0002
+
+#define AT_REGS_LEN    (75 * sizeof(u32))
+#define AT_EEPROM_LEN  512
+
+#define ATL1C_GET_DESC(R, i, type)     (&(((type *)((R)->desc))[i]))
+#define ATL1C_RFD_DESC(R, i)   ATL1C_GET_DESC(R, i, struct atl1c_rx_free_desc)
+#define ATL1C_TPD_DESC(R, i)   ATL1C_GET_DESC(R, i, struct atl1c_tpd_desc)
+#define ATL1C_RRD_DESC(R, i)   ATL1C_GET_DESC(R, i, struct atl1c_recv_ret_status)
+
+/* tpd word 1 bit 0:7 General Checksum task offload */
+#define TPD_L4HDR_OFFSET_MASK  0x00FF
+#define TPD_L4HDR_OFFSET_SHIFT 0
+
+/* tpd word 1 bit 0:7 Large Send task offload (IPv4/IPV6) */
+#define TPD_TCPHDR_OFFSET_MASK 0x00FF
+#define TPD_TCPHDR_OFFSET_SHIFT        0
+
+/* tpd word 1 bit 0:7 Custom Checksum task offload */
+#define TPD_PLOADOFFSET_MASK   0x00FF
+#define TPD_PLOADOFFSET_SHIFT  0
+
+/* tpd word 1 bit 8:17 */
+#define TPD_CCSUM_EN_MASK      0x0001
+#define TPD_CCSUM_EN_SHIFT     8
+#define TPD_IP_CSUM_MASK       0x0001
+#define TPD_IP_CSUM_SHIFT      9
+#define TPD_TCP_CSUM_MASK      0x0001
+#define TPD_TCP_CSUM_SHIFT     10
+#define TPD_UDP_CSUM_MASK      0x0001
+#define TPD_UDP_CSUM_SHIFT     11
+#define TPD_LSO_EN_MASK                0x0001  /* TCP Large Send Offload */
+#define TPD_LSO_EN_SHIFT       12
+#define TPD_LSO_VER_MASK       0x0001
+#define TPD_LSO_VER_SHIFT      13      /* 0 : ipv4; 1 : ipv4/ipv6 */
+#define TPD_CON_VTAG_MASK      0x0001
+#define TPD_CON_VTAG_SHIFT     14
+#define TPD_INS_VTAG_MASK      0x0001
+#define TPD_INS_VTAG_SHIFT     15
+#define TPD_IPV4_PACKET_MASK   0x0001  /* valid when LSO VER  is 1 */
+#define TPD_IPV4_PACKET_SHIFT  16
+#define TPD_ETH_TYPE_MASK      0x0001
+#define TPD_ETH_TYPE_SHIFT     17      /* 0 : 802.3 frame; 1 : Ethernet */
+
+/* tpd word 18:25 Custom Checksum task offload */
+#define TPD_CCSUM_OFFSET_MASK  0x00FF
+#define TPD_CCSUM_OFFSET_SHIFT 18
+#define TPD_CCSUM_EPAD_MASK    0x0001
+#define TPD_CCSUM_EPAD_SHIFT   30
+
+/* tpd word 18:30 Large Send task offload (IPv4/IPV6) */
+#define TPD_MSS_MASK            0x1FFF
+#define TPD_MSS_SHIFT          18
+
+#define TPD_EOP_MASK           0x0001
+#define TPD_EOP_SHIFT          31
+
+struct atl1c_tpd_desc {
+       __le16  buffer_len; /* include 4-byte CRC */
+       __le16  vlan_tag;
+       __le32  word1;
+       __le64  buffer_addr;
+};
+
+struct atl1c_tpd_ext_desc {
+       u32 reservd_0;
+       __le32 word1;
+       __le32 pkt_len;
+       u32 reservd_1;
+};
+/* rrs word 0 bit 0:31 */
+#define RRS_RX_CSUM_MASK       0xFFFF
+#define RRS_RX_CSUM_SHIFT      0
+#define RRS_RX_RFD_CNT_MASK    0x000F
+#define RRS_RX_RFD_CNT_SHIFT   16
+#define RRS_RX_RFD_INDEX_MASK  0x0FFF
+#define RRS_RX_RFD_INDEX_SHIFT 20
+
+/* rrs flag bit 0:16 */
+#define RRS_HEAD_LEN_MASK      0x00FF
+#define RRS_HEAD_LEN_SHIFT     0
+#define RRS_HDS_TYPE_MASK      0x0003
+#define RRS_HDS_TYPE_SHIFT     8
+#define RRS_CPU_NUM_MASK       0x0003
+#define        RRS_CPU_NUM_SHIFT       10
+#define RRS_HASH_FLG_MASK      0x000F
+#define RRS_HASH_FLG_SHIFT     12
+
+#define RRS_HDS_TYPE_HEAD      1
+#define RRS_HDS_TYPE_DATA      2
+
+#define RRS_IS_NO_HDS_TYPE(flag) \
+       (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == 0)
+
+#define RRS_IS_HDS_HEAD(flag) \
+       (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \
+                       RRS_HDS_TYPE_HEAD)
+
+#define RRS_IS_HDS_DATA(flag) \
+       (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \
+                       RRS_HDS_TYPE_DATA)
+
+/* rrs word 3 bit 0:31 */
+#define RRS_PKT_SIZE_MASK      0x3FFF
+#define RRS_PKT_SIZE_SHIFT     0
+#define RRS_ERR_L4_CSUM_MASK   0x0001
+#define RRS_ERR_L4_CSUM_SHIFT  14
+#define RRS_ERR_IP_CSUM_MASK   0x0001
+#define RRS_ERR_IP_CSUM_SHIFT  15
+#define RRS_VLAN_INS_MASK      0x0001
+#define RRS_VLAN_INS_SHIFT     16
+#define RRS_PROT_ID_MASK       0x0007
+#define RRS_PROT_ID_SHIFT      17
+#define RRS_RX_ERR_SUM_MASK    0x0001
+#define RRS_RX_ERR_SUM_SHIFT   20
+#define RRS_RX_ERR_CRC_MASK    0x0001
+#define RRS_RX_ERR_CRC_SHIFT   21
+#define RRS_RX_ERR_FAE_MASK    0x0001
+#define RRS_RX_ERR_FAE_SHIFT   22
+#define RRS_RX_ERR_TRUNC_MASK  0x0001
+#define RRS_RX_ERR_TRUNC_SHIFT 23
+#define RRS_RX_ERR_RUNC_MASK   0x0001
+#define RRS_RX_ERR_RUNC_SHIFT  24
+#define RRS_RX_ERR_ICMP_MASK   0x0001
+#define RRS_RX_ERR_ICMP_SHIFT  25
+#define RRS_PACKET_BCAST_MASK  0x0001
+#define RRS_PACKET_BCAST_SHIFT 26
+#define RRS_PACKET_MCAST_MASK  0x0001
+#define RRS_PACKET_MCAST_SHIFT 27
+#define RRS_PACKET_TYPE_MASK   0x0001
+#define RRS_PACKET_TYPE_SHIFT  28
+#define RRS_FIFO_FULL_MASK     0x0001
+#define RRS_FIFO_FULL_SHIFT    29
+#define RRS_802_3_LEN_ERR_MASK         0x0001
+#define RRS_802_3_LEN_ERR_SHIFT 30
+#define RRS_RXD_UPDATED_MASK   0x0001
+#define RRS_RXD_UPDATED_SHIFT  31
+
+#define RRS_ERR_L4_CSUM         0x00004000
+#define RRS_ERR_IP_CSUM         0x00008000
+#define RRS_VLAN_INS            0x00010000
+#define RRS_RX_ERR_SUM          0x00100000
+#define RRS_RX_ERR_CRC          0x00200000
+#define RRS_802_3_LEN_ERR      0x40000000
+#define RRS_RXD_UPDATED                0x80000000
+
+#define RRS_PACKET_TYPE_802_3          1
+#define RRS_PACKET_TYPE_ETH    0
+#define RRS_PACKET_IS_ETH(word) \
+       (((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK == \
+                       RRS_PACKET_TYPE_ETH)
+#define RRS_RXD_IS_VALID(word) \
+       ((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1)
+
+#define RRS_PACKET_PROT_IS_IPV4_ONLY(word) \
+       ((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 1)
+#define RRS_PACKET_PROT_IS_IPV6_ONLY(word) \
+       ((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 6)
+
+struct atl1c_recv_ret_status {
+       __le32  word0;
+       __le32  rss_hash;
+       __le16  vlan_tag;
+       __le16  flag;
+       __le32  word3;
+};
+
+/* RFD desciptor */
+struct atl1c_rx_free_desc {
+       __le64  buffer_addr;
+};
+
+/* DMA Order Settings */
+enum atl1c_dma_order {
+       atl1c_dma_ord_in = 1,
+       atl1c_dma_ord_enh = 2,
+       atl1c_dma_ord_out = 4
+};
+
+enum atl1c_dma_rcb {
+       atl1c_rcb_64 = 0,
+       atl1c_rcb_128 = 1
+};
+
+enum atl1c_mac_speed {
+       atl1c_mac_speed_0 = 0,
+       atl1c_mac_speed_10_100 = 1,
+       atl1c_mac_speed_1000 = 2
+};
+
+enum atl1c_dma_req_block {
+       atl1c_dma_req_128 = 0,
+       atl1c_dma_req_256 = 1,
+       atl1c_dma_req_512 = 2,
+       atl1c_dma_req_1024 = 3,
+       atl1c_dma_req_2048 = 4,
+       atl1c_dma_req_4096 = 5
+};
+
+enum atl1c_rss_mode {
+       atl1c_rss_mode_disable = 0,
+       atl1c_rss_sig_que = 1,
+       atl1c_rss_mul_que_sig_int = 2,
+       atl1c_rss_mul_que_mul_int = 4,
+};
+
+enum atl1c_rss_type {
+       atl1c_rss_disable = 0,
+       atl1c_rss_ipv4 = 1,
+       atl1c_rss_ipv4_tcp = 2,
+       atl1c_rss_ipv6 = 4,
+       atl1c_rss_ipv6_tcp = 8
+};
+
+enum atl1c_nic_type {
+       athr_l1c = 0,
+       athr_l2c = 1,
+};
+
+enum atl1c_trans_queue {
+       atl1c_trans_normal = 0,
+       atl1c_trans_high = 1
+};
+
+struct atl1c_hw_stats {
+       /* rx */
+       unsigned long rx_ok;            /* The number of good packet received. */
+       unsigned long rx_bcast;         /* The number of good broadcast packet received. */
+       unsigned long rx_mcast;         /* The number of good multicast packet received. */
+       unsigned long rx_pause;         /* The number of Pause packet received. */
+       unsigned long rx_ctrl;          /* The number of Control packet received other than Pause frame. */
+       unsigned long rx_fcs_err;       /* The number of packets with bad FCS. */
+       unsigned long rx_len_err;       /* The number of packets with mismatch of length field and actual size. */
+       unsigned long rx_byte_cnt;      /* The number of bytes of good packet received. FCS is NOT included. */
+       unsigned long rx_runt;          /* The number of packets received that are less than 64 byte long and with good FCS. */
+       unsigned long rx_frag;          /* The number of packets received that are less than 64 byte long and with bad FCS. */
+       unsigned long rx_sz_64;         /* The number of good and bad packets received that are 64 byte long. */
+       unsigned long rx_sz_65_127;     /* The number of good and bad packets received that are between 65 and 127-byte long. */
+       unsigned long rx_sz_128_255;    /* The number of good and bad packets received that are between 128 and 255-byte long. */
+       unsigned long rx_sz_256_511;    /* The number of good and bad packets received that are between 256 and 511-byte long. */
+       unsigned long rx_sz_512_1023;   /* The number of good and bad packets received that are between 512 and 1023-byte long. */
+       unsigned long rx_sz_1024_1518;  /* The number of good and bad packets received that are between 1024 and 1518-byte long. */
+       unsigned long rx_sz_1519_max;   /* The number of good and bad packets received that are between 1519-byte and MTU. */
+       unsigned long rx_sz_ov;         /* The number of good and bad packets received that are more than MTU size truncated by Selene. */
+       unsigned long rx_rxf_ov;        /* The number of frame dropped due to occurrence of RX FIFO overflow. */
+       unsigned long rx_rrd_ov;        /* The number of frame dropped due to occurrence of RRD overflow. */
+       unsigned long rx_align_err;     /* Alignment Error */
+       unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */
+       unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */
+       unsigned long rx_err_addr;      /* The number of packets dropped due to address filtering. */
+
+       /* tx */
+       unsigned long tx_ok;            /* The number of good packet transmitted. */
+       unsigned long tx_bcast;         /* The number of good broadcast packet transmitted. */
+       unsigned long tx_mcast;         /* The number of good multicast packet transmitted. */
+       unsigned long tx_pause;         /* The number of Pause packet transmitted. */
+       unsigned long tx_exc_defer;     /* The number of packets transmitted with excessive deferral. */
+       unsigned long tx_ctrl;          /* The number of packets transmitted is a control frame, excluding Pause frame. */
+       unsigned long tx_defer;         /* The number of packets transmitted that is deferred. */
+       unsigned long tx_byte_cnt;      /* The number of bytes of data transmitted. FCS is NOT included. */
+       unsigned long tx_sz_64;         /* The number of good and bad packets transmitted that are 64 byte long. */
+       unsigned long tx_sz_65_127;     /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
+       unsigned long tx_sz_128_255;    /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
+       unsigned long tx_sz_256_511;    /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
+       unsigned long tx_sz_512_1023;   /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
+       unsigned long tx_sz_1024_1518;  /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
+       unsigned long tx_sz_1519_max;   /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
+       unsigned long tx_1_col;         /* The number of packets subsequently transmitted successfully with a single prior collision. */
+       unsigned long tx_2_col;         /* The number of packets subsequently transmitted successfully with multiple prior collisions. */
+       unsigned long tx_late_col;      /* The number of packets transmitted with late collisions. */
+       unsigned long tx_abort_col;     /* The number of transmit packets aborted due to excessive collisions. */
+       unsigned long tx_underrun;      /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
+       unsigned long tx_rd_eop;        /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
+       unsigned long tx_len_err;       /* The number of transmit packets with length field does NOT match the actual frame size. */
+       unsigned long tx_trunc;         /* The number of transmit packets truncated due to size exceeding MTU. */
+       unsigned long tx_bcast_byte;    /* The byte count of broadcast packet transmitted, excluding FCS. */
+       unsigned long tx_mcast_byte;    /* The byte count of multicast packet transmitted, excluding FCS. */
+};
+
+struct atl1c_hw {
+       u8 __iomem      *hw_addr;            /* inner register address */
+       struct atl1c_adapter *adapter;
+       enum atl1c_nic_type  nic_type;
+       enum atl1c_dma_order dma_order;
+       enum atl1c_dma_rcb   rcb_value;
+       enum atl1c_dma_req_block dmar_block;
+       enum atl1c_dma_req_block dmaw_block;
+
+       u16 device_id;
+       u16 vendor_id;
+       u16 subsystem_id;
+       u16 subsystem_vendor_id;
+       u8 revision_id;
+
+       u32 intr_mask;
+       u8 dmaw_dly_cnt;
+       u8 dmar_dly_cnt;
+
+       u8 preamble_len;
+       u16 max_frame_size;
+       u16 min_frame_size;
+
+       enum atl1c_mac_speed mac_speed;
+       bool mac_duplex;
+       bool hibernate;
+       u16 media_type;
+#define MEDIA_TYPE_AUTO_SENSOR  0
+#define MEDIA_TYPE_100M_FULL    1
+#define MEDIA_TYPE_100M_HALF    2
+#define MEDIA_TYPE_10M_FULL     3
+#define MEDIA_TYPE_10M_HALF     4
+
+       u16 autoneg_advertised;
+       u16 mii_autoneg_adv_reg;
+       u16 mii_1000t_ctrl_reg;
+
+       u16 tx_imt;     /* TX Interrupt Moderator timer ( 2us resolution) */
+       u16 rx_imt;     /* RX Interrupt Moderator timer ( 2us resolution) */
+       u16 ict;        /* Interrupt Clear timer (2us resolution) */
+       u16 ctrl_flags;
+#define ATL1C_INTR_CLEAR_ON_READ       0x0001
+#define ATL1C_INTR_MODRT_ENABLE                0x0002
+#define ATL1C_CMB_ENABLE               0x0004
+#define ATL1C_SMB_ENABLE               0x0010
+#define ATL1C_TXQ_MODE_ENHANCE         0x0020
+#define ATL1C_RX_IPV6_CHKSUM           0x0040
+#define ATL1C_ASPM_L0S_SUPPORT         0x0080
+#define ATL1C_ASPM_L1_SUPPORT          0x0100
+#define ATL1C_ASPM_CTRL_MON            0x0200
+#define ATL1C_HIB_DISABLE              0x0400
+#define ATL1C_LINK_CAP_1000M           0x0800
+#define ATL1C_FPGA_VERSION             0x8000
+       u16 cmb_tpd;
+       u16 cmb_rrd;
+       u16 cmb_rx_timer; /* 2us resolution */
+       u16 cmb_tx_timer;
+       u32 smb_timer;
+
+       u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
+                         interrupt request */
+       u16 tpd_thresh;
+       u8 tpd_burst;   /* Number of TPD to prefetch in cache-aligned burst. */
+       u8 rfd_burst;
+       enum atl1c_rss_type rss_type;
+       enum atl1c_rss_mode rss_mode;
+       u8 rss_hash_bits;
+       u32 base_cpu;
+       u32 indirect_tab;
+       u8 mac_addr[ETH_ALEN];
+       u8 perm_mac_addr[ETH_ALEN];
+
+       bool phy_configured;
+       bool re_autoneg;
+       bool emi_ca;
+};
+
+/*
+ * atl1c_ring_header represents a single, contiguous block of DMA space
+ * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
+ * message blocks (cmb, smb) described below
+ */
+struct atl1c_ring_header {
+       void *desc;             /* virtual address */
+       dma_addr_t dma;         /* physical address*/
+       unsigned int size;      /* length in bytes */
+};
+
+/*
+ * atl1c_buffer is wrapper around a pointer to a socket buffer
+ * so a DMA handle can be stored along with the skb
+ */
+struct atl1c_buffer {
+       struct sk_buff *skb;    /* socket buffer */
+       u16 length;             /* rx buffer length */
+       u16 state;              /* state of buffer */
+#define ATL1_BUFFER_FREE       0
+#define ATL1_BUFFER_BUSY       1
+       dma_addr_t dma;
+};
+
+/* transimit packet descriptor (tpd) ring */
+struct atl1c_tpd_ring {
+       void *desc;             /* descriptor ring virtual address */
+       dma_addr_t dma;         /* descriptor ring physical address */
+       u16 size;               /* descriptor ring length in bytes */
+       u16 count;              /* number of descriptors in the ring */
+       u16 next_to_use;        /* this is protectd by adapter->tx_lock */
+       atomic_t next_to_clean;
+       struct atl1c_buffer *buffer_info;
+};
+
+/* receive free descriptor (rfd) ring */
+struct atl1c_rfd_ring {
+       void *desc;             /* descriptor ring virtual address */
+       dma_addr_t dma;         /* descriptor ring physical address */
+       u16 size;               /* descriptor ring length in bytes */
+       u16 count;              /* number of descriptors in the ring */
+       u16 next_to_use;
+       u16 next_to_clean;
+       struct atl1c_buffer *buffer_info;
+};
+
+/* receive return desciptor (rrd) ring */
+struct atl1c_rrd_ring {
+       void *desc;             /* descriptor ring virtual address */
+       dma_addr_t dma;         /* descriptor ring physical address */
+       u16 size;               /* descriptor ring length in bytes */
+       u16 count;              /* number of descriptors in the ring */
+       u16 next_to_use;
+       u16 next_to_clean;
+};
+
+struct atl1c_cmb {
+       void *cmb;
+       dma_addr_t dma;
+};
+
+struct atl1c_smb {
+       void *smb;
+       dma_addr_t dma;
+};
+
+/* board specific private data structure */
+struct atl1c_adapter {
+       struct net_device   *netdev;
+       struct pci_dev      *pdev;
+       struct vlan_group   *vlgrp;
+       struct napi_struct  napi;
+       struct atl1c_hw        hw;
+       struct atl1c_hw_stats  hw_stats;
+       struct net_device_stats net_stats;
+       struct mii_if_info  mii;    /* MII interface info */
+       u16 rx_buffer_len;
+
+       unsigned long flags;
+#define __AT_TESTING        0x0001
+#define __AT_RESETTING      0x0002
+#define __AT_DOWN           0x0003
+       u32 msg_enable;
+
+       bool have_msi;
+       u32 wol;
+       u16 link_speed;
+       u16 link_duplex;
+
+       spinlock_t mdio_lock;
+       spinlock_t tx_lock;
+       atomic_t irq_sem;
+
+       struct work_struct reset_task;
+       struct work_struct link_chg_task;
+       struct timer_list watchdog_timer;
+       struct timer_list phy_config_timer;
+
+       /* All Descriptor memory */
+       struct atl1c_ring_header ring_header;
+       struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE];
+       struct atl1c_rfd_ring rfd_ring[AT_MAX_RECEIVE_QUEUE];
+       struct atl1c_rrd_ring rrd_ring[AT_MAX_RECEIVE_QUEUE];
+       struct atl1c_cmb cmb;
+       struct atl1c_smb smb;
+       int num_rx_queues;
+       u32 bd_number;     /* board number;*/
+};
+
+#define AT_WRITE_REG(a, reg, value) ( \
+               writel((value), ((a)->hw_addr + reg)))
+
+#define AT_WRITE_FLUSH(a) (\
+               readl((a)->hw_addr))
+
+#define AT_READ_REG(a, reg, pdata) do {                                        \
+               if (unlikely((a)->hibernate)) {                         \
+                       readl((a)->hw_addr + reg);                      \
+                       *(u32 *)pdata = readl((a)->hw_addr + reg);      \
+               } else {                                                \
+                       *(u32 *)pdata = readl((a)->hw_addr + reg);      \
+               }                                                       \
+       } while (0)
+
+#define AT_WRITE_REGB(a, reg, value) (\
+               writeb((value), ((a)->hw_addr + reg)))
+
+#define AT_READ_REGB(a, reg) (\
+               readb((a)->hw_addr + reg))
+
+#define AT_WRITE_REGW(a, reg, value) (\
+               writew((value), ((a)->hw_addr + reg)))
+
+#define AT_READ_REGW(a, reg) (\
+               readw((a)->hw_addr + reg))
+
+#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \
+               writel((value), (((a)->hw_addr + reg) + ((offset) << 2))))
+
+#define AT_READ_REG_ARRAY(a, reg, offset) ( \
+               readl(((a)->hw_addr + reg) + ((offset) << 2)))
+
+extern char atl1c_driver_name[];
+extern char atl1c_driver_version[];
+
+extern int atl1c_up(struct atl1c_adapter *adapter);
+extern void atl1c_down(struct atl1c_adapter *adapter);
+extern void atl1c_reinit_locked(struct atl1c_adapter *adapter);
+extern s32 atl1c_reset_hw(struct atl1c_hw *hw);
+extern void atl1c_set_ethtool_ops(struct net_device *netdev);
+#endif /* _ATL1C_H_ */
diff --git a/drivers/net/atl1c/atl1c_ethtool.c b/drivers/net/atl1c/atl1c_ethtool.c
new file mode 100644 (file)
index 0000000..45c5b73
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * Copyright(c) 2009 - 2009 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+
+#include "atl1c.h"
+
+static int atl1c_get_settings(struct net_device *netdev,
+                             struct ethtool_cmd *ecmd)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       struct atl1c_hw *hw = &adapter->hw;
+
+       ecmd->supported = (SUPPORTED_10baseT_Half  |
+                          SUPPORTED_10baseT_Full  |
+                          SUPPORTED_100baseT_Half |
+                          SUPPORTED_100baseT_Full |
+                          SUPPORTED_Autoneg       |
+                          SUPPORTED_TP);
+       if (hw->ctrl_flags & ATL1C_LINK_CAP_1000M)
+               ecmd->supported |= SUPPORTED_1000baseT_Full;
+
+       ecmd->advertising = ADVERTISED_TP;
+
+       ecmd->advertising |= hw->autoneg_advertised;
+
+       ecmd->port = PORT_TP;
+       ecmd->phy_address = 0;
+       ecmd->transceiver = XCVR_INTERNAL;
+
+       if (adapter->link_speed != SPEED_0) {
+               ecmd->speed = adapter->link_speed;
+               if (adapter->link_duplex == FULL_DUPLEX)
+                       ecmd->duplex = DUPLEX_FULL;
+               else
+                       ecmd->duplex = DUPLEX_HALF;
+       } else {
+               ecmd->speed = -1;
+               ecmd->duplex = -1;
+       }
+
+       ecmd->autoneg = AUTONEG_ENABLE;
+       return 0;
+}
+
+static int atl1c_set_settings(struct net_device *netdev,
+                             struct ethtool_cmd *ecmd)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       struct atl1c_hw *hw = &adapter->hw;
+       u16  autoneg_advertised;
+
+       while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+               msleep(1);
+
+       if (ecmd->autoneg == AUTONEG_ENABLE) {
+               autoneg_advertised = ADVERTISED_Autoneg;
+       } else {
+               if (ecmd->speed == SPEED_1000) {
+                       if (ecmd->duplex != DUPLEX_FULL) {
+                               if (netif_msg_link(adapter))
+                                       dev_warn(&adapter->pdev->dev,
+                                               "1000M half is invalid\n");
+                               clear_bit(__AT_RESETTING, &adapter->flags);
+                               return -EINVAL;
+                       }
+                       autoneg_advertised = ADVERTISED_1000baseT_Full;
+               } else if (ecmd->speed == SPEED_100) {
+                       if (ecmd->duplex == DUPLEX_FULL)
+                               autoneg_advertised = ADVERTISED_100baseT_Full;
+                       else
+                               autoneg_advertised = ADVERTISED_100baseT_Half;
+               } else {
+                       if (ecmd->duplex == DUPLEX_FULL)
+                               autoneg_advertised = ADVERTISED_10baseT_Full;
+                       else
+                               autoneg_advertised = ADVERTISED_10baseT_Half;
+               }
+       }
+
+       if (hw->autoneg_advertised != autoneg_advertised) {
+               hw->autoneg_advertised = autoneg_advertised;
+               if (atl1c_restart_autoneg(hw) != 0) {
+                       if (netif_msg_link(adapter))
+                               dev_warn(&adapter->pdev->dev,
+                                       "ethtool speed/duplex setting failed\n");
+                       clear_bit(__AT_RESETTING, &adapter->flags);
+                       return -EINVAL;
+               }
+       }
+       clear_bit(__AT_RESETTING, &adapter->flags);
+       return 0;
+}
+
+static u32 atl1c_get_tx_csum(struct net_device *netdev)
+{
+       return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+static u32 atl1c_get_msglevel(struct net_device *netdev)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       return adapter->msg_enable;
+}
+
+static void atl1c_set_msglevel(struct net_device *netdev, u32 data)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       adapter->msg_enable = data;
+}
+
+static int atl1c_get_regs_len(struct net_device *netdev)
+{
+       return AT_REGS_LEN;
+}
+
+static void atl1c_get_regs(struct net_device *netdev,
+                          struct ethtool_regs *regs, void *p)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       struct atl1c_hw *hw = &adapter->hw;
+       u32 *regs_buff = p;
+       u16 phy_data;
+
+       memset(p, 0, AT_REGS_LEN);
+
+       regs->version = 0;
+       AT_READ_REG(hw, REG_VPD_CAP,              p++);
+       AT_READ_REG(hw, REG_PM_CTRL,              p++);
+       AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL,  p++);
+       AT_READ_REG(hw, REG_TWSI_CTRL,            p++);
+       AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL,   p++);
+       AT_READ_REG(hw, REG_MASTER_CTRL,          p++);
+       AT_READ_REG(hw, REG_MANUAL_TIMER_INIT,    p++);
+       AT_READ_REG(hw, REG_IRQ_MODRT_TIMER_INIT, p++);
+       AT_READ_REG(hw, REG_GPHY_CTRL,            p++);
+       AT_READ_REG(hw, REG_LINK_CTRL,            p++);
+       AT_READ_REG(hw, REG_IDLE_STATUS,          p++);
+       AT_READ_REG(hw, REG_MDIO_CTRL,            p++);
+       AT_READ_REG(hw, REG_SERDES_LOCK,          p++);
+       AT_READ_REG(hw, REG_MAC_CTRL,             p++);
+       AT_READ_REG(hw, REG_MAC_IPG_IFG,          p++);
+       AT_READ_REG(hw, REG_MAC_STA_ADDR,         p++);
+       AT_READ_REG(hw, REG_MAC_STA_ADDR+4,       p++);
+       AT_READ_REG(hw, REG_RX_HASH_TABLE,        p++);
+       AT_READ_REG(hw, REG_RX_HASH_TABLE+4,      p++);
+       AT_READ_REG(hw, REG_RXQ_CTRL,             p++);
+       AT_READ_REG(hw, REG_TXQ_CTRL,             p++);
+       AT_READ_REG(hw, REG_MTU,                  p++);
+       AT_READ_REG(hw, REG_WOL_CTRL,             p++);
+
+       atl1c_read_phy_reg(hw, MII_BMCR, &phy_data);
+       regs_buff[73] = (u32) phy_data;
+       atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
+       regs_buff[74] = (u32) phy_data;
+}
+
+static int atl1c_get_eeprom_len(struct net_device *netdev)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+       if (atl1c_check_eeprom_exist(&adapter->hw))
+               return AT_EEPROM_LEN;
+       else
+               return 0;
+}
+
+static int atl1c_get_eeprom(struct net_device *netdev,
+               struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       struct atl1c_hw *hw = &adapter->hw;
+       u32 *eeprom_buff;
+       int first_dword, last_dword;
+       int ret_val = 0;
+       int i;
+
+       if (eeprom->len == 0)
+               return -EINVAL;
+
+       if (!atl1c_check_eeprom_exist(hw)) /* not exist */
+               return -EINVAL;
+
+       eeprom->magic = adapter->pdev->vendor |
+                       (adapter->pdev->device << 16);
+
+       first_dword = eeprom->offset >> 2;
+       last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
+
+       eeprom_buff = kmalloc(sizeof(u32) *
+                       (last_dword - first_dword + 1), GFP_KERNEL);
+       if (eeprom_buff == NULL)
+               return -ENOMEM;
+
+       for (i = first_dword; i < last_dword; i++) {
+               if (!atl1c_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) {
+                       kfree(eeprom_buff);
+                       return -EIO;
+               }
+       }
+
+       memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
+                       eeprom->len);
+       kfree(eeprom_buff);
+
+       return ret_val;
+       return 0;
+}
+
+static void atl1c_get_drvinfo(struct net_device *netdev,
+               struct ethtool_drvinfo *drvinfo)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+       strncpy(drvinfo->driver,  atl1c_driver_name, sizeof(drvinfo->driver));
+       strncpy(drvinfo->version, atl1c_driver_version,
+               sizeof(drvinfo->version));
+       strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+       strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+               sizeof(drvinfo->bus_info));
+       drvinfo->n_stats = 0;
+       drvinfo->testinfo_len = 0;
+       drvinfo->regdump_len = atl1c_get_regs_len(netdev);
+       drvinfo->eedump_len = atl1c_get_eeprom_len(netdev);
+}
+
+static void atl1c_get_wol(struct net_device *netdev,
+                         struct ethtool_wolinfo *wol)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+       wol->supported = WAKE_MAGIC | WAKE_PHY;
+       wol->wolopts = 0;
+
+       if (adapter->wol & AT_WUFC_EX)
+               wol->wolopts |= WAKE_UCAST;
+       if (adapter->wol & AT_WUFC_MC)
+               wol->wolopts |= WAKE_MCAST;
+       if (adapter->wol & AT_WUFC_BC)
+               wol->wolopts |= WAKE_BCAST;
+       if (adapter->wol & AT_WUFC_MAG)
+               wol->wolopts |= WAKE_MAGIC;
+       if (adapter->wol & AT_WUFC_LNKC)
+               wol->wolopts |= WAKE_PHY;
+
+       return;
+}
+
+static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+       if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
+                           WAKE_MCAST | WAKE_BCAST | WAKE_MCAST))
+               return -EOPNOTSUPP;
+       /* these settings will always override what we currently have */
+       adapter->wol = 0;
+
+       if (wol->wolopts & WAKE_MAGIC)
+               adapter->wol |= AT_WUFC_MAG;
+       if (wol->wolopts & WAKE_PHY)
+               adapter->wol |= AT_WUFC_LNKC;
+
+       return 0;
+}
+
+static int atl1c_nway_reset(struct net_device *netdev)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       if (netif_running(netdev))
+               atl1c_reinit_locked(adapter);
+       return 0;
+}
+
+static struct ethtool_ops atl1c_ethtool_ops = {
+       .get_settings           = atl1c_get_settings,
+       .set_settings           = atl1c_set_settings,
+       .get_drvinfo            = atl1c_get_drvinfo,
+       .get_regs_len           = atl1c_get_regs_len,
+       .get_regs               = atl1c_get_regs,
+       .get_wol                = atl1c_get_wol,
+       .set_wol                = atl1c_set_wol,
+       .get_msglevel           = atl1c_get_msglevel,
+       .set_msglevel           = atl1c_set_msglevel,
+       .nway_reset             = atl1c_nway_reset,
+       .get_link               = ethtool_op_get_link,
+       .get_eeprom_len         = atl1c_get_eeprom_len,
+       .get_eeprom             = atl1c_get_eeprom,
+       .get_tx_csum            = atl1c_get_tx_csum,
+       .get_sg                 = ethtool_op_get_sg,
+       .set_sg                 = ethtool_op_set_sg,
+};
+
+void atl1c_set_ethtool_ops(struct net_device *netdev)
+{
+       SET_ETHTOOL_OPS(netdev, &atl1c_ethtool_ops);
+}
diff --git a/drivers/net/atl1c/atl1c_hw.c b/drivers/net/atl1c/atl1c_hw.c
new file mode 100644 (file)
index 0000000..3e69b94
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+
+#include "atl1c.h"
+
+/*
+ * check_eeprom_exist
+ * return 1 if eeprom exist
+ */
+int atl1c_check_eeprom_exist(struct atl1c_hw *hw)
+{
+       u32 data;
+
+       AT_READ_REG(hw, REG_TWSI_DEBUG, &data);
+       if (data & TWSI_DEBUG_DEV_EXIST)
+               return 1;
+
+       return 0;
+}
+
+void atl1c_hw_set_mac_addr(struct atl1c_hw *hw)
+{
+       u32 value;
+       /*
+        * 00-0B-6A-F6-00-DC
+        * 0:  6AF600DC 1: 000B
+        * low dword
+        */
+       value = (((u32)hw->mac_addr[2]) << 24) |
+               (((u32)hw->mac_addr[3]) << 16) |
+               (((u32)hw->mac_addr[4]) << 8)  |
+               (((u32)hw->mac_addr[5])) ;
+       AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
+       /* hight dword */
+       value = (((u32)hw->mac_addr[0]) << 8) |
+               (((u32)hw->mac_addr[1])) ;
+       AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
+}
+
+/*
+ * atl1c_get_permanent_address
+ * return 0 if get valid mac address,
+ */
+static int atl1c_get_permanent_address(struct atl1c_hw *hw)
+{
+       u32 addr[2];
+       u32 i;
+       u32 otp_ctrl_data;
+       u32 twsi_ctrl_data;
+       u8  eth_addr[ETH_ALEN];
+
+       /* init */
+       addr[0] = addr[1] = 0;
+       AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
+       if (atl1c_check_eeprom_exist(hw)) {
+               /* Enable OTP CLK */
+               if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) {
+                       otp_ctrl_data |= OTP_CTRL_CLK_EN;
+                       AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
+                       AT_WRITE_FLUSH(hw);
+                       msleep(1);
+               }
+
+               AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
+               twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
+               AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
+               for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
+                       msleep(10);
+                       AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
+                       if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
+                               break;
+               }
+               if (i >= AT_TWSI_EEPROM_TIMEOUT)
+                       return -1;
+       }
+       /* Disable OTP_CLK */
+       if (otp_ctrl_data & OTP_CTRL_CLK_EN) {
+               otp_ctrl_data &= ~OTP_CTRL_CLK_EN;
+               AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
+               AT_WRITE_FLUSH(hw);
+               msleep(1);
+       }
+
+       /* maybe MAC-address is from BIOS */
+       AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);
+       AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);
+       *(u32 *) &eth_addr[2] = swab32(addr[0]);
+       *(u16 *) &eth_addr[0] = swab16(*(u16 *)&addr[1]);
+
+       if (is_valid_ether_addr(eth_addr)) {
+               memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+               return 0;
+       }
+
+       return -1;
+}
+
+bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value)
+{
+       int i;
+       int ret = false;
+       u32 otp_ctrl_data;
+       u32 control;
+       u32 data;
+
+       if (offset & 3)
+               return ret; /* address do not align */
+
+       AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
+       if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
+               AT_WRITE_REG(hw, REG_OTP_CTRL,
+                               (otp_ctrl_data | OTP_CTRL_CLK_EN));
+
+       AT_WRITE_REG(hw, REG_EEPROM_DATA_LO, 0);
+       control = (offset & EEPROM_CTRL_ADDR_MASK) << EEPROM_CTRL_ADDR_SHIFT;
+       AT_WRITE_REG(hw, REG_EEPROM_CTRL, control);
+
+       for (i = 0; i < 10; i++) {
+               udelay(100);
+               AT_READ_REG(hw, REG_EEPROM_CTRL, &control);
+               if (control & EEPROM_CTRL_RW)
+                       break;
+       }
+       if (control & EEPROM_CTRL_RW) {
+               AT_READ_REG(hw, REG_EEPROM_CTRL, &data);
+               AT_READ_REG(hw, REG_EEPROM_DATA_LO, p_value);
+               data = data & 0xFFFF;
+               *p_value = swab32((data << 16) | (*p_value >> 16));
+               ret = true;
+       }
+       if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
+               AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
+
+       return ret;
+}
+/*
+ * Reads the adapter's MAC address from the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+int atl1c_read_mac_addr(struct atl1c_hw *hw)
+{
+       int err = 0;
+
+       err = atl1c_get_permanent_address(hw);
+       if (err)
+               random_ether_addr(hw->perm_mac_addr);
+
+       memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
+       return 0;
+}
+
+/*
+ * atl1c_hash_mc_addr
+ *  purpose
+ *      set hash value for a multicast address
+ *      hash calcu processing :
+ *          1. calcu 32bit CRC for multicast address
+ *          2. reverse crc with MSB to LSB
+ */
+u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr)
+{
+       u32 crc32;
+       u32 value = 0;
+       int i;
+
+       crc32 = ether_crc_le(6, mc_addr);
+       for (i = 0; i < 32; i++)
+               value |= (((crc32 >> i) & 1) << (31 - i));
+
+       return value;
+}
+
+/*
+ * Sets the bit in the multicast table corresponding to the hash value.
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ */
+void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value)
+{
+       u32 hash_bit, hash_reg;
+       u32 mta;
+
+       /*
+        * The HASH Table  is a register array of 2 32-bit registers.
+        * It is treated like an array of 64 bits.  We want to set
+        * bit BitArray[hash_value]. So we figure out what register
+        * the bit is in, read it, OR in the new bit, then write
+        * back the new value.  The register is determined by the
+        * upper bit of the hash value and the bit within that
+        * register are determined by the lower 5 bits of the value.
+        */
+       hash_reg = (hash_value >> 31) & 0x1;
+       hash_bit = (hash_value >> 26) & 0x1F;
+
+       mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
+
+       mta |= (1 << hash_bit);
+
+       AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
+}
+
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+       u32 val;
+       int i;
+
+       val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+               MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
+               MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+       AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+       for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+               udelay(2);
+               AT_READ_REG(hw, REG_MDIO_CTRL, &val);
+               if (!(val & (MDIO_START | MDIO_BUSY)))
+                       break;
+       }
+       if (!(val & (MDIO_START | MDIO_BUSY))) {
+               *phy_data = (u16)val;
+               return 0;
+       }
+
+       return -1;
+}
+
+/*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
+{
+       int i;
+       u32 val;
+
+       val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT   |
+              (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+              MDIO_SUP_PREAMBLE | MDIO_START |
+              MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+       AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+       for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+               udelay(2);
+               AT_READ_REG(hw, REG_MDIO_CTRL, &val);
+               if (!(val & (MDIO_START | MDIO_BUSY)))
+                       break;
+       }
+
+       if (!(val & (MDIO_START | MDIO_BUSY)))
+               return 0;
+
+       return -1;
+}
+
+/*
+ * Configures PHY autoneg and flow control advertisement settings
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
+{
+       u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_SPEED_MASK;
+       u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP &
+                               ~GIGA_CR_1000T_SPEED_MASK;
+
+       if (hw->autoneg_advertised & ADVERTISED_10baseT_Half)
+               mii_adv_data |= ADVERTISE_10HALF;
+       if (hw->autoneg_advertised & ADVERTISED_10baseT_Full)
+               mii_adv_data |= ADVERTISE_10FULL;
+       if (hw->autoneg_advertised & ADVERTISED_100baseT_Half)
+               mii_adv_data |= ADVERTISE_100HALF;
+       if (hw->autoneg_advertised & ADVERTISED_100baseT_Full)
+               mii_adv_data |= ADVERTISE_100FULL;
+
+       if (hw->autoneg_advertised & ADVERTISED_Autoneg)
+               mii_adv_data |= ADVERTISE_10HALF  | ADVERTISE_10FULL |
+                               ADVERTISE_100HALF | ADVERTISE_100FULL;
+
+       if (hw->ctrl_flags & ATL1C_LINK_CAP_1000M) {
+               if (hw->autoneg_advertised & ADVERTISED_1000baseT_Half)
+                       mii_giga_ctrl_data |= ADVERTISE_1000HALF;
+               if (hw->autoneg_advertised & ADVERTISED_1000baseT_Full)
+                       mii_giga_ctrl_data |= ADVERTISE_1000FULL;
+               if (hw->autoneg_advertised & ADVERTISED_Autoneg)
+                       mii_giga_ctrl_data |= ADVERTISE_1000HALF |
+                                       ADVERTISE_1000FULL;
+       }
+
+       if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 ||
+           atl1c_write_phy_reg(hw, MII_GIGA_CR, mii_giga_ctrl_data) != 0)
+               return -1;
+       return 0;
+}
+
+void atl1c_phy_disable(struct atl1c_hw *hw)
+{
+       AT_WRITE_REGW(hw, REG_GPHY_CTRL,
+                       GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
+}
+
+static void atl1c_phy_magic_data(struct atl1c_hw *hw)
+{
+       u16 data;
+
+       data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE |
+               ((1 & ANA_INTERVAL_SEL_TIMER_MASK) <<
+               ANA_INTERVAL_SEL_TIMER_SHIFT);
+
+       atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_18);
+       atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+       data = (2 & ANA_SERDES_CDR_BW_MASK) | ANA_MS_PAD_DBG |
+               ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP | ANA_SERDES_EN_PLL |
+               ANA_SERDES_EN_LCKDT;
+
+       atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_5);
+       atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+       data = (44 & ANA_LONG_CABLE_TH_100_MASK) |
+               ((33 & ANA_SHORT_CABLE_TH_100_MASK) <<
+               ANA_SHORT_CABLE_TH_100_SHIFT) | ANA_BP_BAD_LINK_ACCUM |
+               ANA_BP_SMALL_BW;
+
+       atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_54);
+       atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+       data = (11 & ANA_IECHO_ADJ_MASK) | ((11 & ANA_IECHO_ADJ_MASK) <<
+               ANA_IECHO_ADJ_2_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
+               ANA_IECHO_ADJ_1_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
+               ANA_IECHO_ADJ_0_SHIFT);
+
+       atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_4);
+       atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+       data = ANA_RESTART_CAL | ((7 & ANA_MANUL_SWICH_ON_MASK) <<
+               ANA_MANUL_SWICH_ON_SHIFT) | ANA_MAN_ENABLE |
+               ANA_SEL_HSP | ANA_EN_HB | ANA_OEN_125M;
+
+       atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_0);
+       atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+       if (hw->ctrl_flags & ATL1C_HIB_DISABLE) {
+               atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_41);
+               if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
+                       return;
+               data &= ~ANA_TOP_PS_EN;
+               atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+               atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_11);
+               if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
+                       return;
+               data &= ~ANA_PS_HIB_EN;
+               atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+       }
+}
+
+int atl1c_phy_reset(struct atl1c_hw *hw)
+{
+       struct atl1c_adapter *adapter = hw->adapter;
+       struct pci_dev *pdev = adapter->pdev;
+       u32 phy_ctrl_data = GPHY_CTRL_DEFAULT;
+       u32 mii_ier_data = IER_LINK_UP | IER_LINK_DOWN;
+       int err;
+
+       if (hw->ctrl_flags & ATL1C_HIB_DISABLE)
+               phy_ctrl_data &= ~GPHY_CTRL_HIB_EN;
+
+       AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
+       AT_WRITE_FLUSH(hw);
+       msleep(40);
+       phy_ctrl_data |= GPHY_CTRL_EXT_RESET;
+       AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
+       AT_WRITE_FLUSH(hw);
+       msleep(10);
+
+       /*Enable PHY LinkChange Interrupt */
+       err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data);
+       if (err) {
+               if (netif_msg_hw(adapter))
+                       dev_err(&pdev->dev,
+                               "Error enable PHY linkChange Interrupt\n");
+               return err;
+       }
+       if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
+               atl1c_phy_magic_data(hw);
+       return 0;
+}
+
+int atl1c_phy_init(struct atl1c_hw *hw)
+{
+       struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
+       struct pci_dev *pdev = adapter->pdev;
+       int ret_val;
+       u16 mii_bmcr_data = BMCR_RESET;
+       u16 phy_id1, phy_id2;
+
+       if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &phy_id1) != 0) ||
+               (atl1c_read_phy_reg(hw, MII_PHYSID2, &phy_id2) != 0)) {
+                       if (netif_msg_link(adapter))
+                               dev_err(&pdev->dev, "Error get phy ID\n");
+               return -1;
+       }
+       switch (hw->media_type) {
+       case MEDIA_TYPE_AUTO_SENSOR:
+               ret_val = atl1c_phy_setup_adv(hw);
+               if (ret_val) {
+                       if (netif_msg_link(adapter))
+                               dev_err(&pdev->dev,
+                                       "Error Setting up Auto-Negotiation\n");
+                       return ret_val;
+               }
+               mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG;
+               break;
+       case MEDIA_TYPE_100M_FULL:
+               mii_bmcr_data |= BMCR_SPEED_100 | BMCR_FULL_DUPLEX;
+               break;
+       case MEDIA_TYPE_100M_HALF:
+               mii_bmcr_data |= BMCR_SPEED_100;
+               break;
+       case MEDIA_TYPE_10M_FULL:
+               mii_bmcr_data |= BMCR_SPEED_10 | BMCR_FULL_DUPLEX;
+               break;
+       case MEDIA_TYPE_10M_HALF:
+               mii_bmcr_data |= BMCR_SPEED_10;
+               break;
+       default:
+               if (netif_msg_link(adapter))
+                       dev_err(&pdev->dev, "Wrong Media type %d\n",
+                               hw->media_type);
+               return -1;
+               break;
+       }
+
+       ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
+       if (ret_val)
+               return ret_val;
+       hw->phy_configured = true;
+
+       return 0;
+}
+
+/*
+ * Detects the current speed and duplex settings of the hardware.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ */
+int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
+{
+       int err;
+       u16 phy_data;
+
+       /* Read   PHY Specific Status Register (17) */
+       err = atl1c_read_phy_reg(hw, MII_GIGA_PSSR, &phy_data);
+       if (err)
+               return err;
+
+       if (!(phy_data & GIGA_PSSR_SPD_DPLX_RESOLVED))
+               return -1;
+
+       switch (phy_data & GIGA_PSSR_SPEED) {
+       case GIGA_PSSR_1000MBS:
+               *speed = SPEED_1000;
+               break;
+       case GIGA_PSSR_100MBS:
+               *speed = SPEED_100;
+               break;
+       case  GIGA_PSSR_10MBS:
+               *speed = SPEED_10;
+               break;
+       default:
+               return -1;
+               break;
+       }
+
+       if (phy_data & GIGA_PSSR_DPLX)
+               *duplex = FULL_DUPLEX;
+       else
+               *duplex = HALF_DUPLEX;
+
+       return 0;
+}
+
+int atl1c_restart_autoneg(struct atl1c_hw *hw)
+{
+       int err = 0;
+       u16 mii_bmcr_data = BMCR_RESET;
+
+       err = atl1c_phy_setup_adv(hw);
+       if (err)
+               return err;
+       mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG;
+
+       return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
+}
diff --git a/drivers/net/atl1c/atl1c_hw.h b/drivers/net/atl1c/atl1c_hw.h
new file mode 100644 (file)
index 0000000..c2c738d
--- /dev/null
@@ -0,0 +1,859 @@
+/*
+ * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _ATL1C_HW_H_
+#define _ATL1C_HW_H_
+
+#include <linux/types.h>
+#include <linux/mii.h>
+
+struct atl1c_adapter;
+struct atl1c_hw;
+
+/* function prototype */
+void atl1c_phy_disable(struct atl1c_hw *hw);
+void atl1c_hw_set_mac_addr(struct atl1c_hw *hw);
+int atl1c_phy_reset(struct atl1c_hw *hw);
+int atl1c_read_mac_addr(struct atl1c_hw *hw);
+int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex);
+u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr);
+void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value);
+int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data);
+int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data);
+bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value);
+int atl1c_phy_init(struct atl1c_hw *hw);
+int atl1c_check_eeprom_exist(struct atl1c_hw *hw);
+int atl1c_restart_autoneg(struct atl1c_hw *hw);
+
+/* register definition */
+#define REG_DEVICE_CAP                 0x5C
+#define DEVICE_CAP_MAX_PAYLOAD_MASK     0x7
+#define DEVICE_CAP_MAX_PAYLOAD_SHIFT    0
+
+#define REG_DEVICE_CTRL                        0x60
+#define DEVICE_CTRL_MAX_PAYLOAD_MASK    0x7
+#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT   5
+#define DEVICE_CTRL_MAX_RREQ_SZ_MASK    0x7
+#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT   12
+
+#define REG_LINK_CTRL                  0x68
+#define LINK_CTRL_L0S_EN               0x01
+#define LINK_CTRL_L1_EN                        0x02
+
+#define REG_VPD_CAP                    0x6C
+#define VPD_CAP_ID_MASK                 0xff
+#define VPD_CAP_ID_SHIFT                0
+#define VPD_CAP_NEXT_PTR_MASK           0xFF
+#define VPD_CAP_NEXT_PTR_SHIFT          8
+#define VPD_CAP_VPD_ADDR_MASK           0x7FFF
+#define VPD_CAP_VPD_ADDR_SHIFT          16
+#define VPD_CAP_VPD_FLAG                0x80000000
+
+#define REG_VPD_DATA                   0x70
+
+#define REG_PCIE_UC_SEVERITY           0x10C
+#define PCIE_UC_SERVRITY_TRN           0x00000001
+#define PCIE_UC_SERVRITY_DLP           0x00000010
+#define PCIE_UC_SERVRITY_PSN_TLP       0x00001000
+#define PCIE_UC_SERVRITY_FCP           0x00002000
+#define PCIE_UC_SERVRITY_CPL_TO                0x00004000
+#define PCIE_UC_SERVRITY_CA            0x00008000
+#define PCIE_UC_SERVRITY_UC            0x00010000
+#define PCIE_UC_SERVRITY_ROV           0x00020000
+#define PCIE_UC_SERVRITY_MLFP          0x00040000
+#define PCIE_UC_SERVRITY_ECRC          0x00080000
+#define PCIE_UC_SERVRITY_UR            0x00100000
+
+#define REG_DEV_SERIALNUM_CTRL         0x200
+#define REG_DEV_MAC_SEL_MASK           0x0 /* 0:EUI; 1:MAC */
+#define REG_DEV_MAC_SEL_SHIFT          0
+#define REG_DEV_SERIAL_NUM_EN_MASK     0x1
+#define REG_DEV_SERIAL_NUM_EN_SHIFT    1
+
+#define REG_TWSI_CTRL                  0x218
+#define TWSI_CTRL_LD_OFFSET_MASK        0xFF
+#define TWSI_CTRL_LD_OFFSET_SHIFT       0
+#define TWSI_CTRL_LD_SLV_ADDR_MASK      0x7
+#define TWSI_CTRL_LD_SLV_ADDR_SHIFT     8
+#define TWSI_CTRL_SW_LDSTART            0x800
+#define TWSI_CTRL_HW_LDSTART            0x1000
+#define TWSI_CTRL_SMB_SLV_ADDR_MASK     0x7F
+#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT    15
+#define TWSI_CTRL_LD_EXIST              0x400000
+#define TWSI_CTRL_READ_FREQ_SEL_MASK    0x3
+#define TWSI_CTRL_READ_FREQ_SEL_SHIFT   23
+#define TWSI_CTRL_FREQ_SEL_100K         0
+#define TWSI_CTRL_FREQ_SEL_200K         1
+#define TWSI_CTRL_FREQ_SEL_300K         2
+#define TWSI_CTRL_FREQ_SEL_400K         3
+#define TWSI_CTRL_SMB_SLV_ADDR
+#define TWSI_CTRL_WRITE_FREQ_SEL_MASK   0x3
+#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT  24
+
+
+#define REG_PCIE_DEV_MISC_CTRL         0x21C
+#define PCIE_DEV_MISC_EXT_PIPE         0x2
+#define PCIE_DEV_MISC_RETRY_BUFDIS     0x1
+#define PCIE_DEV_MISC_SPIROM_EXIST     0x4
+#define PCIE_DEV_MISC_SERDES_ENDIAN            0x8
+#define PCIE_DEV_MISC_SERDES_SEL_DIN           0x10
+
+#define REG_PCIE_PHYMISC               0x1000
+#define PCIE_PHYMISC_FORCE_RCV_DET     0x4
+
+#define REG_TWSI_DEBUG                 0x1108
+#define TWSI_DEBUG_DEV_EXIST           0x20000000
+
+#define REG_EEPROM_CTRL                        0x12C0
+#define EEPROM_CTRL_DATA_HI_MASK       0xFFFF
+#define EEPROM_CTRL_DATA_HI_SHIFT      0
+#define EEPROM_CTRL_ADDR_MASK          0x3FF
+#define EEPROM_CTRL_ADDR_SHIFT         16
+#define EEPROM_CTRL_ACK                        0x40000000
+#define EEPROM_CTRL_RW                 0x80000000
+
+#define REG_EEPROM_DATA_LO             0x12C4
+
+#define REG_OTP_CTRL                   0x12F0
+#define OTP_CTRL_CLK_EN                        0x0002
+
+#define REG_PM_CTRL                    0x12F8
+#define PM_CTRL_SDES_EN                        0x00000001
+#define PM_CTRL_RBER_EN                        0x00000002
+#define PM_CTRL_CLK_REQ_EN             0x00000004
+#define PM_CTRL_ASPM_L1_EN             0x00000008
+#define PM_CTRL_SERDES_L1_EN           0x00000010
+#define PM_CTRL_SERDES_PLL_L1_EN       0x00000020
+#define PM_CTRL_SERDES_PD_EX_L1                0x00000040
+#define PM_CTRL_SERDES_BUDS_RX_L1_EN   0x00000080
+#define PM_CTRL_L0S_ENTRY_TIMER_MASK   0xF
+#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT  8
+#define PM_CTRL_ASPM_L0S_EN            0x00001000
+#define PM_CTRL_CLK_SWH_L1             0x00002000
+#define PM_CTRL_CLK_PWM_VER1_1         0x00004000
+#define PM_CTRL_PCIE_RECV              0x00008000
+#define PM_CTRL_L1_ENTRY_TIMER_MASK    0xF
+#define PM_CTRL_L1_ENTRY_TIMER_SHIFT   16
+#define PM_CTRL_PM_REQ_TIMER_MASK      0xF
+#define PM_CTRL_PM_REQ_TIMER_SHIFT     20
+#define PM_CTRL_LCKDET_TIMER_MASK      0x3F
+#define PM_CTRL_LCKDET_TIMER_SHIFT     24
+#define PM_CTRL_MAC_ASPM_CHK           0x40000000
+#define PM_CTRL_HOTRST                 0x80000000
+
+/* Selene Master Control Register */
+#define REG_MASTER_CTRL                        0x1400
+#define MASTER_CTRL_SOFT_RST            0x1
+#define MASTER_CTRL_TEST_MODE_MASK     0x3
+#define MASTER_CTRL_TEST_MODE_SHIFT    2
+#define MASTER_CTRL_BERT_START         0x10
+#define MASTER_CTRL_MTIMER_EN           0x100
+#define MASTER_CTRL_MANUAL_INT          0x200
+#define MASTER_CTRL_TX_ITIMER_EN       0x400
+#define MASTER_CTRL_RX_ITIMER_EN       0x800
+#define MASTER_CTRL_CLK_SEL_DIS                0x1000
+#define MASTER_CTRL_CLK_SWH_MODE       0x2000
+#define MASTER_CTRL_INT_RDCLR          0x4000
+#define MASTER_CTRL_REV_NUM_SHIFT      16
+#define MASTER_CTRL_REV_NUM_MASK       0xff
+#define MASTER_CTRL_DEV_ID_SHIFT       24
+#define MASTER_CTRL_DEV_ID_MASK                0x7f
+#define MASTER_CTRL_OTP_SEL            0x80000000
+
+/* Timer Initial Value Register */
+#define REG_MANUAL_TIMER_INIT          0x1404
+
+/* IRQ ModeratorTimer Initial Value Register */
+#define REG_IRQ_MODRT_TIMER_INIT       0x1408
+#define IRQ_MODRT_TIMER_MASK           0xffff
+#define IRQ_MODRT_TX_TIMER_SHIFT       0
+#define IRQ_MODRT_RX_TIMER_SHIFT       16
+
+#define REG_GPHY_CTRL                  0x140C
+#define GPHY_CTRL_EXT_RESET            0x1
+#define GPHY_CTRL_RTL_MODE             0x2
+#define GPHY_CTRL_LED_MODE             0x4
+#define GPHY_CTRL_ANEG_NOW             0x8
+#define GPHY_CTRL_REV_ANEG             0x10
+#define GPHY_CTRL_GATE_25M_EN          0x20
+#define GPHY_CTRL_LPW_EXIT             0x40
+#define GPHY_CTRL_PHY_IDDQ             0x80
+#define GPHY_CTRL_PHY_IDDQ_DIS         0x100
+#define GPHY_CTRL_GIGA_DIS             0x200
+#define GPHY_CTRL_HIB_EN               0x400
+#define GPHY_CTRL_HIB_PULSE            0x800
+#define GPHY_CTRL_SEL_ANA_RST          0x1000
+#define GPHY_CTRL_PHY_PLL_ON           0x2000
+#define GPHY_CTRL_PWDOWN_HW            0x4000
+#define GPHY_CTRL_PHY_PLL_BYPASS       0x8000
+
+#define GPHY_CTRL_DEFAULT (             \
+               GPHY_CTRL_SEL_ANA_RST   |\
+               GPHY_CTRL_HIB_PULSE     |\
+               GPHY_CTRL_HIB_EN)
+
+#define GPHY_CTRL_PW_WOL_DIS (          \
+               GPHY_CTRL_SEL_ANA_RST   |\
+               GPHY_CTRL_HIB_PULSE     |\
+               GPHY_CTRL_HIB_EN        |\
+               GPHY_CTRL_PWDOWN_HW     |\
+               GPHY_CTRL_PHY_IDDQ)
+
+/* Block IDLE Status Register */
+#define REG_IDLE_STATUS                0x1410
+#define IDLE_STATUS_MASK               0x00FF
+#define IDLE_STATUS_RXMAC_NO_IDLE              0x1
+#define IDLE_STATUS_TXMAC_NO_IDLE              0x2
+#define IDLE_STATUS_RXQ_NO_IDLE                0x4
+#define IDLE_STATUS_TXQ_NO_IDLE                0x8
+#define IDLE_STATUS_DMAR_NO_IDLE               0x10
+#define IDLE_STATUS_DMAW_NO_IDLE               0x20
+#define IDLE_STATUS_SMB_NO_IDLE                0x40
+#define IDLE_STATUS_CMB_NO_IDLE                0x80
+
+/* MDIO Control Register */
+#define REG_MDIO_CTRL                  0x1414
+#define MDIO_DATA_MASK                 0xffff  /* On MDIO write, the 16-bit
+                                                * control data to write to PHY
+                                                * MII management register */
+#define MDIO_DATA_SHIFT                0       /* On MDIO read, the 16-bit
+                                                * status data that was read
+                                                * from the PHY MII management register */
+#define MDIO_REG_ADDR_MASK             0x1f    /* MDIO register address */
+#define MDIO_REG_ADDR_SHIFT            16
+#define MDIO_RW                        0x200000  /* 1: read, 0: write */
+#define MDIO_SUP_PREAMBLE              0x400000  /* Suppress preamble */
+#define MDIO_START                     0x800000  /* Write 1 to initiate the MDIO
+                                                  * master. And this bit is self
+                                                  * cleared after one cycle */
+#define MDIO_CLK_SEL_SHIFT             24
+#define MDIO_CLK_25_4                  0
+#define MDIO_CLK_25_6                  2
+#define MDIO_CLK_25_8                  3
+#define MDIO_CLK_25_10                 4
+#define MDIO_CLK_25_14                 5
+#define MDIO_CLK_25_20                 6
+#define MDIO_CLK_25_28                 7
+#define MDIO_BUSY                      0x8000000
+#define MDIO_AP_EN                     0x10000000
+#define MDIO_WAIT_TIMES                10
+
+/* MII PHY Status Register */
+#define REG_PHY_STATUS                 0x1418
+#define PHY_GENERAL_STATUS_MASK                0xFFFF
+#define PHY_STATUS_RECV_ENABLE         0x0001
+#define PHY_OE_PWSP_STATUS_MASK                0x07FF
+#define PHY_OE_PWSP_STATUS_SHIFT       16
+#define PHY_STATUS_LPW_STATE           0x80000000
+/* BIST Control and Status Register0 (for the Packet Memory) */
+#define REG_BIST0_CTRL                 0x141c
+#define BIST0_NOW                      0x1
+#define BIST0_SRAM_FAIL                0x2 /* 1: The SRAM failure is
+                                            * un-repairable  because
+                                            * it has address decoder
+                                            * failure or more than 1 cell
+                                            * stuck-to-x failure */
+#define BIST0_FUSE_FLAG                0x4
+
+/* BIST Control and Status Register1(for the retry buffer of PCI Express) */
+#define REG_BIST1_CTRL                 0x1420
+#define BIST1_NOW                      0x1
+#define BIST1_SRAM_FAIL                0x2
+#define BIST1_FUSE_FLAG                0x4
+
+/* SerDes Lock Detect Control and Status Register */
+#define REG_SERDES_LOCK                0x1424
+#define SERDES_LOCK_DETECT             0x1  /* SerDes lock detected. This signal
+                                             * comes from Analog SerDes */
+#define SERDES_LOCK_DETECT_EN          0x2  /* 1: Enable SerDes Lock detect function */
+
+/* MAC Control Register  */
+#define REG_MAC_CTRL                   0x1480
+#define MAC_CTRL_TX_EN                 0x1
+#define MAC_CTRL_RX_EN                 0x2
+#define MAC_CTRL_TX_FLOW               0x4
+#define MAC_CTRL_RX_FLOW               0x8
+#define MAC_CTRL_LOOPBACK              0x10
+#define MAC_CTRL_DUPLX                 0x20
+#define MAC_CTRL_ADD_CRC               0x40
+#define MAC_CTRL_PAD                   0x80
+#define MAC_CTRL_LENCHK                0x100
+#define MAC_CTRL_HUGE_EN               0x200
+#define MAC_CTRL_PRMLEN_SHIFT          10
+#define MAC_CTRL_PRMLEN_MASK           0xf
+#define MAC_CTRL_RMV_VLAN              0x4000
+#define MAC_CTRL_PROMIS_EN             0x8000
+#define MAC_CTRL_TX_PAUSE              0x10000
+#define MAC_CTRL_SCNT                  0x20000
+#define MAC_CTRL_SRST_TX               0x40000
+#define MAC_CTRL_TX_SIMURST            0x80000
+#define MAC_CTRL_SPEED_SHIFT           20
+#define MAC_CTRL_SPEED_MASK            0x3
+#define MAC_CTRL_DBG_TX_BKPRESURE      0x400000
+#define MAC_CTRL_TX_HUGE               0x800000
+#define MAC_CTRL_RX_CHKSUM_EN          0x1000000
+#define MAC_CTRL_MC_ALL_EN             0x2000000
+#define MAC_CTRL_BC_EN                 0x4000000
+#define MAC_CTRL_DBG                   0x8000000
+#define MAC_CTRL_SINGLE_PAUSE_EN       0x10000000
+
+/* MAC IPG/IFG Control Register  */
+#define REG_MAC_IPG_IFG                0x1484
+#define MAC_IPG_IFG_IPGT_SHIFT         0       /* Desired back to back
+                                                * inter-packet gap. The
+                                                * default is 96-bit time */
+#define MAC_IPG_IFG_IPGT_MASK          0x7f
+#define MAC_IPG_IFG_MIFG_SHIFT         8       /* Minimum number of IFG to
+                                                * enforce in between RX frames */
+#define MAC_IPG_IFG_MIFG_MASK          0xff    /* Frame gap below such IFP is dropped */
+#define MAC_IPG_IFG_IPGR1_SHIFT        16      /* 64bit Carrier-Sense window */
+#define MAC_IPG_IFG_IPGR1_MASK         0x7f
+#define MAC_IPG_IFG_IPGR2_SHIFT        24      /* 96-bit IPG window */
+#define MAC_IPG_IFG_IPGR2_MASK         0x7f
+
+/* MAC STATION ADDRESS  */
+#define REG_MAC_STA_ADDR               0x1488
+
+/* Hash table for multicast address */
+#define REG_RX_HASH_TABLE              0x1490
+
+/* MAC Half-Duplex Control Register */
+#define REG_MAC_HALF_DUPLX_CTRL        0x1498
+#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT  0      /* Collision Window */
+#define MAC_HALF_DUPLX_CTRL_LCOL_MASK   0x3ff
+#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12
+#define MAC_HALF_DUPLX_CTRL_RETRY_MASK  0xf
+#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN  0x10000
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_C   0x20000
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_P   0x40000 /* No back-off on backpressure,
+                                                * immediately start the
+                                                * transmission after back pressure */
+#define MAC_HALF_DUPLX_CTRL_ABEBE        0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */
+#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT  20      /* Maximum binary exponential number */
+#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK   0xf
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24      /* IPG to start JAM for collision based flow control in half-duplex */
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK  0xf     /* mode. In unit of 8-bit time */
+
+/* Maximum Frame Length Control Register   */
+#define REG_MTU                        0x149c
+
+/* Wake-On-Lan control register */
+#define REG_WOL_CTRL                   0x14a0
+#define WOL_PATTERN_EN                 0x00000001
+#define WOL_PATTERN_PME_EN              0x00000002
+#define WOL_MAGIC_EN                    0x00000004
+#define WOL_MAGIC_PME_EN                0x00000008
+#define WOL_LINK_CHG_EN                 0x00000010
+#define WOL_LINK_CHG_PME_EN             0x00000020
+#define WOL_PATTERN_ST                  0x00000100
+#define WOL_MAGIC_ST                    0x00000200
+#define WOL_LINKCHG_ST                  0x00000400
+#define WOL_CLK_SWITCH_EN               0x00008000
+#define WOL_PT0_EN                      0x00010000
+#define WOL_PT1_EN                      0x00020000
+#define WOL_PT2_EN                      0x00040000
+#define WOL_PT3_EN                      0x00080000
+#define WOL_PT4_EN                      0x00100000
+#define WOL_PT5_EN                      0x00200000
+#define WOL_PT6_EN                      0x00400000
+
+/* WOL Length ( 2 DWORD ) */
+#define REG_WOL_PATTERN_LEN            0x14a4
+#define WOL_PT_LEN_MASK                 0x7f
+#define WOL_PT0_LEN_SHIFT               0
+#define WOL_PT1_LEN_SHIFT               8
+#define WOL_PT2_LEN_SHIFT               16
+#define WOL_PT3_LEN_SHIFT               24
+#define WOL_PT4_LEN_SHIFT               0
+#define WOL_PT5_LEN_SHIFT               8
+#define WOL_PT6_LEN_SHIFT               16
+
+/* Internal SRAM Partition Register */
+#define RFDX_HEAD_ADDR_MASK            0x03FF
+#define RFDX_HARD_ADDR_SHIFT           0
+#define RFDX_TAIL_ADDR_MASK            0x03FF
+#define RFDX_TAIL_ADDR_SHIFT            16
+
+#define REG_SRAM_RFD0_INFO             0x1500
+#define REG_SRAM_RFD1_INFO             0x1504
+#define REG_SRAM_RFD2_INFO             0x1508
+#define        REG_SRAM_RFD3_INFO              0x150C
+
+#define REG_RFD_NIC_LEN                        0x1510 /* In 8-bytes */
+#define RFD_NIC_LEN_MASK               0x03FF
+
+#define REG_SRAM_TRD_ADDR              0x1518
+#define TPD_HEAD_ADDR_MASK             0x03FF
+#define TPD_HEAD_ADDR_SHIFT            0
+#define TPD_TAIL_ADDR_MASK             0x03FF
+#define TPD_TAIL_ADDR_SHIFT            16
+
+#define REG_SRAM_TRD_LEN               0x151C /* In 8-bytes */
+#define TPD_NIC_LEN_MASK               0x03FF
+
+#define REG_SRAM_RXF_ADDR              0x1520
+#define REG_SRAM_RXF_LEN               0x1524
+#define REG_SRAM_TXF_ADDR              0x1528
+#define REG_SRAM_TXF_LEN               0x152C
+#define REG_SRAM_TCPH_ADDR             0x1530
+#define REG_SRAM_PKTH_ADDR             0x1532
+
+/*
+ * Load Ptr Register
+ * Software sets this bit after the initialization of the head and tail */
+#define REG_LOAD_PTR                   0x1534
+
+/*
+ * addresses of all descriptors, as well as the following descriptor
+ * control register, which triggers each function block to load the head
+ * pointer to prepare for the operation. This bit is then self-cleared
+ * after one cycle.
+ */
+#define REG_RX_BASE_ADDR_HI            0x1540
+#define REG_TX_BASE_ADDR_HI            0x1544
+#define REG_SMB_BASE_ADDR_HI           0x1548
+#define REG_SMB_BASE_ADDR_LO           0x154C
+#define REG_RFD0_HEAD_ADDR_LO          0x1550
+#define REG_RFD1_HEAD_ADDR_LO          0x1554
+#define REG_RFD2_HEAD_ADDR_LO          0x1558
+#define REG_RFD3_HEAD_ADDR_LO          0x155C
+#define REG_RFD_RING_SIZE              0x1560
+#define RFD_RING_SIZE_MASK             0x0FFF
+#define REG_RX_BUF_SIZE                        0x1564
+#define RX_BUF_SIZE_MASK               0xFFFF
+#define REG_RRD0_HEAD_ADDR_LO          0x1568
+#define REG_RRD1_HEAD_ADDR_LO          0x156C
+#define REG_RRD2_HEAD_ADDR_LO          0x1570
+#define REG_RRD3_HEAD_ADDR_LO          0x1574
+#define REG_RRD_RING_SIZE              0x1578
+#define RRD_RING_SIZE_MASK             0x0FFF
+#define REG_HTPD_HEAD_ADDR_LO          0x157C
+#define REG_NTPD_HEAD_ADDR_LO          0x1580
+#define REG_TPD_RING_SIZE              0x1584
+#define TPD_RING_SIZE_MASK             0xFFFF
+#define REG_CMB_BASE_ADDR_LO           0x1588
+
+/* RSS about */
+#define REG_RSS_KEY0                    0x14B0
+#define REG_RSS_KEY1                    0x14B4
+#define REG_RSS_KEY2                    0x14B8
+#define REG_RSS_KEY3                    0x14BC
+#define REG_RSS_KEY4                    0x14C0
+#define REG_RSS_KEY5                    0x14C4
+#define REG_RSS_KEY6                    0x14C8
+#define REG_RSS_KEY7                    0x14CC
+#define REG_RSS_KEY8                    0x14D0
+#define REG_RSS_KEY9                    0x14D4
+#define REG_IDT_TABLE0                 0x14E0
+#define REG_IDT_TABLE1                  0x14E4
+#define REG_IDT_TABLE2                  0x14E8
+#define REG_IDT_TABLE3                  0x14EC
+#define REG_IDT_TABLE4                  0x14F0
+#define REG_IDT_TABLE5                  0x14F4
+#define REG_IDT_TABLE6                  0x14F8
+#define REG_IDT_TABLE7                  0x14FC
+#define REG_IDT_TABLE                   REG_IDT_TABLE0
+#define REG_RSS_HASH_VALUE              0x15B0
+#define REG_RSS_HASH_FLAG               0x15B4
+#define REG_BASE_CPU_NUMBER             0x15B8
+
+/* TXQ Control Register */
+#define REG_TXQ_CTRL                   0x1590
+#define        TXQ_NUM_TPD_BURST_MASK          0xF
+#define TXQ_NUM_TPD_BURST_SHIFT        0
+#define TXQ_CTRL_IP_OPTION_EN          0x10
+#define TXQ_CTRL_EN                     0x20
+#define TXQ_CTRL_ENH_MODE               0x40
+#define TXQ_CTRL_LS_8023_EN            0x80
+#define TXQ_TXF_BURST_NUM_SHIFT        16
+#define TXQ_TXF_BURST_NUM_MASK         0xFFFF
+
+/* Jumbo packet Threshold for task offload */
+#define REG_TX_TSO_OFFLOAD_THRESH      0x1594 /* In 8-bytes */
+#define TX_TSO_OFFLOAD_THRESH_MASK     0x07FF
+
+#define        REG_TXF_WATER_MARK              0x1598 /* In 8-bytes */
+#define TXF_WATER_MARK_MASK            0x0FFF
+#define TXF_LOW_WATER_MARK_SHIFT       0
+#define TXF_HIGH_WATER_MARK_SHIFT      16
+#define TXQ_CTRL_BURST_MODE_EN         0x80000000
+
+#define REG_THRUPUT_MON_CTRL           0x159C
+#define THRUPUT_MON_RATE_MASK          0x3
+#define THRUPUT_MON_RATE_SHIFT         0
+#define THRUPUT_MON_EN                 0x80
+
+/* RXQ Control Register */
+#define REG_RXQ_CTRL                   0x15A0
+#define ASPM_THRUPUT_LIMIT_MASK                0x3
+#define ASPM_THRUPUT_LIMIT_SHIFT       0
+#define ASPM_THRUPUT_LIMIT_NO          0x00
+#define ASPM_THRUPUT_LIMIT_1M          0x01
+#define ASPM_THRUPUT_LIMIT_10M         0x02
+#define ASPM_THRUPUT_LIMIT_100M                0x04
+#define RXQ1_CTRL_EN                   0x10
+#define RXQ2_CTRL_EN                   0x20
+#define RXQ3_CTRL_EN                   0x40
+#define IPV6_CHKSUM_CTRL_EN            0x80
+#define RSS_HASH_BITS_MASK             0x00FF
+#define RSS_HASH_BITS_SHIFT            8
+#define RSS_HASH_IPV4                  0x10000
+#define RSS_HASH_IPV4_TCP              0x20000
+#define RSS_HASH_IPV6                  0x40000
+#define RSS_HASH_IPV6_TCP              0x80000
+#define RXQ_RFD_BURST_NUM_MASK         0x003F
+#define RXQ_RFD_BURST_NUM_SHIFT                20
+#define RSS_MODE_MASK                  0x0003
+#define RSS_MODE_SHIFT                 26
+#define RSS_NIP_QUEUE_SEL_MASK         0x1
+#define RSS_NIP_QUEUE_SEL_SHIFT                28
+#define RRS_HASH_CTRL_EN               0x20000000
+#define RX_CUT_THRU_EN                 0x40000000
+#define RXQ_CTRL_EN                    0x80000000
+
+#define REG_RFD_FREE_THRESH            0x15A4
+#define RFD_FREE_THRESH_MASK           0x003F
+#define RFD_FREE_HI_THRESH_SHIFT       0
+#define RFD_FREE_LO_THRESH_SHIFT       6
+
+/* RXF flow control register */
+#define REG_RXQ_RXF_PAUSE_THRESH       0x15A8
+#define RXQ_RXF_PAUSE_TH_HI_SHIFT       0
+#define RXQ_RXF_PAUSE_TH_HI_MASK        0x0FFF
+#define RXQ_RXF_PAUSE_TH_LO_SHIFT       16
+#define RXQ_RXF_PAUSE_TH_LO_MASK        0x0FFF
+
+#define REG_RXD_DMA_CTRL               0x15AC
+#define RXD_DMA_THRESH_MASK            0x0FFF  /* In 8-bytes */
+#define RXD_DMA_THRESH_SHIFT           0
+#define RXD_DMA_DOWN_TIMER_MASK                0xFFFF
+#define RXD_DMA_DOWN_TIMER_SHIFT       16
+
+/* DMA Engine Control Register */
+#define REG_DMA_CTRL                   0x15C0
+#define DMA_CTRL_DMAR_IN_ORDER          0x1
+#define DMA_CTRL_DMAR_ENH_ORDER         0x2
+#define DMA_CTRL_DMAR_OUT_ORDER         0x4
+#define DMA_CTRL_RCB_VALUE              0x8
+#define DMA_CTRL_DMAR_BURST_LEN_MASK    0x0007
+#define DMA_CTRL_DMAR_BURST_LEN_SHIFT   4
+#define DMA_CTRL_DMAW_BURST_LEN_MASK    0x0007
+#define DMA_CTRL_DMAW_BURST_LEN_SHIFT   7
+#define DMA_CTRL_DMAR_REQ_PRI           0x400
+#define DMA_CTRL_DMAR_DLY_CNT_MASK      0x001F
+#define DMA_CTRL_DMAR_DLY_CNT_SHIFT     11
+#define DMA_CTRL_DMAW_DLY_CNT_MASK      0x000F
+#define DMA_CTRL_DMAW_DLY_CNT_SHIFT     16
+#define DMA_CTRL_CMB_EN                0x100000
+#define DMA_CTRL_SMB_EN                        0x200000
+#define DMA_CTRL_CMB_NOW               0x400000
+#define MAC_CTRL_SMB_DIS               0x1000000
+#define DMA_CTRL_SMB_NOW               0x80000000
+
+/* CMB/SMB Control Register */
+#define REG_SMB_STAT_TIMER             0x15C4  /* 2us resolution */
+#define SMB_STAT_TIMER_MASK            0xFFFFFF
+#define REG_CMB_TPD_THRESH             0x15C8
+#define CMB_TPD_THRESH_MASK            0xFFFF
+#define REG_CMB_TX_TIMER               0x15CC  /* 2us resolution */
+#define CMB_TX_TIMER_MASK              0xFFFF
+
+/* Mail box */
+#define MB_RFDX_PROD_IDX_MASK          0xFFFF
+#define REG_MB_RFD0_PROD_IDX           0x15E0
+#define REG_MB_RFD1_PROD_IDX           0x15E4
+#define REG_MB_RFD2_PROD_IDX           0x15E8
+#define REG_MB_RFD3_PROD_IDX           0x15EC
+
+#define MB_PRIO_PROD_IDX_MASK          0xFFFF
+#define REG_MB_PRIO_PROD_IDX           0x15F0
+#define MB_HTPD_PROD_IDX_SHIFT         0
+#define MB_NTPD_PROD_IDX_SHIFT         16
+
+#define MB_PRIO_CONS_IDX_MASK          0xFFFF
+#define REG_MB_PRIO_CONS_IDX           0x15F4
+#define MB_HTPD_CONS_IDX_SHIFT         0
+#define MB_NTPD_CONS_IDX_SHIFT         16
+
+#define REG_MB_RFD01_CONS_IDX          0x15F8
+#define MB_RFD0_CONS_IDX_MASK          0x0000FFFF
+#define MB_RFD1_CONS_IDX_MASK          0xFFFF0000
+#define REG_MB_RFD23_CONS_IDX          0x15FC
+#define MB_RFD2_CONS_IDX_MASK          0x0000FFFF
+#define MB_RFD3_CONS_IDX_MASK          0xFFFF0000
+
+/* Interrupt Status Register */
+#define REG_ISR                        0x1600
+#define ISR_SMB                                0x00000001
+#define ISR_TIMER                      0x00000002
+/*
+ * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set
+ * in Table 51 Selene Master Control Register (Offset 0x1400).
+ */
+#define ISR_MANUAL                     0x00000004
+#define ISR_HW_RXF_OV                          0x00000008 /* RXF overflow interrupt */
+#define ISR_RFD0_UR                    0x00000010 /* RFD0 under run */
+#define ISR_RFD1_UR                    0x00000020
+#define ISR_RFD2_UR                    0x00000040
+#define ISR_RFD3_UR                    0x00000080
+#define ISR_TXF_UR                     0x00000100
+#define ISR_DMAR_TO_RST                        0x00000200
+#define ISR_DMAW_TO_RST                        0x00000400
+#define ISR_TX_CREDIT                  0x00000800
+#define ISR_GPHY                       0x00001000
+/* GPHY low power state interrupt */
+#define ISR_GPHY_LPW                           0x00002000
+#define ISR_TXQ_TO_RST                 0x00004000
+#define ISR_TX_PKT                     0x00008000
+#define ISR_RX_PKT_0                   0x00010000
+#define ISR_RX_PKT_1                   0x00020000
+#define ISR_RX_PKT_2                   0x00040000
+#define ISR_RX_PKT_3                   0x00080000
+#define ISR_MAC_RX                     0x00100000
+#define ISR_MAC_TX                     0x00200000
+#define ISR_UR_DETECTED                        0x00400000
+#define ISR_FERR_DETECTED              0x00800000
+#define ISR_NFERR_DETECTED             0x01000000
+#define ISR_CERR_DETECTED              0x02000000
+#define ISR_PHY_LINKDOWN               0x04000000
+#define ISR_DIS_INT                    0x80000000
+
+/* Interrupt Mask Register */
+#define REG_IMR                                0x1604
+
+#define IMR_NORMAL_MASK                (\
+               ISR_MANUAL      |\
+               ISR_HW_RXF_OV   |\
+               ISR_RFD0_UR     |\
+               ISR_TXF_UR      |\
+               ISR_DMAR_TO_RST |\
+               ISR_TXQ_TO_RST  |\
+               ISR_DMAW_TO_RST |\
+               ISR_GPHY        |\
+               ISR_TX_PKT      |\
+               ISR_RX_PKT_0    |\
+               ISR_GPHY_LPW    |\
+               ISR_PHY_LINKDOWN)
+
+#define ISR_RX_PKT     (\
+       ISR_RX_PKT_0    |\
+       ISR_RX_PKT_1    |\
+       ISR_RX_PKT_2    |\
+       ISR_RX_PKT_3)
+
+#define ISR_OVER       (\
+       ISR_RFD0_UR     |\
+       ISR_RFD1_UR     |\
+       ISR_RFD2_UR     |\
+       ISR_RFD3_UR     |\
+       ISR_HW_RXF_OV   |\
+       ISR_TXF_UR)
+
+#define ISR_ERROR      (\
+       ISR_DMAR_TO_RST |\
+       ISR_TXQ_TO_RST  |\
+       ISR_DMAW_TO_RST |\
+       ISR_PHY_LINKDOWN)
+
+#define REG_INT_RETRIG_TIMER           0x1608
+#define INT_RETRIG_TIMER_MASK          0xFFFF
+
+#define REG_HDS_CTRL                   0x160C
+#define HDS_CTRL_EN                    0x0001
+#define HDS_CTRL_BACKFILLSIZE_SHIFT    8
+#define HDS_CTRL_BACKFILLSIZE_MASK     0x0FFF
+#define HDS_CTRL_MAX_HDRSIZE_SHIFT     20
+#define HDS_CTRL_MAC_HDRSIZE_MASK      0x0FFF
+
+#define REG_MAC_RX_STATUS_BIN          0x1700
+#define REG_MAC_RX_STATUS_END          0x175c
+#define REG_MAC_TX_STATUS_BIN          0x1760
+#define REG_MAC_TX_STATUS_END          0x17c0
+
+/* DEBUG ADDR */
+#define REG_DEBUG_DATA0                0x1900
+#define REG_DEBUG_DATA1                0x1904
+
+/* PHY Control Register */
+#define MII_BMCR                       0x00
+#define BMCR_SPEED_SELECT_MSB          0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define BMCR_COLL_TEST_ENABLE          0x0080  /* Collision test enable */
+#define BMCR_FULL_DUPLEX               0x0100  /* FDX =1, half duplex =0 */
+#define BMCR_RESTART_AUTO_NEG          0x0200  /* Restart auto negotiation */
+#define BMCR_ISOLATE                   0x0400  /* Isolate PHY from MII */
+#define BMCR_POWER_DOWN                        0x0800  /* Power down */
+#define BMCR_AUTO_NEG_EN               0x1000  /* Auto Neg Enable */
+#define BMCR_SPEED_SELECT_LSB          0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define BMCR_LOOPBACK                  0x4000  /* 0 = normal, 1 = loopback */
+#define BMCR_RESET                     0x8000  /* 0 = normal, 1 = PHY reset */
+#define BMCR_SPEED_MASK                        0x2040
+#define BMCR_SPEED_1000                        0x0040
+#define BMCR_SPEED_100                 0x2000
+#define BMCR_SPEED_10                  0x0000
+
+/* PHY Status Register */
+#define MII_BMSR                       0x01
+#define BMMSR_EXTENDED_CAPS            0x0001  /* Extended register capabilities */
+#define BMSR_JABBER_DETECT             0x0002  /* Jabber Detected */
+#define BMSR_LINK_STATUS               0x0004  /* Link Status 1 = link */
+#define BMSR_AUTONEG_CAPS              0x0008  /* Auto Neg Capable */
+#define BMSR_REMOTE_FAULT              0x0010  /* Remote Fault Detect */
+#define BMSR_AUTONEG_COMPLETE          0x0020  /* Auto Neg Complete */
+#define BMSR_PREAMBLE_SUPPRESS         0x0040  /* Preamble may be suppressed */
+#define BMSR_EXTENDED_STATUS           0x0100  /* Ext. status info in Reg 0x0F */
+#define BMSR_100T2_HD_CAPS             0x0200  /* 100T2 Half Duplex Capable */
+#define BMSR_100T2_FD_CAPS             0x0400  /* 100T2 Full Duplex Capable */
+#define BMSR_10T_HD_CAPS               0x0800  /* 10T   Half Duplex Capable */
+#define BMSR_10T_FD_CAPS               0x1000  /* 10T   Full Duplex Capable */
+#define BMSR_100X_HD_CAPS              0x2000  /* 100X  Half Duplex Capable */
+#define BMMII_SR_100X_FD_CAPS          0x4000  /* 100X  Full Duplex Capable */
+#define BMMII_SR_100T4_CAPS            0x8000  /* 100T4 Capable */
+
+#define MII_PHYSID1                    0x02
+#define MII_PHYSID2                    0x03
+
+/* Autoneg Advertisement Register */
+#define MII_ADVERTISE                  0x04
+#define ADVERTISE_SPEED_MASK           0x01E0
+#define ADVERTISE_DEFAULT_CAP          0x0DE0
+
+/* 1000BASE-T Control Register */
+#define MII_GIGA_CR                    0x09
+#define GIGA_CR_1000T_REPEATER_DTE     0x0400  /* 1=Repeater/switch device port 0=DTE device */
+
+#define GIGA_CR_1000T_MS_VALUE         0x0800  /* 1=Configure PHY as Master 0=Configure PHY as Slave */
+#define GIGA_CR_1000T_MS_ENABLE                0x1000  /* 1=Master/Slave manual config value 0=Automatic Master/Slave config */
+#define GIGA_CR_1000T_TEST_MODE_NORMAL 0x0000  /* Normal Operation */
+#define GIGA_CR_1000T_TEST_MODE_1      0x2000  /* Transmit Waveform test */
+#define GIGA_CR_1000T_TEST_MODE_2      0x4000  /* Master Transmit Jitter test */
+#define GIGA_CR_1000T_TEST_MODE_3      0x6000  /* Slave Transmit Jitter test */
+#define GIGA_CR_1000T_TEST_MODE_4      0x8000  /* Transmitter Distortion test */
+#define GIGA_CR_1000T_SPEED_MASK       0x0300
+#define GIGA_CR_1000T_DEFAULT_CAP      0x0300
+
+/* PHY Specific Status Register */
+#define MII_GIGA_PSSR                  0x11
+#define GIGA_PSSR_SPD_DPLX_RESOLVED    0x0800  /* 1=Speed & Duplex resolved */
+#define GIGA_PSSR_DPLX                 0x2000  /* 1=Duplex 0=Half Duplex */
+#define GIGA_PSSR_SPEED                        0xC000  /* Speed, bits 14:15 */
+#define GIGA_PSSR_10MBS                        0x0000  /* 00=10Mbs */
+#define GIGA_PSSR_100MBS               0x4000  /* 01=100Mbs */
+#define GIGA_PSSR_1000MBS              0x8000  /* 10=1000Mbs */
+
+/* PHY Interrupt Enable Register */
+#define MII_IER                                0x12
+#define IER_LINK_UP                    0x0400
+#define IER_LINK_DOWN                  0x0800
+
+/* PHY Interrupt Status Register */
+#define MII_ISR                                0x13
+#define ISR_LINK_UP                    0x0400
+#define ISR_LINK_DOWN                  0x0800
+
+/* Cable-Detect-Test Control Register */
+#define MII_CDTC                       0x16
+#define CDTC_EN_OFF                    0   /* sc */
+#define CDTC_EN_BITS                   1
+#define CDTC_PAIR_OFF                  8
+#define CDTC_PAIR_BIT                  2
+
+/* Cable-Detect-Test Status Register */
+#define MII_CDTS                       0x1C
+#define CDTS_STATUS_OFF                        8
+#define CDTS_STATUS_BITS               2
+#define CDTS_STATUS_NORMAL             0
+#define CDTS_STATUS_SHORT              1
+#define CDTS_STATUS_OPEN               2
+#define CDTS_STATUS_INVALID            3
+
+#define MII_DBG_ADDR                   0x1D
+#define MII_DBG_DATA                   0x1E
+
+#define MII_ANA_CTRL_0                 0x0
+#define ANA_RESTART_CAL                        0x0001
+#define ANA_MANUL_SWICH_ON_SHIFT       0x1
+#define ANA_MANUL_SWICH_ON_MASK                0xF
+#define ANA_MAN_ENABLE                 0x0020
+#define ANA_SEL_HSP                    0x0040
+#define ANA_EN_HB                      0x0080
+#define ANA_EN_HBIAS                   0x0100
+#define ANA_OEN_125M                   0x0200
+#define ANA_EN_LCKDT                   0x0400
+#define ANA_LCKDT_PHY                  0x0800
+#define ANA_AFE_MODE                   0x1000
+#define ANA_VCO_SLOW                   0x2000
+#define ANA_VCO_FAST                   0x4000
+#define ANA_SEL_CLK125M_DSP            0x8000
+
+#define MII_ANA_CTRL_4                 0x4
+#define ANA_IECHO_ADJ_MASK             0xF
+#define ANA_IECHO_ADJ_3_SHIFT          0
+#define ANA_IECHO_ADJ_2_SHIFT          4
+#define ANA_IECHO_ADJ_1_SHIFT          8
+#define ANA_IECHO_ADJ_0_SHIFT          12
+
+#define MII_ANA_CTRL_5                 0x5
+#define ANA_SERDES_CDR_BW_SHIFT                0
+#define ANA_SERDES_CDR_BW_MASK         0x3
+#define ANA_MS_PAD_DBG                 0x0004
+#define ANA_SPEEDUP_DBG                        0x0008
+#define ANA_SERDES_TH_LOS_SHIFT                4
+#define ANA_SERDES_TH_LOS_MASK         0x3
+#define ANA_SERDES_EN_DEEM             0x0040
+#define ANA_SERDES_TXELECIDLE          0x0080
+#define ANA_SERDES_BEACON              0x0100
+#define ANA_SERDES_HALFTXDR            0x0200
+#define ANA_SERDES_SEL_HSP             0x0400
+#define ANA_SERDES_EN_PLL              0x0800
+#define ANA_SERDES_EN                  0x1000
+#define ANA_SERDES_EN_LCKDT            0x2000
+
+#define MII_ANA_CTRL_11                        0xB
+#define ANA_PS_HIB_EN                  0x8000
+
+#define MII_ANA_CTRL_18                        0x12
+#define ANA_TEST_MODE_10BT_01SHIFT     0
+#define ANA_TEST_MODE_10BT_01MASK      0x3
+#define ANA_LOOP_SEL_10BT              0x0004
+#define ANA_RGMII_MODE_SW              0x0008
+#define ANA_EN_LONGECABLE              0x0010
+#define ANA_TEST_MODE_10BT_2           0x0020
+#define ANA_EN_10BT_IDLE               0x0400
+#define ANA_EN_MASK_TB                 0x0800
+#define ANA_TRIGGER_SEL_TIMER_SHIFT    12
+#define ANA_TRIGGER_SEL_TIMER_MASK     0x3
+#define ANA_INTERVAL_SEL_TIMER_SHIFT   14
+#define ANA_INTERVAL_SEL_TIMER_MASK    0x3
+
+#define MII_ANA_CTRL_41                        0x29
+#define ANA_TOP_PS_EN                  0x8000
+
+#define MII_ANA_CTRL_54                        0x36
+#define ANA_LONG_CABLE_TH_100_SHIFT    0
+#define ANA_LONG_CABLE_TH_100_MASK     0x3F
+#define ANA_DESERVED                   0x0040
+#define ANA_EN_LIT_CH                  0x0080
+#define ANA_SHORT_CABLE_TH_100_SHIFT   8
+#define ANA_SHORT_CABLE_TH_100_MASK    0x3F
+#define ANA_BP_BAD_LINK_ACCUM          0x4000
+#define ANA_BP_SMALL_BW                        0x8000
+
+#endif /*_ATL1C_HW_H_*/
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c
new file mode 100644 (file)
index 0000000..deb7b53
--- /dev/null
@@ -0,0 +1,2797 @@
+/*
+ * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "atl1c.h"
+
+#define ATL1C_DRV_VERSION "1.0.0.1-NAPI"
+char atl1c_driver_name[] = "atl1c";
+char atl1c_driver_version[] = ATL1C_DRV_VERSION;
+#define PCI_DEVICE_ID_ATTANSIC_L2C      0x1062
+#define PCI_DEVICE_ID_ATTANSIC_L1C      0x1063
+/*
+ * atl1c_pci_tbl - PCI Device ID Table
+ *
+ * Wildcard entries (PCI_ANY_ID) should come last
+ * Last entry must be all 0s
+ *
+ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
+ *   Class, Class Mask, private data (not used) }
+ */
+static struct pci_device_id atl1c_pci_tbl[] = {
+       {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1C)},
+       {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2C)},
+       /* required last entry */
+       { 0 }
+};
+MODULE_DEVICE_TABLE(pci, atl1c_pci_tbl);
+
+MODULE_AUTHOR("Jie Yang <jie.yang@atheros.com>");
+MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(ATL1C_DRV_VERSION);
+
+static int atl1c_stop_mac(struct atl1c_hw *hw);
+static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw);
+static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw);
+static void atl1c_disable_l0s_l1(struct atl1c_hw *hw);
+static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup);
+static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter);
+static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
+                  int *work_done, int work_to_do);
+
+static const u16 atl1c_pay_load_size[] = {
+       128, 256, 512, 1024, 2048, 4096,
+};
+
+static const u16 atl1c_rfd_prod_idx_regs[AT_MAX_RECEIVE_QUEUE] =
+{
+       REG_MB_RFD0_PROD_IDX,
+       REG_MB_RFD1_PROD_IDX,
+       REG_MB_RFD2_PROD_IDX,
+       REG_MB_RFD3_PROD_IDX
+};
+
+static const u16 atl1c_rfd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] =
+{
+       REG_RFD0_HEAD_ADDR_LO,
+       REG_RFD1_HEAD_ADDR_LO,
+       REG_RFD2_HEAD_ADDR_LO,
+       REG_RFD3_HEAD_ADDR_LO
+};
+
+static const u16 atl1c_rrd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] =
+{
+       REG_RRD0_HEAD_ADDR_LO,
+       REG_RRD1_HEAD_ADDR_LO,
+       REG_RRD2_HEAD_ADDR_LO,
+       REG_RRD3_HEAD_ADDR_LO
+};
+
+static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
+       NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
+
+/*
+ * atl1c_init_pcie - init PCIE module
+ */
+static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
+{
+       u32 data;
+       u32 pci_cmd;
+       struct pci_dev *pdev = hw->adapter->pdev;
+
+       AT_READ_REG(hw, PCI_COMMAND, &pci_cmd);
+       pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+       pci_cmd |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+               PCI_COMMAND_IO);
+       AT_WRITE_REG(hw, PCI_COMMAND, pci_cmd);
+
+       /*
+        * Clear any PowerSaveing Settings
+        */
+       pci_enable_wake(pdev, PCI_D3hot, 0);
+       pci_enable_wake(pdev, PCI_D3cold, 0);
+
+       /*
+        * Mask some pcie error bits
+        */
+       AT_READ_REG(hw, REG_PCIE_UC_SEVERITY, &data);
+       data &= ~PCIE_UC_SERVRITY_DLP;
+       data &= ~PCIE_UC_SERVRITY_FCP;
+       AT_WRITE_REG(hw, REG_PCIE_UC_SEVERITY, data);
+
+       if (flag & ATL1C_PCIE_L0S_L1_DISABLE)
+               atl1c_disable_l0s_l1(hw);
+       if (flag & ATL1C_PCIE_PHY_RESET)
+               AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
+       else
+               AT_WRITE_REG(hw, REG_GPHY_CTRL,
+                       GPHY_CTRL_DEFAULT | GPHY_CTRL_EXT_RESET);
+
+       msleep(1);
+}
+
+/*
+ * atl1c_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ */
+static inline void atl1c_irq_enable(struct atl1c_adapter *adapter)
+{
+       if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
+               AT_WRITE_REG(&adapter->hw, REG_ISR, 0x7FFFFFFF);
+               AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask);
+               AT_WRITE_FLUSH(&adapter->hw);
+       }
+}
+
+/*
+ * atl1c_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1c_irq_disable(struct atl1c_adapter *adapter)
+{
+       atomic_inc(&adapter->irq_sem);
+       AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+       AT_WRITE_FLUSH(&adapter->hw);
+       synchronize_irq(adapter->pdev->irq);
+}
+
+/*
+ * atl1c_irq_reset - reset interrupt confiure on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1c_irq_reset(struct atl1c_adapter *adapter)
+{
+       atomic_set(&adapter->irq_sem, 1);
+       atl1c_irq_enable(adapter);
+}
+
+/*
+ * atl1c_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1c_phy_config(unsigned long data)
+{
+       struct atl1c_adapter *adapter = (struct atl1c_adapter *) data;
+       struct atl1c_hw *hw = &adapter->hw;
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->mdio_lock, flags);
+       atl1c_restart_autoneg(hw);
+       spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+}
+
+void atl1c_reinit_locked(struct atl1c_adapter *adapter)
+{
+
+       WARN_ON(in_interrupt());
+       atl1c_down(adapter);
+       atl1c_up(adapter);
+       clear_bit(__AT_RESETTING, &adapter->flags);
+}
+
+static void atl1c_reset_task(struct work_struct *work)
+{
+       struct atl1c_adapter *adapter;
+       struct net_device *netdev;
+
+       adapter = container_of(work, struct atl1c_adapter, reset_task);
+       netdev = adapter->netdev;
+
+       netif_device_detach(netdev);
+       atl1c_down(adapter);
+       atl1c_up(adapter);
+       netif_device_attach(netdev);
+}
+
+static void atl1c_check_link_status(struct atl1c_adapter *adapter)
+{
+       struct atl1c_hw *hw = &adapter->hw;
+       struct net_device *netdev = adapter->netdev;
+       struct pci_dev    *pdev   = adapter->pdev;
+       int err;
+       unsigned long flags;
+       u16 speed, duplex, phy_data;
+
+       spin_lock_irqsave(&adapter->mdio_lock, flags);
+       /* MII_BMSR must read twise */
+       atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
+       atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
+       spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+
+       if ((phy_data & BMSR_LSTATUS) == 0) {
+               /* link down */
+               if (netif_carrier_ok(netdev)) {
+                       hw->hibernate = true;
+                       atl1c_set_aspm(hw, false);
+                       if (atl1c_stop_mac(hw) != 0)
+                               if (netif_msg_hw(adapter))
+                                       dev_warn(&pdev->dev,
+                                               "stop mac failed\n");
+               }
+               netif_carrier_off(netdev);
+       } else {
+               /* Link Up */
+               hw->hibernate = false;
+               spin_lock_irqsave(&adapter->mdio_lock, flags);
+               err = atl1c_get_speed_and_duplex(hw, &speed, &duplex);
+               spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+               if (unlikely(err))
+                       return;
+               /* link result is our setting */
+               if (adapter->link_speed != speed ||
+                   adapter->link_duplex != duplex) {
+                       adapter->link_speed  = speed;
+                       adapter->link_duplex = duplex;
+                       atl1c_enable_tx_ctrl(hw);
+                       atl1c_enable_rx_ctrl(hw);
+                       atl1c_setup_mac_ctrl(adapter);
+                       atl1c_set_aspm(hw, true);
+                       if (netif_msg_link(adapter))
+                               dev_info(&pdev->dev,
+                                       "%s: %s NIC Link is Up<%d Mbps %s>\n",
+                                       atl1c_driver_name, netdev->name,
+                                       adapter->link_speed,
+                                       adapter->link_duplex == FULL_DUPLEX ?
+                                       "Full Duplex" : "Half Duplex");
+               }
+               if (!netif_carrier_ok(netdev))
+                       netif_carrier_on(netdev);
+       }
+}
+
+/*
+ * atl1c_link_chg_task - deal with link change event Out of interrupt context
+ * @netdev: network interface device structure
+ */
+static void atl1c_link_chg_task(struct work_struct *work)
+{
+       struct atl1c_adapter *adapter;
+
+       adapter = container_of(work, struct atl1c_adapter, link_chg_task);
+       atl1c_check_link_status(adapter);
+}
+
+static void atl1c_link_chg_event(struct atl1c_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
+       struct pci_dev    *pdev   = adapter->pdev;
+       u16 phy_data;
+       u16 link_up;
+
+       spin_lock(&adapter->mdio_lock);
+       atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+       atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+       spin_unlock(&adapter->mdio_lock);
+       link_up = phy_data & BMSR_LSTATUS;
+       /* notify upper layer link down ASAP */
+       if (!link_up) {
+               if (netif_carrier_ok(netdev)) {
+                       /* old link state: Up */
+                       netif_carrier_off(netdev);
+                       if (netif_msg_link(adapter))
+                               dev_info(&pdev->dev,
+                                       "%s: %s NIC Link is Down\n",
+                                       atl1c_driver_name, netdev->name);
+                       adapter->link_speed = SPEED_0;
+               }
+       }
+       schedule_work(&adapter->link_chg_task);
+}
+
+static void atl1c_del_timer(struct atl1c_adapter *adapter)
+{
+       del_timer_sync(&adapter->phy_config_timer);
+}
+
+static void atl1c_cancel_work(struct atl1c_adapter *adapter)
+{
+       cancel_work_sync(&adapter->reset_task);
+       cancel_work_sync(&adapter->link_chg_task);
+}
+
+/*
+ * atl1c_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ */
+static void atl1c_tx_timeout(struct net_device *netdev)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+       /* Do the reset outside of interrupt context */
+       schedule_work(&adapter->reset_task);
+}
+
+/*
+ * atl1c_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated.  This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ */
+static void atl1c_set_multi(struct net_device *netdev)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       struct atl1c_hw *hw = &adapter->hw;
+       struct dev_mc_list *mc_ptr;
+       u32 mac_ctrl_data;
+       u32 hash_value;
+
+       /* Check for Promiscuous and All Multicast modes */
+       AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data);
+
+       if (netdev->flags & IFF_PROMISC) {
+               mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
+       } else if (netdev->flags & IFF_ALLMULTI) {
+               mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
+               mac_ctrl_data &= ~MAC_CTRL_PROMIS_EN;
+       } else {
+               mac_ctrl_data &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+       }
+
+       AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+
+       /* clear the old settings from the multicast hash table */
+       AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+       AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+       /* comoute mc addresses' hash value ,and put it into hash table */
+       for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+               hash_value = atl1c_hash_mc_addr(hw, mc_ptr->dmi_addr);
+               atl1c_hash_set(hw, hash_value);
+       }
+}
+
+static void atl1c_vlan_rx_register(struct net_device *netdev,
+                                  struct vlan_group *grp)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       struct pci_dev *pdev = adapter->pdev;
+       u32 mac_ctrl_data = 0;
+
+       if (netif_msg_pktdata(adapter))
+               dev_dbg(&pdev->dev, "atl1c_vlan_rx_register\n");
+
+       atl1c_irq_disable(adapter);
+
+       adapter->vlgrp = grp;
+       AT_READ_REG(&adapter->hw, REG_MAC_CTRL, &mac_ctrl_data);
+
+       if (grp) {
+               /* enable VLAN tag insert/strip */
+               mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+       } else {
+               /* disable VLAN tag insert/strip */
+               mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN;
+       }
+
+       AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data);
+       atl1c_irq_enable(adapter);
+}
+
+static void atl1c_restore_vlan(struct atl1c_adapter *adapter)
+{
+       struct pci_dev *pdev = adapter->pdev;
+
+       if (netif_msg_pktdata(adapter))
+               dev_dbg(&pdev->dev, "atl1c_restore_vlan !");
+       atl1c_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+}
+/*
+ * atl1c_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1c_set_mac_addr(struct net_device *netdev, void *p)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       struct sockaddr *addr = p;
+
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       if (netif_running(netdev))
+               return -EBUSY;
+
+       memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+       memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+       atl1c_hw_set_mac_addr(&adapter->hw);
+
+       return 0;
+}
+
+static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter,
+                               struct net_device *dev)
+{
+       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;
+}
+/*
+ * atl1c_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1c_change_mtu(struct net_device *netdev, int new_mtu)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       int old_mtu   = netdev->mtu;
+       int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+
+       if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
+                       (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+               if (netif_msg_link(adapter))
+                       dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
+               return -EINVAL;
+       }
+       /* set MTU */
+       if (old_mtu != new_mtu && netif_running(netdev)) {
+               while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+                       msleep(1);
+               netdev->mtu = new_mtu;
+               adapter->hw.max_frame_size = new_mtu;
+               atl1c_set_rxbufsize(adapter, netdev);
+               atl1c_down(adapter);
+               atl1c_up(adapter);
+               clear_bit(__AT_RESETTING, &adapter->flags);
+               if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) {
+                       u32 phy_data;
+
+                       AT_READ_REG(&adapter->hw, 0x1414, &phy_data);
+                       phy_data |= 0x10000000;
+                       AT_WRITE_REG(&adapter->hw, 0x1414, phy_data);
+               }
+
+       }
+       return 0;
+}
+
+/*
+ *  caller should hold mdio_lock
+ */
+static int atl1c_mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       u16 result;
+
+       atl1c_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result);
+       return result;
+}
+
+static void atl1c_mdio_write(struct net_device *netdev, int phy_id,
+                            int reg_num, int val)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+       atl1c_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val);
+}
+
+/*
+ * atl1c_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1c_mii_ioctl(struct net_device *netdev,
+                          struct ifreq *ifr, int cmd)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       struct pci_dev *pdev = adapter->pdev;
+       struct mii_ioctl_data *data = if_mii(ifr);
+       unsigned long flags;
+       int retval = 0;
+
+       if (!netif_running(netdev))
+               return -EINVAL;
+
+       spin_lock_irqsave(&adapter->mdio_lock, flags);
+       switch (cmd) {
+       case SIOCGMIIPHY:
+               data->phy_id = 0;
+               break;
+
+       case SIOCGMIIREG:
+               if (!capable(CAP_NET_ADMIN)) {
+                       retval = -EPERM;
+                       goto out;
+               }
+               if (atl1c_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+                                   &data->val_out)) {
+                       retval = -EIO;
+                       goto out;
+               }
+               break;
+
+       case SIOCSMIIREG:
+               if (!capable(CAP_NET_ADMIN)) {
+                       retval = -EPERM;
+                       goto out;
+               }
+               if (data->reg_num & ~(0x1F)) {
+                       retval = -EFAULT;
+                       goto out;
+               }
+
+               dev_dbg(&pdev->dev, "<atl1c_mii_ioctl> write %x %x",
+                               data->reg_num, data->val_in);
+               if (atl1c_write_phy_reg(&adapter->hw,
+                                    data->reg_num, data->val_in)) {
+                       retval = -EIO;
+                       goto out;
+               }
+               break;
+
+       default:
+               retval = -EOPNOTSUPP;
+               break;
+       }
+out:
+       spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+       return retval;
+}
+
+/*
+ * atl1c_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1c_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+       switch (cmd) {
+       case SIOCGMIIPHY:
+       case SIOCGMIIREG:
+       case SIOCSMIIREG:
+               return atl1c_mii_ioctl(netdev, ifr, cmd);
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
+/*
+ * atl1c_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ */
+static int __devinit atl1c_alloc_queues(struct atl1c_adapter *adapter)
+{
+       return 0;
+}
+
+static void atl1c_set_mac_type(struct atl1c_hw *hw)
+{
+       switch (hw->device_id) {
+       case PCI_DEVICE_ID_ATTANSIC_L2C:
+               hw->nic_type = athr_l2c;
+               break;
+
+       case PCI_DEVICE_ID_ATTANSIC_L1C:
+               hw->nic_type = athr_l1c;
+               break;
+
+       default:
+               break;
+       }
+}
+
+static int atl1c_setup_mac_funcs(struct atl1c_hw *hw)
+{
+       u32 phy_status_data;
+       u32 link_ctrl_data;
+
+       atl1c_set_mac_type(hw);
+       AT_READ_REG(hw, REG_PHY_STATUS, &phy_status_data);
+       AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data);
+
+       hw->ctrl_flags = ATL1C_INTR_CLEAR_ON_READ |
+                        ATL1C_INTR_MODRT_ENABLE  |
+                        ATL1C_RX_IPV6_CHKSUM     |
+                        ATL1C_TXQ_MODE_ENHANCE;
+       if (link_ctrl_data & LINK_CTRL_L0S_EN)
+               hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT;
+       if (link_ctrl_data & LINK_CTRL_L1_EN)
+               hw->ctrl_flags |= ATL1C_ASPM_L1_SUPPORT;
+
+       if (hw->nic_type == athr_l1c) {
+               hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON;
+               hw->ctrl_flags |= ATL1C_LINK_CAP_1000M;
+       }
+       return 0;
+}
+/*
+ * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * atl1c_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ */
+static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
+{
+       struct atl1c_hw *hw   = &adapter->hw;
+       struct pci_dev  *pdev = adapter->pdev;
+
+       adapter->wol = 0;
+       adapter->link_speed = SPEED_0;
+       adapter->link_duplex = FULL_DUPLEX;
+       adapter->num_rx_queues = AT_DEF_RECEIVE_QUEUE;
+       adapter->tpd_ring[0].count = 1024;
+       adapter->rfd_ring[0].count = 512;
+
+       hw->vendor_id = pdev->vendor;
+       hw->device_id = pdev->device;
+       hw->subsystem_vendor_id = pdev->subsystem_vendor;
+       hw->subsystem_id = pdev->subsystem_device;
+
+       /* before link up, we assume hibernate is true */
+       hw->hibernate = true;
+       hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
+       if (atl1c_setup_mac_funcs(hw) != 0) {
+               dev_err(&pdev->dev, "set mac function pointers failed\n");
+               return -1;
+       }
+       hw->intr_mask = IMR_NORMAL_MASK;
+       hw->phy_configured = false;
+       hw->preamble_len = 7;
+       hw->max_frame_size = adapter->netdev->mtu;
+       if (adapter->num_rx_queues < 2) {
+               hw->rss_type = atl1c_rss_disable;
+               hw->rss_mode = atl1c_rss_mode_disable;
+       } else {
+               hw->rss_type = atl1c_rss_ipv4;
+               hw->rss_mode = atl1c_rss_mul_que_mul_int;
+               hw->rss_hash_bits = 16;
+       }
+       hw->autoneg_advertised = ADVERTISED_Autoneg;
+       hw->indirect_tab = 0xE4E4E4E4;
+       hw->base_cpu = 0;
+
+       hw->ict = 50000;                /* 100ms */
+       hw->smb_timer = 200000;         /* 400ms */
+       hw->cmb_tpd = 4;
+       hw->cmb_tx_timer = 1;           /* 2 us  */
+       hw->rx_imt = 200;
+       hw->tx_imt = 1000;
+
+       hw->tpd_burst = 5;
+       hw->rfd_burst = 8;
+       hw->dma_order = atl1c_dma_ord_out;
+       hw->dmar_block = atl1c_dma_req_1024;
+       hw->dmaw_block = atl1c_dma_req_1024;
+       hw->dmar_dly_cnt = 15;
+       hw->dmaw_dly_cnt = 4;
+
+       if (atl1c_alloc_queues(adapter)) {
+               dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
+               return -ENOMEM;
+       }
+       /* TODO */
+       atl1c_set_rxbufsize(adapter, adapter->netdev);
+       atomic_set(&adapter->irq_sem, 1);
+       spin_lock_init(&adapter->mdio_lock);
+       spin_lock_init(&adapter->tx_lock);
+       set_bit(__AT_DOWN, &adapter->flags);
+
+       return 0;
+}
+
+/*
+ * atl1c_clean_tx_ring - Free Tx-skb
+ * @adapter: board private structure
+ */
+static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter,
+                               enum atl1c_trans_queue type)
+{
+       struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
+       struct atl1c_buffer *buffer_info;
+       struct pci_dev *pdev = adapter->pdev;
+       u16 index, ring_count;
+
+       ring_count = tpd_ring->count;
+       for (index = 0; index < ring_count; index++) {
+               buffer_info = &tpd_ring->buffer_info[index];
+               if (buffer_info->state == ATL1_BUFFER_FREE)
+                       continue;
+               if (buffer_info->dma)
+                       pci_unmap_single(pdev, buffer_info->dma,
+                                       buffer_info->length,
+                                       PCI_DMA_TODEVICE);
+               if (buffer_info->skb)
+                       dev_kfree_skb(buffer_info->skb);
+               buffer_info->dma = 0;
+               buffer_info->skb = NULL;
+               buffer_info->state = ATL1_BUFFER_FREE;
+       }
+
+       /* Zero out Tx-buffers */
+       memset(tpd_ring->desc, 0, sizeof(struct atl1c_tpd_desc) *
+                               ring_count);
+       atomic_set(&tpd_ring->next_to_clean, 0);
+       tpd_ring->next_to_use = 0;
+}
+
+/*
+ * atl1c_clean_rx_ring - Free rx-reservation skbs
+ * @adapter: board private structure
+ */
+static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter)
+{
+       struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
+       struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+       struct atl1c_buffer *buffer_info;
+       struct pci_dev *pdev = adapter->pdev;
+       int i, j;
+
+       for (i = 0; i < adapter->num_rx_queues; i++) {
+               for (j = 0; j < rfd_ring[i].count; j++) {
+                       buffer_info = &rfd_ring[i].buffer_info[j];
+                       if (buffer_info->state == ATL1_BUFFER_FREE)
+                               continue;
+                       if (buffer_info->dma)
+                               pci_unmap_single(pdev, buffer_info->dma,
+                                               buffer_info->length,
+                                               PCI_DMA_FROMDEVICE);
+                       if (buffer_info->skb)
+                               dev_kfree_skb(buffer_info->skb);
+                       buffer_info->state = ATL1_BUFFER_FREE;
+                       buffer_info->skb = NULL;
+               }
+               /* zero out the descriptor ring */
+               memset(rfd_ring[i].desc, 0, rfd_ring[i].size);
+               rfd_ring[i].next_to_clean = 0;
+               rfd_ring[i].next_to_use = 0;
+               rrd_ring[i].next_to_use = 0;
+               rrd_ring[i].next_to_clean = 0;
+       }
+}
+
+/*
+ * Read / Write Ptr Initialize:
+ */
+static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter)
+{
+       struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
+       struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
+       struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+       struct atl1c_buffer *buffer_info;
+       int i, j;
+
+       for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) {
+               tpd_ring[i].next_to_use = 0;
+               atomic_set(&tpd_ring[i].next_to_clean, 0);
+               buffer_info = tpd_ring[i].buffer_info;
+               for (j = 0; j < tpd_ring->count; j++)
+                       buffer_info[i].state = ATL1_BUFFER_FREE;
+       }
+       for (i = 0; i < adapter->num_rx_queues; i++) {
+               rfd_ring[i].next_to_use = 0;
+               rfd_ring[i].next_to_clean = 0;
+               rrd_ring[i].next_to_use = 0;
+               rrd_ring[i].next_to_clean = 0;
+               for (j = 0; j < rfd_ring[i].count; j++) {
+                       buffer_info = &rfd_ring[i].buffer_info[j];
+                       buffer_info->state = ATL1_BUFFER_FREE;
+               }
+       }
+}
+
+/*
+ * atl1c_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+static void atl1c_free_ring_resources(struct atl1c_adapter *adapter)
+{
+       struct pci_dev *pdev = adapter->pdev;
+
+       pci_free_consistent(pdev, adapter->ring_header.size,
+                                       adapter->ring_header.desc,
+                                       adapter->ring_header.dma);
+       adapter->ring_header.desc = NULL;
+
+       /* Note: just free tdp_ring.buffer_info,
+       *  it contain rfd_ring.buffer_info, do not double free */
+       if (adapter->tpd_ring[0].buffer_info) {
+               kfree(adapter->tpd_ring[0].buffer_info);
+               adapter->tpd_ring[0].buffer_info = NULL;
+       }
+}
+
+/*
+ * atl1c_setup_mem_resources - allocate Tx / RX descriptor resources
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ */
+static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
+{
+       struct pci_dev *pdev = adapter->pdev;
+       struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
+       struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
+       struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+       struct atl1c_ring_header *ring_header = &adapter->ring_header;
+       int num_rx_queues = adapter->num_rx_queues;
+       int size;
+       int i;
+       int count = 0;
+       int rx_desc_count = 0;
+       u32 offset = 0;
+
+       rrd_ring[0].count = rfd_ring[0].count;
+       for (i = 1; i < AT_MAX_TRANSMIT_QUEUE; i++)
+               tpd_ring[i].count = tpd_ring[0].count;
+
+       for (i = 1; i < adapter->num_rx_queues; i++)
+               rfd_ring[i].count = rrd_ring[i].count = rfd_ring[0].count;
+
+       /* 2 tpd queue, one high priority queue,
+        * another normal priority queue */
+       size = sizeof(struct atl1c_buffer) * (tpd_ring->count * 2 +
+               rfd_ring->count * num_rx_queues);
+       tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
+       if (unlikely(!tpd_ring->buffer_info)) {
+               dev_err(&pdev->dev, "kzalloc failed, size = %d\n",
+                       size);
+               goto err_nomem;
+       }
+       for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) {
+               tpd_ring[i].buffer_info =
+                       (struct atl1c_buffer *) (tpd_ring->buffer_info + count);
+               count += tpd_ring[i].count;
+       }
+
+       for (i = 0; i < num_rx_queues; i++) {
+               rfd_ring[i].buffer_info =
+                       (struct atl1c_buffer *) (tpd_ring->buffer_info + count);
+               count += rfd_ring[i].count;
+               rx_desc_count += rfd_ring[i].count;
+       }
+       /*
+        * real ring DMA buffer
+        * each ring/block may need up to 8 bytes for alignment, hence the
+        * additional bytes tacked onto the end.
+        */
+       ring_header->size = size =
+               sizeof(struct atl1c_tpd_desc) * tpd_ring->count * 2 +
+               sizeof(struct atl1c_rx_free_desc) * rx_desc_count +
+               sizeof(struct atl1c_recv_ret_status) * rx_desc_count +
+               sizeof(struct atl1c_hw_stats) +
+               8 * 4 + 8 * 2 * num_rx_queues;
+
+       ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
+                               &ring_header->dma);
+       if (unlikely(!ring_header->desc)) {
+               dev_err(&pdev->dev, "pci_alloc_consistend failed\n");
+               goto err_nomem;
+       }
+       memset(ring_header->desc, 0, ring_header->size);
+       /* init TPD ring */
+
+       tpd_ring[0].dma = roundup(ring_header->dma, 8);
+       offset = tpd_ring[0].dma - ring_header->dma;
+       for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) {
+               tpd_ring[i].dma = ring_header->dma + offset;
+               tpd_ring[i].desc = (u8 *) ring_header->desc + offset;
+               tpd_ring[i].size =
+                       sizeof(struct atl1c_tpd_desc) * tpd_ring[i].count;
+               offset += roundup(tpd_ring[i].size, 8);
+       }
+       /* init RFD ring */
+       for (i = 0; i < num_rx_queues; i++) {
+               rfd_ring[i].dma = ring_header->dma + offset;
+               rfd_ring[i].desc = (u8 *) ring_header->desc + offset;
+               rfd_ring[i].size = sizeof(struct atl1c_rx_free_desc) *
+                               rfd_ring[i].count;
+               offset += roundup(rfd_ring[i].size, 8);
+       }
+
+       /* init RRD ring */
+       for (i = 0; i < num_rx_queues; i++) {
+               rrd_ring[i].dma = ring_header->dma + offset;
+               rrd_ring[i].desc = (u8 *) ring_header->desc + offset;
+               rrd_ring[i].size = sizeof(struct atl1c_recv_ret_status) *
+                               rrd_ring[i].count;
+               offset += roundup(rrd_ring[i].size, 8);
+       }
+
+       adapter->smb.dma = ring_header->dma + offset;
+       adapter->smb.smb = (u8 *)ring_header->desc + offset;
+       return 0;
+
+err_nomem:
+       kfree(tpd_ring->buffer_info);
+       return -ENOMEM;
+}
+
+static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
+{
+       struct atl1c_hw *hw = &adapter->hw;
+       struct atl1c_rfd_ring *rfd_ring = (struct atl1c_rfd_ring *)
+                               adapter->rfd_ring;
+       struct atl1c_rrd_ring *rrd_ring = (struct atl1c_rrd_ring *)
+                               adapter->rrd_ring;
+       struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *)
+                               adapter->tpd_ring;
+       struct atl1c_cmb *cmb = (struct atl1c_cmb *) &adapter->cmb;
+       struct atl1c_smb *smb = (struct atl1c_smb *) &adapter->smb;
+       int i;
+
+       /* TPD */
+       AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI,
+                       (u32)((tpd_ring[atl1c_trans_normal].dma &
+                               AT_DMA_HI_ADDR_MASK) >> 32));
+       /* just enable normal priority TX queue */
+       AT_WRITE_REG(hw, REG_NTPD_HEAD_ADDR_LO,
+                       (u32)(tpd_ring[atl1c_trans_normal].dma &
+                               AT_DMA_LO_ADDR_MASK));
+       AT_WRITE_REG(hw, REG_HTPD_HEAD_ADDR_LO,
+                       (u32)(tpd_ring[atl1c_trans_high].dma &
+                               AT_DMA_LO_ADDR_MASK));
+       AT_WRITE_REG(hw, REG_TPD_RING_SIZE,
+                       (u32)(tpd_ring[0].count & TPD_RING_SIZE_MASK));
+
+
+       /* RFD */
+       AT_WRITE_REG(hw, REG_RX_BASE_ADDR_HI,
+                       (u32)((rfd_ring[0].dma & AT_DMA_HI_ADDR_MASK) >> 32));
+       for (i = 0; i < adapter->num_rx_queues; i++)
+               AT_WRITE_REG(hw, atl1c_rfd_addr_lo_regs[i],
+                       (u32)(rfd_ring[i].dma & AT_DMA_LO_ADDR_MASK));
+
+       AT_WRITE_REG(hw, REG_RFD_RING_SIZE,
+                       rfd_ring[0].count & RFD_RING_SIZE_MASK);
+       AT_WRITE_REG(hw, REG_RX_BUF_SIZE,
+                       adapter->rx_buffer_len & RX_BUF_SIZE_MASK);
+
+       /* RRD */
+       for (i = 0; i < adapter->num_rx_queues; i++)
+               AT_WRITE_REG(hw, atl1c_rrd_addr_lo_regs[i],
+                       (u32)(rrd_ring[i].dma & AT_DMA_LO_ADDR_MASK));
+       AT_WRITE_REG(hw, REG_RRD_RING_SIZE,
+                       (rrd_ring[0].count & RRD_RING_SIZE_MASK));
+
+       /* CMB */
+       AT_WRITE_REG(hw, REG_CMB_BASE_ADDR_LO, cmb->dma & AT_DMA_LO_ADDR_MASK);
+
+       /* SMB */
+       AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_HI,
+                       (u32)((smb->dma & AT_DMA_HI_ADDR_MASK) >> 32));
+       AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_LO,
+                       (u32)(smb->dma & AT_DMA_LO_ADDR_MASK));
+       /* Load all of base address above */
+       AT_WRITE_REG(hw, REG_LOAD_PTR, 1);
+}
+
+static void atl1c_configure_tx(struct atl1c_adapter *adapter)
+{
+       struct atl1c_hw *hw = &adapter->hw;
+       u32 dev_ctrl_data;
+       u32 max_pay_load;
+       u16 tx_offload_thresh;
+       u32 txq_ctrl_data;
+       u32 extra_size = 0;     /* Jumbo frame threshold in QWORD unit */
+
+       extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
+       tx_offload_thresh = MAX_TX_OFFLOAD_THRESH;
+       AT_WRITE_REG(hw, REG_TX_TSO_OFFLOAD_THRESH,
+               (tx_offload_thresh >> 3) & TX_TSO_OFFLOAD_THRESH_MASK);
+       AT_READ_REG(hw, REG_DEVICE_CTRL, &dev_ctrl_data);
+       max_pay_load  = (dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT) &
+                       DEVICE_CTRL_MAX_PAYLOAD_MASK;
+       hw->dmaw_block = min(max_pay_load, hw->dmaw_block);
+       max_pay_load  = (dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT) &
+                       DEVICE_CTRL_MAX_RREQ_SZ_MASK;
+       hw->dmar_block = min(max_pay_load, hw->dmar_block);
+
+       txq_ctrl_data = (hw->tpd_burst & TXQ_NUM_TPD_BURST_MASK) <<
+                       TXQ_NUM_TPD_BURST_SHIFT;
+       if (hw->ctrl_flags & ATL1C_TXQ_MODE_ENHANCE)
+               txq_ctrl_data |= TXQ_CTRL_ENH_MODE;
+       txq_ctrl_data |= (atl1c_pay_load_size[hw->dmar_block] &
+                       TXQ_TXF_BURST_NUM_MASK) << TXQ_TXF_BURST_NUM_SHIFT;
+
+       AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data);
+}
+
+static void atl1c_configure_rx(struct atl1c_adapter *adapter)
+{
+       struct atl1c_hw *hw = &adapter->hw;
+       u32 rxq_ctrl_data;
+
+       rxq_ctrl_data = (hw->rfd_burst & RXQ_RFD_BURST_NUM_MASK) <<
+                       RXQ_RFD_BURST_NUM_SHIFT;
+
+       if (hw->ctrl_flags & ATL1C_RX_IPV6_CHKSUM)
+               rxq_ctrl_data |= IPV6_CHKSUM_CTRL_EN;
+       if (hw->rss_type == atl1c_rss_ipv4)
+               rxq_ctrl_data |= RSS_HASH_IPV4;
+       if (hw->rss_type == atl1c_rss_ipv4_tcp)
+               rxq_ctrl_data |= RSS_HASH_IPV4_TCP;
+       if (hw->rss_type == atl1c_rss_ipv6)
+               rxq_ctrl_data |= RSS_HASH_IPV6;
+       if (hw->rss_type == atl1c_rss_ipv6_tcp)
+               rxq_ctrl_data |= RSS_HASH_IPV6_TCP;
+       if (hw->rss_type != atl1c_rss_disable)
+               rxq_ctrl_data |= RRS_HASH_CTRL_EN;
+
+       rxq_ctrl_data |= (hw->rss_mode & RSS_MODE_MASK) <<
+                       RSS_MODE_SHIFT;
+       rxq_ctrl_data |= (hw->rss_hash_bits & RSS_HASH_BITS_MASK) <<
+                       RSS_HASH_BITS_SHIFT;
+       if (hw->ctrl_flags & ATL1C_ASPM_CTRL_MON)
+               rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_100M &
+                       ASPM_THRUPUT_LIMIT_MASK) << ASPM_THRUPUT_LIMIT_SHIFT;
+
+       AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
+}
+
+static void atl1c_configure_rss(struct atl1c_adapter *adapter)
+{
+       struct atl1c_hw *hw = &adapter->hw;
+
+       AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab);
+       AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu);
+}
+
+static void atl1c_configure_dma(struct atl1c_adapter *adapter)
+{
+       struct atl1c_hw *hw = &adapter->hw;
+       u32 dma_ctrl_data;
+
+       dma_ctrl_data = DMA_CTRL_DMAR_REQ_PRI;
+       if (hw->ctrl_flags & ATL1C_CMB_ENABLE)
+               dma_ctrl_data |= DMA_CTRL_CMB_EN;
+       if (hw->ctrl_flags & ATL1C_SMB_ENABLE)
+               dma_ctrl_data |= DMA_CTRL_SMB_EN;
+       else
+               dma_ctrl_data |= MAC_CTRL_SMB_DIS;
+
+       switch (hw->dma_order) {
+       case atl1c_dma_ord_in:
+               dma_ctrl_data |= DMA_CTRL_DMAR_IN_ORDER;
+               break;
+       case atl1c_dma_ord_enh:
+               dma_ctrl_data |= DMA_CTRL_DMAR_ENH_ORDER;
+               break;
+       case atl1c_dma_ord_out:
+               dma_ctrl_data |= DMA_CTRL_DMAR_OUT_ORDER;
+               break;
+       default:
+               break;
+       }
+
+       dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+               << DMA_CTRL_DMAR_BURST_LEN_SHIFT;
+       dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
+               << DMA_CTRL_DMAW_BURST_LEN_SHIFT;
+       dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK)
+               << DMA_CTRL_DMAR_DLY_CNT_SHIFT;
+       dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK)
+               << DMA_CTRL_DMAW_DLY_CNT_SHIFT;
+
+       AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data);
+}
+
+/*
+ * Stop the mac, transmit and receive units
+ * hw - Struct containing variables accessed by shared code
+ * return : 0  or  idle status (if error)
+ */
+static int atl1c_stop_mac(struct atl1c_hw *hw)
+{
+       u32 data;
+       int timeout;
+
+       AT_READ_REG(hw, REG_RXQ_CTRL, &data);
+       data &= ~(RXQ1_CTRL_EN | RXQ2_CTRL_EN |
+                 RXQ3_CTRL_EN | RXQ_CTRL_EN);
+       AT_WRITE_REG(hw, REG_RXQ_CTRL, data);
+
+       AT_READ_REG(hw, REG_TXQ_CTRL, &data);
+       data &= ~TXQ_CTRL_EN;
+       AT_WRITE_REG(hw, REG_TWSI_CTRL, data);
+
+       for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
+               AT_READ_REG(hw, REG_IDLE_STATUS, &data);
+               if ((data & (IDLE_STATUS_RXQ_NO_IDLE |
+                       IDLE_STATUS_TXQ_NO_IDLE)) == 0)
+                       break;
+               msleep(1);
+       }
+
+       AT_READ_REG(hw, REG_MAC_CTRL, &data);
+       data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN);
+       AT_WRITE_REG(hw, REG_MAC_CTRL, data);
+
+       for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
+               AT_READ_REG(hw, REG_IDLE_STATUS, &data);
+               if ((data & IDLE_STATUS_MASK) == 0)
+                       return 0;
+               msleep(1);
+       }
+       return data;
+}
+
+static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw)
+{
+       u32 data;
+
+       AT_READ_REG(hw, REG_RXQ_CTRL, &data);
+       switch (hw->adapter->num_rx_queues) {
+       case 4:
+               data |= (RXQ3_CTRL_EN | RXQ2_CTRL_EN | RXQ1_CTRL_EN);
+               break;
+       case 3:
+               data |= (RXQ2_CTRL_EN | RXQ1_CTRL_EN);
+               break;
+       case 2:
+               data |= RXQ1_CTRL_EN;
+               break;
+       default:
+               break;
+       }
+       data |= RXQ_CTRL_EN;
+       AT_WRITE_REG(hw, REG_RXQ_CTRL, data);
+}
+
+static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw)
+{
+       u32 data;
+
+       AT_READ_REG(hw, REG_TXQ_CTRL, &data);
+       data |= TXQ_CTRL_EN;
+       AT_WRITE_REG(hw, REG_TXQ_CTRL, data);
+}
+
+/*
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ * hw - Struct containing variables accessed by shared code
+ * return : 0  or  idle status (if error)
+ */
+static int atl1c_reset_mac(struct atl1c_hw *hw)
+{
+       struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
+       struct pci_dev *pdev = adapter->pdev;
+       u32 idle_status_data = 0;
+       int timeout = 0;
+       int ret;
+
+       AT_WRITE_REG(hw, REG_IMR, 0);
+       AT_WRITE_REG(hw, REG_ISR, ISR_DIS_INT);
+
+       ret = atl1c_stop_mac(hw);
+       if (ret)
+               return ret;
+       /*
+        * Issue Soft Reset to the MAC.  This will reset the chip's
+        * transmit, receive, DMA.  It will not effect
+        * the current PCI configuration.  The global reset bit is self-
+        * clearing, and should clear within a microsecond.
+        */
+       AT_WRITE_REGW(hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST);
+       AT_WRITE_FLUSH(hw);
+       msleep(10);
+       /* Wait at least 10ms for All module to be Idle */
+       for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
+               AT_READ_REG(hw, REG_IDLE_STATUS, &idle_status_data);
+               if ((idle_status_data & IDLE_STATUS_MASK) == 0)
+                       break;
+               msleep(1);
+       }
+       if (timeout >= AT_HW_MAX_IDLE_DELAY) {
+               dev_err(&pdev->dev,
+                       "MAC state machine cann't be idle since"
+                       " disabled for 10ms second\n");
+               return -1;
+       }
+       return 0;
+}
+
+static void atl1c_disable_l0s_l1(struct atl1c_hw *hw)
+{
+       u32 pm_ctrl_data;
+
+       AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data);
+       pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
+                       PM_CTRL_L1_ENTRY_TIMER_SHIFT);
+       pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1;
+       pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
+       pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
+       pm_ctrl_data &= ~PM_CTRL_MAC_ASPM_CHK;
+       pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1;
+
+       pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN;
+       pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN;
+       pm_ctrl_data |= PM_CTRL_SERDES_L1_EN;
+       AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data);
+}
+
+/*
+ * Set ASPM state.
+ * Enable/disable L0s/L1 depend on link state.
+ */
+static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup)
+{
+       u32 pm_ctrl_data;
+
+       AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data);
+
+       pm_ctrl_data &= PM_CTRL_SERDES_PD_EX_L1;
+       pm_ctrl_data |= ~PM_CTRL_SERDES_BUDS_RX_L1_EN;
+       pm_ctrl_data |= ~PM_CTRL_SERDES_L1_EN;
+       pm_ctrl_data &=  ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
+                       PM_CTRL_L1_ENTRY_TIMER_SHIFT);
+
+       pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK;
+
+       if (linkup) {
+               pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN;
+               pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1;
+
+               if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) {
+                       pm_ctrl_data |= AT_ASPM_L1_TIMER <<
+                               PM_CTRL_L1_ENTRY_TIMER_SHIFT;
+                       pm_ctrl_data |= PM_CTRL_ASPM_L1_EN;
+               } else
+                       pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
+
+               if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT)
+                       pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN;
+               else
+                       pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
+
+       } else {
+               pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
+               pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN;
+
+               pm_ctrl_data |= PM_CTRL_CLK_SWH_L1;
+
+               if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT)
+                       pm_ctrl_data |= PM_CTRL_ASPM_L1_EN;
+               else
+                       pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
+       }
+
+       AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data);
+}
+
+static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter)
+{
+       struct atl1c_hw *hw = &adapter->hw;
+       struct net_device *netdev = adapter->netdev;
+       u32 mac_ctrl_data;
+
+       mac_ctrl_data = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
+       mac_ctrl_data |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+
+       if (adapter->link_duplex == FULL_DUPLEX) {
+               hw->mac_duplex = true;
+               mac_ctrl_data |= MAC_CTRL_DUPLX;
+       }
+
+       if (adapter->link_speed == SPEED_1000)
+               hw->mac_speed = atl1c_mac_speed_1000;
+       else
+               hw->mac_speed = atl1c_mac_speed_10_100;
+
+       mac_ctrl_data |= (hw->mac_speed & MAC_CTRL_SPEED_MASK) <<
+                       MAC_CTRL_SPEED_SHIFT;
+
+       mac_ctrl_data |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+       mac_ctrl_data |= ((hw->preamble_len & MAC_CTRL_PRMLEN_MASK) <<
+                       MAC_CTRL_PRMLEN_SHIFT);
+
+       if (adapter->vlgrp)
+               mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+
+       mac_ctrl_data |= MAC_CTRL_BC_EN;
+       if (netdev->flags & IFF_PROMISC)
+               mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
+       if (netdev->flags & IFF_ALLMULTI)
+               mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
+
+       mac_ctrl_data |= MAC_CTRL_SINGLE_PAUSE_EN;
+       AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+}
+
+/*
+ * atl1c_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+static int atl1c_configure(struct atl1c_adapter *adapter)
+{
+       struct atl1c_hw *hw = &adapter->hw;
+       u32 master_ctrl_data = 0;
+       u32 intr_modrt_data;
+
+       /* clear interrupt status */
+       AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF);
+       /*  Clear any WOL status */
+       AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+       /* set Interrupt Clear Timer
+        * HW will enable self to assert interrupt event to system after
+        * waiting x-time for software to notify it accept interrupt.
+        */
+       AT_WRITE_REG(hw, REG_INT_RETRIG_TIMER,
+               hw->ict & INT_RETRIG_TIMER_MASK);
+
+       atl1c_configure_des_ring(adapter);
+
+       if (hw->ctrl_flags & ATL1C_INTR_MODRT_ENABLE) {
+               intr_modrt_data = (hw->tx_imt & IRQ_MODRT_TIMER_MASK) <<
+                                       IRQ_MODRT_TX_TIMER_SHIFT;
+               intr_modrt_data |= (hw->rx_imt & IRQ_MODRT_TIMER_MASK) <<
+                                       IRQ_MODRT_RX_TIMER_SHIFT;
+               AT_WRITE_REG(hw, REG_IRQ_MODRT_TIMER_INIT, intr_modrt_data);
+               master_ctrl_data |=
+                       MASTER_CTRL_TX_ITIMER_EN | MASTER_CTRL_RX_ITIMER_EN;
+       }
+
+       if (hw->ctrl_flags & ATL1C_INTR_CLEAR_ON_READ)
+               master_ctrl_data |= MASTER_CTRL_INT_RDCLR;
+
+       AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
+
+       if (hw->ctrl_flags & ATL1C_CMB_ENABLE) {
+               AT_WRITE_REG(hw, REG_CMB_TPD_THRESH,
+                       hw->cmb_tpd & CMB_TPD_THRESH_MASK);
+               AT_WRITE_REG(hw, REG_CMB_TX_TIMER,
+                       hw->cmb_tx_timer & CMB_TX_TIMER_MASK);
+       }
+
+       if (hw->ctrl_flags & ATL1C_SMB_ENABLE)
+               AT_WRITE_REG(hw, REG_SMB_STAT_TIMER,
+                       hw->smb_timer & SMB_STAT_TIMER_MASK);
+       /* set MTU */
+       AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN +
+                       VLAN_HLEN + ETH_FCS_LEN);
+       /* HDS, disable */
+       AT_WRITE_REG(hw, REG_HDS_CTRL, 0);
+
+       atl1c_configure_tx(adapter);
+       atl1c_configure_rx(adapter);
+       atl1c_configure_rss(adapter);
+       atl1c_configure_dma(adapter);
+
+       return 0;
+}
+
+static void atl1c_update_hw_stats(struct atl1c_adapter *adapter)
+{
+       u16 hw_reg_addr = 0;
+       unsigned long *stats_item = NULL;
+       u32 data;
+
+       /* update rx status */
+       hw_reg_addr = REG_MAC_RX_STATUS_BIN;
+       stats_item  = &adapter->hw_stats.rx_ok;
+       while (hw_reg_addr <= REG_MAC_RX_STATUS_END) {
+               AT_READ_REG(&adapter->hw, hw_reg_addr, &data);
+               *stats_item += data;
+               stats_item++;
+               hw_reg_addr += 4;
+       }
+/* update tx status */
+       hw_reg_addr = REG_MAC_TX_STATUS_BIN;
+       stats_item  = &adapter->hw_stats.tx_ok;
+       while (hw_reg_addr <= REG_MAC_TX_STATUS_END) {
+               AT_READ_REG(&adapter->hw, hw_reg_addr, &data);
+               *stats_item += data;
+               stats_item++;
+               hw_reg_addr += 4;
+       }
+}
+
+/*
+ * atl1c_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ */
+static struct net_device_stats *atl1c_get_stats(struct net_device *netdev)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       struct atl1c_hw_stats  *hw_stats = &adapter->hw_stats;
+       struct net_device_stats *net_stats = &adapter->net_stats;
+
+       atl1c_update_hw_stats(adapter);
+       net_stats->rx_packets = hw_stats->rx_ok;
+       net_stats->tx_packets = hw_stats->tx_ok;
+       net_stats->rx_bytes   = hw_stats->rx_byte_cnt;
+       net_stats->tx_bytes   = hw_stats->tx_byte_cnt;
+       net_stats->multicast  = hw_stats->rx_mcast;
+       net_stats->collisions = hw_stats->tx_1_col +
+                               hw_stats->tx_2_col * 2 +
+                               hw_stats->tx_late_col + hw_stats->tx_abort_col;
+       net_stats->rx_errors  = hw_stats->rx_frag + hw_stats->rx_fcs_err +
+                               hw_stats->rx_len_err + hw_stats->rx_sz_ov +
+                               hw_stats->rx_rrd_ov + hw_stats->rx_align_err;
+       net_stats->rx_fifo_errors   = hw_stats->rx_rxf_ov;
+       net_stats->rx_length_errors = hw_stats->rx_len_err;
+       net_stats->rx_crc_errors    = hw_stats->rx_fcs_err;
+       net_stats->rx_frame_errors  = hw_stats->rx_align_err;
+       net_stats->rx_over_errors   = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
+
+       net_stats->rx_missed_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
+
+       net_stats->tx_errors = hw_stats->tx_late_col + hw_stats->tx_abort_col +
+                               hw_stats->tx_underrun + hw_stats->tx_trunc;
+       net_stats->tx_fifo_errors    = hw_stats->tx_underrun;
+       net_stats->tx_aborted_errors = hw_stats->tx_abort_col;
+       net_stats->tx_window_errors  = hw_stats->tx_late_col;
+
+       return &adapter->net_stats;
+}
+
+static inline void atl1c_clear_phy_int(struct atl1c_adapter *adapter)
+{
+       u16 phy_data;
+
+       spin_lock(&adapter->mdio_lock);
+       atl1c_read_phy_reg(&adapter->hw, MII_ISR, &phy_data);
+       spin_unlock(&adapter->mdio_lock);
+}
+
+static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter,
+                               enum atl1c_trans_queue type)
+{
+       struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *)
+                               &adapter->tpd_ring[type];
+       struct atl1c_buffer *buffer_info;
+       u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+       u16 hw_next_to_clean;
+       u16 shift;
+       u32 data;
+
+       if (type == atl1c_trans_high)
+               shift = MB_HTPD_CONS_IDX_SHIFT;
+       else
+               shift = MB_NTPD_CONS_IDX_SHIFT;
+
+       AT_READ_REG(&adapter->hw, REG_MB_PRIO_CONS_IDX, &data);
+       hw_next_to_clean = (data >> shift) & MB_PRIO_PROD_IDX_MASK;
+
+       while (next_to_clean != hw_next_to_clean) {
+               buffer_info = &tpd_ring->buffer_info[next_to_clean];
+               if (buffer_info->state == ATL1_BUFFER_BUSY) {
+                       pci_unmap_page(adapter->pdev, buffer_info->dma,
+                                       buffer_info->length, PCI_DMA_TODEVICE);
+                       buffer_info->dma = 0;
+                       if (buffer_info->skb) {
+                               dev_kfree_skb_irq(buffer_info->skb);
+                               buffer_info->skb = NULL;
+                       }
+                       buffer_info->state = ATL1_BUFFER_FREE;
+               }
+               if (++next_to_clean == tpd_ring->count)
+                       next_to_clean = 0;
+               atomic_set(&tpd_ring->next_to_clean, next_to_clean);
+       }
+
+       if (netif_queue_stopped(adapter->netdev) &&
+                       netif_carrier_ok(adapter->netdev)) {
+               netif_wake_queue(adapter->netdev);
+       }
+
+       return true;
+}
+
+/*
+ * atl1c_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
+ */
+static irqreturn_t atl1c_intr(int irq, void *data)
+{
+       struct net_device *netdev  = data;
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       struct pci_dev *pdev = adapter->pdev;
+       struct atl1c_hw *hw = &adapter->hw;
+       int max_ints = AT_MAX_INT_WORK;
+       int handled = IRQ_NONE;
+       u32 status;
+       u32 reg_data;
+
+       do {
+               AT_READ_REG(hw, REG_ISR, &reg_data);
+               status = reg_data & hw->intr_mask;
+
+               if (status == 0 || (status & ISR_DIS_INT) != 0) {
+                       if (max_ints != AT_MAX_INT_WORK)
+                               handled = IRQ_HANDLED;
+                       break;
+               }
+               /* link event */
+               if (status & ISR_GPHY)
+                       atl1c_clear_phy_int(adapter);
+               /* Ack ISR */
+               AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT);
+               if (status & ISR_RX_PKT) {
+                       if (likely(napi_schedule_prep(&adapter->napi))) {
+                               hw->intr_mask &= ~ISR_RX_PKT;
+                               AT_WRITE_REG(hw, REG_IMR, hw->intr_mask);
+                               __napi_schedule(&adapter->napi);
+                       }
+               }
+               if (status & ISR_TX_PKT)
+                       atl1c_clean_tx_irq(adapter, atl1c_trans_normal);
+
+               handled = IRQ_HANDLED;
+               /* check if PCIE PHY Link down */
+               if (status & ISR_ERROR) {
+                       if (netif_msg_hw(adapter))
+                               dev_err(&pdev->dev,
+                                       "atl1c hardware error (status = 0x%x)\n",
+                                       status & ISR_ERROR);
+                       /* reset MAC */
+                       hw->intr_mask &= ~ISR_ERROR;
+                       AT_WRITE_REG(hw, REG_IMR, hw->intr_mask);
+                       schedule_work(&adapter->reset_task);
+                       break;
+               }
+
+               if (status & ISR_OVER)
+                       if (netif_msg_intr(adapter))
+                               dev_warn(&pdev->dev,
+                                       "TX/RX over flow (status = 0x%x)\n",
+                                       status & ISR_OVER);
+
+               /* link event */
+               if (status & (ISR_GPHY | ISR_MANUAL)) {
+                       adapter->net_stats.tx_carrier_errors++;
+                       atl1c_link_chg_event(adapter);
+                       break;
+               }
+
+       } while (--max_ints > 0);
+       /* re-enable Interrupt*/
+       AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+       return handled;
+}
+
+static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter,
+                 struct sk_buff *skb, struct atl1c_recv_ret_status *prrs)
+{
+       /*
+        * The pid field in RRS in not correct sometimes, so we
+        * cannot figure out if the packet is fragmented or not,
+        * so we tell the KERNEL CHECKSUM_NONE
+        */
+       skb->ip_summed = CHECKSUM_NONE;
+}
+
+static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid)
+{
+       struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[ringid];
+       struct pci_dev *pdev = adapter->pdev;
+       struct atl1c_buffer *buffer_info, *next_info;
+       struct sk_buff *skb;
+       void *vir_addr = NULL;
+       u16 num_alloc = 0;
+       u16 rfd_next_to_use, next_next;
+       struct atl1c_rx_free_desc *rfd_desc;
+
+       next_next = rfd_next_to_use = rfd_ring->next_to_use;
+       if (++next_next == rfd_ring->count)
+               next_next = 0;
+       buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+       next_info = &rfd_ring->buffer_info[next_next];
+
+       while (next_info->state == ATL1_BUFFER_FREE) {
+               rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use);
+
+               skb = dev_alloc_skb(adapter->rx_buffer_len);
+               if (unlikely(!skb)) {
+                       if (netif_msg_rx_err(adapter))
+                               dev_warn(&pdev->dev, "alloc rx buffer failed\n");
+                       break;
+               }
+
+               /*
+                * Make buffer alignment 2 beyond a 16 byte boundary
+                * this will result in a 16 byte aligned IP header after
+                * the 14 byte MAC header is removed
+                */
+               vir_addr = skb->data;
+               buffer_info->state = ATL1_BUFFER_BUSY;
+               buffer_info->skb = skb;
+               buffer_info->length = adapter->rx_buffer_len;
+               buffer_info->dma = pci_map_single(pdev, vir_addr,
+                                               buffer_info->length,
+                                               PCI_DMA_FROMDEVICE);
+               rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+               rfd_next_to_use = next_next;
+               if (++next_next == rfd_ring->count)
+                       next_next = 0;
+               buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+               next_info = &rfd_ring->buffer_info[next_next];
+               num_alloc++;
+       }
+
+       if (num_alloc) {
+               /* TODO: update mailbox here */
+               wmb();
+               rfd_ring->next_to_use = rfd_next_to_use;
+               AT_WRITE_REG(&adapter->hw, atl1c_rfd_prod_idx_regs[ringid],
+                       rfd_ring->next_to_use & MB_RFDX_PROD_IDX_MASK);
+       }
+
+       return num_alloc;
+}
+
+static void atl1c_clean_rrd(struct atl1c_rrd_ring *rrd_ring,
+                       struct  atl1c_recv_ret_status *rrs, u16 num)
+{
+       u16 i;
+       /* the relationship between rrd and rfd is one map one */
+       for (i = 0; i < num; i++, rrs = ATL1C_RRD_DESC(rrd_ring,
+                                       rrd_ring->next_to_clean)) {
+               rrs->word3 &= ~RRS_RXD_UPDATED;
+               if (++rrd_ring->next_to_clean == rrd_ring->count)
+                       rrd_ring->next_to_clean = 0;
+       }
+}
+
+static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring,
+       struct atl1c_recv_ret_status *rrs, u16 num)
+{
+       u16 i;
+       u16 rfd_index;
+       struct atl1c_buffer *buffer_info = rfd_ring->buffer_info;
+
+       rfd_index = (rrs->word0 >> RRS_RX_RFD_INDEX_SHIFT) &
+                       RRS_RX_RFD_INDEX_MASK;
+       for (i = 0; i < num; i++) {
+               buffer_info[rfd_index].skb = NULL;
+               buffer_info[rfd_index].state = ATL1_BUFFER_FREE;
+               if (++rfd_index == rfd_ring->count)
+                       rfd_index = 0;
+       }
+       rfd_ring->next_to_clean = rfd_index;
+}
+
+static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
+                  int *work_done, int work_to_do)
+{
+       u16 rfd_num, rfd_index;
+       u16 count = 0;
+       u16 length;
+       struct pci_dev *pdev = adapter->pdev;
+       struct net_device *netdev  = adapter->netdev;
+       struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[que];
+       struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring[que];
+       struct sk_buff *skb;
+       struct atl1c_recv_ret_status *rrs;
+       struct atl1c_buffer *buffer_info;
+
+       while (1) {
+               if (*work_done >= work_to_do)
+                       break;
+               rrs = ATL1C_RRD_DESC(rrd_ring, rrd_ring->next_to_clean);
+               if (likely(RRS_RXD_IS_VALID(rrs->word3))) {
+                       rfd_num = (rrs->word0 >> RRS_RX_RFD_CNT_SHIFT) &
+                               RRS_RX_RFD_CNT_MASK;
+                       if (unlikely(rfd_num) != 1)
+                               /* TODO support mul rfd*/
+                               if (netif_msg_rx_err(adapter))
+                                       dev_warn(&pdev->dev,
+                                               "Multi rfd not support yet!\n");
+                       goto rrs_checked;
+               } else {
+                       break;
+               }
+rrs_checked:
+               atl1c_clean_rrd(rrd_ring, rrs, rfd_num);
+               if (rrs->word3 & (RRS_RX_ERR_SUM | RRS_802_3_LEN_ERR)) {
+                       atl1c_clean_rfd(rfd_ring, rrs, rfd_num);
+                               if (netif_msg_rx_err(adapter))
+                                       dev_warn(&pdev->dev,
+                                               "wrong packet! rrs word3 is %x\n",
+                                               rrs->word3);
+                       continue;
+               }
+
+               length = le16_to_cpu((rrs->word3 >> RRS_PKT_SIZE_SHIFT) &
+                               RRS_PKT_SIZE_MASK);
+               /* Good Receive */
+               if (likely(rfd_num == 1)) {
+                       rfd_index = (rrs->word0 >> RRS_RX_RFD_INDEX_SHIFT) &
+                                       RRS_RX_RFD_INDEX_MASK;
+                       buffer_info = &rfd_ring->buffer_info[rfd_index];
+                       pci_unmap_single(pdev, buffer_info->dma,
+                               buffer_info->length, PCI_DMA_FROMDEVICE);
+                       skb = buffer_info->skb;
+               } else {
+                       /* TODO */
+                       if (netif_msg_rx_err(adapter))
+                               dev_warn(&pdev->dev,
+                                       "Multi rfd not support yet!\n");
+                       break;
+               }
+               atl1c_clean_rfd(rfd_ring, rrs, rfd_num);
+               skb_put(skb, length - ETH_FCS_LEN);
+               skb->protocol = eth_type_trans(skb, netdev);
+               skb->dev = netdev;
+               atl1c_rx_checksum(adapter, skb, rrs);
+               if (unlikely(adapter->vlgrp) && rrs->word3 & RRS_VLAN_INS) {
+                       u16 vlan;
+
+                       AT_TAG_TO_VLAN(rrs->vlan_tag, vlan);
+                       vlan = le16_to_cpu(vlan);
+                       vlan_hwaccel_receive_skb(skb, adapter->vlgrp, vlan);
+               } else
+                       netif_receive_skb(skb);
+
+               netdev->last_rx = jiffies;
+               (*work_done)++;
+               count++;
+       }
+       if (count)
+               atl1c_alloc_rx_buffer(adapter, que);
+}
+
+/*
+ * atl1c_clean - NAPI Rx polling callback
+ * @adapter: board private structure
+ */
+static int atl1c_clean(struct napi_struct *napi, int budget)
+{
+       struct atl1c_adapter *adapter =
+                       container_of(napi, struct atl1c_adapter, napi);
+       int work_done = 0;
+
+       /* Keep link state information with original netdev */
+       if (!netif_carrier_ok(adapter->netdev))
+               goto quit_polling;
+       /* just enable one RXQ */
+       atl1c_clean_rx_irq(adapter, 0, &work_done, budget);
+
+       if (work_done < budget) {
+quit_polling:
+               napi_complete(napi);
+               adapter->hw.intr_mask |= ISR_RX_PKT;
+               AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask);
+       }
+       return work_done;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+static void atl1c_netpoll(struct net_device *netdev)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+       disable_irq(adapter->pdev->irq);
+       atl1c_intr(adapter->pdev->irq, netdev);
+       enable_irq(adapter->pdev->irq);
+}
+#endif
+
+static inline u16 atl1c_tpd_avail(struct atl1c_adapter *adapter, enum atl1c_trans_queue type)
+{
+       struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
+       u16 next_to_use = 0;
+       u16 next_to_clean = 0;
+
+       next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+       next_to_use   = tpd_ring->next_to_use;
+
+       return (u16)(next_to_clean > next_to_use) ?
+               (next_to_clean - next_to_use - 1) :
+               (tpd_ring->count + next_to_clean - next_to_use - 1);
+}
+
+/*
+ * get next usable tpd
+ * Note: should call atl1c_tdp_avail to make sure
+ * there is enough tpd to use
+ */
+static struct atl1c_tpd_desc *atl1c_get_tpd(struct atl1c_adapter *adapter,
+       enum atl1c_trans_queue type)
+{
+       struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
+       struct atl1c_tpd_desc *tpd_desc;
+       u16 next_to_use = 0;
+
+       next_to_use = tpd_ring->next_to_use;
+       if (++tpd_ring->next_to_use == tpd_ring->count)
+               tpd_ring->next_to_use = 0;
+       tpd_desc = ATL1C_TPD_DESC(tpd_ring, next_to_use);
+       memset(tpd_desc, 0, sizeof(struct atl1c_tpd_desc));
+       return  tpd_desc;
+}
+
+static struct atl1c_buffer *
+atl1c_get_tx_buffer(struct atl1c_adapter *adapter, struct atl1c_tpd_desc *tpd)
+{
+       struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
+
+       return &tpd_ring->buffer_info[tpd -
+                       (struct atl1c_tpd_desc *)tpd_ring->desc];
+}
+
+/* Calculate the transmit packet descript needed*/
+static u16 atl1c_cal_tpd_req(const struct sk_buff *skb)
+{
+       u16 tpd_req;
+       u16 proto_hdr_len = 0;
+
+       tpd_req = skb_shinfo(skb)->nr_frags + 1;
+
+       if (skb_is_gso(skb)) {
+               proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+               if (proto_hdr_len < skb_headlen(skb))
+                       tpd_req++;
+               if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+                       tpd_req++;
+       }
+       return tpd_req;
+}
+
+static int atl1c_tso_csum(struct atl1c_adapter *adapter,
+                         struct sk_buff *skb,
+                         struct atl1c_tpd_desc **tpd,
+                         enum atl1c_trans_queue type)
+{
+       struct pci_dev *pdev = adapter->pdev;
+       u8 hdr_len;
+       u32 real_len;
+       unsigned short offload_type;
+       int err;
+
+       if (skb_is_gso(skb)) {
+               if (skb_header_cloned(skb)) {
+                       err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+                       if (unlikely(err))
+                               return -1;
+               }
+               offload_type = skb_shinfo(skb)->gso_type;
+
+               if (offload_type & SKB_GSO_TCPV4) {
+                       real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
+                                       + ntohs(ip_hdr(skb)->tot_len));
+
+                       if (real_len < skb->len)
+                               pskb_trim(skb, real_len);
+
+                       hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+                       if (unlikely(skb->len == hdr_len)) {
+                               /* only xsum need */
+                               if (netif_msg_tx_queued(adapter))
+                                       dev_warn(&pdev->dev,
+                                               "IPV4 tso with zero data??\n");
+                               goto check_sum;
+                       } else {
+                               ip_hdr(skb)->check = 0;
+                               tcp_hdr(skb)->check = ~csum_tcpudp_magic(
+                                                       ip_hdr(skb)->saddr,
+                                                       ip_hdr(skb)->daddr,
+                                                       0, IPPROTO_TCP, 0);
+                               (*tpd)->word1 |= 1 << TPD_IPV4_PACKET_SHIFT;
+                       }
+               }
+
+               if (offload_type & SKB_GSO_TCPV6) {
+                       struct atl1c_tpd_ext_desc *etpd =
+                               *(struct atl1c_tpd_ext_desc **)(tpd);
+
+                       memset(etpd, 0, sizeof(struct atl1c_tpd_ext_desc));
+                       *tpd = atl1c_get_tpd(adapter, type);
+                       ipv6_hdr(skb)->payload_len = 0;
+                       /* check payload == 0 byte ? */
+                       hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+                       if (unlikely(skb->len == hdr_len)) {
+                               /* only xsum need */
+                               if (netif_msg_tx_queued(adapter))
+                                       dev_warn(&pdev->dev,
+                                               "IPV6 tso with zero data??\n");
+                               goto check_sum;
+                       } else
+                               tcp_hdr(skb)->check = ~csum_ipv6_magic(
+                                               &ipv6_hdr(skb)->saddr,
+                                               &ipv6_hdr(skb)->daddr,
+                                               0, IPPROTO_TCP, 0);
+                       etpd->word1 |= 1 << TPD_LSO_EN_SHIFT;
+                       etpd->word1 |= 1 << TPD_LSO_VER_SHIFT;
+                       etpd->pkt_len = cpu_to_le32(skb->len);
+                       (*tpd)->word1 |= 1 << TPD_LSO_VER_SHIFT;
+               }
+
+               (*tpd)->word1 |= 1 << TPD_LSO_EN_SHIFT;
+               (*tpd)->word1 |= (skb_transport_offset(skb) & TPD_TCPHDR_OFFSET_MASK) <<
+                               TPD_TCPHDR_OFFSET_SHIFT;
+               (*tpd)->word1 |= (skb_shinfo(skb)->gso_size & TPD_MSS_MASK) <<
+                               TPD_MSS_SHIFT;
+               return 0;
+       }
+
+check_sum:
+       if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+               u8 css, cso;
+               cso = skb_transport_offset(skb);
+
+               if (unlikely(cso & 0x1)) {
+                       if (netif_msg_tx_err(adapter))
+                               dev_err(&adapter->pdev->dev,
+                                       "payload offset should not an event number\n");
+                       return -1;
+               } else {
+                       css = cso + skb->csum_offset;
+
+                       (*tpd)->word1 |= ((cso >> 1) & TPD_PLOADOFFSET_MASK) <<
+                                       TPD_PLOADOFFSET_SHIFT;
+                       (*tpd)->word1 |= ((css >> 1) & TPD_CCSUM_OFFSET_MASK) <<
+                                       TPD_CCSUM_OFFSET_SHIFT;
+                       (*tpd)->word1 |= 1 << TPD_CCSUM_EN_SHIFT;
+               }
+       }
+       return 0;
+}
+
+static void atl1c_tx_map(struct atl1c_adapter *adapter,
+                     struct sk_buff *skb, struct atl1c_tpd_desc *tpd,
+                       enum atl1c_trans_queue type)
+{
+       struct atl1c_tpd_desc *use_tpd = NULL;
+       struct atl1c_buffer *buffer_info = NULL;
+       u16 buf_len = skb_headlen(skb);
+       u16 map_len = 0;
+       u16 mapped_len = 0;
+       u16 hdr_len = 0;
+       u16 nr_frags;
+       u16 f;
+       int tso;
+
+       nr_frags = skb_shinfo(skb)->nr_frags;
+       tso = (tpd->word1 >> TPD_LSO_EN_SHIFT) & TPD_LSO_EN_MASK;
+       if (tso) {
+               /* TSO */
+               map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+               use_tpd = tpd;
+
+               buffer_info = atl1c_get_tx_buffer(adapter, use_tpd);
+               buffer_info->length = map_len;
+               buffer_info->dma = pci_map_single(adapter->pdev,
+                                       skb->data, hdr_len, PCI_DMA_TODEVICE);
+               buffer_info->state = ATL1_BUFFER_BUSY;
+               mapped_len += map_len;
+               use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+               use_tpd->buffer_len = cpu_to_le16(buffer_info->length);
+       }
+
+       if (mapped_len < buf_len) {
+               /* mapped_len == 0, means we should use the first tpd,
+                  which is given by caller  */
+               if (mapped_len == 0)
+                       use_tpd = tpd;
+               else {
+                       use_tpd = atl1c_get_tpd(adapter, type);
+                       memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc));
+                       use_tpd = atl1c_get_tpd(adapter, type);
+                       memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc));
+               }
+               buffer_info = atl1c_get_tx_buffer(adapter, use_tpd);
+               buffer_info->length = buf_len - mapped_len;
+               buffer_info->dma =
+                       pci_map_single(adapter->pdev, skb->data + mapped_len,
+                                       buffer_info->length, PCI_DMA_TODEVICE);
+               buffer_info->state = ATL1_BUFFER_BUSY;
+
+               use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+               use_tpd->buffer_len  = cpu_to_le16(buffer_info->length);
+       }
+
+       for (f = 0; f < nr_frags; f++) {
+               struct skb_frag_struct *frag;
+
+               frag = &skb_shinfo(skb)->frags[f];
+
+               use_tpd = atl1c_get_tpd(adapter, type);
+               memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc));
+
+               buffer_info = atl1c_get_tx_buffer(adapter, use_tpd);
+               buffer_info->length = frag->size;
+               buffer_info->dma =
+                       pci_map_page(adapter->pdev, frag->page,
+                                       frag->page_offset,
+                                       buffer_info->length,
+                                       PCI_DMA_TODEVICE);
+               buffer_info->state = ATL1_BUFFER_BUSY;
+
+               use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+               use_tpd->buffer_len  = cpu_to_le16(buffer_info->length);
+       }
+
+       /* The last tpd */
+       use_tpd->word1 |= 1 << TPD_EOP_SHIFT;
+       /* The last buffer info contain the skb address,
+          so it will be free after unmap */
+       buffer_info->skb = skb;
+}
+
+static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb,
+                          struct atl1c_tpd_desc *tpd, enum atl1c_trans_queue type)
+{
+       struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
+       u32 prod_data;
+
+       AT_READ_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, &prod_data);
+       switch (type) {
+       case atl1c_trans_high:
+               prod_data &= 0xFFFF0000;
+               prod_data |= tpd_ring->next_to_use & 0xFFFF;
+               break;
+       case atl1c_trans_normal:
+               prod_data &= 0x0000FFFF;
+               prod_data |= (tpd_ring->next_to_use & 0xFFFF) << 16;
+               break;
+       default:
+               break;
+       }
+       wmb();
+       AT_WRITE_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, prod_data);
+}
+
+static int atl1c_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       unsigned long flags;
+       u16 tpd_req = 1;
+       struct atl1c_tpd_desc *tpd;
+       enum atl1c_trans_queue type = atl1c_trans_normal;
+
+       if (test_bit(__AT_DOWN, &adapter->flags)) {
+               dev_kfree_skb_any(skb);
+               return NETDEV_TX_OK;
+       }
+
+       tpd_req = atl1c_cal_tpd_req(skb);
+       if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) {
+               if (netif_msg_pktdata(adapter))
+                       dev_info(&adapter->pdev->dev, "tx locked\n");
+               return NETDEV_TX_LOCKED;
+       }
+       if (skb->mark == 0x01)
+               type = atl1c_trans_high;
+       else
+               type = atl1c_trans_normal;
+
+       if (atl1c_tpd_avail(adapter, type) < tpd_req) {
+               /* no enough descriptor, just stop queue */
+               netif_stop_queue(netdev);
+               spin_unlock_irqrestore(&adapter->tx_lock, flags);
+               return NETDEV_TX_BUSY;
+       }
+
+       tpd = atl1c_get_tpd(adapter, type);
+
+       /* do TSO and check sum */
+       if (atl1c_tso_csum(adapter, skb, &tpd, type) != 0) {
+               spin_unlock_irqrestore(&adapter->tx_lock, flags);
+               dev_kfree_skb_any(skb);
+               return NETDEV_TX_OK;
+       }
+
+       if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+               u16 vlan = vlan_tx_tag_get(skb);
+               __le16 tag;
+
+               vlan = cpu_to_le16(vlan);
+               AT_VLAN_TO_TAG(vlan, tag);
+               tpd->word1 |= 1 << TPD_INS_VTAG_SHIFT;
+               tpd->vlan_tag = tag;
+       }
+
+       if (skb_network_offset(skb) != ETH_HLEN)
+               tpd->word1 |= 1 << TPD_ETH_TYPE_SHIFT; /* Ethernet frame */
+
+       atl1c_tx_map(adapter, skb, tpd, type);
+       atl1c_tx_queue(adapter, skb, tpd, type);
+
+       netdev->trans_start = jiffies;
+       spin_unlock_irqrestore(&adapter->tx_lock, flags);
+       return NETDEV_TX_OK;
+}
+
+static void atl1c_free_irq(struct atl1c_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
+
+       free_irq(adapter->pdev->irq, netdev);
+
+       if (adapter->have_msi)
+               pci_disable_msi(adapter->pdev);
+}
+
+static int atl1c_request_irq(struct atl1c_adapter *adapter)
+{
+       struct pci_dev    *pdev   = adapter->pdev;
+       struct net_device *netdev = adapter->netdev;
+       int flags = 0;
+       int err = 0;
+
+       adapter->have_msi = true;
+       err = pci_enable_msi(adapter->pdev);
+       if (err) {
+               if (netif_msg_ifup(adapter))
+                       dev_err(&pdev->dev,
+                               "Unable to allocate MSI interrupt Error: %d\n",
+                               err);
+               adapter->have_msi = false;
+       } else
+               netdev->irq = pdev->irq;
+
+       if (!adapter->have_msi)
+               flags |= IRQF_SHARED;
+       err = request_irq(adapter->pdev->irq, &atl1c_intr, flags,
+                       netdev->name, netdev);
+       if (err) {
+               if (netif_msg_ifup(adapter))
+                       dev_err(&pdev->dev,
+                               "Unable to allocate interrupt Error: %d\n",
+                               err);
+               if (adapter->have_msi)
+                       pci_disable_msi(adapter->pdev);
+               return err;
+       }
+       if (netif_msg_ifup(adapter))
+               dev_dbg(&pdev->dev, "atl1c_request_irq OK\n");
+       return err;
+}
+
+int atl1c_up(struct atl1c_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
+       int num;
+       int err;
+       int i;
+
+       netif_carrier_off(netdev);
+       atl1c_init_ring_ptrs(adapter);
+       atl1c_set_multi(netdev);
+       atl1c_restore_vlan(adapter);
+
+       for (i = 0; i < adapter->num_rx_queues; i++) {
+               num = atl1c_alloc_rx_buffer(adapter, i);
+               if (unlikely(num == 0)) {
+                       err = -ENOMEM;
+                       goto err_alloc_rx;
+               }
+       }
+
+       if (atl1c_configure(adapter)) {
+               err = -EIO;
+               goto err_up;
+       }
+
+       err = atl1c_request_irq(adapter);
+       if (unlikely(err))
+               goto err_up;
+
+       clear_bit(__AT_DOWN, &adapter->flags);
+       napi_enable(&adapter->napi);
+       atl1c_irq_enable(adapter);
+       atl1c_check_link_status(adapter);
+       netif_start_queue(netdev);
+       return err;
+
+err_up:
+err_alloc_rx:
+       atl1c_clean_rx_ring(adapter);
+       return err;
+}
+
+void atl1c_down(struct atl1c_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
+
+       atl1c_del_timer(adapter);
+       atl1c_cancel_work(adapter);
+
+       /* signal that we're down so the interrupt handler does not
+        * reschedule our watchdog timer */
+       set_bit(__AT_DOWN, &adapter->flags);
+       netif_carrier_off(netdev);
+       napi_disable(&adapter->napi);
+       atl1c_irq_disable(adapter);
+       atl1c_free_irq(adapter);
+       AT_WRITE_REG(&adapter->hw, REG_ISR, ISR_DIS_INT);
+       /* reset MAC to disable all RX/TX */
+       atl1c_reset_mac(&adapter->hw);
+       msleep(1);
+
+       adapter->link_speed = SPEED_0;
+       adapter->link_duplex = -1;
+       atl1c_clean_tx_ring(adapter, atl1c_trans_normal);
+       atl1c_clean_tx_ring(adapter, atl1c_trans_high);
+       atl1c_clean_rx_ring(adapter);
+}
+
+/*
+ * atl1c_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP).  At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ */
+static int atl1c_open(struct net_device *netdev)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       int err;
+
+       /* disallow open during test */
+       if (test_bit(__AT_TESTING, &adapter->flags))
+               return -EBUSY;
+
+       /* allocate rx/tx dma buffer & descriptors */
+       err = atl1c_setup_ring_resources(adapter);
+       if (unlikely(err))
+               return err;
+
+       err = atl1c_up(adapter);
+       if (unlikely(err))
+               goto err_up;
+
+       if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) {
+               u32 phy_data;
+
+               AT_READ_REG(&adapter->hw, REG_MDIO_CTRL, &phy_data);
+               phy_data |= MDIO_AP_EN;
+               AT_WRITE_REG(&adapter->hw, REG_MDIO_CTRL, phy_data);
+       }
+       return 0;
+
+err_up:
+       atl1c_free_irq(adapter);
+       atl1c_free_ring_resources(adapter);
+       atl1c_reset_mac(&adapter->hw);
+       return err;
+}
+
+/*
+ * atl1c_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS.  The hardware is still under the drivers control, but
+ * needs to be disabled.  A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ */
+static int atl1c_close(struct net_device *netdev)
+{
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+       WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
+       atl1c_down(adapter);
+       atl1c_free_ring_resources(adapter);
+       return 0;
+}
+
+static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+       struct atl1c_hw *hw = &adapter->hw;
+       u32 ctrl;
+       u32 mac_ctrl_data;
+       u32 master_ctrl_data;
+       u32 wol_ctrl_data;
+       u16 mii_bmsr_data;
+       u16 save_autoneg_advertised;
+       u16 mii_intr_status_data;
+       u32 wufc = adapter->wol;
+       u32 i;
+       int retval = 0;
+
+       if (netif_running(netdev)) {
+               WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
+               atl1c_down(adapter);
+       }
+       netif_device_detach(netdev);
+       atl1c_disable_l0s_l1(hw);
+       retval = pci_save_state(pdev);
+       if (retval)
+               return retval;
+       if (wufc) {
+               AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
+               master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS;
+
+               /* get link status */
+               atl1c_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
+               atl1c_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
+               save_autoneg_advertised = hw->autoneg_advertised;
+               hw->autoneg_advertised = ADVERTISED_10baseT_Half;
+               if (atl1c_restart_autoneg(hw) != 0)
+                       if (netif_msg_link(adapter))
+                               dev_warn(&pdev->dev, "phy autoneg failed\n");
+               hw->phy_configured = false; /* re-init PHY when resume */
+               hw->autoneg_advertised = save_autoneg_advertised;
+               /* turn on magic packet wol */
+               if (wufc & AT_WUFC_MAG)
+                       wol_ctrl_data = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+
+               if (wufc & AT_WUFC_LNKC) {
+                       for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
+                               msleep(100);
+                               atl1c_read_phy_reg(hw, MII_BMSR,
+                                       (u16 *)&mii_bmsr_data);
+                               if (mii_bmsr_data & BMSR_LSTATUS)
+                                       break;
+                       }
+                       if ((mii_bmsr_data & BMSR_LSTATUS) == 0)
+                               if (netif_msg_link(adapter))
+                                       dev_warn(&pdev->dev,
+                                               "%s: Link may change"
+                                               "when suspend\n",
+                                               atl1c_driver_name);
+                       wol_ctrl_data |=  WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
+                       /* only link up can wake up */
+                       if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {
+                               if (netif_msg_link(adapter))
+                                       dev_err(&pdev->dev,
+                                               "%s: read write phy "
+                                               "register failed.\n",
+                                               atl1c_driver_name);
+                               goto wol_dis;
+                       }
+               }
+               /* clear phy interrupt */
+               atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data);
+               /* Config MAC Ctrl register */
+               mac_ctrl_data = MAC_CTRL_RX_EN;
+               /* set to 10/100M halt duplex */
+               mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT;
+               mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
+                                MAC_CTRL_PRMLEN_MASK) <<
+                                MAC_CTRL_PRMLEN_SHIFT);
+
+               if (adapter->vlgrp)
+                       mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+
+               /* magic packet maybe Broadcast&multicast&Unicast frame */
+               if (wufc & AT_WUFC_MAG)
+                       mac_ctrl_data |= MAC_CTRL_BC_EN;
+
+               if (netif_msg_hw(adapter))
+                       dev_dbg(&pdev->dev,
+                               "%s: suspend MAC=0x%x\n",
+                               atl1c_driver_name, mac_ctrl_data);
+               AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
+               AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
+               AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+
+               /* pcie patch */
+               AT_READ_REG(hw, REG_PCIE_PHYMISC, &ctrl);
+               ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+               AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
+
+               pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
+               goto suspend_exit;
+       }
+wol_dis:
+
+       /* WOL disabled */
+       AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+
+       /* pcie patch */
+       AT_READ_REG(hw, REG_PCIE_PHYMISC, &ctrl);
+       ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+       AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
+
+       atl1c_phy_disable(hw);
+       hw->phy_configured = false; /* re-init PHY when resume */
+
+       pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+suspend_exit:
+
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+       return 0;
+}
+
+static int atl1c_resume(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       pci_enable_wake(pdev, PCI_D3hot, 0);
+       pci_enable_wake(pdev, PCI_D3cold, 0);
+
+       AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
+
+       atl1c_phy_reset(&adapter->hw);
+       atl1c_reset_mac(&adapter->hw);
+       netif_device_attach(netdev);
+       if (netif_running(netdev))
+               atl1c_up(adapter);
+
+       return 0;
+}
+
+static void atl1c_shutdown(struct pci_dev *pdev)
+{
+       atl1c_suspend(pdev, PMSG_SUSPEND);
+}
+
+static const struct net_device_ops atl1c_netdev_ops = {
+       .ndo_open               = atl1c_open,
+       .ndo_stop               = atl1c_close,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_start_xmit         = atl1c_xmit_frame,
+       .ndo_set_mac_address    = atl1c_set_mac_addr,
+       .ndo_set_multicast_list = atl1c_set_multi,
+       .ndo_change_mtu         = atl1c_change_mtu,
+       .ndo_do_ioctl           = atl1c_ioctl,
+       .ndo_tx_timeout         = atl1c_tx_timeout,
+       .ndo_get_stats          = atl1c_get_stats,
+       .ndo_vlan_rx_register   = atl1c_vlan_rx_register,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = atl1c_netpoll,
+#endif
+};
+
+static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
+{
+       SET_NETDEV_DEV(netdev, &pdev->dev);
+       pci_set_drvdata(pdev, netdev);
+
+       netdev->irq  = pdev->irq;
+       netdev->netdev_ops = &atl1c_netdev_ops;
+       netdev->watchdog_timeo = AT_TX_WATCHDOG;
+       atl1c_set_ethtool_ops(netdev);
+
+       /* TODO: add when ready */
+       netdev->features =      NETIF_F_SG         |
+                               NETIF_F_HW_CSUM    |
+                               NETIF_F_HW_VLAN_TX |
+                               NETIF_F_HW_VLAN_RX |
+                               NETIF_F_TSO        |
+                               NETIF_F_TSO6;
+       return 0;
+}
+
+/*
+ * atl1c_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in atl1c_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * atl1c_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ */
+static int __devinit atl1c_probe(struct pci_dev *pdev,
+                                const struct pci_device_id *ent)
+{
+       struct net_device *netdev;
+       struct atl1c_adapter *adapter;
+       static int cards_found;
+
+       int err = 0;
+
+       /* enable device (incl. PCI PM wakeup and hotplug setup) */
+       err = pci_enable_device_mem(pdev);
+       if (err) {
+               dev_err(&pdev->dev, "cannot enable PCI device\n");
+               return err;
+       }
+
+       /*
+        * The atl1c chip can DMA to 64-bit addresses, but it uses a single
+        * shared register for the high 32 bits, so only a single, aligned,
+        * 4 GB physical address range can be used at a time.
+        *
+        * Supporting 64-bit DMA on this hardware is more trouble than it's
+        * worth.  It is far easier to limit to 32-bit DMA than update
+        * various kernel subsystems to support the mechanics required by a
+        * fixed-high-32-bit system.
+        */
+       if ((pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) ||
+           (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) != 0)) {
+               dev_err(&pdev->dev, "No usable DMA configuration,aborting\n");
+               goto err_dma;
+       }
+
+       err = pci_request_regions(pdev, atl1c_driver_name);
+       if (err) {
+               dev_err(&pdev->dev, "cannot obtain PCI resources\n");
+               goto err_pci_reg;
+       }
+
+       pci_set_master(pdev);
+
+       netdev = alloc_etherdev(sizeof(struct atl1c_adapter));
+       if (netdev == NULL) {
+               err = -ENOMEM;
+               dev_err(&pdev->dev, "etherdev alloc failed\n");
+               goto err_alloc_etherdev;
+       }
+
+       err = atl1c_init_netdev(netdev, pdev);
+       if (err) {
+               dev_err(&pdev->dev, "init netdevice failed\n");
+               goto err_init_netdev;
+       }
+       adapter = netdev_priv(netdev);
+       adapter->bd_number = cards_found;
+       adapter->netdev = netdev;
+       adapter->pdev = pdev;
+       adapter->hw.adapter = adapter;
+       adapter->msg_enable = netif_msg_init(-1, atl1c_default_msg);
+       adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+       if (!adapter->hw.hw_addr) {
+               err = -EIO;
+               dev_err(&pdev->dev, "cannot map device registers\n");
+               goto err_ioremap;
+       }
+       netdev->base_addr = (unsigned long)adapter->hw.hw_addr;
+
+       /* init mii data */
+       adapter->mii.dev = netdev;
+       adapter->mii.mdio_read  = atl1c_mdio_read;
+       adapter->mii.mdio_write = atl1c_mdio_write;
+       adapter->mii.phy_id_mask = 0x1f;
+       adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK;
+       netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64);
+       setup_timer(&adapter->phy_config_timer, atl1c_phy_config,
+                       (unsigned long)adapter);
+       /* setup the private structure */
+       err = atl1c_sw_init(adapter);
+       if (err) {
+               dev_err(&pdev->dev, "net device private data init failed\n");
+               goto err_sw_init;
+       }
+       atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE |
+                       ATL1C_PCIE_PHY_RESET);
+
+       /* Init GPHY as early as possible due to power saving issue  */
+       atl1c_phy_reset(&adapter->hw);
+
+       err = atl1c_reset_mac(&adapter->hw);
+       if (err) {
+               err = -EIO;
+               goto err_reset;
+       }
+
+       device_init_wakeup(&pdev->dev, 1);
+       /* reset the controller to
+        * put the device in a known good starting state */
+       err = atl1c_phy_init(&adapter->hw);
+       if (err) {
+               err = -EIO;
+               goto err_reset;
+       }
+       if (atl1c_read_mac_addr(&adapter->hw) != 0) {
+               err = -EIO;
+               dev_err(&pdev->dev, "get mac address failed\n");
+               goto err_eeprom;
+       }
+       memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+       memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
+       if (netif_msg_probe(adapter))
+               dev_dbg(&pdev->dev,
+                       "mac address : %02x-%02x-%02x-%02x-%02x-%02x\n",
+                       adapter->hw.mac_addr[0], adapter->hw.mac_addr[1],
+                       adapter->hw.mac_addr[2], adapter->hw.mac_addr[3],
+                       adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]);
+
+       atl1c_hw_set_mac_addr(&adapter->hw);
+       INIT_WORK(&adapter->reset_task, atl1c_reset_task);
+       INIT_WORK(&adapter->link_chg_task, atl1c_link_chg_task);
+       err = register_netdev(netdev);
+       if (err) {
+               dev_err(&pdev->dev, "register netdevice failed\n");
+               goto err_register;
+       }
+
+       if (netif_msg_probe(adapter))
+               dev_info(&pdev->dev, "version %s\n", ATL1C_DRV_VERSION);
+       cards_found++;
+       return 0;
+
+err_reset:
+err_register:
+err_sw_init:
+err_eeprom:
+       iounmap(adapter->hw.hw_addr);
+err_init_netdev:
+err_ioremap:
+       free_netdev(netdev);
+err_alloc_etherdev:
+       pci_release_regions(pdev);
+err_pci_reg:
+err_dma:
+       pci_disable_device(pdev);
+       return err;
+}
+
+/*
+ * atl1c_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * atl1c_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.  The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ */
+static void __devexit atl1c_remove(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+       unregister_netdev(netdev);
+       atl1c_phy_disable(&adapter->hw);
+
+       iounmap(adapter->hw.hw_addr);
+
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       free_netdev(netdev);
+}
+
+/*
+ * atl1c_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci connection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t atl1c_io_error_detected(struct pci_dev *pdev,
+                                               pci_channel_state_t state)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+       netif_device_detach(netdev);
+
+       if (netif_running(netdev))
+               atl1c_down(adapter);
+
+       pci_disable_device(pdev);
+
+       /* Request a slot slot reset. */
+       return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/*
+ * atl1c_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot. Implementation
+ * resembles the first-half of the e1000_resume routine.
+ */
+static pci_ers_result_t atl1c_io_slot_reset(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+       if (pci_enable_device(pdev)) {
+               if (netif_msg_hw(adapter))
+                       dev_err(&pdev->dev,
+                               "Cannot re-enable PCI device after reset\n");
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+       pci_set_master(pdev);
+
+       pci_enable_wake(pdev, PCI_D3hot, 0);
+       pci_enable_wake(pdev, PCI_D3cold, 0);
+
+       atl1c_reset_mac(&adapter->hw);
+
+       return PCI_ERS_RESULT_RECOVERED;
+}
+
+/*
+ * atl1c_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells us that
+ * its OK to resume normal operation. Implementation resembles the
+ * second-half of the atl1c_resume routine.
+ */
+static void atl1c_io_resume(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+       if (netif_running(netdev)) {
+               if (atl1c_up(adapter)) {
+                       if (netif_msg_hw(adapter))
+                               dev_err(&pdev->dev,
+                                       "Cannot bring device back up after reset\n");
+                       return;
+               }
+       }
+
+       netif_device_attach(netdev);
+}
+
+static struct pci_error_handlers atl1c_err_handler = {
+       .error_detected = atl1c_io_error_detected,
+       .slot_reset = atl1c_io_slot_reset,
+       .resume = atl1c_io_resume,
+};
+
+static struct pci_driver atl1c_driver = {
+       .name     = atl1c_driver_name,
+       .id_table = atl1c_pci_tbl,
+       .probe    = atl1c_probe,
+       .remove   = __devexit_p(atl1c_remove),
+       /* Power Managment Hooks */
+       .suspend  = atl1c_suspend,
+       .resume   = atl1c_resume,
+       .shutdown = atl1c_shutdown,
+       .err_handler = &atl1c_err_handler
+};
+
+/*
+ * atl1c_init_module - Driver Registration Routine
+ *
+ * atl1c_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ */
+static int __init atl1c_init_module(void)
+{
+       return pci_register_driver(&atl1c_driver);
+}
+
+/*
+ * atl1c_exit_module - Driver Exit Cleanup Routine
+ *
+ * atl1c_exit_module is called just before the driver is removed
+ * from memory.
+ */
+static void __exit atl1c_exit_module(void)
+{
+       pci_unregister_driver(&atl1c_driver);
+}
+
+module_init(atl1c_init_module);
+module_exit(atl1c_exit_module);
index 0089746b8d026ba8acdcd0911cab91075110a84a..bab8a934c33d949127286fdc0ef07714bb7bb4b7 100644 (file)
@@ -90,6 +90,7 @@ static const struct pci_device_id cxgb3_pci_tbl[] = {
        CH_DEVICE(0x30, 2),     /* T3B10 */
        CH_DEVICE(0x31, 3),     /* T3B20 */
        CH_DEVICE(0x32, 1),     /* T3B02 */
+       CH_DEVICE(0x35, 6),     /* T3C20-derived T3C10 */
        {0,}
 };
 
index 2d1433077a8ee992a71ed1e89210ebf8749de816..ac2a974dfe3759d0477f7c97766db196feacb598 100644 (file)
@@ -512,6 +512,13 @@ static const struct adapter_info t3_adap_info[] = {
         F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
         { S_GPIO9, S_GPIO3 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
         &mi1_mdio_ext_ops, "Chelsio T320"},
+       {},
+       {},
+       {1, 0,
+        F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO6_OEN | F_GPIO7_OEN |
+        F_GPIO10_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
+        { S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
+        &mi1_mdio_ext_ops, "Chelsio T310" },
 };
 
 /*
index 5b910cf63740877416f8a25f1b91f94da7b783d8..b8251e827059643203f8a5a02fa73d1156e32a34 100644 (file)
@@ -6011,9 +6011,20 @@ static void nv_shutdown(struct pci_dev *pdev)
        if (netif_running(dev))
                nv_close(dev);
 
-       nv_restore_mac_addr(pdev);
+       /*
+        * Restore the MAC so a kernel started by kexec won't get confused.
+        * If we really go for poweroff, we must not restore the MAC,
+        * otherwise the MAC for WOL will be reversed at least on some boards.
+        */
+       if (system_state != SYSTEM_POWER_OFF) {
+               nv_restore_mac_addr(pdev);
+       }
 
        pci_disable_device(pdev);
+       /*
+        * Apparently it is not possible to reinitialise from D3 hot,
+        * only put the device into D3 if we really go for poweroff.
+        */
        if (system_state == SYSTEM_POWER_OFF) {
                if (pci_enable_wake(pdev, PCI_D3cold, np->wolenabled))
                        pci_enable_wake(pdev, PCI_D3hot, np->wolenabled);
index 5f31bbb614aff948703ce58e770cbeb81dcaf6c3..13f11f402a9948b77878b108dca8ae36ecace50a 100644 (file)
@@ -1175,7 +1175,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
 {
        struct mib_counters *p = &mp->mib_counters;
 
-       spin_lock(&mp->mib_counters_lock);
+       spin_lock_bh(&mp->mib_counters_lock);
        p->good_octets_received += mib_read(mp, 0x00);
        p->good_octets_received += (u64)mib_read(mp, 0x04) << 32;
        p->bad_octets_received += mib_read(mp, 0x08);
@@ -1208,7 +1208,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
        p->bad_crc_event += mib_read(mp, 0x74);
        p->collision += mib_read(mp, 0x78);
        p->late_collision += mib_read(mp, 0x7c);
-       spin_unlock(&mp->mib_counters_lock);
+       spin_unlock_bh(&mp->mib_counters_lock);
 
        mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);
 }
@@ -1575,7 +1575,7 @@ oom:
                return;
        }
 
-       mc_spec = kmalloc(0x200, GFP_KERNEL);
+       mc_spec = kmalloc(0x200, GFP_ATOMIC);
        if (mc_spec == NULL)
                goto oom;
        mc_other = mc_spec + (0x100 >> 2);
@@ -2216,8 +2216,6 @@ static int mv643xx_eth_stop(struct net_device *dev)
        wrlp(mp, INT_MASK, 0x00000000);
        rdlp(mp, INT_MASK);
 
-       del_timer_sync(&mp->mib_counters_timer);
-
        napi_disable(&mp->napi);
 
        del_timer_sync(&mp->rx_oom);
@@ -2229,6 +2227,7 @@ static int mv643xx_eth_stop(struct net_device *dev)
        port_reset(mp);
        mv643xx_eth_get_stats(dev);
        mib_counters_update(mp);
+       del_timer_sync(&mp->mib_counters_timer);
 
        skb_queue_purge(&mp->rx_recycle);
 
index 783c1a7b869e62c20ccf1981cbe3000f5eaddf56..9a78daec2fe9268d3972f3dc8e3206cb6c2e46c8 100644 (file)
@@ -1624,7 +1624,7 @@ static int smsc911x_eeprom_send_cmd(struct smsc911x_data *pdata, u32 op)
        do {
                msleep(1);
                e2cmd = smsc911x_reg_read(pdata, E2P_CMD);
-       } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--));
+       } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (--timeout));
 
        if (!timeout) {
                SMSC_TRACE(DRV, "TIMED OUT");
index a1e4b3895b339d0a007ec07483e6039bf1d212d0..4e15ae068b3ffdfb64bb974d7f6e9080e13f3c97 100644 (file)
@@ -341,7 +341,7 @@ static int smsc9420_eeprom_send_cmd(struct smsc9420_pdata *pd, u32 op)
        do {
                msleep(1);
                e2cmd = smsc9420_reg_read(pd, E2P_CMD);
-       } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--));
+       } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (--timeout));
 
        if (!timeout) {
                smsc_info(HW, "TIMED OUT");
@@ -413,6 +413,7 @@ static int smsc9420_ethtool_get_eeprom(struct net_device *dev,
        }
 
        memcpy(data, &eeprom_data[eeprom->offset], len);
+       eeprom->magic = SMSC9420_EEPROM_MAGIC;
        eeprom->len = len;
        return 0;
 }
@@ -423,6 +424,9 @@ static int smsc9420_ethtool_set_eeprom(struct net_device *dev,
        struct smsc9420_pdata *pd = netdev_priv(dev);
        int ret;
 
+       if (eeprom->magic != SMSC9420_EEPROM_MAGIC)
+               return -EINVAL;
+
        smsc9420_eeprom_enable_access(pd);
        smsc9420_eeprom_send_cmd(pd, E2P_CMD_EPC_CMD_EWEN_);
        ret = smsc9420_eeprom_write_location(pd, eeprom->offset, *data);
index 69c351f93f86cd3c531121411215ca692061c8b2..e441402f77a2e3134d888dd7c1cb49402f27e3d7 100644 (file)
@@ -44,6 +44,7 @@
 #define LAN_REGISTER_EXTENT            (0x400)
 
 #define SMSC9420_EEPROM_SIZE           ((u32)11)
+#define SMSC9420_EEPROM_MAGIC          (0x9420)
 
 #define PKT_BUF_SZ                     (VLAN_ETH_FRAME_LEN + NET_IP_ALIGN + 4)
 
index feaf0e0577d77e9decc37972b72dd5ea44a4706f..43695b76606fdc64331ae0954e51dd3447eb6628 100644 (file)
@@ -909,7 +909,7 @@ static void check_duplex(struct net_device *dev)
                        printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d "
                                   "negotiated capability %4.4x.\n", dev->name,
                                   duplex ? "full" : "half", np->phys[0], negotiated);
-               iowrite16(ioread16(ioaddr + MACCtrl0) | duplex ? 0x20 : 0, ioaddr + MACCtrl0);
+               iowrite16(ioread16(ioaddr + MACCtrl0) | (duplex ? 0x20 : 0), ioaddr + MACCtrl0);
        }
 }
 
index 4918763410686d02750a6f7ef8141271c19b098a..8d64b1da0465c99a0502c642900f325964cf0186 100644 (file)
@@ -1157,7 +1157,7 @@ static void gem_pcs_reset(struct gem *gp)
                if (limit-- <= 0)
                        break;
        }
-       if (limit <= 0)
+       if (limit < 0)
                printk(KERN_WARNING "%s: PCS reset bit would not clear.\n",
                       gp->dev->name);
 }
index 281373281756e381d24125eb841f903eda0a8286..16c528db725109f5382f82a0db1f6978d7c93bcc 100644 (file)
@@ -343,7 +343,7 @@ static void lance_init_ring_dvma(struct net_device *dev)
        ib->phys_addr [5] = dev->dev_addr [4];
 
        /* Setup the Tx ring entries */
-       for (i = 0; i <= TX_RING_SIZE; i++) {
+       for (i = 0; i < TX_RING_SIZE; i++) {
                leptr = LANCE_ADDR(aib + libbuff_offset(tx_buf, i));
                ib->btx_ring [i].tmd0      = leptr;
                ib->btx_ring [i].tmd1_hadr = leptr >> 16;
@@ -399,7 +399,7 @@ static void lance_init_ring_pio(struct net_device *dev)
        sbus_writeb(dev->dev_addr[4], &ib->phys_addr[5]);
 
        /* Setup the Tx ring entries */
-       for (i = 0; i <= TX_RING_SIZE; i++) {
+       for (i = 0; i < TX_RING_SIZE; i++) {
                leptr = libbuff_offset(tx_buf, i);
                sbus_writew(leptr,      &ib->btx_ring [i].tmd0);
                sbus_writeb(leptr >> 16,&ib->btx_ring [i].tmd1_hadr);
index 4595962fb8e1b0f74385fc25cc6d28d57846f878..b080f9493d83fe70a22dd236e3eaf045ca4aaf03 100644 (file)
@@ -2237,8 +2237,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                        phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask;
                        if (phyid != TG3_PHY_ID_BCMAC131) {
                                phyid &= TG3_PHY_OUI_MASK;
-                               if (phyid == TG3_PHY_OUI_1 &&
-                                   phyid == TG3_PHY_OUI_2 &&
+                               if (phyid == TG3_PHY_OUI_1 ||
+                                   phyid == TG3_PHY_OUI_2 ||
                                    phyid == TG3_PHY_OUI_3)
                                        do_low_power = true;
                        }
index 852d0e7c4e62abbfb13421664293dd70182c4126..108bbbeacfb61a956223094160715344894b7b2e 100644 (file)
@@ -263,10 +263,11 @@ static void veth_dev_free(struct net_device *dev)
 }
 
 static const struct net_device_ops veth_netdev_ops = {
-       .ndo_init       = veth_dev_init,
-       .ndo_open       = veth_open,
-       .ndo_start_xmit = veth_xmit,
-       .ndo_get_stats  = veth_get_stats,
+       .ndo_init            = veth_dev_init,
+       .ndo_open            = veth_open,
+       .ndo_start_xmit      = veth_xmit,
+       .ndo_get_stats       = veth_get_stats,
+       .ndo_set_mac_address = eth_mac_addr,
 };
 
 static void veth_setup(struct net_device *dev)
index 067c871cc2266e62a08112161a38bb43a6724d8d..3b9d27ea2950ca4223c1ae72e4f3c340c9148f26 100644 (file)
@@ -157,7 +157,7 @@ enum {
 
 
 /* Firmware version we request when pulling the fw image file */
-#define I2400M_FW_VERSION "1.3"
+#define I2400M_FW_VERSION "1.4"
 
 
 /**
index ad4cdd25613771f60857d4900a77d15f81c454a5..0b28fccec03f4a43ff09811a90db88b5b22bd8a4 100644 (file)
@@ -84,7 +84,7 @@ parport_atari_frob_control(struct parport *p, unsigned char mask,
 static unsigned char
 parport_atari_read_status(struct parport *p)
 {
-       return ((mfp.par_dt_reg & 1 ? 0 : PARPORT_STATUS_BUSY) |
+       return ((st_mfp.par_dt_reg & 1 ? 0 : PARPORT_STATUS_BUSY) |
                PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR);
 }
 
@@ -193,9 +193,9 @@ static int __init parport_atari_init(void)
                sound_ym.wd_data = sound_ym.rd_data_reg_sel | (1 << 5);
                local_irq_restore(flags);
                /* MFP port I0 as input. */
-               mfp.data_dir &= ~1;
+               st_mfp.data_dir &= ~1;
                /* MFP port I0 interrupt on high->low edge. */
-               mfp.active_edge &= ~1;
+               st_mfp.active_edge &= ~1;
                p = parport_register_port((unsigned long)&sound_ym.wd_data,
                                          IRQ_MFP_BUSY, PARPORT_DMA_NONE,
                                          &parport_atari_ops);
index f4b7c79023ffe7d05589dd93526531ea3dc3708f..f3f686581a9026685dc3e6c994b00e88ed88486c 100644 (file)
@@ -61,6 +61,8 @@
 /* global iommu list, set NULL for ignored DMAR units */
 static struct intel_iommu **g_iommus;
 
+static int rwbf_quirk;
+
 /*
  * 0: Present
  * 1-11: Reserved
@@ -785,7 +787,7 @@ static void iommu_flush_write_buffer(struct intel_iommu *iommu)
        u32 val;
        unsigned long flag;
 
-       if (!cap_rwbf(iommu->cap))
+       if (!rwbf_quirk && !cap_rwbf(iommu->cap))
                return;
        val = iommu->gcmd | DMA_GCMD_WBF;
 
@@ -3137,3 +3139,15 @@ static struct iommu_ops intel_iommu_ops = {
        .unmap          = intel_iommu_unmap_range,
        .iova_to_phys   = intel_iommu_iova_to_phys,
 };
+
+static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
+{
+       /*
+        * Mobile 4 Series Chipset neglects to set RWBF capability,
+        * but needs it:
+        */
+       printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
+       rwbf_quirk = 1;
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
index 44f15ff70c1d4f5f6c135d68367cbfb57b31783e..baba2eb5367df54bcc947333beda7e56332f3785 100644 (file)
@@ -103,14 +103,12 @@ static void msix_set_enable(struct pci_dev *dev, int enable)
        }
 }
 
-/*
- * Essentially, this is ((1 << (1 << x)) - 1), but without the
- * undefinedness of a << 32.
- */
 static inline __attribute_const__ u32 msi_mask(unsigned x)
 {
-       static const u32 mask[] = { 1, 2, 4, 0xf, 0xff, 0xffff, 0xffffffff };
-       return mask[x];
+       /* Don't shift by >= width of type */
+       if (x >= 5)
+               return 0xffffffff;
+       return (1 << (1 << x)) - 1;
 }
 
 static void msix_flush_writes(struct irq_desc *desc)
index e3efe6b19ee79210e2885f03b1d21995e2125abb..6d6120007af4ed01d5fdc39331bff59349b1ed00 100644 (file)
@@ -1540,16 +1540,21 @@ void pci_release_region(struct pci_dev *pdev, int bar)
 }
 
 /**
- *     pci_request_region - Reserved PCI I/O and memory resource
+ *     __pci_request_region - Reserved PCI I/O and memory resource
  *     @pdev: PCI device whose resources are to be reserved
  *     @bar: BAR to be reserved
  *     @res_name: Name to be associated with resource.
+ *     @exclusive: whether the region access is exclusive or not
  *
  *     Mark the PCI region associated with PCI device @pdev BR @bar as
  *     being reserved by owner @res_name.  Do not access any
  *     address inside the PCI regions unless this call returns
  *     successfully.
  *
+ *     If @exclusive is set, then the region is marked so that userspace
+ *     is explicitly not allowed to map the resource via /dev/mem or
+ *     sysfs MMIO access.
+ *
  *     Returns 0 on success, or %EBUSY on error.  A warning
  *     message is also printed on failure.
  */
@@ -1588,12 +1593,12 @@ err_out:
 }
 
 /**
- *     pci_request_region - Reserved PCI I/O and memory resource
+ *     pci_request_region - Reserve PCI I/O and memory resource
  *     @pdev: PCI device whose resources are to be reserved
  *     @bar: BAR to be reserved
- *     @res_name: Name to be associated with resource.
+ *     @res_name: Name to be associated with resource
  *
- *     Mark the PCI region associated with PCI device @pdev BR @bar as
+ *     Mark the PCI region associated with PCI device @pdev BAR @bar as
  *     being reserved by owner @res_name.  Do not access any
  *     address inside the PCI regions unless this call returns
  *     successfully.
index 26ddf78ac30049ddb3fd0203828519689dfc886b..07c0aa5275e6edf33ab1914761d6acb3113f1741 100644 (file)
@@ -16,21 +16,21 @@ extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
 #endif
 
 /**
- * Firmware PM callbacks
+ * struct pci_platform_pm_ops - Firmware PM callbacks
  *
- * @is_manageable - returns 'true' if given device is power manageable by the
- *                  platform firmware
+ * @is_manageable: returns 'true' if given device is power manageable by the
+ *                 platform firmware
  *
- * @set_state - invokes the platform firmware to set the device's power state
+ * @set_state: invokes the platform firmware to set the device's power state
  *
- * @choose_state - returns PCI power state of given device preferred by the
- *                 platform; to be used during system-wide transitions from a
- *                 sleeping state to the working state and vice versa
+ * @choose_state: returns PCI power state of given device preferred by the
+ *                platform; to be used during system-wide transitions from a
+ *                sleeping state to the working state and vice versa
  *
- * @can_wakeup - returns 'true' if given device is capable of waking up the
- *               system from a sleeping state
+ * @can_wakeup: returns 'true' if given device is capable of waking up the
+ *              system from a sleeping state
  *
- * @sleep_wake - enables/disables the system wake up capability of given device
+ * @sleep_wake: enables/disables the system wake up capability of given device
  *
  * If given platform is generally capable of power managing PCI devices, all of
  * these callbacks are mandatory.
index 29cbe47f219f8c39f2b3f66490a272f339b1f9d5..36864a935d687bb732f9c09b45f2c647d6dca54c 100644 (file)
@@ -55,6 +55,7 @@ void pci_disable_rom(struct pci_dev *pdev)
 
 /**
  * pci_get_rom_size - obtain the actual size of the ROM image
+ * @pdev: target PCI device
  * @rom: kernel virtual pointer to image of ROM
  * @size: size of PCI window
  *  return: size of actual ROM image
index 94363115a42a69502d8ddd3f029984fd62aa07b6..b3866ad502273bc23545305745863e800336b87a 100644 (file)
@@ -62,6 +62,7 @@ config DELL_LAPTOP
        depends on EXPERIMENTAL
        depends on BACKLIGHT_CLASS_DEVICE
        depends on RFKILL
+       depends on POWER_SUPPLY
        default n
        ---help---
        This driver adds support for rfkill and backlight control to Dell
@@ -301,6 +302,7 @@ config INTEL_MENLOW
 config EEEPC_LAPTOP
        tristate "Eee PC Hotkey Driver (EXPERIMENTAL)"
        depends on ACPI
+       depends on INPUT
        depends on EXPERIMENTAL
        select BACKLIGHT_CLASS_DEVICE
        select HWMON
index 65dc41540c62bdbe72bd0a68f88c042a7f06fd12..45940f31fe9e57642b08bbdb4aa8dc45d8d5d798 100644 (file)
@@ -166,6 +166,7 @@ struct fujitsu_hotkey_t {
        struct platform_device *pf_device;
        struct kfifo *fifo;
        spinlock_t fifo_lock;
+       int rfkill_supported;
        int rfkill_state;
        int logolamp_registered;
        int kblamps_registered;
@@ -526,7 +527,7 @@ static ssize_t
 show_lid_state(struct device *dev,
                        struct device_attribute *attr, char *buf)
 {
-       if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD)
+       if (!(fujitsu_hotkey->rfkill_supported & 0x100))
                return sprintf(buf, "unknown\n");
        if (fujitsu_hotkey->rfkill_state & 0x100)
                return sprintf(buf, "open\n");
@@ -538,7 +539,7 @@ static ssize_t
 show_dock_state(struct device *dev,
                        struct device_attribute *attr, char *buf)
 {
-       if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD)
+       if (!(fujitsu_hotkey->rfkill_supported & 0x200))
                return sprintf(buf, "unknown\n");
        if (fujitsu_hotkey->rfkill_state & 0x200)
                return sprintf(buf, "docked\n");
@@ -550,7 +551,7 @@ static ssize_t
 show_radios_state(struct device *dev,
                        struct device_attribute *attr, char *buf)
 {
-       if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD)
+       if (!(fujitsu_hotkey->rfkill_supported & 0x20))
                return sprintf(buf, "unknown\n");
        if (fujitsu_hotkey->rfkill_state & 0x20)
                return sprintf(buf, "on\n");
@@ -928,8 +929,17 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
                ; /* No action, result is discarded */
        vdbg_printk(FUJLAPTOP_DBG_INFO, "Discarded %i ringbuffer entries\n", i);
 
-       fujitsu_hotkey->rfkill_state =
-               call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
+       fujitsu_hotkey->rfkill_supported =
+               call_fext_func(FUNC_RFKILL, 0x0, 0x0, 0x0);
+
+       /* Make sure our bitmask of supported functions is cleared if the
+          RFKILL function block is not implemented, like on the S7020. */
+       if (fujitsu_hotkey->rfkill_supported == UNSUPPORTED_CMD)
+               fujitsu_hotkey->rfkill_supported = 0;
+
+       if (fujitsu_hotkey->rfkill_supported)
+               fujitsu_hotkey->rfkill_state =
+                       call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
 
        /* Suspect this is a keymap of the application panel, print it */
        printk(KERN_INFO "fujitsu-laptop: BTNI: [0x%x]\n",
@@ -1005,8 +1015,9 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
 
        input = fujitsu_hotkey->input;
 
-       fujitsu_hotkey->rfkill_state =
-               call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
+       if (fujitsu_hotkey->rfkill_supported)
+               fujitsu_hotkey->rfkill_state =
+                       call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
 
        switch (event) {
        case ACPI_FUJITSU_NOTIFY_CODE1:
index 1fd8f2193ed853b143cdd25d1792224c91f4f1b9..4377e93a43d7f97b7087ed5164967743337fc8a5 100644 (file)
@@ -280,8 +280,11 @@ sclp_dispatch_evbufs(struct sccb_header *sccb)
        rc = 0;
        for (offset = sizeof(struct sccb_header); offset < sccb->length;
             offset += evbuf->length) {
-               /* Search for event handler */
                evbuf = (struct evbuf_header *) ((addr_t) sccb + offset);
+               /* Check for malformed hardware response */
+               if (evbuf->length == 0)
+                       break;
+               /* Search for event handler */
                reg = NULL;
                list_for_each(l, &sclp_reg_list) {
                        reg = list_entry(l, struct sclp_register, list);
index 506390496416ea1163d12919042a6f0d0d34df34..77ab6e34a100b758bc3047888e78f1962a90146d 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/memory.h>
 #include <asm/chpid.h>
 #include <asm/sclp.h>
+#include <asm/setup.h>
 
 #include "sclp.h"
 
@@ -474,6 +475,10 @@ static void __init add_memory_merged(u16 rn)
                goto skip_add;
        if (start + size > VMEM_MAX_PHYS)
                size = VMEM_MAX_PHYS - start;
+       if (memory_end_set && (start >= memory_end))
+               goto skip_add;
+       if (memory_end_set && (start + size > memory_end))
+               size = memory_end - start;
        add_memory(0, start, size);
 skip_add:
        first_rn = rn;
index a1a511bdec8cb87961023da3bbf487de6d9a580e..ed1e728763a2192c14acfe1322ef227ddc01f129 100644 (file)
@@ -1573,9 +1573,6 @@ static int ibmvfc_queuecommand(struct scsi_cmnd *cmnd,
        vfc_cmd->resp_len = sizeof(vfc_cmd->rsp);
        vfc_cmd->cancel_key = (unsigned long)cmnd->device->hostdata;
        vfc_cmd->tgt_scsi_id = rport->port_id;
-       if ((rport->supported_classes & FC_COS_CLASS3) &&
-           (fc_host_supported_classes(vhost->host) & FC_COS_CLASS3))
-               vfc_cmd->flags = IBMVFC_CLASS_3_ERR;
        vfc_cmd->iu.xfer_len = scsi_bufflen(cmnd);
        int_to_scsilun(cmnd->device->lun, &vfc_cmd->iu.lun);
        memcpy(vfc_cmd->iu.cdb, cmnd->cmnd, cmnd->cmd_len);
@@ -3266,6 +3263,7 @@ static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, u64 scsi_id)
                return -ENOMEM;
        }
 
+       memset(tgt, 0, sizeof(*tgt));
        tgt->scsi_id = scsi_id;
        tgt->new_scsi_id = scsi_id;
        tgt->vhost = vhost;
@@ -3576,9 +3574,18 @@ static void ibmvfc_log_ae(struct ibmvfc_host *vhost, int events)
 static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt)
 {
        struct ibmvfc_host *vhost = tgt->vhost;
-       struct fc_rport *rport;
+       struct fc_rport *rport = tgt->rport;
        unsigned long flags;
 
+       if (rport) {
+               tgt_dbg(tgt, "Setting rport roles\n");
+               fc_remote_port_rolechg(rport, tgt->ids.roles);
+               spin_lock_irqsave(vhost->host->host_lock, flags);
+               ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
+               spin_unlock_irqrestore(vhost->host->host_lock, flags);
+               return;
+       }
+
        tgt_dbg(tgt, "Adding rport\n");
        rport = fc_remote_port_add(vhost->host, 0, &tgt->ids);
        spin_lock_irqsave(vhost->host->host_lock, flags);
index 87dafd0f8d4416b48e27bf08b3673d391a670abe..b21e071b986214875074ea35748e775a4ec51469 100644 (file)
@@ -32,7 +32,7 @@
 #define IBMVFC_DRIVER_VERSION          "1.0.4"
 #define IBMVFC_DRIVER_DATE             "(November 14, 2008)"
 
-#define IBMVFC_DEFAULT_TIMEOUT 15
+#define IBMVFC_DEFAULT_TIMEOUT 60
 #define IBMVFC_INIT_TIMEOUT            120
 #define IBMVFC_MAX_REQUESTS_DEFAULT    100
 
index 74d07d137daeb75b038071f6fe9a279b927243e1..c9aa7611e40824142534d21aa46fc4461936ba33 100644 (file)
@@ -432,6 +432,7 @@ static int map_sg_data(struct scsi_cmnd *cmd,
                                sdev_printk(KERN_ERR, cmd->device,
                                            "Can't allocate memory "
                                            "for indirect table\n");
+                       scsi_dma_unmap(cmd);
                        return 0;
                }
        }
index 257c24115de9108132d955ab5e488cf0b6c37c3e..809d32d95c76e6457a33469c8a43bf7246ef44e0 100644 (file)
@@ -1998,6 +1998,8 @@ int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev)
        if (!shost->can_queue)
                shost->can_queue = ISCSI_DEF_XMIT_CMDS_MAX;
 
+       if (!shost->transportt->eh_timed_out)
+               shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
        return scsi_add_host(shost, pdev);
 }
 EXPORT_SYMBOL_GPL(iscsi_host_add);
@@ -2020,7 +2022,6 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
        shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size);
        if (!shost)
                return NULL;
-       shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
 
        if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
                if (qdepth != 0)
index a8f30bdaff69a2e1203297a5bbbb7caa823cf550..a7302480bc4a7fb3605f6317631de89e5a9303d4 100644 (file)
@@ -5258,6 +5258,7 @@ lpfc_send_els_event(struct lpfc_vport *vport,
                        sizeof(struct lpfc_name));
                break;
        default:
+               kfree(els_data);
                return;
        }
        memcpy(els_data->wwpn, &ndlp->nlp_portname, sizeof(struct lpfc_name));
index 33a3c13fd8936b717fb3cec81258a76e88478094..f4c57227ec185cf2a6357ebc24bccf674e7e36cf 100644 (file)
@@ -1265,13 +1265,6 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
            test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags))
                msleep(1000);
 
-       if (ha->mqenable) {
-               if (qla25xx_delete_queues(vha, 0) != QLA_SUCCESS)
-                       qla_printk(KERN_WARNING, ha,
-                               "Queue delete failed.\n");
-               vha->req_ques[0] = ha->req_q_map[0]->id;
-       }
-
        qla24xx_disable_vp(vha);
 
        fc_remove_host(vha->host);
@@ -1293,6 +1286,12 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
                    vha->host_no, vha->vp_idx, vha));
         }
 
+       if (ha->mqenable) {
+               if (qla25xx_delete_queues(vha, 0) != QLA_SUCCESS)
+                       qla_printk(KERN_WARNING, ha,
+                               "Queue delete failed.\n");
+       }
+
        scsi_host_put(vha->host);
        qla_printk(KERN_INFO, ha, "vport %d deleted\n", id);
        return 0;
index 023ee77fb027beddfacc5005d2372f0f3a3d584e..e0c5bb54b258a492e9ceb641cada66b07d4785f8 100644 (file)
@@ -2135,6 +2135,7 @@ struct qla_msix_entry {
 /* Work events.  */
 enum qla_work_type {
        QLA_EVT_AEN,
+       QLA_EVT_IDC_ACK,
 };
 
 
@@ -2149,6 +2150,10 @@ struct qla_work_evt {
                        enum fc_host_event_code code;
                        u32 data;
                } aen;
+               struct {
+#define QLA_IDC_ACK_REGS       7
+                       uint16_t mb[QLA_IDC_ACK_REGS];
+               } idc_ack;
        } u;
 };
 
index d78d35e681ab3413f5b3835d1671709ca76e8753..d6ea69df7c5cf584ae21ab4c210c05a0873f1422 100644 (file)
@@ -72,7 +72,7 @@ static char *qla2x00_model_name[QLA_MODEL_NAMES*2] = {
        "QLA2462",      "Sun PCI-X 2.0 to 4Gb FC, Dual Channel",        /* 0x141 */
        "QLE2460",      "Sun PCI-Express to 2Gb FC, Single Channel",    /* 0x142 */
        "QLE2462",      "Sun PCI-Express to 4Gb FC, Single Channel",    /* 0x143 */
-       "QEM2462"       "Server I/O Module 4Gb FC, Dual Channel",       /* 0x144 */
+       "QEM2462",      "Server I/O Module 4Gb FC, Dual Channel",       /* 0x144 */
        "QLE2440",      "PCI-Express to 4Gb FC, Single Channel",        /* 0x145 */
        "QLE2464",      "PCI-Express to 4Gb FC, Quad Channel",          /* 0x146 */
        "QLA2440",      "PCI-X 2.0 to 4Gb FC, Single Channel",          /* 0x147 */
index 7abb045a0410e4eed6624af160188bff170ec797..ffff4255408784ffe24c1a2753a9654950e5ca6d 100644 (file)
@@ -1402,6 +1402,8 @@ struct access_chip_rsp_84xx {
 #define MBA_IDC_NOTIFY         0x8101
 #define MBA_IDC_TIME_EXT       0x8102
 
+#define MBC_IDC_ACK            0x101
+
 struct nvram_81xx {
        /* NVRAM header. */
        uint8_t id[4];
index a336b4bc81a7e50b5d1407ba249c0c5944615a6f..6de283f8f111d0a2a30056594e02b6e410add6f1 100644 (file)
@@ -72,6 +72,7 @@ extern int qla2x00_loop_reset(scsi_qla_host_t *);
 extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
 extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
     fc_host_event_code, u32);
+extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *);
 
 extern void qla2x00_abort_fcport_cmds(fc_port_t *);
 extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *,
@@ -266,6 +267,8 @@ qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *);
 
 extern int qla84xx_verify_chip(struct scsi_qla_host *, uint16_t *);
 
+extern int qla81xx_idc_ack(scsi_qla_host_t *, uint16_t *);
+
 /*
  * Global Function Prototypes in qla_isr.c source file.
  */
@@ -376,10 +379,8 @@ extern int qla2x00_dfs_remove(scsi_qla_host_t *);
 
 /* Globa function prototypes for multi-q */
 extern int qla25xx_request_irq(struct rsp_que *);
-extern int qla25xx_init_req_que(struct scsi_qla_host *, struct req_que *,
-       uint8_t);
-extern int qla25xx_init_rsp_que(struct scsi_qla_host *, struct rsp_que *,
-       uint8_t);
+extern int qla25xx_init_req_que(struct scsi_qla_host *, struct req_que *);
+extern int qla25xx_init_rsp_que(struct scsi_qla_host *, struct rsp_que *);
 extern int qla25xx_create_req_que(struct qla_hw_data *, uint16_t, uint8_t,
        uint16_t, uint8_t, uint8_t);
 extern int qla25xx_create_rsp_que(struct qla_hw_data *, uint16_t, uint8_t,
index f6368a1d3021e1e4e2f2c569d5742683cab61d47..986501759ad4910fa6b93c7db75d355001c47ad8 100644 (file)
@@ -1226,9 +1226,8 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
                        icb->firmware_options_2 |=
                                __constant_cpu_to_le32(BIT_18);
 
-               icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_22);
+               icb->firmware_options_2 &= __constant_cpu_to_le32(~BIT_22);
                icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_23);
-               ha->rsp_q_map[0]->options = icb->firmware_options_2;
 
                WRT_REG_DWORD(&reg->isp25mq.req_q_in, 0);
                WRT_REG_DWORD(&reg->isp25mq.req_q_out, 0);
@@ -3493,7 +3492,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
                rsp = ha->rsp_q_map[i];
                if (rsp) {
                        rsp->options &= ~BIT_0;
-                       ret = qla25xx_init_rsp_que(base_vha, rsp, rsp->options);
+                       ret = qla25xx_init_rsp_que(base_vha, rsp);
                        if (ret != QLA_SUCCESS)
                                DEBUG2_17(printk(KERN_WARNING
                                        "%s Rsp que:%d init failed\n", __func__,
@@ -3507,7 +3506,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
                if (req) {
                /* Clear outstanding commands array. */
                        req->options &= ~BIT_0;
-                       ret = qla25xx_init_req_que(base_vha, req, req->options);
+                       ret = qla25xx_init_req_que(base_vha, req);
                        if (ret != QLA_SUCCESS)
                                DEBUG2_17(printk(KERN_WARNING
                                        "%s Req que:%d init failed\n", __func__,
index e28ad81baf1e09d84edcbfef99e1ce945c2264b3..f250e5b7897cf7387f14579d50dd9462c2b0dc28 100644 (file)
@@ -266,6 +266,40 @@ qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
        }
 }
 
+static void
+qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr)
+{
+       static char *event[] =
+               { "Complete", "Request Notification", "Time Extension" };
+       int rval;
+       struct device_reg_24xx __iomem *reg24 = &vha->hw->iobase->isp24;
+       uint16_t __iomem *wptr;
+       uint16_t cnt, timeout, mb[QLA_IDC_ACK_REGS];
+
+       /* Seed data -- mailbox1 -> mailbox7. */
+       wptr = (uint16_t __iomem *)&reg24->mailbox1;
+       for (cnt = 0; cnt < QLA_IDC_ACK_REGS; cnt++, wptr++)
+               mb[cnt] = RD_REG_WORD(wptr);
+
+       DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
+           "%04x %04x %04x %04x %04x %04x %04x.\n", vha->host_no,
+           event[aen & 0xff],
+           mb[0], mb[1], mb[2], mb[3], mb[4], mb[5], mb[6]));
+
+       /* Acknowledgement needed? [Notify && non-zero timeout]. */
+       timeout = (descr >> 8) & 0xf;
+       if (aen != MBA_IDC_NOTIFY || !timeout)
+               return;
+
+       DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
+           "ACK timeout=%d.\n", vha->host_no, event[aen & 0xff], timeout));
+
+       rval = qla2x00_post_idc_ack_work(vha, mb);
+       if (rval != QLA_SUCCESS)
+               qla_printk(KERN_WARNING, vha->hw,
+                   "IDC failed to post ACK.\n");
+}
+
 /**
  * qla2x00_async_event() - Process aynchronous events.
  * @ha: SCSI driver HA context
@@ -714,21 +748,9 @@ skip_rio:
                    "%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
                break;
        case MBA_IDC_COMPLETE:
-               DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
-                   "Complete -- %04x %04x %04x\n", vha->host_no, mb[1], mb[2],
-                   mb[3]));
-               break;
        case MBA_IDC_NOTIFY:
-               DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
-                   "Request Notification -- %04x %04x %04x\n", vha->host_no,
-                   mb[1], mb[2], mb[3]));
-               /**** Mailbox registers 4 - 7 valid!!! */
-               break;
        case MBA_IDC_TIME_EXT:
-               DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
-                   "Time Extension -- %04x %04x %04x\n", vha->host_no, mb[1],
-                   mb[2], mb[3]));
-               /**** Mailbox registers 4 - 7 valid!!! */
+               qla81xx_idc_event(vha, mb[0], mb[1]);
                break;
        }
 
@@ -1707,7 +1729,6 @@ qla25xx_msix_rsp_q(int irq, void *dev_id)
        struct qla_hw_data *ha;
        struct rsp_que *rsp;
        struct device_reg_24xx __iomem *reg;
-       uint16_t msix_disabled_hccr = 0;
 
        rsp = (struct rsp_que *) dev_id;
        if (!rsp) {
@@ -1720,17 +1741,8 @@ qla25xx_msix_rsp_q(int irq, void *dev_id)
 
        spin_lock_irq(&ha->hardware_lock);
 
-       msix_disabled_hccr = rsp->options;
-       if (!rsp->id)
-               msix_disabled_hccr &= __constant_cpu_to_le32(BIT_22);
-       else
-               msix_disabled_hccr &= __constant_cpu_to_le32(BIT_6);
-
        qla24xx_process_response_queue(rsp);
 
-       if (!msix_disabled_hccr)
-               WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
-
        spin_unlock_irq(&ha->hardware_lock);
 
        return IRQ_HANDLED;
index f94ffbb98e95f2a53918888ed76ebf235b3aa5cc..4c7504cb3990490830e89c85edeea9df7bf004db 100644 (file)
@@ -3090,8 +3090,7 @@ verify_done:
 }
 
 int
-qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req,
-       uint8_t options)
+qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req)
 {
        int rval;
        unsigned long flags;
@@ -3101,7 +3100,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req,
        struct qla_hw_data *ha = vha->hw;
 
        mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
-       mcp->mb[1] = options;
+       mcp->mb[1] = req->options;
        mcp->mb[2] = MSW(LSD(req->dma));
        mcp->mb[3] = LSW(LSD(req->dma));
        mcp->mb[6] = MSW(MSD(req->dma));
@@ -3128,7 +3127,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req,
        mcp->tov = 60;
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
-       if (!(options & BIT_0)) {
+       if (!(req->options & BIT_0)) {
                WRT_REG_DWORD(&reg->req_q_in, 0);
                WRT_REG_DWORD(&reg->req_q_out, 0);
        }
@@ -3142,8 +3141,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req,
 }
 
 int
-qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp,
-       uint8_t options)
+qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
 {
        int rval;
        unsigned long flags;
@@ -3153,7 +3151,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp,
        struct qla_hw_data *ha = vha->hw;
 
        mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
-       mcp->mb[1] = options;
+       mcp->mb[1] = rsp->options;
        mcp->mb[2] = MSW(LSD(rsp->dma));
        mcp->mb[3] = LSW(LSD(rsp->dma));
        mcp->mb[6] = MSW(MSD(rsp->dma));
@@ -3178,7 +3176,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp,
        mcp->tov = 60;
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
-       if (!(options & BIT_0)) {
+       if (!(rsp->options & BIT_0)) {
                WRT_REG_DWORD(&reg->rsp_q_out, 0);
                WRT_REG_DWORD(&reg->rsp_q_in, 0);
        }
@@ -3193,3 +3191,29 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp,
        return rval;
 }
 
+int
+qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb)
+{
+       int rval;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+
+       mcp->mb[0] = MBC_IDC_ACK;
+       memcpy(&mcp->mb[1], mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
+       mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+       mcp->in_mb = MBX_0;
+       mcp->tov = MBX_TOV_SECONDS;
+       mcp->flags = 0;
+       rval = qla2x00_mailbox_command(vha, mcp);
+
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
+                   vha->host_no, rval, mcp->mb[0]));
+       } else {
+               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+       }
+
+       return rval;
+}
index f53179c46423adb449c2480aa205bcd2b868c17a..3f23932210c4231a38c7c8ccd9ccd77a85951e91 100644 (file)
@@ -396,7 +396,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
 
        qla2x00_start_timer(vha, qla2x00_timer, WATCH_INTERVAL);
 
-       memset(vha->req_ques, 0, sizeof(vha->req_ques) * QLA_MAX_HOST_QUES);
+       memset(vha->req_ques, 0, sizeof(vha->req_ques));
        vha->req_ques[0] = ha->req_q_map[0]->id;
        host->can_queue = ha->req_q_map[0]->length + 128;
        host->this_id = 255;
@@ -471,7 +471,7 @@ qla25xx_delete_req_que(struct scsi_qla_host *vha, struct req_que *req)
 
        if (req) {
                req->options |= BIT_0;
-               ret = qla25xx_init_req_que(vha, req, req->options);
+               ret = qla25xx_init_req_que(vha, req);
        }
        if (ret == QLA_SUCCESS)
                qla25xx_free_req_que(vha, req);
@@ -486,7 +486,7 @@ qla25xx_delete_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
 
        if (rsp) {
                rsp->options |= BIT_0;
-               ret = qla25xx_init_rsp_que(vha, rsp, rsp->options);
+               ret = qla25xx_init_rsp_que(vha, rsp);
        }
        if (ret == QLA_SUCCESS)
                qla25xx_free_rsp_que(vha, rsp);
@@ -502,7 +502,7 @@ int qla25xx_update_req_que(struct scsi_qla_host *vha, uint8_t que, uint8_t qos)
 
        req->options |= BIT_3;
        req->qos = qos;
-       ret = qla25xx_init_req_que(vha, req, req->options);
+       ret = qla25xx_init_req_que(vha, req);
        if (ret != QLA_SUCCESS)
                DEBUG2_17(printk(KERN_WARNING "%s failed\n", __func__));
        /* restore options bit */
@@ -632,7 +632,7 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
        req->max_q_depth = ha->req_q_map[0]->max_q_depth;
        mutex_unlock(&ha->vport_lock);
 
-       ret = qla25xx_init_req_que(base_vha, req, options);
+       ret = qla25xx_init_req_que(base_vha, req);
        if (ret != QLA_SUCCESS) {
                qla_printk(KERN_WARNING, ha, "%s failed\n", __func__);
                mutex_lock(&ha->vport_lock);
@@ -710,7 +710,7 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
        if (ret)
                goto que_failed;
 
-       ret = qla25xx_init_rsp_que(base_vha, rsp, options);
+       ret = qla25xx_init_rsp_que(base_vha, rsp);
        if (ret != QLA_SUCCESS) {
                qla_printk(KERN_WARNING, ha, "%s failed\n", __func__);
                mutex_lock(&ha->vport_lock);
index c11f872d3e105776f76b9fe566f24289bb87d331..2f5f72531e23108acde73b9174d22af9e584e83c 100644 (file)
@@ -2522,6 +2522,19 @@ qla2x00_post_aen_work(struct scsi_qla_host *vha, enum fc_host_event_code code,
        return qla2x00_post_work(vha, e, 1);
 }
 
+int
+qla2x00_post_idc_ack_work(struct scsi_qla_host *vha, uint16_t *mb)
+{
+       struct qla_work_evt *e;
+
+       e = qla2x00_alloc_work(vha, QLA_EVT_IDC_ACK, 1);
+       if (!e)
+               return QLA_FUNCTION_FAILED;
+
+       memcpy(e->u.idc_ack.mb, mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
+       return qla2x00_post_work(vha, e, 1);
+}
+
 static void
 qla2x00_do_work(struct scsi_qla_host *vha)
 {
@@ -2539,6 +2552,9 @@ qla2x00_do_work(struct scsi_qla_host *vha)
                        fc_host_post_event(vha->host, fc_get_event_number(),
                            e->u.aen.code, e->u.aen.data);
                        break;
+               case QLA_EVT_IDC_ACK:
+                       qla81xx_idc_ack(vha, e->u.idc_ack.mb);
+                       break;
                }
                if (e->flags & QLA_EVT_FLAG_FREE)
                        kfree(e);
index 9c3b694c049dad0695a4d99d59de28d3a57493ce..284827926effc096155dd3e755a2348fb03631d6 100644 (file)
@@ -684,7 +684,7 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
                    "end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start,
                    le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size)));
 
-               switch (le32_to_cpu(region->code)) {
+               switch (le32_to_cpu(region->code) & 0xff) {
                case FLT_REG_FW:
                        ha->flt_region_fw = start;
                        break;
index cfa4c11a4797abf8a8a2e9b7ee1669ca6d3705ac..79f7053da99b47bec9478f5454d01dcf20685403 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.03.00-k2"
+#define QLA2XXX_VERSION      "8.03.00-k3"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   3
index 66505bb794100320f03aa43344be94284c22dcfd..8f4de20c9deb061266b41f18866931523e93241a 100644 (file)
@@ -317,6 +317,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
        return sdev;
 
 out_device_destroy:
+       scsi_device_set_state(sdev, SDEV_DEL);
        transport_destroy_device(&sdev->sdev_gendev);
        put_device(&sdev->sdev_gendev);
 out:
index 8f0bd3f7a59fdbc9b8c50ab69904d388b4ce24c5..516925d8b570c3fab05d5d1b0a6b729e0ebce395 100644 (file)
@@ -1078,7 +1078,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
        case BLKTRACESETUP:
                return blk_trace_setup(sdp->device->request_queue,
                                       sdp->disk->disk_name,
-                                      sdp->device->sdev_gendev.devt,
+                                      MKDEV(SCSI_GENERIC_MAJOR, sdp->index),
                                       (char *)arg);
        case BLKTRACESTART:
                return blk_trace_startstop(sdp->device->request_queue, 1);
index 0d934bfbdd9b2ded293260968927a7de5e776f88..b4b39811b44544cc76a4c71e00c5c02567a765c2 100644 (file)
@@ -2083,6 +2083,20 @@ static int serial8250_startup(struct uart_port *port)
 
        serial8250_set_mctrl(&up->port, up->port.mctrl);
 
+       /* Serial over Lan (SoL) hack:
+          Intel 8257x Gigabit ethernet chips have a
+          16550 emulation, to be used for Serial Over Lan.
+          Those chips take a longer time than a normal
+          serial device to signalize that a transmission
+          data was queued. Due to that, the above test generally
+          fails. One solution would be to delay the reading of
+          iir. However, this is not reliable, since the timeout
+          is variable. So, let's just don't test if we receive
+          TX irq. This way, we'll never enable UART_BUG_TXEN.
+        */
+       if (up->port.flags & UPF_NO_TXEN_TEST)
+               goto dont_test_tx_en;
+
        /*
         * Do a quick test to see if we receive an
         * interrupt when we enable the TX irq.
@@ -2102,6 +2116,7 @@ static int serial8250_startup(struct uart_port *port)
                up->bugs &= ~UART_BUG_TXEN;
        }
 
+dont_test_tx_en:
        spin_unlock_irqrestore(&up->port.lock, flags);
 
        /*
index 536d8e510f66da655b9106ac7eb2e0719edce2b3..533f82025adf218e6fffbfd1730f94839924be21 100644 (file)
@@ -798,6 +798,21 @@ pci_default_setup(struct serial_private *priv,
        return setup_port(priv, port, bar, offset, board->reg_shift);
 }
 
+static int skip_tx_en_setup(struct serial_private *priv,
+                       const struct pciserial_board *board,
+                       struct uart_port *port, int idx)
+{
+       port->flags |= UPF_NO_TXEN_TEST;
+       printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
+                         "[%04x:%04x] subsystem [%04x:%04x]\n",
+                         priv->dev->vendor,
+                         priv->dev->device,
+                         priv->dev->subsystem_vendor,
+                         priv->dev->subsystem_device);
+
+       return pci_default_setup(priv, board, port, idx);
+}
+
 /* This should be in linux/pci_ids.h */
 #define PCI_VENDOR_ID_SBSMODULARIO     0x124B
 #define PCI_SUBVENDOR_ID_SBSMODULARIO  0x124B
@@ -864,6 +879,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .init           = pci_inteli960ni_init,
                .setup          = pci_default_setup,
        },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_8257X_SOL,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = skip_tx_en_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_82573L_SOL,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = skip_tx_en_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_82573E_SOL,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = skip_tx_en_setup,
+       },
        /*
         * ITE
         */
index 89362d733d6230331c6bead3c8bbce3ef9d28563..8f58f7ff0dd7db29af5c749dbeda386b8c6c10b9 100644 (file)
@@ -877,6 +877,10 @@ static int atmel_startup(struct uart_port *port)
                }
        }
 
+       /* Save current CSR for comparison in atmel_tasklet_func() */
+       atmel_port->irq_status_prev = UART_GET_CSR(port);
+       atmel_port->irq_status = atmel_port->irq_status_prev;
+
        /*
         * Finally, enable the serial port
         */
index 92187e28608aeb6cb03c0a090a38db5d186bd090..ac79cbe4c2cf40e2e5512a4607d517c120784757 100644 (file)
@@ -84,6 +84,8 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        brd->pci_dev = pdev;
        if (pdev->device == PCIE_DEVICE_ID_NEO_4_IBM)
                brd->maxports = 4;
+       else if (pdev->device == PCI_DEVICE_ID_DIGI_NEO_8)
+               brd->maxports = 8;
        else
                brd->maxports = 2;
 
@@ -212,6 +214,7 @@ static struct pci_device_id jsm_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45), 0, 0, 2 },
        { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45PRI), 0, 0, 3 },
        { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_4_IBM), 0, 0, 4 },
+       { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_NEO_8), 0, 0, 5 },
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, jsm_pci_tbl);
index 49698cabc30ddba88a6a6b02cb6ab3dd07da0fac..f5ed9721aabb33c24c9a75c79d58df19e595450f 100644 (file)
@@ -114,7 +114,7 @@ static inline void setmosi(const struct spi_device *spi, int is_on)
 
 static inline int getmiso(const struct spi_device *spi)
 {
-       return gpio_get_value(SPI_MISO_GPIO);
+       return !!gpio_get_value(SPI_MISO_GPIO);
 }
 
 #undef pdata
index c54fc40458b171aa863eec63aa4821a45287d4e2..a4301dc02d275c1f28c77cde42183d1a2d435792 100644 (file)
@@ -297,19 +297,6 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
 }
 EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend);
 
-/**
- * usb_hcd_pci_resume_early - resume a PCI-based HCD before IRQs are enabled
- * @dev: USB Host Controller being resumed
- *
- * Store this function in the HCD's struct pci_driver as .resume_early.
- */
-int usb_hcd_pci_resume_early(struct pci_dev *dev)
-{
-       pci_restore_state(dev);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(usb_hcd_pci_resume_early);
-
 /**
  * usb_hcd_pci_resume - power management resume of a PCI-based HCD
  * @dev: USB Host Controller being resumed
@@ -333,6 +320,8 @@ int usb_hcd_pci_resume(struct pci_dev *dev)
        }
 #endif
 
+       pci_restore_state(dev);
+
        hcd = pci_get_drvdata(dev);
        if (hcd->state != HC_STATE_SUSPENDED) {
                dev_dbg(hcd->self.controller,
index 5b94a56bec2356d7945ec4d56bca543d0c229a26..f750eb1ab595e926aecba81a9579f8674eae76fa 100644 (file)
@@ -257,7 +257,6 @@ extern void usb_hcd_pci_remove(struct pci_dev *dev);
 
 #ifdef CONFIG_PM
 extern int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t msg);
-extern int usb_hcd_pci_resume_early(struct pci_dev *dev);
 extern int usb_hcd_pci_resume(struct pci_dev *dev);
 #endif /* CONFIG_PM */
 
index 9b36205c5759d3d1f8cf11b8edeba1958d1371e1..0ce4e2819847c13fb7548fcf910923495d4588ba 100644 (file)
@@ -904,8 +904,8 @@ static void pxa25x_ep_fifo_flush(struct usb_ep *_ep)
 
        /* most IN status is the same, but ISO can't stall */
        *ep->reg_udccs = UDCCS_BI_TPC|UDCCS_BI_FTF|UDCCS_BI_TUR
-               | (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
-                       ? 0 : UDCCS_BI_SST;
+               | (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
+                       ? 0 : UDCCS_BI_SST);
 }
 
 
index bb21fb0a4969d0bc793f22c091c5053b973ddeac..abb9a7706ec7c370dd0835db9d04b0e3f1abc6b8 100644 (file)
@@ -432,7 +432,6 @@ static struct pci_driver ehci_pci_driver = {
 
 #ifdef CONFIG_PM
        .suspend =      usb_hcd_pci_suspend,
-       .resume_early = usb_hcd_pci_resume_early,
        .resume =       usb_hcd_pci_resume,
 #endif
        .shutdown =     usb_hcd_pci_shutdown,
index 5d625c3fd4232b163699ac5975bfe6da08d639a7..f9961b4c0da3e5065f054aa7dc34a619e00b8187 100644 (file)
@@ -487,7 +487,6 @@ static struct pci_driver ohci_pci_driver = {
 
 #ifdef CONFIG_PM
        .suspend =      usb_hcd_pci_suspend,
-       .resume_early = usb_hcd_pci_resume_early,
        .resume =       usb_hcd_pci_resume,
 #endif
 
index 944f7e0ca4df1327eeb7025f706677741f462ae0..cf5e4cf7ea425828ca099af27dc6d2639ded8f9a 100644 (file)
@@ -942,7 +942,6 @@ static struct pci_driver uhci_pci_driver = {
 
 #ifdef CONFIG_PM
        .suspend =      usb_hcd_pci_suspend,
-       .resume_early = usb_hcd_pci_resume_early,
        .resume =       usb_hcd_pci_resume,
 #endif /* PM */
 };
index 2291c5f5af5152b3aadcf029f48fcc73dd05fba6..958751ccea432cd3f41bda0dbd55828f5d15efd4 100644 (file)
@@ -227,13 +227,13 @@ void scan_async_work(struct work_struct *work)
         * Now that the ASL is updated, complete the removal of any
         * removed qsets.
         */
-       spin_lock(&whc->lock);
+       spin_lock_irq(&whc->lock);
 
        list_for_each_entry_safe(qset, t, &whc->async_removed_list, list_node) {
                qset_remove_complete(whc, qset);
        }
 
-       spin_unlock(&whc->lock);
+       spin_unlock_irq(&whc->lock);
 }
 
 /**
index 7dc85a0bee7c2f563c3c89f8e7d5aa9229ffd4df..df8b85f07092e3c398a410fff318f9b9b772ba7c 100644 (file)
@@ -255,13 +255,13 @@ void scan_periodic_work(struct work_struct *work)
         * Now that the PZL is updated, complete the removal of any
         * removed qsets.
         */
-       spin_lock(&whc->lock);
+       spin_lock_irq(&whc->lock);
 
        list_for_each_entry_safe(qset, t, &whc->periodic_removed_list, list_node) {
                qset_remove_complete(whc, qset);
        }
 
-       spin_unlock(&whc->lock);
+       spin_unlock_irq(&whc->lock);
 }
 
 /**
index bf0af660df8a07e7b922871a8da860dff77accea..fb19803060cf6c35727c9f287f5668bf670ed969 100644 (file)
@@ -1054,10 +1054,7 @@ config FB_RIVA_BACKLIGHT
 
 config FB_I810
        tristate "Intel 810/815 support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && PCI && X86_32
-       select AGP
-       select AGP_INTEL
-       select FB
+       depends on EXPERIMENTAL && FB && PCI && X86_32 && AGP_INTEL
        select FB_MODE_HELPERS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
@@ -1120,10 +1117,7 @@ config FB_CARILLO_RANCH
 
 config FB_INTEL
        tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && PCI && X86
-       select FB
-       select AGP
-       select AGP_INTEL
+       depends on EXPERIMENTAL && FB && PCI && X86 && AGP_INTEL
        select FB_MODE_HELPERS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
index 8058572a74283303f178d03d0e97e64632c85099..018850c116c646edbeadf5cc6e4fc828e3901eff 100644 (file)
@@ -841,7 +841,7 @@ static int tt_detect(void)
                tt_dmasnd.ctrl = DMASND_CTRL_OFF;
                udelay(20);             /* wait a while for things to settle down */
        }
-       mono_moni = (mfp.par_dt_reg & 0x80) == 0;
+       mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
 
        tt_get_par(&par);
        tt_encode_var(&atafb_predefined[0], &par);
@@ -2035,7 +2035,7 @@ static int stste_detect(void)
                tt_dmasnd.ctrl = DMASND_CTRL_OFF;
                udelay(20);             /* wait a while for things to settle down */
        }
-       mono_moni = (mfp.par_dt_reg & 0x80) == 0;
+       mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
 
        stste_get_par(&par);
        stste_encode_var(&atafb_predefined[0], &par);
@@ -2086,20 +2086,20 @@ static void st_ovsc_switch(void)
                return;
        local_irq_save(flags);
 
-       mfp.tim_ct_b = 0x10;
-       mfp.active_edge |= 8;
-       mfp.tim_ct_b = 0;
-       mfp.tim_dt_b = 0xf0;
-       mfp.tim_ct_b = 8;
-       while (mfp.tim_dt_b > 1)        /* TOS does it this way, don't ask why */
+       st_mfp.tim_ct_b = 0x10;
+       st_mfp.active_edge |= 8;
+       st_mfp.tim_ct_b = 0;
+       st_mfp.tim_dt_b = 0xf0;
+       st_mfp.tim_ct_b = 8;
+       while (st_mfp.tim_dt_b > 1)     /* TOS does it this way, don't ask why */
                ;
-       new = mfp.tim_dt_b;
+       new = st_mfp.tim_dt_b;
        do {
                udelay(LINE_DELAY);
                old = new;
-               new = mfp.tim_dt_b;
+               new = st_mfp.tim_dt_b;
        } while (old != new);
-       mfp.tim_ct_b = 0x10;
+       st_mfp.tim_ct_b = 0x10;
        udelay(SYNC_DELAY);
 
        if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
index e6e299feb51bd5151eba736e03309d89da1d29ae..2181ce4d7ebd4c75009683c2f50bb0d1eebcd034 100644 (file)
@@ -2365,7 +2365,6 @@ static void fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx
 static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
 {
        u32     pmgt;
-       u16     pwr_command;
        struct pci_dev *pdev = par->pdev;
 
        if (!par->pm_reg)
index 09a3d5522b43d9a2b6d00f3612f6c88c516068ae..325c10ff6a2cd2dc616228bead8fc5c8cdb7f034 100644 (file)
@@ -406,7 +406,7 @@ config ITCO_WDT
        ---help---
          Hardware driver for the intel TCO timer based watchdog devices.
          These drivers are included in the Intel 82801 I/O Controller
-         Hub family (from ICH0 up to ICH8) and in the Intel 6300ESB
+         Hub family (from ICH0 up to ICH10) and in the Intel 63xxESB
          controller hub.
 
          The TCO (Total Cost of Ownership) timer is a watchdog timer
index 5531691f46eaf51746db11cd23acc61dbde095ed..e35d545892325b15f1b26427bf5475728e8a8504 100644 (file)
@@ -107,10 +107,10 @@ static int at91_wdt_close(struct inode *inode, struct file *file)
 static int at91_wdt_settimeout(int new_time)
 {
        /*
-        * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
+        * All counting occurs at SLOW_CLOCK / 128 = 256 Hz
         *
         * Since WDV is a 16-bit counter, the maximum period is
-        * 65536 / 0.256 = 256 seconds.
+        * 65536 / 256 = 256 seconds.
         */
        if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
                return -EINVAL;
index b1da287f90ecc24bc5395234a5d71198f0fb630a..a56ac84381b1d3ad3a879cee04bfd657fe907565 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/miscdevice.h>
 #include <linux/module.h>
index 2474ebca88f6d816837765b667bdf7e9e4ea087f..d8264ad0be41f91f8ac9cfcc8ce79faff8d0f48d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     intel TCO vendor specific watchdog driver support
  *
- *     (c) Copyright 2006-2008 Wim Van Sebroeck <wim@iguana.be>.
+ *     (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>.
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
@@ -19,7 +19,7 @@
 
 /* Module and version information */
 #define DRV_NAME       "iTCO_vendor_support"
-#define DRV_VERSION    "1.02"
+#define DRV_VERSION    "1.03"
 #define PFX            DRV_NAME ": "
 
 /* Includes */
@@ -77,6 +77,26 @@ MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (n
  *         20.6 seconds.
  */
 
+static void supermicro_old_pre_start(unsigned long acpibase)
+{
+       unsigned long val32;
+
+       /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
+       val32 = inl(SMI_EN);
+       val32 &= 0xffffdfff;    /* Turn off SMI clearing watchdog */
+       outl(val32, SMI_EN);    /* Needed to activate watchdog */
+}
+
+static void supermicro_old_pre_stop(unsigned long acpibase)
+{
+       unsigned long val32;
+
+       /* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */
+       val32 = inl(SMI_EN);
+       val32 |= 0x00002000;    /* Turn on SMI clearing watchdog */
+       outl(val32, SMI_EN);    /* Needed to deactivate watchdog */
+}
+
 static void supermicro_old_pre_keepalive(unsigned long acpibase)
 {
        /* Reload TCO Timer (done in iTCO_wdt_keepalive) + */
@@ -228,14 +248,18 @@ static void supermicro_new_pre_set_heartbeat(unsigned int heartbeat)
 void iTCO_vendor_pre_start(unsigned long acpibase,
                           unsigned int heartbeat)
 {
-       if (vendorsupport == SUPERMICRO_NEW_BOARD)
+       if (vendorsupport == SUPERMICRO_OLD_BOARD)
+               supermicro_old_pre_start(acpibase);
+       else if (vendorsupport == SUPERMICRO_NEW_BOARD)
                supermicro_new_pre_start(heartbeat);
 }
 EXPORT_SYMBOL(iTCO_vendor_pre_start);
 
 void iTCO_vendor_pre_stop(unsigned long acpibase)
 {
-       if (vendorsupport == SUPERMICRO_NEW_BOARD)
+       if (vendorsupport == SUPERMICRO_OLD_BOARD)
+               supermicro_old_pre_stop(acpibase);
+       else if (vendorsupport == SUPERMICRO_NEW_BOARD)
                supermicro_new_pre_stop();
 }
 EXPORT_SYMBOL(iTCO_vendor_pre_stop);
index 5b395a4ddfdfec67dbd4324acbc521258977a855..352334947ea30ba0726bdb214915494d9122ddbe 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *     intel TCO Watchdog Driver (Used in i82801 and i6300ESB chipsets)
+ *     intel TCO Watchdog Driver (Used in i82801 and i63xxESB chipsets)
  *
- *     (c) Copyright 2006-2008 Wim Van Sebroeck <wim@iguana.be>.
+ *     (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>.
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
@@ -63,7 +63,7 @@
 
 /* Module and version information */
 #define DRV_NAME       "iTCO_wdt"
-#define DRV_VERSION    "1.04"
+#define DRV_VERSION    "1.05"
 #define PFX            DRV_NAME ": "
 
 /* Includes */
@@ -236,16 +236,16 @@ MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
 
 /* Address definitions for the TCO */
 /* TCO base address */
-#define        TCOBASE         iTCO_wdt_private.ACPIBASE + 0x60
+#define TCOBASE                iTCO_wdt_private.ACPIBASE + 0x60
 /* SMI Control and Enable Register */
-#define        SMI_EN          iTCO_wdt_private.ACPIBASE + 0x30
+#define SMI_EN         iTCO_wdt_private.ACPIBASE + 0x30
 
 #define TCO_RLD                TCOBASE + 0x00  /* TCO Timer Reload and Curr. Value */
 #define TCOv1_TMR      TCOBASE + 0x01  /* TCOv1 Timer Initial Value    */
-#define        TCO_DAT_IN      TCOBASE + 0x02  /* TCO Data In Register         */
-#define        TCO_DAT_OUT     TCOBASE + 0x03  /* TCO Data Out Register        */
-#define        TCO1_STS        TCOBASE + 0x04  /* TCO1 Status Register         */
-#define        TCO2_STS        TCOBASE + 0x06  /* TCO2 Status Register         */
+#define TCO_DAT_IN     TCOBASE + 0x02  /* TCO Data In Register         */
+#define TCO_DAT_OUT    TCOBASE + 0x03  /* TCO Data Out Register        */
+#define TCO1_STS       TCOBASE + 0x04  /* TCO1 Status Register         */
+#define TCO2_STS       TCOBASE + 0x06  /* TCO2 Status Register         */
 #define TCO1_CNT       TCOBASE + 0x08  /* TCO1 Control Register        */
 #define TCO2_CNT       TCOBASE + 0x0a  /* TCO2 Control Register        */
 #define TCOv2_TMR      TCOBASE + 0x12  /* TCOv2 Timer Initial Value    */
@@ -338,7 +338,6 @@ static int iTCO_wdt_unset_NO_REBOOT_bit(void)
 static int iTCO_wdt_start(void)
 {
        unsigned int val;
-       unsigned long val32;
 
        spin_lock(&iTCO_wdt_private.io_lock);
 
@@ -351,11 +350,6 @@ static int iTCO_wdt_start(void)
                return -EIO;
        }
 
-       /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
-       val32 = inl(SMI_EN);
-       val32 &= 0xffffdfff;    /* Turn off SMI clearing watchdog */
-       outl(val32, SMI_EN);
-
        /* Force the timer to its reload value by writing to the TCO_RLD
           register */
        if (iTCO_wdt_private.iTCO_version == 2)
@@ -378,7 +372,6 @@ static int iTCO_wdt_start(void)
 static int iTCO_wdt_stop(void)
 {
        unsigned int val;
-       unsigned long val32;
 
        spin_lock(&iTCO_wdt_private.io_lock);
 
@@ -390,11 +383,6 @@ static int iTCO_wdt_stop(void)
        outw(val, TCO1_CNT);
        val = inw(TCO1_CNT);
 
-       /* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */
-       val32 = inl(SMI_EN);
-       val32 |= 0x00002000;
-       outl(val32, SMI_EN);
-
        /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
        iTCO_wdt_set_NO_REBOOT_bit();
 
@@ -649,6 +637,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
        int ret;
        u32 base_address;
        unsigned long RCBA;
+       unsigned long val32;
 
        /*
         *      Find the ACPI/PM base I/O address which is the base
@@ -695,6 +684,10 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
                ret = -EIO;
                goto out;
        }
+       /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
+       val32 = inl(SMI_EN);
+       val32 &= 0xffffdfff;    /* Turn off SMI clearing watchdog */
+       outl(val32, SMI_EN);
 
        /* The TCO I/O registers reside in a 32-byte range pointed to
           by the TCOBASE value */
index 9b91617b9582d320b67ce6c1984663d48659e03d..56892a142ee273eef1112ea212792556ecfc806b 100644 (file)
@@ -45,6 +45,13 @@ static int xen_suspend(void *data)
                       err);
                return err;
        }
+       err = sysdev_suspend(PMSG_SUSPEND);
+       if (err) {
+               printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
+                       err);
+               device_power_up(PMSG_RESUME);
+               return err;
+       }
 
        xen_mm_pin_all();
        gnttab_suspend();
@@ -61,6 +68,7 @@ static int xen_suspend(void *data)
        gnttab_resume();
        xen_mm_unpin_all();
 
+       sysdev_resume();
        device_power_up(PMSG_RESUME);
 
        if (!*cancelled) {
index 062299acbccddc2d8f808d6cb85722cdd9ef6d09..72ab251cdb9cd0c527b8c18c58f9ca6bca1ed621 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -302,9 +302,10 @@ void bio_init(struct bio *bio)
 struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
 {
        struct bio *bio = NULL;
+       void *p;
 
        if (bs) {
-               void *p = mempool_alloc(bs->bio_pool, gfp_mask);
+               p = mempool_alloc(bs->bio_pool, gfp_mask);
 
                if (p)
                        bio = p + bs->front_pad;
@@ -329,7 +330,7 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
                        }
                        if (unlikely(!bvl)) {
                                if (bs)
-                                       mempool_free(bio, bs->bio_pool);
+                                       mempool_free(p, bs->bio_pool);
                                else
                                        kfree(bio);
                                bio = NULL;
index 35443cc4b9a976607f41866d68c202855c1bf16b..42491d728e9950f9c1f6f1cc4741e2997690f05f 100644 (file)
@@ -38,19 +38,12 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
 static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                   struct btrfs_path *path, int level, int slot);
 
-inline void btrfs_init_path(struct btrfs_path *p)
-{
-       memset(p, 0, sizeof(*p));
-}
-
 struct btrfs_path *btrfs_alloc_path(void)
 {
        struct btrfs_path *path;
-       path = kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS);
-       if (path) {
-               btrfs_init_path(path);
+       path = kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS);
+       if (path)
                path->reada = 1;
-       }
        return path;
 }
 
@@ -69,14 +62,38 @@ noinline void btrfs_set_path_blocking(struct btrfs_path *p)
 
 /*
  * reset all the locked nodes in the patch to spinning locks.
+ *
+ * held is used to keep lockdep happy, when lockdep is enabled
+ * we set held to a blocking lock before we go around and
+ * retake all the spinlocks in the path.  You can safely use NULL
+ * for held
  */
-noinline void btrfs_clear_path_blocking(struct btrfs_path *p)
+noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
+                                       struct extent_buffer *held)
 {
        int i;
-       for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+       /* lockdep really cares that we take all of these spinlocks
+        * in the right order.  If any of the locks in the path are not
+        * currently blocking, it is going to complain.  So, make really
+        * really sure by forcing the path to blocking before we clear
+        * the path blocking.
+        */
+       if (held)
+               btrfs_set_lock_blocking(held);
+       btrfs_set_path_blocking(p);
+#endif
+
+       for (i = BTRFS_MAX_LEVEL - 1; i >= 0; i--) {
                if (p->nodes[i] && p->locks[i])
                        btrfs_clear_lock_blocking(p->nodes[i]);
        }
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+       if (held)
+               btrfs_clear_lock_blocking(held);
+#endif
 }
 
 /* this also releases the path */
@@ -286,7 +303,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
                                                  trans->transid, level, &ins);
                BUG_ON(ret);
                cow = btrfs_init_new_buffer(trans, root, prealloc_dest,
-                                           buf->len);
+                                           buf->len, level);
        } else {
                cow = btrfs_alloc_free_block(trans, root, buf->len,
                                             parent_start,
@@ -917,9 +934,9 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
 
                /* promote the child to a root */
                child = read_node_slot(root, mid, 0);
+               BUG_ON(!child);
                btrfs_tree_lock(child);
                btrfs_set_lock_blocking(child);
-               BUG_ON(!child);
                ret = btrfs_cow_block(trans, root, child, mid, 0, &child, 0);
                BUG_ON(ret);
 
@@ -1566,7 +1583,7 @@ cow_done:
                if (!p->skip_locking)
                        p->locks[level] = 1;
 
-               btrfs_clear_path_blocking(p);
+               btrfs_clear_path_blocking(p, NULL);
 
                /*
                 * we have a lock on b and as long as we aren't changing
@@ -1605,7 +1622,7 @@ cow_done:
 
                                btrfs_set_path_blocking(p);
                                sret = split_node(trans, root, p, level);
-                               btrfs_clear_path_blocking(p);
+                               btrfs_clear_path_blocking(p, NULL);
 
                                BUG_ON(sret > 0);
                                if (sret) {
@@ -1625,7 +1642,7 @@ cow_done:
 
                                btrfs_set_path_blocking(p);
                                sret = balance_level(trans, root, p, level);
-                               btrfs_clear_path_blocking(p);
+                               btrfs_clear_path_blocking(p, NULL);
 
                                if (sret) {
                                        ret = sret;
@@ -1688,13 +1705,13 @@ cow_done:
                        if (!p->skip_locking) {
                                int lret;
 
-                               btrfs_clear_path_blocking(p);
+                               btrfs_clear_path_blocking(p, NULL);
                                lret = btrfs_try_spin_lock(b);
 
                                if (!lret) {
                                        btrfs_set_path_blocking(p);
                                        btrfs_tree_lock(b);
-                                       btrfs_clear_path_blocking(p);
+                                       btrfs_clear_path_blocking(p, b);
                                }
                        }
                } else {
@@ -1706,7 +1723,7 @@ cow_done:
                                btrfs_set_path_blocking(p);
                                sret = split_leaf(trans, root, key,
                                                      p, ins_len, ret == 0);
-                               btrfs_clear_path_blocking(p);
+                               btrfs_clear_path_blocking(p, NULL);
 
                                BUG_ON(sret > 0);
                                if (sret) {
@@ -3926,7 +3943,6 @@ find_next_key:
                                btrfs_release_path(root, path);
                                goto again;
                        } else {
-                               btrfs_clear_path_blocking(path);
                                goto out;
                        }
                }
@@ -3946,7 +3962,7 @@ find_next_key:
                path->locks[level - 1] = 1;
                path->nodes[level - 1] = cur;
                unlock_up(path, level, 1);
-               btrfs_clear_path_blocking(path);
+               btrfs_clear_path_blocking(path, NULL);
        }
 out:
        if (ret == 0)
index 531db112c8bd5e003bde909c4adfb8c74a8b4e64..766b31ae3186e46f54d5d9fbe6fed621651c6520 100644 (file)
@@ -43,11 +43,7 @@ struct btrfs_ordered_sum;
 
 #define BTRFS_ACL_NOT_CACHED    ((void *)-1)
 
-#ifdef CONFIG_LOCKDEP
-# define BTRFS_MAX_LEVEL 7
-#else
-# define BTRFS_MAX_LEVEL 8
-#endif
+#define BTRFS_MAX_LEVEL 8
 
 /* holds pointers to all of the tree roots */
 #define BTRFS_ROOT_TREE_OBJECTID 1ULL
@@ -1715,7 +1711,8 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
                                             u64 empty_size);
 struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
                                            struct btrfs_root *root,
-                                           u64 bytenr, u32 blocksize);
+                                           u64 bytenr, u32 blocksize,
+                                           int level);
 int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
                       struct btrfs_root *root,
                       u64 num_bytes, u64 parent, u64 min_bytes,
@@ -1834,9 +1831,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
 struct btrfs_path *btrfs_alloc_path(void);
 void btrfs_free_path(struct btrfs_path *p);
-void btrfs_init_path(struct btrfs_path *p);
 void btrfs_set_path_blocking(struct btrfs_path *p);
-void btrfs_clear_path_blocking(struct btrfs_path *p);
 void btrfs_unlock_up_safe(struct btrfs_path *p, int level);
 
 int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
index 5aebddd711934817e6f2993375bc1031e3330e63..adda739a0215345b99476435ad35f703174b1d26 100644 (file)
@@ -75,6 +75,40 @@ struct async_submit_bio {
        struct btrfs_work work;
 };
 
+/* These are used to set the lockdep class on the extent buffer locks.
+ * The class is set by the readpage_end_io_hook after the buffer has
+ * passed csum validation but before the pages are unlocked.
+ *
+ * The lockdep class is also set by btrfs_init_new_buffer on freshly
+ * allocated blocks.
+ *
+ * The class is based on the level in the tree block, which allows lockdep
+ * to know that lower nodes nest inside the locks of higher nodes.
+ *
+ * We also add a check to make sure the highest level of the tree is
+ * the same as our lockdep setup here.  If BTRFS_MAX_LEVEL changes, this
+ * code needs update as well.
+ */
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# if BTRFS_MAX_LEVEL != 8
+#  error
+# endif
+static struct lock_class_key btrfs_eb_class[BTRFS_MAX_LEVEL + 1];
+static const char *btrfs_eb_name[BTRFS_MAX_LEVEL + 1] = {
+       /* leaf */
+       "btrfs-extent-00",
+       "btrfs-extent-01",
+       "btrfs-extent-02",
+       "btrfs-extent-03",
+       "btrfs-extent-04",
+       "btrfs-extent-05",
+       "btrfs-extent-06",
+       "btrfs-extent-07",
+       /* highest possible level */
+       "btrfs-extent-08",
+};
+#endif
+
 /*
  * extents on the btree inode are pretty simple, there's one extent
  * that covers the entire device
@@ -347,6 +381,15 @@ static int check_tree_block_fsid(struct btrfs_root *root,
        return ret;
 }
 
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level)
+{
+       lockdep_set_class_and_name(&eb->lock,
+                          &btrfs_eb_class[level],
+                          btrfs_eb_name[level]);
+}
+#endif
+
 static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
                               struct extent_state *state)
 {
@@ -392,6 +435,8 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
        }
        found_level = btrfs_header_level(eb);
 
+       btrfs_set_buffer_lockdep_class(eb, found_level);
+
        ret = csum_tree_block(root, eb, 1);
        if (ret)
                ret = -EIO;
@@ -1777,7 +1822,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        ret = find_and_setup_root(tree_root, fs_info,
                                  BTRFS_DEV_TREE_OBJECTID, dev_root);
        dev_root->track_dirty = 1;
-
        if (ret)
                goto fail_extent_root;
 
index 494a56eb298614d6f443b37ff375e94f06f44b92..95029db227be5767d17eeab2a11cb36b63709849 100644 (file)
@@ -101,4 +101,14 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
 int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
                       struct btrfs_root *root);
 int btree_lock_page_hook(struct page *page);
+
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level);
+#else
+static inline void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb,
+                                                int level)
+{
+}
+#endif
 #endif
index 7527523c2d2d851ce1200424dce799814ac5a1fa..0a5d796c9f7ee3086bd3c8bccdfc63b59d674e0f 100644 (file)
@@ -1323,8 +1323,25 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
 int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
                         struct btrfs_root *root)
 {
-       finish_current_insert(trans, root->fs_info->extent_root, 1);
-       del_pending_extents(trans, root->fs_info->extent_root, 1);
+       u64 start;
+       u64 end;
+       int ret;
+
+       while(1) {
+               finish_current_insert(trans, root->fs_info->extent_root, 1);
+               del_pending_extents(trans, root->fs_info->extent_root, 1);
+
+               /* is there more work to do? */
+               ret = find_first_extent_bit(&root->fs_info->pending_del,
+                                           0, &start, &end, EXTENT_WRITEBACK);
+               if (!ret)
+                       continue;
+               ret = find_first_extent_bit(&root->fs_info->extent_ins,
+                                           0, &start, &end, EXTENT_WRITEBACK);
+               if (!ret)
+                       continue;
+               break;
+       }
        return 0;
 }
 
@@ -2211,13 +2228,12 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
        u64 end;
        u64 priv;
        u64 search = 0;
-       u64 skipped = 0;
        struct btrfs_fs_info *info = extent_root->fs_info;
        struct btrfs_path *path;
        struct pending_extent_op *extent_op, *tmp;
        struct list_head insert_list, update_list;
        int ret;
-       int num_inserts = 0, max_inserts;
+       int num_inserts = 0, max_inserts, restart = 0;
 
        path = btrfs_alloc_path();
        INIT_LIST_HEAD(&insert_list);
@@ -2233,19 +2249,19 @@ again:
                ret = find_first_extent_bit(&info->extent_ins, search, &start,
                                            &end, EXTENT_WRITEBACK);
                if (ret) {
-                       if (skipped && all && !num_inserts &&
+                       if (restart && !num_inserts &&
                            list_empty(&update_list)) {
-                               skipped = 0;
+                               restart = 0;
                                search = 0;
                                continue;
                        }
-                       mutex_unlock(&info->extent_ins_mutex);
                        break;
                }
 
                ret = try_lock_extent(&info->extent_ins, start, end, GFP_NOFS);
                if (!ret) {
-                       skipped = 1;
+                       if (all)
+                               restart = 1;
                        search = end + 1;
                        if (need_resched()) {
                                mutex_unlock(&info->extent_ins_mutex);
@@ -2264,7 +2280,7 @@ again:
                        list_add_tail(&extent_op->list, &insert_list);
                        search = end + 1;
                        if (num_inserts == max_inserts) {
-                               mutex_unlock(&info->extent_ins_mutex);
+                               restart = 1;
                                break;
                        }
                } else if (extent_op->type == PENDING_BACKREF_UPDATE) {
@@ -2280,7 +2296,6 @@ again:
         * somebody marked this thing for deletion then just unlock it and be
         * done, the free_extents will handle it
         */
-       mutex_lock(&info->extent_ins_mutex);
        list_for_each_entry_safe(extent_op, tmp, &update_list, list) {
                clear_extent_bits(&info->extent_ins, extent_op->bytenr,
                                  extent_op->bytenr + extent_op->num_bytes - 1,
@@ -2302,6 +2317,10 @@ again:
        if (!list_empty(&update_list)) {
                ret = update_backrefs(trans, extent_root, path, &update_list);
                BUG_ON(ret);
+
+               /* we may have COW'ed new blocks, so lets start over */
+               if (all)
+                       restart = 1;
        }
 
        /*
@@ -2309,9 +2328,9 @@ again:
         * need to make sure everything is cleaned then reset everything and
         * go back to the beginning
         */
-       if (!num_inserts && all && skipped) {
+       if (!num_inserts && restart) {
                search = 0;
-               skipped = 0;
+               restart = 0;
                INIT_LIST_HEAD(&update_list);
                INIT_LIST_HEAD(&insert_list);
                goto again;
@@ -2368,27 +2387,19 @@ again:
        BUG_ON(ret);
 
        /*
-        * if we broke out of the loop in order to insert stuff because we hit
-        * the maximum number of inserts at a time we can handle, then loop
-        * back and pick up where we left off
+        * if restart is set for whatever reason we need to go back and start
+        * searching through the pending list again.
+        *
+        * We just inserted some extents, which could have resulted in new
+        * blocks being allocated, which would result in new blocks needing
+        * updates, so if all is set we _must_ restart to get the updated
+        * blocks.
         */
-       if (num_inserts == max_inserts) {
-               INIT_LIST_HEAD(&insert_list);
-               INIT_LIST_HEAD(&update_list);
-               num_inserts = 0;
-               goto again;
-       }
-
-       /*
-        * again, if we need to make absolutely sure there are no more pending
-        * extent operations left and we know that we skipped some, go back to
-        * the beginning and do it all again
-        */
-       if (all && skipped) {
+       if (restart || all) {
                INIT_LIST_HEAD(&insert_list);
                INIT_LIST_HEAD(&update_list);
                search = 0;
-               skipped = 0;
+               restart = 0;
                num_inserts = 0;
                goto again;
        }
@@ -2709,6 +2720,8 @@ again:
                goto again;
        }
 
+       if (!err)
+               finish_current_insert(trans, extent_root, 0);
        return err;
 }
 
@@ -2859,7 +2872,8 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
 
        if (data & BTRFS_BLOCK_GROUP_METADATA) {
                last_ptr = &root->fs_info->last_alloc;
-               empty_cluster = 64 * 1024;
+               if (!btrfs_test_opt(root, SSD))
+                       empty_cluster = 64 * 1024;
        }
 
        if ((data & BTRFS_BLOCK_GROUP_DATA) && btrfs_test_opt(root, SSD))
@@ -3402,7 +3416,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
 
 struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
                                            struct btrfs_root *root,
-                                           u64 bytenr, u32 blocksize)
+                                           u64 bytenr, u32 blocksize,
+                                           int level)
 {
        struct extent_buffer *buf;
 
@@ -3410,6 +3425,7 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
        if (!buf)
                return ERR_PTR(-ENOMEM);
        btrfs_set_header_generation(buf, trans->transid);
+       btrfs_set_buffer_lockdep_class(buf, level);
        btrfs_tree_lock(buf);
        clean_tree_block(trans, root, buf);
 
@@ -3453,7 +3469,8 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
                return ERR_PTR(ret);
        }
 
-       buf = btrfs_init_new_buffer(trans, root, ins.objectid, blocksize);
+       buf = btrfs_init_new_buffer(trans, root, ins.objectid,
+                                   blocksize, level);
        return buf;
 }
 
@@ -5641,7 +5658,9 @@ static noinline int relocate_one_extent(struct btrfs_root *extent_root,
                        prev_block = block_start;
                }
 
+               mutex_lock(&extent_root->fs_info->trans_mutex);
                btrfs_record_root_in_trans(found_root);
+               mutex_unlock(&extent_root->fs_info->trans_mutex);
                if (ref_path->owner_objectid >= BTRFS_FIRST_FREE_OBJECTID) {
                        /*
                         * try to update data extent references while
index 37d43b516b79bdb7cb64dd153a06a805be59dd94..ebe6b29e60698156250708766c70bb74b903bfb6 100644 (file)
@@ -415,8 +415,6 @@ static int split_state(struct extent_io_tree *tree, struct extent_state *orig,
 
        node = tree_insert(&tree->state, prealloc->end, &prealloc->rb_node);
        if (node) {
-               struct extent_state *found;
-               found = rb_entry(node, struct extent_state, rb_node);
                free_extent_state(prealloc);
                return -EEXIST;
        }
index 3e8023efaff7581568f8d9a4f131a01c37f76d3b..872f104576e580699985fec78c19a1421b1aa46d 100644 (file)
@@ -1222,7 +1222,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
        /*
         * ok we haven't committed the transaction yet, lets do a commit
         */
-       if (file->private_data)
+       if (file && file->private_data)
                btrfs_ioctl_trans_end(file);
 
        trans = btrfs_start_transaction(root, 1);
@@ -1231,7 +1231,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
                goto out;
        }
 
-       ret = btrfs_log_dentry_safe(trans, root, file->f_dentry);
+       ret = btrfs_log_dentry_safe(trans, root, dentry);
        if (ret < 0)
                goto out;
 
@@ -1245,7 +1245,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
         * file again, but that will end up using the synchronization
         * inside btrfs_sync_log to keep things safe.
         */
-       mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+       mutex_unlock(&dentry->d_inode->i_mutex);
 
        if (ret > 0) {
                ret = btrfs_commit_transaction(trans, root);
@@ -1253,7 +1253,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
                btrfs_sync_log(trans, root);
                ret = btrfs_end_transaction(trans, root);
        }
-       mutex_lock(&file->f_dentry->d_inode->i_mutex);
+       mutex_lock(&dentry->d_inode->i_mutex);
 out:
        return ret > 0 ? EIO : ret;
 }
index 2aa79873eb46a46baa00503d6682de1861db7c45..cc7334d833c9d27f4a139b6b96232e959f1458a5 100644 (file)
@@ -84,7 +84,6 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
        search_key.type = 0;
        search_key.offset = 0;
 
-       btrfs_init_path(path);
        start_found = 0;
        ret = btrfs_search_slot(trans, root, &search_key, path, 0, 0);
        if (ret < 0)
index 8f0706210a478cc8866b3dd280b2860e75089757..3cee77ae03c81e0fe8340ceedb268ca96c2a1521 100644 (file)
@@ -2531,8 +2531,6 @@ noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
        key.offset = (u64)-1;
        key.type = (u8)-1;
 
-       btrfs_init_path(path);
-
 search_again:
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
        if (ret < 0)
@@ -4263,7 +4261,7 @@ static int btrfs_releasepage(struct page *page, gfp_t gfp_flags)
 {
        if (PageWriteback(page) || PageDirty(page))
                return 0;
-       return __btrfs_releasepage(page, gfp_flags);
+       return __btrfs_releasepage(page, gfp_flags & GFP_NOFS);
 }
 
 static void btrfs_invalidatepage(struct page *page, unsigned long offset)
index 9ebe9385129be7a32c3394a9d20ab13ff119fcb9..85506c4a3af7406c248b575149863ccdb8eb88f0 100644 (file)
 #include "extent_io.h"
 #include "locking.h"
 
-/*
- * btrfs_header_level() isn't free, so don't call it when lockdep isn't
- * on
- */
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-static inline void spin_nested(struct extent_buffer *eb)
-{
-       spin_lock_nested(&eb->lock, BTRFS_MAX_LEVEL - btrfs_header_level(eb));
-}
-#else
 static inline void spin_nested(struct extent_buffer *eb)
 {
        spin_lock(&eb->lock);
 }
-#endif
 
 /*
  * Setting a lock to blocking will drop the spinlock and set the
index f3fd7e2cbc383aaefd42be70a02f80c759b6979b..19a4daf03ccb6d7d8730d4d8c9602a24dc0c370b 100644 (file)
@@ -379,7 +379,6 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
        btrfs_start_delalloc_inodes(root);
        btrfs_wait_ordered_extents(root, 0);
 
-       btrfs_clean_old_snapshots(root);
        trans = btrfs_start_transaction(root, 1);
        ret = btrfs_commit_transaction(trans, root);
        sb->s_dirt = 0;
@@ -511,6 +510,10 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
        struct btrfs_root *root = btrfs_sb(sb);
        int ret;
 
+       ret = btrfs_parse_options(root, data);
+       if (ret)
+               return -EINVAL;
+
        if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
                return 0;
 
index 919172de5c9aa9ce64630f593f74a7942e8292fd..4112d53d4f4dad195636c6ffa93deaded831af6e 100644 (file)
@@ -688,7 +688,9 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
                num_bytes -= btrfs_root_used(&dirty->root->root_item);
                bytes_used = btrfs_root_used(&root->root_item);
                if (num_bytes) {
+                       mutex_lock(&root->fs_info->trans_mutex);
                        btrfs_record_root_in_trans(root);
+                       mutex_unlock(&root->fs_info->trans_mutex);
                        btrfs_set_root_used(&root->root_item,
                                            bytes_used - num_bytes);
                }
index 20794290256b4f977f14a5ea95810781edc7bbad..9c462fbd60fac14ad17f192afb08c37794295d36 100644 (file)
@@ -2832,7 +2832,9 @@ again:
                BUG_ON(!wc.replay_dest);
 
                wc.replay_dest->log_root = log;
+               mutex_lock(&fs_info->trans_mutex);
                btrfs_record_root_in_trans(wc.replay_dest);
+               mutex_unlock(&fs_info->trans_mutex);
                ret = walk_log_tree(trans, log, &wc);
                BUG_ON(ret);
 
index bcd14ebccae16e751e67a73cf79c2dfbbf0db465..1316139bf9e8209750ba671edd042df4976307ab 100644 (file)
@@ -2894,10 +2894,6 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
                free_extent_map(em);
        }
 
-       map = kzalloc(sizeof(*map), GFP_NOFS);
-       if (!map)
-               return -ENOMEM;
-
        em = alloc_extent_map(GFP_NOFS);
        if (!em)
                return -ENOMEM;
@@ -3106,6 +3102,8 @@ int btrfs_read_sys_array(struct btrfs_root *root)
        if (!sb)
                return -ENOMEM;
        btrfs_set_buffer_uptodate(sb);
+       btrfs_set_buffer_lockdep_class(sb, 0);
+
        write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE);
        array_size = btrfs_super_sys_array_size(super_copy);
 
index 665d446b25bc034241ef54c3c6b1d239c0ccf0f9..9f697419ed8e34ec041c92d8f6794c8b4b06ab33 100644 (file)
@@ -777,6 +777,7 @@ static int __set_page_dirty(struct page *page,
                        __inc_zone_page_state(page, NR_FILE_DIRTY);
                        __inc_bdi_stat(mapping->backing_dev_info,
                                        BDI_RECLAIMABLE);
+                       task_dirty_inc(current);
                        task_io_account_write(PAGE_CACHE_SIZE);
                }
                radix_tree_tag_set(&mapping->page_tree,
@@ -3108,7 +3109,7 @@ int sync_dirty_buffer(struct buffer_head *bh)
        if (test_clear_buffer_dirty(bh)) {
                get_bh(bh);
                bh->b_end_io = end_buffer_write_sync;
-               ret = submit_bh(WRITE_SYNC, bh);
+               ret = submit_bh(WRITE, bh);
                wait_on_buffer(bh);
                if (buffer_eopnotsupp(bh)) {
                        clear_buffer_eopnotsupp(bh);
index 73ac7ebd1dfcc253db5a40d9aa91379764dbebdb..851388fafc7302dbae9d5b5f7f33da5101eed4cd 100644 (file)
@@ -1,3 +1,13 @@
+Version 1.57
+------------
+Improve support for multiple security contexts to the same server. We
+used to use the same "vcnumber" for all connections which could cause
+the server to treat subsequent connections, especially those that
+are authenticated as guest, as reconnections, invalidating the earlier
+user's smb session.  This fix allows cifs to mount multiple times to the
+same server with different userids without risking invalidating earlier
+established security contexts.
+
 Version 1.56
 ------------
 Add "forcemandatorylock" mount option to allow user to use mandatory
@@ -7,7 +17,10 @@ specified and user does not have access to query information about the
 top of the share.  Fix problem in 2.6.28 resolving DFS paths to
 Samba servers (worked to Windows).  Fix rmdir so that pending search
 (readdir) requests do not get invalid results which include the now
-removed directory.
+removed directory.  Fix oops in cifs_dfs_ref.c when prefixpath is not reachable
+when using DFS.  Add better file create support to servers which support
+the CIFS POSIX protocol extensions (this adds support for new flags
+on create, and improves semantics for write of locked ranges).
 
 Version 1.55
 ------------
index 7ac481841f8726a272068a730235d0cd322bc799..2b1d28a9ee287b6b998c034c403c240b101c682e 100644 (file)
@@ -100,5 +100,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
 extern const struct export_operations cifs_export_ops;
 #endif /* EXPERIMENTAL */
 
-#define CIFS_VERSION   "1.56"
+#define CIFS_VERSION   "1.57"
 #endif                         /* _CIFSFS_H */
index 94c1ca0ec9539ef1ee08ff9983e291b2c21e7449..e004f6db5fc87904e21d6ebc4eb0cb56ccc15d29 100644 (file)
@@ -164,9 +164,12 @@ struct TCP_Server_Info {
        /* multiplexed reads or writes */
        unsigned int maxBuf;    /* maxBuf specifies the maximum */
        /* message size the server can send or receive for non-raw SMBs */
-       unsigned int maxRw;     /* maxRw specifies the maximum */
+       unsigned int max_rw;    /* maxRw specifies the maximum */
        /* message size the server can send or receive for */
        /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
+       unsigned int max_vcs;   /* maximum number of smb sessions, at least
+                                  those that can be specified uniquely with
+                                  vcnumbers */
        char sessid[4];         /* unique token id for this session */
        /* (returned on Negotiate */
        int capabilities; /* allow selective disabling of caps by smb sess */
@@ -210,6 +213,7 @@ struct cifsSesInfo {
        unsigned overrideSecFlg;  /* if non-zero override global sec flags */
        __u16 ipc_tid;          /* special tid for connection to IPC share */
        __u16 flags;
+       __u16 vcnum;
        char *serverOS;         /* name of operating system underlying server */
        char *serverNOS;        /* name of network operating system of server */
        char *serverDomain;     /* security realm of server */
index 382ba62988094b58ec396ae7872a104ff7a66104..083dfc57c7a3e53adf54f32e9af4c56a8c2eeb9f 100644 (file)
@@ -42,6 +42,7 @@ extern void _FreeXid(unsigned int);
 #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));
 #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
 extern char *build_path_from_dentry(struct dentry *);
+extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
 /* extern void renew_parental_timestamps(struct dentry *direntry);*/
 extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
@@ -91,6 +92,9 @@ extern u64 cifs_UnixTimeToNT(struct timespec);
 extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
 extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
 
+extern void posix_fill_in_inode(struct inode *tmp_inode,
+                               FILE_UNIX_BASIC_INFO *pData, int isNewInode);
+extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum);
 extern int cifs_get_inode_info(struct inode **pinode,
                        const unsigned char *search_path,
                        FILE_ALL_INFO *pfile_info,
index 552642a507c4be6744e32a0738c07d27bd89a635..939e2f76b9596203ab68276a59aad6fd8c36981e 100644 (file)
@@ -528,14 +528,15 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
                server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
                                (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
+               server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
                GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
                /* even though we do not use raw we might as well set this
                accurately, in case we ever find a need for it */
                if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
-                       server->maxRw = 0xFF00;
+                       server->max_rw = 0xFF00;
                        server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
                } else {
-                       server->maxRw = 0;/* we do not need to use raw anyway */
+                       server->max_rw = 0;/* do not need to use raw anyway */
                        server->capabilities = CAP_MPX_MODE;
                }
                tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
@@ -638,7 +639,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
        /* probably no need to store and check maxvcs */
        server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
                        (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
-       server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
+       server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
        cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
        GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
        server->capabilities = le32_to_cpu(pSMBr->Capabilities);
index 2209be94305132f375b1082193bdcf7280c312d8..da0f4ffa06132f725570a79f7e0b5fb0b65d1eb6 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/string.h>
 #include <linux/list.h>
 #include <linux/wait.h>
-#include <linux/ipv6.h>
 #include <linux/pagemap.h>
 #include <linux/ctype.h>
 #include <linux/utsname.h>
@@ -35,6 +34,7 @@
 #include <linux/freezer.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
+#include <net/ipv6.h>
 #include "cifspdu.h"
 #include "cifsglob.h"
 #include "cifsproto.h"
@@ -1379,8 +1379,8 @@ cifs_find_tcp_session(struct sockaddr_storage *addr)
                     server->addr.sockAddr.sin_addr.s_addr))
                        continue;
                else if (addr->ss_family == AF_INET6 &&
-                        memcmp(&server->addr.sockAddr6.sin6_addr,
-                               &addr6->sin6_addr, sizeof(addr6->sin6_addr)))
+                        !ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr,
+                                         &addr6->sin6_addr))
                        continue;
 
                ++server->srv_count;
@@ -2180,6 +2180,33 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
                           "mount option supported"));
 }
 
+static int
+is_path_accessible(int xid, struct cifsTconInfo *tcon,
+                  struct cifs_sb_info *cifs_sb, const char *full_path)
+{
+       int rc;
+       __u64 inode_num;
+       FILE_ALL_INFO *pfile_info;
+
+       rc = CIFSGetSrvInodeNumber(xid, tcon, full_path, &inode_num,
+                                  cifs_sb->local_nls,
+                                  cifs_sb->mnt_cifs_flags &
+                                               CIFS_MOUNT_MAP_SPECIAL_CHR);
+       if (rc != -EOPNOTSUPP)
+               return rc;
+
+       pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+       if (pfile_info == NULL)
+               return -ENOMEM;
+
+       rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
+                             0 /* not legacy */, cifs_sb->local_nls,
+                             cifs_sb->mnt_cifs_flags &
+                               CIFS_MOUNT_MAP_SPECIAL_CHR);
+       kfree(pfile_info);
+       return rc;
+}
+
 int
 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
           char *mount_data, const char *devname)
@@ -2190,6 +2217,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
        struct cifsSesInfo *pSesInfo = NULL;
        struct cifsTconInfo *tcon = NULL;
        struct TCP_Server_Info *srvTcp = NULL;
+       char   *full_path;
 
        xid = GetXid();
 
@@ -2426,6 +2454,23 @@ mount_fail_check:
                cifs_sb->rsize = min(cifs_sb->rsize,
                               (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
 
+       if (!rc && cifs_sb->prepathlen) {
+               /* build_path_to_root works only when we have a valid tcon */
+               full_path = cifs_build_path_to_root(cifs_sb);
+               if (full_path == NULL) {
+                       rc = -ENOMEM;
+                       goto mount_fail_check;
+               }
+               rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
+               if (rc) {
+                       cERROR(1, ("Path %s in not accessible: %d",
+                                               full_path, rc));
+                       kfree(full_path);
+                       goto mount_fail_check;
+               }
+               kfree(full_path);
+       }
+
        /* volume_info->password is freed above when existing session found
        (in which case it is not needed anymore) but when new sesion is created
        the password ptr is put in the new session structure (in which case the
index 964aad03c5ad82d914ad504a8453f09f149d5c67..89fb728326523f6f3367a7343e057350341f423a 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   vfs operations that deal with dentries
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2008
+ *   Copyright (C) International Business Machines  Corp., 2002,2009
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -129,6 +129,78 @@ cifs_bp_rename_retry:
        return full_path;
 }
 
+static int cifs_posix_open(char *full_path, struct inode **pinode,
+                   struct super_block *sb, int mode, int oflags,
+                   int *poplock, __u16 *pnetfid, int xid)
+{
+       int rc;
+       __u32 oplock;
+       FILE_UNIX_BASIC_INFO *presp_data;
+       __u32 posix_flags = 0;
+       struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+
+       cFYI(1, ("posix open %s", full_path));
+
+       presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
+       if (presp_data == NULL)
+               return -ENOMEM;
+
+/* So far cifs posix extensions can only map the following flags.
+   There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but
+   so far we do not seem to need them, and we can treat them as local only */
+       if ((oflags & (FMODE_READ | FMODE_WRITE)) ==
+               (FMODE_READ | FMODE_WRITE))
+               posix_flags = SMB_O_RDWR;
+       else if (oflags & FMODE_READ)
+               posix_flags = SMB_O_RDONLY;
+       else if (oflags & FMODE_WRITE)
+               posix_flags = SMB_O_WRONLY;
+       if (oflags & O_CREAT)
+               posix_flags |= SMB_O_CREAT;
+       if (oflags & O_EXCL)
+               posix_flags |= SMB_O_EXCL;
+       if (oflags & O_TRUNC)
+               posix_flags |= SMB_O_TRUNC;
+       if (oflags & O_APPEND)
+               posix_flags |= SMB_O_APPEND;
+       if (oflags & O_SYNC)
+               posix_flags |= SMB_O_SYNC;
+       if (oflags & O_DIRECTORY)
+               posix_flags |= SMB_O_DIRECTORY;
+       if (oflags & O_NOFOLLOW)
+               posix_flags |= SMB_O_NOFOLLOW;
+       if (oflags & O_DIRECT)
+               posix_flags |= SMB_O_DIRECT;
+
+
+       rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
+                       pnetfid, presp_data, &oplock, full_path,
+                       cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
+       if (rc)
+               goto posix_open_ret;
+
+       if (presp_data->Type == cpu_to_le32(-1))
+               goto posix_open_ret; /* open ok, caller does qpathinfo */
+
+       /* get new inode and set it up */
+       if (!pinode)
+               goto posix_open_ret; /* caller does not need info */
+
+       *pinode = cifs_new_inode(sb, &presp_data->UniqueId);
+
+       /* We do not need to close the file if new_inode fails since
+          the caller will retry qpathinfo as long as inode is null */
+       if (*pinode == NULL)
+               goto posix_open_ret;
+
+       posix_fill_in_inode(*pinode, presp_data, 1);
+
+posix_open_ret:
+       kfree(presp_data);
+       return rc;
+}
+
 static void setup_cifs_dentry(struct cifsTconInfo *tcon,
                              struct dentry *direntry,
                              struct inode *newinode)
@@ -150,7 +222,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
        int xid;
        int create_options = CREATE_NOT_DIR;
        int oplock = 0;
-       /* BB below access is too much for the mknod to request */
+       int oflags;
+       /*
+        * BB below access is probably too much for mknod to request
+        *    but we have to do query and setpathinfo so requesting
+        *    less could fail (unless we want to request getatr and setatr
+        *    permissions (only).  At least for POSIX we do not have to
+        *    request so much.
+        */
        int desiredAccess = GENERIC_READ | GENERIC_WRITE;
        __u16 fileHandle;
        struct cifs_sb_info *cifs_sb;
@@ -174,13 +253,43 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
        }
 
        mode &= ~current->fs->umask;
+       if (oplockEnabled)
+               oplock = REQ_OPLOCK;
 
-       if (nd && (nd->flags & LOOKUP_OPEN)) {
-               int oflags = nd->intent.open.flags;
+       if (nd && (nd->flags & LOOKUP_OPEN))
+               oflags = nd->intent.open.flags;
+       else
+               oflags = FMODE_READ;
+
+       if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
+           (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+                       le64_to_cpu(tcon->fsUnixInfo.Capability))) {
+               rc = cifs_posix_open(full_path, &newinode, inode->i_sb,
+                                    mode, oflags, &oplock, &fileHandle, xid);
+               /* EIO could indicate that (posix open) operation is not
+                  supported, despite what server claimed in capability
+                  negotation.  EREMOTE indicates DFS junction, which is not
+                  handled in posix open */
+
+               if ((rc == 0) && (newinode == NULL))
+                       goto cifs_create_get_file_info; /* query inode info */
+               else if (rc == 0) /* success, no need to query */
+                       goto cifs_create_set_dentry;
+               else if ((rc != -EIO) && (rc != -EREMOTE) &&
+                        (rc != -EOPNOTSUPP)) /* path not found or net err */
+                       goto cifs_create_out;
+               /* else fallthrough to retry, using older open call, this is
+                  case where server does not support this SMB level, and
+                  falsely claims capability (also get here for DFS case
+                  which should be rare for path not covered on files) */
+       }
 
+       if (nd && (nd->flags & LOOKUP_OPEN)) {
+               /* if the file is going to stay open, then we
+                  need to set the desired access properly */
                desiredAccess = 0;
                if (oflags & FMODE_READ)
-                       desiredAccess |= GENERIC_READ;
+                       desiredAccess |= GENERIC_READ; /* is this too little? */
                if (oflags & FMODE_WRITE) {
                        desiredAccess |= GENERIC_WRITE;
                        if (!(oflags & FMODE_READ))
@@ -199,8 +308,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 
        /* BB add processing to set equivalent of mode - e.g. via CreateX with
           ACLs */
-       if (oplockEnabled)
-               oplock = REQ_OPLOCK;
 
        buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
        if (buf == NULL) {
@@ -233,116 +340,112 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
        }
        if (rc) {
                cFYI(1, ("cifs_create returned 0x%x", rc));
-       } else {
-               /* If Open reported that we actually created a file
-               then we now have to set the mode if possible */
-               if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
-                       struct cifs_unix_set_info_args args = {
+               goto cifs_create_out;
+       }
+
+       /* If Open reported that we actually created a file
+          then we now have to set the mode if possible */
+       if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
+               struct cifs_unix_set_info_args args = {
                                .mode   = mode,
                                .ctime  = NO_CHANGE_64,
                                .atime  = NO_CHANGE_64,
                                .mtime  = NO_CHANGE_64,
                                .device = 0,
-                       };
+               };
 
-                       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
-                               args.uid = (__u64) current_fsuid();
-                               if (inode->i_mode & S_ISGID)
-                                       args.gid = (__u64) inode->i_gid;
-                               else
-                                       args.gid = (__u64) current_fsgid();
-                       } else {
-                               args.uid = NO_CHANGE_64;
-                               args.gid = NO_CHANGE_64;
-                       }
-                       CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
-                               cifs_sb->local_nls,
-                               cifs_sb->mnt_cifs_flags &
-                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
+               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+                       args.uid = (__u64) current_fsuid();
+                       if (inode->i_mode & S_ISGID)
+                               args.gid = (__u64) inode->i_gid;
+                       else
+                               args.gid = (__u64) current_fsgid();
                } else {
-                       /* BB implement mode setting via Windows security
-                          descriptors e.g. */
-                       /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
-
-                       /* Could set r/o dos attribute if mode & 0222 == 0 */
+                       args.uid = NO_CHANGE_64;
+                       args.gid = NO_CHANGE_64;
                }
+               CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
+                       cifs_sb->local_nls,
+                       cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+       } else {
+               /* BB implement mode setting via Windows security
+                  descriptors e.g. */
+               /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
 
-               /* server might mask mode so we have to query for it */
-               if (tcon->unix_ext)
-                       rc = cifs_get_inode_info_unix(&newinode, full_path,
-                                                inode->i_sb, xid);
-               else {
-                       rc = cifs_get_inode_info(&newinode, full_path,
-                                                buf, inode->i_sb, xid,
-                                                &fileHandle);
-                       if (newinode) {
-                               if (cifs_sb->mnt_cifs_flags &
-                                   CIFS_MOUNT_DYNPERM)
-                                       newinode->i_mode = mode;
-                               if ((oplock & CIFS_CREATE_ACTION) &&
-                                   (cifs_sb->mnt_cifs_flags &
-                                    CIFS_MOUNT_SET_UID)) {
-                                       newinode->i_uid = current_fsuid();
-                                       if (inode->i_mode & S_ISGID)
-                                               newinode->i_gid =
-                                                       inode->i_gid;
-                                       else
-                                               newinode->i_gid =
-                                                       current_fsgid();
-                               }
+               /* Could set r/o dos attribute if mode & 0222 == 0 */
+       }
+
+cifs_create_get_file_info:
+       /* server might mask mode so we have to query for it */
+       if (tcon->unix_ext)
+               rc = cifs_get_inode_info_unix(&newinode, full_path,
+                                             inode->i_sb, xid);
+       else {
+               rc = cifs_get_inode_info(&newinode, full_path, buf,
+                                        inode->i_sb, xid, &fileHandle);
+               if (newinode) {
+                       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
+                               newinode->i_mode = mode;
+                       if ((oplock & CIFS_CREATE_ACTION) &&
+                           (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
+                               newinode->i_uid = current_fsuid();
+                               if (inode->i_mode & S_ISGID)
+                                       newinode->i_gid = inode->i_gid;
+                               else
+                                       newinode->i_gid = current_fsgid();
                        }
                }
+       }
 
-               if (rc != 0) {
-                       cFYI(1, ("Create worked, get_inode_info failed rc = %d",
-                                rc));
-               } else
-                       setup_cifs_dentry(tcon, direntry, newinode);
-
-               if ((nd == NULL /* nfsd case - nfs srv does not set nd */) ||
-                       (!(nd->flags & LOOKUP_OPEN))) {
-                       /* mknod case - do not leave file open */
-                       CIFSSMBClose(xid, tcon, fileHandle);
-               } else if (newinode) {
-                       struct cifsFileInfo *pCifsFile =
-                          kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
-
-                       if (pCifsFile == NULL)
-                               goto cifs_create_out;
-                       pCifsFile->netfid = fileHandle;
-                       pCifsFile->pid = current->tgid;
-                       pCifsFile->pInode = newinode;
-                       pCifsFile->invalidHandle = false;
-                       pCifsFile->closePend     = false;
-                       init_MUTEX(&pCifsFile->fh_sem);
-                       mutex_init(&pCifsFile->lock_mutex);
-                       INIT_LIST_HEAD(&pCifsFile->llist);
-                       atomic_set(&pCifsFile->wrtPending, 0);
-
-                       /* set the following in open now
+cifs_create_set_dentry:
+       if (rc == 0)
+               setup_cifs_dentry(tcon, direntry, newinode);
+       else
+               cFYI(1, ("Create worked, get_inode_info failed rc = %d", rc));
+
+       /* nfsd case - nfs srv does not set nd */
+       if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
+               /* mknod case - do not leave file open */
+               CIFSSMBClose(xid, tcon, fileHandle);
+       } else if (newinode) {
+               struct cifsFileInfo *pCifsFile =
+                       kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
+
+               if (pCifsFile == NULL)
+                       goto cifs_create_out;
+               pCifsFile->netfid = fileHandle;
+               pCifsFile->pid = current->tgid;
+               pCifsFile->pInode = newinode;
+               pCifsFile->invalidHandle = false;
+               pCifsFile->closePend     = false;
+               init_MUTEX(&pCifsFile->fh_sem);
+               mutex_init(&pCifsFile->lock_mutex);
+               INIT_LIST_HEAD(&pCifsFile->llist);
+               atomic_set(&pCifsFile->wrtPending, 0);
+
+               /* set the following in open now
                                pCifsFile->pfile = file; */
-                       write_lock(&GlobalSMBSeslock);
-                       list_add(&pCifsFile->tlist, &tcon->openFileList);
-                       pCifsInode = CIFS_I(newinode);
-                       if (pCifsInode) {
-                               /* if readable file instance put first in list*/
-                               if (write_only) {
-                                       list_add_tail(&pCifsFile->flist,
-                                               &pCifsInode->openFileList);
-                               } else {
-                                       list_add(&pCifsFile->flist,
-                                               &pCifsInode->openFileList);
-                               }
-                               if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
-                                       pCifsInode->clientCanCacheAll = true;
-                                       pCifsInode->clientCanCacheRead = true;
-                                       cFYI(1, ("Exclusive Oplock inode %p",
-                                               newinode));
-                               } else if ((oplock & 0xF) == OPLOCK_READ)
-                                       pCifsInode->clientCanCacheRead = true;
+               write_lock(&GlobalSMBSeslock);
+               list_add(&pCifsFile->tlist, &tcon->openFileList);
+               pCifsInode = CIFS_I(newinode);
+               if (pCifsInode) {
+                       /* if readable file instance put first in list*/
+                       if (write_only) {
+                               list_add_tail(&pCifsFile->flist,
+                                             &pCifsInode->openFileList);
+                       } else {
+                               list_add(&pCifsFile->flist,
+                                        &pCifsInode->openFileList);
                        }
-                       write_unlock(&GlobalSMBSeslock);
+                       if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+                               pCifsInode->clientCanCacheAll = true;
+                               pCifsInode->clientCanCacheRead = true;
+                               cFYI(1, ("Exclusive Oplock inode %p",
+                                       newinode));
+                       } else if ((oplock & 0xF) == OPLOCK_READ)
+                               pCifsInode->clientCanCacheRead = true;
                }
+               write_unlock(&GlobalSMBSeslock);
        }
 cifs_create_out:
        kfree(buf);
index bcf7b518466413023097ba69b7a5cb8cb4c4a449..4690a360c85587ed85a76db68ab4c5afed4f998e 100644 (file)
@@ -199,6 +199,49 @@ static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat,
        pfnd_dat->Gid = cpu_to_le64(pinode->i_gid);
 }
 
+/**
+ * cifs_new inode - create new inode, initialize, and hash it
+ * @sb - pointer to superblock
+ * @inum - if valid pointer and serverino is enabled, replace i_ino with val
+ *
+ * Create a new inode, initialize it for CIFS and hash it. Returns the new
+ * inode or NULL if one couldn't be allocated.
+ *
+ * If the share isn't mounted with "serverino" or inum is a NULL pointer then
+ * we'll just use the inode number assigned by new_inode(). Note that this can
+ * mean i_ino collisions since the i_ino assigned by new_inode is not
+ * guaranteed to be unique.
+ */
+struct inode *
+cifs_new_inode(struct super_block *sb, __u64 *inum)
+{
+       struct inode *inode;
+
+       inode = new_inode(sb);
+       if (inode == NULL)
+               return NULL;
+
+       /*
+        * BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we
+        *     stop passing inum as ptr. Are there sanity checks we can use to
+        *     ensure that the server is really filling in that field? Also,
+        *     if serverino is disabled, perhaps we should be using iunique()?
+        */
+       if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
+               inode->i_ino = (unsigned long) *inum;
+
+       /*
+        * must set this here instead of cifs_alloc_inode since VFS will
+        * clobber i_flags
+        */
+       if (sb->s_flags & MS_NOATIME)
+               inode->i_flags |= S_NOATIME | S_NOCMTIME;
+
+       insert_inode_hash(inode);
+
+       return inode;
+}
+
 int cifs_get_inode_info_unix(struct inode **pinode,
        const unsigned char *full_path, struct super_block *sb, int xid)
 {
@@ -233,22 +276,11 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 
        /* get new inode */
        if (*pinode == NULL) {
-               *pinode = new_inode(sb);
+               *pinode = cifs_new_inode(sb, &find_data.UniqueId);
                if (*pinode == NULL) {
                        rc = -ENOMEM;
                        goto cgiiu_exit;
                }
-               /* Is an i_ino of zero legal? */
-               /* note ino incremented to unique num in new_inode */
-               /* Are there sanity checks we can use to ensure that
-                  the server is really filling in that field? */
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
-                       (*pinode)->i_ino = (unsigned long)find_data.UniqueId;
-
-               if (sb->s_flags & MS_NOATIME)
-                       (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
-
-               insert_inode_hash(*pinode);
        }
 
        inode = *pinode;
@@ -465,11 +497,9 @@ int cifs_get_inode_info(struct inode **pinode,
 
        /* get new inode */
        if (*pinode == NULL) {
-               *pinode = new_inode(sb);
-               if (*pinode == NULL) {
-                       rc = -ENOMEM;
-                       goto cgii_exit;
-               }
+               __u64 inode_num;
+               __u64 *pinum = &inode_num;
+
                /* Is an i_ino of zero legal? Can we use that to check
                   if the server supports returning inode numbers?  Are
                   there other sanity checks we can use to ensure that
@@ -486,22 +516,26 @@ int cifs_get_inode_info(struct inode **pinode,
 
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
                        int rc1 = 0;
-                       __u64 inode_num;
 
                        rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
-                                       full_path, &inode_num,
+                                       full_path, pinum,
                                        cifs_sb->local_nls,
                                        cifs_sb->mnt_cifs_flags &
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
                        if (rc1) {
                                cFYI(1, ("GetSrvInodeNum rc %d", rc1));
+                               pinum = NULL;
                                /* BB EOPNOSUPP disable SERVER_INUM? */
-                       } else /* do we need cast or hash to ino? */
-                               (*pinode)->i_ino = inode_num;
-               } /* else ino incremented to unique num in new_inode*/
-               if (sb->s_flags & MS_NOATIME)
-                       (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
-               insert_inode_hash(*pinode);
+                       }
+               } else {
+                       pinum = NULL;
+               }
+
+               *pinode = cifs_new_inode(sb, pinum);
+               if (*pinode == NULL) {
+                       rc = -ENOMEM;
+                       goto cgii_exit;
+               }
        }
        inode = *pinode;
        cifsInfo = CIFS_I(inode);
@@ -621,7 +655,7 @@ static const struct inode_operations cifs_ipc_inode_ops = {
        .lookup = cifs_lookup,
 };
 
-static char *build_path_to_root(struct cifs_sb_info *cifs_sb)
+char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
 {
        int pplen = cifs_sb->prepathlen;
        int dfsplen;
@@ -678,7 +712,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
                return inode;
 
        cifs_sb = CIFS_SB(inode->i_sb);
-       full_path = build_path_to_root(cifs_sb);
+       full_path = cifs_build_path_to_root(cifs_sb);
        if (full_path == NULL)
                return ERR_PTR(-ENOMEM);
 
@@ -1017,7 +1051,7 @@ out_reval:
        return rc;
 }
 
-static void posix_fill_in_inode(struct inode *tmp_inode,
+void posix_fill_in_inode(struct inode *tmp_inode,
        FILE_UNIX_BASIC_INFO *pData, int isNewInode)
 {
        struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
@@ -1114,24 +1148,14 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
                        else
                                direntry->d_op = &cifs_dentry_ops;
 
-                       newinode = new_inode(inode->i_sb);
+                       newinode = cifs_new_inode(inode->i_sb,
+                                                 &pInfo->UniqueId);
                        if (newinode == NULL) {
                                kfree(pInfo);
                                goto mkdir_get_info;
                        }
 
-                       /* Is an i_ino of zero legal? */
-                       /* Are there sanity checks we can use to ensure that
-                          the server is really filling in that field? */
-                       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
-                               newinode->i_ino =
-                                       (unsigned long)pInfo->UniqueId;
-                       } /* note ino incremented to unique num in new_inode */
-                       if (inode->i_sb->s_flags & MS_NOATIME)
-                               newinode->i_flags |= S_NOATIME | S_NOCMTIME;
                        newinode->i_nlink = 2;
-
-                       insert_inode_hash(newinode);
                        d_instantiate(direntry, newinode);
 
                        /* we already checked in POSIXCreate whether
index 9f51f9bf0292f4a67aee9ca82aae2f6d3b6cc5d0..c2c01ff4c32c1b21965ebf814ee83a93318c7a31 100644 (file)
@@ -56,35 +56,34 @@ static inline void dump_cifs_file_struct(struct file *file, char *label)
 }
 #endif /* DEBUG2 */
 
-/* Returns one if new inode created (which therefore needs to be hashed) */
+/* Returns 1 if new inode created, 2 if both dentry and inode were */
 /* Might check in the future if inode number changed so we can rehash inode */
-static int construct_dentry(struct qstr *qstring, struct file *file,
-       struct inode **ptmp_inode, struct dentry **pnew_dentry)
+static int
+construct_dentry(struct qstr *qstring, struct file *file,
+                struct inode **ptmp_inode, struct dentry **pnew_dentry,
+                __u64 *inum)
 {
-       struct dentry *tmp_dentry;
-       struct cifs_sb_info *cifs_sb;
-       struct cifsTconInfo *pTcon;
+       struct dentry *tmp_dentry = NULL;
+       struct super_block *sb = file->f_path.dentry->d_sb;
        int rc = 0;
 
        cFYI(1, ("For %s", qstring->name));
-       cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-       pTcon = cifs_sb->tcon;
 
        qstring->hash = full_name_hash(qstring->name, qstring->len);
        tmp_dentry = d_lookup(file->f_path.dentry, qstring);
        if (tmp_dentry) {
+               /* BB: overwrite old name? i.e. tmp_dentry->d_name and
+                * tmp_dentry->d_name.len??
+                */
                cFYI(0, ("existing dentry with inode 0x%p",
                         tmp_dentry->d_inode));
                *ptmp_inode = tmp_dentry->d_inode;
-/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
                if (*ptmp_inode == NULL) {
-                       *ptmp_inode = new_inode(file->f_path.dentry->d_sb);
+                       *ptmp_inode = cifs_new_inode(sb, inum);
                        if (*ptmp_inode == NULL)
                                return rc;
                        rc = 1;
                }
-               if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
-                       (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
        } else {
                tmp_dentry = d_alloc(file->f_path.dentry, qstring);
                if (tmp_dentry == NULL) {
@@ -93,15 +92,14 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
                        return rc;
                }
 
-               *ptmp_inode = new_inode(file->f_path.dentry->d_sb);
-               if (pTcon->nocase)
+               if (CIFS_SB(sb)->tcon->nocase)
                        tmp_dentry->d_op = &cifs_ci_dentry_ops;
                else
                        tmp_dentry->d_op = &cifs_dentry_ops;
+
+               *ptmp_inode = cifs_new_inode(sb, inum);
                if (*ptmp_inode == NULL)
                        return rc;
-               if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
-                       (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
                rc = 2;
        }
 
@@ -822,7 +820,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
 /* inode num, inode type and filename returned */
 static int cifs_get_name_from_search_buf(struct qstr *pqst,
        char *current_entry, __u16 level, unsigned int unicode,
-       struct cifs_sb_info *cifs_sb, int max_len, ino_t *pinum)
+       struct cifs_sb_info *cifs_sb, int max_len, __u64 *pinum)
 {
        int rc = 0;
        unsigned int len = 0;
@@ -842,9 +840,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
                        len = strnlen(filename, PATH_MAX);
                }
 
-               /* BB fixme - hash low and high 32 bits if not 64 bit arch BB */
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
-                       *pinum = pFindData->UniqueId;
+               *pinum = pFindData->UniqueId;
        } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
                FILE_DIRECTORY_INFO *pFindData =
                        (FILE_DIRECTORY_INFO *)current_entry;
@@ -907,7 +903,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
        struct qstr qstring;
        struct cifsFileInfo *pCifsF;
        unsigned int obj_type;
-       ino_t  inum;
+       __u64  inum;
        struct cifs_sb_info *cifs_sb;
        struct inode *tmp_inode;
        struct dentry *tmp_dentry;
@@ -940,20 +936,18 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
        if (rc)
                return rc;
 
-       rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry);
+       /* only these two infolevels return valid inode numbers */
+       if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX ||
+           pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO)
+               rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry,
+                                       &inum);
+       else
+               rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry,
+                                       NULL);
+
        if ((tmp_inode == NULL) || (tmp_dentry == NULL))
                return -ENOMEM;
 
-       if (rc) {
-               /* inode created, we need to hash it with right inode number */
-               if (inum != 0) {
-                       /* BB fixme - hash the 2 32 quantities bits together if
-                        *  necessary BB */
-                       tmp_inode->i_ino = inum;
-               }
-               insert_inode_hash(tmp_inode);
-       }
-
        /* we pass in rc below, indicating whether it is a new inode,
           so we can figure out whether to invalidate the inode cached
           data if the file has changed */
index 5f22de7b79a900fe9bbd79e68f9823da136d132e..5c68b4282be917bc48ba04e77b0af2120952d50a 100644 (file)
 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
                         unsigned char *p24);
 
+/* Checks if this is the first smb session to be reconnected after
+   the socket has been reestablished (so we know whether to use vc 0).
+   Called while holding the cifs_tcp_ses_lock, so do not block */
+static bool is_first_ses_reconnect(struct cifsSesInfo *ses)
+{
+       struct list_head *tmp;
+       struct cifsSesInfo *tmp_ses;
+
+       list_for_each(tmp, &ses->server->smb_ses_list) {
+               tmp_ses = list_entry(tmp, struct cifsSesInfo,
+                                    smb_ses_list);
+               if (tmp_ses->need_reconnect == false)
+                       return false;
+       }
+       /* could not find a session that was already connected,
+          this must be the first one we are reconnecting */
+       return true;
+}
+
+/*
+ *     vc number 0 is treated specially by some servers, and should be the
+ *      first one we request.  After that we can use vcnumbers up to maxvcs,
+ *     one for each smb session (some Windows versions set maxvcs incorrectly
+ *     so maxvc=1 can be ignored).  If we have too many vcs, we can reuse
+ *     any vc but zero (some servers reset the connection on vcnum zero)
+ *
+ */
+static __le16 get_next_vcnum(struct cifsSesInfo *ses)
+{
+       __u16 vcnum = 0;
+       struct list_head *tmp;
+       struct cifsSesInfo *tmp_ses;
+       __u16 max_vcs = ses->server->max_vcs;
+       __u16 i;
+       int free_vc_found = 0;
+
+       /* Quoting the MS-SMB specification: "Windows-based SMB servers set this
+       field to one but do not enforce this limit, which allows an SMB client
+       to establish more virtual circuits than allowed by this value ... but
+       other server implementations can enforce this limit." */
+       if (max_vcs < 2)
+               max_vcs = 0xFFFF;
+
+       write_lock(&cifs_tcp_ses_lock);
+       if ((ses->need_reconnect) && is_first_ses_reconnect(ses))
+                       goto get_vc_num_exit;  /* vcnum will be zero */
+       for (i = ses->server->srv_count - 1; i < max_vcs; i++) {
+               if (i == 0) /* this is the only connection, use vc 0 */
+                       break;
+
+               free_vc_found = 1;
+
+               list_for_each(tmp, &ses->server->smb_ses_list) {
+                       tmp_ses = list_entry(tmp, struct cifsSesInfo,
+                                            smb_ses_list);
+                       if (tmp_ses->vcnum == i) {
+                               free_vc_found = 0;
+                               break; /* found duplicate, try next vcnum */
+                       }
+               }
+               if (free_vc_found)
+                       break; /* we found a vcnumber that will work - use it */
+       }
+
+       if (i == 0)
+               vcnum = 0; /* for most common case, ie if one smb session, use
+                             vc zero.  Also for case when no free vcnum, zero
+                             is safest to send (some clients only send zero) */
+       else if (free_vc_found == 0)
+               vcnum = 1;  /* we can not reuse vc=0 safely, since some servers
+                               reset all uids on that, but 1 is ok. */
+       else
+               vcnum = i;
+       ses->vcnum = vcnum;
+get_vc_num_exit:
+       write_unlock(&cifs_tcp_ses_lock);
+
+       return le16_to_cpu(vcnum);
+}
+
 static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
 {
        __u32 capabilities = 0;
 
        /* init fields common to all four types of SessSetup */
-       /* note that header is initialized to zero in header_assemble */
+       /* Note that offsets for first seven fields in req struct are same  */
+       /*      in CIFS Specs so does not matter which of 3 forms of struct */
+       /*      that we use in next few lines                               */
+       /* Note that header is initialized to zero in header_assemble */
        pSMB->req.AndXCommand = 0xFF;
        pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
        pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+       pSMB->req.VcNumber = get_next_vcnum(ses);
 
        /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
 
@@ -71,7 +155,6 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
        if (ses->capabilities & CAP_UNIX)
                capabilities |= CAP_UNIX;
 
-       /* BB check whether to init vcnum BB */
        return capabilities;
 }
 
@@ -228,7 +311,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
 
        kfree(ses->serverOS);
        /* UTF-8 string will not grow more than four times as big as UCS-16 */
-       ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
+       ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
        if (ses->serverOS != NULL)
                cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
        data += 2 * (len + 1);
@@ -241,7 +324,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
                return rc;
 
        kfree(ses->serverNOS);
-       ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
+       ses->serverNOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
        if (ses->serverNOS != NULL) {
                cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
                                   nls_cp);
index 9c6d815dd1918b42640b4819393ac056b21da17f..39bd4d38e889878632b786b17a3951fa0aa2284a 100644 (file)
@@ -1938,6 +1938,8 @@ ULONG_IOCTL(SET_BITMAP_FILE)
 /* Big K */
 COMPATIBLE_IOCTL(PIO_FONT)
 COMPATIBLE_IOCTL(GIO_FONT)
+COMPATIBLE_IOCTL(PIO_CMAP)
+COMPATIBLE_IOCTL(GIO_CMAP)
 ULONG_IOCTL(KDSIGACCEPT)
 COMPATIBLE_IOCTL(KDGETKEYCODE)
 COMPATIBLE_IOCTL(KDSETKEYCODE)
index aafc9eba1c25c8aace126bafc56e70d058695621..b0c87dce66a32e56b40b5248a0019c380818ae5b 100644 (file)
@@ -868,7 +868,7 @@ static inline unsigned ext4_rec_len_from_disk(__le16 dlen)
 {
        unsigned len = le16_to_cpu(dlen);
 
-       if (len == EXT4_MAX_REC_LEN)
+       if (len == EXT4_MAX_REC_LEN || len == 0)
                return 1 << 16;
        return len;
 }
index 03ba20be132997140e4dcae313dadb865149427e..cbd2ca99d11351d757f36194173ee716d89bdc4f 100644 (file)
 static inline int ext4_begin_ordered_truncate(struct inode *inode,
                                              loff_t new_size)
 {
-       return jbd2_journal_begin_ordered_truncate(&EXT4_I(inode)->jinode,
-                                                  new_size);
+       return jbd2_journal_begin_ordered_truncate(
+                                       EXT4_SB(inode->i_sb)->s_journal,
+                                       &EXT4_I(inode)->jinode,
+                                       new_size);
 }
 
 static void ext4_invalidatepage(struct page *page, unsigned long offset);
@@ -2437,6 +2439,7 @@ static int ext4_da_writepages(struct address_space *mapping,
        int no_nrwrite_index_update;
        int pages_written = 0;
        long pages_skipped;
+       int range_cyclic, cycled = 1, io_done = 0;
        int needed_blocks, ret = 0, nr_to_writebump = 0;
        struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
 
@@ -2488,9 +2491,15 @@ static int ext4_da_writepages(struct address_space *mapping,
        if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
                range_whole = 1;
 
-       if (wbc->range_cyclic)
+       range_cyclic = wbc->range_cyclic;
+       if (wbc->range_cyclic) {
                index = mapping->writeback_index;
-       else
+               if (index)
+                       cycled = 0;
+               wbc->range_start = index << PAGE_CACHE_SHIFT;
+               wbc->range_end  = LLONG_MAX;
+               wbc->range_cyclic = 0;
+       } else
                index = wbc->range_start >> PAGE_CACHE_SHIFT;
 
        mpd.wbc = wbc;
@@ -2504,6 +2513,7 @@ static int ext4_da_writepages(struct address_space *mapping,
        wbc->no_nrwrite_index_update = 1;
        pages_skipped = wbc->pages_skipped;
 
+retry:
        while (!ret && wbc->nr_to_write > 0) {
 
                /*
@@ -2546,6 +2556,7 @@ static int ext4_da_writepages(struct address_space *mapping,
                        pages_written += mpd.pages_written;
                        wbc->pages_skipped = pages_skipped;
                        ret = 0;
+                       io_done = 1;
                } else if (wbc->nr_to_write)
                        /*
                         * There is no more writeout needed
@@ -2554,6 +2565,13 @@ static int ext4_da_writepages(struct address_space *mapping,
                         */
                        break;
        }
+       if (!io_done && !cycled) {
+               cycled = 1;
+               index = 0;
+               wbc->range_start = index << PAGE_CACHE_SHIFT;
+               wbc->range_end  = mapping->writeback_index - 1;
+               goto retry;
+       }
        if (pages_skipped != wbc->pages_skipped)
                printk(KERN_EMERG "This should not happen leaving %s "
                                "with nr_to_write = %ld ret = %d\n",
@@ -2561,6 +2579,7 @@ static int ext4_da_writepages(struct address_space *mapping,
 
        /* Update index */
        index += pages_written;
+       wbc->range_cyclic = range_cyclic;
        if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
                /*
                 * set the writeback_index so that range_cyclic
index deba54f6cbed2af2d504224d2910829951e98d1c..4415beeb0b620c46611348c7092fa75c42cf2337 100644 (file)
@@ -3693,6 +3693,8 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
        pa->pa_free = pa->pa_len;
        atomic_set(&pa->pa_count, 1);
        spin_lock_init(&pa->pa_lock);
+       INIT_LIST_HEAD(&pa->pa_inode_list);
+       INIT_LIST_HEAD(&pa->pa_group_list);
        pa->pa_deleted = 0;
        pa->pa_linear = 0;
 
@@ -3755,6 +3757,7 @@ ext4_mb_new_group_pa(struct ext4_allocation_context *ac)
        atomic_set(&pa->pa_count, 1);
        spin_lock_init(&pa->pa_lock);
        INIT_LIST_HEAD(&pa->pa_inode_list);
+       INIT_LIST_HEAD(&pa->pa_group_list);
        pa->pa_deleted = 0;
        pa->pa_linear = 1;
 
@@ -4476,23 +4479,26 @@ static int ext4_mb_release_context(struct ext4_allocation_context *ac)
                        pa->pa_free -= ac->ac_b_ex.fe_len;
                        pa->pa_len -= ac->ac_b_ex.fe_len;
                        spin_unlock(&pa->pa_lock);
-                       /*
-                        * We want to add the pa to the right bucket.
-                        * Remove it from the list and while adding
-                        * make sure the list to which we are adding
-                        * doesn't grow big.
-                        */
-                       if (likely(pa->pa_free)) {
-                               spin_lock(pa->pa_obj_lock);
-                               list_del_rcu(&pa->pa_inode_list);
-                               spin_unlock(pa->pa_obj_lock);
-                               ext4_mb_add_n_trim(ac);
-                       }
                }
-               ext4_mb_put_pa(ac, ac->ac_sb, pa);
        }
        if (ac->alloc_semp)
                up_read(ac->alloc_semp);
+       if (pa) {
+               /*
+                * We want to add the pa to the right bucket.
+                * Remove it from the list and while adding
+                * make sure the list to which we are adding
+                * doesn't grow big.  We need to release
+                * alloc_semp before calling ext4_mb_add_n_trim()
+                */
+               if (pa->pa_linear && likely(pa->pa_free)) {
+                       spin_lock(pa->pa_obj_lock);
+                       list_del_rcu(&pa->pa_inode_list);
+                       spin_unlock(pa->pa_obj_lock);
+                       ext4_mb_add_n_trim(ac);
+               }
+               ext4_mb_put_pa(ac, ac->ac_sb, pa);
+       }
        if (ac->ac_bitmap_page)
                page_cache_release(ac->ac_bitmap_page);
        if (ac->ac_buddy_page)
index 734abca25e359bc4b21f3e8b67674cc9c320698a..fe64d9f79852f1dc22764cfa00f261c84858107b 100644 (file)
@@ -481,7 +481,7 @@ int ext4_ext_migrate(struct inode *inode)
                                        + 1);
        if (IS_ERR(handle)) {
                retval = PTR_ERR(handle);
-               goto err_out;
+               return retval;
        }
        tmp_inode = ext4_new_inode(handle,
                                inode->i_sb->s_root->d_inode,
@@ -489,8 +489,7 @@ int ext4_ext_migrate(struct inode *inode)
        if (IS_ERR(tmp_inode)) {
                retval = -ENOMEM;
                ext4_journal_stop(handle);
-               tmp_inode = NULL;
-               goto err_out;
+               return retval;
        }
        i_size_write(tmp_inode, i_size_read(inode));
        /*
@@ -618,8 +617,7 @@ err_out:
 
        ext4_journal_stop(handle);
 
-       if (tmp_inode)
-               iput(tmp_inode);
+       iput(tmp_inode);
 
        return retval;
 }
index e5f06a5f045ee72ed825748d760485ec8739240f..a5732c58f676747554a7b1c6da9a0c5e6787eb7b 100644 (file)
@@ -3046,14 +3046,17 @@ static void ext4_write_super(struct super_block *sb)
 static int ext4_sync_fs(struct super_block *sb, int wait)
 {
        int ret = 0;
+       tid_t target;
 
        trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
        sb->s_dirt = 0;
        if (EXT4_SB(sb)->s_journal) {
-               if (wait)
-                       ret = ext4_force_commit(sb);
-               else
-                       jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, NULL);
+               if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal,
+                                             &target)) {
+                       if (wait)
+                               jbd2_log_wait_commit(EXT4_SB(sb)->s_journal,
+                                                    target);
+               }
        } else {
                ext4_commit_super(sb, EXT4_SB(sb)->s_es, wait);
        }
index eb343008eded0fd86851417f60717650dda96857..58144102bf253b2244fee8fe44ce1a7c02cfbc79 100644 (file)
@@ -450,7 +450,7 @@ int __jbd2_log_space_left(journal_t *journal)
 }
 
 /*
- * Called under j_state_lock.  Returns true if a transaction was started.
+ * Called under j_state_lock.  Returns true if a transaction commit was started.
  */
 int __jbd2_log_start_commit(journal_t *journal, tid_t target)
 {
@@ -518,7 +518,8 @@ int jbd2_journal_force_commit_nested(journal_t *journal)
 
 /*
  * Start a commit of the current running transaction (if any).  Returns true
- * if a transaction was started, and fills its tid in at *ptid
+ * if a transaction is going to be committed (or is currently already
+ * committing), and fills its tid in at *ptid
  */
 int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid)
 {
@@ -528,15 +529,19 @@ int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid)
        if (journal->j_running_transaction) {
                tid_t tid = journal->j_running_transaction->t_tid;
 
-               ret = __jbd2_log_start_commit(journal, tid);
-               if (ret && ptid)
+               __jbd2_log_start_commit(journal, tid);
+               /* There's a running transaction and we've just made sure
+                * it's commit has been scheduled. */
+               if (ptid)
                        *ptid = tid;
-       } else if (journal->j_committing_transaction && ptid) {
+               ret = 1;
+       } else if (journal->j_committing_transaction) {
                /*
                 * If ext3_write_super() recently started a commit, then we
                 * have to wait for completion of that transaction
                 */
-               *ptid = journal->j_committing_transaction->t_tid;
+               if (ptid)
+                       *ptid = journal->j_committing_transaction->t_tid;
                ret = 1;
        }
        spin_unlock(&journal->j_state_lock);
index 46b4e347ed7d9f3949df7b2b475bda7d7f2b8fef..28ce21d8598e11f16182a973d31d7e8bef83c145 100644 (file)
@@ -2129,26 +2129,46 @@ done:
 }
 
 /*
- * This function must be called when inode is journaled in ordered mode
- * before truncation happens. It starts writeout of truncated part in
- * case it is in the committing transaction so that we stand to ordered
- * mode consistency guarantees.
+ * File truncate and transaction commit interact with each other in a
+ * non-trivial way.  If a transaction writing data block A is
+ * committing, we cannot discard the data by truncate until we have
+ * written them.  Otherwise if we crashed after the transaction with
+ * write has committed but before the transaction with truncate has
+ * committed, we could see stale data in block A.  This function is a
+ * helper to solve this problem.  It starts writeout of the truncated
+ * part in case it is in the committing transaction.
+ *
+ * Filesystem code must call this function when inode is journaled in
+ * ordered mode before truncation happens and after the inode has been
+ * placed on orphan list with the new inode size. The second condition
+ * avoids the race that someone writes new data and we start
+ * committing the transaction after this function has been called but
+ * before a transaction for truncate is started (and furthermore it
+ * allows us to optimize the case where the addition to orphan list
+ * happens in the same transaction as write --- we don't have to write
+ * any data in such case).
  */
-int jbd2_journal_begin_ordered_truncate(struct jbd2_inode *inode,
+int jbd2_journal_begin_ordered_truncate(journal_t *journal,
+                                       struct jbd2_inode *jinode,
                                        loff_t new_size)
 {
-       journal_t *journal;
-       transaction_t *commit_trans;
+       transaction_t *inode_trans, *commit_trans;
        int ret = 0;
 
-       if (!inode->i_transaction && !inode->i_next_transaction)
+       /* This is a quick check to avoid locking if not necessary */
+       if (!jinode->i_transaction)
                goto out;
-       journal = inode->i_transaction->t_journal;
+       /* Locks are here just to force reading of recent values, it is
+        * enough that the transaction was not committing before we started
+        * a transaction adding the inode to orphan list */
        spin_lock(&journal->j_state_lock);
        commit_trans = journal->j_committing_transaction;
        spin_unlock(&journal->j_state_lock);
-       if (inode->i_transaction == commit_trans) {
-               ret = filemap_fdatawrite_range(inode->i_vfs_inode->i_mapping,
+       spin_lock(&journal->j_list_lock);
+       inode_trans = jinode->i_transaction;
+       spin_unlock(&journal->j_list_lock);
+       if (inode_trans == commit_trans) {
+               ret = filemap_fdatawrite_range(jinode->i_vfs_inode->i_mapping,
                        new_size, LLONG_MAX);
                if (ret)
                        jbd2_journal_abort(journal, ret);
index 228d8c4bfd18a1925fd57ac3880e2e47031470d2..06f8e63f6cb1dc929e0ad9c0627320066db57cb1 100644 (file)
@@ -614,9 +614,11 @@ static inline void __mntput(struct vfsmount *mnt)
         */
        for_each_possible_cpu(cpu) {
                struct mnt_writer *cpu_writer = &per_cpu(mnt_writers, cpu);
-               if (cpu_writer->mnt != mnt)
-                       continue;
                spin_lock(&cpu_writer->lock);
+               if (cpu_writer->mnt != mnt) {
+                       spin_unlock(&cpu_writer->lock);
+                       continue;
+               }
                atomic_add(cpu_writer->count, &mnt->__mnt_writers);
                cpu_writer->count = 0;
                /*
index dae3f28f30d4779ee69cc8780d8424818b0fbfa4..331f2e88e284e44e373cbda23ab41a024c01c6b1 100644 (file)
@@ -156,7 +156,7 @@ static int inotify_handle_get_wd(struct inotify_handle *ih,
        int ret;
 
        do {
-               if (unlikely(!idr_pre_get(&ih->idr, GFP_KERNEL)))
+               if (unlikely(!idr_pre_get(&ih->idr, GFP_NOFS)))
                        return -ENOSPC;
                ret = idr_get_new_above(&ih->idr, watch, ih->last_wd+1, &watch->wd);
        } while (ret == -EAGAIN);
index 3c3532e1307c838495b60e52d9eb9eada0ab69fd..172850a9a12a7d78cc115e80500979673f4ae7f5 100644 (file)
@@ -513,8 +513,10 @@ static inline int ocfs2_jbd2_file_inode(handle_t *handle, struct inode *inode)
 static inline int ocfs2_begin_ordered_truncate(struct inode *inode,
                                               loff_t new_size)
 {
-       return jbd2_journal_begin_ordered_truncate(&OCFS2_I(inode)->ip_jinode,
-                                                  new_size);
+       return jbd2_journal_begin_ordered_truncate(
+                               OCFS2_SB(inode->i_sb)->journal->j_journal,
+                               &OCFS2_I(inode)->ip_jinode,
+                               new_size);
 }
 
 #endif /* OCFS2_JOURNAL_H */
index 5267098532bfc8a3a6c25026119a14c144d49f5c..a1a4cfe1921040d6044657e6c235e2f5d55f8292 100644 (file)
@@ -48,8 +48,16 @@ int seq_open(struct file *file, const struct seq_operations *op)
         */
        file->f_version = 0;
 
-       /* SEQ files support lseek, but not pread/pwrite */
-       file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
+       /*
+        * seq_files support lseek() and pread().  They do not implement
+        * write() at all, but we clear FMODE_PWRITE here for historical
+        * reasons.
+        *
+        * If a client of seq_files a) implements file.write() and b) wishes to
+        * support pwrite() then that client will need to implement its own
+        * file.open() which calls seq_open() and then sets FMODE_PWRITE.
+        */
+       file->f_mode &= ~FMODE_PWRITE;
        return 0;
 }
 EXPORT_SYMBOL(seq_open);
@@ -131,6 +139,22 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
        int err = 0;
 
        mutex_lock(&m->lock);
+
+       /* Don't assume *ppos is where we left it */
+       if (unlikely(*ppos != m->read_pos)) {
+               m->read_pos = *ppos;
+               while ((err = traverse(m, *ppos)) == -EAGAIN)
+                       ;
+               if (err) {
+                       /* With prejudice... */
+                       m->read_pos = 0;
+                       m->version = 0;
+                       m->index = 0;
+                       m->count = 0;
+                       goto Done;
+               }
+       }
+
        /*
         * seq_file->op->..m_start/m_stop/m_next may do special actions
         * or optimisations based on the file->f_version, so we want to
@@ -230,8 +254,10 @@ Fill:
 Done:
        if (!copied)
                copied = err;
-       else
+       else {
                *ppos += copied;
+               m->read_pos += copied;
+       }
        file->f_version = m->version;
        mutex_unlock(&m->lock);
        return copied;
@@ -266,16 +292,18 @@ loff_t seq_lseek(struct file *file, loff_t offset, int origin)
                        if (offset < 0)
                                break;
                        retval = offset;
-                       if (offset != file->f_pos) {
+                       if (offset != m->read_pos) {
                                while ((retval=traverse(m, offset)) == -EAGAIN)
                                        ;
                                if (retval) {
                                        /* with extreme prejudice... */
                                        file->f_pos = 0;
+                                       m->read_pos = 0;
                                        m->version = 0;
                                        m->index = 0;
                                        m->count = 0;
                                } else {
+                                       m->read_pos = offset;
                                        retval = file->f_pos = offset;
                                }
                        }
index 61dce001dd572ef74685c42b0a1b83fa7307703b..8349ed6b1412aa13e9f23d17fad91e66c9ec1915 100644 (file)
@@ -82,7 +82,22 @@ static struct super_block *alloc_super(struct file_system_type *type)
                 * lock ordering than usbfs:
                 */
                lockdep_set_class(&s->s_lock, &type->s_lock_key);
-               down_write(&s->s_umount);
+               /*
+                * sget() can have s_umount recursion.
+                *
+                * When it cannot find a suitable sb, it allocates a new
+                * one (this one), and tries again to find a suitable old
+                * one.
+                *
+                * In case that succeeds, it will acquire the s_umount
+                * lock of the old one. Since these are clearly distrinct
+                * locks, and this object isn't exposed yet, there's no
+                * risk of deadlocks.
+                *
+                * Annotate this by putting this lock in a different
+                * subclass.
+                */
+               down_write_nested(&s->s_umount, SINGLE_DEPTH_NESTING);
                s->s_count = S_BIAS;
                atomic_set(&s->s_active, 1);
                mutex_init(&s->s_vfs_rename_mutex);
index 6a123b8ff3f5605735255f7ccaf084af547743dd..b042bd7034b1fc74d6cd6399e24b3a2057689a2f 100644 (file)
@@ -186,10 +186,9 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
        BUILD_BUG_ON(TFD_CLOEXEC != O_CLOEXEC);
        BUILD_BUG_ON(TFD_NONBLOCK != O_NONBLOCK);
 
-       if (flags & ~(TFD_CLOEXEC | TFD_NONBLOCK))
-               return -EINVAL;
-       if (clockid != CLOCK_MONOTONIC &&
-           clockid != CLOCK_REALTIME)
+       if ((flags & ~TFD_CREATE_FLAGS) ||
+           (clockid != CLOCK_MONOTONIC &&
+            clockid != CLOCK_REALTIME))
                return -EINVAL;
 
        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
@@ -201,7 +200,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
        hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);
 
        ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
-                              flags & (O_CLOEXEC | O_NONBLOCK));
+                              flags & TFD_SHARED_FCNTL_FLAGS);
        if (ufd < 0)
                kfree(ctx);
 
@@ -219,7 +218,8 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
        if (copy_from_user(&ktmr, utmr, sizeof(ktmr)))
                return -EFAULT;
 
-       if (!timespec_valid(&ktmr.it_value) ||
+       if ((flags & ~TFD_SETTIME_FLAGS) ||
+           !timespec_valid(&ktmr.it_value) ||
            !timespec_valid(&ktmr.it_interval))
                return -EINVAL;
 
index d71dc44e21edbe7077bda8d35f9b259aac61522d..cb329edc925b915ae5e590edeb4840810f811326 100644 (file)
@@ -165,6 +165,75 @@ test_page_region(
        return (mask && (page_private(page) & mask) == mask);
 }
 
+/*
+ *     Mapping of multi-page buffers into contiguous virtual space
+ */
+
+typedef struct a_list {
+       void            *vm_addr;
+       struct a_list   *next;
+} a_list_t;
+
+static a_list_t                *as_free_head;
+static int             as_list_len;
+static DEFINE_SPINLOCK(as_lock);
+
+/*
+ *     Try to batch vunmaps because they are costly.
+ */
+STATIC void
+free_address(
+       void            *addr)
+{
+       a_list_t        *aentry;
+
+#ifdef CONFIG_XEN
+       /*
+        * Xen needs to be able to make sure it can get an exclusive
+        * RO mapping of pages it wants to turn into a pagetable.  If
+        * a newly allocated page is also still being vmap()ed by xfs,
+        * it will cause pagetable construction to fail.  This is a
+        * quick workaround to always eagerly unmap pages so that Xen
+        * is happy.
+        */
+       vunmap(addr);
+       return;
+#endif
+
+       aentry = kmalloc(sizeof(a_list_t), GFP_NOWAIT);
+       if (likely(aentry)) {
+               spin_lock(&as_lock);
+               aentry->next = as_free_head;
+               aentry->vm_addr = addr;
+               as_free_head = aentry;
+               as_list_len++;
+               spin_unlock(&as_lock);
+       } else {
+               vunmap(addr);
+       }
+}
+
+STATIC void
+purge_addresses(void)
+{
+       a_list_t        *aentry, *old;
+
+       if (as_free_head == NULL)
+               return;
+
+       spin_lock(&as_lock);
+       aentry = as_free_head;
+       as_free_head = NULL;
+       as_list_len = 0;
+       spin_unlock(&as_lock);
+
+       while ((old = aentry) != NULL) {
+               vunmap(aentry->vm_addr);
+               aentry = aentry->next;
+               kfree(old);
+       }
+}
+
 /*
  *     Internal xfs_buf_t object manipulation
  */
@@ -264,7 +333,7 @@ xfs_buf_free(
                uint            i;
 
                if ((bp->b_flags & XBF_MAPPED) && (bp->b_page_count > 1))
-                       vm_unmap_ram(bp->b_addr - bp->b_offset, bp->b_page_count);
+                       free_address(bp->b_addr - bp->b_offset);
 
                for (i = 0; i < bp->b_page_count; i++) {
                        struct page     *page = bp->b_pages[i];
@@ -386,8 +455,10 @@ _xfs_buf_map_pages(
                bp->b_addr = page_address(bp->b_pages[0]) + bp->b_offset;
                bp->b_flags |= XBF_MAPPED;
        } else if (flags & XBF_MAPPED) {
-               bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count,
-                                       -1, PAGE_KERNEL);
+               if (as_list_len > 64)
+                       purge_addresses();
+               bp->b_addr = vmap(bp->b_pages, bp->b_page_count,
+                                       VM_MAP, PAGE_KERNEL);
                if (unlikely(bp->b_addr == NULL))
                        return -ENOMEM;
                bp->b_addr += bp->b_offset;
@@ -1672,6 +1743,8 @@ xfsbufd(
                        count++;
                }
 
+               if (as_list_len > 0)
+                       purge_addresses();
                if (count)
                        blk_run_address_space(target->bt_mapping);
 
index 83c51aba534b727a363d22559eaa153dd90c9dda..e16fdb1f4f4fe11caada4239cbc621f084936552 100644 (file)
@@ -478,7 +478,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 #define __swp_type(x)                  (((x).val >> 2) & 0x1f)
 #define __swp_offset(x)                        ((x).val >> 8)
 #define __swp_entry(type, offset)      ((swp_entry_t) { ((type) << 2) | ((offset) << 8) })
-#define __pte_to_swp_entry(pte)                ((swp_entry_t) { (pte).pte })
+#define __pte_to_swp_entry(_pte)       ((swp_entry_t) { (_pte).pte })
 #define __swp_entry_to_pte(x)          ((pte_t) { (x).val })
 
 static inline int pte_file(pte_t pte)
index 8190b9bcc2d967e366833e04823f6899e9e33aea..e5f4ae989abf15bd0b7ead6428840584cede0f85 100644 (file)
@@ -1321,6 +1321,8 @@ void drm_gem_object_free(struct kref *kref);
 struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
                                            size_t size);
 void drm_gem_object_handle_free(struct kref *kref);
+void drm_gem_vm_open(struct vm_area_struct *vma);
+void drm_gem_vm_close(struct vm_area_struct *vma);
 int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
 
 static inline void
index d54de24bf371f52025d6bad298f01b50b8b5522f..5ded1acfb5430fd969094e9fa817c285aefa9611 100644 (file)
@@ -609,7 +609,7 @@ extern char *drm_get_dvi_i_subconnector_name(int val);
 extern char *drm_get_dvi_i_select_name(int val);
 extern char *drm_get_tv_subconnector_name(int val);
 extern char *drm_get_tv_select_name(int val);
-extern void drm_fb_release(struct file *filp);
+extern void drm_fb_release(struct drm_file *file_priv);
 extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group);
 extern struct edid *drm_get_edid(struct drm_connector *connector,
                                 struct i2c_adapter *adapter);
index 0c6f0e11b41bcfc823d94571c3be853087440e5a..0b0d236c215469120e031af56d5e80a4ca475e5c 100644 (file)
@@ -54,13 +54,13 @@ struct drm_crtc_helper_funcs {
                           struct drm_display_mode *mode,
                           struct drm_display_mode *adjusted_mode);
        /* Actually set the mode */
-       void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
-                        struct drm_display_mode *adjusted_mode, int x, int y,
-                        struct drm_framebuffer *old_fb);
+       int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
+                       struct drm_display_mode *adjusted_mode, int x, int y,
+                       struct drm_framebuffer *old_fb);
 
        /* Move the crtc on the current fb to the given position *optional* */
-       void (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
-                             struct drm_framebuffer *old_fb);
+       int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
+                            struct drm_framebuffer *old_fb);
 };
 
 struct drm_encoder_helper_funcs {
index 2aa283ab062b215ddb37975d8e55193ecd502c5f..1b16108a54174346e2f64be1aca0b6474c1e13e8 100644 (file)
@@ -171,8 +171,6 @@ struct bio {
 #define BIO_RW_FAILFAST_TRANSPORT      8
 #define BIO_RW_FAILFAST_DRIVER         9
 
-#define BIO_RW_SYNC    (BIO_RW_SYNCIO | BIO_RW_UNPLUG)
-
 #define bio_rw_flagged(bio, flag)      ((bio)->bi_rw & (1 << (flag)))
 
 /*
index 25379cba2370f2dd6cb11931d9a6649aaee40a8d..6e915878e88c2a4c8b27bea51e1a6e010fee93e9 100644 (file)
@@ -15,6 +15,7 @@ enum blktrace_cat {
        BLK_TC_WRITE    = 1 << 1,       /* writes */
        BLK_TC_BARRIER  = 1 << 2,       /* barrier */
        BLK_TC_SYNC     = 1 << 3,       /* sync IO */
+       BLK_TC_SYNCIO   = BLK_TC_SYNC,
        BLK_TC_QUEUE    = 1 << 4,       /* queueing/merging */
        BLK_TC_REQUEUE  = 1 << 5,       /* requeueing */
        BLK_TC_ISSUE    = 1 << 6,       /* issue */
index 45e5b1921fbb5ceeb50a33514a423b53d9d46cd0..47f343c7bddaaca551c8fb2114160fb5f362c4e1 100644 (file)
@@ -147,6 +147,8 @@ extern void put_driver(struct device_driver *drv);
 extern struct device_driver *driver_find(const char *name,
                                         struct bus_type *bus);
 extern int driver_probe_done(void);
+extern int wait_for_device_probe(void);
+
 
 /* sysfs interface for exporting driver attributes */
 
index 3e68469c1885e3df7e7078b0c39aab5237cb7f06..f0413845f20ee75481543cb97c570d6dbda142b4 100644 (file)
@@ -121,6 +121,7 @@ struct dma_chan_percpu {
  * @local: per-cpu pointer to a struct dma_chan_percpu
  * @client-count: how many clients are using this channel
  * @table_count: number of appearances in the mem-to-mem allocation table
+ * @private: private data for certain client-channel associations
  */
 struct dma_chan {
        struct dma_device *device;
@@ -134,6 +135,7 @@ struct dma_chan {
        struct dma_chan_percpu *local;
        int client_count;
        int table_count;
+       void *private;
 };
 
 /**
index 6e199c8dfacc4f3c40307076535d41da914afeb8..cca686b39123dca178f26512e5fcbf0db114a41b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * include/linux/firmware-map.h:
  *  Copyright (C) 2008 SUSE LINUX Products GmbH
- *  by Bernhard Walle <bwalle@suse.de>
+ *  by Bernhard Walle <bernhard.walle@gmx.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License v2.0 as published by
index 6022f44043f2a01305bb09564c82d78bd08ad006..92734c0012e679cb3326ba25be08f52dce81fbc8 100644 (file)
@@ -54,24 +54,30 @@ struct inodes_stat_t {
 #define MAY_ACCESS 16
 #define MAY_OPEN 32
 
+/*
+ * flags in file.f_mode.  Note that FMODE_READ and FMODE_WRITE must correspond
+ * to O_WRONLY and O_RDWR via the strange trick in __dentry_open()
+ */
+
 /* file is open for reading */
 #define FMODE_READ             ((__force fmode_t)1)
 /* file is open for writing */
 #define FMODE_WRITE            ((__force fmode_t)2)
 /* file is seekable */
 #define FMODE_LSEEK            ((__force fmode_t)4)
-/* file can be accessed using pread/pwrite */
+/* file can be accessed using pread */
 #define FMODE_PREAD            ((__force fmode_t)8)
-#define FMODE_PWRITE           FMODE_PREAD     /* These go hand in hand */
+/* file can be accessed using pwrite */
+#define FMODE_PWRITE           ((__force fmode_t)16)
 /* File is opened for execution with sys_execve / sys_uselib */
-#define FMODE_EXEC             ((__force fmode_t)16)
+#define FMODE_EXEC             ((__force fmode_t)32)
 /* File is opened with O_NDELAY (only set for block devices) */
-#define FMODE_NDELAY           ((__force fmode_t)32)
+#define FMODE_NDELAY           ((__force fmode_t)64)
 /* File is opened with O_EXCL (only set for block devices) */
-#define FMODE_EXCL             ((__force fmode_t)64)
+#define FMODE_EXCL             ((__force fmode_t)128)
 /* File is opened using open(.., 3, ..) and is writeable only for ioctls
    (specialy hack for floppy.c) */
-#define FMODE_WRITE_IOCTL      ((__force fmode_t)128)
+#define FMODE_WRITE_IOCTL      ((__force fmode_t)256)
 
 /*
  * Don't update ctime and mtime.
@@ -87,10 +93,10 @@ struct inodes_stat_t {
 #define WRITE 1
 #define READA 2                /* read-ahead  - don't block if no resources */
 #define SWRITE 3       /* for ll_rw_block() - wait for buffer lock */
-#define READ_SYNC      (READ | (1 << BIO_RW_SYNC))
+#define READ_SYNC      (READ | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG))
 #define READ_META      (READ | (1 << BIO_RW_META))
-#define WRITE_SYNC     (WRITE | (1 << BIO_RW_SYNC))
-#define SWRITE_SYNC    (SWRITE | (1 << BIO_RW_SYNC))
+#define WRITE_SYNC     (WRITE | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG))
+#define SWRITE_SYNC    (SWRITE | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG))
 #define WRITE_BARRIER  (WRITE | (1 << BIO_RW_BARRIER))
 #define DISCARD_NOBARRIER (1 << BIO_RW_DISCARD)
 #define DISCARD_BARRIER ((1 << BIO_RW_DISCARD) | (1 << BIO_RW_BARRIER))
index f8ff918c208f047f86b42894dfb3a6c211db2238..e1ff5b14310e817197fbf77c5af9522f2b862f6b 100644 (file)
@@ -210,6 +210,7 @@ static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci)
 
        /* Move the mac addresses to the beginning of the new header. */
        memmove(skb->data, skb->data + VLAN_HLEN, 2 * VLAN_ETH_ALEN);
+       skb->mac_header -= VLAN_HLEN;
 
        /* first, the ethernet type */
        veth->h_vlan_proto = htons(ETH_P_8021Q);
index b28b37eb11c626da84e8152f4878b8c593125ec3..4d248b3f1323d828170a9de92d2aba1db7c5f0f4 100644 (file)
@@ -1150,7 +1150,8 @@ extern int           jbd2_journal_clear_err  (journal_t *);
 extern int        jbd2_journal_bmap(journal_t *, unsigned long, unsigned long long *);
 extern int        jbd2_journal_force_commit(journal_t *);
 extern int        jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *inode);
-extern int        jbd2_journal_begin_ordered_truncate(struct jbd2_inode *inode, loff_t new_size);
+extern int        jbd2_journal_begin_ordered_truncate(journal_t *journal,
+                               struct jbd2_inode *inode, loff_t new_size);
 extern void       jbd2_journal_init_jbd_inode(struct jbd2_inode *jinode, struct inode *inode);
 extern void       jbd2_journal_release_jbd_inode(journal_t *journal, struct jbd2_inode *jinode);
 
index 5715f190760161fbbdfbdd3231f6e87c9a905b72..0424326f167963d5b764554ebec95029b8b99439 100644 (file)
@@ -58,10 +58,10 @@ struct kvm_irqchip {
        __u32 pad;
         union {
                char dummy[512];  /* reserving space */
-#ifdef CONFIG_X86
+#ifdef __KVM_HAVE_PIT
                struct kvm_pic_state pic;
 #endif
-#if defined(CONFIG_X86) || defined(CONFIG_IA64)
+#ifdef __KVM_HAVE_IOAPIC
                struct kvm_ioapic_state ioapic;
 #endif
        } chip;
@@ -384,16 +384,16 @@ struct kvm_trace_rec {
 #define KVM_CAP_MP_STATE 14
 #define KVM_CAP_COALESCED_MMIO 15
 #define KVM_CAP_SYNC_MMU 16  /* Changes to host mmap are reflected in guest */
-#if defined(CONFIG_X86)||defined(CONFIG_IA64)
+#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT
 #define KVM_CAP_DEVICE_ASSIGNMENT 17
 #endif
 #define KVM_CAP_IOMMU 18
-#if defined(CONFIG_X86)
+#ifdef __KVM_HAVE_MSI
 #define KVM_CAP_DEVICE_MSI 20
 #endif
 /* Bug in KVM_SET_USER_MEMORY_REGION fixed: */
 #define KVM_CAP_DESTROY_MEMORY_REGION_WORKS 21
-#if defined(CONFIG_X86)
+#ifdef __KVM_HAVE_USER_NMI
 #define KVM_CAP_USER_NMI 22
 #endif
 
index ec49d0be7f5245614c00e566a5f3702bccd6fa5e..bf6f703642fc81c21b33608cb48aff5477a0605b 100644 (file)
@@ -285,6 +285,7 @@ void kvm_free_physmem(struct kvm *kvm);
 struct  kvm *kvm_arch_create_vm(void);
 void kvm_arch_destroy_vm(struct kvm *kvm);
 void kvm_free_all_assigned_devices(struct kvm *kvm);
+void kvm_arch_sync_events(struct kvm *kvm);
 
 int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
 int kvm_cpu_has_interrupt(struct kvm_vcpu *v);
index 323561582c100bf1b18c3a3b6084eda970f89eeb..065cdf8c09fb50fcce6ff67bcae848ac555c6b7a 100644 (file)
@@ -1041,10 +1041,23 @@ extern void free_bootmem_with_active_regions(int nid,
 typedef int (*work_fn_t)(unsigned long, unsigned long, void *);
 extern void work_with_active_regions(int nid, work_fn_t work_fn, void *data);
 extern void sparse_memory_present_with_active_regions(int nid);
-#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
-extern int early_pfn_to_nid(unsigned long pfn);
-#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
 #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
+
+#if !defined(CONFIG_ARCH_POPULATES_NODE_MAP) && \
+    !defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID)
+static inline int __early_pfn_to_nid(unsigned long pfn)
+{
+       return 0;
+}
+#else
+/* please see mm/page_alloc.c */
+extern int __meminit early_pfn_to_nid(unsigned long pfn);
+#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+/* there is a per-arch backend function. */
+extern int __meminit __early_pfn_to_nid(unsigned long pfn);
+#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
+#endif
+
 extern void set_dma_reserve(unsigned long new_dma_reserve);
 extern void memmap_init_zone(unsigned long, int, unsigned long,
                                unsigned long, enum memmap_context);
@@ -1159,6 +1172,7 @@ extern int filemap_fault(struct vm_area_struct *, struct vm_fault *);
 
 /* mm/page-writeback.c */
 int write_one_page(struct page *page, int wait);
+void task_dirty_inc(struct task_struct *tsk);
 
 /* readahead.c */
 #define VM_MAX_READAHEAD       128     /* kbytes */
@@ -1304,5 +1318,6 @@ void vmemmap_populate_print_last(void);
 
 extern void *alloc_locked_buffer(size_t size);
 extern void free_locked_buffer(void *buffer, size_t size);
+extern void release_locked_buffer(void *buffer, size_t size);
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
index 09c14e213b63eb72f2f614695a886e67da7444d8..1aca6cebbb78916aaeb4764b3ec7e7da3276cf91 100644 (file)
@@ -1071,7 +1071,7 @@ void sparse_init(void);
 #endif /* CONFIG_SPARSEMEM */
 
 #ifdef CONFIG_NODES_SPAN_OTHER_NODES
-#define early_pfn_in_nid(pfn, nid)     (early_pfn_to_nid(pfn) == (nid))
+bool early_pfn_in_nid(unsigned long pfn, int nid);
 #else
 #define early_pfn_in_nid(pfn, nid)     (1)
 #endif
index 52a9fe08451cfa105c733099350355a8b89dc028..aca8c458aa8a7a23e87198ce8a9cb9eba8f3d87b 100644 (file)
 #define PCI_DEVICE_ID_VIA_VT3351       0x0351
 #define PCI_DEVICE_ID_VIA_VT3364       0x0364
 #define PCI_DEVICE_ID_VIA_8371_0       0x0391
+#define PCI_DEVICE_ID_VIA_6415         0x0415
 #define PCI_DEVICE_ID_VIA_8501_0       0x0501
 #define PCI_DEVICE_ID_VIA_82C561       0x0561
 #define PCI_DEVICE_ID_VIA_82C586_1     0x0571
 #define PCI_DEVICE_ID_DIGI_DF_M_E      0x0071
 #define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072
 #define PCI_DEVICE_ID_DIGI_DF_M_A      0x0073
+#define PCI_DEVICE_ID_DIGI_NEO_8       0x00B1
 #define PCI_DEVICE_ID_NEO_2DB9          0x00C8
 #define PCI_DEVICE_ID_NEO_2DB9PRI       0x00C9
 #define PCI_DEVICE_ID_NEO_2RJ45         0x00CA
 #define PCI_DEVICE_ID_INTEL_82378      0x0484
 #define PCI_DEVICE_ID_INTEL_I960       0x0960
 #define PCI_DEVICE_ID_INTEL_I960RM     0x0962
+#define PCI_DEVICE_ID_INTEL_8257X_SOL  0x1062
+#define PCI_DEVICE_ID_INTEL_82573E_SOL 0x1085
+#define PCI_DEVICE_ID_INTEL_82573L_SOL 0x108F
 #define PCI_DEVICE_ID_INTEL_82815_MC   0x1130
 #define PCI_DEVICE_ID_INTEL_82815_CGC  0x1132
 #define PCI_DEVICE_ID_INTEL_82092AA_0  0x1221
index de2e0a8f6728c668a2005ee3b36147a3b3caeec6..24ba5f67b3a3a590480b6ad32b62326be2156c9f 100644 (file)
@@ -381,10 +381,12 @@ struct dev_pm_info {
 
 #ifdef CONFIG_PM_SLEEP
 extern void device_pm_lock(void);
+extern int sysdev_resume(void);
 extern void device_power_up(pm_message_t state);
 extern void device_resume(pm_message_t state);
 
 extern void device_pm_unlock(void);
+extern int sysdev_suspend(pm_message_t state);
 extern int device_power_down(pm_message_t state);
 extern int device_suspend(pm_message_t state);
 extern int device_prepare_suspend(pm_message_t state);
index 40ea5058c2ec0ced97079290c08cd5bac08d1dca..f616f31576d719597cd91b25498fece72e24cc8d 100644 (file)
@@ -19,6 +19,7 @@ struct seq_file {
        size_t from;
        size_t count;
        loff_t index;
+       loff_t read_pos;
        u64 version;
        struct mutex lock;
        const struct seq_operations *op;
index 90bbbf0b1161bd592a19c1b2cc3f6803776c53df..df9245c7bd3be3b384146434a0494eea946225dd 100644 (file)
@@ -296,6 +296,7 @@ struct uart_port {
 #define UPF_HARDPPS_CD         ((__force upf_t) (1 << 11))
 #define UPF_LOW_LATENCY                ((__force upf_t) (1 << 13))
 #define UPF_BUGGY_UART         ((__force upf_t) (1 << 14))
+#define UPF_NO_TXEN_TEST       ((__force upf_t) (1 << 15))
 #define UPF_MAGIC_MULTIPLIER   ((__force upf_t) (1 << 16))
 #define UPF_CONS_FLOW          ((__force upf_t) (1 << 23))
 #define UPF_SHARE_IRQ          ((__force upf_t) (1 << 24))
index cf2cb50f77d1fe5f19e9894b78f4532789054ce7..9dcf956ad18ab20ce4ebb5a7f2e33636be4a6551 100644 (file)
@@ -416,15 +416,6 @@ extern void              skb_over_panic(struct sk_buff *skb, int len,
                                     void *here);
 extern void          skb_under_panic(struct sk_buff *skb, int len,
                                      void *here);
-extern void          skb_truesize_bug(struct sk_buff *skb);
-
-static inline void skb_truesize_check(struct sk_buff *skb)
-{
-       int len = sizeof(struct sk_buff) + skb->len;
-
-       if (unlikely((int)skb->truesize < len))
-               skb_truesize_bug(skb);
-}
 
 extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
                        int getfrag(void *from, char *to, int offset,
index f96d13c281e81d03bf0b791ccb10b1a918e12055..24c5602bee99d268f2a1fd29238279d6c9bb3db3 100644 (file)
@@ -127,6 +127,7 @@ int kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr);
 void * __must_check __krealloc(const void *, size_t, gfp_t);
 void * __must_check krealloc(const void *, size_t, gfp_t);
 void kfree(const void *);
+void kzfree(const void *);
 size_t ksize(const void *);
 
 /*
index bf8de281b4ed2a8e8131d34274711f81520d70f6..eed4254bd503f639f7a161dac634f3f68a93d9ed 100644 (file)
@@ -83,6 +83,13 @@ extern int spi_bitbang_stop(struct spi_bitbang *spi);
  *  int getmiso(struct spi_device *);
  *  void spidelay(unsigned);
  *
+ * setsck()'s is_on parameter is a zero/nonzero boolean.
+ *
+ * setmosi()'s is_on parameter is a zero/nonzero boolean.
+ *
+ * getmiso() is required to return 0 or 1 only. Any other value is invalid
+ * and will result in improper operation.
+ *
  * A non-inlined routine would call bitbang_txrx_*() routines.  The
  * main loop could easily compile down to a handful of instructions,
  * especially if the delay is a NOP (to run at peak speed).
index 86cb0501d3e20428b749eb2156bf5abc301e1c20..2d0792983f8c2d7500b8e7a595b48b36ff6579f2 100644 (file)
 /* For O_CLOEXEC and O_NONBLOCK */
 #include <linux/fcntl.h>
 
-/* Flags for timerfd_settime.  */
+/*
+ * CAREFUL: Check include/asm-generic/fcntl.h when defining
+ * new flags, since they might collide with O_* ones. We want
+ * to re-use O_* flags that couldn't possibly have a meaning
+ * from eventfd, in order to leave a free define-space for
+ * shared O_* flags.
+ */
 #define TFD_TIMER_ABSTIME (1 << 0)
-
-/* Flags for timerfd_create.  */
 #define TFD_CLOEXEC O_CLOEXEC
 #define TFD_NONBLOCK O_NONBLOCK
 
+#define TFD_SHARED_FCNTL_FLAGS (TFD_CLOEXEC | TFD_NONBLOCK)
+/* Flags for timerfd_create.  */
+#define TFD_CREATE_FLAGS TFD_SHARED_FCNTL_FLAGS
+/* Flags for timerfd_settime.  */
+#define TFD_SETTIME_FLAGS TFD_TIMER_ABSTIME
 
 #endif /* _LINUX_TIMERFD_H */
-
index 506e7620a986332cf5fda9e04d04050a88a49129..9c0890c7a06a357dd62e12cde059ca86764f8efa 100644 (file)
@@ -84,6 +84,10 @@ extern struct vm_struct *get_vm_area_caller(unsigned long size,
                                        unsigned long flags, void *caller);
 extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
                                        unsigned long start, unsigned long end);
+extern struct vm_struct *__get_vm_area_caller(unsigned long size,
+                                       unsigned long flags,
+                                       unsigned long start, unsigned long end,
+                                       void *caller);
 extern struct vm_struct *get_vm_area_node(unsigned long size,
                                          unsigned long flags, int node,
                                          gfp_t gfp_mask);
index ce3b5b6226838ca1d1595b519d02e6223efcb67b..eefeeaf7fc467123b6766da9ff8543b215a87f37 100644 (file)
@@ -860,7 +860,6 @@ static inline void sk_mem_uncharge(struct sock *sk, int size)
 
 static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb)
 {
-       skb_truesize_check(skb);
        sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
        sk->sk_wmem_queued -= skb->truesize;
        sk_mem_uncharge(sk, skb->truesize);
index 708105e163df8fbbbe69c7fc74a29693d6f3ed58..8d4ff5afc1d80b56963cbf119b162a3ebce61124 100644 (file)
@@ -370,10 +370,14 @@ void __init prepare_namespace(void)
                ssleep(root_delay);
        }
 
-       /* wait for the known devices to complete their probing */
-       while (driver_probe_done() != 0)
-               msleep(100);
-       async_synchronize_full();
+       /*
+        * wait for the known devices to complete their probing
+        *
+        * Note: this is a potential source of long boot delays.
+        * For example, it is not atypical to wait 5 seconds here
+        * for the touchpad of a laptop to initialize.
+        */
+       wait_for_device_probe();
 
        md_run_setup();
 
@@ -399,6 +403,7 @@ void __init prepare_namespace(void)
                while (driver_probe_done() != 0 ||
                        (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)
                        msleep(100);
+               async_synchronize_full();
        }
 
        is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
index ff95e319288472caaf3aa086c0fca769b0706b2f..9bdddbcb3d6a62614b0d43783abc9a265948bdde 100644 (file)
@@ -281,8 +281,9 @@ static void __init autodetect_raid(void)
         */
        printk(KERN_INFO "md: Waiting for all devices to be available before autodetect\n");
        printk(KERN_INFO "md: If you don't use raid, use raid=noautodetect\n");
-       while (driver_probe_done() < 0)
-               msleep(100);
+
+       wait_for_device_probe();
+
        fd = sys_open("/dev/md0", 0, 0);
        if (fd >= 0) {
                sys_ioctl(fd, RAID_AUTORUN, raid_autopart);
index 170a9213c1b68d6cee652fb7758fef556ecf127f..e4791b3ba55d45c163f3dd8cc0551f0aa7a1e766 100644 (file)
@@ -51,6 +51,7 @@ obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
 obj-$(CONFIG_PM) += power/
+obj-$(CONFIG_FREEZER) += power/
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
 obj-$(CONFIG_KEXEC) += kexec.o
 obj-$(CONFIG_BACKTRACE_SELF_TEST) += backtracetest.o
index e14db9c089b9db31df71296b199f173974b7410e..9edb5c4b79b4f1a88a0487f588c36fc6207f54a9 100644 (file)
@@ -1122,8 +1122,8 @@ static void cgroup_kill_sb(struct super_block *sb) {
 
        mutex_unlock(&cgroup_mutex);
 
-       kfree(root);
        kill_litter_super(sb);
+       kfree(root);
 }
 
 static struct file_system_type cgroup_fs_type = {
index f89d373a9c6d7ff5e6848404d4db5b84eb35819f..438701adce2344faab6551f3c833f3bb36c60b05 100644 (file)
@@ -1165,6 +1165,7 @@ static int futex_wait(u32 __user *uaddr, int fshared,
                      u32 val, ktime_t *abs_time, u32 bitset, int clockrt)
 {
        struct task_struct *curr = current;
+       struct restart_block *restart;
        DECLARE_WAITQUEUE(wait, curr);
        struct futex_hash_bucket *hb;
        struct futex_q q;
@@ -1216,11 +1217,13 @@ retry:
 
                if (!ret)
                        goto retry;
-               return ret;
+               goto out;
        }
        ret = -EWOULDBLOCK;
-       if (uval != val)
-               goto out_unlock_put_key;
+       if (unlikely(uval != val)) {
+               queue_unlock(&q, hb);
+               goto out_put_key;
+       }
 
        /* Only actually queue if *uaddr contained val.  */
        queue_me(&q, hb);
@@ -1284,38 +1287,38 @@ retry:
         */
 
        /* If we were woken (and unqueued), we succeeded, whatever. */
+       ret = 0;
        if (!unqueue_me(&q))
-               return 0;
+               goto out_put_key;
+       ret = -ETIMEDOUT;
        if (rem)
-               return -ETIMEDOUT;
+               goto out_put_key;
 
        /*
         * We expect signal_pending(current), but another thread may
         * have handled it for us already.
         */
+       ret = -ERESTARTSYS;
        if (!abs_time)
-               return -ERESTARTSYS;
-       else {
-               struct restart_block *restart;
-               restart = &current_thread_info()->restart_block;
-               restart->fn = futex_wait_restart;
-               restart->futex.uaddr = (u32 *)uaddr;
-               restart->futex.val = val;
-               restart->futex.time = abs_time->tv64;
-               restart->futex.bitset = bitset;
-               restart->futex.flags = 0;
-
-               if (fshared)
-                       restart->futex.flags |= FLAGS_SHARED;
-               if (clockrt)
-                       restart->futex.flags |= FLAGS_CLOCKRT;
-               return -ERESTART_RESTARTBLOCK;
-       }
+               goto out_put_key;
 
-out_unlock_put_key:
-       queue_unlock(&q, hb);
-       put_futex_key(fshared, &q.key);
+       restart = &current_thread_info()->restart_block;
+       restart->fn = futex_wait_restart;
+       restart->futex.uaddr = (u32 *)uaddr;
+       restart->futex.val = val;
+       restart->futex.time = abs_time->tv64;
+       restart->futex.bitset = bitset;
+       restart->futex.flags = 0;
+
+       if (fshared)
+               restart->futex.flags |= FLAGS_SHARED;
+       if (clockrt)
+               restart->futex.flags |= FLAGS_CLOCKRT;
 
+       ret = -ERESTART_RESTARTBLOCK;
+
+out_put_key:
+       put_futex_key(fshared, &q.key);
 out:
        return ret;
 }
index 8a6d7b08864ea199108cae686adbe1a8886a56a5..483899578259ebc725264bedae6abb132295b9d3 100644 (file)
@@ -1465,6 +1465,11 @@ int kernel_kexec(void)
                error = device_power_down(PMSG_FREEZE);
                if (error)
                        goto Enable_irqs;
+
+               /* Suspend system devices */
+               error = sysdev_suspend(PMSG_FREEZE);
+               if (error)
+                       goto Power_up_devices;
        } else
 #endif
        {
@@ -1477,6 +1482,8 @@ int kernel_kexec(void)
 
 #ifdef CONFIG_KEXEC_JUMP
        if (kexec_image->preserve_context) {
+               sysdev_resume();
+ Power_up_devices:
                device_power_up(PMSG_RESTORE);
  Enable_irqs:
                local_irq_enable();
index 2313a4cc14ea19d94faffaf4e6c6f7e0a109581e..e976e505648d2cf9d8e94085bcce6f1ec16afd8b 100644 (file)
@@ -680,6 +680,33 @@ static void cpu_timer_fire(struct k_itimer *timer)
        }
 }
 
+/*
+ * Sample a process (thread group) timer for the given group_leader task.
+ * Must be called with tasklist_lock held for reading.
+ */
+static int cpu_timer_sample_group(const clockid_t which_clock,
+                                 struct task_struct *p,
+                                 union cpu_time_count *cpu)
+{
+       struct task_cputime cputime;
+
+       thread_group_cputimer(p, &cputime);
+       switch (CPUCLOCK_WHICH(which_clock)) {
+       default:
+               return -EINVAL;
+       case CPUCLOCK_PROF:
+               cpu->cpu = cputime_add(cputime.utime, cputime.stime);
+               break;
+       case CPUCLOCK_VIRT:
+               cpu->cpu = cputime.utime;
+               break;
+       case CPUCLOCK_SCHED:
+               cpu->sched = cputime.sum_exec_runtime + task_delta_exec(p);
+               break;
+       }
+       return 0;
+}
+
 /*
  * Guts of sys_timer_settime for CPU timers.
  * This is called with the timer locked and interrupts disabled.
@@ -741,7 +768,7 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags,
        if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
                cpu_clock_sample(timer->it_clock, p, &val);
        } else {
-               cpu_clock_sample_group(timer->it_clock, p, &val);
+               cpu_timer_sample_group(timer->it_clock, p, &val);
        }
 
        if (old) {
@@ -889,7 +916,7 @@ void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
                        read_unlock(&tasklist_lock);
                        goto dead;
                } else {
-                       cpu_clock_sample_group(timer->it_clock, p, &now);
+                       cpu_timer_sample_group(timer->it_clock, p, &now);
                        clear_dead = (unlikely(p->exit_state) &&
                                      thread_group_empty(p));
                }
@@ -1244,7 +1271,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)
                        clear_dead_task(timer, now);
                        goto out_unlock;
                }
-               cpu_clock_sample_group(timer->it_clock, p, &now);
+               cpu_timer_sample_group(timer->it_clock, p, &now);
                bump_cpu_timer(timer, now);
                /* Leave the tasklist_lock locked for the call below.  */
        }
@@ -1408,33 +1435,6 @@ void run_posix_cpu_timers(struct task_struct *tsk)
        }
 }
 
-/*
- * Sample a process (thread group) timer for the given group_leader task.
- * Must be called with tasklist_lock held for reading.
- */
-static int cpu_timer_sample_group(const clockid_t which_clock,
-                                 struct task_struct *p,
-                                 union cpu_time_count *cpu)
-{
-       struct task_cputime cputime;
-
-       thread_group_cputimer(p, &cputime);
-       switch (CPUCLOCK_WHICH(which_clock)) {
-       default:
-               return -EINVAL;
-       case CPUCLOCK_PROF:
-               cpu->cpu = cputime_add(cputime.utime, cputime.stime);
-               break;
-       case CPUCLOCK_VIRT:
-               cpu->cpu = cputime.utime;
-               break;
-       case CPUCLOCK_SCHED:
-               cpu->sched = cputime.sum_exec_runtime + task_delta_exec(p);
-               break;
-       }
-       return 0;
-}
-
 /*
  * Set one of the process-wide special case CPU timers.
  * The tsk->sighand->siglock must be held by the caller.
index d7a10167a25b37d787418bfbee02e68ba4e28c55..720ea4f781bd4896ef8922b9e55442f447967ab5 100644 (file)
@@ -3,7 +3,7 @@ ifeq ($(CONFIG_PM_DEBUG),y)
 EXTRA_CFLAGS   +=      -DDEBUG
 endif
 
-obj-y                          := main.o
+obj-$(CONFIG_PM)               += main.o
 obj-$(CONFIG_PM_SLEEP)         += console.o
 obj-$(CONFIG_FREEZER)          += process.o
 obj-$(CONFIG_HIBERNATION)      += swsusp.o disk.o snapshot.o swap.o user.o
index b8628be2a465c4841ccc69135d91618b56b2d6ca..a3961b205de743c30f9588e02d28f1f959b46db6 100644 (file)
@@ -78,6 +78,12 @@ void pm_restore_console(void)
        }
        set_console(orig_fgconsole);
        release_console_sem();
+
+       if (vt_waitactive(orig_fgconsole)) {
+               pr_debug("Resume: Can't switch VCs.");
+               return;
+       }
+
        kmsg_redirect = orig_kmsg;
 }
 #endif
index 432ee575c9ee4fd201481a9ebdb674c29b96dab8..4a4a206b1979c657c887df31907166080a004d8f 100644 (file)
@@ -227,6 +227,12 @@ static int create_image(int platform_mode)
                        "aborting hibernation\n");
                goto Enable_irqs;
        }
+       sysdev_suspend(PMSG_FREEZE);
+       if (error) {
+               printk(KERN_ERR "PM: Some devices failed to power down, "
+                       "aborting hibernation\n");
+               goto Power_up_devices;
+       }
 
        if (hibernation_test(TEST_CORE))
                goto Power_up;
@@ -242,9 +248,11 @@ static int create_image(int platform_mode)
        if (!in_suspend)
                platform_leave(platform_mode);
  Power_up:
+       sysdev_resume();
        /* NOTE:  device_power_up() is just a resume() for devices
         * that suspended with irqs off ... no overall powerup.
         */
+ Power_up_devices:
        device_power_up(in_suspend ?
                (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
  Enable_irqs:
@@ -335,6 +343,7 @@ static int resume_target_kernel(void)
                        "aborting resume\n");
                goto Enable_irqs;
        }
+       sysdev_suspend(PMSG_QUIESCE);
        /* We'll ignore saved state, but this gets preempt count (etc) right */
        save_processor_state();
        error = restore_highmem();
@@ -357,6 +366,7 @@ static int resume_target_kernel(void)
        swsusp_free();
        restore_processor_state();
        touch_softlockup_watchdog();
+       sysdev_resume();
        device_power_up(PMSG_RECOVER);
  Enable_irqs:
        local_irq_enable();
@@ -440,6 +450,7 @@ int hibernation_platform_enter(void)
        local_irq_disable();
        error = device_power_down(PMSG_HIBERNATE);
        if (!error) {
+               sysdev_suspend(PMSG_HIBERNATE);
                hibernation_ops->enter();
                /* We should never get here */
                while (1);
@@ -594,6 +605,12 @@ static int software_resume(void)
        int error;
        unsigned int flags;
 
+       /*
+        * If the user said "noresume".. bail out early.
+        */
+       if (noresume)
+               return 0;
+
        /*
         * name_to_dev_t() below takes a sysfs buffer mutex when sysfs
         * is configured into the kernel. Since the regular hibernate
@@ -610,6 +627,11 @@ static int software_resume(void)
                        mutex_unlock(&pm_mutex);
                        return -ENOENT;
                }
+               /*
+                * Some device discovery might still be in progress; we need
+                * to wait for this to finish.
+                */
+               wait_for_device_probe();
                swsusp_resume_device = name_to_dev_t(resume_file);
                pr_debug("PM: Resume from partition %s\n", resume_file);
        } else {
index b4d219016b6ca351f19ad2a08e6f7c9aada2ab7e..c9632f841f646fbfc146ecee855fd04068a548ae 100644 (file)
@@ -298,8 +298,12 @@ static int suspend_enter(suspend_state_t state)
                goto Done;
        }
 
-       if (!suspend_test(TEST_CORE))
-               error = suspend_ops->enter(state);
+       error = sysdev_suspend(PMSG_SUSPEND);
+       if (!error) {
+               if (!suspend_test(TEST_CORE))
+                       error = suspend_ops->enter(state);
+               sysdev_resume();
+       }
 
        device_power_up(PMSG_RESUME);
  Done:
index 6da14358537c8779db14f4ccab91a64365270d16..505f319e489c901ad0fbba6fecd1b508246fec14 100644 (file)
@@ -60,6 +60,7 @@ static struct block_device *resume_bdev;
 static int submit(int rw, pgoff_t page_off, struct page *page,
                        struct bio **bio_chain)
 {
+       const int bio_rw = rw | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
        struct bio *bio;
 
        bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1);
@@ -80,7 +81,7 @@ static int submit(int rw, pgoff_t page_off, struct page *page,
        bio_get(bio);
 
        if (bio_chain == NULL) {
-               submit_bio(rw | (1 << BIO_RW_SYNC), bio);
+               submit_bio(bio_rw, bio);
                wait_on_page_locked(page);
                if (rw == READ)
                        bio_set_pages_dirty(bio);
@@ -90,7 +91,7 @@ static int submit(int rw, pgoff_t page_off, struct page *page,
                        get_page(page); /* These pages are freed later */
                bio->bi_private = *bio_chain;
                *bio_chain = bio;
-               submit_bio(rw | (1 << BIO_RW_SYNC), bio);
+               submit_bio(bio_rw, bio);
        }
        return 0;
 }
index 005b93d839ba1268da0c80c3106739ee388d996a..6c85359364f2bcfd31bb06e77ec0eda7585e08dc 100644 (file)
@@ -95,15 +95,15 @@ static int snapshot_open(struct inode *inode, struct file *filp)
                data->swap = swsusp_resume_device ?
                        swap_type_of(swsusp_resume_device, 0, NULL) : -1;
                data->mode = O_RDONLY;
-               error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
+               error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
                if (error)
-                       pm_notifier_call_chain(PM_POST_RESTORE);
+                       pm_notifier_call_chain(PM_POST_HIBERNATION);
        } else {
                data->swap = -1;
                data->mode = O_WRONLY;
-               error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
+               error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
                if (error)
-                       pm_notifier_call_chain(PM_POST_HIBERNATION);
+                       pm_notifier_call_chain(PM_POST_RESTORE);
        }
        if (error)
                atomic_inc(&snapshot_device_available);
index 69188f226a93251009d22d6dc453ce3d59220816..e3602d0755b0dd99c9fb47887fd67d371cdd5424 100644 (file)
@@ -73,7 +73,6 @@ EXPORT_SYMBOL(oops_in_progress);
  * driver system.
  */
 static DECLARE_MUTEX(console_sem);
-static DECLARE_MUTEX(secondary_console_sem);
 struct console *console_drivers;
 EXPORT_SYMBOL_GPL(console_drivers);
 
@@ -891,12 +890,14 @@ void suspend_console(void)
        printk("Suspending console(s) (use no_console_suspend to debug)\n");
        acquire_console_sem();
        console_suspended = 1;
+       up(&console_sem);
 }
 
 void resume_console(void)
 {
        if (!console_suspend_enabled)
                return;
+       down(&console_sem);
        console_suspended = 0;
        release_console_sem();
 }
@@ -912,11 +913,9 @@ void resume_console(void)
 void acquire_console_sem(void)
 {
        BUG_ON(in_interrupt());
-       if (console_suspended) {
-               down(&secondary_console_sem);
-               return;
-       }
        down(&console_sem);
+       if (console_suspended)
+               return;
        console_locked = 1;
        console_may_schedule = 1;
 }
@@ -926,6 +925,10 @@ int try_acquire_console_sem(void)
 {
        if (down_trylock(&console_sem))
                return -1;
+       if (console_suspended) {
+               up(&console_sem);
+               return -1;
+       }
        console_locked = 1;
        console_may_schedule = 0;
        return 0;
@@ -979,7 +982,7 @@ void release_console_sem(void)
        unsigned wake_klogd = 0;
 
        if (console_suspended) {
-               up(&secondary_console_sem);
+               up(&console_sem);
                return;
        }
 
index c1d0ed360088f5a5378ae4b6db9555e7e0b90f21..410eec404133fd267eb80041395e21d266f0e552 100644 (file)
@@ -6944,20 +6944,26 @@ static void free_rootdomain(struct root_domain *rd)
 
 static void rq_attach_root(struct rq *rq, struct root_domain *rd)
 {
+       struct root_domain *old_rd = NULL;
        unsigned long flags;
 
        spin_lock_irqsave(&rq->lock, flags);
 
        if (rq->rd) {
-               struct root_domain *old_rd = rq->rd;
+               old_rd = rq->rd;
 
                if (cpumask_test_cpu(rq->cpu, old_rd->online))
                        set_rq_offline(rq);
 
                cpumask_clear_cpu(rq->cpu, old_rd->span);
 
-               if (atomic_dec_and_test(&old_rd->refcount))
-                       free_rootdomain(old_rd);
+               /*
+                * If we dont want to free the old_rt yet then
+                * set old_rd to NULL to skip the freeing later
+                * in this function:
+                */
+               if (!atomic_dec_and_test(&old_rd->refcount))
+                       old_rd = NULL;
        }
 
        atomic_inc(&rd->refcount);
@@ -6968,6 +6974,9 @@ static void rq_attach_root(struct rq *rq, struct root_domain *rd)
                set_rq_online(rq);
 
        spin_unlock_irqrestore(&rq->lock, flags);
+
+       if (old_rd)
+               free_rootdomain(old_rd);
 }
 
 static int __init_refok init_rootdomain(struct root_domain *rd, bool bootmem)
index e2a4ff6fc3a6bb1509472dad03d0ad41df855748..34e707e5ab87f002ab93f0eb70e776cb09704354 100644 (file)
@@ -52,6 +52,7 @@ config FUNCTION_TRACER
        depends on HAVE_FUNCTION_TRACER
        depends on DEBUG_KERNEL
        select FRAME_POINTER
+       select KALLSYMS
        select TRACING
        select CONTEXT_SWITCH_TRACER
        help
@@ -238,6 +239,7 @@ config STACK_TRACER
        depends on DEBUG_KERNEL
        select FUNCTION_TRACER
        select STACKTRACE
+       select KALLSYMS
        help
          This special tracer records the maximum stack footprint of the
          kernel and displays it in debugfs/tracing/stack_trace.
@@ -302,4 +304,27 @@ config FTRACE_STARTUP_TEST
          functioning properly. It will do tests on all the configured
          tracers of ftrace.
 
+config MMIOTRACE
+       bool "Memory mapped IO tracing"
+       depends on HAVE_MMIOTRACE_SUPPORT && DEBUG_KERNEL && PCI
+       select TRACING
+       help
+         Mmiotrace traces Memory Mapped I/O access and is meant for
+         debugging and reverse engineering. It is called from the ioremap
+         implementation and works via page faults. Tracing is disabled by
+         default and can be enabled at run-time.
+
+         See Documentation/tracers/mmiotrace.txt.
+         If you are not helping to develop drivers, say N.
+
+config MMIOTRACE_TEST
+       tristate "Test module for mmiotrace"
+       depends on MMIOTRACE && m
+       help
+         This is a dumb module for testing mmiotrace. It is very dangerous
+         as it will write garbage to IO memory starting at a given address.
+         However, it should be safe to use on e.g. unused portion of VRAM.
+
+         Say N, unless you absolutely know what you are doing.
+
 endmenu
index 9a236ffe2aa45188cacabfc8fbc15e81c6091f64..fdf913dfc7e8eada7de16b320b62d283b18447a5 100644 (file)
@@ -2033,7 +2033,7 @@ free:
 static int start_graph_tracing(void)
 {
        struct ftrace_ret_stack **ret_stack_list;
-       int ret;
+       int ret, cpu;
 
        ret_stack_list = kmalloc(FTRACE_RETSTACK_ALLOC_SIZE *
                                sizeof(struct ftrace_ret_stack *),
@@ -2042,6 +2042,10 @@ static int start_graph_tracing(void)
        if (!ret_stack_list)
                return -ENOMEM;
 
+       /* The cpu_boot init_task->ret_stack will never be freed */
+       for_each_online_cpu(cpu)
+               ftrace_graph_init_task(idle_task(cpu));
+
        do {
                ret = alloc_retstack_tasklist(ret_stack_list);
        } while (ret == -EAGAIN);
index fffcb069f1dcb48213ec0c51a4c8d1774e8235a4..80e503ef6136c208cef128006578ec7227a35678 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/mmiotrace.h>
 #include <linux/pci.h>
+#include <asm/atomic.h>
 
 #include "trace.h"
 
@@ -19,6 +20,7 @@ struct header_iter {
 static struct trace_array *mmio_trace_array;
 static bool overrun_detected;
 static unsigned long prev_overruns;
+static atomic_t dropped_count;
 
 static void mmio_reset_data(struct trace_array *tr)
 {
@@ -121,11 +123,11 @@ static void mmio_close(struct trace_iterator *iter)
 
 static unsigned long count_overruns(struct trace_iterator *iter)
 {
-       unsigned long cnt = 0;
+       unsigned long cnt = atomic_xchg(&dropped_count, 0);
        unsigned long over = ring_buffer_overruns(iter->tr->buffer);
 
        if (over > prev_overruns)
-               cnt = over - prev_overruns;
+               cnt += over - prev_overruns;
        prev_overruns = over;
        return cnt;
 }
@@ -310,8 +312,10 @@ static void __trace_mmiotrace_rw(struct trace_array *tr,
 
        event   = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
                                           &irq_flags);
-       if (!event)
+       if (!event) {
+               atomic_inc(&dropped_count);
                return;
+       }
        entry   = ring_buffer_event_data(event);
        tracing_generic_entry_update(&entry->ent, 0, preempt_count());
        entry->ent.type                 = TRACE_MMIO_RW;
@@ -338,8 +342,10 @@ static void __trace_mmiotrace_map(struct trace_array *tr,
 
        event   = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
                                           &irq_flags);
-       if (!event)
+       if (!event) {
+               atomic_inc(&dropped_count);
                return;
+       }
        entry   = ring_buffer_event_data(event);
        tracing_generic_entry_update(&entry->ent, 0, preempt_count());
        entry->ent.type                 = TRACE_MMIO_MAP;
index 88c8eb70f54aeb3508dda9c668f082b9a43b0c78..bc8e80a86bca4c0cf730fcf6b7bc568f2808f7e7 100644 (file)
@@ -23,10 +23,20 @@ static int trace_test_buffer_cpu(struct trace_array *tr, int cpu)
 {
        struct ring_buffer_event *event;
        struct trace_entry *entry;
+       unsigned int loops = 0;
 
        while ((event = ring_buffer_consume(tr->buffer, cpu, NULL))) {
                entry = ring_buffer_event_data(event);
 
+               /*
+                * The ring buffer is a size of trace_buf_size, if
+                * we loop more than the size, there's something wrong
+                * with the ring buffer.
+                */
+               if (loops++ > trace_buf_size) {
+                       printk(KERN_CONT ".. bad ring buffer ");
+                       goto failed;
+               }
                if (!trace_valid_entry(entry)) {
                        printk(KERN_CONT ".. invalid entry %d ",
                                entry->type);
@@ -57,11 +67,20 @@ static int trace_test_buffer(struct trace_array *tr, unsigned long *count)
 
        cnt = ring_buffer_entries(tr->buffer);
 
+       /*
+        * The trace_test_buffer_cpu runs a while loop to consume all data.
+        * If the calling tracer is broken, and is constantly filling
+        * the buffer, this will run forever, and hard lock the box.
+        * We disable the ring buffer while we do this test to prevent
+        * a hard lock up.
+        */
+       tracing_off();
        for_each_possible_cpu(cpu) {
                ret = trace_test_buffer_cpu(tr, cpu);
                if (ret)
                        break;
        }
+       tracing_on();
        __raw_spin_unlock(&ftrace_max_lock);
        local_irq_restore(flags);
 
index 29044f500269c3b9ad9b834adc21a77557ac897b..1bcf9cd4baa08a85633e5758721b7ef21f4df787 100644 (file)
@@ -838,7 +838,7 @@ config FIREWIRE_OHCI_REMOTE_DMA
 
          If unsure, say N.
 
-menuconfig BUILD_DOCSRC
+config BUILD_DOCSRC
        bool "Build targets in Documentation/ tree"
        depends on HEADERS_CHECK
        help
index 037161d61b4e72432d9d6bae71507d251b522afc..cbe9e0581b75dcaf06335ccc017a68789d6247d2 100644 (file)
@@ -660,7 +660,7 @@ void *alloc_locked_buffer(size_t size)
        return buffer;
 }
 
-void free_locked_buffer(void *buffer, size_t size)
+void release_locked_buffer(void *buffer, size_t size)
 {
        unsigned long pgsz = PAGE_ALIGN(size) >> PAGE_SHIFT;
 
@@ -670,6 +670,11 @@ void free_locked_buffer(void *buffer, size_t size)
        current->mm->locked_vm -= pgsz;
 
        up_write(&current->mm->mmap_sem);
+}
+
+void free_locked_buffer(void *buffer, size_t size)
+{
+       release_locked_buffer(buffer, size);
 
        kfree(buffer);
 }
index 3c84128596ba88892cd1394e334d6c0c5bd12e3d..74dc57c74349ff124dd31a3e04531ee503ecedca 100644 (file)
@@ -240,7 +240,7 @@ void bdi_writeout_inc(struct backing_dev_info *bdi)
 }
 EXPORT_SYMBOL_GPL(bdi_writeout_inc);
 
-static inline void task_dirty_inc(struct task_struct *tsk)
+void task_dirty_inc(struct task_struct *tsk)
 {
        prop_inc_single(&vm_dirties, &tsk->dirties);
 }
@@ -1230,6 +1230,7 @@ int __set_page_dirty_nobuffers(struct page *page)
                                __inc_zone_page_state(page, NR_FILE_DIRTY);
                                __inc_bdi_stat(mapping->backing_dev_info,
                                                BDI_RECLAIMABLE);
+                               task_dirty_inc(current);
                                task_io_account_write(PAGE_CACHE_SIZE);
                        }
                        radix_tree_tag_set(&mapping->page_tree,
@@ -1262,7 +1263,7 @@ EXPORT_SYMBOL(redirty_page_for_writepage);
  * If the mapping doesn't provide a set_page_dirty a_op, then
  * just fall through and assume that it wants buffer_heads.
  */
-static int __set_page_dirty(struct page *page)
+int set_page_dirty(struct page *page)
 {
        struct address_space *mapping = page_mapping(page);
 
@@ -1280,14 +1281,6 @@ static int __set_page_dirty(struct page *page)
        }
        return 0;
 }
-
-int set_page_dirty(struct page *page)
-{
-       int ret = __set_page_dirty(page);
-       if (ret)
-               task_dirty_inc(current);
-       return ret;
-}
 EXPORT_SYMBOL(set_page_dirty);
 
 /*
index 5675b30738546451c47771e5703f06830a63898a..5c44ed49ca93c5a1d7a39f5570b0d1254a45de80 100644 (file)
@@ -2989,7 +2989,7 @@ static int __meminit next_active_region_index_in_nid(int index, int nid)
  * was used and there are no special requirements, this is a convenient
  * alternative
  */
-int __meminit early_pfn_to_nid(unsigned long pfn)
+int __meminit __early_pfn_to_nid(unsigned long pfn)
 {
        int i;
 
@@ -3000,10 +3000,33 @@ int __meminit early_pfn_to_nid(unsigned long pfn)
                if (start_pfn <= pfn && pfn < end_pfn)
                        return early_node_map[i].nid;
        }
+       /* This is a memory hole */
+       return -1;
+}
+#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
+
+int __meminit early_pfn_to_nid(unsigned long pfn)
+{
+       int nid;
 
+       nid = __early_pfn_to_nid(pfn);
+       if (nid >= 0)
+               return nid;
+       /* just returns 0 */
        return 0;
 }
-#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
+
+#ifdef CONFIG_NODES_SPAN_OTHER_NODES
+bool __meminit early_pfn_in_nid(unsigned long pfn, int node)
+{
+       int nid;
+
+       nid = __early_pfn_to_nid(pfn);
+       if (nid >= 0 && nid != node)
+               return false;
+       return true;
+}
+#endif
 
 /* Basic iterator support to walk early_node_map[] */
 #define for_each_active_range_index_in_nid(i, nid) \
index dc6ce0afbded84abdfa553300e6ac9d06e00d0a9..3023c475e0415fc0c6ec537a556e6d3835a2b1d9 100644 (file)
@@ -111,7 +111,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc)
                goto out;
        }
        if (wbc->sync_mode == WB_SYNC_ALL)
-               rw |= (1 << BIO_RW_SYNC);
+               rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
        count_vm_event(PSWPOUT);
        set_page_writeback(page);
        unlock_page(page);
index 7e6304dfafab174884bad5820a0194f449906a32..312fafe0ab6ed4815ac02da3f712aca18bacbbad 100644 (file)
@@ -635,7 +635,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
 
                if (!bdev) {
                        if (bdev_p)
-                               *bdev_p = sis->bdev;
+                               *bdev_p = bdget(sis->bdev->bd_dev);
 
                        spin_unlock(&swap_lock);
                        return i;
@@ -647,7 +647,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
                                        struct swap_extent, list);
                        if (se->start_block == offset) {
                                if (bdev_p)
-                                       *bdev_p = sis->bdev;
+                                       *bdev_p = bdget(sis->bdev->bd_dev);
 
                                spin_unlock(&swap_lock);
                                bdput(bdev);
index cb00b748ce47886446975d96466c2154f4d52fa3..37eaccdf3054e13d60cd83cf5c6cb9869731aec1 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -129,6 +129,26 @@ void *krealloc(const void *p, size_t new_size, gfp_t flags)
 }
 EXPORT_SYMBOL(krealloc);
 
+/**
+ * kzfree - like kfree but zero memory
+ * @p: object to free memory of
+ *
+ * The memory of the object @p points to is zeroed before freed.
+ * If @p is %NULL, kzfree() does nothing.
+ */
+void kzfree(const void *p)
+{
+       size_t ks;
+       void *mem = (void *)p;
+
+       if (unlikely(ZERO_OR_NULL_PTR(mem)))
+               return;
+       ks = ksize(mem);
+       memset(mem, 0, ks);
+       kfree(mem);
+}
+EXPORT_SYMBOL(kzfree);
+
 /*
  * strndup_user - duplicate an existing string from user space
  * @s: The string to duplicate
index 75f49d312e8c1d47648f3e96b8a1eb6d14076405..903cad46e796b94bde12306efbce62b532be3713 100644 (file)
@@ -1012,6 +1012,8 @@ void __init vmalloc_init(void)
 void unmap_kernel_range(unsigned long addr, unsigned long size)
 {
        unsigned long end = addr + size;
+
+       flush_cache_vunmap(addr, end);
        vunmap_page_range(addr, end);
        flush_tlb_kernel_range(addr, end);
 }
@@ -1106,6 +1108,14 @@ struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
 }
 EXPORT_SYMBOL_GPL(__get_vm_area);
 
+struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags,
+                                      unsigned long start, unsigned long end,
+                                      void *caller)
+{
+       return __get_vm_area_node(size, flags, start, end, -1, GFP_KERNEL,
+                                 caller);
+}
+
 /**
  *     get_vm_area  -  reserve a contiguous kernel virtual area
  *     @size:          size of the area
index 9a27c44aa327f8f46ddbde07776df8644db82de5..6177e3bcd66bdc7b8fc74cb583d47bb89c4940ef 100644 (file)
@@ -2057,31 +2057,31 @@ static unsigned long shrink_all_zones(unsigned long nr_pages, int prio,
                                      int pass, struct scan_control *sc)
 {
        struct zone *zone;
-       unsigned long nr_to_scan, ret = 0;
-       enum lru_list l;
+       unsigned long ret = 0;
 
        for_each_zone(zone) {
+               enum lru_list l;
 
                if (!populated_zone(zone))
                        continue;
-
                if (zone_is_all_unreclaimable(zone) && prio != DEF_PRIORITY)
                        continue;
 
                for_each_evictable_lru(l) {
+                       enum zone_stat_item ls = NR_LRU_BASE + l;
+                       unsigned long lru_pages = zone_page_state(zone, ls);
+
                        /* For pass = 0, we don't shrink the active list */
-                       if (pass == 0 &&
-                               (l == LRU_ACTIVE || l == LRU_ACTIVE_FILE))
+                       if (pass == 0 && (l == LRU_ACTIVE_ANON ||
+                                               l == LRU_ACTIVE_FILE))
                                continue;
 
-                       zone->lru[l].nr_scan +=
-                               (zone_page_state(zone, NR_LRU_BASE + l)
-                                                               >> prio) + 1;
+                       zone->lru[l].nr_scan += (lru_pages >> prio) + 1;
                        if (zone->lru[l].nr_scan >= nr_pages || pass > 3) {
+                               unsigned long nr_to_scan;
+
                                zone->lru[l].nr_scan = 0;
-                               nr_to_scan = min(nr_pages,
-                                       zone_page_state(zone,
-                                                       NR_LRU_BASE + l));
+                               nr_to_scan = min(nr_pages, lru_pages);
                                ret += shrink_list(l, nr_to_scan, zone,
                                                                sc, prio);
                                if (ret >= nr_pages)
@@ -2089,7 +2089,6 @@ static unsigned long shrink_all_zones(unsigned long nr_pages, int prio,
                        }
                }
        }
-
        return ret;
 }
 
@@ -2112,7 +2111,6 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
                .may_swap = 0,
                .swap_cluster_max = nr_pages,
                .may_writepage = 1,
-               .swappiness = vm_swappiness,
                .isolate_pages = isolate_pages_global,
        };
 
@@ -2146,10 +2144,8 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
                int prio;
 
                /* Force reclaiming mapped pages in the passes #3 and #4 */
-               if (pass > 2) {
+               if (pass > 2)
                        sc.may_swap = 1;
-                       sc.swappiness = 100;
-               }
 
                for (prio = DEF_PRIORITY; prio >= 0; prio--) {
                        unsigned long nr_to_scan = nr_pages - ret;
index 55151faaf90c1793c53e38bed732ff3c5bd53397..b0767abf23e57f32e73d54ca2b44ebdeec1d5f11 100644 (file)
@@ -32,24 +32,14 @@ static __net_init int setup_net(struct net *net)
 {
        /* Must be called with net_mutex held */
        struct pernet_operations *ops;
-       int error;
-       struct net_generic *ng;
+       int error = 0;
 
        atomic_set(&net->count, 1);
+
 #ifdef NETNS_REFCNT_DEBUG
        atomic_set(&net->use_count, 0);
 #endif
 
-       error = -ENOMEM;
-       ng = kzalloc(sizeof(struct net_generic) +
-                       INITIAL_NET_GEN_PTRS * sizeof(void *), GFP_KERNEL);
-       if (ng == NULL)
-               goto out;
-
-       ng->len = INITIAL_NET_GEN_PTRS;
-       rcu_assign_pointer(net->gen, ng);
-
-       error = 0;
        list_for_each_entry(ops, &pernet_list, list) {
                if (ops->init) {
                        error = ops->init(net);
@@ -70,7 +60,6 @@ out_undo:
        }
 
        rcu_barrier();
-       kfree(ng);
        goto out;
 }
 
@@ -78,16 +67,43 @@ out_undo:
 static struct kmem_cache *net_cachep;
 static struct workqueue_struct *netns_wq;
 
-static struct net *net_alloc(void)
+static struct net_generic *net_alloc_generic(void)
 {
-       return kmem_cache_zalloc(net_cachep, GFP_KERNEL);
+       struct net_generic *ng;
+       size_t generic_size = sizeof(struct net_generic) +
+               INITIAL_NET_GEN_PTRS * sizeof(void *);
+
+       ng = kzalloc(generic_size, GFP_KERNEL);
+       if (ng)
+               ng->len = INITIAL_NET_GEN_PTRS;
+
+       return ng;
 }
 
-static void net_free(struct net *net)
+static struct net *net_alloc(void)
 {
+       struct net *net = NULL;
+       struct net_generic *ng;
+
+       ng = net_alloc_generic();
+       if (!ng)
+               goto out;
+
+       net = kmem_cache_zalloc(net_cachep, GFP_KERNEL);
        if (!net)
-               return;
+               goto out_free;
+
+       rcu_assign_pointer(net->gen, ng);
+out:
+       return net;
+
+out_free:
+       kfree(ng);
+       goto out;
+}
 
+static void net_free(struct net *net)
+{
 #ifdef NETNS_REFCNT_DEBUG
        if (unlikely(atomic_read(&net->use_count) != 0)) {
                printk(KERN_EMERG "network namespace not free! Usage: %d\n",
@@ -112,27 +128,28 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
        err = -ENOMEM;
        new_net = net_alloc();
        if (!new_net)
-               goto out;
+               goto out_err;
 
        mutex_lock(&net_mutex);
        err = setup_net(new_net);
-       if (err)
-               goto out_unlock;
-
-       rtnl_lock();
-       list_add_tail(&new_net->list, &net_namespace_list);
-       rtnl_unlock();
-
-
-out_unlock:
+       if (!err) {
+               rtnl_lock();
+               list_add_tail(&new_net->list, &net_namespace_list);
+               rtnl_unlock();
+       }
        mutex_unlock(&net_mutex);
+
+       if (err)
+               goto out_free;
 out:
        put_net(old_net);
-       if (err) {
-               net_free(new_net);
-               new_net = ERR_PTR(err);
-       }
        return new_net;
+
+out_free:
+       net_free(new_net);
+out_err:
+       new_net = ERR_PTR(err);
+       goto out;
 }
 
 static void cleanup_net(struct work_struct *work)
@@ -188,6 +205,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
 
 static int __init net_ns_init(void)
 {
+       struct net_generic *ng;
        int err;
 
        printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net));
@@ -202,6 +220,12 @@ static int __init net_ns_init(void)
                panic("Could not create netns workq");
 #endif
 
+       ng = net_alloc_generic();
+       if (!ng)
+               panic("Could not allocate generic netns");
+
+       rcu_assign_pointer(init_net.gen, ng);
+
        mutex_lock(&net_mutex);
        err = setup_net(&init_net);
 
index da74b844f4eab0464374a1a667cea8aa40a7bf26..c6a6b166f8d6f733a4dc9f7143bd565aaddf7e8f 100644 (file)
@@ -143,14 +143,6 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here)
        BUG();
 }
 
-void skb_truesize_bug(struct sk_buff *skb)
-{
-       WARN(net_ratelimit(), KERN_ERR "SKB BUG: Invalid truesize (%u) "
-              "len=%u, sizeof(sk_buff)=%Zd\n",
-              skb->truesize, skb->len, sizeof(struct sk_buff));
-}
-EXPORT_SYMBOL(skb_truesize_bug);
-
 /*     Allocate a new skbuff. We do this ourselves so we can fill in a few
  *     'private' fields and also do memory statistics to find all the
  *     [BEEP] leaks.
index 6f2e1337975de8e09b079339f2c2819caddfa8ea..6e4f14d1ef818a3844d40e51425e5792effcf7d2 100644 (file)
@@ -1137,7 +1137,6 @@ void sock_rfree(struct sk_buff *skb)
 {
        struct sock *sk = skb->sk;
 
-       skb_truesize_check(skb);
        atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
        sk_mem_uncharge(skb->sk, skb->truesize);
 }
index 6bb2635b5dedda5201b0791a58b6a9f76f94ea6f..7bc992976d29bd18b70dd39544791d66f4351901 100644 (file)
@@ -3,11 +3,16 @@
  *
  * This is an implementation of the CIPSO 2.2 protocol as specified in
  * draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in
- * FIPS-188, copies of both documents can be found in the Documentation
- * directory.  While CIPSO never became a full IETF RFC standard many vendors
+ * FIPS-188.  While CIPSO never became a full IETF RFC standard many vendors
  * have chosen to adopt the protocol and over the years it has become a
  * de-facto standard for labeled networking.
  *
+ * The CIPSO draft specification can be found in the kernel's Documentation
+ * directory as well as the following URL:
+ *   http://netlabel.sourceforge.net/files/draft-ietf-cipso-ipsecurity-01.txt
+ * The FIPS-188 specification can be found at the following URL:
+ *   http://www.itl.nist.gov/fipspubs/fip188.htm
+ *
  * Author: Paul Moore <paul.moore@hp.com>
  *
  */
index dda42f0bd7a3b986d23be16b6f44c87333af0844..da2c3b8794f2b39d3c5e4948b08cd78167f5ae2e 100644 (file)
@@ -2023,7 +2023,6 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
                last_lost = tp->snd_una;
        }
 
-       /* First pass: retransmit lost packets. */
        tcp_for_write_queue_from(skb, sk) {
                __u8 sacked = TCP_SKB_CB(skb)->sacked;
 
index b0246307aac497ae36b8266180b48a244c9c374d..12caa822a232eeddc0fc97606fc5002a86a4daf7 100644 (file)
@@ -51,7 +51,7 @@ my %pidctr;
 
 while (<>) {
        my $line = $_;
-       if ($line =~ /([0-9\.]+)\] calling  ([a-zA-Z0-9\_]+)\+/) {
+       if ($line =~ /([0-9\.]+)\] calling  ([a-zA-Z0-9\_\.]+)\+/) {
                my $func = $2;
                if ($done == 0) {
                        $start{$func} = $1;
@@ -87,7 +87,7 @@ while (<>) {
                $count = $count + 1;
        }
 
-       if ($line =~ /([0-9\.]+)\] initcall ([a-zA-Z0-9\_]+)\+.*returned/) {
+       if ($line =~ /([0-9\.]+)\] initcall ([a-zA-Z0-9\_\.]+)\+.*returned/) {
                if ($done == 0) {
                        $end{$2} = $1;
                        $maxtime = $1;
index d40449cafa84a44dac9f21c54364913c777ffc6d..528492bcba5bf73e8f809490c9d6d8c8ea821ec8 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/bin/perl
 
 use File::Basename;
 
@@ -29,27 +29,151 @@ my $filename = $vmlinux_name;
 my $target = "0";
 my $function;
 my $module = "";
-my $func_offset;
+my $func_offset = 0;
 my $vmaoffset = 0;
 
+my %regs;
+
+
+sub parse_x86_regs
+{
+       my ($line) = @_;
+       if ($line =~ /EAX: ([0-9a-f]+) EBX: ([0-9a-f]+) ECX: ([0-9a-f]+) EDX: ([0-9a-f]+)/) {
+               $regs{"%eax"} = $1;
+               $regs{"%ebx"} = $2;
+               $regs{"%ecx"} = $3;
+               $regs{"%edx"} = $4;
+       }
+       if ($line =~ /ESI: ([0-9a-f]+) EDI: ([0-9a-f]+) EBP: ([0-9a-f]+) ESP: ([0-9a-f]+)/) {
+               $regs{"%esi"} = $1;
+               $regs{"%edi"} = $2;
+               $regs{"%esp"} = $4;
+       }
+       if ($line =~ /RAX: ([0-9a-f]+) RBX: ([0-9a-f]+) RCX: ([0-9a-f]+)/) {
+               $regs{"%eax"} = $1;
+               $regs{"%ebx"} = $2;
+               $regs{"%ecx"} = $3;
+       }
+       if ($line =~ /RDX: ([0-9a-f]+) RSI: ([0-9a-f]+) RDI: ([0-9a-f]+)/) {
+               $regs{"%edx"} = $1;
+               $regs{"%esi"} = $2;
+               $regs{"%edi"} = $3;
+       }
+       if ($line =~ /RBP: ([0-9a-f]+) R08: ([0-9a-f]+) R09: ([0-9a-f]+)/) {
+               $regs{"%r08"} = $2;
+               $regs{"%r09"} = $3;
+       }
+       if ($line =~ /R10: ([0-9a-f]+) R11: ([0-9a-f]+) R12: ([0-9a-f]+)/) {
+               $regs{"%r10"} = $1;
+               $regs{"%r11"} = $2;
+               $regs{"%r12"} = $3;
+       }
+       if ($line =~ /R13: ([0-9a-f]+) R14: ([0-9a-f]+) R15: ([0-9a-f]+)/) {
+               $regs{"%r13"} = $1;
+               $regs{"%r14"} = $2;
+               $regs{"%r15"} = $3;
+       }
+}
+
+sub reg_name
+{
+       my ($reg) = @_;
+       $reg =~ s/r(.)x/e\1x/;
+       $reg =~ s/r(.)i/e\1i/;
+       $reg =~ s/r(.)p/e\1p/;
+       return $reg;
+}
+
+sub process_x86_regs
+{
+       my ($line, $cntr) = @_;
+       my $str = "";
+       if (length($line) < 40) {
+               return ""; # not an asm istruction
+       }
+
+       # find the arguments to the instruction
+       if ($line =~ /([0-9a-zA-Z\,\%\(\)\-\+]+)$/) {
+               $lastword = $1;
+       } else {
+               return "";
+       }
+
+       # we need to find the registers that get clobbered,
+       # since their value is no longer relevant for previous
+       # instructions in the stream.
+
+       $clobber = $lastword;
+       # first, remove all memory operands, they're read only
+       $clobber =~ s/\([a-z0-9\%\,]+\)//g;
+       # then, remove everything before the comma, thats the read part
+       $clobber =~ s/.*\,//g;
+
+       # if this is the instruction that faulted, we haven't actually done
+       # the write yet... nothing is clobbered.
+       if ($cntr == 0) {
+               $clobber = "";
+       }
+
+       foreach $reg (keys(%regs)) {
+               my $clobberprime = reg_name($clobber);
+               my $lastwordprime = reg_name($lastword);
+               my $val = $regs{$reg};
+               if ($val =~ /^[0]+$/) {
+                       $val = "0";
+               } else {
+                       $val =~ s/^0*//;
+               }
+
+               # first check if we're clobbering this register; if we do
+               # we print it with a =>, and then delete its value
+               if ($clobber =~ /$reg/ || $clobberprime =~ /$reg/) {
+                       if (length($val) > 0) {
+                               $str = $str . " $reg => $val ";
+                       }
+                       $regs{$reg} = "";
+                       $val = "";
+               }
+               # now check if we're reading this register
+               if ($lastword =~ /$reg/ || $lastwordprime =~ /$reg/) {
+                       if (length($val) > 0) {
+                               $str = $str . " $reg = $val ";
+                       }
+               }
+       }
+       return $str;
+}
+
+# parse the oops
 while (<STDIN>) {
        my $line = $_;
        if ($line =~ /EIP: 0060:\[\<([a-z0-9]+)\>\]/) {
                $target = $1;
        }
+       if ($line =~ /RIP: 0010:\[\<([a-z0-9]+)\>\]/) {
+               $target = $1;
+       }
        if ($line =~ /EIP is at ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]/) {
                $function = $1;
                $func_offset = $2;
        }
+       if ($line =~ /RIP: 0010:\[\<[0-9a-f]+\>\]  \[\<[0-9a-f]+\>\] ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]/) {
+               $function = $1;
+               $func_offset = $2;
+       }
 
        # check if it's a module
        if ($line =~ /EIP is at ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]+\W\[([a-zA-Z0-9\_\-]+)\]/) {
                $module = $3;
        }
+       if ($line =~ /RIP: 0010:\[\<[0-9a-f]+\>\]  \[\<[0-9a-f]+\>\] ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]+\W\[([a-zA-Z0-9\_\-]+)\]/) {
+               $module = $3;
+       }
+       parse_x86_regs($line);
 }
 
 my $decodestart = hex($target) - hex($func_offset);
-my $decodestop = $decodestart + 8192;
+my $decodestop = hex($target) + 8192;
 if ($target eq "0") {
        print "No oops found!\n";
        print "Usage: \n";
@@ -84,6 +208,7 @@ my $counter = 0;
 my $state   = 0;
 my $center  = 0;
 my @lines;
+my @reglines;
 
 sub InRange {
        my ($address, $target) = @_;
@@ -188,16 +313,36 @@ while ($finish < $counter) {
 
 my $i;
 
-my $fulltext = "";
+
+# start annotating the registers in the asm.
+# this goes from the oopsing point back, so that the annotator
+# can track (opportunistically) which registers got written and
+# whos value no longer is relevant.
+
+$i = $center;
+while ($i >= $start) {
+       $reglines[$i] = process_x86_regs($lines[$i], $center - $i);
+       $i = $i - 1;
+}
+
 $i = $start;
 while ($i < $finish) {
+       my $line;
        if ($i == $center) {
-               $fulltext = $fulltext . "*$lines[$i]     <----- faulting instruction\n";
+               $line =  "*$lines[$i] ";
        } else {
-               $fulltext = $fulltext .  " $lines[$i]\n";
+               $line =  " $lines[$i] ";
+       }
+       print $line;
+       if (defined($reglines[$i]) && length($reglines[$i]) > 0) {
+               my $c = 60 - length($line);
+               while ($c > 0) { print " "; $c = $c - 1; };
+               print "| $reglines[$i]";
        }
+       if ($i == $center) {
+               print "<--- faulting instruction";
+       }
+       print "\n";
        $i = $i +1;
 }
 
-print $fulltext;
-
index 491b8b1b6abf326cd1e018c813d14fbbd0402e0b..4eea60b1693e1173960f34e7c73927f5fe61fccb 100644 (file)
@@ -210,6 +210,7 @@ static void do_usb_table(void *symval, unsigned long size,
 static int do_hid_entry(const char *filename,
                             struct hid_device_id *id, char *alias)
 {
+       id->bus = TO_NATIVE(id->bus);
        id->vendor = TO_NATIVE(id->vendor);
        id->product = TO_NATIVE(id->product);
 
index 2500886fb90aa0273743cc67ba40da48c6b4fa5c..ee448cdc6a2b3cd47ca22fd94fd0995d5985f9ae 100755 (executable)
@@ -86,6 +86,14 @@ echo "%endif"
 echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE"
 
 echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$KERNELRELEASE"
+
+echo "%ifnarch ppc64"
+echo 'cp vmlinux vmlinux.orig'
+echo 'bzip2 -9 vmlinux'
+echo 'mv vmlinux.bz2 $RPM_BUILD_ROOT'"/boot/vmlinux-$KERNELRELEASE.bz2"
+echo 'mv vmlinux.orig vmlinux'
+echo "%endif"
+
 echo ""
 echo "%clean"
 echo '#echo -rf $RPM_BUILD_ROOT'
index f6946cf99ce1bd0a06f9835157f39d4b2b80e971..f1c4b35bc32428b030f053d46010f21b6812c76f 100755 (executable)
@@ -58,14 +58,7 @@ fi
 # Check for svn and a svn repo.
 if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then
        rev=`echo $rev | awk '{print $NF}'`
-       changes=`svn status 2>/dev/null | grep '^[AMD]' | wc -l`
-
-       # Are there uncommitted changes?
-       if [ $changes != 0 ]; then
-               printf -- '-svn%s%s' "$rev" -dirty
-       else
-               printf -- '-svn%s' "$rev"
-       fi
+       printf -- '-svn%s' "$rev"
 
        # All done with svn
        exit
index fdbe78bb5e2b6ad8359aeabb26b0fcf98af44957..5bd8b1003d446b1f4e80dd7e9a788685263a3a6e 100755 (executable)
@@ -76,7 +76,10 @@ all_sources()
 
 all_kconfigs()
 {
-       find_sources $ALLSOURCE_ARCHS 'Kconfig*'
+       for arch in $ALLSOURCE_ARCHS; do
+               find_sources $arch 'Kconfig*'
+       done
+       find_other_sources 'Kconfig*'
 }
 
 all_defconfigs()
@@ -99,7 +102,8 @@ exuberant()
        -I ____cacheline_internodealigned_in_smp                \
        -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL                      \
        --extra=+f --c-kinds=+px                                \
-       --regex-asm='/^ENTRY\(([^)]*)\).*/\1/'
+       --regex-asm='/^ENTRY\(([^)]*)\).*/\1/'                  \
+       --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/'
 
        all_kconfigs | xargs $1 -a                              \
        --langdef=kconfig --language-force=kconfig              \
@@ -117,7 +121,9 @@ exuberant()
 
 emacs()
 {
-       all_sources | xargs $1 -a
+       all_sources | xargs $1 -a                               \
+       --regex='/^ENTRY(\([^)]*\)).*/\1/'                      \
+       --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/'
 
        all_kconfigs | xargs $1 -a                              \
        --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/'
index f58701a7b728619a5a50e3bc74981baa23ab60cf..3f4b26647386f58d5932e8e1b78f0e57f8752bf6 100644 (file)
@@ -490,8 +490,10 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
                lock_sock(sk);
                rc = netlbl_sock_getattr(sk, &secattr);
                release_sock(sk);
-               if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
+               if (rc == 0)
                        rc = -EACCES;
+               else if (rc == -ENOMSG)
+                       rc = 0;
                netlbl_secattr_destroy(&secattr);
        }
 
index dd4a12dc09aa44f4c50c5b60f2cf5584c5635589..077a85262c1c2592c8323b6f249fc645aaf5ecc7 100644 (file)
@@ -47,7 +47,7 @@ static int snd_jack_dev_register(struct snd_device *device)
        int err;
 
        snprintf(jack->name, sizeof(jack->name), "%s %s",
-                card->longname, jack->id);
+                card->shortname, jack->id);
        jack->input_dev->name = jack->name;
 
        /* Default to the sound card device. */
index 57d9f154c88b96ad5df87893f70e5690449c1d31..38931f2f6967e0f1f11c0e0296bd398e1770d538 100644 (file)
@@ -847,23 +847,23 @@ static int __init AtaIrqInit(void)
           of events. So all we need to keep the music playing is
           to provide the sound hardware with new data upon
           an interrupt from timer A. */
-       mfp.tim_ct_a = 0;       /* ++roman: Stop timer before programming! */
-       mfp.tim_dt_a = 1;       /* Cause interrupt after first event. */
-       mfp.tim_ct_a = 8;       /* Turn on event counting. */
+       st_mfp.tim_ct_a = 0;    /* ++roman: Stop timer before programming! */
+       st_mfp.tim_dt_a = 1;    /* Cause interrupt after first event. */
+       st_mfp.tim_ct_a = 8;    /* Turn on event counting. */
        /* Register interrupt handler. */
        if (request_irq(IRQ_MFP_TIMA, AtaInterrupt, IRQ_TYPE_SLOW, "DMA sound",
                        AtaInterrupt))
                return 0;
-       mfp.int_en_a |= 0x20;   /* Turn interrupt on. */
-       mfp.int_mk_a |= 0x20;
+       st_mfp.int_en_a |= 0x20;        /* Turn interrupt on. */
+       st_mfp.int_mk_a |= 0x20;
        return 1;
 }
 
 #ifdef MODULE
 static void AtaIrqCleanUp(void)
 {
-       mfp.tim_ct_a = 0;       /* stop timer */
-       mfp.int_en_a &= ~0x20;  /* turn interrupt off */
+       st_mfp.tim_ct_a = 0;            /* stop timer */
+       st_mfp.int_en_a &= ~0x20;       /* turn interrupt off */
        free_irq(IRQ_MFP_TIMA, AtaInterrupt);
 }
 #endif /* MODULE */
@@ -1599,7 +1599,7 @@ static int __init dmasound_atari_init(void)
                is_falcon = 0;
            } else
                return -ENODEV;
-           if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0)
+           if ((st_mfp.int_en_a & st_mfp.int_mk_a & 0x20) == 0)
                return dmasound_init();
            else {
                printk("DMA sound driver: Timer A interrupt already in use\n");
index 11e791b965f6a772588ac7dff64437b3ec836e70..c8d9178f47e59bf327b17433017d24460620a5e5 100644 (file)
@@ -1947,16 +1947,13 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
        return 0;
 }
 
-static int azx_resume_early(struct pci_dev *pci)
-{
-       return pci_restore_state(pci);
-}
-
 static int azx_resume(struct pci_dev *pci)
 {
        struct snd_card *card = pci_get_drvdata(pci);
        struct azx *chip = card->private_data;
 
+       pci_set_power_state(pci, PCI_D0);
+       pci_restore_state(pci);
        if (pci_enable_device(pci) < 0) {
                printk(KERN_ERR "hda-intel: pci_enable_device failed, "
                       "disabling device\n");
@@ -2468,7 +2465,6 @@ static struct pci_driver driver = {
        .remove = __devexit_p(azx_remove),
 #ifdef CONFIG_PM
        .suspend = azx_suspend,
-       .resume_early = azx_resume_early,
        .resume = azx_resume,
 #endif
 };
index 18c7c91786bc3d5ff40d615b4a7adc49b13bbedc..6c870c12a1777f887076166b4009d7d18b6cd315 100644 (file)
@@ -26,7 +26,7 @@
  * SPI 0 -> 1st PCM1796 (front)
  * SPI 1 -> 2nd PCM1796 (surround)
  * SPI 2 -> 3rd PCM1796 (center/LFE)
- * SPI 4 -> 4th PCM1796 (back) and EEPROM self-destruct (do not use!)
+ * SPI 4 -> 4th PCM1796 (back)
  *
  * GPIO 2 -> M0 of CS5381
  * GPIO 3 -> M1 of CS5381
@@ -207,12 +207,6 @@ static void xonar_gpio_changed(struct oxygen *chip);
 static inline void pcm1796_write_spi(struct oxygen *chip, unsigned int codec,
                                     u8 reg, u8 value)
 {
-       /*
-        * We don't want to do writes on SPI 4 because the EEPROM, which shares
-        * the same pin, might get confused and broken.  We'd better take care
-        * that the driver works with the default register values ...
-        */
-#if 0
        /* maps ALSA channel pair number to SPI output */
        static const u8 codec_map[4] = {
                0, 1, 2, 4
@@ -223,7 +217,6 @@ static inline void pcm1796_write_spi(struct oxygen *chip, unsigned int codec,
                         (codec_map[codec] << OXYGEN_SPI_CODEC_SHIFT) |
                         OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
                         (reg << 8) | value);
-#endif
 }
 
 static inline void pcm1796_write_i2c(struct oxygen *chip, unsigned int codec,
@@ -757,9 +750,6 @@ static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -12700, 100, 0);
 
 static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
 {
-       if (!strncmp(template->name, "Master Playback ", 16))
-               /* disable volume/mute because they would require SPI writes */
-               return 1;
        if (!strncmp(template->name, "CD Capture ", 11))
                /* CD in is actually connected to the video in pin */
                template->private_value ^= AC97_CD ^ AC97_VIDEO;
@@ -850,8 +840,9 @@ static const struct oxygen_model model_xonar_d2 = {
        .dac_volume_min = 0x0f,
        .dac_volume_max = 0xff,
        .misc_flags = OXYGEN_MISC_MIDI,
-       .function_flags = OXYGEN_FUNCTION_SPI,
-       .dac_i2s_format = OXYGEN_I2S_FORMAT_I2S,
+       .function_flags = OXYGEN_FUNCTION_SPI |
+                         OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+       .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
        .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
 };
 
index 2ab83129d9b04b846c7fd15a076a53cdef1d1c21..19e37451c216182ebdc9d800f304a66f5e6bc9e7 100644 (file)
@@ -2524,7 +2524,6 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
                 * build the rate table and bitmap flags
                 */
                int r, idx;
-               unsigned int nonzero_rates = 0;
 
                fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
                if (fp->rate_table == NULL) {
@@ -2532,24 +2531,27 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
                        return -1;
                }
 
-               fp->nr_rates = nr_rates;
-               fp->rate_min = fp->rate_max = combine_triple(&fmt[8]);
+               fp->nr_rates = 0;
+               fp->rate_min = fp->rate_max = 0;
                for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) {
                        unsigned int rate = combine_triple(&fmt[idx]);
+                       if (!rate)
+                               continue;
                        /* C-Media CM6501 mislabels its 96 kHz altsetting */
                        if (rate == 48000 && nr_rates == 1 &&
-                           chip->usb_id == USB_ID(0x0d8c, 0x0201) &&
+                           (chip->usb_id == USB_ID(0x0d8c, 0x0201) ||
+                            chip->usb_id == USB_ID(0x0d8c, 0x0102)) &&
                            fp->altsetting == 5 && fp->maxpacksize == 392)
                                rate = 96000;
-                       fp->rate_table[r] = rate;
-                       nonzero_rates |= rate;
-                       if (rate < fp->rate_min)
+                       fp->rate_table[fp->nr_rates] = rate;
+                       if (!fp->rate_min || rate < fp->rate_min)
                                fp->rate_min = rate;
-                       else if (rate > fp->rate_max)
+                       if (!fp->rate_max || rate > fp->rate_max)
                                fp->rate_max = rate;
                        fp->rates |= snd_pcm_rate_to_rate_bit(rate);
+                       fp->nr_rates++;
                }
-               if (!nonzero_rates) {
+               if (!fp->nr_rates) {
                        hwc_debug("All rates were zero. Skipping format!\n");
                        return -1;
                }
index 320641ab5be7bf972a78603d1c988ef8fae8f08a..26bad373fe65c012de152ac4f753076951390330 100644 (file)
@@ -1625,6 +1625,7 @@ static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi,
        }
 
        ep_info.out_ep = get_endpoint(hostif, 2)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+       ep_info.out_interval = 0;
        ep_info.out_cables = endpoint->out_cables & 0x5555;
        err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]);
        if (err < 0)
index e9693a29d00e2fe5b159632e301ca4cd0d08bb4d..4c403750360082f0e53d3e5459c17d78797ab9e0 100644 (file)
@@ -73,14 +73,13 @@ static int kvm_iommu_map_memslots(struct kvm *kvm)
 {
        int i, r = 0;
 
-       down_read(&kvm->slots_lock);
        for (i = 0; i < kvm->nmemslots; i++) {
                r = kvm_iommu_map_pages(kvm, kvm->memslots[i].base_gfn,
                                        kvm->memslots[i].npages);
                if (r)
                        break;
        }
-       up_read(&kvm->slots_lock);
+
        return r;
 }
 
@@ -190,12 +189,11 @@ static void kvm_iommu_put_pages(struct kvm *kvm,
 static int kvm_iommu_unmap_memslots(struct kvm *kvm)
 {
        int i;
-       down_read(&kvm->slots_lock);
+
        for (i = 0; i < kvm->nmemslots; i++) {
                kvm_iommu_put_pages(kvm, kvm->memslots[i].base_gfn,
                                    kvm->memslots[i].npages);
        }
-       up_read(&kvm->slots_lock);
 
        return 0;
 }
index 3a5a08298aabd1a06c770c2cf4c2b657fae0af14..29a667ce35b0ebc1840f1fcbb6ae3cf3313fa3b8 100644 (file)
@@ -173,7 +173,6 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
                assigned_dev->host_irq_disabled = false;
        }
        mutex_unlock(&assigned_dev->kvm->lock);
-       kvm_put_kvm(assigned_dev->kvm);
 }
 
 static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
@@ -181,8 +180,6 @@ static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
        struct kvm_assigned_dev_kernel *assigned_dev =
                (struct kvm_assigned_dev_kernel *) dev_id;
 
-       kvm_get_kvm(assigned_dev->kvm);
-
        schedule_work(&assigned_dev->interrupt_work);
 
        disable_irq_nosync(irq);
@@ -213,6 +210,7 @@ static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)
        }
 }
 
+/* The function implicit hold kvm->lock mutex due to cancel_work_sync() */
 static void kvm_free_assigned_irq(struct kvm *kvm,
                                  struct kvm_assigned_dev_kernel *assigned_dev)
 {
@@ -228,11 +226,24 @@ static void kvm_free_assigned_irq(struct kvm *kvm,
        if (!assigned_dev->irq_requested_type)
                return;
 
-       if (cancel_work_sync(&assigned_dev->interrupt_work))
-               /* We had pending work. That means we will have to take
-                * care of kvm_put_kvm.
-                */
-               kvm_put_kvm(kvm);
+       /*
+        * In kvm_free_device_irq, cancel_work_sync return true if:
+        * 1. work is scheduled, and then cancelled.
+        * 2. work callback is executed.
+        *
+        * The first one ensured that the irq is disabled and no more events
+        * would happen. But for the second one, the irq may be enabled (e.g.
+        * for MSI). So we disable irq here to prevent further events.
+        *
+        * Notice this maybe result in nested disable if the interrupt type is
+        * INTx, but it's OK for we are going to free it.
+        *
+        * If this function is a part of VM destroy, please ensure that till
+        * now, the kvm state is still legal for probably we also have to wait
+        * interrupt_work done.
+        */
+       disable_irq_nosync(assigned_dev->host_irq);
+       cancel_work_sync(&assigned_dev->interrupt_work);
 
        free_irq(assigned_dev->host_irq, (void *)assigned_dev);
 
@@ -285,8 +296,8 @@ static int assigned_device_update_intx(struct kvm *kvm,
 
        if (irqchip_in_kernel(kvm)) {
                if (!msi2intx &&
-                   adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI) {
-                       free_irq(adev->host_irq, (void *)kvm);
+                   (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI)) {
+                       free_irq(adev->host_irq, (void *)adev);
                        pci_disable_msi(adev->dev);
                }
 
@@ -455,6 +466,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
        struct kvm_assigned_dev_kernel *match;
        struct pci_dev *dev;
 
+       down_read(&kvm->slots_lock);
        mutex_lock(&kvm->lock);
 
        match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
@@ -516,6 +528,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
 
 out:
        mutex_unlock(&kvm->lock);
+       up_read(&kvm->slots_lock);
        return r;
 out_list_del:
        list_del(&match->list);
@@ -527,6 +540,7 @@ out_put:
 out_free:
        kfree(match);
        mutex_unlock(&kvm->lock);
+       up_read(&kvm->slots_lock);
        return r;
 }
 #endif
@@ -789,11 +803,19 @@ static int kvm_mmu_notifier_clear_flush_young(struct mmu_notifier *mn,
        return young;
 }
 
+static void kvm_mmu_notifier_release(struct mmu_notifier *mn,
+                                    struct mm_struct *mm)
+{
+       struct kvm *kvm = mmu_notifier_to_kvm(mn);
+       kvm_arch_flush_shadow(kvm);
+}
+
 static const struct mmu_notifier_ops kvm_mmu_notifier_ops = {
        .invalidate_page        = kvm_mmu_notifier_invalidate_page,
        .invalidate_range_start = kvm_mmu_notifier_invalidate_range_start,
        .invalidate_range_end   = kvm_mmu_notifier_invalidate_range_end,
        .clear_flush_young      = kvm_mmu_notifier_clear_flush_young,
+       .release                = kvm_mmu_notifier_release,
 };
 #endif /* CONFIG_MMU_NOTIFIER && KVM_ARCH_WANT_MMU_NOTIFIER */
 
@@ -883,6 +905,7 @@ static void kvm_destroy_vm(struct kvm *kvm)
 {
        struct mm_struct *mm = kvm->mm;
 
+       kvm_arch_sync_events(kvm);
        spin_lock(&kvm_lock);
        list_del(&kvm->vm_list);
        spin_unlock(&kvm_lock);