Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 22 Jul 2009 17:11:47 +0000 (10:11 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 22 Jul 2009 17:11:47 +0000 (10:11 -0700)
* 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  clocksource: Prevent NULL pointer dereference
  timer: Avoid reading uninitialized data

165 files changed:
CREDITS
Documentation/RCU/rculist_nulls.txt
Documentation/connector/cn_test.c
Documentation/connector/ucon.c
Documentation/networking/6pack.txt
MAINTAINERS
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/mn10300/kernel/vmlinux.lds.S
block/blk-sysfs.c
block/elevator.c
drivers/block/ataflop.c
drivers/block/virtio_blk.c
drivers/block/z2ram.c
drivers/char/hvc_console.c
drivers/char/nozomi.c
drivers/char/pcmcia/ipwireless/tty.c
drivers/char/specialix.c
drivers/char/vc_screen.c
drivers/connector/cn_queue.c
drivers/connector/connector.c
drivers/hid/hid-core.c
drivers/hid/usbhid/hiddev.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/mmc/host/mvsdio.c
drivers/mmc/host/pxamci.c
drivers/mtd/ubi/gluebi.c
drivers/mtd/ubi/scan.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/arm/Kconfig
drivers/net/arm/Makefile
drivers/net/arm/w90p910_ether.c [new file with mode: 0644]
drivers/net/atl1c/atl1c.h
drivers/net/atl1c/atl1c_main.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/e100.c
drivers/net/hamradio/6pack.c
drivers/net/ibm_newemac/rgmii.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/en_ethtool.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/sc92031.c
drivers/net/sky2.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/usb/class/cdc-acm.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/video/backlight/pwm_bl.c
drivers/video/fbmon.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/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]
include/asm-generic/vmlinux.lds.h
include/linux/interrupt.h
include/linux/sched.h
include/net/sock.h
include/net/tcp.h
kernel/freezer.c
kernel/irq/internals.h
kernel/irq/manage.c
kernel/irq/migration.c
kernel/perf_counter.c
kernel/sched.c
kernel/sched_fair.c
net/9p/client.c
net/can/bcm.c
net/can/raw.c
net/core/sock.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv6/tcp_ipv6.c
net/netfilter/nf_conntrack_core.c
net/netfilter/xt_osf.c
scripts/kconfig/lxdialog/util.c
scripts/kconfig/mconf.c
scripts/package/builddeb
sound/core/seq/Makefile
sound/isa/gus/gus_pcm.c
sound/pci/ca0106/ca0106_main.c
sound/pci/ctxfi/ctdaio.c
sound/pci/hda/hda_codec.c
sound/pci/hda/patch_sigmatel.c

diff --git a/CREDITS b/CREDITS
index 2b88fb3..e76d300 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 93cb28d..18f9651 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 f688eba..6a5be5d 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 d738cde..c5092ad 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 d0777a1..8f33942 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 18c3f0c..ebc2691 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 4762d90..7d61ae6 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 a2df5bb..dbcac9c 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 e021a80..bc74278 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 17a21a2..851f245 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 0322696..6b97754 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 5411810..ee331fd 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 d927edd..9e87e08 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 c6f61a1..840cfda 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 ae84411..7139e0d 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 6f678d9..09b7b1a 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 9ea9c05..facbd49 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 89b3ccf..7936085 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 69214fc..31093af 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 27f8d1b..2eb182f 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 abc79d4..98548c6 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 16561ab..f8a664f 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 565b813..fadfa82 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 cbd52f8..0b78b87 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 d0be99b..a36ad8d 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 e0bf8cc..9f9b828 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 beffa00..6b94462 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 d6c0677..685f160 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 79cad0a..9da36ba 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 6136c33..6225eda 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 8a1caf2..bf2b2d1 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 84b9c55..e57bf6f 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 d979110..809be26 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 426e064..753ed81 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 0fb2ce5..dbade93 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 f4867ce..b09484f 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 b2f30f0..2ad68cd 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 799a1d1..75e563d 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 0d63f74..c438ca8 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 a625659..ebd6ceb 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 a68ade8..3d743cc 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 70a0ad6..cd83db2 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 a3789d7..4062e24 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 c1f76dd..bd65690 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 57c128c..e66aa13 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 b86662f..e95d54f 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 c97acdf..451cf8a 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 c536551..999f239 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 81f5b95..dc0dd9b 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 18a4cd2..cd040fe 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 94b8e27..a5312b2 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 a1b5087..fd5e887 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 a63e15c..5b96ea5 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 5a4e7c7..fb1795d 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 6184005..349ee3f 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 c96ba3d..f4aa079 100644 (file)
@@ -107,7 +107,7 @@ SECTIONS
   __init_end = .;
   /* freed after init ends here */
 
-  BSS(4)
+  BSS_SECTION(0, PAGE_SIZE, 4)
 
   _end = . ;
 
