]> pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge commit '305b07680f' into orion/master
authorNicolas Pitre <nico@cam.org>
Mon, 16 Mar 2009 01:41:23 +0000 (21:41 -0400)
committerNicolas Pitre <nico@cam.org>
Mon, 16 Mar 2009 01:41:23 +0000 (21:41 -0400)
471 files changed:
Documentation/ABI/testing/sysfs-bus-pci
Documentation/DocBook/Makefile
Documentation/DocBook/device-drivers.tmpl [new file with mode: 0644]
Documentation/DocBook/kernel-api.tmpl
Documentation/cgroups/cpusets.txt
Documentation/driver-model/device.txt
Documentation/dvb/README.flexcop [deleted file]
Documentation/dvb/technisat.txt
Documentation/filesystems/sysfs.txt
Documentation/kernel-parameters.txt
Documentation/scsi/cxgb3i.txt
MAINTAINERS
Makefile
README
arch/arm/kernel/entry-common.S
arch/arm/kernel/fiq.c
arch/arm/kernel/setup.c
arch/arm/mach-at91/pm.c
arch/arm/mach-davinci/board-evm.c
arch/arm/mach-davinci/clock.c
arch/arm/mach-davinci/usb.c
arch/arm/mach-ep93xx/include/mach/platform.h
arch/arm/mach-mx1/devices.c
arch/arm/mach-mx1/mx1ads.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-orion5x/common.c
arch/arm/mach-rpc/riscpc.c
arch/arm/mach-s3c6410/mach-smdk6410.c
arch/arm/mm/abort-ev6.S
arch/arm/mm/copypage-feroceon.c
arch/arm/mm/copypage-v3.c
arch/arm/mm/copypage-v4mc.c
arch/arm/mm/copypage-v4wb.c
arch/arm/mm/copypage-v4wt.c
arch/arm/mm/copypage-xsc3.c
arch/arm/mm/copypage-xscale.c
arch/arm/plat-omap/Makefile
arch/arm/plat-omap/common.c
arch/arm/plat-omap/include/mach/common.h
arch/arm/plat-omap/include/mach/pm.h
arch/arm/plat-s3c64xx/clock.c
arch/arm/plat-s3c64xx/gpiolib.c
arch/arm/plat-s3c64xx/include/plat/irqs.h
arch/arm/plat-s3c64xx/irq-eint.c
arch/arm/plat-s3c64xx/irq.c
arch/arm/plat-s3c64xx/s3c6400-clock.c
arch/arm/tools/mach-types
arch/ia64/Kconfig
arch/ia64/configs/xen_domu_defconfig [new file with mode: 0644]
arch/ia64/include/asm/sn/bte.h
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/unwind.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/mips/Kconfig
arch/mips/alchemy/common/time.c
arch/mips/include/asm/seccomp.h
arch/mips/kernel/irq.c
arch/mips/kernel/linux32.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/syscall.c
arch/mips/mm/cache.c
arch/mn10300/Kconfig
arch/mn10300/unit-asb2305/pci.c
arch/powerpc/include/asm/compat.h
arch/powerpc/include/asm/seccomp.h
arch/powerpc/kernel/align.c
arch/powerpc/lib/copyuser_64.S
arch/powerpc/lib/memcpy_64.S
arch/powerpc/platforms/86xx/gef_sbc610.c
arch/powerpc/sysdev/ppc4xx_pci.c
arch/s390/crypto/aes_s390.c
arch/sh/boards/board-ap325rxa.c
arch/sh/kernel/cpu/sh2a/clock-sh7201.c
arch/sparc/include/asm/compat.h
arch/sparc/include/asm/seccomp.h
arch/sparc/kernel/chmc.c
arch/um/drivers/vde_user.c
arch/x86/Kconfig
arch/x86/include/asm/iomap.h
arch/x86/include/asm/seccomp_32.h
arch/x86/include/asm/seccomp_64.h
arch/x86/kernel/acpi/wakeup_64.S
arch/x86/kernel/apm_32.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/ptrace.c
arch/x86/kernel/time_64.c
arch/x86/kernel/vmiclock_32.c
arch/x86/mach-default/setup.c
arch/x86/mach-voyager/setup.c
arch/x86/mach-voyager/voyager_smp.c
arch/x86/mm/init_64.c
arch/x86/mm/iomap_32.c
arch/x86/mm/kmmio.c
arch/x86/mm/pageattr.c
arch/x86/mm/pat.c
arch/x86/mm/testmmiotrace.c
arch/x86/oprofile/op_model_ppro.c
arch/x86/xen/enlighten.c
block/blk-merge.c
block/genhd.c
crypto/ahash.c
crypto/api.c
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/battery.c
drivers/acpi/ec.c
drivers/ata/pata_amd.c
drivers/ata/pata_it821x.c
drivers/ata/pata_legacy.c
drivers/ata/sata_mv.c
drivers/atm/lanai.c
drivers/base/base.h
drivers/base/dd.c
drivers/base/power/main.c
drivers/base/sys.c
drivers/block/ataflop.c
drivers/block/cciss.c
drivers/block/xen-blkfront.c
drivers/char/scc.h
drivers/char/sx.c
drivers/crypto/ixp4xx_crypto.c
drivers/crypto/padlock-aes.c
drivers/crypto/padlock-sha.c
drivers/dma/iop-adma.c
drivers/dma/mv_xor.c
drivers/gpu/drm/drm_bufs.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/drm_lock.c
drivers/gpu/drm/drm_stub.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/i915_irq.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/i2c/busses/i2c-acorn.c
drivers/i2c/busses/i2c-amd8111.c
drivers/i2c/busses/i2c-ixp2000.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-pxa.c
drivers/i2c/busses/scx200_i2c.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-dev.c
drivers/ide/Kconfig
drivers/ide/amd74xx.c
drivers/ide/atiixp.c
drivers/ide/ide-cd.c
drivers/ide/ide-cd.h
drivers/ide/ide-gd.c
drivers/ide/ide-gd.h
drivers/ide/ide-tape.c
drivers/ide/ide.c
drivers/ide/it821x.c
drivers/ieee1394/dma.h
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ieee1394_transactions.c
drivers/ieee1394/ieee1394_transactions.h
drivers/ieee1394/iso.h
drivers/ieee1394/nodemgr.c
drivers/ieee1394/nodemgr.h
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/bf54x-keys.c
drivers/input/keyboard/corgikbd.c
drivers/input/keyboard/omap-keypad.c
drivers/input/keyboard/spitzkbd.c
drivers/input/mouse/Kconfig
drivers/input/mouse/elantech.c
drivers/input/mouse/pxa930_trkball.c
drivers/input/mouse/synaptics.c
drivers/input/serio/ambakmi.c
drivers/input/serio/gscps2.c
drivers/input/serio/sa1111ps2.c
drivers/input/touchscreen/atmel_tsadcc.c
drivers/input/touchscreen/corgi_ts.c
drivers/input/touchscreen/tsc2007.c
drivers/input/touchscreen/usbtouchscreen.c
drivers/isdn/sc/shmem.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/media/dvb/Kconfig
drivers/media/dvb/Makefile
drivers/media/dvb/b2c2/flexcop-hw-filter.c
drivers/media/dvb/b2c2/flexcop-pci.c
drivers/media/dvb/b2c2/flexcop.c
drivers/media/dvb/firewire/Kconfig [new file with mode: 0644]
drivers/media/dvb/firewire/Makefile [new file with mode: 0644]
drivers/media/dvb/firewire/firedtv-1394.c [new file with mode: 0644]
drivers/media/dvb/firewire/firedtv-avc.c [new file with mode: 0644]
drivers/media/dvb/firewire/firedtv-ci.c [new file with mode: 0644]
drivers/media/dvb/firewire/firedtv-dvb.c [new file with mode: 0644]
drivers/media/dvb/firewire/firedtv-fe.c [new file with mode: 0644]
drivers/media/dvb/firewire/firedtv-rc.c [new file with mode: 0644]
drivers/media/dvb/firewire/firedtv.h [new file with mode: 0644]
drivers/media/video/em28xx/em28xx-audio.c
drivers/media/video/pxa_camera.c
drivers/media/video/sh_mobile_ceu_camera.c
drivers/media/video/uvc/uvc_status.c
drivers/message/fusion/mptbase.c
drivers/misc/hpilo.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mtd/chips/map_rom.c
drivers/mtd/devices/slram.c
drivers/mtd/lpddr/Kconfig
drivers/mtd/maps/Kconfig
drivers/mtd/maps/bfin-async-flash.c
drivers/mtd/maps/ck804xrom.c
drivers/mtd/maps/physmap.c
drivers/mtd/nand/orion_nand.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/arm/Makefile
drivers/net/arm/etherh.c
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/b44.c
drivers/net/cxgb3/cxgb3_main.c
drivers/net/cxgb3/t3_hw.c
drivers/net/forcedeth.c
drivers/net/gianfar.c
drivers/net/hp-plus.c
drivers/net/mv643xx_eth.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/r8169.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/usb/asix.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/usbnet.c
drivers/net/usb/zaurus.c
drivers/net/veth.c
drivers/net/wimax/i2400m/i2400m.h
drivers/net/wireless/ath9k/main.c
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/libertas/ethtool.c
drivers/net/wireless/libertas/if_usb.c
drivers/net/wireless/libertas/main.c
drivers/net/wireless/libertas/persistcfg.c
drivers/net/wireless/libertas/scan.c
drivers/net/wireless/libertas/tx.c
drivers/net/wireless/libertas/wext.c
drivers/net/wireless/orinoco/orinoco.c
drivers/net/wireless/rtl818x/rtl8187_dev.c
drivers/parport/parport_atari.c
drivers/pci/dmar.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/intr_remapping.c
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/portdrv_pci.c
drivers/pci/quirks.c
drivers/platform/x86/fujitsu-laptop.c
drivers/scsi/cxgb3i/cxgb3i.h
drivers/scsi/cxgb3i/cxgb3i_ddp.c
drivers/scsi/cxgb3i/cxgb3i_ddp.h
drivers/scsi/cxgb3i/cxgb3i_init.c
drivers/scsi/cxgb3i/cxgb3i_iscsi.c
drivers/scsi/cxgb3i/cxgb3i_offload.c
drivers/scsi/cxgb3i/cxgb3i_offload.h
drivers/scsi/cxgb3i/cxgb3i_pdu.c
drivers/scsi/cxgb3i/cxgb3i_pdu.h
drivers/scsi/hptiop.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_lib.c
drivers/scsi/scsi_scan.c
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/serial/8250.c
drivers/serial/8250_pci.c
drivers/serial/sh-sci.h
drivers/staging/panel/panel.c
drivers/staging/rtl8187se/Kconfig
drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
drivers/staging/rtl8187se/r8180_core.c
drivers/staging/winbond/wbusb.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/message.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/f_obex.c
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/fsl_usb2_udc.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-mem.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci.h
drivers/usb/musb/davinci.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musb_host.c
drivers/usb/serial/option.c
drivers/usb/storage/unusual_devs.h
drivers/video/atafb.c
drivers/video/aty/aty128fb.c
drivers/video/pxafb.c
drivers/w1/slaves/Kconfig
drivers/w1/slaves/Makefile
drivers/w1/slaves/w1_ds2433.c
drivers/xen/manage.c
fs/Makefile
fs/bio.c
fs/btrfs/btrfs_inode.h
fs/btrfs/ctree.h
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.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/dcache.c
fs/ext4/balloc.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/super.c
fs/jffs2/background.c
fs/jffs2/readinode.c
fs/ocfs2/alloc.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmthread.c
fs/ocfs2/dlm/dlmunlock.c
fs/ocfs2/dlmglue.c
fs/ocfs2/ocfs2.h
fs/ocfs2/super.c
fs/ocfs2/xattr.c
fs/proc/inode.c
fs/proc/page.c
fs/xfs/linux-2.6/xfs_buf.c
include/drm/drmP.h
include/drm/drm_crtc.h
include/drm/drm_crtc_helper.h
include/drm/drm_edid.h
include/linux/Kbuild
include/linux/blkdev.h
include/linux/compiler-gcc.h
include/linux/dcbnl.h
include/linux/device.h
include/linux/i2c-dev.h
include/linux/i2c.h
include/linux/ide.h
include/linux/if_vlan.h
include/linux/intel-iommu.h
include/linux/io-mapping.h
include/linux/netfilter/xt_NFLOG.h
include/linux/pci_ids.h
include/linux/pm.h
include/linux/rcuclassic.h
include/linux/rcupdate.h
include/linux/rcupreempt.h
include/linux/rcutree.h
include/linux/sched.h
include/linux/serial_core.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/spi/spi_bitbang.h
include/linux/user_namespace.h
include/net/netfilter/nf_conntrack_core.h
include/net/sock.h
init/do_mounts.c
init/do_mounts_md.c
init/main.c
kernel/kexec.c
kernel/power/console.c
kernel/power/disk.c
kernel/power/main.c
kernel/power/user.c
kernel/printk.c
kernel/rcuclassic.c
kernel/rcupdate.c
kernel/rcupreempt.c
kernel/rcutree.c
kernel/sched.c
kernel/seccomp.c
kernel/sys.c
kernel/user.c
kernel/user_namespace.c
lib/Kconfig.debug
mm/shmem.c
mm/swapfile.c
mm/util.c
mm/vmalloc.c
mm/vmscan.c
net/8021q/vlan_core.c
net/core/dev.c
net/core/net_namespace.c
net/core/skbuff.c
net/core/sock.c
net/ipv4/cipso_ipv4.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv4/tcp_scalable.c
net/ipv6/inet6_hashtables.c
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
net/netfilter/nfnetlink_log.c
net/netfilter/x_tables.c
net/netfilter/xt_recent.c
net/sched/sch_drr.c
scripts/checkpatch.pl
security/selinux/netlabel.c
sound/core/oss/rate.c
sound/oss/dmasound/dmasound_atari.c
sound/pci/aw2/aw2-alsa.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/hda/hda_hwdep.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/pcxhr/pcxhr.h

index ceddcff4082a0cfc2bdc692148ec455bb9e165f0..e638e15a8895abef445cedccb2df273f1e3ad0e1 100644 (file)
@@ -1,3 +1,46 @@
+What:          /sys/bus/pci/drivers/.../bind
+Date:          December 2003
+Contact:       linux-pci@vger.kernel.org
+Description:
+               Writing a device location to this file will cause
+               the driver to attempt to bind to the device found at
+               this location.  This is useful for overriding default
+               bindings.  The format for the location is: DDDD:BB:DD.F.
+               That is Domain:Bus:Device.Function and is the same as
+               found in /sys/bus/pci/devices/.  For example:
+               # echo 0000:00:19.0 > /sys/bus/pci/drivers/foo/bind
+               (Note: kernels before 2.6.28 may require echo -n).
+
+What:          /sys/bus/pci/drivers/.../unbind
+Date:          December 2003
+Contact:       linux-pci@vger.kernel.org
+Description:
+               Writing a device location to this file will cause the
+               driver to attempt to unbind from the device found at
+               this location.  This may be useful when overriding default
+               bindings.  The format for the location is: DDDD:BB:DD.F.
+               That is Domain:Bus:Device.Function and is the same as
+               found in /sys/bus/pci/devices/. For example:
+               # echo 0000:00:19.0 > /sys/bus/pci/drivers/foo/unbind
+               (Note: kernels before 2.6.28 may require echo -n).
+
+What:          /sys/bus/pci/drivers/.../new_id
+Date:          December 2003
+Contact:       linux-pci@vger.kernel.org
+Description:
+               Writing a device ID to this file will attempt to
+               dynamically add a new device ID to a PCI device driver.
+               This may allow the driver to support more hardware than
+               was included in the driver's static device ID support
+               table at compile time.  The format for the device ID is:
+               VVVV DDDD SVVV SDDD CCCC MMMM PPPP.  That is Vendor ID,
+               Device ID, Subsystem Vendor ID, Subsystem Device ID,
+               Class, Class Mask, and Private Driver Data.  The Vendor ID
+               and Device ID fields are required, the rest are optional.
+               Upon successfully adding an ID, the driver will probe
+               for the device and attempt to bind to it.  For example:
+               # echo "8086 10f5" > /sys/bus/pci/drivers/foo/new_id
+
 What:          /sys/bus/pci/devices/.../vpd
 Date:          February 2008
 Contact:       Ben Hutchings <bhutchings@solarflare.com>
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 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
diff --git a/Documentation/dvb/README.flexcop b/Documentation/dvb/README.flexcop
deleted file mode 100644 (file)
index 5515469..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-This README escorted the skystar2-driver rewriting procedure. It describes the
-state of the new flexcop-driver set and some internals are written down here
-too.
-
-This document hopefully describes things about the flexcop and its
-device-offsprings. Goal was to write an easy-to-write and easy-to-read set of
-drivers based on the skystar2.c and other information.
-
-Remark: flexcop-pci.c was a copy of skystar2.c, but every line has been
-touched and rewritten.
-
-History & News
-==============
-  2005-04-01 - correct USB ISOC transfers (thanks to Vadim Catana)
-
-
-
-
-General coding processing
-=========================
-
-We should proceed as follows (as long as no one complains):
-
-0) Think before start writing code!
-
-1) rewriting the skystar2.c with the help of the flexcop register descriptions
-and splitting up the files to a pci-bus-part and a flexcop-part.
-The new driver will be called b2c2-flexcop-pci.ko/b2c2-flexcop-usb.ko for the
-device-specific part and b2c2-flexcop.ko for the common flexcop-functions.
-
-2) Search for errors in the leftover of flexcop-pci.c (compare with pluto2.c
-and other pci drivers)
-
-3) make some beautification (see 'Improvements when rewriting (refactoring) is
-done')
-
-4) Testing the new driver and maybe substitute the skystar2.c with it, to reach
-a wider tester audience.
-
-5) creating an usb-bus-part using the already written flexcop code for the pci
-card.
-
-Idea: create a kernel-object for the flexcop and export all important
-functions. This option saves kernel-memory, but maybe a lot of functions have
-to be exported to kernel namespace.
-
-
-Current situation
-=================
-
-0) Done :)
-1) Done (some minor issues left)
-2) Done
-3) Not ready yet, more information is necessary
-4) next to be done (see the table below)
-5) USB driver is working (yes, there are some minor issues)
-
-What seems to be ready?
------------------------
-
-1) Rewriting
-1a) i2c is cut off from the flexcop-pci.c and seems to work
-1b) moved tuner and demod stuff from flexcop-pci.c to flexcop-tuner-fe.c
-1c) moved lnb and diseqc stuff from flexcop-pci.c to flexcop-tuner-fe.c
-1e) eeprom (reading MAC address)
-1d) sram (no dynamic sll size detection (commented out) (using default as JJ told me))
-1f) misc. register accesses for reading parameters (e.g. resetting, revision)
-1g) pid/mac filter (flexcop-hw-filter.c)
-1i) dvb-stuff initialization in flexcop.c (done)
-1h) dma stuff (now just using the size-irq, instead of all-together, to be done)
-1j) remove flexcop initialization from flexcop-pci.c completely (done)
-1l) use a well working dma IRQ method (done, see 'Known bugs and problems and TODO')
-1k) cleanup flexcop-files (remove unused EXPORT_SYMBOLs, make static from
-non-static where possible, moved code to proper places)
-
-2) Search for errors in the leftover of flexcop-pci.c (partially done)
-5a) add MAC address reading
-5c) feeding of ISOC data to the software demux (format of the isochronous data
-and speed optimization, no real error) (thanks to Vadim Catana)
-
-What to do in the near future?
---------------------------------------
-(no special order here)
-
-5) USB driver
-5b) optimize isoc-transfer (submitting/killing isoc URBs when transfer is starting)
-
-Testing changes
----------------
-
-O             = item is working
-P             = item is partially working
-X             = item is not working
-N             = item does not apply here
-<empty field> = item need to be examined
-
-       | PCI                               | USB
-item   | mt352 | nxt2002 | stv0299 | mt312 | mt352 | nxt2002 | stv0299 | mt312
--------+-------+---------+---------+-------+-------+---------+---------+-------
-1a)    | O     |         |         |       | N     | N       | N       | N
-1b)    | O     |         |         |       |       |         | O       |
-1c)    | N     | N       |         |       | N     | N       | O       |
-1d)    |                 O                 |                 O
-1e)    |                 O                 |                 O
-1f)    |                                   P
-1g)    |                                   O
-1h)    |                 P                 |
-1i)    |                 O                 |                 N
-1j)    |                 O                 |                 N
-1l)    |                 O                 |                 N
-2)     |                 O                 |                 N
-5a)    |                 N                 |                 O
-5b)*   |                 N                 |
-5c)    |                 N                 |                 O
-
-* - not done yet
-
-Known bugs and problems and TODO
---------------------------------
-
-1g/h/l) when pid filtering is enabled on the pci card
-
-DMA usage currently:
-  The DMA is splitted in 2 equal-sized subbuffers. The Flexcop writes to first
-  address and triggers an IRQ when it's full and starts writing to the second
-  address. When the second address is full, the IRQ is triggered again, and
-  the flexcop writes to first address again, and so on.
-  The buffersize of each address is currently 640*188 bytes.
-
-  Problem is, when using hw-pid-filtering and doing some low-bandwidth
-  operation (like scanning) the buffers won't be filled enough to trigger
-  the IRQ. That's why:
-
-  When PID filtering is activated, the timer IRQ is used. Every 1.97 ms the IRQ
-  is triggered.  Is the current write address of DMA1 different to the one
-  during the last IRQ, then the data is passed to the demuxer.
-
-  There is an additional DMA-IRQ-method: packet count IRQ. This isn't
-  implemented correctly yet.
-
-  The solution is to disable HW PID filtering, but I don't know how the DVB
-  API software demux behaves on slow systems with 45MBit/s TS.
-
-Solved bugs :)
---------------
-1g) pid-filtering (somehow pid index 4 and 5 (EMM_PID and ECM_PID) aren't
-working)
-SOLUTION: also index 0 was affected, because net_translation is done for
-these indexes by default
-
-5b) isochronous transfer does only work in the first attempt (for the Sky2PC
-USB, Air2PC is working) SOLUTION: the flexcop was going asleep and never really
-woke up again (don't know if this need fixes, see
-flexcop-fe-tuner.c:flexcop_sleep)
-
-NEWS: when the driver is loaded and unloaded and loaded again (w/o doing
-anything in the while the driver is loaded the first time), no transfers take
-place anymore.
-
-Improvements when rewriting (refactoring) is done
-=================================================
-
-- split sleeping of the flexcop (misc_204.ACPI3_sig = 1;) from lnb_control
-  (enable sleeping for other demods than dvb-s)
-- add support for CableStar (stv0297 Microtune 203x/ALPS) (almost done, incompatibilities with the Nexus-CA)
-
-Debugging
----------
-- add verbose debugging to skystar2.c (dump the reg_dw_data) and compare it
-  with this flexcop, this is important, because i2c is now using the
-  flexcop_ibi_value union from flexcop-reg.h (do you have a better idea for
-  that, please tell us so).
-
-Everything which is identical in the following table, can be put into a common
-flexcop-module.
-
-                 PCI                  USB
--------------------------------------------------------------------------------
-Different:
-Register access:  accessing IO memory  USB control message
-I2C bus:          I2C bus of the FC    USB control message
-Data transfer:    DMA                  isochronous transfer
-EEPROM transfer:  through i2c bus      not clear yet
-
-Identical:
-Streaming:                 accessing registers
-PID Filtering:             accessing registers
-Sram destinations:         accessing registers
-Tuner/Demod:                     I2C bus
-DVB-stuff:            can be written for common use
-
-Acknowledgements (just for the rewriting part)
-================
-
-Bjarne Steinsbo thought a lot in the first place of the pci part for this code
-sharing idea.
-
-Andreas Oberritter for providing a recent PCI initialization template
-(pluto2.c).
-
-Boleslaw Ciesielski for pointing out a problem with firmware loader.
-
-Vadim Catana for correcting the USB transfer.
-
-comments, critics and ideas to linux-dvb@linuxtv.org.
index cdf6ee4b2da1804e31d32a4bb77d86b12b588228..3f435ffb289c71d297d8e25bdffaa1d37d0ab2f8 100644 (file)
@@ -1,5 +1,5 @@
-How to set up the Technisat devices
-===================================
+How to set up the Technisat/B2C2 Flexcop devices
+================================================
 
 1) Find out what device you have
 ================================
@@ -16,54 +16,60 @@ DVB: registering frontend 0 (Conexant CX24123/CX24109)...
 
 If the Technisat is the only TV device in your box get rid of unnecessary modules and check this one:
 "Multimedia devices" => "Customise analog and hybrid tuner modules to build"
-In this directory uncheck every driver which is activated there.
+In this directory uncheck every driver which is activated there (except "Simple tuner support" for case 9 only).
 
 Then please activate:
 2a) Main module part:
 
 a.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters"
-b.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" => "Technisat/B2C2 Air/Sky/Cable2PC PCI" in case of a PCI card OR
+b.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" => "Technisat/B2C2 Air/Sky/Cable2PC PCI" in case of a PCI card
+OR
 c.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" => "Technisat/B2C2 Air/Sky/Cable2PC USB" in case of an USB 1.1 adapter
 d.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" => "Enable debug for the B2C2 FlexCop drivers"
 Notice: d.) is helpful for troubleshooting
 
 2b) Frontend module part:
 
-1.) Revision 2.3:
+1.) SkyStar DVB-S Revision 2.3:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "Zarlink VP310/MT312/ZL10313 based"
 
-2.) Revision 2.6:
+2.) SkyStar DVB-S Revision 2.6:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "ST STV0299 based"
 
-3.) Revision 2.7:
+3.) SkyStar DVB-S Revision 2.7:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "Samsung S5H1420 based"
 c.)"Multimedia devices" => "Customise DVB frontends" => "Integrant ITD1000 Zero IF tuner for DVB-S/DSS"
 d.)"Multimedia devices" => "Customise DVB frontends" => "ISL6421 SEC controller"
 
-4.) Revision 2.8:
+4.) SkyStar DVB-S Revision 2.8:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "Conexant CX24113/CX24128 tuner for DVB-S/DSS"
 c.)"Multimedia devices" => "Customise DVB frontends" => "Conexant CX24123 based"
 d.)"Multimedia devices" => "Customise DVB frontends" => "ISL6421 SEC controller"
 
-5.) DVB-T card:
+5.) AirStar DVB-T card:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "Zarlink MT352 based"
 
-6.) DVB-C card:
+6.) CableStar DVB-C card:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "ST STV0297 based"
 
-7.) ATSC card 1st generation:
+7.) AirStar ATSC card 1st generation:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "Broadcom BCM3510"
 
-8.) ATSC card 2nd generation:
+8.) AirStar ATSC card 2nd generation:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "NxtWave Communications NXT2002/NXT2004 based"
-c.)"Multimedia devices" => "Customise DVB frontends" => "LG Electronics LGDT3302/LGDT3303 based"
+c.)"Multimedia devices" => "Customise DVB frontends" => "Generic I2C PLL based tuners"
 
-Author: Uwe Bugla <uwe.bugla@gmx.de> December 2008
+9.) AirStar ATSC card 3rd generation:
+a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
+b.)"Multimedia devices" => "Customise DVB frontends" => "LG Electronics LGDT3302/LGDT3303 based"
+c.)"Multimedia devices" => "Customise analog and hybrid tuner modules to build" => "Simple tuner support"
+
+Author: Uwe Bugla <uwe.bugla@gmx.de> February 2009
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:
index b182626739ea7e7fb5c4ca98ce02b8bc76b21608..54f21a5c262b02ef6cb4718f72b8357693197cf3 100644 (file)
@@ -114,7 +114,7 @@ In addition, the following text indicates that the option:
 Parameters denoted with BOOT are actually interpreted by the boot
 loader, and have no meaning to the kernel directly.
 Do not modify the syntax of boot loader parameters without extreme
-need or coordination with <Documentation/x86/i386/boot.txt>.
+need or coordination with <Documentation/x86/boot.txt>.
 
 There are also arch-specific kernel-parameters not documented here.
 See for example <Documentation/x86/x86_64/boot-options.txt>.
@@ -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
@@ -868,8 +868,10 @@ and is between 256 and 4096 characters. It is defined in the file
        icn=            [HW,ISDN]
                        Format: <io>[,<membase>[,<icn_id>[,<icn_id2>]]]
 
-       ide=            [HW] (E)IDE subsystem
-                       Format: ide=nodma or ide=doubler
+       ide-core.nodma= [HW] (E)IDE subsystem
+                       Format: =0.0 to prevent dma on hda, =0.1 hdb =1.0 hdc
+                       .vlb_clock .pci_clock .noflush .noprobe .nowerr .cdrom
+                       .chs .ignore_cable are additional options
                        See Documentation/ide/ide.txt.
 
        idebus=         [HW] (E)IDE subsystem - VLB/PCI bus speed
@@ -2449,7 +2451,7 @@ and is between 256 and 4096 characters. It is defined in the file
                        See Documentation/fb/modedb.txt.
 
        vga=            [BOOT,X86-32] Select a particular video mode
-                       See Documentation/x86/i386/boot.txt and
+                       See Documentation/x86/boot.txt and
                        Documentation/svga.txt.
                        Use vga=ask for menu.
                        This is actually a boot loader parameter; the value is
index 8141fa01978e0d7392390e68009c0b612ba0aa6f..7ac8032ee9b2a5f082554386c46df084fe993a5b 100644 (file)
@@ -4,7 +4,7 @@ Introduction
 ============
 
 The Chelsio T3 ASIC based Adapters (S310, S320, S302, S304, Mezz cards, etc.
-series of products) supports iSCSI acceleration and iSCSI Direct Data Placement
+series of products) support iSCSI acceleration and iSCSI Direct Data Placement
 (DDP) where the hardware handles the expensive byte touching operations, such
 as CRC computation and verification, and direct DMA to the final host memory
 destination:
@@ -31,9 +31,9 @@ destination:
          the TCP segments onto the wire. It handles TCP retransmission if
          needed.
 
-         On receving, S3 h/w recovers the iSCSI PDU by reassembling TCP
+         On receiving, S3 h/w recovers the iSCSI PDU by reassembling TCP
          segments, separating the header and data, calculating and verifying
-         the digests, then forwards the header to the host. The payload data,
+         the digests, then forwarding the header to the host. The payload data,
          if possible, will be directly placed into the pre-posted host DDP
          buffer. Otherwise, the payload data will be sent to the host too.
 
@@ -68,9 +68,8 @@ The following steps need to be taken to accelerates the open-iscsi initiator:
        sure the ip address is unique in the network.
 
 3. edit /etc/iscsi/iscsid.conf
-   The default setting for MaxRecvDataSegmentLength (131072) is too big,
-   replace "node.conn[0].iscsi.MaxRecvDataSegmentLength" to be a value no
-   bigger than 15360 (for example 8192):
+   The default setting for MaxRecvDataSegmentLength (131072) is too big;
+   replace with a value no bigger than 15360 (for example 8192):
 
        node.conn[0].iscsi.MaxRecvDataSegmentLength = 8192
 
index 06e03913d2d31e69f458792bdc74fdf3d2e4d840..1c2ca1dc66f2006765dba54bb05edf8a5b57d258 100644 (file)
@@ -2464,7 +2464,7 @@ S:        Maintained
 
 ISDN SUBSYSTEM
 P:     Karsten Keil
-M:     kkeil@suse.de
+M:     isdn@linux-pingi.de
 L:     isdn4linux@listserv.isdn4linux.de (subscribers-only)
 W:     http://www.isdn4linux.de
 T:     git kernel.org:/pub/scm/linux/kernel/kkeil/isdn-2.6.git
@@ -3334,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
index 59cf6dacec072b76ac4aee84a424f6e7498cfda5..d04ee0ad1dccce7ea2503637ffbe6d8753074ffe 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 29
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc7
 NAME = Erotic Pickled Herring
 
 # *DOCUMENTATION*
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 49a6ba926c2bc346bcde289d7948ad4521bf985d..159d0416f270cb34988b7f5a95eb971a05004597 100644 (file)
@@ -111,6 +111,7 @@ ENTRY(mcount)
        .globl mcount_call
 mcount_call:
        bl ftrace_stub
+       ldr lr, [fp, #-4]                       @ restore lr
        ldmia sp!, {r0-r3, pc}
 
 ENTRY(ftrace_caller)
@@ -122,6 +123,7 @@ ENTRY(ftrace_caller)
        .globl ftrace_call
 ftrace_call:
        bl ftrace_stub
+       ldr lr, [fp, #-4]                       @ restore lr
        ldmia sp!, {r0-r3, pc}
 
 #else
@@ -133,6 +135,7 @@ ENTRY(mcount)
        adr r0, ftrace_stub
        cmp r0, r2
        bne trace
+       ldr lr, [fp, #-4]                       @ restore lr
        ldmia sp!, {r0-r3, pc}
 
 trace:
@@ -141,6 +144,7 @@ trace:
        sub r0, r0, #MCOUNT_INSN_SIZE
        mov lr, pc
        mov pc, r2
+       mov lr, r1                              @ restore lr
        ldmia sp!, {r0-r3, pc}
 
 #endif /* CONFIG_DYNAMIC_FTRACE */
index 36f81d967979c0ce62b78912e7d6e3874d9fc06d..6ff7919613d7de1225ec1ca23c1003511194e048 100644 (file)
@@ -88,7 +88,7 @@ void set_fiq_handler(void *start, unsigned int length)
  * disable irqs for the duration.  Note - these functions are almost
  * entirely coded in assembly.
  */
-void __attribute__((naked)) set_fiq_regs(struct pt_regs *regs)
+void __naked set_fiq_regs(struct pt_regs *regs)
 {
        register unsigned long tmp;
        asm volatile (
@@ -106,7 +106,7 @@ void __attribute__((naked)) set_fiq_regs(struct pt_regs *regs)
        : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
 }
 
-void __attribute__((naked)) get_fiq_regs(struct pt_regs *regs)
+void __naked get_fiq_regs(struct pt_regs *regs)
 {
        register unsigned long tmp;
        asm volatile (
index 7049815d66d566e7d89c08fd3c25e33b8c48c995..68d6494c0389751d5584e94e833ae139ae53d76b 100644 (file)
@@ -233,12 +233,13 @@ static void __init cacheid_init(void)
        unsigned int cachetype = read_cpuid_cachetype();
        unsigned int arch = cpu_architecture();
 
-       if (arch >= CPU_ARCH_ARMv7) {
-               cacheid = CACHEID_VIPT_NONALIASING;
-               if ((cachetype & (3 << 14)) == 1 << 14)
-                       cacheid |= CACHEID_ASID_TAGGED;
-       } else if (arch >= CPU_ARCH_ARMv6) {
-               if (cachetype & (1 << 23))
+       if (arch >= CPU_ARCH_ARMv6) {
+               if ((cachetype & (7 << 29)) == 4 << 29) {
+                       /* ARMv7 register format */
+                       cacheid = CACHEID_VIPT_NONALIASING;
+                       if ((cachetype & (3 << 14)) == 1 << 14)
+                               cacheid |= CACHEID_ASID_TAGGED;
+               } else if (cachetype & (1 << 23))
                        cacheid = CACHEID_VIPT_ALIASING;
                else
                        cacheid = CACHEID_VIPT_NONALIASING;
index 9bb4f043aa22beb3fd08d0750cb75c155097b113..7ac812dc055a792476ffdc5a93e6568ae75e069a 100644 (file)
@@ -332,7 +332,6 @@ static int at91_pm_enter(suspend_state_t state)
                        at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR));
 
 error:
-       sdram_selfrefresh_disable();
        target_state = PM_SUSPEND_ON;
        at91_irq_resume();
        at91_gpio_resume();
index a957d239a6838f20458525a2710fa094073f674e..38b6a9ce2a93cc8caecaa2d471e30c3198ce4421 100644 (file)
@@ -311,6 +311,9 @@ evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
        gpio_request(gpio + 7, "nCF_SEL");
        gpio_direction_output(gpio + 7, 1);
 
+       /* irlml6401 sustains over 3A, switches 5V in under 8 msec */
+       setup_usb(500, 8);
+
        return 0;
 }
 
@@ -417,9 +420,6 @@ static __init void davinci_evm_init(void)
        platform_add_devices(davinci_evm_devices,
                             ARRAY_SIZE(davinci_evm_devices));
        evm_init_i2c();
-
-       /* irlml6401 sustains over 3A, switches 5V in under 8 msec */
-       setup_usb(500, 8);
 }
 
 static __init void davinci_evm_irq_init(void)
index 28f6dbc95bd7afe8303abf89d4efb479a71c488f..abb92b7eca0c4adf20284e35ad9dac81961a12ae 100644 (file)
@@ -230,6 +230,11 @@ static struct clk davinci_clks[] = {
                .rate = &commonrate,
                .lpsc = DAVINCI_LPSC_GPIO,
        },
+       {
+               .name = "usb",
+               .rate = &commonrate,
+               .lpsc = DAVINCI_LPSC_USB,
+       },
        {
                .name = "AEMIFCLK",
                .rate = &commonrate,
index 867ead2559adf9e6b0f41f12e8af6c40b2083cc1..69680784448a20a259f96ef059e2c4c375b0ea17 100644 (file)
@@ -47,6 +47,7 @@ static struct musb_hdrc_platform_data usb_data = {
 #elif defined(CONFIG_USB_MUSB_HOST)
        .mode           = MUSB_HOST,
 #endif
+       .clock          = "usb",
        .config         = &musb_config,
 };
 
index 88f7e88f152f07d28c81faa0374b68be974f6533..05f0f4f2f3ce8939215a82795a0be73547a83b71 100644 (file)
@@ -4,6 +4,8 @@
 
 #ifndef __ASSEMBLY__
 
+struct i2c_board_info;
+
 struct ep93xx_eth_data
 {
        unsigned char   dev_addr[6];
index 686d8d2dbb24d975fc0cedc5369681b73649ea23..a95644193f3f9cd4c723f31d561ce10cf69b1d48 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+
+#include <mach/irqs.h>
 #include <mach/hardware.h>
 
 static struct resource imx_csi_resources[] = {
index 2e4b185fe4a90dce82002ba122a071608f56a3f7..3200cf60e384d95df97d435b73b50e90f36aaa6f 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include <mach/irqs.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/imx-uart.h>
index 38c88fbe658de56f20fe6711a8043aba18c1ee0a..e39cd2c46cfa328f63e3a765c4eecb53d57caf68 100644 (file)
@@ -178,7 +178,9 @@ static int __init omap3_beagle_i2c_init(void)
 #ifdef CONFIG_I2C2_OMAP_BEAGLE
        omap_register_i2c_bus(2, 400, NULL, 0);
 #endif
-       omap_register_i2c_bus(3, 400, NULL, 0);
+       /* Bus 3 is attached to the DVI port where devices like the pico DLP
+        * projector don't work reliably with 400kHz */
+       omap_register_i2c_bus(3, 100, NULL, 0);
        return 0;
 }
 
index 0a623379789f03c4603cc43f33ebabcb2a8759b4..8a0e49d842566dffe67037dc2dfef3ccf4f0bce4 100644 (file)
@@ -431,6 +431,10 @@ void __init orion5x_uart1_init(void)
 /*****************************************************************************
  * XOR engine
  ****************************************************************************/
+struct mv_xor_platform_shared_data orion5x_xor_shared_data = {
+       .dram           = &orion5x_mbus_dram_info,
+};
+
 static struct resource orion5x_xor_shared_resources[] = {
        {
                .name   = "xor low",
@@ -448,6 +452,9 @@ static struct resource orion5x_xor_shared_resources[] = {
 static struct platform_device orion5x_xor_shared = {
        .name           = MV_XOR_SHARED_NAME,
        .id             = 0,
+       .dev            = {
+               .platform_data  = &orion5x_xor_shared_data,
+       },
        .num_resources  = ARRAY_SIZE(orion5x_xor_shared_resources),
        .resource       = orion5x_xor_shared_resources,
 };
index e88d417736af1225cdadca8825ff43e000958712..c7fc01e9d1f64bd9c5be760475f7d9537e497312 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/serial_8250.h>
 #include <linux/ata_platform.h>
 #include <linux/io.h>
+#include <linux/i2c.h>
 
 #include <asm/elf.h>
 #include <asm/mach-types.h>
@@ -201,8 +202,13 @@ static struct platform_device *devs[] __initdata = {
        &pata_device,
 };
 
+static struct i2c_board_info i2c_rtc = {
+       I2C_BOARD_INFO("pcf8583", 0x50)
+};
+
 static int __init rpc_init(void)
 {
+       i2c_register_board_info(0, &i2c_rtc, 1);
        return platform_add_devices(devs, ARRAY_SIZE(devs));
 }
 
index 3c4d47145c832bd5ce75a7b7689242e052177684..25f7935576f843adf6e61cc9839a95b638a0de7b 100644 (file)
@@ -129,7 +129,7 @@ static struct s3c_fb_platdata smdk6410_lcd_pdata __initdata = {
        .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
 };
 
-struct map_desc smdk6410_iodesc[] = {};
+static struct map_desc smdk6410_iodesc[] = {};
 
 static struct platform_device *smdk6410_devices[] __initdata = {
 #ifdef CONFIG_SMDK6410_SD_CH0
@@ -146,7 +146,7 @@ static struct platform_device *smdk6410_devices[] __initdata = {
 
 static struct i2c_board_info i2c_devs0[] __initdata = {
        { I2C_BOARD_INFO("24c08", 0x50), },
-       { I2C_BOARD_INFO("WM8580", 0X1b), },
+       { I2C_BOARD_INFO("wm8580", 0x1b), },
 };
 
 static struct i2c_board_info i2c_devs1[] __initdata = {
index 8a7f65ba14b761cb81ceaa87689f1f0d9a91ed3f..94077fbd96b7691850275d71114eb2b9d328f5d3 100644 (file)
@@ -23,7 +23,8 @@ ENTRY(v6_early_abort)
 #ifdef CONFIG_CPU_32v6K
        clrex
 #else
-       strex   r0, r1, [sp]                    @ Clear the exclusive monitor
+       sub     r1, sp, #4                      @ Get unused stack location
+       strex   r0, r1, [r1]                    @ Clear the exclusive monitor
 #endif
        mrc     p15, 0, r1, c5, c0, 0           @ get FSR
        mrc     p15, 0, r0, c6, c0, 0           @ get FAR
index c3ba6a94da0cc458ec9b38b24aafaf9a4ba87d0b..70997d5bee2d76d1d617a5ce5453437e51e4c009 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/highmem.h>
 
-static void __attribute__((naked))
+static void __naked
 feroceon_copy_user_page(void *kto, const void *kfrom)
 {
        asm("\
index 70ed96c8af8e6db46fc06ed1f3e835126bbdd20a..de9c06854ad724547b36937fcc57fa2f1905f1e0 100644 (file)
@@ -15,7 +15,7 @@
  *
  * FIXME: do we need to handle cache stuff...
  */
-static void __attribute__((naked))
+static void __naked
 v3_copy_user_page(void *kto, const void *kfrom)
 {
        asm("\n\
index 1601698b9800fa04cac49e5982d530dbb4284931..7370a7142b0424eba7f356151048db8cff66a38f 100644 (file)
@@ -44,7 +44,7 @@ static DEFINE_SPINLOCK(minicache_lock);
  * instruction.  If your processor does not supply this, you have to write your
  * own copy_user_highpage that does the right thing.
  */
-static void __attribute__((naked))
+static void __naked
 mc_copy_user_page(void *from, void *to)
 {
        asm volatile(
index 3ec93dab7656dc34ff3c2135e60de5659d9aa572..9ab098414227e928007212f6159d8fcba88fc763 100644 (file)
@@ -22,7 +22,7 @@
  * instruction.  If your processor does not supply this, you have to write your
  * own copy_user_highpage that does the right thing.
  */
-static void __attribute__((naked))
+static void __naked
 v4wb_copy_user_page(void *kto, const void *kfrom)
 {
        asm("\
index 0f1188efae455e22b3f95af3e760399171a8f3e6..300efafd66431ae02b042df0e065efca88424bf3 100644 (file)
@@ -20,7 +20,7 @@
  * dirty data in the cache.  However, we do have to ensure that
  * subsequent reads are up to date.
  */
-static void __attribute__((naked))
+static void __naked
 v4wt_copy_user_page(void *kto, const void *kfrom)
 {
        asm("\
index 39a994542cadff71c6d829c38b009f343b9bfb18..bc4525f5ab2326d266c828dac8c21f81a7655854 100644 (file)
@@ -29,7 +29,7 @@
  * if we eventually end up using our copied page.
  *
  */
-static void __attribute__((naked))
+static void __naked
 xsc3_mc_copy_user_page(void *kto, const void *kfrom)
 {
        asm("\
index d18f2397ee2dd7b0903514317466251990a78d7f..76824d3e966a5a1b34105775aeb96b8acb086f4d 100644 (file)
@@ -42,7 +42,7 @@ static DEFINE_SPINLOCK(minicache_lock);
  * Dcache aliasing issue.  The writes will be forwarded to the write buffer,
  * and merged as appropriate.
  */
-static void __attribute__((naked))
+static void __naked
 mc_copy_user_page(void *from, void *to)
 {
        /*
index deaff58878a2fe7cfd1324cf2afc6653eaf7ec99..04a100cfb8e5fcfe67057938f7472114150c04b1 100644 (file)
@@ -18,7 +18,8 @@ obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
 obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
 obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
-obj-$(CONFIG_I2C_OMAP) += i2c.o
+i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o
+obj-y += $(i2c-omap-m) $(i2c-omap-y)
 
 # OMAP mailbox framework
 obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
index 0843b8882f9311aa38dd972537dd5f5f757e86e7..6825fbb5a056d91682c7b3c67e669a9d4fb780aa 100644 (file)
@@ -199,21 +199,17 @@ static struct clocksource clocksource_32k = {
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-/*
- * Rounds down to nearest nsec.
- */
-unsigned long long omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
-{
-       return cyc2ns(&clocksource_32k, ticks_32k);
-}
-
 /*
  * Returns current time from boot in nsecs. It's OK for this to wrap
  * around for now, as it's just a relative time stamp.
  */
 unsigned long long sched_clock(void)
 {
-       return omap_32k_ticks_to_nsecs(omap_32k_read());
+       unsigned long long ret;
+
+       ret = (unsigned long long)omap_32k_read();
+       ret = (ret * clocksource_32k.mult_orig) >> clocksource_32k.shift;
+       return ret;
 }
 
 static int __init omap_init_clocksource_32k(void)
index ef70e2b0f05413d78e246b27e17ab3602d690cea..e746ec7e785e30ab17f4cce27e8bc797d49fd6c3 100644 (file)
@@ -35,7 +35,7 @@ extern void omap_map_common_io(void);
 extern struct sys_timer omap_timer;
 extern void omap_serial_init(void);
 extern void omap_serial_enable_clocks(int enable);
-#ifdef CONFIG_I2C_OMAP
+#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
 extern int omap_register_i2c_bus(int bus_id, u32 clkrate,
                                 struct i2c_board_info const *info,
                                 unsigned len);
index 2a9c27ad4c373b349ae85db6fb7f06dd6b0f0035..37e2f0f38b462bb803bd6615dc6c070909993a40 100644 (file)
        !defined(CONFIG_ARCH_OMAP15XX) && \
        !defined(CONFIG_ARCH_OMAP16XX) && \
        !defined(CONFIG_ARCH_OMAP24XX)
-#error "Power management for this processor not implemented yet"
+#warning "Power management for this processor not implemented yet"
 #endif
 
 #ifndef __ASSEMBLER__
index 136c982c68e1b92099bbd1d3b28691dbdac8ba51..ad1b9682c9c3457b32470f3f1bcfd23da1de0811 100644 (file)
@@ -248,7 +248,7 @@ static struct clk *clks[] __initdata = {
        &clk_48m,
 };
 
-void s3c64xx_register_clocks(void)
+void __init s3c64xx_register_clocks(void)
 {
        struct clk *clkp;
        int ret;
index cc62941d7b5c53f1721be0671abd35286c29639b..ee9188add8fbd7b0fb2243ad6e9a002a0b98b29b 100644 (file)
@@ -417,4 +417,4 @@ static __init int s3c64xx_gpiolib_init(void)
        return 0;
 }
 
-arch_initcall(s3c64xx_gpiolib_init);
+core_initcall(s3c64xx_gpiolib_init);
index 2846f550b727792b043268cce7728a5ccd71b0c3..f865bf4d709eaea2299f93c85de83b59c5b7457e 100644 (file)
 #define IRQ_ONENAND1           S3C64XX_IRQ_VIC1(12)
 #define IRQ_NFC                        S3C64XX_IRQ_VIC1(13)
 #define IRQ_CFCON              S3C64XX_IRQ_VIC1(14)
-#define IRQ_UHOST              S3C64XX_IRQ_VIC1(15)
+#define IRQ_USBH               S3C64XX_IRQ_VIC1(15)
 #define IRQ_SPI0               S3C64XX_IRQ_VIC1(16)
 #define IRQ_SPI1               S3C64XX_IRQ_VIC1(17)
 #define IRQ_IIC                        S3C64XX_IRQ_VIC1(18)
index 1f7cc0067f5cdd19fad4c487b2a2821687de3b92..cf524826c93a68fb757daf6a58333dee784a1182 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/gpio.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 
 #include <asm/hardware/vic.h>
 
 #include <plat/regs-irqtype.h>
+#include <plat/regs-gpio.h>
+#include <plat/gpio-cfg.h>
 
 #include <mach/map.h>
 #include <plat/cpu.h>
@@ -55,7 +58,7 @@ static void s3c_irq_eint_unmask(unsigned int irq)
        u32 mask;
 
        mask = __raw_readl(S3C64XX_EINT0MASK);
-       mask |= eint_irq_to_bit(irq);
+       mask &= ~eint_irq_to_bit(irq);
        __raw_writel(mask, S3C64XX_EINT0MASK);
 }
 
@@ -74,6 +77,7 @@ static void s3c_irq_eint_maskack(unsigned int irq)
 static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type)
 {
        int offs = eint_offset(irq);
+       int pin;
        int shift;
        u32 ctrl, mask;
        u32 newvalue = 0;
@@ -125,6 +129,15 @@ static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type)
        ctrl |= newvalue << shift;
        __raw_writel(ctrl, reg);
 
+       /* set the GPIO pin appropriately */
+
+       if (offs < 23)
+               pin = S3C64XX_GPN(offs);
+       else
+               pin = S3C64XX_GPM(offs - 23);
+
+       s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(2));
+
        return 0;
 }
 
@@ -181,7 +194,7 @@ static void s3c_irq_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
        s3c_irq_demux_eint(20, 27);
 }
 
-int __init s3c64xx_init_irq_eint(void)
+static int __init s3c64xx_init_irq_eint(void)
 {
        int irq;
 
index a94f1d5e819df993cc8d887780cfaf4e605459cb..f22edf7c2d2de65b8fee6ba955468d8b9feb7bcf 100644 (file)
@@ -207,7 +207,7 @@ static struct irq_chip s3c_irq_uart = {
 
 static void __init s3c64xx_uart_irq(struct uart_irq *uirq)
 {
-       void *reg_base = uirq->regs;
+       void __iomem *reg_base = uirq->regs;
        unsigned int irq;
        int offs;
 
index 8d9a0cada668d725ac0c18616b838205d3721e4d..05b17528041e36f451e4bc5f0e30b8d33ab316ea 100644 (file)
@@ -36,7 +36,7 @@
  * ext_xtal_mux for want of an actual name from the manual.
 */
 
-struct clk clk_ext_xtal_mux = {
+static struct clk clk_ext_xtal_mux = {
        .name           = "ext_xtal",
        .id             = -1,
 };
@@ -63,7 +63,7 @@ struct clksrc_clk {
        void __iomem            *reg_divider;
 };
 
-struct clk clk_fout_apll = {
+static struct clk clk_fout_apll = {
        .name           = "fout_apll",
        .id             = -1,
 };
@@ -78,7 +78,7 @@ static struct clk_sources clk_src_apll = {
        .nr_sources     = ARRAY_SIZE(clk_src_apll_list),
 };
 
-struct clksrc_clk clk_mout_apll = {
+static struct clksrc_clk clk_mout_apll = {
        .clk    = {
                .name           = "mout_apll",
                .id             = -1,
@@ -88,7 +88,7 @@ struct clksrc_clk clk_mout_apll = {
        .sources        = &clk_src_apll,
 };
 
-struct clk clk_fout_epll = {
+static struct clk clk_fout_epll = {
        .name           = "fout_epll",
        .id             = -1,
 };
@@ -103,7 +103,7 @@ static struct clk_sources clk_src_epll = {
        .nr_sources     = ARRAY_SIZE(clk_src_epll_list),
 };
 
-struct clksrc_clk clk_mout_epll = {
+static struct clksrc_clk clk_mout_epll = {
        .clk    = {
                .name           = "mout_epll",
                .id             = -1,
@@ -123,7 +123,7 @@ static struct clk_sources clk_src_mpll = {
        .nr_sources     = ARRAY_SIZE(clk_src_mpll_list),
 };
 
-struct clksrc_clk clk_mout_mpll = {
+static struct clksrc_clk clk_mout_mpll = {
        .clk = {
                .name           = "mout_mpll",
                .id             = -1,
@@ -145,7 +145,7 @@ static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
        return rate;
 }
 
-struct clk clk_dout_mpll = {
+static struct clk clk_dout_mpll = {
        .name           = "dout_mpll",
        .id             = -1,
        .parent         = &clk_mout_mpll.clk,
@@ -189,10 +189,10 @@ static struct clk_sources clkset_uart = {
 };
 
 static struct clk *clkset_uhost_list[] = {
+       &clk_48m,
        &clk_mout_epll.clk,
        &clk_dout_mpll,
        &clk_fin_epll,
-       &clk_48m,
 };
 
 static struct clk_sources clkset_uhost = {
@@ -239,10 +239,12 @@ static int s3c64xx_setrate_clksrc(struct clk *clk, unsigned long rate)
 
        rate = clk_round_rate(clk, rate);
        div = clk_get_rate(clk->parent) / rate;
+       if (div > 16)
+               return -EINVAL;
 
        val = __raw_readl(reg);
-       val &= ~sclk->mask;
-       val |= (rate - 1) << sclk->shift;
+       val &= ~(0xf << sclk->shift);
+       val |= (div - 1) << sclk->shift;
        __raw_writel(val, reg);
 
        return 0;
@@ -351,7 +353,7 @@ static struct clksrc_clk clk_mmc2 = {
 
 static struct clksrc_clk clk_usbhost = {
        .clk    = {
-               .name           = "usb-host-bus",
+               .name           = "usb-bus-host",
                .id             = -1,
                .ctrlbit        = S3C_CLKCON_SCLK_UHOST,
                .enable         = s3c64xx_sclk_ctrl,
index fd23c0e9e69863d5bfdec7ad61ee1a2568e1f820..b4211d8b2ac706de53314c2d95d3ccaedeaa98b0 100644 (file)
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Sun Nov 30 16:39:36 2008
+# Last update: Thu Mar 12 18:01:45 2009
 #
 # machine_is_xxx       CONFIG_xxxx             MACH_TYPE_xxx           number
 #
@@ -1811,7 +1811,7 @@ pilz_pmi5         MACH_PILZ_PMI5          PILZ_PMI5               1820
 jade                   MACH_JADE               JADE                    1821
 ks8695_softplc         MACH_KS8695_SOFTPLC     KS8695_SOFTPLC          1822
 gprisc3                        MACH_GPRISC3            GPRISC3                 1823
-stamp9260              MACH_STAMP9260          STAMP9260               1824
+stamp9g20              MACH_STAMP9G20          STAMP9G20               1824
 smdk6430               MACH_SMDK6430           SMDK6430                1825
 smdkc100               MACH_SMDKC100           SMDKC100                1826
 tavorevb               MACH_TAVOREVB           TAVOREVB                1827
@@ -1993,4 +1993,134 @@ spark                   MACH_SPARK              SPARK                   2002
 benzina                        MACH_BENZINA            BENZINA                 2003
 blaze                  MACH_BLAZE              BLAZE                   2004
 linkstation_ls_hgl     MACH_LINKSTATION_LS_HGL LINKSTATION_LS_HGL      2005
-htcvenus               MACH_HTCVENUS           HTCVENUS                2006
+htckovsky              MACH_HTCVENUS           HTCVENUS                2006
+sony_prs505            MACH_SONY_PRS505        SONY_PRS505             2007
+hanlin_v3              MACH_HANLIN_V3          HANLIN_V3               2008
+sapphira               MACH_SAPPHIRA           SAPPHIRA                2009
+dack_sda_01            MACH_DACK_SDA_01        DACK_SDA_01             2010
+armbox                 MACH_ARMBOX             ARMBOX                  2011
+harris_rvp             MACH_HARRIS_RVP         HARRIS_RVP              2012
+ribaldo                        MACH_RIBALDO            RIBALDO                 2013
+agora                  MACH_AGORA              AGORA                   2014
+omap3_mini             MACH_OMAP3_MINI         OMAP3_MINI              2015
+a9sam6432_b            MACH_A9SAM6432_B        A9SAM6432_B             2016
+usg2410                        MACH_USG2410            USG2410                 2017
+pc72052_i10_revb       MACH_PC72052_I10_REVB   PC72052_I10_REVB        2018
+mx35_exm32             MACH_MX35_EXM32         MX35_EXM32              2019
+topas910               MACH_TOPAS910           TOPAS910                2020
+hyena                  MACH_HYENA              HYENA                   2021
+pospax                 MACH_POSPAX             POSPAX                  2022
+hdl_gx                 MACH_HDL_GX             HDL_GX                  2023
+ctera_4bay             MACH_CTERA_4BAY         CTERA_4BAY              2024
+ctera_plug_c           MACH_CTERA_PLUG_C       CTERA_PLUG_C            2025
+crwea_plug_i           MACH_CRWEA_PLUG_I       CRWEA_PLUG_I            2026
+egauge2                        MACH_EGAUGE2            EGAUGE2                 2027
+didj                   MACH_DIDJ               DIDJ                    2028
+m_s3c2443              MACH_MEISTER            MEISTER                 2029
+htcblackstone          MACH_HTCBLACKSTONE      HTCBLACKSTONE           2030
+cpuat9g20              MACH_CPUAT9G20          CPUAT9G20               2031
+smdk6440               MACH_SMDK6440           SMDK6440                2032
+omap_35xx_mvp          MACH_OMAP_35XX_MVP      OMAP_35XX_MVP           2033
+ctera_plug_i           MACH_CTERA_PLUG_I       CTERA_PLUG_I            2034
+pvg610_100             MACH_PVG610             PVG610                  2035
+hprw6815               MACH_HPRW6815           HPRW6815                2036
+omap3_oswald           MACH_OMAP3_OSWALD       OMAP3_OSWALD            2037
+nas4220b               MACH_NAS4220B           NAS4220B                2038
+htcraphael_cdma                MACH_HTCRAPHAEL_CDMA    HTCRAPHAEL_CDMA         2039
+htcdiamond_cdma                MACH_HTCDIAMOND_CDMA    HTCDIAMOND_CDMA         2040
+scaler                 MACH_SCALER             SCALER                  2041
+zylonite2              MACH_ZYLONITE2          ZYLONITE2               2042
+aspenite               MACH_ASPENITE           ASPENITE                2043
+teton                  MACH_TETON              TETON                   2044
+ttc_dkb                        MACH_TTC_DKB            TTC_DKB                 2045
+bishop2                        MACH_BISHOP2            BISHOP2                 2046
+ippv5                  MACH_IPPV5              IPPV5                   2047
+farm926                        MACH_FARM926            FARM926                 2048
+mmccpu                 MACH_MMCCPU             MMCCPU                  2049
+sgmsfl                 MACH_SGMSFL             SGMSFL                  2050
+tt8000                 MACH_TT8000             TT8000                  2051
+zrn4300lp              MACH_ZRN4300LP          ZRN4300LP               2052
+mptc                   MACH_MPTC               MPTC                    2053
+h6051                  MACH_H6051              H6051                   2054
+pvg610_101             MACH_PVG610_101         PVG610_101              2055
+stamp9261_pc_evb       MACH_STAMP9261_PC_EVB   STAMP9261_PC_EVB        2056
+pelco_odysseus         MACH_PELCO_ODYSSEUS     PELCO_ODYSSEUS          2057
+tny_a9260              MACH_TNY_A9260          TNY_A9260               2058
+tny_a9g20              MACH_TNY_A9G20          TNY_A9G20               2059
+aesop_mp2530f          MACH_AESOP_MP2530F      AESOP_MP2530F           2060
+dx900                  MACH_DX900              DX900                   2061
+cpodc2                 MACH_CPODC2             CPODC2                  2062
+tilt_8925              MACH_TILT_8925          TILT_8925               2063
+davinci_dm357_evm      MACH_DAVINCI_DM357_EVM  DAVINCI_DM357_EVM       2064
+swordfish              MACH_SWORDFISH          SWORDFISH               2065
+corvus                 MACH_CORVUS             CORVUS                  2066
+taurus                 MACH_TAURUS             TAURUS                  2067
+axm                    MACH_AXM                AXM                     2068
+axc                    MACH_AXC                AXC                     2069
+baby                   MACH_BABY               BABY                    2070
+mp200                  MACH_MP200              MP200                   2071
+pcm043                 MACH_PCM043             PCM043                  2072
+hanlin_v3c             MACH_HANLIN_V3C         HANLIN_V3C              2073
+kbk9g20                        MACH_KBK9G20            KBK9G20                 2074
+adsturbog5             MACH_ADSTURBOG5         ADSTURBOG5              2075
+avenger_lite1          MACH_AVENGER_LITE1      AVENGER_LITE1           2076
+suc82x                 MACH_SUC                SUC                     2077
+at91sam7s256           MACH_AT91SAM7S256       AT91SAM7S256            2078
+mendoza                        MACH_MENDOZA            MENDOZA                 2079
+kira                   MACH_KIRA               KIRA                    2080
+mx1hbm                 MACH_MX1HBM             MX1HBM                  2081
+quatro43xx             MACH_QUATRO43XX         QUATRO43XX              2082
+quatro4230             MACH_QUATRO4230         QUATRO4230              2083
+nsb400                 MACH_NSB400             NSB400                  2084
+drp255                 MACH_DRP255             DRP255                  2085
+thoth                  MACH_THOTH              THOTH                   2086
+firestone              MACH_FIRESTONE          FIRESTONE               2087
+asusp750               MACH_ASUSP750           ASUSP750                2088
+ctera_dl               MACH_CTERA_DL           CTERA_DL                2089
+socr                   MACH_SOCR               SOCR                    2090
+htcoxygen              MACH_HTCOXYGEN          HTCOXYGEN               2091
+heroc                  MACH_HEROC              HEROC                   2092
+zeno6800               MACH_ZENO6800           ZENO6800                2093
+sc2mcs                 MACH_SC2MCS             SC2MCS                  2094
+gene100                        MACH_GENE100            GENE100                 2095
+as353x                 MACH_AS353X             AS353X                  2096
+sheevaplug             MACH_SHEEVAPLUG         SHEEVAPLUG              2097
+at91sam9g20            MACH_AT91SAM9G20        AT91SAM9G20             2098
+mv88f6192gtw_fe                MACH_MV88F6192GTW_FE    MV88F6192GTW_FE         2099
+cc9200                 MACH_CC9200             CC9200                  2100
+sm9200                 MACH_SM9200             SM9200                  2101
+tp9200                 MACH_TP9200             TP9200                  2102
+snapperdv              MACH_SNAPPERDV          SNAPPERDV               2103
+avengers_lite          MACH_AVENGERS_LITE      AVENGERS_LITE           2104
+avengers_lite1         MACH_AVENGERS_LITE1     AVENGERS_LITE1          2105
+omap3axon              MACH_OMAP3AXON          OMAP3AXON               2106
+ma8xx                  MACH_MA8XX              MA8XX                   2107
+mp201ek                        MACH_MP201EK            MP201EK                 2108
+davinci_tux            MACH_DAVINCI_TUX        DAVINCI_TUX             2109
+mpa1600                        MACH_MPA1600            MPA1600                 2110
+pelco_troy             MACH_PELCO_TROY         PELCO_TROY              2111
+nsb667                 MACH_NSB667             NSB667                  2112
+rovers5_4mpix          MACH_ROVERS5_4MPIX      ROVERS5_4MPIX           2113
+twocom                 MACH_TWOCOM             TWOCOM                  2114
+ubisys_p9_rcu3r2       MACH_UBISYS_P9_RCU3R2   UBISYS_P9_RCU3R2        2115
+hero_espresso          MACH_HERO_ESPRESSO      HERO_ESPRESSO           2116
+afeusb                 MACH_AFEUSB             AFEUSB                  2117
+t830                   MACH_T830               T830                    2118
+spd8020_cc             MACH_SPD8020_CC         SPD8020_CC              2119
+om_3d7k                        MACH_OM_3D7K            OM_3D7K                 2120
+picocom2               MACH_PICOCOM2           PICOCOM2                2121
+uwg4mx27               MACH_UWG4MX27           UWG4MX27                2122
+uwg4mx31               MACH_UWG4MX31           UWG4MX31                2123
+cherry                 MACH_CHERRY             CHERRY                  2124
+mx51_babbage           MACH_MX51_BABBAGE       MX51_BABBAGE            2125
+s3c2440turkiye         MACH_S3C2440TURKIYE     S3C2440TURKIYE          2126
+tx37                   MACH_TX37               TX37                    2127
+sbc2800_9g20           MACH_SBC2800_9G20       SBC2800_9G20            2128
+benzglb                        MACH_BENZGLB            BENZGLB                 2129
+benztd                 MACH_BENZTD             BENZTD                  2130
+cartesio_plus          MACH_CARTESIO_PLUS      CARTESIO_PLUS           2131
+solrad_g20             MACH_SOLRAD_G20         SOLRAD_G20              2132
+mx27wallace            MACH_MX27WALLACE        MX27WALLACE             2133
+fmzwebmodul            MACH_FMZWEBMODUL        FMZWEBMODUL             2134
+rd78x00_masa           MACH_RD78X00_MASA       RD78X00_MASA            2135
+smallogger             MACH_SMALLOGGER         SMALLOGGER              2136
index 6183aeccecf1f9d564cc2bc2832943a235ed3871..153e727a6e8ecffb23e70bdc39ef3314b34c0aae 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
@@ -635,6 +638,17 @@ config DMAR
          and include PCI device scope covered by these DMA
          remapping devices.
 
+config DMAR_DEFAULT_ON
+       def_bool y
+       prompt "Enable DMA Remapping Devices by default"
+       depends on DMAR
+       help
+         Selecting this option will enable a DMAR device at boot time if
+         one is found. If this option is not selected, DMAR support can
+         be enabled by passing intel_iommu=on to the kernel. It is
+         recommended you say N here while the DMAR code remains
+         experimental.
+
 endmenu
 
 endif
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 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 5cfd3d91001aed8043764c88778d2df3e91681cf..e13125058bedb03eb56d2ab291d7c3e3628c9c25 100644 (file)
@@ -507,7 +507,7 @@ static int iosapic_find_sharable_irq(unsigned long trigger, unsigned long pol)
        if (trigger == IOSAPIC_EDGE)
                return -EINVAL;
 
-       for (i = 0; i <= NR_IRQS; i++) {
+       for (i = 0; i < NR_IRQS; i++) {
                info = &iosapic_intr_info[i];
                if (info->trigger == trigger && info->polarity == pol &&
                    (info->dmode == IOSAPIC_FIXED ||
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 67810b77d998768199b3978d288130968e837865..b6c0e63a0bf61535386fff325adaf5f3e40e2932 100644 (file)
@@ -2149,7 +2149,7 @@ unw_remove_unwind_table (void *handle)
 
        /* next, remove hash table entries for this table */
 
-       for (index = 0; index <= UNW_HASH_SIZE; ++index) {
+       for (index = 0; index < UNW_HASH_SIZE; ++index) {
                tmp = unw.cache + unw.hash[index];
                if (unw.hash[index] >= UNW_CACHE_SIZE
                    || tmp->ip < table->start || tmp->ip >= table->end)
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 600eef3f3ac7db71dc165946e657da08ee79a9ac..e61465a18c7e4b6e66ba35194b1b7ae0eda5ddb7 100644 (file)
@@ -603,7 +603,7 @@ config CAVIUM_OCTEON_SIMULATOR
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
        select SYS_SUPPORTS_HIGHMEM
-       select CPU_CAVIUM_OCTEON
+       select SYS_HAS_CPU_CAVIUM_OCTEON
        help
          The Octeon simulator is software performance model of the Cavium
          Octeon Processor. It supports simulating Octeon processors on x86
@@ -618,7 +618,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
        select SYS_SUPPORTS_BIG_ENDIAN
        select SYS_SUPPORTS_HIGHMEM
        select SYS_HAS_EARLY_PRINTK
-       select CPU_CAVIUM_OCTEON
+       select SYS_HAS_CPU_CAVIUM_OCTEON
        select SWAP_IO_SPACE
        help
          This option supports all of the Octeon reference boards from Cavium
@@ -1234,6 +1234,7 @@ config CPU_SB1
 
 config CPU_CAVIUM_OCTEON
        bool "Cavium Octeon processor"
+       depends on SYS_HAS_CPU_CAVIUM_OCTEON
        select IRQ_CPU
        select IRQ_CPU_OCTEON
        select CPU_HAS_PREFETCH
@@ -1314,6 +1315,9 @@ config SYS_HAS_CPU_RM9000
 config SYS_HAS_CPU_SB1
        bool
 
+config SYS_HAS_CPU_CAVIUM_OCTEON
+       bool
+
 #
 # CPU may reorder R->R, R->W, W->R, W->W
 # Reordering beyond LL and SC is handled in WEAK_REORDERING_BEYOND_LLSC
@@ -1387,6 +1391,7 @@ config 32BIT
 config 64BIT
        bool "64-bit kernel"
        depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL
+       select HAVE_SYSCALL_WRAPPERS
        help
          Select this option if you want to build a 64-bit kernel.
 
index 6fd441d16af57e6af53fa410fee70dac5204d66c..f58d4ffb89456c1c1d6d3076906631946b1aba48 100644 (file)
@@ -118,7 +118,7 @@ void __init plat_time_init(void)
         * setup counter 1 (RTC) to tick at full speed
         */
        t = 0xffffff;
-       while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S) && t--)
+       while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S) && --t)
                asm volatile ("nop");
        if (!t)
                goto cntr_err;
@@ -127,7 +127,7 @@ void __init plat_time_init(void)
        au_sync();
 
        t = 0xffffff;
-       while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && t--)
+       while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && --t)
                asm volatile ("nop");
        if (!t)
                goto cntr_err;
@@ -135,7 +135,7 @@ void __init plat_time_init(void)
        au_sync();
 
        t = 0xffffff;
-       while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && t--)
+       while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && --t)
                asm volatile ("nop");
        if (!t)
                goto cntr_err;
index 36ed44070256243fe1bac9f7618154481fabd7ef..a6772e9507f5ac109d5422d66c1184dcbbc7839d 100644 (file)
@@ -1,6 +1,5 @@
 #ifndef __ASM_SECCOMP_H
 
-#include <linux/thread_info.h>
 #include <linux/unistd.h>
 
 #define __NR_seccomp_read __NR_read
index a0ff2b66e22b453f23d909959d3c37694cd5fd80..4b4007b3083a8f881cef80371e68a2a688c55f32 100644 (file)
@@ -111,7 +111,6 @@ int show_interrupts(struct seq_file *p, void *v)
                        seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
                seq_printf(p, " %14s", irq_desc[i].chip->name);
-               seq_printf(p, "-%-8s", irq_desc[i].name);
                seq_printf(p, "  %s", action->name);
 
                for (action=action->next; action; action = action->next)
index aa2c55e3b55ffda84dff352114a6bf904aa07580..2f8452b404c71be4a22bdf508dcedb54320d45c4 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/binfmts.h>
 #include <linux/security.h>
+#include <linux/syscalls.h>
 #include <linux/compat.h>
 #include <linux/vfs.h>
 #include <linux/ipc.h>
@@ -63,9 +64,9 @@
 #define merge_64(r1, r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL))
 #endif
 
-asmlinkage unsigned long
-sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
-         unsigned long flags, unsigned long fd, unsigned long pgoff)
+SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len,
+       unsigned long, prot, unsigned long, flags, unsigned long, fd,
+       unsigned long, pgoff)
 {
        struct file * file = NULL;
        unsigned long error;
@@ -121,21 +122,21 @@ struct rlimit32 {
        int     rlim_max;
 };
 
-asmlinkage long sys32_truncate64(const char __user * path,
-       unsigned long __dummy, int a2, int a3)
+SYSCALL_DEFINE4(32_truncate64, const char __user *, path,
+       unsigned long, __dummy, unsigned long, a2, unsigned long, a3)
 {
        return sys_truncate(path, merge_64(a2, a3));
 }
 
-asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
-       int a2, int a3)
+SYSCALL_DEFINE4(32_ftruncate64, unsigned long, fd, unsigned long, __dummy,
+       unsigned long, a2, unsigned long, a3)
 {
        return sys_ftruncate(fd, merge_64(a2, a3));
 }
 
-asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
-                           unsigned int offset_low, loff_t __user * result,
-                           unsigned int origin)
+SYSCALL_DEFINE5(32_llseek, unsigned long, fd, unsigned long, offset_high,
+       unsigned long, offset_low, loff_t __user *, result,
+       unsigned long, origin)
 {
        return sys_llseek(fd, offset_high, offset_low, result, origin);
 }
@@ -144,20 +145,20 @@ asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
    lseek back to original location.  They fail just like lseek does on
    non-seekable files.  */
 
-asmlinkage ssize_t sys32_pread(unsigned int fd, char __user * buf,
-                              size_t count, u32 unused, u64 a4, u64 a5)
+SYSCALL_DEFINE6(32_pread, unsigned long, fd, char __user *, buf, size_t, count,
+       unsigned long, unused, unsigned long, a4, unsigned long, a5)
 {
        return sys_pread64(fd, buf, count, merge_64(a4, a5));
 }
 
-asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char __user * buf,
-                               size_t count, u32 unused, u64 a4, u64 a5)
+SYSCALL_DEFINE6(32_pwrite, unsigned int, fd, const char __user *, buf,
+       size_t, count, u32, unused, u64, a4, u64, a5)
 {
        return sys_pwrite64(fd, buf, count, merge_64(a4, a5));
 }
 
-asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
-       struct compat_timespec __user *interval)
+SYSCALL_DEFINE2(32_sched_rr_get_interval, compat_pid_t, pid,
+       struct compat_timespec __user *interval)
 {
        struct timespec t;
        int ret;
@@ -174,8 +175,8 @@ asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
 
 #ifdef CONFIG_SYSVIPC
 
-asmlinkage long
-sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
+SYSCALL_DEFINE6(32_ipc, u32, call, long, first, long, second, long, third,
+       unsigned long, ptr, unsigned long, fifth)
 {
        int version, err;
 
@@ -233,8 +234,8 @@ sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
 
 #else
 
-asmlinkage long
-sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
+SYSCALL_DEFINE6(32_ipc, u32, call, int, first, int, second, int, third,
+       u32, ptr, u32 fifth)
 {
        return -ENOSYS;
 }
@@ -242,7 +243,7 @@ sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
 #endif /* CONFIG_SYSVIPC */
 
 #ifdef CONFIG_MIPS32_N32
-asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg)
+SYSCALL_DEFINE4(n32_semctl, int, semid, int, semnum, int, cmd, u32, arg)
 {
        /* compat_sys_semctl expects a pointer to union semun */
        u32 __user *uptr = compat_alloc_user_space(sizeof(u32));
@@ -251,13 +252,14 @@ asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg)
        return compat_sys_semctl(semid, semnum, cmd, uptr);
 }
 
-asmlinkage long sysn32_msgsnd(int msqid, u32 msgp, unsigned msgsz, int msgflg)
+SYSCALL_DEFINE4(n32_msgsnd, int, msqid, u32, msgp, unsigned int, msgsz,
+       int, msgflg)
 {
        return compat_sys_msgsnd(msqid, msgsz, msgflg, compat_ptr(msgp));
 }
 
-asmlinkage long sysn32_msgrcv(int msqid, u32 msgp, size_t msgsz, int msgtyp,
-                             int msgflg)
+SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,
+       int, msgtyp, int, msgflg)
 {
        return compat_sys_msgrcv(msqid, msgsz, msgtyp, msgflg, IPC_64,
                                 compat_ptr(msgp));
@@ -277,7 +279,7 @@ struct sysctl_args32
 
 #ifdef CONFIG_SYSCTL_SYSCALL
 
-asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args)
+SYSCALL_DEFINE1(32_sysctl, struct sysctl_args32 __user *, args)
 {
        struct sysctl_args32 tmp;
        int error;
@@ -316,9 +318,16 @@ asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args)
        return error;
 }
 
+#else
+
+SYSCALL_DEFINE1(32_sysctl, struct sysctl_args32 __user *, args)
+{
+       return -ENOSYS;
+}
+
 #endif /* CONFIG_SYSCTL_SYSCALL */
 
-asmlinkage long sys32_newuname(struct new_utsname __user * name)
+SYSCALL_DEFINE1(32_newuname, struct new_utsname __user *, name)
 {
        int ret = 0;
 
@@ -334,7 +343,7 @@ asmlinkage long sys32_newuname(struct new_utsname __user * name)
        return ret;
 }
 
-asmlinkage int sys32_personality(unsigned long personality)
+SYSCALL_DEFINE1(32_personality, unsigned long, personality)
 {
        int ret;
        personality &= 0xffffffff;
@@ -357,7 +366,7 @@ struct ustat32 {
 
 extern asmlinkage long sys_ustat(dev_t dev, struct ustat __user * ubuf);
 
-asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32)
+SYSCALL_DEFINE2(32_ustat, dev_t, dev, struct ustat32 __user *, ubuf32)
 {
        int err;
        struct ustat tmp;
@@ -381,8 +390,8 @@ out:
        return err;
 }
 
-asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
-       s32 count)
+SYSCALL_DEFINE4(32_sendfile, long, out_fd, long, in_fd,
+       compat_off_t __user *, offset, s32, count)
 {
        mm_segment_t old_fs = get_fs();
        int ret;
index 51d1ba415b90adaab205ee6fafd784ef1aa97bd6..9ab70c3b5be6bac233e00568ac3ce9dd51f410e8 100644 (file)
@@ -399,7 +399,7 @@ einval:     li      v0, -ENOSYS
        sys     sys_swapon              2
        sys     sys_reboot              3
        sys     sys_old_readdir         3
-       sys     old_mmap                6       /* 4090 */
+       sys     sys_mips_mmap           6       /* 4090 */
        sys     sys_munmap              2
        sys     sys_truncate            2
        sys     sys_ftruncate           2
@@ -519,7 +519,7 @@ einval:     li      v0, -ENOSYS
        sys     sys_sendfile            4
        sys     sys_ni_syscall          0
        sys     sys_ni_syscall          0
-       sys     sys_mmap2               6       /* 4210 */
+       sys     sys_mips_mmap2          6       /* 4210 */
        sys     sys_truncate64          4
        sys     sys_ftruncate64         4
        sys     sys_stat64              2
index a9e1716189948c2b76eaa47aa985208277d00667..9b46986671545dea233ce1f96aca4f59e7eb912a 100644 (file)
@@ -207,7 +207,7 @@ sys_call_table:
        PTR     sys_newlstat
        PTR     sys_poll
        PTR     sys_lseek
-       PTR     old_mmap
+       PTR     sys_mips_mmap
        PTR     sys_mprotect                    /* 5010 */
        PTR     sys_munmap
        PTR     sys_brk
index 30f3b6317a83f1ec7d753cdb49b96d1aedce1186..7438e92f8a010566e183f986190b14de82e70bd7 100644 (file)
@@ -129,12 +129,12 @@ EXPORT(sysn32_call_table)
        PTR     sys_newlstat
        PTR     sys_poll
        PTR     sys_lseek
-       PTR     old_mmap
+       PTR     sys_mips_mmap
        PTR     sys_mprotect                    /* 6010 */
        PTR     sys_munmap
        PTR     sys_brk
-       PTR     sys32_rt_sigaction
-       PTR     sys32_rt_sigprocmask
+       PTR     sys_32_rt_sigaction
+       PTR     sys_32_rt_sigprocmask
        PTR     compat_sys_ioctl                /* 6015 */
        PTR     sys_pread64
        PTR     sys_pwrite64
@@ -159,7 +159,7 @@ EXPORT(sysn32_call_table)
        PTR     compat_sys_setitimer
        PTR     sys_alarm
        PTR     sys_getpid
-       PTR     sys32_sendfile
+       PTR     sys_32_sendfile
        PTR     sys_socket                      /* 6040 */
        PTR     sys_connect
        PTR     sys_accept
@@ -181,14 +181,14 @@ EXPORT(sysn32_call_table)
        PTR     sys_exit
        PTR     compat_sys_wait4
        PTR     sys_kill                        /* 6060 */
-       PTR     sys32_newuname
+       PTR     sys_32_newuname
        PTR     sys_semget
        PTR     sys_semop
-       PTR     sysn32_semctl
+       PTR     sys_n32_semctl
        PTR     sys_shmdt                       /* 6065 */
        PTR     sys_msgget
-       PTR     sysn32_msgsnd
-       PTR     sysn32_msgrcv
+       PTR     sys_n32_msgsnd
+       PTR     sys_n32_msgrcv
        PTR     compat_sys_msgctl
        PTR     compat_sys_fcntl                /* 6070 */
        PTR     sys_flock
@@ -245,15 +245,15 @@ EXPORT(sysn32_call_table)
        PTR     sys_getsid
        PTR     sys_capget
        PTR     sys_capset
-       PTR     sys32_rt_sigpending             /* 6125 */
+       PTR     sys_32_rt_sigpending            /* 6125 */
        PTR     compat_sys_rt_sigtimedwait
-       PTR     sys32_rt_sigqueueinfo
+       PTR     sys_32_rt_sigqueueinfo
        PTR     sysn32_rt_sigsuspend
        PTR     sys32_sigaltstack
        PTR     compat_sys_utime                /* 6130 */
        PTR     sys_mknod
-       PTR     sys32_personality
-       PTR     sys32_ustat
+       PTR     sys_32_personality
+       PTR     sys_32_ustat
        PTR     compat_sys_statfs
        PTR     compat_sys_fstatfs              /* 6135 */
        PTR     sys_sysfs
@@ -265,14 +265,14 @@ EXPORT(sysn32_call_table)
        PTR     sys_sched_getscheduler
        PTR     sys_sched_get_priority_max
        PTR     sys_sched_get_priority_min
-       PTR     sys32_sched_rr_get_interval     /* 6145 */
+       PTR     sys_32_sched_rr_get_interval    /* 6145 */
        PTR     sys_mlock
        PTR     sys_munlock
        PTR     sys_mlockall
        PTR     sys_munlockall
        PTR     sys_vhangup                     /* 6150 */
        PTR     sys_pivot_root
-       PTR     sys32_sysctl
+       PTR     sys_32_sysctl
        PTR     sys_prctl
        PTR     compat_sys_adjtimex
        PTR     compat_sys_setrlimit            /* 6155 */
index fefef4af8595493ec3c5414f3fb0fcaff14869b1..b0fef4ff9827610210ef3dc16d903d347491169d 100644 (file)
@@ -265,12 +265,12 @@ sys_call_table:
        PTR     sys_olduname
        PTR     sys_umask                       /* 4060 */
        PTR     sys_chroot
-       PTR     sys32_ustat
+       PTR     sys_32_ustat
        PTR     sys_dup2
        PTR     sys_getppid
        PTR     sys_getpgrp                     /* 4065 */
        PTR     sys_setsid
-       PTR     sys32_sigaction
+       PTR     sys_32_sigaction
        PTR     sys_sgetmask
        PTR     sys_ssetmask
        PTR     sys_setreuid                    /* 4070 */
@@ -293,7 +293,7 @@ sys_call_table:
        PTR     sys_swapon
        PTR     sys_reboot
        PTR     compat_sys_old_readdir
-       PTR     old_mmap                        /* 4090 */
+       PTR     sys_mips_mmap                   /* 4090 */
        PTR     sys_munmap
        PTR     sys_truncate
        PTR     sys_ftruncate
@@ -320,12 +320,12 @@ sys_call_table:
        PTR     compat_sys_wait4
        PTR     sys_swapoff                     /* 4115 */
        PTR     compat_sys_sysinfo
-       PTR     sys32_ipc
+       PTR     sys_32_ipc
        PTR     sys_fsync
        PTR     sys32_sigreturn
        PTR     sys32_clone                     /* 4120 */
        PTR     sys_setdomainname
-       PTR     sys32_newuname
+       PTR     sys_32_newuname
        PTR     sys_ni_syscall                  /* sys_modify_ldt */
        PTR     compat_sys_adjtimex
        PTR     sys_mprotect                    /* 4125 */
@@ -339,11 +339,11 @@ sys_call_table:
        PTR     sys_fchdir
        PTR     sys_bdflush
        PTR     sys_sysfs                       /* 4135 */
-       PTR     sys32_personality
+       PTR     sys_32_personality
        PTR     sys_ni_syscall                  /* for afs_syscall */
        PTR     sys_setfsuid
        PTR     sys_setfsgid
-       PTR     sys32_llseek                    /* 4140 */
+       PTR     sys_32_llseek                   /* 4140 */
        PTR     compat_sys_getdents
        PTR     compat_sys_select
        PTR     sys_flock
@@ -356,7 +356,7 @@ sys_call_table:
        PTR     sys_ni_syscall                  /* 4150 */
        PTR     sys_getsid
        PTR     sys_fdatasync
-       PTR     sys32_sysctl
+       PTR     sys_32_sysctl
        PTR     sys_mlock
        PTR     sys_munlock                     /* 4155 */
        PTR     sys_mlockall
@@ -368,7 +368,7 @@ sys_call_table:
        PTR     sys_sched_yield
        PTR     sys_sched_get_priority_max
        PTR     sys_sched_get_priority_min
-       PTR     sys32_sched_rr_get_interval     /* 4165 */
+       PTR     sys_32_sched_rr_get_interval    /* 4165 */
        PTR     compat_sys_nanosleep
        PTR     sys_mremap
        PTR     sys_accept
@@ -397,25 +397,25 @@ sys_call_table:
        PTR     sys_getresgid
        PTR     sys_prctl
        PTR     sys32_rt_sigreturn
-       PTR     sys32_rt_sigaction
-       PTR     sys32_rt_sigprocmask            /* 4195 */
-       PTR     sys32_rt_sigpending
+       PTR     sys_32_rt_sigaction
+       PTR     sys_32_rt_sigprocmask           /* 4195 */
+       PTR     sys_32_rt_sigpending
        PTR     compat_sys_rt_sigtimedwait
-       PTR     sys32_rt_sigqueueinfo
+       PTR     sys_32_rt_sigqueueinfo
        PTR     sys32_rt_sigsuspend
-       PTR     sys32_pread                     /* 4200 */
-       PTR     sys32_pwrite
+       PTR     sys_32_pread                    /* 4200 */
+       PTR     sys_32_pwrite
        PTR     sys_chown
        PTR     sys_getcwd
        PTR     sys_capget
        PTR     sys_capset                      /* 4205 */
        PTR     sys32_sigaltstack
-       PTR     sys32_sendfile
+       PTR     sys_32_sendfile
        PTR     sys_ni_syscall
        PTR     sys_ni_syscall
-       PTR     sys32_mmap2                     /* 4210 */
-       PTR     sys32_truncate64
-       PTR     sys32_ftruncate64
+       PTR     sys_mips_mmap2                  /* 4210 */
+       PTR     sys_32_truncate64
+       PTR     sys_32_ftruncate64
        PTR     sys_newstat
        PTR     sys_newlstat
        PTR     sys_newfstat                    /* 4215 */
@@ -481,7 +481,7 @@ sys_call_table:
        PTR     compat_sys_mq_notify            /* 4275 */
        PTR     compat_sys_mq_getsetattr
        PTR     sys_ni_syscall                  /* sys_vserver */
-       PTR     sys32_waitid
+       PTR     sys_32_waitid
        PTR     sys_ni_syscall                  /* available, was setaltroot */
        PTR     sys_add_key                     /* 4280 */
        PTR     sys_request_key
index a4e106c56ab5d1d6d28d8e823b66ea657f6a8aaa..830c5ef9932b389cbc4ad7f1410b750721a6b070 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/compiler.h>
+#include <linux/syscalls.h>
 #include <linux/uaccess.h>
 
 #include <asm/abi.h>
@@ -338,8 +339,8 @@ asmlinkage int sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
 }
 
 #ifdef CONFIG_TRAD_SIGNALS
-asmlinkage int sys_sigaction(int sig, const struct sigaction __user *act,
-       struct sigaction __user *oact)
+SYSCALL_DEFINE3(sigaction, int, sig, const struct sigaction __user *, act,
+       struct sigaction __user *oact)
 {
        struct k_sigaction new_ka, old_ka;
        int ret;
index 652709b353adf045be0a1e526910844f467dff0b..2e74075ac0cadcc7c64b92fa98f3a0d7794ae479 100644 (file)
@@ -349,8 +349,8 @@ asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
        return -ERESTARTNOHAND;
 }
 
-asmlinkage int sys32_sigaction(int sig, const struct sigaction32 __user *act,
-                               struct sigaction32 __user *oact)
+SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act,
+       struct sigaction32 __user *, oact)
 {
        struct k_sigaction new_ka, old_ka;
        int ret;
@@ -704,9 +704,9 @@ struct mips_abi mips_abi_32 = {
        .restart        = __NR_O32_restart_syscall
 };
 
-asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
-                                 struct sigaction32 __user *oact,
-                                 unsigned int sigsetsize)
+SYSCALL_DEFINE4(32_rt_sigaction, int, sig,
+       const struct sigaction32 __user *, act,
+       struct sigaction32 __user *, oact, unsigned int, sigsetsize)
 {
        struct k_sigaction new_sa, old_sa;
        int ret = -EINVAL;
@@ -748,8 +748,8 @@ out:
        return ret;
 }
 
-asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
-       compat_sigset_t __user *oset, unsigned int sigsetsize)
+SYSCALL_DEFINE4(32_rt_sigprocmask, int, how, compat_sigset_t __user *, set,
+       compat_sigset_t __user *, oset, unsigned int, sigsetsize)
 {
        sigset_t old_set, new_set;
        int ret;
@@ -770,8 +770,8 @@ asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
        return ret;
 }
 
-asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset,
-       unsigned int sigsetsize)
+SYSCALL_DEFINE2(32_rt_sigpending, compat_sigset_t __user *, uset,
+       unsigned int, sigsetsize)
 {
        int ret;
        sigset_t set;
@@ -787,7 +787,8 @@ asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset,
        return ret;
 }
 
-asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
+SYSCALL_DEFINE3(32_rt_sigqueueinfo, int, pid, int, sig,
+       compat_siginfo_t __user *, uinfo)
 {
        siginfo_t info;
        int ret;
@@ -802,10 +803,9 @@ asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *
        return ret;
 }
 
-asmlinkage long
-sys32_waitid(int which, compat_pid_t pid,
-            compat_siginfo_t __user *uinfo, int options,
-            struct compat_rusage __user *uru)
+SYSCALL_DEFINE5(32_waitid, int, which, compat_pid_t, pid,
+            compat_siginfo_t __user *, uinfo, int, options,
+            struct compat_rusage __user *, uru)
 {
        siginfo_t info;
        struct rusage ru;
index 37970d9b2186eed4f26d8b736d731f35fb5d7b72..8cf3846440401b682b01cf26aaa93ba25699c68c 100644 (file)
@@ -152,9 +152,9 @@ out:
        return error;
 }
 
-asmlinkage unsigned long
-old_mmap(unsigned long addr, unsigned long len, int prot,
-       int flags, int fd, off_t offset)
+SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
+       unsigned long, prot, unsigned long, flags, unsigned long,
+       fd, off_t, offset)
 {
        unsigned long result;
 
@@ -168,9 +168,9 @@ out:
        return result;
 }
 
-asmlinkage unsigned long
-sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
-          unsigned long flags, unsigned long fd, unsigned long pgoff)
+SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
+       unsigned long, prot, unsigned long, flags, unsigned long, fd,
+       unsigned long, pgoff)
 {
        if (pgoff & (~PAGE_MASK >> 12))
                return -EINVAL;
@@ -240,7 +240,7 @@ out:
 /*
  * Compacrapability ...
  */
-asmlinkage int sys_uname(struct old_utsname __user * name)
+SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
 {
        if (name && !copy_to_user(name, utsname(), sizeof (*name)))
                return 0;
@@ -250,7 +250,7 @@ asmlinkage int sys_uname(struct old_utsname __user * name)
 /*
  * Compacrapability ...
  */
-asmlinkage int sys_olduname(struct oldold_utsname __user * name)
+SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
 {
        int error;
 
@@ -279,7 +279,7 @@ asmlinkage int sys_olduname(struct oldold_utsname __user * name)
        return error;
 }
 
-asmlinkage int sys_set_thread_area(unsigned long addr)
+SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
 {
        struct thread_info *ti = task_thread_info(current);
 
@@ -290,7 +290,7 @@ asmlinkage int sys_set_thread_area(unsigned long addr)
        return 0;
 }
 
-asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
+asmlinkage int _sys_sysmips(long cmd, long arg1, long arg2, long arg3)
 {
        switch (cmd) {
        case MIPS_ATOMIC_SET:
@@ -325,8 +325,8 @@ asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
  *
  * This is really horribly ugly.
  */
-asmlinkage int sys_ipc(unsigned int call, int first, int second,
-                      unsigned long third, void __user *ptr, long fifth)
+SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, int, second,
+       unsigned long, third, void __user *, ptr, long, fifth)
 {
        int version, ret;
 
@@ -411,7 +411,7 @@ asmlinkage int sys_ipc(unsigned int call, int first, int second,
 /*
  * No implemented yet ...
  */
-asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
+SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op)
 {
        return -ENOSYS;
 }
index 98ad0a82c29e84cd35303809e3c473c6a7531e10..694d51f523d1fd8d5cbf057534e6031bf36f5327 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/linkage.h>
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/syscalls.h>
 #include <linux/mm.h>
 
 #include <asm/cacheflush.h>
@@ -58,8 +59,8 @@ EXPORT_SYMBOL(_dma_cache_wback_inv);
  * We could optimize the case where the cache argument is not BCACHE but
  * that seems very atypical use ...
  */
-asmlinkage int sys_cacheflush(unsigned long addr,
-       unsigned long bytes, unsigned int cache)
+SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes,
+       unsigned int, cache)
 {
        if (bytes == 0)
                return 0;
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 d811a8cd7b58c9397200be83cf0ee333c313e037..4774c2f92232b8ce98177d555b4d2c592dc076e5 100644 (file)
@@ -210,5 +210,10 @@ struct compat_shmid64_ds {
        compat_ulong_t __unused6;
 };
 
+static inline int is_compat_task(void)
+{
+       return test_thread_flag(TIF_32BIT);
+}
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_COMPAT_H */
index 853765eb1f6584e23edc6f1c8c3272814c0fa395..00c1d9133cfe12fa17db2d6f25a0f34c3e72ce20 100644 (file)
@@ -1,10 +1,6 @@
 #ifndef _ASM_POWERPC_SECCOMP_H
 #define _ASM_POWERPC_SECCOMP_H
 
-#ifdef __KERNEL__
-#include <linux/thread_info.h>
-#endif
-
 #include <linux/unistd.h>
 
 #define __NR_seccomp_read __NR_read
index ada06924a423b312e1e404c65a3d446e92fb31ea..73cb6a3229ae40f3da6a5b080f8757f486325872 100644 (file)
@@ -367,27 +367,24 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
 static int emulate_fp_pair(unsigned char __user *addr, unsigned int reg,
                           unsigned int flags)
 {
-       char *ptr = (char *) &current->thread.TS_FPR(reg);
-       int i, ret;
+       char *ptr0 = (char *) &current->thread.TS_FPR(reg);
+       char *ptr1 = (char *) &current->thread.TS_FPR(reg+1);
+       int i, ret, sw = 0;
 
        if (!(flags & F))
                return 0;
        if (reg & 1)
                return 0;       /* invalid form: FRS/FRT must be even */
-       if (!(flags & SW)) {
-               /* not byte-swapped - easy */
-               if (!(flags & ST))
-                       ret = __copy_from_user(ptr, addr, 16);
-               else
-                       ret = __copy_to_user(addr, ptr, 16);
-       } else {
-               /* each FPR value is byte-swapped separately */
-               ret = 0;
-               for (i = 0; i < 16; ++i) {
-                       if (!(flags & ST))
-                               ret |= __get_user(ptr[i^7], addr + i);
-                       else
-                               ret |= __put_user(ptr[i^7], addr + i);
+       if (flags & SW)
+               sw = 7;
+       ret = 0;
+       for (i = 0; i < 8; ++i) {
+               if (!(flags & ST)) {
+                       ret |= __get_user(ptr0[i^sw], addr + i);
+                       ret |= __get_user(ptr1[i^sw], addr + i + 8);
+               } else {
+                       ret |= __put_user(ptr0[i^sw], addr + i);
+                       ret |= __put_user(ptr1[i^sw], addr + i + 8);
                }
        }
        if (ret)
index 70693a5c12a113d36d55a0dd1800a255589e73a0..693b14a778fa152f4c595b22e30ca52bc724bee5 100644 (file)
@@ -62,18 +62,19 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 72:    std     r8,8(r3)
        beq+    3f
        addi    r3,r3,16
-23:    ld      r9,8(r4)
 .Ldo_tail:
        bf      cr7*4+1,1f
-       rotldi  r9,r9,32
+23:    lwz     r9,8(r4)
+       addi    r4,r4,4
 73:    stw     r9,0(r3)
        addi    r3,r3,4
 1:     bf      cr7*4+2,2f
-       rotldi  r9,r9,16
+44:    lhz     r9,8(r4)
+       addi    r4,r4,2
 74:    sth     r9,0(r3)
        addi    r3,r3,2
 2:     bf      cr7*4+3,3f
-       rotldi  r9,r9,8
+45:    lbz     r9,8(r4)
 75:    stb     r9,0(r3)
 3:     li      r3,0
        blr
@@ -141,11 +142,24 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 6:     cmpwi   cr1,r5,8
        addi    r3,r3,32
        sld     r9,r9,r10
-       ble     cr1,.Ldo_tail
+       ble     cr1,7f
 34:    ld      r0,8(r4)
        srd     r7,r0,r11
        or      r9,r7,r9
-       b       .Ldo_tail
+7:
+       bf      cr7*4+1,1f
+       rotldi  r9,r9,32
+94:    stw     r9,0(r3)
+       addi    r3,r3,4
+1:     bf      cr7*4+2,2f
+       rotldi  r9,r9,16
+95:    sth     r9,0(r3)
+       addi    r3,r3,2
+2:     bf      cr7*4+3,3f
+       rotldi  r9,r9,8
+96:    stb     r9,0(r3)
+3:     li      r3,0
+       blr
 
 .Ldst_unaligned:
        PPC_MTOCRF      0x01,r6         /* put #bytes to 8B bdry into cr7 */
@@ -218,7 +232,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 121:
 132:
        addi    r3,r3,8
-123:
 134:
 135:
 138:
@@ -226,6 +239,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 140:
 141:
 142:
+123:
+144:
+145:
 
 /*
  * here we have had a fault on a load and r3 points to the first
@@ -309,6 +325,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 187:
 188:
 189:   
+194:
+195:
+196:
 1:
        ld      r6,-24(r1)
        ld      r5,-8(r1)
@@ -329,7 +348,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
        .llong  72b,172b
        .llong  23b,123b
        .llong  73b,173b
+       .llong  44b,144b
        .llong  74b,174b
+       .llong  45b,145b
        .llong  75b,175b
        .llong  24b,124b
        .llong  25b,125b
@@ -347,6 +368,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
        .llong  79b,179b
        .llong  80b,180b
        .llong  34b,134b
+       .llong  94b,194b
+       .llong  95b,195b
+       .llong  96b,196b
        .llong  35b,135b
        .llong  81b,181b
        .llong  36b,136b
index fe2d34e5332d8250dd778ca77489631e2a4e9266..e178922b2c2129e808a427464ce8fccc34643309 100644 (file)
@@ -53,18 +53,19 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 3:     std     r8,8(r3)
        beq     3f
        addi    r3,r3,16
-       ld      r9,8(r4)
 .Ldo_tail:
        bf      cr7*4+1,1f
-       rotldi  r9,r9,32
+       lwz     r9,8(r4)
+       addi    r4,r4,4
        stw     r9,0(r3)
        addi    r3,r3,4
 1:     bf      cr7*4+2,2f
-       rotldi  r9,r9,16
+       lhz     r9,8(r4)
+       addi    r4,r4,2
        sth     r9,0(r3)
        addi    r3,r3,2
 2:     bf      cr7*4+3,3f
-       rotldi  r9,r9,8
+       lbz     r9,8(r4)
        stb     r9,0(r3)
 3:     ld      r3,48(r1)       /* return dest pointer */
        blr
@@ -133,11 +134,24 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
        cmpwi   cr1,r5,8
        addi    r3,r3,32
        sld     r9,r9,r10
-       ble     cr1,.Ldo_tail
+       ble     cr1,6f
        ld      r0,8(r4)
        srd     r7,r0,r11
        or      r9,r7,r9
-       b       .Ldo_tail
+6:
+       bf      cr7*4+1,1f
+       rotldi  r9,r9,32
+       stw     r9,0(r3)
+       addi    r3,r3,4
+1:     bf      cr7*4+2,2f
+       rotldi  r9,r9,16
+       sth     r9,0(r3)
+       addi    r3,r3,2
+2:     bf      cr7*4+3,3f
+       rotldi  r9,r9,8
+       stb     r9,0(r3)
+3:     ld      r3,48(r1)       /* return dest pointer */
+       blr
 
 .Ldst_unaligned:
        PPC_MTOCRF      0x01,r6         # put #bytes to 8B bdry into cr7
index fb371f5ce132c657ab910824d6d4c998b59c574d..d6b772ba3b8f8238ea3ecd5d27c2b77843b9dcda 100644 (file)
@@ -142,6 +142,10 @@ static void __init gef_sbc610_nec_fixup(struct pci_dev *pdev)
 {
        unsigned int val;
 
+       /* Do not do the fixup on other platforms! */
+       if (!machine_is(gef_sbc610))
+               return;
+
        printk(KERN_INFO "Running NEC uPD720101 Fixup\n");
 
        /* Ensure ports 1, 2, 3, 4 & 5 are enabled */
index 77fae5f64f2e0741ff6900135f9337cfac6093b0..5558d932b4d5c87b84f5a3826577607fa5220514 100644 (file)
@@ -204,6 +204,23 @@ static int __init ppc4xx_setup_one_pci_PMM(struct pci_controller   *hose,
 {
        u32 ma, pcila, pciha;
 
+       /* Hack warning ! The "old" PCI 2.x cell only let us configure the low
+        * 32-bit of incoming PLB addresses. The top 4 bits of the 36-bit
+        * address are actually hard wired to a value that appears to depend
+        * on the specific SoC. For example, it's 0 on 440EP and 1 on 440EPx.
+        *
+        * The trick here is we just crop those top bits and ignore them when
+        * programming the chip. That means the device-tree has to be right
+        * for the specific part used (we don't print a warning if it's wrong
+        * but on the other hand, you'll crash quickly enough), but at least
+        * this code should work whatever the hard coded value is
+        */
+       plb_addr &= 0xffffffffull;
+
+       /* Note: Due to the above hack, the test below doesn't actually test
+        * if you address is above 4G, but it tests that address and
+        * (address + size) are both contained in the same 4G
+        */
        if ((plb_addr + size) > 0xffffffffull || !is_power_of_2(size) ||
            size < 0x1000 || (plb_addr & (size - 1)) != 0) {
                printk(KERN_WARNING "%s: Resource out of range\n",
index c42cd898f68bfdece3e98706e44ab048abe61038..6118890c946d89244e587cdc880726a1d7893073 100644 (file)
@@ -556,7 +556,7 @@ static void __exit aes_s390_fini(void)
 module_init(aes_s390_init);
 module_exit(aes_s390_fini);
 
-MODULE_ALIAS("aes");
+MODULE_ALIAS("aes-all");
 
 MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
 MODULE_LICENSE("GPL");
index 7c35787d29b45b22a41c58bb57491137df7f4db4..72da416f6162bbd10d022f5452708ec48d42910a 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_gpio.h>
-#include <media/ov772x.h>
 #include <media/soc_camera_platform.h>
 #include <media/sh_mobile_ceu.h>
 #include <video/sh_mobile_lcdc.h>
@@ -224,7 +223,6 @@ static void camera_power(int val)
 }
 
 #ifdef CONFIG_I2C
-/* support for the old ncm03j camera */
 static unsigned char camera_ncm03j_magic[] =
 {
        0x87, 0x00, 0x88, 0x08, 0x89, 0x01, 0x8A, 0xE8,
@@ -245,23 +243,6 @@ static unsigned char camera_ncm03j_magic[] =
        0x63, 0xD4, 0x64, 0xEA, 0xD6, 0x0F,
 };
 
-static int camera_probe(void)
-{
-       struct i2c_adapter *a = i2c_get_adapter(0);
-       struct i2c_msg msg;
-       int ret;
-
-       camera_power(1);
-       msg.addr = 0x6e;
-       msg.buf = camera_ncm03j_magic;
-       msg.len = 2;
-       msg.flags = 0;
-       ret = i2c_transfer(a, &msg, 1);
-       camera_power(0);
-
-       return ret;
-}
-
 static int camera_set_capture(struct soc_camera_platform_info *info,
                              int enable)
 {
@@ -313,35 +294,8 @@ static struct platform_device camera_device = {
                .platform_data  = &camera_info,
        },
 };
-
-static int __init camera_setup(void)
-{
-       if (camera_probe() > 0)
-               platform_device_register(&camera_device);
-
-       return 0;
-}
-late_initcall(camera_setup);
-
 #endif /* CONFIG_I2C */
 
-static int ov7725_power(struct device *dev, int mode)
-{
-       camera_power(0);
-       if (mode)
-               camera_power(1);
-
-       return 0;
-}
-
-static struct ov772x_camera_info ov7725_info = {
-       .buswidth  = SOCAM_DATAWIDTH_8,
-       .flags = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP,
-       .link = {
-               .power  = ov7725_power,
-       },
-};
-
 static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
        .flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
        SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
@@ -392,6 +346,9 @@ static struct platform_device *ap325rxa_devices[] __initdata = {
        &ap325rxa_nor_flash_device,
        &lcdc_device,
        &ceu_device,
+#ifdef CONFIG_I2C
+       &camera_device,
+#endif
        &nand_flash_device,
        &sdcard_cn3_device,
 };
@@ -400,10 +357,6 @@ static struct i2c_board_info __initdata ap325rxa_i2c_devices[] = {
        {
                I2C_BOARD_INFO("pcf8563", 0x51),
        },
-       {
-               I2C_BOARD_INFO("ov772x", 0x21),
-               .platform_data = &ov7725_info,
-       },
 };
 
 static struct spi_board_info ap325rxa_spi_devices[] = {
index 020a96fe961a0b1cfa682cd919b22ab4f3af92cf..4a5e59732334ca70782a167c5eccaf4e133b9ffd 100644 (file)
@@ -18,8 +18,8 @@
 #include <asm/freq.h>
 #include <asm/io.h>
 
-const static int pll1rate[]={1,2,3,4,6,8};
-const static int pfc_divisors[]={1,2,3,4,6,8,12};
+static const int pll1rate[]={1,2,3,4,6,8};
+static const int pfc_divisors[]={1,2,3,4,6,8,12};
 #define ifc_divisors pfc_divisors
 
 #if (CONFIG_SH_CLK_MD == 0)
index f260b58f5ce9d34ac224d2781bf4e0ac277849d4..0e706257918f35397b10657be3b95538ef23e45b 100644 (file)
@@ -240,4 +240,9 @@ struct compat_shmid64_ds {
        unsigned int    __unused2;
 };
 
+static inline int is_compat_task(void)
+{
+       return test_thread_flag(TIF_32BIT);
+}
+
 #endif /* _ASM_SPARC64_COMPAT_H */
index 7fcd9968192bc0b26b1fe7d1c67a1e3f08b5359c..adca1bce41d4a2b96632a1dfdcdab457df916bf1 100644 (file)
@@ -1,11 +1,5 @@
 #ifndef _ASM_SECCOMP_H
 
-#include <linux/thread_info.h> /* already defines TIF_32BIT */
-
-#ifndef TIF_32BIT
-#error "unexpected TIF_32BIT on sparc64"
-#endif
-
 #include <linux/unistd.h>
 
 #define __NR_seccomp_read __NR_read
index 3b9f4d6e14a9d3119a939e7b5edfc3aec30c554b..e1a9598e2a4db8b0c0cc36aca1c7ac5addb1dbc5 100644 (file)
@@ -306,6 +306,7 @@ static int jbusmc_print_dimm(int syndrome_code,
                buf[1] = '?';
                buf[2] = '?';
                buf[3] = '\0';
+               return 0;
        }
        p = dp->controller;
        prop = &p->layout;
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 9c39095b33fc0d1dbdc7f92408314dae1ed38e87..bc2fbadff9f90fe681d9c30ae621d1ec94e348cf 100644 (file)
@@ -1803,7 +1803,7 @@ config DMAR
          remapping devices.
 
 config DMAR_DEFAULT_ON
-       def_bool n
+       def_bool y
        prompt "Enable DMA Remapping Devices by default"
        depends on DMAR
        help
index c1f06289b14b31b82834fa623c7ac744a7aa55be..86af26091d6c3c2146da4e5f6f3abbfd6cb165ba 100644 (file)
@@ -23,6 +23,9 @@
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 
+int
+is_io_mapping_possible(resource_size_t base, unsigned long size);
+
 void *
 iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
 
index a6ad87b352c448e8b1f2c2b3e3dd9591fe593248..b811d6f5780cd261a8e33a7799d3bd50aa46015b 100644 (file)
@@ -1,12 +1,6 @@
 #ifndef _ASM_X86_SECCOMP_32_H
 #define _ASM_X86_SECCOMP_32_H
 
-#include <linux/thread_info.h>
-
-#ifdef TIF_32BIT
-#error "unexpected TIF_32BIT on i386"
-#endif
-
 #include <linux/unistd.h>
 
 #define __NR_seccomp_read __NR_read
index 4171bb794e9e736bbfcb60588a4e9d81d1edcb31..84ec1bd161a5839bdce90c4f8ed80f53bd45f03e 100644 (file)
@@ -1,14 +1,6 @@
 #ifndef _ASM_X86_SECCOMP_64_H
 #define _ASM_X86_SECCOMP_64_H
 
-#include <linux/thread_info.h>
-
-#ifdef TIF_32BIT
-#error "unexpected TIF_32BIT on x86_64"
-#else
-#define TIF_32BIT TIF_IA32
-#endif
-
 #include <linux/unistd.h>
 #include <asm/ia32_unistd.h>
 
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 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 25cf624eccb781d6c5e942e24989a77adc6427d0..fe79985ce0f2f6fb4ae23f3bc92a791994ed9f62 100644 (file)
@@ -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:
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 5a4c23d898926149e65b8cb5d826b7e868f4a527..06ca07f6ad86243884c7852c13334d9da9604acf 100644 (file)
@@ -1388,7 +1388,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
 #ifdef CONFIG_X86_32
 # define IS_IA32       1
 #elif defined CONFIG_IA32_EMULATION
-# define IS_IA32       test_thread_flag(TIF_IA32)
+# define IS_IA32       is_compat_task()
 #else
 # define IS_IA32       0
 #endif
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 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 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 7ffcdeec4631fa7b1adf54ec2bbbd71ee98402ba..b9cc84a2a4fc7ae200540e120518f20bd6408ba9 100644 (file)
@@ -65,7 +65,7 @@ static volatile unsigned long smp_invalidate_needed;
 
 /* Bitmask of CPUs present in the system - exported by i386_syms.c, used
  * by scheduler but indexed physically */
-cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
+static cpumask_t voyager_phys_cpu_present_map = CPU_MASK_NONE;
 
 /* The internal functions */
 static void send_CPI(__u32 cpuset, __u8 cpi);
@@ -366,19 +366,19 @@ void __init find_smp_config(void)
        /* set up everything for just this CPU, we can alter
         * this as we start the other CPUs later */
        /* now get the CPU disposition from the extended CMOS */
-       cpus_addr(phys_cpu_present_map)[0] =
+       cpus_addr(voyager_phys_cpu_present_map)[0] =
            voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK);
-       cpus_addr(phys_cpu_present_map)[0] |=
+       cpus_addr(voyager_phys_cpu_present_map)[0] |=
            voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK + 1) << 8;
-       cpus_addr(phys_cpu_present_map)[0] |=
+       cpus_addr(voyager_phys_cpu_present_map)[0] |=
            voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK +
                                       2) << 16;
-       cpus_addr(phys_cpu_present_map)[0] |=
+       cpus_addr(voyager_phys_cpu_present_map)[0] |=
            voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK +
                                       3) << 24;
-       init_cpu_possible(&phys_cpu_present_map);
-       printk("VOYAGER SMP: phys_cpu_present_map = 0x%lx\n",
-              cpus_addr(phys_cpu_present_map)[0]);
+       init_cpu_possible(&voyager_phys_cpu_present_map);
+       printk("VOYAGER SMP: voyager_phys_cpu_present_map = 0x%lx\n",
+              cpus_addr(voyager_phys_cpu_present_map)[0]);
        /* Here we set up the VIC to enable SMP */
        /* enable the CPIs by writing the base vector to their register */
        outb(VIC_DEFAULT_CPI_BASE, VIC_CPI_BASE_REGISTER);
@@ -628,15 +628,15 @@ void __init smp_boot_cpus(void)
                /* now that the cat has probed the Voyager System Bus, sanity
                 * check the cpu map */
                if (((voyager_quad_processors | voyager_extended_vic_processors)
-                    & cpus_addr(phys_cpu_present_map)[0]) !=
-                   cpus_addr(phys_cpu_present_map)[0]) {
+                    & cpus_addr(voyager_phys_cpu_present_map)[0]) !=
+                   cpus_addr(voyager_phys_cpu_present_map)[0]) {
                        /* should panic */
                        printk("\n\n***WARNING*** "
                               "Sanity check of CPU present map FAILED\n");
                }
        } else if (voyager_level == 4)
                voyager_extended_vic_processors =
-                   cpus_addr(phys_cpu_present_map)[0];
+                   cpus_addr(voyager_phys_cpu_present_map)[0];
 
        /* this sets up the idle task to run on the current cpu */
        voyager_extended_cpus = 1;
@@ -670,7 +670,7 @@ void __init smp_boot_cpus(void)
        /* loop over all the extended VIC CPUs and boot them.  The
         * Quad CPUs must be bootstrapped by their extended VIC cpu */
        for (i = 0; i < nr_cpu_ids; i++) {
-               if (i == boot_cpu_id || !cpu_isset(i, phys_cpu_present_map))
+               if (i == boot_cpu_id || !cpu_isset(i, voyager_phys_cpu_present_map))
                        continue;
                do_boot_cpu(i);
                /* This udelay seems to be needed for the Quad boots
index e6d36b490250bed6952f2d93de3d1f337c3cf7f4..b1352250096e0d734ea4a03650e7d92ae8c2d8ba 100644 (file)
@@ -714,6 +714,8 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
        pos = start_pfn << PAGE_SHIFT;
        end_pfn = ((pos + (PMD_SIZE - 1)) >> PMD_SHIFT)
                        << (PMD_SHIFT - PAGE_SHIFT);
+       if (end_pfn > (end >> PAGE_SHIFT))
+               end_pfn = end >> PAGE_SHIFT;
        if (start_pfn < end_pfn) {
                nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
                pos = end_pfn << PAGE_SHIFT;
index ca53224fc56c8eeb1c57feccdccf93e09c25b2cb..04102d42ff4250873a519620958855e9b50770ff 100644 (file)
 #include <asm/pat.h>
 #include <linux/module.h>
 
+int is_io_mapping_possible(resource_size_t base, unsigned long size)
+{
+#ifndef CONFIG_X86_PAE
+       /* There is no way to map greater than 1 << 32 address without PAE */
+       if (base + size > 0x100000000ULL)
+               return 0;
+#endif
+       return 1;
+}
+EXPORT_SYMBOL_GPL(is_io_mapping_possible);
+
 /* Map 'pfn' using fixed map 'type' and protections 'prot'
  */
 void *
index 93d82038af4b541853420a48502df0fc4c9c2407..9f205030d9aac6a6dbdb6f620b47fcba8b4acb2f 100644 (file)
@@ -32,11 +32,14 @@ struct kmmio_fault_page {
        struct list_head list;
        struct kmmio_fault_page *release_next;
        unsigned long page; /* location of the fault page */
+       bool old_presence; /* page presence prior to arming */
+       bool armed;
 
        /*
         * Number of times this page has been registered as a part
         * of a probe. If zero, page is disarmed and this may be freed.
-        * Used only by writers (RCU).
+        * Used only by writers (RCU) and post_kmmio_handler().
+        * Protected by kmmio_lock, when linked into kmmio_page_table.
         */
        int count;
 };
@@ -105,57 +108,85 @@ static struct kmmio_fault_page *get_kmmio_fault_page(unsigned long page)
        return NULL;
 }
 
-static void set_page_present(unsigned long addr, bool present,
-                                                       unsigned int *pglevel)
+static void set_pmd_presence(pmd_t *pmd, bool present, bool *old)
+{
+       pmdval_t v = pmd_val(*pmd);
+       *old = !!(v & _PAGE_PRESENT);
+       v &= ~_PAGE_PRESENT;
+       if (present)
+               v |= _PAGE_PRESENT;
+       set_pmd(pmd, __pmd(v));
+}
+
+static void set_pte_presence(pte_t *pte, bool present, bool *old)
+{
+       pteval_t v = pte_val(*pte);
+       *old = !!(v & _PAGE_PRESENT);
+       v &= ~_PAGE_PRESENT;
+       if (present)
+               v |= _PAGE_PRESENT;
+       set_pte_atomic(pte, __pte(v));
+}
+
+static int set_page_presence(unsigned long addr, bool present, bool *old)
 {
-       pteval_t pteval;
-       pmdval_t pmdval;
        unsigned int level;
-       pmd_t *pmd;
        pte_t *pte = lookup_address(addr, &level);
 
        if (!pte) {
                pr_err("kmmio: no pte for page 0x%08lx\n", addr);
-               return;
+               return -1;
        }
 
-       if (pglevel)
-               *pglevel = level;
-
        switch (level) {
        case PG_LEVEL_2M:
-               pmd = (pmd_t *)pte;
-               pmdval = pmd_val(*pmd) & ~_PAGE_PRESENT;
-               if (present)
-                       pmdval |= _PAGE_PRESENT;
-               set_pmd(pmd, __pmd(pmdval));
+               set_pmd_presence((pmd_t *)pte, present, old);
                break;
-
        case PG_LEVEL_4K:
-               pteval = pte_val(*pte) & ~_PAGE_PRESENT;
-               if (present)
-                       pteval |= _PAGE_PRESENT;
-               set_pte_atomic(pte, __pte(pteval));
+               set_pte_presence(pte, present, old);
                break;
-
        default:
                pr_err("kmmio: unexpected page level 0x%x.\n", level);
-               return;
+               return -1;
        }
 
        __flush_tlb_one(addr);
+       return 0;
 }
 
-/** Mark the given page as not present. Access to it will trigger a fault. */
-static void arm_kmmio_fault_page(unsigned long page, unsigned int *pglevel)
+/*
+ * Mark the given page as not present. Access to it will trigger a fault.
+ *
+ * Struct kmmio_fault_page is protected by RCU and kmmio_lock, but the
+ * protection is ignored here. RCU read lock is assumed held, so the struct
+ * will not disappear unexpectedly. Furthermore, the caller must guarantee,
+ * that double arming the same virtual address (page) cannot occur.
+ *
+ * Double disarming on the other hand is allowed, and may occur when a fault
+ * and mmiotrace shutdown happen simultaneously.
+ */
+static int arm_kmmio_fault_page(struct kmmio_fault_page *f)
 {
-       set_page_present(page & PAGE_MASK, false, pglevel);
+       int ret;
+       WARN_ONCE(f->armed, KERN_ERR "kmmio page already armed.\n");
+       if (f->armed) {
+               pr_warning("kmmio double-arm: page 0x%08lx, ref %d, old %d\n",
+                                       f->page, f->count, f->old_presence);
+       }
+       ret = set_page_presence(f->page, false, &f->old_presence);
+       WARN_ONCE(ret < 0, KERN_ERR "kmmio arming 0x%08lx failed.\n", f->page);
+       f->armed = true;
+       return ret;
 }
 
-/** Mark the given page as present. */
-static void disarm_kmmio_fault_page(unsigned long page, unsigned int *pglevel)
+/** Restore the given page to saved presence state. */
+static void disarm_kmmio_fault_page(struct kmmio_fault_page *f)
 {
-       set_page_present(page & PAGE_MASK, true, pglevel);
+       bool tmp;
+       int ret = set_page_presence(f->page, f->old_presence, &tmp);
+       WARN_ONCE(ret < 0,
+                       KERN_ERR "kmmio disarming 0x%08lx failed.\n", f->page);
+       f->armed = false;
 }
 
 /*
@@ -202,28 +233,32 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr)
 
        ctx = &get_cpu_var(kmmio_ctx);
        if (ctx->active) {
-               disarm_kmmio_fault_page(faultpage->page, NULL);
                if (addr == ctx->addr) {
                        /*
-                        * On SMP we sometimes get recursive probe hits on the
-                        * same address. Context is already saved, fall out.
+                        * A second fault on the same page means some other
+                        * condition needs handling by do_page_fault(), the
+                        * page really not being present is the most common.
                         */
-                       pr_debug("kmmio: duplicate probe hit on CPU %d, for "
-                                               "address 0x%08lx.\n",
-                                               smp_processor_id(), addr);
-                       ret = 1;
-                       goto no_kmmio_ctx;
-               }
-               /*
-                * Prevent overwriting already in-flight context.
-                * This should not happen, let's hope disarming at least
-                * prevents a panic.
-                */
-               pr_emerg("kmmio: recursive probe hit on CPU %d, "
+                       pr_debug("kmmio: secondary hit for 0x%08lx CPU %d.\n",
+                                       addr, smp_processor_id());
+
+                       if (!faultpage->old_presence)
+                               pr_info("kmmio: unexpected secondary hit for "
+                                       "address 0x%08lx on CPU %d.\n", addr,
+                                       smp_processor_id());
+               } else {
+                       /*
+                        * Prevent overwriting already in-flight context.
+                        * This should not happen, let's hope disarming at
+                        * least prevents a panic.
+                        */
+                       pr_emerg("kmmio: recursive probe hit on CPU %d, "
                                        "for address 0x%08lx. Ignoring.\n",
                                        smp_processor_id(), addr);
-               pr_emerg("kmmio: previous hit was at 0x%08lx.\n",
-                                       ctx->addr);
+                       pr_emerg("kmmio: previous hit was at 0x%08lx.\n",
+                                               ctx->addr);
+                       disarm_kmmio_fault_page(faultpage);
+               }
                goto no_kmmio_ctx;
        }
        ctx->active++;
@@ -244,7 +279,7 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr)
        regs->flags &= ~X86_EFLAGS_IF;
 
        /* Now we set present bit in PTE and single step. */
-       disarm_kmmio_fault_page(ctx->fpage->page, NULL);
+       disarm_kmmio_fault_page(ctx->fpage);
 
        /*
         * If another cpu accesses the same page while we are stepping,
@@ -275,7 +310,7 @@ static int post_kmmio_handler(unsigned long condition, struct pt_regs *regs)
        struct kmmio_context *ctx = &get_cpu_var(kmmio_ctx);
 
        if (!ctx->active) {
-               pr_debug("kmmio: spurious debug trap on CPU %d.\n",
+               pr_warning("kmmio: spurious debug trap on CPU %d.\n",
                                                        smp_processor_id());
                goto out;
        }
@@ -283,7 +318,11 @@ static int post_kmmio_handler(unsigned long condition, struct pt_regs *regs)
        if (ctx->probe && ctx->probe->post_handler)
                ctx->probe->post_handler(ctx->probe, condition, regs);
 
-       arm_kmmio_fault_page(ctx->fpage->page, NULL);
+       /* Prevent racing against release_kmmio_fault_page(). */
+       spin_lock(&kmmio_lock);
+       if (ctx->fpage->count)
+               arm_kmmio_fault_page(ctx->fpage);
+       spin_unlock(&kmmio_lock);
 
        regs->flags &= ~X86_EFLAGS_TF;
        regs->flags |= ctx->saved_flags;
@@ -315,20 +354,24 @@ static int add_kmmio_fault_page(unsigned long page)
        f = get_kmmio_fault_page(page);
        if (f) {
                if (!f->count)
-                       arm_kmmio_fault_page(f->page, NULL);
+                       arm_kmmio_fault_page(f);
                f->count++;
                return 0;
        }
 
-       f = kmalloc(sizeof(*f), GFP_ATOMIC);
+       f = kzalloc(sizeof(*f), GFP_ATOMIC);
        if (!f)
                return -1;
 
        f->count = 1;
        f->page = page;
-       list_add_rcu(&f->list, kmmio_page_list(f->page));
 
-       arm_kmmio_fault_page(f->page, NULL);
+       if (arm_kmmio_fault_page(f)) {
+               kfree(f);
+               return -1;
+       }
+
+       list_add_rcu(&f->list, kmmio_page_list(f->page));
 
        return 0;
 }
@@ -347,7 +390,7 @@ static void release_kmmio_fault_page(unsigned long page,
        f->count--;
        BUG_ON(f->count < 0);
        if (!f->count) {
-               disarm_kmmio_fault_page(f->page, NULL);
+               disarm_kmmio_fault_page(f);
                f->release_next = *release_list;
                *release_list = f;
        }
index 8ca0d8566fc826cb8f7f42b05133c4498da59e64..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:
index aebbf67a79d02326724e91065180675ecb525637..e0ab173b6974ba4e7f150adf480fd6e603a5c20c 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/bootmem.h>
 #include <linux/debugfs.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
@@ -868,6 +869,7 @@ pgprot_t pgprot_writecombine(pgprot_t prot)
        else
                return pgprot_noncached(prot);
 }
+EXPORT_SYMBOL_GPL(pgprot_writecombine);
 
 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT)
 
index ab50a8d7402c8c7f4320f0fd803a22a2d9abf84a..427fd1b56df5540f6a871f31c99c92af4f3edacd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Written by Pekka Paalanen, 2008 <pq@iki.fi>
+ * Written by Pekka Paalanen, 2008-2009 <pq@iki.fi>
  */
 #include <linux/module.h>
 #include <linux/io.h>
@@ -9,35 +9,74 @@
 
 static unsigned long mmio_address;
 module_param(mmio_address, ulong, 0);
-MODULE_PARM_DESC(mmio_address, "Start address of the mapping of 16 kB.");
+MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB "
+                               "(or 8 MB if read_far is non-zero).");
+
+static unsigned long read_far = 0x400100;
+module_param(read_far, ulong, 0);
+MODULE_PARM_DESC(read_far, " Offset of a 32-bit read within 8 MB "
+                               "(default: 0x400100).");
+
+static unsigned v16(unsigned i)
+{
+       return i * 12 + 7;
+}
+
+static unsigned v32(unsigned i)
+{
+       return i * 212371 + 13;
+}
 
 static void do_write_test(void __iomem *p)
 {
        unsigned int i;
+       pr_info(MODULE_NAME ": write test.\n");
        mmiotrace_printk("Write test.\n");
+
        for (i = 0; i < 256; i++)
                iowrite8(i, p + i);
+
        for (i = 1024; i < (5 * 1024); i += 2)
-               iowrite16(i * 12 + 7, p + i);
+               iowrite16(v16(i), p + i);
+
        for (i = (5 * 1024); i < (16 * 1024); i += 4)
-               iowrite32(i * 212371 + 13, p + i);
+               iowrite32(v32(i), p + i);
 }
 
 static void do_read_test(void __iomem *p)
 {
        unsigned int i;
+       unsigned errs[3] = { 0 };
+       pr_info(MODULE_NAME ": read test.\n");
        mmiotrace_printk("Read test.\n");
+
        for (i = 0; i < 256; i++)
-               ioread8(p + i);
+               if (ioread8(p + i) != i)
+                       ++errs[0];
+
        for (i = 1024; i < (5 * 1024); i += 2)
-               ioread16(p + i);
+               if (ioread16(p + i) != v16(i))
+                       ++errs[1];
+
        for (i = (5 * 1024); i < (16 * 1024); i += 4)
-               ioread32(p + i);
+               if (ioread32(p + i) != v32(i))
+                       ++errs[2];
+
+       mmiotrace_printk("Read errors: 8-bit %d, 16-bit %d, 32-bit %d.\n",
+                                               errs[0], errs[1], errs[2]);
 }
 
-static void do_test(void)
+static void do_read_far_test(void __iomem *p)
 {
-       void __iomem *p = ioremap_nocache(mmio_address, 0x4000);
+       pr_info(MODULE_NAME ": read far test.\n");
+       mmiotrace_printk("Read far test.\n");
+
+       ioread32(p + read_far);
+}
+
+static void do_test(unsigned long size)
+{
+       void __iomem *p = ioremap_nocache(mmio_address, size);
        if (!p) {
                pr_err(MODULE_NAME ": could not ioremap, aborting.\n");
                return;
@@ -45,11 +84,15 @@ static void do_test(void)
        mmiotrace_printk("ioremap returned %p.\n", p);
        do_write_test(p);
        do_read_test(p);
+       if (read_far && read_far < size - 4)
+               do_read_far_test(p);
        iounmap(p);
 }
 
 static int __init init(void)
 {
+       unsigned long size = (read_far) ? (8 << 20) : (16 << 10);
+
        if (mmio_address == 0) {
                pr_err(MODULE_NAME ": you have to use the module argument "
                                                        "mmio_address.\n");
@@ -58,10 +101,11 @@ static int __init init(void)
                return -ENXIO;
        }
 
-       pr_warning(MODULE_NAME ": WARNING: mapping 16 kB @ 0x%08lx "
-                                       "in PCI address space, and writing "
-                                       "rubbish in there.\n", mmio_address);
-       do_test();
+       pr_warning(MODULE_NAME ": WARNING: mapping %lu kB @ 0x%08lx in PCI "
+               "address space, and writing 16 kB of rubbish in there.\n",
+                size >> 10, mmio_address);
+       do_test(size);
+       pr_info(MODULE_NAME ": All done.\n");
        return 0;
 }
 
index e9f80c744cf3409d72f77dd9044ec1dd90534609..10131fbdaadada1781bddde6749e83a4cb200a8f 100644 (file)
@@ -78,8 +78,18 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
        if (cpu_has_arch_perfmon) {
                union cpuid10_eax eax;
                eax.full = cpuid_eax(0xa);
-               if (counter_width < eax.split.bit_width)
-                       counter_width = eax.split.bit_width;
+
+               /*
+                * For Core2 (family 6, model 15), don't reset the
+                * counter width:
+                */
+               if (!(eax.split.version_id == 0 &&
+                       current_cpu_data.x86 == 6 &&
+                               current_cpu_data.x86_model == 15)) {
+
+                       if (counter_width < eax.split.bit_width)
+                               counter_width = eax.split.bit_width;
+               }
        }
 
        /* clear all counters */
index bea215230b20cdf4fc41ac5fd4e060dcbaec4ec1..b58e9633814923aa5e13cd2f491086830528db6a 100644 (file)
@@ -1672,6 +1672,9 @@ asmlinkage void __init xen_start_kernel(void)
           possible map and a non-dummy shared_info. */
        per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
 
+       local_irq_disable();
+       early_boot_irqs_off();
+
        xen_raw_console_write("mapping kernel into physical memory\n");
        pgd = xen_setup_kernel_pagetable(pgd, xen_start_info->nr_pages);
 
index b92f5b0866b0972b80e5b7f69e1fae046608a90b..a104593e70c38cdfdaebc1cf1214934e37ce3284 100644 (file)
@@ -38,72 +38,84 @@ void blk_recalc_rq_sectors(struct request *rq, int nsect)
        }
 }
 
-void blk_recalc_rq_segments(struct request *rq)
+static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
+                                            struct bio *bio,
+                                            unsigned int *seg_size_ptr)
 {
-       int nr_phys_segs;
        unsigned int phys_size;
        struct bio_vec *bv, *bvprv = NULL;
-       int seg_size;
-       int cluster;
-       struct req_iterator iter;
-       int high, highprv = 1;
-       struct request_queue *q = rq->q;
+       int cluster, i, high, highprv = 1;
+       unsigned int seg_size, nr_phys_segs;
+       struct bio *fbio;
 
-       if (!rq->bio)
-               return;
+       if (!bio)
+               return 0;
 
+       fbio = bio;
        cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
        seg_size = 0;
        phys_size = nr_phys_segs = 0;
-       rq_for_each_segment(bv, rq, iter) {
-               /*
-                * the trick here is making sure that a high page is never
-                * considered part of another segment, since that might
-                * change with the bounce page.
-                */
-               high = page_to_pfn(bv->bv_page) > q->bounce_pfn;
-               if (high || highprv)
-                       goto new_segment;
-               if (cluster) {
-                       if (seg_size + bv->bv_len > q->max_segment_size)
-                               goto new_segment;
-                       if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv))
-                               goto new_segment;
-                       if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv))
+       for_each_bio(bio) {
+               bio_for_each_segment(bv, bio, i) {
+                       /*
+                        * the trick here is making sure that a high page is
+                        * never considered part of another segment, since that
+                        * might change with the bounce page.
+                        */
+                       high = page_to_pfn(bv->bv_page) > q->bounce_pfn;
+                       if (high || highprv)
                                goto new_segment;
+                       if (cluster) {
+                               if (seg_size + bv->bv_len > q->max_segment_size)
+                                       goto new_segment;
+                               if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv))
+                                       goto new_segment;
+                               if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv))
+                                       goto new_segment;
+
+                               seg_size += bv->bv_len;
+                               bvprv = bv;
+                               continue;
+                       }
+new_segment:
+                       if (nr_phys_segs == 1 && seg_size >
+                           fbio->bi_seg_front_size)
+                               fbio->bi_seg_front_size = seg_size;
 
-                       seg_size += bv->bv_len;
+                       nr_phys_segs++;
                        bvprv = bv;
-                       continue;
+                       seg_size = bv->bv_len;
+                       highprv = high;
                }
-new_segment:
-               if (nr_phys_segs == 1 && seg_size > rq->bio->bi_seg_front_size)
-                       rq->bio->bi_seg_front_size = seg_size;
-
-               nr_phys_segs++;
-               bvprv = bv;
-               seg_size = bv->bv_len;
-               highprv = high;
        }
 
-       if (nr_phys_segs == 1 && seg_size > rq->bio->bi_seg_front_size)
+       if (seg_size_ptr)
+               *seg_size_ptr = seg_size;
+
+       return nr_phys_segs;
+}
+
+void blk_recalc_rq_segments(struct request *rq)
+{
+       unsigned int seg_size = 0, phys_segs;
+
+       phys_segs = __blk_recalc_rq_segments(rq->q, rq->bio, &seg_size);
+
+       if (phys_segs == 1 && seg_size > rq->bio->bi_seg_front_size)
                rq->bio->bi_seg_front_size = seg_size;
        if (seg_size > rq->biotail->bi_seg_back_size)
                rq->biotail->bi_seg_back_size = seg_size;
 
-       rq->nr_phys_segments = nr_phys_segs;
+       rq->nr_phys_segments = phys_segs;
 }
 
 void blk_recount_segments(struct request_queue *q, struct bio *bio)
 {
-       struct request rq;
        struct bio *nxt = bio->bi_next;
-       rq.q = q;
-       rq.bio = rq.biotail = bio;
+
        bio->bi_next = NULL;
-       blk_recalc_rq_segments(&rq);
+       bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio, NULL);
        bio->bi_next = nxt;
-       bio->bi_phys_segments = rq.nr_phys_segments;
        bio->bi_flags |= (1 << BIO_SEG_VALID);
 }
 EXPORT_SYMBOL(blk_recount_segments);
index e1eadcc9546a72ec0d1c76d933143767dd357536..a9ec910974c1934675b887d2fc8c2d0703579b01 100644 (file)
@@ -256,6 +256,22 @@ void blkdev_show(struct seq_file *seqf, off_t offset)
 }
 #endif /* CONFIG_PROC_FS */
 
+/**
+ * register_blkdev - register a new block device
+ *
+ * @major: the requested major device number [1..255]. If @major=0, try to
+ *         allocate any unused major number.
+ * @name: the name of the new block device as a zero terminated string
+ *
+ * The @name must be unique within the system.
+ *
+ * The return value depends on the @major input parameter.
+ *  - if a major device number was requested in range [1..255] then the
+ *    function returns zero on success, or a negative error code
+ *  - if any unused major number was requested with @major=0 parameter
+ *    then the return value is the allocated major number in range
+ *    [1..255] or a negative error code otherwise
+ */
 int register_blkdev(unsigned int major, const char *name)
 {
        struct blk_major_name **n, *p;
index ba5292d69ebd206cdbf9961e130cf089dc584dd2..b2d1ee32cfe829c774071367b5e40a9d5553dc3f 100644 (file)
@@ -214,7 +214,7 @@ static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
        seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
                                             "yes" : "no");
        seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
-       seq_printf(m, "digestsize   : %u\n", alg->cra_hash.digestsize);
+       seq_printf(m, "digestsize   : %u\n", alg->cra_ahash.digestsize);
 }
 
 const struct crypto_type crypto_ahash_type = {
index efe77df6863f4378f4f0da414591f940870b76ea..38a2bc02a98c7f6648f7a7a3388c6182b88c07f9 100644 (file)
@@ -215,8 +215,19 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
        mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
        type &= mask;
 
-       alg = try_then_request_module(crypto_alg_lookup(name, type, mask),
-                                     name);
+       alg = crypto_alg_lookup(name, type, mask);
+       if (!alg) {
+               char tmp[CRYPTO_MAX_ALG_NAME];
+
+               request_module(name);
+
+               if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask) &&
+                   snprintf(tmp, sizeof(tmp), "%s-all", name) < sizeof(tmp))
+                       request_module(tmp);
+
+               alg = crypto_alg_lookup(name, type, mask);
+       }
+
        if (alg)
                return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg;
 
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 63719ab9ea4448839d64d81faa187250ef21637d..115b1cd6dcf55c32afbe5ec2ab348b3f438db34f 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_amd"
-#define DRV_VERSION "0.3.11"
+#define DRV_VERSION "0.4.1"
 
 /**
  *     timing_setup            -       shared timing computation and load
@@ -145,6 +145,13 @@ static int amd_pre_reset(struct ata_link *link, unsigned long deadline)
        return ata_sff_prereset(link, deadline);
 }
 
+/**
+ *     amd_cable_detect        -       report cable type
+ *     @ap: port
+ *
+ *     AMD controller/BIOS setups record the cable type in word 0x42
+ */
+
 static int amd_cable_detect(struct ata_port *ap)
 {
        static const u32 bitmask[2] = {0x03, 0x0C};
@@ -157,6 +164,40 @@ static int amd_cable_detect(struct ata_port *ap)
        return ATA_CBL_PATA40;
 }
 
+/**
+ *     amd_fifo_setup          -       set the PIO FIFO for ATA/ATAPI
+ *     @ap: ATA interface
+ *     @adev: ATA device
+ *
+ *     Set the PCI fifo for this device according to the devices present
+ *     on the bus at this point in time. We need to turn the post write buffer
+ *     off for ATAPI devices as we may need to issue a word sized write to the
+ *     device as the final I/O
+ */
+
+static void amd_fifo_setup(struct ata_port *ap)
+{
+       struct ata_device *adev;
+       struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+       static const u8 fifobit[2] = { 0xC0, 0x30};
+       u8 fifo = fifobit[ap->port_no];
+       u8 r;
+
+
+       ata_for_each_dev(adev, &ap->link, ENABLED) {
+               if (adev->class == ATA_DEV_ATAPI)
+                       fifo = 0;
+       }
+       if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411) /* FIFO is broken */
+               fifo = 0;
+
+       /* On the later chips the read prefetch bits become no-op bits */
+       pci_read_config_byte(pdev, 0x41, &r);
+       r &= ~fifobit[ap->port_no];
+       r |= fifo;
+       pci_write_config_byte(pdev, 0x41, r);
+}
+
 /**
  *     amd33_set_piomode       -       set initial PIO mode data
  *     @ap: ATA interface
@@ -167,21 +208,25 @@ static int amd_cable_detect(struct ata_port *ap)
 
 static void amd33_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
+       amd_fifo_setup(ap);
        timing_setup(ap, adev, 0x40, adev->pio_mode, 1);
 }
 
 static void amd66_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
+       amd_fifo_setup(ap);
        timing_setup(ap, adev, 0x40, adev->pio_mode, 2);
 }
 
 static void amd100_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
+       amd_fifo_setup(ap);
        timing_setup(ap, adev, 0x40, adev->pio_mode, 3);
 }
 
 static void amd133_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
+       amd_fifo_setup(ap);
        timing_setup(ap, adev, 0x40, adev->pio_mode, 4);
 }
 
@@ -397,6 +442,16 @@ static struct ata_port_operations nv133_port_ops = {
        .set_dmamode    = nv133_set_dmamode,
 };
 
+static void amd_clear_fifo(struct pci_dev *pdev)
+{
+       u8 fifo;
+       /* Disable the FIFO, the FIFO logic will re-enable it as
+          appropriate */
+       pci_read_config_byte(pdev, 0x41, &fifo);
+       fifo &= 0x0F;
+       pci_write_config_byte(pdev, 0x41, fifo);
+}
+
 static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        static const struct ata_port_info info[10] = {
@@ -503,14 +558,8 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        if (type < 3)
                ata_pci_bmdma_clear_simplex(pdev);
-
-       /* Check for AMD7411 */
-       if (type == 3)
-               /* FIFO is broken */
-               pci_write_config_byte(pdev, 0x41, fifo & 0x0F);
-       else
-               pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
-
+       if (pdev->vendor == PCI_VENDOR_ID_AMD)
+               amd_clear_fifo(pdev);
        /* Cable detection on Nvidia chips doesn't work too well,
         * cache BIOS programmed UDMA mode.
         */
@@ -536,18 +585,11 @@ static int amd_reinit_one(struct pci_dev *pdev)
                return rc;
 
        if (pdev->vendor == PCI_VENDOR_ID_AMD) {
-               u8 fifo;
-               pci_read_config_byte(pdev, 0x41, &fifo);
-               if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411)
-                       /* FIFO is broken */
-                       pci_write_config_byte(pdev, 0x41, fifo & 0x0F);
-               else
-                       pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
+               amd_clear_fifo(pdev);
                if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 ||
                    pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
                        ata_pci_bmdma_clear_simplex(pdev);
        }
-
        ata_host_resume(host);
        return 0;
 }
index f1bb2f9fecbf347b50bb5d76253b6c6bb67e31b9..b05b86a912c5ddb7f7ae14a20bd15af76e61da54 100644 (file)
@@ -557,6 +557,9 @@ static unsigned int it821x_read_id(struct ata_device *adev,
                id[83] |= 0x4400;       /* Word 83 is valid and LBA48 */
                id[86] |= 0x0400;       /* LBA48 on */
                id[ATA_ID_MAJOR_VER] |= 0x1F;
+               /* Clear the serial number because it's different each boot
+                  which breaks validation on resume */
+               memset(&id[ATA_ID_SERNO], 0x20, ATA_ID_SERNO_LEN);
        }
        return err_mask;
 }
index 6c1d778b63a9cd58a06dc4772fcfc15f8350d428..e3bc1b436284bfa42ac977fe372c98340df24b2d 100644 (file)
@@ -283,9 +283,10 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
 static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
                        unsigned char *buf, unsigned int buflen, int rw)
 {
-       if (ata_id_has_dword_io(dev->id)) {
+       int slop = buflen & 3;
+       /* 32bit I/O capable *and* we need to write a whole number of dwords */
+       if (ata_id_has_dword_io(dev->id) && (slop == 0 || slop == 3)) {
                struct ata_port *ap = dev->link->ap;
-               int slop = buflen & 3;
                unsigned long flags;
 
                local_irq_save(flags);
@@ -735,7 +736,7 @@ static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
        struct ata_port *ap = adev->link->ap;
        int slop = buflen & 3;
 
-       if (ata_id_has_dword_io(adev->id)) {
+       if (ata_id_has_dword_io(adev->id) && (slop == 0 || slop == 3)) {
                if (rw == WRITE)
                        iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
                else
index 4ae1a4138b47078072bedf2e889338e6bd8a0cb2..7007edd2d4517fed1a5b75773622cae9da003e44 100644 (file)
@@ -3114,19 +3114,17 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
                writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
        }
 
-       if (!IS_SOC(hpriv)) {
-               /* Clear any currently outstanding host interrupt conditions */
-               writelfl(0, mmio + hpriv->irq_cause_ofs);
+       /* Clear any currently outstanding host interrupt conditions */
+       writelfl(0, mmio + hpriv->irq_cause_ofs);
 
-               /* and unmask interrupt generation for host regs */
-               writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
+       /* and unmask interrupt generation for host regs */
+       writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
 
-               /*
-                * enable only global host interrupts for now.
-                * The per-port interrupts get done later as ports are set up.
-                */
-               mv_set_main_irq_mask(host, 0, PCI_ERR);
-       }
+       /*
+        * enable only global host interrupts for now.
+        * The per-port interrupts get done later as ports are set up.
+        */
+       mv_set_main_irq_mask(host, 0, PCI_ERR);
 done:
        return rc;
 }
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 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 d2cb67b61176674f7e8df4230f1d807db2190ee3..b5a06111463018b5d93f3d2b944caf9c60654281 100644 (file)
@@ -3611,11 +3611,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
                schedule_timeout_uninterruptible(30*HZ);
 
                /* Now try to get the controller to respond to a no-op */
-               for (i=0; i<12; i++) {
+               for (i=0; i<30; i++) {
                        if (cciss_noop(pdev) == 0)
                                break;
-                       else
-                               printk("cciss: no-op failed%s\n", (i < 11 ? "; re-trying" : ""));
+
+                       schedule_timeout_uninterruptible(HZ);
+               }
+               if (i == 30) {
+                       printk(KERN_ERR "cciss: controller seems dead\n");
+                       return -EBUSY;
                }
        }
 
index 918ef725de41c849f3f78b7e30f80d7709e01a39..b6c8ce25435994558885e9e4b9c4ac6aafaa9357 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/hdreg.h>
 #include <linux/cdrom.h>
 #include <linux/module.h>
+#include <linux/scatterlist.h>
 
 #include <xen/xenbus.h>
 #include <xen/grant_table.h>
@@ -82,6 +83,7 @@ struct blkfront_info
        enum blkif_state connected;
        int ring_ref;
        struct blkif_front_ring ring;
+       struct scatterlist sg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
        unsigned int evtchn, irq;
        struct request_queue *rq;
        struct work_struct work;
@@ -204,12 +206,11 @@ static int blkif_queue_request(struct request *req)
        struct blkfront_info *info = req->rq_disk->private_data;
        unsigned long buffer_mfn;
        struct blkif_request *ring_req;
-       struct req_iterator iter;
-       struct bio_vec *bvec;
        unsigned long id;
        unsigned int fsect, lsect;
-       int ref;
+       int i, ref;
        grant_ref_t gref_head;
+       struct scatterlist *sg;
 
        if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
                return 1;
@@ -238,12 +239,13 @@ static int blkif_queue_request(struct request *req)
        if (blk_barrier_rq(req))
                ring_req->operation = BLKIF_OP_WRITE_BARRIER;
 
-       ring_req->nr_segments = 0;
-       rq_for_each_segment(bvec, req, iter) {
-               BUG_ON(ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST);
-               buffer_mfn = pfn_to_mfn(page_to_pfn(bvec->bv_page));
-               fsect = bvec->bv_offset >> 9;
-               lsect = fsect + (bvec->bv_len >> 9) - 1;
+       ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
+       BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
+
+       for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
+               buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg)));
+               fsect = sg->offset >> 9;
+               lsect = fsect + (sg->length >> 9) - 1;
                /* install a grant reference. */
                ref = gnttab_claim_grant_reference(&gref_head);
                BUG_ON(ref == -ENOSPC);
@@ -254,16 +256,12 @@ static int blkif_queue_request(struct request *req)
                                buffer_mfn,
                                rq_data_dir(req) );
 
-               info->shadow[id].frame[ring_req->nr_segments] =
-                               mfn_to_pfn(buffer_mfn);
-
-               ring_req->seg[ring_req->nr_segments] =
+               info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
+               ring_req->seg[i] =
                                (struct blkif_request_segment) {
                                        .gref       = ref,
                                        .first_sect = fsect,
                                        .last_sect  = lsect };
-
-               ring_req->nr_segments++;
        }
 
        info->ring.req_prod_pvt++;
@@ -622,6 +620,8 @@ static int setup_blkring(struct xenbus_device *dev,
        SHARED_RING_INIT(sring);
        FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);
 
+       sg_init_table(info->sg, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+
        err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring));
        if (err < 0) {
                free_page((unsigned long)sring);
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 2d637e0fbc038df28dbfbff2d342b89edf6db4a4..d9e751be8c5fb120e5f0d06ef27684c8f33fa549 100644 (file)
@@ -457,10 +457,12 @@ static int init_ixp_crypto(void)
        if (!ctx_pool) {
                goto err;
        }
-       ret = qmgr_request_queue(SEND_QID, NPE_QLEN_TOTAL, 0, 0);
+       ret = qmgr_request_queue(SEND_QID, NPE_QLEN_TOTAL, 0, 0,
+                                "ixp_crypto:out", NULL);
        if (ret)
                goto err;
-       ret = qmgr_request_queue(RECV_QID, NPE_QLEN, 0, 0);
+       ret = qmgr_request_queue(RECV_QID, NPE_QLEN, 0, 0,
+                                "ixp_crypto:in", NULL);
        if (ret) {
                qmgr_release_queue(SEND_QID);
                goto err;
index 856b3cc2558387b7b239923c37c54f9d47b250ff..3f0fdd18255db9febb61836d44b3d7382385140d 100644 (file)
@@ -489,4 +489,4 @@ MODULE_DESCRIPTION("VIA PadLock AES algorithm support");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Michal Ludvig");
 
-MODULE_ALIAS("aes");
+MODULE_ALIAS("aes-all");
index a7fbadebf62330864734e5302be660d2f39ab51a..a2c8e8514b6340ac85915f158d7780491ce8b4a8 100644 (file)
@@ -304,7 +304,7 @@ MODULE_DESCRIPTION("VIA PadLock SHA1/SHA256 algorithms support.");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Michal Ludvig");
 
-MODULE_ALIAS("sha1");
-MODULE_ALIAS("sha256");
+MODULE_ALIAS("sha1-all");
+MODULE_ALIAS("sha256-all");
 MODULE_ALIAS("sha1-padlock");
 MODULE_ALIAS("sha256-padlock");
index ea5440dd10dc1ffb56dda5393d51f388e02ca87b..647374acba94a7c526d04236af5a855f81b7258c 100644 (file)
@@ -1401,7 +1401,7 @@ MODULE_ALIAS("platform:iop-adma");
 
 static struct platform_driver iop_adma_driver = {
        .probe          = iop_adma_probe,
-       .remove         = iop_adma_remove,
+       .remove         = __devexit_p(iop_adma_remove),
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "iop-adma",
index d35cbd1ff0b31e6635dd803eeae708cf75d68772..5d5d5b31867fc9e28dd70696e52ad00fa68c997c 100644 (file)
@@ -1287,7 +1287,7 @@ mv_xor_conf_mbus_windows(struct mv_xor_shared_private *msp,
 
 static struct platform_driver mv_xor_driver = {
        .probe          = mv_xor_probe,
-       .remove         = mv_xor_remove,
+       .remove         = __devexit_p(mv_xor_remove),
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = MV_XOR_NAME,
index 72c667f9bee1aadbc4067687d05aca0849be751b..12715d3c078d6e9d111c265fe96b5ccc63961d3e 100644 (file)
@@ -420,7 +420,7 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
                                dev->sigdata.lock = NULL;
                        master->lock.hw_lock = NULL;   /* SHM removed */
                        master->lock.file_priv = NULL;
-                       wake_up_interruptible(&master->lock.lock_queue);
+                       wake_up_interruptible_all(&master->lock.lock_queue);
                }
                break;
        case _DRM_AGP:
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..1c3a8c5571408a6f0a698a53b58f93f6f471a9a9 100644 (file)
@@ -452,6 +452,59 @@ static void drm_setup_crtcs(struct drm_device *dev)
        kfree(modes);
        kfree(enabled);
 }
+
+/**
+ * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
+ * @encoder: encoder to test
+ * @crtc: crtc to test
+ *
+ * Return false if @encoder can't be driven by @crtc, true otherwise.
+ */
+static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
+                               struct drm_crtc *crtc)
+{
+       struct drm_device *dev;
+       struct drm_crtc *tmp;
+       int crtc_mask = 1;
+
+       WARN(!crtc, "checking null crtc?");
+
+       dev = crtc->dev;
+
+       list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
+               if (tmp == crtc)
+                       break;
+               crtc_mask <<= 1;
+       }
+
+       if (encoder->possible_crtcs & crtc_mask)
+               return true;
+       return false;
+}
+
+/*
+ * Check the CRTC we're going to map each output to vs. its current
+ * CRTC.  If they don't match, we have to disable the output and the CRTC
+ * since the driver will have to re-route things.
+ */
+static void
+drm_crtc_prepare_encoders(struct drm_device *dev)
+{
+       struct drm_encoder_helper_funcs *encoder_funcs;
+       struct drm_encoder *encoder;
+
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               encoder_funcs = encoder->helper_private;
+               /* Disable unused encoders */
+               if (encoder->crtc == NULL)
+                       (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
+               /* Disable encoders whose CRTC is about to change */
+               if (encoder_funcs->get_crtc &&
+                   encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
+                       (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
+       }
+}
+
 /**
  * drm_crtc_set_mode - set a mode
  * @crtc: CRTC to program
@@ -512,8 +565,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;
                }
        }
@@ -547,12 +600,16 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
                encoder_funcs->prepare(encoder);
        }
 
+       drm_crtc_prepare_encoders(dev);
+
        crtc_funcs->prepare(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) {
 
@@ -615,7 +672,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
        struct drm_device *dev;
        struct drm_crtc **save_crtcs, *new_crtc;
        struct drm_encoder **save_encoders, *new_encoder;
-       struct drm_framebuffer *old_fb;
+       struct drm_framebuffer *old_fb = NULL;
        bool save_enabled;
        bool mode_changed = false;
        bool fb_changed = false;
@@ -666,9 +723,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
         * and then just flip_or_move it */
        if (set->crtc->fb != set->fb) {
                /* If we have no fb then treat it as a full mode set */
-               if (set->crtc->fb == NULL)
+               if (set->crtc->fb == NULL) {
+                       DRM_DEBUG("crtc has no fb, full mode set\n");
                        mode_changed = true;
-               else if ((set->fb->bits_per_pixel !=
+               else if ((set->fb->bits_per_pixel !=
                         set->crtc->fb->bits_per_pixel) ||
                         set->fb->depth != set->crtc->fb->depth)
                        fb_changed = true;
@@ -680,7 +738,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                fb_changed = true;
 
        if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
-               DRM_DEBUG("modes are different\n");
+               DRM_DEBUG("modes are different, full mode set\n");
                drm_mode_debug_printmodeline(&set->crtc->mode);
                drm_mode_debug_printmodeline(set->mode);
                mode_changed = true;
@@ -706,6 +764,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                }
 
                if (new_encoder != connector->encoder) {
+                       DRM_DEBUG("encoder changed, full mode switch\n");
                        mode_changed = true;
                        connector->encoder = new_encoder;
                }
@@ -732,10 +791,20 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                        if (set->connectors[ro] == connector)
                                new_crtc = set->crtc;
                }
+
+               /* Make sure the new CRTC will work with the encoder */
+               if (new_crtc &&
+                   !drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
+                       ret = -EINVAL;
+                       goto fail_set_mode;
+               }
                if (new_crtc != connector->encoder->crtc) {
+                       DRM_DEBUG("crtc changed, full mode switch\n");
                        mode_changed = true;
                        connector->encoder->crtc = new_crtc;
                }
+               DRM_DEBUG("setting connector %d crtc to %p\n",
+                         connector->base.id, new_crtc);
        }
 
        /* mode_set_base is not a required function */
@@ -752,6 +821,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 +836,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);
@@ -774,9 +848,14 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 
 fail_set_mode:
        set->crtc->enabled = save_enabled;
+       set->crtc->fb = old_fb;
        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 5a4d3244758a102ec7cea6ed87342619dd47c85e..a839a28d8ee606763ad213d9dc785bc4dde0dd6c 100644 (file)
@@ -125,7 +125,7 @@ static bool edid_is_valid(struct edid *edid)
                DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version);
                goto bad;
        }
-       if (edid->revision <= 0 || edid->revision > 3) {
+       if (edid->revision > 3) {
                DRM_ERROR("EDID has minor version %d, which is not between 0-3\n", edid->revision);
                goto bad;
        }
@@ -320,10 +320,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
        mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo);
 
        mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo;
-       mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 8) |
+       mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 4) |
                                              pt->vsync_offset_lo);
        mode->vsync_end = mode->vsync_start +
-               ((pt->vsync_pulse_width_hi << 8) |
+               ((pt->vsync_pulse_width_hi << 4) |
                 pt->vsync_pulse_width_lo);
        mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo);
 
index b06a53715853af03df4717108106a72c1effdba5..f52663ebe016f5ea194b5aa2a403881ebb2e0448 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;
@@ -481,6 +484,7 @@ int drm_release(struct inode *inode, struct file *filp)
        mutex_lock(&dev->struct_mutex);
 
        if (file_priv->is_master) {
+               struct drm_master *master = file_priv->master;
                struct drm_file *temp;
                list_for_each_entry(temp, &dev->filelist, lhead) {
                        if ((temp->master == file_priv->master) &&
@@ -488,6 +492,19 @@ int drm_release(struct inode *inode, struct file *filp)
                                temp->authenticated = 0;
                }
 
+               /**
+                * Since the master is disappearing, so is the
+                * possibility to lock.
+                */
+
+               if (master->lock.hw_lock) {
+                       if (dev->sigdata.lock == master->lock.hw_lock)
+                               dev->sigdata.lock = NULL;
+                       master->lock.hw_lock = NULL;
+                       master->lock.file_priv = NULL;
+                       wake_up_interruptible_all(&master->lock.lock_queue);
+               }
+
                if (file_priv->minor->master == file_priv->master) {
                        /* drop the reference held my the minor */
                        drm_master_put(&file_priv->minor->master);
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 3795dbc0f50cff99b167fc0659f0d0862c8d57d5..93e677a481f5388f380bc86547297e8f87bddbb0 100644 (file)
@@ -435,6 +435,8 @@ EXPORT_SYMBOL(drm_vblank_get);
  */
 void drm_vblank_put(struct drm_device *dev, int crtc)
 {
+       BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0);
+
        /* Last user schedules interrupt disable */
        if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
                mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
@@ -460,8 +462,9 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
         * so that interrupts remain enabled in the interim.
         */
        if (!dev->vblank_inmodeset[crtc]) {
-               dev->vblank_inmodeset[crtc] = 1;
-               drm_vblank_get(dev, crtc);
+               dev->vblank_inmodeset[crtc] = 0x1;
+               if (drm_vblank_get(dev, crtc) == 0)
+                       dev->vblank_inmodeset[crtc] |= 0x2;
        }
 }
 EXPORT_SYMBOL(drm_vblank_pre_modeset);
@@ -473,9 +476,12 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
        if (dev->vblank_inmodeset[crtc]) {
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
                dev->vblank_disable_allowed = 1;
-               dev->vblank_inmodeset[crtc] = 0;
                spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-               drm_vblank_put(dev, crtc);
+
+               if (dev->vblank_inmodeset[crtc] & 0x2)
+                       drm_vblank_put(dev, crtc);
+
+               dev->vblank_inmodeset[crtc] = 0;
        }
 }
 EXPORT_SYMBOL(drm_vblank_post_modeset);
index 46e7b28f0707397d545948dc21bbcc272f16eb6f..e2f70a516c34412112078131203309c3656622d7 100644 (file)
@@ -80,6 +80,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
                __set_current_state(TASK_INTERRUPTIBLE);
                if (!master->lock.hw_lock) {
                        /* Device has been unregistered */
+                       send_sig(SIGTERM, current, 0);
                        ret = -EINTR;
                        break;
                }
@@ -93,7 +94,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
                /* Contention */
                schedule();
                if (signal_pending(current)) {
-                       ret = -ERESTARTSYS;
+                       ret = -EINTR;
                        break;
                }
        }
index 46bb923b097c39ad6fef2c37f29e59ae0c648f42..7c8b15b22bf2e089fd9356debc9f967031723cbe 100644 (file)
@@ -146,14 +146,6 @@ static void drm_master_destroy(struct kref *kref)
 
        drm_ht_remove(&master->magiclist);
 
-       if (master->lock.hw_lock) {
-               if (dev->sigdata.lock == master->lock.hw_lock)
-                       dev->sigdata.lock = NULL;
-               master->lock.hw_lock = NULL;
-               master->lock.file_priv = NULL;
-               wake_up_interruptible(&master->lock.lock_queue);
-       }
-
        drm_free(master, sizeof(*master), DRM_MEM_DRIVER);
 }
 
@@ -176,7 +168,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
            file_priv->minor->master != file_priv->master) {
                mutex_lock(&dev->struct_mutex);
                file_priv->minor->master = drm_master_get(file_priv->master);
-               mutex_lock(&dev->struct_mutex);
+               mutex_unlock(&dev->struct_mutex);
        }
 
        return 0;
index 81f1cff56fd5e2ff02313849a2d9f4d412d22237..6dab63bdc4c10e3182447bb61fbd5930d8366d6f 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);
@@ -811,7 +811,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
        dev_priv->hws_map.flags = 0;
        dev_priv->hws_map.mtrr = 0;
 
-       drm_core_ioremap(&dev_priv->hws_map, dev);
+       drm_core_ioremap_wc(&dev_priv->hws_map, dev);
        if (dev_priv->hws_map.handle == NULL) {
                i915_dma_cleanup(dev);
                dev_priv->status_gfx_addr = 0;
@@ -1090,6 +1090,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
         dev_priv->mm.gtt_mapping =
                io_mapping_create_wc(dev->agp->base,
                                     dev->agp->agp_info.aper_size * 1024*1024);
+       if (dev_priv->mm.gtt_mapping == NULL) {
+               ret = -EIO;
+               goto out_rmmap;
+       }
+
        /* Set up a WC MTRR for non-PAT systems.  This is more common than
         * one would think, because the kernel disables PAT on first
         * generation Core chips because WC PAT gets overridden by a UC
@@ -1122,7 +1127,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (!I915_NEED_GFX_HWS(dev)) {
                ret = i915_init_phys_hws(dev);
                if (ret != 0)
-                       goto out_rmmap;
+                       goto out_iomapfree;
        }
 
        /* On the 945G/GM, the chipset reports the MSI capability on the
@@ -1161,6 +1166,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        return 0;
 
+out_iomapfree:
+       io_mapping_free(dev_priv->mm.gtt_mapping);
 out_rmmap:
        iounmap(dev_priv->regs);
 free_priv:
index aac12ee31a46e86540e7e2cba43d8cef273e27c2..b293ef0bae7153805d587201c8ce6c84f3703f4c 100644 (file)
@@ -27,6 +27,7 @@
  *
  */
 
+#include <linux/device.h>
 #include "drmP.h"
 #include "drm.h"
 #include "i915_drm.h"
@@ -66,6 +67,14 @@ 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)) {
+               if (i915_gem_idle(dev))
+                       dev_err(&dev->pdev->dev,
+                               "GEM idle failed, resume may fail\n");
+               drm_irq_uninstall(dev);
+       }
+
        intel_opregion_free(dev);
 
        if (state.event == PM_EVENT_SUSPEND) {
@@ -79,6 +88,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 +101,26 @@ 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);
+
+               drm_irq_install(dev);
+       }
+
+       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..85685bfd12daf02fb26bea88a90e521d6e3237c2 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;
@@ -1030,6 +1051,9 @@ i915_gem_retire_requests(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        uint32_t seqno;
 
+       if (!dev_priv->hw_status_page)
+               return;
+
        seqno = i915_get_gem_seqno(dev);
 
        while (!list_empty(&dev_priv->mm.request_list)) {
@@ -1996,30 +2020,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 +2051,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 +2070,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 +2281,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 +2512,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 +2588,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 +2607,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 +2670,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 +2679,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 +2794,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 +2875,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 +2934,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 +2944,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 +2983,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 +3129,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 +3142,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 +3184,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 +3192,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 +3210,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 +3292,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
@@ -3497,7 +3548,7 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
        user_data = (char __user *) (uintptr_t) args->data_ptr;
        obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset;
 
-       DRM_ERROR("obj_addr %p, %lld\n", obj_addr, args->size);
+       DRM_DEBUG("obj_addr %p, %lld\n", obj_addr, args->size);
        ret = copy_from_user(obj_addr, user_data, args->size);
        if (ret)
                return -EFAULT;
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 548ff2c66431ee93a205b15d84362084da7486ce..87b6b603469ea278780af278fb9b7dc92d013ed0 100644 (file)
@@ -383,12 +383,13 @@ int i915_irq_emit(struct drm_device *dev, void *data,
        drm_i915_irq_emit_t *emit = data;
        int result;
 
-       RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
-
        if (!dev_priv) {
                DRM_ERROR("called with no initialization\n");
                return -EINVAL;
        }
+
+       RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
+
        mutex_lock(&dev->struct_mutex);
        result = i915_emit_irq(dev);
        mutex_unlock(&dev->struct_mutex);
index 4ca82a0255255e09f82426bc23b2bc25da555f08..fc28e2bbd5427e6030869724dfb9bd20b5797451 100644 (file)
@@ -111,6 +111,12 @@ parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
        panel_fixed_mode->clock = dvo_timing->clock * 10;
        panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
 
+       /* Some VBTs have bogus h/vtotal values */
+       if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
+               panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
+       if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
+               panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
+
        drm_mode_set_name(panel_fixed_mode);
 
        dev_priv->vbt_mode = panel_fixed_mode;
@@ -135,6 +141,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..a2834276cb38637949648dad2ae2b59de8995fbf 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 9fee3ca17344b9ab6adf895b4869a82e7d8bac6b..9aefb5e5864df92b9f5d6226db680c55e8bdf274 100644 (file)
@@ -79,10 +79,11 @@ static struct i2c_algo_bit_data ioc_data = {
        .getsda         = ioc_getsda,
        .getscl         = ioc_getscl,
        .udelay         = 80,
-       .timeout        = 100
+       .timeout        = HZ,
 };
 
 static struct i2c_adapter ioc_ops = {
+       .nr                     = 0,
        .algo_data              = &ioc_data,
 };
 
@@ -90,7 +91,7 @@ static int __init i2c_ioc_init(void)
 {
        force_ones = FORCE_ONES | SCL | SDA;
 
-       return i2c_bit_add_bus(&ioc_ops);
+       return i2c_bit_add_numbered_bus(&ioc_ops);
 }
 
 module_init(i2c_ioc_init);
index edab51973bf5501c303fc56a23b1f90f722b1e6a..a7c59908c457cbeb23937904dc6d6a76a05e060c 100644 (file)
@@ -72,7 +72,7 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus)
 {
        int timeout = 500;
 
-       while (timeout-- && (inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF))
+       while ((inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF) && --timeout)
                udelay(1);
 
        if (!timeout) {
@@ -88,7 +88,7 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
 {
        int timeout = 500;
 
-       while (timeout-- && (~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF))
+       while ((~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF) && --timeout)
                udelay(1);
 
        if (!timeout) {
index 8e8467970481bb86972eadcb16bdb2dce7cf6a3d..c016f7a2c5fc2712433dbd83ec7d1c6dd1d48f3b 100644 (file)
@@ -114,7 +114,7 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev)
        drv_data->algo_data.getsda = ixp2000_bit_getsda;
        drv_data->algo_data.getscl = ixp2000_bit_getscl;
        drv_data->algo_data.udelay = 6;
-       drv_data->algo_data.timeout = 100;
+       drv_data->algo_data.timeout = HZ;
 
        strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
                sizeof(drv_data->adapter.name));
index eeda276f8f164021a9f59c12e1c7612ac60d94b4..7f186bbcb99d965bc69cdc8df5bd1cd83b8e89da 100644 (file)
@@ -482,7 +482,7 @@ mv64xxx_i2c_map_regs(struct platform_device *pd,
        return 0;
 }
 
-static void __devexit
+static void
 mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data)
 {
        if (drv_data->reg_base) {
@@ -577,7 +577,7 @@ mv64xxx_i2c_remove(struct platform_device *dev)
 
 static struct platform_driver mv64xxx_i2c_driver = {
        .probe  = mv64xxx_i2c_probe,
-       .remove = mv64xxx_i2c_remove,
+       .remove = __devexit_p(mv64xxx_i2c_remove),
        .driver = {
                .owner  = THIS_MODULE,
                .name   = MV64XXX_I2C_CTLR_NAME,
index 6af68146c34248507c0d8df07691992c31d54991..bdb1f7510e91555209bdf5dedfd20a48f50e1aba 100644 (file)
@@ -644,7 +644,7 @@ static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c,
 
        i2c_pxa_start_message(i2c);
 
-       while (timeout-- && i2c->msg_num > 0) {
+       while (i2c->msg_num > 0 && --timeout) {
                i2c_pxa_handler(0, i2c);
                udelay(10);
        }
index 162b74a04886c5497296579c6bbabda7015f2948..42df0eca43d5229b1fd88624e3fee4c369f0f462 100644 (file)
@@ -76,7 +76,7 @@ static struct i2c_algo_bit_data scx200_i2c_data = {
        .getsda         = scx200_i2c_getsda,
        .getscl         = scx200_i2c_getscl,
        .udelay         = 10,
-       .timeout        = 100,
+       .timeout        = HZ,
 };
 
 static struct i2c_adapter scx200_i2c_ops = {
index b1c9abe24c7b2a84f143c264d82a3ee74cdc0639..e7d984866de0465f5846225c6b59a0072fec7fd1 100644 (file)
@@ -1831,7 +1831,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
        case I2C_SMBUS_QUICK:
                msg[0].len = 0;
                /* Special case: The read/write field is used as data */
-               msg[0].flags = flags | (read_write==I2C_SMBUS_READ)?I2C_M_RD:0;
+               msg[0].flags = flags | (read_write == I2C_SMBUS_READ ?
+                                       I2C_M_RD : 0);
                num = 1;
                break;
        case I2C_SMBUS_BYTE:
index c171988a9f517d7009319674265c47a10859a8c3..7e13d2df9af384f0b048faa36c427171dab30fa0 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-dev.h>
 #include <linux/smp_lock.h>
+#include <linux/jiffies.h>
 #include <asm/uaccess.h>
 
 static struct i2c_driver i2cdev_driver;
@@ -422,7 +423,10 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                client->adapter->retries = arg;
                break;
        case I2C_TIMEOUT:
-               client->adapter->timeout = arg;
+               /* For historical reasons, user-space sets the timeout
+                * value in units of 10 ms.
+                */
+               client->adapter->timeout = msecs_to_jiffies(arg * 10);
                break;
        default:
                /* NOTE:  returning a fault code here could cause trouble
index 3dad2299d9c57e9b22ec420bb180c93d975b1e77..e072903b12f016aab1aa0d72e0939907253ff033 100644 (file)
@@ -46,7 +46,7 @@ menuconfig IDE
          SMART parameters from disk drives.
 
          To compile this driver as a module, choose M here: the
-         module will be called ide.
+         module will be called ide-core.ko.
 
          For further information, please read <file:Documentation/ide/ide.txt>.
 
index 69660a431cd9890f707c87d7e7a38f3429e643de..77267c85996578a47adb19d7104db6992e128e38 100644 (file)
@@ -166,7 +166,7 @@ static unsigned int init_chipset_amd74xx(struct pci_dev *dev)
         * Check for broken FIFO support.
         */
        if (dev->vendor == PCI_VENDOR_ID_AMD &&
-           dev->vendor == PCI_DEVICE_ID_AMD_VIPER_7411)
+           dev->device == PCI_DEVICE_ID_AMD_VIPER_7411)
                t &= 0x0f;
        else
                t |= 0xf0;
index b2735d28f5cc22019b88c8f159da1af91dccbb7e..ecd1e62ca91a86b0373bf7156e8326e67ffbfa25 100644 (file)
@@ -52,7 +52,7 @@ static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
        struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
        unsigned long flags;
-       int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
+       int timing_shift = (drive->dn ^ 1) * 8;
        u32 pio_timing_data;
        u16 pio_mode_data;
 
@@ -85,7 +85,7 @@ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
        struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
        unsigned long flags;
-       int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
+       int timing_shift = (drive->dn ^ 1) * 8;
        u32 tmp32;
        u16 tmp16;
        u16 udma_ctl = 0;
index 0bfeb0c79d6e8e172cdbb5fd3af9a9df084351c5..ddfbea41d296a738a1efb5ace07b22b9a7dff2ad 100644 (file)
@@ -55,7 +55,7 @@
 
 static DEFINE_MUTEX(idecd_ref_mutex);
 
-static void ide_cd_release(struct kref *);
+static void ide_cd_release(struct device *);
 
 static struct cdrom_info *ide_cd_get(struct gendisk *disk)
 {
@@ -67,7 +67,7 @@ static struct cdrom_info *ide_cd_get(struct gendisk *disk)
                if (ide_device_get(cd->drive))
                        cd = NULL;
                else
-                       kref_get(&cd->kref);
+                       get_device(&cd->dev);
 
        }
        mutex_unlock(&idecd_ref_mutex);
@@ -79,7 +79,7 @@ static void ide_cd_put(struct cdrom_info *cd)
        ide_drive_t *drive = cd->drive;
 
        mutex_lock(&idecd_ref_mutex);
-       kref_put(&cd->kref, ide_cd_release);
+       put_device(&cd->dev);
        ide_device_put(drive);
        mutex_unlock(&idecd_ref_mutex);
 }
@@ -194,6 +194,14 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive,
                        bio_sectors = max(bio_sectors(failed_command->bio), 4U);
                        sector &= ~(bio_sectors - 1);
 
+                       /*
+                        * The SCSI specification allows for the value
+                        * returned by READ CAPACITY to be up to 75 2K
+                        * sectors past the last readable block.
+                        * Therefore, if we hit a medium error within the
+                        * last 75 2K sectors, we decrease the saved size
+                        * value.
+                        */
                        if (sector < get_capacity(info->disk) &&
                            drive->probed_capacity - sector < 4 * 75)
                                set_capacity(info->disk, sector);
@@ -1790,15 +1798,17 @@ static void ide_cd_remove(ide_drive_t *drive)
        ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
 
        ide_proc_unregister_driver(drive, info->driver);
-
+       device_del(&info->dev);
        del_gendisk(info->disk);
 
-       ide_cd_put(info);
+       mutex_lock(&idecd_ref_mutex);
+       put_device(&info->dev);
+       mutex_unlock(&idecd_ref_mutex);
 }
 
-static void ide_cd_release(struct kref *kref)
+static void ide_cd_release(struct device *dev)
 {
-       struct cdrom_info *info = to_ide_drv(kref, cdrom_info);
+       struct cdrom_info *info = to_ide_drv(dev, cdrom_info);
        struct cdrom_device_info *devinfo = &info->devinfo;
        ide_drive_t *drive = info->drive;
        struct gendisk *g = info->disk;
@@ -1997,7 +2007,12 @@ static int ide_cd_probe(ide_drive_t *drive)
 
        ide_init_disk(g, drive);
 
-       kref_init(&info->kref);
+       info->dev.parent = &drive->gendev;
+       info->dev.release = ide_cd_release;
+       dev_set_name(&info->dev, dev_name(&drive->gendev));
+
+       if (device_register(&info->dev))
+               goto out_free_disk;
 
        info->drive = drive;
        info->driver = &ide_cdrom_driver;
@@ -2011,7 +2026,7 @@ static int ide_cd_probe(ide_drive_t *drive)
        g->driverfs_dev = &drive->gendev;
        g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
        if (ide_cdrom_setup(drive)) {
-               ide_cd_release(&info->kref);
+               put_device(&info->dev);
                goto failed;
        }
 
@@ -2021,6 +2036,8 @@ static int ide_cd_probe(ide_drive_t *drive)
        add_disk(g);
        return 0;
 
+out_free_disk:
+       put_disk(g);
 out_free_cd:
        kfree(info);
 failed:
index ac40d6cb90a240725ae40d661e428e27ebc36aef..c878bfcf111698430e8f870c0ccbc4e12b6e71ca 100644 (file)
@@ -80,7 +80,7 @@ struct cdrom_info {
        ide_drive_t             *drive;
        struct ide_driver       *driver;
        struct gendisk          *disk;
-       struct kref             kref;
+       struct device           dev;
 
        /* Buffer for table of contents.  NULL if we haven't allocated
           a TOC buffer for this device yet. */
index 7857b209c6df7616397e9a1e20a621807729f83e..047109419902c0ad6b3f741e68fdaab0e05a1069 100644 (file)
@@ -25,7 +25,7 @@ module_param(debug_mask, ulong, 0644);
 
 static DEFINE_MUTEX(ide_disk_ref_mutex);
 
-static void ide_disk_release(struct kref *);
+static void ide_disk_release(struct device *);
 
 static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
 {
@@ -37,7 +37,7 @@ static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
                if (ide_device_get(idkp->drive))
                        idkp = NULL;
                else
-                       kref_get(&idkp->kref);
+                       get_device(&idkp->dev);
        }
        mutex_unlock(&ide_disk_ref_mutex);
        return idkp;
@@ -48,7 +48,7 @@ static void ide_disk_put(struct ide_disk_obj *idkp)
        ide_drive_t *drive = idkp->drive;
 
        mutex_lock(&ide_disk_ref_mutex);
-       kref_put(&idkp->kref, ide_disk_release);
+       put_device(&idkp->dev);
        ide_device_put(drive);
        mutex_unlock(&ide_disk_ref_mutex);
 }
@@ -66,17 +66,18 @@ static void ide_gd_remove(ide_drive_t *drive)
        struct gendisk *g = idkp->disk;
 
        ide_proc_unregister_driver(drive, idkp->driver);
-
+       device_del(&idkp->dev);
        del_gendisk(g);
-
        drive->disk_ops->flush(drive);
 
-       ide_disk_put(idkp);
+       mutex_lock(&ide_disk_ref_mutex);
+       put_device(&idkp->dev);
+       mutex_unlock(&ide_disk_ref_mutex);
 }
 
-static void ide_disk_release(struct kref *kref)
+static void ide_disk_release(struct device *dev)
 {
-       struct ide_disk_obj *idkp = to_ide_drv(kref, ide_disk_obj);
+       struct ide_disk_obj *idkp = to_ide_drv(dev, ide_disk_obj);
        ide_drive_t *drive = idkp->drive;
        struct gendisk *g = idkp->disk;
 
@@ -348,7 +349,12 @@ static int ide_gd_probe(ide_drive_t *drive)
 
        ide_init_disk(g, drive);
 
-       kref_init(&idkp->kref);
+       idkp->dev.parent = &drive->gendev;
+       idkp->dev.release = ide_disk_release;
+       dev_set_name(&idkp->dev, dev_name(&drive->gendev));
+
+       if (device_register(&idkp->dev))
+               goto out_free_disk;
 
        idkp->drive = drive;
        idkp->driver = &ide_gd_driver;
@@ -373,6 +379,8 @@ static int ide_gd_probe(ide_drive_t *drive)
        add_disk(g);
        return 0;
 
+out_free_disk:
+       put_disk(g);
 out_free_idkp:
        kfree(idkp);
 failed:
index a86779f0756b7c117ece8a93c3acaa649c6dd9d9..b604bdd318a1294a6e7cb8c9d2addcca68f8759d 100644 (file)
@@ -17,7 +17,7 @@ struct ide_disk_obj {
        ide_drive_t             *drive;
        struct ide_driver       *driver;
        struct gendisk          *disk;
-       struct kref             kref;
+       struct device           dev;
        unsigned int            openers;        /* protected by BKL for now */
 
        /* Last failed packet command */
index d7ecd3c79757f036e0f9f5d083a63f31b64059b1..bb450a7608c2fe9a8ef08f19b03d86ba980f3fde 100644 (file)
@@ -169,7 +169,7 @@ typedef struct ide_tape_obj {
        ide_drive_t             *drive;
        struct ide_driver       *driver;
        struct gendisk          *disk;
-       struct kref             kref;
+       struct device           dev;
 
        /*
         *      failed_pc points to the last failed packet command, or contains
@@ -267,7 +267,7 @@ static DEFINE_MUTEX(idetape_ref_mutex);
 
 static struct class *idetape_sysfs_class;
 
-static void ide_tape_release(struct kref *);
+static void ide_tape_release(struct device *);
 
 static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
 {
@@ -279,7 +279,7 @@ static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
                if (ide_device_get(tape->drive))
                        tape = NULL;
                else
-                       kref_get(&tape->kref);
+                       get_device(&tape->dev);
        }
        mutex_unlock(&idetape_ref_mutex);
        return tape;
@@ -290,7 +290,7 @@ static void ide_tape_put(struct ide_tape_obj *tape)
        ide_drive_t *drive = tape->drive;
 
        mutex_lock(&idetape_ref_mutex);
-       kref_put(&tape->kref, ide_tape_release);
+       put_device(&tape->dev);
        ide_device_put(drive);
        mutex_unlock(&idetape_ref_mutex);
 }
@@ -308,7 +308,7 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
        mutex_lock(&idetape_ref_mutex);
        tape = idetape_devs[i];
        if (tape)
-               kref_get(&tape->kref);
+               get_device(&tape->dev);
        mutex_unlock(&idetape_ref_mutex);
        return tape;
 }
@@ -2256,15 +2256,17 @@ static void ide_tape_remove(ide_drive_t *drive)
        idetape_tape_t *tape = drive->driver_data;
 
        ide_proc_unregister_driver(drive, tape->driver);
-
+       device_del(&tape->dev);
        ide_unregister_region(tape->disk);
 
-       ide_tape_put(tape);
+       mutex_lock(&idetape_ref_mutex);
+       put_device(&tape->dev);
+       mutex_unlock(&idetape_ref_mutex);
 }
 
-static void ide_tape_release(struct kref *kref)
+static void ide_tape_release(struct device *dev)
 {
-       struct ide_tape_obj *tape = to_ide_drv(kref, ide_tape_obj);
+       struct ide_tape_obj *tape = to_ide_drv(dev, ide_tape_obj);
        ide_drive_t *drive = tape->drive;
        struct gendisk *g = tape->disk;
 
@@ -2407,7 +2409,12 @@ static int ide_tape_probe(ide_drive_t *drive)
 
        ide_init_disk(g, drive);
 
-       kref_init(&tape->kref);
+       tape->dev.parent = &drive->gendev;
+       tape->dev.release = ide_tape_release;
+       dev_set_name(&tape->dev, dev_name(&drive->gendev));
+
+       if (device_register(&tape->dev))
+               goto out_free_disk;
 
        tape->drive = drive;
        tape->driver = &idetape_driver;
@@ -2436,6 +2443,8 @@ static int ide_tape_probe(ide_drive_t *drive)
 
        return 0;
 
+out_free_disk:
+       put_disk(g);
 out_free_tape:
        kfree(tape);
 failed:
index 258805da15c33f596079fd1a804b25d24d10c2cb..0920e3b0c962451d6e98cff91bf87e5e150b0afb 100644 (file)
@@ -337,6 +337,7 @@ static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp)
        int a, b, i, j = 1;
        unsigned int *dev_param_mask = (unsigned int *)kp->arg;
 
+       /* controller . device (0 or 1) [ : 1 (set) | 0 (clear) ] */
        if (sscanf(s, "%d.%d:%d", &a, &b, &j) != 3 &&
            sscanf(s, "%d.%d", &a, &b) != 2)
                return -EINVAL;
@@ -349,7 +350,7 @@ static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp)
        if (j)
                *dev_param_mask |= (1 << i);
        else
-               *dev_param_mask &= (1 << i);
+               *dev_param_mask &= ~(1 << i);
 
        return 0;
 }
@@ -392,6 +393,8 @@ static int ide_set_disk_chs(const char *str, struct kernel_param *kp)
 {
        int a, b, c = 0, h = 0, s = 0, i, j = 1;
 
+       /* controller . device (0 or 1) : Cylinders , Heads , Sectors */
+       /* controller . device (0 or 1) : 1 (use CHS) | 0 (ignore CHS) */
        if (sscanf(str, "%d.%d:%d,%d,%d", &a, &b, &c, &h, &s) != 5 &&
            sscanf(str, "%d.%d:%d", &a, &b, &j) != 3)
                return -EINVAL;
@@ -407,7 +410,7 @@ static int ide_set_disk_chs(const char *str, struct kernel_param *kp)
        if (j)
                ide_disks |= (1 << i);
        else
-               ide_disks &= (1 << i);
+               ide_disks &= ~(1 << i);
 
        ide_disks_chs[i].cyl  = c;
        ide_disks_chs[i].head = h;
@@ -469,6 +472,8 @@ static int ide_set_ignore_cable(const char *s, struct kernel_param *kp)
 {
        int i, j = 1;
 
+       /* controller (ignore) */
+       /* controller : 1 (ignore) | 0 (use) */
        if (sscanf(s, "%d:%d", &i, &j) != 2 && sscanf(s, "%d", &i) != 1)
                return -EINVAL;
 
@@ -478,7 +483,7 @@ static int ide_set_ignore_cable(const char *s, struct kernel_param *kp)
        if (j)
                ide_ignore_cable |= (1 << i);
        else
-               ide_ignore_cable &= (1 << i);
+               ide_ignore_cable &= ~(1 << i);
 
        return 0;
 }
index e1c4f5437396b076bf09f55f32eed07e9ef6b9f4..13b8153112edf3394235f3009aaefd18e1197bc4 100644 (file)
@@ -5,9 +5,8 @@
  *  May be copied or modified under the terms of the GNU General Public License
  *  Based in part on the ITE vendor provided SCSI driver.
  *
- *  Documentation available from
- *     http://www.ite.com.tw/pc/IT8212F_V04.pdf
- *  Some other documents are NDA.
+ *  Documentation:
+ *     Datasheet is freely available, some other documents under NDA.
  *
  *  The ITE8212 isn't exactly a standard IDE controller. It has two
  *  modes. In pass through mode then it is an IDE controller. In its smart
index 2727bcd24194c6e36651fadbc9439721708e93a8..467373cab8e5a1fc7ed1ffcea2e14560b8898db3 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <asm/types.h>
 
+struct file;
 struct pci_dev;
 struct scatterlist;
 struct vm_area_struct;
index 2beb8d94f7bd3b7584c2c30003c98892b97d3e43..87233800372182916a51caaebbc3b06f89472963 100644 (file)
@@ -1275,7 +1275,7 @@ static void __exit ieee1394_cleanup(void)
        unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
 }
 
-module_init(ieee1394_init);
+fs_initcall(ieee1394_init);
 module_exit(ieee1394_cleanup);
 
 /* Exported symbols */
@@ -1314,6 +1314,7 @@ EXPORT_SYMBOL(hpsb_make_lock64packet);
 EXPORT_SYMBOL(hpsb_make_phypacket);
 EXPORT_SYMBOL(hpsb_read);
 EXPORT_SYMBOL(hpsb_write);
+EXPORT_SYMBOL(hpsb_lock);
 EXPORT_SYMBOL(hpsb_packet_success);
 
 /** highlevel.c **/
index 10c3d9f8c038ea944750bff2e913ef8b3c12d8b0..675b3135d5f19a78816976b0835deb54468c94af 100644 (file)
@@ -501,8 +501,6 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
        if (length == 0)
                return -EINVAL;
 
-       BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
-
        packet = hpsb_make_readpacket(host, node, addr, length);
 
        if (!packet) {
@@ -550,8 +548,6 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
        if (length == 0)
                return -EINVAL;
 
-       BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
-
        packet = hpsb_make_writepacket(host, node, addr, buffer, length);
 
        if (!packet)
@@ -570,3 +566,30 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
 
        return retval;
 }
+
+int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
+             u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
+{
+       struct hpsb_packet *packet;
+       int retval = 0;
+
+       packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
+       if (!packet)
+               return -ENOMEM;
+
+       packet->generation = generation;
+       retval = hpsb_send_packet_and_wait(packet);
+       if (retval < 0)
+               goto hpsb_lock_fail;
+
+       retval = hpsb_packet_success(packet);
+
+       if (retval == 0)
+               *data = packet->data[0];
+
+hpsb_lock_fail:
+       hpsb_free_tlabel(packet);
+       hpsb_free_packet(packet);
+
+       return retval;
+}
index d2d5bc3546d74093b2fe0ce56ef913b63ef6648e..20b693be14b22f558491285e895e7cad5bf20828 100644 (file)
@@ -30,6 +30,8 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
              u64 addr, quadlet_t *buffer, size_t length);
 int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
               u64 addr, quadlet_t *buffer, size_t length);
+int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
+             u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
 
 #ifdef HPSB_DEBUG_TLABELS
 extern spinlock_t hpsb_tlabel_lock;
index b5de5f21ef78a57e45032500867fdb24538de00e..c2089c093aa76eaf1165391a3ea2d8d5b023b960 100644 (file)
@@ -13,6 +13,7 @@
 #define IEEE1394_ISO_H
 
 #include <linux/spinlock_types.h>
+#include <linux/wait.h>
 #include <asm/atomic.h>
 #include <asm/types.h>
 
index 906c5a98d8142585a1ad86ef2c1d55f9b16cc3eb..53aada5bbe1ebad918803836b8752a21cecbb37e 100644 (file)
@@ -971,6 +971,9 @@ static struct unit_directory *nodemgr_process_unit_directory
        ud->ud_kv = ud_kv;
        ud->id = (*id)++;
 
+       /* inherit vendor_id from root directory if none exists in unit dir */
+       ud->vendor_id = ne->vendor_id;
+
        csr1212_for_each_dir_entry(ne->csr, kv, ud_kv, dentry) {
                switch (kv->key.id) {
                case CSR1212_KV_ID_VENDOR:
@@ -1265,7 +1268,8 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
                csr1212_destroy_csr(csr);
        }
 
-       /* Mark the node current */
+       /* Finally, mark the node current */
+       smp_wmb();
        ne->generation = generation;
 
        if (ne->in_limbo) {
@@ -1798,7 +1802,7 @@ void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet)
 {
        packet->host = ne->host;
        packet->generation = ne->generation;
-       barrier();
+       smp_rmb();
        packet->node_id = ne->nodeid;
 }
 
@@ -1807,7 +1811,7 @@ int hpsb_node_write(struct node_entry *ne, u64 addr,
 {
        unsigned int generation = ne->generation;
 
-       barrier();
+       smp_rmb();
        return hpsb_write(ne->host, ne->nodeid, generation,
                          addr, buffer, length);
 }
index 15ea09733e84fbc1ee4588f730ed77b049aa1e5c..ee5acdbd114aed18c942fd11c6a38bbc3193be10 100644 (file)
 #define _IEEE1394_NODEMGR_H
 
 #include <linux/device.h>
+#include <asm/system.h>
 #include <asm/types.h>
 
 #include "ieee1394_core.h"
+#include "ieee1394_transactions.h"
 #include "ieee1394_types.h"
 
 struct csr1212_csr;
@@ -154,6 +156,22 @@ static inline int hpsb_node_entry_valid(struct node_entry *ne)
 void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet);
 int hpsb_node_write(struct node_entry *ne, u64 addr,
                    quadlet_t *buffer, size_t length);
+static inline int hpsb_node_read(struct node_entry *ne, u64 addr,
+                                quadlet_t *buffer, size_t length)
+{
+       unsigned int g = ne->generation;
+
+       smp_rmb();
+       return hpsb_read(ne->host, ne->nodeid, g, addr, buffer, length);
+}
+static inline int hpsb_node_lock(struct node_entry *ne, u64 addr, int extcode,
+                                quadlet_t *buffer, quadlet_t arg)
+{
+       unsigned int g = ne->generation;
+
+       smp_rmb();
+       return hpsb_lock(ne->host, ne->nodeid, g, addr, extcode, buffer, arg);
+}
 int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *));
 
 int init_ieee1394_nodemgr(void);
index c3c8b9bc40ae6220f46a8dba295f8a87c7e1e6e3..45470f18d7e9ea7c252a1a2c4e671490483da36b 100644 (file)
@@ -839,7 +839,7 @@ static void atkbd_disconnect(struct serio *serio)
  */
 static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd)
 {
-       const unsigned int forced_release_keys[] = {
+       static const unsigned int forced_release_keys[] = {
                0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93,
        };
        int i;
@@ -856,7 +856,7 @@ static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd)
  */
 static void atkbd_hp_keymap_fixup(struct atkbd *atkbd)
 {
-       const unsigned int forced_release_keys[] = {
+       static const unsigned int forced_release_keys[] = {
                0x94,
        };
        int i;
index 19284016e0f4d1c2ce47e3f86f4a5f59e04445fc..ee855c5202e827b8545978f023204937b13dccc2 100644 (file)
@@ -209,8 +209,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev)
                goto out;
        }
 
-       if (!pdata->debounce_time || !pdata->debounce_time > MAX_MULT ||
-           !pdata->coldrive_time || !pdata->coldrive_time > MAX_MULT) {
+       if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT ||
+           !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) {
                printk(KERN_ERR DRV_NAME
                        ": Invalid Debounce/Columdrive Time from pdata\n");
                bfin_write_KPAD_MSEL(0xFF0);    /* Default MSEL */
index c8ed065ea0cbd9f2d360331c101b2052bc8d2ebb..abb04c82c622edd638228054f1d6dc8a9066accd 100644 (file)
@@ -288,7 +288,7 @@ static int corgikbd_resume(struct platform_device *dev)
 #define corgikbd_resume                NULL
 #endif
 
-static int __init corgikbd_probe(struct platform_device *pdev)
+static int __devinit corgikbd_probe(struct platform_device *pdev)
 {
        struct corgikbd *corgikbd;
        struct input_dev *input_dev;
@@ -368,7 +368,7 @@ static int __init corgikbd_probe(struct platform_device *pdev)
        return err;
 }
 
-static int corgikbd_remove(struct platform_device *pdev)
+static int __devexit corgikbd_remove(struct platform_device *pdev)
 {
        int i;
        struct corgikbd *corgikbd = platform_get_drvdata(pdev);
@@ -388,7 +388,7 @@ static int corgikbd_remove(struct platform_device *pdev)
 
 static struct platform_driver corgikbd_driver = {
        .probe          = corgikbd_probe,
-       .remove         = corgikbd_remove,
+       .remove         = __devexit_p(corgikbd_remove),
        .suspend        = corgikbd_suspend,
        .resume         = corgikbd_resume,
        .driver         = {
@@ -397,7 +397,7 @@ static struct platform_driver corgikbd_driver = {
        },
 };
 
-static int __devinit corgikbd_init(void)
+static int __init corgikbd_init(void)
 {
        return platform_driver_register(&corgikbd_driver);
 }
index 3f3d1198cdb10dd76fb4973766ab9d6e1908d246..058fa8b02c21ee1b939085c024c23884e2f6ca1d 100644 (file)
@@ -279,7 +279,7 @@ static int omap_kp_resume(struct platform_device *dev)
 #define omap_kp_resume NULL
 #endif
 
-static int __init omap_kp_probe(struct platform_device *pdev)
+static int __devinit omap_kp_probe(struct platform_device *pdev)
 {
        struct omap_kp *omap_kp;
        struct input_dev *input_dev;
@@ -422,7 +422,7 @@ err1:
        return -EINVAL;
 }
 
-static int omap_kp_remove(struct platform_device *pdev)
+static int __devexit omap_kp_remove(struct platform_device *pdev)
 {
        struct omap_kp *omap_kp = platform_get_drvdata(pdev);
 
@@ -454,7 +454,7 @@ static int omap_kp_remove(struct platform_device *pdev)
 
 static struct platform_driver omap_kp_driver = {
        .probe          = omap_kp_probe,
-       .remove         = omap_kp_remove,
+       .remove         = __devexit_p(omap_kp_remove),
        .suspend        = omap_kp_suspend,
        .resume         = omap_kp_resume,
        .driver         = {
@@ -463,7 +463,7 @@ static struct platform_driver omap_kp_driver = {
        },
 };
 
-static int __devinit omap_kp_init(void)
+static int __init omap_kp_init(void)
 {
        printk(KERN_INFO "OMAP Keypad Driver\n");
        return platform_driver_register(&omap_kp_driver);
index c48b76a46a58ef5adf68601171007db16cae1abb..9d1781a618e99466f0855f480cbb8974e6a3fbd8 100644 (file)
@@ -343,7 +343,7 @@ static int spitzkbd_resume(struct platform_device *dev)
 #define spitzkbd_resume                NULL
 #endif
 
-static int __init spitzkbd_probe(struct platform_device *dev)
+static int __devinit spitzkbd_probe(struct platform_device *dev)
 {
        struct spitzkbd *spitzkbd;
        struct input_dev *input_dev;
@@ -444,7 +444,7 @@ static int __init spitzkbd_probe(struct platform_device *dev)
        return err;
 }
 
-static int spitzkbd_remove(struct platform_device *dev)
+static int __devexit spitzkbd_remove(struct platform_device *dev)
 {
        int i;
        struct spitzkbd *spitzkbd = platform_get_drvdata(dev);
@@ -470,7 +470,7 @@ static int spitzkbd_remove(struct platform_device *dev)
 
 static struct platform_driver spitzkbd_driver = {
        .probe          = spitzkbd_probe,
-       .remove         = spitzkbd_remove,
+       .remove         = __devexit_p(spitzkbd_remove),
        .suspend        = spitzkbd_suspend,
        .resume         = spitzkbd_resume,
        .driver         = {
@@ -479,7 +479,7 @@ static struct platform_driver spitzkbd_driver = {
        },
 };
 
-static int __devinit spitzkbd_init(void)
+static int __init spitzkbd_init(void)
 {
        return platform_driver_register(&spitzkbd_driver);
 }
index 093c8c1bca746b651a4c18ab260931a02dac5dae..9705f3a00a3d944a5e3883e3cdf2fce4de20a2e8 100644 (file)
@@ -70,7 +70,7 @@ config MOUSE_PS2_SYNAPTICS
 config MOUSE_PS2_LIFEBOOK
        bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED
        default y
-       depends on MOUSE_PS2
+       depends on MOUSE_PS2 && X86
        help
          Say Y here if you have a Fujitsu B-series Lifebook PS/2
          TouchScreen connected to your system.
index b9a25d57bc5ea085222597430fd8bb242ba2adee..6ab0eb1ada1c6e94c5c4f3e14d846e24f6b3339d 100644 (file)
@@ -542,7 +542,7 @@ int elantech_detect(struct psmouse *psmouse, int set_properties)
            ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE11) ||
            ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE11) ||
            ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) {
-               pr_err("elantech.c: sending Elantech magic knock failed.\n");
+               pr_debug("elantech.c: sending Elantech magic knock failed.\n");
                return -1;
        }
 
@@ -551,8 +551,27 @@ int elantech_detect(struct psmouse *psmouse, int set_properties)
         * set of magic numbers
         */
        if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) {
-               pr_info("elantech.c: unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
-                       param[0], param[1], param[2]);
+               pr_debug("elantech.c: "
+                        "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n",
+                        param[0], param[1], param[2]);
+               return -1;
+       }
+
+       /*
+        * Query touchpad's firmware version and see if it reports known
+        * value to avoid mis-detection. Logitech mice are known to respond
+        * to Elantech magic knock and there might be more.
+        */
+       if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) {
+               pr_debug("elantech.c: failed to query firmware version.\n");
+               return -1;
+       }
+
+       pr_debug("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n",
+                param[0], param[1], param[2]);
+
+       if (param[0] == 0 || param[1] != 0) {
+               pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n");
                return -1;
        }
 
@@ -600,8 +619,7 @@ int elantech_init(struct psmouse *psmouse)
        int i, error;
        unsigned char param[3];
 
-       etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL);
-       psmouse->private = etd;
+       psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL);
        if (!etd)
                return -1;
 
@@ -610,14 +628,12 @@ int elantech_init(struct psmouse *psmouse)
                etd->parity[i] = etd->parity[i & (i - 1)] ^ 1;
 
        /*
-        * Find out what version hardware this is
+        * Do the version query again so we can store the result
         */
        if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) {
                pr_err("elantech.c: failed to query firmware version.\n");
                goto init_fail;
        }
-       pr_info("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n",
-               param[0], param[1], param[2]);
        etd->fw_version_maj = param[0];
        etd->fw_version_min = param[2];
 
index d297accf9a7feeb8077737c187d39d64c3f89c0b..1e827ad0afbedd58a36438cb1fe23e4a0ad3adf8 100644 (file)
@@ -83,7 +83,7 @@ static int write_tbcr(struct pxa930_trkball *trkball, int v)
 
        __raw_writel(v, trkball->mmio_base + TBCR);
 
-       while (i--) {
+       while (--i) {
                if (__raw_readl(trkball->mmio_base + TBCR) == v)
                        break;
                msleep(1);
index 865fc69e9bc39e8ef81b213722e572c95917fb0e..f3e4f7b0240d04d40521f3ff1b79302293c0ea32 100644 (file)
@@ -182,11 +182,6 @@ static int synaptics_identify(struct psmouse *psmouse)
 
 static int synaptics_query_hardware(struct psmouse *psmouse)
 {
-       int retries = 0;
-
-       while ((retries++ < 3) && psmouse_reset(psmouse))
-               /* empty */;
-
        if (synaptics_identify(psmouse))
                return -1;
        if (synaptics_model_id(psmouse))
@@ -582,6 +577,8 @@ static int synaptics_reconnect(struct psmouse *psmouse)
        struct synaptics_data *priv = psmouse->private;
        struct synaptics_data old_priv = *priv;
 
+       psmouse_reset(psmouse);
+
        if (synaptics_detect(psmouse, 0))
                return -1;
 
@@ -640,6 +637,8 @@ int synaptics_init(struct psmouse *psmouse)
        if (!priv)
                return -1;
 
+       psmouse_reset(psmouse);
+
        if (synaptics_query_hardware(psmouse)) {
                printk(KERN_ERR "Unable to query Synaptics hardware.\n");
                goto init_fail;
index b10ffae7c39b341319f89142e01b0845fe5001c3..e29cdc13a199c007ab8ac6c6337086fe3685c5c4 100644 (file)
@@ -57,7 +57,7 @@ static int amba_kmi_write(struct serio *io, unsigned char val)
        struct amba_kmi_port *kmi = io->port_data;
        unsigned int timeleft = 10000; /* timeout in 100ms */
 
-       while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--)
+       while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && --timeleft)
                udelay(10);
 
        if (timeleft)
@@ -129,8 +129,8 @@ static int amba_kmi_probe(struct amba_device *dev, void *id)
        io->write       = amba_kmi_write;
        io->open        = amba_kmi_open;
        io->close       = amba_kmi_close;
-       strlcpy(io->name, dev->dev.bus_id, sizeof(io->name));
-       strlcpy(io->phys, dev->dev.bus_id, sizeof(io->phys));
+       strlcpy(io->name, dev_name(&dev->dev), sizeof(io->name));
+       strlcpy(io->phys, dev_name(&dev->dev), sizeof(io->phys));
        io->port_data   = kmi;
        io->dev.parent  = &dev->dev;
 
index adc3bd6e7f7bbc9a0d038d748dd3f95794a46f8f..bd0f92d9f40f991c479d9237b851e381887f47e8 100644 (file)
@@ -359,7 +359,7 @@ static int __init gscps2_probe(struct parisc_device *dev)
 
        snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s",
                 (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse");
-       strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
+       strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys));
        serio->id.type          = SERIO_8042;
        serio->write            = gscps2_write;
        serio->open             = gscps2_open;
index 2ad88780a170aec1a61bc118c6013ae09dbbfacd..57953c0eb82fa8302b23eb84edf9e6507e5915b3 100644 (file)
@@ -246,8 +246,8 @@ static int __devinit ps2_probe(struct sa1111_dev *dev)
        serio->write            = ps2_write;
        serio->open             = ps2_open;
        serio->close            = ps2_close;
-       strlcpy(serio->name, dev->dev.bus_id, sizeof(serio->name));
-       strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
+       strlcpy(serio->name, dev_name(&dev->dev), sizeof(serio->name));
+       strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys));
        serio->port_data        = ps2if;
        serio->dev.parent       = &dev->dev;
        ps2if->io               = serio;
index a89a6a8f05e6c9631f7368fb2488e080490b6fe0..055969e8be132de9a3954c85384b9801b4bcb667 100644 (file)
@@ -236,7 +236,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
        ts_dev->bufferedmeasure = 0;
 
        snprintf(ts_dev->phys, sizeof(ts_dev->phys),
-                "%s/input0", pdev->dev.bus_id);
+                "%s/input0", dev_name(&pdev->dev));
 
        input_dev->name = "atmel touch screen controller";
        input_dev->phys = ts_dev->phys;
index 65202c9f63ffbe4f7838654d59514ea34048ed7d..3fb51b54fe61e22a9960ae0cb58d19721a5d1932 100644 (file)
@@ -268,7 +268,7 @@ static int corgits_resume(struct platform_device *dev)
 #define corgits_resume         NULL
 #endif
 
-static int __init corgits_probe(struct platform_device *pdev)
+static int __devinit corgits_probe(struct platform_device *pdev)
 {
        struct corgi_ts *corgi_ts;
        struct input_dev *input_dev;
@@ -343,7 +343,7 @@ static int __init corgits_probe(struct platform_device *pdev)
        return err;
 }
 
-static int corgits_remove(struct platform_device *pdev)
+static int __devexit corgits_remove(struct platform_device *pdev)
 {
        struct corgi_ts *corgi_ts = platform_get_drvdata(pdev);
 
@@ -352,12 +352,13 @@ static int corgits_remove(struct platform_device *pdev)
        corgi_ts->machinfo->put_hsync();
        input_unregister_device(corgi_ts->input);
        kfree(corgi_ts);
+
        return 0;
 }
 
 static struct platform_driver corgits_driver = {
        .probe          = corgits_probe,
-       .remove         = corgits_remove,
+       .remove         = __devexit_p(corgits_remove),
        .suspend        = corgits_suspend,
        .resume         = corgits_resume,
        .driver         = {
@@ -366,7 +367,7 @@ static struct platform_driver corgits_driver = {
        },
 };
 
-static int __devinit corgits_init(void)
+static int __init corgits_init(void)
 {
        return platform_driver_register(&corgits_driver);
 }
index b75dc2990574e9549d483846d30f77e6f0eb08c1..4ab070246892c5935d8482af73f0499b98b199b6 100644 (file)
@@ -289,7 +289,8 @@ static int tsc2007_probe(struct i2c_client *client,
 
        pdata->init_platform_hw();
 
-       snprintf(ts->phys, sizeof(ts->phys), "%s/input0", client->dev.bus_id);
+       snprintf(ts->phys, sizeof(ts->phys),
+                "%s/input0", dev_name(&client->dev));
 
        input_dev->name = "TSC2007 Touchscreen";
        input_dev->phys = ts->phys;
index 5080b26ba1608ba2c54e1abe4de83d72d2ed62cf..fb7cb9bdfbd5c4971cedeb064b8839ae3d09365a 100644 (file)
@@ -60,6 +60,10 @@ static int swap_xy;
 module_param(swap_xy, bool, 0644);
 MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
 
+static int hwcalib_xy;
+module_param(hwcalib_xy, bool, 0644);
+MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available");
+
 /* device specifc data/functions */
 struct usbtouch_usb;
 struct usbtouch_device_info {
@@ -118,6 +122,7 @@ enum {
 
 #define USB_DEVICE_HID_CLASS(vend, prod) \
        .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \
+               | USB_DEVICE_ID_MATCH_INT_PROTOCOL \
                | USB_DEVICE_ID_MATCH_DEVICE, \
        .idVendor = (vend), \
        .idProduct = (prod), \
@@ -260,8 +265,13 @@ static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 
 static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
-       dev->x = (pkt[8] << 8) | pkt[7];
-       dev->y = (pkt[10] << 8) | pkt[9];
+       if (hwcalib_xy) {
+               dev->x = (pkt[4] << 8) | pkt[3];
+               dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]);
+       } else {
+               dev->x = (pkt[8] << 8) | pkt[7];
+               dev->y = (pkt[10] << 8) | pkt[9];
+       }
        dev->touch = (pkt[2] & 0x40) ? 1 : 0;
 
        return 1;
@@ -294,6 +304,12 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
                        return ret;
        }
 
+       /* Default min/max xy are the raw values, override if using hw-calib */
+       if (hwcalib_xy) {
+               input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0);
+               input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0);
+       }
+
        return 0;
 }
 #endif
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 01e3cffd03b8fd28dae613614f3efd10c04f2416..e2466425d9cad798edf40858183404408b319e3d 100644 (file)
@@ -1237,8 +1237,9 @@ static void end_sync_write(struct bio *bio, int error)
        update_head_pos(mirror, r1_bio);
 
        if (atomic_dec_and_test(&r1_bio->remaining)) {
-               md_done_sync(mddev, r1_bio->sectors, uptodate);
+               sector_t s = r1_bio->sectors;
                put_buf(r1_bio);
+               md_done_sync(mddev, s, uptodate);
        }
 }
 
index 6736d6dff981c8a1a5c12e773c3d788410a0f191..7301631abe0453a4791dec55ba0eff84912876c3 100644 (file)
@@ -1236,6 +1236,7 @@ static void end_sync_read(struct bio *bio, int error)
        /* for reconstruct, we always reschedule after a read.
         * for resync, only after all reads
         */
+       rdev_dec_pending(conf->mirrors[d].rdev, conf->mddev);
        if (test_bit(R10BIO_IsRecover, &r10_bio->state) ||
            atomic_dec_and_test(&r10_bio->remaining)) {
                /* we have read all the blocks,
@@ -1243,7 +1244,6 @@ static void end_sync_read(struct bio *bio, int error)
                 */
                reschedule_retry(r10_bio);
        }
-       rdev_dec_pending(conf->mirrors[d].rdev, conf->mddev);
 }
 
 static void end_sync_write(struct bio *bio, int error)
@@ -1264,11 +1264,13 @@ static void end_sync_write(struct bio *bio, int error)
 
        update_head_pos(i, r10_bio);
 
+       rdev_dec_pending(conf->mirrors[d].rdev, mddev);
        while (atomic_dec_and_test(&r10_bio->remaining)) {
                if (r10_bio->master_bio == NULL) {
                        /* the primary of several recovery bios */
-                       md_done_sync(mddev, r10_bio->sectors, 1);
+                       sector_t s = r10_bio->sectors;
                        put_buf(r10_bio);
+                       md_done_sync(mddev, s, 1);
                        break;
                } else {
                        r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio;
@@ -1276,7 +1278,6 @@ static void end_sync_write(struct bio *bio, int error)
                        r10_bio = r10_bio2;
                }
        }
-       rdev_dec_pending(conf->mirrors[d].rdev, mddev);
 }
 
 /*
@@ -1749,8 +1750,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
        if (!go_faster && conf->nr_waiting)
                msleep_interruptible(1000);
 
-       bitmap_cond_end_sync(mddev->bitmap, sector_nr);
-
        /* Again, very different code for resync and recovery.
         * Both must result in an r10bio with a list of bios that
         * have bi_end_io, bi_sector, bi_bdev set,
@@ -1886,6 +1885,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                /* resync. Schedule a read for every block at this virt offset */
                int count = 0;
 
+               bitmap_cond_end_sync(mddev->bitmap, sector_nr);
+
                if (!bitmap_start_sync(mddev->bitmap, sector_nr,
                                       &sync_blocks, mddev->degraded) &&
                    !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
@@ -2010,13 +2011,13 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
        /* There is nowhere to write, so all non-sync
         * drives must be failed, so try the next chunk...
         */
-       {
-       sector_t sec = max_sector - sector_nr;
-       sectors_skipped += sec;
+       if (sector_nr + max_sync < max_sector)
+               max_sector = sector_nr + max_sync;
+
+       sectors_skipped += (max_sector - sector_nr);
        chunks_skipped ++;
        sector_nr = max_sector;
        goto skipped;
-       }
 }
 
 static int run(mddev_t *mddev)
index 40ebde53b3ce22443a60be62357c5722f64f256d..b0198691892a4a4ecab85d7febccf554c5dfe381 100644 (file)
@@ -51,6 +51,10 @@ comment "Supported SDMC DM1105 Adapters"
        depends on DVB_CORE && PCI && I2C
 source "drivers/media/dvb/dm1105/Kconfig"
 
+comment "Supported FireWire (IEEE 1394) Adapters"
+       depends on DVB_CORE && IEEE1394
+source "drivers/media/dvb/firewire/Kconfig"
+
 comment "Supported DVB Frontends"
        depends on DVB_CORE
 source "drivers/media/dvb/frontends/Kconfig"
index f91e9eb15e52effa8e9f15d1e0e2e4573beeae59..6092a5bb5a7d8901562e4efee7868cb003819d4f 100644 (file)
@@ -3,3 +3,5 @@
 #
 
 obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/
+
+obj-$(CONFIG_DVB_FIREDTV)      += firewire/
index b386cc66c6b31e3b89a2b982e5ad8efede9fdead..451974ba32f37adb656356291146716c8358d819 100644 (file)
@@ -192,6 +192,7 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d
 
        return 0;
 }
+EXPORT_SYMBOL(flexcop_pid_feed_control);
 
 void flexcop_hw_filter_init(struct flexcop_device *fc)
 {
index 5b30dfc7846b2fbbe870efb38901e311c3bc2375..76e37fd96bb6a3995e1ec301b36d166f507e54d3 100644 (file)
@@ -13,9 +13,9 @@ static int enable_pid_filtering = 1;
 module_param(enable_pid_filtering, int, 0444);
 MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1");
 
-static int irq_chk_intv;
+static int irq_chk_intv = 100;
 module_param(irq_chk_intv, int, 0644);
-MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently just debugging).");
+MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ streaming watchdog.");
 
 #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
 #define dprintk(level,args...) \
@@ -34,7 +34,9 @@ MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently jus
 
 static int debug;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS);
+MODULE_PARM_DESC(debug,
+       "set debug level (1=info,2=regs,4=TS,8=irqdma,16=check (|-able))."
+        DEBSTATUS);
 
 #define DRIVER_VERSION "0.1"
 #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver"
@@ -58,6 +60,8 @@ struct flexcop_pci {
        int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */
        u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */
        int count;
+       int count_prev;
+       int stream_problem;
 
        spinlock_t irq_lock;
 
@@ -103,18 +107,32 @@ static void flexcop_pci_irq_check_work(struct work_struct *work)
                container_of(work, struct flexcop_pci, irq_check_work.work);
        struct flexcop_device *fc = fc_pci->fc_dev;
 
-       flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714);
-
-       flexcop_dump_reg(fc_pci->fc_dev,dma1_000,4);
-
-       if (v.sram_dest_reg_714.net_ovflow_error)
-               deb_chk("sram net_ovflow_error\n");
-       if (v.sram_dest_reg_714.media_ovflow_error)
-               deb_chk("sram media_ovflow_error\n");
-       if (v.sram_dest_reg_714.cai_ovflow_error)
-               deb_chk("sram cai_ovflow_error\n");
-       if (v.sram_dest_reg_714.cai_ovflow_error)
-               deb_chk("sram cai_ovflow_error\n");
+       if (fc->feedcount) {
+
+               if (fc_pci->count == fc_pci->count_prev) {
+                       deb_chk("no IRQ since the last check\n");
+                       if (fc_pci->stream_problem++ == 3) {
+                               struct dvb_demux_feed *feed;
+
+                               spin_lock_irq(&fc->demux.lock);
+                               list_for_each_entry(feed, &fc->demux.feed_list,
+                                       list_head) {
+                                       flexcop_pid_feed_control(fc, feed, 0);
+                               }
+
+                               list_for_each_entry(feed, &fc->demux.feed_list,
+                                       list_head) {
+                                       flexcop_pid_feed_control(fc, feed, 1);
+                               }
+                               spin_unlock_irq(&fc->demux.lock);
+
+                               fc_pci->stream_problem = 0;
+                       }
+               } else {
+                       fc_pci->stream_problem = 0;
+                       fc_pci->count_prev = fc_pci->count;
+               }
+       }
 
        schedule_delayed_work(&fc_pci->irq_check_work,
                        msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv));
@@ -216,16 +234,12 @@ static int flexcop_pci_stream_control(struct flexcop_device *fc, int onoff)
                flexcop_dma_control_timer_irq(fc,FC_DMA_1,1);
                deb_irq("IRQ enabled\n");
 
+               fc_pci->count_prev = fc_pci->count;
+
 //             fc_pci->active_dma1_addr = 0;
 //             flexcop_dma_control_size_irq(fc,FC_DMA_1,1);
 
-               if (irq_chk_intv > 0)
-                       schedule_delayed_work(&fc_pci->irq_check_work,
-                                       msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv));
        } else {
-               if (irq_chk_intv > 0)
-                       cancel_delayed_work(&fc_pci->irq_check_work);
-
                flexcop_dma_control_timer_irq(fc,FC_DMA_1,0);
                deb_irq("IRQ disabled\n");
 
@@ -299,8 +313,6 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci)
                                        IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0)
                goto err_pci_iounmap;
 
-
-
        fc_pci->init_state |= FC_PCI_INIT;
        return ret;
 
@@ -375,6 +387,10 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
        INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work);
 
+               if (irq_chk_intv > 0)
+                       schedule_delayed_work(&fc_pci->irq_check_work,
+               msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv));
+
        return ret;
 
 err_fc_exit:
@@ -393,6 +409,9 @@ static void flexcop_pci_remove(struct pci_dev *pdev)
 {
        struct flexcop_pci *fc_pci = pci_get_drvdata(pdev);
 
+       if (irq_chk_intv > 0)
+               cancel_delayed_work(&fc_pci->irq_check_work);
+
        flexcop_pci_dma_exit(fc_pci);
        flexcop_device_exit(fc_pci->fc_dev);
        flexcop_pci_exit(fc_pci);
index 676413a915b45c3302995dfe82d49d283843c625..91068952b502b753a349467c78927ae75ce8a670 100644 (file)
@@ -212,8 +212,7 @@ void flexcop_reset_block_300(struct flexcop_device *fc)
        v210.sw_reset_210.Block_reset_enable = 0xb2;
 
        fc->write_ibi_reg(fc,sw_reset_210,v210);
-       msleep(1);
-
+       udelay(1000);
        fc->write_ibi_reg(fc,ctrl_208,v208_save);
 }
 
diff --git a/drivers/media/dvb/firewire/Kconfig b/drivers/media/dvb/firewire/Kconfig
new file mode 100644 (file)
index 0000000..6902825
--- /dev/null
@@ -0,0 +1,22 @@
+config DVB_FIREDTV
+       tristate "FireDTV and FloppyDTV"
+       depends on DVB_CORE && IEEE1394
+       help
+         Support for DVB receivers from Digital Everywhere
+         which are connected via IEEE 1394 (FireWire).
+
+         These devices don't have an MPEG decoder built in,
+         so you need an external software decoder to watch TV.
+
+         To compile this driver as a module, say M here:
+         the module will be called firedtv.
+
+if DVB_FIREDTV
+
+config DVB_FIREDTV_IEEE1394
+       def_bool IEEE1394
+
+config DVB_FIREDTV_INPUT
+       def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m)
+
+endif # DVB_FIREDTV
diff --git a/drivers/media/dvb/firewire/Makefile b/drivers/media/dvb/firewire/Makefile
new file mode 100644 (file)
index 0000000..2034695
--- /dev/null
@@ -0,0 +1,8 @@
+obj-$(CONFIG_DVB_FIREDTV) += firedtv.o
+
+firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o
+firedtv-$(CONFIG_DVB_FIREDTV_IEEE1394) += firedtv-1394.o
+firedtv-$(CONFIG_DVB_FIREDTV_INPUT)    += firedtv-rc.o
+
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-$(CONFIG_DVB_FIREDTV_IEEE1394) += -Idrivers/ieee1394
diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c
new file mode 100644 (file)
index 0000000..4e20765
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2007-2008 Ben Backx <ben@bbackx.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <dma.h>
+#include <csr1212.h>
+#include <highlevel.h>
+#include <hosts.h>
+#include <ieee1394.h>
+#include <iso.h>
+#include <nodemgr.h>
+
+#include "firedtv.h"
+
+static LIST_HEAD(node_list);
+static DEFINE_SPINLOCK(node_list_lock);
+
+#define FIREWIRE_HEADER_SIZE   4
+#define CIP_HEADER_SIZE                8
+
+static void rawiso_activity_cb(struct hpsb_iso *iso)
+{
+       struct firedtv *f, *fdtv = NULL;
+       unsigned int i, num, packet;
+       unsigned char *buf;
+       unsigned long flags;
+       int count;
+
+       spin_lock_irqsave(&node_list_lock, flags);
+       list_for_each_entry(f, &node_list, list)
+               if (f->backend_data == iso) {
+                       fdtv = f;
+                       break;
+               }
+       spin_unlock_irqrestore(&node_list_lock, flags);
+
+       packet = iso->first_packet;
+       num = hpsb_iso_n_ready(iso);
+
+       if (!fdtv) {
+               dev_err(fdtv->device, "received at unknown iso channel\n");
+               goto out;
+       }
+
+       for (i = 0; i < num; i++, packet = (packet + 1) % iso->buf_packets) {
+               buf = dma_region_i(&iso->data_buf, unsigned char,
+                       iso->infos[packet].offset + CIP_HEADER_SIZE);
+               count = (iso->infos[packet].len - CIP_HEADER_SIZE) /
+                       (188 + FIREWIRE_HEADER_SIZE);
+
+               /* ignore empty packet */
+               if (iso->infos[packet].len <= CIP_HEADER_SIZE)
+                       continue;
+
+               while (count--) {
+                       if (buf[FIREWIRE_HEADER_SIZE] == 0x47)
+                               dvb_dmx_swfilter_packets(&fdtv->demux,
+                                               &buf[FIREWIRE_HEADER_SIZE], 1);
+                       else
+                               dev_err(fdtv->device,
+                                       "skipping invalid packet\n");
+                       buf += 188 + FIREWIRE_HEADER_SIZE;
+               }
+       }
+out:
+       hpsb_iso_recv_release_packets(iso, num);
+}
+
+static inline struct node_entry *node_of(struct firedtv *fdtv)
+{
+       return container_of(fdtv->device, struct unit_directory, device)->ne;
+}
+
+static int node_lock(struct firedtv *fdtv, u64 addr, void *data, __be32 arg)
+{
+       return hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP, data,
+                             (__force quadlet_t)arg);
+}
+
+static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len)
+{
+       return hpsb_node_read(node_of(fdtv), addr, data, len);
+}
+
+static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
+{
+       return hpsb_node_write(node_of(fdtv), addr, data, len);
+}
+
+#define FDTV_ISO_BUFFER_PACKETS 256
+#define FDTV_ISO_BUFFER_SIZE (FDTV_ISO_BUFFER_PACKETS * 200)
+
+static int start_iso(struct firedtv *fdtv)
+{
+       struct hpsb_iso *iso_handle;
+       int ret;
+
+       iso_handle = hpsb_iso_recv_init(node_of(fdtv)->host,
+                               FDTV_ISO_BUFFER_SIZE, FDTV_ISO_BUFFER_PACKETS,
+                               fdtv->isochannel, HPSB_ISO_DMA_DEFAULT,
+                               -1, /* stat.config.irq_interval */
+                               rawiso_activity_cb);
+       if (iso_handle == NULL) {
+               dev_err(fdtv->device, "cannot initialize iso receive\n");
+               return -ENOMEM;
+       }
+       fdtv->backend_data = iso_handle;
+
+       ret = hpsb_iso_recv_start(iso_handle, -1, -1, 0);
+       if (ret != 0) {
+               dev_err(fdtv->device, "cannot start iso receive\n");
+               hpsb_iso_shutdown(iso_handle);
+               fdtv->backend_data = NULL;
+       }
+       return ret;
+}
+
+static void stop_iso(struct firedtv *fdtv)
+{
+       struct hpsb_iso *iso_handle = fdtv->backend_data;
+
+       if (iso_handle != NULL) {
+               hpsb_iso_stop(iso_handle);
+               hpsb_iso_shutdown(iso_handle);
+       }
+       fdtv->backend_data = NULL;
+}
+
+static const struct firedtv_backend fdtv_1394_backend = {
+       .lock           = node_lock,
+       .read           = node_read,
+       .write          = node_write,
+       .start_iso      = start_iso,
+       .stop_iso       = stop_iso,
+};
+
+static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
+                       int cts, u8 *data, size_t length)
+{
+       struct firedtv *f, *fdtv = NULL;
+       unsigned long flags;
+       int su;
+
+       if (length == 0 || (data[0] & 0xf0) != 0)
+               return;
+
+       su = data[1] & 0x7;
+
+       spin_lock_irqsave(&node_list_lock, flags);
+       list_for_each_entry(f, &node_list, list)
+               if (node_of(f)->host == host &&
+                   node_of(f)->nodeid == nodeid &&
+                   (f->subunit == su || (f->subunit == 0 && su == 0x7))) {
+                       fdtv = f;
+                       break;
+               }
+       spin_unlock_irqrestore(&node_list_lock, flags);
+
+       if (fdtv)
+               avc_recv(fdtv, data, length);
+}
+
+static int node_probe(struct device *dev)
+{
+       struct unit_directory *ud =
+                       container_of(dev, struct unit_directory, device);
+       struct firedtv *fdtv;
+       int kv_len, err;
+       void *kv_str;
+
+       kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t);
+       kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv);
+
+       fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len);
+       if (!fdtv)
+               return -ENOMEM;
+
+       /*
+        * Work around a bug in udev's path_id script:  Use the fw-host's dev
+        * instead of the unit directory's dev as parent of the input device.
+        */
+       err = fdtv_register_rc(fdtv, dev->parent->parent);
+       if (err)
+               goto fail_free;
+
+       spin_lock_irq(&node_list_lock);
+       list_add_tail(&fdtv->list, &node_list);
+       spin_unlock_irq(&node_list_lock);
+
+       err = avc_identify_subunit(fdtv);
+       if (err)
+               goto fail;
+
+       err = fdtv_dvb_register(fdtv);
+       if (err)
+               goto fail;
+
+       avc_register_remote_control(fdtv);
+       return 0;
+fail:
+       spin_lock_irq(&node_list_lock);
+       list_del(&fdtv->list);
+       spin_unlock_irq(&node_list_lock);
+       fdtv_unregister_rc(fdtv);
+fail_free:
+       kfree(fdtv);
+       return err;
+}
+
+static int node_remove(struct device *dev)
+{
+       struct firedtv *fdtv = dev->driver_data;
+
+       fdtv_dvb_unregister(fdtv);
+
+       spin_lock_irq(&node_list_lock);
+       list_del(&fdtv->list);
+       spin_unlock_irq(&node_list_lock);
+
+       cancel_work_sync(&fdtv->remote_ctrl_work);
+       fdtv_unregister_rc(fdtv);
+
+       kfree(fdtv);
+       return 0;
+}
+
+static int node_update(struct unit_directory *ud)
+{
+       struct firedtv *fdtv = ud->device.driver_data;
+
+       if (fdtv->isochannel >= 0)
+               cmp_establish_pp_connection(fdtv, fdtv->subunit,
+                                           fdtv->isochannel);
+       return 0;
+}
+
+static struct hpsb_protocol_driver fdtv_driver = {
+       .name           = "firedtv",
+       .update         = node_update,
+       .driver         = {
+               .probe  = node_probe,
+               .remove = node_remove,
+       },
+};
+
+static struct hpsb_highlevel fdtv_highlevel = {
+       .name           = "firedtv",
+       .fcp_request    = fcp_request,
+};
+
+int __init fdtv_1394_init(struct ieee1394_device_id id_table[])
+{
+       int ret;
+
+       hpsb_register_highlevel(&fdtv_highlevel);
+       fdtv_driver.id_table = id_table;
+       ret = hpsb_register_protocol(&fdtv_driver);
+       if (ret) {
+               printk(KERN_ERR "firedtv: failed to register protocol\n");
+               hpsb_unregister_highlevel(&fdtv_highlevel);
+       }
+       return ret;
+}
+
+void __exit fdtv_1394_exit(void)
+{
+       hpsb_unregister_protocol(&fdtv_driver);
+       hpsb_unregister_highlevel(&fdtv_highlevel);
+}
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c
new file mode 100644 (file)
index 0000000..b55d9cc
--- /dev/null
@@ -0,0 +1,1315 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Ben Backx <ben@bbackx.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ */
+
+#include <linux/bug.h>
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+#include <linux/stringify.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include "firedtv.h"
+
+#define FCP_COMMAND_REGISTER           0xfffff0000b00ULL
+
+#define AVC_CTYPE_CONTROL              0x0
+#define AVC_CTYPE_STATUS               0x1
+#define AVC_CTYPE_NOTIFY               0x3
+
+#define AVC_RESPONSE_ACCEPTED          0x9
+#define AVC_RESPONSE_STABLE            0xc
+#define AVC_RESPONSE_CHANGED           0xd
+#define AVC_RESPONSE_INTERIM           0xf
+
+#define AVC_SUBUNIT_TYPE_TUNER         (0x05 << 3)
+#define AVC_SUBUNIT_TYPE_UNIT          (0x1f << 3)
+
+#define AVC_OPCODE_VENDOR              0x00
+#define AVC_OPCODE_READ_DESCRIPTOR     0x09
+#define AVC_OPCODE_DSIT                        0xc8
+#define AVC_OPCODE_DSD                 0xcb
+
+#define DESCRIPTOR_TUNER_STATUS        0x80
+#define DESCRIPTOR_SUBUNIT_IDENTIFIER  0x00
+
+#define SFE_VENDOR_DE_COMPANYID_0      0x00 /* OUI of Digital Everywhere */
+#define SFE_VENDOR_DE_COMPANYID_1      0x12
+#define SFE_VENDOR_DE_COMPANYID_2      0x87
+
+#define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL 0x0a
+#define SFE_VENDOR_OPCODE_LNB_CONTROL          0x52
+#define SFE_VENDOR_OPCODE_TUNE_QPSK            0x58 /* for DVB-S */
+
+#define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION 0x00
+#define SFE_VENDOR_OPCODE_HOST2CA              0x56
+#define SFE_VENDOR_OPCODE_CA2HOST              0x57
+#define SFE_VENDOR_OPCODE_CISTATUS             0x59
+#define SFE_VENDOR_OPCODE_TUNE_QPSK2           0x60 /* for DVB-S2 */
+
+#define SFE_VENDOR_TAG_CA_RESET                        0x00
+#define SFE_VENDOR_TAG_CA_APPLICATION_INFO     0x01
+#define SFE_VENDOR_TAG_CA_PMT                  0x02
+#define SFE_VENDOR_TAG_CA_DATE_TIME            0x04
+#define SFE_VENDOR_TAG_CA_MMI                  0x05
+#define SFE_VENDOR_TAG_CA_ENTER_MENU           0x07
+
+#define EN50221_LIST_MANAGEMENT_ONLY   0x03
+#define EN50221_TAG_APP_INFO           0x9f8021
+#define EN50221_TAG_CA_INFO            0x9f8031
+
+struct avc_command_frame {
+       int length;
+       u8 ctype;
+       u8 subunit;
+       u8 opcode;
+       u8 operand[509];
+};
+
+struct avc_response_frame {
+       int length;
+       u8 response;
+       u8 subunit;
+       u8 opcode;
+       u8 operand[509];
+};
+
+#define AVC_DEBUG_FCP_SUBACTIONS       1
+#define AVC_DEBUG_FCP_PAYLOADS         2
+
+static int avc_debug;
+module_param_named(debug, avc_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
+       ", FCP subactions = "   __stringify(AVC_DEBUG_FCP_SUBACTIONS)
+       ", FCP payloads = "     __stringify(AVC_DEBUG_FCP_PAYLOADS)
+       ", or all = -1)");
+
+static const char *debug_fcp_ctype(unsigned int ctype)
+{
+       static const char *ctypes[] = {
+               [0x0] = "CONTROL",              [0x1] = "STATUS",
+               [0x2] = "SPECIFIC INQUIRY",     [0x3] = "NOTIFY",
+               [0x4] = "GENERAL INQUIRY",      [0x8] = "NOT IMPLEMENTED",
+               [0x9] = "ACCEPTED",             [0xa] = "REJECTED",
+               [0xb] = "IN TRANSITION",        [0xc] = "IMPLEMENTED/STABLE",
+               [0xd] = "CHANGED",              [0xf] = "INTERIM",
+       };
+       const char *ret = ctype < ARRAY_SIZE(ctypes) ? ctypes[ctype] : NULL;
+
+       return ret ? ret : "?";
+}
+
+static const char *debug_fcp_opcode(unsigned int opcode,
+                                   const u8 *data, size_t length)
+{
+       switch (opcode) {
+       case AVC_OPCODE_VENDOR:                 break;
+       case AVC_OPCODE_READ_DESCRIPTOR:        return "ReadDescriptor";
+       case AVC_OPCODE_DSIT:                   return "DirectSelectInfo.Type";
+       case AVC_OPCODE_DSD:                    return "DirectSelectData";
+       default:                                return "?";
+       }
+
+       if (length < 7 ||
+           data[3] != SFE_VENDOR_DE_COMPANYID_0 ||
+           data[4] != SFE_VENDOR_DE_COMPANYID_1 ||
+           data[5] != SFE_VENDOR_DE_COMPANYID_2)
+               return "Vendor";
+
+       switch (data[6]) {
+       case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: return "RegisterRC";
+       case SFE_VENDOR_OPCODE_LNB_CONTROL:             return "LNBControl";
+       case SFE_VENDOR_OPCODE_TUNE_QPSK:               return "TuneQPSK";
+       case SFE_VENDOR_OPCODE_HOST2CA:                 return "Host2CA";
+       case SFE_VENDOR_OPCODE_CA2HOST:                 return "CA2Host";
+       }
+       return "Vendor";
+}
+
+static void debug_fcp(const u8 *data, size_t length)
+{
+       unsigned int subunit_type, subunit_id, op;
+       const char *prefix = data[0] > 7 ? "FCP <- " : "FCP -> ";
+
+       if (avc_debug & AVC_DEBUG_FCP_SUBACTIONS) {
+               subunit_type = data[1] >> 3;
+               subunit_id = data[1] & 7;
+               op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2];
+               printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n",
+                      prefix, subunit_type, subunit_id, length,
+                      debug_fcp_ctype(data[0]),
+                      debug_fcp_opcode(op, data, length));
+       }
+
+       if (avc_debug & AVC_DEBUG_FCP_PAYLOADS)
+               print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, 16, 1,
+                              data, length, false);
+}
+
+static int __avc_write(struct firedtv *fdtv,
+               const struct avc_command_frame *c, struct avc_response_frame *r)
+{
+       int err, retry;
+
+       if (r)
+               fdtv->avc_reply_received = false;
+
+       for (retry = 0; retry < 6; retry++) {
+               if (unlikely(avc_debug))
+                       debug_fcp(&c->ctype, c->length);
+
+               err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER,
+                                          (void *)&c->ctype, c->length);
+               if (err) {
+                       fdtv->avc_reply_received = true;
+                       dev_err(fdtv->device, "FCP command write failed\n");
+                       return err;
+               }
+
+               if (!r)
+                       return 0;
+
+               /*
+                * AV/C specs say that answers should be sent within 150 ms.
+                * Time out after 200 ms.
+                */
+               if (wait_event_timeout(fdtv->avc_wait,
+                                      fdtv->avc_reply_received,
+                                      msecs_to_jiffies(200)) != 0) {
+                       r->length = fdtv->response_length;
+                       memcpy(&r->response, fdtv->response, r->length);
+
+                       return 0;
+               }
+       }
+       dev_err(fdtv->device, "FCP response timed out\n");
+       return -ETIMEDOUT;
+}
+
+static int avc_write(struct firedtv *fdtv,
+               const struct avc_command_frame *c, struct avc_response_frame *r)
+{
+       int ret;
+
+       if (mutex_lock_interruptible(&fdtv->avc_mutex))
+               return -EINTR;
+
+       ret = __avc_write(fdtv, c, r);
+
+       mutex_unlock(&fdtv->avc_mutex);
+       return ret;
+}
+
+int avc_recv(struct firedtv *fdtv, void *data, size_t length)
+{
+       struct avc_response_frame *r =
+                       data - offsetof(struct avc_response_frame, response);
+
+       if (unlikely(avc_debug))
+               debug_fcp(data, length);
+
+       if (length >= 8 &&
+           r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
+           r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
+           r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
+           r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) {
+               if (r->response == AVC_RESPONSE_CHANGED) {
+                       fdtv_handle_rc(fdtv,
+                           r->operand[4] << 8 | r->operand[5]);
+                       schedule_work(&fdtv->remote_ctrl_work);
+               } else if (r->response != AVC_RESPONSE_INTERIM) {
+                       dev_info(fdtv->device,
+                                "remote control result = %d\n", r->response);
+               }
+               return 0;
+       }
+
+       if (fdtv->avc_reply_received) {
+               dev_err(fdtv->device, "out-of-order AVC response, ignored\n");
+               return -EIO;
+       }
+
+       memcpy(fdtv->response, data, length);
+       fdtv->response_length = length;
+
+       fdtv->avc_reply_received = true;
+       wake_up(&fdtv->avc_wait);
+
+       return 0;
+}
+
+/*
+ * tuning command for setting the relative LNB frequency
+ * (not supported by the AVC standard)
+ */
+static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
+                              struct dvb_frontend_parameters *params,
+                              struct avc_command_frame *c)
+{
+       c->opcode = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
+
+       c->operand[4] = (params->frequency >> 24) & 0xff;
+       c->operand[5] = (params->frequency >> 16) & 0xff;
+       c->operand[6] = (params->frequency >> 8) & 0xff;
+       c->operand[7] = params->frequency & 0xff;
+
+       c->operand[8] = ((params->u.qpsk.symbol_rate / 1000) >> 8) & 0xff;
+       c->operand[9] = (params->u.qpsk.symbol_rate / 1000) & 0xff;
+
+       switch (params->u.qpsk.fec_inner) {
+       case FEC_1_2:   c->operand[10] = 0x1; break;
+       case FEC_2_3:   c->operand[10] = 0x2; break;
+       case FEC_3_4:   c->operand[10] = 0x3; break;
+       case FEC_5_6:   c->operand[10] = 0x4; break;
+       case FEC_7_8:   c->operand[10] = 0x5; break;
+       case FEC_4_5:
+       case FEC_8_9:
+       case FEC_AUTO:
+       default:        c->operand[10] = 0x0;
+       }
+
+       if (fdtv->voltage == 0xff)
+               c->operand[11] = 0xff;
+       else if (fdtv->voltage == SEC_VOLTAGE_18) /* polarisation */
+               c->operand[11] = 0;
+       else
+               c->operand[11] = 1;
+
+       if (fdtv->tone == 0xff)
+               c->operand[12] = 0xff;
+       else if (fdtv->tone == SEC_TONE_ON) /* band */
+               c->operand[12] = 1;
+       else
+               c->operand[12] = 0;
+
+       if (fdtv->type == FIREDTV_DVB_S2) {
+               c->operand[13] = 0x1;
+               c->operand[14] = 0xff;
+               c->operand[15] = 0xff;
+               c->length = 20;
+       } else {
+               c->length = 16;
+       }
+}
+
+static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params,
+                               struct avc_command_frame *c)
+{
+       c->opcode = AVC_OPCODE_DSD;
+
+       c->operand[0] = 0;    /* source plug */
+       c->operand[1] = 0xd2; /* subfunction replace */
+       c->operand[2] = 0x20; /* system id = DVB */
+       c->operand[3] = 0x00; /* antenna number */
+       c->operand[4] = 0x11; /* system_specific_multiplex selection_length */
+
+       /* multiplex_valid_flags, high byte */
+       c->operand[5] =   0 << 7 /* reserved */
+                       | 0 << 6 /* Polarisation */
+                       | 0 << 5 /* Orbital_Pos */
+                       | 1 << 4 /* Frequency */
+                       | 1 << 3 /* Symbol_Rate */
+                       | 0 << 2 /* FEC_outer */
+                       | (params->u.qam.fec_inner  != FEC_AUTO ? 1 << 1 : 0)
+                       | (params->u.qam.modulation != QAM_AUTO ? 1 << 0 : 0);
+
+       /* multiplex_valid_flags, low byte */
+       c->operand[6] =   0 << 7 /* NetworkID */
+                       | 0 << 0 /* reserved */ ;
+
+       c->operand[7]  = 0x00;
+       c->operand[8]  = 0x00;
+       c->operand[9]  = 0x00;
+       c->operand[10] = 0x00;
+
+       c->operand[11] = (((params->frequency / 4000) >> 16) & 0xff) | (2 << 6);
+       c->operand[12] = ((params->frequency / 4000) >> 8) & 0xff;
+       c->operand[13] = (params->frequency / 4000) & 0xff;
+       c->operand[14] = ((params->u.qpsk.symbol_rate / 1000) >> 12) & 0xff;
+       c->operand[15] = ((params->u.qpsk.symbol_rate / 1000) >> 4) & 0xff;
+       c->operand[16] = ((params->u.qpsk.symbol_rate / 1000) << 4) & 0xf0;
+       c->operand[17] = 0x00;
+
+       switch (params->u.qpsk.fec_inner) {
+       case FEC_1_2:   c->operand[18] = 0x1; break;
+       case FEC_2_3:   c->operand[18] = 0x2; break;
+       case FEC_3_4:   c->operand[18] = 0x3; break;
+       case FEC_5_6:   c->operand[18] = 0x4; break;
+       case FEC_7_8:   c->operand[18] = 0x5; break;
+       case FEC_8_9:   c->operand[18] = 0x6; break;
+       case FEC_4_5:   c->operand[18] = 0x8; break;
+       case FEC_AUTO:
+       default:        c->operand[18] = 0x0;
+       }
+
+       switch (params->u.qam.modulation) {
+       case QAM_16:    c->operand[19] = 0x08; break;
+       case QAM_32:    c->operand[19] = 0x10; break;
+       case QAM_64:    c->operand[19] = 0x18; break;
+       case QAM_128:   c->operand[19] = 0x20; break;
+       case QAM_256:   c->operand[19] = 0x28; break;
+       case QAM_AUTO:
+       default:        c->operand[19] = 0x00;
+       }
+
+       c->operand[20] = 0x00;
+       c->operand[21] = 0x00;
+       /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
+       c->operand[22] = 0x00;
+
+       c->length = 28;
+}
+
+static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params,
+                               struct avc_command_frame *c)
+{
+       struct dvb_ofdm_parameters *ofdm = &params->u.ofdm;
+
+       c->opcode = AVC_OPCODE_DSD;
+
+       c->operand[0] = 0;    /* source plug */
+       c->operand[1] = 0xd2; /* subfunction replace */
+       c->operand[2] = 0x20; /* system id = DVB */
+       c->operand[3] = 0x00; /* antenna number */
+       c->operand[4] = 0x0c; /* system_specific_multiplex selection_length */
+
+       /* multiplex_valid_flags, high byte */
+       c->operand[5] =
+             0 << 7 /* reserved */
+           | 1 << 6 /* CenterFrequency */
+           | (ofdm->bandwidth      != BANDWIDTH_AUTO        ? 1 << 5 : 0)
+           | (ofdm->constellation  != QAM_AUTO              ? 1 << 4 : 0)
+           | (ofdm->hierarchy_information != HIERARCHY_AUTO ? 1 << 3 : 0)
+           | (ofdm->code_rate_HP   != FEC_AUTO              ? 1 << 2 : 0)
+           | (ofdm->code_rate_LP   != FEC_AUTO              ? 1 << 1 : 0)
+           | (ofdm->guard_interval != GUARD_INTERVAL_AUTO   ? 1 << 0 : 0);
+
+       /* multiplex_valid_flags, low byte */
+       c->operand[6] =
+             0 << 7 /* NetworkID */
+           | (ofdm->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0)
+           | 0 << 5 /* OtherFrequencyFlag */
+           | 0 << 0 /* reserved */ ;
+
+       c->operand[7]  = 0x0;
+       c->operand[8]  = (params->frequency / 10) >> 24;
+       c->operand[9]  = ((params->frequency / 10) >> 16) & 0xff;
+       c->operand[10] = ((params->frequency / 10) >>  8) & 0xff;
+       c->operand[11] = (params->frequency / 10) & 0xff;
+
+       switch (ofdm->bandwidth) {
+       case BANDWIDTH_7_MHZ:   c->operand[12] = 0x20; break;
+       case BANDWIDTH_8_MHZ:
+       case BANDWIDTH_6_MHZ:   /* not defined by AVC spec */
+       case BANDWIDTH_AUTO:
+       default:                c->operand[12] = 0x00;
+       }
+
+       switch (ofdm->constellation) {
+       case QAM_16:    c->operand[13] = 1 << 6; break;
+       case QAM_64:    c->operand[13] = 2 << 6; break;
+       case QPSK:
+       default:        c->operand[13] = 0x00;
+       }
+
+       switch (ofdm->hierarchy_information) {
+       case HIERARCHY_1:       c->operand[13] |= 1 << 3; break;
+       case HIERARCHY_2:       c->operand[13] |= 2 << 3; break;
+       case HIERARCHY_4:       c->operand[13] |= 3 << 3; break;
+       case HIERARCHY_AUTO:
+       case HIERARCHY_NONE:
+       default:                break;
+       }
+
+       switch (ofdm->code_rate_HP) {
+       case FEC_2_3:   c->operand[13] |= 1; break;
+       case FEC_3_4:   c->operand[13] |= 2; break;
+       case FEC_5_6:   c->operand[13] |= 3; break;
+       case FEC_7_8:   c->operand[13] |= 4; break;
+       case FEC_1_2:
+       default:        break;
+       }
+
+       switch (ofdm->code_rate_LP) {
+       case FEC_2_3:   c->operand[14] = 1 << 5; break;
+       case FEC_3_4:   c->operand[14] = 2 << 5; break;
+       case FEC_5_6:   c->operand[14] = 3 << 5; break;
+       case FEC_7_8:   c->operand[14] = 4 << 5; break;
+       case FEC_1_2:
+       default:        c->operand[14] = 0x00; break;
+       }
+
+       switch (ofdm->guard_interval) {
+       case GUARD_INTERVAL_1_16:       c->operand[14] |= 1 << 3; break;
+       case GUARD_INTERVAL_1_8:        c->operand[14] |= 2 << 3; break;
+       case GUARD_INTERVAL_1_4:        c->operand[14] |= 3 << 3; break;
+       case GUARD_INTERVAL_1_32:
+       case GUARD_INTERVAL_AUTO:
+       default:                        break;
+       }
+
+       switch (ofdm->transmission_mode) {
+       case TRANSMISSION_MODE_8K:      c->operand[14] |= 1 << 1; break;
+       case TRANSMISSION_MODE_2K:
+       case TRANSMISSION_MODE_AUTO:
+       default:                        break;
+       }
+
+       c->operand[15] = 0x00; /* network_ID[0] */
+       c->operand[16] = 0x00; /* network_ID[1] */
+       /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
+       c->operand[17] = 0x00;
+
+       c->length = 24;
+}
+
+int avc_tuner_dsd(struct firedtv *fdtv,
+                 struct dvb_frontend_parameters *params)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+
+       switch (fdtv->type) {
+       case FIREDTV_DVB_S:
+       case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break;
+       case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(params, c); break;
+       case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(params, c); break;
+       default:
+               BUG();
+       }
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       msleep(500);
+#if 0
+       /* FIXME: */
+       /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */
+       if (status)
+               *status = r->operand[2];
+#endif
+       return 0;
+}
+
+int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+       int pos, k;
+
+       if (pidc > 16 && pidc != 0xff)
+               return -EINVAL;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_DSD;
+
+       c->operand[0] = 0;      /* source plug */
+       c->operand[1] = 0xd2;   /* subfunction replace */
+       c->operand[2] = 0x20;   /* system id = DVB */
+       c->operand[3] = 0x00;   /* antenna number */
+       c->operand[4] = 0x00;   /* system_specific_multiplex selection_length */
+       c->operand[5] = pidc;   /* Nr_of_dsd_sel_specs */
+
+       pos = 6;
+       if (pidc != 0xff)
+               for (k = 0; k < pidc; k++) {
+                       c->operand[pos++] = 0x13; /* flowfunction relay */
+                       c->operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
+                       c->operand[pos++] = (pid[k] >> 8) & 0x1f;
+                       c->operand[pos++] = pid[k] & 0xff;
+                       c->operand[pos++] = 0x00; /* tableID */
+                       c->operand[pos++] = 0x00; /* filter_length */
+               }
+
+       c->length = ALIGN(3 + pos, 4);
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       msleep(50);
+       return 0;
+}
+
+int avc_tuner_get_ts(struct firedtv *fdtv)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+       int sl;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_DSIT;
+
+       sl = fdtv->type == FIREDTV_DVB_T ? 0x0c : 0x11;
+
+       c->operand[0] = 0;      /* source plug */
+       c->operand[1] = 0xd2;   /* subfunction replace */
+       c->operand[2] = 0xff;   /* status */
+       c->operand[3] = 0x20;   /* system id = DVB */
+       c->operand[4] = 0x00;   /* antenna number */
+       c->operand[5] = 0x0;    /* system_specific_search_flags */
+       c->operand[6] = sl;     /* system_specific_multiplex selection_length */
+       c->operand[7] = 0x00;   /* valid_flags [0] */
+       c->operand[8] = 0x00;   /* valid_flags [1] */
+       c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */
+
+       c->length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       msleep(250);
+       return 0;
+}
+
+int avc_identify_subunit(struct firedtv *fdtv)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_READ_DESCRIPTOR;
+
+       c->operand[0] = DESCRIPTOR_SUBUNIT_IDENTIFIER;
+       c->operand[1] = 0xff;
+       c->operand[2] = 0x00;
+       c->operand[3] = 0x00; /* length highbyte */
+       c->operand[4] = 0x08; /* length lowbyte  */
+       c->operand[5] = 0x00; /* offset highbyte */
+       c->operand[6] = 0x0d; /* offset lowbyte  */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       if ((r->response != AVC_RESPONSE_STABLE &&
+            r->response != AVC_RESPONSE_ACCEPTED) ||
+           (r->operand[3] << 8) + r->operand[4] != 8) {
+               dev_err(fdtv->device, "cannot read subunit identifier\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+#define SIZEOF_ANTENNA_INPUT_INFO 22
+
+int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+       int length;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_READ_DESCRIPTOR;
+
+       c->operand[0] = DESCRIPTOR_TUNER_STATUS;
+       c->operand[1] = 0xff;   /* read_result_status */
+       c->operand[2] = 0x00;   /* reserved */
+       c->operand[3] = 0;      /* SIZEOF_ANTENNA_INPUT_INFO >> 8; */
+       c->operand[4] = 0;      /* SIZEOF_ANTENNA_INPUT_INFO & 0xff; */
+       c->operand[5] = 0x00;
+       c->operand[6] = 0x00;
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       if (r->response != AVC_RESPONSE_STABLE &&
+           r->response != AVC_RESPONSE_ACCEPTED) {
+               dev_err(fdtv->device, "cannot read tuner status\n");
+               return -EINVAL;
+       }
+
+       length = r->operand[9];
+       if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) {
+               dev_err(fdtv->device, "got invalid tuner status\n");
+               return -EINVAL;
+       }
+
+       stat->active_system             = r->operand[10];
+       stat->searching                 = r->operand[11] >> 7 & 1;
+       stat->moving                    = r->operand[11] >> 6 & 1;
+       stat->no_rf                     = r->operand[11] >> 5 & 1;
+       stat->input                     = r->operand[12] >> 7 & 1;
+       stat->selected_antenna          = r->operand[12] & 0x7f;
+       stat->ber                       = r->operand[13] << 24 |
+                                         r->operand[14] << 16 |
+                                         r->operand[15] << 8 |
+                                         r->operand[16];
+       stat->signal_strength           = r->operand[17];
+       stat->raster_frequency          = r->operand[18] >> 6 & 2;
+       stat->rf_frequency              = (r->operand[18] & 0x3f) << 16 |
+                                         r->operand[19] << 8 |
+                                         r->operand[20];
+       stat->man_dep_info_length       = r->operand[21];
+       stat->front_end_error           = r->operand[22] >> 4 & 1;
+       stat->antenna_error             = r->operand[22] >> 3 & 1;
+       stat->front_end_power_status    = r->operand[22] >> 1 & 1;
+       stat->power_supply              = r->operand[22] & 1;
+       stat->carrier_noise_ratio       = r->operand[23] << 8 |
+                                         r->operand[24];
+       stat->power_supply_voltage      = r->operand[27];
+       stat->antenna_voltage           = r->operand[28];
+       stat->firewire_bus_voltage      = r->operand[29];
+       stat->ca_mmi                    = r->operand[30] & 1;
+       stat->ca_pmt_reply              = r->operand[31] >> 7 & 1;
+       stat->ca_date_time_request      = r->operand[31] >> 6 & 1;
+       stat->ca_application_info       = r->operand[31] >> 5 & 1;
+       stat->ca_module_present_status  = r->operand[31] >> 4 & 1;
+       stat->ca_dvb_flag               = r->operand[31] >> 3 & 1;
+       stat->ca_error_flag             = r->operand[31] >> 2 & 1;
+       stat->ca_initialization_status  = r->operand[31] >> 1 & 1;
+
+       return 0;
+}
+
+int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
+                   char conttone, char nrdiseq,
+                   struct dvb_diseqc_master_cmd *diseqcmd)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+       int i, j, k;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL;
+
+       c->operand[4] = voltage;
+       c->operand[5] = nrdiseq;
+
+       i = 6;
+
+       for (j = 0; j < nrdiseq; j++) {
+               c->operand[i++] = diseqcmd[j].msg_len;
+
+               for (k = 0; k < diseqcmd[j].msg_len; k++)
+                       c->operand[i++] = diseqcmd[j].msg[k];
+       }
+
+       c->operand[i++] = burst;
+       c->operand[i++] = conttone;
+
+       c->length = ALIGN(3 + i, 4);
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       if (r->response != AVC_RESPONSE_ACCEPTED) {
+               dev_err(fdtv->device, "LNB control failed\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int avc_register_remote_control(struct firedtv *fdtv)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_NOTIFY;
+       c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
+
+       c->length = 8;
+
+       return avc_write(fdtv, c, NULL);
+}
+
+void avc_remote_ctrl_work(struct work_struct *work)
+{
+       struct firedtv *fdtv =
+                       container_of(work, struct firedtv, remote_ctrl_work);
+
+       /* Should it be rescheduled in failure cases? */
+       avc_register_remote_control(fdtv);
+}
+
+#if 0 /* FIXME: unused */
+int avc_tuner_host2ca(struct firedtv *fdtv)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+       c->operand[6] = 0; /* more/last */
+       c->operand[7] = 0; /* length */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       return 0;
+}
+#endif
+
+static int get_ca_object_pos(struct avc_response_frame *r)
+{
+       int length = 1;
+
+       /* Check length of length field */
+       if (r->operand[7] & 0x80)
+               length = (r->operand[7] & 0x7f) + 1;
+       return length + 7;
+}
+
+static int get_ca_object_length(struct avc_response_frame *r)
+{
+#if 0 /* FIXME: unused */
+       int size = 0;
+       int i;
+
+       if (r->operand[7] & 0x80)
+               for (i = 0; i < (r->operand[7] & 0x7f); i++) {
+                       size <<= 8;
+                       size += r->operand[8 + i];
+               }
+#endif
+       return r->operand[7];
+}
+
+int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+       int pos;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_STATUS;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       /* FIXME: check response code and validate response data */
+
+       pos = get_ca_object_pos(r);
+       app_info[0] = (EN50221_TAG_APP_INFO >> 16) & 0xff;
+       app_info[1] = (EN50221_TAG_APP_INFO >>  8) & 0xff;
+       app_info[2] = (EN50221_TAG_APP_INFO >>  0) & 0xff;
+       app_info[3] = 6 + r->operand[pos + 4];
+       app_info[4] = 0x01;
+       memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]);
+       *len = app_info[3] + 4;
+
+       return 0;
+}
+
+int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+       int pos;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_STATUS;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       pos = get_ca_object_pos(r);
+       app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff;
+       app_info[1] = (EN50221_TAG_CA_INFO >>  8) & 0xff;
+       app_info[2] = (EN50221_TAG_CA_INFO >>  0) & 0xff;
+       app_info[3] = 2;
+       app_info[4] = r->operand[pos + 0];
+       app_info[5] = r->operand[pos + 1];
+       *len = app_info[3] + 4;
+
+       return 0;
+}
+
+int avc_ca_reset(struct firedtv *fdtv)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_RESET; /* ca tag */
+       c->operand[6] = 0; /* more/last */
+       c->operand[7] = 1; /* length */
+       c->operand[8] = 0; /* force hardware reset */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       return 0;
+}
+
+int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+       int list_management;
+       int program_info_length;
+       int pmt_cmd_id;
+       int read_pos;
+       int write_pos;
+       int es_info_length;
+       int crc32_csum;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       if (msg[0] != EN50221_LIST_MANAGEMENT_ONLY) {
+               dev_info(fdtv->device, "forcing list_management to ONLY\n");
+               msg[0] = EN50221_LIST_MANAGEMENT_ONLY;
+       }
+       /* We take the cmd_id from the programme level only! */
+       list_management = msg[0];
+       program_info_length = ((msg[4] & 0x0f) << 8) + msg[5];
+       if (program_info_length > 0)
+               program_info_length--; /* Remove pmt_cmd_id */
+       pmt_cmd_id = msg[6];
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_PMT; /* ca tag */
+       c->operand[6] = 0; /* more/last */
+       /* c->operand[7] = XXXprogram_info_length + 17; */ /* length */
+       c->operand[8] = list_management;
+       c->operand[9] = 0x01; /* pmt_cmd=OK_descramble */
+
+       /* TS program map table */
+
+       c->operand[10] = 0x02; /* Table id=2 */
+       c->operand[11] = 0x80; /* Section syntax + length */
+       /* c->operand[12] = XXXprogram_info_length + 12; */
+       c->operand[13] = msg[1]; /* Program number */
+       c->operand[14] = msg[2];
+       c->operand[15] = 0x01; /* Version number=0 + current/next=1 */
+       c->operand[16] = 0x00; /* Section number=0 */
+       c->operand[17] = 0x00; /* Last section number=0 */
+       c->operand[18] = 0x1f; /* PCR_PID=1FFF */
+       c->operand[19] = 0xff;
+       c->operand[20] = (program_info_length >> 8); /* Program info length */
+       c->operand[21] = (program_info_length & 0xff);
+
+       /* CA descriptors at programme level */
+       read_pos = 6;
+       write_pos = 22;
+       if (program_info_length > 0) {
+               pmt_cmd_id = msg[read_pos++];
+               if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
+                       dev_err(fdtv->device,
+                               "invalid pmt_cmd_id %d\n", pmt_cmd_id);
+
+               memcpy(&c->operand[write_pos], &msg[read_pos],
+                      program_info_length);
+               read_pos += program_info_length;
+               write_pos += program_info_length;
+       }
+       while (read_pos < length) {
+               c->operand[write_pos++] = msg[read_pos++];
+               c->operand[write_pos++] = msg[read_pos++];
+               c->operand[write_pos++] = msg[read_pos++];
+               es_info_length =
+                       ((msg[read_pos] & 0x0f) << 8) + msg[read_pos + 1];
+               read_pos += 2;
+               if (es_info_length > 0)
+                       es_info_length--; /* Remove pmt_cmd_id */
+               c->operand[write_pos++] = es_info_length >> 8;
+               c->operand[write_pos++] = es_info_length & 0xff;
+               if (es_info_length > 0) {
+                       pmt_cmd_id = msg[read_pos++];
+                       if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
+                               dev_err(fdtv->device, "invalid pmt_cmd_id %d "
+                                       "at stream level\n", pmt_cmd_id);
+
+                       memcpy(&c->operand[write_pos], &msg[read_pos],
+                              es_info_length);
+                       read_pos += es_info_length;
+                       write_pos += es_info_length;
+               }
+       }
+
+       /* CRC */
+       c->operand[write_pos++] = 0x00;
+       c->operand[write_pos++] = 0x00;
+       c->operand[write_pos++] = 0x00;
+       c->operand[write_pos++] = 0x00;
+
+       c->operand[7] = write_pos - 8;
+       c->operand[12] = write_pos - 13;
+
+       crc32_csum = crc32_be(0, &c->operand[10], c->operand[12] - 1);
+       c->operand[write_pos - 4] = (crc32_csum >> 24) & 0xff;
+       c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff;
+       c->operand[write_pos - 2] = (crc32_csum >>  8) & 0xff;
+       c->operand[write_pos - 1] = (crc32_csum >>  0) & 0xff;
+
+       c->length = ALIGN(3 + write_pos, 4);
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       if (r->response != AVC_RESPONSE_ACCEPTED) {
+               dev_err(fdtv->device,
+                       "CA PMT failed with response 0x%x\n", r->response);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_STATUS;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */
+       c->operand[6] = 0; /* more/last */
+       c->operand[7] = 0; /* length */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       /* FIXME: check response code and validate response data */
+
+       *interval = r->operand[get_ca_object_pos(r)];
+
+       return 0;
+}
+
+int avc_ca_enter_menu(struct firedtv *fdtv)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_STATUS;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
+       c->operand[6] = 0; /* more/last */
+       c->operand[7] = 0; /* length */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       return 0;
+}
+
+int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_STATUS;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_MMI;
+       c->operand[6] = 0; /* more/last */
+       c->operand[7] = 0; /* length */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       /* FIXME: check response code and validate response data */
+
+       *len = get_ca_object_length(r);
+       memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len);
+
+       return 0;
+}
+
+#define CMP_OUTPUT_PLUG_CONTROL_REG_0  0xfffff0000904ULL
+
+static int cmp_read(struct firedtv *fdtv, void *buf, u64 addr, size_t len)
+{
+       int ret;
+
+       if (mutex_lock_interruptible(&fdtv->avc_mutex))
+               return -EINTR;
+
+       ret = fdtv->backend->read(fdtv, addr, buf, len);
+       if (ret < 0)
+               dev_err(fdtv->device, "CMP: read I/O error\n");
+
+       mutex_unlock(&fdtv->avc_mutex);
+       return ret;
+}
+
+static int cmp_lock(struct firedtv *fdtv, void *data, u64 addr, __be32 arg)
+{
+       int ret;
+
+       if (mutex_lock_interruptible(&fdtv->avc_mutex))
+               return -EINTR;
+
+       ret = fdtv->backend->lock(fdtv, addr, data, arg);
+       if (ret < 0)
+               dev_err(fdtv->device, "CMP: lock I/O error\n");
+
+       mutex_unlock(&fdtv->avc_mutex);
+       return ret;
+}
+
+static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift)
+{
+       return (be32_to_cpu(opcr) >> shift) & mask;
+}
+
+static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift)
+{
+       *opcr &= ~cpu_to_be32(mask << shift);
+       *opcr |= cpu_to_be32((value & mask) << shift);
+}
+
+#define get_opcr_online(v)             get_opcr((v), 0x1, 31)
+#define get_opcr_p2p_connections(v)    get_opcr((v), 0x3f, 24)
+#define get_opcr_channel(v)            get_opcr((v), 0x3f, 16)
+
+#define set_opcr_p2p_connections(p, v) set_opcr((p), (v), 0x3f, 24)
+#define set_opcr_channel(p, v)         set_opcr((p), (v), 0x3f, 16)
+#define set_opcr_data_rate(p, v)       set_opcr((p), (v), 0x3, 14)
+#define set_opcr_overhead_id(p, v)     set_opcr((p), (v), 0xf, 10)
+
+int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel)
+{
+       __be32 old_opcr, opcr;
+       u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
+       int attempts = 0;
+       int ret;
+
+       ret = cmp_read(fdtv, &opcr, opcr_address, 4);
+       if (ret < 0)
+               return ret;
+
+repeat:
+       if (!get_opcr_online(opcr)) {
+               dev_err(fdtv->device, "CMP: output offline\n");
+               return -EBUSY;
+       }
+
+       old_opcr = opcr;
+
+       if (get_opcr_p2p_connections(opcr)) {
+               if (get_opcr_channel(opcr) != channel) {
+                       dev_err(fdtv->device, "CMP: cannot change channel\n");
+                       return -EBUSY;
+               }
+               dev_info(fdtv->device, "CMP: overlaying connection\n");
+
+               /* We don't allocate isochronous resources. */
+       } else {
+               set_opcr_channel(&opcr, channel);
+               set_opcr_data_rate(&opcr, 2); /* S400 */
+
+               /* FIXME: this is for the worst case - optimize */
+               set_opcr_overhead_id(&opcr, 0);
+
+               /*
+                * FIXME: allocate isochronous channel and bandwidth at IRM
+                * fdtv->backend->alloc_resources(fdtv, channels_mask, bw);
+                */
+       }
+
+       set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) + 1);
+
+       ret = cmp_lock(fdtv, &opcr, opcr_address, old_opcr);
+       if (ret < 0)
+               return ret;
+
+       if (old_opcr != opcr) {
+               /*
+                * FIXME: if old_opcr.P2P_Connections > 0,
+                * deallocate isochronous channel and bandwidth at IRM
+                * if (...)
+                *      fdtv->backend->dealloc_resources(fdtv, channel, bw);
+                */
+
+               if (++attempts < 6) /* arbitrary limit */
+                       goto repeat;
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel)
+{
+       __be32 old_opcr, opcr;
+       u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
+       int attempts = 0;
+
+       if (cmp_read(fdtv, &opcr, opcr_address, 4) < 0)
+               return;
+
+repeat:
+       if (!get_opcr_online(opcr) || !get_opcr_p2p_connections(opcr) ||
+           get_opcr_channel(opcr) != channel) {
+               dev_err(fdtv->device, "CMP: no connection to break\n");
+               return;
+       }
+
+       old_opcr = opcr;
+       set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) - 1);
+
+       if (cmp_lock(fdtv, &opcr, opcr_address, old_opcr) < 0)
+               return;
+
+       if (old_opcr != opcr) {
+               /*
+                * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last
+                * owner, deallocate isochronous channel and bandwidth at IRM
+                * if (...)
+                *      fdtv->backend->dealloc_resources(fdtv, channel, bw);
+                */
+
+               if (++attempts < 6) /* arbitrary limit */
+                       goto repeat;
+       }
+}
diff --git a/drivers/media/dvb/firewire/firedtv-ci.c b/drivers/media/dvb/firewire/firedtv-ci.c
new file mode 100644 (file)
index 0000000..eeb80d0
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/dvb/ca.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+
+#include <dvbdev.h>
+
+#include "firedtv.h"
+
+#define EN50221_TAG_APP_INFO_ENQUIRY   0x9f8020
+#define EN50221_TAG_CA_INFO_ENQUIRY    0x9f8030
+#define EN50221_TAG_CA_PMT             0x9f8032
+#define EN50221_TAG_ENTER_MENU         0x9f8022
+
+static int fdtv_ca_ready(struct firedtv_tuner_status *stat)
+{
+       return stat->ca_initialization_status   == 1 &&
+              stat->ca_error_flag              == 0 &&
+              stat->ca_dvb_flag                == 1 &&
+              stat->ca_module_present_status   == 1;
+}
+
+static int fdtv_get_ca_flags(struct firedtv_tuner_status *stat)
+{
+       int flags = 0;
+
+       if (stat->ca_module_present_status == 1)
+               flags |= CA_CI_MODULE_PRESENT;
+       if (stat->ca_initialization_status == 1 &&
+           stat->ca_error_flag            == 0 &&
+           stat->ca_dvb_flag              == 1)
+               flags |= CA_CI_MODULE_READY;
+       return flags;
+}
+
+static int fdtv_ca_reset(struct firedtv *fdtv)
+{
+       return avc_ca_reset(fdtv) ? -EFAULT : 0;
+}
+
+static int fdtv_ca_get_caps(void *arg)
+{
+       struct ca_caps *cap = arg;
+
+       cap->slot_num = 1;
+       cap->slot_type = CA_CI;
+       cap->descr_num = 1;
+       cap->descr_type = CA_ECD;
+       return 0;
+}
+
+static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
+{
+       struct firedtv_tuner_status stat;
+       struct ca_slot_info *slot = arg;
+
+       if (avc_tuner_status(fdtv, &stat))
+               return -EFAULT;
+
+       if (slot->num != 0)
+               return -EFAULT;
+
+       slot->type = CA_CI;
+       slot->flags = fdtv_get_ca_flags(&stat);
+       return 0;
+}
+
+static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg)
+{
+       struct ca_msg *reply = arg;
+
+       return avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
+}
+
+static int fdtv_ca_info(struct firedtv *fdtv, void *arg)
+{
+       struct ca_msg *reply = arg;
+
+       return avc_ca_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
+}
+
+static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg)
+{
+       struct ca_msg *reply = arg;
+
+       return avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
+}
+
+static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
+{
+       struct firedtv_tuner_status stat;
+       int err;
+
+       switch (fdtv->ca_last_command) {
+       case EN50221_TAG_APP_INFO_ENQUIRY:
+               err = fdtv_ca_app_info(fdtv, arg);
+               break;
+       case EN50221_TAG_CA_INFO_ENQUIRY:
+               err = fdtv_ca_info(fdtv, arg);
+               break;
+       default:
+               if (avc_tuner_status(fdtv, &stat))
+                       err = -EFAULT;
+               else if (stat.ca_mmi == 1)
+                       err = fdtv_ca_get_mmi(fdtv, arg);
+               else {
+                       dev_info(fdtv->device, "unhandled CA message 0x%08x\n",
+                                fdtv->ca_last_command);
+                       err = -EFAULT;
+               }
+       }
+       fdtv->ca_last_command = 0;
+       return err;
+}
+
+static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
+{
+       struct ca_msg *msg = arg;
+       int data_pos;
+       int data_length;
+       int i;
+
+       data_pos = 4;
+       if (msg->msg[3] & 0x80) {
+               data_length = 0;
+               for (i = 0; i < (msg->msg[3] & 0x7f); i++)
+                       data_length = (data_length << 8) + msg->msg[data_pos++];
+       } else {
+               data_length = msg->msg[3];
+       }
+
+       return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ? -EFAULT : 0;
+}
+
+static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
+{
+       struct ca_msg *msg = arg;
+       int err;
+
+       /* Do we need a semaphore for this? */
+       fdtv->ca_last_command =
+               (msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2];
+       switch (fdtv->ca_last_command) {
+       case EN50221_TAG_CA_PMT:
+               err = fdtv_ca_pmt(fdtv, arg);
+               break;
+       case EN50221_TAG_APP_INFO_ENQUIRY:
+               /* handled in ca_get_msg */
+               err = 0;
+               break;
+       case EN50221_TAG_CA_INFO_ENQUIRY:
+               /* handled in ca_get_msg */
+               err = 0;
+               break;
+       case EN50221_TAG_ENTER_MENU:
+               err = avc_ca_enter_menu(fdtv);
+               break;
+       default:
+               dev_err(fdtv->device, "unhandled CA message 0x%08x\n",
+                       fdtv->ca_last_command);
+               err = -EFAULT;
+       }
+       return err;
+}
+
+static int fdtv_ca_ioctl(struct inode *inode, struct file *file,
+                           unsigned int cmd, void *arg)
+{
+       struct dvb_device *dvbdev = file->private_data;
+       struct firedtv *fdtv = dvbdev->priv;
+       struct firedtv_tuner_status stat;
+       int err;
+
+       switch (cmd) {
+       case CA_RESET:
+               err = fdtv_ca_reset(fdtv);
+               break;
+       case CA_GET_CAP:
+               err = fdtv_ca_get_caps(arg);
+               break;
+       case CA_GET_SLOT_INFO:
+               err = fdtv_ca_get_slot_info(fdtv, arg);
+               break;
+       case CA_GET_MSG:
+               err = fdtv_ca_get_msg(fdtv, arg);
+               break;
+       case CA_SEND_MSG:
+               err = fdtv_ca_send_msg(fdtv, arg);
+               break;
+       default:
+               dev_info(fdtv->device, "unhandled CA ioctl %u\n", cmd);
+               err = -EOPNOTSUPP;
+       }
+
+       /* FIXME Is this necessary? */
+       avc_tuner_status(fdtv, &stat);
+
+       return err;
+}
+
+static unsigned int fdtv_ca_io_poll(struct file *file, poll_table *wait)
+{
+       return POLLIN;
+}
+
+static struct file_operations fdtv_ca_fops = {
+       .owner          = THIS_MODULE,
+       .ioctl          = dvb_generic_ioctl,
+       .open           = dvb_generic_open,
+       .release        = dvb_generic_release,
+       .poll           = fdtv_ca_io_poll,
+};
+
+static struct dvb_device fdtv_ca = {
+       .users          = 1,
+       .readers        = 1,
+       .writers        = 1,
+       .fops           = &fdtv_ca_fops,
+       .kernel_ioctl   = fdtv_ca_ioctl,
+};
+
+int fdtv_ca_register(struct firedtv *fdtv)
+{
+       struct firedtv_tuner_status stat;
+       int err;
+
+       if (avc_tuner_status(fdtv, &stat))
+               return -EINVAL;
+
+       if (!fdtv_ca_ready(&stat))
+               return -EFAULT;
+
+       err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
+                                 &fdtv_ca, fdtv, DVB_DEVICE_CA);
+
+       if (stat.ca_application_info == 0)
+               dev_err(fdtv->device, "CaApplicationInfo is not set\n");
+       if (stat.ca_date_time_request == 1)
+               avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval);
+
+       return err;
+}
+
+void fdtv_ca_release(struct firedtv *fdtv)
+{
+       if (fdtv->cadev)
+               dvb_unregister_device(fdtv->cadev);
+}
diff --git a/drivers/media/dvb/firewire/firedtv-dvb.c b/drivers/media/dvb/firewire/firedtv-dvb.c
new file mode 100644 (file)
index 0000000..9d308dd
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include <dmxdev.h>
+#include <dvb_demux.h>
+#include <dvbdev.h>
+#include <dvb_frontend.h>
+
+#include "firedtv.h"
+
+static int alloc_channel(struct firedtv *fdtv)
+{
+       int i;
+
+       for (i = 0; i < 16; i++)
+               if (!__test_and_set_bit(i, &fdtv->channel_active))
+                       break;
+       return i;
+}
+
+static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[])
+{
+       int i, n;
+
+       for (i = 0, n = 0; i < 16; i++)
+               if (test_bit(i, &fdtv->channel_active))
+                       pid[n++] = fdtv->channel_pid[i];
+       *pidc = n;
+}
+
+static inline void dealloc_channel(struct firedtv *fdtv, int i)
+{
+       __clear_bit(i, &fdtv->channel_active);
+}
+
+int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       struct firedtv *fdtv = dvbdmxfeed->demux->priv;
+       int pidc, c, ret;
+       u16 pids[16];
+
+       switch (dvbdmxfeed->type) {
+       case DMX_TYPE_TS:
+       case DMX_TYPE_SEC:
+               break;
+       default:
+               dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n",
+                       dvbdmxfeed->type);
+               return -EINVAL;
+       }
+
+       if (mutex_lock_interruptible(&fdtv->demux_mutex))
+               return -EINTR;
+
+       if (dvbdmxfeed->type == DMX_TYPE_TS) {
+               switch (dvbdmxfeed->pes_type) {
+               case DMX_TS_PES_VIDEO:
+               case DMX_TS_PES_AUDIO:
+               case DMX_TS_PES_TELETEXT:
+               case DMX_TS_PES_PCR:
+               case DMX_TS_PES_OTHER:
+                       c = alloc_channel(fdtv);
+                       break;
+               default:
+                       dev_err(fdtv->device,
+                               "can't start dmx feed: invalid pes type %u\n",
+                               dvbdmxfeed->pes_type);
+                       ret = -EINVAL;
+                       goto out;
+               }
+       } else {
+               c = alloc_channel(fdtv);
+       }
+
+       if (c > 15) {
+               dev_err(fdtv->device, "can't start dmx feed: busy\n");
+               ret = -EBUSY;
+               goto out;
+       }
+
+       dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c;
+       fdtv->channel_pid[c] = dvbdmxfeed->pid;
+       collect_channels(fdtv, &pidc, pids);
+
+       if (dvbdmxfeed->pid == 8192) {
+               ret = avc_tuner_get_ts(fdtv);
+               if (ret) {
+                       dealloc_channel(fdtv, c);
+                       dev_err(fdtv->device, "can't get TS\n");
+                       goto out;
+               }
+       } else {
+               ret = avc_tuner_set_pids(fdtv, pidc, pids);
+               if (ret) {
+                       dealloc_channel(fdtv, c);
+                       dev_err(fdtv->device, "can't set PIDs\n");
+                       goto out;
+               }
+       }
+out:
+       mutex_unlock(&fdtv->demux_mutex);
+
+       return ret;
+}
+
+int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       struct dvb_demux *demux = dvbdmxfeed->demux;
+       struct firedtv *fdtv = demux->priv;
+       int pidc, c, ret;
+       u16 pids[16];
+
+       if (dvbdmxfeed->type == DMX_TYPE_TS &&
+           !((dvbdmxfeed->ts_type & TS_PACKET) &&
+             (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
+
+               if (dvbdmxfeed->ts_type & TS_DECODER) {
+                       if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
+                           !demux->pesfilter[dvbdmxfeed->pes_type])
+                               return -EINVAL;
+
+                       demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
+                       demux->pesfilter[dvbdmxfeed->pes_type] = NULL;
+               }
+
+               if (!(dvbdmxfeed->ts_type & TS_DECODER &&
+                     dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
+                       return 0;
+       }
+
+       if (mutex_lock_interruptible(&fdtv->demux_mutex))
+               return -EINTR;
+
+       c = (unsigned long)dvbdmxfeed->priv;
+       dealloc_channel(fdtv, c);
+       collect_channels(fdtv, &pidc, pids);
+
+       ret = avc_tuner_set_pids(fdtv, pidc, pids);
+
+       mutex_unlock(&fdtv->demux_mutex);
+
+       return ret;
+}
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+int fdtv_dvb_register(struct firedtv *fdtv)
+{
+       int err;
+
+       err = dvb_register_adapter(&fdtv->adapter, fdtv_model_names[fdtv->type],
+                                  THIS_MODULE, fdtv->device, adapter_nr);
+       if (err < 0)
+               goto fail_log;
+
+       /*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/
+       fdtv->demux.dmx.capabilities = 0;
+
+       fdtv->demux.priv        = fdtv;
+       fdtv->demux.filternum   = 16;
+       fdtv->demux.feednum     = 16;
+       fdtv->demux.start_feed  = fdtv_start_feed;
+       fdtv->demux.stop_feed   = fdtv_stop_feed;
+       fdtv->demux.write_to_decoder = NULL;
+
+       err = dvb_dmx_init(&fdtv->demux);
+       if (err)
+               goto fail_unreg_adapter;
+
+       fdtv->dmxdev.filternum    = 16;
+       fdtv->dmxdev.demux        = &fdtv->demux.dmx;
+       fdtv->dmxdev.capabilities = 0;
+
+       err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter);
+       if (err)
+               goto fail_dmx_release;
+
+       fdtv->frontend.source = DMX_FRONTEND_0;
+
+       err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend);
+       if (err)
+               goto fail_dmxdev_release;
+
+       err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx,
+                                              &fdtv->frontend);
+       if (err)
+               goto fail_rem_frontend;
+
+       dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
+
+       fdtv_frontend_init(fdtv);
+       err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
+       if (err)
+               goto fail_net_release;
+
+       err = fdtv_ca_register(fdtv);
+       if (err)
+               dev_info(fdtv->device,
+                        "Conditional Access Module not enabled\n");
+       return 0;
+
+fail_net_release:
+       dvb_net_release(&fdtv->dvbnet);
+       fdtv->demux.dmx.close(&fdtv->demux.dmx);
+fail_rem_frontend:
+       fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
+fail_dmxdev_release:
+       dvb_dmxdev_release(&fdtv->dmxdev);
+fail_dmx_release:
+       dvb_dmx_release(&fdtv->demux);
+fail_unreg_adapter:
+       dvb_unregister_adapter(&fdtv->adapter);
+fail_log:
+       dev_err(fdtv->device, "DVB initialization failed\n");
+       return err;
+}
+
+void fdtv_dvb_unregister(struct firedtv *fdtv)
+{
+       fdtv_ca_release(fdtv);
+       dvb_unregister_frontend(&fdtv->fe);
+       dvb_net_release(&fdtv->dvbnet);
+       fdtv->demux.dmx.close(&fdtv->demux.dmx);
+       fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
+       dvb_dmxdev_release(&fdtv->dmxdev);
+       dvb_dmx_release(&fdtv->demux);
+       dvb_unregister_adapter(&fdtv->adapter);
+}
+
+const char *fdtv_model_names[] = {
+       [FIREDTV_UNKNOWN] = "unknown type",
+       [FIREDTV_DVB_S]   = "FireDTV S/CI",
+       [FIREDTV_DVB_C]   = "FireDTV C/CI",
+       [FIREDTV_DVB_T]   = "FireDTV T/CI",
+       [FIREDTV_DVB_S2]  = "FireDTV S2  ",
+};
+
+struct firedtv *fdtv_alloc(struct device *dev,
+                          const struct firedtv_backend *backend,
+                          const char *name, size_t name_len)
+{
+       struct firedtv *fdtv;
+       int i;
+
+       fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
+       if (!fdtv)
+               return NULL;
+
+       dev->driver_data        = fdtv;
+       fdtv->device            = dev;
+       fdtv->isochannel        = -1;
+       fdtv->voltage           = 0xff;
+       fdtv->tone              = 0xff;
+       fdtv->backend           = backend;
+
+       mutex_init(&fdtv->avc_mutex);
+       init_waitqueue_head(&fdtv->avc_wait);
+       fdtv->avc_reply_received = true;
+       mutex_init(&fdtv->demux_mutex);
+       INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
+
+       for (i = ARRAY_SIZE(fdtv_model_names); --i; )
+               if (strlen(fdtv_model_names[i]) <= name_len &&
+                   strncmp(name, fdtv_model_names[i], name_len) == 0)
+                       break;
+       fdtv->type = i;
+
+       return fdtv;
+}
+
+#define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
+                    IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
+
+#define DIGITAL_EVERYWHERE_OUI 0x001287
+#define AVC_UNIT_SPEC_ID_ENTRY 0x00a02d
+#define AVC_SW_VERSION_ENTRY   0x010001
+
+static struct ieee1394_device_id fdtv_id_table[] = {
+       {
+               /* FloppyDTV S/CI and FloppyDTV S2 */
+               .match_flags    = MATCH_FLAGS,
+               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
+               .model_id       = 0x000024,
+               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
+               .version        = AVC_SW_VERSION_ENTRY,
+       }, {
+               /* FloppyDTV T/CI */
+               .match_flags    = MATCH_FLAGS,
+               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
+               .model_id       = 0x000025,
+               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
+               .version        = AVC_SW_VERSION_ENTRY,
+       }, {
+               /* FloppyDTV C/CI */
+               .match_flags    = MATCH_FLAGS,
+               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
+               .model_id       = 0x000026,
+               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
+               .version        = AVC_SW_VERSION_ENTRY,
+       }, {
+               /* FireDTV S/CI and FloppyDTV S2 */
+               .match_flags    = MATCH_FLAGS,
+               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
+               .model_id       = 0x000034,
+               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
+               .version        = AVC_SW_VERSION_ENTRY,
+       }, {
+               /* FireDTV T/CI */
+               .match_flags    = MATCH_FLAGS,
+               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
+               .model_id       = 0x000035,
+               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
+               .version        = AVC_SW_VERSION_ENTRY,
+       }, {
+               /* FireDTV C/CI */
+               .match_flags    = MATCH_FLAGS,
+               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
+               .model_id       = 0x000036,
+               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
+               .version        = AVC_SW_VERSION_ENTRY,
+       }, {}
+};
+MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
+
+static int __init fdtv_init(void)
+{
+       return fdtv_1394_init(fdtv_id_table);
+}
+
+static void __exit fdtv_exit(void)
+{
+       fdtv_1394_exit();
+}
+
+module_init(fdtv_init);
+module_exit(fdtv_exit);
+
+MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
+MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
+MODULE_DESCRIPTION("FireDTV DVB Driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("FireDTV DVB");
diff --git a/drivers/media/dvb/firewire/firedtv-fe.c b/drivers/media/dvb/firewire/firedtv-fe.c
new file mode 100644 (file)
index 0000000..7ba4363
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <dvb_frontend.h>
+
+#include "firedtv.h"
+
+static int fdtv_dvb_init(struct dvb_frontend *fe)
+{
+       struct firedtv *fdtv = fe->sec_priv;
+       int err;
+
+       /* FIXME - allocate free channel at IRM */
+       fdtv->isochannel = fdtv->adapter.num;
+
+       err = cmp_establish_pp_connection(fdtv, fdtv->subunit,
+                                         fdtv->isochannel);
+       if (err) {
+               dev_err(fdtv->device,
+                       "could not establish point to point connection\n");
+               return err;
+       }
+
+       return fdtv->backend->start_iso(fdtv);
+}
+
+static int fdtv_sleep(struct dvb_frontend *fe)
+{
+       struct firedtv *fdtv = fe->sec_priv;
+
+       fdtv->backend->stop_iso(fdtv);
+       cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel);
+       fdtv->isochannel = -1;
+       return 0;
+}
+
+#define LNBCONTROL_DONTCARE 0xff
+
+static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe,
+                                      struct dvb_diseqc_master_cmd *cmd)
+{
+       struct firedtv *fdtv = fe->sec_priv;
+
+       return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE,
+                              LNBCONTROL_DONTCARE, 1, cmd);
+}
+
+static int fdtv_diseqc_send_burst(struct dvb_frontend *fe,
+                                 fe_sec_mini_cmd_t minicmd)
+{
+       return 0;
+}
+
+static int fdtv_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+       struct firedtv *fdtv = fe->sec_priv;
+
+       fdtv->tone = tone;
+       return 0;
+}
+
+static int fdtv_set_voltage(struct dvb_frontend *fe,
+                           fe_sec_voltage_t voltage)
+{
+       struct firedtv *fdtv = fe->sec_priv;
+
+       fdtv->voltage = voltage;
+       return 0;
+}
+
+static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       struct firedtv *fdtv = fe->sec_priv;
+       struct firedtv_tuner_status stat;
+
+       if (avc_tuner_status(fdtv, &stat))
+               return -EINVAL;
+
+       if (stat.no_rf)
+               *status = 0;
+       else
+               *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC |
+                         FE_HAS_CARRIER | FE_HAS_LOCK;
+       return 0;
+}
+
+static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct firedtv *fdtv = fe->sec_priv;
+       struct firedtv_tuner_status stat;
+
+       if (avc_tuner_status(fdtv, &stat))
+               return -EINVAL;
+
+       *ber = stat.ber;
+       return 0;
+}
+
+static int fdtv_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+       struct firedtv *fdtv = fe->sec_priv;
+       struct firedtv_tuner_status stat;
+
+       if (avc_tuner_status(fdtv, &stat))
+               return -EINVAL;
+
+       *strength = stat.signal_strength << 8;
+       return 0;
+}
+
+static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct firedtv *fdtv = fe->sec_priv;
+       struct firedtv_tuner_status stat;
+
+       if (avc_tuner_status(fdtv, &stat))
+               return -EINVAL;
+
+       /* C/N[dB] = -10 * log10(snr / 65535) */
+       *snr = stat.carrier_noise_ratio * 257;
+       return 0;
+}
+
+static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       return -EOPNOTSUPP;
+}
+
+#define ACCEPTED 0x9
+
+static int fdtv_set_frontend(struct dvb_frontend *fe,
+                            struct dvb_frontend_parameters *params)
+{
+       struct firedtv *fdtv = fe->sec_priv;
+
+       /* FIXME: avc_tuner_dsd never returns ACCEPTED. Check status? */
+       if (avc_tuner_dsd(fdtv, params) != ACCEPTED)
+               return -EINVAL;
+       else
+               return 0; /* not sure of this... */
+}
+
+static int fdtv_get_frontend(struct dvb_frontend *fe,
+                            struct dvb_frontend_parameters *params)
+{
+       return -EOPNOTSUPP;
+}
+
+void fdtv_frontend_init(struct firedtv *fdtv)
+{
+       struct dvb_frontend_ops *ops = &fdtv->fe.ops;
+       struct dvb_frontend_info *fi = &ops->info;
+
+       ops->init                       = fdtv_dvb_init;
+       ops->sleep                      = fdtv_sleep;
+
+       ops->set_frontend               = fdtv_set_frontend;
+       ops->get_frontend               = fdtv_get_frontend;
+
+       ops->read_status                = fdtv_read_status;
+       ops->read_ber                   = fdtv_read_ber;
+       ops->read_signal_strength       = fdtv_read_signal_strength;
+       ops->read_snr                   = fdtv_read_snr;
+       ops->read_ucblocks              = fdtv_read_uncorrected_blocks;
+
+       ops->diseqc_send_master_cmd     = fdtv_diseqc_send_master_cmd;
+       ops->diseqc_send_burst          = fdtv_diseqc_send_burst;
+       ops->set_tone                   = fdtv_set_tone;
+       ops->set_voltage                = fdtv_set_voltage;
+
+       switch (fdtv->type) {
+       case FIREDTV_DVB_S:
+       case FIREDTV_DVB_S2:
+               fi->type                = FE_QPSK;
+
+               fi->frequency_min       = 950000;
+               fi->frequency_max       = 2150000;
+               fi->frequency_stepsize  = 125;
+               fi->symbol_rate_min     = 1000000;
+               fi->symbol_rate_max     = 40000000;
+
+               fi->caps                = FE_CAN_INVERSION_AUTO |
+                                         FE_CAN_FEC_1_2        |
+                                         FE_CAN_FEC_2_3        |
+                                         FE_CAN_FEC_3_4        |
+                                         FE_CAN_FEC_5_6        |
+                                         FE_CAN_FEC_7_8        |
+                                         FE_CAN_FEC_AUTO       |
+                                         FE_CAN_QPSK;
+               break;
+
+       case FIREDTV_DVB_C:
+               fi->type                = FE_QAM;
+
+               fi->frequency_min       = 47000000;
+               fi->frequency_max       = 866000000;
+               fi->frequency_stepsize  = 62500;
+               fi->symbol_rate_min     = 870000;
+               fi->symbol_rate_max     = 6900000;
+
+               fi->caps                = FE_CAN_INVERSION_AUTO |
+                                         FE_CAN_QAM_16         |
+                                         FE_CAN_QAM_32         |
+                                         FE_CAN_QAM_64         |
+                                         FE_CAN_QAM_128        |
+                                         FE_CAN_QAM_256        |
+                                         FE_CAN_QAM_AUTO;
+               break;
+
+       case FIREDTV_DVB_T:
+               fi->type                = FE_OFDM;
+
+               fi->frequency_min       = 49000000;
+               fi->frequency_max       = 861000000;
+               fi->frequency_stepsize  = 62500;
+
+               fi->caps                = FE_CAN_INVERSION_AUTO         |
+                                         FE_CAN_FEC_2_3                |
+                                         FE_CAN_TRANSMISSION_MODE_AUTO |
+                                         FE_CAN_GUARD_INTERVAL_AUTO    |
+                                         FE_CAN_HIERARCHY_AUTO;
+               break;
+
+       default:
+               dev_err(fdtv->device, "no frontend for model type %d\n",
+                       fdtv->type);
+       }
+       strcpy(fi->name, fdtv_model_names[fdtv->type]);
+
+       fdtv->fe.dvb = &fdtv->adapter;
+       fdtv->fe.sec_priv = fdtv;
+}
diff --git a/drivers/media/dvb/firewire/firedtv-rc.c b/drivers/media/dvb/firewire/firedtv-rc.c
new file mode 100644 (file)
index 0000000..46a6324
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ */
+
+#include <linux/bitops.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include "firedtv.h"
+
+/* fixed table with older keycodes, geared towards MythTV */
+const static u16 oldtable[] = {
+
+       /* code from device: 0x4501...0x451f */
+
+       KEY_ESC,
+       KEY_F9,
+       KEY_1,
+       KEY_2,
+       KEY_3,
+       KEY_4,
+       KEY_5,
+       KEY_6,
+       KEY_7,
+       KEY_8,
+       KEY_9,
+       KEY_I,
+       KEY_0,
+       KEY_ENTER,
+       KEY_RED,
+       KEY_UP,
+       KEY_GREEN,
+       KEY_F10,
+       KEY_SPACE,
+       KEY_F11,
+       KEY_YELLOW,
+       KEY_DOWN,
+       KEY_BLUE,
+       KEY_Z,
+       KEY_P,
+       KEY_PAGEDOWN,
+       KEY_LEFT,
+       KEY_W,
+       KEY_RIGHT,
+       KEY_P,
+       KEY_M,
+
+       /* code from device: 0x4540...0x4542 */
+
+       KEY_R,
+       KEY_V,
+       KEY_C,
+};
+
+/* user-modifiable table for a remote as sold in 2008 */
+const static u16 keytable[] = {
+
+       /* code from device: 0x0300...0x031f */
+
+       [0x00] = KEY_POWER,
+       [0x01] = KEY_SLEEP,
+       [0x02] = KEY_STOP,
+       [0x03] = KEY_OK,
+       [0x04] = KEY_RIGHT,
+       [0x05] = KEY_1,
+       [0x06] = KEY_2,
+       [0x07] = KEY_3,
+       [0x08] = KEY_LEFT,
+       [0x09] = KEY_4,
+       [0x0a] = KEY_5,
+       [0x0b] = KEY_6,
+       [0x0c] = KEY_UP,
+       [0x0d] = KEY_7,
+       [0x0e] = KEY_8,
+       [0x0f] = KEY_9,
+       [0x10] = KEY_DOWN,
+       [0x11] = KEY_TITLE,     /* "OSD" - fixme */
+       [0x12] = KEY_0,
+       [0x13] = KEY_F20,       /* "16:9" - fixme */
+       [0x14] = KEY_SCREEN,    /* "FULL" - fixme */
+       [0x15] = KEY_MUTE,
+       [0x16] = KEY_SUBTITLE,
+       [0x17] = KEY_RECORD,
+       [0x18] = KEY_TEXT,
+       [0x19] = KEY_AUDIO,
+       [0x1a] = KEY_RED,
+       [0x1b] = KEY_PREVIOUS,
+       [0x1c] = KEY_REWIND,
+       [0x1d] = KEY_PLAYPAUSE,
+       [0x1e] = KEY_NEXT,
+       [0x1f] = KEY_VOLUMEUP,
+
+       /* code from device: 0x0340...0x0354 */
+
+       [0x20] = KEY_CHANNELUP,
+       [0x21] = KEY_F21,       /* "4:3" - fixme */
+       [0x22] = KEY_TV,
+       [0x23] = KEY_DVD,
+       [0x24] = KEY_VCR,
+       [0x25] = KEY_AUX,
+       [0x26] = KEY_GREEN,
+       [0x27] = KEY_YELLOW,
+       [0x28] = KEY_BLUE,
+       [0x29] = KEY_CHANNEL,   /* "CH.LIST" */
+       [0x2a] = KEY_VENDOR,    /* "CI" - fixme */
+       [0x2b] = KEY_VOLUMEDOWN,
+       [0x2c] = KEY_CHANNELDOWN,
+       [0x2d] = KEY_LAST,
+       [0x2e] = KEY_INFO,
+       [0x2f] = KEY_FORWARD,
+       [0x30] = KEY_LIST,
+       [0x31] = KEY_FAVORITES,
+       [0x32] = KEY_MENU,
+       [0x33] = KEY_EPG,
+       [0x34] = KEY_EXIT,
+};
+
+int fdtv_register_rc(struct firedtv *fdtv, struct device *dev)
+{
+       struct input_dev *idev;
+       int i, err;
+
+       idev = input_allocate_device();
+       if (!idev)
+               return -ENOMEM;
+
+       fdtv->remote_ctrl_dev = idev;
+       idev->name = "FireDTV remote control";
+       idev->dev.parent = dev;
+       idev->evbit[0] = BIT_MASK(EV_KEY);
+       idev->keycode = kmemdup(keytable, sizeof(keytable), GFP_KERNEL);
+       if (!idev->keycode) {
+               err = -ENOMEM;
+               goto fail;
+       }
+       idev->keycodesize = sizeof(keytable[0]);
+       idev->keycodemax = ARRAY_SIZE(keytable);
+
+       for (i = 0; i < ARRAY_SIZE(keytable); i++)
+               set_bit(keytable[i], idev->keybit);
+
+       err = input_register_device(idev);
+       if (err)
+               goto fail_free_keymap;
+
+       return 0;
+
+fail_free_keymap:
+       kfree(idev->keycode);
+fail:
+       input_free_device(idev);
+       return err;
+}
+
+void fdtv_unregister_rc(struct firedtv *fdtv)
+{
+       kfree(fdtv->remote_ctrl_dev->keycode);
+       input_unregister_device(fdtv->remote_ctrl_dev);
+}
+
+void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code)
+{
+       u16 *keycode = fdtv->remote_ctrl_dev->keycode;
+
+       if (code >= 0x0300 && code <= 0x031f)
+               code = keycode[code - 0x0300];
+       else if (code >= 0x0340 && code <= 0x0354)
+               code = keycode[code - 0x0320];
+       else if (code >= 0x4501 && code <= 0x451f)
+               code = oldtable[code - 0x4501];
+       else if (code >= 0x4540 && code <= 0x4542)
+               code = oldtable[code - 0x4521];
+       else {
+               printk(KERN_DEBUG "firedtv: invalid key code 0x%04x "
+                      "from remote control\n", code);
+               return;
+       }
+
+       input_report_key(fdtv->remote_ctrl_dev, code, 1);
+       input_report_key(fdtv->remote_ctrl_dev, code, 0);
+}
diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/dvb/firewire/firedtv.h
new file mode 100644 (file)
index 0000000..d48530b
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ */
+
+#ifndef _FIREDTV_H
+#define _FIREDTV_H
+
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/frontend.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/spinlock_types.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include <demux.h>
+#include <dmxdev.h>
+#include <dvb_demux.h>
+#include <dvb_frontend.h>
+#include <dvb_net.h>
+#include <dvbdev.h>
+
+struct firedtv_tuner_status {
+       unsigned active_system:8;
+       unsigned searching:1;
+       unsigned moving:1;
+       unsigned no_rf:1;
+       unsigned input:1;
+       unsigned selected_antenna:7;
+       unsigned ber:32;
+       unsigned signal_strength:8;
+       unsigned raster_frequency:2;
+       unsigned rf_frequency:22;
+       unsigned man_dep_info_length:8;
+       unsigned front_end_error:1;
+       unsigned antenna_error:1;
+       unsigned front_end_power_status:1;
+       unsigned power_supply:1;
+       unsigned carrier_noise_ratio:16;
+       unsigned power_supply_voltage:8;
+       unsigned antenna_voltage:8;
+       unsigned firewire_bus_voltage:8;
+       unsigned ca_mmi:1;
+       unsigned ca_pmt_reply:1;
+       unsigned ca_date_time_request:1;
+       unsigned ca_application_info:1;
+       unsigned ca_module_present_status:1;
+       unsigned ca_dvb_flag:1;
+       unsigned ca_error_flag:1;
+       unsigned ca_initialization_status:1;
+};
+
+enum model_type {
+       FIREDTV_UNKNOWN = 0,
+       FIREDTV_DVB_S   = 1,
+       FIREDTV_DVB_C   = 2,
+       FIREDTV_DVB_T   = 3,
+       FIREDTV_DVB_S2  = 4,
+};
+
+struct device;
+struct input_dev;
+struct firedtv;
+
+struct firedtv_backend {
+       int (*lock)(struct firedtv *fdtv, u64 addr, void *data, __be32 arg);
+       int (*read)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
+       int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
+       int (*start_iso)(struct firedtv *fdtv);
+       void (*stop_iso)(struct firedtv *fdtv);
+};
+
+struct firedtv {
+       struct device *device;
+       struct list_head list;
+
+       struct dvb_adapter      adapter;
+       struct dmxdev           dmxdev;
+       struct dvb_demux        demux;
+       struct dmx_frontend     frontend;
+       struct dvb_net          dvbnet;
+       struct dvb_frontend     fe;
+
+       struct dvb_device       *cadev;
+       int                     ca_last_command;
+       int                     ca_time_interval;
+
+       struct mutex            avc_mutex;
+       wait_queue_head_t       avc_wait;
+       bool                    avc_reply_received;
+       struct work_struct      remote_ctrl_work;
+       struct input_dev        *remote_ctrl_dev;
+
+       enum model_type         type;
+       char                    subunit;
+       char                    isochannel;
+       fe_sec_voltage_t        voltage;
+       fe_sec_tone_mode_t      tone;
+
+       const struct firedtv_backend *backend;
+       void                    *backend_data;
+
+       struct mutex            demux_mutex;
+       unsigned long           channel_active;
+       u16                     channel_pid[16];
+
+       size_t                  response_length;
+       u8                      response[512];
+};
+
+/* firedtv-1394.c */
+#ifdef CONFIG_DVB_FIREDTV_IEEE1394
+int fdtv_1394_init(struct ieee1394_device_id id_table[]);
+void fdtv_1394_exit(void);
+#else
+static inline int fdtv_1394_init(struct ieee1394_device_id it[]) { return 0; }
+static inline void fdtv_1394_exit(void) {}
+#endif
+
+/* firedtv-avc.c */
+int avc_recv(struct firedtv *fdtv, void *data, size_t length);
+int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat);
+struct dvb_frontend_parameters;
+int avc_tuner_dsd(struct firedtv *fdtv, struct dvb_frontend_parameters *params);
+int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]);
+int avc_tuner_get_ts(struct firedtv *fdtv);
+int avc_identify_subunit(struct firedtv *fdtv);
+struct dvb_diseqc_master_cmd;
+int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
+                   char conttone, char nrdiseq,
+                   struct dvb_diseqc_master_cmd *diseqcmd);
+void avc_remote_ctrl_work(struct work_struct *work);
+int avc_register_remote_control(struct firedtv *fdtv);
+int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
+int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
+int avc_ca_reset(struct firedtv *fdtv);
+int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length);
+int avc_ca_get_time_date(struct firedtv *fdtv, int *interval);
+int avc_ca_enter_menu(struct firedtv *fdtv);
+int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len);
+int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel);
+void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel);
+
+/* firedtv-ci.c */
+int fdtv_ca_register(struct firedtv *fdtv);
+void fdtv_ca_release(struct firedtv *fdtv);
+
+/* firedtv-dvb.c */
+int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed);
+int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
+int fdtv_dvb_register(struct firedtv *fdtv);
+void fdtv_dvb_unregister(struct firedtv *fdtv);
+struct firedtv *fdtv_alloc(struct device *dev,
+                          const struct firedtv_backend *backend,
+                          const char *name, size_t name_len);
+extern const char *fdtv_model_names[];
+
+/* firedtv-fe.c */
+void fdtv_frontend_init(struct firedtv *fdtv);
+
+/* firedtv-rc.c */
+#ifdef CONFIG_DVB_FIREDTV_INPUT
+int fdtv_register_rc(struct firedtv *fdtv, struct device *dev);
+void fdtv_unregister_rc(struct firedtv *fdtv);
+void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code);
+#else
+static inline int fdtv_register_rc(struct firedtv *fdtv,
+                                  struct device *dev) { return 0; }
+static inline void fdtv_unregister_rc(struct firedtv *fdtv) {}
+static inline void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) {}
+#endif
+
+#endif /* _FIREDTV_H */
index 5d882a44e3eee5444c00062f3e5edf70b118cc4e..2ac738fa6a07e0cd66fac559fd3c9688060dff39 100644 (file)
@@ -463,6 +463,8 @@ static int em28xx_audio_init(struct em28xx *dev)
        pcm->info_flags = 0;
        pcm->private_data = dev;
        strcpy(pcm->name, "Empia 28xx Capture");
+
+       snd_card_set_dev(card, &dev->udev->dev);
        strcpy(card->driver, "Empia Em28xx Audio");
        strcpy(card->shortname, "Em28xx Audio");
        strcpy(card->longname, "Empia Em28xx Audio");
index a1d6008efcbb5c5a2f22164dc6ab55e9b9b8e366..07c334f25aae69bf257a2a0cff91465bd5e784b9 100644 (file)
@@ -1155,23 +1155,23 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
 {
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
        struct pxa_camera_dev *pcdev = ici->priv;
-       const struct soc_camera_data_format *host_fmt, *cam_fmt = NULL;
-       const struct soc_camera_format_xlate *xlate;
+       const struct soc_camera_data_format *cam_fmt = NULL;
+       const struct soc_camera_format_xlate *xlate = NULL;
        struct soc_camera_sense sense = {
                .master_clock = pcdev->mclk,
                .pixel_clock_max = pcdev->ciclk / 4,
        };
-       int ret, buswidth;
+       int ret;
 
-       xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
-       if (!xlate) {
-               dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
-               return -EINVAL;
-       }
+       if (pixfmt) {
+               xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
+               if (!xlate) {
+                       dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+                       return -EINVAL;
+               }
 
-       buswidth = xlate->buswidth;
-       host_fmt = xlate->host_fmt;
-       cam_fmt = xlate->cam_fmt;
+               cam_fmt = xlate->cam_fmt;
+       }
 
        /* If PCLK is used to latch data from the sensor, check sense */
        if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
@@ -1201,8 +1201,8 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
        }
 
        if (pixfmt && !ret) {
-               icd->buswidth = buswidth;
-               icd->current_fmt = host_fmt;
+               icd->buswidth = xlate->buswidth;
+               icd->current_fmt = xlate->host_fmt;
        }
 
        return ret;
index 9a2586b07a05c610728de368efe637baddd2778a..ddcb81d0b81a36df1ebebe0b6663c0eed1887040 100644 (file)
@@ -603,21 +603,18 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
        const struct soc_camera_format_xlate *xlate;
        int ret;
 
+       if (!pixfmt)
+               return icd->ops->set_fmt(icd, pixfmt, rect);
+
        xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
        if (!xlate) {
                dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
                return -EINVAL;
        }
 
-       switch (pixfmt) {
-       case 0:                         /* Only geometry change */
-               ret = icd->ops->set_fmt(icd, pixfmt, rect);
-               break;
-       default:
-               ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect);
-       }
+       ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect);
 
-       if (pixfmt && !ret) {
+       if (!ret) {
                icd->buswidth = xlate->buswidth;
                icd->current_fmt = xlate->host_fmt;
                pcdev->camera_fmt = xlate->cam_fmt;
index c1e4ae27c61388f9c70c529badef2dfc9dd0808d..c705f248da8856d72c384d5b69b67df0c86a7567 100644 (file)
@@ -46,8 +46,8 @@ static int uvc_input_init(struct uvc_device *dev)
        usb_to_input_id(udev, &input->id);
        input->dev.parent = &dev->intf->dev;
 
-       set_bit(EV_KEY, input->evbit);
-       set_bit(BTN_0, input->keybit);
+       __set_bit(EV_KEY, input->evbit);
+       __set_bit(KEY_CAMERA, input->keybit);
 
        if ((ret = input_register_device(input)) < 0)
                goto error;
@@ -70,8 +70,10 @@ static void uvc_input_cleanup(struct uvc_device *dev)
 static void uvc_input_report_key(struct uvc_device *dev, unsigned int code,
        int value)
 {
-       if (dev->input)
+       if (dev->input) {
                input_report_key(dev->input, code, value);
+               input_sync(dev->input);
+       }
 }
 
 #else
@@ -96,7 +98,7 @@ static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len)
                        return;
                uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n",
                        data[1], data[3] ? "pressed" : "released", len);
-               uvc_input_report_key(dev, BTN_0, data[3]);
+               uvc_input_report_key(dev, KEY_CAMERA, data[3]);
        } else {
                uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x "
                        "len %d.\n", data[1], data[2], data[3], len);
index 96ac88317b8ecbadd702a3934c883b579e50aa49..ea3aafbbda449696b6653edc9ebf02094490e067 100644 (file)
@@ -91,9 +91,9 @@ MODULE_PARM_DESC(mpt_msi_enable_fc, " Enable MSI Support for FC \
                controllers (default=0)");
 
 static int mpt_msi_enable_sas;
-module_param(mpt_msi_enable_sas, int, 1);
+module_param(mpt_msi_enable_sas, int, 0);
 MODULE_PARM_DESC(mpt_msi_enable_sas, " Enable MSI Support for SAS \
-               controllers (default=1)");
+               controllers (default=0)");
 
 
 static int mpt_channel_mapping;
index f26667a7abf7c6ce0e7a3a911d7bb193f2489859..cf991850f01ba04b23ad40b1ded35747735b0bf4 100644 (file)
@@ -710,6 +710,7 @@ out:
 
 static struct pci_device_id ilo_devices[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB204) },
+       { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3307) },
        { }
 };
 MODULE_DEVICE_TABLE(pci, ilo_devices);
@@ -758,7 +759,7 @@ static void __exit ilo_exit(void)
        class_destroy(ilo_class);
 }
 
-MODULE_VERSION("0.06");
+MODULE_VERSION("1.0");
 MODULE_ALIAS(ILO_NAME);
 MODULE_DESCRIPTION(ILO_NAME);
 MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");
index 8cff5f5e7f86dfa6f743317910afb028db7ca2df..406da9a8d453718b7d057e174199a139cab332e1 100644 (file)
@@ -107,6 +107,7 @@ static const struct sdhci_pci_fixes sdhci_ene_714 = {
 
 static const struct sdhci_pci_fixes sdhci_cafe = {
        .quirks         = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
+                         SDHCI_QUIRK_NO_BUSY_IRQ |
                          SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
 };
 
index f52f3053ed9251a9d3c3b795997e0f6dbd3ffbf5..accb592764edb4522a24160eced3db7afca13f4a 100644 (file)
@@ -1291,8 +1291,11 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
                if (host->cmd->data)
                        DBG("Cannot wait for busy signal when also "
                                "doing a data transfer");
-               else
+               else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ))
                        return;
+
+               /* The controller does not support the end-of-busy IRQ,
+                * fall through and take the SDHCI_INT_RESPONSE */
        }
 
        if (intmask & SDHCI_INT_RESPONSE)
index ebb83657e27ab2b1257ab8ef54a3cb6de18d5abf..43c37c68d07af44c15ab89bb372730b13517be5a 100644 (file)
@@ -208,6 +208,8 @@ 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 does not provide transfer-complete interrupt when not busy */
+#define SDHCI_QUIRK_NO_BUSY_IRQ                                (1<<14)
 
        int                     irq;            /* Device IRQ */
        void __iomem *          ioaddr;         /* Mapped address */
index 821d0ed6bae3970453a38d2e40bb0bb802930b1d..c76d6e5f47ee305868da2bc6b382c205107b2247 100644 (file)
@@ -19,6 +19,7 @@ static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
 static void maprom_nop (struct mtd_info *);
 static struct mtd_info *map_rom_probe(struct map_info *map);
+static int maprom_erase (struct mtd_info *mtd, struct erase_info *info);
 
 static struct mtd_chip_driver maprom_chipdrv = {
        .probe  = map_rom_probe,
@@ -42,6 +43,7 @@ static struct mtd_info *map_rom_probe(struct map_info *map)
        mtd->read = maprom_read;
        mtd->write = maprom_write;
        mtd->sync = maprom_nop;
+       mtd->erase = maprom_erase;
        mtd->flags = MTD_CAP_ROM;
        mtd->erasesize = map->size;
        mtd->writesize = 1;
@@ -71,6 +73,12 @@ static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *re
        return -EIO;
 }
 
+static int maprom_erase (struct mtd_info *mtd, struct erase_info *info)
+{
+       /* We do our best 8) */
+       return -EROFS;
+}
+
 static int __init map_rom_init(void)
 {
        register_mtd_chip_driver(&maprom_chipdrv);
index a425d09f35a02fd9f3fbd2f0ff9df68019ba11e3..00248e81ecd5b3350a71a3c5e5e79c03be7af088 100644 (file)
@@ -267,22 +267,28 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength)
        if (*(szlength) != '+') {
                devlength = simple_strtoul(szlength, &buffer, 0);
                devlength = handle_unit(devlength, buffer) - devstart;
+               if (devlength < devstart)
+                       goto err_out;
+
+               devlength -= devstart;
        } else {
                devlength = simple_strtoul(szlength + 1, &buffer, 0);
                devlength = handle_unit(devlength, buffer);
        }
        T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n",
                        devname, devstart, devlength);
-       if ((devstart < 0) || (devlength < 0) || (devlength % SLRAM_BLK_SZ != 0)) {
-               E("slram: Illegal start / length parameter.\n");
-               return(-EINVAL);
-       }
+       if (devlength % SLRAM_BLK_SZ != 0)
+               goto err_out;
 
        if ((devstart = register_device(devname, devstart, devlength))){
                unregister_devices();
                return((int)devstart);
        }
        return(0);
+
+err_out:
+       E("slram: Illegal length parameter.\n");
+       return(-EINVAL);
 }
 
 #ifndef MODULE
index acd4ea9b22781f841e4737d748e53122b8f020a7..5a401d8047ab52bfcdd690041272e80dfafda9cb 100644 (file)
@@ -12,6 +12,7 @@ config MTD_LPDDR
          DDR memories, intended for battery-operated systems.
 
 config MTD_QINFO_PROBE
+       depends on MTD_LPDDR
        tristate "Detect flash chips by QINFO probe"
        help
            Device Information for LPDDR chips is offered through the Overlay
index 0225cbbf22de3ceb21b14a6bb8cf05cb3987817a..043d50fb6ef65abd085a98cc42fe8ca6942dc85c 100644 (file)
@@ -491,7 +491,7 @@ config MTD_PCMCIA_ANONYMOUS
 
 config MTD_BFIN_ASYNC
        tristate "Blackfin BF533-STAMP Flash Chip Support"
-       depends on BFIN533_STAMP && MTD_CFI
+       depends on BFIN533_STAMP && MTD_CFI && MTD_COMPLEX_MAPPINGS
        select MTD_PARTITIONS
        default y
        help
index 6fec86aaed7ebd0100e9d921e4e01bc37806a047..576611f605db1df5063775a677d3cc499cb010e7 100644 (file)
@@ -152,14 +152,18 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev)
 
        if (gpio_request(state->enet_flash_pin, DRIVER_NAME)) {
                pr_devinit(KERN_ERR DRIVER_NAME ": Failed to request gpio %d\n", state->enet_flash_pin);
+               kfree(state);
                return -EBUSY;
        }
        gpio_direction_output(state->enet_flash_pin, 1);
 
        pr_devinit(KERN_NOTICE DRIVER_NAME ": probing %d-bit flash bus\n", state->map.bankwidth * 8);
        state->mtd = do_map_probe(memory->name, &state->map);
-       if (!state->mtd)
+       if (!state->mtd) {
+               gpio_free(state->enet_flash_pin);
+               kfree(state);
                return -ENXIO;
+       }
 
 #ifdef CONFIG_MTD_PARTITIONS
        ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
index 5f7a245ed13294b5038aaed76e4a1383debc49a6..424f17d6ffd1270bfae71befae6975781814f168 100644 (file)
@@ -342,9 +342,9 @@ static struct pci_device_id ck804xrom_pci_tbl[] = {
        { 0, }
 };
 
+#if 0
 MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl);
 
-#if 0
 static struct pci_driver ck804xrom_driver = {
        .name =         MOD_NAME,
        .id_table =     ck804xrom_pci_tbl,
index 87743661d48ebfc4e43f317f5ceddee6e9397fe8..4b122e7ab4b3a5efb36071359137e0a2637c80df 100644 (file)
@@ -29,6 +29,7 @@ struct physmap_flash_info {
        struct map_info         map[MAX_RESOURCES];
 #ifdef CONFIG_MTD_PARTITIONS
        int                     nr_parts;
+       struct mtd_partition    *parts;
 #endif
 };
 
@@ -45,25 +46,26 @@ static int physmap_flash_remove(struct platform_device *dev)
 
        physmap_data = dev->dev.platform_data;
 
-#ifdef CONFIG_MTD_CONCAT
-       if (info->cmtd != info->mtd[0]) {
+#ifdef CONFIG_MTD_PARTITIONS
+       if (info->nr_parts) {
+               del_mtd_partitions(info->cmtd);
+               kfree(info->parts);
+       } else if (physmap_data->nr_parts)
+               del_mtd_partitions(info->cmtd);
+       else
                del_mtd_device(info->cmtd);
+#else
+       del_mtd_device(info->cmtd);
+#endif
+
+#ifdef CONFIG_MTD_CONCAT
+       if (info->cmtd != info->mtd[0])
                mtd_concat_destroy(info->cmtd);
-       }
 #endif
 
        for (i = 0; i < MAX_RESOURCES; i++) {
-               if (info->mtd[i] != NULL) {
-#ifdef CONFIG_MTD_PARTITIONS
-                       if (info->nr_parts || physmap_data->nr_parts)
-                               del_mtd_partitions(info->mtd[i]);
-                       else
-                               del_mtd_device(info->mtd[i]);
-#else
-                       del_mtd_device(info->mtd[i]);
-#endif
+               if (info->mtd[i] != NULL)
                        map_destroy(info->mtd[i]);
-               }
        }
        return 0;
 }
@@ -86,9 +88,6 @@ static int physmap_flash_probe(struct platform_device *dev)
        int err = 0;
        int i;
        int devices_found = 0;
-#ifdef CONFIG_MTD_PARTITIONS
-       struct mtd_partition *parts;
-#endif
 
        physmap_data = dev->dev.platform_data;
        if (physmap_data == NULL)
@@ -167,10 +166,11 @@ static int physmap_flash_probe(struct platform_device *dev)
                goto err_out;
 
 #ifdef CONFIG_MTD_PARTITIONS
-       err = parse_mtd_partitions(info->cmtd, part_probe_types, &parts, 0);
+       err = parse_mtd_partitions(info->cmtd, part_probe_types,
+                               &info->parts, 0);
        if (err > 0) {
-               add_mtd_partitions(info->cmtd, parts, err);
-               kfree(parts);
+               add_mtd_partitions(info->cmtd, info->parts, err);
+               info->nr_parts = err;
                return 0;
        }
 
index 917cf8d3ae9561c5e4e1559758b46efb89d466d2..c2dfd3ea353d61315a8ed4bfc8c056201c30f67e 100644 (file)
@@ -149,7 +149,7 @@ static int __devexit orion_nand_remove(struct platform_device *pdev)
 
 static struct platform_driver orion_nand_driver = {
        .probe          = orion_nand_probe,
-       .remove         = orion_nand_remove,
+       .remove         = __devexit_p(orion_nand_remove),
        .driver         = {
                .name   = "orion_nand",
                .owner  = THIS_MODULE,
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/
index c69c0cdba4a26b1cc254f1ac112cce46171c5f04..811a3ccd14c107c56136af8884022f7cd9f4498f 100644 (file)
@@ -4,7 +4,7 @@
 #
 
 obj-$(CONFIG_ARM_AM79C961A)    += am79c961a.o
-obj-$(CONFIG_ARM_ETHERH)       += etherh.o ../8390.o
+obj-$(CONFIG_ARM_ETHERH)       += etherh.o
 obj-$(CONFIG_ARM_ETHER3)       += ether3.o
 obj-$(CONFIG_ARM_ETHER1)       += ether1.o
 obj-$(CONFIG_ARM_AT91_ETHER)   += at91_ether.o
index 54b52e5b1821bbcd196b3f2f70cea19c51a5ec37..f52f668c49bfae5fcf526d299f9368661dd0d32c 100644 (file)
@@ -641,15 +641,15 @@ static const struct net_device_ops etherh_netdev_ops = {
        .ndo_open               = etherh_open,
        .ndo_stop               = etherh_close,
        .ndo_set_config         = etherh_set_config,
-       .ndo_start_xmit         = ei_start_xmit,
-       .ndo_tx_timeout         = ei_tx_timeout,
-       .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_start_xmit         = __ei_start_xmit,
+       .ndo_tx_timeout         = __ei_tx_timeout,
+       .ndo_get_stats          = __ei_get_stats,
+       .ndo_set_multicast_list = __ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = ei_poll,
+       .ndo_poll_controller    = __ei_poll,
 #endif
 };
 
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 c38512ebcea65fd0408ae0821d3be177b2854e26..dc5f051005faaf2af5aafbf7fa46974537883e33 100644 (file)
@@ -1264,8 +1264,14 @@ static void b44_clear_stats(struct b44 *bp)
 static void b44_chip_reset(struct b44 *bp, int reset_kind)
 {
        struct ssb_device *sdev = bp->sdev;
+       bool was_enabled;
 
-       if (ssb_device_is_enabled(bp->sdev)) {
+       was_enabled = ssb_device_is_enabled(bp->sdev);
+
+       ssb_device_enable(bp->sdev, 0);
+       ssb_pcicore_dev_irqvecs_enable(&sdev->bus->pcicore, sdev);
+
+       if (was_enabled) {
                bw32(bp, B44_RCV_LAZY, 0);
                bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);
                b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1);
@@ -1277,10 +1283,8 @@ static void b44_chip_reset(struct b44 *bp, int reset_kind)
                }
                bw32(bp, B44_DMARX_CTRL, 0);
                bp->rx_prod = bp->rx_cons = 0;
-       } else
-               ssb_pcicore_dev_irqvecs_enable(&sdev->bus->pcicore, sdev);
+       }
 
-       ssb_device_enable(bp->sdev, 0);
        b44_clear_stats(bp);
 
        /*
@@ -2236,6 +2240,7 @@ static void __devexit b44_remove_one(struct ssb_device *sdev)
        struct net_device *dev = ssb_get_drvdata(sdev);
 
        unregister_netdev(dev);
+       ssb_device_disable(sdev, 0);
        ssb_bus_may_powerdown(sdev->bus);
        free_netdev(dev);
        ssb_pcihost_set_power_state(sdev, PCI_D3hot);
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 9b12a13a640f1383fdd3265ae3ebe69949f1b936..9831b3f408aa17fc44431c47b73b8e1057f046eb 100644 (file)
@@ -1284,7 +1284,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
        spin_lock_irqsave(&priv->txlock, flags);
 
        /* check if there is space to queue this packet */
-       if (nr_frags > priv->num_txbdfree) {
+       if ((nr_frags+1) > priv->num_txbdfree) {
                /* no space, stop the queue */
                netif_stop_queue(dev);
                dev->stats.tx_fifo_errors++;
index 5e070f44663504b7207e19caeb7fdd2a91621acb..0486cbe01adbc6195dcd8c4d186227f0cc4406d8 100644 (file)
@@ -467,7 +467,7 @@ init_module(void)
                        if (this_dev != 0) break; /* only autoprobe 1st one */
                        printk(KERN_NOTICE "hp-plus.c: Presently autoprobing (not recommended) for a single card.\n");
                }
-               dev = alloc_ei_netdev();
+               dev = alloc_eip_netdev();
                if (!dev)
                        break;
                dev->irq = irq[this_dev];
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 9f33e442f40339f0d4d862c05c7be39f29502694..13087782ac4068425c78d870022d2c872a5b0d66 100644 (file)
@@ -588,7 +588,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                adapter->pci_mem_read = netxen_nic_pci_mem_read_2M;
                adapter->pci_mem_write = netxen_nic_pci_mem_write_2M;
 
-               mem_ptr0 = ioremap(mem_base, mem_len);
+               mem_ptr0 = pci_ioremap_bar(pdev, 0);
+               if (mem_ptr0 == NULL) {
+                       dev_err(&pdev->dev, "failed to map PCI bar 0\n");
+                       return -EIO;
+               }
+
                pci_len0 = mem_len;
                first_page_group_start = 0;
                first_page_group_end   = 0;
@@ -795,9 +800,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * See if the firmware gave us a virtual-physical port mapping.
         */
        adapter->physical_port = adapter->portnum;
-       i = adapter->pci_read_normalize(adapter, CRB_V2P(adapter->portnum));
-       if (i != 0x55555555)
-               adapter->physical_port = i;
+       if (adapter->fw_major < 4) {
+               i = adapter->pci_read_normalize(adapter,
+                               CRB_V2P(adapter->portnum));
+               if (i != 0x55555555)
+                       adapter->physical_port = i;
+       }
 
        adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED);
 
index 0771eb6fc6eb452cbf9e0a06793b9f7d0ba32e4d..b3473401c83a3dd0257f006683a831a791c8b1c4 100644 (file)
@@ -81,9 +81,9 @@ static const int multicast_filter_limit = 32;
 #define RTL8169_TX_TIMEOUT     (6*HZ)
 #define RTL8169_PHY_TIMEOUT    (10*HZ)
 
-#define RTL_EEPROM_SIG         cpu_to_le32(0x8129)
-#define RTL_EEPROM_SIG_MASK    cpu_to_le32(0xffff)
+#define RTL_EEPROM_SIG         0x8129
 #define RTL_EEPROM_SIG_ADDR    0x0000
+#define RTL_EEPROM_MAC_ADDR    0x0007
 
 /* write/read MMIO register */
 #define RTL_W8(reg, val8)      writeb ((val8), ioaddr + (reg))
@@ -293,6 +293,11 @@ enum rtl_register_content {
        /* Cfg9346Bits */
        Cfg9346_Lock    = 0x00,
        Cfg9346_Unlock  = 0xc0,
+       Cfg9346_Program = 0x80,         /* Programming mode */
+       Cfg9346_EECS    = 0x08,         /* Chip select */
+       Cfg9346_EESK    = 0x04,         /* Serial data clock */
+       Cfg9346_EEDI    = 0x02,         /* Data input */
+       Cfg9346_EEDO    = 0x01,         /* Data output */
 
        /* rx_mode_bits */
        AcceptErr       = 0x20,
@@ -305,6 +310,7 @@ enum rtl_register_content {
        /* RxConfigBits */
        RxCfgFIFOShift  = 13,
        RxCfgDMAShift   =  8,
+       RxCfg9356SEL    =  6,           /* EEPROM type: 0 = 9346, 1 = 9356 */
 
        /* TxConfigBits */
        TxInterFrameGapShift = 24,
@@ -1963,6 +1969,108 @@ static const struct net_device_ops rtl8169_netdev_ops = {
 
 };
 
+/* Delay between EEPROM clock transitions. Force out buffered PCI writes. */
+#define RTL_EEPROM_DELAY()     RTL_R8(Cfg9346)
+#define RTL_EEPROM_READ_CMD    6
+
+/* read 16bit word stored in EEPROM. EEPROM is addressed by words. */
+static u16 rtl_eeprom_read(void __iomem *ioaddr, int addr)
+{
+       u16 result = 0;
+       int cmd, cmd_len, i;
+
+       /* check for EEPROM address size (in bits) */
+       if (RTL_R32(RxConfig) & (1 << RxCfg9356SEL)) {
+               /* EEPROM is 93C56 */
+               cmd_len = 3 + 8; /* 3 bits for command id and 8 for address */
+               cmd = (RTL_EEPROM_READ_CMD << 8) | (addr & 0xff);
+       } else {
+               /* EEPROM is 93C46 */
+               cmd_len = 3 + 6; /* 3 bits for command id and 6 for address */
+               cmd = (RTL_EEPROM_READ_CMD << 6) | (addr & 0x3f);
+       }
+
+       /* enter programming mode */
+       RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS);
+       RTL_EEPROM_DELAY();
+
+       /* write command and requested address */
+       while (cmd_len--) {
+               u8 x = Cfg9346_Program | Cfg9346_EECS;
+
+               x |= (cmd & (1 << cmd_len)) ? Cfg9346_EEDI : 0;
+
+               /* write a bit */
+               RTL_W8(Cfg9346, x);
+               RTL_EEPROM_DELAY();
+
+               /* raise clock */
+               RTL_W8(Cfg9346, x | Cfg9346_EESK);
+               RTL_EEPROM_DELAY();
+       }
+
+       /* lower clock */
+       RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS);
+       RTL_EEPROM_DELAY();
+
+       /* read back 16bit value */
+       for (i = 16; i > 0; i--) {
+               /* raise clock */
+               RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS | Cfg9346_EESK);
+               RTL_EEPROM_DELAY();
+
+               result <<= 1;
+               result |= (RTL_R8(Cfg9346) & Cfg9346_EEDO) ? 1 : 0;
+
+               /* lower clock */
+               RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS);
+               RTL_EEPROM_DELAY();
+       }
+
+       RTL_W8(Cfg9346, Cfg9346_Program);
+       /* leave programming mode */
+       RTL_W8(Cfg9346, Cfg9346_Lock);
+
+       return result;
+}
+
+static void rtl_init_mac_address(struct rtl8169_private *tp,
+                                void __iomem *ioaddr)
+{
+       struct pci_dev *pdev = tp->pci_dev;
+       u16 x;
+       u8 mac[8];
+
+       /* read EEPROM signature */
+       x = rtl_eeprom_read(ioaddr, RTL_EEPROM_SIG_ADDR);
+
+       if (x != RTL_EEPROM_SIG) {
+               dev_info(&pdev->dev, "Missing EEPROM signature: %04x\n", x);
+               return;
+       }
+
+       /* read MAC address */
+       x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR);
+       mac[0] = x & 0xff;
+       mac[1] = x >> 8;
+       x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + 1);
+       mac[2] = x & 0xff;
+       mac[3] = x >> 8;
+       x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + 2);
+       mac[4] = x & 0xff;
+       mac[5] = x >> 8;
+
+       if (netif_msg_probe(tp)) {
+               DECLARE_MAC_BUF(buf);
+
+               dev_info(&pdev->dev, "MAC address found in EEPROM: %s\n",
+                        print_mac(buf, mac));
+       }
+
+       if (is_valid_ether_addr(mac))
+               rtl_rar_set(tp, mac);
+}
+
 static int __devinit
 rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -2141,6 +2249,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        tp->mmio_addr = ioaddr;
 
+       rtl_init_mac_address(tp, ioaddr);
+
        /* Get MAC address */
        for (i = 0; i < MAC_ADDR_LEN; i++)
                dev->dev_addr[i] = RTL_R8(MAC0 + i);
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 e009481c606c740cea0b2a30fd7bad7f30f3fe8d..396f821b5ff00cdd11bc5033b709b3c6ba06d131 100644 (file)
@@ -1451,6 +1451,14 @@ static const struct usb_device_id        products [] = {
        // Cables-to-Go USB Ethernet Adapter
        USB_DEVICE(0x0b95, 0x772a),
        .driver_info = (unsigned long) &ax88772_info,
+}, {
+       // ABOCOM for pci
+       USB_DEVICE(0x14ea, 0xab11),
+       .driver_info = (unsigned long) &ax88178_info,
+}, {
+       // ASIX 88772a
+       USB_DEVICE(0x0db0, 0xa877),
+       .driver_info = (unsigned long) &ax88772_info,
 },
        { },            // END
 };
index 0e061dfea78d15226e65da13e5aa1f764c09bd30..55e8ecc3a9e5d5bd6eb88038530ccada469bb2c6 100644 (file)
@@ -559,6 +559,11 @@ static const struct usb_device_id  products [] = {
        USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
                        USB_CDC_PROTO_NONE),
        .driver_info = (unsigned long) &cdc_info,
+}, {
+       /* Ericsson F3507g */
+       USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1900, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+       .driver_info = (unsigned long) &cdc_info,
 },
        { },            // END
 };
index aa31490788880bb3b609acae0a9ab7332cce28c7..c32284ff3f54a698018021603e4ccbd92f7777a3 100644 (file)
@@ -723,8 +723,8 @@ u32 usbnet_get_link (struct net_device *net)
        if (dev->mii.mdio_read)
                return mii_link_ok(&dev->mii);
 
-       /* Otherwise, say we're up (to avoid breaking scripts) */
-       return 1;
+       /* Otherwise, dtrt for drivers calling netif_carrier_{on,off} */
+       return ethtool_op_get_link(net);
 }
 EXPORT_SYMBOL_GPL(usbnet_get_link);
 
index e24f7b3ace4bd470fcfbf65dffc69bf2df20f383..04882c8f9bf18dfd547802704c72012f18e57761 100644 (file)
@@ -341,6 +341,11 @@ static const struct usb_device_id  products [] = {
        USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM,
                        USB_CDC_PROTO_NONE),
        .driver_info = (unsigned long) &bogus_mdlm_info,
+}, {
+       /* Motorola MOTOMAGX phones */
+       USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+       .driver_info = (unsigned long) &bogus_mdlm_info,
 },
 
 /* Olympus has some models with a Zaurus-compatible option.
index 852d0e7c4e62abbfb13421664293dd70182c4126..124fe75b8a8a964928092b3d42c397fa847ac943 100644 (file)
@@ -239,6 +239,16 @@ static int veth_open(struct net_device *dev)
        return 0;
 }
 
+static int veth_close(struct net_device *dev)
+{
+       struct veth_priv *priv = netdev_priv(dev);
+
+       netif_carrier_off(dev);
+       netif_carrier_off(priv->peer);
+
+       return 0;
+}
+
 static int veth_dev_init(struct net_device *dev)
 {
        struct veth_net_stats *stats;
@@ -263,10 +273,12 @@ 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_stop            = veth_close,
+       .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)
@@ -279,44 +291,6 @@ static void veth_setup(struct net_device *dev)
        dev->destructor = veth_dev_free;
 }
 
-static void veth_change_state(struct net_device *dev)
-{
-       struct net_device *peer;
-       struct veth_priv *priv;
-
-       priv = netdev_priv(dev);
-       peer = priv->peer;
-
-       if (netif_carrier_ok(peer)) {
-               if (!netif_carrier_ok(dev))
-                       netif_carrier_on(dev);
-       } else {
-               if (netif_carrier_ok(dev))
-                       netif_carrier_off(dev);
-       }
-}
-
-static int veth_device_event(struct notifier_block *unused,
-                            unsigned long event, void *ptr)
-{
-       struct net_device *dev = ptr;
-
-       if (dev->netdev_ops->ndo_open != veth_open)
-               goto out;
-
-       switch (event) {
-       case NETDEV_CHANGE:
-               veth_change_state(dev);
-               break;
-       }
-out:
-       return NOTIFY_DONE;
-}
-
-static struct notifier_block veth_notifier_block __read_mostly = {
-       .notifier_call  = veth_device_event,
-};
-
 /*
  * netlink interface
  */
@@ -467,14 +441,12 @@ static struct rtnl_link_ops veth_link_ops = {
 
 static __init int veth_init(void)
 {
-       register_netdevice_notifier(&veth_notifier_block);
        return rtnl_link_register(&veth_link_ops);
 }
 
 static __exit void veth_exit(void)
 {
        rtnl_link_unregister(&veth_link_ops);
-       unregister_netdevice_notifier(&veth_notifier_block);
 }
 
 module_init(veth_init);
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 727f067aca4f8a764cbf9284c287b20ad96b73e4..0e80990d8e843b7420ff437963d967e6a054d7eb 100644 (file)
@@ -1538,6 +1538,7 @@ bad2:
 bad:
        if (ah)
                ath9k_hw_detach(ah);
+       ath9k_exit_debug(sc);
 
        return error;
 }
@@ -1545,7 +1546,7 @@ bad:
 static int ath_attach(u16 devid, struct ath_softc *sc)
 {
        struct ieee80211_hw *hw = sc->hw;
-       int error = 0;
+       int error = 0, i;
 
        DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n");
 
@@ -1589,11 +1590,11 @@ static int ath_attach(u16 devid, struct ath_softc *sc)
        /* initialize tx/rx engine */
        error = ath_tx_init(sc, ATH_TXBUF);
        if (error != 0)
-               goto detach;
+               goto error_attach;
 
        error = ath_rx_init(sc, ATH_RXBUF);
        if (error != 0)
-               goto detach;
+               goto error_attach;
 
 #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
        /* Initialze h/w Rfkill */
@@ -1601,8 +1602,9 @@ static int ath_attach(u16 devid, struct ath_softc *sc)
                INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll);
 
        /* Initialize s/w rfkill */
-       if (ath_init_sw_rfkill(sc))
-               goto detach;
+       error = ath_init_sw_rfkill(sc);
+       if (error)
+               goto error_attach;
 #endif
 
        error = ieee80211_register_hw(hw);
@@ -1611,8 +1613,16 @@ static int ath_attach(u16 devid, struct ath_softc *sc)
        ath_init_leds(sc);
 
        return 0;
-detach:
-       ath_detach(sc);
+
+error_attach:
+       /* cleanup tx queues */
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+               if (ATH_TXQ_SETUP(sc, i))
+                       ath_tx_cleanupq(sc, &sc->tx.txq[i]);
+
+       ath9k_hw_detach(sc->sc_ah);
+       ath9k_exit_debug(sc);
+
        return error;
 }
 
index b0ee86c6268501754651206d88b87fdcfceb2401..ab13ff22a8c0852c68d525d71299115615447bc0 100644 (file)
@@ -148,7 +148,7 @@ static void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
                pci_unmap_single(dev,
                                pci_unmap_addr(&txq->cmd[index]->meta, mapping),
                                pci_unmap_len(&txq->cmd[index]->meta, len),
-                               PCI_DMA_TODEVICE);
+                               PCI_DMA_BIDIRECTIONAL);
 
        /* Unmap chunks, if any. */
        for (i = 1; i < num_tbs; i++) {
@@ -964,7 +964,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
         * within command buffer array. */
        txcmd_phys = pci_map_single(priv->pci_dev,
                                    out_cmd, sizeof(struct iwl_cmd),
-                                   PCI_DMA_TODEVICE);
+                                   PCI_DMA_BIDIRECTIONAL);
        pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
        pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd));
        /* Add buffer containing Tx command and MAC(!) header to TFD's
@@ -1115,7 +1115,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
                        IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd);
 
        phys_addr = pci_map_single(priv->pci_dev, out_cmd,
-                                  len, PCI_DMA_TODEVICE);
+                                  len, PCI_DMA_BIDIRECTIONAL);
        pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr);
        pci_unmap_len_set(&out_cmd->meta, len, len);
        phys_addr += offsetof(struct iwl_cmd, hdr);
@@ -1212,7 +1212,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
        pci_unmap_single(priv->pci_dev,
                pci_unmap_addr(&txq->cmd[cmd_idx]->meta, mapping),
                pci_unmap_len(&txq->cmd[cmd_idx]->meta, len),
-               PCI_DMA_TODEVICE);
+               PCI_DMA_BIDIRECTIONAL);
 
        for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
             q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
index 61d2f50470c8e82f76e031cc82011846689f4723..b118a35ec605dd36dafbb27968dacefec444a62d 100644 (file)
@@ -23,7 +23,7 @@ static const char * mesh_stat_strings[]= {
 static void lbs_ethtool_get_drvinfo(struct net_device *dev,
                                         struct ethtool_drvinfo *info)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        snprintf(info->fw_version, 32, "%u.%u.%u.p%u",
                priv->fwrelease >> 24 & 0xff,
@@ -47,7 +47,7 @@ static int lbs_ethtool_get_eeprom_len(struct net_device *dev)
 static int lbs_ethtool_get_eeprom(struct net_device *dev,
                                   struct ethtool_eeprom *eeprom, u8 * bytes)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        struct cmd_ds_802_11_eeprom_access cmd;
        int ret;
 
@@ -76,7 +76,7 @@ out:
 static void lbs_ethtool_get_stats(struct net_device *dev,
                                  struct ethtool_stats *stats, uint64_t *data)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        struct cmd_ds_mesh_access mesh_access;
        int ret;
 
@@ -113,7 +113,7 @@ static void lbs_ethtool_get_stats(struct net_device *dev,
 
 static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        if (sset == ETH_SS_STATS && dev == priv->mesh_dev)
                return MESH_STATS_NUM;
@@ -143,7 +143,7 @@ static void lbs_ethtool_get_strings(struct net_device *dev,
 static void lbs_ethtool_get_wol(struct net_device *dev,
                                struct ethtool_wolinfo *wol)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        if (priv->wol_criteria == 0xffffffff) {
                /* Interface driver didn't configure wake */
@@ -166,7 +166,7 @@ static void lbs_ethtool_get_wol(struct net_device *dev,
 static int lbs_ethtool_set_wol(struct net_device *dev,
                               struct ethtool_wolinfo *wol)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        uint32_t criteria = 0;
 
        if (priv->wol_criteria == 0xffffffff && wol->wolopts)
index 2fc637ad85c741b84b94ba1a7f230f30077a4b8a..ea3dc038be76e3c88d89abb9e75328b993501b77 100644 (file)
@@ -59,7 +59,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp);
 static ssize_t if_usb_firmware_set(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        struct if_usb_card *cardp = priv->card;
        char fwname[FIRMWARE_NAME_MAX];
        int ret;
@@ -86,7 +86,7 @@ static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set);
 static ssize_t if_usb_boot2_set(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        struct if_usb_card *cardp = priv->card;
        char fwname[FIRMWARE_NAME_MAX];
        int ret;
index 4e0007d200308d72741d5580eb0396684e636524..f76623e0ff9a55106c7a62855f21721a10dd4a8a 100644 (file)
@@ -222,7 +222,7 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
 static ssize_t lbs_anycast_get(struct device *dev,
                struct device_attribute *attr, char * buf)
 {
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        struct cmd_ds_mesh_access mesh_access;
        int ret;
 
@@ -241,7 +241,7 @@ static ssize_t lbs_anycast_get(struct device *dev,
 static ssize_t lbs_anycast_set(struct device *dev,
                struct device_attribute *attr, const char * buf, size_t count)
 {
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        struct cmd_ds_mesh_access mesh_access;
        uint32_t datum;
        int ret;
@@ -263,7 +263,7 @@ static ssize_t lbs_anycast_set(struct device *dev,
 static ssize_t lbs_prb_rsp_limit_get(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        struct cmd_ds_mesh_access mesh_access;
        int ret;
        u32 retry_limit;
@@ -286,7 +286,7 @@ static ssize_t lbs_prb_rsp_limit_get(struct device *dev,
 static ssize_t lbs_prb_rsp_limit_set(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        struct cmd_ds_mesh_access mesh_access;
        int ret;
        unsigned long retry_limit;
@@ -321,7 +321,7 @@ static void lbs_remove_mesh(struct lbs_private *priv);
 static ssize_t lbs_rtap_get(struct device *dev,
                struct device_attribute *attr, char * buf)
 {
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        return snprintf(buf, 5, "0x%X\n", priv->monitormode);
 }
 
@@ -332,7 +332,7 @@ static ssize_t lbs_rtap_set(struct device *dev,
                struct device_attribute *attr, const char * buf, size_t count)
 {
        int monitor_mode;
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
 
        sscanf(buf, "%x", &monitor_mode);
        if (monitor_mode) {
@@ -383,7 +383,7 @@ static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set );
 static ssize_t lbs_mesh_get(struct device *dev,
                struct device_attribute *attr, char * buf)
 {
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
 }
 
@@ -393,7 +393,7 @@ static ssize_t lbs_mesh_get(struct device *dev,
 static ssize_t lbs_mesh_set(struct device *dev,
                struct device_attribute *attr, const char * buf, size_t count)
 {
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        int enable;
        int ret, action = CMD_ACT_MESH_CONFIG_STOP;
 
@@ -452,7 +452,7 @@ static struct attribute_group lbs_mesh_attr_group = {
  */
 static int lbs_dev_open(struct net_device *dev)
 {
-       struct lbs_private *priv = netdev_priv(dev) ;
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
 
        lbs_deb_enter(LBS_DEB_NET);
@@ -521,7 +521,7 @@ static int lbs_mesh_stop(struct net_device *dev)
  */
 static int lbs_eth_stop(struct net_device *dev)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_NET);
 
@@ -538,7 +538,7 @@ static int lbs_eth_stop(struct net_device *dev)
 
 static void lbs_tx_timeout(struct net_device *dev)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_TX);
 
@@ -590,7 +590,7 @@ EXPORT_SYMBOL_GPL(lbs_host_to_card_done);
  */
 static struct net_device_stats *lbs_get_stats(struct net_device *dev)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_NET);
        return &priv->stats;
@@ -599,7 +599,7 @@ static struct net_device_stats *lbs_get_stats(struct net_device *dev)
 static int lbs_set_mac_address(struct net_device *dev, void *addr)
 {
        int ret = 0;
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        struct sockaddr *phwaddr = addr;
        struct cmd_ds_802_11_mac_address cmd;
 
@@ -732,7 +732,7 @@ static void lbs_set_mcast_worker(struct work_struct *work)
 
 static void lbs_set_multicast_list(struct net_device *dev)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        schedule_work(&priv->mcast_work);
 }
@@ -748,7 +748,7 @@ static void lbs_set_multicast_list(struct net_device *dev)
 static int lbs_thread(void *data)
 {
        struct net_device *dev = data;
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        wait_queue_t wait;
 
        lbs_deb_enter(LBS_DEB_THREAD);
@@ -1184,6 +1184,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
                goto done;
        }
        priv = netdev_priv(dev);
+       dev->ml_priv = priv;
 
        if (lbs_init_adapter(priv)) {
                lbs_pr_err("failed to initialize adapter structure.\n");
index d42b7a5a1b3f32a564579771e19149429348db5b..18fe29faf99b1cb1362a81c5f65fe0e1c47cc46c 100644 (file)
@@ -18,7 +18,7 @@
 static int mesh_get_default_parameters(struct device *dev,
                                       struct mrvl_mesh_defaults *defs)
 {
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        struct cmd_ds_mesh_config cmd;
        int ret;
 
@@ -57,7 +57,7 @@ static ssize_t bootflag_get(struct device *dev,
 static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr,
                            const char *buf, size_t count)
 {
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        struct cmd_ds_mesh_config cmd;
        uint32_t datum;
        int ret;
@@ -100,7 +100,7 @@ static ssize_t boottime_get(struct device *dev,
 static ssize_t boottime_set(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        struct cmd_ds_mesh_config cmd;
        uint32_t datum;
        int ret;
@@ -152,7 +152,7 @@ static ssize_t channel_get(struct device *dev,
 static ssize_t channel_set(struct device *dev, struct device_attribute *attr,
                           const char *buf, size_t count)
 {
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        struct cmd_ds_mesh_config cmd;
        uint32_t datum;
        int ret;
@@ -210,7 +210,7 @@ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr,
        struct cmd_ds_mesh_config cmd;
        struct mrvl_mesh_defaults defs;
        struct mrvl_meshie *ie;
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        int len;
        int ret;
 
@@ -269,7 +269,7 @@ static ssize_t protocol_id_set(struct device *dev,
        struct cmd_ds_mesh_config cmd;
        struct mrvl_mesh_defaults defs;
        struct mrvl_meshie *ie;
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        uint32_t datum;
        int ret;
 
@@ -323,7 +323,7 @@ static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr,
        struct cmd_ds_mesh_config cmd;
        struct mrvl_mesh_defaults defs;
        struct mrvl_meshie *ie;
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        uint32_t datum;
        int ret;
 
@@ -377,7 +377,7 @@ static ssize_t capability_set(struct device *dev, struct device_attribute *attr,
        struct cmd_ds_mesh_config cmd;
        struct mrvl_mesh_defaults defs;
        struct mrvl_meshie *ie;
-       struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+       struct lbs_private *priv = to_net_dev(dev)->ml_priv;
        uint32_t datum;
        int ret;
 
index 57f6c12cda2085a902a8fae4e1e950c138f34475..9014950f4328aa135835d74d3fb27ee19d9ac305 100644 (file)
@@ -945,7 +945,7 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
                 union iwreq_data *wrqu, char *extra)
 {
        DECLARE_SSID_BUF(ssid);
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
 
        lbs_deb_enter(LBS_DEB_WEXT);
@@ -1008,7 +1008,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
                 struct iw_point *dwrq, char *extra)
 {
 #define SCAN_ITEM_SIZE 128
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        int err = 0;
        char *ev = extra;
        char *stop = ev + dwrq->length;
index dac462641170e6193da4f04cfd44e39222520ba3..68bec31ae03bcfb6c0659e3fefdb3a110a7d886e 100644 (file)
@@ -60,7 +60,7 @@ static u32 convert_radiotap_rate_to_mv(u8 rate)
 int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        unsigned long flags;
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        struct txpd *txpd;
        char *p802x_hdr;
        uint16_t pkt_len;
index c6102e08179e6ba7d9fcc09d7fb8a26da721024b..f16d136ab4bb5555b2069fcdf151eedd0db47277 100644 (file)
@@ -163,7 +163,7 @@ static int lbs_get_name(struct net_device *dev, struct iw_request_info *info,
 static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
                         struct iw_freq *fwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        struct chan_freq_power *cfp;
 
        lbs_deb_enter(LBS_DEB_WEXT);
@@ -189,7 +189,7 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
 static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info,
                        struct sockaddr *awrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -207,7 +207,7 @@ static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info,
 static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info,
                         struct iw_point *dwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -231,7 +231,7 @@ static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info,
 static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info,
                         struct iw_point *dwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -248,7 +248,7 @@ static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info,
 static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
                         struct iw_point *dwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -273,7 +273,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
                        struct iw_param *vwrq, char *extra)
 {
        int ret = 0;
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        u32 val = vwrq->value;
 
        lbs_deb_enter(LBS_DEB_WEXT);
@@ -293,7 +293,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
 static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
                        struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
        u16 val = 0;
 
@@ -315,7 +315,7 @@ out:
 static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
                         struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
        u32 val = vwrq->value;
 
@@ -336,7 +336,7 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
 static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info,
                         struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
        u16 val = 0;
 
@@ -359,7 +359,7 @@ out:
 static int lbs_get_mode(struct net_device *dev,
                         struct iw_request_info *info, u32 * uwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -385,7 +385,7 @@ static int lbs_get_txpow(struct net_device *dev,
                          struct iw_request_info *info,
                          struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        s16 curlevel = 0;
        int ret = 0;
 
@@ -418,7 +418,7 @@ out:
 static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info,
                          struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
        u16 slimit = 0, llimit = 0;
 
@@ -466,7 +466,7 @@ out:
 static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info,
                          struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
        u16 val = 0;
 
@@ -542,7 +542,7 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
                          struct iw_point *dwrq, char *extra)
 {
        int i, j;
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        struct iw_range *range = (struct iw_range *)extra;
        struct chan_freq_power *cfp;
        u8 rates[MAX_RATES + 1];
@@ -708,7 +708,7 @@ out:
 static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
                          struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -758,7 +758,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
 static int lbs_get_power(struct net_device *dev, struct iw_request_info *info,
                          struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -781,7 +781,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
                EXCELLENT = 95,
                PERFECT = 100
        };
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        u32 rssi_qual;
        u32 tx_qual;
        u32 quality = 0;
@@ -886,7 +886,7 @@ static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info,
                  struct iw_freq *fwrq, char *extra)
 {
        int ret = -EINVAL;
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        struct chan_freq_power *cfp;
        struct assoc_request * assoc_req;
 
@@ -943,7 +943,7 @@ static int lbs_mesh_set_freq(struct net_device *dev,
                             struct iw_request_info *info,
                             struct iw_freq *fwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        struct chan_freq_power *cfp;
        int ret = -EINVAL;
 
@@ -994,7 +994,7 @@ out:
 static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
                  struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        u8 new_rate = 0;
        int ret = -EINVAL;
        u8 rates[MAX_RATES + 1];
@@ -1054,7 +1054,7 @@ out:
 static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info,
                  struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -1079,7 +1079,7 @@ static int lbs_set_mode(struct net_device *dev,
                  struct iw_request_info *info, u32 * uwrq, char *extra)
 {
        int ret = 0;
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        struct assoc_request * assoc_req;
 
        lbs_deb_enter(LBS_DEB_WEXT);
@@ -1124,7 +1124,7 @@ static int lbs_get_encode(struct net_device *dev,
                           struct iw_request_info *info,
                           struct iw_point *dwrq, u8 * extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 
        lbs_deb_enter(LBS_DEB_WEXT);
@@ -1319,7 +1319,7 @@ static int lbs_set_encode(struct net_device *dev,
                    struct iw_point *dwrq, char *extra)
 {
        int ret = 0;
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        struct assoc_request * assoc_req;
        u16 is_default = 0, index = 0, set_tx_key = 0;
 
@@ -1395,7 +1395,7 @@ static int lbs_get_encodeext(struct net_device *dev,
                              char *extra)
 {
        int ret = -EINVAL;
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
        int index, max_key_len;
 
@@ -1501,7 +1501,7 @@ static int lbs_set_encodeext(struct net_device *dev,
                              char *extra)
 {
        int ret = 0;
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
        int alg = ext->alg;
        struct assoc_request * assoc_req;
@@ -1639,7 +1639,7 @@ static int lbs_set_genie(struct net_device *dev,
                          struct iw_point *dwrq,
                          char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
        struct assoc_request * assoc_req;
 
@@ -1685,7 +1685,7 @@ static int lbs_get_genie(struct net_device *dev,
                          char *extra)
 {
        int ret = 0;
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -1713,7 +1713,7 @@ static int lbs_set_auth(struct net_device *dev,
                         struct iw_param *dwrq,
                         char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        struct assoc_request * assoc_req;
        int ret = 0;
        int updated = 0;
@@ -1816,7 +1816,7 @@ static int lbs_get_auth(struct net_device *dev,
                         char *extra)
 {
        int ret = 0;
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -1857,7 +1857,7 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
                   struct iw_param *vwrq, char *extra)
 {
        int ret = 0;
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        s16 dbm = (s16) vwrq->value;
 
        lbs_deb_enter(LBS_DEB_WEXT);
@@ -1936,7 +1936,7 @@ out:
 static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info,
                   struct iw_point *dwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -1971,7 +1971,7 @@ static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info,
 static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
                   struct iw_point *dwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
        u8 ssid[IW_ESSID_MAX_SIZE];
        u8 ssid_len = 0;
@@ -2040,7 +2040,7 @@ static int lbs_mesh_get_essid(struct net_device *dev,
                              struct iw_request_info *info,
                              struct iw_point *dwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -2058,7 +2058,7 @@ static int lbs_mesh_set_essid(struct net_device *dev,
                              struct iw_request_info *info,
                              struct iw_point *dwrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
 
        lbs_deb_enter(LBS_DEB_WEXT);
@@ -2102,7 +2102,7 @@ static int lbs_mesh_set_essid(struct net_device *dev,
 static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
                 struct sockaddr *awrq, char *extra)
 {
-       struct lbs_private *priv = netdev_priv(dev);
+       struct lbs_private *priv = dev->ml_priv;
        struct assoc_request * assoc_req;
        int ret = 0;
 
index 45a04faa7818e7ead799eeee65030bd08ede0592..067d1a9c728b47e3755398c1a2809d7279eefd59 100644 (file)
@@ -3157,8 +3157,20 @@ static int orinoco_pm_notifier(struct notifier_block *notifier,
 
        return NOTIFY_DONE;
 }
+
+static void orinoco_register_pm_notifier(struct orinoco_private *priv)
+{
+       priv->pm_notifier.notifier_call = orinoco_pm_notifier;
+       register_pm_notifier(&priv->pm_notifier);
+}
+
+static void orinoco_unregister_pm_notifier(struct orinoco_private *priv)
+{
+       unregister_pm_notifier(&priv->pm_notifier);
+}
 #else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */
-#define orinoco_pm_notifier NULL
+#define orinoco_register_pm_notifier(priv) do { } while(0)
+#define orinoco_unregister_pm_notifier(priv) do { } while(0)
 #endif
 
 /********************************************************************/
@@ -3648,8 +3660,7 @@ struct net_device
        priv->cached_fw = NULL;
 
        /* Register PM notifiers */
-       priv->pm_notifier.notifier_call = orinoco_pm_notifier;
-       register_pm_notifier(&priv->pm_notifier);
+       orinoco_register_pm_notifier(priv);
 
        return dev;
 }
@@ -3673,7 +3684,7 @@ void free_orinocodev(struct net_device *dev)
                kfree(rx_data);
        }
 
-       unregister_pm_notifier(&priv->pm_notifier);
+       orinoco_unregister_pm_notifier(priv);
        orinoco_uncache_fw(priv);
 
        priv->wpa_ie_len = 0;
index 22bc07ef2f3784f70d3588d0a481993dde08a9b8..f4747a1134ba97420e8a0525964449efba6b5a2b 100644 (file)
@@ -48,6 +48,10 @@ static struct usb_device_id rtl8187_table[] __devinitdata = {
        {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B},
        {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B},
        {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B},
+       /* Surecom */
+       {USB_DEVICE(0x0769, 0x11F2), .driver_info = DEVICE_RTL8187},
+       /* Logitech */
+       {USB_DEVICE(0x0789, 0x010C), .driver_info = DEVICE_RTL8187},
        /* Netgear */
        {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187},
        {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187},
@@ -57,8 +61,16 @@ static struct usb_device_id rtl8187_table[] __devinitdata = {
        /* Sitecom */
        {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187},
        {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B},
+       /* Sphairon Access Systems GmbH */
+       {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187},
+       /* Dick Smith Electronics */
+       {USB_DEVICE(0x1371, 0x9401), .driver_info = DEVICE_RTL8187},
        /* Abocom */
        {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187},
+       /* Qcom */
+       {USB_DEVICE(0x18E8, 0x6232), .driver_info = DEVICE_RTL8187},
+       /* AirLive */
+       {USB_DEVICE(0x1b75, 0x8187), .driver_info = DEVICE_RTL8187},
        {}
 };
 
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 f5a662a50acb12edea158dc114002cf1be33a418..26c536b51c5acd80d5f4915bb4980a666bed06b5 100644 (file)
@@ -330,6 +330,14 @@ parse_dmar_table(void)
        entry_header = (struct acpi_dmar_header *)(dmar + 1);
        while (((unsigned long)entry_header) <
                        (((unsigned long)dmar) + dmar_tbl->length)) {
+               /* Avoid looping forever on bad ACPI tables */
+               if (entry_header->length == 0) {
+                       printk(KERN_WARNING PREFIX
+                               "Invalid 0-length structure\n");
+                       ret = -EINVAL;
+                       break;
+               }
+
                dmar_table_print_dmar_entry(entry_header);
 
                switch (entry_header->type) {
@@ -491,7 +499,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
        int map_size;
        u32 ver;
        static int iommu_allocated = 0;
-       int agaw;
+       int agaw = 0;
 
        iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
        if (!iommu)
@@ -507,6 +515,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
        iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
        iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
 
+#ifdef CONFIG_DMAR
        agaw = iommu_calculate_agaw(iommu);
        if (agaw < 0) {
                printk(KERN_ERR
@@ -514,6 +523,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
                        iommu->seq_id);
                goto error;
        }
+#endif
        iommu->agaw = agaw;
 
        /* the registers might be more than one page */
@@ -571,19 +581,49 @@ static inline void reclaim_free_desc(struct q_inval *qi)
        }
 }
 
+static int qi_check_fault(struct intel_iommu *iommu, int index)
+{
+       u32 fault;
+       int head;
+       struct q_inval *qi = iommu->qi;
+       int wait_index = (index + 1) % QI_LENGTH;
+
+       fault = readl(iommu->reg + DMAR_FSTS_REG);
+
+       /*
+        * If IQE happens, the head points to the descriptor associated
+        * with the error. No new descriptors are fetched until the IQE
+        * is cleared.
+        */
+       if (fault & DMA_FSTS_IQE) {
+               head = readl(iommu->reg + DMAR_IQH_REG);
+               if ((head >> 4) == index) {
+                       memcpy(&qi->desc[index], &qi->desc[wait_index],
+                                       sizeof(struct qi_desc));
+                       __iommu_flush_cache(iommu, &qi->desc[index],
+                                       sizeof(struct qi_desc));
+                       writel(DMA_FSTS_IQE, iommu->reg + DMAR_FSTS_REG);
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
 /*
  * Submit the queued invalidation descriptor to the remapping
  * hardware unit and wait for its completion.
  */
-void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
+int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
 {
+       int rc = 0;
        struct q_inval *qi = iommu->qi;
        struct qi_desc *hw, wait_desc;
        int wait_index, index;
        unsigned long flags;
 
        if (!qi)
-               return;
+               return 0;
 
        hw = qi->desc;
 
@@ -601,7 +641,8 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
 
        hw[index] = *desc;
 
-       wait_desc.low = QI_IWD_STATUS_DATA(2) | QI_IWD_STATUS_WRITE | QI_IWD_TYPE;
+       wait_desc.low = QI_IWD_STATUS_DATA(QI_DONE) |
+                       QI_IWD_STATUS_WRITE | QI_IWD_TYPE;
        wait_desc.high = virt_to_phys(&qi->desc_status[wait_index]);
 
        hw[wait_index] = wait_desc;
@@ -612,13 +653,11 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
        qi->free_head = (qi->free_head + 2) % QI_LENGTH;
        qi->free_cnt -= 2;
 
-       spin_lock(&iommu->register_lock);
        /*
         * update the HW tail register indicating the presence of
         * new descriptors.
         */
        writel(qi->free_head << 4, iommu->reg + DMAR_IQT_REG);
-       spin_unlock(&iommu->register_lock);
 
        while (qi->desc_status[wait_index] != QI_DONE) {
                /*
@@ -628,15 +667,21 @@ void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
                 * a deadlock where the interrupt context can wait indefinitely
                 * for free slots in the queue.
                 */
+               rc = qi_check_fault(iommu, index);
+               if (rc)
+                       goto out;
+
                spin_unlock(&qi->q_lock);
                cpu_relax();
                spin_lock(&qi->q_lock);
        }
-
-       qi->desc_status[index] = QI_DONE;
+out:
+       qi->desc_status[index] = qi->desc_status[wait_index] = QI_DONE;
 
        reclaim_free_desc(qi);
        spin_unlock_irqrestore(&qi->q_lock, flags);
+
+       return rc;
 }
 
 /*
@@ -649,13 +694,13 @@ void qi_global_iec(struct intel_iommu *iommu)
        desc.low = QI_IEC_TYPE;
        desc.high = 0;
 
+       /* should never fail */
        qi_submit_sync(&desc, iommu);
 }
 
 int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm,
                     u64 type, int non_present_entry_flush)
 {
-
        struct qi_desc desc;
 
        if (non_present_entry_flush) {
@@ -669,10 +714,7 @@ int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm,
                        | QI_CC_GRAN(type) | QI_CC_TYPE;
        desc.high = 0;
 
-       qi_submit_sync(&desc, iommu);
-
-       return 0;
-
+       return qi_submit_sync(&desc, iommu);
 }
 
 int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
@@ -702,10 +744,7 @@ int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
        desc.high = QI_IOTLB_ADDR(addr) | QI_IOTLB_IH(ih)
                | QI_IOTLB_AM(size_order);
 
-       qi_submit_sync(&desc, iommu);
-
-       return 0;
-
+       return qi_submit_sync(&desc, iommu);
 }
 
 /*
index db85284ffb621a98d93252f8c6d6069aa43fb006..39ae37589fda7f6106d845148d1175b4a927b1df 100644 (file)
@@ -111,6 +111,7 @@ struct controller {
        int cmd_busy;
        unsigned int no_cmd_complete:1;
        unsigned int link_active_reporting:1;
+       unsigned int notification_enabled:1;
 };
 
 #define INT_BUTTON_IGNORE              0
@@ -170,6 +171,7 @@ extern int pciehp_configure_device(struct slot *p_slot);
 extern int pciehp_unconfigure_device(struct slot *p_slot);
 extern void pciehp_queue_pushbutton_work(struct work_struct *work);
 struct controller *pcie_init(struct pcie_device *dev);
+int pcie_init_notification(struct controller *ctrl);
 int pciehp_enable_slot(struct slot *p_slot);
 int pciehp_disable_slot(struct slot *p_slot);
 int pcie_enable_notification(struct controller *ctrl);
index c2485542f54356f01c016e83c082e96e3866b62c..681e3912b821a4dce3f5ee11844b73cf6e8b316d 100644 (file)
@@ -434,6 +434,13 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
                goto err_out_release_ctlr;
        }
 
+       /* Enable events after we have setup the data structures */
+       rc = pcie_init_notification(ctrl);
+       if (rc) {
+               ctrl_err(ctrl, "Notification initialization failed\n");
+               goto err_out_release_ctlr;
+       }
+
        /* Check if slot is occupied */
        t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
        t_slot->hpc_ops->get_adapter_status(t_slot, &value);
index 71a8012886b0f0705dcd6cfb27827720ce006cf4..7a16c6897bb92698abc8edfb9af1d909f235453d 100644 (file)
@@ -934,7 +934,7 @@ static void pcie_disable_notification(struct controller *ctrl)
                ctrl_warn(ctrl, "Cannot disable software notification\n");
 }
 
-static int pcie_init_notification(struct controller *ctrl)
+int pcie_init_notification(struct controller *ctrl)
 {
        if (pciehp_request_irq(ctrl))
                return -1;
@@ -942,13 +942,17 @@ static int pcie_init_notification(struct controller *ctrl)
                pciehp_free_irq(ctrl);
                return -1;
        }
+       ctrl->notification_enabled = 1;
        return 0;
 }
 
 static void pcie_shutdown_notification(struct controller *ctrl)
 {
-       pcie_disable_notification(ctrl);
-       pciehp_free_irq(ctrl);
+       if (ctrl->notification_enabled) {
+               pcie_disable_notification(ctrl);
+               pciehp_free_irq(ctrl);
+               ctrl->notification_enabled = 0;
+       }
 }
 
 static int pcie_init_slot(struct controller *ctrl)
@@ -1110,13 +1114,8 @@ struct controller *pcie_init(struct pcie_device *dev)
        if (pcie_init_slot(ctrl))
                goto abort_ctrl;
 
-       if (pcie_init_notification(ctrl))
-               goto abort_slot;
-
        return ctrl;
 
-abort_slot:
-       pcie_cleanup_slot(ctrl);
 abort_ctrl:
        kfree(ctrl);
 abort:
index f78371b2252976efb8ab86c7eaf87a7240949ea5..45effc5726c0f63a55862c85eaa6d9cb4a38c706 100644 (file)
@@ -207,7 +207,7 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
        return index;
 }
 
-static void qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
+static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
 {
        struct qi_desc desc;
 
@@ -215,7 +215,7 @@ static void qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
                   | QI_IEC_SELECTIVE;
        desc.high = 0;
 
-       qi_submit_sync(&desc, iommu);
+       return qi_submit_sync(&desc, iommu);
 }
 
 int map_irq_to_irte_handle(int irq, u16 *sub_handle)
@@ -283,6 +283,7 @@ int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
 
 int modify_irte(int irq, struct irte *irte_modified)
 {
+       int rc;
        int index;
        struct irte *irte;
        struct intel_iommu *iommu;
@@ -303,14 +304,15 @@ int modify_irte(int irq, struct irte *irte_modified)
        set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1));
        __iommu_flush_cache(iommu, irte, sizeof(*irte));
 
-       qi_flush_iec(iommu, index, 0);
-
+       rc = qi_flush_iec(iommu, index, 0);
        spin_unlock(&irq_2_ir_lock);
-       return 0;
+
+       return rc;
 }
 
 int flush_irte(int irq)
 {
+       int rc;
        int index;
        struct intel_iommu *iommu;
        struct irq_2_iommu *irq_iommu;
@@ -326,10 +328,10 @@ int flush_irte(int irq)
 
        index = irq_iommu->irte_index + irq_iommu->sub_handle;
 
-       qi_flush_iec(iommu, index, irq_iommu->irte_mask);
+       rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask);
        spin_unlock(&irq_2_ir_lock);
 
-       return 0;
+       return rc;
 }
 
 struct intel_iommu *map_ioapic_to_ir(int apic)
@@ -355,6 +357,7 @@ struct intel_iommu *map_dev_to_ir(struct pci_dev *dev)
 
 int free_irte(int irq)
 {
+       int rc = 0;
        int index, i;
        struct irte *irte;
        struct intel_iommu *iommu;
@@ -375,7 +378,7 @@ int free_irte(int irq)
        if (!irq_iommu->sub_handle) {
                for (i = 0; i < (1 << irq_iommu->irte_mask); i++)
                        set_64bit((unsigned long *)irte, 0);
-               qi_flush_iec(iommu, index, irq_iommu->irte_mask);
+               rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask);
        }
 
        irq_iommu->iommu = NULL;
@@ -385,7 +388,7 @@ int free_irte(int irq)
 
        spin_unlock(&irq_2_ir_lock);
 
-       return 0;
+       return rc;
 }
 
 static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
index aac7006949f15c9eb52b56968a4dca6ef812e3c2..d0c9736858689f62f19dc6fd85572dacc3c2d3ec 100644 (file)
@@ -108,6 +108,34 @@ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
 }
 #endif  /*  0  */
 
+
+static void set_device_error_reporting(struct pci_dev *dev, void *data)
+{
+       bool enable = *((bool *)data);
+
+       if (dev->pcie_type != PCIE_RC_PORT &&
+           dev->pcie_type != PCIE_SW_UPSTREAM_PORT &&
+           dev->pcie_type != PCIE_SW_DOWNSTREAM_PORT)
+               return;
+
+       if (enable)
+               pci_enable_pcie_error_reporting(dev);
+       else
+               pci_disable_pcie_error_reporting(dev);
+}
+
+/**
+ * set_downstream_devices_error_reporting - enable/disable the error reporting  bits on the root port and its downstream ports.
+ * @dev: pointer to root port's pci_dev data structure
+ * @enable: true = enable error reporting, false = disable error reporting.
+ */
+static void set_downstream_devices_error_reporting(struct pci_dev *dev,
+                                                  bool enable)
+{
+       set_device_error_reporting(dev, &enable);
+       pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
+}
+
 static int find_device_iter(struct device *device, void *data)
 {
        struct pci_dev *dev;
@@ -525,15 +553,11 @@ void aer_enable_rootport(struct aer_rpc *rpc)
        pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, &reg32);
        pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
 
-       /* Enable Root Port device reporting error itself */
-       pci_read_config_word(pdev, pos+PCI_EXP_DEVCTL, &reg16);
-       reg16 = reg16 |
-               PCI_EXP_DEVCTL_CERE |
-               PCI_EXP_DEVCTL_NFERE |
-               PCI_EXP_DEVCTL_FERE |
-               PCI_EXP_DEVCTL_URRE;
-       pci_write_config_word(pdev, pos+PCI_EXP_DEVCTL,
-               reg16);
+       /*
+        * Enable error reporting for the root port device and downstream port
+        * devices.
+        */
+       set_downstream_devices_error_reporting(pdev, true);
 
        /* Enable Root Port's interrupt in response to error messages */
        pci_write_config_dword(pdev,
@@ -553,6 +577,12 @@ static void disable_root_aer(struct aer_rpc *rpc)
        u32 reg32;
        int pos;
 
+       /*
+        * Disable error reporting for the root port device and downstream port
+        * devices.
+        */
+       set_downstream_devices_error_reporting(pdev, false);
+
        pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
        /* Disable Root's interrupt in response to error messages */
        pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, 0);
index f9b874eaeb9f80daea9f7eff884574cf7f749008..248b4db915526e5819c7050737f4467456aeda9f 100644 (file)
@@ -97,8 +97,6 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
 
        pcie_portdrv_save_config(dev);
 
-       pci_enable_pcie_error_reporting(dev);
-
        return 0;
 }
 
index baad093aafe3c75088c6a1f19d28d826dd5a63de..f20d55368edb7edfb5d0a6bc9ef1a8746da6b8cb 100644 (file)
@@ -1584,6 +1584,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SERVERWORKS,   PCI_DEVICE_ID_SERVERWORKS_
  */
 #define AMD_813X_MISC                  0x40
 #define AMD_813X_NOIOAMODE             (1<<0)
+#define AMD_813X_REV_B2                        0x13
 
 static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev)
 {
@@ -1591,6 +1592,8 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev)
 
        if (noioapicquirk)
                return;
+       if (dev->revision == AMD_813X_REV_B2)
+               return;
 
        pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword);
        pci_config_dword &= ~AMD_813X_NOIOAMODE;
@@ -1981,7 +1984,6 @@ static void __devinit quirk_msi_ht_cap(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE,
                        quirk_msi_ht_cap);
 
-
 /* The nVidia CK804 chipset may have 2 HT MSI mappings.
  * MSI are supported if the MSI capability set in any of these mappings.
  */
@@ -2032,6 +2034,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS,
                         PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB,
                         ht_enable_msi_mapping);
 
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE,
+                        ht_enable_msi_mapping);
+
 /* The P5N32-SLI Premium motherboard from Asus has a problem with msi
  * for the MCP55 NIC. It is not yet determined whether the msi problem
  * also affects other devices. As for now, turn off msi for this device.
@@ -2048,10 +2053,100 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
                        PCI_DEVICE_ID_NVIDIA_NVENET_15,
                        nvenet_msi_disable);
 
-static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev)
+static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev)
 {
        struct pci_dev *host_bridge;
+       int pos;
+       int i, dev_no;
+       int found = 0;
+
+       dev_no = dev->devfn >> 3;
+       for (i = dev_no; i >= 0; i--) {
+               host_bridge = pci_get_slot(dev->bus, PCI_DEVFN(i, 0));
+               if (!host_bridge)
+                       continue;
+
+               pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE);
+               if (pos != 0) {
+                       found = 1;
+                       break;
+               }
+               pci_dev_put(host_bridge);
+       }
+
+       if (!found)
+               return;
+
+       /* root did that ! */
+       if (msi_ht_cap_enabled(host_bridge))
+               goto out;
+
+       ht_enable_msi_mapping(dev);
+
+out:
+       pci_dev_put(host_bridge);
+}
+
+static void __devinit ht_disable_msi_mapping(struct pci_dev *dev)
+{
+       int pos, ttl = 48;
+
+       pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
+       while (pos && ttl--) {
+               u8 flags;
+
+               if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
+                                        &flags) == 0) {
+                       dev_info(&dev->dev, "Enabling HT MSI Mapping\n");
+
+                       pci_write_config_byte(dev, pos + HT_MSI_FLAGS,
+                                             flags & ~HT_MSI_FLAGS_ENABLE);
+               }
+               pos = pci_find_next_ht_capability(dev, pos,
+                                                 HT_CAPTYPE_MSI_MAPPING);
+       }
+}
+
+static int __devinit ht_check_msi_mapping(struct pci_dev *dev)
+{
        int pos, ttl = 48;
+       int found = 0;
+
+       /* check if there is HT MSI cap or enabled on this device */
+       pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
+       while (pos && ttl--) {
+               u8 flags;
+
+               if (found < 1)
+                       found = 1;
+               if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
+                                        &flags) == 0) {
+                       if (flags & HT_MSI_FLAGS_ENABLE) {
+                               if (found < 2) {
+                                       found = 2;
+                                       break;
+                               }
+                       }
+               }
+               pos = pci_find_next_ht_capability(dev, pos,
+                                                 HT_CAPTYPE_MSI_MAPPING);
+       }
+
+       return found;
+}
+
+static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev)
+{
+       struct pci_dev *host_bridge;
+       int pos;
+       int found;
+
+       /* check if there is HT MSI cap or enabled on this device */
+       found = ht_check_msi_mapping(dev);
+
+       /* no HT MSI CAP */
+       if (found == 0)
+               return;
 
        /*
         * HT MSI mapping should be disabled on devices that are below
@@ -2067,24 +2162,19 @@ static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev)
        pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE);
        if (pos != 0) {
                /* Host bridge is to HT */
-               ht_enable_msi_mapping(dev);
+               if (found == 1) {
+                       /* it is not enabled, try to enable it */
+                       nv_ht_enable_msi_mapping(dev);
+               }
                return;
        }
 
-       /* Host bridge is not to HT, disable HT MSI mapping on this device */
-       pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
-       while (pos && ttl--) {
-               u8 flags;
+       /* HT MSI is not enabled */
+       if (found == 1)
+               return;
 
-               if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
-                                        &flags) == 0) {
-                       dev_info(&dev->dev, "Disabling HT MSI mapping");
-                       pci_write_config_byte(dev, pos + HT_MSI_FLAGS,
-                                             flags & ~HT_MSI_FLAGS_ENABLE);
-               }
-               pos = pci_find_next_ht_capability(dev, pos,
-                                                 HT_CAPTYPE_MSI_MAPPING);
-       }
+       /* Host bridge is not to HT, disable HT MSI mapping on this device */
+       ht_disable_msi_mapping(dev);
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk);
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 fde6e4c634e71878c79e4ae771781fc968663467..a7cf550b9cca0ba030f7b58a8c81ccc2ef954e41 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/list.h>
 #include <linux/netdevice.h>
 #include <linux/scatterlist.h>
+#include <linux/skbuff.h>
 #include <scsi/libiscsi_tcp.h>
 
 /* from cxgb3 LLD */
@@ -113,6 +114,26 @@ struct cxgb3i_endpoint {
        struct cxgb3i_conn *cconn;
 };
 
+/**
+ * struct cxgb3i_task_data - private iscsi task data
+ *
+ * @nr_frags:  # of coalesced page frags (from scsi sgl)
+ * @frags:     coalesced page frags (from scsi sgl)
+ * @skb:       tx pdu skb
+ * @offset:    data offset for the next pdu
+ * @count:     max. possible pdu payload
+ * @sgoffset:  offset to the first sg entry for a given offset
+ */
+#define MAX_PDU_FRAGS  ((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512)
+struct cxgb3i_task_data {
+       unsigned short nr_frags;
+       skb_frag_t frags[MAX_PDU_FRAGS];
+       struct sk_buff *skb;
+       unsigned int offset;
+       unsigned int count;
+       unsigned int sgoffset;
+};
+
 int cxgb3i_iscsi_init(void);
 void cxgb3i_iscsi_cleanup(void);
 
index 08f3a09d92330863fa692263ecd556b0185285d3..a83d36e4926fc64b646e3d828f1a0d878304a66b 100644 (file)
@@ -639,10 +639,11 @@ static int ddp_init(struct t3cdev *tdev)
        write_unlock(&cxgb3i_ddp_rwlock);
 
        ddp_log_info("nppods %u (0x%x ~ 0x%x), bits %u, mask 0x%x,0x%x "
-                       "pkt %u,%u.\n",
+                       "pkt %u/%u, %u/%u.\n",
                        ppmax, ddp->llimit, ddp->ulimit, ddp->idx_bits,
                        ddp->idx_mask, ddp->rsvd_tag_mask,
-                       ddp->max_txsz, ddp->max_rxsz);
+                       ddp->max_txsz, uinfo.max_txsz,
+                       ddp->max_rxsz, uinfo.max_rxsz);
        return 0;
 
 free_ddp_map:
@@ -654,8 +655,8 @@ free_ddp_map:
  * cxgb3i_adapter_ddp_init - initialize the adapter's ddp resource
  * @tdev: t3cdev adapter
  * @tformat: tag format
- * @txsz: max tx pkt size, filled in by this func.
- * @rxsz: max rx pkt size, filled in by this func.
+ * @txsz: max tx pdu payload size, filled in by this func.
+ * @rxsz: max rx pdu payload size, filled in by this func.
  * initialize the ddp pagepod manager for a given adapter if needed and
  * setup the tag format for a given iscsi entity
  */
@@ -685,10 +686,12 @@ int cxgb3i_adapter_ddp_init(struct t3cdev *tdev,
                      tformat->sw_bits, tformat->rsvd_bits,
                      tformat->rsvd_shift, tformat->rsvd_mask);
 
-       *txsz = ddp->max_txsz;
-       *rxsz = ddp->max_rxsz;
-       ddp_log_info("ddp max pkt size: %u, %u.\n",
-                    ddp->max_txsz, ddp->max_rxsz);
+       *txsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
+                       ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN);
+       *rxsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
+                       ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN);
+       ddp_log_info("max payload size: %u/%u, %u/%u.\n",
+                    *txsz, ddp->max_txsz, *rxsz, ddp->max_rxsz);
        return 0;
 }
 EXPORT_SYMBOL_GPL(cxgb3i_adapter_ddp_init);
index 5c7c4d95c493c044141a38281e3a06b98f09464f..3faae7831c838a97693e6f91d4fe77460c9f7b5b 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef __CXGB3I_ULP2_DDP_H__
 #define __CXGB3I_ULP2_DDP_H__
 
+#include <linux/vmalloc.h>
+
 /**
  * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity
  *
@@ -85,8 +87,9 @@ struct cxgb3i_ddp_info {
        struct sk_buff **gl_skb;
 };
 
+#define ISCSI_PDU_NONPAYLOAD_LEN       312 /* bhs(48) + ahs(256) + digest(8) */
 #define ULP2_MAX_PKT_SIZE      16224
-#define ULP2_MAX_PDU_PAYLOAD   (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_MAX)
+#define ULP2_MAX_PDU_PAYLOAD   (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN)
 #define PPOD_PAGES_MAX         4
 #define PPOD_PAGES_SHIFT       2       /* 4 pages per pod */
 
index 091ecb4d9f3d8c8febaed68af246c69b2e486768..1ce9f244e46c53d9725cb9d953b0b8169e1470fe 100644 (file)
@@ -12,8 +12,8 @@
 #include "cxgb3i.h"
 
 #define DRV_MODULE_NAME         "cxgb3i"
-#define DRV_MODULE_VERSION     "1.0.0"
-#define DRV_MODULE_RELDATE     "Jun. 1, 2008"
+#define DRV_MODULE_VERSION     "1.0.1"
+#define DRV_MODULE_RELDATE     "Jan. 2009"
 
 static char version[] =
        "Chelsio S3xx iSCSI Driver " DRV_MODULE_NAME
index d83464b9b3f9c66c23fc9dd379626287e835cfdb..fa2a44f37b361e657a6d37bb452c90b6e461200c 100644 (file)
@@ -364,7 +364,8 @@ cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth,
 
        cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost,
                                          cmds_max,
-                                         sizeof(struct iscsi_tcp_task),
+                                         sizeof(struct iscsi_tcp_task) +
+                                         sizeof(struct cxgb3i_task_data),
                                          initial_cmdsn, ISCSI_MAX_TARGET);
        if (!cls_session)
                return NULL;
@@ -402,17 +403,15 @@ static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn *conn)
 {
        struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
        struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-       unsigned int max = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
-                                cconn->hba->snic->tx_max_size -
-                                ISCSI_PDU_NONPAYLOAD_MAX);
+       unsigned int max = max(512 * MAX_SKB_FRAGS, SKB_TX_HEADROOM);
 
+       max = min(cconn->hba->snic->tx_max_size, max);
        if (conn->max_xmit_dlength)
-               conn->max_xmit_dlength = min_t(unsigned int,
-                                               conn->max_xmit_dlength, max);
+               conn->max_xmit_dlength = min(conn->max_xmit_dlength, max);
        else
                conn->max_xmit_dlength = max;
        align_pdu_size(conn->max_xmit_dlength);
-       cxgb3i_log_info("conn 0x%p, max xmit %u.\n",
+       cxgb3i_api_debug("conn 0x%p, max xmit %u.\n",
                         conn, conn->max_xmit_dlength);
        return 0;
 }
@@ -427,9 +426,7 @@ static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn)
 {
        struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
        struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-       unsigned int max = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
-                                cconn->hba->snic->rx_max_size -
-                                ISCSI_PDU_NONPAYLOAD_MAX);
+       unsigned int max = cconn->hba->snic->rx_max_size;
 
        align_pdu_size(max);
        if (conn->max_recv_dlength) {
@@ -439,8 +436,7 @@ static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn)
                                         conn->max_recv_dlength, max);
                        return -EINVAL;
                }
-               conn->max_recv_dlength = min_t(unsigned int,
-                                               conn->max_recv_dlength, max);
+               conn->max_recv_dlength = min(conn->max_recv_dlength, max);
                align_pdu_size(conn->max_recv_dlength);
        } else
                conn->max_recv_dlength = max;
@@ -844,7 +840,7 @@ static struct scsi_host_template cxgb3i_host_template = {
        .proc_name              = "cxgb3i",
        .queuecommand           = iscsi_queuecommand,
        .change_queue_depth     = iscsi_change_queue_depth,
-       .can_queue              = 128 * (ISCSI_DEF_XMIT_CMDS_MAX - 1),
+       .can_queue              = CXGB3I_SCSI_QDEPTH_DFLT - 1,
        .sg_tablesize           = SG_ALL,
        .max_sectors            = 0xFFFF,
        .cmd_per_lun            = ISCSI_DEF_CMD_PER_LUN,
index a865f1fefe8bfebbcbc2af1a391238acb840849d..de3b3b614cca7a92fff8e395be632d3a3eb6b2db 100644 (file)
 #include "cxgb3i_ddp.h"
 
 #ifdef __DEBUG_C3CN_CONN__
-#define c3cn_conn_debug         cxgb3i_log_info
+#define c3cn_conn_debug                cxgb3i_log_debug
 #else
 #define c3cn_conn_debug(fmt...)
 #endif
 
 #ifdef __DEBUG_C3CN_TX__
-#define c3cn_tx_debug         cxgb3i_log_debug
+#define c3cn_tx_debug          cxgb3i_log_debug
 #else
 #define c3cn_tx_debug(fmt...)
 #endif
 
 #ifdef __DEBUG_C3CN_RX__
-#define c3cn_rx_debug         cxgb3i_log_debug
+#define c3cn_rx_debug          cxgb3i_log_debug
 #else
 #define c3cn_rx_debug(fmt...)
 #endif
@@ -47,9 +47,9 @@ static int cxgb3_rcv_win = 256 * 1024;
 module_param(cxgb3_rcv_win, int, 0644);
 MODULE_PARM_DESC(cxgb3_rcv_win, "TCP receive window in bytes (default=256KB)");
 
-static int cxgb3_snd_win = 64 * 1024;
+static int cxgb3_snd_win = 128 * 1024;
 module_param(cxgb3_snd_win, int, 0644);
-MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=64KB)");
+MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=128KB)");
 
 static int cxgb3_rx_credit_thres = 10 * 1024;
 module_param(cxgb3_rx_credit_thres, int, 0644);
@@ -301,8 +301,8 @@ static void act_open_req_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
 static void skb_entail(struct s3_conn *c3cn, struct sk_buff *skb,
                       int flags)
 {
-       CXGB3_SKB_CB(skb)->seq = c3cn->write_seq;
-       CXGB3_SKB_CB(skb)->flags = flags;
+       skb_tcp_seq(skb) = c3cn->write_seq;
+       skb_flags(skb) = flags;
        __skb_queue_tail(&c3cn->write_queue, skb);
 }
 
@@ -457,12 +457,9 @@ static unsigned int wrlen __read_mostly;
  * The number of WRs needed for an skb depends on the number of fragments
  * in the skb and whether it has any payload in its main body.  This maps the
  * length of the gather list represented by an skb into the # of necessary WRs.
- *
- * The max. length of an skb is controlled by the max pdu size which is ~16K.
- * Also, assume the min. fragment length is the sector size (512), then add
- * extra fragment counts for iscsi bhs and payload padding.
+ * The extra two fragments are for iscsi bhs and payload padding.
  */
-#define SKB_WR_LIST_SIZE       (16384/512 + 3)
+#define SKB_WR_LIST_SIZE       (MAX_SKB_FRAGS + 2)
 static unsigned int skb_wrs[SKB_WR_LIST_SIZE] __read_mostly;
 
 static void s3_init_wr_tab(unsigned int wr_len)
@@ -485,7 +482,7 @@ static void s3_init_wr_tab(unsigned int wr_len)
 
 static inline void reset_wr_list(struct s3_conn *c3cn)
 {
-       c3cn->wr_pending_head = NULL;
+       c3cn->wr_pending_head = c3cn->wr_pending_tail = NULL;
 }
 
 /*
@@ -496,7 +493,7 @@ static inline void reset_wr_list(struct s3_conn *c3cn)
 static inline void enqueue_wr(struct s3_conn *c3cn,
                              struct sk_buff *skb)
 {
-       skb_wr_data(skb) = NULL;
+       skb_tx_wr_next(skb) = NULL;
 
        /*
         * We want to take an extra reference since both us and the driver
@@ -509,10 +506,22 @@ static inline void enqueue_wr(struct s3_conn *c3cn,
        if (!c3cn->wr_pending_head)
                c3cn->wr_pending_head = skb;
        else
-               skb_wr_data(skb) = skb;
+               skb_tx_wr_next(c3cn->wr_pending_tail) = skb;
        c3cn->wr_pending_tail = skb;
 }
 
+static int count_pending_wrs(struct s3_conn *c3cn)
+{
+       int n = 0;
+       const struct sk_buff *skb = c3cn->wr_pending_head;
+
+       while (skb) {
+               n += skb->csum;
+               skb = skb_tx_wr_next(skb);
+       }
+       return n;
+}
+
 static inline struct sk_buff *peek_wr(const struct s3_conn *c3cn)
 {
        return c3cn->wr_pending_head;
@@ -529,8 +538,8 @@ static inline struct sk_buff *dequeue_wr(struct s3_conn *c3cn)
 
        if (likely(skb)) {
                /* Don't bother clearing the tail */
-               c3cn->wr_pending_head = skb_wr_data(skb);
-               skb_wr_data(skb) = NULL;
+               c3cn->wr_pending_head = skb_tx_wr_next(skb);
+               skb_tx_wr_next(skb) = NULL;
        }
        return skb;
 }
@@ -543,13 +552,14 @@ static void purge_wr_queue(struct s3_conn *c3cn)
 }
 
 static inline void make_tx_data_wr(struct s3_conn *c3cn, struct sk_buff *skb,
-                                  int len)
+                                  int len, int req_completion)
 {
        struct tx_data_wr *req;
 
        skb_reset_transport_header(skb);
        req = (struct tx_data_wr *)__skb_push(skb, sizeof(*req));
-       req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA));
+       req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA) |
+                       (req_completion ? F_WR_COMPL : 0));
        req->wr_lo = htonl(V_WR_TID(c3cn->tid));
        req->sndseq = htonl(c3cn->snd_nxt);
        /* len includes the length of any HW ULP additions */
@@ -592,7 +602,7 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion)
 
        if (unlikely(c3cn->state == C3CN_STATE_CONNECTING ||
                     c3cn->state == C3CN_STATE_CLOSE_WAIT_1 ||
-                    c3cn->state == C3CN_STATE_ABORTING)) {
+                    c3cn->state >= C3CN_STATE_ABORTING)) {
                c3cn_tx_debug("c3cn 0x%p, in closing state %u.\n",
                              c3cn, c3cn->state);
                return 0;
@@ -615,7 +625,7 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion)
                if (c3cn->wr_avail < wrs_needed) {
                        c3cn_tx_debug("c3cn 0x%p, skb len %u/%u, frag %u, "
                                      "wr %d < %u.\n",
-                                     c3cn, skb->len, skb->datalen, frags,
+                                     c3cn, skb->len, skb->data_len, frags,
                                      wrs_needed, c3cn->wr_avail);
                        break;
                }
@@ -627,20 +637,24 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion)
                c3cn->wr_unacked += wrs_needed;
                enqueue_wr(c3cn, skb);
 
-               if (likely(CXGB3_SKB_CB(skb)->flags & C3CB_FLAG_NEED_HDR)) {
-                       len += ulp_extra_len(skb);
-                       make_tx_data_wr(c3cn, skb, len);
-                       c3cn->snd_nxt += len;
-                       if ((req_completion
-                            && c3cn->wr_unacked == wrs_needed)
-                           || (CXGB3_SKB_CB(skb)->flags & C3CB_FLAG_COMPL)
-                           || c3cn->wr_unacked >= c3cn->wr_max / 2) {
-                               struct work_request_hdr *wr = cplhdr(skb);
+               c3cn_tx_debug("c3cn 0x%p, enqueue, skb len %u/%u, frag %u, "
+                               "wr %d, left %u, unack %u.\n",
+                               c3cn, skb->len, skb->data_len, frags,
+                               wrs_needed, c3cn->wr_avail, c3cn->wr_unacked);
+
 
-                               wr->wr_hi |= htonl(F_WR_COMPL);
+               if (likely(skb_flags(skb) & C3CB_FLAG_NEED_HDR)) {
+                       if ((req_completion &&
+                               c3cn->wr_unacked == wrs_needed) ||
+                           (skb_flags(skb) & C3CB_FLAG_COMPL) ||
+                           c3cn->wr_unacked >= c3cn->wr_max / 2) {
+                               req_completion = 1;
                                c3cn->wr_unacked = 0;
                        }
-                       CXGB3_SKB_CB(skb)->flags &= ~C3CB_FLAG_NEED_HDR;
+                       len += ulp_extra_len(skb);
+                       make_tx_data_wr(c3cn, skb, len, req_completion);
+                       c3cn->snd_nxt += len;
+                       skb_flags(skb) &= ~C3CB_FLAG_NEED_HDR;
                }
 
                total_size += skb->truesize;
@@ -735,8 +749,11 @@ static void process_act_establish(struct s3_conn *c3cn, struct sk_buff *skb)
        if (unlikely(c3cn_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED)))
                /* upper layer has requested closing */
                send_abort_req(c3cn);
-       else if (c3cn_push_tx_frames(c3cn, 1))
+       else {
+               if (skb_queue_len(&c3cn->write_queue))
+                       c3cn_push_tx_frames(c3cn, 1);
                cxgb3i_conn_tx_open(c3cn);
+       }
 }
 
 static int do_act_establish(struct t3cdev *cdev, struct sk_buff *skb,
@@ -1082,8 +1099,8 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb)
                return;
        }
 
-       CXGB3_SKB_CB(skb)->seq = ntohl(hdr_cpl->seq);
-       CXGB3_SKB_CB(skb)->flags = 0;
+       skb_tcp_seq(skb) = ntohl(hdr_cpl->seq);
+       skb_flags(skb) = 0;
 
        skb_reset_transport_header(skb);
        __skb_pull(skb, sizeof(struct cpl_iscsi_hdr));
@@ -1103,12 +1120,12 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb)
                goto abort_conn;
 
        skb_ulp_mode(skb) = ULP2_FLAG_DATA_READY;
-       skb_ulp_pdulen(skb) = ntohs(ddp_cpl.len);
-       skb_ulp_ddigest(skb) = ntohl(ddp_cpl.ulp_crc);
+       skb_rx_pdulen(skb) = ntohs(ddp_cpl.len);
+       skb_rx_ddigest(skb) = ntohl(ddp_cpl.ulp_crc);
        status = ntohl(ddp_cpl.ddp_status);
 
        c3cn_rx_debug("rx skb 0x%p, len %u, pdulen %u, ddp status 0x%x.\n",
-                     skb, skb->len, skb_ulp_pdulen(skb), status);
+                     skb, skb->len, skb_rx_pdulen(skb), status);
 
        if (status & (1 << RX_DDP_STATUS_HCRC_SHIFT))
                skb_ulp_mode(skb) |= ULP2_FLAG_HCRC_ERROR;
@@ -1126,7 +1143,7 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb)
        } else if (status & (1 << RX_DDP_STATUS_DDP_SHIFT))
                skb_ulp_mode(skb) |= ULP2_FLAG_DATA_DDPED;
 
-       c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_ulp_pdulen(skb);
+       c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_rx_pdulen(skb);
        __pskb_trim(skb, len);
        __skb_queue_tail(&c3cn->receive_queue, skb);
        cxgb3i_conn_pdu_ready(c3cn);
@@ -1151,12 +1168,27 @@ static int do_iscsi_hdr(struct t3cdev *t3dev, struct sk_buff *skb, void *ctx)
  * Process an acknowledgment of WR completion.  Advance snd_una and send the
  * next batch of work requests from the write queue.
  */
+static void check_wr_invariants(struct s3_conn *c3cn)
+{
+       int pending = count_pending_wrs(c3cn);
+
+       if (unlikely(c3cn->wr_avail + pending != c3cn->wr_max))
+               cxgb3i_log_error("TID %u: credit imbalance: avail %u, "
+                               "pending %u, total should be %u\n",
+                               c3cn->tid, c3cn->wr_avail, pending,
+                               c3cn->wr_max);
+}
+
 static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb)
 {
        struct cpl_wr_ack *hdr = cplhdr(skb);
        unsigned int credits = ntohs(hdr->credits);
        u32 snd_una = ntohl(hdr->snd_una);
 
+       c3cn_tx_debug("%u WR credits, avail %u, unack %u, TID %u, state %u.\n",
+                       credits, c3cn->wr_avail, c3cn->wr_unacked,
+                       c3cn->tid, c3cn->state);
+
        c3cn->wr_avail += credits;
        if (c3cn->wr_unacked > c3cn->wr_max - c3cn->wr_avail)
                c3cn->wr_unacked = c3cn->wr_max - c3cn->wr_avail;
@@ -1171,6 +1203,17 @@ static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb)
                        break;
                }
                if (unlikely(credits < p->csum)) {
+                       struct tx_data_wr *w = cplhdr(p);
+                       cxgb3i_log_error("TID %u got %u WR credits need %u, "
+                                        "len %u, main body %u, frags %u, "
+                                        "seq # %u, ACK una %u, ACK nxt %u, "
+                                        "WR_AVAIL %u, WRs pending %u\n",
+                                        c3cn->tid, credits, p->csum, p->len,
+                                        p->len - p->data_len,
+                                        skb_shinfo(p)->nr_frags,
+                                        ntohl(w->sndseq), snd_una,
+                                        ntohl(hdr->snd_nxt), c3cn->wr_avail,
+                                        count_pending_wrs(c3cn) - credits);
                        p->csum -= credits;
                        break;
                } else {
@@ -1180,15 +1223,24 @@ static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb)
                }
        }
 
-       if (unlikely(before(snd_una, c3cn->snd_una)))
+       check_wr_invariants(c3cn);
+
+       if (unlikely(before(snd_una, c3cn->snd_una))) {
+               cxgb3i_log_error("TID %u, unexpected sequence # %u in WR_ACK "
+                                "snd_una %u\n",
+                                c3cn->tid, snd_una, c3cn->snd_una);
                goto out_free;
+       }
 
        if (c3cn->snd_una != snd_una) {
                c3cn->snd_una = snd_una;
                dst_confirm(c3cn->dst_cache);
        }
 
-       if (skb_queue_len(&c3cn->write_queue) && c3cn_push_tx_frames(c3cn, 0))
+       if (skb_queue_len(&c3cn->write_queue)) {
+               if (c3cn_push_tx_frames(c3cn, 0))
+                       cxgb3i_conn_tx_open(c3cn);
+       } else
                cxgb3i_conn_tx_open(c3cn);
 out_free:
        __kfree_skb(skb);
@@ -1452,7 +1504,7 @@ static void init_offload_conn(struct s3_conn *c3cn,
                              struct dst_entry *dst)
 {
        BUG_ON(c3cn->cdev != cdev);
-       c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs;
+       c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs - 1;
        c3cn->wr_unacked = 0;
        c3cn->mss_idx = select_mss(c3cn, dst_mtu(dst));
 
@@ -1671,9 +1723,17 @@ int cxgb3i_c3cn_send_pdus(struct s3_conn *c3cn, struct sk_buff *skb)
                goto out_err;
        }
 
-       err = -EPIPE;
        if (c3cn->err) {
                c3cn_tx_debug("c3cn 0x%p, err %d.\n", c3cn, c3cn->err);
+               err = -EPIPE;
+               goto out_err;
+       }
+
+       if (c3cn->write_seq - c3cn->snd_una >= cxgb3_snd_win) {
+               c3cn_tx_debug("c3cn 0x%p, snd %u - %u > %u.\n",
+                               c3cn, c3cn->write_seq, c3cn->snd_una,
+                               cxgb3_snd_win);
+               err = -EAGAIN;
                goto out_err;
        }
 
index d23156907ffdce1b8bb58dee792e2ee7204b4f8a..6344b9eb2589cfe42c8e33ff5606e5ae0e6b53f4 100644 (file)
@@ -178,25 +178,33 @@ void cxgb3i_c3cn_release(struct s3_conn *);
  * @flag:      see C3CB_FLAG_* below
  * @ulp_mode:  ULP mode/submode of sk_buff
  * @seq:       tcp sequence number
- * @ddigest:   pdu data digest
- * @pdulen:    recovered pdu length
- * @wr_data:   scratch area for tx wr
  */
+struct cxgb3_skb_rx_cb {
+       __u32 ddigest;                  /* data digest */
+       __u32 pdulen;                   /* recovered pdu length */
+};
+
+struct cxgb3_skb_tx_cb {
+       struct sk_buff *wr_next;        /* next wr */
+};
+
 struct cxgb3_skb_cb {
        __u8 flags;
        __u8 ulp_mode;
        __u32 seq;
-       __u32 ddigest;
-       __u32 pdulen;
-       struct sk_buff *wr_data;
+       union {
+               struct cxgb3_skb_rx_cb rx;
+               struct cxgb3_skb_tx_cb tx;
+       };
 };
 
 #define CXGB3_SKB_CB(skb)      ((struct cxgb3_skb_cb *)&((skb)->cb[0]))
-
+#define skb_flags(skb)         (CXGB3_SKB_CB(skb)->flags)
 #define skb_ulp_mode(skb)      (CXGB3_SKB_CB(skb)->ulp_mode)
-#define skb_ulp_ddigest(skb)   (CXGB3_SKB_CB(skb)->ddigest)
-#define skb_ulp_pdulen(skb)    (CXGB3_SKB_CB(skb)->pdulen)
-#define skb_wr_data(skb)       (CXGB3_SKB_CB(skb)->wr_data)
+#define skb_tcp_seq(skb)       (CXGB3_SKB_CB(skb)->seq)
+#define skb_rx_ddigest(skb)    (CXGB3_SKB_CB(skb)->rx.ddigest)
+#define skb_rx_pdulen(skb)     (CXGB3_SKB_CB(skb)->rx.pdulen)
+#define skb_tx_wr_next(skb)    (CXGB3_SKB_CB(skb)->tx.wr_next)
 
 enum c3cb_flags {
        C3CB_FLAG_NEED_HDR = 1 << 0,    /* packet needs a TX_DATA_WR header */
@@ -217,6 +225,7 @@ struct sge_opaque_hdr {
 /* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
 #define TX_HEADER_LEN \
                (sizeof(struct tx_data_wr) + sizeof(struct sge_opaque_hdr))
+#define SKB_TX_HEADROOM                SKB_MAX_HEAD(TX_HEADER_LEN)
 
 /*
  * get and set private ip for iscsi traffic
index ce7ce8c6094c549e44079079557ebb2d1f49791b..17115c230d6582ca8d8522166f774a999727ed3f 100644 (file)
 #define cxgb3i_tx_debug(fmt...)
 #endif
 
+/* always allocate rooms for AHS */
+#define SKB_TX_PDU_HEADER_LEN  \
+       (sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE)
+static unsigned int skb_extra_headroom;
 static struct page *pad_page;
 
 /*
@@ -146,12 +150,13 @@ static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc)
 
 void cxgb3i_conn_cleanup_task(struct iscsi_task *task)
 {
-       struct iscsi_tcp_task *tcp_task = task->dd_data;
+       struct cxgb3i_task_data *tdata = task->dd_data +
+                                       sizeof(struct iscsi_tcp_task);
 
        /* never reached the xmit task callout */
-       if (tcp_task->dd_data)
-               kfree_skb(tcp_task->dd_data);
-       tcp_task->dd_data = NULL;
+       if (tdata->skb)
+               __kfree_skb(tdata->skb);
+       memset(tdata, 0, sizeof(struct cxgb3i_task_data));
 
        /* MNC - Do we need a check in case this is called but
         * cxgb3i_conn_alloc_pdu has never been called on the task */
@@ -159,28 +164,102 @@ void cxgb3i_conn_cleanup_task(struct iscsi_task *task)
        iscsi_tcp_cleanup_task(task);
 }
 
-/*
- * We do not support ahs yet
- */
+static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt,
+                               unsigned int offset, unsigned int *off,
+                               struct scatterlist **sgp)
+{
+       int i;
+       struct scatterlist *sg;
+
+       for_each_sg(sgl, sg, sgcnt, i) {
+               if (offset < sg->length) {
+                       *off = offset;
+                       *sgp = sg;
+                       return 0;
+               }
+               offset -= sg->length;
+       }
+       return -EFAULT;
+}
+
+static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
+                               unsigned int dlen, skb_frag_t *frags,
+                               int frag_max)
+{
+       unsigned int datalen = dlen;
+       unsigned int sglen = sg->length - sgoffset;
+       struct page *page = sg_page(sg);
+       int i;
+
+       i = 0;
+       do {
+               unsigned int copy;
+
+               if (!sglen) {
+                       sg = sg_next(sg);
+                       if (!sg) {
+                               cxgb3i_log_error("%s, sg NULL, len %u/%u.\n",
+                                                __func__, datalen, dlen);
+                               return -EINVAL;
+                       }
+                       sgoffset = 0;
+                       sglen = sg->length;
+                       page = sg_page(sg);
+
+               }
+               copy = min(datalen, sglen);
+               if (i && page == frags[i - 1].page &&
+                   sgoffset + sg->offset ==
+                       frags[i - 1].page_offset + frags[i - 1].size) {
+                       frags[i - 1].size += copy;
+               } else {
+                       if (i >= frag_max) {
+                               cxgb3i_log_error("%s, too many pages %u, "
+                                                "dlen %u.\n", __func__,
+                                                frag_max, dlen);
+                               return -EINVAL;
+                       }
+
+                       frags[i].page = page;
+                       frags[i].page_offset = sg->offset + sgoffset;
+                       frags[i].size = copy;
+                       i++;
+               }
+               datalen -= copy;
+               sgoffset += copy;
+               sglen -= copy;
+       } while (datalen);
+
+       return i;
+}
+
 int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
 {
+       struct iscsi_conn *conn = task->conn;
        struct iscsi_tcp_task *tcp_task = task->dd_data;
-       struct sk_buff *skb;
+       struct cxgb3i_task_data *tdata = task->dd_data + sizeof(*tcp_task);
+       struct scsi_cmnd *sc = task->sc;
+       int headroom = SKB_TX_PDU_HEADER_LEN;
 
+       tcp_task->dd_data = tdata;
        task->hdr = NULL;
-       /* always allocate rooms for AHS */
-       skb = alloc_skb(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE +
-                       TX_HEADER_LEN,  GFP_ATOMIC);
-       if (!skb)
+
+       /* write command, need to send data pdus */
+       if (skb_extra_headroom && (opcode == ISCSI_OP_SCSI_DATA_OUT ||
+           (opcode == ISCSI_OP_SCSI_CMD &&
+           (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_TO_DEVICE))))
+               headroom += min(skb_extra_headroom, conn->max_xmit_dlength);
+
+       tdata->skb = alloc_skb(TX_HEADER_LEN + headroom, GFP_ATOMIC);
+       if (!tdata->skb)
                return -ENOMEM;
+       skb_reserve(tdata->skb, TX_HEADER_LEN);
 
        cxgb3i_tx_debug("task 0x%p, opcode 0x%x, skb 0x%p.\n",
-                       task, opcode, skb);
+                       task, opcode, tdata->skb);
 
-       tcp_task->dd_data = skb;
-       skb_reserve(skb, TX_HEADER_LEN);
-       task->hdr = (struct iscsi_hdr *)skb->data;
-       task->hdr_max = sizeof(struct iscsi_hdr);
+       task->hdr = (struct iscsi_hdr *)tdata->skb->data;
+       task->hdr_max = SKB_TX_PDU_HEADER_LEN;
 
        /* data_out uses scsi_cmd's itt */
        if (opcode != ISCSI_OP_SCSI_DATA_OUT)
@@ -192,13 +271,13 @@ int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
 int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
                              unsigned int count)
 {
-       struct iscsi_tcp_task *tcp_task = task->dd_data;
-       struct sk_buff *skb = tcp_task->dd_data;
        struct iscsi_conn *conn = task->conn;
-       struct page *pg;
+       struct iscsi_tcp_task *tcp_task = task->dd_data;
+       struct cxgb3i_task_data *tdata = tcp_task->dd_data;
+       struct sk_buff *skb = tdata->skb;
        unsigned int datalen = count;
        int i, padlen = iscsi_padding(count);
-       skb_frag_t *frag;
+       struct page *pg;
 
        cxgb3i_tx_debug("task 0x%p,0x%p, offset %u, count %u, skb 0x%p.\n",
                        task, task->sc, offset, count, skb);
@@ -209,90 +288,94 @@ int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
                return 0;
 
        if (task->sc) {
-               struct scatterlist *sg;
-               struct scsi_data_buffer *sdb;
-               unsigned int sgoffset = offset;
-               struct page *sgpg;
-               unsigned int sglen;
-
-               sdb = scsi_out(task->sc);
-               sg = sdb->table.sgl;
-
-               for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) {
-                       cxgb3i_tx_debug("sg %d, page 0x%p, len %u offset %u\n",
-                                       i, sg_page(sg), sg->length, sg->offset);
-
-                       if (sgoffset < sg->length)
-                               break;
-                       sgoffset -= sg->length;
+               struct scsi_data_buffer *sdb = scsi_out(task->sc);
+               struct scatterlist *sg = NULL;
+               int err;
+
+               tdata->offset = offset;
+               tdata->count = count;
+               err = sgl_seek_offset(sdb->table.sgl, sdb->table.nents,
+                                       tdata->offset, &tdata->sgoffset, &sg);
+               if (err < 0) {
+                       cxgb3i_log_warn("tpdu, sgl %u, bad offset %u/%u.\n",
+                                       sdb->table.nents, tdata->offset,
+                                       sdb->length);
+                       return err;
                }
-               sgpg = sg_page(sg);
-               sglen = sg->length - sgoffset;
-
-               do {
-                       int j = skb_shinfo(skb)->nr_frags;
-                       unsigned int copy;
-
-                       if (!sglen) {
-                               sg = sg_next(sg);
-                               sgpg = sg_page(sg);
-                               sgoffset = 0;
-                               sglen = sg->length;
-                               ++i;
+               err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count,
+                                       tdata->frags, MAX_PDU_FRAGS);
+               if (err < 0) {
+                       cxgb3i_log_warn("tpdu, sgl %u, bad offset %u + %u.\n",
+                                       sdb->table.nents, tdata->offset,
+                                       tdata->count);
+                       return err;
+               }
+               tdata->nr_frags = err;
+
+               if (tdata->nr_frags > MAX_SKB_FRAGS ||
+                   (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) {
+                       char *dst = skb->data + task->hdr_len;
+                       skb_frag_t *frag = tdata->frags;
+
+                       /* data fits in the skb's headroom */
+                       for (i = 0; i < tdata->nr_frags; i++, frag++) {
+                               char *src = kmap_atomic(frag->page,
+                                                       KM_SOFTIRQ0);
+
+                               memcpy(dst, src+frag->page_offset, frag->size);
+                               dst += frag->size;
+                               kunmap_atomic(src, KM_SOFTIRQ0);
                        }
-                       copy = min(sglen, datalen);
-                       if (j && skb_can_coalesce(skb, j, sgpg,
-                                                 sg->offset + sgoffset)) {
-                               skb_shinfo(skb)->frags[j - 1].size += copy;
-                       } else {
-                               get_page(sgpg);
-                               skb_fill_page_desc(skb, j, sgpg,
-                                                  sg->offset + sgoffset, copy);
+                       if (padlen) {
+                               memset(dst, 0, padlen);
+                               padlen = 0;
                        }
-                       sgoffset += copy;
-                       sglen -= copy;
-                       datalen -= copy;
-               } while (datalen);
+                       skb_put(skb, count + padlen);
+               } else {
+                       /* data fit into frag_list */
+                       for (i = 0; i < tdata->nr_frags; i++)
+                               get_page(tdata->frags[i].page);
+
+                       memcpy(skb_shinfo(skb)->frags, tdata->frags,
+                               sizeof(skb_frag_t) * tdata->nr_frags);
+                       skb_shinfo(skb)->nr_frags = tdata->nr_frags;
+                       skb->len += count;
+                       skb->data_len += count;
+                       skb->truesize += count;
+               }
+
        } else {
                pg = virt_to_page(task->data);
 
-               while (datalen) {
-                       i = skb_shinfo(skb)->nr_frags;
-                       frag = &skb_shinfo(skb)->frags[i];
-
-                       get_page(pg);
-                       frag->page = pg;
-                       frag->page_offset = 0;
-                       frag->size = min((unsigned int)PAGE_SIZE, datalen);
-
-                       skb_shinfo(skb)->nr_frags++;
-                       datalen -= frag->size;
-                       pg++;
-               }
+               get_page(pg);
+               skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data),
+                                       count);
+               skb->len += count;
+               skb->data_len += count;
+               skb->truesize += count;
        }
 
        if (padlen) {
                i = skb_shinfo(skb)->nr_frags;
-               frag = &skb_shinfo(skb)->frags[i];
-               frag->page = pad_page;
-               frag->page_offset = 0;
-               frag->size = padlen;
-               skb_shinfo(skb)->nr_frags++;
+               get_page(pad_page);
+               skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, pad_page, 0,
+                                padlen);
+
+               skb->data_len += padlen;
+               skb->truesize += padlen;
+               skb->len += padlen;
        }
 
-       datalen = count + padlen;
-       skb->data_len += datalen;
-       skb->truesize += datalen;
-       skb->len += datalen;
        return 0;
 }
 
 int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
 {
-       struct iscsi_tcp_task *tcp_task = task->dd_data;
-       struct sk_buff *skb = tcp_task->dd_data;
        struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
        struct cxgb3i_conn *cconn = tcp_conn->dd_data;
+       struct iscsi_tcp_task *tcp_task = task->dd_data;
+       struct cxgb3i_task_data *tdata = tcp_task->dd_data;
+       struct sk_buff *skb = tdata->skb;
        unsigned int datalen;
        int err;
 
@@ -300,13 +383,14 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
                return 0;
 
        datalen = skb->data_len;
-       tcp_task->dd_data = NULL;
+       tdata->skb = NULL;
        err = cxgb3i_c3cn_send_pdus(cconn->cep->c3cn, skb);
-       cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
-                       task, skb, skb->len, skb->data_len, err);
        if (err > 0) {
                int pdulen = err;
 
+       cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
+                       task, skb, skb->len, skb->data_len, err);
+
                if (task->conn->hdrdgst_en)
                        pdulen += ISCSI_DIGEST_SIZE;
                if (datalen && task->conn->datadgst_en)
@@ -325,12 +409,14 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
                return err;
        }
        /* reset skb to send when we are called again */
-       tcp_task->dd_data = skb;
+       tdata->skb = skb;
        return -EAGAIN;
 }
 
 int cxgb3i_pdu_init(void)
 {
+       if (SKB_TX_HEADROOM > (512 * MAX_SKB_FRAGS))
+               skb_extra_headroom = SKB_TX_HEADROOM;
        pad_page = alloc_page(GFP_KERNEL);
        if (!pad_page)
                return -ENOMEM;
@@ -366,7 +452,9 @@ void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn)
        skb = skb_peek(&c3cn->receive_queue);
        while (!err && skb) {
                __skb_unlink(skb, &c3cn->receive_queue);
-               read += skb_ulp_pdulen(skb);
+               read += skb_rx_pdulen(skb);
+               cxgb3i_rx_debug("conn 0x%p, cn 0x%p, rx skb 0x%p, pdulen %u.\n",
+                               conn, c3cn, skb, skb_rx_pdulen(skb));
                err = cxgb3i_conn_read_pdu_skb(conn, skb);
                __kfree_skb(skb);
                skb = skb_peek(&c3cn->receive_queue);
@@ -377,6 +465,11 @@ void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn)
                cxgb3i_c3cn_rx_credits(c3cn, read);
        }
        conn->rxdata_octets += read;
+
+       if (err) {
+               cxgb3i_log_info("conn 0x%p rx failed err %d.\n", conn, err);
+               iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+       }
 }
 
 void cxgb3i_conn_tx_open(struct s3_conn *c3cn)
index a3f685cc236299521aa54e4e8207b974875b3aee..0770b23d90da1a704019e6d538a8aae2640f21d4 100644 (file)
@@ -53,7 +53,7 @@ struct cpl_rx_data_ddp_norss {
 #define ULP2_FLAG_DCRC_ERROR           0x20
 #define ULP2_FLAG_PAD_ERROR            0x40
 
-void cxgb3i_conn_closing(struct s3_conn *);
+void cxgb3i_conn_closing(struct s3_conn *c3cn);
 void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn);
 void cxgb3i_conn_tx_open(struct s3_conn *c3cn);
 #endif
index a48e4990fe12fc79f06d649faa5dac4887f0a65e..34be88d7afa53da88fc2910ede911bfe9b758550 100644 (file)
@@ -1251,6 +1251,7 @@ static struct pci_device_id hptiop_id_table[] = {
        { PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x4321), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops },
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 940dc32ff0dc731523c0e02849e3772950260ef0..b82ffd90632e256ca0ce5c7d478dae715f3e8318 100644 (file)
@@ -1040,12 +1040,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                action = ACTION_FAIL;
                        break;
                case ABORTED_COMMAND:
+                       action = ACTION_FAIL;
                        if (sshdr.asc == 0x10) { /* DIF */
                                description = "Target Data Integrity Failure";
-                               action = ACTION_FAIL;
                                error = -EILSEQ;
-                       } else
-                               action = ACTION_RETRY;
+                       }
                        break;
                case NOT_READY:
                        /* If the device is in the process of becoming
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 d57566b8be0ad9f095a0ef0525b5c265b61e8b2c..55310dbc10a669f6b9cbf3bb5627d9bf8badc171 100644 (file)
@@ -107,6 +107,7 @@ static void scsi_disk_release(struct device *cdev);
 static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
 static void sd_print_result(struct scsi_disk *, int);
 
+static DEFINE_SPINLOCK(sd_index_lock);
 static DEFINE_IDA(sd_index_ida);
 
 /* This semaphore is used to mediate the 0->1 reference get in the
@@ -1914,7 +1915,9 @@ static int sd_probe(struct device *dev)
                if (!ida_pre_get(&sd_index_ida, GFP_KERNEL))
                        goto out_put;
 
+               spin_lock(&sd_index_lock);
                error = ida_get_new(&sd_index_ida, &index);
+               spin_unlock(&sd_index_lock);
        } while (error == -EAGAIN);
 
        if (error)
@@ -1936,7 +1939,9 @@ static int sd_probe(struct device *dev)
        return 0;
 
  out_free_index:
+       spin_lock(&sd_index_lock);
        ida_remove(&sd_index_ida, index);
+       spin_unlock(&sd_index_lock);
  out_put:
        put_disk(gd);
  out_free:
@@ -1986,7 +1991,9 @@ static void scsi_disk_release(struct device *dev)
        struct scsi_disk *sdkp = to_scsi_disk(dev);
        struct gendisk *disk = sdkp->disk;
        
+       spin_lock(&sd_index_lock);
        ida_remove(&sd_index_ida, sdkp->index);
+       spin_unlock(&sd_index_lock);
 
        disk->private_data = NULL;
        put_disk(disk);
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 3599828b976600848d644d51c42db442d808a708..022e89ffec1da4bc8da86bf6ba8471634f4fdaad 100644 (file)
 # define SCSPTR3       0xffed0024      /* 16 bit SCIF */
 # define SCSPTR4       0xffee0024      /* 16 bit SCIF */
 # define SCSPTR5       0xffef0024      /* 16 bit SCIF */
-# define SCIF_OPER     0x0001          /* Overrun error bit */
+# define SCIF_ORER     0x0001          /* Overrun error bit */
 # define SCSCR_INIT(port)      0x3a    /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \
       defined(CONFIG_CPU_SUBTYPE_SH7203) || \
index ab69c1bf36a8205fd80a2abb46cd7c16e1d9d5be..c2747bc88c6fbe42861857cca5dd6190e5559a28 100644 (file)
@@ -2164,19 +2164,20 @@ static void __exit panel_cleanup_module(void)
        if (scan_timer.function != NULL)
                del_timer(&scan_timer);
 
-       if (keypad_enabled)
-               misc_deregister(&keypad_dev);
+       if (pprt != NULL) {
+               if (keypad_enabled)
+                       misc_deregister(&keypad_dev);
+
+               if (lcd_enabled) {
+                       panel_lcd_print("\x0cLCD driver " PANEL_VERSION
+                                       "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-");
+                       misc_deregister(&lcd_dev);
+               }
 
-       if (lcd_enabled) {
-               panel_lcd_print("\x0cLCD driver " PANEL_VERSION
-                               "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-");
-               misc_deregister(&lcd_dev);
+               /* TODO: free all input signals */
+               parport_release(pprt);
+               parport_unregister_device(pprt);
        }
-
-       /* TODO: free all input signals */
-
-       parport_release(pprt);
-       parport_unregister_device(pprt);
        parport_unregister_driver(&panel_driver);
 }
 
index 79c225acd1ad7b9904668c40586d8f0e6c7ee0fd..f636296b54bc7fd7d809755682ecf844e0aa5f2e 100644 (file)
@@ -1,5 +1,6 @@
 config RTL8187SE
        tristate "RealTek RTL8187SE Wireless LAN NIC driver"
        depends on PCI
+       depends on WIRELESS_EXT && COMPAT_NET_DEV_OPS
        default N
        ---help---
index af64cfbe16dbbb056e6dde50b50f2f1e7e022544..7370296225e19b78942d076cf84fca84e6a0ffb9 100644 (file)
@@ -234,20 +234,21 @@ out:
 void ieee80211_crypto_deinit(void)
 {
        struct list_head *ptr, *n;
+       struct ieee80211_crypto_alg *alg = NULL;
 
        if (hcrypt == NULL)
                return;
 
-       for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
-            ptr = n, n = ptr->next) {
-               struct ieee80211_crypto_alg *alg =
-                       (struct ieee80211_crypto_alg *) ptr;
-               list_del(ptr);
-               printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
-                      "'%s' (deinit)\n", alg->ops->name);
-               kfree(alg);
+       list_for_each_safe(ptr, n, &hcrypt->algs) {
+               alg = list_entry(ptr, struct ieee80211_crypto_alg, list);
+               if (alg) {
+                       list_del(ptr);
+                       printk(KERN_DEBUG
+                              "ieee80211_crypt: unregistered algorithm '%s' (deinit)\n",
+                              alg->ops->name);
+                       kfree(alg);
+               }
        }
-
        kfree(hcrypt);
 }
 
index 94534955e38b52eae91fe8f732d2a0f56cedd928..66de5cc8ddf119a85d4b66c4829bfe4c97422b90 100644 (file)
@@ -6161,10 +6161,10 @@ static void __exit rtl8180_pci_module_exit(void)
 {
        pci_unregister_driver (&rtl8180_pci_driver);
        rtl8180_proc_module_remove();
-       ieee80211_crypto_deinit();
        ieee80211_crypto_tkip_exit();
        ieee80211_crypto_ccmp_exit();
        ieee80211_crypto_wep_exit();
+       ieee80211_crypto_deinit();
        DMESG("Exiting");
 }
 
index b003f9a7e1518b58f62ec83787a529652481a1f9..f716b2e92b654a55f848aecd370c0736861f201f 100644 (file)
@@ -319,16 +319,18 @@ static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id
        struct usb_device *udev = interface_to_usbdev(intf);
        struct wbsoft_priv *priv;
        struct ieee80211_hw *dev;
-       int err;
+       int nr, err;
 
        usb_get_dev(udev);
 
        // 20060630.2 Check the device if it already be opened
-       err = usb_control_msg(udev, usb_rcvctrlpipe( udev, 0 ),
-                             0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,
-                             0x0, 0x400, &ltmp, 4, HZ*100 );
-       if (err)
+       nr = usb_control_msg(udev, usb_rcvctrlpipe( udev, 0 ),
+                            0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,
+                            0x0, 0x400, &ltmp, 4, HZ*100 );
+       if (nr < 0) {
+               err = nr;
                goto error;
+       }
 
        ltmp = cpu_to_le32(ltmp);
        if (ltmp) {  // Is already initialized?
@@ -337,8 +339,10 @@ static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id
        }
 
        dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
-       if (!dev)
+       if (!dev) {
+               err = -ENOMEM;
                goto error;
+       }
 
        priv = dev->priv;
 
@@ -369,9 +373,11 @@ static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id
        }
 
        dev->extra_tx_headroom = 12;    /* FIXME */
-       dev->flags = 0;
+       dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
+       dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
 
        dev->channel_change_time = 1000;
+       dev->max_signal = 100;
        dev->queues = 1;
 
        dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
index 326dd7f65ee9aaf0b846d09c80c9d6d2b260b0d8..b3d5a23ab56fbf5c3832aa76d69e27caf15a9ff4 100644 (file)
@@ -1376,6 +1376,15 @@ static struct usb_device_id acm_ids[] = {
        { USB_DEVICE(0x0572, 0x1324), /* Conexant USB MODEM RD02-D400 */
        .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
        },
+       { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */
+       },
+       { USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */
+       .driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on
+                                          data interface instead of
+                                          communications interface.
+                                          Maybe we should define a new
+                                          quirk for this. */
+       },
 
        /* control interfaces with various AT-command sets */
        { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
index 31fb204f44c6a020467f952b5ed855132ba0dff7..49e7f56e0d7f72ea14800a3caf719538897234e3 100644 (file)
@@ -653,7 +653,7 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type,
                if (result <= 0 && result != -ETIMEDOUT)
                        continue;
                if (result > 1 && ((u8 *)buf)[1] != type) {
-                       result = -EPROTO;
+                       result = -ENODATA;
                        continue;
                }
                break;
@@ -696,8 +696,13 @@ static int usb_get_string(struct usb_device *dev, unsigned short langid,
                        USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
                        (USB_DT_STRING << 8) + index, langid, buf, size,
                        USB_CTRL_GET_TIMEOUT);
-               if (!(result == 0 || result == -EPIPE))
-                       break;
+               if (result == 0 || result == -EPIPE)
+                       continue;
+               if (result > 1 && ((u8 *) buf)[1] != USB_DT_STRING) {
+                       result = -ENODATA;
+                       continue;
+               }
+               break;
        }
        return result;
 }
index 3219d137340a31009893184301b801068fe7e62a..e55fef52a5dc5797c02121e0d7482d528a66144f 100644 (file)
@@ -191,6 +191,7 @@ config USB_GADGET_OMAP
        boolean "OMAP USB Device Controller"
        depends on ARCH_OMAP
        select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
+       select USB_OTG_UTILS if ARCH_OMAP
        help
           Many Texas Instruments OMAP processors have flexible full
           speed USB device controllers, with support for up to 30
index 80c2e7e9622f63507c16b4ec2682709936423f45..38aa896cc5db36317c8e4b7e03a1dc4734bb5c1c 100644 (file)
@@ -366,9 +366,9 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
                f->hs_descriptors = usb_copy_descriptors(hs_function);
 
                obex->hs.obex_in = usb_find_endpoint(hs_function,
-                               f->descriptors, &obex_hs_ep_in_desc);
+                               f->hs_descriptors, &obex_hs_ep_in_desc);
                obex->hs.obex_out = usb_find_endpoint(hs_function,
-                               f->descriptors, &obex_hs_ep_out_desc);
+                               f->hs_descriptors, &obex_hs_ep_out_desc);
        }
 
        /* Avoid letting this gadget enumerate until the userspace
index b10fa31cc9157a8f60a538ac8da42946f366efdc..1ab9dac7e12df8eec07e5ed278e48ca90cdd3bc5 100644 (file)
@@ -3879,7 +3879,11 @@ static int __init check_parameters(struct fsg_dev *fsg)
        mod_data.protocol_type = USB_SC_SCSI;
        mod_data.protocol_name = "Transparent SCSI";
 
-       if (gadget_is_sh(fsg->gadget))
+       /* Some peripheral controllers are known not to be able to
+        * halt bulk endpoints correctly.  If one of them is present,
+        * disable stalls.
+        */
+       if (gadget_is_sh(fsg->gadget) || gadget_is_at91(fsg->gadget))
                mod_data.can_stall = 0;
 
        if (mod_data.release == 0xffff) {       // Parameter wasn't set
index f3c6703cffda3c700399f8352f2ed5bf76530b6f..d8d9a52a44b34e5a517c3a8dd923478e3b88b198 100644 (file)
@@ -404,7 +404,10 @@ static void struct_ep_qh_setup(struct fsl_udc *udc, unsigned char ep_num,
        }
        if (zlt)
                tmp |= EP_QUEUE_HEAD_ZLT_SEL;
+
        p_QH->max_pkt_length = cpu_to_le32(tmp);
+       p_QH->next_dtd_ptr = 1;
+       p_QH->size_ioc_int_sts = 0;
 
        return;
 }
index 4725d15d096f559fc833d0e0f6323bcff4aa7631..e551bb38852be35eefeb532a23c260ecff6109ff 100644 (file)
@@ -485,6 +485,7 @@ static int ehci_init(struct usb_hcd *hcd)
         * periodic_size can shrink by USBCMD update if hcc_params allows.
         */
        ehci->periodic_size = DEFAULT_I_TDPS;
+       INIT_LIST_HEAD(&ehci->cached_itd_list);
        if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0)
                return retval;
 
@@ -497,6 +498,7 @@ static int ehci_init(struct usb_hcd *hcd)
 
        ehci->reclaim = NULL;
        ehci->next_uframe = -1;
+       ehci->clock_frame = -1;
 
        /*
         * dedicate a qh for the async ring head, since we couldn't unlink
index 0431397836f65e859f1a2b1829f418fa3697f65d..10d52919abbb1513feefe95ecaa5c5aa518a7443 100644 (file)
@@ -128,6 +128,7 @@ static inline void qh_put (struct ehci_qh *qh)
 
 static void ehci_mem_cleanup (struct ehci_hcd *ehci)
 {
+       free_cached_itd_list(ehci);
        if (ehci->async)
                qh_put (ehci->async);
        ehci->async = NULL;
index a081ee65bde6d933f3f2000c67028d461ece27c7..07bcb931021b48a9b00ffeac887288448c7d696e 100644 (file)
@@ -1004,7 +1004,8 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
 
                is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0;
                stream->bEndpointAddress &= 0x0f;
-               stream->ep->hcpriv = NULL;
+               if (stream->ep)
+                       stream->ep->hcpriv = NULL;
 
                if (stream->rescheduled) {
                        ehci_info (ehci, "ep%d%s-iso rescheduled "
@@ -1653,14 +1654,28 @@ itd_complete (
                        (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
        }
        iso_stream_put (ehci, stream);
-       /* OK to recycle this ITD now that its completion callback ran. */
+
 done:
        usb_put_urb(urb);
        itd->urb = NULL;
-       itd->stream = NULL;
-       list_move(&itd->itd_list, &stream->free_list);
-       iso_stream_put(ehci, stream);
-
+       if (ehci->clock_frame != itd->frame || itd->index[7] != -1) {
+               /* OK to recycle this ITD now. */
+               itd->stream = NULL;
+               list_move(&itd->itd_list, &stream->free_list);
+               iso_stream_put(ehci, stream);
+       } else {
+               /* HW might remember this ITD, so we can't recycle it yet.
+                * Move it to a safe place until a new frame starts.
+                */
+               list_move(&itd->itd_list, &ehci->cached_itd_list);
+               if (stream->refcount == 2) {
+                       /* If iso_stream_put() were called here, stream
+                        * would be freed.  Instead, just prevent reuse.
+                        */
+                       stream->ep->hcpriv = NULL;
+                       stream->ep = NULL;
+               }
+       }
        return retval;
 }
 
@@ -2101,6 +2116,20 @@ done:
 
 /*-------------------------------------------------------------------------*/
 
+static void free_cached_itd_list(struct ehci_hcd *ehci)
+{
+       struct ehci_itd *itd, *n;
+
+       list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) {
+               struct ehci_iso_stream  *stream = itd->stream;
+               itd->stream = NULL;
+               list_move(&itd->itd_list, &stream->free_list);
+               iso_stream_put(ehci, stream);
+       }
+}
+
+/*-------------------------------------------------------------------------*/
+
 static void
 scan_periodic (struct ehci_hcd *ehci)
 {
@@ -2115,10 +2144,17 @@ scan_periodic (struct ehci_hcd *ehci)
         * Touches as few pages as possible:  cache-friendly.
         */
        now_uframe = ehci->next_uframe;
-       if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
+       if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
                clock = ehci_readl(ehci, &ehci->regs->frame_index);
-       else
+               clock_frame = (clock >> 3) % ehci->periodic_size;
+       } else  {
                clock = now_uframe + mod - 1;
+               clock_frame = -1;
+       }
+       if (ehci->clock_frame != clock_frame) {
+               free_cached_itd_list(ehci);
+               ehci->clock_frame = clock_frame;
+       }
        clock %= mod;
        clock_frame = clock >> 3;
 
@@ -2277,6 +2313,10 @@ restart:
                        /* rescan the rest of this frame, then ... */
                        clock = now;
                        clock_frame = clock >> 3;
+                       if (ehci->clock_frame != clock_frame) {
+                               free_cached_itd_list(ehci);
+                               ehci->clock_frame = clock_frame;
+                       }
                } else {
                        now_uframe++;
                        now_uframe %= mod;
index fb7054ccf4fce90c516397f9923e6195c149768e..262b00c9b334286583d8fb84d394bac07a86a304 100644 (file)
@@ -87,6 +87,10 @@ struct ehci_hcd {                    /* one per controller */
        int                     next_uframe;    /* scan periodic, start here */
        unsigned                periodic_sched; /* periodic activity count */
 
+       /* list of itds completed while clock_frame was still active */
+       struct list_head        cached_itd_list;
+       unsigned                clock_frame;
+
        /* per root hub port */
        unsigned long           reset_done [EHCI_MAX_ROOT_PORTS];
 
@@ -220,6 +224,8 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
        }
 }
 
+static void free_cached_itd_list(struct ehci_hcd *ehci);
+
 /*-------------------------------------------------------------------------*/
 
 #include <linux/usb/ehci_def.h>
index 5a8fd5d57a11a9e303969f623157e01030d3c569..2dc7606f319c1e0e857e6c70a0178e0f477a5d6c 100644 (file)
@@ -377,18 +377,8 @@ int __init musb_platform_init(struct musb *musb)
        u32             revision;
 
        musb->mregs += DAVINCI_BASE_OFFSET;
-#if 0
-       /* REVISIT there's something odd about clocking, this
-        * didn't appear do the job ...
-        */
-       musb->clock = clk_get(pDevice, "usb");
-       if (IS_ERR(musb->clock))
-               return PTR_ERR(musb->clock);
 
-       status = clk_enable(musb->clock);
-       if (status < 0)
-               return -ENODEV;
-#endif
+       clk_enable(musb->clock);
 
        /* returns zero if e.g. not clocked */
        revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
@@ -453,5 +443,8 @@ int musb_platform_exit(struct musb *musb)
        }
 
        phy_off();
+
+       clk_disable(musb->clock);
+
        return 0;
 }
index 2cc34fa05b7391813cb386342849b15bab714bc5..af77e46590065fd5b8890bd819ac20d0cc912b82 100644 (file)
 
 
 unsigned musb_debug;
-module_param(musb_debug, uint, S_IRUGO | S_IWUSR);
+module_param_named(debug, musb_debug, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug message level. Default = 0");
 
 #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
@@ -767,6 +767,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
 #ifdef CONFIG_USB_MUSB_HDRC_HCD
                case OTG_STATE_A_HOST:
                case OTG_STATE_A_SUSPEND:
+                       usb_hcd_resume_root_hub(musb_to_hcd(musb));
                        musb_root_disconnect(musb);
                        if (musb->a_wait_bcon != 0)
                                musb_platform_try_idle(musb, jiffies
@@ -1815,7 +1816,7 @@ static void musb_free(struct musb *musb)
 #ifdef CONFIG_SYSFS
        device_remove_file(musb->controller, &dev_attr_mode);
        device_remove_file(musb->controller, &dev_attr_vbus);
-#ifdef CONFIG_USB_MUSB_OTG
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
        device_remove_file(musb->controller, &dev_attr_srp);
 #endif
 #endif
@@ -2063,7 +2064,7 @@ fail2:
 #ifdef CONFIG_SYSFS
        device_remove_file(musb->controller, &dev_attr_mode);
        device_remove_file(musb->controller, &dev_attr_vbus);
-#ifdef CONFIG_USB_MUSB_OTG
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
        device_remove_file(musb->controller, &dev_attr_srp);
 #endif
 #endif
@@ -2243,10 +2244,10 @@ static int __init musb_init(void)
        return platform_driver_probe(&musb_driver, musb_probe);
 }
 
-/* make us init after usbcore and before usb
- * gadget and host-side drivers start to register
+/* make us init after usbcore and i2c (transceivers, regulators, etc)
+ * and before usb gadget and host-side drivers start to register
  */
-subsys_initcall(musb_init);
+fs_initcall(musb_init);
 
 static void __exit musb_cleanup(void)
 {
index 4ea305387981655db2aca1858fe4c5fe6b9011a2..c7ebd0867fcca9281ecf25abc130c91389444240 100644 (file)
@@ -575,7 +575,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
        struct usb_request      *request = &req->request;
        struct musb_ep          *musb_ep = &musb->endpoints[epnum].ep_out;
        void __iomem            *epio = musb->endpoints[epnum].regs;
-       u16                     fifo_count = 0;
+       unsigned                fifo_count = 0;
        u16                     len = musb_ep->packet_sz;
 
        csr = musb_readw(epio, MUSB_RXCSR);
@@ -687,7 +687,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                                        len, fifo_count,
                                        musb_ep->packet_sz);
 
-                       fifo_count = min(len, fifo_count);
+                       fifo_count = min_t(unsigned, len, fifo_count);
 
 #ifdef CONFIG_USB_TUSB_OMAP_DMA
                        if (tusb_dma_omap() && musb_ep->dma) {
index a035ceccf95019c09082139be0727bf395a7a311..6dbbd0786a6a0955877dca888f107b641d50eec0 100644 (file)
@@ -335,16 +335,11 @@ musb_save_toggle(struct musb_hw_ep *ep, int is_in, struct urb *urb)
 static struct musb_qh *
 musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
 {
-       int                     is_in;
        struct musb_hw_ep       *ep = qh->hw_ep;
        struct musb             *musb = ep->musb;
+       int                     is_in = usb_pipein(urb->pipe);
        int                     ready = qh->is_ready;
 
-       if (ep->is_shared_fifo)
-               is_in = 1;
-       else
-               is_in = usb_pipein(urb->pipe);
-
        /* save toggle eagerly, for paranoia */
        switch (qh->type) {
        case USB_ENDPOINT_XFER_BULK:
@@ -432,7 +427,7 @@ musb_advance_schedule(struct musb *musb, struct urb *urb,
        else
                qh = musb_giveback(qh, urb, urb->status);
 
-       if (qh && qh->is_ready && !list_empty(&qh->hep->urb_list)) {
+       if (qh != NULL && qh->is_ready) {
                DBG(4, "... next ep%d %cX urb %p\n",
                                hw_ep->epnum, is_in ? 'R' : 'T',
                                next_urb(qh));
@@ -942,8 +937,8 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb)
        switch (musb->ep0_stage) {
        case MUSB_EP0_IN:
                fifo_dest = urb->transfer_buffer + urb->actual_length;
-               fifo_count = min(len, ((u16) (urb->transfer_buffer_length
-                                       - urb->actual_length)));
+               fifo_count = min_t(size_t, len, urb->transfer_buffer_length -
+                                  urb->actual_length);
                if (fifo_count < len)
                        urb->status = -EOVERFLOW;
 
@@ -976,10 +971,9 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb)
                }
                /* FALLTHROUGH */
        case MUSB_EP0_OUT:
-               fifo_count = min(qh->maxpacket, ((u16)
-                               (urb->transfer_buffer_length
-                               - urb->actual_length)));
-
+               fifo_count = min_t(size_t, qh->maxpacket,
+                                  urb->transfer_buffer_length -
+                                  urb->actual_length);
                if (fifo_count) {
                        fifo_dest = (u8 *) (urb->transfer_buffer
                                        + urb->actual_length);
@@ -1161,7 +1155,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
        struct urb              *urb;
        struct musb_hw_ep       *hw_ep = musb->endpoints + epnum;
        void __iomem            *epio = hw_ep->regs;
-       struct musb_qh          *qh = hw_ep->out_qh;
+       struct musb_qh          *qh = hw_ep->is_shared_fifo ? hw_ep->in_qh
+                                                           : hw_ep->out_qh;
        u32                     status = 0;
        void __iomem            *mbase = musb->mregs;
        struct dma_channel      *dma;
@@ -1308,7 +1303,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
                 * packets before updating TXCSR ... other docs disagree ...
                 */
                /* PIO:  start next packet in this URB */
-               wLength = min(qh->maxpacket, (u16) wLength);
+               if (wLength > qh->maxpacket)
+                       wLength = qh->maxpacket;
                musb_write_fifo(hw_ep, wLength, buf);
                qh->segsize = wLength;
 
@@ -1867,19 +1863,21 @@ static int musb_urb_enqueue(
        }
        qh->type_reg = type_reg;
 
-       /* precompute rxinterval/txinterval register */
-       interval = min((u8)16, epd->bInterval); /* log encoding */
+       /* Precompute RXINTERVAL/TXINTERVAL register */
        switch (qh->type) {
        case USB_ENDPOINT_XFER_INT:
-               /* fullspeed uses linear encoding */
-               if (USB_SPEED_FULL == urb->dev->speed) {
-                       interval = epd->bInterval;
-                       if (!interval)
-                               interval = 1;
+               /*
+                * Full/low speeds use the  linear encoding,
+                * high speed uses the logarithmic encoding.
+                */
+               if (urb->dev->speed <= USB_SPEED_FULL) {
+                       interval = max_t(u8, epd->bInterval, 1);
+                       break;
                }
                /* FALLTHROUGH */
        case USB_ENDPOINT_XFER_ISOC:
-               /* iso always uses log encoding */
+               /* ISO always uses logarithmic encoding */
+               interval = min_t(u8, epd->bInterval, 16);
                break;
        default:
                /* REVISIT we actually want to use NAK limits, hinting to the
@@ -2037,9 +2035,9 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                goto done;
 
        /* Any URB not actively programmed into endpoint hardware can be
-        * immediately given back.  Such an URB must be at the head of its
+        * immediately given back; that's any URB not at the head of an
         * endpoint queue, unless someday we get real DMA queues.  And even
-        * then, it might not be known to the hardware...
+        * if it's at the head, it might not be known to the hardware...
         *
         * Otherwise abort current transfer, pending dma, etc.; urb->status
         * has already been updated.  This is a synchronous abort; it'd be
@@ -2078,6 +2076,15 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                qh->is_ready = 0;
                __musb_giveback(musb, urb, 0);
                qh->is_ready = ready;
+
+               /* If nothing else (usually musb_giveback) is using it
+                * and its URB list has emptied, recycle this qh.
+                */
+               if (ready && list_empty(&qh->hep->urb_list)) {
+                       qh->hep->hcpriv = NULL;
+                       list_del(&qh->ring);
+                       kfree(qh);
+               }
        } else
                ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
 done:
@@ -2093,15 +2100,16 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
        unsigned long           flags;
        struct musb             *musb = hcd_to_musb(hcd);
        u8                      is_in = epnum & USB_DIR_IN;
-       struct musb_qh          *qh = hep->hcpriv;
-       struct urb              *urb, *tmp;
+       struct musb_qh          *qh;
+       struct urb              *urb;
        struct list_head        *sched;
 
-       if (!qh)
-               return;
-
        spin_lock_irqsave(&musb->lock, flags);
 
+       qh = hep->hcpriv;
+       if (qh == NULL)
+               goto exit;
+
        switch (qh->type) {
        case USB_ENDPOINT_XFER_CONTROL:
                sched = &musb->control;
@@ -2135,13 +2143,28 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
 
                /* cleanup */
                musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
-       } else
-               urb = NULL;
 
-       /* then just nuke all the others */
-       list_for_each_entry_safe_from(urb, tmp, &hep->urb_list, urb_list)
-               musb_giveback(qh, urb, -ESHUTDOWN);
+               /* Then nuke all the others ... and advance the
+                * queue on hw_ep (e.g. bulk ring) when we're done.
+                */
+               while (!list_empty(&hep->urb_list)) {
+                       urb = next_urb(qh);
+                       urb->status = -ESHUTDOWN;
+                       musb_advance_schedule(musb, urb, qh->hw_ep, is_in);
+               }
+       } else {
+               /* Just empty the queue; the hardware is busy with
+                * other transfers, and since !qh->is_ready nothing
+                * will activate any of these as it advances.
+                */
+               while (!list_empty(&hep->urb_list))
+                       __musb_giveback(musb, next_urb(qh), -ESHUTDOWN);
 
+               hep->hcpriv = NULL;
+               list_del(&qh->ring);
+               kfree(qh);
+       }
+exit:
        spin_unlock_irqrestore(&musb->lock, flags);
 }
 
index bfd0b68ceccd52942b864a79dfccdbe28735f5a5..b7c132bded7f43bf5fc6b69e7852d8e87dbabbf1 100644 (file)
@@ -294,7 +294,11 @@ static int  option_send_setup(struct tty_struct *tty, struct usb_serial_port *po
 
 /* Ericsson products */
 #define ERICSSON_VENDOR_ID                     0x0bdb
-#define ERICSSON_PRODUCT_F3507G                        0x1900
+#define ERICSSON_PRODUCT_F3507G_1              0x1900
+#define ERICSSON_PRODUCT_F3507G_2              0x1902
+
+#define BENQ_VENDOR_ID                         0x04a5
+#define BENQ_PRODUCT_H10                       0x4068
 
 static struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
@@ -509,7 +513,10 @@ static struct usb_device_id option_ids[] = {
        { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) },
        { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
        { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
-       { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G) },
+       { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_1) },
+       { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_2) },
+       { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
+       { USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 50dc33a6065bd01b61bac0b26da138eabd015c68..6f59c8e510ea433be6f623890d97bab675d97b77 100644 (file)
@@ -907,13 +907,13 @@ UNUSUAL_DEV(  0x05e3, 0x0701, 0x0000, 0xffff,
                "Genesys Logic",
                "USB to IDE Optical",
                US_SC_DEVICE, US_PR_DEVICE, NULL,
-               US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
+               US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
 
 UNUSUAL_DEV(  0x05e3, 0x0702, 0x0000, 0xffff,
                "Genesys Logic",
                "USB to IDE Disk",
                US_SC_DEVICE, US_PR_DEVICE, NULL,
-               US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
+               US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Ben Efros <ben@pc-doctor.com> */
 UNUSUAL_DEV(  0x05e3, 0x0723, 0x9451, 0x9451,
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 48ff701d3a72b9cd1d5a6cb7b345a89e9678e50d..2552b9f325ee9b4c33eea202329e23e47b544c3e 100644 (file)
@@ -2230,7 +2230,7 @@ static int __devexit pxafb_remove(struct platform_device *dev)
 
 static struct platform_driver pxafb_driver = {
        .probe          = pxafb_probe,
-       .remove         = pxafb_remove,
+       .remove         = __devexit_p(pxafb_remove),
        .suspend        = pxafb_suspend,
        .resume         = pxafb_resume,
        .driver         = {
index 8d0b1fb1e52edb6eeb57f98887e399d8a4c4b7af..1f51366417b9370b064488427eb5353234b117e1 100644 (file)
@@ -16,6 +16,12 @@ config W1_SLAVE_SMEM
          Say Y here if you want to connect 1-wire
          simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire.
 
+config W1_SLAVE_DS2431
+       tristate "1kb EEPROM family support (DS2431)"
+       help
+         Say Y here if you want to use a 1-wire
+         1kb EEPROM family device (DS2431)
+
 config W1_SLAVE_DS2433
        tristate "4kb EEPROM family support (DS2433)"
        help
index 990f400b6d22dc82563a382f6c0b7defd09820a6..f1f51f19b129115790996cb7349c1e53b1a9db8c 100644 (file)
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_W1_SLAVE_THERM)   += w1_therm.o
 obj-$(CONFIG_W1_SLAVE_SMEM)    += w1_smem.o
+obj-$(CONFIG_W1_SLAVE_DS2431)  += w1_ds2431.o
 obj-$(CONFIG_W1_SLAVE_DS2433)  += w1_ds2433.o
 obj-$(CONFIG_W1_SLAVE_DS2760)  += w1_ds2760.o
 obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o
index 858c16a544c21bc4517c50b853c394e8004373be..1394471488228d2f747475256a3236103a7973f4 100644 (file)
@@ -156,6 +156,9 @@ out_up:
  */
 static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
 {
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
+       struct w1_f23_data *f23 = sl->family_data;
+#endif
        u8 wrbuf[4];
        u8 rdbuf[W1_PAGE_SIZE + 3];
        u8 es = (addr + len - 1) & 0x1f;
@@ -196,7 +199,9 @@ static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
 
        /* Reset the bus to wake up the EEPROM (this may not be needed) */
        w1_reset_bus(sl->master);
-
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
+       f23->validcrc &= ~(1 << (addr >> W1_PAGE_BITS));
+#endif
        return 0;
 }
 
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 38bc735c67ad2ebfe79a4d64d35e6ad01117c8d6..dc20db348679d9f300f68af931b4e9b3a0019752 100644 (file)
@@ -69,10 +69,12 @@ obj-$(CONFIG_DLM)           += dlm/
 # Do not add any filesystems before this line
 obj-$(CONFIG_REISERFS_FS)      += reiserfs/
 obj-$(CONFIG_EXT3_FS)          += ext3/ # Before ext2 so root fs can be ext3
-obj-$(CONFIG_EXT4_FS)          += ext4/ # Before ext2 so root fs can be ext4
+obj-$(CONFIG_EXT2_FS)          += ext2/
+# We place ext4 after ext2 so plain ext2 root fs's are mounted using ext2
+# unless explicitly requested by rootfstype
+obj-$(CONFIG_EXT4_FS)          += ext4/
 obj-$(CONFIG_JBD)              += jbd/
 obj-$(CONFIG_JBD2)             += jbd2/
-obj-$(CONFIG_EXT2_FS)          += ext2/
 obj-$(CONFIG_CRAMFS)           += cramfs/
 obj-$(CONFIG_SQUASHFS)         += squashfs/
 obj-y                          += ramfs/
index 72ab251cdb9cd0c527b8c18c58f9ca6bca1ed621..124b95c4d58286649d8d0f982edd9074af18ac82 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -302,7 +302,7 @@ 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;
+       void *uninitialized_var(p);
 
        if (bs) {
                p = mempool_alloc(bs->bio_pool, gfp_mask);
index a8c9693b75ac42e939edaede65a29a31244d66c8..72677ce2b74fc87b1ff6a277906492389085f687 100644 (file)
@@ -66,6 +66,9 @@ struct btrfs_inode {
         */
        struct list_head delalloc_inodes;
 
+       /* the space_info for where this inode's data allocations are done */
+       struct btrfs_space_info *space_info;
+
        /* full 64 bit generation number, struct vfs_inode doesn't have a big
         * enough field for this.
         */
@@ -94,6 +97,11 @@ struct btrfs_inode {
         */
        u64 delalloc_bytes;
 
+       /* total number of bytes that may be used for this inode for
+        * delalloc
+        */
+       u64 reserved_bytes;
+
        /*
         * the size of the file stored in the metadata on disk.  data=ordered
         * means the in-memory i_size might be larger than the size on disk
index 766b31ae3186e46f54d5d9fbe6fed621651c6520..82491ba8fa40a451d0396f7f0b13c7a625414548 100644 (file)
@@ -596,13 +596,27 @@ struct btrfs_block_group_item {
 
 struct btrfs_space_info {
        u64 flags;
-       u64 total_bytes;
-       u64 bytes_used;
-       u64 bytes_pinned;
-       u64 bytes_reserved;
-       u64 bytes_readonly;
-       int full;
-       int force_alloc;
+
+       u64 total_bytes;        /* total bytes in the space */
+       u64 bytes_used;         /* total bytes used on disk */
+       u64 bytes_pinned;       /* total bytes pinned, will be freed when the
+                                  transaction finishes */
+       u64 bytes_reserved;     /* total bytes the allocator has reserved for
+                                  current allocations */
+       u64 bytes_readonly;     /* total bytes that are read only */
+
+       /* delalloc accounting */
+       u64 bytes_delalloc;     /* number of bytes reserved for allocation,
+                                  this space is not necessarily reserved yet
+                                  by the allocator */
+       u64 bytes_may_use;      /* number of bytes that may be used for
+                                  delalloc */
+
+       int full;               /* indicates that we cannot allocate any more
+                                  chunks for this space */
+       int force_alloc;        /* set if we need to force a chunk alloc for
+                                  this space */
+
        struct list_head list;
 
        /* for block groups in our same type */
@@ -1782,6 +1796,16 @@ int btrfs_add_dead_reloc_root(struct btrfs_root *root);
 int btrfs_cleanup_reloc_trees(struct btrfs_root *root);
 int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len);
 u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags);
+void btrfs_set_inode_space_info(struct btrfs_root *root, struct inode *ionde);
+int btrfs_check_metadata_free_space(struct btrfs_root *root);
+int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode,
+                               u64 bytes);
+void btrfs_free_reserved_data_space(struct btrfs_root *root,
+                                   struct inode *inode, u64 bytes);
+void btrfs_delalloc_reserve_space(struct btrfs_root *root, struct inode *inode,
+                                u64 bytes);
+void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode,
+                             u64 bytes);
 /* ctree.c */
 int btrfs_previous_item(struct btrfs_root *root,
                        struct btrfs_path *path, u64 min_objectid,
@@ -2027,8 +2051,6 @@ int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
 unsigned long btrfs_force_ra(struct address_space *mapping,
                              struct file_ra_state *ra, struct file *file,
                              pgoff_t offset, pgoff_t last_index);
-int btrfs_check_free_space(struct btrfs_root *root, u64 num_required,
-                          int for_del);
 int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page);
 int btrfs_readpage(struct file *file, struct page *page);
 void btrfs_delete_inode(struct inode *inode);
index 0a5d796c9f7ee3086bd3c8bccdfc63b59d674e0f..6b5966aacf447bfd14fbd2a2a1ef3be8b1280c29 100644 (file)
@@ -60,6 +60,10 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                              u64 bytenr, u64 num_bytes, int alloc,
                              int mark_free);
 
+static int do_chunk_alloc(struct btrfs_trans_handle *trans,
+                         struct btrfs_root *extent_root, u64 alloc_bytes,
+                         u64 flags, int force);
+
 static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits)
 {
        return (cache->flags & bits) == bits;
@@ -1909,6 +1913,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
        found->bytes_pinned = 0;
        found->bytes_reserved = 0;
        found->bytes_readonly = 0;
+       found->bytes_delalloc = 0;
        found->full = 0;
        found->force_alloc = 0;
        *space_info = found;
@@ -1972,6 +1977,233 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
        return flags;
 }
 
+static u64 btrfs_get_alloc_profile(struct btrfs_root *root, u64 data)
+{
+       struct btrfs_fs_info *info = root->fs_info;
+       u64 alloc_profile;
+
+       if (data) {
+               alloc_profile = info->avail_data_alloc_bits &
+                       info->data_alloc_profile;
+               data = BTRFS_BLOCK_GROUP_DATA | alloc_profile;
+       } else if (root == root->fs_info->chunk_root) {
+               alloc_profile = info->avail_system_alloc_bits &
+                       info->system_alloc_profile;
+               data = BTRFS_BLOCK_GROUP_SYSTEM | alloc_profile;
+       } else {
+               alloc_profile = info->avail_metadata_alloc_bits &
+                       info->metadata_alloc_profile;
+               data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile;
+       }
+
+       return btrfs_reduce_alloc_profile(root, data);
+}
+
+void btrfs_set_inode_space_info(struct btrfs_root *root, struct inode *inode)
+{
+       u64 alloc_target;
+
+       alloc_target = btrfs_get_alloc_profile(root, 1);
+       BTRFS_I(inode)->space_info = __find_space_info(root->fs_info,
+                                                      alloc_target);
+}
+
+/*
+ * for now this just makes sure we have at least 5% of our metadata space free
+ * for use.
+ */
+int btrfs_check_metadata_free_space(struct btrfs_root *root)
+{
+       struct btrfs_fs_info *info = root->fs_info;
+       struct btrfs_space_info *meta_sinfo;
+       u64 alloc_target, thresh;
+       int committed = 0, ret;
+
+       /* get the space info for where the metadata will live */
+       alloc_target = btrfs_get_alloc_profile(root, 0);
+       meta_sinfo = __find_space_info(info, alloc_target);
+
+again:
+       spin_lock(&meta_sinfo->lock);
+       if (!meta_sinfo->full)
+               thresh = meta_sinfo->total_bytes * 80;
+       else
+               thresh = meta_sinfo->total_bytes * 95;
+
+       do_div(thresh, 100);
+
+       if (meta_sinfo->bytes_used + meta_sinfo->bytes_reserved +
+           meta_sinfo->bytes_pinned + meta_sinfo->bytes_readonly > thresh) {
+               struct btrfs_trans_handle *trans;
+               if (!meta_sinfo->full) {
+                       meta_sinfo->force_alloc = 1;
+                       spin_unlock(&meta_sinfo->lock);
+
+                       trans = btrfs_start_transaction(root, 1);
+                       if (!trans)
+                               return -ENOMEM;
+
+                       ret = do_chunk_alloc(trans, root->fs_info->extent_root,
+                                            2 * 1024 * 1024, alloc_target, 0);
+                       btrfs_end_transaction(trans, root);
+                       goto again;
+               }
+               spin_unlock(&meta_sinfo->lock);
+
+               if (!committed) {
+                       committed = 1;
+                       trans = btrfs_join_transaction(root, 1);
+                       if (!trans)
+                               return -ENOMEM;
+                       ret = btrfs_commit_transaction(trans, root);
+                       if (ret)
+                               return ret;
+                       goto again;
+               }
+               return -ENOSPC;
+       }
+       spin_unlock(&meta_sinfo->lock);
+
+       return 0;
+}
+
+/*
+ * This will check the space that the inode allocates from to make sure we have
+ * enough space for bytes.
+ */
+int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode,
+                               u64 bytes)
+{
+       struct btrfs_space_info *data_sinfo;
+       int ret = 0, committed = 0;
+
+       /* make sure bytes are sectorsize aligned */
+       bytes = (bytes + root->sectorsize - 1) & ~((u64)root->sectorsize - 1);
+
+       data_sinfo = BTRFS_I(inode)->space_info;
+again:
+       /* make sure we have enough space to handle the data first */
+       spin_lock(&data_sinfo->lock);
+       if (data_sinfo->total_bytes - data_sinfo->bytes_used -
+           data_sinfo->bytes_delalloc - data_sinfo->bytes_reserved -
+           data_sinfo->bytes_pinned - data_sinfo->bytes_readonly -
+           data_sinfo->bytes_may_use < bytes) {
+               struct btrfs_trans_handle *trans;
+
+               /*
+                * if we don't have enough free bytes in this space then we need
+                * to alloc a new chunk.
+                */
+               if (!data_sinfo->full) {
+                       u64 alloc_target;
+
+                       data_sinfo->force_alloc = 1;
+                       spin_unlock(&data_sinfo->lock);
+
+                       alloc_target = btrfs_get_alloc_profile(root, 1);
+                       trans = btrfs_start_transaction(root, 1);
+                       if (!trans)
+                               return -ENOMEM;
+
+                       ret = do_chunk_alloc(trans, root->fs_info->extent_root,
+                                            bytes + 2 * 1024 * 1024,
+                                            alloc_target, 0);
+                       btrfs_end_transaction(trans, root);
+                       if (ret)
+                               return ret;
+                       goto again;
+               }
+               spin_unlock(&data_sinfo->lock);
+
+               /* commit the current transaction and try again */
+               if (!committed) {
+                       committed = 1;
+                       trans = btrfs_join_transaction(root, 1);
+                       if (!trans)
+                               return -ENOMEM;
+                       ret = btrfs_commit_transaction(trans, root);
+                       if (ret)
+                               return ret;
+                       goto again;
+               }
+
+               printk(KERN_ERR "no space left, need %llu, %llu delalloc bytes"
+                      ", %llu bytes_used, %llu bytes_reserved, "
+                      "%llu bytes_pinned, %llu bytes_readonly, %llu may use"
+                      "%llu total\n", bytes, data_sinfo->bytes_delalloc,
+                      data_sinfo->bytes_used, data_sinfo->bytes_reserved,
+                      data_sinfo->bytes_pinned, data_sinfo->bytes_readonly,
+                      data_sinfo->bytes_may_use, data_sinfo->total_bytes);
+               return -ENOSPC;
+       }
+       data_sinfo->bytes_may_use += bytes;
+       BTRFS_I(inode)->reserved_bytes += bytes;
+       spin_unlock(&data_sinfo->lock);
+
+       return btrfs_check_metadata_free_space(root);
+}
+
+/*
+ * if there was an error for whatever reason after calling
+ * btrfs_check_data_free_space, call this so we can cleanup the counters.
+ */
+void btrfs_free_reserved_data_space(struct btrfs_root *root,
+                                   struct inode *inode, u64 bytes)
+{
+       struct btrfs_space_info *data_sinfo;
+
+       /* make sure bytes are sectorsize aligned */
+       bytes = (bytes + root->sectorsize - 1) & ~((u64)root->sectorsize - 1);
+
+       data_sinfo = BTRFS_I(inode)->space_info;
+       spin_lock(&data_sinfo->lock);
+       data_sinfo->bytes_may_use -= bytes;
+       BTRFS_I(inode)->reserved_bytes -= bytes;
+       spin_unlock(&data_sinfo->lock);
+}
+
+/* called when we are adding a delalloc extent to the inode's io_tree */
+void btrfs_delalloc_reserve_space(struct btrfs_root *root, struct inode *inode,
+                                 u64 bytes)
+{
+       struct btrfs_space_info *data_sinfo;
+
+       /* get the space info for where this inode will be storing its data */
+       data_sinfo = BTRFS_I(inode)->space_info;
+
+       /* make sure we have enough space to handle the data first */
+       spin_lock(&data_sinfo->lock);
+       data_sinfo->bytes_delalloc += bytes;
+
+       /*
+        * we are adding a delalloc extent without calling
+        * btrfs_check_data_free_space first.  This happens on a weird
+        * writepage condition, but shouldn't hurt our accounting
+        */
+       if (unlikely(bytes > BTRFS_I(inode)->reserved_bytes)) {
+               data_sinfo->bytes_may_use -= BTRFS_I(inode)->reserved_bytes;
+               BTRFS_I(inode)->reserved_bytes = 0;
+       } else {
+               data_sinfo->bytes_may_use -= bytes;
+               BTRFS_I(inode)->reserved_bytes -= bytes;
+       }
+
+       spin_unlock(&data_sinfo->lock);
+}
+
+/* called when we are clearing an delalloc extent from the inode's io_tree */
+void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode,
+                             u64 bytes)
+{
+       struct btrfs_space_info *info;
+
+       info = BTRFS_I(inode)->space_info;
+
+       spin_lock(&info->lock);
+       info->bytes_delalloc -= bytes;
+       spin_unlock(&info->lock);
+}
+
 static int do_chunk_alloc(struct btrfs_trans_handle *trans,
                          struct btrfs_root *extent_root, u64 alloc_bytes,
                          u64 flags, int force)
@@ -3105,6 +3337,10 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes)
               (unsigned long long)(info->total_bytes - info->bytes_used -
                                    info->bytes_pinned - info->bytes_reserved),
               (info->full) ? "" : "not ");
+       printk(KERN_INFO "space_info total=%llu, pinned=%llu, delalloc=%llu,"
+              " may_use=%llu, used=%llu\n", info->total_bytes,
+              info->bytes_pinned, info->bytes_delalloc, info->bytes_may_use,
+              info->bytes_used);
 
        down_read(&info->groups_sem);
        list_for_each_entry(cache, &info->block_groups, list) {
@@ -3131,24 +3367,10 @@ static int __btrfs_reserve_extent(struct btrfs_trans_handle *trans,
 {
        int ret;
        u64 search_start = 0;
-       u64 alloc_profile;
        struct btrfs_fs_info *info = root->fs_info;
 
-       if (data) {
-               alloc_profile = info->avail_data_alloc_bits &
-                       info->data_alloc_profile;
-               data = BTRFS_BLOCK_GROUP_DATA | alloc_profile;
-       } else if (root == root->fs_info->chunk_root) {
-               alloc_profile = info->avail_system_alloc_bits &
-                       info->system_alloc_profile;
-               data = BTRFS_BLOCK_GROUP_SYSTEM | alloc_profile;
-       } else {
-               alloc_profile = info->avail_metadata_alloc_bits &
-                       info->metadata_alloc_profile;
-               data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile;
-       }
+       data = btrfs_get_alloc_profile(root, data);
 again:
-       data = btrfs_reduce_alloc_profile(root, data);
        /*
         * the only place that sets empty_size is btrfs_realloc_node, which
         * is not called recursively on allocations
index 3e8023efaff7581568f8d9a4f131a01c37f76d3b..dc78954861b333d75e831e27c6bbe7760f6e1de9 100644 (file)
@@ -1091,19 +1091,24 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
                WARN_ON(num_pages > nrptrs);
                memset(pages, 0, sizeof(struct page *) * nrptrs);
 
-               ret = btrfs_check_free_space(root, write_bytes, 0);
+               ret = btrfs_check_data_free_space(root, inode, write_bytes);
                if (ret)
                        goto out;
 
                ret = prepare_pages(root, file, pages, num_pages,
                                    pos, first_index, last_index,
                                    write_bytes);
-               if (ret)
+               if (ret) {
+                       btrfs_free_reserved_data_space(root, inode,
+                                                      write_bytes);
                        goto out;
+               }
 
                ret = btrfs_copy_from_user(pos, num_pages,
                                           write_bytes, pages, buf);
                if (ret) {
+                       btrfs_free_reserved_data_space(root, inode,
+                                                      write_bytes);
                        btrfs_drop_pages(pages, num_pages);
                        goto out;
                }
@@ -1111,8 +1116,11 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
                ret = dirty_and_release_pages(NULL, root, file, pages,
                                              num_pages, pos, write_bytes);
                btrfs_drop_pages(pages, num_pages);
-               if (ret)
+               if (ret) {
+                       btrfs_free_reserved_data_space(root, inode,
+                                                      write_bytes);
                        goto out;
+               }
 
                if (will_write) {
                        btrfs_fdatawrite_range(inode->i_mapping, pos,
@@ -1136,6 +1144,8 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
        }
 out:
        mutex_unlock(&inode->i_mutex);
+       if (ret)
+               err = ret;
 
 out_nolock:
        kfree(pages);
@@ -1222,7 +1232,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 +1241,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 +1255,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 +1263,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 3cee77ae03c81e0fe8340ceedb268ca96c2a1521..7d4f948bc22a5b5c811b93b385ff36d5b49e8977 100644 (file)
@@ -101,34 +101,6 @@ static int btrfs_init_inode_security(struct inode *inode,  struct inode *dir)
        return err;
 }
 
-/*
- * a very lame attempt at stopping writes when the FS is 85% full.  There
- * are countless ways this is incorrect, but it is better than nothing.
- */
-int btrfs_check_free_space(struct btrfs_root *root, u64 num_required,
-                          int for_del)
-{
-       u64 total;
-       u64 used;
-       u64 thresh;
-       int ret = 0;
-
-       spin_lock(&root->fs_info->delalloc_lock);
-       total = btrfs_super_total_bytes(&root->fs_info->super_copy);
-       used = btrfs_super_bytes_used(&root->fs_info->super_copy);
-       if (for_del)
-               thresh = total * 90;
-       else
-               thresh = total * 85;
-
-       do_div(thresh, 100);
-
-       if (used + root->fs_info->delalloc_bytes + num_required > thresh)
-               ret = -ENOSPC;
-       spin_unlock(&root->fs_info->delalloc_lock);
-       return ret;
-}
-
 /*
  * this does all the hard work for inserting an inline extent into
  * the btree.  The caller should have done a btrfs_drop_extents so that
@@ -1190,6 +1162,7 @@ static int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end,
         */
        if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) {
                struct btrfs_root *root = BTRFS_I(inode)->root;
+               btrfs_delalloc_reserve_space(root, inode, end - start + 1);
                spin_lock(&root->fs_info->delalloc_lock);
                BTRFS_I(inode)->delalloc_bytes += end - start + 1;
                root->fs_info->delalloc_bytes += end - start + 1;
@@ -1223,9 +1196,12 @@ static int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end,
                               (unsigned long long)end - start + 1,
                               (unsigned long long)
                               root->fs_info->delalloc_bytes);
+                       btrfs_delalloc_free_space(root, inode, (u64)-1);
                        root->fs_info->delalloc_bytes = 0;
                        BTRFS_I(inode)->delalloc_bytes = 0;
                } else {
+                       btrfs_delalloc_free_space(root, inode,
+                                                 end - start + 1);
                        root->fs_info->delalloc_bytes -= end - start + 1;
                        BTRFS_I(inode)->delalloc_bytes -= end - start + 1;
                }
@@ -2245,10 +2221,6 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
 
        root = BTRFS_I(dir)->root;
 
-       ret = btrfs_check_free_space(root, 1, 1);
-       if (ret)
-               goto fail;
-
        trans = btrfs_start_transaction(root, 1);
 
        btrfs_set_trans_block_group(trans, dir);
@@ -2261,7 +2233,6 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
        nr = trans->blocks_used;
 
        btrfs_end_transaction_throttle(trans, root);
-fail:
        btrfs_btree_balance_dirty(root, nr);
        return ret;
 }
@@ -2284,10 +2255,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
                return -ENOTEMPTY;
        }
 
-       ret = btrfs_check_free_space(root, 1, 1);
-       if (ret)
-               goto fail;
-
        trans = btrfs_start_transaction(root, 1);
        btrfs_set_trans_block_group(trans, dir);
 
@@ -2304,7 +2271,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
 fail_trans:
        nr = trans->blocks_used;
        ret = btrfs_end_transaction_throttle(trans, root);
-fail:
        btrfs_btree_balance_dirty(root, nr);
 
        if (ret && !err)
@@ -2818,7 +2784,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
        if (size <= hole_start)
                return 0;
 
-       err = btrfs_check_free_space(root, 1, 0);
+       err = btrfs_check_metadata_free_space(root);
        if (err)
                return err;
 
@@ -3014,6 +2980,7 @@ static noinline void init_btrfs_i(struct inode *inode)
        bi->last_trans = 0;
        bi->logged_trans = 0;
        bi->delalloc_bytes = 0;
+       bi->reserved_bytes = 0;
        bi->disk_i_size = 0;
        bi->flags = 0;
        bi->index_cnt = (u64)-1;
@@ -3035,6 +3002,7 @@ static int btrfs_init_locked_inode(struct inode *inode, void *p)
        inode->i_ino = args->ino;
        init_btrfs_i(inode);
        BTRFS_I(inode)->root = args->root;
+       btrfs_set_inode_space_info(args->root, inode);
        return 0;
 }
 
@@ -3455,6 +3423,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
        BTRFS_I(inode)->index_cnt = 2;
        BTRFS_I(inode)->root = root;
        BTRFS_I(inode)->generation = trans->transid;
+       btrfs_set_inode_space_info(root, inode);
 
        if (mode & S_IFDIR)
                owner = 0;
@@ -3602,7 +3571,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
        if (!new_valid_dev(rdev))
                return -EINVAL;
 
-       err = btrfs_check_free_space(root, 1, 0);
+       err = btrfs_check_metadata_free_space(root);
        if (err)
                goto fail;
 
@@ -3665,7 +3634,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
        u64 objectid;
        u64 index = 0;
 
-       err = btrfs_check_free_space(root, 1, 0);
+       err = btrfs_check_metadata_free_space(root);
        if (err)
                goto fail;
        trans = btrfs_start_transaction(root, 1);
@@ -3733,7 +3702,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
                return -ENOENT;
 
        btrfs_inc_nlink(inode);
-       err = btrfs_check_free_space(root, 1, 0);
+       err = btrfs_check_metadata_free_space(root);
        if (err)
                goto fail;
        err = btrfs_set_inode_index(dir, &index);
@@ -3779,7 +3748,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        u64 index = 0;
        unsigned long nr = 1;
 
-       err = btrfs_check_free_space(root, 1, 0);
+       err = btrfs_check_metadata_free_space(root);
        if (err)
                goto out_unlock;
 
@@ -4336,7 +4305,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page)
        u64 page_start;
        u64 page_end;
 
-       ret = btrfs_check_free_space(root, PAGE_CACHE_SIZE, 0);
+       ret = btrfs_check_data_free_space(root, inode, PAGE_CACHE_SIZE);
        if (ret)
                goto out;
 
@@ -4349,6 +4318,7 @@ again:
 
        if ((page->mapping != inode->i_mapping) ||
            (page_start >= size)) {
+               btrfs_free_reserved_data_space(root, inode, PAGE_CACHE_SIZE);
                /* page got truncated out from underneath us */
                goto out_unlock;
        }
@@ -4631,7 +4601,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)
                return -EXDEV;
 
-       ret = btrfs_check_free_space(root, 1, 0);
+       ret = btrfs_check_metadata_free_space(root);
        if (ret)
                goto out_unlock;
 
@@ -4749,7 +4719,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
        if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(root))
                return -ENAMETOOLONG;
 
-       err = btrfs_check_free_space(root, 1, 0);
+       err = btrfs_check_metadata_free_space(root);
        if (err)
                goto out_fail;
 
index 988fdc8b49ebb92b7ad7d5d9163f3fc23e866d16..bca729fc80c83e07a3847b2b7bb6e73123d6c30f 100644 (file)
@@ -70,7 +70,7 @@ static noinline int create_subvol(struct btrfs_root *root,
        u64 index = 0;
        unsigned long nr = 1;
 
-       ret = btrfs_check_free_space(root, 1, 0);
+       ret = btrfs_check_metadata_free_space(root);
        if (ret)
                goto fail_commit;
 
@@ -203,7 +203,7 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
        if (!root->ref_cows)
                return -EINVAL;
 
-       ret = btrfs_check_free_space(root, 1, 0);
+       ret = btrfs_check_metadata_free_space(root);
        if (ret)
                goto fail_unlock;
 
@@ -374,7 +374,7 @@ static int btrfs_defrag_file(struct file *file)
        unsigned long i;
        int ret;
 
-       ret = btrfs_check_free_space(root, inode->i_size, 0);
+       ret = btrfs_check_data_free_space(root, inode, inode->i_size);
        if (ret)
                return -ENOSPC;
 
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 39bd4d38e889878632b786b17a3951fa0aa2284a..45e59d3c7f1f5ae07d3c3a6dbde094b80dc78dac 100644 (file)
@@ -1913,6 +1913,9 @@ COMPATIBLE_IOCTL(FIONREAD)  /* This is also TIOCINQ */
 /* 0x00 */
 COMPATIBLE_IOCTL(FIBMAP)
 COMPATIBLE_IOCTL(FIGETBSZ)
+/* 'X' - originally XFS but some now in the VFS */
+COMPATIBLE_IOCTL(FIFREEZE)
+COMPATIBLE_IOCTL(FITHAW)
 /* RAID */
 COMPATIBLE_IOCTL(RAID_VERSION)
 COMPATIBLE_IOCTL(GET_ARRAY_INFO)
index 937df0fb0da5aefbb1a69b94c6a06afbe1747439..07e2d4a44bda3204c083a6e38ef79fe9b144d958 100644 (file)
@@ -1180,7 +1180,7 @@ struct dentry *d_obtain_alias(struct inode *inode)
        iput(inode);
        return res;
 }
-EXPORT_SYMBOL_GPL(d_obtain_alias);
+EXPORT_SYMBOL(d_obtain_alias);
 
 /**
  * d_splice_alias - splice a disconnected dentry into the tree if one exists
index 9a50b8052dcfab2865d34aebf54b459ec81e54b7..de9459b4cb943205c4bb40b442a486c657855f5e 100644 (file)
@@ -609,7 +609,9 @@ int ext4_claim_free_blocks(struct ext4_sb_info *sbi,
  */
 int ext4_should_retry_alloc(struct super_block *sb, int *retries)
 {
-       if (!ext4_has_free_blocks(EXT4_SB(sb), 1) || (*retries)++ > 3)
+       if (!ext4_has_free_blocks(EXT4_SB(sb), 1) ||
+           (*retries)++ > 3 ||
+           !EXT4_SB(sb)->s_journal)
                return 0;
 
        jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
index 4fb86a0061d033db005eb485d92263ede5120664..f18a919be70becf286c74364345a464e4d6e75e6 100644 (file)
@@ -715,6 +715,13 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
 
        if (sbi->s_log_groups_per_flex) {
                ret2 = find_group_flex(sb, dir, &group);
+               if (ret2 == -1) {
+                       ret2 = find_group_other(sb, dir, &group);
+                       if (ret2 == 0 && printk_ratelimit())
+                               printk(KERN_NOTICE "ext4: find_group_flex "
+                                      "failed, fallback succeeded dir %lu\n",
+                                      dir->i_ino);
+               }
                goto got_group;
        }
 
index cbd2ca99d11351d757f36194173ee716d89bdc4f..c7fed5b1874532ca17d1c1a2724f19096bda6c7e 100644 (file)
@@ -1368,6 +1368,10 @@ retry:
                goto out;
        }
 
+       /* We cannot recurse into the filesystem as the transaction is already
+        * started */
+       flags |= AOP_FLAG_NOFS;
+
        page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page) {
                ext4_journal_stop(handle);
@@ -1377,7 +1381,7 @@ retry:
        *pagep = page;
 
        ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
-                                                       ext4_get_block);
+                               ext4_get_block);
 
        if (!ret && ext4_should_journal_data(inode)) {
                ret = walk_page_buffers(handle, page_buffers(page),
@@ -2540,7 +2544,7 @@ retry:
 
                ext4_journal_stop(handle);
 
-               if (mpd.retval == -ENOSPC) {
+               if ((mpd.retval == -ENOSPC) && sbi->s_journal) {
                        /* commit the transaction which would
                         * free blocks released in the transaction
                         * and try again
@@ -2667,6 +2671,9 @@ retry:
                ret = PTR_ERR(handle);
                goto out;
        }
+       /* We cannot recurse into the filesystem as the transaction is already
+        * started */
+       flags |= AOP_FLAG_NOFS;
 
        page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page) {
index a5732c58f676747554a7b1c6da9a0c5e6787eb7b..39d1993cfa1370c3718dffd95231660f3dc606b4 100644 (file)
@@ -3091,7 +3091,6 @@ static int ext4_freeze(struct super_block *sb)
 
                /* Journal blocked and flushed, clear needs_recovery flag. */
                EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
-               ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
                error = ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
                if (error)
                        goto out;
index 3cceef4ad2b7df413e98b8171cadf074de83ad2d..e9580104b6ba477894b60c6bb3e69839c5677d2f 100644 (file)
@@ -95,13 +95,17 @@ static int jffs2_garbage_collect_thread(void *_c)
                        spin_unlock(&c->erase_completion_lock);
                        
 
-               /* This thread is purely an optimisation. But if it runs when
-                  other things could be running, it actually makes things a
-                  lot worse. Use yield() and put it at the back of the runqueue
-                  every time. Especially during boot, pulling an inode in
-                  with read_inode() is much preferable to having the GC thread
-                  get there first. */
-               yield();
+               /* Problem - immediately after bootup, the GCD spends a lot
+                * of time in places like jffs2_kill_fragtree(); so much so
+                * that userspace processes (like gdm and X) are starved
+                * despite plenty of cond_resched()s and renicing.  Yield()
+                * doesn't help, either (presumably because userspace and GCD
+                * are generally competing for a higher latency resource -
+                * disk).
+                * This forces the GCD to slow the hell down.   Pulling an
+                * inode in with read_inode() is much preferable to having
+                * the GC thread get there first. */
+               schedule_timeout_interruptible(msecs_to_jiffies(50));
 
                /* Put_super will send a SIGKILL and then wait on the sem.
                 */
index 6ca08ad887c09211bf98ab57cb1ec8578bd5d632..1fc1e92356eeb8f2a5c115082edf0109bb37a6db 100644 (file)
@@ -220,7 +220,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
                                struct jffs2_tmp_dnode_info *tn)
 {
        uint32_t fn_end = tn->fn->ofs + tn->fn->size;
-       struct jffs2_tmp_dnode_info *this;
+       struct jffs2_tmp_dnode_info *this, *ptn;
 
        dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw));
 
@@ -251,11 +251,18 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
        if (this) {
                /* If the node is coincident with another at a lower address,
                   back up until the other node is found. It may be relevant */
-               while (this->overlapped)
-                       this = tn_prev(this);
-
-               /* First node should never be marked overlapped */
-               BUG_ON(!this);
+               while (this->overlapped) {
+                       ptn = tn_prev(this);
+                       if (!ptn) {
+                               /*
+                                * We killed a node which set the overlapped
+                                * flags during the scan. Fix it up.
+                                */
+                               this->overlapped = 0;
+                               break;
+                       }
+                       this = ptn;
+               }
                dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole");
        }
 
@@ -360,7 +367,17 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
                        }
                        if (!this->overlapped)
                                break;
-                       this = tn_prev(this);
+
+                       ptn = tn_prev(this);
+                       if (!ptn) {
+                               /*
+                                * We killed a node which set the overlapped
+                                * flags during the scan. Fix it up.
+                                */
+                               this->overlapped = 0;
+                               break;
+                       }
+                       this = ptn;
                }
        }
 
@@ -456,8 +473,15 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c,
                eat_last(&rii->tn_root, &last->rb);
                ver_insert(&ver_root, last);
 
-               if (unlikely(last->overlapped))
-                       continue;
+               if (unlikely(last->overlapped)) {
+                       if (pen)
+                               continue;
+                       /*
+                        * We killed a node which set the overlapped
+                        * flags during the scan. Fix it up.
+                        */
+                       last->overlapped = 0;
+               }
 
                /* Now we have a bunch of nodes in reverse version
                   order, in the tree at ver_root. Most of the time,
index 60fe74035db5745fb541bdcc6983d3bb442e17ce..3a9e5deed74d5ec6900b3b531328ab21fb682a49 100644 (file)
@@ -4796,6 +4796,29 @@ out:
        return ret;
 }
 
+static int ocfs2_replace_extent_rec(struct inode *inode,
+                                   handle_t *handle,
+                                   struct ocfs2_path *path,
+                                   struct ocfs2_extent_list *el,
+                                   int split_index,
+                                   struct ocfs2_extent_rec *split_rec)
+{
+       int ret;
+
+       ret = ocfs2_path_bh_journal_access(handle, inode, path,
+                                          path_num_items(path) - 1);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       el->l_recs[split_index] = *split_rec;
+
+       ocfs2_journal_dirty(handle, path_leaf_bh(path));
+out:
+       return ret;
+}
+
 /*
  * Mark part or all of the extent record at split_index in the leaf
  * pointed to by path as written. This removes the unwritten
@@ -4885,7 +4908,9 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
 
        if (ctxt.c_contig_type == CONTIG_NONE) {
                if (ctxt.c_split_covers_rec)
-                       el->l_recs[split_index] = *split_rec;
+                       ret = ocfs2_replace_extent_rec(inode, handle,
+                                                      path, el,
+                                                      split_index, split_rec);
                else
                        ret = ocfs2_split_and_insert(inode, handle, path, et,
                                                     &last_eb_bh, split_index,
index 54e182a27caf81a86b96fb9cc133b5776346e028..0a2813947853dfd68372506b9fb43de894c3d577 100644 (file)
@@ -1849,12 +1849,12 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
                if (!mle) {
                        if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN &&
                            res->owner != assert->node_idx) {
-                               mlog(ML_ERROR, "assert_master from "
-                                         "%u, but current owner is "
-                                         "%u! (%.*s)\n",
-                                      assert->node_idx, res->owner,
-                                      namelen, name);
-                               goto kill;
+                               mlog(ML_ERROR, "DIE! Mastery assert from %u, "
+                                    "but current owner is %u! (%.*s)\n",
+                                    assert->node_idx, res->owner, namelen,
+                                    name);
+                               __dlm_print_one_lock_resource(res);
+                               BUG();
                        }
                } else if (mle->type != DLM_MLE_MIGRATION) {
                        if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN) {
index d1295203029fd927131e626c44f97def0433a918..4060bb328bc8a08c22bbd77c59835d757ebdcda5 100644 (file)
@@ -181,8 +181,7 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm,
 
                spin_lock(&res->spinlock);
                /* This ensures that clear refmap is sent after the set */
-               __dlm_wait_on_lockres_flags(res, (DLM_LOCK_RES_SETREF_INPROG |
-                                                 DLM_LOCK_RES_MIGRATING));
+               __dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG);
                spin_unlock(&res->spinlock);
 
                /* clear our bit from the master's refmap, ignore errors */
index 86ca085ef3246b8066d7f9f976b0866e7e63e168..fcf879ed69308e9518d0504428d3afbe13ee9f8f 100644 (file)
@@ -117,11 +117,11 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm,
        else
                BUG_ON(res->owner == dlm->node_num);
 
-       spin_lock(&dlm->spinlock);
+       spin_lock(&dlm->ast_lock);
        /* We want to be sure that we're not freeing a lock
         * that still has AST's pending... */
        in_use = !list_empty(&lock->ast_list);
-       spin_unlock(&dlm->spinlock);
+       spin_unlock(&dlm->ast_lock);
        if (in_use) {
               mlog(ML_ERROR, "lockres %.*s: Someone is calling dlmunlock "
                    "while waiting for an ast!", res->lockname.len,
index 206a2370876a8c82f4c6ad04f101a7d801be6e5b..7219a86d34ccc3102b360e10c298ed50fda903a7 100644 (file)
@@ -320,9 +320,14 @@ static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb,
                                        struct ocfs2_lock_res *lockres);
 static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,
                                                int convert);
-#define ocfs2_log_dlm_error(_func, _err, _lockres) do {                        \
-       mlog(ML_ERROR, "DLM error %d while calling %s on resource %s\n", \
-            _err, _func, _lockres->l_name);                            \
+#define ocfs2_log_dlm_error(_func, _err, _lockres) do {                                        \
+       if ((_lockres)->l_type != OCFS2_LOCK_TYPE_DENTRY)                               \
+               mlog(ML_ERROR, "DLM error %d while calling %s on resource %s\n",        \
+                    _err, _func, _lockres->l_name);                                    \
+       else                                                                            \
+               mlog(ML_ERROR, "DLM error %d while calling %s on resource %.*s%08x\n",  \
+                    _err, _func, OCFS2_DENTRY_LOCK_INO_START - 1, (_lockres)->l_name,  \
+                    (unsigned int)ocfs2_get_dentry_lock_ino(_lockres));                \
 } while (0)
 static int ocfs2_downconvert_thread(void *arg);
 static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb,
index 077384135f4ea763cd30105b9df51521b9565227..946d3c34b90ba29e0e1cc0d44df7ca9bfe1878f5 100644 (file)
@@ -341,6 +341,9 @@ struct ocfs2_super
        struct ocfs2_node_map           osb_recovering_orphan_dirs;
        unsigned int                    *osb_orphan_wipes;
        wait_queue_head_t               osb_wipe_event;
+
+       /* used to protect metaecc calculation check of xattr. */
+       spinlock_t osb_xattr_lock;
 };
 
 #define OCFS2_SB(sb)       ((struct ocfs2_super *)(sb)->s_fs_info)
index b1cb38fbe80706817a2fdf6be8dda71f348eb568..7ac83a81ee55d86466329d7f9b568432666b5144 100644 (file)
@@ -1537,6 +1537,13 @@ static int ocfs2_get_sector(struct super_block *sb,
        unlock_buffer(*bh);
        ll_rw_block(READ, 1, bh);
        wait_on_buffer(*bh);
+       if (!buffer_uptodate(*bh)) {
+               mlog_errno(-EIO);
+               brelse(*bh);
+               *bh = NULL;
+               return -EIO;
+       }
+
        return 0;
 }
 
@@ -1747,6 +1754,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
        INIT_LIST_HEAD(&osb->blocked_lock_list);
        osb->blocked_lock_count = 0;
        spin_lock_init(&osb->osb_lock);
+       spin_lock_init(&osb->osb_xattr_lock);
        ocfs2_init_inode_steal_slot(osb);
 
        atomic_set(&osb->alloc_stats.moves, 0);
index 915039fffe6ed37149a47d1929929f79b0865d5c..4ddd788add67bcc9df070da373a47e9105b0c242 100644 (file)
@@ -82,13 +82,14 @@ struct ocfs2_xattr_set_ctxt {
 
 #define OCFS2_XATTR_ROOT_SIZE  (sizeof(struct ocfs2_xattr_def_value_root))
 #define OCFS2_XATTR_INLINE_SIZE        80
+#define OCFS2_XATTR_HEADER_GAP 4
 #define OCFS2_XATTR_FREE_IN_IBODY      (OCFS2_MIN_XATTR_INLINE_SIZE \
                                         - sizeof(struct ocfs2_xattr_header) \
-                                        - sizeof(__u32))
+                                        - OCFS2_XATTR_HEADER_GAP)
 #define OCFS2_XATTR_FREE_IN_BLOCK(ptr) ((ptr)->i_sb->s_blocksize \
                                         - sizeof(struct ocfs2_xattr_block) \
                                         - sizeof(struct ocfs2_xattr_header) \
-                                        - sizeof(__u32))
+                                        - OCFS2_XATTR_HEADER_GAP)
 
 static struct ocfs2_xattr_def_value_root def_xv = {
        .xv.xr_list.l_count = cpu_to_le16(1),
@@ -274,10 +275,12 @@ static int ocfs2_read_xattr_bucket(struct ocfs2_xattr_bucket *bucket,
                               bucket->bu_blocks, bucket->bu_bhs, 0,
                               NULL);
        if (!rc) {
+               spin_lock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock);
                rc = ocfs2_validate_meta_ecc_bhs(bucket->bu_inode->i_sb,
                                                 bucket->bu_bhs,
                                                 bucket->bu_blocks,
                                                 &bucket_xh(bucket)->xh_check);
+               spin_unlock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock);
                if (rc)
                        mlog_errno(rc);
        }
@@ -310,9 +313,11 @@ static void ocfs2_xattr_bucket_journal_dirty(handle_t *handle,
 {
        int i;
 
+       spin_lock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock);
        ocfs2_compute_meta_ecc_bhs(bucket->bu_inode->i_sb,
                                   bucket->bu_bhs, bucket->bu_blocks,
                                   &bucket_xh(bucket)->xh_check);
+       spin_unlock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock);
 
        for (i = 0; i < bucket->bu_blocks; i++)
                ocfs2_journal_dirty(handle, bucket->bu_bhs[i]);
@@ -1507,7 +1512,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
                last += 1;
        }
 
-       free = min_offs - ((void *)last - xs->base) - sizeof(__u32);
+       free = min_offs - ((void *)last - xs->base) - OCFS2_XATTR_HEADER_GAP;
        if (free < 0)
                return -EIO;
 
@@ -2190,7 +2195,7 @@ static int ocfs2_xattr_can_be_in_inode(struct inode *inode,
                last += 1;
        }
 
-       free = min_offs - ((void *)last - xs->base) - sizeof(__u32);
+       free = min_offs - ((void *)last - xs->base) - OCFS2_XATTR_HEADER_GAP;
        if (free < 0)
                return 0;
 
@@ -2592,8 +2597,9 @@ static int __ocfs2_xattr_set_handle(struct inode *inode,
 
        if (!ret) {
                /* Update inode ctime. */
-               ret = ocfs2_journal_access(ctxt->handle, inode, xis->inode_bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_journal_access_di(ctxt->handle, inode,
+                                             xis->inode_bh,
+                                             OCFS2_JOURNAL_ACCESS_WRITE);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -5060,8 +5066,8 @@ try_again:
        xh_free_start = le16_to_cpu(xh->xh_free_start);
        header_size = sizeof(struct ocfs2_xattr_header) +
                        count * sizeof(struct ocfs2_xattr_entry);
-       max_free = OCFS2_XATTR_BUCKET_SIZE -
-               le16_to_cpu(xh->xh_name_value_len) - header_size;
+       max_free = OCFS2_XATTR_BUCKET_SIZE - header_size -
+               le16_to_cpu(xh->xh_name_value_len) - OCFS2_XATTR_HEADER_GAP;
 
        mlog_bug_on_msg(header_size > blocksize, "bucket %llu has header size "
                        "of %u which exceed block size\n",
@@ -5094,7 +5100,7 @@ try_again:
                        need = 0;
        }
 
-       free = xh_free_start - header_size;
+       free = xh_free_start - header_size - OCFS2_XATTR_HEADER_GAP;
        /*
         * We need to make sure the new name/value pair
         * can exist in the same block.
@@ -5127,7 +5133,8 @@ try_again:
                        }
 
                        xh_free_start = le16_to_cpu(xh->xh_free_start);
-                       free = xh_free_start - header_size;
+                       free = xh_free_start - header_size
+                               - OCFS2_XATTR_HEADER_GAP;
                        if (xh_free_start % blocksize < need)
                                free -= xh_free_start % blocksize;
 
index 3e76bb9b3ad668d8ceab574a8f6d7d4a5f2e6ef6..d8bb5c671f420a83c17c740425e6f71f9d85799e 100644 (file)
@@ -485,8 +485,10 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
                        }
                }
                unlock_new_inode(inode);
-       } else
+       } else {
               module_put(de->owner);
+              de_put(de);
+       }
        return inode;
 
 out_ino:
index 767d95a6d1b1bfdd713226915fb20bcca921347d..2d1345112a42d83ea0317dcd551e4766fb879bb8 100644 (file)
@@ -107,7 +107,7 @@ static ssize_t kpageflags_read(struct file *file, char __user *buf,
                else
                        kflags = ppage->flags;
 
-               uflags = kpf_copy_bit(KPF_LOCKED, PG_locked, kflags) |
+               uflags = kpf_copy_bit(kflags, KPF_LOCKED, PG_locked) |
                        kpf_copy_bit(kflags, KPF_ERROR, PG_error) |
                        kpf_copy_bit(kflags, KPF_REFERENCED, PG_referenced) |
                        kpf_copy_bit(kflags, KPF_UPTODATE, PG_uptodate) |
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 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..c7d4b2e606a5f73f5fbed9217449b16c504b7e4d 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 {
@@ -76,6 +76,7 @@ struct drm_encoder_helper_funcs {
        void (*mode_set)(struct drm_encoder *encoder,
                         struct drm_display_mode *mode,
                         struct drm_display_mode *adjusted_mode);
+       struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder);
        /* detect for DAC style encoders */
        enum drm_connector_status (*detect)(struct drm_encoder *encoder,
                                            struct drm_connector *connector);
index c707c15f5164ef3a9410dbc98d246f34189be804..ff8d27af47869b611067a2bef26c140042bf03d7 100644 (file)
@@ -58,10 +58,10 @@ struct detailed_pixel_timing {
        u8 hsync_pulse_width_lo;
        u8 vsync_pulse_width_lo:4;
        u8 vsync_offset_lo:4;
-       u8 hsync_pulse_width_hi:2;
-       u8 hsync_offset_hi:2;
        u8 vsync_pulse_width_hi:2;
        u8 vsync_offset_hi:2;
+       u8 hsync_pulse_width_hi:2;
+       u8 hsync_offset_hi:2;
        u8 width_mm_lo;
        u8 height_mm_lo;
        u8 height_mm_hi:4;
index b97cdc516a8fcb078e29f1b2745db7f6040a880a..106c3ba50844459b463c4fcaea0cad40a9baf026 100644 (file)
@@ -52,6 +52,7 @@ header-y += const.h
 header-y += cgroupstats.h
 header-y += cramfs_fs.h
 header-y += cycx_cfm.h
+header-y += dcbnl.h
 header-y += dlmconstants.h
 header-y += dlm_device.h
 header-y += dlm_netlink.h
index dcaa0fd84b02c36453f8d7cc211c5eaf3d12aa7b..465d6babc847a2603d4f23a5e842cd7dc07b308e 100644 (file)
@@ -708,6 +708,8 @@ struct req_iterator {
 };
 
 /* This should not be used directly - use rq_for_each_segment */
+#define for_each_bio(_bio)             \
+       for (; _bio; _bio = _bio->bi_next)
 #define __rq_for_each_bio(_bio, rq)    \
        if ((rq->bio))                  \
                for (_bio = (rq)->bio; _bio; _bio = _bio->bi_next)
index 1514d534deebb7f52361d1ef27382ac791ba955f..a3ed7cb8ca346e7fba7170022c46928480b896a6 100644 (file)
 #define __deprecated                   __attribute__((deprecated))
 #define __packed                       __attribute__((packed))
 #define __weak                         __attribute__((weak))
-#define __naked                                __attribute__((naked))
+
+/*
+ * it doesn't make sense on ARM (currently the only user of __naked) to trace
+ * naked functions because then mcount is called without stack and frame pointer
+ * being set up and there is no chance to restore the lr register to the value
+ * before mcount was called.
+ */
+#define __naked                                __attribute__((naked)) notrace
+
 #define __noreturn                     __attribute__((noreturn))
 
 /*
index b0ef274e00319d575082168ef3bb763fdf6447b9..7d2e10006188415694e16bcbba545f6fd28381de 100644 (file)
 #ifndef __LINUX_DCBNL_H__
 #define __LINUX_DCBNL_H__
 
+#include <linux/types.h>
+
 #define DCB_PROTO_VERSION 1
 
 struct dcbmsg {
-       unsigned char      dcb_family;
+       __u8               dcb_family;
        __u8               cmd;
        __u16              dcb_pad;
 };
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 311315b56b611a7b2b9d44a2b930eb8c3b9b8def..fd53bfd2647044be7d48d26adc4de31b6c5d238e 100644 (file)
@@ -33,7 +33,7 @@
  */
 #define I2C_RETRIES    0x0701  /* number of times a device address should
                                   be polled when not acknowledging */
-#define I2C_TIMEOUT    0x0702  /* set timeout in jiffies - call with int */
+#define I2C_TIMEOUT    0x0702  /* set timeout in units of 10 ms */
 
 /* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses
  * are NOT supported! (due to code brokenness)
index fcfbfea3af72d670d7100ca221014c7dece36363..c86c3b07604c2cf46cd492ef948e826f2d9c58d0 100644 (file)
@@ -361,7 +361,7 @@ struct i2c_adapter {
        struct mutex bus_lock;
        struct mutex clist_lock;
 
-       int timeout;
+       int timeout;                    /* in jiffies */
        int retries;
        struct device dev;              /* the adapter device */
 
index 194da5a4b0d683a0d0c42628c00f2c3459ac109d..fe235b65207ee74d43e74818d94bdaf6759816d5 100644 (file)
@@ -663,7 +663,7 @@ typedef struct ide_drive_s ide_drive_t;
 #define to_ide_device(dev)             container_of(dev, ide_drive_t, gendev)
 
 #define to_ide_drv(obj, cont_type)     \
-       container_of(obj, struct cont_type, kref)
+       container_of(obj, struct cont_type, dev)
 
 #define ide_drv_g(disk, cont_type)     \
        container_of((disk)->private_data, struct cont_type, driver)
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 c4f6c101dbcddd91e0b7d045a345a4d6fba28777..d2e3cbfba14f45ea30b34bc78e36735c5db2755d 100644 (file)
@@ -194,6 +194,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
 /* FSTS_REG */
 #define DMA_FSTS_PPF ((u32)2)
 #define DMA_FSTS_PFO ((u32)1)
+#define DMA_FSTS_IQE (1 << 4)
 #define dma_fsts_fault_record_index(s) (((s) >> 8) & 0xff)
 
 /* FRCD_REG, 32 bits access */
@@ -328,7 +329,7 @@ extern int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
                          unsigned int size_order, u64 type,
                          int non_present_entry_flush);
 
-extern void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);
+extern int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);
 
 extern void *intel_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t);
 extern void intel_free_coherent(struct device *, size_t, void *, dma_addr_t);
index 82df31726a546de40a1d010c588f56f7c1d3955c..0adb0f91568c1cfd407b1e88c1dce5b39d0080d5 100644 (file)
  * See Documentation/io_mapping.txt
  */
 
-/* this struct isn't actually defined anywhere */
-struct io_mapping;
-
 #ifdef CONFIG_HAVE_ATOMIC_IOMAP
 
+struct io_mapping {
+       resource_size_t base;
+       unsigned long size;
+       pgprot_t prot;
+};
+
 /*
  * For small address space machines, mapping large objects
  * into the kernel virtual space isn't practical. Where
@@ -43,23 +46,40 @@ struct io_mapping;
  */
 
 static inline struct io_mapping *
-io_mapping_create_wc(unsigned long base, unsigned long size)
+io_mapping_create_wc(resource_size_t base, unsigned long size)
 {
-       return (struct io_mapping *) base;
+       struct io_mapping *iomap;
+
+       if (!is_io_mapping_possible(base, size))
+               return NULL;
+
+       iomap = kmalloc(sizeof(*iomap), GFP_KERNEL);
+       if (!iomap)
+               return NULL;
+
+       iomap->base = base;
+       iomap->size = size;
+       iomap->prot = pgprot_writecombine(__pgprot(__PAGE_KERNEL));
+       return iomap;
 }
 
 static inline void
 io_mapping_free(struct io_mapping *mapping)
 {
+       kfree(mapping);
 }
 
 /* Atomic map/unmap */
 static inline void *
 io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset)
 {
-       offset += (unsigned long) mapping;
-       return iomap_atomic_prot_pfn(offset >> PAGE_SHIFT, KM_USER0,
-                                    __pgprot(__PAGE_KERNEL_WC));
+       resource_size_t phys_addr;
+       unsigned long pfn;
+
+       BUG_ON(offset >= mapping->size);
+       phys_addr = mapping->base + offset;
+       pfn = (unsigned long) (phys_addr >> PAGE_SHIFT);
+       return iomap_atomic_prot_pfn(pfn, KM_USER0, mapping->prot);
 }
 
 static inline void
@@ -71,8 +91,12 @@ io_mapping_unmap_atomic(void *vaddr)
 static inline void *
 io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
 {
-       offset += (unsigned long) mapping;
-       return ioremap_wc(offset, PAGE_SIZE);
+       resource_size_t phys_addr;
+
+       BUG_ON(offset >= mapping->size);
+       phys_addr = mapping->base + offset;
+
+       return ioremap_wc(phys_addr, PAGE_SIZE);
 }
 
 static inline void
@@ -83,9 +107,12 @@ io_mapping_unmap(void *vaddr)
 
 #else
 
+/* this struct isn't actually defined anywhere */
+struct io_mapping;
+
 /* Create the io_mapping object*/
 static inline struct io_mapping *
-io_mapping_create_wc(unsigned long base, unsigned long size)
+io_mapping_create_wc(resource_size_t base, unsigned long size)
 {
        return (struct io_mapping *) ioremap_wc(base, size);
 }
index cdcd0ed58f7aced31dd8f909452a9d7e2dcb1bd8..4b36aeb46a102a14f7b261cbbd00819243e920da 100644 (file)
@@ -2,7 +2,7 @@
 #define _XT_NFLOG_TARGET
 
 #define XT_NFLOG_DEFAULT_GROUP         0x1
-#define XT_NFLOG_DEFAULT_THRESHOLD     1
+#define XT_NFLOG_DEFAULT_THRESHOLD     0
 
 #define XT_NFLOG_MASK                  0x0
 
index 114b8192eab93cd8394d07713534140ed0551f81..aca8c458aa8a7a23e87198ce8a9cb9eba8f3d87b 100644 (file)
 #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 f3f697df1d71b439b677efbc0da952ae6d25d066..80044a4f3ab9e1c890021fc0ff9dca533c00f71e 100644 (file)
@@ -181,4 +181,10 @@ extern long rcu_batches_completed_bh(void);
 #define rcu_enter_nohz()       do { } while (0)
 #define rcu_exit_nohz()                do { } while (0)
 
+/* A context switch is a grace period for rcuclassic. */
+static inline int rcu_blocking_is_gp(void)
+{
+       return num_online_cpus() == 1;
+}
+
 #endif /* __LINUX_RCUCLASSIC_H */
index 921340a7b71cf4c88638e2f905aa0fdc1385f958..528343e6da51a7c19cda8797c55cd6640612cb58 100644 (file)
@@ -52,6 +52,9 @@ struct rcu_head {
        void (*func)(struct rcu_head *head);
 };
 
+/* Internal to kernel, but needed by rcupreempt.h. */
+extern int rcu_scheduler_active;
+
 #if defined(CONFIG_CLASSIC_RCU)
 #include <linux/rcuclassic.h>
 #elif defined(CONFIG_TREE_RCU)
@@ -265,6 +268,7 @@ extern void rcu_barrier_sched(void);
 
 /* Internal to kernel */
 extern void rcu_init(void);
+extern void rcu_scheduler_starting(void);
 extern int rcu_needs_cpu(int cpu);
 
 #endif /* __LINUX_RCUPDATE_H */
index 3e05c09b54a22408db83e0f0a87a5a8bf9a40e8f..74304b4538d833ec7bcd26be28bdec8f436d73f7 100644 (file)
@@ -142,4 +142,19 @@ static inline void rcu_exit_nohz(void)
 #define rcu_exit_nohz()                do { } while (0)
 #endif /* CONFIG_NO_HZ */
 
+/*
+ * A context switch is a grace period for rcupreempt synchronize_rcu()
+ * only during early boot, before the scheduler has been initialized.
+ * So, how the heck do we get a context switch?  Well, if the caller
+ * invokes synchronize_rcu(), they are willing to accept a context
+ * switch, so we simply pretend that one happened.
+ *
+ * After boot, there might be a blocked or preempted task in an RCU
+ * read-side critical section, so we cannot then take the fastpath.
+ */
+static inline int rcu_blocking_is_gp(void)
+{
+       return num_online_cpus() == 1 && !rcu_scheduler_active;
+}
+
 #endif /* __LINUX_RCUPREEMPT_H */
index d4368b7975c3d09d5b1c08d2a822adebb06e62ac..a722fb67bb2d5a2500852c4fd5593f0e91777af0 100644 (file)
@@ -326,4 +326,10 @@ static inline void rcu_exit_nohz(void)
 }
 #endif /* CONFIG_NO_HZ */
 
+/* A context switch is a grace period for rcutree. */
+static inline int rcu_blocking_is_gp(void)
+{
+       return num_online_cpus() == 1;
+}
+
 #endif /* __LINUX_RCUTREE_H */
index 8981e52c714f05f19ad5727031058509e06bf6a8..8c216e057c94230ea01c110b0f5bc2c28e8f9ee3 100644 (file)
@@ -2291,9 +2291,13 @@ extern long sched_group_rt_runtime(struct task_group *tg);
 extern int sched_group_set_rt_period(struct task_group *tg,
                                      long rt_period_us);
 extern long sched_group_rt_period(struct task_group *tg);
+extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
 #endif
 #endif
 
+extern int task_can_switch_user(struct user_struct *up,
+                                       struct task_struct *tsk);
+
 #ifdef CONFIG_TASK_XACCT
 static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
 {
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 315bcd375224869a0e54cbaab27274588452d4d3..cc4f45361dbbc8a956f9a9fad2a865dc7f4add33 100644 (file)
@@ -13,6 +13,7 @@ struct user_namespace {
        struct kref             kref;
        struct hlist_head       uidhash_table[UIDHASH_SZ];
        struct user_struct      *creator;
+       struct work_struct      destroyer;
 };
 
 extern struct user_namespace init_user_ns;
index e78afe7f28e35ad48204b83bd43dfc5d710d2f1c..c25068e385169b3aee21594df68446696756ad91 100644 (file)
@@ -59,7 +59,7 @@ static inline int nf_conntrack_confirm(struct sk_buff *skb)
        struct nf_conn *ct = (struct nf_conn *)skb->nfct;
        int ret = NF_ACCEPT;
 
-       if (ct) {
+       if (ct && ct != &nf_conntrack_untracked) {
                if (!nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
                        ret = __nf_conntrack_confirm(skb);
                nf_ct_deliver_cached_events(ct);
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 844209453c02c2248114972fca3f0fcddbdf513d..83697e160b3a786d3d91c14000f116a441f61bfc 100644 (file)
@@ -97,7 +97,7 @@ static inline void mark_rodata_ro(void) { }
 extern void tc_init(void);
 #endif
 
-enum system_states system_state;
+enum system_states system_state __read_mostly;
 EXPORT_SYMBOL(system_state);
 
 /*
@@ -463,6 +463,7 @@ static noinline void __init_refok rest_init(void)
         * at least once to get things moving:
         */
        init_idle_bootup_task(current);
+       rcu_scheduler_starting();
        preempt_enable_no_resched();
        schedule();
        preempt_disable();
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 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 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 bd5a9003497c200d7ef7a44ec252b2d96b2ac562..654c640a6b9c137b6a44c1e57159fbdeeac48b61 100644 (file)
@@ -679,8 +679,8 @@ int rcu_needs_cpu(int cpu)
 void rcu_check_callbacks(int cpu, int user)
 {
        if (user ||
-           (idle_cpu(cpu) && !in_softirq() &&
-                               hardirq_count() <= (1 << HARDIRQ_SHIFT))) {
+           (idle_cpu(cpu) && rcu_scheduler_active &&
+            !in_softirq() && hardirq_count() <= (1 << HARDIRQ_SHIFT))) {
 
                /*
                 * Get here if this CPU took its interrupt from user
index d92a76a881aa47a9aa059c3221910834f6c50cf8..cae8a059cf47f4fab142b001c5f4d25ec8e95006 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/cpu.h>
 #include <linux/mutex.h>
 #include <linux/module.h>
+#include <linux/kernel_stat.h>
 
 enum rcu_barrier {
        RCU_BARRIER_STD,
@@ -55,6 +56,7 @@ static DEFINE_PER_CPU(struct rcu_head, rcu_barrier_head) = {NULL};
 static atomic_t rcu_barrier_cpu_count;
 static DEFINE_MUTEX(rcu_barrier_mutex);
 static struct completion rcu_barrier_completion;
+int rcu_scheduler_active __read_mostly;
 
 /*
  * Awaken the corresponding synchronize_rcu() instance now that a
@@ -80,6 +82,10 @@ void wakeme_after_rcu(struct rcu_head  *head)
 void synchronize_rcu(void)
 {
        struct rcu_synchronize rcu;
+
+       if (rcu_blocking_is_gp())
+               return;
+
        init_completion(&rcu.completion);
        /* Will wake me after RCU finished. */
        call_rcu(&rcu.head, wakeme_after_rcu);
@@ -175,3 +181,9 @@ void __init rcu_init(void)
        __rcu_init();
 }
 
+void rcu_scheduler_starting(void)
+{
+       WARN_ON(num_online_cpus() != 1);
+       WARN_ON(nr_context_switches() > 0);
+       rcu_scheduler_active = 1;
+}
index 33cfc50781f9968d06e79edcb93049441a2a4231..5d59e850fb71f6f58b854cdbd0a1f1792f59c8ad 100644 (file)
@@ -1181,6 +1181,9 @@ void __synchronize_sched(void)
 {
        struct rcu_synchronize rcu;
 
+       if (num_online_cpus() == 1)
+               return;  /* blocking is gp if only one CPU! */
+
        init_completion(&rcu.completion);
        /* Will wake me after RCU finished. */
        call_rcu_sched(&rcu.head, wakeme_after_rcu);
index b2fd602a6f6f0433553a36a79e3a24172a8a2a2f..97ce31579ec0664682e1b2efb792cd77e7c0030e 100644 (file)
@@ -948,8 +948,8 @@ static void rcu_do_batch(struct rcu_data *rdp)
 void rcu_check_callbacks(int cpu, int user)
 {
        if (user ||
-           (idle_cpu(cpu) && !in_softirq() &&
-                               hardirq_count() <= (1 << HARDIRQ_SHIFT))) {
+           (idle_cpu(cpu) && rcu_scheduler_active &&
+            !in_softirq() && hardirq_count() <= (1 << HARDIRQ_SHIFT))) {
 
                /*
                 * Get here if this CPU took its interrupt from user
index 410eec404133fd267eb80041395e21d266f0e552..8e2558c2ba67be440ef7bcb2d95ff8138c806404 100644 (file)
@@ -223,7 +223,7 @@ static void start_rt_bandwidth(struct rt_bandwidth *rt_b)
 {
        ktime_t now;
 
-       if (rt_bandwidth_enabled() && rt_b->rt_runtime == RUNTIME_INF)
+       if (!rt_bandwidth_enabled() || rt_b->rt_runtime == RUNTIME_INF)
                return;
 
        if (hrtimer_active(&rt_b->rt_period_timer))
@@ -9224,6 +9224,16 @@ static int sched_rt_global_constraints(void)
 
        return ret;
 }
+
+int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
+{
+       /* Don't accept realtime tasks when there is no way for them to run */
+       if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
+               return 0;
+
+       return 1;
+}
+
 #else /* !CONFIG_RT_GROUP_SCHED */
 static int sched_rt_global_constraints(void)
 {
@@ -9317,8 +9327,7 @@ cpu_cgroup_can_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
                      struct task_struct *tsk)
 {
 #ifdef CONFIG_RT_GROUP_SCHED
-       /* Don't accept realtime tasks when there is no way for them to run */
-       if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
+       if (!sched_rt_can_attach(cgroup_tg(cgrp), tsk))
                return -EINVAL;
 #else
        /* We don't support RT-tasks being in separate groups */
index ad64fcb731f231d22e539d0e1b094cdd59c7d759..57d4b13b631de36161349feb99ae6f76a2984b06 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/seccomp.h>
 #include <linux/sched.h>
+#include <linux/compat.h>
 
 /* #define SECCOMP_DEBUG 1 */
 #define NR_SECCOMP_MODES 1
@@ -22,7 +23,7 @@ static int mode1_syscalls[] = {
        0, /* null terminated */
 };
 
-#ifdef TIF_32BIT
+#ifdef CONFIG_COMPAT
 static int mode1_syscalls_32[] = {
        __NR_seccomp_read_32, __NR_seccomp_write_32, __NR_seccomp_exit_32, __NR_seccomp_sigreturn_32,
        0, /* null terminated */
@@ -37,8 +38,8 @@ void __secure_computing(int this_syscall)
        switch (mode) {
        case 1:
                syscall = mode1_syscalls;
-#ifdef TIF_32BIT
-               if (test_thread_flag(TIF_32BIT))
+#ifdef CONFIG_COMPAT
+               if (is_compat_task())
                        syscall = mode1_syscalls_32;
 #endif
                do {
index f145c415bc160e62b6d888cf6fa9d3198c00b4a7..37f458e6882adbd1f2b0697e5077c92e4252e03f 100644 (file)
@@ -559,7 +559,7 @@ error:
        abort_creds(new);
        return retval;
 }
-  
+
 /*
  * change the user struct in a credentials set to match the new UID
  */
@@ -571,6 +571,11 @@ static int set_user(struct cred *new)
        if (!new_user)
                return -EAGAIN;
 
+       if (!task_can_switch_user(new_user, current)) {
+               free_uid(new_user);
+               return -EINVAL;
+       }
+
        if (atomic_read(&new_user->processes) >=
                                current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
                        new_user != INIT_USER) {
@@ -631,10 +636,11 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
                        goto error;
        }
 
-       retval = -EAGAIN;
-       if (new->uid != old->uid && set_user(new) < 0)
-               goto error;
-
+       if (new->uid != old->uid) {
+               retval = set_user(new);
+               if (retval < 0)
+                       goto error;
+       }
        if (ruid != (uid_t) -1 ||
            (euid != (uid_t) -1 && euid != old->uid))
                new->suid = new->euid;
@@ -680,9 +686,10 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
        retval = -EPERM;
        if (capable(CAP_SETUID)) {
                new->suid = new->uid = uid;
-               if (uid != old->uid && set_user(new) < 0) {
-                       retval = -EAGAIN;
-                       goto error;
+               if (uid != old->uid) {
+                       retval = set_user(new);
+                       if (retval < 0)
+                               goto error;
                }
        } else if (uid != old->uid && uid != new->suid) {
                goto error;
@@ -734,11 +741,13 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
                        goto error;
        }
 
-       retval = -EAGAIN;
        if (ruid != (uid_t) -1) {
                new->uid = ruid;
-               if (ruid != old->uid && set_user(new) < 0)
-                       goto error;
+               if (ruid != old->uid) {
+                       retval = set_user(new);
+                       if (retval < 0)
+                               goto error;
+               }
        }
        if (euid != (uid_t) -1)
                new->euid = euid;
index 3551ac742395c40af9edeb7d94d0d0b936caba9b..6a9b696128c855f9ddacfc9e3a7a128141379e49 100644 (file)
@@ -362,6 +362,24 @@ static void free_user(struct user_struct *up, unsigned long flags)
 
 #endif
 
+#if defined(CONFIG_RT_GROUP_SCHED) && defined(CONFIG_USER_SCHED)
+/*
+ * We need to check if a setuid can take place. This function should be called
+ * before successfully completing the setuid.
+ */
+int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
+{
+
+       return sched_rt_can_attach(up->tg, tsk);
+
+}
+#else
+int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
+{
+       return 1;
+}
+#endif
+
 /*
  * Locate the user_struct for the passed UID.  If found, take a ref on it.  The
  * caller must undo that ref with free_uid().
index 79084311ee5779a1e12b411ff37a5f04da08e360..076c7c8215b0e15289130fa5339bfc26dced7514 100644 (file)
@@ -60,12 +60,25 @@ int create_user_ns(struct cred *new)
        return 0;
 }
 
-void free_user_ns(struct kref *kref)
+/*
+ * Deferred destructor for a user namespace.  This is required because
+ * free_user_ns() may be called with uidhash_lock held, but we need to call
+ * back to free_uid() which will want to take the lock again.
+ */
+static void free_user_ns_work(struct work_struct *work)
 {
-       struct user_namespace *ns;
-
-       ns = container_of(kref, struct user_namespace, kref);
+       struct user_namespace *ns =
+               container_of(work, struct user_namespace, destroyer);
        free_uid(ns->creator);
        kfree(ns);
 }
+
+void free_user_ns(struct kref *kref)
+{
+       struct user_namespace *ns =
+               container_of(kref, struct user_namespace, kref);
+
+       INIT_WORK(&ns->destroyer, free_user_ns_work);
+       schedule_work(&ns->destroyer);
+}
 EXPORT_SYMBOL(free_user_ns);
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 19d566ccdeeab8c6a1f0431602b3bd3dd5a76026..4103a239ce843326faca51c61c5b0b105797b24b 100644 (file)
@@ -169,13 +169,13 @@ static inline struct shmem_sb_info *SHMEM_SB(struct super_block *sb)
  */
 static inline int shmem_acct_size(unsigned long flags, loff_t size)
 {
-       return (flags & VM_ACCOUNT) ?
-               security_vm_enough_memory_kern(VM_ACCT(size)) : 0;
+       return (flags & VM_NORESERVE) ?
+               0 : security_vm_enough_memory_kern(VM_ACCT(size));
 }
 
 static inline void shmem_unacct_size(unsigned long flags, loff_t size)
 {
-       if (flags & VM_ACCOUNT)
+       if (!(flags & VM_NORESERVE))
                vm_unacct_memory(VM_ACCT(size));
 }
 
@@ -187,13 +187,13 @@ static inline void shmem_unacct_size(unsigned long flags, loff_t size)
  */
 static inline int shmem_acct_block(unsigned long flags)
 {
-       return (flags & VM_ACCOUNT) ?
-               0 : security_vm_enough_memory_kern(VM_ACCT(PAGE_CACHE_SIZE));
+       return (flags & VM_NORESERVE) ?
+               security_vm_enough_memory_kern(VM_ACCT(PAGE_CACHE_SIZE)) : 0;
 }
 
 static inline void shmem_unacct_blocks(unsigned long flags, long pages)
 {
-       if (!(flags & VM_ACCOUNT))
+       if (flags & VM_NORESERVE)
                vm_unacct_memory(pages * VM_ACCT(PAGE_CACHE_SIZE));
 }
 
@@ -1515,8 +1515,8 @@ static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
-static struct inode *
-shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
+static struct inode *shmem_get_inode(struct super_block *sb, int mode,
+                                       dev_t dev, unsigned long flags)
 {
        struct inode *inode;
        struct shmem_inode_info *info;
@@ -1537,6 +1537,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
                info = SHMEM_I(inode);
                memset(info, 0, (char *)inode - (char *)info);
                spin_lock_init(&info->lock);
+               info->flags = flags & VM_NORESERVE;
                INIT_LIST_HEAD(&info->swaplist);
 
                switch (mode & S_IFMT) {
@@ -1779,9 +1780,10 @@ static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
 static int
 shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 {
-       struct inode *inode = shmem_get_inode(dir->i_sb, mode, dev);
+       struct inode *inode;
        int error = -ENOSPC;
 
+       inode = shmem_get_inode(dir->i_sb, mode, dev, VM_NORESERVE);
        if (inode) {
                error = security_inode_init_security(inode, dir, NULL, NULL,
                                                     NULL);
@@ -1920,7 +1922,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
        if (len > PAGE_CACHE_SIZE)
                return -ENAMETOOLONG;
 
-       inode = shmem_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
+       inode = shmem_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0, VM_NORESERVE);
        if (!inode)
                return -ENOSPC;
 
@@ -2332,7 +2334,7 @@ static int shmem_fill_super(struct super_block *sb,
        sb->s_flags |= MS_POSIXACL;
 #endif
 
-       inode = shmem_get_inode(sb, S_IFDIR | sbinfo->mode, 0);
+       inode = shmem_get_inode(sb, S_IFDIR | sbinfo->mode, 0, VM_NORESERVE);
        if (!inode)
                goto failed;
        inode->i_uid = sbinfo->uid;
@@ -2574,12 +2576,12 @@ int shmem_unuse(swp_entry_t entry, struct page *page)
        return 0;
 }
 
-#define shmem_file_operations ramfs_file_operations
-#define shmem_vm_ops generic_file_vm_ops
-#define shmem_get_inode ramfs_get_inode
-#define shmem_acct_size(a, b) 0
-#define shmem_unacct_size(a, b) do {} while (0)
-#define SHMEM_MAX_BYTES LLONG_MAX
+#define shmem_vm_ops                           generic_file_vm_ops
+#define shmem_file_operations                  ramfs_file_operations
+#define shmem_get_inode(sb, mode, dev, flags)  ramfs_get_inode(sb, mode, dev)
+#define shmem_acct_size(flags, size)           0
+#define shmem_unacct_size(flags, size)         do {} while (0)
+#define SHMEM_MAX_BYTES                                LLONG_MAX
 
 #endif /* CONFIG_SHMEM */
 
@@ -2589,7 +2591,7 @@ int shmem_unuse(swp_entry_t entry, struct page *page)
  * shmem_file_setup - get an unlinked file living in tmpfs
  * @name: name for dentry (to be seen in /proc/<pid>/maps
  * @size: size to be set for the file
- * @flags: vm_flags
+ * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
  */
 struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
 {
@@ -2623,13 +2625,10 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
                goto put_dentry;
 
        error = -ENOSPC;
-       inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
+       inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0, flags);
        if (!inode)
                goto close_file;
 
-#ifdef CONFIG_SHMEM
-       SHMEM_I(inode)->flags = (flags & VM_NORESERVE) ? 0 : VM_ACCOUNT;
-#endif
        d_instantiate(dentry, inode);
        inode->i_size = size;
        inode->i_nlink = 0;     /* It is unlinked */
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 4dd2636d0b92664230f9d7fa8b439cea2802e34f..520a7598026995c1aafe82dfbf523e9fcb7143a2 100644 (file)
@@ -323,6 +323,7 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
        unsigned long addr;
        int purged = 0;
 
+       BUG_ON(!size);
        BUG_ON(size & ~PAGE_MASK);
 
        va = kmalloc_node(sizeof(struct vmap_area),
@@ -334,6 +335,9 @@ retry:
        addr = ALIGN(vstart, align);
 
        spin_lock(&vmap_area_lock);
+       if (addr + size - 1 < addr)
+               goto overflow;
+
        /* XXX: could have a last_hole cache */
        n = vmap_area_root.rb_node;
        if (n) {
@@ -365,6 +369,8 @@ retry:
 
                while (addr + size > first->va_start && addr + size <= vend) {
                        addr = ALIGN(first->va_end + PAGE_SIZE, align);
+                       if (addr + size - 1 < addr)
+                               goto overflow;
 
                        n = rb_next(&first->rb_node);
                        if (n)
@@ -375,6 +381,7 @@ retry:
        }
 found:
        if (addr + size > vend) {
+overflow:
                spin_unlock(&vmap_area_lock);
                if (!purged) {
                        purge_vmap_area_lazy();
@@ -498,6 +505,7 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
        static DEFINE_SPINLOCK(purge_lock);
        LIST_HEAD(valist);
        struct vmap_area *va;
+       struct vmap_area *n_va;
        int nr = 0;
 
        /*
@@ -537,7 +545,7 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
 
        if (nr) {
                spin_lock(&vmap_area_lock);
-               list_for_each_entry(va, &valist, purge_list)
+               list_for_each_entry_safe(va, n_va, &valist, purge_list)
                        __free_vmap_area(va);
                spin_unlock(&vmap_area_lock);
        }
@@ -1012,6 +1020,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);
 }
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 e9db889d6222c466e6ad2a896dcdcdfd8d7d2d94..2886d2fb9ab5d84dc8177a01778606a82904d6b5 100644 (file)
@@ -1,12 +1,16 @@
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/if_vlan.h>
+#include <linux/netpoll.h>
 #include "vlan.h"
 
 /* VLAN rx hw acceleration helper.  This acts like netif_{rx,receive_skb}(). */
 int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
                      u16 vlan_tci, int polling)
 {
+       if (netpoll_rx(skb))
+               return NET_RX_DROP;
+
        if (skb_bond_should_drop(skb))
                goto drop;
 
@@ -100,6 +104,9 @@ int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
 {
        int err = NET_RX_SUCCESS;
 
+       if (netpoll_receive_skb(skb))
+               return NET_RX_DROP;
+
        switch (vlan_gro_common(napi, grp, vlan_tci, skb)) {
        case -1:
                return netif_receive_skb(skb);
@@ -126,6 +133,9 @@ int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
        if (!skb)
                goto out;
 
+       if (netpoll_receive_skb(skb))
+               goto out;
+
        err = NET_RX_SUCCESS;
 
        switch (vlan_gro_common(napi, grp, vlan_tci, skb)) {
index a17e00662363ad04fc432fe08be012cd9433fb23..72b0d26fd46d037e9a4016a810e06d940df5431a 100644 (file)
@@ -2488,6 +2488,9 @@ static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 
 int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
+       if (netpoll_receive_skb(skb))
+               return NET_RX_DROP;
+
        switch (__napi_gro_receive(napi, skb)) {
        case -1:
                return netif_receive_skb(skb);
@@ -2558,6 +2561,9 @@ int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info)
        if (!skb)
                goto out;
 
+       if (netpoll_receive_skb(skb))
+               goto out;
+
        err = NET_RX_SUCCESS;
 
        switch (__napi_gro_receive(napi, skb)) {
index 55151faaf90c1793c53e38bed732ff3c5bd53397..2adb1a7d361f8391ebeeccf78cb7823527c2a1e7 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,24 +60,50 @@ out_undo:
        }
 
        rcu_barrier();
-       kfree(ng);
        goto out;
 }
 
+static struct net_generic *net_alloc_generic(void)
+{
+       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;
+}
+
 #ifdef CONFIG_NET_NS
 static struct kmem_cache *net_cachep;
 static struct workqueue_struct *netns_wq;
 
 static struct net *net_alloc(void)
 {
-       return kmem_cache_zalloc(net_cachep, GFP_KERNEL);
+       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)
+               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)
 {
-       if (!net)
-               return;
-
 #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..5f97caa158e81ba95143e7c769ab30de3a1cac43 100644 (file)
@@ -696,7 +696,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
        if (len < 0)
                return -EINVAL;
 
-       v.val = 0;
+       memset(&v, 0, sizeof(v));
 
        switch(optname) {
        case SO_DEBUG:
@@ -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 a6961d75c7ea6b744d699602bfbdf547694764fe..c28976a7e59641501782f44c84eec1714694c59a 100644 (file)
@@ -1374,7 +1374,8 @@ static u8 tcp_sacktag_one(struct sk_buff *skb, struct sock *sk,
 
 static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
                           struct tcp_sacktag_state *state,
-                          unsigned int pcount, int shifted, int mss)
+                          unsigned int pcount, int shifted, int mss,
+                          int dup_sack)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        struct sk_buff *prev = tcp_write_queue_prev(sk, skb);
@@ -1410,7 +1411,7 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
        }
 
        /* We discard results */
-       tcp_sacktag_one(skb, sk, state, 0, pcount);
+       tcp_sacktag_one(skb, sk, state, dup_sack, pcount);
 
        /* Difference in this won't matter, both ACKed by the same cumul. ACK */
        TCP_SKB_CB(prev)->sacked |= (TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS);
@@ -1561,7 +1562,7 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb,
 
        if (!skb_shift(prev, skb, len))
                goto fallback;
-       if (!tcp_shifted_skb(sk, skb, state, pcount, len, mss))
+       if (!tcp_shifted_skb(sk, skb, state, pcount, len, mss, dup_sack))
                goto out;
 
        /* Hole filled allows collapsing with the next as well, this is very
@@ -1580,7 +1581,7 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb,
        len = skb->len;
        if (skb_shift(prev, skb, len)) {
                pcount += tcp_skb_pcount(skb);
-               tcp_shifted_skb(sk, skb, state, tcp_skb_pcount(skb), len, mss);
+               tcp_shifted_skb(sk, skb, state, tcp_skb_pcount(skb), len, mss, 0);
        }
 
 out:
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 2747ec7bfb63e885fdc286836f41f5e157f6ded8..4660b088a8ce4abe86ef64b18d4f007926b7424a 100644 (file)
@@ -1,6 +1,6 @@
 /* Tom Kelly's Scalable TCP
  *
- * See htt://www-lce.eng.cam.ac.uk/~ctk21/scalable/
+ * See http://www.deneholme.net/tom/scalable/
  *
  * John Heffner <jheffner@sc.edu>
  */
index 8fe267feb81e2af5e110f97e67916345df0493a1..1bcc3431859ede58e1166a9efaa101461e1cc8e6 100644 (file)
@@ -258,11 +258,11 @@ unique:
 
        if (twp != NULL) {
                *twp = tw;
-               NET_INC_STATS_BH(twsk_net(tw), LINUX_MIB_TIMEWAITRECYCLED);
+               NET_INC_STATS_BH(net, LINUX_MIB_TIMEWAITRECYCLED);
        } else if (tw != NULL) {
                /* Silly. Should hash-dance instead... */
                inet_twsk_deschedule(tw, death_row);
-               NET_INC_STATS_BH(twsk_net(tw), LINUX_MIB_TIMEWAITRECYCLED);
+               NET_INC_STATS_BH(net, LINUX_MIB_TIMEWAITRECYCLED);
 
                inet_twsk_put(tw);
        }
index c323643ffcf964214bcffb522c518cb6546bc38c..72dbb6d1a6b3e1b97eb3514c9b44a28688c09d43 100644 (file)
@@ -201,8 +201,9 @@ icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
 
        if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
            nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
-               nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
-                             "nf_ct_icmpv6: ICMPv6 checksum failed\n");
+               if (LOG_INVALID(net, IPPROTO_ICMPV6))
+                       nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
+                                     "nf_ct_icmpv6: ICMPv6 checksum failed ");
                return -NF_ACCEPT;
        }
 
index fa49dc7fe100ffb0cd7a48e1b626c87019903197..c712e9fc6bba2d3c1fca0a2e578067d3963a341e 100644 (file)
@@ -39,7 +39,7 @@
 #endif
 
 #define NFULNL_NLBUFSIZ_DEFAULT        NLMSG_GOODSIZE
-#define NFULNL_TIMEOUT_DEFAULT         HZ      /* every second */
+#define NFULNL_TIMEOUT_DEFAULT         100     /* every second */
 #define NFULNL_QTHRESH_DEFAULT         100     /* 100 packets */
 #define NFULNL_COPY_RANGE_MAX  0xFFFF  /* max packet size is limited by 16-bit struct nfattr nfa_len field */
 
@@ -590,8 +590,10 @@ nfulnl_log_packet(u_int8_t pf,
 
        qthreshold = inst->qthreshold;
        /* per-rule qthreshold overrides per-instance */
-       if (qthreshold > li->u.ulog.qthreshold)
-               qthreshold = li->u.ulog.qthreshold;
+       if (li->u.ulog.qthreshold)
+               if (qthreshold > li->u.ulog.qthreshold)
+                       qthreshold = li->u.ulog.qthreshold;
+
 
        switch (inst->copy_mode) {
        case NFULNL_COPY_META:
index bfbf521f6ea5a4bba99387781d9033cba0ff30a1..5baccfa5a0deb53657424ffd9b6c78713b57a8a1 100644 (file)
@@ -827,59 +827,143 @@ static const struct file_operations xt_table_ops = {
        .release = seq_release_net,
 };
 
-static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos)
+/*
+ * Traverse state for ip{,6}_{tables,matches} for helping crossing
+ * the multi-AF mutexes.
+ */
+struct nf_mttg_trav {
+       struct list_head *head, *curr;
+       uint8_t class, nfproto;
+};
+
+enum {
+       MTTG_TRAV_INIT,
+       MTTG_TRAV_NFP_UNSPEC,
+       MTTG_TRAV_NFP_SPEC,
+       MTTG_TRAV_DONE,
+};
+
+static void *xt_mttg_seq_next(struct seq_file *seq, void *v, loff_t *ppos,
+    bool is_target)
 {
-       struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private;
-       u_int16_t af = (unsigned long)pde->data;
+       static const uint8_t next_class[] = {
+               [MTTG_TRAV_NFP_UNSPEC] = MTTG_TRAV_NFP_SPEC,
+               [MTTG_TRAV_NFP_SPEC]   = MTTG_TRAV_DONE,
+       };
+       struct nf_mttg_trav *trav = seq->private;
+
+       switch (trav->class) {
+       case MTTG_TRAV_INIT:
+               trav->class = MTTG_TRAV_NFP_UNSPEC;
+               mutex_lock(&xt[NFPROTO_UNSPEC].mutex);
+               trav->head = trav->curr = is_target ?
+                       &xt[NFPROTO_UNSPEC].target : &xt[NFPROTO_UNSPEC].match;
+               break;
+       case MTTG_TRAV_NFP_UNSPEC:
+               trav->curr = trav->curr->next;
+               if (trav->curr != trav->head)
+                       break;
+               mutex_unlock(&xt[NFPROTO_UNSPEC].mutex);
+               mutex_lock(&xt[trav->nfproto].mutex);
+               trav->head = trav->curr = is_target ?
+                       &xt[trav->nfproto].target : &xt[trav->nfproto].match;
+               trav->class = next_class[trav->class];
+               break;
+       case MTTG_TRAV_NFP_SPEC:
+               trav->curr = trav->curr->next;
+               if (trav->curr != trav->head)
+                       break;
+               /* fallthru, _stop will unlock */
+       default:
+               return NULL;
+       }
 
-       mutex_lock(&xt[af].mutex);
-       return seq_list_start(&xt[af].match, *pos);
+       if (ppos != NULL)
+               ++*ppos;
+       return trav;
 }
 
-static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *xt_mttg_seq_start(struct seq_file *seq, loff_t *pos,
+    bool is_target)
 {
-       struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private;
-       u_int16_t af = (unsigned long)pde->data;
+       struct nf_mttg_trav *trav = seq->private;
+       unsigned int j;
 
-       return seq_list_next(v, &xt[af].match, pos);
+       trav->class = MTTG_TRAV_INIT;
+       for (j = 0; j < *pos; ++j)
+               if (xt_mttg_seq_next(seq, NULL, NULL, is_target) == NULL)
+                       return NULL;
+       return trav;
 }
 
-static void xt_match_seq_stop(struct seq_file *seq, void *v)
+static void xt_mttg_seq_stop(struct seq_file *seq, void *v)
 {
-       struct proc_dir_entry *pde = seq->private;
-       u_int16_t af = (unsigned long)pde->data;
+       struct nf_mttg_trav *trav = seq->private;
+
+       switch (trav->class) {
+       case MTTG_TRAV_NFP_UNSPEC:
+               mutex_unlock(&xt[NFPROTO_UNSPEC].mutex);
+               break;
+       case MTTG_TRAV_NFP_SPEC:
+               mutex_unlock(&xt[trav->nfproto].mutex);
+               break;
+       }
+}
 
-       mutex_unlock(&xt[af].mutex);
+static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       return xt_mttg_seq_start(seq, pos, false);
 }
 
-static int xt_match_seq_show(struct seq_file *seq, void *v)
+static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *ppos)
 {
-       struct xt_match *match = list_entry(v, struct xt_match, list);
+       return xt_mttg_seq_next(seq, v, ppos, false);
+}
 
-       if (strlen(match->name))
-               return seq_printf(seq, "%s\n", match->name);
-       else
-               return 0;
+static int xt_match_seq_show(struct seq_file *seq, void *v)
+{
+       const struct nf_mttg_trav *trav = seq->private;
+       const struct xt_match *match;
+
+       switch (trav->class) {
+       case MTTG_TRAV_NFP_UNSPEC:
+       case MTTG_TRAV_NFP_SPEC:
+               if (trav->curr == trav->head)
+                       return 0;
+               match = list_entry(trav->curr, struct xt_match, list);
+               return (*match->name == '\0') ? 0 :
+                      seq_printf(seq, "%s\n", match->name);
+       }
+       return 0;
 }
 
 static const struct seq_operations xt_match_seq_ops = {
        .start  = xt_match_seq_start,
        .next   = xt_match_seq_next,
-       .stop   = xt_match_seq_stop,
+       .stop   = xt_mttg_seq_stop,
        .show   = xt_match_seq_show,
 };
 
 static int xt_match_open(struct inode *inode, struct file *file)
 {
+       struct seq_file *seq;
+       struct nf_mttg_trav *trav;
        int ret;
 
-       ret = seq_open(file, &xt_match_seq_ops);
-       if (!ret) {
-               struct seq_file *seq = file->private_data;
+       trav = kmalloc(sizeof(*trav), GFP_KERNEL);
+       if (trav == NULL)
+               return -ENOMEM;
 
-               seq->private = PDE(inode);
+       ret = seq_open(file, &xt_match_seq_ops);
+       if (ret < 0) {
+               kfree(trav);
+               return ret;
        }
-       return ret;
+
+       seq = file->private_data;
+       seq->private = trav;
+       trav->nfproto = (unsigned long)PDE(inode)->data;
+       return 0;
 }
 
 static const struct file_operations xt_match_ops = {
@@ -887,62 +971,63 @@ static const struct file_operations xt_match_ops = {
        .open    = xt_match_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_private,
 };
 
 static void *xt_target_seq_start(struct seq_file *seq, loff_t *pos)
 {
-       struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private;
-       u_int16_t af = (unsigned long)pde->data;
-
-       mutex_lock(&xt[af].mutex);
-       return seq_list_start(&xt[af].target, *pos);
+       return xt_mttg_seq_start(seq, pos, true);
 }
 
-static void *xt_target_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *xt_target_seq_next(struct seq_file *seq, void *v, loff_t *ppos)
 {
-       struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private;
-       u_int16_t af = (unsigned long)pde->data;
-
-       return seq_list_next(v, &xt[af].target, pos);
-}
-
-static void xt_target_seq_stop(struct seq_file *seq, void *v)
-{
-       struct proc_dir_entry *pde = seq->private;
-       u_int16_t af = (unsigned long)pde->data;
-
-       mutex_unlock(&xt[af].mutex);
+       return xt_mttg_seq_next(seq, v, ppos, true);
 }
 
 static int xt_target_seq_show(struct seq_file *seq, void *v)
 {
-       struct xt_target *target = list_entry(v, struct xt_target, list);
-
-       if (strlen(target->name))
-               return seq_printf(seq, "%s\n", target->name);
-       else
-               return 0;
+       const struct nf_mttg_trav *trav = seq->private;
+       const struct xt_target *target;
+
+       switch (trav->class) {
+       case MTTG_TRAV_NFP_UNSPEC:
+       case MTTG_TRAV_NFP_SPEC:
+               if (trav->curr == trav->head)
+                       return 0;
+               target = list_entry(trav->curr, struct xt_target, list);
+               return (*target->name == '\0') ? 0 :
+                      seq_printf(seq, "%s\n", target->name);
+       }
+       return 0;
 }
 
 static const struct seq_operations xt_target_seq_ops = {
        .start  = xt_target_seq_start,
        .next   = xt_target_seq_next,
-       .stop   = xt_target_seq_stop,
+       .stop   = xt_mttg_seq_stop,
        .show   = xt_target_seq_show,
 };
 
 static int xt_target_open(struct inode *inode, struct file *file)
 {
+       struct seq_file *seq;
+       struct nf_mttg_trav *trav;
        int ret;
 
-       ret = seq_open(file, &xt_target_seq_ops);
-       if (!ret) {
-               struct seq_file *seq = file->private_data;
+       trav = kmalloc(sizeof(*trav), GFP_KERNEL);
+       if (trav == NULL)
+               return -ENOMEM;
 
-               seq->private = PDE(inode);
+       ret = seq_open(file, &xt_target_seq_ops);
+       if (ret < 0) {
+               kfree(trav);
+               return ret;
        }
-       return ret;
+
+       seq = file->private_data;
+       seq->private = trav;
+       trav->nfproto = (unsigned long)PDE(inode)->data;
+       return 0;
 }
 
 static const struct file_operations xt_target_ops = {
@@ -950,7 +1035,7 @@ static const struct file_operations xt_target_ops = {
        .open    = xt_target_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_private,
 };
 
 #define FORMAT_TABLES  "_tables_names"
index fe80b614a40033014f48cfe1fad26f3806af85c2..791e030ea9031358d8d19f6da099554fb090b304 100644 (file)
@@ -542,7 +542,7 @@ recent_mt_proc_write(struct file *file, const char __user *input,
        struct recent_entry *e;
        char buf[sizeof("+b335:1d35:1e55:dead:c0de:1715:5afe:c0de")];
        const char *c = buf;
-       union nf_inet_addr addr;
+       union nf_inet_addr addr = {};
        u_int16_t family;
        bool add, succ;
 
index f6b4fa97df70e353b58ed04ba4a74f50f4c8fbcf..e36e94ab4e100a9b3d971c016734ec7f3f21ed2c 100644 (file)
@@ -66,11 +66,15 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 {
        struct drr_sched *q = qdisc_priv(sch);
        struct drr_class *cl = (struct drr_class *)*arg;
+       struct nlattr *opt = tca[TCA_OPTIONS];
        struct nlattr *tb[TCA_DRR_MAX + 1];
        u32 quantum;
        int err;
 
-       err = nla_parse_nested(tb, TCA_DRR_MAX, tca[TCA_OPTIONS], drr_policy);
+       if (!opt)
+               return -EINVAL;
+
+       err = nla_parse_nested(tb, TCA_DRR_MAX, opt, drr_policy);
        if (err < 0)
                return err;
 
index 45eb0ae98ebab2c6a771e1d10bfbb10df9231823..2d5ece798c4c6e786b3e6ee305e9830e490d75e9 100755 (executable)
@@ -10,7 +10,7 @@ use strict;
 my $P = $0;
 $P =~ s@.*/@@g;
 
-my $V = '0.27';
+my $V = '0.28';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -110,7 +110,8 @@ our $Sparse = qr{
                        __iomem|
                        __must_check|
                        __init_refok|
-                       __kprobes
+                       __kprobes|
+                       __ref
                }x;
 our $Attribute = qr{
                        const|
@@ -1240,7 +1241,8 @@ sub process {
                        $realfile =~ s@^([^/]*)/@@;
 
                        $p1_prefix = $1;
-                       if ($tree && $p1_prefix ne '' && -e "$root/$p1_prefix") {
+                       if (!$file && $tree && $p1_prefix ne '' &&
+                           -e "$root/$p1_prefix") {
                                WARN("patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n");
                        }
 
@@ -1583,9 +1585,9 @@ sub process {
                }
 # TEST: allow direct testing of the attribute matcher.
                if ($dbg_attr) {
-                       if ($line =~ /^.\s*$Attribute\s*$/) {
+                       if ($line =~ /^.\s*$Modifier\s*$/) {
                                ERROR("TEST: is attr\n" . $herecurr);
-                       } elsif ($dbg_attr > 1 && $line =~ /^.+($Attribute)/) {
+                       } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) {
                                ERROR("TEST: is not attr ($1 is)\n". $herecurr);
                        }
                        next;
@@ -1657,7 +1659,7 @@ sub process {
 
 # * goes on variable not on type
                # (char*[ const])
-               if ($line =~ m{\($NonptrType(\s*\*[\s\*]*(?:$Modifier\s*)*)\)}) {
+               if ($line =~ m{\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\)}) {
                        my ($from, $to) = ($1, $1);
 
                        # Should start with a space.
@@ -1672,7 +1674,7 @@ sub process {
                        if ($from ne $to) {
                                ERROR("\"(foo$from)\" should be \"(foo$to)\"\n" .  $herecurr);
                        }
-               } elsif ($line =~ m{\b$NonptrType(\s*\*[\s\*]*(?:$Modifier\s*)?)($Ident)}) {
+               } elsif ($line =~ m{\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident)}) {
                        my ($from, $to, $ident) = ($1, $1, $2);
 
                        # Should start with a space.
@@ -1685,8 +1687,8 @@ sub process {
                        # Modifiers should have spaces.
                        $to =~ s/(\b$Modifier$)/$1 /;
 
-                       #print "from<$from> to<$to>\n";
-                       if ($from ne $to) {
+                       #print "from<$from> to<$to> ident<$ident>\n";
+                       if ($from ne $to && $ident !~ /^$Modifier$/) {
                                ERROR("\"foo${from}bar\" should be \"foo${to}bar\"\n" .  $herecurr);
                        }
                }
@@ -1885,11 +1887,11 @@ sub process {
                                        if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
                                                ERROR("space required before that '$op' $at\n" . $hereptr);
                                        }
-                                       if ($op eq '*' && $cc =~/\s*const\b/) {
+                                       if ($op eq '*' && $cc =~/\s*$Modifier\b/) {
                                                # A unary '*' may be const
 
                                        } elsif ($ctx =~ /.xW/) {
-                                               ERROR("space prohibited after that '$op' $at\n" . $hereptr);
+                                               ERROR("Aspace prohibited after that '$op' $at\n" . $hereptr);
                                        }
 
                                # unary ++ and unary -- are allowed no space on one side.
@@ -2560,7 +2562,7 @@ sub process {
                if ($line =~ /\bin_atomic\s*\(/) {
                        if ($realfile =~ m@^drivers/@) {
                                ERROR("do not use in_atomic in drivers\n" . $herecurr);
-                       } else {
+                       } elsif ($realfile !~ m@^kernel/@) {
                                WARN("use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
                        }
                }
index f58701a7b728619a5a50e3bc74981baa23ab60cf..350794ab9b4212d7e50b07f3c778bb42bb81aa3a 100644 (file)
@@ -386,11 +386,12 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
        if (!S_ISSOCK(inode->i_mode) ||
            ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
                return 0;
-
        sock = SOCKET_I(inode);
        sk = sock->sk;
+       if (sk == NULL)
+               return 0;
        sksec = sk->sk_security;
-       if (sksec->nlbl_state != NLBL_REQUIRE)
+       if (sksec == NULL || sksec->nlbl_state != NLBL_REQUIRE)
                return 0;
 
        local_bh_disable();
@@ -490,8 +491,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 a466443c4a2649b819147e70d9f041bc1f25b38b..2fa9299a440dbb99e767c079e664d0a1133e8762 100644 (file)
@@ -157,7 +157,7 @@ static void resample_shrink(struct snd_pcm_plugin *plugin,
                while (dst_frames1 > 0) {
                        S1 = S2;
                        if (src_frames1-- > 0) {
-                               S1 = *src;
+                               S2 = *src;
                                src += src_step;
                        }
                        if (pos & ~R_MASK) {
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 3f00ddf450f81c287b198cdbdf4c8a17b180c4f8..c7c54e7748e9ac6fdbf09f1d4bb11f7106d1bfc3 100644 (file)
@@ -165,7 +165,7 @@ module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable Audiowerk2 soundcard.");
 
 static struct pci_device_id snd_aw2_ids[] = {
-       {PCI_VENDOR_ID_SAA7146, PCI_DEVICE_ID_SAA7146, PCI_ANY_ID, PCI_ANY_ID,
+       {PCI_VENDOR_ID_SAA7146, PCI_DEVICE_ID_SAA7146, 0, 0,
         0, 0, 0},
        {0}
 };
index 7958006a1d66cf9559a62bbda6fbfd48b0994047..101a1c13a20dd0b4cdd106d89dd5867187b2b2f9 100644 (file)
@@ -1528,6 +1528,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .ca0151_chip = 1,
         .spk71 = 1,
         .spdif_bug = 1,
+        .invert_shared_spdif = 1,      /* digital/analog switch swapped */
         .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
         .driver = "Audigy2", .name = "SB Audigy 2 Platinum [SB0240P]",
index 482fb0304ca91fc4a7735408393ec68b888bcefc..4ae51dcb81af861450e37d2219c76b6027746764 100644 (file)
@@ -277,18 +277,19 @@ static ssize_t init_verbs_store(struct device *dev,
 {
        struct snd_hwdep *hwdep = dev_get_drvdata(dev);
        struct hda_codec *codec = hwdep->private_data;
-       char *p;
-       struct hda_verb verb, *v;
+       struct hda_verb *v;
+       int nid, verb, param;
 
-       verb.nid = simple_strtoul(buf, &p, 0);
-       verb.verb = simple_strtoul(p, &p, 0);
-       verb.param = simple_strtoul(p, &p, 0);
-       if (!verb.nid || !verb.verb || !verb.param)
+       if (sscanf(buf, "%i %i %i", &nid, &verb, &param) != 3)
+               return -EINVAL;
+       if (!nid || !verb)
                return -EINVAL;
        v = snd_array_new(&codec->init_verbs);
        if (!v)
                return -ENOMEM;
-       *v = verb;
+       v->nid = nid;
+       v->verb = verb;
+       v->param = param;
        return count;
 }
 
index c8d9178f47e59bf327b17433017d24460620a5e5..5e909e0da04b4b64d18ee9979f38cbaaa853e354 100644 (file)
@@ -2095,6 +2095,8 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01),
        /* including bogus ALC268 in slot#2 that conflicts with ALC888 */
        SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01),
+       /* conflict of ALC268 in slot#3 (digital I/O); a temporary fix */
+       SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba laptop", 0x03),
        {}
 };
 
index ed8fcbd60003cf1ad88af2ded2a5fbda0af2113e..6c26afcb82622d7b0e994f69c334cec8ef90bf33 100644 (file)
@@ -7017,6 +7017,7 @@ static int patch_alc882(struct hda_codec *codec)
                case 0x106b3e00: /* iMac 24 Aluminium */
                        board_config = ALC885_IMAC24;
                        break;
+               case 0x106b00a0: /* MacBookPro3,1 - Another revision */
                case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */
                case 0x106b00a4: /* MacbookPro4,1 */
                case 0x106b2c00: /* Macbook Pro rev3 */
@@ -8469,6 +8470,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
                ALC888_ACER_ASPIRE_4930G),
        SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
                ALC888_ACER_ASPIRE_4930G),
+       SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
+               ALC888_ACER_ASPIRE_4930G),
        SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */
        SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
        SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
@@ -10554,6 +10557,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x1309, "HP xw4*00", ALC262_HP_BPC),
        SND_PCI_QUIRK(0x103c, 0x130a, "HP xw6*00", ALC262_HP_BPC),
        SND_PCI_QUIRK(0x103c, 0x130b, "HP xw8*00", ALC262_HP_BPC),
+       SND_PCI_QUIRK(0x103c, 0x170b, "HP xw*", ALC262_HP_BPC),
        SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
        SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
        SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
index 8027edf3c8f2ab2d13848b45ab3a66495ceb2e81..3bc427645da8ef1411400990b67c9fc181e4cece 100644 (file)
@@ -4989,7 +4989,7 @@ again:
        case STAC_DELL_M4_3:
                spec->num_dmics = 1;
                spec->num_smuxes = 0;
-               spec->num_dmuxes = 0;
+               spec->num_dmuxes = 1;
                break;
        default:
                spec->num_dmics = STAC92HD71BXX_NUM_DMICS;
index 84131a916c92bc379ec1f07cdb515fc37ae13749..69d87dee6995f72e174940a44bd0a4f302b7e7f4 100644 (file)
@@ -97,12 +97,12 @@ struct pcxhr_mgr {
        int capture_chips;
        int fw_file_set;
        int firmware_num;
-       int is_hr_stereo:1;
-       int board_has_aes1:1;   /* if 1 board has AES1 plug and SRC */
-       int board_has_analog:1; /* if 0 the board is digital only */
-       int board_has_mic:1;    /* if 1 the board has microphone input */
-       int board_aes_in_192k:1;/* if 1 the aes input plugs do support 192kHz */
-       int mono_capture:1;     /* if 1 the board does mono capture */
+       unsigned int is_hr_stereo:1;
+       unsigned int board_has_aes1:1;  /* if 1 board has AES1 plug and SRC */
+       unsigned int board_has_analog:1; /* if 0 the board is digital only */
+       unsigned int board_has_mic:1; /* if 1 the board has microphone input */
+       unsigned int board_aes_in_192k:1;/* if 1 the aes input plugs do support 192kHz */
+       unsigned int mono_capture:1; /* if 1 the board does mono capture */
 
        struct snd_dma_buffer hostport;