]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'fix/pcm-hwptr' into for-linus
authorTakashi Iwai <tiwai@suse.de>
Sun, 26 Jul 2009 09:07:07 +0000 (11:07 +0200)
committerTakashi Iwai <tiwai@suse.de>
Sun, 26 Jul 2009 09:07:07 +0000 (11:07 +0200)
* fix/pcm-hwptr:
  ALSA: pcm - Fix hwptr buffer-size overlap bug
  ALSA: pcm - Fix warnings in debug loggings
  ALSA: pcm - Add logging of hwptr updates and interrupt updates
  ALSA: pcm - Fix regressions with VMware

299 files changed:
CREDITS
Documentation/RCU/rculist_nulls.txt
Documentation/connector/cn_test.c
Documentation/connector/ucon.c
Documentation/networking/6pack.txt
Documentation/scheduler/sched-rt-group.txt
MAINTAINERS
Makefile
arch/arm/configs/u300_defconfig
arch/arm/mach-ep93xx/dma-m2p.c
arch/arm/mach-kirkwood/mpp.h
arch/arm/mach-mx3/Kconfig
arch/arm/mach-mx3/Makefile
arch/arm/mach-mx3/armadillo5x0.c
arch/arm/mach-mx3/devices.c
arch/arm/mach-mx3/pcm037.c
arch/arm/mach-mx3/pcm037.h [new file with mode: 0644]
arch/arm/mach-mx3/pcm037_eet.c [new file with mode: 0644]
arch/arm/mach-pxa/include/mach/mfp-pxa300.h
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-realview/core.c
arch/arm/mach-u300/core.c
arch/arm/mach-versatile/core.c
arch/arm/plat-mxc/include/mach/iomux-mx3.h
arch/arm/plat-pxa/gpio.c
arch/blackfin/include/asm/context.S
arch/blackfin/include/asm/cpu.h
arch/blackfin/include/asm/hardirq.h
arch/blackfin/include/asm/processor.h
arch/blackfin/kernel/bfin_dma_5xx.c
arch/blackfin/kernel/bfin_gpio.c
arch/blackfin/kernel/cplb-nompu/cplbinit.c
arch/blackfin/kernel/process.c
arch/blackfin/kernel/setup.c
arch/blackfin/kernel/traps.c
arch/blackfin/lib/lshrdi3.c
arch/blackfin/mach-bf518/boards/ezbrd.c
arch/blackfin/mach-bf518/include/mach/anomaly.h
arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf527/boards/cm_bf527.c
arch/blackfin/mach-bf527/boards/ezbrd.c
arch/blackfin/mach-bf527/boards/ezkit.c
arch/blackfin/mach-bf527/include/mach/anomaly.h
arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf533/boards/stamp.c
arch/blackfin/mach-bf533/include/mach/anomaly.h
arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf537/boards/stamp.c
arch/blackfin/mach-bf537/include/mach/anomaly.h
arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf538/include/mach/anomaly.h
arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf548/boards/ezkit.c
arch/blackfin/mach-bf548/include/mach/anomaly.h
arch/blackfin/mach-bf561/include/mach/anomaly.h
arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf561/include/mach/mem_map.h
arch/blackfin/mach-common/entry.S
arch/blackfin/mach-common/smp.c
arch/ia64/include/asm/fpu.h
arch/ia64/include/asm/xen/hypervisor.h
arch/ia64/kernel/dma-mapping.c
arch/mn10300/kernel/vmlinux.lds.S
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/vector.S
arch/x86/include/asm/io_apic.h
arch/x86/include/asm/lguest_hcall.h
arch/x86/kernel/apic/es7000_32.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/numaq_32.c
arch/x86/kernel/cpu/perf_counter.c
arch/x86/kernel/pvclock.c
arch/x86/lguest/boot.c
arch/x86/mm/fault.c
arch/x86/pci/i386.c
block/blk-sysfs.c
block/elevator.c
drivers/ata/ahci.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/pata_at91.c
drivers/block/ataflop.c
drivers/block/virtio_blk.c
drivers/block/z2ram.c
drivers/char/hvc_console.c
drivers/char/n_tty.c
drivers/char/nozomi.c
drivers/char/pcmcia/ipwireless/tty.c
drivers/char/specialix.c
drivers/char/tty_ldisc.c
drivers/char/tty_port.c
drivers/char/vc_screen.c
drivers/char/vt.c
drivers/connector/cn_queue.c
drivers/connector/connector.c
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_stub.c
drivers/gpu/drm/ttm/ttm_bo_vm.c
drivers/gpu/drm/via/via_irq.c
drivers/hid/hid-core.c
drivers/hid/usbhid/hiddev.c
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/i2c/busses/i2c-simtec.c
drivers/ide/ide-disk.c
drivers/ide/ide-tape.c
drivers/input/evdev.c
drivers/input/joydev.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/atkbd.c
drivers/input/misc/pcspkr.c
drivers/input/misc/wistron_btns.c
drivers/isdn/gigaset/interface.c
drivers/lguest/lg.h
drivers/mmc/host/mvsdio.c
drivers/mmc/host/pxamci.c
drivers/mtd/ubi/gluebi.c
drivers/mtd/ubi/scan.c
drivers/net/8139too.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/arm/Kconfig
drivers/net/arm/Makefile
drivers/net/arm/ixp4xx_eth.c
drivers/net/arm/w90p910_ether.c [new file with mode: 0644]
drivers/net/atl1c/atl1c.h
drivers/net/atl1c/atl1c_main.c
drivers/net/atlx/atl2.c
drivers/net/bnx2x_link.c
drivers/net/bonding/bond_main.c
drivers/net/can/dev.c
drivers/net/can/sja1000/sja1000.c
drivers/net/cs89x0.c
drivers/net/e100.c
drivers/net/ehea/ehea_main.c
drivers/net/fec.c
drivers/net/gianfar.c
drivers/net/hamradio/6pack.c
drivers/net/ibm_newemac/rgmii.c
drivers/net/igb/igb_main.c
drivers/net/isa-skeleton.c
drivers/net/ixgbe/ixgbe_dcb_nl.c
drivers/net/jazzsonic.c
drivers/net/ks8851.c [new file with mode: 0644]
drivers/net/ks8851.h [new file with mode: 0644]
drivers/net/macsonic.c
drivers/net/mlx4/cmd.c
drivers/net/mlx4/en_ethtool.c
drivers/net/mlx4/main.c
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_ctx.c
drivers/net/netxen/netxen_nic_hw.c
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/pcmcia/3c589_cs.c
drivers/net/phy/phy_device.c
drivers/net/plip.c
drivers/net/ppp_async.c
drivers/net/ppp_synctty.c
drivers/net/ps3_gelic_net.c
drivers/net/ps3_gelic_wireless.c
drivers/net/sc92031.c
drivers/net/sky2.c
drivers/net/smc91x.c
drivers/net/smsc911x.c
drivers/net/sunvnet.c
drivers/net/usb/Kconfig
drivers/net/usb/Makefile
drivers/net/usb/cdc-phonet.c [new file with mode: 0644]
drivers/net/usb/cdc_eem.c
drivers/net/usb/kaweth.c
drivers/net/usb/pegasus.c
drivers/net/via-rhine.c
drivers/net/wireless/orinoco/main.c
drivers/serial/bfin_sport_uart.c
drivers/serial/msm_serial.c
drivers/usb/class/cdc-acm.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/video/Kconfig
drivers/video/backlight/pwm_bl.c
drivers/video/fbmon.c
drivers/virtio/virtio_pci.c
drivers/watchdog/ep93xx_wdt.c
fs/9p/vfs_addr.c
fs/Kconfig
fs/cifs/cifs_debug.c
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/dlm/lock.c
fs/dlm/lowcomms.c
fs/dlm/plock.c
fs/gfs2/trace_gfs2.h
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nilfs2/Kconfig [new file with mode: 0644]
fs/pipe.c
include/asm-generic/vmlinux.lds.h
include/drm/drm_pciids.h
include/linux/clockchips.h
include/linux/console_struct.h
include/linux/hrtimer.h
include/linux/interrupt.h
include/linux/lguest.h
include/linux/libata.h
include/linux/perf_counter.h
include/linux/sched.h
include/linux/skbuff.h
include/linux/virtio_net.h
include/net/sock.h
include/net/tcp.h
include/trace/events/block.h
include/trace/events/ext4.h
include/trace/events/irq.h
include/trace/events/jbd2.h
include/trace/events/kmem.h
include/trace/events/lockdep.h
include/trace/events/sched.h
include/trace/events/skb.h
include/trace/events/workqueue.h
init/Kconfig
kernel/fork.c
kernel/freezer.c
kernel/futex.c
kernel/hrtimer.c
kernel/irq/internals.h
kernel/irq/manage.c
kernel/irq/migration.c
kernel/perf_counter.c
kernel/sched.c
kernel/sched_fair.c
kernel/sched_rt.c
kernel/softirq.c
kernel/time/clockevents.c
kernel/time/clocksource.c
kernel/timer.c
kernel/trace/ftrace.c
kernel/trace/trace_functions.c
net/9p/client.c
net/can/bcm.c
net/can/raw.c
net/core/sock.c
net/ipv4/ip_gre.c
net/ipv4/ip_output.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv6/ip6_output.c
net/ipv6/sit.c
net/ipv6/tcp_ipv6.c
net/netfilter/nf_conntrack_core.c
net/netfilter/xt_osf.c
samples/trace_events/trace-events-sample.h
scripts/kconfig/lxdialog/util.c
scripts/kconfig/mconf.c
scripts/package/builddeb
sound/arm/pxa2xx-pcm-lib.c
sound/core/seq/Makefile
sound/isa/gus/gus_pcm.c
sound/pci/ca0106/ca0106_main.c
sound/pci/ctxfi/ctamixer.c
sound/pci/ctxfi/ctdaio.c
sound/pci/ctxfi/ctsrc.c
sound/pci/hda/hda_codec.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/riptide/riptide.c
sound/soc/codecs/tlv320aic3x.c
sound/usb/Kconfig
sound/usb/caiaq/audio.c
sound/usb/caiaq/device.c
sound/usb/caiaq/device.h
sound/usb/usbaudio.c
tools/perf/Documentation/perf-report.txt
tools/perf/Makefile
tools/perf/builtin-annotate.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-stat.c
tools/perf/builtin-top.c
tools/perf/perf.c
tools/perf/perf.h
tools/perf/util/cache.h
tools/perf/util/header.h
tools/perf/util/include/linux/kernel.h
tools/perf/util/parse-events.c
tools/perf/util/parse-events.h
tools/perf/util/string.h
tools/perf/util/strlist.c
tools/perf/util/strlist.h
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/util.h

diff --git a/CREDITS b/CREDITS
index 2b88fb37ad503e12ed271aa26b1068b7c5d93aea..e76d300e9fe4d79b95c5993c566f024d68957a15 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1856,7 +1856,7 @@ E: rfkoenig@immd4.informatik.uni-erlangen.de
 D: The Linux Support Team Erlangen
 
 N: Andreas Koensgen
-E: ajk@iehk.rwth-aachen.de
+E: ajk@comnets.uni-bremen.de
 D: 6pack driver for AX.25
 
 N: Harald Koerfgen
index 93cb28d05dcd92da30dde47ec58205e2b0851022..18f9651ff23d411e96737ec070d4fc6bc29c50fe 100644 (file)
@@ -83,11 +83,12 @@ not detect it missed following items in original chain.
 obj = kmem_cache_alloc(...);
 lock_chain(); // typically a spin_lock()
 obj->key = key;
-atomic_inc(&obj->refcnt);
 /*
  * we need to make sure obj->key is updated before obj->next
+ * or obj->refcnt
  */
 smp_wmb();
+atomic_set(&obj->refcnt, 1);
 hlist_add_head_rcu(&obj->obj_node, list);
 unlock_chain(); // typically a spin_unlock()
 
@@ -159,6 +160,10 @@ out:
 obj = kmem_cache_alloc(cachep);
 lock_chain(); // typically a spin_lock()
 obj->key = key;
+/*
+ * changes to obj->key must be visible before refcnt one
+ */
+smp_wmb();
 atomic_set(&obj->refcnt, 1);
 /*
  * insert obj in RCU way (readers might be traversing chain)
index f688eba8770488e4ebf4fa147e5f6b643be10634..6a5be5d5c8e4895c9f30c8494066eca302ffa056 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     cn_test.c
  * 
- * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
  * All rights reserved.
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -194,5 +194,5 @@ module_init(cn_test_init);
 module_exit(cn_test_fini);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Connector's test module");
index d738cde2a8d51603e7faa207d7aea014ebb80d48..c5092ad0ce4b24912dc361a59dc596ed9ccda011 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     ucon.c
  *
- * Copyright (c) 2004+ Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004+ Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
index d0777a1200e1a3a3c224db65cac7fe0d866ea44f..8f339428fdf441d40bb653a226dc12fe9baea928 100644 (file)
@@ -1,7 +1,7 @@
 This is the 6pack-mini-HOWTO, written by
 
 Andreas Könsgen DG3KQ
-Internet: ajk@iehk.rwth-aachen.de
+Internet: ajk@comnets.uni-bremen.de
 AMPR-net: dg3kq@db0pra.ampr.org
 AX.25:    dg3kq@db0ach.#nrw.deu.eu
 
index 1df7f9cdab0576227671703c6fec1fc780ec596b..86eabe6c3419fd4f26aba47a090ecc1caff9a1fd 100644 (file)
@@ -73,7 +73,7 @@ The remaining CPU time will be used for user input and other tasks. Because
 realtime tasks have explicitly allocated the CPU time they need to perform
 their tasks, buffer underruns in the graphics or audio can be eliminated.
 
-NOTE: the above example is not fully implemented as of yet (2.6.25). We still
+NOTE: the above example is not fully implemented yet. We still
 lack an EDF scheduler to make non-uniform periods usable.
 
 
@@ -140,14 +140,15 @@ The other option is:
 
 .o CONFIG_CGROUP_SCHED (aka "Basis for grouping tasks" = "Control groups")
 
-This uses the /cgroup virtual file system and "/cgroup/<cgroup>/cpu.rt_runtime_us"
-to control the CPU time reserved for each control group instead.
+This uses the /cgroup virtual file system and
+"/cgroup/<cgroup>/cpu.rt_runtime_us" to control the CPU time reserved for each
+control group instead.
 
 For more information on working with control groups, you should read
 Documentation/cgroups/cgroups.txt as well.
 
-Group settings are checked against the following limits in order to keep the configuration
-schedulable:
+Group settings are checked against the following limits in order to keep the
+configuration schedulable:
 
    \Sum_{i} runtime_{i} / global_period <= global_runtime / global_period
 
@@ -189,7 +190,7 @@ Implementing SCHED_EDF might take a while to complete. Priority Inheritance is
 the biggest challenge as the current linux PI infrastructure is geared towards
 the limited static priority levels 0-99. With deadline scheduling you need to
 do deadline inheritance (since priority is inversely proportional to the
-deadline delta (deadline - now).
+deadline delta (deadline - now)).
 
 This means the whole PI machinery will have to be reworked - and that is one of
 the most complex pieces of code we have.
index 18c3f0c41c95a034d98efda6cc4f7db905325a4a..ebc269152faf78f5136cb45432f29c39f8c67abe 100644 (file)
@@ -150,7 +150,7 @@ F:  drivers/scsi/53c700*
 
 6PACK NETWORK DRIVER FOR AX.25
 P:     Andreas Koensgen
-M:     ajk@iehk.rwth-aachen.de
+M:     ajk@comnets.uni-bremen.de
 L:     linux-hams@vger.kernel.org
 S:     Maintained
 F:     drivers/net/hamradio/6pack.c
@@ -1612,6 +1612,13 @@ S:       Supported
 F:     fs/configfs/
 F:     include/linux/configfs.h
 
+CONNECTOR
+P:     Evgeniy Polyakov
+M:     zbr@ioremap.net
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/connector/
+
 CONTROL GROUPS (CGROUPS)
 P:     Paul Menage
 M:     menage@google.com
@@ -4089,6 +4096,7 @@ L:        netfilter@vger.kernel.org
 L:     coreteam@netfilter.org
 W:     http://www.netfilter.org/
 W:     http://www.iptables.org/
+T:     git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6.git
 S:     Supported
 F:     include/linux/netfilter*
 F:     include/linux/netfilter/
@@ -5586,7 +5594,6 @@ S:        Odd Fixes
 F:     drivers/net/starfire*
 
 STARMODE RADIO IP (STRIP) PROTOCOL DRIVER
-W:     http://mosquitonet.Stanford.EDU/strip.html
 S:     Orphan
 F:     drivers/net/wireless/strip.c
 F:     include/linux/if_strip.h
index be0abacd042d8620eaf09133bd2f16214f141601..063d738405edbfe90b34de9335dab957b6362274 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 31
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc4
 NAME = Man-Eating Seals of Antiquity
 
 # *DOCUMENTATION*
@@ -343,7 +343,8 @@ KBUILD_CPPFLAGS := -D__KERNEL__
 KBUILD_CFLAGS   := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
                   -fno-strict-aliasing -fno-common \
                   -Werror-implicit-function-declaration \
-                  -Wno-format-security
+                  -Wno-format-security \
+                  -fno-delete-null-pointer-checks
 KBUILD_AFLAGS   := -D__ASSEMBLY__
 
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
index 4762d900129841d637604195ecb8aaf4effcd218..7d61ae6e75daf7e9da06b214818ee0ad2ff22efa 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.31-rc1
-# Thu Jul  2 00:16:59 2009
+# Linux kernel version: 2.6.31-rc3
+# Thu Jul 16 23:36:10 2009
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -9,7 +9,6 @@ CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_MMU=y
-CONFIG_HAVE_TCM=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -113,7 +112,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-CONFIG_LBDAF=y
+# CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -542,13 +541,14 @@ CONFIG_INPUT_EVDEV=y
 #
 CONFIG_INPUT_KEYBOARD=y
 # CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_KEYBOARD_SUNKBD is not set
 # CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
-# CONFIG_KEYBOARD_LM8323 is not set
-# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
@@ -911,7 +911,6 @@ CONFIG_REGULATOR=y
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
 CONFIG_FILE_LOCKING=y
@@ -1122,7 +1121,6 @@ CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC32 is not set
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_ALLOCATOR=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
index a2df5bb7dff0d9cf799d8770e158dfc9885373e8..dbcac9c40a28883df558565be3c7e52c37426053 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/io.h>
 
 #include <mach/dma.h>
 #include <mach/hardware.h>
index e021a80c2cafa00df3cba91543a6e5dc55d05f7b..bc74278ed311c2bef402d6e16d808111669ed96e 100644 (file)
 
 #define MPP48_GPIO             MPP( 48, 0x0, 1, 1, 0,   0,   0,   1    )
 #define MPP48_TSMP12           MPP( 48, 0x1, 1, 1, 0,   0,   0,   1    )
-#define MPP48_TDM_DTX          MPP( 48. 0x2, 0, 1, 0,   0,   0,   1    )
+#define MPP48_TDM_DTX          MPP( 48, 0x2, 0, 1, 0,   0,   0,   1    )
 
 #define MPP49_GPIO             MPP( 49, 0x0, 1, 1, 0,   0,   0,   1    )
 #define MPP49_TSMP9            MPP( 49, 0x1, 1, 1, 0,   0,   0,   1    )
index 17a21a291e2f6eb7d9bdb7593e76f2c2ecac2cc4..851f2458bf65f0d7443d02941f898d3c17e6494c 100644 (file)
@@ -36,6 +36,14 @@ config MACH_PCM037
          Include support for Phytec pcm037 platform. This includes
          specific configurations for the board and its peripherals.
 
+config MACH_PCM037_EET
+       bool "Support pcm037 EET board extensions"
+       depends on MACH_PCM037
+       help
+         Add support for PCM037 EET baseboard extensions. If you are using the
+         OLED display with EET, use "video=mx3fb:CMEL-OLED" kernel
+         command-line parameter.
+
 config MACH_MX31LITE
        bool "Support MX31 LITEKIT (LogicPD)"
        select ARCH_MX31
index 0322696bd11a19ad0402852b8858efe3750c6303..6b9775471be684d52e2d5fc53bc018d7ff0d3bf9 100644 (file)
@@ -11,6 +11,7 @@ obj-$(CONFIG_MACH_MX31ADS)    += mx31ads.o
 obj-$(CONFIG_MACH_MX31LILLY)   += mx31lilly.o mx31lilly-db.o
 obj-$(CONFIG_MACH_MX31LITE)    += mx31lite.o
 obj-$(CONFIG_MACH_PCM037)      += pcm037.o
+obj-$(CONFIG_MACH_PCM037_EET)  += pcm037_eet.o
 obj-$(CONFIG_MACH_MX31_3DS)    += mx31pdk.o
 obj-$(CONFIG_MACH_MX31MOBOARD) += mx31moboard.o mx31moboard-devboard.o \
                                   mx31moboard-marxbot.o
index 541181090b370dffca050e92d4a11bae94c0eb29..ee331fd6b1bd9c6e5f72159de2249e7d38e2fb7d 100644 (file)
@@ -31,6 +31,8 @@
 #include <linux/smsc911x.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <mach/mmc.h>
 #include <mach/ipu.h>
 #include <mach/mx3fb.h>
+#include <mach/mxc_nand.h>
 
 #include "devices.h"
+#include "crm_regs.h"
 
 static int armadillo5x0_pins[] = {
        /* UART1 */
@@ -93,7 +97,56 @@ static int armadillo5x0_pins[] = {
        MX31_PIN_FPSHIFT__FPSHIFT,
        MX31_PIN_DRDY0__DRDY0,
        IOMUX_MODE(MX31_PIN_LCS1, IOMUX_CONFIG_GPIO), /*ADV7125_PSAVE*/
+};
 
+/*
+ * NAND Flash
+ */
+static struct mxc_nand_platform_data armadillo5x0_nand_flash_pdata = {
+       .width          = 1,
+       .hw_ecc         = 1,
+};
+
+/*
+ * MTD NOR Flash
+ */
+static struct mtd_partition armadillo5x0_nor_flash_partitions[] = {
+       {
+               .name           = "nor.bootloader",
+               .offset         = 0x00000000,
+               .size           = 4*32*1024,
+       }, {
+               .name           = "nor.kernel",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 16*128*1024,
+       }, {
+               .name           = "nor.userland",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 110*128*1024,
+       }, {
+               .name           = "nor.config",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 1*128*1024,
+       },
+};
+
+static struct physmap_flash_data armadillo5x0_nor_flash_pdata = {
+       .width          = 2,
+       .parts          = armadillo5x0_nor_flash_partitions,
+       .nr_parts       = ARRAY_SIZE(armadillo5x0_nor_flash_partitions),
+};
+
+static struct resource armadillo5x0_nor_flash_resource = {
+       .flags          = IORESOURCE_MEM,
+       .start          = CS0_BASE_ADDR,
+       .end            = CS0_BASE_ADDR + SZ_64M - 1,
+};
+
+static struct platform_device armadillo5x0_nor_flash = {
+       .name                   = "physmap-flash",
+       .id                     = -1,
+       .num_resources          = 1,
+       .resource               = &armadillo5x0_nor_flash_resource,
 };
 
 /*
@@ -272,6 +325,16 @@ static void __init armadillo5x0_init(void)
        /* Register FB */
        mxc_register_device(&mx3_ipu, &mx3_ipu_data);
        mxc_register_device(&mx3_fb, &mx3fb_pdata);
+
+       /* Register NOR Flash */
+       mxc_register_device(&armadillo5x0_nor_flash,
+                           &armadillo5x0_nor_flash_pdata);
+
+       /* Register NAND Flash */
+       mxc_register_device(&mxc_nand_device, &armadillo5x0_nand_flash_pdata);
+
+       /* set NAND page size to 2k if not configured via boot mode pins */
+       __raw_writel(__raw_readl(MXC_CCM_RCSR) | (1 << 30), MXC_CCM_RCSR);
 }
 
 static void __init armadillo5x0_timer_init(void)
index d927eddcad460432200db70adf10ae4a5263f55e..9e87e08fb121f50288d8e98682b1d5e6d4a4aafa 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/platform_device.h>
 #include <linux/serial.h>
 #include <linux/gpio.h>
-#include <linux/dma-mapping.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/common.h>
index c6f61a1f06c8a2477bbc74e5111433abadbb0c6f..840cfda341d08c883489cc537d5ed851e93bd58d 100644 (file)
@@ -18,7 +18,7 @@
 
 #include <linux/types.h>
 #include <linux/init.h>
-
+#include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/plat-ram.h>
 #include <linux/irq.h>
 #include <linux/fsl_devices.h>
 
-#include <mach/hardware.h>
+#include <media/soc_camera.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
+#include <mach/board-pcm037.h>
 #include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/i2c.h>
 #include <mach/imx-uart.h>
 #include <mach/iomux-mx3.h>
 #include <mach/ipu.h>
-#include <mach/board-pcm037.h>
+#include <mach/mmc.h>
+#include <mach/mx3_camera.h>
 #include <mach/mx3fb.h>
 #include <mach/mxc_nand.h>
-#include <mach/mmc.h>
-#ifdef CONFIG_I2C_IMX
-#include <mach/i2c.h>
-#endif
 
 #include "devices.h"
+#include "pcm037.h"
+
+static enum pcm037_board_variant pcm037_instance = PCM037_PCM970;
+
+static int __init pcm037_variant_setup(char *str)
+{
+       if (!strcmp("eet", str))
+               pcm037_instance = PCM037_EET;
+       else if (strcmp("pcm970", str))
+               pr_warning("Unknown pcm037 baseboard variant %s\n", str);
+
+       return 1;
+}
+
+/* Supported values: "pcm970" (default) and "eet" */
+__setup("pcm037_variant=", pcm037_variant_setup);
+
+enum pcm037_board_variant pcm037_variant(void)
+{
+       return pcm037_instance;
+}
+
+/* UART1 with RTS/CTS handshake signals */
+static unsigned int pcm037_uart1_handshake_pins[] = {
+       MX31_PIN_CTS1__CTS1,
+       MX31_PIN_RTS1__RTS1,
+       MX31_PIN_TXD1__TXD1,
+       MX31_PIN_RXD1__RXD1,
+};
+
+/* UART1 without RTS/CTS handshake signals */
+static unsigned int pcm037_uart1_pins[] = {
+       MX31_PIN_TXD1__TXD1,
+       MX31_PIN_RXD1__RXD1,
+};
 
 static unsigned int pcm037_pins[] = {
        /* I2C */
        MX31_PIN_CSPI2_MOSI__SCL,
        MX31_PIN_CSPI2_MISO__SDA,
+       MX31_PIN_CSPI2_SS2__I2C3_SDA,
+       MX31_PIN_CSPI2_SCLK__I2C3_SCL,
        /* SDHC1 */
        MX31_PIN_SD1_DATA3__SD1_DATA3,
        MX31_PIN_SD1_DATA2__SD1_DATA2,
@@ -73,11 +111,6 @@ static unsigned int pcm037_pins[] = {
        MX31_PIN_CSPI1_SS0__SS0,
        MX31_PIN_CSPI1_SS1__SS1,
        MX31_PIN_CSPI1_SS2__SS2,
-       /* UART1 */
-       MX31_PIN_CTS1__CTS1,
-       MX31_PIN_RTS1__RTS1,
-       MX31_PIN_TXD1__TXD1,
-       MX31_PIN_RXD1__RXD1,
        /* UART2 */
        MX31_PIN_TXD2__TXD2,
        MX31_PIN_RXD2__RXD2,
@@ -120,6 +153,22 @@ static unsigned int pcm037_pins[] = {
        MX31_PIN_D3_SPL__D3_SPL,
        MX31_PIN_D3_CLS__D3_CLS,
        MX31_PIN_LCS0__GPI03_23,
+       /* CSI */
+       IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_GPIO),
+       MX31_PIN_CSI_D6__CSI_D6,
+       MX31_PIN_CSI_D7__CSI_D7,
+       MX31_PIN_CSI_D8__CSI_D8,
+       MX31_PIN_CSI_D9__CSI_D9,
+       MX31_PIN_CSI_D10__CSI_D10,
+       MX31_PIN_CSI_D11__CSI_D11,
+       MX31_PIN_CSI_D12__CSI_D12,
+       MX31_PIN_CSI_D13__CSI_D13,
+       MX31_PIN_CSI_D14__CSI_D14,
+       MX31_PIN_CSI_D15__CSI_D15,
+       MX31_PIN_CSI_HSYNC__CSI_HSYNC,
+       MX31_PIN_CSI_MCLK__CSI_MCLK,
+       MX31_PIN_CSI_PIXCLK__CSI_PIXCLK,
+       MX31_PIN_CSI_VSYNC__CSI_VSYNC,
 };
 
 static struct physmap_flash_data pcm037_flash_data = {
@@ -250,19 +299,43 @@ static struct mxc_nand_platform_data pcm037_nand_board_info = {
        .hw_ecc = 1,
 };
 
-#ifdef CONFIG_I2C_IMX
 static struct imxi2c_platform_data pcm037_i2c_1_data = {
        .bitrate = 100000,
 };
 
+static struct imxi2c_platform_data pcm037_i2c_2_data = {
+       .bitrate = 20000,
+};
+
 static struct at24_platform_data board_eeprom = {
        .byte_len = 4096,
        .page_size = 32,
        .flags = AT24_FLAG_ADDR16,
 };
 
+static int pcm037_camera_power(struct device *dev, int on)
+{
+       /* disable or enable the camera in X7 or X8 PCM970 connector */
+       gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), !on);
+       return 0;
+}
+
+static struct i2c_board_info pcm037_i2c_2_devices[] = {
+       {
+               I2C_BOARD_INFO("mt9t031", 0x5d),
+       },
+};
+
+static struct soc_camera_link iclink = {
+       .bus_id         = 0,            /* Must match with the camera ID */
+       .power          = pcm037_camera_power,
+       .board_info     = &pcm037_i2c_2_devices[0],
+       .i2c_adapter_id = 2,
+       .module_name    = "mt9t031",
+};
+
 static struct i2c_board_info pcm037_i2c_devices[] = {
-       {
+       {
                I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
                .platform_data = &board_eeprom,
        }, {
@@ -270,7 +343,14 @@ static struct i2c_board_info pcm037_i2c_devices[] = {
                .type = "pcf8563",
        }
 };
-#endif
+
+static struct platform_device pcm037_camera = {
+       .name   = "soc-camera-pdrv",
+       .id     = 0,
+       .dev    = {
+               .platform_data = &iclink,
+       },
+};
 
 /* Not connected by default */
 #ifdef PCM970_SDHC_RW_SWITCH
@@ -334,9 +414,41 @@ static struct imxmmc_platform_data sdhc_pdata = {
        .exit = pcm970_sdhc1_exit,
 };
 
+struct mx3_camera_pdata camera_pdata = {
+       .dma_dev        = &mx3_ipu.dev,
+       .flags          = MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10,
+       .mclk_10khz     = 2000,
+};
+
+static int __init pcm037_camera_alloc_dma(const size_t buf_size)
+{
+       dma_addr_t dma_handle;
+       void *buf;
+       int dma;
+
+       if (buf_size < 2 * 1024 * 1024)
+               return -EINVAL;
+
+       buf = dma_alloc_coherent(NULL, buf_size, &dma_handle, GFP_KERNEL);
+       if (!buf) {
+               pr_err("%s: cannot allocate camera buffer-memory\n", __func__);
+               return -ENOMEM;
+       }
+
+       memset(buf, 0, buf_size);
+
+       dma = dma_declare_coherent_memory(&mx3_camera.dev,
+                                       dma_handle, dma_handle, buf_size,
+                                       DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
+
+       /* The way we call dma_declare_coherent_memory only a malloc can fail */
+       return dma & DMA_MEMORY_MAP ? 0 : -ENOMEM;
+}
+
 static struct platform_device *devices[] __initdata = {
        &pcm037_flash,
        &pcm037_sram_device,
+       &pcm037_camera,
 };
 
 static struct ipu_platform_data mx3_ipu_data = {
@@ -377,6 +489,22 @@ static const struct fb_videomode fb_modedb[] = {
                .sync           = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH,
                .vmode          = FB_VMODE_NONINTERLACED,
                .flag           = 0,
+       }, {
+               /* 240x320 @ 60 Hz */
+               .name           = "CMEL-OLED",
+               .refresh        = 60,
+               .xres           = 240,
+               .yres           = 320,
+               .pixclock       = 185925,
+               .left_margin    = 9,
+               .right_margin   = 16,
+               .upper_margin   = 7,
+               .lower_margin   = 9,
+               .hsync_len      = 1,
+               .vsync_len      = 1,
+               .sync           = FB_SYNC_OE_ACT_HIGH | FB_SYNC_CLK_INVERT,
+               .vmode          = FB_VMODE_NONINTERLACED,
+               .flag           = 0,
        },
 };
 
@@ -397,6 +525,14 @@ static void __init mxc_board_init(void)
        mxc_iomux_setup_multiple_pins(pcm037_pins, ARRAY_SIZE(pcm037_pins),
                        "pcm037");
 
+       if (pcm037_variant() == PCM037_EET)
+               mxc_iomux_setup_multiple_pins(pcm037_uart1_pins,
+                       ARRAY_SIZE(pcm037_uart1_pins), "pcm037_uart1");
+       else
+               mxc_iomux_setup_multiple_pins(pcm037_uart1_handshake_pins,
+                       ARRAY_SIZE(pcm037_uart1_handshake_pins),
+                       "pcm037_uart1");
+
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
        mxc_register_device(&mxc_uart_device0, &uart_pdata);
@@ -415,18 +551,30 @@ static void __init mxc_board_init(void)
        }
 
 
-#ifdef CONFIG_I2C_IMX
+       /* I2C adapters and devices */
        i2c_register_board_info(1, pcm037_i2c_devices,
                        ARRAY_SIZE(pcm037_i2c_devices));
 
        mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data);
-#endif
+       mxc_register_device(&mxc_i2c_device2, &pcm037_i2c_2_data);
+
        mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info);
        mxc_register_device(&mxcsdhc_device0, &sdhc_pdata);
        mxc_register_device(&mx3_ipu, &mx3_ipu_data);
        mxc_register_device(&mx3_fb, &mx3fb_pdata);
        if (!gpio_usbotg_hs_activate())
                mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
+
+       /* CSI */
+       /* Camera power: default - off */
+       ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), "mt9t031-power");
+       if (!ret)
+               gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), 1);
+       else
+               iclink.power = NULL;
+
+       if (!pcm037_camera_alloc_dma(4 * 1024 * 1024))
+               mxc_register_device(&mx3_camera, &camera_pdata);
 }
 
 static void __init pcm037_timer_init(void)
@@ -448,4 +596,3 @@ MACHINE_START(PCM037, "Phytec Phycore pcm037")
        .init_machine   = mxc_board_init,
        .timer          = &pcm037_timer,
 MACHINE_END
-
diff --git a/arch/arm/mach-mx3/pcm037.h b/arch/arm/mach-mx3/pcm037.h
new file mode 100644 (file)
index 0000000..d692972
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __PCM037_H__
+#define __PCM037_H__
+
+enum pcm037_board_variant {
+       PCM037_PCM970,
+       PCM037_EET,
+};
+
+extern enum pcm037_board_variant pcm037_variant(void);
+
+#endif
diff --git a/arch/arm/mach-mx3/pcm037_eet.c b/arch/arm/mach-mx3/pcm037_eet.c
new file mode 100644 (file)
index 0000000..fe52fb1
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2009
+ * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#include <mach/common.h>
+#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
+#include <mach/spi.h>
+#endif
+#include <mach/iomux-mx3.h>
+
+#include <asm/mach-types.h>
+
+#include "pcm037.h"
+#include "devices.h"
+
+static unsigned int pcm037_eet_pins[] = {
+       /* SPI #1 */
+       MX31_PIN_CSPI1_MISO__MISO,
+       MX31_PIN_CSPI1_MOSI__MOSI,
+       MX31_PIN_CSPI1_SCLK__SCLK,
+       MX31_PIN_CSPI1_SPI_RDY__SPI_RDY,
+       MX31_PIN_CSPI1_SS0__SS0,
+       MX31_PIN_CSPI1_SS1__SS1,
+       MX31_PIN_CSPI1_SS2__SS2,
+
+       /* Reserve and hardwire GPIO 57 high - S6E63D6 chipselect */
+       IOMUX_MODE(MX31_PIN_KEY_COL7, IOMUX_CONFIG_GPIO),
+       /* GPIO keys */
+       IOMUX_MODE(MX31_PIN_GPIO1_0,    IOMUX_CONFIG_GPIO), /* 0 */
+       IOMUX_MODE(MX31_PIN_GPIO1_1,    IOMUX_CONFIG_GPIO), /* 1 */
+       IOMUX_MODE(MX31_PIN_GPIO1_2,    IOMUX_CONFIG_GPIO), /* 2 */
+       IOMUX_MODE(MX31_PIN_GPIO1_3,    IOMUX_CONFIG_GPIO), /* 3 */
+       IOMUX_MODE(MX31_PIN_SVEN0,      IOMUX_CONFIG_GPIO), /* 32 */
+       IOMUX_MODE(MX31_PIN_STX0,       IOMUX_CONFIG_GPIO), /* 33 */
+       IOMUX_MODE(MX31_PIN_SRX0,       IOMUX_CONFIG_GPIO), /* 34 */
+       IOMUX_MODE(MX31_PIN_SIMPD0,     IOMUX_CONFIG_GPIO), /* 35 */
+       IOMUX_MODE(MX31_PIN_RTS1,       IOMUX_CONFIG_GPIO), /* 38 */
+       IOMUX_MODE(MX31_PIN_CTS1,       IOMUX_CONFIG_GPIO), /* 39 */
+       IOMUX_MODE(MX31_PIN_KEY_ROW4,   IOMUX_CONFIG_GPIO), /* 50 */
+       IOMUX_MODE(MX31_PIN_KEY_ROW5,   IOMUX_CONFIG_GPIO), /* 51 */
+       IOMUX_MODE(MX31_PIN_KEY_ROW6,   IOMUX_CONFIG_GPIO), /* 52 */
+       IOMUX_MODE(MX31_PIN_KEY_ROW7,   IOMUX_CONFIG_GPIO), /* 53 */
+
+       /* LEDs */
+       IOMUX_MODE(MX31_PIN_DTR_DTE1,   IOMUX_CONFIG_GPIO), /* 44 */
+       IOMUX_MODE(MX31_PIN_DSR_DTE1,   IOMUX_CONFIG_GPIO), /* 45 */
+       IOMUX_MODE(MX31_PIN_KEY_COL5,   IOMUX_CONFIG_GPIO), /* 55 */
+       IOMUX_MODE(MX31_PIN_KEY_COL6,   IOMUX_CONFIG_GPIO), /* 56 */
+};
+
+/* SPI */
+static struct spi_board_info pcm037_spi_dev[] = {
+       {
+               .modalias       = "dac124s085",
+               .max_speed_hz   = 400000,
+               .bus_num        = 0,
+               .chip_select    = 0,            /* Index in pcm037_spi1_cs[] */
+               .mode           = SPI_CPHA,
+       },
+};
+
+/* Platform Data for MXC CSPI */
+#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
+static int pcm037_spi1_cs[] = {MXC_SPI_CS(1), IOMUX_TO_GPIO(MX31_PIN_KEY_COL7)};
+
+struct spi_imx_master pcm037_spi1_master = {
+       .chipselect = pcm037_spi1_cs,
+       .num_chipselect = ARRAY_SIZE(pcm037_spi1_cs),
+};
+#endif
+
+/* GPIO-keys input device */
+static struct gpio_keys_button pcm037_gpio_keys[] = {
+       {
+               .type   = EV_KEY,
+               .code   = KEY_L,
+               .gpio   = 0,
+               .desc   = "Wheel Manual",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_A,
+               .gpio   = 1,
+               .desc   = "Wheel AF",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_V,
+               .gpio   = 2,
+               .desc   = "Wheel View",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_M,
+               .gpio   = 3,
+               .desc   = "Wheel Menu",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_UP,
+               .gpio   = 32,
+               .desc   = "Nav Pad Up",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_RIGHT,
+               .gpio   = 33,
+               .desc   = "Nav Pad Right",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_DOWN,
+               .gpio   = 34,
+               .desc   = "Nav Pad Down",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_LEFT,
+               .gpio   = 35,
+               .desc   = "Nav Pad Left",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_ENTER,
+               .gpio   = 38,
+               .desc   = "Nav Pad Ok",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_O,
+               .gpio   = 39,
+               .desc   = "Wheel Off",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = BTN_FORWARD,
+               .gpio   = 50,
+               .desc   = "Focus Forward",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = BTN_BACK,
+               .gpio   = 51,
+               .desc   = "Focus Backward",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = BTN_MIDDLE,
+               .gpio   = 52,
+               .desc   = "Release Half",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = BTN_EXTRA,
+               .gpio   = 53,
+               .desc   = "Release Full",
+               .wakeup = 0,
+       },
+};
+
+static struct gpio_keys_platform_data pcm037_gpio_keys_platform_data = {
+       .buttons        = pcm037_gpio_keys,
+       .nbuttons       = ARRAY_SIZE(pcm037_gpio_keys),
+       .rep            = 0, /* No auto-repeat */
+};
+
+static struct platform_device pcm037_gpio_keys_device = {
+       .name   = "gpio-keys",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &pcm037_gpio_keys_platform_data,
+       },
+};
+
+static int eet_init_devices(void)
+{
+       if (!machine_is_pcm037() || pcm037_variant() != PCM037_EET)
+               return 0;
+
+       mxc_iomux_setup_multiple_pins(pcm037_eet_pins,
+                               ARRAY_SIZE(pcm037_eet_pins), "pcm037_eet");
+
+       /* SPI */
+       spi_register_board_info(pcm037_spi_dev, ARRAY_SIZE(pcm037_spi_dev));
+#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
+       mxc_register_device(&mxc_spi_device0, &pcm037_spi1_master);
+#endif
+
+       platform_device_register(&pcm037_gpio_keys_device);
+
+       return 0;
+}
+
+late_initcall(eet_init_devices);
index ae8441192ef07a2d0c3ab7f07fafdbf2f974859b..7139e0dc26d16062304bd72beca1f339e61899e7 100644 (file)
 #define GPIO37_ULPI_DATA_OUT_7 MFP_CFG(GPIO37, AF3)
 #define GPIO33_ULPI_OTG_INTR   MFP_CFG(GPIO33, AF1)
 
-#define ULPI_DIR       MFP_CFG_DRV(ULPI_DIR, MFP_AF0, MFP_DS01X)
-#define ULPI_NXT       MFP_CFG_DRV(ULPI_NXT, MFP_AF0, MFP_DS01X)
-#define ULPI_STP       MFP_CFG_DRV(ULPI_STP, MFP_AF0, MFP_DS01X)
+#define ULPI_DIR       MFP_CFG_DRV(ULPI_DIR, AF0, DS01X)
+#define ULPI_NXT       MFP_CFG_DRV(ULPI_NXT, AF0, DS01X)
+#define ULPI_STP       MFP_CFG_DRV(ULPI_STP, AF0, DS01X)
 #endif /* CONFIG_CPU_PXA310 */
 
 #endif /* __ASM_ARCH_MFP_PXA300_H */
index 6f678d93bf4eb2f0da4b1a142c39945d127503be..09b7b1a10cadf9beb86fb51affa9bbea4ed26c11 100644 (file)
@@ -250,7 +250,7 @@ static DEFINE_PXA3_CKEN(pxa3xx_mmc2, MMC2, 19500000, 0);
 static struct clk_lookup pxa3xx_clkregs[] = {
        INIT_CLKREG(&clk_pxa3xx_pout, NULL, "CLK_POUT"),
        /* Power I2C clock is always on */
-       INIT_CLKREG(&clk_dummy, "pxa2xx-i2c.1", NULL),
+       INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL),
        INIT_CLKREG(&clk_pxa3xx_lcd, "pxa2xx-fb", NULL),
        INIT_CLKREG(&clk_pxa3xx_camera, NULL, "CAMCLK"),
        INIT_CLKREG(&clk_pxa3xx_ac97, NULL, "AC97CLK"),
index 9ea9c05093cd47afed1d6798d5a2eeb9d9333f43..facbd49eec67e30bb1d3dbfedf2364fe964a1cdc 100644 (file)
@@ -208,8 +208,7 @@ struct platform_device realview_i2c_device = {
 
 static struct i2c_board_info realview_i2c_board_info[] = {
        {
-               I2C_BOARD_INFO("rtc-ds1307", 0xd0 >> 1),
-               .type = "ds1338",
+               I2C_BOARD_INFO("ds1338", 0xd0 >> 1),
        },
 };
 
index 89b3ccf35e1bbf74740c2c856f03ad908b694fe9..7936085dd75881c3faca30adcbede5a8ba60db56 100644 (file)
@@ -455,8 +455,8 @@ void __init u300_init_irq(void)
        for (i = 0; i < NR_IRQS; i++)
                set_bit(i, (unsigned long *) &mask[0]);
        u300_enable_intcon_clock();
-       vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], 0);
-       vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], 0);
+       vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], mask[0]);
+       vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], mask[1]);
 }
 
 
index 69214fc8bd19576093accb6904549ecc2e12fa0c..31093af7d05211ba940d80d6700291257db1bb6c 100644 (file)
@@ -342,8 +342,7 @@ static struct platform_device versatile_i2c_device = {
 
 static struct i2c_board_info versatile_i2c_board_info[] = {
        {
-               I2C_BOARD_INFO("rtc-ds1307", 0xd0 >> 1),
-               .type = "ds1338",
+               I2C_BOARD_INFO("ds1338", 0xd0 >> 1),
        },
 };
 
index 27f8d1b2bc6ba611bc0759b1900f81a39182c9d9..2eb182f73876acfc1c33965d2e82e3f20a23360f 100644 (file)
@@ -602,6 +602,8 @@ enum iomux_pins {
 #define MX31_PIN_I2C_DAT__SDA          IOMUX_MODE(MX31_PIN_I2C_DAT, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_DCD_DTE1__I2C2_SDA    IOMUX_MODE(MX31_PIN_DCD_DTE1, IOMUX_CONFIG_ALT2)
 #define MX31_PIN_RI_DTE1__I2C2_SCL     IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_CSPI2_SS2__I2C3_SDA   IOMUX_MODE(MX31_PIN_CSPI2_SS2, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI2_SCLK__I2C3_SCL  IOMUX_MODE(MX31_PIN_CSPI2_SCLK, IOMUX_CONFIG_ALT1)
 #define MX31_PIN_CSI_D4__CSI_D4                IOMUX_MODE(MX31_PIN_CSI_D4, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_CSI_D5__CSI_D5                IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_CSI_D6__CSI_D6                IOMUX_MODE(MX31_PIN_CSI_D6, IOMUX_CONFIG_FUNC)
index abc79d44acaacd472a3f1996c5c060487cbeba08..98548c6903a08aadff48196e2c4f6148968fc83d 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sysdev.h>
-#include <linux/bootmem.h>
+#include <linux/slab.h>
 
 #include <mach/gpio.h>
 
@@ -112,17 +112,12 @@ static int __init pxa_init_gpio_chip(int gpio_end)
        int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
        struct pxa_gpio_chip *chips;
 
-       /* this is early, we have to use bootmem allocator, and we really
-        * want this to be allocated dynamically for different 'gpio_end'
-        */
-       chips = alloc_bootmem_low(nbanks * sizeof(struct pxa_gpio_chip));
+       chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
        if (chips == NULL) {
                pr_err("%s: failed to allocate GPIO chips\n", __func__);
                return -ENOMEM;
        }
 
-       memset(chips, 0, nbanks * sizeof(struct pxa_gpio_chip));
-
        for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
                struct gpio_chip *c = &chips[i].chip;
 
index 16561ab18b38b602a9426a9f0c6c0b8bcb8aac93..f8a664f022b1ad1022bf7c9aa842e369124e4808 100644 (file)
        [--sp] = RETN;
        [--sp] = RETE;
        [--sp] = SEQSTAT;
-#ifdef CONFIG_KGDB
-       r1.l = lo(IPEND);
-       r1.h = hi(IPEND);
+#ifdef CONFIG_DEBUG_KERNEL
+       p1.l = lo(IPEND);
+       p1.h = hi(IPEND);
+       r1 = [p1];
        [--sp] = r1;
 #else
        [--sp] = r0;    /* Skip IPEND as well. */
index 565b8136855ed16d5237376cc7186878dcc46855..fadfa82f93b2d11c3ffa3cbfa9324a10c4b94261 100644 (file)
@@ -32,7 +32,6 @@ struct blackfin_cpudata {
        struct task_struct *idle;
        unsigned int imemctl;
        unsigned int dmemctl;
-       unsigned long loops_per_jiffy;
        unsigned long dcache_invld_count;
        unsigned long icache_invld_count;
 };
index cbd52f86bb9f752ce8f33dff091546e815a3ed38..0b78b873df5103fca28d39673703a4aac45e3e04 100644 (file)
@@ -6,6 +6,9 @@
 extern void ack_bad_irq(unsigned int irq);
 #define ack_bad_irq ack_bad_irq
 
+/* Define until common code gets sane defaults */
+#define HARDIRQ_BITS 9
+
 #include <asm-generic/hardirq.h>
 
 #endif
index d0be99be8308d3a9324dacae900939f384e6f1e0..a36ad8dac0681914dd067af2a6c1609d39e475c5 100644 (file)
@@ -105,23 +105,16 @@ static inline uint32_t __pure bfin_revid(void)
        /* Always use CHIPID, to work around ANOMALY_05000234 */
        uint32_t revid = (bfin_read_CHIPID() & CHIPID_VERSION) >> 28;
 
-#ifdef CONFIG_BF52x
-       /* ANOMALY_05000357
+#ifdef _BOOTROM_GET_DXE_ADDRESS_TWI
+       /*
+        * ANOMALY_05000364
         * Incorrect Revision Number in DSPID Register
         */
-       if (revid == 0)
-               switch (bfin_read16(_BOOTROM_GET_DXE_ADDRESS_TWI)) {
-               case 0x0010:
-                       revid = 0;
-                       break;
-               case 0x2796:
-                       revid = 1;
-                       break;
-               default:
-                       revid = 0xFFFF;
-                       break;
-               }
+       if (ANOMALY_05000364 &&
+           bfin_read16(_BOOTROM_GET_DXE_ADDRESS_TWI) == 0x2796)
+               revid = 1;
 #endif
+
        return revid;
 }
 
index e0bf8cc06907abd67040c37127f0091792c39a8a..9f9b82816652d6bddc4c67199699d9ba22647e1f 100644 (file)
@@ -253,32 +253,31 @@ void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size)
        BUG_ON(src % 4);
        BUG_ON(size % 4);
 
-       /* Force a sync in case a previous config reset on this channel
-        * occurred.  This is needed so subsequent writes to DMA registers
-        * are not spuriously lost/corrupted.
-        */
-       __builtin_bfin_ssync();
-
        src_ch = 0;
        /* Find an avalible memDMA channel */
        while (1) {
-               if (!src_ch || src_ch == (struct dma_register *)MDMA_S1_NEXT_DESC_PTR) {
-                       dst_ch = (struct dma_register *)MDMA_D0_NEXT_DESC_PTR;
-                       src_ch = (struct dma_register *)MDMA_S0_NEXT_DESC_PTR;
-               } else {
+               if (src_ch == (struct dma_register *)MDMA_S0_NEXT_DESC_PTR) {
                        dst_ch = (struct dma_register *)MDMA_D1_NEXT_DESC_PTR;
                        src_ch = (struct dma_register *)MDMA_S1_NEXT_DESC_PTR;
+               } else {
+                       dst_ch = (struct dma_register *)MDMA_D0_NEXT_DESC_PTR;
+                       src_ch = (struct dma_register *)MDMA_S0_NEXT_DESC_PTR;
                }
 
-               if (!bfin_read16(&src_ch->cfg)) {
+               if (!bfin_read16(&src_ch->cfg))
+                       break;
+               else if (bfin_read16(&dst_ch->irq_status) & DMA_DONE) {
+                       bfin_write16(&src_ch->cfg, 0);
                        break;
-               } else {
-                       if (bfin_read16(&src_ch->irq_status) & DMA_DONE)
-                               bfin_write16(&src_ch->cfg, 0);
                }
-
        }
 
+       /* Force a sync in case a previous config reset on this channel
+        * occurred.  This is needed so subsequent writes to DMA registers
+        * are not spuriously lost/corrupted.
+        */
+       __builtin_bfin_ssync();
+
        /* Destination */
        bfin_write32(&dst_ch->start_addr, dst);
        bfin_write16(&dst_ch->x_count, size >> 2);
index beffa00a93c3a6e2d98f236e82f1653e232c40e8..6b94462713710b612f3fb82e351b92d5e5bdb46a 100644 (file)
@@ -686,14 +686,12 @@ void bfin_gpio_pm_hibernate_restore(void)
                *port_fer[bank] = gpio_bank_saved[bank].fer;
 #endif
                gpio_array[bank]->inen  = gpio_bank_saved[bank].inen;
+               gpio_array[bank]->data_set = gpio_bank_saved[bank].data
+                                               & gpio_bank_saved[bank].dir;
                gpio_array[bank]->dir   = gpio_bank_saved[bank].dir;
                gpio_array[bank]->polar = gpio_bank_saved[bank].polar;
                gpio_array[bank]->edge  = gpio_bank_saved[bank].edge;
                gpio_array[bank]->both  = gpio_bank_saved[bank].both;
-
-               gpio_array[bank]->data_set = gpio_bank_saved[bank].data
-                                               | gpio_bank_saved[bank].dir;
-
                gpio_array[bank]->maska = gpio_bank_saved[bank].maska;
        }
        AWA_DUMMY_READ(maska);
index d6c067782e638987ba406164f6df65adeb0b15db..685f160a5a369789671f948e2132d36fb5c2e29b 100644 (file)
@@ -72,13 +72,24 @@ void __init generate_cplb_tables_cpu(unsigned int cpu)
        }
 
        /* Cover L1 memory.  One 4M area for code and data each is enough.  */
-       if (L1_DATA_A_LENGTH || L1_DATA_B_LENGTH) {
-               d_tbl[i_d].addr = L1_DATA_A_START;
-               d_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
+       if (cpu == 0) {
+               if (L1_DATA_A_LENGTH || L1_DATA_B_LENGTH) {
+                       d_tbl[i_d].addr = L1_DATA_A_START;
+                       d_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
+               }
+               i_tbl[i_i].addr = L1_CODE_START;
+               i_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
        }
-       i_tbl[i_i].addr = L1_CODE_START;
-       i_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
-
+#ifdef CONFIG_SMP
+       else {
+               if (L1_DATA_A_LENGTH || L1_DATA_B_LENGTH) {
+                       d_tbl[i_d].addr = COREB_L1_DATA_A_START;
+                       d_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
+               }
+               i_tbl[i_i].addr = COREB_L1_CODE_START;
+               i_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
+       }
+#endif
        first_switched_dcplb = i_d;
        first_switched_icplb = i_i;
 
index 79cad0ac5892eacdcb153e046eb3ee6115c5c69d..9da36bab7ccb10194a3cde2c40628f4e52aeeccb 100644 (file)
@@ -361,7 +361,7 @@ static inline
 int in_mem_const(unsigned long addr, unsigned long size,
                  unsigned long const_addr, unsigned long const_size)
 {
-       return in_mem_const_off(addr, 0, size, const_addr, const_size);
+       return in_mem_const_off(addr, size, 0, const_addr, const_size);
 }
 #define IN_ASYNC(bnum, bctlnum) \
 ({ \
@@ -390,13 +390,13 @@ int bfin_mem_access_type(unsigned long addr, unsigned long size)
        if (in_mem_const(addr, size, L1_DATA_B_START, L1_DATA_B_LENGTH))
                return cpu == 0 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA;
 #ifdef COREB_L1_CODE_START
-       if (in_mem_const(addr, size, COREB_L1_CODE_START, L1_CODE_LENGTH))
+       if (in_mem_const(addr, size, COREB_L1_CODE_START, COREB_L1_CODE_LENGTH))
                return cpu == 1 ? BFIN_MEM_ACCESS_ITEST : BFIN_MEM_ACCESS_IDMA;
        if (in_mem_const(addr, size, COREB_L1_SCRATCH_START, L1_SCRATCH_LENGTH))
                return cpu == 1 ? BFIN_MEM_ACCESS_CORE_ONLY : -EFAULT;
-       if (in_mem_const(addr, size, COREB_L1_DATA_A_START, L1_DATA_A_LENGTH))
+       if (in_mem_const(addr, size, COREB_L1_DATA_A_START, COREB_L1_DATA_A_LENGTH))
                return cpu == 1 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA;
-       if (in_mem_const(addr, size, COREB_L1_DATA_B_START, L1_DATA_B_LENGTH))
+       if (in_mem_const(addr, size, COREB_L1_DATA_B_START, COREB_L1_DATA_B_LENGTH))
                return cpu == 1 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA;
 #endif
        if (in_mem_const(addr, size, L2_START, L2_LENGTH))
@@ -472,13 +472,13 @@ int _access_ok(unsigned long addr, unsigned long size)
        if (in_mem_const_off(addr, size, _ebss_b_l1 - _sdata_b_l1, L1_DATA_B_START, L1_DATA_B_LENGTH))
                return 1;
 #ifdef COREB_L1_CODE_START
-       if (in_mem_const(addr, size, COREB_L1_CODE_START, L1_CODE_LENGTH))
+       if (in_mem_const(addr, size, COREB_L1_CODE_START, COREB_L1_CODE_LENGTH))
                return 1;
        if (in_mem_const(addr, size, COREB_L1_SCRATCH_START, L1_SCRATCH_LENGTH))
                return 1;
-       if (in_mem_const(addr, size, COREB_L1_DATA_A_START, L1_DATA_A_LENGTH))
+       if (in_mem_const(addr, size, COREB_L1_DATA_A_START, COREB_L1_DATA_A_LENGTH))
                return 1;
-       if (in_mem_const(addr, size, COREB_L1_DATA_B_START, L1_DATA_B_LENGTH))
+       if (in_mem_const(addr, size, COREB_L1_DATA_B_START, COREB_L1_DATA_B_LENGTH))
                return 1;
 #endif
        if (in_mem_const_off(addr, size, _ebss_l2 - _stext_l2, L2_START, L2_LENGTH))
index 6136c33e919f79b700efcac55623eaf5a53f1911..6225edae488edeb713db588487fe709d839572eb 100644 (file)
@@ -168,7 +168,6 @@ void __cpuinit bfin_setup_cpudata(unsigned int cpu)
        struct blackfin_cpudata *cpudata = &per_cpu(cpu_data, cpu);
 
        cpudata->idle = current;
-       cpudata->loops_per_jiffy = loops_per_jiffy;
        cpudata->imemctl = bfin_read_IMEM_CONTROL();
        cpudata->dmemctl = bfin_read_DMEM_CONTROL();
 }
@@ -568,17 +567,23 @@ static __init void memory_setup(void)
 #  endif                               /* ANOMALY_05000263 */
 # endif                                /* CONFIG_ROMFS_FS */
 
-       memory_end -= mtd_size;
-
-       if (mtd_size == 0) {
-               console_init();
-               panic("Don't boot kernel without rootfs attached.");
+       /* Since the default MTD_UCLINUX has no magic number, we just blindly
+        * read 8 past the end of the kernel's image, and look at it.
+        * When no image is attached, mtd_size is set to a random number
+        * Do some basic sanity checks before operating on things
+        */
+       if (mtd_size == 0 || memory_end <= mtd_size) {
+               pr_emerg("Could not find valid ram mtd attached.\n");
+       } else {
+               memory_end -= mtd_size;
+
+               /* Relocate MTD image to the top of memory after the uncached memory area */
+               uclinux_ram_map.phys = memory_mtd_start = memory_end;
+               uclinux_ram_map.size = mtd_size;
+               pr_info("Found mtd parition at 0x%p, (len=0x%lx), moving to 0x%p\n",
+                       _end, mtd_size, (void *)memory_mtd_start);
+               dma_memcpy((void *)uclinux_ram_map.phys, _end, uclinux_ram_map.size);
        }
-
-       /* Relocate MTD image to the top of memory after the uncached memory area */
-       uclinux_ram_map.phys = memory_mtd_start = memory_end;
-       uclinux_ram_map.size = mtd_size;
-       dma_memcpy((void *)uclinux_ram_map.phys, _end, uclinux_ram_map.size);
 #endif                         /* CONFIG_MTD_UCLINUX */
 
 #if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
@@ -868,13 +873,6 @@ void __init setup_arch(char **cmdline_p)
        else
                printk(KERN_CONT "and Disabled\n");
 
-#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
-       /* we need to initialize the Flashrom device here since we might
-        * do things with flash early on in the boot
-        */
-       flash_probe();
-#endif
-
        printk(KERN_INFO "Boot Mode: %i\n", bfin_read_SYSCR() & 0xF);
 
        /* Newer parts mirror SWRST bits in SYSCR */
@@ -938,10 +936,6 @@ void __init setup_arch(char **cmdline_p)
                               CPU, bfin_revid());
        }
 
-       /* We can't run on BF548-0.1 due to ANOMALY 05000448 */
-       if (bfin_cpuid() == 0x27de && bfin_revid() == 1)
-               panic("You can't run on this processor due to 05000448");
-
        printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n");
 
        printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n",
@@ -1164,9 +1158,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                sclk/1000000, sclk%1000000);
        seq_printf(m, "bogomips\t: %lu.%02lu\n"
                "Calibration\t: %lu loops\n",
-               (cpudata->loops_per_jiffy * HZ) / 500000,
-               ((cpudata->loops_per_jiffy * HZ) / 5000) % 100,
-               (cpudata->loops_per_jiffy * HZ));
+               (loops_per_jiffy * HZ) / 500000,
+               ((loops_per_jiffy * HZ) / 5000) % 100,
+               (loops_per_jiffy * HZ));
 
        /* Check Cache configutation */
        switch (cpudata->dmemctl & (1 << DMC0_P | 1 << DMC1_P)) {
index 8a1caf2bb5b9defa94dc1fff7c6803afb3324fad..bf2b2d1f8ae5f35ecd64b68abbbc324f444fa421 100644 (file)
@@ -570,11 +570,12 @@ asmlinkage void trap_c(struct pt_regs *fp)
        if (kernel_mode_regs(fp) || (current && !current->mm)) {
                console_verbose();
                oops_in_progress = 1;
-               if (strerror)
-                       verbose_printk(strerror);
        }
 
        if (sig != SIGTRAP) {
+               if (strerror)
+                       verbose_printk(strerror);
+
                dump_bfin_process(fp);
                dump_bfin_mem(fp);
                show_regs(fp);
@@ -619,7 +620,9 @@ asmlinkage void trap_c(struct pt_regs *fp)
                force_sig_info(sig, &info, current);
        }
 
-       if (ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8))
+       if ((ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8)) ||
+           (ANOMALY_05000281 && trapnr == VEC_HWERR) ||
+           (ANOMALY_05000189 && (trapnr == VEC_CPLB_I_VL || trapnr == VEC_CPLB_VL)))
                fp->pc = SAFE_USER_INSTRUCTION;
 
  traps_done:
index 84b9c5592220eac8648306a57295047b21456671..e57bf6fbdf3f4040bee13652a35c984b8cc45d85 100644 (file)
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#define BITS_PER_UNIT 8
-
-typedef int SItype __attribute__ ((mode(SI)));
-typedef unsigned int USItype __attribute__ ((mode(SI)));
-typedef int DItype __attribute__ ((mode(DI)));
-typedef int word_type __attribute__ ((mode(__word__)));
-
-struct DIstruct {
-       SItype high, low;
-};
-
-typedef union {
-       struct DIstruct s;
-       DItype ll;
-} DIunion;
+#include "gcclib.h"
 
 #ifdef CONFIG_ARITHMETIC_OPS_L1
 DItype __lshrdi3(DItype u, word_type b)__attribute__((l1_text));
index d9791106be9f71b16187201736815a09bcfa8445..809be268e42d4fcdf20ea802bb35bb1d87677559 100644 (file)
@@ -534,7 +534,7 @@ static struct platform_device i2c_bfin_twi_device = {
 #endif
 
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
-#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
        },
index 426e064062a0322ed4a21fe29096869fdcf71cce..753ed810e1c61f8bc0b63d6a117c82504f3fbd9e 100644 (file)
@@ -82,6 +82,7 @@
 #define ANOMALY_05000179 (0)
 #define ANOMALY_05000182 (0)
 #define ANOMALY_05000183 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
 #define ANOMALY_05000202 (0)
 #define ANOMALY_05000215 (0)
 #define ANOMALY_05000357 (0)
 #define ANOMALY_05000362 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000371 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (0)
index 0fb2ce5d840e14ae73ba9058d19e4da9f3bd0733..dbade93395eb2b996e1467702504436a6c97c958 100644 (file)
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
index f4867ce0c618b89f64c9d634739f65bf8934de89..b09484f538f41abdf1ebf69ebd48acb7fe61f9c4 100644 (file)
@@ -793,7 +793,7 @@ static struct platform_device i2c_bfin_twi_device = {
 #endif
 
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
-#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
                .type = "pcf8574_lcd",
index b2f30f06b73e2290b40bc518d292c0a135ed6f14..2ad68cd10ae674af6b7d693afb98f7cbcdc79320 100644 (file)
@@ -591,7 +591,7 @@ static struct platform_device i2c_bfin_twi_device = {
 #endif
 
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
-#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
        },
index 799a1d1fa89044f87eae1691350199fae081f851..75e563d3f9d4f0f49aa87921a11781e8fbcbd01b 100644 (file)
@@ -858,7 +858,7 @@ static struct platform_device i2c_bfin_twi_device = {
 #endif
 
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
-#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
        },
index 0d63f7406168cd154684dd352c9b741f8f7ec8b0..c438ca89d8c9047c71669ffd652d67a92f135eb1 100644 (file)
 #define ANOMALY_05000443 (1)
 /* The WURESET Bit in the SYSCR Register is not Functional */
 #define ANOMALY_05000445 (1)
+/* USB DMA Short Packet Data Corruption */
+#define ANOMALY_05000450 (1)
 /* BCODE_QUICKBOOT, BCODE_ALLBOOT, and BCODE_FULLBOOT Settings in SYSCR Register Not Functional */
 #define ANOMALY_05000451 (1)
 /* Incorrect Default Hysteresis Setting for RESET, NMI, and BMODE Signals */
 #define ANOMALY_05000179 (0)
 #define ANOMALY_05000182 (0)
 #define ANOMALY_05000183 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
 #define ANOMALY_05000202 (0)
 #define ANOMALY_05000215 (0)
 #define ANOMALY_05000412 (0)
 #define ANOMALY_05000447 (0)
 #define ANOMALY_05000448 (0)
-#define ANOMALY_05000450 (0)
 
 #endif
index a625659dd67f4470d0ff310e833362ddd6ff3ebe..ebd6cebc1fbc40bd500b6df924b05fd81b1b53f7 100644 (file)
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
index a68ade8a3ca2a876c721c030efa84dfa01087d0d..3d743ccaff6ab8d4b543b091f72833b8c8f73a21 100644 (file)
@@ -453,7 +453,7 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
                .irq = 39,
        },
 #endif
-#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
        },
index 70a0ad69c6106f94c95a4b835cb917d4c086880c..cd83db2fb1a17fdc99e3cba7a7423005430afc80 100644 (file)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000353 (1)
 #define ANOMALY_05000362 (1)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
 #define ANOMALY_05000389 (0)
index a3789d7ccf8c233c4fc182be215ba7585742c7c8..4062e24e759bbc83eb51dedf8386fb7dcc9792bd 100644 (file)
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
index c1f76dd2c4ed50aac0fb806098e776854782b8b7..bd656907b8c01588983d0f4e3c1cf267679d0c5c 100644 (file)
@@ -1313,10 +1313,10 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
        {
                I2C_BOARD_INFO("ad7142_joystick", 0x2C),
-               .irq = IRQ_PF5,
+               .irq = IRQ_PG5,
        },
 #endif
-#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
        },
index 57c128cc3b6480a57762e5269bbccfb9365a6718..e66aa131f517d66ec5fe17588bf71d5f8c1cb7ef 100644 (file)
 #define ANOMALY_05000179 (0)
 #define ANOMALY_05000182 (0)
 #define ANOMALY_05000183 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
 #define ANOMALY_05000202 (0)
 #define ANOMALY_05000215 (0)
 #define ANOMALY_05000353 (1)
 #define ANOMALY_05000362 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
 #define ANOMALY_05000389 (0)
index b86662fb9de76fad4cf16b0ee3a46e5d81db4d32..e95d54f9af6c008075cb9529b47e066ac376cc4d 100644 (file)
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
index c97acdf85cd3020b70a362b17ceb53e16464813f..451cf8a82a42b0e1edbb3525232cf485587158af 100644 (file)
 #define ANOMALY_05000158 (0)
 #define ANOMALY_05000171 (0)
 #define ANOMALY_05000182 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
 #define ANOMALY_05000202 (0)
 #define ANOMALY_05000215 (0)
 #define ANOMALY_05000353 (1)
 #define ANOMALY_05000362 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
 #define ANOMALY_05000389 (0)
index c536551eb4b8ff64dd35194d9270e32014aa8704..999f239fe1a6376373efe75f5424398d48308ee1 100644 (file)
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
index 81f5b95cc3612d1592765274056c090627c6dfff..dc0dd9b2bcef46383369795cda3a3a19264e2fe4 100644 (file)
@@ -864,7 +864,7 @@ static struct i2c_board_info __initdata bfin_i2c_board_info0[] = {
 
 #if !defined(CONFIG_BF542)     /* The BF542 only has 1 TWI */
 static struct i2c_board_info __initdata bfin_i2c_board_info1[] = {
-#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
        },
index 18a4cd24f6732492bfeb9ed2bbb5ededb30f38fb..cd040fe0bc5c10e47b38f6fbd1882d5f3dbdad34 100644 (file)
 #define ANOMALY_05000179 (0)
 #define ANOMALY_05000182 (0)
 #define ANOMALY_05000183 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
 #define ANOMALY_05000202 (0)
 #define ANOMALY_05000215 (0)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000362 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000400 (0)
 #define ANOMALY_05000412 (0)
index 94b8e277f09d1d1773291fc6065c4be73e0b285a..a5312b2d267e25117d53a6875f0ffcc0c75c4e9c 100644 (file)
 #define ANOMALY_05000273 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000353 (1)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
 #define ANOMALY_05000389 (0)
index a1b50878553fbfc462e63a869a5ab7be1c190722..fd5e8878b8c419f73f99b84d89a5db7b96748173 100644 (file)
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
index a63e15c86d90438dec954ce6b6d883682e13374a..5b96ea549a049bb00a902e779da827e338d6d9da 100644 (file)
@@ -37,7 +37,6 @@
 
 /* Memory Map for ADSP-BF561 processors */
 
-#ifdef CONFIG_BF561
 #define COREA_L1_CODE_START       0xFFA00000
 #define COREA_L1_DATA_A_START     0xFF800000
 #define COREA_L1_DATA_B_START     0xFF900000
 #define BFIN_DCACHESIZE        (0*1024)
 #define BFIN_DSUPBANKS 0
 #endif /*CONFIG_BFIN_DCACHE*/
+
+/*
+ * If we are in SMP mode, then the cache settings of Core B will match
+ * the settings of Core A.  If we aren't, then we assume Core B is not
+ * using any cache.  This allows the rest of the kernel to work with
+ * the core in either mode as we are only loading user code into it and
+ * it is the user's problem to make sure they aren't doing something
+ * stupid there.
+ *
+ * Note that we treat the L1 code region as a contiguous blob to make
+ * the rest of the kernel simpler.  Easier to check one region than a
+ * bunch of small ones.  Again, possible misbehavior here is the fault
+ * of the user -- don't try to use memory that doesn't exist.
+ */
+#ifdef CONFIG_SMP
+# define COREB_L1_CODE_LENGTH     L1_CODE_LENGTH
+# define COREB_L1_DATA_A_LENGTH   L1_DATA_A_LENGTH
+# define COREB_L1_DATA_B_LENGTH   L1_DATA_B_LENGTH
+#else
+# define COREB_L1_CODE_LENGTH     0x14000
+# define COREB_L1_DATA_A_LENGTH   0x8000
+# define COREB_L1_DATA_B_LENGTH   0x8000
 #endif
 
 /* Level 2 Memory */
index 5a4e7c7fd92c4e0976ce58f1bf977b6911390775..fb1795d5be2af2e9765f31c1c40fafd90257580e 100644 (file)
@@ -218,7 +218,7 @@ ENTRY(_ex_single_step)
        /* Single stepping only a single instruction, so clear the trace
         * bit here.  */
        r7 = syscfg;
-       bitclr (r7, 0);
+       bitclr (r7, SYSCFG_SSSTEP_P);
        syscfg = R7;
        jump _ex_trap_c;
 
@@ -251,7 +251,7 @@ ENTRY(_ex_single_step)
        if !cc jump _bfin_return_from_exception;
 
        r7 = syscfg;
-       bitclr (r7, 0);
+       bitclr (r7, SYSCFG_SSSTEP_P);   /* Turn off single step */
        syscfg = R7;
 
        /* Fall through to _bfin_return_from_exception.  */
@@ -342,9 +342,11 @@ ENTRY(_ex_trap_c)
        r6 = retx;
        [p5 + PDA_RETX] = r6;
 #endif
+       /* Save the state of single stepping */
        r6 = SYSCFG;
        [p5 + PDA_SYSCFG] = r6;
-       BITCLR(r6, 0);
+       /* Clear it while we handle the exception in IRQ5 mode */
+       BITCLR(r6, SYSCFG_SSSTEP_P);
        SYSCFG = r6;
 
        /* Disable all interrupts, but make sure level 5 is enabled so
@@ -367,7 +369,7 @@ ENDPROC(_ex_trap_c)
  * exception. This is a unrecoverable event, so crash.
  * Note: this cannot be ENTRY() as we jump here with "if cc jump" ...
  */
-_double_fault:
+ENTRY(_double_fault)
        /* Turn caches & protection off, to ensure we don't get any more
         * double exceptions
         */
@@ -872,7 +874,7 @@ ENTRY(_ret_from_exception)
        raise 15;               /* raise evt15 to do signal or reschedule */
 4:
        r0 = syscfg;
-       bitclr(r0, 0);
+       bitclr(r0, SYSCFG_SSSTEP_P);            /* Turn off single step */
        syscfg = r0;
 5:
        rts;
index 61840059dfac30feb314fcf373f4ef51dea943cd..349ee3f5466a8dd089902e335e765e1492563509 100644 (file)
@@ -211,6 +211,8 @@ int smp_call_function(void (*func)(void *info), void *info, int wait)
                return 0;
 
        msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+       if (!msg)
+               return -ENOMEM;
        INIT_LIST_HEAD(&msg->list);
        msg->call_struct.func = func;
        msg->call_struct.info = info;
@@ -252,6 +254,8 @@ int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
        cpu_set(cpu, callmap);
 
        msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+       if (!msg)
+               return -ENOMEM;
        INIT_LIST_HEAD(&msg->list);
        msg->call_struct.func = func;
        msg->call_struct.info = info;
@@ -287,6 +291,8 @@ void smp_send_reschedule(int cpu)
                return;
 
        msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+       if (!msg)
+               return;
        memset(msg, 0, sizeof(msg));
        INIT_LIST_HEAD(&msg->list);
        msg->type = BFIN_IPI_RESCHEDULE;
@@ -314,6 +320,8 @@ void smp_send_stop(void)
                return;
 
        msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+       if (!msg)
+               return;
        memset(msg, 0, sizeof(msg));
        INIT_LIST_HEAD(&msg->list);
        msg->type = BFIN_IPI_CPU_STOP;
@@ -450,7 +458,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
        unsigned int cpu;
 
        for_each_online_cpu(cpu)
-               bogosum += per_cpu(cpu_data, cpu).loops_per_jiffy;
+               bogosum += loops_per_jiffy;
 
        printk(KERN_INFO "SMP: Total of %d processors activated "
               "(%lu.%02lu BogoMIPS).\n",
index 0c26157cffa55fe0ea1c348fd0a542b11e6c46c3..b6395ad1500a00f7d2a133b3633bed96fd91be2f 100644 (file)
@@ -6,6 +6,8 @@
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
+#include <linux/types.h>
+
 /* floating point status register: */
 #define FPSR_TRAP_VD   (1 << 0)        /* invalid op trap disabled */
 #define FPSR_TRAP_DD   (1 << 1)        /* denormal trap disabled */
index e425227a418e9b15a40a0dce0d8f09be3061ec90..88afb54501e48feba6c24d6f25c7f5967b308c89 100644 (file)
@@ -33,6 +33,7 @@
 #ifndef _ASM_IA64_XEN_HYPERVISOR_H
 #define _ASM_IA64_XEN_HYPERVISOR_H
 
+#include <linux/err.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/version.h>     /* to compile feature.c */
 #include <xen/features.h>              /* to comiple xen-netfront.c */
index 086a2aeb0404e6a889d6b10cfe766eca20a568c3..39a3cd0a417326be10680e9d9cb52458e400051f 100644 (file)
@@ -6,6 +6,14 @@ int iommu_detected __read_mostly;
 struct dma_map_ops *dma_ops;
 EXPORT_SYMBOL(dma_ops);
 
+#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
+
+static int __init dma_init(void)
+{
+       dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+}
+fs_initcall(dma_init);
+
 struct dma_map_ops *dma_get_ops(struct device *dev)
 {
        return dma_ops;
index c96ba3da95ac15b6b2582fae648925179e2d9d6b..f4aa079346543f4ecfc47388bec429c66cf35733 100644 (file)
@@ -107,7 +107,7 @@ SECTIONS
   __init_end = .;
   /* freed after init ends here */
 
-  BSS(4)
+  BSS_SECTION(0, PAGE_SIZE, 4)
 
   _end = . ;
 
index 9fa2c7dcd05a4501034395e6f587523cffb969d0..ef149880c145bf5d0ac639e87ba57c094b86bf51 100644 (file)
@@ -736,15 +736,16 @@ void user_disable_single_step(struct task_struct *task)
 {
        struct pt_regs *regs = task->thread.regs;
 
-
-#if defined(CONFIG_BOOKE)
-       /* If DAC then do not single step, skip */
-       if (task->thread.dabr)
-               return;
-#endif
-
        if (regs != NULL) {
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#if defined(CONFIG_BOOKE)
+               /* If DAC don't clear DBCRO_IDM or MSR_DE */
+               if (task->thread.dabr)
+                       task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT);
+               else {
+                       task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM);
+                       regs->msr &= ~MSR_DE;
+               }
+#elif defined(CONFIG_40x)
                task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM);
                regs->msr &= ~MSR_DE;
 #else
index ef36cbbc5882281ccb26ca2c0b4fd14bf23a06d3..ea4d64644d029a283fe17e379d03be319d845b2e 100644 (file)
@@ -80,10 +80,10 @@ _GLOBAL(load_up_altivec)
        mtvscr  vr0
        REST_32VRS(0,r4,r5)
 #ifndef CONFIG_SMP
-       /* Update last_task_used_math to 'current' */
+       /* Update last_task_used_altivec to 'current' */
        subi    r4,r5,THREAD            /* Back to 'current' */
        fromreal(r4)
-       PPC_STL r4,ADDROFF(last_task_used_math)(r3)
+       PPC_STL r4,ADDROFF(last_task_used_altivec)(r3)
 #endif /* CONFIG_SMP */
        /* restore registers and return */
        blr
@@ -172,7 +172,7 @@ _GLOBAL(load_up_vsx)
        oris    r12,r12,MSR_VSX@h
        std     r12,_MSR(r1)
 #ifndef CONFIG_SMP
-       /* Update last_task_used_math to 'current' */
+       /* Update last_task_used_vsx to 'current' */
        ld      r4,PACACURRENT(r13)
        std     r4,0(r3)
 #endif /* CONFIG_SMP */
index daf866ed0612413f3781cdf6f863e8038daebe85..330ee807f89e7e007a93d093c08b9108b3af22d0 100644 (file)
@@ -161,6 +161,7 @@ extern int io_apic_set_pci_routing(struct device *dev, int irq,
                 struct io_apic_irq_attr *irq_attr);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
+extern void ioapic_insert_resources(void);
 
 extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
 extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
@@ -180,6 +181,7 @@ extern void ioapic_write_entry(int apic, int pin,
 #define io_apic_assign_pci_irqs 0
 static const int timer_through_8259 = 0;
 static inline void ioapic_init_mappings(void)  { }
+static inline void ioapic_insert_resources(void) { }
 
 static inline void probe_nr_irqs_gsi(void)     { }
 #endif
index d31c4a684078080ebe48fbc4d90ebd7f67dce568..33600a66755ff9e8931695c1e5eada1e7bb530ac 100644 (file)
@@ -30,7 +30,7 @@
 #include <asm/hw_irq.h>
 #include <asm/kvm_para.h>
 
-/*G:031 But first, how does our Guest contact the Host to ask for privileged
+/*G:030 But first, how does our Guest contact the Host to ask for privileged
  * operations?  There are two ways: the direct way is to make a "hypercall",
  * to make requests of the Host Itself.
  *
index 69328ac8de9c86e106d30af1337a80ab0d4488b1..8952a5890281cc363094cc2f67fed1159e6d7674 100644 (file)
@@ -652,7 +652,8 @@ static int es7000_mps_oem_check_cluster(struct mpc_table *mpc, char *oem,
        return ret && es7000_apic_is_cluster();
 }
 
-struct apic apic_es7000_cluster = {
+/* We've been warned by a false positive warning.Use __refdata to keep calm. */
+struct apic __refdata apic_es7000_cluster = {
 
        .name                           = "es7000",
        .probe                          = probe_es7000,
index 90b5e6efa938ed58ee846ba6969c3c2fc762fb7c..2284a4812b68cfb83ab987388d058004ccb5ee55 100644 (file)
@@ -4181,28 +4181,20 @@ fake_ioapic_page:
        }
 }
 
-static int __init ioapic_insert_resources(void)
+void __init ioapic_insert_resources(void)
 {
        int i;
        struct resource *r = ioapic_resources;
 
        if (!r) {
-               if (nr_ioapics > 0) {
+               if (nr_ioapics > 0)
                        printk(KERN_ERR
                                "IO APIC resources couldn't be allocated.\n");
-                       return -1;
-               }
-               return 0;
+               return;
        }
 
        for (i = 0; i < nr_ioapics; i++) {
                insert_resource(&iomem_resource, r);
                r++;
        }
-
-       return 0;
 }
-
-/* Insert the IO APIC resources after PCI initialization has occured to handle
- * IO APICS that are mapped in on a BAR in PCI space. */
-late_initcall(ioapic_insert_resources);
index 533e59c6fc823a7bb3813cedb74f921765b5d434..ca96e68f0d23230efb4aa74e3227d9d584d4a237 100644 (file)
@@ -493,7 +493,8 @@ static void numaq_setup_portio_remap(void)
                (u_long) xquad_portio, (u_long) num_quads*XQUAD_PORTIO_QUAD);
 }
 
-struct apic apic_numaq = {
+/* Use __refdata to keep false positive warning calm.  */
+struct apic __refdata apic_numaq = {
 
        .name                           = "NUMAQ",
        .probe                          = probe_numaq,
index 36c3dc7b8991d4a5b7ea8709c9003b161c058d6f..a7aa8f900954811e046f397547a19e88291aaeb3 100644 (file)
@@ -65,6 +65,52 @@ static DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters) = {
        .enabled = 1,
 };
 
+/*
+ * Not sure about some of these
+ */
+static const u64 p6_perfmon_event_map[] =
+{
+  [PERF_COUNT_HW_CPU_CYCLES]           = 0x0079,
+  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,
+  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0000,
+  [PERF_COUNT_HW_CACHE_MISSES]         = 0x0000,
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,
+  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,
+  [PERF_COUNT_HW_BUS_CYCLES]           = 0x0062,
+};
+
+static u64 p6_pmu_event_map(int event)
+{
+       return p6_perfmon_event_map[event];
+}
+
+/*
+ * Counter setting that is specified not to count anything.
+ * We use this to effectively disable a counter.
+ *
+ * L2_RQSTS with 0 MESI unit mask.
+ */
+#define P6_NOP_COUNTER                 0x0000002EULL
+
+static u64 p6_pmu_raw_event(u64 event)
+{
+#define P6_EVNTSEL_EVENT_MASK          0x000000FFULL
+#define P6_EVNTSEL_UNIT_MASK           0x0000FF00ULL
+#define P6_EVNTSEL_EDGE_MASK           0x00040000ULL
+#define P6_EVNTSEL_INV_MASK            0x00800000ULL
+#define P6_EVNTSEL_COUNTER_MASK                0xFF000000ULL
+
+#define P6_EVNTSEL_MASK                        \
+       (P6_EVNTSEL_EVENT_MASK |        \
+        P6_EVNTSEL_UNIT_MASK  |        \
+        P6_EVNTSEL_EDGE_MASK  |        \
+        P6_EVNTSEL_INV_MASK   |        \
+        P6_EVNTSEL_COUNTER_MASK)
+
+       return event & P6_EVNTSEL_MASK;
+}
+
+
 /*
  * Intel PerfMon v3. Used on Core2 and later.
  */
@@ -666,6 +712,7 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
 {
        struct perf_counter_attr *attr = &counter->attr;
        struct hw_perf_counter *hwc = &counter->hw;
+       u64 config;
        int err;
 
        if (!x86_pmu_initialized())
@@ -718,14 +765,40 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
 
        if (attr->config >= x86_pmu.max_events)
                return -EINVAL;
+
        /*
         * The generic map:
         */
-       hwc->config |= x86_pmu.event_map(attr->config);
+       config = x86_pmu.event_map(attr->config);
+
+       if (config == 0)
+               return -ENOENT;
+
+       if (config == -1LL)
+               return -EINVAL;
+
+       hwc->config |= config;
 
        return 0;
 }
 
+static void p6_pmu_disable_all(void)
+{
+       struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+       u64 val;
+
+       if (!cpuc->enabled)
+               return;
+
+       cpuc->enabled = 0;
+       barrier();
+
+       /* p6 only has one enable register */
+       rdmsrl(MSR_P6_EVNTSEL0, val);
+       val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
+       wrmsrl(MSR_P6_EVNTSEL0, val);
+}
+
 static void intel_pmu_disable_all(void)
 {
        wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
@@ -767,6 +840,23 @@ void hw_perf_disable(void)
        return x86_pmu.disable_all();
 }
 
+static void p6_pmu_enable_all(void)
+{
+       struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+       unsigned long val;
+
+       if (cpuc->enabled)
+               return;
+
+       cpuc->enabled = 1;
+       barrier();
+
+       /* p6 only has one enable register */
+       rdmsrl(MSR_P6_EVNTSEL0, val);
+       val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+       wrmsrl(MSR_P6_EVNTSEL0, val);
+}
+
 static void intel_pmu_enable_all(void)
 {
        wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl);
@@ -784,13 +874,13 @@ static void amd_pmu_enable_all(void)
        barrier();
 
        for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               struct perf_counter *counter = cpuc->counters[idx];
                u64 val;
 
                if (!test_bit(idx, cpuc->active_mask))
                        continue;
-               rdmsrl(MSR_K7_EVNTSEL0 + idx, val);
-               if (val & ARCH_PERFMON_EVENTSEL0_ENABLE)
-                       continue;
+
+               val = counter->hw.config;
                val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
                wrmsrl(MSR_K7_EVNTSEL0 + idx, val);
        }
@@ -819,16 +909,13 @@ static inline void intel_pmu_ack_status(u64 ack)
 
 static inline void x86_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
 {
-       int err;
-       err = checking_wrmsrl(hwc->config_base + idx,
+       (void)checking_wrmsrl(hwc->config_base + idx,
                              hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE);
 }
 
 static inline void x86_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
 {
-       int err;
-       err = checking_wrmsrl(hwc->config_base + idx,
-                             hwc->config);
+       (void)checking_wrmsrl(hwc->config_base + idx, hwc->config);
 }
 
 static inline void
@@ -836,13 +923,24 @@ intel_pmu_disable_fixed(struct hw_perf_counter *hwc, int __idx)
 {
        int idx = __idx - X86_PMC_IDX_FIXED;
        u64 ctrl_val, mask;
-       int err;
 
        mask = 0xfULL << (idx * 4);
 
        rdmsrl(hwc->config_base, ctrl_val);
        ctrl_val &= ~mask;
-       err = checking_wrmsrl(hwc->config_base, ctrl_val);
+       (void)checking_wrmsrl(hwc->config_base, ctrl_val);
+}
+
+static inline void
+p6_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
+{
+       struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+       u64 val = P6_NOP_COUNTER;
+
+       if (cpuc->enabled)
+               val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+
+       (void)checking_wrmsrl(hwc->config_base + idx, val);
 }
 
 static inline void
@@ -943,6 +1041,19 @@ intel_pmu_enable_fixed(struct hw_perf_counter *hwc, int __idx)
        err = checking_wrmsrl(hwc->config_base, ctrl_val);
 }
 
+static void p6_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
+{
+       struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+       u64 val;
+
+       val = hwc->config;
+       if (cpuc->enabled)
+               val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+
+       (void)checking_wrmsrl(hwc->config_base + idx, val);
+}
+
+
 static void intel_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
 {
        if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
@@ -959,8 +1070,6 @@ static void amd_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
 
        if (cpuc->enabled)
                x86_pmu_enable_counter(hwc, idx);
-       else
-               x86_pmu_disable_counter(hwc, idx);
 }
 
 static int
@@ -1176,6 +1285,49 @@ static void intel_pmu_reset(void)
        local_irq_restore(flags);
 }
 
+static int p6_pmu_handle_irq(struct pt_regs *regs)
+{
+       struct perf_sample_data data;
+       struct cpu_hw_counters *cpuc;
+       struct perf_counter *counter;
+       struct hw_perf_counter *hwc;
+       int idx, handled = 0;
+       u64 val;
+
+       data.regs = regs;
+       data.addr = 0;
+
+       cpuc = &__get_cpu_var(cpu_hw_counters);
+
+       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+
+               counter = cpuc->counters[idx];
+               hwc = &counter->hw;
+
+               val = x86_perf_counter_update(counter, hwc, idx);
+               if (val & (1ULL << (x86_pmu.counter_bits - 1)))
+                       continue;
+
+               /*
+                * counter overflow
+                */
+               handled         = 1;
+               data.period     = counter->hw.last_period;
+
+               if (!x86_perf_counter_set_period(counter, hwc, idx))
+                       continue;
+
+               if (perf_counter_overflow(counter, 1, &data))
+                       p6_pmu_disable_counter(hwc, idx);
+       }
+
+       if (handled)
+               inc_irq_stat(apic_perf_irqs);
+
+       return handled;
+}
 
 /*
  * This handler is triggered by the local APIC, so the APIC IRQ handling
@@ -1185,14 +1337,13 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
 {
        struct perf_sample_data data;
        struct cpu_hw_counters *cpuc;
-       int bit, cpu, loops;
+       int bit, loops;
        u64 ack, status;
 
        data.regs = regs;
        data.addr = 0;
 
-       cpu = smp_processor_id();
-       cpuc = &per_cpu(cpu_hw_counters, cpu);
+       cpuc = &__get_cpu_var(cpu_hw_counters);
 
        perf_disable();
        status = intel_pmu_get_status();
@@ -1249,14 +1400,13 @@ static int amd_pmu_handle_irq(struct pt_regs *regs)
        struct cpu_hw_counters *cpuc;
        struct perf_counter *counter;
        struct hw_perf_counter *hwc;
-       int cpu, idx, handled = 0;
+       int idx, handled = 0;
        u64 val;
 
        data.regs = regs;
        data.addr = 0;
 
-       cpu = smp_processor_id();
-       cpuc = &per_cpu(cpu_hw_counters, cpu);
+       cpuc = &__get_cpu_var(cpu_hw_counters);
 
        for (idx = 0; idx < x86_pmu.num_counters; idx++) {
                if (!test_bit(idx, cpuc->active_mask))
@@ -1353,6 +1503,32 @@ static __read_mostly struct notifier_block perf_counter_nmi_notifier = {
        .priority               = 1
 };
 
+static struct x86_pmu p6_pmu = {
+       .name                   = "p6",
+       .handle_irq             = p6_pmu_handle_irq,
+       .disable_all            = p6_pmu_disable_all,
+       .enable_all             = p6_pmu_enable_all,
+       .enable                 = p6_pmu_enable_counter,
+       .disable                = p6_pmu_disable_counter,
+       .eventsel               = MSR_P6_EVNTSEL0,
+       .perfctr                = MSR_P6_PERFCTR0,
+       .event_map              = p6_pmu_event_map,
+       .raw_event              = p6_pmu_raw_event,
+       .max_events             = ARRAY_SIZE(p6_perfmon_event_map),
+       .max_period             = (1ULL << 31) - 1,
+       .version                = 0,
+       .num_counters           = 2,
+       /*
+        * Counters have 40 bits implemented. However they are designed such
+        * that bits [32-39] are sign extensions of bit 31. As such the
+        * effective width of a counter for P6-like PMU is 32 bits only.
+        *
+        * See IA-32 Intel Architecture Software developer manual Vol 3B
+        */
+       .counter_bits           = 32,
+       .counter_mask           = (1ULL << 32) - 1,
+};
+
 static struct x86_pmu intel_pmu = {
        .name                   = "Intel",
        .handle_irq             = intel_pmu_handle_irq,
@@ -1392,6 +1568,37 @@ static struct x86_pmu amd_pmu = {
        .max_period             = (1ULL << 47) - 1,
 };
 
+static int p6_pmu_init(void)
+{
+       switch (boot_cpu_data.x86_model) {
+       case 1:
+       case 3:  /* Pentium Pro */
+       case 5:
+       case 6:  /* Pentium II */
+       case 7:
+       case 8:
+       case 11: /* Pentium III */
+               break;
+       case 9:
+       case 13:
+               /* Pentium M */
+               break;
+       default:
+               pr_cont("unsupported p6 CPU model %d ",
+                       boot_cpu_data.x86_model);
+               return -ENODEV;
+       }
+
+       if (!cpu_has_apic) {
+               pr_info("no Local APIC, try rebooting with lapic");
+               return -ENODEV;
+       }
+
+       x86_pmu                         = p6_pmu;
+
+       return 0;
+}
+
 static int intel_pmu_init(void)
 {
        union cpuid10_edx edx;
@@ -1400,8 +1607,14 @@ static int intel_pmu_init(void)
        unsigned int ebx;
        int version;
 
-       if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+       if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+               /* check for P6 processor family */
+          if (boot_cpu_data.x86 == 6) {
+               return p6_pmu_init();
+          } else {
                return -ENODEV;
+          }
+       }
 
        /*
         * Check whether the Architectural PerfMon supports
index 4f9c55f3a7c0f7e2590a5e248428bd19aa0d5c37..03801f2f761fc312ba80353425c1cc7243a0105f 100644 (file)
@@ -60,7 +60,7 @@ static inline u64 scale_delta(u64 delta, u32 mul_frac, int shift)
                "adc  %5,%%edx ; "
                : "=A" (product), "=r" (tmp1), "=r" (tmp2)
                : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
-#elif __x86_64__
+#elif defined(__x86_64__)
        __asm__ (
                "mul %%rdx ; shrd $32,%%rdx,%%rax"
                : "=a" (product) : "0" (delta), "d" ((u64)mul_frac) );
index 7bc65f0f62c4fc51607dd443641d1273cb4ebb03..f2bf1f73d468942590d5c914e874d24fa23d22b0 100644 (file)
@@ -379,6 +379,11 @@ static void lguest_cpuid(unsigned int *ax, unsigned int *bx,
 
        native_cpuid(ax, bx, cx, dx);
        switch (function) {
+       case 0: /* ID and highest CPUID.  Futureproof a little by sticking to
+                * older ones. */
+               if (*ax > 5)
+                       *ax = 5;
+               break;
        case 1: /* Basic feature request. */
                /* We only allow kernel to see SSE3, CMPXCHG16B and SSSE3 */
                *cx &= 0x00002201;
@@ -1079,7 +1084,7 @@ static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf,
        return insn_len;
 }
 
-/*G:030 Once we get to lguest_init(), we know we're a Guest.  The various
+/*G:029 Once we get to lguest_init(), we know we're a Guest.  The various
  * pv_ops structures in the kernel provide points for (almost) every routine we
  * have to override to avoid privileged instructions. */
 __init void lguest_init(void)
index 85307cc6e45f951b80a7d49d19cc873b779bd595..bfae139182ffbf0d2c5098d824f9d9ed7d8b6827 100644 (file)
@@ -697,7 +697,7 @@ show_signal_msg(struct pt_regs *regs, unsigned long error_code,
        if (!printk_ratelimit())
                return;
 
-       printk(KERN_CONT "%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
+       printk("%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
                task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
                tsk->comm, task_pid_nr(tsk), address,
                (void *)regs->ip, (void *)regs->sp, error_code);
index 0fb56db16d1813897b7f7fea6df2af75a20fd2a0..52e62e57fedd53a385147cf1399cd84f89f7bc4b 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/pat.h>
 #include <asm/e820.h>
 #include <asm/pci_x86.h>
+#include <asm/io_apic.h>
 
 
 static int
@@ -227,6 +228,12 @@ void __init pcibios_resource_survey(void)
        pcibios_allocate_resources(1);
 
        e820_reserve_resources_late();
+       /*
+        * Insert the IO APIC resources after PCI initialization has
+        * occured to handle IO APICS that are mapped in on a BAR in
+        * PCI space, but before trying to assign unassigned pci res.
+        */
+       ioapic_insert_resources();
 }
 
 /**
index b1cd04087d6a4db5f8ba3e2d9b4f8db1221ed424..418d63619680e8df2b9ab2ba0cdd5f31bcfb4ee4 100644 (file)
@@ -16,9 +16,9 @@ struct queue_sysfs_entry {
 };
 
 static ssize_t
-queue_var_show(unsigned int var, char *page)
+queue_var_show(unsigned long var, char *page)
 {
-       return sprintf(page, "%d\n", var);
+       return sprintf(page, "%lu\n", var);
 }
 
 static ssize_t
@@ -77,7 +77,8 @@ queue_requests_store(struct request_queue *q, const char *page, size_t count)
 
 static ssize_t queue_ra_show(struct request_queue *q, char *page)
 {
-       int ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10);
+       unsigned long ra_kb = q->backing_dev_info.ra_pages <<
+                                       (PAGE_CACHE_SHIFT - 10);
 
        return queue_var_show(ra_kb, (page));
 }
@@ -189,9 +190,9 @@ static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
 
 static ssize_t queue_rq_affinity_show(struct request_queue *q, char *page)
 {
-       unsigned int set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags);
+       bool set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags);
 
-       return queue_var_show(set != 0, page);
+       return queue_var_show(set, page);
 }
 
 static ssize_t
index 6f2375339a996a794c17c96d0f32aa724fd1fae2..2d511f9105e16abcf93cad6ac849ad9996661a32 100644 (file)
@@ -101,11 +101,16 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio)
                return 0;
 
        /*
-        * Don't merge if failfast settings don't match
+        * Don't merge if failfast settings don't match.
+        *
+        * FIXME: The negation in front of each condition is necessary
+        * because bio and request flags use different bit positions
+        * and the accessors return those bits directly.  This
+        * ugliness will soon go away.
         */
-       if (bio_failfast_dev(bio)       != blk_failfast_dev(rq)         ||
-           bio_failfast_transport(bio) != blk_failfast_transport(rq)   ||
-           bio_failfast_driver(bio)    != blk_failfast_driver(rq))
+       if (!bio_failfast_dev(bio)       != !blk_failfast_dev(rq)       ||
+           !bio_failfast_transport(bio) != !blk_failfast_transport(rq) ||
+           !bio_failfast_driver(bio)    != !blk_failfast_driver(rq))
                return 0;
 
        if (!elv_iosched_allow_merge(rq, bio))
index 15a23031833f46e921957c48578723caf9b2446e..336eb1ed73cc3e9dd858ab0bf9cade009498f78b 100644 (file)
@@ -513,6 +513,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
        { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
        { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
+       { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
        { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
        { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
        { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
index 045a486a09eae25a16174a7c697e52796dcbc503..2c6aedaef7185e649f506b7c656ce8eb042c3e9e 100644 (file)
@@ -3392,17 +3392,27 @@ int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel)
 
 static int ata_dev_set_mode(struct ata_device *dev)
 {
+       struct ata_port *ap = dev->link->ap;
        struct ata_eh_context *ehc = &dev->link->eh_context;
+       const bool nosetxfer = dev->horkage & ATA_HORKAGE_NOSETXFER;
        const char *dev_err_whine = "";
        int ign_dev_err = 0;
-       unsigned int err_mask;
+       unsigned int err_mask = 0;
        int rc;
 
        dev->flags &= ~ATA_DFLAG_PIO;
        if (dev->xfer_shift == ATA_SHIFT_PIO)
                dev->flags |= ATA_DFLAG_PIO;
 
-       err_mask = ata_dev_set_xfermode(dev);
+       if (nosetxfer && ap->flags & ATA_FLAG_SATA && ata_id_is_sata(dev->id))
+               dev_err_whine = " (SET_XFERMODE skipped)";
+       else {
+               if (nosetxfer)
+                       ata_dev_printk(dev, KERN_WARNING,
+                                      "NOSETXFER but PATA detected - can't "
+                                      "skip SETXFER, might malfunction\n");
+               err_mask = ata_dev_set_xfermode(dev);
+       }
 
        if (err_mask & ~AC_ERR_DEV)
                goto fail;
@@ -4297,6 +4307,12 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        /* Devices which aren't very happy with higher link speeds */
        { "WD My Book",                 NULL,   ATA_HORKAGE_1_5_GBPS, },
 
+       /*
+        * Devices which choke on SETXFER.  Applies only if both the
+        * device and controller are SATA.
+        */
+       { "PIONEER DVD-RW  DVRTD08",    "1.00", ATA_HORKAGE_NOSETXFER },
+
        /* End Marker */
        { }
 };
index fa22f94ca4150247b39a0e26fa7541d4cbee4ba4..1a07c061f644f37d76e7efe831a028ff6b8c1953 100644 (file)
@@ -2517,6 +2517,10 @@ int ata_eh_reset(struct ata_link *link, int classify,
 
                        ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
                        rc = ata_do_reset(link, reset, classes, deadline, true);
+                       if (rc) {
+                               failed_link = link;
+                               goto fail;
+                       }
                }
        } else {
                if (verbose)
index 4b27617be26da7ecfadd5ac53476237348559310..8561a9f195c11ed9dd2a49979da8970a7a70e633 100644 (file)
@@ -312,11 +312,12 @@ err_ide_ioremap:
 static int __devexit pata_at91_remove(struct platform_device *pdev)
 {
        struct ata_host *host = dev_get_drvdata(&pdev->dev);
-       struct at91_ide_info *info = host->private_data;
+       struct at91_ide_info *info;
        struct device *dev = &pdev->dev;
 
        if (!host)
                return 0;
+       info = host->private_data;
 
        ata_host_detach(host);
 
index f5e7180d7f47d050ed0e39a37ad748054658b52b..3ff02941b3dd40c57ca9a2cc56d7442c5cd538cb 100644 (file)
@@ -1627,7 +1627,7 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode,
                                drive, dtp->blocks, dtp->spt, dtp->stretch);
 
                /* sanity check */
-               if (!dtp || setprm.track != dtp->blocks/dtp->spt/2 ||
+               if (setprm.track != dtp->blocks/dtp->spt/2 ||
                    setprm.head != 2) {
                        redo_fd_request();
                        return -EINVAL;
index 43db3ea15b54936da4502526602c117876bd67fc..aa1a3d5a3e2bc3f202bb695da2624f4d8cfd03b5 100644 (file)
@@ -213,7 +213,7 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
         * Only allow the generic SCSI ioctls if the host can support it.
         */
        if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI))
-               return -ENOIOCTLCMD;
+               return -ENOTTY;
 
        return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
 }
@@ -360,6 +360,9 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
        blk_queue_max_phys_segments(vblk->disk->queue, vblk->sg_elems-2);
        blk_queue_max_hw_segments(vblk->disk->queue, vblk->sg_elems-2);
 
+       /* No need to bounce any requests */
+       blk_queue_bounce_limit(vblk->disk->queue, BLK_BOUNCE_ANY);
+
        /* No real sector limit. */
        blk_queue_max_sectors(vblk->disk->queue, -1U);
 
@@ -424,7 +427,12 @@ static unsigned int features[] = {
        VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY
 };
 
-static struct virtio_driver virtio_blk = {
+/*
+ * virtio_blk causes spurious section mismatch warning by
+ * simultaneously referring to a __devinit and a __devexit function.
+ * Use __refdata to avoid this warning.
+ */
+static struct virtio_driver __refdata virtio_blk = {
        .feature_table = features,
        .feature_table_size = ARRAY_SIZE(features),
        .driver.name =  KBUILD_MODNAME,
index 4575171e5beb1bd754e0fe0ba11600b0fce4ea3f..b2590409f25efb1911dc8e87a4d88c2dc0b3d719 100644 (file)
@@ -374,7 +374,7 @@ err:
 static void __exit z2_exit(void)
 {
     int i, j;
-    blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), 256);
+    blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), Z2MINOR_COUNT);
     unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
     del_gendisk(z2ram_gendisk);
     put_disk(z2ram_gendisk);
index 94e7e3c8c05ad3f0720aaae3d6df588eebd2d50b..d97779ef72cb2846dabe8487ebf4cc0b4c7c6bf3 100644 (file)
@@ -552,7 +552,7 @@ static int hvc_chars_in_buffer(struct tty_struct *tty)
        struct hvc_struct *hp = tty->driver_data;
 
        if (!hp)
-               return -1;
+               return 0;
        return hp->n_outbuf;
 }
 
index 94a5d5020abcec935e08d6bc74180a249ea58423..ff47907ff1bf9f9ae8ddc3e073c06ae4f3a615df 100644 (file)
@@ -1331,9 +1331,6 @@ handle_newline:
 
 static void n_tty_write_wakeup(struct tty_struct *tty)
 {
-       /* Write out any echoed characters that are still pending */
-       process_echoes(tty);
-
        if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags))
                kill_fasync(&tty->fasync, SIGIO, POLL_OUT);
 }
index 574f1c79b6e637ededd5a4708651bc7902aea960..ec58d8c387ff2303f67db428622f68b7eff76057 100644 (file)
@@ -828,7 +828,7 @@ static int receive_data(enum port_type index, struct nozomi *dc)
        struct port *port = &dc->port[index];
        void __iomem *addr = port->dl_addr[port->toggle_dl];
        struct tty_struct *tty = tty_port_tty_get(&port->port);
-       int i;
+       int i, ret;
 
        if (unlikely(!tty)) {
                DBG1("tty not open for port: %d?", index);
@@ -844,12 +844,14 @@ static int receive_data(enum port_type index, struct nozomi *dc)
 
                /* disable interrupt in downlink... */
                disable_transmit_dl(index, dc);
-               return 0;
+               ret = 0;
+               goto put;
        }
 
        if (unlikely(size == 0)) {
                dev_err(&dc->pdev->dev, "size == 0?\n");
-               return 1;
+               ret = 1;
+               goto put;
        }
 
        tty_buffer_request_room(tty, size);
@@ -871,8 +873,10 @@ static int receive_data(enum port_type index, struct nozomi *dc)
        }
 
        set_bit(index, &dc->flip);
+       ret = 1;
+put:
        tty_kref_put(tty);
-       return 1;
+       return ret;
 }
 
 /* Debug for interrupts */
@@ -1862,16 +1866,14 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty)
 {
        struct port *port = tty->driver_data;
        struct nozomi *dc = get_dc_by_tty(tty);
-       s32 rval;
+       s32 rval = 0;
 
        if (unlikely(!dc || !port)) {
-               rval = -ENODEV;
                goto exit_in_buffer;
        }
 
        if (unlikely(!port->port.count)) {
                dev_err(&dc->pdev->dev, "No tty open?\n");
-               rval = -ENODEV;
                goto exit_in_buffer;
        }
 
index 569f2f7743a78ddc80f4e7714c6456506b8a4995..674b3ab3587d505458fbdb802fc0a7cbcdf7d2eb 100644 (file)
@@ -320,10 +320,10 @@ static int ipw_chars_in_buffer(struct tty_struct *linux_tty)
        struct ipw_tty *tty = linux_tty->driver_data;
 
        if (!tty)
-               return -ENODEV;
+               return 0;
 
        if (!tty->open_count)
-               return -EINVAL;
+               return 0;
 
        return tty->tx_bytes_queued;
 }
index bfe4cdb2febb17c65ed8900b7dff9a5b40ed7921..268e17f9ec3f50c4586607bb0dd59e76442f3bee 100644 (file)
@@ -1809,10 +1809,10 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file,
                if (clear & TIOCM_DTR)
                        port->MSVR &= ~MSVR_DTR;
        }
-       spin_lock_irqsave(&bp->lock, flags);
+       spin_lock(&bp->lock);
        sx_out(bp, CD186x_CAR, port_No(port));
        sx_out(bp, CD186x_MSVR, port->MSVR);
-       spin_unlock_irqrestore(&bp->lock, flags);
+       spin_unlock(&bp->lock);
        spin_unlock_irqrestore(&port->lock, flags);
        func_exit();
        return 0;
@@ -1833,11 +1833,11 @@ static int sx_send_break(struct tty_struct *tty, int length)
        port->break_length = SPECIALIX_TPS / HZ * length;
        port->COR2 |= COR2_ETC;
        port->IER  |= IER_TXRDY;
-       spin_lock_irqsave(&bp->lock, flags);
+       spin_lock(&bp->lock);
        sx_out(bp, CD186x_CAR, port_No(port));
        sx_out(bp, CD186x_COR2, port->COR2);
        sx_out(bp, CD186x_IER, port->IER);
-       spin_unlock_irqrestore(&bp->lock, flags);
+       spin_unlock(&bp->lock);
        spin_unlock_irqrestore(&port->lock, flags);
        sx_wait_CCR(bp);
        spin_lock_irqsave(&bp->lock, flags);
@@ -2023,9 +2023,9 @@ static void sx_unthrottle(struct tty_struct *tty)
        if (sx_crtscts(tty))
                port->MSVR |= MSVR_DTR;
        /* Else clause: see remark in "sx_throttle"... */
-       spin_lock_irqsave(&bp->lock, flags);
+       spin_lock(&bp->lock);
        sx_out(bp, CD186x_CAR, port_No(port));
-       spin_unlock_irqrestore(&bp->lock, flags);
+       spin_unlock(&bp->lock);
        if (I_IXOFF(tty)) {
                spin_unlock_irqrestore(&port->lock, flags);
                sx_wait_CCR(bp);
@@ -2035,9 +2035,9 @@ static void sx_unthrottle(struct tty_struct *tty)
                sx_wait_CCR(bp);
                spin_lock_irqsave(&port->lock, flags);
        }
-       spin_lock_irqsave(&bp->lock, flags);
+       spin_lock(&bp->lock);
        sx_out(bp, CD186x_MSVR, port->MSVR);
-       spin_unlock_irqrestore(&bp->lock, flags);
+       spin_unlock(&bp->lock);
        spin_unlock_irqrestore(&port->lock, flags);
 
        func_exit();
@@ -2061,10 +2061,10 @@ static void sx_stop(struct tty_struct *tty)
 
        spin_lock_irqsave(&port->lock, flags);
        port->IER &= ~IER_TXRDY;
-       spin_lock_irqsave(&bp->lock, flags);
+       spin_lock(&bp->lock);
        sx_out(bp, CD186x_CAR, port_No(port));
        sx_out(bp, CD186x_IER, port->IER);
-       spin_unlock_irqrestore(&bp->lock, flags);
+       spin_unlock(&bp->lock);
        spin_unlock_irqrestore(&port->lock, flags);
 
        func_exit();
@@ -2089,10 +2089,10 @@ static void sx_start(struct tty_struct *tty)
        spin_lock_irqsave(&port->lock, flags);
        if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
                port->IER |= IER_TXRDY;
-               spin_lock_irqsave(&bp->lock, flags);
+               spin_lock(&bp->lock);
                sx_out(bp, CD186x_CAR, port_No(port));
                sx_out(bp, CD186x_IER, port->IER);
-               spin_unlock_irqrestore(&bp->lock, flags);
+               spin_unlock(&bp->lock);
        }
        spin_unlock_irqrestore(&port->lock, flags);
 
index 0ef0dc97ba20cbb65496e8b82572a6aa526d0ccb..acd76b767d4c10aac5b540e31a1cd2dddf3c8436 100644 (file)
@@ -790,17 +790,20 @@ void tty_ldisc_hangup(struct tty_struct *tty)
         * N_TTY.
         */
        if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
-               /* Avoid racing set_ldisc */
+               /* Avoid racing set_ldisc or tty_ldisc_release */
                mutex_lock(&tty->ldisc_mutex);
-               /* Switch back to N_TTY */
-               tty_ldisc_halt(tty);
-               tty_ldisc_wait_idle(tty);
-               tty_ldisc_reinit(tty);
-               /* At this point we have a closed ldisc and we want to
-                  reopen it. We could defer this to the next open but
-                  it means auditing a lot of other paths so this is a FIXME */
-               WARN_ON(tty_ldisc_open(tty, tty->ldisc));
-               tty_ldisc_enable(tty);
+               if (tty->ldisc) {       /* Not yet closed */
+                       /* Switch back to N_TTY */
+                       tty_ldisc_halt(tty);
+                       tty_ldisc_wait_idle(tty);
+                       tty_ldisc_reinit(tty);
+                       /* At this point we have a closed ldisc and we want to
+                          reopen it. We could defer this to the next open but
+                          it means auditing a lot of other paths so this is
+                          a FIXME */
+                       WARN_ON(tty_ldisc_open(tty, tty->ldisc));
+                       tty_ldisc_enable(tty);
+               }
                mutex_unlock(&tty->ldisc_mutex);
                tty_reset_termios(tty);
        }
@@ -865,6 +868,7 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
 
        tty_ldisc_wait_idle(tty);
 
+       mutex_lock(&tty->ldisc_mutex);
        /*
         * Now kill off the ldisc
         */
@@ -875,6 +879,7 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
 
        /* Ensure the next open requests the N_TTY ldisc */
        tty_set_termios_ldisc(tty, N_TTY);
+       mutex_unlock(&tty->ldisc_mutex);
 
        /* This will need doing differently if we need to lock */
        if (o_tty)
index 4e862a75f7ff213bd62022e852a9d485b65adbbf..9769b1149f7602cf9c2c7ea1a3eab70bfad9b0a0 100644 (file)
@@ -267,7 +267,7 @@ int tty_port_block_til_ready(struct tty_port *port,
        if (retval == 0)
                port->flags |= ASYNC_NORMAL_ACTIVE;
        spin_unlock_irqrestore(&port->lock, flags);
-       return 0;
+       return retval;
        
 }
 EXPORT_SYMBOL(tty_port_block_til_ready);
index d94d25c12aa87ccacfe12d72ea5e72d4f3f4f93c..c1791a63d99d40c2e1dbe7a4fba6e1f8cfba8c16 100644 (file)
@@ -495,11 +495,15 @@ void vcs_remove_sysfs(int index)
 
 int __init vcs_init(void)
 {
+       unsigned int i;
+
        if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
                panic("unable to get major %d for vcs device", VCS_MAJOR);
        vc_class = class_create(THIS_MODULE, "vc");
 
        device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
        device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+       for (i = 0; i < MIN_NR_CONSOLES; i++)
+               vcs_make_sysfs(i);
        return 0;
 }
index 7947bd1b4cf75969c6a502358a30600d42b3e185..404f4c1ee43145c5429f6639f0454e5a59818f3f 100644 (file)
@@ -770,14 +770,12 @@ int vc_allocate(unsigned int currcons)    /* return 0 on success */
            visual_init(vc, currcons, 1);
            if (!*vc->vc_uni_pagedir_loc)
                con_set_default_unimap(vc);
-           if (!vc->vc_kmalloced)
-               vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
+           vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
            if (!vc->vc_screenbuf) {
                kfree(vc);
                vc_cons[currcons].d = NULL;
                return -ENOMEM;
            }
-           vc->vc_kmalloced = 1;
            vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
            vcs_make_sysfs(currcons);
            atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, &param);
@@ -913,10 +911,8 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
        if (new_scr_end > new_origin)
                scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
                            new_scr_end - new_origin);
-       if (vc->vc_kmalloced)
-               kfree(vc->vc_screenbuf);
+       kfree(vc->vc_screenbuf);
        vc->vc_screenbuf = newscreen;
-       vc->vc_kmalloced = 1;
        vc->vc_screenbuf_size = new_screen_size;
        set_origin(vc);
 
@@ -995,8 +991,7 @@ void vc_deallocate(unsigned int currcons)
                vc->vc_sw->con_deinit(vc);
                put_pid(vc->vt_pid);
                module_put(vc->vc_sw->owner);
-               if (vc->vc_kmalloced)
-                       kfree(vc->vc_screenbuf);
+               kfree(vc->vc_screenbuf);
                if (currcons >= MIN_NR_CONSOLES)
                        kfree(vc);
                vc_cons[currcons].d = NULL;
@@ -2881,7 +2876,6 @@ static int __init con_init(void)
                INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
                visual_init(vc, currcons, 1);
                vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
-               vc->vc_kmalloced = 0;
                vc_init(vc, vc->vc_rows, vc->vc_cols,
                        currcons || !vc->vc_sw->con_save_screen);
        }
index c769ef269fb5833e96b3ac32ece432c4ce1de564..408c2af25d5097c93f41c6fc519bbfbcae0f230f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     cn_queue.c
  *
- * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
index fd336c5a9057a8da729ebd2d3961cbb7b6a4c271..08b2500f21ec1757cd57472326843642e0a2460f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     connector.c
  *
- * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -33,7 +33,7 @@
 #include <net/sock.h>
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
 
 static u32 cn_idx = CN_IDX_CONNECTOR;
index 2960b6d73456d65b672ad4a7b715976113002859..9903f270e4409c8239add50adc2a3db80ca56623 100644 (file)
@@ -101,6 +101,10 @@ int drm_debugfs_create_files(struct drm_info_list *files, int count,
                        continue;
 
                tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
+               if (tmp == NULL) {
+                       ret = -1;
+                       goto fail;
+               }
                ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
                                          root, tmp, &drm_debugfs_fops);
                if (!ent) {
index 8104ecaea26fbe7170d4c85b41ee0a96e6a0bec4..ffe8f4394d50d71f96411200d9d4d90907bd5f2c 100644 (file)
@@ -134,26 +134,29 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
        BUG_ON((size & (PAGE_SIZE - 1)) != 0);
 
        obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+       if (!obj)
+               goto free;
 
        obj->dev = dev;
        obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
-       if (IS_ERR(obj->filp)) {
-               kfree(obj);
-               return NULL;
-       }
+       if (IS_ERR(obj->filp))
+               goto free;
 
        kref_init(&obj->refcount);
        kref_init(&obj->handlecount);
        obj->size = size;
        if (dev->driver->gem_init_object != NULL &&
            dev->driver->gem_init_object(obj) != 0) {
-               fput(obj->filp);
-               kfree(obj);
-               return NULL;
+               goto fput;
        }
        atomic_inc(&dev->object_count);
        atomic_add(obj->size, &dev->object_memory);
        return obj;
+fput:
+       fput(obj->filp);
+free:
+       kfree(obj);
+       return NULL;
 }
 EXPORT_SYMBOL(drm_gem_object_alloc);
 
index 155a5bbce680ac4187f297699644a29317a188e6..55bb8a82d6127cb5d1ec3bea675e0001de593122 100644 (file)
@@ -489,7 +489,7 @@ int drm_put_minor(struct drm_minor **minor_p)
  */
 void drm_put_dev(struct drm_device *dev)
 {
-       struct drm_driver *driver = dev->driver;
+       struct drm_driver *driver;
        struct drm_map_list *r_list, *list_temp;
 
        DRM_DEBUG("\n");
@@ -498,6 +498,7 @@ void drm_put_dev(struct drm_device *dev)
                DRM_ERROR("cleanup called no dev\n");
                return;
        }
+       driver = dev->driver;
 
        drm_vblank_cleanup(dev);
 
index 40b75032ea47459a43b5de71d8801c84e201180b..fe949a12fe40b4804ebcdd047d7286629d0de51d 100644 (file)
@@ -327,7 +327,7 @@ ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp,
                goto out_unref;
 
        kmap_offset = dev_offset - bo->vm_node->start;
-       if (unlikely(kmap_offset) >= bo->num_pages) {
+       if (unlikely(kmap_offset >= bo->num_pages)) {
                ret = -EFBIG;
                goto out_unref;
        }
@@ -401,7 +401,7 @@ ssize_t ttm_bo_fbdev_io(struct ttm_buffer_object *bo, const char __user *wbuf,
        bool dummy;
 
        kmap_offset = (*f_pos >> PAGE_SHIFT);
-       if (unlikely(kmap_offset) >= bo->num_pages)
+       if (unlikely(kmap_offset >= bo->num_pages))
                return -EFBIG;
 
        page_offset = *f_pos & ~PAGE_MASK;
index c248c1d37268ac64cfed64e8b6bfba43b3d80332..5935b8842e8687c144ec6503b85ae7e9bee81b68 100644 (file)
@@ -183,7 +183,7 @@ int via_enable_vblank(struct drm_device *dev, int crtc)
        }
 
        status = VIA_READ(VIA_REG_INTERRUPT);
-       VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE);
+       VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE);
 
        VIA_WRITE8(0x83d4, 0x11);
        VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
@@ -194,6 +194,10 @@ int via_enable_vblank(struct drm_device *dev, int crtc)
 void via_disable_vblank(struct drm_device *dev, int crtc)
 {
        drm_via_private_t *dev_priv = dev->dev_private;
+       u32 status;
+
+       status = VIA_READ(VIA_REG_INTERRUPT);
+       VIA_WRITE(VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE);
 
        VIA_WRITE8(0x83d4, 0x11);
        VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
index f2c21d5d24e80e43bc3e482218fd20873f106c07..5eb10c2ce6654b6794041cfd813c95dc01261835 100644 (file)
@@ -1075,14 +1075,16 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event);
  */
 int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt)
 {
-       struct hid_report_enum *report_enum = hid->report_enum + type;
-       struct hid_driver *hdrv = hid->driver;
+       struct hid_report_enum *report_enum;
+       struct hid_driver *hdrv;
        struct hid_report *report;
        unsigned int i;
        int ret;
 
        if (!hid || !hid->driver)
                return -ENODEV;
+       report_enum = hid->report_enum + type;
+       hdrv = hid->driver;
 
        if (!size) {
                dbg_hid("empty report\n");
index 9e9421525fb9125fa962c2266550f67545855b39..215b2addddbb7c5be5e765dcbe0fd771146129db 100644 (file)
@@ -527,8 +527,10 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
                        goto goodreturn;
 
                case HIDIOCGCOLLECTIONINDEX:
+                       i = field->usage[uref->usage_index].collection_index;
+                       unlock_kernel();
                        kfree(uref_multi);
-                       return field->usage[uref->usage_index].collection_index;
+                       return i;
                case HIDIOCGUSAGES:
                        for (i = 0; i < uref_multi->num_values; i++)
                                uref_multi->values[i] =
index 3fae3a91ce5b4acb1d6284a838a348229e2d682b..c89687a10835538307212949317042f40042129c 100644 (file)
@@ -187,6 +187,11 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
        davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh);
        davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl);
 
+       /* Respond at reserved "SMBus Host" slave address" (and zero);
+        * we seem to have no option to not respond...
+        */
+       davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08);
+
        dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk);
        dev_dbg(dev->dev, "PSC  = %d\n",
                davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG));
@@ -387,7 +392,7 @@ static void terminate_write(struct davinci_i2c_dev *dev)
        davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
 
        if (!dev->terminate)
-               dev_err(dev->dev, "TDR IRQ while no data to send\n");
+               dev_dbg(dev->dev, "TDR IRQ while no data to send\n");
 }
 
 /*
@@ -473,9 +478,14 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
                        break;
 
                case DAVINCI_I2C_IVR_AAS:
-                       dev_warn(dev->dev, "Address as slave interrupt\n");
-               }/* switch */
-       }/* while */
+                       dev_dbg(dev->dev, "Address as slave interrupt\n");
+                       break;
+
+               default:
+                       dev_warn(dev->dev, "Unrecognized irq stat %d\n", stat);
+                       break;
+               }
+       }
 
        return count ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -505,7 +515,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
+       ioarea = request_mem_region(mem->start, resource_size(mem),
                                    pdev->name);
        if (!ioarea) {
                dev_err(&pdev->dev, "I2C region already claimed\n");
@@ -523,7 +533,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
        dev->irq = irq->start;
        platform_set_drvdata(pdev, dev);
 
-       dev->clk = clk_get(&pdev->dev, "I2CCLK");
+       dev->clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(dev->clk)) {
                r = -ENODEV;
                goto err_free_mem;
@@ -568,7 +578,7 @@ err_free_mem:
        put_device(&pdev->dev);
        kfree(dev);
 err_release_region:
-       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+       release_mem_region(mem->start, resource_size(mem));
 
        return r;
 }
@@ -591,7 +601,7 @@ static int davinci_i2c_remove(struct platform_device *pdev)
        kfree(dev);
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+       release_mem_region(mem->start, resource_size(mem));
        return 0;
 }
 
index ad8d2010c9211cf0f28f9201aa7346662357626b..fdd83277c8a81ac22441ce7ddea5188b0247e34f 100644 (file)
@@ -806,7 +806,7 @@ omap_i2c_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
+       ioarea = request_mem_region(mem->start, resource_size(mem),
                        pdev->name);
        if (!ioarea) {
                dev_err(&pdev->dev, "I2C region already claimed\n");
@@ -905,7 +905,7 @@ err_free_mem:
        platform_set_drvdata(pdev, NULL);
        kfree(dev);
 err_release_region:
-       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+       release_mem_region(mem->start, resource_size(mem));
 
        return r;
 }
@@ -925,7 +925,7 @@ omap_i2c_remove(struct platform_device *pdev)
        iounmap(dev->base);
        kfree(dev);
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+       release_mem_region(mem->start, resource_size(mem));
        return 0;
 }
 
index 1c01083b01b5ac0bc3f7eac54a657a72fb049ea0..4f3d99cd16927c2d9ae57c6bbda6d3894e5a9f6b 100644 (file)
@@ -563,7 +563,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
                goto err_irq;
        }
 
-       size = (res->end - res->start) + 1;
+       size = resource_size(res);
 
        pd->reg = ioremap(res->start, size);
        if (pd->reg == NULL) {
index 042fda295f3a557cd56c623a6aab980ae362271e..6407f47bda82db92b5ba2f2926851f774a938e91 100644 (file)
@@ -92,7 +92,7 @@ static int simtec_i2c_probe(struct platform_device *dev)
                goto err;
        }
 
-       size = (res->end-res->start)+1;
+       size = resource_size(res);
 
        pd->ioarea = request_mem_region(res->start, size, dev->name);
        if (pd->ioarea == NULL) {
index 695181120cdb9f14d0a16740c901345d599d052b..7f878017b736fcd913cfaea1e3939f10bb6cdf82 100644 (file)
@@ -455,6 +455,7 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
 
        rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
        rq->special = cmd;
+       cmd->rq = rq;
 }
 
 ide_devset_get(multcount, mult_count);
index 013dc595fab63754b391b33a7efd6b3e287167c3..bc5fb12b913c365da7610365c2167b7a7820e4de 100644 (file)
@@ -1064,6 +1064,7 @@ static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd,
                tape->best_dsc_rw_freq = config.dsc_rw_frequency;
                break;
        case 0x0350:
+               memset(&config, 0, sizeof(config));
                config.dsc_rw_frequency = (int) tape->best_dsc_rw_freq;
                config.nr_stages = 1;
                if (copy_to_user(argp, &config, sizeof(config)))
index 114efd8dc8f585cfc389dfbb28d11c3c0cd0d3fb..1148140d08a1faf72967dc3068e41c71488054d8 100644 (file)
@@ -608,8 +608,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                                                    p, compat_mode);
 
                        if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
-                               return str_to_user(dev_name(&evdev->dev),
-                                                  _IOC_SIZE(cmd), p);
+                               return str_to_user(dev->name, _IOC_SIZE(cmd), p);
 
                        if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
                                return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
index 0e12f89276a370e753ccbb9e111030f5f83ae253..4cfd084fa8972dda828fa59197eee7e383a03d0c 100644 (file)
@@ -536,7 +536,7 @@ static int joydev_ioctl_common(struct joydev *joydev,
        default:
                if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) {
                        int len;
-                       const char *name = dev_name(&dev->dev);
+                       const char *name = dev->name;
 
                        if (!name)
                                return 0;
index b868b8d5fbb3e29c58a78c69f5350098fd9ed6f2..f155ad8cdae7e16b8240b20c95c983be24536c41 100644 (file)
@@ -470,20 +470,20 @@ static void xpad_irq_out(struct urb *urb)
        status = urb->status;
 
        switch (status) {
-               case 0:
+       case 0:
                /* success */
-               break;
-               case -ECONNRESET:
-               case -ENOENT:
-               case -ESHUTDOWN:
-                       /* this urb is terminated, clean up */
-                       dbg("%s - urb shutting down with status: %d",
-                               __func__, status);
-                       return;
-               default:
-                       dbg("%s - nonzero urb status received: %d",
-                               __func__, status);
-                       goto exit;
+               return;
+
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dbg("%s - urb shutting down with status: %d", __func__, status);
+               return;
+
+       default:
+               dbg("%s - nonzero urb status received: %d", __func__, status);
+               goto exit;
        }
 
 exit:
index df3f8aa68115c48109739f84df30eee651a8ef4e..95fe0452dae48e809d4c7c6db9dab80fae57d127 100644 (file)
@@ -894,6 +894,13 @@ static unsigned int atkbd_amilo_pa1510_forced_release_keys[] = {
        0xb0, 0xae, -1U
 };
 
+/*
+ * Amilo Pi 3525 key release for Fn+Volume keys not working
+ */
+static unsigned int atkbd_amilo_pi3525_forced_release_keys[] = {
+       0x20, 0xa0, 0x2e, 0xae, 0x30, 0xb0, -1U
+};
+
 /*
  * Amilo Xi 3650 key release for light touch bar not working
  */
@@ -901,6 +908,13 @@ static unsigned int atkbd_amilo_xi3650_forced_release_keys[] = {
        0x67, 0xed, 0x90, 0xa2, 0x99, 0xa4, 0xae, 0xb0, -1U
 };
 
+/*
+ * Soltech TA12 system with broken key release on volume keys and mute key
+ */
+static unsigned int atkdb_soltech_ta12_forced_release_keys[] = {
+       0xa0, 0xae, 0xb0, -1U
+};
+
 /*
  * atkbd_set_keycode_table() initializes keyboard's keycode table
  * according to the selected scancode set
@@ -1567,6 +1581,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
                .callback = atkbd_setup_forced_release,
                .driver_data = atkbd_amilo_pa1510_forced_release_keys,
        },
+       {
+               .ident = "Fujitsu Amilo Pi 3525",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 3525"),
+               },
+               .callback = atkbd_setup_forced_release,
+               .driver_data = atkbd_amilo_pi3525_forced_release_keys,
+       },
        {
                .ident = "Fujitsu Amilo Xi 3650",
                .matches = {
@@ -1576,6 +1599,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
                .callback = atkbd_setup_forced_release,
                .driver_data = atkbd_amilo_xi3650_forced_release_keys,
        },
+       {
+               .ident = "Soltech Corporation TA12",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Soltech Corporation"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TA12"),
+               },
+               .callback = atkbd_setup_forced_release,
+               .driver_data = atkdb_soltech_ta12_forced_release_keys,
+       },
        { }
 };
 
index 6d67af5387adcfdff514133ca9f1ce9d0bf39f8b..21cb755a54fb925deda36db17933a0991bb0969c 100644 (file)
@@ -114,7 +114,7 @@ static int __devexit pcspkr_remove(struct platform_device *dev)
        return 0;
 }
 
-static int pcspkr_suspend(struct platform_device *dev, pm_message_t state)
+static int pcspkr_suspend(struct device *dev)
 {
        pcspkr_event(NULL, EV_SND, SND_BELL, 0);
 
@@ -127,14 +127,18 @@ static void pcspkr_shutdown(struct platform_device *dev)
        pcspkr_event(NULL, EV_SND, SND_BELL, 0);
 }
 
+static struct dev_pm_ops pcspkr_pm_ops = {
+       .suspend = pcspkr_suspend,
+};
+
 static struct platform_driver pcspkr_platform_driver = {
        .driver         = {
                .name   = "pcspkr",
                .owner  = THIS_MODULE,
+               .pm     = &pcspkr_pm_ops,
        },
        .probe          = pcspkr_probe,
        .remove         = __devexit_p(pcspkr_remove),
-       .suspend        = pcspkr_suspend,
        .shutdown       = pcspkr_shutdown,
 };
 
index 7c8957dd22c03d42252e410af97e385c78b2c4b7..26e17a9a22eb7fd030edba83537a6d3b68749081 100644 (file)
@@ -644,6 +644,15 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                },
                .driver_data = keymap_fs_amilo_pro_v2000
        },
+       {
+               .callback = dmi_matched,
+               .ident = "Maxdata Pro 7000 DX",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"),
+               },
+               .driver_data = keymap_fs_amilo_pro_v2000
+       },
        {
                .callback = dmi_matched,
                .ident = "Fujitsu N3510",
index 1ebfcab746623d8fd09acf35d6b753afc0963c12..8ff7e35c70696de765b8ab3dc2e4b61a02ee3356 100644 (file)
@@ -408,6 +408,8 @@ static int if_write_room(struct tty_struct *tty)
        return retval;
 }
 
+/* FIXME: This function does not have error returns */
+
 static int if_chars_in_buffer(struct tty_struct *tty)
 {
        struct cardstate *cs;
index 9c3138265f8e4fa62892321c97cd62d88c52584c..01c591923793f4d494fffef7d86a17f0da43f479 100644 (file)
@@ -38,8 +38,6 @@ struct lguest_pages
 #define CHANGED_GDT_TLS                4 /* Actually a subset of CHANGED_GDT */
 #define CHANGED_ALL            3
 
-struct lguest;
-
 struct lg_cpu {
        unsigned int id;
        struct lguest *lg;
index b56d72ff06e9efbf169d5b2f0c7af2c4f6e7589e..34e23489811ae74ea14594f1af1cb84f7a6e6b58 100644 (file)
@@ -384,7 +384,7 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
                                u16 val[2] = {0, 0};
                                val[0] = mvsd_read(MVSD_FIFO);
                                val[1] = mvsd_read(MVSD_FIFO);
-                               memcpy(p, &val, s);
+                               memcpy(p, ((void *)&val) + 4 - s, s);
                                s = 0;
                                intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
                        }
@@ -423,7 +423,7 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
                if (s < 4) {
                        if (s && (intr_status & MVSD_NOR_TX_AVAIL)) {
                                u16 val[2] = {0, 0};
-                               memcpy(&val, p, s);
+                               memcpy(((void *)&val) + 4 - s, p, s);
                                mvsd_write(MVSD_FIFO, val[0]);
                                mvsd_write(MVSD_FIFO, val[1]);
                                s = 0;
index d7d7109ef47e10b665059433ec962db77f176f7d..e55ac792d68c700e2bfc0d9b86d992c5f4199faf 100644 (file)
@@ -168,12 +168,12 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
 
        if (data->flags & MMC_DATA_READ) {
                host->dma_dir = DMA_FROM_DEVICE;
-               dcmd = DCMD_INCTRGADDR | DCMD_FLOWTRG;
+               dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC;
                DRCMR(host->dma_drcmrtx) = 0;
                DRCMR(host->dma_drcmrrx) = host->dma | DRCMR_MAPVLD;
        } else {
                host->dma_dir = DMA_TO_DEVICE;
-               dcmd = DCMD_INCSRCADDR | DCMD_FLOWSRC;
+               dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG;
                DRCMR(host->dma_drcmrrx) = 0;
                DRCMR(host->dma_drcmrtx) = host->dma | DRCMR_MAPVLD;
        }
index 95aaac03f9389a8727b3ed65f91124dc592c15dc..b5e478fa26612b188aa664541503457b2e58d2af 100644 (file)
@@ -332,6 +332,7 @@ static int gluebi_create(struct ubi_device_info *di,
        }
 
        gluebi->vol_id = vi->vol_id;
+       gluebi->ubi_num = vi->ubi_num;
        mtd->type = MTD_UBIVOLUME;
        if (!di->ro_mode)
                mtd->flags = MTD_WRITEABLE;
index f60895ee0aebde9098e1f5251be0a38ecd6cf02f..a423131b617141faaaf7b998e49ceb8b23146fce 100644 (file)
@@ -781,7 +781,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
                        return -EINVAL;
                }
 
-               image_seq = be32_to_cpu(ech->ec);
+               image_seq = be32_to_cpu(ech->image_seq);
                if (!si->image_seq_set) {
                        ubi->image_seq = image_seq;
                        si->image_seq_set = 1;
index 8ae72ec14456d4dc2e31141777a1bf35776fc78a..0e2ba21d4441810a279432229d7d078ef3e65bdd 100644 (file)
@@ -908,6 +908,7 @@ static const struct net_device_ops rtl8139_netdev_ops = {
        .ndo_open               = rtl8139_open,
        .ndo_stop               = rtl8139_close,
        .ndo_get_stats          = rtl8139_get_stats,
+       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = rtl8139_set_mac_address,
        .ndo_start_xmit         = rtl8139_start_xmit,
index c155bd3ec9f1a47640d4706626f544afe2e335bb..b5a7513df4eb99f3f2312d7fad6edfcc468fdd40 100644 (file)
@@ -1729,6 +1729,12 @@ config KS8842
        help
          This platform driver is for Micrel KSZ8842 chip.
 
+config KS8851
+       tristate "Micrel KS8851 SPI"
+       depends on SPI
+       help
+         SPI driver for Micrel KS8851 SPI attached network chip.
+
 config VIA_RHINE
        tristate "VIA Rhine support"
        depends on NET_PCI && PCI
index 4b58a59f211b4e329e791ae3bf881a7f9edf7a81..ead8cab3cfe1d464dd0294949efaf1f02ec4d3be 100644 (file)
@@ -88,6 +88,7 @@ obj-$(CONFIG_SKGE) += skge.o
 obj-$(CONFIG_SKY2) += sky2.o
 obj-$(CONFIG_SKFP) += skfp/
 obj-$(CONFIG_KS8842)   += ks8842.o
+obj-$(CONFIG_KS8851)   += ks8851.o
 obj-$(CONFIG_VIA_RHINE) += via-rhine.o
 obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
 obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
index 2895db13bfa4459cebc86b89c2e7dc1fc5971495..c37ee9e6b67b93c989de07689c0c47bad7150d50 100644 (file)
@@ -63,3 +63,11 @@ config IXP4XX_ETH
        help
          Say Y here if you want to use built-in Ethernet ports
          on IXP4xx processor.
+
+config W90P910_ETH
+       tristate "Nuvoton w90p910 Ethernet support"
+       depends on ARM && ARCH_W90X900
+       select PHYLIB
+       help
+         Say Y here if you want to use built-in Ethernet ports
+         on w90p910 processor.
index 811a3ccd14c107c56136af8884022f7cd9f4498f..303171f589e61f2379587f9d13ddbc4b416263e6 100644 (file)
@@ -11,3 +11,4 @@ obj-$(CONFIG_ARM_AT91_ETHER)  += at91_ether.o
 obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o
 obj-$(CONFIG_EP93XX_ETH)       += ep93xx_eth.o
 obj-$(CONFIG_IXP4XX_ETH)       += ixp4xx_eth.o
+obj-$(CONFIG_W90P910_ETH)      += w90p910_ether.o
index 6f42ad728915b2683ee9ee66a9e11562c890453e..3fe09876e76d3f5c62e0878adf7545317760a2c3 100644 (file)
@@ -1142,7 +1142,9 @@ static const struct net_device_ops ixp4xx_netdev_ops = {
        .ndo_start_xmit = eth_xmit,
        .ndo_set_multicast_list = eth_set_mcast_list,
        .ndo_do_ioctl = eth_ioctl,
-
+       .ndo_change_mtu = eth_change_mtu,
+       .ndo_set_mac_address = eth_mac_addr,
+       .ndo_validate_addr = eth_validate_addr,
 };
 
 static int __devinit eth_init_one(struct platform_device *pdev)
diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c
new file mode 100644 (file)
index 0000000..616fb79
--- /dev/null
@@ -0,0 +1,1105 @@
+/*
+ * Copyright (c) 2008-2009 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;version 2 of the License.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mii.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#define DRV_MODULE_NAME                "w90p910-emc"
+#define DRV_MODULE_VERSION     "0.1"
+
+/* Ethernet MAC Registers */
+#define REG_CAMCMR             0x00
+#define REG_CAMEN              0x04
+#define REG_CAMM_BASE          0x08
+#define REG_CAML_BASE          0x0c
+#define REG_TXDLSA             0x88
+#define REG_RXDLSA             0x8C
+#define REG_MCMDR              0x90
+#define REG_MIID               0x94
+#define REG_MIIDA              0x98
+#define REG_FFTCR              0x9C
+#define REG_TSDR               0xa0
+#define REG_RSDR               0xa4
+#define REG_DMARFC             0xa8
+#define REG_MIEN               0xac
+#define REG_MISTA              0xb0
+#define REG_CTXDSA             0xcc
+#define REG_CTXBSA             0xd0
+#define REG_CRXDSA             0xd4
+#define REG_CRXBSA             0xd8
+
+/* mac controller bit */
+#define MCMDR_RXON             0x01
+#define MCMDR_ACP              (0x01 << 3)
+#define MCMDR_SPCRC            (0x01 << 5)
+#define MCMDR_TXON             (0x01 << 8)
+#define MCMDR_FDUP             (0x01 << 18)
+#define MCMDR_ENMDC            (0x01 << 19)
+#define MCMDR_OPMOD            (0x01 << 20)
+#define SWR                    (0x01 << 24)
+
+/* cam command regiser */
+#define CAMCMR_AUP             0x01
+#define CAMCMR_AMP             (0x01 << 1)
+#define CAMCMR_ABP             (0x01 << 2)
+#define CAMCMR_CCAM            (0x01 << 3)
+#define CAMCMR_ECMP            (0x01 << 4)
+#define CAM0EN                 0x01
+
+/* mac mii controller bit */
+#define MDCCR                  (0x0a << 20)
+#define PHYAD                  (0x01 << 8)
+#define PHYWR                  (0x01 << 16)
+#define PHYBUSY                        (0x01 << 17)
+#define PHYPRESP               (0x01 << 18)
+#define CAM_ENTRY_SIZE         0x08
+
+/* rx and tx status */
+#define TXDS_TXCP              (0x01 << 19)
+#define RXDS_CRCE              (0x01 << 17)
+#define RXDS_PTLE              (0x01 << 19)
+#define RXDS_RXGD              (0x01 << 20)
+#define RXDS_ALIE              (0x01 << 21)
+#define RXDS_RP                        (0x01 << 22)
+
+/* mac interrupt status*/
+#define MISTA_EXDEF            (0x01 << 19)
+#define MISTA_TXBERR           (0x01 << 24)
+#define MISTA_TDU              (0x01 << 23)
+#define MISTA_RDU              (0x01 << 10)
+#define MISTA_RXBERR           (0x01 << 11)
+
+#define ENSTART                        0x01
+#define ENRXINTR               0x01
+#define ENRXGD                 (0x01 << 4)
+#define ENRXBERR               (0x01 << 11)
+#define ENTXINTR               (0x01 << 16)
+#define ENTXCP                 (0x01 << 18)
+#define ENTXABT                        (0x01 << 21)
+#define ENTXBERR               (0x01 << 24)
+#define ENMDC                  (0x01 << 19)
+#define PHYBUSY                        (0x01 << 17)
+#define MDCCR_VAL              0xa00000
+
+/* rx and tx owner bit */
+#define RX_OWEN_DMA            (0x01 << 31)
+#define RX_OWEN_CPU            (~(0x03 << 30))
+#define TX_OWEN_DMA            (0x01 << 31)
+#define TX_OWEN_CPU            (~(0x01 << 31))
+
+/* tx frame desc controller bit */
+#define MACTXINTEN             0x04
+#define CRCMODE                        0x02
+#define PADDINGMODE            0x01
+
+/* fftcr controller bit */
+#define TXTHD                  (0x03 << 8)
+#define BLENGTH                        (0x01 << 20)
+
+/* global setting for driver */
+#define RX_DESC_SIZE           50
+#define TX_DESC_SIZE           10
+#define MAX_RBUFF_SZ           0x600
+#define MAX_TBUFF_SZ           0x600
+#define TX_TIMEOUT             50
+#define DELAY                  1000
+#define CAM0                   0x0
+
+static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg);
+
+struct w90p910_rxbd {
+       unsigned int sl;
+       unsigned int buffer;
+       unsigned int reserved;
+       unsigned int next;
+};
+
+struct w90p910_txbd {
+       unsigned int mode;
+       unsigned int buffer;
+       unsigned int sl;
+       unsigned int next;
+};
+
+struct recv_pdesc {
+       struct w90p910_rxbd desclist[RX_DESC_SIZE];
+       char recv_buf[RX_DESC_SIZE][MAX_RBUFF_SZ];
+};
+
+struct tran_pdesc {
+       struct w90p910_txbd desclist[TX_DESC_SIZE];
+       char tran_buf[RX_DESC_SIZE][MAX_TBUFF_SZ];
+};
+
+struct  w90p910_ether {
+       struct recv_pdesc *rdesc;
+       struct recv_pdesc *rdesc_phys;
+       struct tran_pdesc *tdesc;
+       struct tran_pdesc *tdesc_phys;
+       struct net_device_stats stats;
+       struct platform_device *pdev;
+       struct sk_buff *skb;
+       struct clk *clk;
+       struct clk *rmiiclk;
+       struct mii_if_info mii;
+       struct timer_list check_timer;
+       void __iomem *reg;
+       unsigned int rxirq;
+       unsigned int txirq;
+       unsigned int cur_tx;
+       unsigned int cur_rx;
+       unsigned int finish_tx;
+       unsigned int rx_packets;
+       unsigned int rx_bytes;
+       unsigned int start_tx_ptr;
+       unsigned int start_rx_ptr;
+       unsigned int linkflag;
+       spinlock_t lock;
+};
+
+static void update_linkspeed_register(struct net_device *dev,
+                               unsigned int speed, unsigned int duplex)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = __raw_readl(ether->reg + REG_MCMDR);
+
+       if (speed == SPEED_100) {
+               /* 100 full/half duplex */
+               if (duplex == DUPLEX_FULL) {
+                       val |= (MCMDR_OPMOD | MCMDR_FDUP);
+               } else {
+                       val |= MCMDR_OPMOD;
+                       val &= ~MCMDR_FDUP;
+               }
+       } else {
+               /* 10 full/half duplex */
+               if (duplex == DUPLEX_FULL) {
+                       val |= MCMDR_FDUP;
+                       val &= ~MCMDR_OPMOD;
+               } else {
+                       val &= ~(MCMDR_FDUP | MCMDR_OPMOD);
+               }
+       }
+
+       __raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void update_linkspeed(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       struct platform_device *pdev;
+       unsigned int bmsr, bmcr, lpa, speed, duplex;
+
+       pdev = ether->pdev;
+
+       if (!mii_link_ok(&ether->mii)) {
+               ether->linkflag = 0x0;
+               netif_carrier_off(dev);
+               dev_warn(&pdev->dev, "%s: Link down.\n", dev->name);
+               return;
+       }
+
+       if (ether->linkflag == 1)
+               return;
+
+       bmsr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMSR);
+       bmcr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMCR);
+
+       if (bmcr & BMCR_ANENABLE) {
+               if (!(bmsr & BMSR_ANEGCOMPLETE))
+                       return;
+
+               lpa = w90p910_mdio_read(dev, ether->mii.phy_id, MII_LPA);
+
+               if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF))
+                       speed = SPEED_100;
+               else
+                       speed = SPEED_10;
+
+               if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL))
+                       duplex = DUPLEX_FULL;
+               else
+                       duplex = DUPLEX_HALF;
+
+       } else {
+               speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
+               duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
+       }
+
+       update_linkspeed_register(dev, speed, duplex);
+
+       dev_info(&pdev->dev, "%s: Link now %i-%s\n", dev->name, speed,
+                       (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
+       ether->linkflag = 0x01;
+
+       netif_carrier_on(dev);
+}
+
+static void w90p910_check_link(unsigned long dev_id)
+{
+       struct net_device *dev = (struct net_device *) dev_id;
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       update_linkspeed(dev);
+       mod_timer(&ether->check_timer, jiffies + msecs_to_jiffies(1000));
+}
+
+static void w90p910_write_cam(struct net_device *dev,
+                               unsigned int x, unsigned char *pval)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int msw, lsw;
+
+       msw = (pval[0] << 24) | (pval[1] << 16) | (pval[2] << 8) | pval[3];
+
+       lsw = (pval[4] << 24) | (pval[5] << 16);
+
+       __raw_writel(lsw, ether->reg + REG_CAML_BASE + x * CAM_ENTRY_SIZE);
+       __raw_writel(msw, ether->reg + REG_CAMM_BASE + x * CAM_ENTRY_SIZE);
+}
+
+static void w90p910_init_desc(struct net_device *dev)
+{
+       struct w90p910_ether *ether;
+       struct w90p910_txbd  *tdesc, *tdesc_phys;
+       struct w90p910_rxbd  *rdesc, *rdesc_phys;
+       unsigned int i, j;
+
+       ether = netdev_priv(dev);
+
+       ether->tdesc = (struct tran_pdesc *)
+                       dma_alloc_coherent(NULL, sizeof(struct tran_pdesc),
+                               (dma_addr_t *) &ether->tdesc_phys, GFP_KERNEL);
+
+       ether->rdesc = (struct recv_pdesc *)
+                       dma_alloc_coherent(NULL, sizeof(struct recv_pdesc),
+                               (dma_addr_t *) &ether->rdesc_phys, GFP_KERNEL);
+
+       for (i = 0; i < TX_DESC_SIZE; i++) {
+               tdesc = &(ether->tdesc->desclist[i]);
+
+               j = ((i + 1) / TX_DESC_SIZE);
+
+               if (j != 0) {
+                       tdesc_phys = &(ether->tdesc_phys->desclist[0]);
+                       ether->start_tx_ptr = (unsigned int)tdesc_phys;
+                       tdesc->next = (unsigned int)ether->start_tx_ptr;
+               } else {
+                       tdesc_phys = &(ether->tdesc_phys->desclist[i+1]);
+                       tdesc->next = (unsigned int)tdesc_phys;
+               }
+
+               tdesc->buffer = (unsigned int)ether->tdesc_phys->tran_buf[i];
+               tdesc->sl = 0;
+               tdesc->mode = 0;
+       }
+
+       for (i = 0; i < RX_DESC_SIZE; i++) {
+               rdesc = &(ether->rdesc->desclist[i]);
+
+               j = ((i + 1) / RX_DESC_SIZE);
+
+               if (j != 0) {
+                       rdesc_phys = &(ether->rdesc_phys->desclist[0]);
+                       ether->start_rx_ptr = (unsigned int)rdesc_phys;
+                       rdesc->next = (unsigned int)ether->start_rx_ptr;
+               } else {
+                       rdesc_phys = &(ether->rdesc_phys->desclist[i+1]);
+                       rdesc->next = (unsigned int)rdesc_phys;
+               }
+
+               rdesc->sl = RX_OWEN_DMA;
+               rdesc->buffer = (unsigned int)ether->rdesc_phys->recv_buf[i];
+         }
+}
+
+static void w90p910_set_fifo_threshold(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = TXTHD | BLENGTH;
+       __raw_writel(val, ether->reg + REG_FFTCR);
+}
+
+static void w90p910_return_default_idle(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = __raw_readl(ether->reg + REG_MCMDR);
+       val |= SWR;
+       __raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void w90p910_trigger_rx(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       __raw_writel(ENSTART, ether->reg + REG_RSDR);
+}
+
+static void w90p910_trigger_tx(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       __raw_writel(ENSTART, ether->reg + REG_TSDR);
+}
+
+static void w90p910_enable_mac_interrupt(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = ENTXINTR | ENRXINTR | ENRXGD | ENTXCP;
+       val |= ENTXBERR | ENRXBERR | ENTXABT;
+
+       __raw_writel(val, ether->reg + REG_MIEN);
+}
+
+static void w90p910_get_and_clear_int(struct net_device *dev,
+                                                       unsigned int *val)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       *val = __raw_readl(ether->reg + REG_MISTA);
+       __raw_writel(*val, ether->reg + REG_MISTA);
+}
+
+static void w90p910_set_global_maccmd(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = __raw_readl(ether->reg + REG_MCMDR);
+       val |= MCMDR_SPCRC | MCMDR_ENMDC | MCMDR_ACP | ENMDC;
+       __raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void w90p910_enable_cam(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       w90p910_write_cam(dev, CAM0, dev->dev_addr);
+
+       val = __raw_readl(ether->reg + REG_CAMEN);
+       val |= CAM0EN;
+       __raw_writel(val, ether->reg + REG_CAMEN);
+}
+
+static void w90p910_enable_cam_command(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = CAMCMR_ECMP | CAMCMR_ABP | CAMCMR_AMP;
+       __raw_writel(val, ether->reg + REG_CAMCMR);
+}
+
+static void w90p910_enable_tx(struct net_device *dev, unsigned int enable)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = __raw_readl(ether->reg + REG_MCMDR);
+
+       if (enable)
+               val |= MCMDR_TXON;
+       else
+               val &= ~MCMDR_TXON;
+
+       __raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void w90p910_enable_rx(struct net_device *dev, unsigned int enable)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = __raw_readl(ether->reg + REG_MCMDR);
+
+       if (enable)
+               val |= MCMDR_RXON;
+       else
+               val &= ~MCMDR_RXON;
+
+       __raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void w90p910_set_curdest(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       __raw_writel(ether->start_rx_ptr, ether->reg + REG_RXDLSA);
+       __raw_writel(ether->start_tx_ptr, ether->reg + REG_TXDLSA);
+}
+
+static void w90p910_reset_mac(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       spin_lock(&ether->lock);
+
+       w90p910_enable_tx(dev, 0);
+       w90p910_enable_rx(dev, 0);
+       w90p910_set_fifo_threshold(dev);
+       w90p910_return_default_idle(dev);
+
+       if (!netif_queue_stopped(dev))
+               netif_stop_queue(dev);
+
+       w90p910_init_desc(dev);
+
+       dev->trans_start = jiffies;
+       ether->cur_tx = 0x0;
+       ether->finish_tx = 0x0;
+       ether->cur_rx = 0x0;
+
+       w90p910_set_curdest(dev);
+       w90p910_enable_cam(dev);
+       w90p910_enable_cam_command(dev);
+       w90p910_enable_mac_interrupt(dev);
+       w90p910_enable_tx(dev, 1);
+       w90p910_enable_rx(dev, 1);
+       w90p910_trigger_tx(dev);
+       w90p910_trigger_rx(dev);
+
+       dev->trans_start = jiffies;
+
+       if (netif_queue_stopped(dev))
+               netif_wake_queue(dev);
+
+       spin_unlock(&ether->lock);
+}
+
+static void w90p910_mdio_write(struct net_device *dev,
+                                       int phy_id, int reg, int data)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       struct platform_device *pdev;
+       unsigned int val, i;
+
+       pdev = ether->pdev;
+
+       __raw_writel(data, ether->reg + REG_MIID);
+
+       val = (phy_id << 0x08) | reg;
+       val |= PHYBUSY | PHYWR | MDCCR_VAL;
+       __raw_writel(val, ether->reg + REG_MIIDA);
+
+       for (i = 0; i < DELAY; i++) {
+               if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0)
+                       break;
+       }
+
+       if (i == DELAY)
+               dev_warn(&pdev->dev, "mdio write timed out\n");
+}
+
+static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       struct platform_device *pdev;
+       unsigned int val, i, data;
+
+       pdev = ether->pdev;
+
+       val = (phy_id << 0x08) | reg;
+       val |= PHYBUSY | MDCCR_VAL;
+       __raw_writel(val, ether->reg + REG_MIIDA);
+
+       for (i = 0; i < DELAY; i++) {
+               if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0)
+                       break;
+       }
+
+       if (i == DELAY) {
+               dev_warn(&pdev->dev, "mdio read timed out\n");
+               data = 0xffff;
+       } else {
+               data = __raw_readl(ether->reg + REG_MIID);
+       }
+
+       return data;
+}
+
+static int set_mac_address(struct net_device *dev, void *addr)
+{
+       struct sockaddr *address = addr;
+
+       if (!is_valid_ether_addr(address->sa_data))
+               return -EADDRNOTAVAIL;
+
+       memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
+       w90p910_write_cam(dev, CAM0, dev->dev_addr);
+
+       return 0;
+}
+
+static int w90p910_ether_close(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       dma_free_writecombine(NULL, sizeof(struct w90p910_rxbd),
+                               ether->rdesc, (dma_addr_t)ether->rdesc_phys);
+       dma_free_writecombine(NULL, sizeof(struct w90p910_txbd),
+                               ether->tdesc, (dma_addr_t)ether->tdesc_phys);
+
+       netif_stop_queue(dev);
+
+       del_timer_sync(&ether->check_timer);
+       clk_disable(ether->rmiiclk);
+       clk_disable(ether->clk);
+
+       free_irq(ether->txirq, dev);
+       free_irq(ether->rxirq, dev);
+
+       return 0;
+}
+
+static struct net_device_stats *w90p910_ether_stats(struct net_device *dev)
+{
+       struct w90p910_ether *ether;
+
+       ether = netdev_priv(dev);
+
+       return &ether->stats;
+}
+
+static int w90p910_send_frame(struct net_device *dev,
+                                       unsigned char *data, int length)
+{
+       struct w90p910_ether *ether;
+       struct w90p910_txbd *txbd;
+       struct platform_device *pdev;
+       unsigned char *buffer;
+
+       ether = netdev_priv(dev);
+       pdev = ether->pdev;
+
+       txbd = &ether->tdesc->desclist[ether->cur_tx];
+       buffer = ether->tdesc->tran_buf[ether->cur_tx];
+       if (length > 1514) {
+               dev_err(&pdev->dev, "send data %d bytes, check it\n", length);
+               length = 1514;
+       }
+
+       txbd->sl = length & 0xFFFF;
+
+       memcpy(buffer, data, length);
+
+       txbd->mode = TX_OWEN_DMA | PADDINGMODE | CRCMODE | MACTXINTEN;
+
+       w90p910_enable_tx(dev, 1);
+
+       w90p910_trigger_tx(dev);
+
+       ether->cur_tx = (ether->cur_tx+1) % TX_DESC_SIZE;
+       txbd = &ether->tdesc->desclist[ether->cur_tx];
+
+       dev->trans_start = jiffies;
+
+       if (txbd->mode & TX_OWEN_DMA)
+               netif_stop_queue(dev);
+
+       return 0;
+}
+
+static int w90p910_ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       if (!(w90p910_send_frame(dev, skb->data, skb->len))) {
+               ether->skb = skb;
+               dev_kfree_skb_irq(skb);
+               return 0;
+       }
+       return -1;
+}
+
+static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
+{
+       struct w90p910_ether *ether;
+       struct w90p910_txbd  *txbd;
+       struct platform_device *pdev;
+       struct tran_pdesc *tran_pdesc;
+       struct net_device *dev;
+       unsigned int cur_entry, entry, status;
+
+       dev = (struct net_device *)dev_id;
+       ether = netdev_priv(dev);
+       pdev = ether->pdev;
+
+       spin_lock(&ether->lock);
+
+       w90p910_get_and_clear_int(dev, &status);
+
+       cur_entry = __raw_readl(ether->reg + REG_CTXDSA);
+
+       tran_pdesc = ether->tdesc_phys;
+       entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]);
+
+       while (entry != cur_entry) {
+               txbd = &ether->tdesc->desclist[ether->finish_tx];
+
+               ether->finish_tx = (ether->finish_tx + 1) % TX_DESC_SIZE;
+
+               if (txbd->sl & TXDS_TXCP) {
+                       ether->stats.tx_packets++;
+                       ether->stats.tx_bytes += txbd->sl & 0xFFFF;
+               } else {
+                       ether->stats.tx_errors++;
+               }
+
+               txbd->sl = 0x0;
+               txbd->mode = 0x0;
+
+               if (netif_queue_stopped(dev))
+                       netif_wake_queue(dev);
+
+               entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]);
+       }
+
+       if (status & MISTA_EXDEF) {
+               dev_err(&pdev->dev, "emc defer exceed interrupt\n");
+       } else if (status & MISTA_TXBERR) {
+                       dev_err(&pdev->dev, "emc bus error interrupt\n");
+                       w90p910_reset_mac(dev);
+               } else if (status & MISTA_TDU) {
+                               if (netif_queue_stopped(dev))
+                                       netif_wake_queue(dev);
+                       }
+
+       spin_unlock(&ether->lock);
+
+       return IRQ_HANDLED;
+}
+
+static void netdev_rx(struct net_device *dev)
+{
+       struct w90p910_ether *ether;
+       struct w90p910_rxbd *rxbd;
+       struct platform_device *pdev;
+       struct recv_pdesc *rdesc_phys;
+       struct sk_buff *skb;
+       unsigned char *data;
+       unsigned int length, status, val, entry;
+
+       ether = netdev_priv(dev);
+       pdev = ether->pdev;
+       rdesc_phys = ether->rdesc_phys;
+
+       rxbd = &ether->rdesc->desclist[ether->cur_rx];
+
+       do {
+               val = __raw_readl(ether->reg + REG_CRXDSA);
+               entry = (unsigned int)&rdesc_phys->desclist[ether->cur_rx];
+
+               if (val == entry)
+                       break;
+
+               status = rxbd->sl;
+               length = status & 0xFFFF;
+
+               if (status & RXDS_RXGD) {
+                       data = ether->rdesc->recv_buf[ether->cur_rx];
+                       skb = dev_alloc_skb(length+2);
+                       if (!skb) {
+                               dev_err(&pdev->dev, "get skb buffer error\n");
+                               ether->stats.rx_dropped++;
+                               return;
+                       }
+
+                       skb->dev = dev;
+                       skb_reserve(skb, 2);
+                       skb_put(skb, length);
+                       skb_copy_to_linear_data(skb, data, length);
+                       skb->protocol = eth_type_trans(skb, dev);
+                       ether->stats.rx_packets++;
+                       ether->stats.rx_bytes += length;
+                       netif_rx(skb);
+               } else {
+                       ether->stats.rx_errors++;
+
+                       if (status & RXDS_RP) {
+                               dev_err(&pdev->dev, "rx runt err\n");
+                               ether->stats.rx_length_errors++;
+                       } else if (status & RXDS_CRCE) {
+                                       dev_err(&pdev->dev, "rx crc err\n");
+                                       ether->stats.rx_crc_errors++;
+                               }
+
+                       if (status & RXDS_ALIE) {
+                               dev_err(&pdev->dev, "rx aligment err\n");
+                               ether->stats.rx_frame_errors++;
+                       } else if (status & RXDS_PTLE) {
+                                       dev_err(&pdev->dev, "rx longer err\n");
+                                       ether->stats.rx_over_errors++;
+                               }
+                       }
+
+               rxbd->sl = RX_OWEN_DMA;
+               rxbd->reserved = 0x0;
+               ether->cur_rx = (ether->cur_rx+1) % RX_DESC_SIZE;
+               rxbd = &ether->rdesc->desclist[ether->cur_rx];
+
+               dev->last_rx = jiffies;
+       } while (1);
+}
+
+static irqreturn_t w90p910_rx_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev;
+       struct w90p910_ether  *ether;
+       struct platform_device *pdev;
+       unsigned int status;
+
+       dev = (struct net_device *)dev_id;
+       ether = netdev_priv(dev);
+       pdev = ether->pdev;
+
+       spin_lock(&ether->lock);
+
+       w90p910_get_and_clear_int(dev, &status);
+
+       if (status & MISTA_RDU) {
+               netdev_rx(dev);
+
+               w90p910_trigger_rx(dev);
+
+               spin_unlock(&ether->lock);
+               return IRQ_HANDLED;
+       } else if (status & MISTA_RXBERR) {
+                       dev_err(&pdev->dev, "emc rx bus error\n");
+                       w90p910_reset_mac(dev);
+               }
+
+       netdev_rx(dev);
+       spin_unlock(&ether->lock);
+       return IRQ_HANDLED;
+}
+
+static int w90p910_ether_open(struct net_device *dev)
+{
+       struct w90p910_ether *ether;
+       struct platform_device *pdev;
+
+       ether = netdev_priv(dev);
+       pdev = ether->pdev;
+
+       w90p910_reset_mac(dev);
+       w90p910_set_fifo_threshold(dev);
+       w90p910_set_curdest(dev);
+       w90p910_enable_cam(dev);
+       w90p910_enable_cam_command(dev);
+       w90p910_enable_mac_interrupt(dev);
+       w90p910_set_global_maccmd(dev);
+       w90p910_enable_rx(dev, 1);
+
+       ether->rx_packets = 0x0;
+       ether->rx_bytes = 0x0;
+
+       if (request_irq(ether->txirq, w90p910_tx_interrupt,
+                                               0x0, pdev->name, dev)) {
+               dev_err(&pdev->dev, "register irq tx failed\n");
+               return -EAGAIN;
+       }
+
+       if (request_irq(ether->rxirq, w90p910_rx_interrupt,
+                                               0x0, pdev->name, dev)) {
+               dev_err(&pdev->dev, "register irq rx failed\n");
+               return -EAGAIN;
+       }
+
+       mod_timer(&ether->check_timer, jiffies + msecs_to_jiffies(1000));
+       netif_start_queue(dev);
+       w90p910_trigger_rx(dev);
+
+       dev_info(&pdev->dev, "%s is OPENED\n", dev->name);
+
+       return 0;
+}
+
+static void w90p910_ether_set_multicast_list(struct net_device *dev)
+{
+       struct w90p910_ether *ether;
+       unsigned int rx_mode;
+
+       ether = netdev_priv(dev);
+
+       if (dev->flags & IFF_PROMISC)
+               rx_mode = CAMCMR_AUP | CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP;
+       else if ((dev->flags & IFF_ALLMULTI) || dev->mc_list)
+                       rx_mode = CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP;
+               else
+                               rx_mode = CAMCMR_ECMP | CAMCMR_ABP;
+       __raw_writel(rx_mode, ether->reg + REG_CAMCMR);
+}
+
+static int w90p910_ether_ioctl(struct net_device *dev,
+                                               struct ifreq *ifr, int cmd)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       struct mii_ioctl_data *data = if_mii(ifr);
+
+       return generic_mii_ioctl(&ether->mii, data, cmd, NULL);
+}
+
+static void w90p910_get_drvinfo(struct net_device *dev,
+                                       struct ethtool_drvinfo *info)
+{
+       strcpy(info->driver, DRV_MODULE_NAME);
+       strcpy(info->version, DRV_MODULE_VERSION);
+}
+
+static int w90p910_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       return mii_ethtool_gset(&ether->mii, cmd);
+}
+
+static int w90p910_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       return mii_ethtool_sset(&ether->mii, cmd);
+}
+
+static int w90p910_nway_reset(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       return mii_nway_restart(&ether->mii);
+}
+
+static u32 w90p910_get_link(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       return mii_link_ok(&ether->mii);
+}
+
+static const struct ethtool_ops w90p910_ether_ethtool_ops = {
+       .get_settings   = w90p910_get_settings,
+       .set_settings   = w90p910_set_settings,
+       .get_drvinfo    = w90p910_get_drvinfo,
+       .nway_reset     = w90p910_nway_reset,
+       .get_link       = w90p910_get_link,
+};
+
+static const struct net_device_ops w90p910_ether_netdev_ops = {
+       .ndo_open               = w90p910_ether_open,
+       .ndo_stop               = w90p910_ether_close,
+       .ndo_start_xmit         = w90p910_ether_start_xmit,
+       .ndo_get_stats          = w90p910_ether_stats,
+       .ndo_set_multicast_list = w90p910_ether_set_multicast_list,
+       .ndo_set_mac_address    = set_mac_address,
+       .ndo_do_ioctl           = w90p910_ether_ioctl,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+};
+
+static void __init get_mac_address(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       struct platform_device *pdev;
+       char addr[6];
+
+       pdev = ether->pdev;
+
+       addr[0] = 0x00;
+       addr[1] = 0x02;
+       addr[2] = 0xac;
+       addr[3] = 0x55;
+       addr[4] = 0x88;
+       addr[5] = 0xa8;
+
+       if (is_valid_ether_addr(addr))
+               memcpy(dev->dev_addr, &addr, 0x06);
+       else
+               dev_err(&pdev->dev, "invalid mac address\n");
+}
+
+static int w90p910_ether_setup(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       ether_setup(dev);
+       dev->netdev_ops = &w90p910_ether_netdev_ops;
+       dev->ethtool_ops = &w90p910_ether_ethtool_ops;
+
+       dev->tx_queue_len = 16;
+       dev->dma = 0x0;
+       dev->watchdog_timeo = TX_TIMEOUT;
+
+       get_mac_address(dev);
+
+       spin_lock_init(&ether->lock);
+
+       ether->cur_tx = 0x0;
+       ether->cur_rx = 0x0;
+       ether->finish_tx = 0x0;
+       ether->linkflag = 0x0;
+       ether->mii.phy_id = 0x01;
+       ether->mii.phy_id_mask = 0x1f;
+       ether->mii.reg_num_mask = 0x1f;
+       ether->mii.dev = dev;
+       ether->mii.mdio_read = w90p910_mdio_read;
+       ether->mii.mdio_write = w90p910_mdio_write;
+
+       setup_timer(&ether->check_timer, w90p910_check_link,
+                                               (unsigned long)dev);
+
+       return 0;
+}
+
+static int __devinit w90p910_ether_probe(struct platform_device *pdev)
+{
+       struct w90p910_ether *ether;
+       struct net_device *dev;
+       struct resource *res;
+       int error;
+
+       dev = alloc_etherdev(sizeof(struct w90p910_ether));
+       if (!dev)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to get I/O memory\n");
+               error = -ENXIO;
+               goto failed_free;
+       }
+
+       res = request_mem_region(res->start, resource_size(res), pdev->name);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to request I/O memory\n");
+               error = -EBUSY;
+               goto failed_free;
+       }
+
+       ether = netdev_priv(dev);
+
+       ether->reg = ioremap(res->start, resource_size(res));
+       if (ether->reg == NULL) {
+               dev_err(&pdev->dev, "failed to remap I/O memory\n");
+               error = -ENXIO;
+               goto failed_free_mem;
+       }
+
+       ether->txirq = platform_get_irq(pdev, 0);
+       if (ether->txirq < 0) {
+               dev_err(&pdev->dev, "failed to get ether tx irq\n");
+               error = -ENXIO;
+               goto failed_free_io;
+       }
+
+       ether->rxirq = platform_get_irq(pdev, 1);
+       if (ether->rxirq < 0) {
+               dev_err(&pdev->dev, "failed to get ether rx irq\n");
+               error = -ENXIO;
+               goto failed_free_txirq;
+       }
+
+       platform_set_drvdata(pdev, dev);
+
+       ether->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(ether->clk)) {
+               dev_err(&pdev->dev, "failed to get ether clock\n");
+               error = PTR_ERR(ether->clk);
+               goto failed_free_rxirq;
+       }
+
+       ether->rmiiclk = clk_get(&pdev->dev, "RMII");
+       if (IS_ERR(ether->rmiiclk)) {
+               dev_err(&pdev->dev, "failed to get ether clock\n");
+               error = PTR_ERR(ether->rmiiclk);
+               goto failed_put_clk;
+       }
+
+       ether->pdev = pdev;
+
+       w90p910_ether_setup(dev);
+
+       error = register_netdev(dev);
+       if (error != 0) {
+               dev_err(&pdev->dev, "Regiter EMC w90p910 FAILED\n");
+               error = -ENODEV;
+               goto failed_put_rmiiclk;
+       }
+
+       return 0;
+failed_put_rmiiclk:
+       clk_put(ether->rmiiclk);
+failed_put_clk:
+       clk_put(ether->clk);
+failed_free_rxirq:
+       free_irq(ether->rxirq, pdev);
+       platform_set_drvdata(pdev, NULL);
+failed_free_txirq:
+       free_irq(ether->txirq, pdev);
+failed_free_io:
+       iounmap(ether->reg);
+failed_free_mem:
+       release_mem_region(res->start, resource_size(res));
+failed_free:
+       free_netdev(dev);
+       return error;
+}
+
+static int __devexit w90p910_ether_remove(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       unregister_netdev(dev);
+       clk_put(ether->rmiiclk);
+       clk_put(ether->clk);
+       del_timer_sync(&ether->check_timer);
+       platform_set_drvdata(pdev, NULL);
+       free_netdev(dev);
+       return 0;
+}
+
+static struct platform_driver w90p910_ether_driver = {
+       .probe          = w90p910_ether_probe,
+       .remove         = __devexit_p(w90p910_ether_remove),
+       .driver         = {
+               .name   = "w90p910-emc",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init w90p910_ether_init(void)
+{
+       return platform_driver_register(&w90p910_ether_driver);
+}
+
+static void __exit w90p910_ether_exit(void)
+{
+       platform_driver_unregister(&w90p910_ether_driver);
+}
+
+module_init(w90p910_ether_init);
+module_exit(w90p910_ether_exit);
+
+MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
+MODULE_DESCRIPTION("w90p910 MAC driver!");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:w90p910-emc");
+
index e1658ef3fcdf04f0e75f71af8ddfae7e0113476a..2a1120ad2e74a4da9bf7186a0e7359d96a7e4ed3 100644 (file)
@@ -188,14 +188,14 @@ struct atl1c_tpd_ext_desc {
 #define RRS_HDS_TYPE_DATA      2
 
 #define RRS_IS_NO_HDS_TYPE(flag) \
-       (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == 0)
+       ((((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 == \
+       ((((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 == \
+       ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \
                        RRS_HDS_TYPE_DATA)
 
 /* rrs word 3 bit 0:31 */
@@ -245,7 +245,7 @@ struct atl1c_tpd_ext_desc {
 #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 == \
+       ((((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)
index cd547a205fb96d9d9a71f37cfbc57286686f31d2..a383122679de029b4e33a652d7007d071339cf3e 100644 (file)
@@ -1689,7 +1689,7 @@ static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
                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)
+                       if (unlikely(rfd_num != 1))
                                /* TODO support mul rfd*/
                                if (netif_msg_rx_err(adapter))
                                        dev_warn(&pdev->dev,
index c734b1983ec14667bc2debd4d5eec05b4f66369d..204db961029e798e74a8dc990d7b086207c0771c 100644 (file)
@@ -2071,7 +2071,7 @@ static int atl2_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))
                return -EOPNOTSUPP;
 
-       if (wol->wolopts & (WAKE_MCAST|WAKE_BCAST|WAKE_MCAST))
+       if (wol->wolopts & (WAKE_UCAST | WAKE_BCAST | WAKE_MCAST))
                return -EOPNOTSUPP;
 
        /* these settings will always override what we currently have */
index ed648acef7cffef16ee31923562b0a8b9c9ed731..2ee581a2cdec7f6210d0f95a71e996ec788299c5 100644 (file)
@@ -4212,13 +4212,14 @@ static void bnx2x_turn_off_sf(struct bnx2x *bp, u8 port)
 u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
                              u8 *version, u16 len)
 {
-       struct bnx2x *bp = params->bp;
+       struct bnx2x *bp;
        u32 ext_phy_type = 0;
        u32 spirom_ver = 0;
        u8 status = 0 ;
 
        if (version == NULL || params == NULL)
                return -EINVAL;
+       bp = params->bp;
 
        spirom_ver = REG_RD(bp, params->shmem_base +
                   offsetof(struct shmem_region,
index d927f71af8a31b9096b4ded0f9b18ab47a847116..aa1be1feceedad372f01d082904b66470f55273e 100644 (file)
@@ -1459,8 +1459,16 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
         * ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond
         */
        if (bond->slave_cnt == 0) {
-               if (slave_dev->type != ARPHRD_ETHER)
-                       bond_setup_by_slave(bond_dev, slave_dev);
+               if (bond_dev->type != slave_dev->type) {
+                       dev_close(bond_dev);
+                       pr_debug("%s: change device type from %d to %d\n",
+                               bond_dev->name, bond_dev->type, slave_dev->type);
+                       if (slave_dev->type != ARPHRD_ETHER)
+                               bond_setup_by_slave(bond_dev, slave_dev);
+                       else
+                               ether_setup(bond_dev);
+                       dev_open(bond_dev);
+               }
        } else if (bond_dev->type != slave_dev->type) {
                pr_err(DRV_NAME ": %s ether type (%d) is different "
                        "from other slaves (%d), can not enslave it.\n",
index 574daddc21bfb02817fb3b49cfe5dec624936f8e..9e4283aff828d9adc1f03db2276b38add2b9a31d 100644 (file)
@@ -346,7 +346,7 @@ void can_restart(unsigned long data)
        skb = dev_alloc_skb(sizeof(struct can_frame));
        if (skb == NULL) {
                err = -ENOMEM;
-               goto out;
+               goto restart;
        }
        skb->dev = dev;
        skb->protocol = htons(ETH_P_CAN);
@@ -361,13 +361,13 @@ void can_restart(unsigned long data)
        stats->rx_packets++;
        stats->rx_bytes += cf->can_dlc;
 
+restart:
        dev_dbg(dev->dev.parent, "restarted\n");
        priv->can_stats.restarts++;
 
        /* Now restart the device */
        err = priv->do_set_mode(dev, CAN_MODE_START);
 
-out:
        netif_carrier_on(dev);
        if (err)
                dev_err(dev->dev.parent, "Error %d during restart", err);
@@ -473,6 +473,10 @@ int open_candev(struct net_device *dev)
                return -EINVAL;
        }
 
+       /* Switch carrier on if device was stopped while in bus-off state */
+       if (!netif_carrier_ok(dev))
+               netif_carrier_on(dev);
+
        setup_timer(&priv->restart_timer, can_restart, (unsigned long)dev);
 
        return 0;
index 571f133a8fec5a94bf1493defb66f56c56520681..08ebee79d8a6a5e5d850922654b2529a34200d98 100644 (file)
@@ -63,7 +63,6 @@
 #include <linux/can.h>
 #include <linux/can/dev.h>
 #include <linux/can/error.h>
-#include <linux/can/dev.h>
 
 #include "sja1000.h"
 
index 3eee666a9cd26773fa4712704cf7066ec7f0cbc5..55445f980f9c975596d41b3a9e9a0887155f061b 100644 (file)
@@ -1524,6 +1524,7 @@ static void net_timeout(struct net_device *dev)
 static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
        struct net_local *lp = netdev_priv(dev);
+       unsigned long flags;
 
        if (net_debug > 3) {
                printk("%s: sent %d byte packet of type %x\n",
@@ -1535,7 +1536,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
                   ask the chip to start transmitting before the
                   whole packet has been completely uploaded. */
 
-       spin_lock_irq(&lp->lock);
+       spin_lock_irqsave(&lp->lock, flags);
        netif_stop_queue(dev);
 
        /* initiate a transmit sequence */
@@ -1549,13 +1550,13 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
                 * we're waiting for TxOk, so return 1 and requeue this packet.
                 */
 
-               spin_unlock_irq(&lp->lock);
+               spin_unlock_irqrestore(&lp->lock, flags);
                if (net_debug) printk("cs89x0: Tx buffer not free!\n");
                return NETDEV_TX_BUSY;
        }
        /* Write the contents of the packet */
        writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
-       spin_unlock_irq(&lp->lock);
+       spin_unlock_irqrestore(&lp->lock, flags);
        lp->stats.tx_bytes += skb->len;
        dev->trans_start = jiffies;
        dev_kfree_skb (skb);
index efa680f4b8ddceebf8ce166cc3d02409de533a5e..41b648a67fec34d071a5ee681b713e4cada6ee87 100644 (file)
@@ -1897,6 +1897,9 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
 
                        if (ioread8(&nic->csr->scb.status) & rus_no_res)
                                nic->ru_running = RU_SUSPENDED;
+               pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr,
+                                              sizeof(struct rfd),
+                                              PCI_DMA_BIDIRECTIONAL);
                return -ENODATA;
        }
 
index 147c4b088fb3c3467fa3b9027aa887067ccf8114..e8d46cc1bec2525ac014a727f7743dd77c108848 100644 (file)
@@ -3080,7 +3080,9 @@ static const struct net_device_ops ehea_netdev_ops = {
        .ndo_poll_controller    = ehea_netpoll,
 #endif
        .ndo_get_stats          = ehea_get_stats,
+       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = ehea_set_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_multicast_list = ehea_set_multicast_list,
        .ndo_change_mtu         = ehea_change_mtu,
        .ndo_vlan_rx_register   = ehea_vlan_rx_register,
index 0f19b743749bdf8b52783793276c36a247f3f928..d4b98074b1b787e481c3d13f6dd351494245ac11 100644 (file)
@@ -1642,6 +1642,7 @@ static const struct net_device_ops fec_netdev_ops = {
        .ndo_stop               = fec_enet_close,
        .ndo_start_xmit         = fec_enet_start_xmit,
        .ndo_set_multicast_list = set_multicast_list,
+       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_tx_timeout         = fec_timeout,
        .ndo_set_mac_address    = fec_set_mac_address,
index 4ae1d259fced7d6525a6818a1c641db5d1cf3850..43d813ed9f45f17af2ed57cf2d61c6d2fafddd6a 100644 (file)
@@ -156,6 +156,8 @@ static const struct net_device_ops gfar_netdev_ops = {
        .ndo_tx_timeout = gfar_timeout,
        .ndo_do_ioctl = gfar_ioctl,
        .ndo_vlan_rx_register = gfar_vlan_rx_register,
+       .ndo_set_mac_address = eth_mac_addr,
+       .ndo_validate_addr = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = gfar_netpoll,
 #endif
index 155160052c8bd5dc690c1bfe04b253654e739cab..981ab530e9aca771028a1a4f636a514fb19bf18c 100644 (file)
@@ -3,7 +3,7 @@
  *             devices like TTY. It interfaces between a raw TTY and the
  *             kernel's AX.25 protocol layers.
  *
- * Authors:    Andreas Könsgen <ajk@iehk.rwth-aachen.de>
+ * Authors:    Andreas Könsgen <ajk@comnets.uni-bremen.de>
  *              Ralf Baechle DL5RB <ralf@linux-mips.org>
  *
  * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by
index 1d5379de6900f5558e8130b0e4c84b5e3e85f818..8d76cb89dbd61e6d252ed30fbe1bf211f5081732 100644 (file)
@@ -188,11 +188,12 @@ void rgmii_put_mdio(struct of_device *ofdev, int input)
 void rgmii_detach(struct of_device *ofdev, int input)
 {
        struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
-       struct rgmii_regs __iomem *p = dev->base;
-
-       mutex_lock(&dev->lock);
+       struct rgmii_regs __iomem *p;
 
        BUG_ON(!dev || dev->users == 0);
+       p = dev->base;
+
+       mutex_lock(&dev->lock);
 
        RGMII_DBG(dev, "detach(%d)" NL, input);
 
index be480292aba18f998baf33100a436736e72df1e1..adb09d32625df3c2b4a565324f17927ed2db033d 100644 (file)
@@ -127,14 +127,48 @@ static void igb_restore_vlan(struct igb_adapter *);
 static void igb_ping_all_vfs(struct igb_adapter *);
 static void igb_msg_task(struct igb_adapter *);
 static int igb_rcv_msg_from_vf(struct igb_adapter *, u32);
-static inline void igb_set_rah_pool(struct e1000_hw *, int , int);
 static void igb_set_mc_list_pools(struct igb_adapter *, int, u16);
 static void igb_vmm_control(struct igb_adapter *);
-static inline void igb_set_vmolr(struct e1000_hw *, int);
-static inline int igb_set_vf_rlpml(struct igb_adapter *, int, int);
 static int igb_set_vf_mac(struct igb_adapter *adapter, int, unsigned char *);
 static void igb_restore_vf_multicasts(struct igb_adapter *adapter);
 
+static inline void igb_set_vmolr(struct e1000_hw *hw, int vfn)
+{
+       u32 reg_data;
+
+       reg_data = rd32(E1000_VMOLR(vfn));
+       reg_data |= E1000_VMOLR_BAM |    /* Accept broadcast */
+                   E1000_VMOLR_ROPE |   /* Accept packets matched in UTA */
+                   E1000_VMOLR_ROMPE |  /* Accept packets matched in MTA */
+                   E1000_VMOLR_AUPE |   /* Accept untagged packets */
+                   E1000_VMOLR_STRVLAN; /* Strip vlan tags */
+       wr32(E1000_VMOLR(vfn), reg_data);
+}
+
+static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
+                                 int vfn)
+{
+       struct e1000_hw *hw = &adapter->hw;
+       u32 vmolr;
+
+       vmolr = rd32(E1000_VMOLR(vfn));
+       vmolr &= ~E1000_VMOLR_RLPML_MASK;
+       vmolr |= size | E1000_VMOLR_LPE;
+       wr32(E1000_VMOLR(vfn), vmolr);
+
+       return 0;
+}
+
+static inline void igb_set_rah_pool(struct e1000_hw *hw, int pool, int entry)
+{
+       u32 reg_data;
+
+       reg_data = rd32(E1000_RAH(entry));
+       reg_data &= ~E1000_RAH_POOL_MASK;
+       reg_data |= E1000_RAH_POOL_1 << pool;;
+       wr32(E1000_RAH(entry), reg_data);
+}
+
 #ifdef CONFIG_PM
 static int igb_suspend(struct pci_dev *, pm_message_t);
 static int igb_resume(struct pci_dev *);
@@ -5418,43 +5452,6 @@ static void igb_io_resume(struct pci_dev *pdev)
        igb_get_hw_control(adapter);
 }
 
-static inline void igb_set_vmolr(struct e1000_hw *hw, int vfn)
-{
-       u32 reg_data;
-
-       reg_data = rd32(E1000_VMOLR(vfn));
-       reg_data |= E1000_VMOLR_BAM |    /* Accept broadcast */
-                   E1000_VMOLR_ROPE |   /* Accept packets matched in UTA */
-                   E1000_VMOLR_ROMPE |  /* Accept packets matched in MTA */
-                   E1000_VMOLR_AUPE |   /* Accept untagged packets */
-                   E1000_VMOLR_STRVLAN; /* Strip vlan tags */
-       wr32(E1000_VMOLR(vfn), reg_data);
-}
-
-static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
-                                 int vfn)
-{
-       struct e1000_hw *hw = &adapter->hw;
-       u32 vmolr;
-
-       vmolr = rd32(E1000_VMOLR(vfn));
-       vmolr &= ~E1000_VMOLR_RLPML_MASK;
-       vmolr |= size | E1000_VMOLR_LPE;
-       wr32(E1000_VMOLR(vfn), vmolr);
-
-       return 0;
-}
-
-static inline void igb_set_rah_pool(struct e1000_hw *hw, int pool, int entry)
-{
-       u32 reg_data;
-
-       reg_data = rd32(E1000_RAH(entry));
-       reg_data &= ~E1000_RAH_POOL_MASK;
-       reg_data |= E1000_RAH_POOL_1 << pool;;
-       wr32(E1000_RAH(entry), reg_data);
-}
-
 static void igb_set_mc_list_pools(struct igb_adapter *adapter,
                                  int entry_count, u16 total_rar_filters)
 {
index 73585fd8f29fdaee4a4647e6cdebe986c396e5ff..d12377b843581c1947fd1bdb33b9e9fe6d6ca4e4 100644 (file)
@@ -430,7 +430,8 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
         * hardware interrupt handler.  Queue flow control is
         * thus managed under this lock as well.
         */
-       spin_lock_irq(&np->lock);
+       unsigned long flags;
+       spin_lock_irqsave(&np->lock, flags);
 
        add_to_tx_ring(np, skb, length);
        dev->trans_start = jiffies;
@@ -446,7 +447,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
         * is when the transmit statistics are updated.
         */
 
-       spin_unlock_irq(&np->lock);
+       spin_unlock_irqrestore(&np->lock, flags);
 #else
        /* This is the case for older hardware which takes
         * a single transmit buffer at a time, and it is
index 7c5978ad929adc43424b4c1b475c2ef54c25ded9..da2c8514b8d07c856a69e798d9971e7df650c588 100644 (file)
@@ -106,8 +106,6 @@ static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
-       DPRINTK(DRV, INFO, "Get DCB Admin Mode.\n");
-
        return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED);
 }
 
@@ -116,8 +114,6 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
        u8 err = 0;
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
-       DPRINTK(DRV, INFO, "Set DCB Admin Mode.\n");
-
        if (state > 0) {
                /* Turn on DCB */
                if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
@@ -175,6 +171,8 @@ static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev,
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
        int i, j;
 
+       memset(perm_addr, 0xff, MAX_ADDR_LEN);
+
        for (i = 0; i < netdev->addr_len; i++)
                perm_addr[i] = adapter->hw.mac.perm_addr[i];
 
index d12106b47bf2a6cbd9130c9f5840a4322108f5d2..2f286091394d3241bc0bff2cef271ee79c141c00 100644 (file)
@@ -229,6 +229,7 @@ static int __init jazz_sonic_probe(struct platform_device *pdev)
        lp = netdev_priv(dev);
        lp->device = &pdev->dev;
        SET_NETDEV_DEV(dev, &pdev->dev);
+       platform_set_drvdata(pdev, dev);
 
        netdev_boot_setup_check(dev);
 
diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c
new file mode 100644 (file)
index 0000000..9a1dea6
--- /dev/null
@@ -0,0 +1,1322 @@
+/* drivers/net/ks8651.c
+ *
+ * Copyright 2009 Simtec Electronics
+ *     http://www.simtec.co.uk/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define DEBUG
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/cache.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+
+#include <linux/spi/spi.h>
+
+#include "ks8851.h"
+
+/**
+ * struct ks8851_rxctrl - KS8851 driver rx control
+ * @mchash: Multicast hash-table data.
+ * @rxcr1: KS_RXCR1 register setting
+ * @rxcr2: KS_RXCR2 register setting
+ *
+ * Representation of the settings needs to control the receive filtering
+ * such as the multicast hash-filter and the receive register settings. This
+ * is used to make the job of working out if the receive settings change and
+ * then issuing the new settings to the worker that will send the necessary
+ * commands.
+ */
+struct ks8851_rxctrl {
+       u16     mchash[4];
+       u16     rxcr1;
+       u16     rxcr2;
+};
+
+/**
+ * union ks8851_tx_hdr - tx header data
+ * @txb: The header as bytes
+ * @txw: The header as 16bit, little-endian words
+ *
+ * A dual representation of the tx header data to allow
+ * access to individual bytes, and to allow 16bit accesses
+ * with 16bit alignment.
+ */
+union ks8851_tx_hdr {
+       u8      txb[6];
+       __le16  txw[3];
+};
+
+/**
+ * struct ks8851_net - KS8851 driver private data
+ * @netdev: The network device we're bound to
+ * @spidev: The spi device we're bound to.
+ * @lock: Lock to ensure that the device is not accessed when busy.
+ * @statelock: Lock on this structure for tx list.
+ * @mii: The MII state information for the mii calls.
+ * @rxctrl: RX settings for @rxctrl_work.
+ * @tx_work: Work queue for tx packets
+ * @irq_work: Work queue for servicing interrupts
+ * @rxctrl_work: Work queue for updating RX mode and multicast lists
+ * @txq: Queue of packets for transmission.
+ * @spi_msg1: pre-setup SPI transfer with one message, @spi_xfer1.
+ * @spi_msg2: pre-setup SPI transfer with two messages, @spi_xfer2.
+ * @txh: Space for generating packet TX header in DMA-able data
+ * @rxd: Space for receiving SPI data, in DMA-able space.
+ * @txd: Space for transmitting SPI data, in DMA-able space.
+ * @msg_enable: The message flags controlling driver output (see ethtool).
+ * @fid: Incrementing frame id tag.
+ * @rc_ier: Cached copy of KS_IER.
+ * @rc_rxqcr: Cached copy of KS_RXQCR.
+ *
+ * The @lock ensures that the chip is protected when certain operations are
+ * in progress. When the read or write packet transfer is in progress, most
+ * of the chip registers are not ccessible until the transfer is finished and
+ * the DMA has been de-asserted.
+ *
+ * The @statelock is used to protect information in the structure which may
+ * need to be accessed via several sources, such as the network driver layer
+ * or one of the work queues.
+ *
+ * We align the buffers we may use for rx/tx to ensure that if the SPI driver
+ * wants to DMA map them, it will not have any problems with data the driver
+ * modifies.
+ */
+struct ks8851_net {
+       struct net_device       *netdev;
+       struct spi_device       *spidev;
+       struct mutex            lock;
+       spinlock_t              statelock;
+
+       union ks8851_tx_hdr     txh ____cacheline_aligned;
+       u8                      rxd[8];
+       u8                      txd[8];
+
+       u32                     msg_enable ____cacheline_aligned;
+       u16                     tx_space;
+       u8                      fid;
+
+       u16                     rc_ier;
+       u16                     rc_rxqcr;
+
+       struct mii_if_info      mii;
+       struct ks8851_rxctrl    rxctrl;
+
+       struct work_struct      tx_work;
+       struct work_struct      irq_work;
+       struct work_struct      rxctrl_work;
+
+       struct sk_buff_head     txq;
+
+       struct spi_message      spi_msg1;
+       struct spi_message      spi_msg2;
+       struct spi_transfer     spi_xfer1;
+       struct spi_transfer     spi_xfer2[2];
+};
+
+static int msg_enable;
+
+#define ks_info(_ks, _msg...) dev_info(&(_ks)->spidev->dev, _msg)
+#define ks_warn(_ks, _msg...) dev_warn(&(_ks)->spidev->dev, _msg)
+#define ks_dbg(_ks, _msg...) dev_dbg(&(_ks)->spidev->dev, _msg)
+#define ks_err(_ks, _msg...) dev_err(&(_ks)->spidev->dev, _msg)
+
+/* shift for byte-enable data */
+#define BYTE_EN(_x)    ((_x) << 2)
+
+/* turn register number and byte-enable mask into data for start of packet */
+#define MK_OP(_byteen, _reg) (BYTE_EN(_byteen) | (_reg)  << (8+2) | (_reg) >> 6)
+
+/* SPI register read/write calls.
+ *
+ * All these calls issue SPI transactions to access the chip's registers. They
+ * all require that the necessary lock is held to prevent accesses when the
+ * chip is busy transfering packet data (RX/TX FIFO accesses).
+ */
+
+/**
+ * ks8851_wrreg16 - write 16bit register value to chip
+ * @ks: The chip state
+ * @reg: The register address
+ * @val: The value to write
+ *
+ * Issue a write to put the value @val into the register specified in @reg.
+ */
+static void ks8851_wrreg16(struct ks8851_net *ks, unsigned reg, unsigned val)
+{
+       struct spi_transfer *xfer = &ks->spi_xfer1;
+       struct spi_message *msg = &ks->spi_msg1;
+       __le16 txb[2];
+       int ret;
+
+       txb[0] = cpu_to_le16(MK_OP(reg & 2 ? 0xC : 0x03, reg) | KS_SPIOP_WR);
+       txb[1] = cpu_to_le16(val);
+
+       xfer->tx_buf = txb;
+       xfer->rx_buf = NULL;
+       xfer->len = 4;
+
+       ret = spi_sync(ks->spidev, msg);
+       if (ret < 0)
+               ks_err(ks, "spi_sync() failed\n");
+}
+
+/**
+ * ks8851_rx_1msg - select whether to use one or two messages for spi read
+ * @ks: The device structure
+ *
+ * Return whether to generate a single message with a tx and rx buffer
+ * supplied to spi_sync(), or alternatively send the tx and rx buffers
+ * as separate messages.
+ *
+ * Depending on the hardware in use, a single message may be more efficient
+ * on interrupts or work done by the driver.
+ *
+ * This currently always returns true until we add some per-device data passed
+ * from the platform code to specify which mode is better.
+ */
+static inline bool ks8851_rx_1msg(struct ks8851_net *ks)
+{
+       return true;
+}
+
+/**
+ * ks8851_rdreg - issue read register command and return the data
+ * @ks: The device state
+ * @op: The register address and byte enables in message format.
+ * @rxb: The RX buffer to return the result into
+ * @rxl: The length of data expected.
+ *
+ * This is the low level read call that issues the necessary spi message(s)
+ * to read data from the register specified in @op.
+ */
+static void ks8851_rdreg(struct ks8851_net *ks, unsigned op,
+                        u8 *rxb, unsigned rxl)
+{
+       struct spi_transfer *xfer;
+       struct spi_message *msg;
+       __le16 *txb = (__le16 *)ks->txd;
+       u8 *trx = ks->rxd;
+       int ret;
+
+       txb[0] = cpu_to_le16(op | KS_SPIOP_RD);
+
+       if (ks8851_rx_1msg(ks)) {
+               msg = &ks->spi_msg1;
+               xfer = &ks->spi_xfer1;
+
+               xfer->tx_buf = txb;
+               xfer->rx_buf = trx;
+               xfer->len = rxl + 2;
+       } else {
+               msg = &ks->spi_msg2;
+               xfer = ks->spi_xfer2;
+
+               xfer->tx_buf = txb;
+               xfer->rx_buf = NULL;
+               xfer->len = 2;
+
+               xfer++;
+               xfer->tx_buf = NULL;
+               xfer->rx_buf = trx;
+               xfer->len = rxl;
+       }
+
+       ret = spi_sync(ks->spidev, msg);
+       if (ret < 0)
+               ks_err(ks, "read: spi_sync() failed\n");
+       else if (ks8851_rx_1msg(ks))
+               memcpy(rxb, trx + 2, rxl);
+       else
+               memcpy(rxb, trx, rxl);
+}
+
+/**
+ * ks8851_rdreg8 - read 8 bit register from device
+ * @ks: The chip information
+ * @reg: The register address
+ *
+ * Read a 8bit register from the chip, returning the result
+*/
+static unsigned ks8851_rdreg8(struct ks8851_net *ks, unsigned reg)
+{
+       u8 rxb[1];
+
+       ks8851_rdreg(ks, MK_OP(1 << (reg & 3), reg), rxb, 1);
+       return rxb[0];
+}
+
+/**
+ * ks8851_rdreg16 - read 16 bit register from device
+ * @ks: The chip information
+ * @reg: The register address
+ *
+ * Read a 16bit register from the chip, returning the result
+*/
+static unsigned ks8851_rdreg16(struct ks8851_net *ks, unsigned reg)
+{
+       __le16 rx = 0;
+
+       ks8851_rdreg(ks, MK_OP(reg & 2 ? 0xC : 0x3, reg), (u8 *)&rx, 2);
+       return le16_to_cpu(rx);
+}
+
+/**
+ * ks8851_rdreg32 - read 32 bit register from device
+ * @ks: The chip information
+ * @reg: The register address
+ *
+ * Read a 32bit register from the chip.
+ *
+ * Note, this read requires the address be aligned to 4 bytes.
+*/
+static unsigned ks8851_rdreg32(struct ks8851_net *ks, unsigned reg)
+{
+       __le32 rx = 0;
+
+       WARN_ON(reg & 3);
+
+       ks8851_rdreg(ks, MK_OP(0xf, reg), (u8 *)&rx, 4);
+       return le32_to_cpu(rx);
+}
+
+/**
+ * ks8851_soft_reset - issue one of the soft reset to the device
+ * @ks: The device state.
+ * @op: The bit(s) to set in the GRR
+ *
+ * Issue the relevant soft-reset command to the device's GRR register
+ * specified by @op.
+ *
+ * Note, the delays are in there as a caution to ensure that the reset
+ * has time to take effect and then complete. Since the datasheet does
+ * not currently specify the exact sequence, we have chosen something
+ * that seems to work with our device.
+ */
+static void ks8851_soft_reset(struct ks8851_net *ks, unsigned op)
+{
+       ks8851_wrreg16(ks, KS_GRR, op);
+       mdelay(1);      /* wait a short time to effect reset */
+       ks8851_wrreg16(ks, KS_GRR, 0);
+       mdelay(1);      /* wait for condition to clear */
+}
+
+/**
+ * ks8851_write_mac_addr - write mac address to device registers
+ * @dev: The network device
+ *
+ * Update the KS8851 MAC address registers from the address in @dev.
+ *
+ * This call assumes that the chip is not running, so there is no need to
+ * shutdown the RXQ process whilst setting this.
+*/
+static int ks8851_write_mac_addr(struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       u16 *mcp = (u16 *)dev->dev_addr;
+
+       mutex_lock(&ks->lock);
+
+       ks8851_wrreg16(ks, KS_MARL, mcp[0]);
+       ks8851_wrreg16(ks, KS_MARM, mcp[1]);
+       ks8851_wrreg16(ks, KS_MARH, mcp[2]);
+
+       mutex_unlock(&ks->lock);
+
+       return 0;
+}
+
+/**
+ * ks8851_init_mac - initialise the mac address
+ * @ks: The device structure
+ *
+ * Get or create the initial mac address for the device and then set that
+ * into the station address register. Currently we assume that the device
+ * does not have a valid mac address in it, and so we use random_ether_addr()
+ * to create a new one.
+ *
+ * In future, the driver should check to see if the device has an EEPROM
+ * attached and whether that has a valid ethernet address in it.
+ */
+static void ks8851_init_mac(struct ks8851_net *ks)
+{
+       struct net_device *dev = ks->netdev;
+
+       random_ether_addr(dev->dev_addr);
+       ks8851_write_mac_addr(dev);
+}
+
+/**
+ * ks8851_irq - device interrupt handler
+ * @irq: Interrupt number passed from the IRQ hnalder.
+ * @pw: The private word passed to register_irq(), our struct ks8851_net.
+ *
+ * Disable the interrupt from happening again until we've processed the
+ * current status by scheduling ks8851_irq_work().
+ */
+static irqreturn_t ks8851_irq(int irq, void *pw)
+{
+       struct ks8851_net *ks = pw;
+
+       disable_irq_nosync(irq);
+       schedule_work(&ks->irq_work);
+       return IRQ_HANDLED;
+}
+
+/**
+ * ks8851_rdfifo - read data from the receive fifo
+ * @ks: The device state.
+ * @buff: The buffer address
+ * @len: The length of the data to read
+ *
+ * Issue an RXQ FIFO read command and read the @len ammount of data from
+ * the FIFO into the buffer specified by @buff.
+ */
+static void ks8851_rdfifo(struct ks8851_net *ks, u8 *buff, unsigned len)
+{
+       struct spi_transfer *xfer = ks->spi_xfer2;
+       struct spi_message *msg = &ks->spi_msg2;
+       u8 txb[1];
+       int ret;
+
+       if (netif_msg_rx_status(ks))
+               ks_dbg(ks, "%s: %d@%p\n", __func__, len, buff);
+
+       /* set the operation we're issuing */
+       txb[0] = KS_SPIOP_RXFIFO;
+
+       xfer->tx_buf = txb;
+       xfer->rx_buf = NULL;
+       xfer->len = 1;
+
+       xfer++;
+       xfer->rx_buf = buff;
+       xfer->tx_buf = NULL;
+       xfer->len = len;
+
+       ret = spi_sync(ks->spidev, msg);
+       if (ret < 0)
+               ks_err(ks, "%s: spi_sync() failed\n", __func__);
+}
+
+/**
+ * ks8851_dbg_dumpkkt - dump initial packet contents to debug
+ * @ks: The device state
+ * @rxpkt: The data for the received packet
+ *
+ * Dump the initial data from the packet to dev_dbg().
+*/
+static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt)
+{
+       ks_dbg(ks, "pkt %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n",
+              rxpkt[4], rxpkt[5], rxpkt[6], rxpkt[7],
+              rxpkt[8], rxpkt[9], rxpkt[10], rxpkt[11],
+              rxpkt[12], rxpkt[13], rxpkt[14], rxpkt[15]);
+}
+
+/**
+ * ks8851_rx_pkts - receive packets from the host
+ * @ks: The device information.
+ *
+ * This is called from the IRQ work queue when the system detects that there
+ * are packets in the receive queue. Find out how many packets there are and
+ * read them from the FIFO.
+ */
+static void ks8851_rx_pkts(struct ks8851_net *ks)
+{
+       struct sk_buff *skb;
+       unsigned rxfc;
+       unsigned rxlen;
+       unsigned rxstat;
+       u32 rxh;
+       u8 *rxpkt;
+
+       rxfc = ks8851_rdreg8(ks, KS_RXFC);
+
+       if (netif_msg_rx_status(ks))
+               ks_dbg(ks, "%s: %d packets\n", __func__, rxfc);
+
+       /* Currently we're issuing a read per packet, but we could possibly
+        * improve the code by issuing a single read, getting the receive
+        * header, allocating the packet and then reading the packet data
+        * out in one go.
+        *
+        * This form of operation would require us to hold the SPI bus'
+        * chipselect low during the entie transaction to avoid any
+        * reset to the data stream comming from the chip.
+        */
+
+       for (; rxfc != 0; rxfc--) {
+               rxh = ks8851_rdreg32(ks, KS_RXFHSR);
+               rxstat = rxh & 0xffff;
+               rxlen = rxh >> 16;
+
+               if (netif_msg_rx_status(ks))
+                       ks_dbg(ks, "rx: stat 0x%04x, len 0x%04x\n",
+                               rxstat, rxlen);
+
+               /* the length of the packet includes the 32bit CRC */
+
+               /* set dma read address */
+               ks8851_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI | 0x00);
+
+               /* start the packet dma process, and set auto-dequeue rx */
+               ks8851_wrreg16(ks, KS_RXQCR,
+                              ks->rc_rxqcr | RXQCR_SDA | RXQCR_ADRFE);
+
+               if (rxlen > 0) {
+                       skb = netdev_alloc_skb(ks->netdev, rxlen + 2 + 8);
+                       if (!skb) {
+                               /* todo - dump frame and move on */
+                       }
+
+                       /* two bytes to ensure ip is aligned, and four bytes
+                        * for the status header and 4 bytes of garbage */
+                       skb_reserve(skb, 2 + 4 + 4);
+
+                       rxpkt = skb_put(skb, rxlen - 4) - 8;
+
+                       /* align the packet length to 4 bytes, and add 4 bytes
+                        * as we're getting the rx status header as well */
+                       ks8851_rdfifo(ks, rxpkt, ALIGN(rxlen, 4) + 8);
+
+                       if (netif_msg_pktdata(ks))
+                               ks8851_dbg_dumpkkt(ks, rxpkt);
+
+                       skb->protocol = eth_type_trans(skb, ks->netdev);
+                       netif_rx(skb);
+
+                       ks->netdev->stats.rx_packets++;
+                       ks->netdev->stats.rx_bytes += rxlen - 4;
+               }
+
+               ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
+       }
+}
+
+/**
+ * ks8851_irq_work - work queue handler for dealing with interrupt requests
+ * @work: The work structure that was scheduled by schedule_work()
+ *
+ * This is the handler invoked when the ks8851_irq() is called to find out
+ * what happened, as we cannot allow ourselves to sleep whilst waiting for
+ * anything other process has the chip's lock.
+ *
+ * Read the interrupt status, work out what needs to be done and then clear
+ * any of the interrupts that are not needed.
+ */
+static void ks8851_irq_work(struct work_struct *work)
+{
+       struct ks8851_net *ks = container_of(work, struct ks8851_net, irq_work);
+       unsigned status;
+       unsigned handled = 0;
+
+       mutex_lock(&ks->lock);
+
+       status = ks8851_rdreg16(ks, KS_ISR);
+
+       if (netif_msg_intr(ks))
+               dev_dbg(&ks->spidev->dev, "%s: status 0x%04x\n",
+                       __func__, status);
+
+       if (status & IRQ_LCI) {
+               /* should do something about checking link status */
+               handled |= IRQ_LCI;
+       }
+
+       if (status & IRQ_LDI) {
+               u16 pmecr = ks8851_rdreg16(ks, KS_PMECR);
+               pmecr &= ~PMECR_WKEVT_MASK;
+               ks8851_wrreg16(ks, KS_PMECR, pmecr | PMECR_WKEVT_LINK);
+
+               handled |= IRQ_LDI;
+       }
+
+       if (status & IRQ_RXPSI)
+               handled |= IRQ_RXPSI;
+
+       if (status & IRQ_TXI) {
+               handled |= IRQ_TXI;
+
+               /* no lock here, tx queue should have been stopped */
+
+               /* update our idea of how much tx space is available to the
+                * system */
+               ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR);
+
+               if (netif_msg_intr(ks))
+                       ks_dbg(ks, "%s: txspace %d\n", __func__, ks->tx_space);
+       }
+
+       if (status & IRQ_RXI)
+               handled |= IRQ_RXI;
+
+       if (status & IRQ_SPIBEI) {
+               dev_err(&ks->spidev->dev, "%s: spi bus error\n", __func__);
+               handled |= IRQ_SPIBEI;
+       }
+
+       ks8851_wrreg16(ks, KS_ISR, handled);
+
+       if (status & IRQ_RXI) {
+               /* the datasheet says to disable the rx interrupt during
+                * packet read-out, however we're masking the interrupt
+                * from the device so do not bother masking just the RX
+                * from the device. */
+
+               ks8851_rx_pkts(ks);
+       }
+
+       /* if something stopped the rx process, probably due to wanting
+        * to change the rx settings, then do something about restarting
+        * it. */
+       if (status & IRQ_RXPSI) {
+               struct ks8851_rxctrl *rxc = &ks->rxctrl;
+
+               /* update the multicast hash table */
+               ks8851_wrreg16(ks, KS_MAHTR0, rxc->mchash[0]);
+               ks8851_wrreg16(ks, KS_MAHTR1, rxc->mchash[1]);
+               ks8851_wrreg16(ks, KS_MAHTR2, rxc->mchash[2]);
+               ks8851_wrreg16(ks, KS_MAHTR3, rxc->mchash[3]);
+
+               ks8851_wrreg16(ks, KS_RXCR2, rxc->rxcr2);
+               ks8851_wrreg16(ks, KS_RXCR1, rxc->rxcr1);
+       }
+
+       mutex_unlock(&ks->lock);
+
+       if (status & IRQ_TXI)
+               netif_wake_queue(ks->netdev);
+
+       enable_irq(ks->netdev->irq);
+}
+
+/**
+ * calc_txlen - calculate size of message to send packet
+ * @len: Lenght of data
+ *
+ * Returns the size of the TXFIFO message needed to send
+ * this packet.
+ */
+static inline unsigned calc_txlen(unsigned len)
+{
+       return ALIGN(len + 4, 4);
+}
+
+/**
+ * ks8851_wrpkt - write packet to TX FIFO
+ * @ks: The device state.
+ * @txp: The sk_buff to transmit.
+ * @irq: IRQ on completion of the packet.
+ *
+ * Send the @txp to the chip. This means creating the relevant packet header
+ * specifying the length of the packet and the other information the chip
+ * needs, such as IRQ on completion. Send the header and the packet data to
+ * the device.
+ */
+static void ks8851_wrpkt(struct ks8851_net *ks, struct sk_buff *txp, bool irq)
+{
+       struct spi_transfer *xfer = ks->spi_xfer2;
+       struct spi_message *msg = &ks->spi_msg2;
+       unsigned fid = 0;
+       int ret;
+
+       if (netif_msg_tx_queued(ks))
+               dev_dbg(&ks->spidev->dev, "%s: skb %p, %d@%p, irq %d\n",
+                       __func__, txp, txp->len, txp->data, irq);
+
+       fid = ks->fid++;
+       fid &= TXFR_TXFID_MASK;
+
+       if (irq)
+               fid |= TXFR_TXIC;       /* irq on completion */
+
+       /* start header at txb[1] to align txw entries */
+       ks->txh.txb[1] = KS_SPIOP_TXFIFO;
+       ks->txh.txw[1] = cpu_to_le16(fid);
+       ks->txh.txw[2] = cpu_to_le16(txp->len);
+
+       xfer->tx_buf = &ks->txh.txb[1];
+       xfer->rx_buf = NULL;
+       xfer->len = 5;
+
+       xfer++;
+       xfer->tx_buf = txp->data;
+       xfer->rx_buf = NULL;
+       xfer->len = ALIGN(txp->len, 4);
+
+       ret = spi_sync(ks->spidev, msg);
+       if (ret < 0)
+               ks_err(ks, "%s: spi_sync() failed\n", __func__);
+}
+
+/**
+ * ks8851_done_tx - update and then free skbuff after transmitting
+ * @ks: The device state
+ * @txb: The buffer transmitted
+ */
+static void ks8851_done_tx(struct ks8851_net *ks, struct sk_buff *txb)
+{
+       struct net_device *dev = ks->netdev;
+
+       dev->stats.tx_bytes += txb->len;
+       dev->stats.tx_packets++;
+
+       dev_kfree_skb(txb);
+}
+
+/**
+ * ks8851_tx_work - process tx packet(s)
+ * @work: The work strucutre what was scheduled.
+ *
+ * This is called when a number of packets have been scheduled for
+ * transmission and need to be sent to the device.
+ */
+static void ks8851_tx_work(struct work_struct *work)
+{
+       struct ks8851_net *ks = container_of(work, struct ks8851_net, tx_work);
+       struct sk_buff *txb;
+       bool last = false;
+
+       mutex_lock(&ks->lock);
+
+       while (!last) {
+               txb = skb_dequeue(&ks->txq);
+               last = skb_queue_empty(&ks->txq);
+
+               ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA);
+               ks8851_wrpkt(ks, txb, last);
+               ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
+               ks8851_wrreg16(ks, KS_TXQCR, TXQCR_METFE);
+
+               ks8851_done_tx(ks, txb);
+       }
+
+       mutex_unlock(&ks->lock);
+}
+
+/**
+ * ks8851_set_powermode - set power mode of the device
+ * @ks: The device state
+ * @pwrmode: The power mode value to write to KS_PMECR.
+ *
+ * Change the power mode of the chip.
+ */
+static void ks8851_set_powermode(struct ks8851_net *ks, unsigned pwrmode)
+{
+       unsigned pmecr;
+
+       if (netif_msg_hw(ks))
+               ks_dbg(ks, "setting power mode %d\n", pwrmode);
+
+       pmecr = ks8851_rdreg16(ks, KS_PMECR);
+       pmecr &= ~PMECR_PM_MASK;
+       pmecr |= pwrmode;
+
+       ks8851_wrreg16(ks, KS_PMECR, pmecr);
+}
+
+/**
+ * ks8851_net_open - open network device
+ * @dev: The network device being opened.
+ *
+ * Called when the network device is marked active, such as a user executing
+ * 'ifconfig up' on the device.
+ */
+static int ks8851_net_open(struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+
+       /* lock the card, even if we may not actually be doing anything
+        * else at the moment */
+       mutex_lock(&ks->lock);
+
+       if (netif_msg_ifup(ks))
+               ks_dbg(ks, "opening %s\n", dev->name);
+
+       /* bring chip out of any power saving mode it was in */
+       ks8851_set_powermode(ks, PMECR_PM_NORMAL);
+
+       /* issue a soft reset to the RX/TX QMU to put it into a known
+        * state. */
+       ks8851_soft_reset(ks, GRR_QMU);
+
+       /* setup transmission parameters */
+
+       ks8851_wrreg16(ks, KS_TXCR, (TXCR_TXE | /* enable transmit process */
+                                    TXCR_TXPE | /* pad to min length */
+                                    TXCR_TXCRC | /* add CRC */
+                                    TXCR_TXFCE)); /* enable flow control */
+
+       /* auto-increment tx data, reset tx pointer */
+       ks8851_wrreg16(ks, KS_TXFDPR, TXFDPR_TXFPAI);
+
+       /* setup receiver control */
+
+       ks8851_wrreg16(ks, KS_RXCR1, (RXCR1_RXPAFMA | /*  from mac filter */
+                                     RXCR1_RXFCE | /* enable flow control */
+                                     RXCR1_RXBE | /* broadcast enable */
+                                     RXCR1_RXUE | /* unicast enable */
+                                     RXCR1_RXE)); /* enable rx block */
+
+       /* transfer entire frames out in one go */
+       ks8851_wrreg16(ks, KS_RXCR2, RXCR2_SRDBL_FRAME);
+
+       /* set receive counter timeouts */
+       ks8851_wrreg16(ks, KS_RXDTTR, 1000); /* 1ms after first frame to IRQ */
+       ks8851_wrreg16(ks, KS_RXDBCTR, 4096); /* >4Kbytes in buffer to IRQ */
+       ks8851_wrreg16(ks, KS_RXFCTR, 10);  /* 10 frames to IRQ */
+
+       ks->rc_rxqcr = (RXQCR_RXFCTE |  /* IRQ on frame count exceeded */
+                       RXQCR_RXDBCTE | /* IRQ on byte count exceeded */
+                       RXQCR_RXDTTE);  /* IRQ on time exceeded */
+
+       ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
+
+       /* clear then enable interrupts */
+
+#define STD_IRQ (IRQ_LCI |     /* Link Change */       \
+                IRQ_TXI |      /* TX done */           \
+                IRQ_RXI |      /* RX done */           \
+                IRQ_SPIBEI |   /* SPI bus error */     \
+                IRQ_TXPSI |    /* TX process stop */   \
+                IRQ_RXPSI)     /* RX process stop */
+
+       ks->rc_ier = STD_IRQ;
+       ks8851_wrreg16(ks, KS_ISR, STD_IRQ);
+       ks8851_wrreg16(ks, KS_IER, STD_IRQ);
+
+       netif_start_queue(ks->netdev);
+
+       if (netif_msg_ifup(ks))
+               ks_dbg(ks, "network device %s up\n", dev->name);
+
+       mutex_unlock(&ks->lock);
+       return 0;
+}
+
+/**
+ * ks8851_net_stop - close network device
+ * @dev: The device being closed.
+ *
+ * Called to close down a network device which has been active. Cancell any
+ * work, shutdown the RX and TX process and then place the chip into a low
+ * power state whilst it is not being used.
+ */
+static int ks8851_net_stop(struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+
+       if (netif_msg_ifdown(ks))
+               ks_info(ks, "%s: shutting down\n", dev->name);
+
+       netif_stop_queue(dev);
+
+       mutex_lock(&ks->lock);
+
+       /* stop any outstanding work */
+       flush_work(&ks->irq_work);
+       flush_work(&ks->tx_work);
+       flush_work(&ks->rxctrl_work);
+
+       /* turn off the IRQs and ack any outstanding */
+       ks8851_wrreg16(ks, KS_IER, 0x0000);
+       ks8851_wrreg16(ks, KS_ISR, 0xffff);
+
+       /* shutdown RX process */
+       ks8851_wrreg16(ks, KS_RXCR1, 0x0000);
+
+       /* shutdown TX process */
+       ks8851_wrreg16(ks, KS_TXCR, 0x0000);
+
+       /* set powermode to soft power down to save power */
+       ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN);
+
+       /* ensure any queued tx buffers are dumped */
+       while (!skb_queue_empty(&ks->txq)) {
+               struct sk_buff *txb = skb_dequeue(&ks->txq);
+
+               if (netif_msg_ifdown(ks))
+                       ks_dbg(ks, "%s: freeing txb %p\n", __func__, txb);
+
+               dev_kfree_skb(txb);
+       }
+
+       mutex_unlock(&ks->lock);
+       return 0;
+}
+
+/**
+ * ks8851_start_xmit - transmit packet
+ * @skb: The buffer to transmit
+ * @dev: The device used to transmit the packet.
+ *
+ * Called by the network layer to transmit the @skb. Queue the packet for
+ * the device and schedule the necessary work to transmit the packet when
+ * it is free.
+ *
+ * We do this to firstly avoid sleeping with the network device locked,
+ * and secondly so we can round up more than one packet to transmit which
+ * means we can try and avoid generating too many transmit done interrupts.
+ */
+static int ks8851_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       unsigned needed = calc_txlen(skb->len);
+       int ret = NETDEV_TX_OK;
+
+       if (netif_msg_tx_queued(ks))
+               ks_dbg(ks, "%s: skb %p, %d@%p\n", __func__,
+                      skb, skb->len, skb->data);
+
+       spin_lock(&ks->statelock);
+
+       if (needed > ks->tx_space) {
+               netif_stop_queue(dev);
+               ret = NETDEV_TX_BUSY;
+       } else {
+               ks->tx_space -= needed;
+               skb_queue_tail(&ks->txq, skb);
+       }
+
+       spin_unlock(&ks->statelock);
+       schedule_work(&ks->tx_work);
+
+       return ret;
+}
+
+/**
+ * ks8851_rxctrl_work - work handler to change rx mode
+ * @work: The work structure this belongs to.
+ *
+ * Lock the device and issue the necessary changes to the receive mode from
+ * the network device layer. This is done so that we can do this without
+ * having to sleep whilst holding the network device lock.
+ *
+ * Since the recommendation from Micrel is that the RXQ is shutdown whilst the
+ * receive parameters are programmed, we issue a write to disable the RXQ and
+ * then wait for the interrupt handler to be triggered once the RXQ shutdown is
+ * complete. The interrupt handler then writes the new values into the chip.
+ */
+static void ks8851_rxctrl_work(struct work_struct *work)
+{
+       struct ks8851_net *ks = container_of(work, struct ks8851_net, rxctrl_work);
+
+       mutex_lock(&ks->lock);
+
+       /* need to shutdown RXQ before modifying filter parameters */
+       ks8851_wrreg16(ks, KS_RXCR1, 0x00);
+
+       mutex_unlock(&ks->lock);
+}
+
+static void ks8851_set_rx_mode(struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       struct ks8851_rxctrl rxctrl;
+
+       memset(&rxctrl, 0, sizeof(rxctrl));
+
+       if (dev->flags & IFF_PROMISC) {
+               /* interface to receive everything */
+
+               rxctrl.rxcr1 = RXCR1_RXAE | RXCR1_RXINVF;
+       } else if (dev->flags & IFF_ALLMULTI) {
+               /* accept all multicast packets */
+
+               rxctrl.rxcr1 = (RXCR1_RXME | RXCR1_RXAE |
+                               RXCR1_RXPAFMA | RXCR1_RXMAFMA);
+       } else if (dev->flags & IFF_MULTICAST && dev->mc_count > 0) {
+               struct dev_mc_list *mcptr = dev->mc_list;
+               u32 crc;
+               int i;
+
+               /* accept some multicast */
+
+               for (i = dev->mc_count; i > 0; i--) {
+                       crc = ether_crc(ETH_ALEN, mcptr->dmi_addr);
+                       crc >>= (32 - 6);  /* get top six bits */
+
+                       rxctrl.mchash[crc >> 4] |= (1 << (crc & 0xf));
+                       mcptr = mcptr->next;
+               }
+
+               rxctrl.rxcr1 = RXCR1_RXME | RXCR1_RXAE | RXCR1_RXPAFMA;
+       } else {
+               /* just accept broadcast / unicast */
+               rxctrl.rxcr1 = RXCR1_RXPAFMA;
+       }
+
+       rxctrl.rxcr1 |= (RXCR1_RXUE | /* unicast enable */
+                        RXCR1_RXBE | /* broadcast enable */
+                        RXCR1_RXE | /* RX process enable */
+                        RXCR1_RXFCE); /* enable flow control */
+
+       rxctrl.rxcr2 |= RXCR2_SRDBL_FRAME;
+
+       /* schedule work to do the actual set of the data if needed */
+
+       spin_lock(&ks->statelock);
+
+       if (memcmp(&rxctrl, &ks->rxctrl, sizeof(rxctrl)) != 0) {
+               memcpy(&ks->rxctrl, &rxctrl, sizeof(ks->rxctrl));
+               schedule_work(&ks->rxctrl_work);
+       }
+
+       spin_unlock(&ks->statelock);
+}
+
+static int ks8851_set_mac_address(struct net_device *dev, void *addr)
+{
+       struct sockaddr *sa = addr;
+
+       if (netif_running(dev))
+               return -EBUSY;
+
+       if (!is_valid_ether_addr(sa->sa_data))
+               return -EADDRNOTAVAIL;
+
+       memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
+       return ks8851_write_mac_addr(dev);
+}
+
+static int ks8851_net_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+
+       if (!netif_running(dev))
+               return -EINVAL;
+
+       return generic_mii_ioctl(&ks->mii, if_mii(req), cmd, NULL);
+}
+
+static const struct net_device_ops ks8851_netdev_ops = {
+       .ndo_open               = ks8851_net_open,
+       .ndo_stop               = ks8851_net_stop,
+       .ndo_do_ioctl           = ks8851_net_ioctl,
+       .ndo_start_xmit         = ks8851_start_xmit,
+       .ndo_set_mac_address    = ks8851_set_mac_address,
+       .ndo_set_rx_mode        = ks8851_set_rx_mode,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
+/* ethtool support */
+
+static void ks8851_get_drvinfo(struct net_device *dev,
+                              struct ethtool_drvinfo *di)
+{
+       strlcpy(di->driver, "KS8851", sizeof(di->driver));
+       strlcpy(di->version, "1.00", sizeof(di->version));
+       strlcpy(di->bus_info, dev_name(dev->dev.parent), sizeof(di->bus_info));
+}
+
+static u32 ks8851_get_msglevel(struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       return ks->msg_enable;
+}
+
+static void ks8851_set_msglevel(struct net_device *dev, u32 to)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       ks->msg_enable = to;
+}
+
+static int ks8851_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       return mii_ethtool_gset(&ks->mii, cmd);
+}
+
+static int ks8851_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       return mii_ethtool_sset(&ks->mii, cmd);
+}
+
+static u32 ks8851_get_link(struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       return mii_link_ok(&ks->mii);
+}
+
+static int ks8851_nway_reset(struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       return mii_nway_restart(&ks->mii);
+}
+
+static const struct ethtool_ops ks8851_ethtool_ops = {
+       .get_drvinfo    = ks8851_get_drvinfo,
+       .get_msglevel   = ks8851_get_msglevel,
+       .set_msglevel   = ks8851_set_msglevel,
+       .get_settings   = ks8851_get_settings,
+       .set_settings   = ks8851_set_settings,
+       .get_link       = ks8851_get_link,
+       .nway_reset     = ks8851_nway_reset,
+};
+
+/* MII interface controls */
+
+/**
+ * ks8851_phy_reg - convert MII register into a KS8851 register
+ * @reg: MII register number.
+ *
+ * Return the KS8851 register number for the corresponding MII PHY register
+ * if possible. Return zero if the MII register has no direct mapping to the
+ * KS8851 register set.
+ */
+static int ks8851_phy_reg(int reg)
+{
+       switch (reg) {
+       case MII_BMCR:
+               return KS_P1MBCR;
+       case MII_BMSR:
+               return KS_P1MBSR;
+       case MII_PHYSID1:
+               return KS_PHY1ILR;
+       case MII_PHYSID2:
+               return KS_PHY1IHR;
+       case MII_ADVERTISE:
+               return KS_P1ANAR;
+       case MII_LPA:
+               return KS_P1ANLPR;
+       }
+
+       return 0x0;
+}
+
+/**
+ * ks8851_phy_read - MII interface PHY register read.
+ * @dev: The network device the PHY is on.
+ * @phy_addr: Address of PHY (ignored as we only have one)
+ * @reg: The register to read.
+ *
+ * This call reads data from the PHY register specified in @reg. Since the
+ * device does not support all the MII registers, the non-existant values
+ * are always returned as zero.
+ *
+ * We return zero for unsupported registers as the MII code does not check
+ * the value returned for any error status, and simply returns it to the
+ * caller. The mii-tool that the driver was tested with takes any -ve error
+ * as real PHY capabilities, thus displaying incorrect data to the user.
+ */
+static int ks8851_phy_read(struct net_device *dev, int phy_addr, int reg)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       int ksreg;
+       int result;
+
+       ksreg = ks8851_phy_reg(reg);
+       if (!ksreg)
+               return 0x0;     /* no error return allowed, so use zero */
+
+       mutex_lock(&ks->lock);
+       result = ks8851_rdreg16(ks, ksreg);
+       mutex_unlock(&ks->lock);
+
+       return result;
+}
+
+static void ks8851_phy_write(struct net_device *dev,
+                            int phy, int reg, int value)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       int ksreg;
+
+       ksreg = ks8851_phy_reg(reg);
+       if (ksreg) {
+               mutex_lock(&ks->lock);
+               ks8851_wrreg16(ks, ksreg, value);
+               mutex_unlock(&ks->lock);
+       }
+}
+
+/**
+ * ks8851_read_selftest - read the selftest memory info.
+ * @ks: The device state
+ *
+ * Read and check the TX/RX memory selftest information.
+ */
+static int ks8851_read_selftest(struct ks8851_net *ks)
+{
+       unsigned both_done = MBIR_TXMBF | MBIR_RXMBF;
+       int ret = 0;
+       unsigned rd;
+
+       rd = ks8851_rdreg16(ks, KS_MBIR);
+
+       if ((rd & both_done) != both_done) {
+               ks_warn(ks, "Memory selftest not finished\n");
+               return 0;
+       }
+
+       if (rd & MBIR_TXMBFA) {
+               ks_err(ks, "TX memory selftest fail\n");
+               ret |= 1;
+       }
+
+       if (rd & MBIR_RXMBFA) {
+               ks_err(ks, "RX memory selftest fail\n");
+               ret |= 2;
+       }
+
+       return 0;
+}
+
+/* driver bus management functions */
+
+static int __devinit ks8851_probe(struct spi_device *spi)
+{
+       struct net_device *ndev;
+       struct ks8851_net *ks;
+       int ret;
+
+       ndev = alloc_etherdev(sizeof(struct ks8851_net));
+       if (!ndev) {
+               dev_err(&spi->dev, "failed to alloc ethernet device\n");
+               return -ENOMEM;
+       }
+
+       spi->bits_per_word = 8;
+
+       ks = netdev_priv(ndev);
+
+       ks->netdev = ndev;
+       ks->spidev = spi;
+       ks->tx_space = 6144;
+
+       mutex_init(&ks->lock);
+       spin_lock_init(&ks->statelock);
+
+       INIT_WORK(&ks->tx_work, ks8851_tx_work);
+       INIT_WORK(&ks->irq_work, ks8851_irq_work);
+       INIT_WORK(&ks->rxctrl_work, ks8851_rxctrl_work);
+
+       /* initialise pre-made spi transfer messages */
+
+       spi_message_init(&ks->spi_msg1);
+       spi_message_add_tail(&ks->spi_xfer1, &ks->spi_msg1);
+
+       spi_message_init(&ks->spi_msg2);
+       spi_message_add_tail(&ks->spi_xfer2[0], &ks->spi_msg2);
+       spi_message_add_tail(&ks->spi_xfer2[1], &ks->spi_msg2);
+
+       /* setup mii state */
+       ks->mii.dev             = ndev;
+       ks->mii.phy_id          = 1,
+       ks->mii.phy_id_mask     = 1;
+       ks->mii.reg_num_mask    = 0xf;
+       ks->mii.mdio_read       = ks8851_phy_read;
+       ks->mii.mdio_write      = ks8851_phy_write;
+
+       dev_info(&spi->dev, "message enable is %d\n", msg_enable);
+
+       /* set the default message enable */
+       ks->msg_enable = netif_msg_init(msg_enable, (NETIF_MSG_DRV |
+                                                    NETIF_MSG_PROBE |
+                                                    NETIF_MSG_LINK));
+
+       skb_queue_head_init(&ks->txq);
+
+       SET_ETHTOOL_OPS(ndev, &ks8851_ethtool_ops);
+       SET_NETDEV_DEV(ndev, &spi->dev);
+
+       dev_set_drvdata(&spi->dev, ks);
+
+       ndev->if_port = IF_PORT_100BASET;
+       ndev->netdev_ops = &ks8851_netdev_ops;
+       ndev->irq = spi->irq;
+
+       /* simple check for a valid chip being connected to the bus */
+
+       if ((ks8851_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) {
+               dev_err(&spi->dev, "failed to read device ID\n");
+               ret = -ENODEV;
+               goto err_id;
+       }
+
+       ks8851_read_selftest(ks);
+       ks8851_init_mac(ks);
+
+       ret = request_irq(spi->irq, ks8851_irq, IRQF_TRIGGER_LOW,
+                         ndev->name, ks);
+       if (ret < 0) {
+               dev_err(&spi->dev, "failed to get irq\n");
+               goto err_irq;
+       }
+
+       ret = register_netdev(ndev);
+       if (ret) {
+               dev_err(&spi->dev, "failed to register network device\n");
+               goto err_netdev;
+       }
+
+       dev_info(&spi->dev, "revision %d, MAC %pM, IRQ %d\n",
+                CIDER_REV_GET(ks8851_rdreg16(ks, KS_CIDER)),
+                ndev->dev_addr, ndev->irq);
+
+       return 0;
+
+
+err_netdev:
+       free_irq(ndev->irq, ndev);
+
+err_id:
+err_irq:
+       free_netdev(ndev);
+       return ret;
+}
+
+static int __devexit ks8851_remove(struct spi_device *spi)
+{
+       struct ks8851_net *priv = dev_get_drvdata(&spi->dev);
+
+       if (netif_msg_drv(priv))
+               dev_info(&spi->dev, "remove");
+
+       unregister_netdev(priv->netdev);
+       free_irq(spi->irq, priv);
+       free_netdev(priv->netdev);
+
+       return 0;
+}
+
+static struct spi_driver ks8851_driver = {
+       .driver = {
+               .name = "ks8851",
+               .owner = THIS_MODULE,
+       },
+       .probe = ks8851_probe,
+       .remove = __devexit_p(ks8851_remove),
+};
+
+static int __init ks8851_init(void)
+{
+       return spi_register_driver(&ks8851_driver);
+}
+
+static void __exit ks8851_exit(void)
+{
+       spi_unregister_driver(&ks8851_driver);
+}
+
+module_init(ks8851_init);
+module_exit(ks8851_exit);
+
+MODULE_DESCRIPTION("KS8851 Network driver");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL");
+
+module_param_named(message, msg_enable, int, 0);
+MODULE_PARM_DESC(message, "Message verbosity level (0=none, 31=all)");
diff --git a/drivers/net/ks8851.h b/drivers/net/ks8851.h
new file mode 100644 (file)
index 0000000..85abe14
--- /dev/null
@@ -0,0 +1,296 @@
+/* drivers/net/ks8851.h
+ *
+ * Copyright 2009 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *
+ * KS8851 register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define KS_CCR                                 0x08
+#define CCR_EEPROM                             (1 << 9)
+#define CCR_SPI                                        (1 << 8)
+#define CCR_32PIN                              (1 << 0)
+
+/* MAC address registers */
+#define KS_MARL                                        0x10
+#define KS_MARM                                        0x12
+#define KS_MARH                                        0x14
+
+#define KS_OBCR                                        0x20
+#define OBCR_ODS_16mA                          (1 << 6)
+
+#define KS_EEPCR                               0x22
+#define EEPCR_EESA                             (1 << 4)
+#define EEPCR_EESB                             (1 << 3)
+#define EEPCR_EEDO                             (1 << 2)
+#define EEPCR_EESCK                            (1 << 1)
+#define EEPCR_EECS                             (1 << 0)
+
+#define KS_MBIR                                        0x24
+#define MBIR_TXMBF                             (1 << 12)
+#define MBIR_TXMBFA                            (1 << 11)
+#define MBIR_RXMBF                             (1 << 4)
+#define MBIR_RXMBFA                            (1 << 3)
+
+#define KS_GRR                                 0x26
+#define GRR_QMU                                        (1 << 1)
+#define GRR_GSR                                        (1 << 0)
+
+#define KS_WFCR                                        0x2A
+#define WFCR_MPRXE                             (1 << 7)
+#define WFCR_WF3E                              (1 << 3)
+#define WFCR_WF2E                              (1 << 2)
+#define WFCR_WF1E                              (1 << 1)
+#define WFCR_WF0E                              (1 << 0)
+
+#define KS_WF0CRC0                             0x30
+#define KS_WF0CRC1                             0x32
+#define KS_WF0BM0                              0x34
+#define KS_WF0BM1                              0x36
+#define KS_WF0BM2                              0x38
+#define KS_WF0BM3                              0x3A
+
+#define KS_WF1CRC0                             0x40
+#define KS_WF1CRC1                             0x42
+#define KS_WF1BM0                              0x44
+#define KS_WF1BM1                              0x46
+#define KS_WF1BM2                              0x48
+#define KS_WF1BM3                              0x4A
+
+#define KS_WF2CRC0                             0x50
+#define KS_WF2CRC1                             0x52
+#define KS_WF2BM0                              0x54
+#define KS_WF2BM1                              0x56
+#define KS_WF2BM2                              0x58
+#define KS_WF2BM3                              0x5A
+
+#define KS_WF3CRC0                             0x60
+#define KS_WF3CRC1                             0x62
+#define KS_WF3BM0                              0x64
+#define KS_WF3BM1                              0x66
+#define KS_WF3BM2                              0x68
+#define KS_WF3BM3                              0x6A
+
+#define KS_TXCR                                        0x70
+#define TXCR_TCGICMP                           (1 << 8)
+#define TXCR_TCGUDP                            (1 << 7)
+#define TXCR_TCGTCP                            (1 << 6)
+#define TXCR_TCGIP                             (1 << 5)
+#define TXCR_FTXQ                              (1 << 4)
+#define TXCR_TXFCE                             (1 << 3)
+#define TXCR_TXPE                              (1 << 2)
+#define TXCR_TXCRC                             (1 << 1)
+#define TXCR_TXE                               (1 << 0)
+
+#define KS_TXSR                                        0x72
+#define TXSR_TXLC                              (1 << 13)
+#define TXSR_TXMC                              (1 << 12)
+#define TXSR_TXFID_MASK                                (0x3f << 0)
+#define TXSR_TXFID_SHIFT                       (0)
+#define TXSR_TXFID_GET(_v)                     (((_v) >> 0) & 0x3f)
+
+#define KS_RXCR1                               0x74
+#define RXCR1_FRXQ                             (1 << 15)
+#define RXCR1_RXUDPFCC                         (1 << 14)
+#define RXCR1_RXTCPFCC                         (1 << 13)
+#define RXCR1_RXIPFCC                          (1 << 12)
+#define RXCR1_RXPAFMA                          (1 << 11)
+#define RXCR1_RXFCE                            (1 << 10)
+#define RXCR1_RXEFE                            (1 << 9)
+#define RXCR1_RXMAFMA                          (1 << 8)
+#define RXCR1_RXBE                             (1 << 7)
+#define RXCR1_RXME                             (1 << 6)
+#define RXCR1_RXUE                             (1 << 5)
+#define RXCR1_RXAE                             (1 << 4)
+#define RXCR1_RXINVF                           (1 << 1)
+#define RXCR1_RXE                              (1 << 0)
+
+#define KS_RXCR2                               0x76
+#define RXCR2_SRDBL_MASK                       (0x7 << 5)
+#define RXCR2_SRDBL_SHIFT                      (5)
+#define RXCR2_SRDBL_4B                         (0x0 << 5)
+#define RXCR2_SRDBL_8B                         (0x1 << 5)
+#define RXCR2_SRDBL_16B                                (0x2 << 5)
+#define RXCR2_SRDBL_32B                                (0x3 << 5)
+#define RXCR2_SRDBL_FRAME                      (0x4 << 5)
+#define RXCR2_IUFFP                            (1 << 4)
+#define RXCR2_RXIUFCEZ                         (1 << 3)
+#define RXCR2_UDPLFE                           (1 << 2)
+#define RXCR2_RXICMPFCC                                (1 << 1)
+#define RXCR2_RXSAF                            (1 << 0)
+
+#define KS_TXMIR                               0x78
+
+#define KS_RXFHSR                              0x7C
+#define RXFSHR_RXFV                            (1 << 15)
+#define RXFSHR_RXICMPFCS                       (1 << 13)
+#define RXFSHR_RXIPFCS                         (1 << 12)
+#define RXFSHR_RXTCPFCS                                (1 << 11)
+#define RXFSHR_RXUDPFCS                                (1 << 10)
+#define RXFSHR_RXBF                            (1 << 7)
+#define RXFSHR_RXMF                            (1 << 6)
+#define RXFSHR_RXUF                            (1 << 5)
+#define RXFSHR_RXMR                            (1 << 4)
+#define RXFSHR_RXFT                            (1 << 3)
+#define RXFSHR_RXFTL                           (1 << 2)
+#define RXFSHR_RXRF                            (1 << 1)
+#define RXFSHR_RXCE                            (1 << 0)
+
+#define KS_RXFHBCR                             0x7E
+#define KS_TXQCR                               0x80
+#define TXQCR_AETFE                            (1 << 2)
+#define TXQCR_TXQMAM                           (1 << 1)
+#define TXQCR_METFE                            (1 << 0)
+
+#define KS_RXQCR                               0x82
+#define RXQCR_RXDTTS                           (1 << 12)
+#define RXQCR_RXDBCTS                          (1 << 11)
+#define RXQCR_RXFCTS                           (1 << 10)
+#define RXQCR_RXIPHTOE                         (1 << 9)
+#define RXQCR_RXDTTE                           (1 << 7)
+#define RXQCR_RXDBCTE                          (1 << 6)
+#define RXQCR_RXFCTE                           (1 << 5)
+#define RXQCR_ADRFE                            (1 << 4)
+#define RXQCR_SDA                              (1 << 3)
+#define RXQCR_RRXEF                            (1 << 0)
+
+#define KS_TXFDPR                              0x84
+#define TXFDPR_TXFPAI                          (1 << 14)
+#define TXFDPR_TXFP_MASK                       (0x7ff << 0)
+#define TXFDPR_TXFP_SHIFT                      (0)
+
+#define KS_RXFDPR                              0x86
+#define RXFDPR_RXFPAI                          (1 << 14)
+
+#define KS_RXDTTR                              0x8C
+#define KS_RXDBCTR                             0x8E
+
+#define KS_IER                                 0x90
+#define KS_ISR                                 0x92
+#define IRQ_LCI                                        (1 << 15)
+#define IRQ_TXI                                        (1 << 14)
+#define IRQ_RXI                                        (1 << 13)
+#define IRQ_RXOI                               (1 << 11)
+#define IRQ_TXPSI                              (1 << 9)
+#define IRQ_RXPSI                              (1 << 8)
+#define IRQ_TXSAI                              (1 << 6)
+#define IRQ_RXWFDI                             (1 << 5)
+#define IRQ_RXMPDI                             (1 << 4)
+#define IRQ_LDI                                        (1 << 3)
+#define IRQ_EDI                                        (1 << 2)
+#define IRQ_SPIBEI                             (1 << 1)
+#define IRQ_DEDI                               (1 << 0)
+
+#define KS_RXFCTR                              0x9C
+#define KS_RXFC                                        0x9D
+#define RXFCTR_RXFC_MASK                       (0xff << 8)
+#define RXFCTR_RXFC_SHIFT                      (8)
+#define RXFCTR_RXFC_GET(_v)                    (((_v) >> 8) & 0xff)
+#define RXFCTR_RXFCT_MASK                      (0xff << 0)
+#define RXFCTR_RXFCT_SHIFT                     (0)
+
+#define KS_TXNTFSR                             0x9E
+
+#define KS_MAHTR0                              0xA0
+#define KS_MAHTR1                              0xA2
+#define KS_MAHTR2                              0xA4
+#define KS_MAHTR3                              0xA6
+
+#define KS_FCLWR                               0xB0
+#define KS_FCHWR                               0xB2
+#define KS_FCOWR                               0xB4
+
+#define KS_CIDER                               0xC0
+#define CIDER_ID                               0x8870
+#define CIDER_REV_MASK                         (0x7 << 1)
+#define CIDER_REV_SHIFT                                (1)
+#define CIDER_REV_GET(_v)                      (((_v) >> 1) & 0x7)
+
+#define KS_CGCR                                        0xC6
+
+#define KS_IACR                                        0xC8
+#define IACR_RDEN                              (1 << 12)
+#define IACR_TSEL_MASK                         (0x3 << 10)
+#define IACR_TSEL_SHIFT                                (10)
+#define IACR_TSEL_MIB                          (0x3 << 10)
+#define IACR_ADDR_MASK                         (0x1f << 0)
+#define IACR_ADDR_SHIFT                                (0)
+
+#define KS_IADLR                               0xD0
+#define KS_IAHDR                               0xD2
+
+#define KS_PMECR                               0xD4
+#define PMECR_PME_DELAY                                (1 << 14)
+#define PMECR_PME_POL                          (1 << 12)
+#define PMECR_WOL_WAKEUP                       (1 << 11)
+#define PMECR_WOL_MAGICPKT                     (1 << 10)
+#define PMECR_WOL_LINKUP                       (1 << 9)
+#define PMECR_WOL_ENERGY                       (1 << 8)
+#define PMECR_AUTO_WAKE_EN                     (1 << 7)
+#define PMECR_WAKEUP_NORMAL                    (1 << 6)
+#define PMECR_WKEVT_MASK                       (0xf << 2)
+#define PMECR_WKEVT_SHIFT                      (2)
+#define PMECR_WKEVT_GET(_v)                    (((_v) >> 2) & 0xf)
+#define PMECR_WKEVT_ENERGY                     (0x1 << 2)
+#define PMECR_WKEVT_LINK                       (0x2 << 2)
+#define PMECR_WKEVT_MAGICPKT                   (0x4 << 2)
+#define PMECR_WKEVT_FRAME                      (0x8 << 2)
+#define PMECR_PM_MASK                          (0x3 << 0)
+#define PMECR_PM_SHIFT                         (0)
+#define PMECR_PM_NORMAL                                (0x0 << 0)
+#define PMECR_PM_ENERGY                                (0x1 << 0)
+#define PMECR_PM_SOFTDOWN                      (0x2 << 0)
+#define PMECR_PM_POWERSAVE                     (0x3 << 0)
+
+/* Standard MII PHY data */
+#define KS_P1MBCR                              0xE4
+#define KS_P1MBSR                              0xE6
+#define KS_PHY1ILR                             0xE8
+#define KS_PHY1IHR                             0xEA
+#define KS_P1ANAR                              0xEC
+#define KS_P1ANLPR                             0xEE
+
+#define KS_P1SCLMD                             0xF4
+#define P1SCLMD_LEDOFF                         (1 << 15)
+#define P1SCLMD_TXIDS                          (1 << 14)
+#define P1SCLMD_RESTARTAN                      (1 << 13)
+#define P1SCLMD_DISAUTOMDIX                    (1 << 10)
+#define P1SCLMD_FORCEMDIX                      (1 << 9)
+#define P1SCLMD_AUTONEGEN                      (1 << 7)
+#define P1SCLMD_FORCE100                       (1 << 6)
+#define P1SCLMD_FORCEFDX                       (1 << 5)
+#define P1SCLMD_ADV_FLOW                       (1 << 4)
+#define P1SCLMD_ADV_100BT_FDX                  (1 << 3)
+#define P1SCLMD_ADV_100BT_HDX                  (1 << 2)
+#define P1SCLMD_ADV_10BT_FDX                   (1 << 1)
+#define P1SCLMD_ADV_10BT_HDX                   (1 << 0)
+
+#define KS_P1CR                                        0xF6
+#define P1CR_HP_MDIX                           (1 << 15)
+#define P1CR_REV_POL                           (1 << 13)
+#define P1CR_OP_100M                           (1 << 10)
+#define P1CR_OP_FDX                            (1 << 9)
+#define P1CR_OP_MDI                            (1 << 7)
+#define P1CR_AN_DONE                           (1 << 6)
+#define P1CR_LINK_GOOD                         (1 << 5)
+#define P1CR_PNTR_FLOW                         (1 << 4)
+#define P1CR_PNTR_100BT_FDX                    (1 << 3)
+#define P1CR_PNTR_100BT_HDX                    (1 << 2)
+#define P1CR_PNTR_10BT_FDX                     (1 << 1)
+#define P1CR_PNTR_10BT_HDX                     (1 << 0)
+
+/* TX Frame control */
+
+#define TXFR_TXIC                              (1 << 15)
+#define TXFR_TXFID_MASK                                (0x3f << 0)
+#define TXFR_TXFID_SHIFT                       (0)
+
+/* SPI frame opcodes */
+#define KS_SPIOP_RD                            (0x00)
+#define KS_SPIOP_WR                            (0x40)
+#define KS_SPIOP_RXFIFO                                (0x80)
+#define KS_SPIOP_TXFIFO                                (0xC0)
index acd143da161d5da4a6e757e10c8b6a9a4e2bc809..61eabcac734cdbce1de299924867858740a92ac3 100644 (file)
@@ -179,7 +179,7 @@ static const struct net_device_ops macsonic_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
-static int __init macsonic_init(struct net_device *dev)
+static int __devinit macsonic_init(struct net_device *dev)
 {
        struct sonic_local* lp = netdev_priv(dev);
 
@@ -223,7 +223,7 @@ static int __init macsonic_init(struct net_device *dev)
        return 0;
 }
 
-static int __init mac_onboard_sonic_ethernet_addr(struct net_device *dev)
+static int __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
 {
        struct sonic_local *lp = netdev_priv(dev);
        const int prom_addr = ONBOARD_SONIC_PROM_BASE;
@@ -288,7 +288,7 @@ static int __init mac_onboard_sonic_ethernet_addr(struct net_device *dev)
        } else return 0;
 }
 
-static int __init mac_onboard_sonic_probe(struct net_device *dev)
+static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
 {
        /* Bwahahaha */
        static int once_is_more_than_enough;
@@ -409,7 +409,7 @@ static int __init mac_onboard_sonic_probe(struct net_device *dev)
        return macsonic_init(dev);
 }
 
-static int __init mac_nubus_sonic_ethernet_addr(struct net_device *dev,
+static int __devinit mac_nubus_sonic_ethernet_addr(struct net_device *dev,
                                                unsigned long prom_addr,
                                                int id)
 {
@@ -424,7 +424,7 @@ static int __init mac_nubus_sonic_ethernet_addr(struct net_device *dev,
        return 0;
 }
 
-static int __init macsonic_ident(struct nubus_dev *ndev)
+static int __devinit macsonic_ident(struct nubus_dev *ndev)
 {
        if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC &&
            ndev->dr_sw == NUBUS_DRSW_SONIC_LC)
@@ -449,7 +449,7 @@ static int __init macsonic_ident(struct nubus_dev *ndev)
        return -1;
 }
 
-static int __init mac_nubus_sonic_probe(struct net_device *dev)
+static int __devinit mac_nubus_sonic_probe(struct net_device *dev)
 {
        static int slots;
        struct nubus_dev* ndev = NULL;
@@ -562,7 +562,7 @@ static int __init mac_nubus_sonic_probe(struct net_device *dev)
        return macsonic_init(dev);
 }
 
-static int __init mac_sonic_probe(struct platform_device *pdev)
+static int __devinit mac_sonic_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
        struct sonic_local *lp;
@@ -575,6 +575,7 @@ static int __init mac_sonic_probe(struct platform_device *pdev)
        lp = netdev_priv(dev);
        lp->device = &pdev->dev;
        SET_NETDEV_DEV(dev, &pdev->dev);
+       platform_set_drvdata(pdev, dev);
 
        /* This will catch fatal stuff like -ENOMEM as well as success */
        err = mac_onboard_sonic_probe(dev);
index 2845a0560b84e18fcd28c64e9caa145b59c9a034..65ec77dc31f5b5c4a542a22a2f7d11c464a9d664 100644 (file)
@@ -80,7 +80,9 @@ enum {
        /* Bad management packet (silently discarded): */
        CMD_STAT_BAD_PKT        = 0x30,
        /* More outstanding CQEs in CQ than new CQ size: */
-       CMD_STAT_BAD_SIZE       = 0x40
+       CMD_STAT_BAD_SIZE       = 0x40,
+       /* Multi Function device support required: */
+       CMD_STAT_MULTI_FUNC_REQ = 0x50,
 };
 
 enum {
@@ -128,6 +130,7 @@ static int mlx4_status_to_errno(u8 status)
                [CMD_STAT_LAM_NOT_PRE]    = -EAGAIN,
                [CMD_STAT_BAD_PKT]        = -EINVAL,
                [CMD_STAT_BAD_SIZE]       = -ENOMEM,
+               [CMD_STAT_MULTI_FUNC_REQ] = -EACCES,
        };
 
        if (status >= ARRAY_SIZE(trans_table) ||
index 091f99052c91673f4536004e885cdebca05f598c..86467b444ac679ab4b4a62e25aaba29c38d12bf2 100644 (file)
@@ -220,7 +220,7 @@ static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        cmd->autoneg = AUTONEG_DISABLE;
        cmd->supported = SUPPORTED_10000baseT_Full;
-       cmd->advertising = SUPPORTED_10000baseT_Full;
+       cmd->advertising = ADVERTISED_1000baseT_Full;
        if (netif_carrier_ok(dev)) {
                cmd->speed = SPEED_10000;
                cmd->duplex = DUPLEX_FULL;
index 018348c011933b1240153f24ee95ba836c83c22c..dac621b1e9fc9a287fb8b4f7fdfa4f538ecc2a77 100644 (file)
@@ -729,7 +729,10 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
 
        err = mlx4_QUERY_FW(dev);
        if (err) {
-               mlx4_err(dev, "QUERY_FW command failed, aborting.\n");
+               if (err == -EACCES)
+                       mlx4_info(dev, "non-primary physical function, skipping.\n");
+               else
+                       mlx4_err(dev, "QUERY_FW command failed, aborting.\n");
                return err;
        }
 
@@ -1285,6 +1288,7 @@ static struct pci_device_id mlx4_pci_table[] = {
        { PCI_VDEVICE(MELLANOX, 0x6750) }, /* MT25408 "Hermon" EN 10GigE PCIe gen2 */
        { PCI_VDEVICE(MELLANOX, 0x6372) }, /* MT25458 ConnectX EN 10GBASE-T 10GigE */
        { PCI_VDEVICE(MELLANOX, 0x675a) }, /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */
+       { PCI_VDEVICE(MELLANOX, 0x6764) }, /* MT26468 ConnectX EN 10GigE PCIe gen2*/
        { 0, }
 };
 
index e1cdba752e09daa397c331b9c5708da267d8a7d9..f86e05047d19db0bdd56feb1b726373fcbeee733 100644 (file)
 #define NETXEN_CTX_SIGNATURE   0xdee0
 #define NETXEN_CTX_SIGNATURE_V2        0x0002dee0
 #define NETXEN_CTX_RESET       0xbad0
+#define NETXEN_CTX_D3_RESET    0xacc0
 #define NETXEN_RCV_PRODUCER(ringid)    (ringid)
 
 #define PHAN_PEG_RCV_INITIALIZED       0xff01
@@ -773,6 +774,8 @@ struct nx_host_tx_ring {
        u32 crb_cmd_consumer;
        u32 num_desc;
 
+       struct netdev_queue *txq;
+
        struct netxen_cmd_buffer *cmd_buf_arr;
        struct cmd_desc_type0 *desc_head;
        dma_addr_t phys_addr;
index 4754f5cffad078ce53436b26330b6a0623ee4749..9f8ae4719e2fb4a9d91d4893db5baf675ccd7616 100644 (file)
@@ -684,10 +684,8 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
                        goto err_out_free;
        } else {
                err = netxen_init_old_ctx(adapter);
-               if (err) {
-                       netxen_free_hw_resources(adapter);
-                       return err;
-               }
+               if (err)
+                       goto err_out_free;
        }
 
        return 0;
@@ -708,15 +706,18 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter)
        int port = adapter->portnum;
 
        if (adapter->fw_major >= 4) {
-               nx_fw_cmd_destroy_tx_ctx(adapter);
                nx_fw_cmd_destroy_rx_ctx(adapter);
+               nx_fw_cmd_destroy_tx_ctx(adapter);
        } else {
                netxen_api_lock(adapter);
                NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port),
-                               NETXEN_CTX_RESET | port);
+                               NETXEN_CTX_D3_RESET | port);
                netxen_api_unlock(adapter);
        }
 
+       /* Allow dma queues to drain after context reset */
+       msleep(20);
+
        recv_ctx = &adapter->recv_ctx;
 
        if (recv_ctx->hwctx != NULL) {
index ce3b89d2cbb6c11e3ab5749446bec617dcc4edeb..b9123d445c966bbfc2ae7dc7e6f7e9ec46b9711c 100644 (file)
@@ -461,13 +461,14 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
        i = 0;
 
        tx_ring = adapter->tx_ring;
-       netif_tx_lock_bh(adapter->netdev);
+       __netif_tx_lock_bh(tx_ring->txq);
 
        producer = tx_ring->producer;
        consumer = tx_ring->sw_consumer;
 
-       if (nr_desc >= find_diff_among(producer, consumer, tx_ring->num_desc)) {
-               netif_tx_unlock_bh(adapter->netdev);
+       if (nr_desc >= netxen_tx_avail(tx_ring)) {
+               netif_tx_stop_queue(tx_ring->txq);
+               __netif_tx_unlock_bh(tx_ring->txq);
                return -EBUSY;
        }
 
@@ -490,7 +491,7 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
 
        netxen_nic_update_cmd_producer(adapter, tx_ring);
 
-       netif_tx_unlock_bh(adapter->netdev);
+       __netif_tx_unlock_bh(tx_ring->txq);
 
        return 0;
 }
index b899bd51fcd87e2563fa4fd495b8c760fe5c0e6d..5d3343ef3d86312713481186b541656b1eba3470 100644 (file)
@@ -214,6 +214,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
        adapter->tx_ring = tx_ring;
 
        tx_ring->num_desc = adapter->num_txd;
+       tx_ring->txq = netdev_get_tx_queue(netdev, 0);
 
        cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring));
        if (cmd_buf_arr == NULL) {
@@ -1400,10 +1401,10 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
                smp_mb();
 
                if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
-                       netif_tx_lock(netdev);
+                       __netif_tx_lock(tx_ring->txq, smp_processor_id());
                        if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
                                netif_wake_queue(netdev);
-                       netif_tx_unlock(netdev);
+                       __netif_tx_unlock(tx_ring->txq);
                }
        }
        /*
index 27539ddf94c4f9304c8310e652c1ee7f120f78af..637ac8b89bac3e530962ae111bc0329d53c71bf6 100644 (file)
@@ -215,9 +215,9 @@ netxen_napi_disable(struct netxen_adapter *adapter)
 
        for (ring = 0; ring < adapter->max_sds_rings; ring++) {
                sds_ring = &recv_ctx->sds_rings[ring];
-               napi_disable(&sds_ring->napi);
                netxen_nic_disable_int(sds_ring);
-               synchronize_irq(sds_ring->irq);
+               napi_synchronize(&sds_ring->napi);
+               napi_disable(&sds_ring->napi);
        }
 }
 
@@ -833,11 +833,11 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
 
        adapter->ahw.linkup = 0;
 
-       netxen_napi_enable(adapter);
-
        if (adapter->max_sds_rings > 1)
                netxen_config_rss(adapter, 1);
 
+       netxen_napi_enable(adapter);
+
        if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION)
                netxen_linkevent_request(adapter, 1);
        else
@@ -851,8 +851,9 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
 static void
 netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
 {
+       spin_lock(&adapter->tx_clean_lock);
        netif_carrier_off(netdev);
-       netif_stop_queue(netdev);
+       netif_tx_disable(netdev);
 
        if (adapter->stop_port)
                adapter->stop_port(adapter);
@@ -863,9 +864,10 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
        netxen_napi_disable(adapter);
 
        netxen_release_tx_buffers(adapter);
+       spin_unlock(&adapter->tx_clean_lock);
 
-       FLUSH_SCHEDULED_WORK();
        del_timer_sync(&adapter->watchdog_timer);
+       FLUSH_SCHEDULED_WORK();
 }
 
 
@@ -943,8 +945,8 @@ err_out_free_sw:
 static void
 netxen_nic_detach(struct netxen_adapter *adapter)
 {
-       netxen_release_rx_buffers(adapter);
        netxen_free_hw_resources(adapter);
+       netxen_release_rx_buffers(adapter);
        netxen_nic_free_irq(adapter);
        netxen_free_sw_resources(adapter);
 
@@ -1533,10 +1535,12 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter)
                printk(KERN_ALERT
                       "%s: Device temperature %d degrees C exceeds"
                       " maximum allowed. Hardware has been shut down.\n",
-                      netxen_nic_driver_name, temp_val);
+                      netdev->name, temp_val);
+
+               netif_device_detach(netdev);
+               netxen_nic_down(adapter, netdev);
+               netxen_nic_detach(adapter);
 
-               netif_carrier_off(netdev);
-               netif_stop_queue(netdev);
                rv = 1;
        } else if (temp_state == NX_TEMP_WARN) {
                if (adapter->temp == NX_TEMP_NORMAL) {
@@ -1544,13 +1548,13 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter)
                               "%s: Device temperature %d degrees C "
                               "exceeds operating range."
                               " Immediate action needed.\n",
-                              netxen_nic_driver_name, temp_val);
+                              netdev->name, temp_val);
                }
        } else {
                if (adapter->temp == NX_TEMP_WARN) {
                        printk(KERN_INFO
                               "%s: Device temperature is now %d degrees C"
-                              " in normal range.\n", netxen_nic_driver_name,
+                              " in normal range.\n", netdev->name,
                               temp_val);
                }
        }
@@ -1623,7 +1627,7 @@ void netxen_watchdog_task(struct work_struct *work)
        struct netxen_adapter *adapter =
                container_of(work, struct netxen_adapter, watchdog_task);
 
-       if ((adapter->portnum  == 0) && netxen_nic_check_temp(adapter))
+       if (netxen_nic_check_temp(adapter))
                return;
 
        if (!adapter->has_link_events)
@@ -1645,6 +1649,9 @@ static void netxen_tx_timeout_task(struct work_struct *work)
        struct netxen_adapter *adapter =
                container_of(work, struct netxen_adapter, tx_timeout_task);
 
+       if (!netif_running(adapter->netdev))
+               return;
+
        printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
               netxen_nic_driver_name, adapter->netdev->name);
 
@@ -1757,7 +1764,8 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget)
 
        if ((work_done < budget) && tx_complete) {
                napi_complete(&sds_ring->napi);
-               netxen_nic_enable_int(sds_ring);
+               if (netif_running(adapter->netdev))
+                       netxen_nic_enable_int(sds_ring);
        }
 
        return work_done;
index ec7cf5ac4f0595275551e3addecf16747be79c92..690b9c76d34ebf9f22772a727268e1441db4d92f 100644 (file)
@@ -156,6 +156,7 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev);
 static int el3_rx(struct net_device *dev);
 static int el3_close(struct net_device *dev);
 static void el3_tx_timeout(struct net_device *dev);
+static void set_rx_mode(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static const struct ethtool_ops netdev_ethtool_ops;
 
@@ -488,8 +489,7 @@ static void tc589_reset(struct net_device *dev)
     /* Switch to register set 1 for normal use. */
     EL3WINDOW(1);
 
-    /* Accept b-cast and phys addr only. */
-    outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
+    set_rx_mode(dev);
     outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
     outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
     outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
@@ -700,7 +700,7 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id)
                if (fifo_diag & 0x2000) {
                    /* Rx underrun */
                    tc589_wait_for_completion(dev, RxReset);
-                   set_multicast_list(dev);
+                   set_rx_mode(dev);
                    outw(RxEnable, ioaddr + EL3_CMD);
                }
                outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
@@ -905,14 +905,11 @@ static int el3_rx(struct net_device *dev)
     return 0;
 }
 
-static void set_multicast_list(struct net_device *dev)
+static void set_rx_mode(struct net_device *dev)
 {
-    struct el3_private *lp = netdev_priv(dev);
-    struct pcmcia_device *link = lp->p_dev;
     unsigned int ioaddr = dev->base_addr;
     u16 opts = SetRxFilter | RxStation | RxBroadcast;
 
-    if (!pcmcia_dev_present(link)) return;
     if (dev->flags & IFF_PROMISC)
        opts |= RxMulticast | RxProm;
     else if (dev->mc_count || (dev->flags & IFF_ALLMULTI))
@@ -920,6 +917,16 @@ static void set_multicast_list(struct net_device *dev)
     outw(opts, ioaddr + EL3_CMD);
 }
 
+static void set_multicast_list(struct net_device *dev)
+{
+       struct el3_private *priv = netdev_priv(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       set_rx_mode(dev);
+       spin_unlock_irqrestore(&priv->lock, flags);
+}
+
 static int el3_close(struct net_device *dev)
 {
     struct el3_private *lp = netdev_priv(dev);
index eba937c463767fd1e07ea2425db0a17165e263ab..b10fedd8214394b591bfb81bd102c8d38fce9fb1 100644 (file)
@@ -134,8 +134,10 @@ int phy_scan_fixups(struct phy_device *phydev)
 
                        err = fixup->run(phydev);
 
-                       if (err < 0)
+                       if (err < 0) {
+                               mutex_unlock(&phy_fixup_lock);
                                return err;
+                       }
                }
        }
        mutex_unlock(&phy_fixup_lock);
index 7a62f781fef2b83fdfe55dc0cad944cb5a2d7c8b..2ca8b0d84ee2d7f2647e3064e6f1615f116c1294 100644 (file)
@@ -270,6 +270,9 @@ static const struct net_device_ops plip_netdev_ops = {
        .ndo_stop                = plip_close,
        .ndo_start_xmit          = plip_tx_packet,
        .ndo_do_ioctl            = plip_ioctl,
+       .ndo_change_mtu          = eth_change_mtu,
+       .ndo_set_mac_address     = eth_mac_addr,
+       .ndo_validate_addr       = eth_validate_addr,
 };
 
 /* Entry point of PLIP driver.
index 17c116bb332c7e0c41da3f97aeb3ac3755097e87..6de8399d6dd92d26875cca679ec332c19082d736 100644 (file)
@@ -356,6 +356,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
        if (!skb_queue_empty(&ap->rqueue))
                tasklet_schedule(&ap->tsk);
        ap_put(ap);
+       tty_unthrottle(tty);
 }
 
 static void
index aa3d39f38e2257deee5e72e9df06453be96e3046..d2fa2db1358633771439013546758654444c6a00 100644 (file)
@@ -397,6 +397,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
        if (!skb_queue_empty(&ap->rqueue))
                tasklet_schedule(&ap->tsk);
        sp_put(ap);
+       tty_unthrottle(tty);
 }
 
 static void
index d1a5fb4d6acb1e63e479abea8db9a1e1f4a3e5f7..a3932c9f3406c9d4e75967fc392d759cffb78330 100644 (file)
@@ -1411,6 +1411,7 @@ static const struct net_device_ops gelic_netdevice_ops = {
        .ndo_set_multicast_list = gelic_net_set_multi,
        .ndo_change_mtu = gelic_net_change_mtu,
        .ndo_tx_timeout = gelic_net_tx_timeout,
+       .ndo_set_mac_address = eth_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = gelic_net_poll_controller,
index b6b3ca9bdb213a9fa995b35cda8cc72f0cf480d2..6932b08d746b38b1c830d3ea3f720496562e9129 100644 (file)
@@ -2707,6 +2707,7 @@ static const struct net_device_ops gelic_wl_netdevice_ops = {
        .ndo_set_multicast_list = gelic_net_set_multi,
        .ndo_change_mtu = gelic_net_change_mtu,
        .ndo_tx_timeout = gelic_net_tx_timeout,
+       .ndo_set_mac_address = eth_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = gelic_net_poll_controller,
index 18821f217e19fa286a732973cfc917463638e672..e3156c97bb58b5a163a5c8f6531cbf8b842a4201 100644 (file)
@@ -1593,6 +1593,7 @@ out:
 static struct pci_device_id sc92031_pci_device_id_table[] __devinitdata = {
        { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x2031) },
        { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x8139) },
+       { PCI_DEVICE(0x1088, 0x2031) },
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, sc92031_pci_device_id_table);
index daf961ab68bc27e3fa16ddea89784aa0091b42e2..3550c5dcd93c599ed2e91f4424821c87523c76fb 100644 (file)
@@ -1151,14 +1151,7 @@ stopped:
 
        /* reset the Rx prefetch unit */
        sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
-
-       /* Reset the RAM Buffer receive queue */
-       sky2_write8(hw, RB_ADDR(rxq, RB_CTRL), RB_RST_SET);
-
-       /* Reset Rx MAC FIFO */
-       sky2_write8(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), GMF_RST_SET);
-
-       sky2_read8(hw, B0_CTST);
+       mmiowb();
 }
 
 /* Clean out receive buffer area, assumes receiver hardware stopped */
@@ -1825,12 +1818,6 @@ static int sky2_down(struct net_device *dev)
        if (netif_msg_ifdown(sky2))
                printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
 
-       /* Disable port IRQ */
-       imask = sky2_read32(hw, B0_IMSK);
-       imask &= ~portirq_msk[port];
-       sky2_write32(hw, B0_IMSK, imask);
-       sky2_read32(hw, B0_IMSK);
-
        /* Force flow control off */
        sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
 
@@ -1870,8 +1857,6 @@ static int sky2_down(struct net_device *dev)
 
        sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET);
 
-       sky2_rx_stop(sky2);
-
        sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
        sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
 
@@ -1881,6 +1866,14 @@ static int sky2_down(struct net_device *dev)
        sky2_write32(hw, STAT_ISR_TIMER_CNT, 0);
        sky2_read8(hw, STAT_ISR_TIMER_CTRL);
 
+       sky2_rx_stop(sky2);
+
+       /* Disable port IRQ */
+       imask = sky2_read32(hw, B0_IMSK);
+       imask &= ~portirq_msk[port];
+       sky2_write32(hw, B0_IMSK, imask);
+       sky2_read32(hw, B0_IMSK);
+
        synchronize_irq(hw->pdev->irq);
        napi_synchronize(&hw->napi);
 
index fdcbaf8dfa739618a5a8f25bc27f6c24222e8004..1c70e999cc50d866ab5ebdba0956b25bba83659d 100644 (file)
@@ -1774,6 +1774,7 @@ static const struct net_device_ops smc_netdev_ops = {
        .ndo_start_xmit         = smc_hard_start_xmit,
        .ndo_tx_timeout         = smc_timeout,
        .ndo_set_multicast_list = smc_set_multicast_list,
+       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 66067f9d91c05499264762c8f0a4600351b7e8e5..94b6d2658ddc016cea883126e276bbf4c0c936bf 100644 (file)
@@ -1779,6 +1779,7 @@ static const struct net_device_ops smsc911x_netdev_ops = {
        .ndo_get_stats          = smsc911x_get_stats,
        .ndo_set_multicast_list = smsc911x_set_multicast_list,
        .ndo_do_ioctl           = smsc911x_do_ioctl,
+       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = smsc911x_set_mac_address,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index a82fb2aca4cb7d89fe52e8bb31dfe4b6eacac505..f1e5e4542c2a04084b419c990e67760e05253f82 100644 (file)
@@ -1016,7 +1016,9 @@ static const struct net_device_ops vnet_ops = {
        .ndo_open               = vnet_open,
        .ndo_stop               = vnet_close,
        .ndo_set_multicast_list = vnet_set_rx_mode,
+       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = vnet_set_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
        .ndo_tx_timeout         = vnet_tx_timeout,
        .ndo_change_mtu         = vnet_change_mtu,
        .ndo_start_xmit         = vnet_start_xmit,
index a906d3998131a512b0f125f3f8892cf38c3bdaf5..c47237c2d638ef97dc3a2d10186c0cdf55e9c452 100644 (file)
@@ -369,4 +369,12 @@ config USB_NET_INT51X1
          (Powerline Communications) solution with an Intellon
          INT51x1/INT5200 chip, like the "devolo dLan duo".
 
+config USB_CDC_PHONET
+       tristate "CDC Phonet support"
+       depends on PHONET
+       help
+         Choose this option to support the Phonet interface to a Nokia
+         cellular modem, as found on most Nokia handsets with the
+         "PC suite" USB profile.
+
 endmenu
index b870b0b1cbe0a1280ad7900a05c148417ff7729f..e17afb78f37220df2c8c6a13eb420aa14280fd09 100644 (file)
@@ -21,4 +21,5 @@ obj-$(CONFIG_USB_NET_ZAURUS)  += zaurus.o
 obj-$(CONFIG_USB_NET_MCS7830)  += mcs7830.o
 obj-$(CONFIG_USB_USBNET)       += usbnet.o
 obj-$(CONFIG_USB_NET_INT51X1)  += int51x1.o
+obj-$(CONFIG_USB_CDC_PHONET)   += cdc-phonet.o
 
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
new file mode 100644 (file)
index 0000000..792af72
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+ * phonet.c -- USB CDC Phonet host driver
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * Author: Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Â See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/cdc.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/if_phonet.h>
+
+#define PN_MEDIA_USB   0x1B
+
+static const unsigned rxq_size = 17;
+
+struct usbpn_dev {
+       struct net_device       *dev;
+
+       struct usb_interface    *intf, *data_intf;
+       struct usb_device       *usb;
+       unsigned int            tx_pipe, rx_pipe;
+       u8 active_setting;
+       u8 disconnected;
+
+       unsigned                tx_queue;
+       spinlock_t              tx_lock;
+
+       spinlock_t              rx_lock;
+       struct sk_buff          *rx_skb;
+       struct urb              *urbs[0];
+};
+
+static void tx_complete(struct urb *req);
+static void rx_complete(struct urb *req);
+
+/*
+ * Network device callbacks
+ */
+static int usbpn_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct usbpn_dev *pnd = netdev_priv(dev);
+       struct urb *req = NULL;
+       unsigned long flags;
+       int err;
+
+       if (skb->protocol != htons(ETH_P_PHONET))
+               goto drop;
+
+       req = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!req)
+               goto drop;
+       usb_fill_bulk_urb(req, pnd->usb, pnd->tx_pipe, skb->data, skb->len,
+                               tx_complete, skb);
+       req->transfer_flags = URB_ZERO_PACKET;
+       err = usb_submit_urb(req, GFP_ATOMIC);
+       if (err) {
+               usb_free_urb(req);
+               goto drop;
+       }
+
+       spin_lock_irqsave(&pnd->tx_lock, flags);
+       pnd->tx_queue++;
+       if (pnd->tx_queue >= dev->tx_queue_len)
+               netif_stop_queue(dev);
+       spin_unlock_irqrestore(&pnd->tx_lock, flags);
+       return 0;
+
+drop:
+       dev_kfree_skb(skb);
+       dev->stats.tx_dropped++;
+       return 0;
+}
+
+static void tx_complete(struct urb *req)
+{
+       struct sk_buff *skb = req->context;
+       struct net_device *dev = skb->dev;
+       struct usbpn_dev *pnd = netdev_priv(dev);
+
+       switch (req->status) {
+       case 0:
+               dev->stats.tx_bytes += skb->len;
+               break;
+
+       case -ENOENT:
+       case -ECONNRESET:
+       case -ESHUTDOWN:
+               dev->stats.tx_aborted_errors++;
+       default:
+               dev->stats.tx_errors++;
+               dev_dbg(&dev->dev, "TX error (%d)\n", req->status);
+       }
+       dev->stats.tx_packets++;
+
+       spin_lock(&pnd->tx_lock);
+       pnd->tx_queue--;
+       netif_wake_queue(dev);
+       spin_unlock(&pnd->tx_lock);
+
+       dev_kfree_skb_any(skb);
+       usb_free_urb(req);
+}
+
+static int rx_submit(struct usbpn_dev *pnd, struct urb *req, gfp_t gfp_flags)
+{
+       struct net_device *dev = pnd->dev;
+       struct page *page;
+       int err;
+
+       page = __netdev_alloc_page(dev, gfp_flags);
+       if (!page)
+               return -ENOMEM;
+
+       usb_fill_bulk_urb(req, pnd->usb, pnd->rx_pipe, page_address(page),
+                               PAGE_SIZE, rx_complete, dev);
+       req->transfer_flags = 0;
+       err = usb_submit_urb(req, gfp_flags);
+       if (unlikely(err)) {
+               dev_dbg(&dev->dev, "RX submit error (%d)\n", err);
+               netdev_free_page(dev, page);
+       }
+       return err;
+}
+
+static void rx_complete(struct urb *req)
+{
+       struct net_device *dev = req->context;
+       struct usbpn_dev *pnd = netdev_priv(dev);
+       struct page *page = virt_to_page(req->transfer_buffer);
+       struct sk_buff *skb;
+       unsigned long flags;
+
+       switch (req->status) {
+       case 0:
+               spin_lock_irqsave(&pnd->rx_lock, flags);
+               skb = pnd->rx_skb;
+               if (!skb) {
+                       skb = pnd->rx_skb = netdev_alloc_skb(dev, 12);
+                       if (likely(skb)) {
+                               /* Can't use pskb_pull() on page in IRQ */
+                               memcpy(skb_put(skb, 1), page_address(page), 1);
+                               skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
+                                               page, 1, req->actual_length);
+                               page = NULL;
+                       }
+               } else {
+                       skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
+                                       page, 0, req->actual_length);
+                       page = NULL;
+               }
+               if (req->actual_length < PAGE_SIZE)
+                       pnd->rx_skb = NULL; /* Last fragment */
+               else
+                       skb = NULL;
+               spin_unlock_irqrestore(&pnd->rx_lock, flags);
+               if (skb) {
+                       skb->protocol = htons(ETH_P_PHONET);
+                       skb_reset_mac_header(skb);
+                       __skb_pull(skb, 1);
+                       skb->dev = dev;
+                       dev->stats.rx_packets++;
+                       dev->stats.rx_bytes += skb->len;
+
+                       netif_rx(skb);
+               }
+               goto resubmit;
+
+       case -ENOENT:
+       case -ECONNRESET:
+       case -ESHUTDOWN:
+               req = NULL;
+               break;
+
+       case -EOVERFLOW:
+               dev->stats.rx_over_errors++;
+               dev_dbg(&dev->dev, "RX overflow\n");
+               break;
+
+       case -EILSEQ:
+               dev->stats.rx_crc_errors++;
+               break;
+       }
+
+       dev->stats.rx_errors++;
+resubmit:
+       if (page)
+               netdev_free_page(dev, page);
+       if (req)
+               rx_submit(pnd, req, GFP_ATOMIC);
+}
+
+static int usbpn_close(struct net_device *dev);
+
+static int usbpn_open(struct net_device *dev)
+{
+       struct usbpn_dev *pnd = netdev_priv(dev);
+       int err;
+       unsigned i;
+       unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber;
+
+       err = usb_set_interface(pnd->usb, num, pnd->active_setting);
+       if (err)
+               return err;
+
+       for (i = 0; i < rxq_size; i++) {
+               struct urb *req = usb_alloc_urb(0, GFP_KERNEL);
+
+               if (!req || rx_submit(pnd, req, GFP_KERNEL)) {
+                       usbpn_close(dev);
+                       return -ENOMEM;
+               }
+               pnd->urbs[i] = req;
+       }
+
+       netif_wake_queue(dev);
+       return 0;
+}
+
+static int usbpn_close(struct net_device *dev)
+{
+       struct usbpn_dev *pnd = netdev_priv(dev);
+       unsigned i;
+       unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber;
+
+       netif_stop_queue(dev);
+
+       for (i = 0; i < rxq_size; i++) {
+               struct urb *req = pnd->urbs[i];
+
+               if (!req)
+                       continue;
+               usb_kill_urb(req);
+               usb_free_urb(req);
+               pnd->urbs[i] = NULL;
+       }
+
+       return usb_set_interface(pnd->usb, num, !pnd->active_setting);
+}
+
+static int usbpn_set_mtu(struct net_device *dev, int new_mtu)
+{
+       if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU))
+               return -EINVAL;
+
+       dev->mtu = new_mtu;
+       return 0;
+}
+
+static const struct net_device_ops usbpn_ops = {
+       .ndo_open       = usbpn_open,
+       .ndo_stop       = usbpn_close,
+       .ndo_start_xmit = usbpn_xmit,
+       .ndo_change_mtu = usbpn_set_mtu,
+};
+
+static void usbpn_setup(struct net_device *dev)
+{
+       dev->features           = 0;
+       dev->netdev_ops         = &usbpn_ops,
+       dev->header_ops         = &phonet_header_ops;
+       dev->type               = ARPHRD_PHONET;
+       dev->flags              = IFF_POINTOPOINT | IFF_NOARP;
+       dev->mtu                = PHONET_MAX_MTU;
+       dev->hard_header_len    = 1;
+       dev->dev_addr[0]        = PN_MEDIA_USB;
+       dev->addr_len           = 1;
+       dev->tx_queue_len       = 3;
+
+       dev->destructor         = free_netdev;
+}
+
+/*
+ * USB driver callbacks
+ */
+static struct usb_device_id usbpn_ids[] = {
+       {
+               .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+                       | USB_DEVICE_ID_MATCH_INT_CLASS
+                       | USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+               .idVendor = 0x0421, /* Nokia */
+               .bInterfaceClass = USB_CLASS_COMM,
+               .bInterfaceSubClass = 0xFE,
+       },
+       { },
+};
+
+MODULE_DEVICE_TABLE(usb, usbpn_ids);
+
+static struct usb_driver usbpn_driver;
+
+int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+       static const char ifname[] = "usbpn%d";
+       const struct usb_cdc_union_desc *union_header = NULL;
+       const struct usb_cdc_header_desc *phonet_header = NULL;
+       const struct usb_host_interface *data_desc;
+       struct usb_interface *data_intf;
+       struct usb_device *usbdev = interface_to_usbdev(intf);
+       struct net_device *dev;
+       struct usbpn_dev *pnd;
+       u8 *data;
+       int len, err;
+
+       data = intf->altsetting->extra;
+       len = intf->altsetting->extralen;
+       while (len >= 3) {
+               u8 dlen = data[0];
+               if (dlen < 3)
+                       return -EINVAL;
+
+               /* bDescriptorType */
+               if (data[1] == USB_DT_CS_INTERFACE) {
+                       /* bDescriptorSubType */
+                       switch (data[2]) {
+                       case USB_CDC_UNION_TYPE:
+                               if (union_header || dlen < 5)
+                                       break;
+                               union_header =
+                                       (struct usb_cdc_union_desc *)data;
+                               break;
+                       case 0xAB:
+                               if (phonet_header || dlen < 5)
+                                       break;
+                               phonet_header =
+                                       (struct usb_cdc_header_desc *)data;
+                               break;
+                       }
+               }
+               data += dlen;
+               len -= dlen;
+       }
+
+       if (!union_header || !phonet_header)
+               return -EINVAL;
+
+       data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0);
+       if (data_intf == NULL)
+               return -ENODEV;
+       /* Data interface has one inactive and one active setting */
+       if (data_intf->num_altsetting != 2)
+               return -EINVAL;
+       if (data_intf->altsetting[0].desc.bNumEndpoints == 0
+        && data_intf->altsetting[1].desc.bNumEndpoints == 2)
+               data_desc = data_intf->altsetting + 1;
+       else
+       if (data_intf->altsetting[0].desc.bNumEndpoints == 2
+        && data_intf->altsetting[1].desc.bNumEndpoints == 0)
+               data_desc = data_intf->altsetting;
+       else
+               return -EINVAL;
+
+       dev = alloc_netdev(sizeof(*pnd) + sizeof(pnd->urbs[0]) * rxq_size,
+                               ifname, usbpn_setup);
+       if (!dev)
+               return -ENOMEM;
+
+       pnd = netdev_priv(dev);
+       SET_NETDEV_DEV(dev, &intf->dev);
+       netif_stop_queue(dev);
+
+       pnd->dev = dev;
+       pnd->usb = usb_get_dev(usbdev);
+       pnd->intf = intf;
+       pnd->data_intf = data_intf;
+       spin_lock_init(&pnd->tx_lock);
+       spin_lock_init(&pnd->rx_lock);
+       /* Endpoints */
+       if (usb_pipein(data_desc->endpoint[0].desc.bEndpointAddress)) {
+               pnd->rx_pipe = usb_rcvbulkpipe(usbdev,
+                       data_desc->endpoint[0].desc.bEndpointAddress);
+               pnd->tx_pipe = usb_sndbulkpipe(usbdev,
+                       data_desc->endpoint[1].desc.bEndpointAddress);
+       } else {
+               pnd->rx_pipe = usb_rcvbulkpipe(usbdev,
+                       data_desc->endpoint[1].desc.bEndpointAddress);
+               pnd->tx_pipe = usb_sndbulkpipe(usbdev,
+                       data_desc->endpoint[0].desc.bEndpointAddress);
+       }
+       pnd->active_setting = data_desc - data_intf->altsetting;
+
+       err = usb_driver_claim_interface(&usbpn_driver, data_intf, pnd);
+       if (err)
+               goto out;
+
+       /* Force inactive mode until the network device is brought UP */
+       usb_set_interface(usbdev, union_header->bSlaveInterface0,
+                               !pnd->active_setting);
+       usb_set_intfdata(intf, pnd);
+
+       err = register_netdev(dev);
+       if (err) {
+               usb_driver_release_interface(&usbpn_driver, data_intf);
+               goto out;
+       }
+
+       dev_dbg(&dev->dev, "USB CDC Phonet device found\n");
+       return 0;
+
+out:
+       usb_set_intfdata(intf, NULL);
+       free_netdev(dev);
+       return err;
+}
+
+static void usbpn_disconnect(struct usb_interface *intf)
+{
+       struct usbpn_dev *pnd = usb_get_intfdata(intf);
+       struct usb_device *usb = pnd->usb;
+
+       if (pnd->disconnected)
+               return;
+
+       pnd->disconnected = 1;
+       usb_driver_release_interface(&usbpn_driver,
+                       (pnd->intf == intf) ? pnd->data_intf : pnd->intf);
+       unregister_netdev(pnd->dev);
+       usb_put_dev(usb);
+}
+
+static struct usb_driver usbpn_driver = {
+       .name =         "cdc_phonet",
+       .probe =        usbpn_probe,
+       .disconnect =   usbpn_disconnect,
+       .id_table =     usbpn_ids,
+};
+
+static int __init usbpn_init(void)
+{
+       return usb_register(&usbpn_driver);
+}
+
+static void __exit usbpn_exit(void)
+{
+       usb_deregister(&usbpn_driver);
+}
+
+module_init(usbpn_init);
+module_exit(usbpn_exit);
+
+MODULE_AUTHOR("Remi Denis-Courmont");
+MODULE_DESCRIPTION("USB CDC Phonet host interface");
+MODULE_LICENSE("GPL");
index cd35d50e46d4686982f9b285c7967cfb00a381de..45cebfb302cf438e769f0865decbf9f86a0f90b8 100644 (file)
@@ -311,7 +311,7 @@ static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                         *      bmCRC = 0       : CRC = 0xDEADBEEF
                         */
                        if (header & BIT(14))
-                               crc2 = ~crc32_le(~0, skb2->data, len);
+                               crc2 = ~crc32_le(~0, skb2->data, skb2->len);
                        else
                                crc2 = 0xdeadbeef;
 
index e0131478971829902dd2f8e836f7b17d0d74aeda..1f9ec29fce5042fc3a17f16f4a1c0708b9e6e50c 100644 (file)
@@ -999,6 +999,9 @@ static const struct net_device_ops kaweth_netdev_ops = {
        .ndo_tx_timeout =               kaweth_tx_timeout,
        .ndo_set_multicast_list =       kaweth_set_rx_mode,
        .ndo_get_stats =                kaweth_netdev_stats,
+       .ndo_change_mtu =               eth_change_mtu,
+       .ndo_set_mac_address =          eth_mac_addr,
+       .ndo_validate_addr =            eth_validate_addr,
 };
 
 static int kaweth_probe(
index 73acbd244aa106493cbdf7c3474937ee44e370f1..631d269ac980a8bb75647875dd1770241a48f5ba 100644 (file)
@@ -1493,6 +1493,9 @@ static const struct net_device_ops pegasus_netdev_ops = {
        .ndo_set_multicast_list =       pegasus_set_multicast,
        .ndo_get_stats =                pegasus_netdev_stats,
        .ndo_tx_timeout =               pegasus_tx_timeout,
+       .ndo_change_mtu =               eth_change_mtu,
+       .ndo_set_mac_address =          eth_mac_addr,
+       .ndo_validate_addr =            eth_validate_addr,
 };
 
 static struct usb_driver pegasus_driver = {
index d3489a3c4c03b28907035181134c20ccb44b9233..88c30a58b4bda50d0b5fb610916365076cbdf1c5 100644 (file)
@@ -621,6 +621,7 @@ static const struct net_device_ops rhine_netdev_ops = {
        .ndo_start_xmit          = rhine_start_tx,
        .ndo_get_stats           = rhine_get_stats,
        .ndo_set_multicast_list  = rhine_set_rx_mode,
+       .ndo_change_mtu          = eth_change_mtu,
        .ndo_validate_addr       = eth_validate_addr,
        .ndo_set_mac_address     = eth_mac_addr,
        .ndo_do_ioctl            = netdev_ioctl,
index 345593c4accbe3c2f007acd9836e66a9ff8375e0..a370e510f19f8e3800f8f30d55eda1587032bbf6 100644 (file)
@@ -2521,6 +2521,8 @@ static const struct net_device_ops orinoco_netdev_ops = {
        .ndo_start_xmit         = orinoco_xmit,
        .ndo_set_multicast_list = orinoco_set_multicast_list,
        .ndo_change_mtu         = orinoco_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
        .ndo_tx_timeout         = orinoco_tx_timeout,
        .ndo_get_stats          = orinoco_get_stats,
 };
@@ -2555,7 +2557,6 @@ struct net_device
        priv->wireless_data.spy_data = &priv->spy_data;
        dev->wireless_data = &priv->wireless_data;
 #endif
-       /* we use the default eth_mac_addr for setting the MAC addr */
 
        /* Reserve space in skb for the SNAP header */
        dev->hard_header_len += ENCAPS_OVERHEAD;
index 34b4ae0fe76041f4eda4132e1a81a54784652557..c108b1a0ce988de4fd91d905d7b26fc205c00e7d 100644 (file)
@@ -236,7 +236,6 @@ static int sport_startup(struct uart_port *port)
        int retval;
 
        pr_debug("%s enter\n", __func__);
-       memset(buffer, 20, '\0');
        snprintf(buffer, 20, "%s rx", up->name);
        retval = request_irq(up->rx_irq, sport_uart_rx_irq, IRQF_SAMPLE_RANDOM, buffer, up);
        if (retval) {
index 698048f64f5e9aa0ef49d51578460978815b1dc6..f7c24baa141673a03084e3951b80d345c205d3c6 100644 (file)
@@ -730,7 +730,6 @@ static int __devexit msm_serial_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver msm_platform_driver = {
-       .probe = msm_serial_probe,
        .remove = msm_serial_remove,
        .driver = {
                .name = "msm_serial",
index 5b15d9d8896b9b0efe08a7d44303486e6f290811..e1f89416ef8cdf6235b2cfcebdbda23ab213f7e7 100644 (file)
@@ -750,7 +750,7 @@ static int acm_tty_chars_in_buffer(struct tty_struct *tty)
 {
        struct acm *acm = tty->driver_data;
        if (!ACM_READY(acm))
-               return -EINVAL;
+               return 0;
        /*
         * This is inaccurate (overcounts), but it works.
         */
index bfc5ce000ef92e8d664407dfd62dbf0ba4592832..ccd4dd340d2cff34ed7cedcd9c108a8be5e856f6 100644 (file)
@@ -521,7 +521,7 @@ static int mos7720_chars_in_buffer(struct tty_struct *tty)
        mos7720_port = usb_get_serial_port_data(port);
        if (mos7720_port == NULL) {
                dbg("%s:leaving ...........", __func__);
-               return -ENODEV;
+               return 0;
        }
 
        for (i = 0; i < NUM_URBS; ++i) {
index 14971a926990575aa6afd30c5c364d4b7f1e8539..3bc609fe2242a574643fe84353cf9de665fc25e3 100644 (file)
@@ -727,7 +727,7 @@ static int ti_write_room(struct tty_struct *tty)
        dbg("%s - port %d", __func__, port->number);
 
        if (tport == NULL)
-               return -ENODEV;
+               return 0;
 
        spin_lock_irqsave(&tport->tp_lock, flags);
        room = ti_buf_space_avail(tport->tp_write_buf);
@@ -748,7 +748,7 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
        dbg("%s - port %d", __func__, port->number);
 
        if (tport == NULL)
-               return -ENODEV;
+               return 0;
 
        spin_lock_irqsave(&tport->tp_lock, flags);
        chars = ti_buf_data_avail(tport->tp_write_buf);
index 8afcf08eba9868710366f23058f8793d71034fdc..3b54b39401781a7b42c076b66cad74eab0ff5259 100644 (file)
@@ -1119,12 +1119,13 @@ config FB_CARILLO_RANCH
 
 config FB_INTEL
        tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && FB && PCI && X86 && AGP_INTEL
+       depends on EXPERIMENTAL && FB && PCI && X86 && AGP_INTEL && EMBEDDED
        select FB_MODE_HELPERS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        select FB_BOOT_VESA_SUPPORT if FB_INTEL = y
+       depends on !DRM_I915
        help
          This driver supports the on-board graphics built in to the Intel
           830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets.
index e641584e212e64c087cada21136b6840ff18d2e5..88716626744391a89cae97a5658fb3cc0ffbd545 100644 (file)
@@ -145,6 +145,8 @@ static int pwm_backlight_suspend(struct platform_device *pdev,
        struct backlight_device *bl = platform_get_drvdata(pdev);
        struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
 
+       if (pb->notify)
+               pb->notify(0);
        pwm_config(pb->pwm, 0, pb->period);
        pwm_disable(pb->pwm);
        return 0;
index 5c1a2c01778fe6e195df9405d0409d7a1a2a09f9..9ae9cd32bd065b1142d63c9975ad51fd1a1972e5 100644 (file)
@@ -256,8 +256,8 @@ static void fix_edid(unsigned char *edid, int fix)
 
 static int edid_checksum(unsigned char *edid)
 {
-       unsigned char i, csum = 0, all_null = 0;
-       int err = 0, fix = check_edid(edid);
+       unsigned char csum = 0, all_null = 0;
+       int i, err = 0, fix = check_edid(edid);
 
        if (fix)
                fix_edid(edid, fix);
index 193c8f0e5cc5708a8e1077c0a60bc04c3eaafd2d..bcec78ffc765b67e190d87d5fbf2c35b72e2f0eb 100644 (file)
@@ -669,7 +669,7 @@ static int __init virtio_pci_init(void)
 
        err = pci_register_driver(&virtio_pci_driver);
        if (err)
-               device_unregister(virtio_pci_root);
+               root_device_unregister(virtio_pci_root);
 
        return err;
 }
index e9f950ff86eaee3e685bd35b4eb9c17221da4cde..cdd55e0d09f8410b949f730fb1cdd6ba07db8ddd 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/watchdog.h>
 #include <linux/timer.h>
 #include <linux/uaccess.h>
+#include <linux/io.h>
 #include <mach/hardware.h>
 
 #define WDT_VERSION    "0.3"
index 6fcb1e7095cfe0a97255170656d76e3fe8ed9a30..92828281a30b9a0a449255003d6bf4468fab0512 100644 (file)
@@ -57,7 +57,7 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page)
        buffer = kmap(page);
        offset = page_offset(page);
 
-       retval = v9fs_file_readn(filp, buffer, NULL, offset, PAGE_CACHE_SIZE);
+       retval = v9fs_file_readn(filp, buffer, NULL, PAGE_CACHE_SIZE, offset);
        if (retval < 0)
                goto done;
 
index a97263be6a91d4927bef9dd8c3e834c7c251a472..0e7da7bb5d9351756f691e4ced2e0df2c56a23f6 100644 (file)
@@ -186,32 +186,7 @@ source "fs/romfs/Kconfig"
 source "fs/sysv/Kconfig"
 source "fs/ufs/Kconfig"
 source "fs/exofs/Kconfig"
-
-config NILFS2_FS
-       tristate "NILFS2 file system support (EXPERIMENTAL)"
-       depends on BLOCK && EXPERIMENTAL
-       select CRC32
-       help
-         NILFS2 is a log-structured file system (LFS) supporting continuous
-         snapshotting.  In addition to versioning capability of the entire
-         file system, users can even restore files mistakenly overwritten or
-         destroyed just a few seconds ago.  Since this file system can keep
-         consistency like conventional LFS, it achieves quick recovery after
-         system crashes.
-
-         NILFS2 creates a number of checkpoints every few seconds or per
-         synchronous write basis (unless there is no change).  Users can
-         select significant versions among continuously created checkpoints,
-         and can change them into snapshots which will be preserved for long
-         periods until they are changed back to checkpoints.  Each
-         snapshot is mountable as a read-only file system concurrently with
-         its writable mount, and this feature is convenient for online backup.
-
-         Some features including atime, extended attributes, and POSIX ACLs,
-         are not supported yet.
-
-         To compile this file system support as a module, choose M here: the
-         module will be called nilfs2.  If unsure, say N.
+source "fs/nilfs2/Kconfig"
 
 endif # MISC_FILESYSTEMS
 
index 7f19fefd3d45a2790d426e68e59f80f687b4911c..42cec2a7c0cf41aa250aa01a18df4cc67a9264f9 100644 (file)
@@ -261,6 +261,8 @@ static ssize_t cifs_stats_proc_write(struct file *file,
                                        atomic_set(&tcon->num_reads, 0);
                                        atomic_set(&tcon->num_oplock_brks, 0);
                                        atomic_set(&tcon->num_opens, 0);
+                                       atomic_set(&tcon->num_posixopens, 0);
+                                       atomic_set(&tcon->num_posixmkdirs, 0);
                                        atomic_set(&tcon->num_closes, 0);
                                        atomic_set(&tcon->num_deletes, 0);
                                        atomic_set(&tcon->num_mkdirs, 0);
@@ -347,11 +349,15 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
                                        atomic_read(&tcon->num_locks),
                                        atomic_read(&tcon->num_hardlinks),
                                        atomic_read(&tcon->num_symlinks));
-                               seq_printf(m, "\nOpens: %d Closes: %d"
+                               seq_printf(m, "\nOpens: %d Closes: %d "
                                              "Deletes: %d",
                                        atomic_read(&tcon->num_opens),
                                        atomic_read(&tcon->num_closes),
                                        atomic_read(&tcon->num_deletes));
+                               seq_printf(m, "\nPosix Opens: %d "
+                                             "Posix Mkdirs: %d",
+                                       atomic_read(&tcon->num_posixopens),
+                                       atomic_read(&tcon->num_posixmkdirs));
                                seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
                                        atomic_read(&tcon->num_mkdirs),
                                        atomic_read(&tcon->num_rmdirs));
index 63f6cdfa56387b355f0fa8f5b7ff0ae7a00c9ab0..6084d6379c03fb95ddf268e33ba903a55aa3b7c7 100644 (file)
@@ -260,6 +260,8 @@ struct cifsTconInfo {
        atomic_t num_closes;
        atomic_t num_deletes;
        atomic_t num_mkdirs;
+       atomic_t num_posixopens;
+       atomic_t num_posixmkdirs;
        atomic_t num_rmdirs;
        atomic_t num_renames;
        atomic_t num_t2renames;
index 922f5fe2084c902b75d58b42edb85af920bfc6d9..1866bc2927d4f376182e98e71182fcff345f0a71 100644 (file)
@@ -1113,7 +1113,10 @@ PsxCreat:
 psx_create_err:
        cifs_buf_release(pSMB);
 
-       cifs_stats_inc(&tcon->num_mkdirs);
+       if (posix_flags & SMB_O_DIRECTORY)
+               cifs_stats_inc(&tcon->num_posixmkdirs);
+       else
+               cifs_stats_inc(&tcon->num_posixopens);
 
        if (rc == -EAGAIN)
                goto PsxCreat;
index e16d7592116ad7dbedd557d8df37497d6370155c..9bb5c8750736e73813ac2f5e50edae28932016e3 100644 (file)
@@ -2726,6 +2726,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
 
                /* mostly informational -- no need to fail on error here */
+               kfree(tcon->nativeFileSystem);
                tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
                                                      bytes_left, is_unicode,
                                                      nls_codepage);
index 205ec95b347e3001b6cb4358b8c6539802d95bed..eb507c453c5ff7ca221f933619a085461bec3300 100644 (file)
@@ -435,7 +435,7 @@ static int search_rsb(struct dlm_ls *ls, char *name, int len, int b,
 static int find_rsb(struct dlm_ls *ls, char *name, int namelen,
                    unsigned int flags, struct dlm_rsb **r_ret)
 {
-       struct dlm_rsb *r, *tmp;
+       struct dlm_rsb *r = NULL, *tmp;
        uint32_t hash, bucket;
        int error = -EINVAL;
 
index cdb580a9c7a28352e903fa660c848826966b9dc1..618a60f03886bf75118cefbe1fa113c1733e6baf 100644 (file)
@@ -902,7 +902,7 @@ static void tcp_connect_to_sock(struct connection *con)
        int result = -EHOSTUNREACH;
        struct sockaddr_storage saddr, src_addr;
        int addr_len;
-       struct socket *sock;
+       struct socket *sock = NULL;
 
        if (con->nodeid == 0) {
                log_print("attempt to connect sock 0 foiled");
@@ -962,6 +962,8 @@ out_err:
        if (con->sock) {
                sock_release(con->sock);
                con->sock = NULL;
+       } else if (sock) {
+               sock_release(sock);
        }
        /*
         * Some errors are fatal and this list might need adjusting. For other
index 894a32d438d5094bb9f1882825f5f01f12f096d7..16f682e26c07e49493e8a667a6b36cf0cf9f6bb6 100644 (file)
@@ -353,7 +353,7 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
 {
        struct dlm_plock_info info;
        struct plock_op *op;
-       int found = 0;
+       int found = 0, do_callback = 0;
 
        if (count != sizeof(info))
                return -EINVAL;
@@ -366,21 +366,24 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
 
        spin_lock(&ops_lock);
        list_for_each_entry(op, &recv_list, list) {
-               if (op->info.fsid == info.fsid && op->info.number == info.number &&
+               if (op->info.fsid == info.fsid &&
+                   op->info.number == info.number &&
                    op->info.owner == info.owner) {
+                       struct plock_xop *xop = (struct plock_xop *)op;
                        list_del_init(&op->list);
-                       found = 1;
-                       op->done = 1;
                        memcpy(&op->info, &info, sizeof(info));
+                       if (xop->callback)
+                               do_callback = 1;
+                       else
+                               op->done = 1;
+                       found = 1;
                        break;
                }
        }
        spin_unlock(&ops_lock);
 
        if (found) {
-               struct plock_xop *xop;
-               xop = (struct plock_xop *)op;
-               if (xop->callback)
+               if (do_callback)
                        dlm_plock_callback(op);
                else
                        wake_up(&recv_wq);
index 98d6ef1c1dc067eba8a780fca4c5dac84dd1d379..148d55c14171dee39435c83d56c906c09dcd0cf8 100644 (file)
@@ -1,12 +1,11 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM gfs2
+
 #if !defined(_TRACE_GFS2_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_GFS2_H
 
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM gfs2
-#define TRACE_INCLUDE_FILE trace_gfs2
-
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
 #include <linux/dlmconstants.h>
@@ -403,5 +402,6 @@ TRACE_EVENT(gfs2_block_alloc,
 /* This part must be outside protection */
 #undef TRACE_INCLUDE_PATH
 #define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_gfs2
 #include <trace/define_trace.h>
 
index c2d061675d80724ecf1f3ae45b467f7286cf28db..8d25ccb2d51d514a27a5098cfd13ad872cb46dc8 100644 (file)
@@ -1242,20 +1242,6 @@ error:
        return error;
 }
 
-/*
- * Initialize a session.
- * Note: save the mount rsize and wsize for create_server negotiation.
- */
-static void nfs4_init_session(struct nfs_client *clp,
-                             unsigned int wsize, unsigned int rsize)
-{
-#if defined(CONFIG_NFS_V4_1)
-       if (nfs4_has_session(clp)) {
-               clp->cl_session->fc_attrs.max_rqst_sz = wsize;
-               clp->cl_session->fc_attrs.max_resp_sz = rsize;
-       }
-#endif /* CONFIG_NFS_V4_1 */
-}
 
 /*
  * Session has been established, and the client marked ready.
@@ -1350,7 +1336,9 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
        BUG_ON(!server->nfs_client->rpc_ops);
        BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
 
-       nfs4_init_session(server->nfs_client, server->wsize, server->rsize);
+       error = nfs4_init_session(server);
+       if (error < 0)
+               goto error;
 
        /* Probe the root fh to retrieve its FSID */
        error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path);
index 38d42c29fb923191e38e7fa045b05f49a808b0ab..32062c33c859496198395db435117c7c33105d3d 100644 (file)
@@ -1025,12 +1025,12 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
                                res = NULL;
                                goto out;
                        /* This turned out not to be a regular file */
-                       case -EISDIR:
                        case -ENOTDIR:
                                goto no_open;
                        case -ELOOP:
                                if (!(nd->intent.open.flags & O_NOFOLLOW))
                                        goto no_open;
+                       /* case -EISDIR: */
                        /* case -EINVAL: */
                        default:
                                goto out;
index 61bc3a32e1e25780c4b9aa896814e22945fc2842..6ea07a3c75d4942f6197e54791b7504502d3f54c 100644 (file)
@@ -220,6 +220,7 @@ extern void nfs4_destroy_session(struct nfs4_session *session);
 extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
 extern int nfs4_proc_create_session(struct nfs_client *, int reset);
 extern int nfs4_proc_destroy_session(struct nfs4_session *);
+extern int nfs4_init_session(struct nfs_server *server);
 #else /* CONFIG_NFS_v4_1 */
 static inline int nfs4_setup_sequence(struct nfs_client *clp,
                struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
@@ -227,6 +228,11 @@ static inline int nfs4_setup_sequence(struct nfs_client *clp,
 {
        return 0;
 }
+
+static inline int nfs4_init_session(struct nfs_server *server)
+{
+       return 0;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 extern struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[];
index ff0c080db59bd01f2b715a701aa256256abd136f..6917311f201c32d679772337e440ba21e807a04b 100644 (file)
@@ -2040,15 +2040,9 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
                .rpc_argp = &args,
                .rpc_resp = &res,
        };
-       int status;
 
        nfs_fattr_init(info->fattr);
-       status = nfs4_recover_expired_lease(server);
-       if (!status)
-               status = nfs4_check_client_ready(server->nfs_client);
-       if (!status)
-               status = nfs4_call_sync(server, &msg, &args, &res, 0);
-       return status;
+       return nfs4_call_sync(server, &msg, &args, &res, 0);
 }
 
 static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -4099,15 +4093,23 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
        if (request->fl_start < 0 || request->fl_end < 0)
                return -EINVAL;
 
-       if (IS_GETLK(cmd))
-               return nfs4_proc_getlk(state, F_GETLK, request);
+       if (IS_GETLK(cmd)) {
+               if (state != NULL)
+                       return nfs4_proc_getlk(state, F_GETLK, request);
+               return 0;
+       }
 
        if (!(IS_SETLK(cmd) || IS_SETLKW(cmd)))
                return -EINVAL;
 
-       if (request->fl_type == F_UNLCK)
-               return nfs4_proc_unlck(state, cmd, request);
+       if (request->fl_type == F_UNLCK) {
+               if (state != NULL)
+                       return nfs4_proc_unlck(state, cmd, request);
+               return 0;
+       }
 
+       if (state == NULL)
+               return -ENOLCK;
        do {
                status = nfs4_proc_setlk(state, cmd, request);
                if ((status != -EAGAIN) || IS_SETLK(cmd))
@@ -4793,6 +4795,22 @@ int nfs4_proc_destroy_session(struct nfs4_session *session)
        return status;
 }
 
+int nfs4_init_session(struct nfs_server *server)
+{
+       struct nfs_client *clp = server->nfs_client;
+       int ret;
+
+       if (!nfs4_has_session(clp))
+               return 0;
+
+       clp->cl_session->fc_attrs.max_rqst_sz = server->wsize;
+       clp->cl_session->fc_attrs.max_resp_sz = server->rsize;
+       ret = nfs4_recover_expired_lease(server);
+       if (!ret)
+               ret = nfs4_check_client_ready(clp);
+       return ret;
+}
+
 /*
  * Renew the cl_session lease.
  */
index b73c5a728655adef0a90751b18133c75895aac0c..65ca8c18476fb3d1e437fed82685f50d824a92c5 100644 (file)
@@ -553,6 +553,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
        INIT_LIST_HEAD(&lsp->ls_sequence.list);
        lsp->ls_seqid.sequence = &lsp->ls_sequence;
        atomic_set(&lsp->ls_count, 1);
+       lsp->ls_state = state;
        lsp->ls_owner = fl_owner;
        spin_lock(&clp->cl_lock);
        nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64);
@@ -587,7 +588,6 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_
                if (lsp != NULL)
                        break;
                if (new != NULL) {
-                       new->ls_state = state;
                        list_add(&new->ls_locks, &state->lock_states);
                        set_bit(LK_STATE_IN_USE, &state->flags);
                        lsp = new;
diff --git a/fs/nilfs2/Kconfig b/fs/nilfs2/Kconfig
new file mode 100644 (file)
index 0000000..72da095
--- /dev/null
@@ -0,0 +1,25 @@
+config NILFS2_FS
+       tristate "NILFS2 file system support (EXPERIMENTAL)"
+       depends on BLOCK && EXPERIMENTAL
+       select CRC32
+       help
+         NILFS2 is a log-structured file system (LFS) supporting continuous
+         snapshotting.  In addition to versioning capability of the entire
+         file system, users can even restore files mistakenly overwritten or
+         destroyed just a few seconds ago.  Since this file system can keep
+         consistency like conventional LFS, it achieves quick recovery after
+         system crashes.
+
+         NILFS2 creates a number of checkpoints every few seconds or per
+         synchronous write basis (unless there is no change).  Users can
+         select significant versions among continuously created checkpoints,
+         and can change them into snapshots which will be preserved for long
+         periods until they are changed back to checkpoints.  Each
+         snapshot is mountable as a read-only file system concurrently with
+         its writable mount, and this feature is convenient for online backup.
+
+         Some features including atime, extended attributes, and POSIX ACLs,
+         are not supported yet.
+
+         To compile this file system support as a module, choose M here: the
+         module will be called nilfs2.  If unsure, say N.
index f7dd21ad85a61937666eddf0ccbff66e11e6c3fd..52c4151148383c2e9cd89f891e322241e110d3c1 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -68,8 +68,8 @@ void pipe_double_lock(struct pipe_inode_info *pipe1,
                pipe_lock_nested(pipe1, I_MUTEX_PARENT);
                pipe_lock_nested(pipe2, I_MUTEX_CHILD);
        } else {
-               pipe_lock_nested(pipe2, I_MUTEX_CHILD);
-               pipe_lock_nested(pipe1, I_MUTEX_PARENT);
+               pipe_lock_nested(pipe2, I_MUTEX_PARENT);
+               pipe_lock_nested(pipe1, I_MUTEX_CHILD);
        }
 }
 
index a553f1041cf1e1fe7210c92e5be2e5159975a65d..6ad76bf5fb40dd03b03682fa561b943ad209650d 100644 (file)
@@ -30,9 +30,7 @@
  *     EXCEPTION_TABLE(...)
  *     NOTES
  *
- *     __bss_start = .;
- *     BSS_SECTION(0, 0)
- *     __bss_stop = .;
+ *     BSS_SECTION(0, 0, 0)
  *     _end = .;
  *
  *     /DISCARD/ : {
  * bss (Block Started by Symbol) - uninitialized data
  * zeroed during startup
  */
-#define SBSS                                                           \
+#define SBSS(sbss_align)                                               \
+       . = ALIGN(sbss_align);                                          \
        .sbss : AT(ADDR(.sbss) - LOAD_OFFSET) {                         \
                *(.sbss)                                                \
                *(.scommon)                                             \
 #define BSS(bss_align)                                                 \
        . = ALIGN(bss_align);                                           \
        .bss : AT(ADDR(.bss) - LOAD_OFFSET) {                           \
-               VMLINUX_SYMBOL(__bss_start) = .;                        \
                *(.bss.page_aligned)                                    \
                *(.dynbss)                                              \
                *(.bss)                                                 \
                *(COMMON)                                               \
-               VMLINUX_SYMBOL(__bss_stop) = .;                         \
        }
 
 /*
                INIT_RAM_FS                                             \
        }
 
-#define BSS_SECTION(sbss_align, bss_align)                             \
-       SBSS                                                            \
+#define BSS_SECTION(sbss_align, bss_align, stop_align)                 \
+       . = ALIGN(sbss_align);                                          \
+       VMLINUX_SYMBOL(__bss_start) = .;                                \
+       SBSS(sbss_align)                                                \
        BSS(bss_align)                                                  \
-       . = ALIGN(4);
-
+       . = ALIGN(stop_align);                                          \
+       VMLINUX_SYMBOL(__bss_stop) = .;
index 45c18672b0936dc50c04b0cb33f105376401db2b..7174818c2c13a3a561d8ab13e28f4283d02c75d1 100644 (file)
@@ -43,6 +43,7 @@
        {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4B48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9441, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9442, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x9443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9444, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x944A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9599, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV635|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x959B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV635|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95C0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x95C2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x95C4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95C5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95C6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95C7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95C9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x95C2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x95C4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95CD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95CE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
index 20a100fe2b4f3040554f3994706d8f7b238460af..3a1dbba4d3ae2da500e710387d130cd8ad5dd4c2 100644 (file)
@@ -143,12 +143,3 @@ extern void clockevents_notify(unsigned long reason, void *arg);
 #endif
 
 #endif
-
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
-extern ktime_t clockevents_get_next_event(int cpu);
-#else
-static inline ktime_t clockevents_get_next_event(int cpu)
-{
-       return (ktime_t) { .tv64 = KTIME_MAX };
-}
-#endif
index d71f7c0f931b34b63bfacde2b06d19ffc5001616..38fe59dc89aefaa97871270371f28ff74bf8ca3f 100644 (file)
@@ -89,7 +89,6 @@ struct vc_data {
        unsigned int    vc_need_wrap    : 1;
        unsigned int    vc_can_do_color : 1;
        unsigned int    vc_report_mouse : 2;
-       unsigned int    vc_kmalloced    : 1;
        unsigned char   vc_utf          : 1;    /* Unicode UTF-8 encoding */
        unsigned char   vc_utf_count;
                 int    vc_utf_char;
index 54648e625efdff605b043a3aa766be7c2c3581ee..4759917adc71ae371da1cc3a45d46b22a55d4015 100644 (file)
@@ -448,7 +448,7 @@ extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
 
 static inline void timer_stats_account_hrtimer(struct hrtimer *timer)
 {
-       if (likely(!timer->start_pid))
+       if (likely(!timer->start_site))
                return;
        timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
                                 timer->function, timer->start_comm, 0);
index 2721f07e93548150a195123bb13e02e1bfa4664b..35e7df1e9f309c7d1ee1aadce99660e969222980 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/irqflags.h>
 #include <linux/smp.h>
 #include <linux/percpu.h>
+#include <linux/hrtimer.h>
 
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
  * IRQTF_RUNTHREAD - signals that the interrupt handler thread should run
  * IRQTF_DIED      - handler thread died
  * IRQTF_WARNED    - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed
+ * IRQTF_AFFINITY  - irq thread is requested to adjust affinity
  */
 enum {
        IRQTF_RUNTHREAD,
        IRQTF_DIED,
        IRQTF_WARNED,
+       IRQTF_AFFINITY,
 };
 
 typedef irqreturn_t (*irq_handler_t)(int, void *);
@@ -517,6 +520,31 @@ extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu);
 extern void tasklet_init(struct tasklet_struct *t,
                         void (*func)(unsigned long), unsigned long data);
 
+struct tasklet_hrtimer {
+       struct hrtimer          timer;
+       struct tasklet_struct   tasklet;
+       enum hrtimer_restart    (*function)(struct hrtimer *);
+};
+
+extern void
+tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
+                    enum hrtimer_restart (*function)(struct hrtimer *),
+                    clockid_t which_clock, enum hrtimer_mode mode);
+
+static inline
+int tasklet_hrtimer_start(struct tasklet_hrtimer *ttimer, ktime_t time,
+                         const enum hrtimer_mode mode)
+{
+       return hrtimer_start(&ttimer->timer, time, mode);
+}
+
+static inline
+void tasklet_hrtimer_cancel(struct tasklet_hrtimer *ttimer)
+{
+       hrtimer_cancel(&ttimer->timer);
+       tasklet_kill(&ttimer->tasklet);
+}
+
 /*
  * Autoprobing for irqs:
  *
index 7bc1440fc47305418967134e2f65e0e23ea24572..dbf2479e808ef30e650cd23b2f52755a4cb22c37 100644 (file)
@@ -11,7 +11,7 @@
 #define LG_CLOCK_MIN_DELTA     100UL
 #define LG_CLOCK_MAX_DELTA     ULONG_MAX
 
-/*G:032 The second method of communicating with the Host is to via "struct
+/*G:031 The second method of communicating with the Host is to via "struct
  * lguest_data".  Once the Guest's initialization hypercall tells the Host where
  * this is, the Guest and Host both publish information in it. :*/
 struct lguest_data
index 3d501db36a26a52f0f960e59fc8e1a1504356c58..79b6d7fd4ac2d217bea7bfebe81b6c4b7a5b770b 100644 (file)
@@ -385,6 +385,7 @@ enum {
                                                    not multiple of 16 bytes */
        ATA_HORKAGE_FIRMWARE_WARN = (1 << 12),  /* firmware update warning */
        ATA_HORKAGE_1_5_GBPS    = (1 << 13),    /* force 1.5 Gbps */
+       ATA_HORKAGE_NOSETXFER   = (1 << 14),    /* skip SETXFER, SATA only */
 
         /* DMA mask for user DMA control: User visible values; DO NOT
            renumber */
index 5e970c7d3fd5b1c484ddc621dbbbc29921071926..bd15d7a5f5ce39474d4c845e1cb7d85bf9150bd9 100644 (file)
@@ -120,8 +120,9 @@ enum perf_counter_sample_format {
        PERF_SAMPLE_ID                          = 1U << 6,
        PERF_SAMPLE_CPU                         = 1U << 7,
        PERF_SAMPLE_PERIOD                      = 1U << 8,
+       PERF_SAMPLE_STREAM_ID                   = 1U << 9,
 
-       PERF_SAMPLE_MAX = 1U << 9,              /* non-ABI */
+       PERF_SAMPLE_MAX = 1U << 10,             /* non-ABI */
 };
 
 /*
@@ -312,16 +313,7 @@ enum perf_event_type {
         *      struct perf_event_header        header;
         *      u64                             time;
         *      u64                             id;
-        *      u64                             sample_period;
-        * };
-        */
-       PERF_EVENT_PERIOD               = 4,
-
-       /*
-        * struct {
-        *      struct perf_event_header        header;
-        *      u64                             time;
-        *      u64                             id;
+        *      u64                             stream_id;
         * };
         */
        PERF_EVENT_THROTTLE             = 5,
@@ -356,6 +348,7 @@ enum perf_event_type {
         *      { u64                   time;     } && PERF_SAMPLE_TIME
         *      { u64                   addr;     } && PERF_SAMPLE_ADDR
         *      { u64                   id;       } && PERF_SAMPLE_ID
+        *      { u64                   stream_id;} && PERF_SAMPLE_STREAM_ID
         *      { u32                   cpu, res; } && PERF_SAMPLE_CPU
         *      { u64                   period;   } && PERF_SAMPLE_PERIOD
         *
index 16a982e389fb289560d13039bfb608fd82bbdae2..3ab08e4bb6b87c608d8e58b3f37e4260c18c1f4e 100644 (file)
@@ -209,7 +209,7 @@ extern unsigned long long time_sync_thresh;
                        ((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0)
 #define task_contributes_to_load(task) \
                                ((task->state & TASK_UNINTERRUPTIBLE) != 0 && \
-                                (task->flags & PF_FROZEN) == 0)
+                                (task->flags & PF_FREEZING) == 0)
 
 #define __set_task_state(tsk, state_value)             \
        do { (tsk)->state = (state_value); } while (0)
@@ -1680,6 +1680,7 @@ extern cputime_t task_gtime(struct task_struct *p);
 #define PF_MEMALLOC    0x00000800      /* Allocating memory */
 #define PF_FLUSHER     0x00001000      /* responsible for disk writeback */
 #define PF_USED_MATH   0x00002000      /* if unset the fpu must be initialized before use */
+#define PF_FREEZING    0x00004000      /* freeze in progress. do not account to load */
 #define PF_NOFREEZE    0x00008000      /* this thread should not be frozen */
 #define PF_FROZEN      0x00010000      /* frozen for system suspend */
 #define PF_FSTRANS     0x00020000      /* inside a filesystem transaction */
index b47b3f039d147ee63cd4dbb1f99201c1e1814bb7..f2c69a2cca172aff841e6ce97656d5fa9cb412a9 100644 (file)
@@ -1342,12 +1342,12 @@ static inline int skb_network_offset(const struct sk_buff *skb)
  * shifting the start of the packet by 2 bytes. Drivers should do this
  * with:
  *
- * skb_reserve(NET_IP_ALIGN);
+ * skb_reserve(skb, NET_IP_ALIGN);
  *
  * The downside to this alignment of the IP header is that the DMA is now
  * unaligned. On some architectures the cost of an unaligned DMA is high
  * and this cost outweighs the gains made by aligning the IP header.
- * 
+ *
  * Since this trade off varies between architectures, we allow NET_IP_ALIGN
  * to be overridden.
  */
index cec79adbe3ea60934ad69f3ef00484f12b97b065..9c543d6ac535699cf8bab7a4c7209a997cc8e8d1 100644 (file)
@@ -27,6 +27,7 @@
 #define VIRTIO_NET_F_CTRL_VQ   17      /* Control channel available */
 #define VIRTIO_NET_F_CTRL_RX   18      /* Control channel RX mode support */
 #define VIRTIO_NET_F_CTRL_VLAN 19      /* Control channel VLAN filtering */
+#define VIRTIO_NET_F_CTRL_RX_EXTRA 20  /* Extra RX mode control support */
 
 #define VIRTIO_NET_S_LINK_UP   1       /* Link is up */
 
@@ -81,14 +82,19 @@ typedef __u8 virtio_net_ctrl_ack;
 #define VIRTIO_NET_ERR    1
 
 /*
- * Control the RX mode, ie. promisucous and allmulti.  PROMISC and
- * ALLMULTI commands require an "out" sg entry containing a 1 byte
- * state value, zero = disable, non-zero = enable.  These commands
- * are supported with the VIRTIO_NET_F_CTRL_RX feature.
+ * Control the RX mode, ie. promisucous, allmulti, etc...
+ * All commands require an "out" sg entry containing a 1 byte
+ * state value, zero = disable, non-zero = enable.  Commands
+ * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature.
+ * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA.
  */
 #define VIRTIO_NET_CTRL_RX    0
  #define VIRTIO_NET_CTRL_RX_PROMISC      0
  #define VIRTIO_NET_CTRL_RX_ALLMULTI     1
+ #define VIRTIO_NET_CTRL_RX_ALLUNI       2
+ #define VIRTIO_NET_CTRL_RX_NOMULTI      3
+ #define VIRTIO_NET_CTRL_RX_NOUNI        4
+ #define VIRTIO_NET_CTRL_RX_NOBCAST      5
 
 /*
  * Control the MAC filter table.
index 2c0da9239b95971b1fe4bd1aaa675fba7f4a50a9..950409dcec3d5763bf4822c4fb8599e20808c728 100644 (file)
@@ -104,15 +104,15 @@ struct net;
 
 /**
  *     struct sock_common - minimal network layer representation of sockets
+ *     @skc_node: main hash linkage for various protocol lookup tables
+ *     @skc_nulls_node: main hash linkage for UDP/UDP-Lite protocol
+ *     @skc_refcnt: reference count
+ *     @skc_hash: hash value used with various protocol lookup tables
  *     @skc_family: network address family
  *     @skc_state: Connection state
  *     @skc_reuse: %SO_REUSEADDR setting
  *     @skc_bound_dev_if: bound device index if != 0
- *     @skc_node: main hash linkage for various protocol lookup tables
- *     @skc_nulls_node: main hash linkage for UDP/UDP-Lite protocol
  *     @skc_bind_node: bind hash linkage for various protocol lookup tables
- *     @skc_refcnt: reference count
- *     @skc_hash: hash value used with various protocol lookup tables
  *     @skc_prot: protocol handlers inside a network family
  *     @skc_net: reference to the network namespace of this socket
  *
@@ -120,17 +120,21 @@ struct net;
  *     for struct sock and struct inet_timewait_sock.
  */
 struct sock_common {
-       unsigned short          skc_family;
-       volatile unsigned char  skc_state;
-       unsigned char           skc_reuse;
-       int                     skc_bound_dev_if;
+       /*
+        * first fields are not copied in sock_copy()
+        */
        union {
                struct hlist_node       skc_node;
                struct hlist_nulls_node skc_nulls_node;
        };
-       struct hlist_node       skc_bind_node;
        atomic_t                skc_refcnt;
+
        unsigned int            skc_hash;
+       unsigned short          skc_family;
+       volatile unsigned char  skc_state;
+       unsigned char           skc_reuse;
+       int                     skc_bound_dev_if;
+       struct hlist_node       skc_bind_node;
        struct proto            *skc_prot;
 #ifdef CONFIG_NET_NS
        struct net              *skc_net;
@@ -208,15 +212,17 @@ struct sock {
         * don't add nothing before this first member (__sk_common) --acme
         */
        struct sock_common      __sk_common;
+#define sk_node                        __sk_common.skc_node
+#define sk_nulls_node          __sk_common.skc_nulls_node
+#define sk_refcnt              __sk_common.skc_refcnt
+
+#define sk_copy_start          __sk_common.skc_hash
+#define sk_hash                        __sk_common.skc_hash
 #define sk_family              __sk_common.skc_family
 #define sk_state               __sk_common.skc_state
 #define sk_reuse               __sk_common.skc_reuse
 #define sk_bound_dev_if                __sk_common.skc_bound_dev_if
-#define sk_node                        __sk_common.skc_node
-#define sk_nulls_node          __sk_common.skc_nulls_node
 #define sk_bind_node           __sk_common.skc_bind_node
-#define sk_refcnt              __sk_common.skc_refcnt
-#define sk_hash                        __sk_common.skc_hash
 #define sk_prot                        __sk_common.skc_prot
 #define sk_net                 __sk_common.skc_net
        kmemcheck_bitfield_begin(flags);
index 19f4150f4d4d166380f95079c1877af28e6d62a5..88af843064710bf43e25cb6932aa40479c19e07e 100644 (file)
@@ -1425,6 +1425,11 @@ struct tcp_request_sock_ops {
 #ifdef CONFIG_TCP_MD5SIG
        struct tcp_md5sig_key   *(*md5_lookup) (struct sock *sk,
                                                struct request_sock *req);
+       int                     (*calc_md5_hash) (char *location,
+                                                 struct tcp_md5sig_key *md5,
+                                                 struct sock *sk,
+                                                 struct request_sock *req,
+                                                 struct sk_buff *skb);
 #endif
 };
 
index d6b05f42dd44d85e488eaa65c67a105e1e7ad36c..9a74b468a2291dd19e0ee3b8ad364943b3a8b4bb 100644 (file)
@@ -1,3 +1,6 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM block
+
 #if !defined(_TRACE_BLOCK_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_BLOCK_H
 
@@ -5,9 +8,6 @@
 #include <linux/blkdev.h>
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM block
-
 TRACE_EVENT(block_rq_abort,
 
        TP_PROTO(struct request_queue *q, struct request *rq),
index dfbc9b0edc880faf5ce2b270eedec2e4fab1540c..7d8b5bc741857401acf0ee81f8eaa9b98b52c1cd 100644 (file)
@@ -1,9 +1,9 @@
-#if !defined(_TRACE_EXT4_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_EXT4_H
-
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM ext4
 
+#if !defined(_TRACE_EXT4_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_EXT4_H
+
 #include <linux/writeback.h>
 #include "../../../fs/ext4/ext4.h"
 #include "../../../fs/ext4/mballoc.h"
index b0c7ede55eb156c0d4880dee2555dc4b35577887..1cb0c3aa11e613659a0a87cc9c72ea4d14f69a3f 100644 (file)
@@ -1,12 +1,12 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM irq
+
 #if !defined(_TRACE_IRQ_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_IRQ_H
 
 #include <linux/tracepoint.h>
 #include <linux/interrupt.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM irq
-
 #define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq }
 #define show_softirq_name(val)                 \
        __print_symbolic(val,                   \
index 845b0b4b48fda1077b851f44a99042d79f2e7591..10813fa0c8d07b68035b3bdc287fe0e0304a7788 100644 (file)
@@ -1,12 +1,12 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM jbd2
+
 #if !defined(_TRACE_JBD2_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_JBD2_H
 
 #include <linux/jbd2.h>
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM jbd2
-
 TRACE_EVENT(jbd2_checkpoint,
 
        TP_PROTO(journal_t *journal, int result),
index 9baba50d6512e594658485779244bbdde751916b..1493c541f9c44566a21553c5947aa1fa93fc702e 100644 (file)
@@ -1,12 +1,12 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM kmem
+
 #if !defined(_TRACE_KMEM_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_KMEM_H
 
 #include <linux/types.h>
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM kmem
-
 /*
  * The order of these masks is important. Matching masks will be seen
  * first and the left over flags will end up showing by themselves.
index 0e956c9dfd7eed1676d049ab2f1c6375983ba556..bcf1d209a00dabf7838aae49c2e5edcc5fc6dde8 100644 (file)
@@ -1,12 +1,12 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM lockdep
+
 #if !defined(_TRACE_LOCKDEP_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_LOCKDEP_H
 
 #include <linux/lockdep.h>
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM lockdep
-
 #ifdef CONFIG_LOCKDEP
 
 TRACE_EVENT(lock_acquire,
index 24ab5bcff7b2bfaebfe7ed4d544f286c43c416a3..8949bb7eb08278bbe30d6785a1e6c1902db8a99a 100644 (file)
@@ -1,12 +1,12 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM sched
+
 #if !defined(_TRACE_SCHED_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_SCHED_H
 
 #include <linux/sched.h>
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM sched
-
 /*
  * Tracepoint for calling kthread_stop, performed to end a kthread:
  */
index 1e8fabb57c06e4db8f46704153642bf873f87f77..e499863b96693b108fef4c2bc5b07fd52624ba63 100644 (file)
@@ -1,12 +1,12 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM skb
+
 #if !defined(_TRACE_SKB_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_SKB_H
 
 #include <linux/skbuff.h>
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM skb
-
 /*
  * Tracepoint for free an sk_buff:
  */
index 035f1bff288e66586c2d4697e1bc8d5e0ee9329e..fcfd9a1e4b9640a7c4d3e26c44f2aac38e3b6810 100644 (file)
@@ -1,3 +1,6 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM workqueue
+
 #if !defined(_TRACE_WORKQUEUE_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_WORKQUEUE_H
 
@@ -5,9 +8,6 @@
 #include <linux/sched.h>
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM workqueue
-
 TRACE_EVENT(workqueue_insertion,
 
        TP_PROTO(struct task_struct *wq_thread, struct work_struct *work),
index 1ce05a4cb5f6ffb945391dd93c8e7e172d511d8f..cb2c092702260def4bd2dfe8a2bb4334ea57fbb2 100644 (file)
@@ -962,7 +962,7 @@ config PERF_COUNTERS
 
 config EVENT_PROFILE
        bool "Tracepoint profile sources"
-       depends on PERF_COUNTERS && EVENT_TRACER
+       depends on PERF_COUNTERS && EVENT_TRACING
        default y
 
 endmenu
index bd2959228871d05926dbb0ddfc3b5fe4f54c59d9..9b42695f0d1484a1a7ee405b9aa73996d29da7ae 100644 (file)
@@ -1407,14 +1407,11 @@ long do_fork(unsigned long clone_flags,
                if (clone_flags & CLONE_VFORK) {
                        p->vfork_done = &vfork;
                        init_completion(&vfork);
-               } else if (!(clone_flags & CLONE_VM)) {
-                       /*
-                        * vfork will do an exec which will call
-                        * set_task_comm()
-                        */
-                       perf_counter_fork(p);
                }
 
+               if (!(clone_flags & CLONE_THREAD))
+                       perf_counter_fork(p);
+
                audit_finish_fork(p);
                tracehook_report_clone(regs, clone_flags, nr, p);
 
index 2f4936cf708367c90f3d16fe5a4d9b49ec66e90e..bd1d42b17cb2f52f5156506ba25d75376102af7f 100644 (file)
@@ -44,12 +44,19 @@ void refrigerator(void)
        recalc_sigpending(); /* We sent fake signal, clean it up */
        spin_unlock_irq(&current->sighand->siglock);
 
+       /* prevent accounting of that task to load */
+       current->flags |= PF_FREEZING;
+
        for (;;) {
                set_current_state(TASK_UNINTERRUPTIBLE);
                if (!frozen(current))
                        break;
                schedule();
        }
+
+       /* Remove the accounting blocker */
+       current->flags &= ~PF_FREEZING;
+
        pr_debug("%s left refrigerator\n", current->comm);
        __set_current_state(save);
 }
index 794c862125feff034a231d4f16a5106189625d10..0672ff88f159f3041206750b3427fdd68aa0afc1 100644 (file)
@@ -247,6 +247,7 @@ again:
        if (err < 0)
                return err;
 
+       page = compound_head(page);
        lock_page(page);
        if (!page->mapping) {
                unlock_page(page);
index 9002958a96e70ef0f8acc70ceeccac5327efae9e..49da79ab8486df682bc7f252674b4a01b810c108 100644 (file)
@@ -191,6 +191,46 @@ struct hrtimer_clock_base *lock_hrtimer_base(const struct hrtimer *timer,
        }
 }
 
+
+/*
+ * Get the preferred target CPU for NOHZ
+ */
+static int hrtimer_get_target(int this_cpu, int pinned)
+{
+#ifdef CONFIG_NO_HZ
+       if (!pinned && get_sysctl_timer_migration() && idle_cpu(this_cpu)) {
+               int preferred_cpu = get_nohz_load_balancer();
+
+               if (preferred_cpu >= 0)
+                       return preferred_cpu;
+       }
+#endif
+       return this_cpu;
+}
+
+/*
+ * With HIGHRES=y we do not migrate the timer when it is expiring
+ * before the next event on the target cpu because we cannot reprogram
+ * the target cpu hardware and we would cause it to fire late.
+ *
+ * Called with cpu_base->lock of target cpu held.
+ */
+static int
+hrtimer_check_target(struct hrtimer *timer, struct hrtimer_clock_base *new_base)
+{
+#ifdef CONFIG_HIGH_RES_TIMERS
+       ktime_t expires;
+
+       if (!new_base->cpu_base->hres_active)
+               return 0;
+
+       expires = ktime_sub(hrtimer_get_expires(timer), new_base->offset);
+       return expires.tv64 <= new_base->cpu_base->expires_next.tv64;
+#else
+       return 0;
+#endif
+}
+
 /*
  * Switch the timer base to the current CPU when possible.
  */
@@ -200,16 +240,8 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
 {
        struct hrtimer_clock_base *new_base;
        struct hrtimer_cpu_base *new_cpu_base;
-       int cpu, preferred_cpu = -1;
-
-       cpu = smp_processor_id();
-#if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP)
-       if (!pinned && get_sysctl_timer_migration() && idle_cpu(cpu)) {
-               preferred_cpu = get_nohz_load_balancer();
-               if (preferred_cpu >= 0)
-                       cpu = preferred_cpu;
-       }
-#endif
+       int this_cpu = smp_processor_id();
+       int cpu = hrtimer_get_target(this_cpu, pinned);
 
 again:
        new_cpu_base = &per_cpu(hrtimer_bases, cpu);
@@ -217,7 +249,7 @@ again:
 
        if (base != new_base) {
                /*
-                * We are trying to schedule the timer on the local CPU.
+                * We are trying to move timer to new_base.
                 * However we can't change timer's base while it is running,
                 * so we keep it on the same CPU. No hassle vs. reprogramming
                 * the event source in the high resolution case. The softirq
@@ -233,38 +265,12 @@ again:
                spin_unlock(&base->cpu_base->lock);
                spin_lock(&new_base->cpu_base->lock);
 
-               /* Optimized away for NOHZ=n SMP=n */
-               if (cpu == preferred_cpu) {
-                       /* Calculate clock monotonic expiry time */
-#ifdef CONFIG_HIGH_RES_TIMERS
-                       ktime_t expires = ktime_sub(hrtimer_get_expires(timer),
-                                                       new_base->offset);
-#else
-                       ktime_t expires = hrtimer_get_expires(timer);
-#endif
-
-                       /*
-                        * Get the next event on target cpu from the
-                        * clock events layer.
-                        * This covers the highres=off nohz=on case as well.
-                        */
-                       ktime_t next = clockevents_get_next_event(cpu);
-
-                       ktime_t delta = ktime_sub(expires, next);
-
-                       /*
-                        * We do not migrate the timer when it is expiring
-                        * before the next event on the target cpu because
-                        * we cannot reprogram the target cpu hardware and
-                        * we would cause it to fire late.
-                        */
-                       if (delta.tv64 < 0) {
-                               cpu = smp_processor_id();
-                               spin_unlock(&new_base->cpu_base->lock);
-                               spin_lock(&base->cpu_base->lock);
-                               timer->base = base;
-                               goto again;
-                       }
+               if (cpu != this_cpu && hrtimer_check_target(timer, new_base)) {
+                       cpu = this_cpu;
+                       spin_unlock(&new_base->cpu_base->lock);
+                       spin_lock(&base->cpu_base->lock);
+                       timer->base = base;
+                       goto again;
                }
                timer->base = new_base;
        }
@@ -1276,14 +1282,22 @@ void hrtimer_interrupt(struct clock_event_device *dev)
 
        expires_next.tv64 = KTIME_MAX;
 
+       spin_lock(&cpu_base->lock);
+       /*
+        * We set expires_next to KTIME_MAX here with cpu_base->lock
+        * held to prevent that a timer is enqueued in our queue via
+        * the migration code. This does not affect enqueueing of
+        * timers which run their callback and need to be requeued on
+        * this CPU.
+        */
+       cpu_base->expires_next.tv64 = KTIME_MAX;
+
        base = cpu_base->clock_base;
 
        for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
                ktime_t basenow;
                struct rb_node *node;
 
-               spin_lock(&cpu_base->lock);
-
                basenow = ktime_add(now, base->offset);
 
                while ((node = base->first)) {
@@ -1316,11 +1330,15 @@ void hrtimer_interrupt(struct clock_event_device *dev)
 
                        __run_hrtimer(timer);
                }
-               spin_unlock(&cpu_base->lock);
                base++;
        }
 
+       /*
+        * Store the new expiry value so the migration code can verify
+        * against it.
+        */
        cpu_base->expires_next = expires_next;
+       spin_unlock(&cpu_base->lock);
 
        /* Reprogramming necessary ? */
        if (expires_next.tv64 != KTIME_MAX) {
index 73468253143ba55883072d1020791c11b1e30210..e70ed5592eb90e406c201e5d2881be679a5fc278 100644 (file)
@@ -42,8 +42,7 @@ static inline void unregister_handler_proc(unsigned int irq,
 
 extern int irq_select_affinity_usr(unsigned int irq);
 
-extern void
-irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask);
+extern void irq_set_thread_affinity(struct irq_desc *desc);
 
 /*
  * Debugging printout:
index 50da676729013dfe8dbc7929a4fdec16412f7780..61c679db4687a853c52f7d5b23b5ba5e267b4c17 100644 (file)
@@ -80,14 +80,22 @@ int irq_can_set_affinity(unsigned int irq)
        return 1;
 }
 
-void
-irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask)
+/**
+ *     irq_set_thread_affinity - Notify irq threads to adjust affinity
+ *     @desc:          irq descriptor which has affitnity changed
+ *
+ *     We just set IRQTF_AFFINITY and delegate the affinity setting
+ *     to the interrupt thread itself. We can not call
+ *     set_cpus_allowed_ptr() here as we hold desc->lock and this
+ *     code can be called from hard interrupt context.
+ */
+void irq_set_thread_affinity(struct irq_desc *desc)
 {
        struct irqaction *action = desc->action;
 
        while (action) {
                if (action->thread)
-                       set_cpus_allowed_ptr(action->thread, cpumask);
+                       set_bit(IRQTF_AFFINITY, &action->thread_flags);
                action = action->next;
        }
 }
@@ -112,7 +120,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
        if (desc->status & IRQ_MOVE_PCNTXT) {
                if (!desc->chip->set_affinity(irq, cpumask)) {
                        cpumask_copy(desc->affinity, cpumask);
-                       irq_set_thread_affinity(desc, cpumask);
+                       irq_set_thread_affinity(desc);
                }
        }
        else {
@@ -122,7 +130,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 #else
        if (!desc->chip->set_affinity(irq, cpumask)) {
                cpumask_copy(desc->affinity, cpumask);
-               irq_set_thread_affinity(desc, cpumask);
+               irq_set_thread_affinity(desc);
        }
 #endif
        desc->status |= IRQ_AFFINITY_SET;
@@ -176,7 +184,7 @@ int irq_select_affinity_usr(unsigned int irq)
        spin_lock_irqsave(&desc->lock, flags);
        ret = setup_affinity(irq, desc);
        if (!ret)
-               irq_set_thread_affinity(desc, desc->affinity);
+               irq_set_thread_affinity(desc);
        spin_unlock_irqrestore(&desc->lock, flags);
 
        return ret;
@@ -443,6 +451,39 @@ static int irq_wait_for_interrupt(struct irqaction *action)
        return -1;
 }
 
+#ifdef CONFIG_SMP
+/*
+ * Check whether we need to change the affinity of the interrupt thread.
+ */
+static void
+irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
+{
+       cpumask_var_t mask;
+
+       if (!test_and_clear_bit(IRQTF_AFFINITY, &action->thread_flags))
+               return;
+
+       /*
+        * In case we are out of memory we set IRQTF_AFFINITY again and
+        * try again next time
+        */
+       if (!alloc_cpumask_var(&mask, GFP_KERNEL)) {
+               set_bit(IRQTF_AFFINITY, &action->thread_flags);
+               return;
+       }
+
+       spin_lock_irq(&desc->lock);
+       cpumask_copy(mask, desc->affinity);
+       spin_unlock_irq(&desc->lock);
+
+       set_cpus_allowed_ptr(current, mask);
+       free_cpumask_var(mask);
+}
+#else
+static inline void
+irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { }
+#endif
+
 /*
  * Interrupt handler thread
  */
@@ -458,6 +499,8 @@ static int irq_thread(void *data)
 
        while (!irq_wait_for_interrupt(action)) {
 
+               irq_thread_check_affinity(desc, action);
+
                atomic_inc(&desc->threads_active);
 
                spin_lock_irq(&desc->lock);
index cfe767ca154501460f9f7e757c08d881611e9c95..fcb6c96f2627297654e9c3336e7f349846205752 100644 (file)
@@ -45,7 +45,7 @@ void move_masked_irq(int irq)
                   < nr_cpu_ids))
                if (!desc->chip->set_affinity(irq, desc->pending_mask)) {
                        cpumask_copy(desc->affinity, desc->pending_mask);
-                       irq_set_thread_affinity(desc, desc->pending_mask);
+                       irq_set_thread_affinity(desc);
                }
 
        cpumask_clear(desc->pending_mask);
index a641eb753b8cc92b664966e3a6932c595f07b111..9509310419545e03d015f851169436921c2fbeb3 100644 (file)
@@ -146,6 +146,28 @@ static void put_ctx(struct perf_counter_context *ctx)
        }
 }
 
+static void unclone_ctx(struct perf_counter_context *ctx)
+{
+       if (ctx->parent_ctx) {
+               put_ctx(ctx->parent_ctx);
+               ctx->parent_ctx = NULL;
+       }
+}
+
+/*
+ * If we inherit counters we want to return the parent counter id
+ * to userspace.
+ */
+static u64 primary_counter_id(struct perf_counter *counter)
+{
+       u64 id = counter->id;
+
+       if (counter->parent)
+               id = counter->parent->id;
+
+       return id;
+}
+
 /*
  * Get the perf_counter_context for a task and lock it.
  * This has to cope with with the fact that until it is locked,
@@ -1288,7 +1310,6 @@ static void perf_counter_cpu_sched_in(struct perf_cpu_context *cpuctx, int cpu)
 #define MAX_INTERRUPTS (~0ULL)
 
 static void perf_log_throttle(struct perf_counter *counter, int enable);
-static void perf_log_period(struct perf_counter *counter, u64 period);
 
 static void perf_adjust_period(struct perf_counter *counter, u64 events)
 {
@@ -1307,8 +1328,6 @@ static void perf_adjust_period(struct perf_counter *counter, u64 events)
        if (!sample_period)
                sample_period = 1;
 
-       perf_log_period(counter, sample_period);
-
        hwc->sample_period = sample_period;
 }
 
@@ -1463,10 +1482,8 @@ static void perf_counter_enable_on_exec(struct task_struct *task)
        /*
         * Unclone this context if we enabled any counter.
         */
-       if (enabled && ctx->parent_ctx) {
-               put_ctx(ctx->parent_ctx);
-               ctx->parent_ctx = NULL;
-       }
+       if (enabled)
+               unclone_ctx(ctx);
 
        spin_unlock(&ctx->lock);
 
@@ -1526,7 +1543,6 @@ __perf_counter_init_context(struct perf_counter_context *ctx,
 
 static struct perf_counter_context *find_get_context(pid_t pid, int cpu)
 {
-       struct perf_counter_context *parent_ctx;
        struct perf_counter_context *ctx;
        struct perf_cpu_context *cpuctx;
        struct task_struct *task;
@@ -1586,11 +1602,7 @@ static struct perf_counter_context *find_get_context(pid_t pid, int cpu)
  retry:
        ctx = perf_lock_task_context(task, &flags);
        if (ctx) {
-               parent_ctx = ctx->parent_ctx;
-               if (parent_ctx) {
-                       put_ctx(parent_ctx);
-                       ctx->parent_ctx = NULL;         /* no longer a clone */
-               }
+               unclone_ctx(ctx);
                spin_unlock_irqrestore(&ctx->lock, flags);
        }
 
@@ -1704,7 +1716,7 @@ perf_read_hw(struct perf_counter *counter, char __user *buf, size_t count)
                values[n++] = counter->total_time_running +
                        atomic64_read(&counter->child_total_time_running);
        if (counter->attr.read_format & PERF_FORMAT_ID)
-               values[n++] = counter->id;
+               values[n++] = primary_counter_id(counter);
        mutex_unlock(&counter->child_mutex);
 
        if (count < n * sizeof(u64))
@@ -1811,8 +1823,6 @@ static int perf_counter_period(struct perf_counter *counter, u64 __user *arg)
 
                counter->attr.sample_freq = value;
        } else {
-               perf_log_period(counter, value);
-
                counter->attr.sample_period = value;
                counter->hw.sample_period = value;
        }
@@ -2661,10 +2671,14 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
        if (sample_type & PERF_SAMPLE_ID)
                header.size += sizeof(u64);
 
+       if (sample_type & PERF_SAMPLE_STREAM_ID)
+               header.size += sizeof(u64);
+
        if (sample_type & PERF_SAMPLE_CPU) {
                header.size += sizeof(cpu_entry);
 
                cpu_entry.cpu = raw_smp_processor_id();
+               cpu_entry.reserved = 0;
        }
 
        if (sample_type & PERF_SAMPLE_PERIOD)
@@ -2703,7 +2717,13 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
        if (sample_type & PERF_SAMPLE_ADDR)
                perf_output_put(&handle, data->addr);
 
-       if (sample_type & PERF_SAMPLE_ID)
+       if (sample_type & PERF_SAMPLE_ID) {
+               u64 id = primary_counter_id(counter);
+
+               perf_output_put(&handle, id);
+       }
+
+       if (sample_type & PERF_SAMPLE_STREAM_ID)
                perf_output_put(&handle, counter->id);
 
        if (sample_type & PERF_SAMPLE_CPU)
@@ -2726,7 +2746,7 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
                        if (sub != counter)
                                sub->pmu->read(sub);
 
-                       group_entry.id = sub->id;
+                       group_entry.id = primary_counter_id(sub);
                        group_entry.counter = atomic64_read(&sub->count);
 
                        perf_output_put(&handle, group_entry);
@@ -2786,15 +2806,8 @@ perf_counter_read_event(struct perf_counter *counter,
        }
 
        if (counter->attr.read_format & PERF_FORMAT_ID) {
-               u64 id;
-
                event.header.size += sizeof(u64);
-               if (counter->parent)
-                       id = counter->parent->id;
-               else
-                       id = counter->id;
-
-               event.format[i++] = id;
+               event.format[i++] = primary_counter_id(counter);
        }
 
        ret = perf_output_begin(&handle, counter, event.header.size, 0, 0);
@@ -2895,8 +2908,11 @@ void perf_counter_fork(struct task_struct *task)
                .event  = {
                        .header = {
                                .type = PERF_EVENT_FORK,
+                               .misc = 0,
                                .size = sizeof(fork_event.event),
                        },
+                       /* .pid  */
+                       /* .ppid */
                },
        };
 
@@ -2968,8 +2984,10 @@ static void perf_counter_comm_event(struct perf_comm_event *comm_event)
        struct perf_cpu_context *cpuctx;
        struct perf_counter_context *ctx;
        unsigned int size;
-       char *comm = comm_event->task->comm;
+       char comm[TASK_COMM_LEN];
 
+       memset(comm, 0, sizeof(comm));
+       strncpy(comm, comm_event->task->comm, sizeof(comm));
        size = ALIGN(strlen(comm)+1, sizeof(u64));
 
        comm_event->comm = comm;
@@ -3004,8 +3022,16 @@ void perf_counter_comm(struct task_struct *task)
 
        comm_event = (struct perf_comm_event){
                .task   = task,
+               /* .comm      */
+               /* .comm_size */
                .event  = {
-                       .header = { .type = PERF_EVENT_COMM, },
+                       .header = {
+                               .type = PERF_EVENT_COMM,
+                               .misc = 0,
+                               /* .size */
+                       },
+                       /* .pid */
+                       /* .tid */
                },
        };
 
@@ -3088,8 +3114,15 @@ static void perf_counter_mmap_event(struct perf_mmap_event *mmap_event)
        char *buf = NULL;
        const char *name;
 
+       memset(tmp, 0, sizeof(tmp));
+
        if (file) {
-               buf = kzalloc(PATH_MAX, GFP_KERNEL);
+               /*
+                * d_path works from the end of the buffer backwards, so we
+                * need to add enough zero bytes after the string to handle
+                * the 64bit alignment we do later.
+                */
+               buf = kzalloc(PATH_MAX + sizeof(u64), GFP_KERNEL);
                if (!buf) {
                        name = strncpy(tmp, "//enomem", sizeof(tmp));
                        goto got_name;
@@ -3100,9 +3133,11 @@ static void perf_counter_mmap_event(struct perf_mmap_event *mmap_event)
                        goto got_name;
                }
        } else {
-               name = arch_vma_name(mmap_event->vma);
-               if (name)
+               if (arch_vma_name(mmap_event->vma)) {
+                       name = strncpy(tmp, arch_vma_name(mmap_event->vma),
+                                      sizeof(tmp));
                        goto got_name;
+               }
 
                if (!vma->vm_mm) {
                        name = strncpy(tmp, "[vdso]", sizeof(tmp));
@@ -3147,8 +3182,16 @@ void __perf_counter_mmap(struct vm_area_struct *vma)
 
        mmap_event = (struct perf_mmap_event){
                .vma    = vma,
+               /* .file_name */
+               /* .file_size */
                .event  = {
-                       .header = { .type = PERF_EVENT_MMAP, },
+                       .header = {
+                               .type = PERF_EVENT_MMAP,
+                               .misc = 0,
+                               /* .size */
+                       },
+                       /* .pid */
+                       /* .tid */
                        .start  = vma->vm_start,
                        .len    = vma->vm_end - vma->vm_start,
                        .pgoff  = vma->vm_pgoff,
@@ -3158,49 +3201,6 @@ void __perf_counter_mmap(struct vm_area_struct *vma)
        perf_counter_mmap_event(&mmap_event);
 }
 
-/*
- * Log sample_period changes so that analyzing tools can re-normalize the
- * event flow.
- */
-
-struct freq_event {
-       struct perf_event_header        header;
-       u64                             time;
-       u64                             id;
-       u64                             period;
-};
-
-static void perf_log_period(struct perf_counter *counter, u64 period)
-{
-       struct perf_output_handle handle;
-       struct freq_event event;
-       int ret;
-
-       if (counter->hw.sample_period == period)
-               return;
-
-       if (counter->attr.sample_type & PERF_SAMPLE_PERIOD)
-               return;
-
-       event = (struct freq_event) {
-               .header = {
-                       .type = PERF_EVENT_PERIOD,
-                       .misc = 0,
-                       .size = sizeof(event),
-               },
-               .time = sched_clock(),
-               .id = counter->id,
-               .period = period,
-       };
-
-       ret = perf_output_begin(&handle, counter, sizeof(event), 1, 0);
-       if (ret)
-               return;
-
-       perf_output_put(&handle, event);
-       perf_output_end(&handle);
-}
-
 /*
  * IRQ throttle logging
  */
@@ -3214,16 +3214,21 @@ static void perf_log_throttle(struct perf_counter *counter, int enable)
                struct perf_event_header        header;
                u64                             time;
                u64                             id;
+               u64                             stream_id;
        } throttle_event = {
                .header = {
-                       .type = PERF_EVENT_THROTTLE + 1,
+                       .type = PERF_EVENT_THROTTLE,
                        .misc = 0,
                        .size = sizeof(throttle_event),
                },
-               .time   = sched_clock(),
-               .id     = counter->id,
+               .time           = sched_clock(),
+               .id             = primary_counter_id(counter),
+               .stream_id      = counter->id,
        };
 
+       if (enable)
+               throttle_event.header.type = PERF_EVENT_UNTHROTTLE;
+
        ret = perf_output_begin(&handle, counter, sizeof(throttle_event), 1, 0);
        if (ret)
                return;
@@ -3671,7 +3676,7 @@ static const struct pmu perf_ops_task_clock = {
 void perf_tpcounter_event(int event_id)
 {
        struct perf_sample_data data = {
-               .regs = get_irq_regs();
+               .regs = get_irq_regs(),
                .addr = 0,
        };
 
@@ -3687,16 +3692,12 @@ extern void ftrace_profile_disable(int);
 
 static void tp_perf_counter_destroy(struct perf_counter *counter)
 {
-       ftrace_profile_disable(perf_event_id(&counter->attr));
+       ftrace_profile_disable(counter->attr.config);
 }
 
 static const struct pmu *tp_perf_counter_init(struct perf_counter *counter)
 {
-       int event_id = perf_event_id(&counter->attr);
-       int ret;
-
-       ret = ftrace_profile_enable(event_id);
-       if (ret)
+       if (ftrace_profile_enable(counter->attr.config))
                return NULL;
 
        counter->destroy = tp_perf_counter_destroy;
@@ -4255,15 +4256,12 @@ void perf_counter_exit_task(struct task_struct *child)
         */
        spin_lock(&child_ctx->lock);
        child->perf_counter_ctxp = NULL;
-       if (child_ctx->parent_ctx) {
-               /*
-                * This context is a clone; unclone it so it can't get
-                * swapped to another process while we're removing all
-                * the counters from it.
-                */
-               put_ctx(child_ctx->parent_ctx);
-               child_ctx->parent_ctx = NULL;
-       }
+       /*
+        * If this context is a clone; unclone it so it can't get
+        * swapped to another process while we're removing all
+        * the counters from it.
+        */
+       unclone_ctx(child_ctx);
        spin_unlock(&child_ctx->lock);
        local_irq_restore(flags);
 
index 01f55ada3598a8e46dd25f7953660d69fc5258ee..1b59e265273b032d6aac2baec9b059646ca563bf 100644 (file)
@@ -493,6 +493,7 @@ struct rt_rq {
 #endif
 #ifdef CONFIG_SMP
        unsigned long rt_nr_migratory;
+       unsigned long rt_nr_total;
        int overloaded;
        struct plist_head pushable_tasks;
 #endif
@@ -2571,15 +2572,37 @@ static void __sched_fork(struct task_struct *p)
        p->se.avg_wakeup                = sysctl_sched_wakeup_granularity;
 
 #ifdef CONFIG_SCHEDSTATS
-       p->se.wait_start                = 0;
-       p->se.sum_sleep_runtime         = 0;
-       p->se.sleep_start               = 0;
-       p->se.block_start               = 0;
-       p->se.sleep_max                 = 0;
-       p->se.block_max                 = 0;
-       p->se.exec_max                  = 0;
-       p->se.slice_max                 = 0;
-       p->se.wait_max                  = 0;
+       p->se.wait_start                        = 0;
+       p->se.wait_max                          = 0;
+       p->se.wait_count                        = 0;
+       p->se.wait_sum                          = 0;
+
+       p->se.sleep_start                       = 0;
+       p->se.sleep_max                         = 0;
+       p->se.sum_sleep_runtime                 = 0;
+
+       p->se.block_start                       = 0;
+       p->se.block_max                         = 0;
+       p->se.exec_max                          = 0;
+       p->se.slice_max                         = 0;
+
+       p->se.nr_migrations_cold                = 0;
+       p->se.nr_failed_migrations_affine       = 0;
+       p->se.nr_failed_migrations_running      = 0;
+       p->se.nr_failed_migrations_hot          = 0;
+       p->se.nr_forced_migrations              = 0;
+       p->se.nr_forced2_migrations             = 0;
+
+       p->se.nr_wakeups                        = 0;
+       p->se.nr_wakeups_sync                   = 0;
+       p->se.nr_wakeups_migrate                = 0;
+       p->se.nr_wakeups_local                  = 0;
+       p->se.nr_wakeups_remote                 = 0;
+       p->se.nr_wakeups_affine                 = 0;
+       p->se.nr_wakeups_affine_attempts        = 0;
+       p->se.nr_wakeups_passive                = 0;
+       p->se.nr_wakeups_idle                   = 0;
+
 #endif
 
        INIT_LIST_HEAD(&p->rt.run_list);
@@ -7266,6 +7289,7 @@ static void migrate_dead_tasks(unsigned int dead_cpu)
 static void calc_global_load_remove(struct rq *rq)
 {
        atomic_long_sub(rq->calc_load_active, &calc_load_tasks);
+       rq->calc_load_active = 0;
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
@@ -7492,6 +7516,7 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
                task_rq_unlock(rq, &flags);
                get_task_struct(p);
                cpu_rq(cpu)->migration_thread = p;
+               rq->calc_load_update = calc_load_update;
                break;
 
        case CPU_ONLINE:
@@ -7502,8 +7527,6 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
                /* Update our root-domain */
                rq = cpu_rq(cpu);
                spin_lock_irqsave(&rq->lock, flags);
-               rq->calc_load_update = calc_load_update;
-               rq->calc_load_active = 0;
                if (rq->rd) {
                        BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
 
@@ -9074,7 +9097,7 @@ static void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq)
 #ifdef CONFIG_SMP
        rt_rq->rt_nr_migratory = 0;
        rt_rq->overloaded = 0;
-       plist_head_init(&rq->rt.pushable_tasks, &rq->lock);
+       plist_head_init(&rt_rq->pushable_tasks, &rq->lock);
 #endif
 
        rt_rq->rt_time = 0;
index ba7fd6e9556f892dd941ecdd9e77be225929c251..9ffb2b2ceba484145b7e2f2a260c311c7eb32921 100644 (file)
@@ -266,6 +266,12 @@ static inline u64 min_vruntime(u64 min_vruntime, u64 vruntime)
        return min_vruntime;
 }
 
+static inline int entity_before(struct sched_entity *a,
+                               struct sched_entity *b)
+{
+       return (s64)(a->vruntime - b->vruntime) < 0;
+}
+
 static inline s64 entity_key(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
        return se->vruntime - cfs_rq->min_vruntime;
@@ -687,7 +693,8 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
                         * all of which have the same weight.
                         */
                        if (sched_feat(NORMALIZED_SLEEPER) &&
-                                       task_of(se)->policy != SCHED_IDLE)
+                                       (!entity_is_task(se) ||
+                                        task_of(se)->policy != SCHED_IDLE))
                                thresh = calc_delta_fair(thresh, se);
 
                        vruntime -= thresh;
@@ -1016,7 +1023,7 @@ static void yield_task_fair(struct rq *rq)
        /*
         * Already in the rightmost position?
         */
-       if (unlikely(!rightmost || rightmost->vruntime < se->vruntime))
+       if (unlikely(!rightmost || entity_before(rightmost, se)))
                return;
 
        /*
@@ -1712,7 +1719,7 @@ static void task_new_fair(struct rq *rq, struct task_struct *p)
 
        /* 'curr' will be NULL if the child belongs to a different group */
        if (sysctl_sched_child_runs_first && this_cpu == task_cpu(p) &&
-                       curr && curr->vruntime < se->vruntime) {
+                       curr && entity_before(curr, se)) {
                /*
                 * Upon rescheduling, sched_class::put_prev_task() will place
                 * 'current' within the tree based on its new key value.
index 9bf0d2a7304569a87ba4aa0c919bbb2531c39c06..3918e01994e0a92bd734d22eebef7047e0a17a57 100644 (file)
@@ -10,6 +10,8 @@ static inline struct task_struct *rt_task_of(struct sched_rt_entity *rt_se)
 
 #ifdef CONFIG_RT_GROUP_SCHED
 
+#define rt_entity_is_task(rt_se) (!(rt_se)->my_q)
+
 static inline struct rq *rq_of_rt_rq(struct rt_rq *rt_rq)
 {
        return rt_rq->rq;
@@ -22,6 +24,8 @@ static inline struct rt_rq *rt_rq_of_se(struct sched_rt_entity *rt_se)
 
 #else /* CONFIG_RT_GROUP_SCHED */
 
+#define rt_entity_is_task(rt_se) (1)
+
 static inline struct rq *rq_of_rt_rq(struct rt_rq *rt_rq)
 {
        return container_of(rt_rq, struct rq, rt);
@@ -73,7 +77,7 @@ static inline void rt_clear_overload(struct rq *rq)
 
 static void update_rt_migration(struct rt_rq *rt_rq)
 {
-       if (rt_rq->rt_nr_migratory && (rt_rq->rt_nr_running > 1)) {
+       if (rt_rq->rt_nr_migratory && rt_rq->rt_nr_total > 1) {
                if (!rt_rq->overloaded) {
                        rt_set_overload(rq_of_rt_rq(rt_rq));
                        rt_rq->overloaded = 1;
@@ -86,6 +90,12 @@ static void update_rt_migration(struct rt_rq *rt_rq)
 
 static void inc_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
 {
+       if (!rt_entity_is_task(rt_se))
+               return;
+
+       rt_rq = &rq_of_rt_rq(rt_rq)->rt;
+
+       rt_rq->rt_nr_total++;
        if (rt_se->nr_cpus_allowed > 1)
                rt_rq->rt_nr_migratory++;
 
@@ -94,6 +104,12 @@ static void inc_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
 
 static void dec_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
 {
+       if (!rt_entity_is_task(rt_se))
+               return;
+
+       rt_rq = &rq_of_rt_rq(rt_rq)->rt;
+
+       rt_rq->rt_nr_total--;
        if (rt_se->nr_cpus_allowed > 1)
                rt_rq->rt_nr_migratory--;
 
index 3a94905fa5d27c4d0ef59ad56e83ad353e14f1fa..eb5e131a048528163c01930a413db3b4676e5c7c 100644 (file)
@@ -345,7 +345,9 @@ void open_softirq(int nr, void (*action)(struct softirq_action *))
        softirq_vec[nr].action = action;
 }
 
-/* Tasklets */
+/*
+ * Tasklets
+ */
 struct tasklet_head
 {
        struct tasklet_struct *head;
@@ -493,6 +495,66 @@ void tasklet_kill(struct tasklet_struct *t)
 
 EXPORT_SYMBOL(tasklet_kill);
 
+/*
+ * tasklet_hrtimer
+ */
+
+/*
+ * The trampoline is called when the hrtimer expires. If this is
+ * called from the hrtimer interrupt then we schedule the tasklet as
+ * the timer callback function expects to run in softirq context. If
+ * it's called in softirq context anyway (i.e. high resolution timers
+ * disabled) then the hrtimer callback is called right away.
+ */
+static enum hrtimer_restart __hrtimer_tasklet_trampoline(struct hrtimer *timer)
+{
+       struct tasklet_hrtimer *ttimer =
+               container_of(timer, struct tasklet_hrtimer, timer);
+
+       if (hrtimer_is_hres_active(timer)) {
+               tasklet_hi_schedule(&ttimer->tasklet);
+               return HRTIMER_NORESTART;
+       }
+       return ttimer->function(timer);
+}
+
+/*
+ * Helper function which calls the hrtimer callback from
+ * tasklet/softirq context
+ */
+static void __tasklet_hrtimer_trampoline(unsigned long data)
+{
+       struct tasklet_hrtimer *ttimer = (void *)data;
+       enum hrtimer_restart restart;
+
+       restart = ttimer->function(&ttimer->timer);
+       if (restart != HRTIMER_NORESTART)
+               hrtimer_restart(&ttimer->timer);
+}
+
+/**
+ * tasklet_hrtimer_init - Init a tasklet/hrtimer combo for softirq callbacks
+ * @ttimer:     tasklet_hrtimer which is initialized
+ * @function:   hrtimer callback funtion which gets called from softirq context
+ * @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME)
+ * @mode:       hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL)
+ */
+void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
+                         enum hrtimer_restart (*function)(struct hrtimer *),
+                         clockid_t which_clock, enum hrtimer_mode mode)
+{
+       hrtimer_init(&ttimer->timer, which_clock, mode);
+       ttimer->timer.function = __hrtimer_tasklet_trampoline;
+       tasklet_init(&ttimer->tasklet, __tasklet_hrtimer_trampoline,
+                    (unsigned long)ttimer);
+       ttimer->function = function;
+}
+EXPORT_SYMBOL_GPL(tasklet_hrtimer_init);
+
+/*
+ * Remote softirq bits
+ */
+
 DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);
 EXPORT_PER_CPU_SYMBOL(softirq_work_list);
 
index 1ad6dd46111920d10c5d83f2f90c1aeeb81ca66d..a6dcd67b041d200fc61f2b2de06890e8a5c65443 100644 (file)
@@ -254,15 +254,4 @@ void clockevents_notify(unsigned long reason, void *arg)
        spin_unlock(&clockevents_lock);
 }
 EXPORT_SYMBOL_GPL(clockevents_notify);
-
-ktime_t clockevents_get_next_event(int cpu)
-{
-       struct tick_device *td;
-       struct clock_event_device *dev;
-
-       td = &per_cpu(tick_cpu_device, cpu);
-       dev = td->evtdev;
-
-       return dev->next_event;
-}
 #endif
index 592bf584d1d2b5fa86a7fb605e4f5cf2901eda11..7466cb8112517b3bbc8869e4c2c91438ee74608c 100644 (file)
@@ -513,7 +513,7 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev,
         * Check to make sure we don't switch to a non-highres capable
         * clocksource if the tick code is in oneshot mode (highres or nohz)
         */
-       if (tick_oneshot_mode_active() &&
+       if (tick_oneshot_mode_active() && ovr &&
            !(ovr->flags & CLOCK_SOURCE_VALID_FOR_HRES)) {
                printk(KERN_WARNING "%s clocksource is not HRT compatible. "
                        "Cannot switch while in HRT/NOHZ mode\n", ovr->name);
index 0b36b9e5cc8b4e27f6adf89de403885cfe8a6687..a7f07d5a6241d882af4466ec3280a89f2681e8c9 100644 (file)
@@ -714,7 +714,7 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
         * networking code - if the timer is re-modified
         * to be the same thing then just return:
         */
-       if (timer->expires == expires && timer_pending(timer))
+       if (timer_pending(timer) && timer->expires == expires)
                return 1;
 
        return __mod_timer(timer, expires, false, TIMER_NOT_PINNED);
index bce9e01a29c8402301635e4d70ed810bb78eb303..4521c77d1a1aff64419d0afb0d6b84906c306454 100644 (file)
@@ -768,7 +768,7 @@ static struct tracer_stat function_stats __initdata = {
        .stat_show      = function_stat_show
 };
 
-static void ftrace_profile_debugfs(struct dentry *d_tracer)
+static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
 {
        struct ftrace_profile_stat *stat;
        struct dentry *entry;
@@ -786,7 +786,6 @@ static void ftrace_profile_debugfs(struct dentry *d_tracer)
                         * The files created are permanent, if something happens
                         * we still do not free memory.
                         */
-                       kfree(stat);
                        WARN(1,
                             "Could not allocate stat file for cpu %d\n",
                             cpu);
@@ -813,7 +812,7 @@ static void ftrace_profile_debugfs(struct dentry *d_tracer)
 }
 
 #else /* CONFIG_FUNCTION_PROFILER */
-static void ftrace_profile_debugfs(struct dentry *d_tracer)
+static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
 {
 }
 #endif /* CONFIG_FUNCTION_PROFILER */
index 7402144bff218ddcb51a9bd7cad8c6948a481651..75ef000613c35db5c7cb8ae71b2f4169f0bfd6d8 100644 (file)
@@ -363,7 +363,7 @@ ftrace_trace_onoff_callback(char *glob, char *cmd, char *param, int enable)
  out_reg:
        ret = register_ftrace_function_probe(glob, ops, count);
 
-       return ret;
+       return ret < 0 ? ret : 0;
 }
 
 static struct ftrace_func_command ftrace_traceon_cmd = {
index dd43a8289b0d9ecaf74aadc205063d2e2eaf8b3a..787ccddb85ea6cd8c53550deef5a11e3336a4ee1 100644 (file)
@@ -117,9 +117,6 @@ static int parse_opts(char *opts, struct p9_client *clnt)
                }
        }
 
-       if (!clnt->trans_mod)
-               clnt->trans_mod = v9fs_get_default_trans();
-
        kfree(options);
        return ret;
 }
@@ -689,6 +686,9 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
        if (err < 0)
                goto error;
 
+       if (!clnt->trans_mod)
+               clnt->trans_mod = v9fs_get_default_trans();
+
        if (clnt->trans_mod == NULL) {
                err = -EPROTONOSUPPORT;
                P9_DPRINTK(P9_DEBUG_ERROR,
@@ -1098,7 +1098,6 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
 
        if (data) {
                memmove(data, dataptr, count);
-               data += count;
        }
 
        if (udata) {
@@ -1192,9 +1191,9 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
 
        err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret);
        if (err) {
-               ret = ERR_PTR(err);
                p9pdu_dump(1, req->rc);
-               goto free_and_error;
+               p9_free_req(clnt, req);
+               goto error;
        }
 
        P9_DPRINTK(P9_DEBUG_9P,
@@ -1211,8 +1210,6 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
        p9_free_req(clnt, req);
        return ret;
 
-free_and_error:
-       p9_free_req(clnt, req);
 error:
        kfree(ret);
        return ERR_PTR(err);
index 95d7f32643aef3a3e0b3830200ea592bb1b54849..72720c7103515d6211da62c387f48f37ad69c56f 100644 (file)
@@ -75,6 +75,7 @@ static __initdata const char banner[] = KERN_INFO
 MODULE_DESCRIPTION("PF_CAN broadcast manager protocol");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
+MODULE_ALIAS("can-proto-2");
 
 /* easy access to can_frame payload */
 static inline u64 GET_U64(const struct can_frame *cp)
@@ -1469,6 +1470,9 @@ static int bcm_release(struct socket *sock)
                bo->ifindex = 0;
        }
 
+       sock_orphan(sk);
+       sock->sk = NULL;
+
        release_sock(sk);
        sock_put(sk);
 
index 6aa154e806ae722c53e71603c0b22865526452a0..f4cc44548bdaa35a2b6947b8c7ef89affe8ac615 100644 (file)
@@ -62,6 +62,7 @@ static __initdata const char banner[] =
 MODULE_DESCRIPTION("PF_CAN raw protocol");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>");
+MODULE_ALIAS("can-proto-1");
 
 #define MASK_ALL 0
 
@@ -306,6 +307,9 @@ static int raw_release(struct socket *sock)
        ro->bound   = 0;
        ro->count   = 0;
 
+       sock_orphan(sk);
+       sock->sk = NULL;
+
        release_sock(sk);
        sock_put(sk);
 
index 6354863b1c687c1917388d26c439fc8eab737bf4..bbb25be7ddfe614432ca8627ba4cbe791f57d569 100644 (file)
@@ -631,7 +631,7 @@ set_rcvbuf:
 
        case SO_TIMESTAMPING:
                if (val & ~SOF_TIMESTAMPING_MASK) {
-                       ret = EINVAL;
+                       ret = -EINVAL;
                        break;
                }
                sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE,
@@ -919,13 +919,19 @@ static inline void sock_lock_init(struct sock *sk)
                        af_family_keys + sk->sk_family);
 }
 
+/*
+ * Copy all fields from osk to nsk but nsk->sk_refcnt must not change yet,
+ * even temporarly, because of RCU lookups. sk_node should also be left as is.
+ */
 static void sock_copy(struct sock *nsk, const struct sock *osk)
 {
 #ifdef CONFIG_SECURITY_NETWORK
        void *sptr = nsk->sk_security;
 #endif
-
-       memcpy(nsk, osk, osk->sk_prot->obj_size);
+       BUILD_BUG_ON(offsetof(struct sock, sk_copy_start) !=
+                    sizeof(osk->sk_node) + sizeof(osk->sk_refcnt));
+       memcpy(&nsk->sk_copy_start, &osk->sk_copy_start,
+              osk->sk_prot->obj_size - offsetof(struct sock, sk_copy_start));
 #ifdef CONFIG_SECURITY_NETWORK
        nsk->sk_security = sptr;
        security_sk_clone(osk, nsk);
@@ -939,8 +945,23 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
        struct kmem_cache *slab;
 
        slab = prot->slab;
-       if (slab != NULL)
-               sk = kmem_cache_alloc(slab, priority);
+       if (slab != NULL) {
+               sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO);
+               if (!sk)
+                       return sk;
+               if (priority & __GFP_ZERO) {
+                       /*
+                        * caches using SLAB_DESTROY_BY_RCU should let
+                        * sk_node.next un-modified. Special care is taken
+                        * when initializing object to zero.
+                        */
+                       if (offsetof(struct sock, sk_node.next) != 0)
+                               memset(sk, 0, offsetof(struct sock, sk_node.next));
+                       memset(&sk->sk_node.pprev, 0,
+                              prot->obj_size - offsetof(struct sock,
+                                                        sk_node.pprev));
+               }
+       }
        else
                sk = kmalloc(prot->obj_size, priority);
 
@@ -1125,6 +1146,11 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
 
                newsk->sk_err      = 0;
                newsk->sk_priority = 0;
+               /*
+                * Before updating sk_refcnt, we must commit prior changes to memory
+                * (Documentation/RCU/rculist_nulls.txt for details)
+                */
+               smp_wmb();
                atomic_set(&newsk->sk_refcnt, 2);
 
                /*
@@ -1840,6 +1866,11 @@ void sock_init_data(struct socket *sock, struct sock *sk)
 
        sk->sk_stamp = ktime_set(-1L, 0);
 
+       /*
+        * Before updating sk_refcnt, we must commit prior changes to memory
+        * (Documentation/RCU/rculist_nulls.txt for details)
+        */
+       smp_wmb();
        atomic_set(&sk->sk_refcnt, 1);
        atomic_set(&sk->sk_wmem_alloc, 1);
        atomic_set(&sk->sk_drops, 0);
index 44e2a3d2359afd99da1324022c221e811d83a0a9..cb4a0f4bd5e5654b465ddee4f32a42504711d5d3 100644 (file)
@@ -735,10 +735,10 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        tos = tiph->tos;
-       if (tos&1) {
+       if (tos == 1) {
+               tos = 0;
                if (skb->protocol == htons(ETH_P_IP))
                        tos = old_iph->tos;
-               tos &= ~1;
        }
 
        {
index 2470262826694d122b5457d6ef4144b66429d7a2..7d08210547291b74bc15d001e55eacdb8dd34281 100644 (file)
@@ -1243,7 +1243,6 @@ int ip_push_pending_frames(struct sock *sk)
                skb->len += tmp_skb->len;
                skb->data_len += tmp_skb->len;
                skb->truesize += tmp_skb->truesize;
-               __sock_put(tmp_skb->sk);
                tmp_skb->destructor = NULL;
                tmp_skb->sk = NULL;
        }
index 5a1ca2698c885775914f05fe17ae45d485cbddd2..6d88219c5e22bd4bf752a543bebfb5af4ae36a1f 100644 (file)
@@ -1160,6 +1160,7 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = {
 #ifdef CONFIG_TCP_MD5SIG
 static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
        .md5_lookup     =       tcp_v4_reqsk_md5_lookup,
+       .calc_md5_hash  =       tcp_v4_md5_hash_skb,
 };
 #endif
 
@@ -1373,7 +1374,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                 */
                char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC);
                if (newkey != NULL)
-                       tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr,
+                       tcp_v4_md5_do_add(newsk, newinet->daddr,
                                          newkey, key->keylen);
                newsk->sk_route_caps &= ~NETIF_F_GSO_MASK;
        }
index 5bdf08d312d9b9b13a824673da237001679c0bff..bd62712848fad8f1a116364002c23cfab903d49e 100644 (file)
@@ -2261,7 +2261,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 #ifdef CONFIG_TCP_MD5SIG
        /* Okay, we have all we need - do the md5 hash if needed */
        if (md5) {
-               tp->af_specific->calc_md5_hash(md5_hash_location,
+               tcp_rsk(req)->af_specific->calc_md5_hash(md5_hash_location,
                                               md5, NULL, req, skb);
        }
 #endif
index 7c76e3d1821551c42acc16d3e2210404a553b4d0..87f8419a68fdf888b37a2643345d89b85005671d 100644 (file)
@@ -1484,7 +1484,6 @@ int ip6_push_pending_frames(struct sock *sk)
                skb->len += tmp_skb->len;
                skb->data_len += tmp_skb->len;
                skb->truesize += tmp_skb->truesize;
-               __sock_put(tmp_skb->sk);
                tmp_skb->destructor = NULL;
                tmp_skb->sk = NULL;
        }
index 68e52308e5520f7180e22c0230aea51133fad265..98b7327d0949aa993751411f6512ebdf304f326f 100644 (file)
@@ -1018,6 +1018,7 @@ static void ipip6_tunnel_setup(struct net_device *dev)
        dev->hard_header_len    = LL_MAX_HEADER + sizeof(struct iphdr);
        dev->mtu                = ETH_DATA_LEN - sizeof(struct iphdr);
        dev->flags              = IFF_NOARP;
+       dev->priv_flags        &= ~IFF_XMIT_DST_RELEASE;
        dev->iflink             = 0;
        dev->addr_len           = 4;
        dev->features           |= NETIF_F_NETNS_LOCAL;
index 58810c65b6359524b171fa9ca0678b9a6a21241c..d849dd53b78810623e62555a85eff50af60d84d1 100644 (file)
@@ -896,6 +896,7 @@ struct request_sock_ops tcp6_request_sock_ops __read_mostly = {
 #ifdef CONFIG_TCP_MD5SIG
 static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
        .md5_lookup     =       tcp_v6_reqsk_md5_lookup,
+       .calc_md5_hash  =       tcp_v6_md5_hash_skb,
 };
 #endif
 
@@ -1441,7 +1442,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                 */
                char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC);
                if (newkey != NULL)
-                       tcp_v6_md5_do_add(newsk, &inet6_sk(sk)->daddr,
+                       tcp_v6_md5_do_add(newsk, &newnp->daddr,
                                          newkey, key->keylen);
        }
 #endif
index 7508f11c5b3952a05ed9b41682f50d7827b3c4e6..b5869b9574b08a52c4c16f04cdb3f17336f9d762 100644 (file)
@@ -561,23 +561,38 @@ struct nf_conn *nf_conntrack_alloc(struct net *net,
                }
        }
 
-       ct = kmem_cache_zalloc(nf_conntrack_cachep, gfp);
+       /*
+        * Do not use kmem_cache_zalloc(), as this cache uses
+        * SLAB_DESTROY_BY_RCU.
+        */
+       ct = kmem_cache_alloc(nf_conntrack_cachep, gfp);
        if (ct == NULL) {
                pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n");
                atomic_dec(&net->ct.count);
                return ERR_PTR(-ENOMEM);
        }
-
+       /*
+        * Let ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.next
+        * and ct->tuplehash[IP_CT_DIR_REPLY].hnnode.next unchanged.
+        */
+       memset(&ct->tuplehash[IP_CT_DIR_MAX], 0,
+              sizeof(*ct) - offsetof(struct nf_conn, tuplehash[IP_CT_DIR_MAX]));
        spin_lock_init(&ct->lock);
-       atomic_set(&ct->ct_general.use, 1);
        ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig;
+       ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.pprev = NULL;
        ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl;
+       ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev = NULL;
        /* Don't set timer yet: wait for confirmation */
        setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct);
 #ifdef CONFIG_NET_NS
        ct->ct_net = net;
 #endif
 
+       /*
+        * changes to lookup keys must be done before setting refcnt to 1
+        */
+       smp_wmb();
+       atomic_set(&ct->ct_general.use, 1);
        return ct;
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_alloc);
index 863e40977a4db6d0b37fcc670137032afec85839..0f482e2440b432434ac96bbf38a942340ef56350 100644 (file)
@@ -330,7 +330,8 @@ static bool xt_osf_match_packet(const struct sk_buff *skb,
                        fcount++;
 
                        if (info->flags & XT_OSF_LOG)
-                               nf_log_packet(p->hooknum, 0, skb, p->in, p->out, NULL,
+                               nf_log_packet(p->family, p->hooknum, skb,
+                                       p->in, p->out, NULL,
                                        "%s [%s:%s] : %pi4:%d -> %pi4:%d hops=%d\n",
                                        f->genre, f->version, f->subtype,
                                        &ip->saddr, ntohs(tcp->source),
@@ -345,7 +346,7 @@ static bool xt_osf_match_packet(const struct sk_buff *skb,
        rcu_read_unlock();
 
        if (!fcount && (info->flags & XT_OSF_LOG))
-               nf_log_packet(p->hooknum, 0, skb, p->in, p->out, NULL,
+               nf_log_packet(p->family, p->hooknum, skb, p->in, p->out, NULL,
                        "Remote OS is not known: %pi4:%u -> %pi4:%u\n",
                                &ip->saddr, ntohs(tcp->source),
                                &ip->daddr, ntohs(tcp->dest));
index 9977a756fb32102dae7b7e4eedf3130c20546e6f..f24ae370e514f77f04342c78d0d180e89e4001f4 100644 (file)
@@ -1,20 +1,3 @@
-/*
- * Notice that this file is not protected like a normal header.
- * We also must allow for rereading of this file. The
- *
- *  || defined(TRACE_HEADER_MULTI_READ)
- *
- * serves this purpose.
- */
-#if !defined(_TRACE_EVENT_SAMPLE_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_EVENT_SAMPLE_H
-
-/*
- * All trace headers should include tracepoint.h, until we finally
- * make it into a standard header.
- */
-#include <linux/tracepoint.h>
-
 /*
  * If TRACE_SYSTEM is defined, that will be the directory created
  * in the ftrace directory under /debugfs/tracing/events/<system>
  * #define TRACE_INCLUDE_FILE trace-events-sample
  *
  * As we do an the bottom of this file.
+ *
+ * Notice that TRACE_SYSTEM should be defined outside of #if
+ * protection, just like TRACE_INCLUDE_FILE.
  */
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM sample
 
+/*
+ * Notice that this file is not protected like a normal header.
+ * We also must allow for rereading of this file. The
+ *
+ *  || defined(TRACE_HEADER_MULTI_READ)
+ *
+ * serves this purpose.
+ */
+#if !defined(_TRACE_EVENT_SAMPLE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_EVENT_SAMPLE_H
+
+/*
+ * All trace headers should include tracepoint.h, until we finally
+ * make it into a standard header.
+ */
+#include <linux/tracepoint.h>
+
 /*
  * The TRACE_EVENT macro is broken up into 5 parts.
  *
index 86d95cca46a7cfc57922e50d8fd91b74fc8da745..f2375ad7ebc9bf07d306fc8de611f631b36cd7bf 100644 (file)
@@ -19,6 +19,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <stdarg.h>
+
 #include "dialog.h"
 
 struct dialog_info dlg;
index 3bcacb4bfd3af8284293a21fa202c886d3339126..25b60bc117f738fabc26efb9a2e8f4f7546cd8d1 100644 (file)
@@ -888,6 +888,8 @@ int main(int ac, char **av)
                        single_menu_mode = 1;
        }
 
+       initscr();
+
        getyx(stdscr, saved_y, saved_x);
        if (init_dialog(NULL)) {
                fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
index b19f1f4962e3dfdb852a4059bf3d1c6122963779..8b357b0bd250b0e04012a08815c01cd3f95f22a3 100644 (file)
@@ -89,7 +89,7 @@ for script in postinst postrm preinst prerm ; do
 set -e
 
 # Pass maintainer script parameters to hook scripts
-export DEB_MAINT_PARAMS="\$@"
+export DEB_MAINT_PARAMS="\$*"
 
 test -d $debhookdir/$script.d && run-parts --arg="$version" $debhookdir/$script.d
 exit 0
index 108b643229baecc3ec592eb300fbd4f332936c8c..6205f37d547ce80e0315be9d97fbc7ce7fa9ebe5 100644 (file)
@@ -75,7 +75,7 @@ int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
 {
        struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
 
-       if (rtd && rtd->params)
+       if (rtd && rtd->params && rtd->params->drcmr)
                *rtd->params->drcmr = 0;
 
        snd_pcm_set_runtime_buffer(substream, NULL);
index 1bcb360330e521f37b82bca91452b7cbc0db8803..941f64a853ebea266d24141af7c4dc71a053165a 100644 (file)
@@ -3,10 +3,6 @@
 # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
 #
 
-ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
-  obj-$(CONFIG_SND_SEQUENCER) += oss/
-endif
-
 snd-seq-device-objs := seq_device.o
 snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \
                 seq_fifo.o seq_prioq.o seq_timer.o \
@@ -19,7 +15,8 @@ snd-seq-virmidi-objs := seq_virmidi.o
 
 obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o
 ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
-obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o
+  obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o
+  obj-$(CONFIG_SND_SEQUENCER) += oss/
 endif
 obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o
 
index edb11eefdfe3e2097f25037cd5bf507de817bdc7..2dcf45bf7293f1d68a3391226110ce34cc2b721d 100644 (file)
@@ -795,13 +795,13 @@ static int snd_gf1_pcm_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
                if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE))
                        continue;
                /* load real volume - better precision */
-               spin_lock_irqsave(&gus->reg_lock, flags);
+               spin_lock(&gus->reg_lock);
                snd_gf1_select_voice(gus, pvoice->number);
                snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
                vol = pvoice == pcmp->pvoices[0] ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right;
                snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol);
                pcmp->final_volume = 1;
-               spin_unlock_irqrestore(&gus->reg_lock, flags);
+               spin_unlock(&gus->reg_lock);
        }
        spin_unlock_irqrestore(&gus->voice_alloc, flags);
        return change;
index f24bf1ecb36d1fa060fda9d817d17a872b11e774..15e4138bce17ea4b42b2904bbe29b43095252d38 100644 (file)
@@ -325,9 +325,9 @@ static struct snd_pcm_hardware snd_ca0106_capture_hw = {
        .rate_max =             192000,
        .channels_min =         2,
        .channels_max =         2,
-       .buffer_bytes_max =     ((65536 - 64) * 8),
+       .buffer_bytes_max =     65536 - 128,
        .period_bytes_min =     64,
-       .period_bytes_max =     (65536 - 64),
+       .period_bytes_max =     32768 - 64,
        .periods_min =          2,
        .periods_max =          2,
        .fifo_size =            0,
index a1db51b3ead82f198483e5b948619ee01d082516..a7f4a671f7b7c51daa84db20e5bb7f4b2336f293 100644 (file)
@@ -242,13 +242,12 @@ static int get_amixer_rsc(struct amixer_mgr *mgr,
 
        /* Allocate mem for amixer resource */
        amixer = kzalloc(sizeof(*amixer), GFP_KERNEL);
-       if (NULL == amixer) {
-               err = -ENOMEM;
-               return err;
-       }
+       if (!amixer)
+               return -ENOMEM;
 
        /* Check whether there are sufficient
         * amixer resources to meet request. */
+       err = 0;
        spin_lock_irqsave(&mgr->mgr_lock, flags);
        for (i = 0; i < desc->msr; i++) {
                err = mgr_get_resource(&mgr->mgr, 1, &idx);
@@ -397,12 +396,11 @@ static int get_sum_rsc(struct sum_mgr *mgr,
 
        /* Allocate mem for sum resource */
        sum = kzalloc(sizeof(*sum), GFP_KERNEL);
-       if (NULL == sum) {
-               err = -ENOMEM;
-               return err;
-       }
+       if (!sum)
+               return -ENOMEM;
 
        /* Check whether there are sufficient sum resources to meet request. */
+       err = 0;
        spin_lock_irqsave(&mgr->mgr_lock, flags);
        for (i = 0; i < desc->msr; i++) {
                err = mgr_get_resource(&mgr->mgr, 1, &idx);
index 082e35c08c02956371fd69120d8fbe8ad7e1eeef..deb6cfa73600027646a3cfcd53041523fd76b875 100644 (file)
@@ -57,9 +57,9 @@ struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = {
 
 struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = {
        [LINEO1] = {.left = 0x40, .right = 0x41},
-       [LINEO2] = {.left = 0x70, .right = 0x71},
+       [LINEO2] = {.left = 0x60, .right = 0x61},
        [LINEO3] = {.left = 0x50, .right = 0x51},
-       [LINEO4] = {.left = 0x60, .right = 0x61},
+       [LINEO4] = {.left = 0x70, .right = 0x71},
        [LINEIM] = {.left = 0x45, .right = 0xc5},
        [SPDIFOO] = {.left = 0x00, .right = 0x01},
        [SPDIFIO] = {.left = 0x05, .right = 0x85},
index e1c145d8b702944472abe2a6bcd309a98a16bd90..df43a5cd3938beeb880d564ae3652639b5369770 100644 (file)
@@ -724,12 +724,11 @@ static int get_srcimp_rsc(struct srcimp_mgr *mgr,
 
        /* Allocate mem for SRCIMP resource */
        srcimp = kzalloc(sizeof(*srcimp), GFP_KERNEL);
-       if (NULL == srcimp) {
-               err = -ENOMEM;
-               return err;
-       }
+       if (!srcimp)
+               return -ENOMEM;
 
        /* Check whether there are sufficient SRCIMP resources. */
+       err = 0;
        spin_lock_irqsave(&mgr->mgr_lock, flags);
        for (i = 0; i < desc->msr; i++) {
                err = mgr_get_resource(&mgr->mgr, 1, &idx);
index 26d255de6bebb73b6fa51b39b740132b7c0b609c..88480c0c58a01fc0f08e6e15802e4493636bc176 100644 (file)
@@ -332,6 +332,12 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
                                                  AC_VERB_GET_CONNECT_LIST, i);
                range_val = !!(parm & (1 << (shift-1))); /* ranges */
                val = parm & mask;
+               if (val == 0) {
+                       snd_printk(KERN_WARNING "hda_codec: "
+                                  "invalid CONNECT_LIST verb %x[%i]:%x\n",
+                                   nid, i, parm);
+                       return 0;
+               }
                parm >>= shift;
                if (range_val) {
                        /* ranges between the previous and this one */
index be7d25fa7f35a3e164cf858aa7f5c4b67afd9ac6..3da85caf8af1318c3a3124606e57545d66f1a8ae 100644 (file)
@@ -3754,7 +3754,7 @@ static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
        int mute = (!ucontrol->value.integer.value[0] &&
                    !ucontrol->value.integer.value[1]);
        /* toggle GPIO1 according to the mute state */
-       snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
+       snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
                            mute ? 0x02 : 0x0);
        return ret;
 }
index bbb9b42e2604c87944dd1567375b375fd3352430..8c8b273116fbcc71bbe241bd6f9b63c69fbcd2ef 100644 (file)
@@ -4505,6 +4505,12 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
                                              &dig_nid, 1);
                if (err < 0)
                        continue;
+               if (dig_nid > 0x7f) {
+                       printk(KERN_ERR "alc880_auto: invalid dig_nid "
+                               "connection 0x%x for NID 0x%x\n", dig_nid,
+                               spec->autocfg.dig_out_pins[i]);
+                       continue;
+               }
                if (!i)
                        spec->multiout.dig_out_nid = dig_nid;
                else {
@@ -10625,6 +10631,18 @@ static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
        alc262_lenovo_3000_automute(codec, 1);
 }
 
+static int amp_stereo_mute_update(struct hda_codec *codec, hda_nid_t nid,
+                                 int dir, int idx, long *valp)
+{
+       int i, change = 0;
+
+       for (i = 0; i < 2; i++, valp++)
+               change |= snd_hda_codec_amp_update(codec, nid, i, dir, idx,
+                                                  HDA_AMP_MUTE,
+                                                  *valp ? 0 : HDA_AMP_MUTE);
+       return change;
+}
+
 /* bind hp and internal speaker mute (with plug check) */
 static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
                                         struct snd_ctl_elem_value *ucontrol)
@@ -10633,13 +10651,8 @@ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
        long *valp = ucontrol->value.integer.value;
        int change;
 
-       change = snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-                                                HDA_AMP_MUTE,
-                                                valp ? 0 : HDA_AMP_MUTE);
-       change |= snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
-                                                HDA_AMP_MUTE,
-                                                valp ? 0 : HDA_AMP_MUTE);
-
+       change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
+       change |= amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
        if (change)
                alc262_fujitsu_automute(codec, 0);
        return change;
@@ -10674,10 +10687,7 @@ static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
        long *valp = ucontrol->value.integer.value;
        int change;
 
-       change = snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
-                                                HDA_AMP_MUTE,
-                                                valp ? 0 : HDA_AMP_MUTE);
-
+       change = amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
        if (change)
                alc262_lenovo_3000_automute(codec, 0);
        return change;
@@ -11848,12 +11858,7 @@ static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol,
        long *valp = ucontrol->value.integer.value;
        int change;
 
-       change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
-                                         HDA_AMP_MUTE,
-                                         valp[0] ? 0 : HDA_AMP_MUTE);
-       change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
-                                          HDA_AMP_MUTE,
-                                          valp[1] ? 0 : HDA_AMP_MUTE);
+       change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
        if (change)
                alc268_acer_automute(codec, 0);
        return change;
index 41b5b3a18c1ee3efcdd910643aaea45e12f59ae1..512f3b9b9a459e27450efad9cb8c875823a99496 100644 (file)
@@ -2378,6 +2378,7 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228,
                      "Dell Vostro 1500", STAC_9205_DELL_M42),
        /* Gateway */
+       SND_PCI_QUIRK(0x107b, 0x0560, "Gateway T6834c", STAC_9205_EAPD),
        SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD),
        {} /* terminator */
 };
@@ -4065,7 +4066,7 @@ static int stac92xx_add_jack(struct hda_codec *codec,
        jack->nid = nid;
        jack->type = type;
 
-       sprintf(name, "%s at %s %s Jack",
+       snprintf(name, sizeof(name), "%s at %s %s Jack",
                snd_hda_get_jack_type(def_conf),
                snd_hda_get_jack_connectivity(def_conf),
                snd_hda_get_jack_location(def_conf));
@@ -5854,6 +5855,8 @@ static unsigned int *stac9872_brd_tbl[STAC_9872_MODELS] = {
 };
 
 static struct snd_pci_quirk stac9872_cfg_tbl[] = {
+       SND_PCI_QUIRK_MASK(0x104d, 0xfff0, 0x81e0,
+                          "Sony VAIO F/S", STAC_9872_VAIO),
        {} /* terminator */
 };
 
@@ -5866,6 +5869,8 @@ static int patch_stac9872(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
        codec->spec = spec;
+       spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
+       spec->pin_nids = stac9872_pin_nids;
 
        spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
                                                        stac9872_models,
@@ -5877,8 +5882,6 @@ static int patch_stac9872(struct hda_codec *codec)
                stac92xx_set_config_regs(codec,
                                         stac9872_brd_tbl[spec->board_config]);
 
-       spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
-       spec->pin_nids = stac9872_pin_nids;
        spec->multiout.dac_nids = spec->dac_nids;
        spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids);
        spec->adc_nids = stac9872_adc_nids;
index 235a71e5ac8de6782f9d24027a347b5dc7852046..b5ca02e2038c9bb42c35c8a194c57974e15b6686 100644 (file)
@@ -2197,9 +2197,12 @@ static int __init alsa_card_riptide_init(void)
        if (err < 0)
                return err;
 #if defined(SUPPORT_JOYSTICK)
-       pci_register_driver(&joystick_driver);
+       err = pci_register_driver(&joystick_driver);
+       /* On failure unregister formerly registered audio driver */
+       if (err < 0)
+               pci_unregister_driver(&driver);
 #endif
-       return 0;
+       return err;
 }
 
 static void __exit alsa_card_riptide_exit(void)
index ab099f482487b7e642d0f3d1372e6001673b3d27..cb0d1bf34b5723b9933ffc023430100b0594511d 100644 (file)
@@ -767,6 +767,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
        int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
        u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
        u16 pll_d = 1;
+       u8 reg;
 
        /* select data word length */
        data =
@@ -801,8 +802,16 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
                pll_q &= 0xf;
                aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
                aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
-       } else
+               /* disable PLL if it is bypassed */
+               reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
+               aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE);
+
+       } else {
                aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
+               /* enable PLL when it is used */
+               reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
+               aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE);
+       }
 
        /* Route Left DAC to left channel input and
         * right DAC to right channel input */
index 523aec188ccf64efa2de3aae90f8550eee77e3aa..73525c048e7f60d7613eef093f850c6d204215e4 100644 (file)
@@ -48,6 +48,7 @@ config SND_USB_CAIAQ
            * Native Instruments Kore Controller
            * Native Instruments Kore Controller 2
            * Native Instruments Audio Kontrol 1
+           * Native Instruments Audio 2 DJ
            * Native Instruments Audio 4 DJ
            * Native Instruments Audio 8 DJ
            * Native Instruments Guitar Rig Session I/O
index 8f9b60c5d74c9714e13c58a8bf4590b9e727951d..121af0644fd9bc901fbbc62cb676738e9049e0c7 100644 (file)
@@ -646,6 +646,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE):
                dev->samplerates |= SNDRV_PCM_RATE_192000;
                /* fall thru */
+       case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ):
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
                dev->samplerates |= SNDRV_PCM_RATE_88200;
index de38108f0b283ab4653693cbe9ac77698de299a1..83e6c1312d47c47ef1cc32eabab5b411d9dfa6b3 100644 (file)
 #include "input.h"
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.18");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.19");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
                         "{Native Instruments, RigKontrol3},"
                         "{Native Instruments, Kore Controller},"
                         "{Native Instruments, Kore Controller 2},"
                         "{Native Instruments, Audio Kontrol 1},"
+                        "{Native Instruments, Audio 2 DJ},"
                         "{Native Instruments, Audio 4 DJ},"
                         "{Native Instruments, Audio 8 DJ},"
                         "{Native Instruments, Session I/O},"
@@ -121,6 +122,11 @@ static struct usb_device_id snd_usb_id_table[] = {
                .idVendor =     USB_VID_NATIVEINSTRUMENTS,
                .idProduct =    USB_PID_AUDIO4DJ
        },
+       {
+               .match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+               .idVendor =     USB_VID_NATIVEINSTRUMENTS,
+               .idProduct =    USB_PID_AUDIO2DJ
+       },
        { /* terminator */ }
 };
 
index ece73514854e2f302ab88da1d1a857d3f43ee3ec..44e3edf88befab4ce60071a3d9b9da72bd9a727e 100644 (file)
@@ -10,6 +10,7 @@
 #define USB_PID_KORECONTROLLER 0x4711
 #define USB_PID_KORECONTROLLER2        0x4712
 #define USB_PID_AK1            0x0815
+#define USB_PID_AUDIO2DJ       0x041c
 #define USB_PID_AUDIO4DJ       0x0839
 #define USB_PID_AUDIO8DJ       0x1978
 #define USB_PID_SESSIONIO      0x1915
index c7b902358b7b268a3dd25178639f41009dedf125..44b9cdc8a83bae15856ca18fb7915acc7197757d 100644 (file)
@@ -2661,7 +2661,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
        struct usb_interface_descriptor *altsd;
        int i, altno, err, stream;
        int format;
-       struct audioformat *fp;
+       struct audioformat *fp = NULL;
        unsigned char *fmt, *csep;
        int num;
 
@@ -2734,6 +2734,18 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                        continue;
                }
 
+               /*
+                * Blue Microphones workaround: The last altsetting is identical
+                * with the previous one, except for a larger packet size, but
+                * is actually a mislabeled two-channel setting; ignore it.
+                */
+               if (fmt[4] == 1 && fmt[5] == 2 && altno == 2 && num == 3 &&
+                   fp && fp->altsetting == 1 && fp->channels == 1 &&
+                   fp->format == SNDRV_PCM_FORMAT_S16_LE &&
+                   le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
+                                                       fp->maxpacksize * 2)
+                       continue;
+
                csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
                /* Creamware Noah has this descriptor after the 2nd endpoint */
                if (!csep && altsd->bNumEndpoints >= 2)
index 8aa3f8c88707f1ab9ea48f123833139ca8cc3ed7..e72e931107826e069d5bfabc3677dca7a2745af6 100644 (file)
@@ -24,6 +24,9 @@ OPTIONS
 --dsos=::
        Only consider symbols in these dsos. CSV that understands
        file://filename entries.
+-n
+--show-nr-samples
+       Show the number of samples for each symbol
 -C::
 --comms=::
        Only consider symbols in these comms. CSV that understands
@@ -33,6 +36,18 @@ OPTIONS
        Only consider these symbols. CSV that understands
        file://filename entries.
 
+-w::
+--field-width=::
+       Force each column width to the provided list, for large terminal
+       readability.
+
+-t::
+--field-separator=::
+
+       Use a special separator character and don't pad with spaces, replacing
+       all occurances of this separator in symbol names (and other output)
+       with a '.' character, that thus it's the only non valid separator.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1]
index 7822b3d6baca22ea302a847a8a12d2ed3bde32a4..a5e9b876ca099668b4bad99c35871798e19009e7 100644 (file)
@@ -345,7 +345,7 @@ BUILTIN_OBJS += builtin-stat.o
 BUILTIN_OBJS += builtin-top.o
 
 PERFLIBS = $(LIB_FILE)
-EXTLIBS =
+EXTLIBS = -lbfd
 
 #
 # Platform specific tweaks
index 5f9eefecc5740b531460d0d63be520f9c73b63f4..1dba568e19410d254b9bdfb1401d04316abbe48d 100644 (file)
@@ -74,20 +74,12 @@ struct fork_event {
        u32 pid, ppid;
 };
 
-struct period_event {
-       struct perf_event_header header;
-       u64 time;
-       u64 id;
-       u64 sample_period;
-};
-
 typedef union event_union {
        struct perf_event_header        header;
        struct ip_event                 ip;
        struct mmap_event               mmap;
        struct comm_event               comm;
        struct fork_event               fork;
-       struct period_event             period;
 } event_t;
 
 
@@ -997,19 +989,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
        return 0;
 }
 
-static int
-process_period_event(event_t *event, unsigned long offset, unsigned long head)
-{
-       dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n",
-               (void *)(offset + head),
-               (void *)(long)(event->header.size),
-               event->period.time,
-               event->period.id,
-               event->period.sample_period);
-
-       return 0;
-}
-
 static int
 process_event(event_t *event, unsigned long offset, unsigned long head)
 {
@@ -1025,9 +1004,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
 
        case PERF_EVENT_FORK:
                return process_fork_event(event, offset, head);
-
-       case PERF_EVENT_PERIOD:
-               return process_period_event(event, offset, head);
        /*
         * We dont process them right now but they are fine:
         */
index 4ef78a5e6f326bf7aa08cc10715403b86574a5fe..6da09928130f8b726446e21e55b4a114a02926dd 100644 (file)
@@ -43,6 +43,7 @@ static int                    call_graph                      = 0;
 static int                     verbose                         = 0;
 static int                     inherit_stat                    = 0;
 static int                     no_samples                      = 0;
+static int                     sample_address                  = 0;
 
 static long                    samples;
 static struct timeval          last_read;
@@ -313,6 +314,10 @@ static void pid_synthesize_mmap_samples(pid_t pid)
                if (*pbf == 'x') { /* vm_exec */
                        char *execname = strchr(bf, '/');
 
+                       /* Catch VDSO */
+                       if (execname == NULL)
+                               execname = strstr(bf, "[vdso]");
+
                        if (execname == NULL)
                                continue;
 
@@ -401,6 +406,9 @@ static void create_counter(int counter, int cpu, pid_t pid)
        if (inherit_stat)
                attr->inherit_stat = 1;
 
+       if (sample_address)
+               attr->sample_type       |= PERF_SAMPLE_ADDR;
+
        if (call_graph)
                attr->sample_type       |= PERF_SAMPLE_CALLCHAIN;
 
@@ -645,6 +653,8 @@ static const struct option options[] = {
                    "be more verbose (show counter open errors, etc)"),
        OPT_BOOLEAN('s', "stat", &inherit_stat,
                    "per thread counts"),
+       OPT_BOOLEAN('d', "data", &sample_address,
+                   "Sample addresses"),
        OPT_BOOLEAN('n', "no-samples", &no_samples,
                    "don't sample"),
        OPT_END()
@@ -654,7 +664,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 {
        int counter;
 
-       argc = parse_options(argc, argv, options, record_usage, 0);
+       argc = parse_options(argc, argv, options, record_usage,
+               PARSE_OPT_STOP_AT_NON_OPTION);
        if (!argc && target_pid == -1 && !system_wide)
                usage_with_options(record_usage, options);
 
index 4e5cc266311e15f683d4b26877e158c83c2c7093..b20a4b6e31b72938b1312bb64f333236bbf4cd88 100644 (file)
@@ -33,8 +33,10 @@ static char          *vmlinux = NULL;
 
 static char            default_sort_order[] = "comm,dso";
 static char            *sort_order = default_sort_order;
-static char            *dso_list_str, *comm_list_str, *sym_list_str;
+static char            *dso_list_str, *comm_list_str, *sym_list_str,
+                       *col_width_list_str;
 static struct strlist  *dso_list, *comm_list, *sym_list;
+static char            *field_sep;
 
 static int             input;
 static int             show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
@@ -49,6 +51,7 @@ static int            verbose;
 static int             modules;
 
 static int             full_paths;
+static int             show_nr_samples;
 
 static unsigned long   page_size;
 static unsigned long   mmap_window = 32;
@@ -98,13 +101,6 @@ struct fork_event {
        u32 pid, ppid;
 };
 
-struct period_event {
-       struct perf_event_header header;
-       u64 time;
-       u64 id;
-       u64 sample_period;
-};
-
 struct lost_event {
        struct perf_event_header header;
        u64 id;
@@ -124,11 +120,37 @@ typedef union event_union {
        struct mmap_event               mmap;
        struct comm_event               comm;
        struct fork_event               fork;
-       struct period_event             period;
        struct lost_event               lost;
        struct read_event               read;
 } event_t;
 
+static int repsep_fprintf(FILE *fp, const char *fmt, ...)
+{
+       int n;
+       va_list ap;
+
+       va_start(ap, fmt);
+       if (!field_sep)
+               n = vfprintf(fp, fmt, ap);
+       else {
+               char *bf = NULL;
+               n = vasprintf(&bf, fmt, ap);
+               if (n > 0) {
+                       char *sep = bf;
+                       while (1) {
+                               sep = strchr(sep, *field_sep);
+                               if (sep == NULL)
+                                       break;
+                               *sep = '.';
+                       }
+               }
+               fputs(bf, fp);
+               free(bf);
+       }
+       va_end(ap);
+       return n;
+}
+
 static LIST_HEAD(dsos);
 static struct dso *kernel_dso;
 static struct dso *vdso;
@@ -360,12 +382,28 @@ static struct thread *thread__new(pid_t pid)
        return self;
 }
 
+static unsigned int dsos__col_width,
+                   comms__col_width,
+                   threads__col_width;
+
 static int thread__set_comm(struct thread *self, const char *comm)
 {
        if (self->comm)
                free(self->comm);
        self->comm = strdup(comm);
-       return self->comm ? 0 : -ENOMEM;
+       if (!self->comm)
+               return -ENOMEM;
+
+       if (!col_width_list_str && !field_sep &&
+           (!comm_list || strlist__has_entry(comm_list, comm))) {
+               unsigned int slen = strlen(comm);
+               if (slen > comms__col_width) {
+                       comms__col_width = slen;
+                       threads__col_width = slen + 6;
+               }
+       }
+
+       return 0;
 }
 
 static size_t thread__fprintf(struct thread *self, FILE *fp)
@@ -536,7 +574,9 @@ struct sort_entry {
 
        int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
        int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
-       size_t  (*print)(FILE *fp, struct hist_entry *);
+       size_t  (*print)(FILE *fp, struct hist_entry *, unsigned int width);
+       unsigned int *width;
+       bool    elide;
 };
 
 static int64_t cmp_null(void *l, void *r)
@@ -558,15 +598,17 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
 }
 
 static size_t
-sort__thread_print(FILE *fp, struct hist_entry *self)
+sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
 {
-       return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid);
+       return repsep_fprintf(fp, "%*s:%5d", width - 6,
+                             self->thread->comm ?: "", self->thread->pid);
 }
 
 static struct sort_entry sort_thread = {
-       .header = "         Command:  Pid",
+       .header = "Command:  Pid",
        .cmp    = sort__thread_cmp,
        .print  = sort__thread_print,
+       .width  = &threads__col_width,
 };
 
 /* --sort comm */
@@ -590,16 +632,17 @@ sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
 }
 
 static size_t
-sort__comm_print(FILE *fp, struct hist_entry *self)
+sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
 {
-       return fprintf(fp, "%16s", self->thread->comm);
+       return repsep_fprintf(fp, "%*s", width, self->thread->comm);
 }
 
 static struct sort_entry sort_comm = {
-       .header         = "         Command",
+       .header         = "Command",
        .cmp            = sort__comm_cmp,
        .collapse       = sort__comm_collapse,
        .print          = sort__comm_print,
+       .width          = &comms__col_width,
 };
 
 /* --sort dso */
@@ -617,18 +660,19 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
 }
 
 static size_t
-sort__dso_print(FILE *fp, struct hist_entry *self)
+sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
 {
        if (self->dso)
-               return fprintf(fp, "%-25s", self->dso->name);
+               return repsep_fprintf(fp, "%-*s", width, self->dso->name);
 
-       return fprintf(fp, "%016llx         ", (u64)self->ip);
+       return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
 }
 
 static struct sort_entry sort_dso = {
-       .header = "Shared Object            ",
+       .header = "Shared Object",
        .cmp    = sort__dso_cmp,
        .print  = sort__dso_print,
+       .width  = &dsos__col_width,
 };
 
 /* --sort symbol */
@@ -648,22 +692,22 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
 }
 
 static size_t
-sort__sym_print(FILE *fp, struct hist_entry *self)
+sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
 {
        size_t ret = 0;
 
        if (verbose)
-               ret += fprintf(fp, "%#018llx  ", (u64)self->ip);
+               ret += repsep_fprintf(fp, "%#018llx  ", (u64)self->ip);
 
+       ret += repsep_fprintf(fp, "[%c] ", self->level);
        if (self->sym) {
-               ret += fprintf(fp, "[%c] %s",
-                       self->dso == kernel_dso ? 'k' :
-                       self->dso == hypervisor_dso ? 'h' : '.', self->sym->name);
+               ret += repsep_fprintf(fp, "%s", self->sym->name);
 
                if (self->sym->module)
-                       ret += fprintf(fp, "\t[%s]", self->sym->module->name);
+                       ret += repsep_fprintf(fp, "\t[%s]",
+                                            self->sym->module->name);
        } else {
-               ret += fprintf(fp, "%#016llx", (u64)self->ip);
+               ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
        }
 
        return ret;
@@ -690,19 +734,19 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
 }
 
 static size_t
-sort__parent_print(FILE *fp, struct hist_entry *self)
+sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
 {
-       size_t ret = 0;
-
-       ret += fprintf(fp, "%-20s", self->parent ? self->parent->name : "[other]");
-
-       return ret;
+       return repsep_fprintf(fp, "%-*s", width,
+                             self->parent ? self->parent->name : "[other]");
 }
 
+static unsigned int parent_symbol__col_width;
+
 static struct sort_entry sort_parent = {
-       .header = "Parent symbol       ",
+       .header = "Parent symbol",
        .cmp    = sort__parent_cmp,
        .print  = sort__parent_print,
+       .width  = &parent_symbol__col_width,
 };
 
 static int sort__need_collapse = 0;
@@ -967,17 +1011,25 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
                return 0;
 
        if (total_samples)
-               ret = percent_color_fprintf(fp, "   %6.2f%%",
-                               (self->count * 100.0) / total_samples);
+               ret = percent_color_fprintf(fp,
+                                           field_sep ? "%.2f" : "   %6.2f%%",
+                                       (self->count * 100.0) / total_samples);
        else
-               ret = fprintf(fp, "%12Ld ", self->count);
+               ret = fprintf(fp, field_sep ? "%lld" : "%12lld ", self->count);
+
+       if (show_nr_samples) {
+               if (field_sep)
+                       fprintf(fp, "%c%lld", *field_sep, self->count);
+               else
+                       fprintf(fp, "%11lld", self->count);
+       }
 
        list_for_each_entry(se, &hist_entry__sort_list, list) {
-               if (exclude_other && (se == &sort_parent))
+               if (se->elide)
                        continue;
 
-               fprintf(fp, "  ");
-               ret += se->print(fp, self);
+               fprintf(fp, "%s", field_sep ?: "  ");
+               ret += se->print(fp, self, se->width ? *se->width : 0);
        }
 
        ret += fprintf(fp, "\n");
@@ -992,6 +1044,18 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
  *
  */
 
+static void dso__calc_col_width(struct dso *self)
+{
+       if (!col_width_list_str && !field_sep &&
+           (!dso_list || strlist__has_entry(dso_list, self->name))) {
+               unsigned int slen = strlen(self->name);
+               if (slen > dsos__col_width)
+                       dsos__col_width = slen;
+       }
+
+       self->slen_calculated = 1;
+}
+
 static struct symbol *
 resolve_symbol(struct thread *thread, struct map **mapp,
               struct dso **dsop, u64 *ipp)
@@ -1011,6 +1075,14 @@ resolve_symbol(struct thread *thread, struct map **mapp,
 
        map = thread__find_map(thread, ip);
        if (map != NULL) {
+               /*
+                * We have to do this here as we may have a dso
+                * with no symbol hit that has a name longer than
+                * the ones with symbols sampled.
+                */
+               if (!sort_dso.elide && !map->dso->slen_calculated)
+                       dso__calc_col_width(map->dso);
+
                if (mapp)
                        *mapp = map;
 got_map:
@@ -1282,35 +1354,67 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
        struct sort_entry *se;
        struct rb_node *nd;
        size_t ret = 0;
+       unsigned int width;
+       char *col_width = col_width_list_str;
 
-       fprintf(fp, "\n");
-       fprintf(fp, "#\n");
-       fprintf(fp, "# (%Ld samples)\n", (u64)total_samples);
+       fprintf(fp, "# Samples: %Ld\n", (u64)total_samples);
        fprintf(fp, "#\n");
 
        fprintf(fp, "# Overhead");
+       if (show_nr_samples) {
+               if (field_sep)
+                       fprintf(fp, "%cSamples", *field_sep);
+               else
+                       fputs("  Samples  ", fp);
+       }
        list_for_each_entry(se, &hist_entry__sort_list, list) {
-               if (exclude_other && (se == &sort_parent))
+               if (se->elide)
                        continue;
-               fprintf(fp, "  %s", se->header);
+               if (field_sep) {
+                       fprintf(fp, "%c%s", *field_sep, se->header);
+                       continue;
+               }
+               width = strlen(se->header);
+               if (se->width) {
+                       if (col_width_list_str) {
+                               if (col_width) {
+                                       *se->width = atoi(col_width);
+                                       col_width = strchr(col_width, ',');
+                                       if (col_width)
+                                               ++col_width;
+                               }
+                       }
+                       width = *se->width = max(*se->width, width);
+               }
+               fprintf(fp, "  %*s", width, se->header);
        }
        fprintf(fp, "\n");
 
+       if (field_sep)
+               goto print_entries;
+
        fprintf(fp, "# ........");
+       if (show_nr_samples)
+               fprintf(fp, " ..........");
        list_for_each_entry(se, &hist_entry__sort_list, list) {
                unsigned int i;
 
-               if (exclude_other && (se == &sort_parent))
+               if (se->elide)
                        continue;
 
                fprintf(fp, "  ");
-               for (i = 0; i < strlen(se->header); i++)
+               if (se->width)
+                       width = *se->width;
+               else
+                       width = strlen(se->header);
+               for (i = 0; i < width; i++)
                        fprintf(fp, ".");
        }
        fprintf(fp, "\n");
 
        fprintf(fp, "#\n");
 
+print_entries:
        for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
                pos = rb_entry(nd, struct hist_entry, rb_node);
                ret += hist_entry__fprintf(fp, pos, total_samples);
@@ -1523,19 +1627,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
        return 0;
 }
 
-static int
-process_period_event(event_t *event, unsigned long offset, unsigned long head)
-{
-       dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n",
-               (void *)(offset + head),
-               (void *)(long)(event->header.size),
-               event->period.time,
-               event->period.id,
-               event->period.sample_period);
-
-       return 0;
-}
-
 static int
 process_lost_event(event_t *event, unsigned long offset, unsigned long head)
 {
@@ -1617,9 +1708,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
        case PERF_EVENT_FORK:
                return process_fork_event(event, offset, head);
 
-       case PERF_EVENT_PERIOD:
-               return process_period_event(event, offset, head);
-
        case PERF_EVENT_LOST:
                return process_lost_event(event, offset, head);
 
@@ -1883,6 +1971,8 @@ static const struct option options[] = {
        OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
        OPT_BOOLEAN('m', "modules", &modules,
                    "load module symbols - WARNING: use only with -k and LIVE kernel"),
+       OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples,
+                   "Show a column with the number of samples"),
        OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
                   "sort by key(s): pid, comm, dso, symbol, parent"),
        OPT_BOOLEAN('P', "full-paths", &full_paths,
@@ -1891,15 +1981,21 @@ static const struct option options[] = {
                   "regex filter to identify parent, see: '--sort parent'"),
        OPT_BOOLEAN('x', "exclude-other", &exclude_other,
                    "Only display entries with parent-match"),
-       OPT_CALLBACK_DEFAULT('c', "callchain", NULL, "output_type,min_percent",
+       OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent",
                     "Display callchains using output_type and min percent threshold. "
-                    "Default: flat,0", &parse_callchain_opt, callchain_default_opt),
+                    "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt),
        OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]",
                   "only consider symbols in these dsos"),
        OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]",
                   "only consider symbols in these comms"),
        OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]",
                   "only consider these symbols"),
+       OPT_STRING('w', "column-widths", &col_width_list_str,
+                  "width[,width...]",
+                  "don't try to adjust column width, use these fixed values"),
+       OPT_STRING('t', "field-separator", &field_sep, "separator",
+                  "separator for columns, no spaces will be added between "
+                  "columns '.' is reserved."),
        OPT_END()
 };
 
@@ -1919,7 +2015,8 @@ static void setup_sorting(void)
 }
 
 static void setup_list(struct strlist **list, const char *list_str,
-                      const char *list_name)
+                      struct sort_entry *se, const char *list_name,
+                      FILE *fp)
 {
        if (list_str) {
                *list = strlist__new(true, list_str);
@@ -1928,6 +2025,11 @@ static void setup_list(struct strlist **list, const char *list_str,
                                list_name);
                        exit(129);
                }
+               if (strlist__nr_entries(*list) == 1) {
+                       fprintf(fp, "# %s: %s\n", list_name,
+                               strlist__entry(*list, 0)->s);
+                       se->elide = true;
+               }
        }
 }
 
@@ -1941,9 +2043,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 
        setup_sorting();
 
-       if (parent_pattern != default_parent_pattern)
+       if (parent_pattern != default_parent_pattern) {
                sort_dimension__add("parent");
-       else
+               sort_parent.elide = 1;
+       } else
                exclude_other = 0;
 
        /*
@@ -1952,11 +2055,17 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
        if (argc)
                usage_with_options(report_usage, options);
 
-       setup_list(&dso_list, dso_list_str, "dso");
-       setup_list(&comm_list, comm_list_str, "comm");
-       setup_list(&sym_list, sym_list_str, "symbol");
-
        setup_pager();
 
+       setup_list(&dso_list, dso_list_str, &sort_dso, "dso", stdout);
+       setup_list(&comm_list, comm_list_str, &sort_comm, "comm", stdout);
+       setup_list(&sym_list, sym_list_str, &sort_sym, "symbol", stdout);
+
+       if (field_sep && *field_sep == '.') {
+               fputs("'.' is the only non valid --field-separator argument\n",
+                     stderr);
+               exit(129);
+       }
+
        return __cmd_report();
 }
index 27921a8ce1a9ae34a4074d7694a184802351b648..f9510eeeb6c7a3f7e832abecbc77d102644c6141 100644 (file)
@@ -511,7 +511,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
 {
        int status;
 
-       argc = parse_options(argc, argv, options, stat_usage, 0);
+       argc = parse_options(argc, argv, options, stat_usage,
+               PARSE_OPT_STOP_AT_NON_OPTION);
        if (!argc)
                usage_with_options(stat_usage, options);
        if (run_count <= 0 || run_count > MAX_RUN)
index 95d5c0ae375ad62fb6ae7f317af9dd097590ea87..c0a423004e153b83249fb1d6631a5499e4375dc5 100644 (file)
@@ -58,6 +58,7 @@ static u64                    count_filter                    =  5;
 static int                     print_entries                   = 15;
 
 static int                     target_pid                      = -1;
+static int                     inherit                         =  0;
 static int                     profile_cpu                     = -1;
 static int                     nr_cpus                         =  0;
 static unsigned int            realtime_prio                   =  0;
@@ -549,7 +550,7 @@ int group_fd;
 static void start_counter(int i, int counter)
 {
        struct perf_counter_attr *attr;
-       unsigned int cpu;
+       int cpu;
 
        cpu = profile_cpu;
        if (target_pid == -1 && profile_cpu == -1)
@@ -559,6 +560,7 @@ static void start_counter(int i, int counter)
 
        attr->sample_type       = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
        attr->freq              = freq;
+       attr->inherit           = (cpu < 0) && inherit;
 
 try_again:
        fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0);
@@ -685,6 +687,8 @@ static const struct option options[] = {
                    "only display functions with more events than this"),
        OPT_BOOLEAN('g', "group", &group,
                            "put the counters into a counter group"),
+       OPT_BOOLEAN('i', "inherit", &inherit,
+                   "child tasks inherit counters"),
        OPT_STRING('s', "sym-filter", &sym_filter, "pattern",
                    "only display symbols matchig this pattern"),
        OPT_BOOLEAN('z', "zero", &zero,
index c5656784c61d555ac1e67d0843c54ed00faa58c9..31982ad064b4781c7b78dd5f9ef32f3f29dd3523 100644 (file)
@@ -12,6 +12,8 @@
 #include "util/cache.h"
 #include "util/quote.h"
 #include "util/run-command.h"
+#include "util/parse-events.h"
+#include "util/string.h"
 
 const char perf_usage_string[] =
        "perf [--version] [--help] COMMAND [ARGS]";
@@ -25,6 +27,8 @@ struct pager_config {
        int val;
 };
 
+static char debugfs_mntpt[MAXPATHLEN];
+
 static int pager_command_config(const char *var, const char *value, void *data)
 {
        struct pager_config *c = data;
@@ -56,6 +60,15 @@ static void commit_pager_choice(void) {
        }
 }
 
+static void set_debugfs_path(void)
+{
+       char *path;
+
+       path = getenv(PERF_DEBUGFS_ENVIRONMENT);
+       snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt,
+                "tracing/events");
+}
+
 static int handle_options(const char*** argv, int* argc, int* envchanged)
 {
        int handled = 0;
@@ -122,6 +135,22 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
                        setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
                        if (envchanged)
                                *envchanged = 1;
+               } else if (!strcmp(cmd, "--debugfs-dir")) {
+                       if (*argc < 2) {
+                               fprintf(stderr, "No directory given for --debugfs-dir.\n");
+                               usage(perf_usage_string);
+                       }
+                       strncpy(debugfs_mntpt, (*argv)[1], MAXPATHLEN);
+                       debugfs_mntpt[MAXPATHLEN - 1] = '\0';
+                       if (envchanged)
+                               *envchanged = 1;
+                       (*argv)++;
+                       (*argc)--;
+               } else if (!prefixcmp(cmd, "--debugfs-dir=")) {
+                       strncpy(debugfs_mntpt, cmd + 14, MAXPATHLEN);
+                       debugfs_mntpt[MAXPATHLEN - 1] = '\0';
+                       if (envchanged)
+                               *envchanged = 1;
                } else {
                        fprintf(stderr, "Unknown option: %s\n", cmd);
                        usage(perf_usage_string);
@@ -228,6 +257,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
        if (use_pager == -1 && p->option & USE_PAGER)
                use_pager = 1;
        commit_pager_choice();
+       set_debugfs_path();
 
        status = p->fn(argc, argv, prefix);
        if (status)
@@ -346,6 +376,49 @@ static int run_argv(int *argcp, const char ***argv)
        return done_alias;
 }
 
+/* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */
+static void get_debugfs_mntpt(void)
+{
+       FILE *file;
+       char fs_type[100];
+       char debugfs[MAXPATHLEN];
+
+       /*
+        * try the standard location
+        */
+       if (valid_debugfs_mount("/sys/kernel/debug/") == 0) {
+               strcpy(debugfs_mntpt, "/sys/kernel/debug/");
+               return;
+       }
+
+       /*
+        * try the sane location
+        */
+       if (valid_debugfs_mount("/debug/") == 0) {
+               strcpy(debugfs_mntpt, "/debug/");
+               return;
+       }
+
+       /*
+        * give up and parse /proc/mounts
+        */
+       file = fopen("/proc/mounts", "r");
+       if (file == NULL)
+               return;
+
+       while (fscanf(file, "%*s %"
+                     STR(MAXPATHLEN)
+                     "s %99s %*s %*d %*d\n",
+                     debugfs, fs_type) == 2) {
+               if (strcmp(fs_type, "debugfs") == 0)
+                       break;
+       }
+       fclose(file);
+       if (strcmp(fs_type, "debugfs") == 0) {
+               strncpy(debugfs_mntpt, debugfs, MAXPATHLEN);
+               debugfs_mntpt[MAXPATHLEN - 1] = '\0';
+       }
+}
 
 int main(int argc, const char **argv)
 {
@@ -354,7 +427,8 @@ int main(int argc, const char **argv)
        cmd = perf_extract_argv0_path(argv[0]);
        if (!cmd)
                cmd = "perf-help";
-
+       /* get debugfs mount point from /proc/mounts */
+       get_debugfs_mntpt();
        /*
         * "perf-xxxx" is the same as "perf xxxx", but we obviously:
         *
@@ -377,6 +451,7 @@ int main(int argc, const char **argv)
        argc--;
        handle_options(&argv, &argc, NULL);
        commit_pager_choice();
+       set_debugfs_path();
        if (argc > 0) {
                if (!prefixcmp(argv[0], "--"))
                        argv[0] += 2;
index 63e67cc5487b5f5791a4dc0709454482afa8c839..e5148e2b6134242f3b42c3dd59fafd54a7acb60f 100644 (file)
@@ -1,7 +1,13 @@
 #ifndef _PERF_PERF_H
 #define _PERF_PERF_H
 
-#if defined(__x86_64__) || defined(__i386__)
+#if defined(__i386__)
+#include "../../arch/x86/include/asm/unistd.h"
+#define rmb()          asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
+#define cpu_relax()    asm volatile("rep; nop" ::: "memory");
+#endif
+
+#if defined(__x86_64__)
 #include "../../arch/x86/include/asm/unistd.h"
 #define rmb()          asm volatile("lfence" ::: "memory")
 #define cpu_relax()    asm volatile("rep; nop" ::: "memory");
index 161d5f413e28701f07acdd7ff2ea72ba9f082bf6..4b50c412b9c574ecafc10c1c4cbaa48d8535194e 100644 (file)
@@ -18,6 +18,7 @@
 #define PERFATTRIBUTES_FILE ".perfattributes"
 #define INFOATTRIBUTES_FILE "info/attributes"
 #define ATTRIBUTE_MACRO_PREFIX "[attr]"
+#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
 
 typedef int (*config_fn_t)(const char *, const char *, void *);
 extern int perf_default_config(const char *, const char *, void *);
index b5ef53ad4c7a1e19309095a3da2d3d4238f22f91..bf280449fcfda3b84a0361548960853721a22323 100644 (file)
@@ -16,7 +16,7 @@ struct perf_header {
        int frozen;
        int attrs, size;
        struct perf_header_attr **attr;
-       off_t attr_offset;
+       s64 attr_offset;
        u64 data_offset;
        u64 data_size;
 };
index 99c1b3d1edd9c5c252427598ae53bb579daebba5..a6b87390cb52648e3a5d02c5486f4eb2635504cd 100644 (file)
        (type *)((char *)__mptr - offsetof(type, member)); })
 #endif
 
+#ifndef max
+#define max(x, y) ({                           \
+       typeof(x) _max1 = (x);                  \
+       typeof(y) _max2 = (y);                  \
+       (void) (&_max1 == &_max2);              \
+       _max1 > _max2 ? _max1 : _max2; })
+#endif
+
 #endif
index 5184959e0615b7e79e38058cac0594a55a3b6fc4..7bdad8df22a66b5ea10e85cdbe9b5bea806f4bb4 100644 (file)
@@ -5,6 +5,7 @@
 #include "parse-events.h"
 #include "exec_cmd.h"
 #include "string.h"
+#include "cache.h"
 
 extern char *strcasestr(const char *haystack, const char *needle);
 
@@ -19,6 +20,8 @@ struct event_symbol {
        char    *alias;
 };
 
+char debugfs_path[MAXPATHLEN];
+
 #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
 #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
 
@@ -71,8 +74,8 @@ static char *sw_event_names[] = {
 #define MAX_ALIASES 8
 
 static char *hw_cache[][MAX_ALIASES] = {
- { "L1-d$",    "l1-d",         "l1d",          "L1-data",              },
- { "L1-i$",    "l1-i",         "l1i",          "L1-instruction",       },
+ { "L1-dcache",        "l1-d",         "l1d",          "L1-data",              },
+ { "L1-icache",        "l1-i",         "l1i",          "L1-instruction",       },
  { "LLC",      "L2"                                                    },
  { "dTLB",     "d-tlb",        "Data-TLB",                             },
  { "iTLB",     "i-tlb",        "Instruction-TLB",                      },
@@ -110,6 +113,88 @@ static unsigned long hw_cache_stat[C(MAX)] = {
  [C(BPU)]      = (CACHE_READ),
 };
 
+#define for_each_subsystem(sys_dir, sys_dirent, sys_next, file, st)           \
+       while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)        \
+       if (snprintf(file, MAXPATHLEN, "%s/%s", debugfs_path,                  \
+                       sys_dirent.d_name) &&                                  \
+          (!stat(file, &st)) && (S_ISDIR(st.st_mode)) &&                      \
+          (strcmp(sys_dirent.d_name, ".")) &&                                 \
+          (strcmp(sys_dirent.d_name, "..")))
+
+#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st)    \
+       while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
+       if (snprintf(file, MAXPATHLEN, "%s/%s/%s", debugfs_path,               \
+                    sys_dirent.d_name, evt_dirent.d_name) &&                  \
+          (!stat(file, &st)) && (S_ISDIR(st.st_mode)) &&                      \
+          (strcmp(evt_dirent.d_name, ".")) &&                                 \
+          (strcmp(evt_dirent.d_name, "..")))
+
+#define MAX_EVENT_LENGTH 30
+
+int valid_debugfs_mount(const char *debugfs)
+{
+       struct statfs st_fs;
+
+       if (statfs(debugfs, &st_fs) < 0)
+               return -ENOENT;
+       else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
+               return -ENOENT;
+       return 0;
+}
+
+static char *tracepoint_id_to_name(u64 config)
+{
+       static char tracepoint_name[2 * MAX_EVENT_LENGTH];
+       DIR *sys_dir, *evt_dir;
+       struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
+       struct stat st;
+       char id_buf[4];
+       int fd;
+       u64 id;
+       char evt_path[MAXPATHLEN];
+
+       if (valid_debugfs_mount(debugfs_path))
+               return "unkown";
+
+       sys_dir = opendir(debugfs_path);
+       if (!sys_dir)
+               goto cleanup;
+
+       for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) {
+               evt_dir = opendir(evt_path);
+               if (!evt_dir)
+                       goto cleanup;
+               for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
+                                                               evt_path, st) {
+                       snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id",
+                                debugfs_path, sys_dirent.d_name,
+                                evt_dirent.d_name);
+                       fd = open(evt_path, O_RDONLY);
+                       if (fd < 0)
+                               continue;
+                       if (read(fd, id_buf, sizeof(id_buf)) < 0) {
+                               close(fd);
+                               continue;
+                       }
+                       close(fd);
+                       id = atoll(id_buf);
+                       if (id == config) {
+                               closedir(evt_dir);
+                               closedir(sys_dir);
+                               snprintf(tracepoint_name, 2 * MAX_EVENT_LENGTH,
+                                       "%s:%s", sys_dirent.d_name,
+                                       evt_dirent.d_name);
+                               return tracepoint_name;
+                       }
+               }
+               closedir(evt_dir);
+       }
+
+cleanup:
+       closedir(sys_dir);
+       return "unkown";
+}
+
 static int is_cache_op_valid(u8 cache_type, u8 cache_op)
 {
        if (hw_cache_stat[cache_type] & COP(cache_op))
@@ -177,6 +262,9 @@ char *event_name(int counter)
                        return sw_event_names[config];
                return "unknown-software";
 
+       case PERF_TYPE_TRACEPOINT:
+               return tracepoint_id_to_name(config);
+
        default:
                break;
        }
@@ -265,6 +353,53 @@ parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
        return 1;
 }
 
+static int parse_tracepoint_event(const char **strp,
+                                   struct perf_counter_attr *attr)
+{
+       const char *evt_name;
+       char sys_name[MAX_EVENT_LENGTH];
+       char id_buf[4];
+       int fd;
+       unsigned int sys_length, evt_length;
+       u64 id;
+       char evt_path[MAXPATHLEN];
+
+       if (valid_debugfs_mount(debugfs_path))
+               return 0;
+
+       evt_name = strchr(*strp, ':');
+       if (!evt_name)
+               return 0;
+
+       sys_length = evt_name - *strp;
+       if (sys_length >= MAX_EVENT_LENGTH)
+               return 0;
+
+       strncpy(sys_name, *strp, sys_length);
+       sys_name[sys_length] = '\0';
+       evt_name = evt_name + 1;
+       evt_length = strlen(evt_name);
+       if (evt_length >= MAX_EVENT_LENGTH)
+               return 0;
+
+       snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
+                sys_name, evt_name);
+       fd = open(evt_path, O_RDONLY);
+       if (fd < 0)
+               return 0;
+
+       if (read(fd, id_buf, sizeof(id_buf)) < 0) {
+               close(fd);
+               return 0;
+       }
+       close(fd);
+       id = atoll(id_buf);
+       attr->config = id;
+       attr->type = PERF_TYPE_TRACEPOINT;
+       *strp = evt_name + evt_length;
+       return 1;
+}
+
 static int check_events(const char *str, unsigned int i)
 {
        int n;
@@ -374,7 +509,8 @@ parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
  */
 static int parse_event_symbols(const char **str, struct perf_counter_attr *attr)
 {
-       if (!(parse_raw_event(str, attr) ||
+       if (!(parse_tracepoint_event(str, attr) ||
+             parse_raw_event(str, attr) ||
              parse_numeric_event(str, attr) ||
              parse_symbolic_event(str, attr) ||
              parse_generic_hw_event(str, attr)))
@@ -422,6 +558,42 @@ static const char * const event_type_descriptors[] = {
        "Hardware cache event",
 };
 
+/*
+ * Print the events from <debugfs_mount_point>/tracing/events
+ */
+
+static void print_tracepoint_events(void)
+{
+       DIR *sys_dir, *evt_dir;
+       struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
+       struct stat st;
+       char evt_path[MAXPATHLEN];
+
+       if (valid_debugfs_mount(debugfs_path))
+               return;
+
+       sys_dir = opendir(debugfs_path);
+       if (!sys_dir)
+               goto cleanup;
+
+       for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) {
+               evt_dir = opendir(evt_path);
+               if (!evt_dir)
+                       goto cleanup;
+               for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
+                                                               evt_path, st) {
+                       snprintf(evt_path, MAXPATHLEN, "%s:%s",
+                                sys_dirent.d_name, evt_dirent.d_name);
+                       fprintf(stderr, "  %-40s [%s]\n", evt_path,
+                               event_type_descriptors[PERF_TYPE_TRACEPOINT+1]);
+               }
+               closedir(evt_dir);
+       }
+
+cleanup:
+       closedir(sys_dir);
+}
+
 /*
  * Print the help text for the event symbols:
  */
@@ -436,7 +608,7 @@ void print_events(void)
 
        for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
                type = syms->type + 1;
-               if (type > ARRAY_SIZE(event_type_descriptors))
+               if (type >= ARRAY_SIZE(event_type_descriptors))
                        type = 0;
 
                if (type != prev_type)
@@ -472,5 +644,7 @@ void print_events(void)
                "rNNN");
        fprintf(stderr, "\n");
 
+       print_tracepoint_events();
+
        exit(129);
 }
index e3d552908e60015517316d2d91cba6324c8fbc2f..1ea5d09b6eb14221db27cebdc9091f03c29bf53b 100644 (file)
@@ -3,6 +3,8 @@
  * Parse symbolic events/counts passed in as options:
  */
 
+struct option;
+
 extern int                     nr_counters;
 
 extern struct perf_counter_attr attrs[MAX_COUNTERS];
@@ -15,3 +17,6 @@ extern int parse_events(const struct option *opt, const char *str, int unset);
 
 extern void print_events(void);
 
+extern char debugfs_path[];
+extern int valid_debugfs_mount(const char *debugfs);
+
index 3dca2f654cd06a31e19728fbc0d10ddb98ea4d27..bf39dfadfd24dd00fe845f1c321bf0994ad768b0 100644 (file)
@@ -5,4 +5,7 @@
 
 int hex2u64(const char *ptr, u64 *val);
 
+#define _STR(x) #x
+#define STR(x) _STR(x)
+
 #endif
index 025a78edfffe72c11aa421abcc2d3ab252dd7d99..7ad38171dc2b9c6a6fb7c8474a1faf24101443cc 100644 (file)
@@ -64,6 +64,7 @@ int strlist__add(struct strlist *self, const char *new_entry)
 
        rb_link_node(&sn->rb_node, parent, p);
        rb_insert_color(&sn->rb_node, &self->entries);
+       ++self->nr_entries;
 
        return 0;
 }
@@ -155,8 +156,9 @@ struct strlist *strlist__new(bool dupstr, const char *slist)
        struct strlist *self = malloc(sizeof(*self));
 
        if (self != NULL) {
-               self->entries = RB_ROOT;
-               self->dupstr = dupstr;
+               self->entries    = RB_ROOT;
+               self->dupstr     = dupstr;
+               self->nr_entries = 0;
                if (slist && strlist__parse_list(self, slist) != 0)
                        goto out_error;
        }
@@ -182,3 +184,17 @@ void strlist__delete(struct strlist *self)
                free(self);
        }
 }
+
+struct str_node *strlist__entry(const struct strlist *self, unsigned int idx)
+{
+       struct rb_node *nd;
+
+       for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
+               struct str_node *pos = rb_entry(nd, struct str_node, rb_node);
+
+               if (!idx--)
+                       return pos;
+       }
+
+       return NULL;
+}
index 2fdcfee87586ab47d69f49cc5ceaf2d71aceadc6..921818e44a542e9aa1f8398d950121cb39fb5c24 100644 (file)
@@ -11,7 +11,8 @@ struct str_node {
 
 struct strlist {
        struct rb_root entries;
-       bool dupstr;
+       unsigned int   nr_entries;
+       bool           dupstr;
 };
 
 struct strlist *strlist__new(bool dupstr, const char *slist);
@@ -21,11 +22,17 @@ void strlist__remove(struct strlist *self, struct str_node *sn);
 int strlist__load(struct strlist *self, const char *filename);
 int strlist__add(struct strlist *self, const char *str);
 
+struct str_node *strlist__entry(const struct strlist *self, unsigned int idx);
 bool strlist__has_entry(struct strlist *self, const char *entry);
 
 static inline bool strlist__empty(const struct strlist *self)
 {
-       return rb_first(&self->entries) == NULL;
+       return self->nr_entries == 0;
+}
+
+static inline unsigned int strlist__nr_entries(const struct strlist *self)
+{
+       return self->nr_entries;
 }
 
 int strlist__parse_list(struct strlist *self, const char *s);
index 4683b67b5ee4316cfb9a7266da799194bb4ad957..28106059bf12b624a309661a82373db36d017f3c 100644 (file)
@@ -6,9 +6,15 @@
 #include <libelf.h>
 #include <gelf.h>
 #include <elf.h>
+#include <bfd.h>
 
 const char *sym_hist_filter;
 
+#ifndef DMGL_PARAMS
+#define DMGL_PARAMS      (1 << 0)       /* Include function args */
+#define DMGL_ANSI        (1 << 1)       /* Include const, volatile, etc */
+#endif
+
 static struct symbol *symbol__new(u64 start, u64 len,
                                  const char *name, unsigned int priv_size,
                                  u64 obj_start, int verbose)
@@ -65,6 +71,7 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
                self->syms = RB_ROOT;
                self->sym_priv_size = sym_priv_size;
                self->find_symbol = dso__find_symbol;
+               self->slen_calculated = 0;
        }
 
        return self;
@@ -373,36 +380,61 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
             idx < nr_entries; \
             ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
 
-static int dso__synthesize_plt_symbols(struct  dso *self, Elf *elf,
-                                      GElf_Ehdr *ehdr, Elf_Scn *scn_dynsym,
-                                      GElf_Shdr *shdr_dynsym,
-                                      size_t dynsym_idx, int verbose)
+/*
+ * We need to check if we have a .dynsym, so that we can handle the
+ * .plt, synthesizing its symbols, that aren't on the symtabs (be it
+ * .dynsym or .symtab).
+ * And always look at the original dso, not at debuginfo packages, that
+ * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
+ */
+static int dso__synthesize_plt_symbols(struct  dso *self, int verbose)
 {
        uint32_t nr_rel_entries, idx;
        GElf_Sym sym;
        u64 plt_offset;
        GElf_Shdr shdr_plt;
        struct symbol *f;
-       GElf_Shdr shdr_rel_plt;
+       GElf_Shdr shdr_rel_plt, shdr_dynsym;
        Elf_Data *reldata, *syms, *symstrs;
-       Elf_Scn *scn_plt_rel, *scn_symstrs;
+       Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
+       size_t dynsym_idx;
+       GElf_Ehdr ehdr;
        char sympltname[1024];
-       int nr = 0, symidx;
+       Elf *elf;
+       int nr = 0, symidx, fd, err = 0;
+
+       fd = open(self->name, O_RDONLY);
+       if (fd < 0)
+               goto out;
+
+       elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
+       if (elf == NULL)
+               goto out_close;
+
+       if (gelf_getehdr(elf, &ehdr) == NULL)
+               goto out_elf_end;
+
+       scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
+                                        ".dynsym", &dynsym_idx);
+       if (scn_dynsym == NULL)
+               goto out_elf_end;
 
-       scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt,
+       scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
                                          ".rela.plt", NULL);
        if (scn_plt_rel == NULL) {
-               scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt,
+               scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
                                                  ".rel.plt", NULL);
                if (scn_plt_rel == NULL)
-                       return 0;
+                       goto out_elf_end;
        }
 
+       err = -1;
+
        if (shdr_rel_plt.sh_link != dynsym_idx)
-               return 0;
+               goto out_elf_end;
 
-       if (elf_section_by_name(elf, ehdr, &shdr_plt, ".plt", NULL) == NULL)
-               return 0;
+       if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
+               goto out_elf_end;
 
        /*
         * Fetch the relocation section to find the indexes to the GOT
@@ -410,19 +442,19 @@ static int dso__synthesize_plt_symbols(struct  dso *self, Elf *elf,
         */
        reldata = elf_getdata(scn_plt_rel, NULL);
        if (reldata == NULL)
-               return -1;
+               goto out_elf_end;
 
        syms = elf_getdata(scn_dynsym, NULL);
        if (syms == NULL)
-               return -1;
+               goto out_elf_end;
 
-       scn_symstrs = elf_getscn(elf, shdr_dynsym->sh_link);
+       scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
        if (scn_symstrs == NULL)
-               return -1;
+               goto out_elf_end;
 
        symstrs = elf_getdata(scn_symstrs, NULL);
        if (symstrs == NULL)
-               return -1;
+               goto out_elf_end;
 
        nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
        plt_offset = shdr_plt.sh_offset;
@@ -441,7 +473,7 @@ static int dso__synthesize_plt_symbols(struct  dso *self, Elf *elf,
                        f = symbol__new(plt_offset, shdr_plt.sh_entsize,
                                        sympltname, self->sym_priv_size, 0, verbose);
                        if (!f)
-                               return -1;
+                               goto out_elf_end;
 
                        dso__insert_symbol(self, f);
                        ++nr;
@@ -459,19 +491,25 @@ static int dso__synthesize_plt_symbols(struct  dso *self, Elf *elf,
                        f = symbol__new(plt_offset, shdr_plt.sh_entsize,
                                        sympltname, self->sym_priv_size, 0, verbose);
                        if (!f)
-                               return -1;
+                               goto out_elf_end;
 
                        dso__insert_symbol(self, f);
                        ++nr;
                }
-       } else {
-               /*
-                * TODO: There are still one more shdr_rel_plt.sh_type
-                * I have to investigate, but probably should be ignored.
-                */
        }
 
-       return nr;
+       err = 0;
+out_elf_end:
+       elf_end(elf);
+out_close:
+       close(fd);
+
+       if (err == 0)
+               return nr;
+out:
+       fprintf(stderr, "%s: problems reading %s PLT info.\n",
+               __func__, self->name);
+       return 0;
 }
 
 static int dso__load_sym(struct dso *self, int fd, const char *name,
@@ -485,10 +523,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
        GElf_Shdr shdr;
        Elf_Data *syms;
        GElf_Sym sym;
-       Elf_Scn *sec, *sec_dynsym, *sec_strndx;
+       Elf_Scn *sec, *sec_strndx;
        Elf *elf;
-       size_t dynsym_idx;
-       int nr = 0;
+       int nr = 0, kernel = !strcmp("[kernel]", self->name);
 
        elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
        if (elf == NULL) {
@@ -504,32 +541,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
                goto out_elf_end;
        }
 
-       /*
-        * We need to check if we have a .dynsym, so that we can handle the
-        * .plt, synthesizing its symbols, that aren't on the symtabs (be it
-        * .dynsym or .symtab)
-        */
-       sec_dynsym = elf_section_by_name(elf, &ehdr, &shdr,
-                                        ".dynsym", &dynsym_idx);
-       if (sec_dynsym != NULL) {
-               nr = dso__synthesize_plt_symbols(self, elf, &ehdr,
-                                                sec_dynsym, &shdr,
-                                                dynsym_idx, verbose);
-               if (nr < 0)
-                       goto out_elf_end;
-       }
-
-       /*
-        * But if we have a full .symtab (that is a superset of .dynsym) we
-        * should add the symbols not in the .dynsyn
-        */
        sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
        if (sec == NULL) {
-               if (sec_dynsym == NULL)
+               sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
+               if (sec == NULL)
                        goto out_elf_end;
-
-               sec = sec_dynsym;
-               gelf_getshdr(sec, &shdr);
        }
 
        syms = elf_getdata(sec, NULL);
@@ -555,12 +571,17 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
        nr_syms = shdr.sh_size / shdr.sh_entsize;
 
        memset(&sym, 0, sizeof(sym));
-       self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
+       if (!kernel) {
+               self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
                                elf_section_by_name(elf, &ehdr, &shdr,
                                                     ".gnu.prelink_undo",
                                                     NULL) != NULL);
+       } else self->adjust_symbols = 0;
+
        elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
                struct symbol *f;
+               const char *name;
+               char *demangled;
                u64 obj_start;
                struct section *section = NULL;
                int is_label = elf_sym__is_label(&sym);
@@ -599,10 +620,19 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
                                goto out_elf_end;
                        }
                }
+               /*
+                * We need to figure out if the object was created from C++ sources
+                * DWARF DW_compile_unit has this, but we don't always have access
+                * to it...
+                */
+               name = elf_sym__name(&sym, symstrs);
+               demangled = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI);
+               if (demangled != NULL)
+                       name = demangled;
 
-               f = symbol__new(sym.st_value, sym.st_size,
-                               elf_sym__name(&sym, symstrs),
+               f = symbol__new(sym.st_value, sym.st_size, name,
                                self->sym_priv_size, obj_start, verbose);
+               free(demangled);
                if (!f)
                        goto out_elf_end;
 
@@ -668,6 +698,11 @@ more:
        if (!ret)
                goto more;
 
+       if (ret > 0) {
+               int nr_plt = dso__synthesize_plt_symbols(self, verbose);
+               if (nr_plt > 0)
+                       ret += nr_plt;
+       }
 out:
        free(name);
        return ret;
index 7918cffb23cd35726cad6eca22acce0fd74cf392..2f92b21c712d2137e3cd85df61650abcedd20be5 100644 (file)
@@ -25,6 +25,7 @@ struct dso {
        struct symbol    *(*find_symbol)(struct dso *, u64 ip);
        unsigned int     sym_priv_size;
        unsigned char    adjust_symbols;
+       unsigned char    slen_calculated;
        char             name[0];
 };
 
index b4be6071c105754a171b5a83272b07ebe300c15b..68fe157d72fb9ddae6991fdfa9b1c69ac7f51fa4 100644 (file)
@@ -50,6 +50,7 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <sys/stat.h>
+#include <sys/statfs.h>
 #include <fcntl.h>
 #include <stddef.h>
 #include <stdlib.h>
@@ -80,6 +81,7 @@
 #include <netdb.h>
 #include <pwd.h>
 #include <inttypes.h>
+#include "../../../include/linux/magic.h"
 
 #ifndef NO_ICONV
 #include <iconv.h>