index b1cd040..418d636 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 6f23753..2d511f9 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 f5e7180..3ff0294 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 fbeefb6..aa1a3d5 100644 (file)
@@ -427,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 4575171..b259040 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 94e7e3c..d97779e 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 280b41c..ec58d8c 100644 (file)
@@ -1866,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 569f2f7..674b3ab 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 bfe4cdb..268e17f 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 d94d25c..c1791a6 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 c769ef2..408c2af 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 fd336c5..08b2500 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 f2c21d5..5eb10c2 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 9e94215..215b2ad 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 6951811..7f87801 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 013dc59..bc5fb12 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 114efd8..1148140 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 0e12f89..4cfd084 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 b868b8d..f155ad8 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 df3f8aa..95fe045 100644 (file)
@@ -895,6 +895,13 @@ static unsigned int atkbd_amilo_pa1510_forced_release_keys[] = {
 };
 
 /*
+ * 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
  */
 static unsigned int atkbd_amilo_xi3650_forced_release_keys[] = {
@@ -902,6 +909,13 @@ static unsigned int atkbd_amilo_xi3650_forced_release_keys[] = {
 };
 
 /*
+ * 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
  */
@@ -1568,6 +1582,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
                .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 = {
                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
@@ -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 6d67af5..21cb755 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 7c8957d..26e17a9 100644 (file)
@@ -646,6 +646,15 @@ static struct dmi_system_id dmi_ids[] __initdata = {
        },
        {
                .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",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
index 1ebfcab..8ff7e35 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 b56d72f..34e2348 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 d7d7109..e55ac79 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 95aaac0..b5e478f 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 f60895e..a423131 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 c155bd3..b5a7513 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 4b58a59..ead8cab 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 2895db1..c37ee9e 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 811a3cc..303171f 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
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 e1658ef..2a1120a 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 cd547a2..a383122 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 ed648ac..2ee581a 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 d927f71..aa1be1f 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 574dadd..9e4283a 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 571f133..08ebee7 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 efa680f..41b648a 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 1551600..981ab53 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 1d5379d..8d76cb8 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 7c5978a..da2c851 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 d12106b..2f28609 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 acd143d..61eabca 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 091f990..86467b4 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 e1cdba7..f86e050 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 4754f5c..9f8ae47 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 ce3b89d..b9123d4 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 b899bd5..5d3343e 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 27539dd..637ac8b 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 ec7cf5a..690b9c7 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 18821f2..e3156c9 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 daf961a..3550c5d 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 a906d39..c47237c 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 b870b0b..e17afb7 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 cd35d50..45cebfb 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 5b15d9d..e1f8941 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 bfc5ce0..ccd4dd3 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 14971a9..3bc609f 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 e641584..8871662 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 5c1a2c0..9ae9cd3 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 e9f950f..cdd55e0 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 6fcb1e7..9282828 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 a97263b..0e7da7b 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 7f19fef..42cec2a 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 63f6cdf..6084d63 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 922f5fe..1866bc2 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 e16d759..9bb5c87 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 c2d0616..8d25ccb 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 38d42c2..32062c3 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 61bc3a3..6ea07a3 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 ff0c080..6917311 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 b73c5a7..65ca8c1 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 a553f10..6ad76bf 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 2721f07..88b056a 100644 (file)
  * 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 *);
index 16a982e..3ab08e4 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 2c0da92..950409d 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 19f4150..88af843 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 2f4936c..bd1d42b 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 7346825..e70ed55 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 50da676..f0de36f 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;
@@ -444,6 +452,34 @@ static int irq_wait_for_interrupt(struct irqaction *action)
 }
 
 /*
+ * 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);
+}
+
+/*
  * Interrupt handler thread
  */
 static int irq_thread(void *data)
@@ -458,6 +494,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 cfe767c..fcb6c96 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 a641eb7..7bc888d 100644 (file)
@@ -2665,6 +2665,7 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
                header.size += sizeof(cpu_entry);
 
                cpu_entry.cpu = raw_smp_processor_id();
+               cpu_entry.reserved = 0;
        }
 
        if (sample_type & PERF_SAMPLE_PERIOD)
index 98972d3..1b59e26 100644 (file)
@@ -7289,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 */
 
@@ -7515,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:
@@ -7525,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));
 
index 7c248dc..9ffb2b2 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;
@@ -1017,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;
 
        /*
@@ -1713,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 dd43a82..787ccdd 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 95d7f32..72720c7 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 6aa154e..f4cc445 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 ba5d211..bbb25be 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);
@@ -1140,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);
 
                /*
@@ -1855,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 5a1ca26..6d88219 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 5bdf08d..bd62712 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 58810c6..d849dd5 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 7508f11..b5869b9 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 863e409..0f482e2 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 86d95cc..f2375ad 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 3bcacb4..25b60bc 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 b19f1f4..8b357b0 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 1bcb360..941f64a 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 edb11ee..2dcf45b 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 f24bf1e..15e4138 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 082e35c..deb6cfa 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 26d255d..88480c0 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 41b5b3a..da7f9f6 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 */
 };
@@ -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;