]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Fri, 20 Jul 2007 15:46:42 +0000 (08:46 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Fri, 20 Jul 2007 15:46:42 +0000 (08:46 -0700)
* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev: (29 commits)
  libata: implement EH fast drain
  libata: schedule probing after SError access failure during autopsy
  libata: clear HOTPLUG flag after a reset
  libata: reorganize ata_ehi_hotplugged()
  libata: improve SCSI scan failure handling
  libata: quickly trigger SATA SPD down after debouncing failed
  libata: improve SATA PHY speed down logic
  The SATA controller device ID is different according to
  ahci: implement SCR_NOTIFICATION r/w
  ahci: make NO_NCQ handling more consistent
  libata: make ->scr_read/write callbacks return error code
  libata: implement AC_ERR_NCQ
  libata: improve EH report formatting
  sata_sil24: separate out sil24_do_softreset()
  sata_sil24: separate out sil24_exec_polled_cmd()
  sata_sil24: replace sil24_update_tf() with sil24_read_tf()
  ahci: separate out ahci_do_softreset()
  ahci: separate out ahci_exec_polled_cmd()
  ahci: separate out ahci_kick_engine()
  ahci: use deadline instead of fixed timeout for 1st FIS for SRST
  ...

115 files changed:
MAINTAINERS
arch/i386/boot/compressed/relocs.c
arch/i386/kernel/vsyscall-note.S
arch/i386/xen/events.c
arch/i386/xen/setup.c
arch/i386/xen/vdso.h [new file with mode: 0644]
arch/m68k/Kconfig
arch/m68k/apollo/config.c
arch/m68k/apollo/dn_ints.c
arch/m68k/atari/atakeyb.c
arch/m68k/bvme6000/config.c
arch/m68k/kernel/head.S
arch/m68k/kernel/setup.c
arch/m68k/kernel/sun3-head.S
arch/m68k/kernel/time.c
arch/m68k/kernel/vmlinux-std.lds
arch/m68k/kernel/vmlinux-sun3.lds
arch/m68k/mac/config.c
arch/m68k/mac/macints.c
arch/m68k/mm/init.c
arch/m68k/mm/sun3kmap.c
arch/m68k/mvme147/config.c
arch/m68k/mvme16x/config.c
arch/m68k/q40/q40ints.c
arch/m68k/sun3/sun3ints.c
arch/m68k/sun3x/prom.c
arch/m68knommu/kernel/setup.c
arch/sparc/kernel/systbls.S
arch/sparc64/defconfig
arch/sparc64/kernel/ds.c
arch/sparc64/kernel/head.S
arch/sparc64/kernel/irq.c
arch/sparc64/kernel/mdesc.c
arch/sparc64/kernel/power.c
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/systbls.S
arch/sparc64/kernel/vio.c
crypto/async_tx/async_memcpy.c
drivers/block/sunvdc.c
drivers/char/Kconfig
drivers/char/serial167.c
drivers/char/tpm/tpm_bios.c
drivers/char/vme_scc.c
drivers/ide/legacy/falconide.c
drivers/lguest/io.c
drivers/md/raid5.c
drivers/net/mac89x0.c
drivers/net/sky2.c
drivers/net/sunvnet.c
drivers/parport/Kconfig
drivers/scsi/Kconfig
drivers/scsi/NCR53C9x.c
drivers/scsi/iscsi_tcp.c
drivers/usb/atm/cxacru.c
drivers/usb/atm/speedtch.c
drivers/usb/atm/ueagle-atm.c
drivers/usb/atm/usbatm.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/usblp.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/message.c
drivers/usb/core/sysfs.c
drivers/usb/core/urb.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/Makefile
drivers/usb/gadget/amd5536udc.c [new file with mode: 0644]
drivers/usb/gadget/amd5536udc.h [new file with mode: 0644]
drivers/usb/gadget/ether.c
drivers/usb/gadget/gadget_chips.h
drivers/usb/gadget/m66592-udc.c
drivers/usb/gadget/m66592-udc.h
drivers/usb/gadget/serial.c
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/r8a66597.h
drivers/usb/host/u132-hcd.c
drivers/usb/host/uhci-q.c
drivers/usb/image/mdc800.c
drivers/usb/image/microtek.c
drivers/usb/misc/adutux.c
drivers/usb/misc/appledisplay.c
drivers/usb/misc/auerswald.c
drivers/usb/misc/ftdi-elan.c
drivers/usb/misc/iowarrior.c
drivers/usb/misc/ldusb.c
drivers/usb/misc/legousbtower.c
drivers/usb/misc/phidgetkit.c
drivers/usb/misc/phidgetmotorcontrol.c
drivers/usb/misc/usblcd.c
drivers/usb/misc/usbtest.c
drivers/usb/misc/uss720.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/sierra.c
drivers/usb/storage/dpcm.c
drivers/usb/storage/onetouch.c
drivers/usb/storage/unusual_devs.h
drivers/video/backlight/cr_bllcd.c
fs/buffer.c
fs/ecryptfs/mmap.c
fs/ocfs2/mmap.c
include/asm-m68k/io.h
include/asm-m68k/raw_io.h
include/asm-sparc/unistd.h
include/asm-sparc64/power.h [deleted file]
include/asm-sparc64/unistd.h
include/asm-sparc64/vio.h
include/linux/async_tx.h
include/linux/slub_def.h
mm/page_alloc.c
net/netfilter/nf_conntrack_helper.c
scripts/Lindent
scripts/mod/modpost.c

index fbe0dca1c0ed9d13974e20cea2bb4a800c662551..f49c5563f060d723b9789451cef25e12bcdf83bb 100644 (file)
@@ -329,6 +329,12 @@ P: Ivan Kokshaysky
 M:     ink@jurassic.park.msu.ru
 S:     Maintained for 2.4; PCI support for 2.6.
 
+AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER
+P:     Thomas Dahlmann
+M:     thomas.dahlmann@amd.com
+L:     info-linux@geode.amd.com
+S:     Supported
+
 AMD GEODE PROCESSOR/CHIPSET SUPPORT
 P:     Jordan Crouse
 M:     info-linux@geode.amd.com
index b0e21c3cee5c91f01075116b495b676e8023028b..2d77ee728f92188f5ea01b2bc27542857be92a74 100644 (file)
@@ -31,6 +31,7 @@ static const char* safe_abs_relocs[] = {
                "__kernel_rt_sigreturn",
                "__kernel_sigreturn",
                "SYSENTER_RETURN",
+               "VDSO_NOTE_MASK",
                "xen_irq_disable_direct_reloc",
                "xen_save_fl_direct_reloc",
 };
index 271f16a8ca01044bbc8f58058286ba812e2a7dab..07c0daf78237bcb1b80ea1401ada31f0f1065cb2 100644 (file)
@@ -14,7 +14,6 @@ ELFNOTE_START(Linux, 0, "a")
 ELFNOTE_END
 
 #ifdef CONFIG_XEN
-
 /*
  * Add a special note telling glibc's dynamic linker a fake hardware
  * flavor that it will use to choose the search path for libraries in the
@@ -28,15 +27,19 @@ ELFNOTE_END
  * It should contain:
  *     hwcap 1 nosegneg
  * to match the mapping of bit to name that we give here.
+ *
+ * At runtime, the fake hardware feature will be considered to be present
+ * if its bit is set in the mask word.  So, we start with the mask 0, and
+ * at boot time we set VDSO_NOTE_NONEGSEG_BIT if running under Xen.
  */
 
-/* Bit used for the pseudo-hwcap for non-negative segments.  We use
-   bit 1 to avoid bugs in some versions of glibc when bit 0 is
-   used; the choice is otherwise arbitrary. */
-#define VDSO_NOTE_NONEGSEG_BIT 1
+#include "../xen/vdso.h"       /* Defines VDSO_NOTE_NONEGSEG_BIT.  */
 
+       .globl VDSO_NOTE_MASK
 ELFNOTE_START(GNU, 2, "a")
-       .long 1, 1<<VDSO_NOTE_NONEGSEG_BIT              /* ncaps, mask */
+       .long 1                 /* ncaps */
+VDSO_NOTE_MASK:
+       .long 0                 /* mask */
        .byte VDSO_NOTE_NONEGSEG_BIT; .asciz "nosegneg" /* bit, name */
 ELFNOTE_END
 #endif
index 8904acc20f8cd14437b2794f5e13e840640c4bd7..da1b173547a112d9fcf1d3dcc86d2bfd67b5c5ff 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/irq.h>
 #include <asm/sync_bitops.h>
 #include <asm/xen/hypercall.h>
+#include <asm/xen/hypervisor.h>
 
 #include <xen/events.h>
 #include <xen/interface/xen.h>
index 2fe6eac510f0644c8a9f96358f0cdcf5bd72b16d..f84e772266461aec8a76b4feeb2ba318e21e0547 100644 (file)
@@ -19,6 +19,7 @@
 #include <xen/features.h>
 
 #include "xen-ops.h"
+#include "vdso.h"
 
 /* These are code, but not functions.  Defined in entry.S */
 extern const char xen_hypervisor_callback[];
@@ -55,6 +56,18 @@ static void xen_idle(void)
        }
 }
 
+/*
+ * Set the bit indicating "nosegneg" library variants should be used.
+ */
+static void fiddle_vdso(void)
+{
+       extern u32 VDSO_NOTE_MASK; /* See ../kernel/vsyscall-note.S.  */
+       extern char vsyscall_int80_start;
+       u32 *mask = (u32 *) ((unsigned long) &VDSO_NOTE_MASK - VDSO_PRELINK +
+                            &vsyscall_int80_start);
+       *mask |= 1 << VDSO_NOTE_NONEGSEG_BIT;
+}
+
 void __init xen_arch_setup(void)
 {
        struct physdev_set_iopl set_iopl;
@@ -93,4 +106,6 @@ void __init xen_arch_setup(void)
 #endif
 
        paravirt_disable_iospace();
+
+       fiddle_vdso();
 }
diff --git a/arch/i386/xen/vdso.h b/arch/i386/xen/vdso.h
new file mode 100644 (file)
index 0000000..861fedf
--- /dev/null
@@ -0,0 +1,4 @@
+/* Bit used for the pseudo-hwcap for non-negative segments.  We use
+   bit 1 to avoid bugs in some versions of glibc when bit 0 is
+   used; the choice is otherwise arbitrary. */
+#define VDSO_NOTE_NONEGSEG_BIT 1
index a86e2e9a639fff5c20a9378cf9f27c52158a4623..20a9c08e59c34ee34b21adb100b33014c99a39ff 100644 (file)
@@ -37,6 +37,10 @@ config TIME_LOW_RES
        bool
        default y
 
+config GENERIC_IOMAP
+       bool
+       default y
+
 config ARCH_MAY_HAVE_PC_FDC
        bool
        depends on Q40 || (BROKEN && SUN3X)
@@ -45,6 +49,9 @@ config ARCH_MAY_HAVE_PC_FDC
 config NO_IOPORT
        def_bool y
 
+config NO_DMA
+       def_bool SUN3
+
 mainmenu "Linux/68k Kernel Configuration"
 
 source "init/Kconfig"
index cb8e7609df4c1308ef105864d88030a318ff0634..78df98f2029af9e5556f33973c71949da070a8fc 100644 (file)
@@ -148,8 +148,8 @@ void dn_serial_print (const char *str)
     }
 }
 
-void config_apollo(void) {
-
+void __init config_apollo(void)
+{
        int i;
 
        dn_setup_model();
index 13bd41bed28e52d600ef76e6d0beaa4abee33b62..5d47f3aa3810fb0d5af3abab09a01156fa6b2a7f 100644 (file)
@@ -37,7 +37,7 @@ static struct irq_controller apollo_irq_controller = {
 };
 
 
-void dn_init_IRQ(void)
+void __init dn_init_IRQ(void)
 {
        m68k_setup_user_interrupt(VEC_USER + 96, 16, dn_process_int);
        m68k_setup_irq_controller(&apollo_irq_controller, IRQ_APOLLO, 16);
index 1c29603b16b31058cd47c6e644b1921d24859a84..2b5f64726a2e88ff851c4c02119f5729e7947d80 100644 (file)
@@ -13,6 +13,7 @@
  * enhanced by Bjoern Brauel and Roman Hodek
  */
 
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
@@ -42,6 +43,9 @@ void (*atari_mouse_interrupt_hook) (char *);
 void (*atari_input_keyboard_interrupt_hook) (unsigned char, char);
 /* Hook for mouse inputdev  driver */
 void (*atari_input_mouse_interrupt_hook) (char *);
+EXPORT_SYMBOL(atari_mouse_interrupt_hook);
+EXPORT_SYMBOL(atari_input_keyboard_interrupt_hook);
+EXPORT_SYMBOL(atari_input_mouse_interrupt_hook);
 
 /* variables for IKBD self test: */
 
@@ -429,6 +433,7 @@ void ikbd_mouse_rel_pos(void)
 
        ikbd_write(cmd, 1);
 }
+EXPORT_SYMBOL(ikbd_mouse_rel_pos);
 
 /* Set absolute mouse position reporting */
 void ikbd_mouse_abs_pos(int xmax, int ymax)
@@ -453,6 +458,7 @@ void ikbd_mouse_thresh(int x, int y)
 
        ikbd_write(cmd, 3);
 }
+EXPORT_SYMBOL(ikbd_mouse_thresh);
 
 /* Set mouse scale */
 void ikbd_mouse_scale(int x, int y)
@@ -495,6 +501,7 @@ void ikbd_mouse_y0_top(void)
 
        ikbd_write(cmd, 1);
 }
+EXPORT_SYMBOL(ikbd_mouse_y0_top);
 
 /* Resume */
 void ikbd_resume(void)
@@ -511,6 +518,7 @@ void ikbd_mouse_disable(void)
 
        ikbd_write(cmd, 1);
 }
+EXPORT_SYMBOL(ikbd_mouse_disable);
 
 /* Pause output */
 void ikbd_pause(void)
@@ -696,7 +704,6 @@ int __init atari_keyb_init(void)
        return 0;
 }
 
-
 int atari_kbdrate(struct kbd_repeat *k)
 {
        if (k->delay > 0) {
index 896ae3d3d91905bcb40b71636e778155345a298b..9433a88a33c4093866e6ea603182f0975e6b0e54 100644 (file)
@@ -97,7 +97,7 @@ static int bvme6000_get_hardware_list(char *buffer)
  * This function is called during kernel startup to initialize
  * the bvme6000 IRQ handling routines.
  */
-static void bvme6000_init_IRQ(void)
+static void __init bvme6000_init_IRQ(void)
 {
        m68k_setup_user_interrupt(VEC_USER, 192, NULL);
 }
index 05741f23356720aef7c7c2ebcb015720ea8dec03..faa6764f1d13617c0b9580d0aef9c8641a325691 100644 (file)
@@ -577,7 +577,7 @@ func_define putn,1
 #endif
 .endm
 
-.text
+.section ".text.head","ax"
 ENTRY(_stext)
 /*
  * Version numbers of the bootinfo interface
index 215c7bd43924f43a21ce8b55d90ef3acc54e6da2..7e6d5fb75390e7a92b5c438c6b0059e03e2e432e 100644 (file)
@@ -58,6 +58,7 @@ extern int end;
 extern unsigned long availmem;
 
 int m68k_num_memory;
+EXPORT_SYMBOL(m68k_num_memory);
 int m68k_realnum_memory;
 EXPORT_SYMBOL(m68k_realnum_memory);
 unsigned long m68k_memoffset;
index 4b5f050204e860ca7f2991e487d83602517b916f..aad01592dbbcd12304674fdfff0ff8ef1903bbdc 100644 (file)
@@ -29,7 +29,7 @@ kernel_pmd_table:              .skip 0x2000
 .globl kernel_pg_dir
 .equ    kernel_pg_dir,kernel_pmd_table
 
-       .section .head
+       .section .text.head
 ENTRY(_stext)
 ENTRY(_start)
 
index 4c065f9ceffcd5ab7fcfe6e8de09b3e6d2adacc9..7db41594d7b6b92d4beed91da8a6d847e16128af 100644 (file)
@@ -72,7 +72,7 @@ static irqreturn_t timer_interrupt(int irq, void *dummy)
        return IRQ_HANDLED;
 }
 
-void time_init(void)
+void __init time_init(void)
 {
        struct rtc_time time;
 
index 40f02b128f22bb3a62ebce9d66349f3f78dc7fdc..c42245775a4db9d520df660424c6c7e690480beb 100644 (file)
@@ -11,6 +11,7 @@ SECTIONS
   . = 0x1000;
   _text = .;                   /* Text and read-only data */
   .text : {
+       *(.text.head)
        TEXT_TEXT
        SCHED_TEXT
        LOCK_TEXT
index f06425b6d20643a9fc32d74bfdc5af6c3487a394..4adffefb5c48c673b5f349a6c0142b4a10a26ada 100644 (file)
@@ -11,7 +11,7 @@ SECTIONS
   . = 0xE002000;
   _text = .;                   /* Text and read-only data */
   .text : {
-       *(.head)
+       *(.text.head)
        TEXT_TEXT
        SCHED_TEXT
        LOCK_TEXT
index 5fd413246f89d923f858b28ca33ec4558679df98..8547dbc5e8d73335a9b78a2bb37a1e416ac37b8f 100644 (file)
@@ -49,6 +49,7 @@ struct mac_booter_data mac_bi_data;
 int mac_bisize = sizeof mac_bi_data;
 
 struct mac_hw_present mac_hw_present;
+EXPORT_SYMBOL(mac_hw_present);
 
 /* New m68k bootinfo stuff and videobase */
 
@@ -84,7 +85,7 @@ extern void nubus_sweep_video(void);
 
 static void mac_get_model(char *str);
 
-static void mac_sched_init(irq_handler_t vector)
+static void __init mac_sched_init(irq_handler_t vector)
 {
        via_init_clock(vector);
 }
@@ -769,7 +770,7 @@ static struct mac_model mac_data_table[] = {
        }
 };
 
-void mac_identify(void)
+void __init mac_identify(void)
 {
        struct mac_model *m;
 
@@ -846,7 +847,7 @@ void mac_identify(void)
        baboon_init();
 }
 
-void mac_report_hardware(void)
+void __init mac_report_hardware(void)
 {
        printk(KERN_INFO "Apple Macintosh %s\n", macintosh_config->name);
 }
index 0fc72d8f786e1ee3f271f1ab088190519a233af5..ecddac4a02b95abc11f80dbff860d2bdaea32fbd 100644 (file)
  *
  */
 
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -224,7 +225,7 @@ static struct irq_controller mac_irq_controller = {
        .disable        = mac_disable_irq,
 };
 
-void mac_init_IRQ(void)
+void __init mac_init_IRQ(void)
 {
 #ifdef DEBUG_MACINTS
        printk("mac_init_IRQ(): Setting things up...\n");
@@ -391,6 +392,7 @@ int mac_irq_pending(unsigned int irq)
        }
        return 0;
 }
+EXPORT_SYMBOL(mac_irq_pending);
 
 static int num_debug[8];
 
index f1de19e1dde66f50317db6f7a40992fdba481f2f..f42caa79e4e89f9fadf73041d33ab81077e7d11f 100644 (file)
@@ -44,7 +44,7 @@ pg_data_t *pg_data_table[65];
 EXPORT_SYMBOL(pg_data_table);
 #endif
 
-void m68k_setup_node(int node)
+void __init m68k_setup_node(int node)
 {
 #ifndef CONFIG_SINGLE_MEMORY_CHUNK
        struct mem_info *info = m68k_memory + node;
index 1af24cb5bfe136b4f8e18337ad72d8609bc4e755..3dc41158c05e973af1a57d9eb43b48fa1db87677 100644 (file)
@@ -105,6 +105,7 @@ void __iomem *sun3_ioremap(unsigned long phys, unsigned long size,
        return (void __iomem *)ret;
 
 }
+EXPORT_SYMBOL(sun3_ioremap);
 
 
 void __iomem *__ioremap(unsigned long phys, unsigned long size, int cache)
@@ -157,3 +158,4 @@ int sun3_map_test(unsigned long addr, char *val)
 
        return ret;
 }
+EXPORT_SYMBOL(sun3_map_test);
index 4a7df9c3f85a533339350dd48669e09e80be6e9f..92fe507141126fd566973e9598c86dd31e9eb389 100644 (file)
@@ -89,7 +89,7 @@ static int mvme147_get_hardware_list(char *buffer)
  * the mvme147 IRQ handling routines.
  */
 
-void mvme147_init_IRQ(void)
+void __init mvme147_init_IRQ(void)
 {
        m68k_setup_user_interrupt(VEC_USER, 192, NULL);
 }
index c829ebb6b1af8510f380801138d6207f2d52c904..daa7851614013c385b7c9f4660120f716849d39b 100644 (file)
@@ -119,7 +119,7 @@ static int mvme16x_get_hardware_list(char *buffer)
  * that the base vectors for the VMEChip2 and PCCChip2 are valid.
  */
 
-static void mvme16x_init_IRQ (void)
+static void __init mvme16x_init_IRQ (void)
 {
        m68k_setup_user_interrupt(VEC_USER, 192, NULL);
 }
index 2fb25ae46a8a2249fc610a9d9fd5e7edb215da79..ad3ed1fb88793e066aca96628a8ecb505f038d05 100644 (file)
@@ -79,7 +79,7 @@ static struct irq_controller q40_irq_controller = {
 
 static int disabled;
 
-void q40_init_IRQ(void)
+void __init q40_init_IRQ(void)
 {
        m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX);
 
index 50df34bf80e320d24342c42a982591a1bee3786a..cf93481adb1d7f3bd074d719338f4072456deaf0 100644 (file)
@@ -97,7 +97,7 @@ static struct irq_controller sun3_irq_controller = {
        .disable        = sun3_disable_irq,
 };
 
-void sun3_init_IRQ(void)
+void __init sun3_init_IRQ(void)
 {
        *sun3_intreg = 1;
 
index 48f8eb7b15653efdb5f66f154801ea63b7b20f10..a7b7e818d6279450119f4a8da5e76cf1c6746466 100644 (file)
@@ -92,7 +92,7 @@ static struct console sun3x_debug = {
        .index  = -1,
 };
 
-void sun3x_prom_init(void)
+void __init sun3x_prom_init(void)
 {
        /* Read the vector table */
 
index 80f4e9d74ac17c7ca55b72fa06ec21e05fe1f29c..2203f694f26bb303ec057debe68bd3746891d4a3 100644 (file)
@@ -231,32 +231,33 @@ void setup_arch(char **cmdline_p)
 /*
  *     Get CPU information for use by the procfs.
  */
-
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
-    char *cpu, *mmu, *fpu;
-    u_long clockfreq;
+       char *cpu, *mmu, *fpu;
+       u_long clockfreq;
 
-    cpu = CPU;
-    mmu = "none";
-    fpu = "none";
+       cpu = CPU;
+       mmu = "none";
+       fpu = "none";
 
 #ifdef CONFIG_COLDFIRE
-    clockfreq = (loops_per_jiffy*HZ)*3;
+       clockfreq = (loops_per_jiffy * HZ) * 3;
 #else
-    clockfreq = (loops_per_jiffy*HZ)*16;
-#endif
-
-    seq_printf(m, "CPU:\t\t%s\n"
-                  "MMU:\t\t%s\n"
-                  "FPU:\t\t%s\n"
-                  "Clocking:\t%lu.%1luMHz\n"
-                  "BogoMips:\t%lu.%02lu\n"
-                  "Calibration:\t%lu loops\n",
-                  cpu, mmu, fpu,
-                  clockfreq/1000000,(clockfreq/100000)%10,
-                  (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100,
-                  (loops_per_jiffy*HZ));
+       clockfreq = (loops_per_jiffy * HZ) * 16;
+#endif
+
+       seq_printf(m, "CPU:\t\t%s\n"
+                     "MMU:\t\t%s\n"
+                     "FPU:\t\t%s\n"
+                     "Clocking:\t%lu.%1luMHz\n"
+                     "BogoMips:\t%lu.%02lu\n"
+                     "Calibration:\t%lu loops\n",
+                     cpu, mmu, fpu,
+                     clockfreq / 1000000,
+                     (clockfreq / 100000) % 10,
+                     (loops_per_jiffy * HZ) / 500000,
+                     ((loops_per_jiffy * HZ) / 5000) % 100,
+                     (loops_per_jiffy * HZ));
 
        return 0;
 }
index 90b52d4dab9a8ce4ec47d18f8ac6b2e188e39c9b..55722840859c89c15df7dc32409cdd902fb7c376 100644 (file)
@@ -1,8 +1,7 @@
-/* $Id: systbls.S,v 1.103 2002/02/08 03:57:14 davem Exp $
- * systbls.S: System call entry point tables for OS compatibility.
+/* systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
  *
  * Based upon preliminary work which is:
  *
@@ -80,7 +79,7 @@ sys_call_table:
 /*295*/        .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
 /*300*/        .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
 /*305*/        .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
-/*310*/        .long sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd
+/*310*/        .long sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd, sys_fallocate
 
 #ifdef CONFIG_SUNOS_EMUL
        /* Now the SunOS syscall table. */
@@ -198,6 +197,6 @@ sunos_sys_table:
        .long sunos_nosys, sunos_nosys, sunos_nosys
        .long sunos_nosys
 /*310*/        .long sunos_nosys, sunos_nosys, sunos_nosys
-       .long sunos_nosys
+       .long sunos_nosys, sunos_nosys
 
 #endif
index 45ebf91a280ce048a812f3350418db966a480242..10e301970a44daa0db1737d6c46c829aee56684f 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.22
-# Tue Jul 17 01:19:52 2007
+# Thu Jul 19 21:30:37 2007
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -16,6 +16,7 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_AUDIT_ARCH=y
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
 CONFIG_SPARC64_PAGE_SIZE_8KB=y
 # CONFIG_SPARC64_PAGE_SIZE_64KB is not set
 # CONFIG_SPARC64_PAGE_SIZE_512KB is not set
@@ -148,7 +149,6 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=1
-CONFIG_VIRT_TO_BUS=y
 CONFIG_SBUS=y
 CONFIG_SBUSCHAR=y
 CONFIG_SUN_AUXIO=y
@@ -317,7 +317,6 @@ CONFIG_CONNECTOR=m
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
@@ -470,10 +469,6 @@ CONFIG_ISCSI_TCP=m
 # CONFIG_SCSI_SUNESP is not set
 # CONFIG_SCSI_SRP is not set
 # CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
@@ -610,10 +605,6 @@ CONFIG_SLHC=m
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
 # CONFIG_ISDN is not set
 # CONFIG_PHONE is not set
 
@@ -782,6 +773,7 @@ CONFIG_I2C_ALGOBIT=y
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
 # CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
@@ -808,11 +800,13 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
@@ -906,6 +900,7 @@ CONFIG_FB_RADEON_I2C=y
 # CONFIG_PROM_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 CONFIG_FONTS=y
 # CONFIG_FONT_8x8 is not set
@@ -1195,6 +1190,11 @@ CONFIG_USB_STORAGE=m
 # DMA Devices
 #
 
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
 #
 # Misc Linux/SPARC drivers
 #
@@ -1385,6 +1385,7 @@ CONFIG_SCHEDSTATS=y
 # CONFIG_DEBUG_MUTEXES is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1461,6 +1462,7 @@ CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
index fa1f04d756a286381ffb741602774ea546594481..1a2062ecb0bc8eb17b27bcc4f271c44dd4a31e00 100644 (file)
 #include <linux/delay.h>
 #include <linux/mutex.h>
 #include <linux/kthread.h>
+#include <linux/reboot.h>
 #include <linux/cpu.h>
 
 #include <asm/ldc.h>
 #include <asm/vio.h>
-#include <asm/power.h>
 #include <asm/mdesc.h>
 #include <asm/head.h>
 #include <asm/irq.h>
@@ -328,7 +328,7 @@ static void domain_shutdown_data(struct ldc_channel *lp,
 
        ds_send(lp, &pkt, sizeof(pkt));
 
-       wake_up_powerd();
+       orderly_poweroff(true);
 }
 
 struct ds_panic_req {
@@ -1133,8 +1133,6 @@ static int __devinit ds_probe(struct vio_dev *vdev,
 
        ds_info = dp;
 
-       start_powerd();
-
        return err;
 
 out_free_ldc:
index 77259526cb152daff39c213176ac02db1cae3346..35feacb6b8ec44d317a195b46c0e3e7dc438c14f 100644 (file)
@@ -458,7 +458,6 @@ tlb_fixup_done:
        or      %g6, %lo(init_thread_union), %g6
        ldx     [%g6 + TI_TASK], %g4
        mov     %sp, %l6
-       mov     %o4, %l7
 
        wr      %g0, ASI_P, %asi
        mov     1, %g1
index 8cb3358674f5257fcaff2ee83448592b1732e3dd..c72795666a624e393248d899bbeb8c70c3ff9e66 100644 (file)
@@ -701,10 +701,10 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
 {
        unsigned long sysino, hv_err;
 
-       BUG_ON(devhandle & ~IMAP_IGN);
-       BUG_ON(devino & ~IMAP_INO);
+       BUG_ON(devhandle & devino);
 
        sysino = devhandle | devino;
+       BUG_ON(sysino & ~(IMAP_IGN | IMAP_INO));
 
        hv_err = sun4v_vintr_set_cookie(devhandle, devino, sysino);
        if (hv_err) {
index 302ba5e5a0bb85d1b8c5f66b938c0177c9e504d2..13a79fe5115b3da4071a6a8aedb3f3d7f819b37e 100644 (file)
@@ -231,6 +231,25 @@ void mdesc_register_notifier(struct mdesc_notifier_client *client)
        mutex_unlock(&mdesc_mutex);
 }
 
+static const u64 *parent_cfg_handle(struct mdesc_handle *hp, u64 node)
+{
+       const u64 *id;
+       u64 a;
+
+       id = NULL;
+       mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
+               u64 target;
+
+               target = mdesc_arc_target(hp, a);
+               id = mdesc_get_property(hp, target,
+                                       "cfg-handle", NULL);
+               if (id)
+                       break;
+       }
+
+       return id;
+}
+
 /* Run 'func' on nodes which are in A but not in B.  */
 static void invoke_on_missing(const char *name,
                              struct mdesc_handle *a,
@@ -240,13 +259,42 @@ static void invoke_on_missing(const char *name,
        u64 node;
 
        mdesc_for_each_node_by_name(a, node, name) {
-               const u64 *id = mdesc_get_property(a, node, "id", NULL);
-               int found = 0;
+               int found = 0, is_vdc_port = 0;
+               const char *name_prop;
+               const u64 *id;
                u64 fnode;
 
+               name_prop = mdesc_get_property(a, node, "name", NULL);
+               if (name_prop && !strcmp(name_prop, "vdc-port")) {
+                       is_vdc_port = 1;
+                       id = parent_cfg_handle(a, node);
+               } else
+                       id = mdesc_get_property(a, node, "id", NULL);
+
+               if (!id) {
+                       printk(KERN_ERR "MD: Cannot find ID for %s node.\n",
+                              (name_prop ? name_prop : name));
+                       continue;
+               }
+
                mdesc_for_each_node_by_name(b, fnode, name) {
-                       const u64 *fid = mdesc_get_property(b, fnode,
-                                                           "id", NULL);
+                       const u64 *fid;
+
+                       if (is_vdc_port) {
+                               name_prop = mdesc_get_property(b, fnode,
+                                                              "name", NULL);
+                               if (!name_prop ||
+                                   strcmp(name_prop, "vdc-port"))
+                                       continue;
+                               fid = parent_cfg_handle(b, fnode);
+                               if (!fid) {
+                                       printk(KERN_ERR "MD: Cannot find ID "
+                                              "for vdc-port node.\n");
+                                       continue;
+                               }
+                       } else
+                               fid = mdesc_get_property(b, fnode,
+                                                        "id", NULL);
 
                        if (*id == *fid) {
                                found = 1;
index 8dd4294ad21ec0bcf0b3345d53f920efe999703c..39f9f6494d4c2f5486ca8d108d23a7922af6efd6 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/pm.h>
 #include <linux/syscalls.h>
+#include <linux/reboot.h>
 
 #include <asm/system.h>
 #include <asm/auxio.h>
 #include <asm/prom.h>
 #include <asm/of_device.h>
 #include <asm/io.h>
-#include <asm/power.h>
 #include <asm/sstate.h>
 
 #include <linux/unistd.h>
@@ -31,20 +31,9 @@ int scons_pwroff = 1;
 
 static void __iomem *power_reg;
 
-static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
-static int button_pressed;
-
-void wake_up_powerd(void)
-{
-       if (button_pressed == 0) {
-               button_pressed = 1;
-               wake_up(&powerd_wait);
-       }
-}
-
 static irqreturn_t power_handler(int irq, void *dev_id)
 {
-       wake_up_powerd();
+       orderly_poweroff(true);
 
        /* FIXME: Check registers for status... */
        return IRQ_HANDLED;
@@ -77,48 +66,6 @@ void machine_power_off(void)
 void (*pm_power_off)(void) = machine_power_off;
 EXPORT_SYMBOL(pm_power_off);
 
-static int powerd(void *__unused)
-{
-       static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
-       char *argv[] = { "/sbin/shutdown", "-h", "now", NULL };
-       DECLARE_WAITQUEUE(wait, current);
-
-       daemonize("powerd");
-
-       add_wait_queue(&powerd_wait, &wait);
-
-       for (;;) {
-               set_task_state(current, TASK_INTERRUPTIBLE);
-               if (button_pressed)
-                       break;
-               flush_signals(current);
-               schedule();
-       }
-       __set_current_state(TASK_RUNNING);
-       remove_wait_queue(&powerd_wait, &wait);
-
-       /* Ok, down we go... */
-       button_pressed = 0;
-       if (kernel_execve("/sbin/shutdown", argv, envp) < 0) {
-               printk(KERN_ERR "powerd: shutdown execution failed\n");
-               machine_power_off();
-       }
-       return 0;
-}
-
-int start_powerd(void)
-{
-       int err;
-
-       err = kernel_thread(powerd, NULL, CLONE_FS);
-       if (err < 0)
-               printk(KERN_ERR "power: Failed to start power daemon.\n");
-       else
-               printk(KERN_INFO "power: powerd running.\n");
-
-       return err;
-}
-
 static int __init has_button_interrupt(unsigned int irq, struct device_node *dp)
 {
        if (irq == 0xffffffff)
@@ -136,20 +83,15 @@ static int __devinit power_probe(struct of_device *op, const struct of_device_id
 
        power_reg = of_ioremap(res, 0, 0x4, "power");
 
-       printk("%s: Control reg at %lx ... ",
+       printk(KERN_INFO "%s: Control reg at %lx\n",
               op->node->name, res->start);
 
        poweroff_method = machine_halt;  /* able to use the standard halt */
 
        if (has_button_interrupt(irq, op->node)) {
-               if (start_powerd() < 0)
-                       return 0;
-
                if (request_irq(irq,
                                power_handler, 0, "power", NULL) < 0)
                        printk(KERN_ERR "power: Cannot setup IRQ handler.\n");
-       } else {
-               printk(KERN_INFO "power: Not using powerd.\n");
        }
 
        return 0;
index abd83129b2e73480031791032ea6a698eac26af8..e8dce90d05d45022589b4a75805798d35c6c4dbf 100644 (file)
@@ -1,8 +1,7 @@
-/* $Id: sys_sparc32.c,v 1.184 2002/02/09 19:49:31 davem Exp $
- * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
+/* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net)
  *
  * These routines maintain argument size conversion between 32bit and 64bit
  * environment.
@@ -1028,3 +1027,10 @@ long compat_sync_file_range(int fd, unsigned long off_high, unsigned long off_lo
                                   (nb_high << 32) | nb_low,
                                   flags);
 }
+
+asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo,
+                                    u32 lenhi, u32 lenlo)
+{
+       return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo,
+                            ((loff_t)lenhi << 32) | lenlo);
+}
index 8765e32155a06c83e21547f3fd30a26d71ac6d91..06d10907d8cee77ed3111a2b87a2a5c6e0bd98cb 100644 (file)
@@ -1,8 +1,7 @@
-/* $Id: systbls.S,v 1.81 2002/02/08 03:57:14 davem Exp $
- * systbls.S: System call entry point tables for OS compatibility.
+/* systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
- * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 1996, 2007 David S. Miller (davem@davemloft.net)
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  *
  * Based upon preliminary work which is:
@@ -81,7 +80,7 @@ sys_call_table32:
        .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
 /*300*/        .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy
        .word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
-/*310*/        .word compat_sys_utimensat, compat_sys_signalfd, compat_sys_timerfd, sys_eventfd
+/*310*/        .word compat_sys_utimensat, compat_sys_signalfd, compat_sys_timerfd, sys_eventfd, compat_sys_fallocate
 
 #endif /* CONFIG_COMPAT */
 
@@ -153,7 +152,7 @@ sys_call_table:
        .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
 /*300*/        .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
        .word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
-/*310*/        .word sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd
+/*310*/        .word sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd, sys_fallocate
 
 #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
     defined(CONFIG_SOLARIS_EMUL_MODULE)
@@ -272,6 +271,6 @@ sunos_sys_table:
        .word sunos_nosys, sunos_nosys, sunos_nosys
        .word sunos_nosys
 /*310*/        .word sunos_nosys, sunos_nosys, sunos_nosys
-       .word sunos_nosys
+       .word sunos_nosys, sunos_nosys
 
 #endif
index 8d3cc4fdb557018740e1f38076ef6a09b9a2f265..491223a6628f92c41cbb4c2c2de4e9d36685d1b7 100644 (file)
@@ -103,9 +103,9 @@ static ssize_t devspec_show(struct device *dev,
        struct vio_dev *vdev = to_vio_dev(dev);
        const char *str = "none";
 
-       if (!strcmp(vdev->type, "network"))
+       if (!strcmp(vdev->type, "vnet-port"))
                str = "vnet";
-       else if (!strcmp(vdev->type, "block"))
+       else if (!strcmp(vdev->type, "vdc-port"))
                str = "vdisk";
 
        return sprintf(buf, "%s\n", str);
@@ -221,6 +221,27 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
                return NULL;
        }
 
+       if (!strcmp(type, "vdc-port")) {
+               u64 a;
+
+               id = NULL;
+               mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
+                       u64 target;
+
+                       target = mdesc_arc_target(hp, a);
+                       id = mdesc_get_property(hp, target,
+                                               "cfg-handle", NULL);
+                       if (id)
+                               break;
+               }
+               if (!id) {
+                       printk(KERN_ERR "VIO: vdc-port lacks parent "
+                              "cfg-handle.\n");
+                       return NULL;
+               }
+       } else
+               id = mdesc_get_property(hp, mp, "id", NULL);
+
        bus_id_name = type;
        if (!strcmp(type, "domain-services-port"))
                bus_id_name = "ds";
@@ -260,13 +281,15 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
 
        vio_fill_channel_info(hp, mp, vdev);
 
-       id = mdesc_get_property(hp, mp, "id", NULL);
-       if (!id)
+       if (!id) {
                snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s",
                         bus_id_name);
-       else
+               vdev->dev_no = ~(u64)0;
+       } else {
                snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu",
                         bus_id_name, *id);
+               vdev->dev_no = *id;
+       }
 
        vdev->dev.parent = parent;
        vdev->dev.bus = &vio_bus_type;
index a973f4ef897d8cb369920f5c301a1e83e9b540e1..047e533fcc5ba249977895ea1c3969f6a6b0be2e 100644 (file)
@@ -36,7 +36,6 @@
  * @offset: offset in pages to start transaction
  * @len: length in bytes
  * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK,
- *     ASYNC_TX_KMAP_SRC, ASYNC_TX_KMAP_DST
  * @depend_tx: memcpy depends on the result of this transaction
  * @cb_fn: function to call when the memcpy completes
  * @cb_param: parameter to pass to the callback routine
@@ -88,23 +87,13 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
                                        __FUNCTION__);
                }
 
-               if (flags & ASYNC_TX_KMAP_DST)
-                       dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
-               else
-                       dest_buf = page_address(dest) + dest_offset;
-
-               if (flags & ASYNC_TX_KMAP_SRC)
-                       src_buf = kmap_atomic(src, KM_USER0) + src_offset;
-               else
-                       src_buf = page_address(src) + src_offset;
+               dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
+               src_buf = kmap_atomic(src, KM_USER1) + src_offset;
 
                memcpy(dest_buf, src_buf, len);
 
-               if (flags & ASYNC_TX_KMAP_DST)
-                       kunmap_atomic(dest_buf, KM_USER0);
-
-               if (flags & ASYNC_TX_KMAP_SRC)
-                       kunmap_atomic(src_buf, KM_USER0);
+               kunmap_atomic(dest_buf, KM_USER0);
+               kunmap_atomic(src_buf, KM_USER1);
 
                async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
        }
index 2288b55d916f9e12fc3ea2332acf40c3dfe67dff..d50b82381155d1990ee5434cc41bf7da59c60a24 100644 (file)
@@ -64,7 +64,6 @@ struct vdc_port {
        u64                     operations;
        u32                     vdisk_size;
        u8                      vdisk_type;
-       u8                      dev_no;
 
        char                    disk_name[32];
 
@@ -703,7 +702,7 @@ static int probe_disk(struct vdc_port *port)
        blk_queue_max_phys_segments(q, port->ring_cookies);
        blk_queue_max_sectors(q, port->max_xfer_size);
        g->major = vdc_major;
-       g->first_minor = port->dev_no << PARTITION_SHIFT;
+       g->first_minor = port->vio.vdev->dev_no << PARTITION_SHIFT;
        strcpy(g->disk_name, port->disk_name);
 
        g->fops = &vdc_fops;
@@ -747,21 +746,16 @@ static int __devinit vdc_port_probe(struct vio_dev *vdev,
 {
        struct mdesc_handle *hp;
        struct vdc_port *port;
-       const u64 *port_id;
        int err;
 
        print_version();
 
        hp = mdesc_grab();
 
-       port_id = mdesc_get_property(hp, vdev->mp, "id", NULL);
        err = -ENODEV;
-       if (!port_id) {
-               printk(KERN_ERR PFX "Port lacks id property.\n");
-               goto err_out_release_mdesc;
-       }
-       if ((*port_id << PARTITION_SHIFT) & ~(u64)MINORMASK) {
-               printk(KERN_ERR PFX "Port id [%lu] too large.\n", *port_id);
+       if ((vdev->dev_no << PARTITION_SHIFT) & ~(u64)MINORMASK) {
+               printk(KERN_ERR PFX "Port id [%lu] too large.\n",
+                      vdev->dev_no);
                goto err_out_release_mdesc;
        }
 
@@ -772,16 +766,14 @@ static int __devinit vdc_port_probe(struct vio_dev *vdev,
                goto err_out_release_mdesc;
        }
 
-       port->dev_no = *port_id;
-
-       if (port->dev_no >= 26)
+       if (vdev->dev_no >= 26)
                snprintf(port->disk_name, sizeof(port->disk_name),
                         VDCBLK_NAME "%c%c",
-                        'a' + (port->dev_no / 26) - 1,
-                        'a' + (port->dev_no % 26));
+                        'a' + ((int)vdev->dev_no / 26) - 1,
+                        'a' + ((int)vdev->dev_no % 26));
        else
                snprintf(port->disk_name, sizeof(port->disk_name),
-                        VDCBLK_NAME "%c", 'a' + (port->dev_no % 26));
+                        VDCBLK_NAME "%c", 'a' + ((int)vdev->dev_no % 26));
 
        err = vio_driver_init(&port->vio, vdev, VDEV_DISK,
                              vdc_versions, ARRAY_SIZE(vdc_versions),
@@ -849,7 +841,7 @@ static struct vio_device_id vdc_port_match[] = {
        },
        {},
 };
-MODULE_DEVICE_TABLE(vio, vdc_match);
+MODULE_DEVICE_TABLE(vio, vdc_port_match);
 
 static struct vio_driver vdc_port_driver = {
        .id_table       = vdc_port_match,
index 9e8f21410d2d06a3f499c5d22397a45fb5ff0472..4373d7cdc5d2cbc8d4282afa971e961f66400108 100644 (file)
@@ -185,7 +185,7 @@ config ESPSERIAL
 
 config MOXA_INTELLIO
        tristate "Moxa Intellio support"
-       depends on SERIAL_NONSTANDARD
+       depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
        help
          Say Y here if you have a Moxa Intellio multiport serial card.
 
@@ -241,7 +241,7 @@ config SYNCLINK
 
 config SYNCLINKMP
        tristate "SyncLink Multiport support"
-       depends on SERIAL_NONSTANDARD
+       depends on SERIAL_NONSTANDARD && PCI
        help
          Enable support for the SyncLink Multiport (2 or 4 ports)
          serial adapter, running asynchronous and HDLC communications up
index c585b4738f86c2b670a46e54c4b5a154a2c5ed5d..f1497cecffd815248a7eb374a0346e4e8fb88e2f 100644 (file)
@@ -2573,16 +2573,10 @@ static struct tty_driver *serial167_console_device(struct console *c,
        return cy_serial_driver;
 }
 
-static int __init serial167_console_setup(struct console *co, char *options)
-{
-       return 0;
-}
-
 static struct console sercons = {
        .name = "ttyS",
        .write = serial167_console_write,
        .device = serial167_console_device,
-       .setup = serial167_console_setup,
        .flags = CON_PRINTBUFFER,
        .index = -1,
 };
index 4eba32b23b297c2f15bd942292c754bcc4d7708b..4b26ce48189b73368685bb5de4ae53549ed5feda 100644 (file)
@@ -427,7 +427,7 @@ static int tpm_ascii_bios_measurements_open(struct inode *inode,
                return -ENOMEM;
 
        if ((err = read_log(log)))
-               return err;
+               goto out_free;
 
        /* now register seq file */
        err = seq_open(file, &tpm_ascii_b_measurments_seqops);
@@ -435,10 +435,15 @@ static int tpm_ascii_bios_measurements_open(struct inode *inode,
                seq = file->private_data;
                seq->private = log;
        } else {
-               kfree(log->bios_event_log);
-               kfree(log);
+               goto out_free;
        }
+
+out:
        return err;
+out_free:
+       kfree(log->bios_event_log);
+       kfree(log);
+       goto out;
 }
 
 const struct file_operations tpm_ascii_bios_measurements_ops = {
index bef6d886d4fb2f6e3e2ea3b69ee1da3e29673b0c..e122a0e87bb0b8a53984262ae29bc5d0d3e34e63 100644 (file)
@@ -1013,18 +1013,10 @@ static struct tty_driver *scc_console_device(struct console *c, int *index)
        return scc_driver;
 }
 
-
-static int __init scc_console_setup(struct console *co, char *options)
-{
-       return 0;
-}
-
-
 static struct console sercons = {
        .name           = "ttyS",
        .write          = scc_console_write,
        .device         = scc_console_device,
-       .setup          = scc_console_setup,
        .flags          = CON_PRINTBUFFER,
        .index          = -1,
 };
index e1e9d9d6893fdd82990abdf124ae049c4e23c681..f0829b83e970db20c5f7a500eee860bf1aa484a2 100644 (file)
@@ -8,6 +8,7 @@
  *  more details.
  */
 
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
@@ -54,6 +55,7 @@ static int falconide_offsets[IDE_NR_PORTS] __initdata = {
      */
 
 int falconide_intr_lock;
+EXPORT_SYMBOL(falconide_intr_lock);
 
 
     /*
index 06bdba2337ef4ba634fe325673fc3f833c765384..c8eb79266991efb68d34e077de859295e8f8edcb 100644 (file)
@@ -187,7 +187,7 @@ static u32 copy_data(struct lguest *srclg,
                /* FIXME: This is not completely portable, since
                   archs do different things for copy_to_user_page. */
                if (copy_from_user(maddr + (dst->addr[di] + dstoff)%PAGE_SIZE,
-                                  (void *__user)src->addr[si], len) != 0) {
+                                  (void __user *)src->addr[si], len) != 0) {
                        kill_guest(srclg, "bad address in sending DMA");
                        totlen = 0;
                        break;
index c8dfdb302916aa81e10f2c82e55198e8daaf4f01..d90ee145effeb8d841061fda1b394eabe3eae385 100644 (file)
@@ -493,12 +493,12 @@ async_copy_data(int frombio, struct bio *bio, struct page *page,
                        if (frombio)
                                tx = async_memcpy(page, bio_page, page_offset,
                                        b_offset, clen,
-                                       ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_SRC,
+                                       ASYNC_TX_DEP_ACK,
                                        tx, NULL, NULL);
                        else
                                tx = async_memcpy(bio_page, page, b_offset,
                                        page_offset, clen,
-                                       ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_DST,
+                                       ASYNC_TX_DEP_ACK,
                                        tx, NULL, NULL);
                }
                if (clen < len) /* hit end of page */
index 26a3b45a4a349e86f8072118969f3d89b2697fb4..62c1c6262febea4261c97bf79d61383bb687401b 100644 (file)
@@ -608,7 +608,7 @@ module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "CS89[02]0 debug level (0-5)");
 MODULE_LICENSE("GPL");
 
-int
+int __init
 init_module(void)
 {
        net_debug = debug;
index a2f32151559e4e05c56293dd566059e1485419a0..13f08a390e1f599e304b112d10ab428a495958c5 100644 (file)
@@ -692,6 +692,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
 {
        struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
        u16 reg;
+       u32 rx_reg;
        int i;
        const u8 *addr = hw->dev[port]->dev_addr;
 
@@ -768,11 +769,11 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
 
        /* Configure Rx MAC FIFO */
        sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
-       reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
+       rx_reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
        if (hw->chip_id == CHIP_ID_YUKON_EX)
-               reg |= GMF_RX_OVER_ON;
+               rx_reg |= GMF_RX_OVER_ON;
 
-       sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
+       sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg);
 
        /* Flush Rx MAC FIFO on any flow control or error */
        sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
index b801e3b3a11a002907d602560e3abfec4cd5234a..ef0066bab2cf77af11f99a2306e51a9a521402ca 100644 (file)
@@ -1136,7 +1136,7 @@ static struct vio_device_id vnet_port_match[] = {
        },
        {},
 };
-MODULE_DEVICE_TABLE(vio, vnet_match);
+MODULE_DEVICE_TABLE(vio, vnet_port_match);
 
 static struct vio_driver vnet_port_driver = {
        .id_table       = vnet_port_match,
index 09c93ff932b15453d316df1d12b7844697d9ca22..d449b150930ea7aedeb0b8ad0cb43a1140575391 100644 (file)
@@ -35,7 +35,7 @@ if PARPORT
 
 config PARPORT_PC
        tristate "PC-style hardware"
-       depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV
+       depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && (!M68K || ISA)
        ---help---
          You should say Y here if you have a PC-style parallel port. All
          IBM PC compatible computers and some Alphas have PC-style
index 372723161c97b8278c594220ff0c949076bdcd55..a947257b89646d8d7e99e5320ab0eaa04fbd62ab 100644 (file)
@@ -483,7 +483,7 @@ source "drivers/scsi/aic94xx/Kconfig"
 # All the I2O code and drivers do not seem to be 64bit safe.
 config SCSI_DPT_I2O
        tristate "Adaptec I2O RAID support "
-       depends on !64BIT && SCSI && PCI
+       depends on !64BIT && SCSI && PCI && VIRT_TO_BUS
        help
          This driver supports all of Adaptec's I2O based RAID controllers as 
          well as the DPT SmartRaid V cards.  This is an Adaptec maintained
index 773d11dd995394843d4d072238395a3608d7fc24..79b4df1581400691d1b9bbf9676b732a01586167 100644 (file)
@@ -95,6 +95,8 @@ enum {
 /* The master ring of all esp hosts we are managing in this driver. */
 static struct NCR_ESP *espchain;
 int nesps = 0, esps_in_use = 0, esps_running = 0;
+EXPORT_SYMBOL(nesps);
+EXPORT_SYMBOL(esps_running);
 
 irqreturn_t esp_intr(int irq, void *dev_id);
 
@@ -524,6 +526,7 @@ void esp_bootup_reset(struct NCR_ESP *esp, struct ESP_regs *eregs)
        /* Eat any bitrot in the chip and we are done... */
        trash = esp_read(eregs->esp_intrpt);
 }
+EXPORT_SYMBOL(esp_bootup_reset);
 
 /* Allocate structure and insert basic data such as SCSI chip frequency
  * data and a pointer to the device
@@ -772,6 +775,7 @@ const char *esp_info(struct Scsi_Host *host)
                panic("Bogon ESP revision");
        };
 }
+EXPORT_SYMBOL(esp_info);
 
 /* From Wolfgang Stanglmeier's NCR scsi driver. */
 struct info_str
@@ -902,6 +906,7 @@ int esp_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t off
                *start = buffer;
        return esp_host_info(esp, buffer, offset, length);
 }
+EXPORT_SYMBOL(esp_proc_info);
 
 static void esp_get_dmabufs(struct NCR_ESP *esp, Scsi_Cmnd *sp)
 {
@@ -3535,6 +3540,7 @@ state_machine:
        if(esp->dma_irq_exit)
                esp->dma_irq_exit(esp);
 }
+EXPORT_SYMBOL(esp_handle);
 
 #ifndef CONFIG_SMP
 irqreturn_t esp_intr(int irq, void *dev_id)
@@ -3631,6 +3637,7 @@ void esp_release(void)
        esps_in_use--;
        esps_running = esps_in_use;
 }
+EXPORT_SYMBOL(esp_release);
 #endif
 
 EXPORT_SYMBOL(esp_abort);
index aebcd5fcdc5518e012bf0ff425616ffcb7cd8cfe..7829ab1e2fb46d5bf350c9c6d54d0ff9dec4a01a 100644 (file)
@@ -1885,7 +1885,7 @@ static int iscsi_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,
        struct sockaddr_in *sin;
        int rc = 0, len;
 
-       addr = kmalloc(GFP_KERNEL, sizeof(*addr));
+       addr = kmalloc(sizeof(*addr), GFP_KERNEL);
        if (!addr)
                return -ENOMEM;
 
index 1bc884051e0f490dbae657df3bd085b5b8e568de..02c52f8d5dbf2b097af0b5f9e6b0a389afa7af6a 100644 (file)
@@ -456,7 +456,7 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,
                                 int* actual_length)
 {
        struct timer_list timer;
-       int status;
+       int status = urb->status;
 
        init_timer(&timer);
        timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT);
@@ -464,7 +464,6 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,
        timer.function = cxacru_timeout_kill;
        add_timer(&timer);
        wait_for_completion(done);
-       status = urb->status;
        del_timer_sync(&timer);
 
        if (actual_length)
index 638b8009b3bc2be1b78d9029d4a64980d94943e9..eb0615abff68a819f4dae10ff2a0010a637dbaaa 100644 (file)
@@ -612,7 +612,8 @@ static void speedtch_handle_int(struct urb *int_urb)
        struct speedtch_instance_data *instance = int_urb->context;
        struct usbatm_data *usbatm = instance->usbatm;
        unsigned int count = int_urb->actual_length;
-       int ret = int_urb->status;
+       int status = int_urb->status;
+       int ret;
 
        /* The magic interrupt for "up state" */
        static const unsigned char up_int[6]   = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 };
@@ -621,8 +622,8 @@ static void speedtch_handle_int(struct urb *int_urb)
 
        atm_dbg(usbatm, "%s entered\n", __func__);
 
-       if (ret < 0) {
-               atm_dbg(usbatm, "%s: nonzero urb status %d!\n", __func__, ret);
+       if (status < 0) {
+               atm_dbg(usbatm, "%s: nonzero urb status %d!\n", __func__, status);
                goto fail;
        }
 
index 8f046659b4e947990036968cc836bf69e8bc73e1..a1a1c9d467e028157c84289a9d92ccd0fe97c4b9 100644 (file)
@@ -1308,11 +1308,13 @@ static void uea_intr(struct urb *urb)
 {
        struct uea_softc *sc = urb->context;
        struct intr_pkt *intr = urb->transfer_buffer;
+       int status = urb->status;
+
        uea_enters(INS_TO_USBDEV(sc));
 
-       if (unlikely(urb->status < 0)) {
+       if (unlikely(status < 0)) {
                uea_err(INS_TO_USBDEV(sc), "uea_intr() failed with %d\n",
-                      urb->status);
+                      status);
                return;
        }
 
index 11e9b15ca45a35fb7c37e84fef91e07c54b2b507..e717f5b1caeeedeadbf51634726356311faa4c95 100644 (file)
@@ -257,9 +257,10 @@ static void usbatm_complete(struct urb *urb)
 {
        struct usbatm_channel *channel = urb->context;
        unsigned long flags;
+       int status = urb->status;
 
        vdbg("%s: urb 0x%p, status %d, actual_length %d",
-            __func__, urb, urb->status, urb->actual_length);
+            __func__, urb, status, urb->actual_length);
 
        /* usually in_interrupt(), but not always */
        spin_lock_irqsave(&channel->lock, flags);
@@ -269,16 +270,16 @@ static void usbatm_complete(struct urb *urb)
 
        spin_unlock_irqrestore(&channel->lock, flags);
 
-       if (unlikely(urb->status) &&
+       if (unlikely(status) &&
                        (!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) ||
-                        urb->status != -EILSEQ ))
+                        status != -EILSEQ ))
        {
-               if (urb->status == -ESHUTDOWN)
+               if (status == -ESHUTDOWN)
                        return;
 
                if (printk_ratelimit())
                        atm_warn(channel->usbatm, "%s: urb 0x%p failed (%d)!\n",
-                               __func__, urb, urb->status);
+                               __func__, urb, status);
                /* throttle processing in case of an error */
                mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS));
        } else
index cd51520c7e72e10286017998bf00081c8d8571cc..fe940e0536e03488016d1171da3866ce8bb6dd00 100644 (file)
@@ -257,9 +257,10 @@ static void acm_ctrl_irq(struct urb *urb)
        struct usb_cdc_notification *dr = urb->transfer_buffer;
        unsigned char *data;
        int newctrl;
-       int status;
+       int retval;
+       int status = urb->status;
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -267,10 +268,10 @@ static void acm_ctrl_irq(struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d", __FUNCTION__, status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero urb status received: %d", __FUNCTION__, status);
                goto exit;
        }
 
@@ -311,10 +312,10 @@ static void acm_ctrl_irq(struct urb *urb)
                        break;
        }
 exit:
-       status = usb_submit_urb (urb, GFP_ATOMIC);
-       if (status)
+       retval = usb_submit_urb (urb, GFP_ATOMIC);
+       if (retval)
                err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, status);
+                    __FUNCTION__, retval);
 }
 
 /* data interface returns incoming bytes, or we got unthrottled */
@@ -324,7 +325,8 @@ static void acm_read_bulk(struct urb *urb)
        struct acm_ru *rcv = urb->context;
        struct acm *acm = rcv->instance;
        int status = urb->status;
-       dbg("Entering acm_read_bulk with status %d", urb->status);
+
+       dbg("Entering acm_read_bulk with status %d", status);
 
        if (!ACM_READY(acm))
                return;
index 9a1478972bf5aee1cf75c5f70434d4e68c5fa83c..5192cd9356def4c3b23fb58783ca0ab379e75f14 100644 (file)
@@ -289,16 +289,17 @@ static int proto_bias = -1;
 static void usblp_bulk_read(struct urb *urb)
 {
        struct usblp *usblp = urb->context;
+       int status = urb->status;
 
        if (usblp->present && usblp->used) {
-               if (urb->status)
+               if (status)
                        printk(KERN_WARNING "usblp%d: "
                            "nonzero read bulk status received: %d\n",
-                           usblp->minor, urb->status);
+                           usblp->minor, status);
        }
        spin_lock(&usblp->lock);
-       if (urb->status < 0)
-               usblp->rstatus = urb->status;
+       if (status < 0)
+               usblp->rstatus = status;
        else
                usblp->rstatus = urb->actual_length;
        usblp->rcomplete = 1;
@@ -311,16 +312,17 @@ static void usblp_bulk_read(struct urb *urb)
 static void usblp_bulk_write(struct urb *urb)
 {
        struct usblp *usblp = urb->context;
+       int status = urb->status;
 
        if (usblp->present && usblp->used) {
-               if (urb->status)
+               if (status)
                        printk(KERN_WARNING "usblp%d: "
                            "nonzero write bulk status received: %d\n",
-                           usblp->minor, urb->status);
+                           usblp->minor, status);
        }
        spin_lock(&usblp->lock);
-       if (urb->status < 0)
-               usblp->wstatus = urb->status;
+       if (status < 0)
+               usblp->wstatus = status;
        else
                usblp->wstatus = urb->actual_length;
        usblp->wcomplete = 1;
@@ -741,10 +743,11 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
                 */
                rv = usblp_wwait(usblp, !!(file->f_flags&O_NONBLOCK));
                if (rv < 0) {
-                       /*
-                        * If interrupted, we simply leave the URB to dangle,
-                        * so the ->release will call usb_kill_urb().
-                        */
+                       if (rv == -EAGAIN) {
+                               /* Presume that it's going to complete well. */
+                               writecount += transfer_length;
+                       }
+                       /* Leave URB dangling, to be cleaned on close. */
                        goto collect_error;
                }
 
index 963520fbef9061db3a42f12d624840bab9976e92..42ef1d5f6c8ad07c78416bdbaa2c3e9c60e7516e 100644 (file)
@@ -99,12 +99,17 @@ EXPORT_SYMBOL_GPL (usb_bus_list_lock);
 /* used for controlling access to virtual root hubs */
 static DEFINE_SPINLOCK(hcd_root_hub_lock);
 
-/* used when updating hcd data */
-static DEFINE_SPINLOCK(hcd_data_lock);
+/* used when updating an endpoint's URB list */
+static DEFINE_SPINLOCK(hcd_urb_list_lock);
 
 /* wait queue for synchronous unlinks */
 DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue);
 
+static inline int is_root_hub(struct usb_device *udev)
+{
+       return (udev->parent == NULL);
+}
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -906,14 +911,13 @@ EXPORT_SYMBOL (usb_calc_bus_time);
 static void urb_unlink(struct usb_hcd *hcd, struct urb *urb)
 {
        unsigned long           flags;
-       int at_root_hub = (urb->dev == hcd->self.root_hub);
 
        /* clear all state linking urb to this dev (and hcd) */
-       spin_lock_irqsave (&hcd_data_lock, flags);
+       spin_lock_irqsave(&hcd_urb_list_lock, flags);
        list_del_init (&urb->urb_list);
-       spin_unlock_irqrestore (&hcd_data_lock, flags);
+       spin_unlock_irqrestore(&hcd_urb_list_lock, flags);
 
-       if (hcd->self.uses_dma && !at_root_hub) {
+       if (hcd->self.uses_dma && !is_root_hub(urb->dev)) {
                if (usb_pipecontrol (urb->pipe)
                        && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
                        dma_unmap_single (hcd->self.controller, urb->setup_dma,
@@ -955,7 +959,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
 
        // FIXME:  verify that quiescing hc works right (RH cleans up)
 
-       spin_lock_irqsave (&hcd_data_lock, flags);
+       spin_lock_irqsave(&hcd_urb_list_lock, flags);
        ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
                        [usb_pipeendpoint(urb->pipe)];
        if (unlikely (!ep))
@@ -972,7 +976,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
                status = -ESHUTDOWN;
                break;
        }
-       spin_unlock_irqrestore (&hcd_data_lock, flags);
+       spin_unlock_irqrestore(&hcd_urb_list_lock, flags);
        if (status) {
                INIT_LIST_HEAD (&urb->urb_list);
                usbmon_urb_submit_error(&hcd->self, urb, status);
@@ -986,7 +990,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
        urb = usb_get_urb (urb);
        atomic_inc (&urb->use_count);
 
-       if (urb->dev == hcd->self.root_hub) {
+       if (is_root_hub(urb->dev)) {
                /* NOTE:  requirement on hub callers (usbfs and the hub
                 * driver, for now) that URBs' urb->transfer_buffer be
                 * valid and usb_buffer_{sync,unmap}() not be needed, since
@@ -1033,18 +1037,6 @@ done:
 
 /*-------------------------------------------------------------------------*/
 
-/* called in any context */
-int usb_hcd_get_frame_number (struct usb_device *udev)
-{
-       struct usb_hcd  *hcd = bus_to_hcd(udev->bus);
-
-       if (!HC_IS_RUNNING (hcd->state))
-               return -ESHUTDOWN;
-       return hcd->driver->get_frame_number (hcd);
-}
-
-/*-------------------------------------------------------------------------*/
-
 /* this makes the hcd giveback() the urb more quickly, by kicking it
  * off hardware queues (which may take a while) and returning it as
  * soon as practical.  we've already set up the urb's return status,
@@ -1055,7 +1047,7 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb)
 {
        int             value;
 
-       if (urb->dev == hcd->self.root_hub)
+       if (is_root_hub(urb->dev))
                value = usb_rh_urb_dequeue (hcd, urb);
        else {
 
@@ -1103,11 +1095,11 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
         * that it was submitted.  But as a rule it can't know whether or
         * not it's already been unlinked ... so we respect the reversed
         * lock sequence needed for the usb_hcd_giveback_urb() code paths
-        * (urb lock, then hcd_data_lock) in case some other CPU is now
+        * (urb lock, then hcd_urb_list_lock) in case some other CPU is now
         * unlinking it.
         */
        spin_lock_irqsave (&urb->lock, flags);
-       spin_lock (&hcd_data_lock);
+       spin_lock(&hcd_urb_list_lock);
 
        sys = &urb->dev->dev;
        hcd = bus_to_hcd(urb->dev->bus);
@@ -1139,17 +1131,16 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
         * finish unlinking the initial failed usb_set_address()
         * or device descriptor fetch.
         */
-       if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags)
-           && hcd->self.root_hub != urb->dev) {
+       if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) &&
+                       !is_root_hub(urb->dev)) {
                dev_warn (hcd->self.controller, "Unlink after no-IRQ?  "
-                       "Controller is probably using the wrong IRQ."
-                       "\n");
+                       "Controller is probably using the wrong IRQ.\n");
                set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
        }
 
        urb->status = status;
 
-       spin_unlock (&hcd_data_lock);
+       spin_unlock(&hcd_urb_list_lock);
        spin_unlock_irqrestore (&urb->lock, flags);
 
        retval = unlink1 (hcd, urb);
@@ -1158,7 +1149,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
        return retval;
 
 done:
-       spin_unlock (&hcd_data_lock);
+       spin_unlock(&hcd_urb_list_lock);
        spin_unlock_irqrestore (&urb->lock, flags);
        if (retval != -EIDRM && sys && sys->driver)
                dev_dbg (sys, "hcd_unlink_urb %p fail %d\n", urb, retval);
@@ -1167,6 +1158,35 @@ done:
 
 /*-------------------------------------------------------------------------*/
 
+/**
+ * usb_hcd_giveback_urb - return URB from HCD to device driver
+ * @hcd: host controller returning the URB
+ * @urb: urb being returned to the USB device driver.
+ * Context: in_interrupt()
+ *
+ * This hands the URB from HCD to its USB device driver, using its
+ * completion function.  The HCD has freed all per-urb resources
+ * (and is done using urb->hcpriv).  It also released all HCD locks;
+ * the device driver won't cause problems if it frees, modifies,
+ * or resubmits this URB.
+ */
+void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
+{
+       urb_unlink(hcd, urb);
+       usbmon_urb_complete (&hcd->self, urb);
+       usb_unanchor_urb(urb);
+
+       /* pass ownership to the completion handler */
+       urb->complete (urb);
+       atomic_dec (&urb->use_count);
+       if (unlikely (urb->reject))
+               wake_up (&usb_kill_urb_queue);
+       usb_put_urb (urb);
+}
+EXPORT_SYMBOL (usb_hcd_giveback_urb);
+
+/*-------------------------------------------------------------------------*/
+
 /* disables the endpoint: cancels any pending urbs, then synchronizes with
  * the hcd to make sure all endpoint state is gone from hardware, and then
  * waits until the endpoint's queue is completely drained. use for
@@ -1186,7 +1206,7 @@ void usb_hcd_endpoint_disable (struct usb_device *udev,
 
        /* ep is already gone from udev->ep_{in,out}[]; no more submits */
 rescan:
-       spin_lock (&hcd_data_lock);
+       spin_lock(&hcd_urb_list_lock);
        list_for_each_entry (urb, &ep->urb_list, urb_list) {
                int     tmp;
 
@@ -1194,7 +1214,7 @@ rescan:
                if (urb->status != -EINPROGRESS)
                        continue;
                usb_get_urb (urb);
-               spin_unlock (&hcd_data_lock);
+               spin_unlock(&hcd_urb_list_lock);
 
                spin_lock (&urb->lock);
                tmp = urb->status;
@@ -1223,7 +1243,7 @@ rescan:
                /* list contents may have changed */
                goto rescan;
        }
-       spin_unlock (&hcd_data_lock);
+       spin_unlock(&hcd_urb_list_lock);
        local_irq_enable ();
 
        /* synchronize with the hardware, so old configuration state
@@ -1240,7 +1260,7 @@ rescan:
         * endpoint_disable methods.
         */
        while (!list_empty (&ep->urb_list)) {
-               spin_lock_irq (&hcd_data_lock);
+               spin_lock_irq(&hcd_urb_list_lock);
 
                /* The list may have changed while we acquired the spinlock */
                urb = NULL;
@@ -1249,7 +1269,7 @@ rescan:
                                        urb_list);
                        usb_get_urb (urb);
                }
-               spin_unlock_irq (&hcd_data_lock);
+               spin_unlock_irq(&hcd_urb_list_lock);
 
                if (urb) {
                        usb_kill_urb (urb);
@@ -1260,6 +1280,18 @@ rescan:
 
 /*-------------------------------------------------------------------------*/
 
+/* called in any context */
+int usb_hcd_get_frame_number (struct usb_device *udev)
+{
+       struct usb_hcd  *hcd = bus_to_hcd(udev->bus);
+
+       if (!HC_IS_RUNNING (hcd->state))
+               return -ESHUTDOWN;
+       return hcd->driver->get_frame_number (hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
 #ifdef CONFIG_PM
 
 int hcd_bus_suspend(struct usb_device *rhdev)
@@ -1394,35 +1426,6 @@ EXPORT_SYMBOL (usb_bus_start_enum);
 
 /*-------------------------------------------------------------------------*/
 
-/**
- * usb_hcd_giveback_urb - return URB from HCD to device driver
- * @hcd: host controller returning the URB
- * @urb: urb being returned to the USB device driver.
- * Context: in_interrupt()
- *
- * This hands the URB from HCD to its USB device driver, using its
- * completion function.  The HCD has freed all per-urb resources
- * (and is done using urb->hcpriv).  It also released all HCD locks;
- * the device driver won't cause problems if it frees, modifies,
- * or resubmits this URB.
- */
-void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
-{
-       urb_unlink(hcd, urb);
-       usbmon_urb_complete (&hcd->self, urb);
-       usb_unanchor_urb(urb);
-
-       /* pass ownership to the completion handler */
-       urb->complete (urb);
-       atomic_dec (&urb->use_count);
-       if (unlikely (urb->reject))
-               wake_up (&usb_kill_urb_queue);
-       usb_put_urb (urb);
-}
-EXPORT_SYMBOL (usb_hcd_giveback_urb);
-
-/*-------------------------------------------------------------------------*/
-
 /**
  * usb_hcd_irq - hook IRQs to HCD framework (bus glue)
  * @irq: the IRQ being raised
index fd74c50b18049b71f85256fa47a62d6199bc2098..e341a1da517fe8589c7153b0bf7811f84c435e51 100644 (file)
@@ -1335,6 +1335,10 @@ int usb_new_device(struct usb_device *udev)
        udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,
                        (((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
 
+       /* Increment the parent's count of unsuspended children */
+       if (udev->parent)
+               usb_autoresume_device(udev->parent);
+
        /* Register the device.  The device driver is responsible
         * for adding the device files to sysfs and for configuring
         * the device.
@@ -1342,13 +1346,11 @@ int usb_new_device(struct usb_device *udev)
        err = device_add(&udev->dev);
        if (err) {
                dev_err(&udev->dev, "can't device_add, error %d\n", err);
+               if (udev->parent)
+                       usb_autosuspend_device(udev->parent);
                goto fail;
        }
 
-       /* Increment the parent's count of unsuspended children */
-       if (udev->parent)
-               usb_autoresume_device(udev->parent);
-
 exit:
        return err;
 
index 530e854961ce99785291b399d92253151c626d9e..25f63f1096b43d4d9a6da4e266e212cf09d48549 100644 (file)
@@ -34,13 +34,14 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
 { 
        struct completion done;
        unsigned long expire;
-       int status;
+       int retval;
+       int status = urb->status;
 
        init_completion(&done);         
        urb->context = &done;
        urb->actual_length = 0;
-       status = usb_submit_urb(urb, GFP_NOIO);
-       if (unlikely(status))
+       retval = usb_submit_urb(urb, GFP_NOIO);
+       if (unlikely(retval))
                goto out;
 
        expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
@@ -55,15 +56,15 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
                        urb->transfer_buffer_length);
 
                usb_kill_urb(urb);
-               status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status;
+               retval = status == -ENOENT ? -ETIMEDOUT : status;
        } else
-               status = urb->status;
+               retval = status;
 out:
        if (actual_length)
                *actual_length = urb->actual_length;
 
        usb_free_urb(urb);
-       return status;
+       return retval;
 }
 
 /*-------------------------------------------------------------------*/
@@ -250,6 +251,7 @@ static void sg_clean (struct usb_sg_request *io)
 static void sg_complete (struct urb *urb)
 {
        struct usb_sg_request   *io = urb->context;
+       int status = urb->status;
 
        spin_lock (&io->lock);
 
@@ -265,21 +267,21 @@ static void sg_complete (struct urb *urb)
         */
        if (io->status
                        && (io->status != -ECONNRESET
-                               || urb->status != -ECONNRESET)
+                               || status != -ECONNRESET)
                        && urb->actual_length) {
                dev_err (io->dev->bus->controller,
                        "dev %s ep%d%s scatterlist error %d/%d\n",
                        io->dev->devpath,
                        usb_pipeendpoint (urb->pipe),
                        usb_pipein (urb->pipe) ? "in" : "out",
-                       urb->status, io->status);
+                       status, io->status);
                // BUG ();
        }
 
-       if (io->status == 0 && urb->status && urb->status != -ECONNRESET) {
-               int             i, found, status;
+       if (io->status == 0 && status && status != -ECONNRESET) {
+               int i, found, retval;
 
-               io->status = urb->status;
+               io->status = status;
 
                /* the previous urbs, and this one, completed already.
                 * unlink pending urbs so they won't rx/tx bad data.
@@ -290,13 +292,13 @@ static void sg_complete (struct urb *urb)
                        if (!io->urbs [i] || !io->urbs [i]->dev)
                                continue;
                        if (found) {
-                               status = usb_unlink_urb (io->urbs [i]);
-                               if (status != -EINPROGRESS
-                                               && status != -ENODEV
-                                               && status != -EBUSY)
+                               retval = usb_unlink_urb (io->urbs [i]);
+                               if (retval != -EINPROGRESS &&
+                                   retval != -ENODEV &&
+                                   retval != -EBUSY)
                                        dev_err (&io->dev->dev,
                                                "%s, unlink --> %d\n",
-                                               __FUNCTION__, status);
+                                               __FUNCTION__, retval);
                        } else if (urb == io->urbs [i])
                                found = 1;
                }
index d47ae89154a7e7b4a2d9ab40e4e733eaebe124be..2ab222be8fd164f58bff7245005ab4f621433a1d 100644 (file)
@@ -441,6 +441,54 @@ static struct attribute_group dev_attr_grp = {
        .attrs = dev_attrs,
 };
 
+/* Binary descriptors */
+
+static ssize_t
+read_descriptors(struct kobject *kobj, struct bin_attribute *attr,
+               char *buf, loff_t off, size_t count)
+{
+       struct usb_device *udev = to_usb_device(
+                       container_of(kobj, struct device, kobj));
+       size_t nleft = count;
+       size_t srclen, n;
+
+       usb_lock_device(udev);
+
+       /* The binary attribute begins with the device descriptor */
+       srclen = sizeof(struct usb_device_descriptor);
+       if (off < srclen) {
+               n = min_t(size_t, nleft, srclen - off);
+               memcpy(buf, off + (char *) &udev->descriptor, n);
+               nleft -= n;
+               buf += n;
+               off = 0;
+       } else {
+               off -= srclen;
+       }
+
+       /* Then follows the raw descriptor entry for the current
+        * configuration (config plus subsidiary descriptors).
+        */
+       if (udev->actconfig) {
+               int cfgno = udev->actconfig - udev->config;
+
+               srclen = __le16_to_cpu(udev->actconfig->desc.wTotalLength);
+               if (off < srclen) {
+                       n = min_t(size_t, nleft, srclen - off);
+                       memcpy(buf, off + udev->rawdescriptors[cfgno], n);
+                       nleft -= n;
+               }
+       }
+       usb_unlock_device(udev);
+       return count - nleft;
+}
+
+static struct bin_attribute dev_bin_attr_descriptors = {
+       .attr = {.name = "descriptors", .mode = 0444},
+       .read = read_descriptors,
+       .size = 18 + 65535,     /* dev descr + max-size raw descriptor */
+};
+
 int usb_create_sysfs_dev_files(struct usb_device *udev)
 {
        struct device *dev = &udev->dev;
@@ -450,6 +498,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
        if (retval)
                return retval;
 
+       retval = device_create_bin_file(dev, &dev_bin_attr_descriptors);
+       if (retval)
+               goto error;
+
        retval = add_persist_attributes(dev);
        if (retval)
                goto error;
@@ -492,6 +544,7 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
        device_remove_file(dev, &dev_attr_serial);
        remove_power_attributes(dev);
        remove_persist_attributes(dev);
+       device_remove_bin_file(dev, &dev_bin_attr_descriptors);
        sysfs_remove_group(&dev->kobj, &dev_attr_grp);
 }
 
index 52ec44b828f3530dd8dfdb33e8452be6aa2a819f..be630228461c046d06fe5232ea91466ad75e861d 100644 (file)
@@ -440,55 +440,57 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
  * @urb: pointer to urb describing a previously submitted request,
  *     may be NULL
  *
- * This routine cancels an in-progress request.  URBs complete only
- * once per submission, and may be canceled only once per submission.
- * Successful cancellation means the requests's completion handler will
- * be called with a status code indicating that the request has been
- * canceled (rather than any other code) and will quickly be removed
- * from host controller data structures.
- *
- * This request is always asynchronous.
- * Success is indicated by returning -EINPROGRESS,
- * at which time the URB will normally have been unlinked but not yet
- * given back to the device driver.  When it is called, the completion
- * function will see urb->status == -ECONNRESET.  Failure is indicated
- * by any other return value.  Unlinking will fail when the URB is not
- * currently "linked" (i.e., it was never submitted, or it was unlinked
- * before, or the hardware is already finished with it), even if the
- * completion handler has not yet run.
+ * This routine cancels an in-progress request.  URBs complete only once
+ * per submission, and may be canceled only once per submission.
+ * Successful cancellation means termination of @urb will be expedited
+ * and the completion handler will be called with a status code
+ * indicating that the request has been canceled (rather than any other
+ * code).
+ *
+ * This request is always asynchronous.  Success is indicated by
+ * returning -EINPROGRESS, at which time the URB will probably not yet
+ * have been given back to the device driver.  When it is eventually
+ * called, the completion function will see @urb->status == -ECONNRESET.
+ * Failure is indicated by usb_unlink_urb() returning any other value.
+ * Unlinking will fail when @urb is not currently "linked" (i.e., it was
+ * never submitted, or it was unlinked before, or the hardware is already
+ * finished with it), even if the completion handler has not yet run.
  *
  * Unlinking and Endpoint Queues:
  *
+ * [The behaviors and guarantees described below do not apply to virtual
+ * root hubs but only to endpoint queues for physical USB devices.]
+ *
  * Host Controller Drivers (HCDs) place all the URBs for a particular
  * endpoint in a queue.  Normally the queue advances as the controller
  * hardware processes each request.  But when an URB terminates with an
- * error its queue stops, at least until that URB's completion routine
- * returns.  It is guaranteed that the queue will not restart until all
- * its unlinked URBs have been fully retired, with their completion
- * routines run, even if that's not until some time after the original
- * completion handler returns.  Normally the same behavior and guarantees
- * apply when an URB terminates because it was unlinked; however if an
- * URB is unlinked before the hardware has started to execute it, then
- * its queue is not guaranteed to stop until all the preceding URBs have
- * completed.
- *
- * This means that USB device drivers can safely build deep queues for
- * large or complex transfers, and clean them up reliably after any sort
- * of aborted transfer by unlinking all pending URBs at the first fault.
- *
- * Note that an URB terminating early because a short packet was received
- * will count as an error if and only if the URB_SHORT_NOT_OK flag is set.
- * Also, that all unlinks performed in any URB completion handler must
- * be asynchronous.
- *
- * Queues for isochronous endpoints are treated differently, because they
- * advance at fixed rates.  Such queues do not stop when an URB is unlinked.
- * An unlinked URB may leave a gap in the stream of packets.  It is undefined
- * whether such gaps can be filled in.
- *
- * When a control URB terminates with an error, it is likely that the
- * status stage of the transfer will not take place, even if it is merely
- * a soft error resulting from a short-packet with URB_SHORT_NOT_OK set.
+ * error its queue generally stops (see below), at least until that URB's
+ * completion routine returns.  It is guaranteed that a stopped queue
+ * will not restart until all its unlinked URBs have been fully retired,
+ * with their completion routines run, even if that's not until some time
+ * after the original completion handler returns.  The same behavior and
+ * guarantee apply when an URB terminates because it was unlinked.
+ *
+ * Bulk and interrupt endpoint queues are guaranteed to stop whenever an
+ * URB terminates with any sort of error, including -ECONNRESET, -ENOENT,
+ * and -EREMOTEIO.  Control endpoint queues behave the same way except
+ * that they are not guaranteed to stop for -EREMOTEIO errors.  Queues
+ * for isochronous endpoints are treated differently, because they must
+ * advance at fixed rates.  Such queues do not stop when an URB
+ * encounters an error or is unlinked.  An unlinked isochronous URB may
+ * leave a gap in the stream of packets; it is undefined whether such
+ * gaps can be filled in.
+ *
+ * Note that early termination of an URB because a short packet was
+ * received will generate a -EREMOTEIO error if and only if the
+ * URB_SHORT_NOT_OK flag is set.  By setting this flag, USB device
+ * drivers can build deep queues for large or complex bulk transfers
+ * and clean them up reliably after any sort of aborted transfer by
+ * unlinking all pending URBs at the first fault.
+ *
+ * When a control URB terminates with an error other than -EREMOTEIO, it
+ * is quite likely that the status stage of the transfer will not take
+ * place.
  */
 int usb_unlink_urb(struct urb *urb)
 {
index 45e01e289455376b68e5f5ceca8ca3a3a2937ec3..767aed5b4bea015938d7d8164c0c1e121942c994 100644 (file)
@@ -82,6 +82,27 @@ choice
           Many controller drivers are platform-specific; these
           often need board-specific hooks.
 
+config USB_GADGET_AMD5536UDC
+       boolean "AMD5536 UDC"
+       depends on PCI
+       select USB_GADGET_DUALSPEED
+       help
+          The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
+          It is a USB Highspeed DMA capable USB device controller. Beside ep0
+          it provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
+          The UDC port supports OTG operation, and may be used as a host port
+          if it's not being used to implement peripheral or OTG roles.
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "amd5536udc" and force all
+          gadget drivers to also be dynamically linked.
+
+config USB_AMD5536UDC
+       tristate
+       depends on USB_GADGET_AMD5536UDC
+       default USB_GADGET
+       select USB_GADGET_SELECTED
+
 config USB_GADGET_FSL_USB2
        boolean "Freescale Highspeed USB DR Peripheral Controller"
        depends on MPC834x || PPC_MPC831x
@@ -156,6 +177,24 @@ config USB_PXA2XX_SMALL
        default y if USB_ETH
        default y if USB_G_SERIAL
 
+config USB_GADGET_M66592
+       boolean "Renesas M66592 USB Peripheral Controller"
+       select USB_GADGET_DUALSPEED
+       help
+          M66592 is a discrete USB peripheral controller chip that
+          supports both full and high speed USB 2.0 data transfers.
+          It has seven configurable endpoints, and endpoint zero.
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "m66592_udc" and force all
+          gadget drivers to also be dynamically linked.
+
+config USB_M66592
+       tristate
+       depends on USB_GADGET_M66592
+       default USB_GADGET
+       select USB_GADGET_SELECTED
+
 config USB_GADGET_GOKU
        boolean "Toshiba TC86C001 'Goku-S'"
        depends on PCI
@@ -261,24 +300,6 @@ config USB_AT91
        depends on USB_GADGET_AT91
        default USB_GADGET
 
-config USB_GADGET_M66592
-       boolean "M66592 driver"
-       select USB_GADGET_DUALSPEED
-       help
-          M66592 is a USB 2.0 peripheral controller.
-
-          It has seven configurable endpoints, and endpoint zero.
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "m66592_udc" and force all
-          gadget drivers to also be dynamically linked.
-
-config USB_M66592
-       tristate
-       depends on USB_GADGET_M66592
-       default USB_GADGET
-       select USB_GADGET_SELECTED
-
 config USB_GADGET_DUMMY_HCD
        boolean "Dummy HCD (DEVELOPMENT)"
        depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL
index 8ae76f7386355074ffba6b3d1fb1a326e323becd..1bc0f03550cea0df21f0f21e3c6cd7fdf7fdff7d 100644 (file)
@@ -7,6 +7,7 @@ endif
 
 obj-$(CONFIG_USB_DUMMY_HCD)    += dummy_hcd.o
 obj-$(CONFIG_USB_NET2280)      += net2280.o
+obj-$(CONFIG_USB_AMD5536UDC)   += amd5536udc.o
 obj-$(CONFIG_USB_PXA2XX)       += pxa2xx_udc.o
 obj-$(CONFIG_USB_GOKU)         += goku_udc.o
 obj-$(CONFIG_USB_OMAP)         += omap_udc.o
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
new file mode 100644 (file)
index 0000000..714156c
--- /dev/null
@@ -0,0 +1,3454 @@
+/*
+ * amd5536.c -- AMD 5536 UDC high/full speed USB device controller
+ *
+ * Copyright (C) 2005-2007 AMD (http://www.amd.com)
+ * Author: Thomas Dahlmann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * The AMD5536 UDC is part of the x86 southbridge AMD Geode CS5536.
+ * It is a USB Highspeed DMA capable USB device controller. Beside ep0 it
+ * provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
+ *
+ * Make sure that UDC is assigned to port 4 by BIOS settings (port can also
+ * be used as host port) and UOC bits PAD_EN and APU are set (should be done
+ * by BIOS init).
+ *
+ * UDC DMA requires 32-bit aligned buffers so DMA with gadget ether does not
+ * work without updating NET_IP_ALIGN. Or PIO mode (module param "use_dma=0")
+ * can be used with gadget ether.
+ */
+
+/* debug control */
+/* #define UDC_VERBOSE */
+
+/* Driver strings */
+#define UDC_MOD_DESCRIPTION            "AMD 5536 UDC - USB Device Controller"
+#define UDC_DRIVER_VERSION_STRING      "01.00.0206 - $Revision: #3 $"
+
+/* system */
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/dmapool.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+
+/* gadget stack */
+#include <linux/usb/ch9.h>
+#include <linux/usb_gadget.h>
+
+/* udc specific */
+#include "amd5536udc.h"
+
+
+static void udc_tasklet_disconnect(unsigned long);
+static void empty_req_queue(struct udc_ep *);
+static int udc_probe(struct udc *dev);
+static void udc_basic_init(struct udc *dev);
+static void udc_setup_endpoints(struct udc *dev);
+static void udc_soft_reset(struct udc *dev);
+static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep);
+static void udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq);
+static int udc_free_dma_chain(struct udc *dev, struct udc_request *req);
+static int udc_create_dma_chain(struct udc_ep *ep, struct udc_request *req,
+                               unsigned long buf_len, gfp_t gfp_flags);
+static int udc_remote_wakeup(struct udc *dev);
+static int udc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id);
+static void udc_pci_remove(struct pci_dev *pdev);
+
+/* description */
+static const char mod_desc[] = UDC_MOD_DESCRIPTION;
+static const char name[] = "amd5536udc";
+
+/* structure to hold endpoint function pointers */
+static const struct usb_ep_ops udc_ep_ops;
+
+/* received setup data */
+static union udc_setup_data setup_data;
+
+/* pointer to device object */
+static struct udc *udc;
+
+/* irq spin lock for soft reset */
+static DEFINE_SPINLOCK(udc_irq_spinlock);
+/* stall spin lock */
+static DEFINE_SPINLOCK(udc_stall_spinlock);
+
+/*
+* slave mode: pending bytes in rx fifo after nyet,
+* used if EPIN irq came but no req was available
+*/
+static unsigned int udc_rxfifo_pending;
+
+/* count soft resets after suspend to avoid loop */
+static int soft_reset_occured;
+static int soft_reset_after_usbreset_occured;
+
+/* timer */
+static struct timer_list udc_timer;
+static int stop_timer;
+
+/* set_rde -- Is used to control enabling of RX DMA. Problem is
+ * that UDC has only one bit (RDE) to enable/disable RX DMA for
+ * all OUT endpoints. So we have to handle race conditions like
+ * when OUT data reaches the fifo but no request was queued yet.
+ * This cannot be solved by letting the RX DMA disabled until a
+ * request gets queued because there may be other OUT packets
+ * in the FIFO (important for not blocking control traffic).
+ * The value of set_rde controls the correspondig timer.
+ *
+ * set_rde -1 == not used, means it is alloed to be set to 0 or 1
+ * set_rde  0 == do not touch RDE, do no start the RDE timer
+ * set_rde  1 == timer function will look whether FIFO has data
+ * set_rde  2 == set by timer function to enable RX DMA on next call
+ */
+static int set_rde = -1;
+
+static DECLARE_COMPLETION(on_exit);
+static struct timer_list udc_pollstall_timer;
+static int stop_pollstall_timer;
+static DECLARE_COMPLETION(on_pollstall_exit);
+
+/* tasklet for usb disconnect */
+static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect,
+               (unsigned long) &udc);
+
+
+/* endpoint names used for print */
+static const char ep0_string[] = "ep0in";
+static const char *ep_string[] = {
+       ep0_string,
+       "ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk",
+       "ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk",
+       "ep11in-bulk", "ep12in-bulk", "ep13in-bulk", "ep14in-bulk",
+       "ep15in-bulk", "ep0out", "ep1out-bulk", "ep2out-bulk", "ep3out-bulk",
+       "ep4out-bulk", "ep5out-bulk", "ep6out-bulk", "ep7out-bulk",
+       "ep8out-bulk", "ep9out-bulk", "ep10out-bulk", "ep11out-bulk",
+       "ep12out-bulk", "ep13out-bulk", "ep14out-bulk", "ep15out-bulk"
+};
+
+/* DMA usage flag */
+static int use_dma = 1;
+/* packet per buffer dma */
+static int use_dma_ppb = 1;
+/* with per descr. update */
+static int use_dma_ppb_du;
+/* buffer fill mode */
+static int use_dma_bufferfill_mode;
+/* full speed only mode */
+static int use_fullspeed;
+/* tx buffer size for high speed */
+static unsigned long hs_tx_buf = UDC_EPIN_BUFF_SIZE;
+
+/* module parameters */
+module_param(use_dma, bool, S_IRUGO);
+MODULE_PARM_DESC(use_dma, "true for DMA");
+module_param(use_dma_ppb, bool, S_IRUGO);
+MODULE_PARM_DESC(use_dma_ppb, "true for DMA in packet per buffer mode");
+module_param(use_dma_ppb_du, bool, S_IRUGO);
+MODULE_PARM_DESC(use_dma_ppb_du,
+       "true for DMA in packet per buffer mode with descriptor update");
+module_param(use_fullspeed, bool, S_IRUGO);
+MODULE_PARM_DESC(use_fullspeed, "true for fullspeed only");
+
+/*---------------------------------------------------------------------------*/
+/* Prints UDC device registers and endpoint irq registers */
+static void print_regs(struct udc *dev)
+{
+       DBG(dev, "------- Device registers -------\n");
+       DBG(dev, "dev config     = %08x\n", readl(&dev->regs->cfg));
+       DBG(dev, "dev control    = %08x\n", readl(&dev->regs->ctl));
+       DBG(dev, "dev status     = %08x\n", readl(&dev->regs->sts));
+       DBG(dev, "\n");
+       DBG(dev, "dev int's      = %08x\n", readl(&dev->regs->irqsts));
+       DBG(dev, "dev intmask    = %08x\n", readl(&dev->regs->irqmsk));
+       DBG(dev, "\n");
+       DBG(dev, "dev ep int's   = %08x\n", readl(&dev->regs->ep_irqsts));
+       DBG(dev, "dev ep intmask = %08x\n", readl(&dev->regs->ep_irqmsk));
+       DBG(dev, "\n");
+       DBG(dev, "USE DMA        = %d\n", use_dma);
+       if (use_dma && use_dma_ppb && !use_dma_ppb_du) {
+               DBG(dev, "DMA mode       = PPBNDU (packet per buffer "
+                       "WITHOUT desc. update)\n");
+               dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBNDU");
+       } else if (use_dma && use_dma_ppb_du && use_dma_ppb_du) {
+               DBG(dev, "DMA mode       = PPBDU (packet per buffer "
+                       "WITH desc. update)\n");
+               dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBDU");
+       }
+       if (use_dma && use_dma_bufferfill_mode) {
+               DBG(dev, "DMA mode       = BF (buffer fill mode)\n");
+               dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "BF");
+       }
+       if (!use_dma) {
+               dev_info(&dev->pdev->dev, "FIFO mode\n");
+       }
+       DBG(dev, "-------------------------------------------------------\n");
+}
+
+/* Masks unused interrupts */
+static int udc_mask_unused_interrupts(struct udc *dev)
+{
+       u32 tmp;
+
+       /* mask all dev interrupts */
+       tmp =   AMD_BIT(UDC_DEVINT_SVC) |
+               AMD_BIT(UDC_DEVINT_ENUM) |
+               AMD_BIT(UDC_DEVINT_US) |
+               AMD_BIT(UDC_DEVINT_UR) |
+               AMD_BIT(UDC_DEVINT_ES) |
+               AMD_BIT(UDC_DEVINT_SI) |
+               AMD_BIT(UDC_DEVINT_SOF)|
+               AMD_BIT(UDC_DEVINT_SC);
+       writel(tmp, &dev->regs->irqmsk);
+
+       /* mask all ep interrupts */
+       writel(UDC_EPINT_MSK_DISABLE_ALL, &dev->regs->ep_irqmsk);
+
+       return 0;
+}
+
+/* Enables endpoint 0 interrupts */
+static int udc_enable_ep0_interrupts(struct udc *dev)
+{
+       u32 tmp;
+
+       DBG(dev, "udc_enable_ep0_interrupts()\n");
+
+       /* read irq mask */
+       tmp = readl(&dev->regs->ep_irqmsk);
+       /* enable ep0 irq's */
+       tmp &= AMD_UNMASK_BIT(UDC_EPINT_IN_EP0)
+               & AMD_UNMASK_BIT(UDC_EPINT_OUT_EP0);
+       writel(tmp, &dev->regs->ep_irqmsk);
+
+       return 0;
+}
+
+/* Enables device interrupts for SET_INTF and SET_CONFIG */
+static int udc_enable_dev_setup_interrupts(struct udc *dev)
+{
+       u32 tmp;
+
+       DBG(dev, "enable device interrupts for setup data\n");
+
+       /* read irq mask */
+       tmp = readl(&dev->regs->irqmsk);
+
+       /* enable SET_INTERFACE, SET_CONFIG and other needed irq's */
+       tmp &= AMD_UNMASK_BIT(UDC_DEVINT_SI)
+               & AMD_UNMASK_BIT(UDC_DEVINT_SC)
+               & AMD_UNMASK_BIT(UDC_DEVINT_UR)
+               & AMD_UNMASK_BIT(UDC_DEVINT_SVC)
+               & AMD_UNMASK_BIT(UDC_DEVINT_ENUM);
+       writel(tmp, &dev->regs->irqmsk);
+
+       return 0;
+}
+
+/* Calculates fifo start of endpoint based on preceeding endpoints */
+static int udc_set_txfifo_addr(struct udc_ep *ep)
+{
+       struct udc      *dev;
+       u32 tmp;
+       int i;
+
+       if (!ep || !(ep->in))
+               return -EINVAL;
+
+       dev = ep->dev;
+       ep->txfifo = dev->txfifo;
+
+       /* traverse ep's */
+       for (i = 0; i < ep->num; i++) {
+               if (dev->ep[i].regs) {
+                       /* read fifo size */
+                       tmp = readl(&dev->ep[i].regs->bufin_framenum);
+                       tmp = AMD_GETBITS(tmp, UDC_EPIN_BUFF_SIZE);
+                       ep->txfifo += tmp;
+               }
+       }
+       return 0;
+}
+
+/* CNAK pending field: bit0 = ep0in, bit16 = ep0out */
+static u32 cnak_pending;
+
+static void UDC_QUEUE_CNAK(struct udc_ep *ep, unsigned num)
+{
+       if (readl(&ep->regs->ctl) & AMD_BIT(UDC_EPCTL_NAK)) {
+               DBG(ep->dev, "NAK could not be cleared for ep%d\n", num);
+               cnak_pending |= 1 << (num);
+               ep->naking = 1;
+       } else
+               cnak_pending = cnak_pending & (~(1 << (num)));
+}
+
+
+/* Enables endpoint, is called by gadget driver */
+static int
+udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc)
+{
+       struct udc_ep           *ep;
+       struct udc              *dev;
+       u32                     tmp;
+       unsigned long           iflags;
+       u8 udc_csr_epix;
+
+       if (!usbep
+                       || usbep->name == ep0_string
+                       || !desc
+                       || desc->bDescriptorType != USB_DT_ENDPOINT)
+               return -EINVAL;
+
+       ep = container_of(usbep, struct udc_ep, ep);
+       dev = ep->dev;
+
+       DBG(dev, "udc_ep_enable() ep %d\n", ep->num);
+
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       spin_lock_irqsave(&dev->lock, iflags);
+       ep->desc = desc;
+
+       ep->halted = 0;
+
+       /* set traffic type */
+       tmp = readl(&dev->ep[ep->num].regs->ctl);
+       tmp = AMD_ADDBITS(tmp, desc->bmAttributes, UDC_EPCTL_ET);
+       writel(tmp, &dev->ep[ep->num].regs->ctl);
+
+       /* set max packet size */
+       tmp = readl(&dev->ep[ep->num].regs->bufout_maxpkt);
+       tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_EP_MAX_PKT_SIZE);
+       ep->ep.maxpacket = desc->wMaxPacketSize;
+       writel(tmp, &dev->ep[ep->num].regs->bufout_maxpkt);
+
+       /* IN ep */
+       if (ep->in) {
+
+               /* ep ix in UDC CSR register space */
+               udc_csr_epix = ep->num;
+
+               /* set buffer size (tx fifo entries) */
+               tmp = readl(&dev->ep[ep->num].regs->bufin_framenum);
+               /* double buffering: fifo size = 2 x max packet size */
+               tmp = AMD_ADDBITS(
+                               tmp,
+                               desc->wMaxPacketSize * UDC_EPIN_BUFF_SIZE_MULT
+                                               / UDC_DWORD_BYTES,
+                               UDC_EPIN_BUFF_SIZE);
+               writel(tmp, &dev->ep[ep->num].regs->bufin_framenum);
+
+               /* calc. tx fifo base addr */
+               udc_set_txfifo_addr(ep);
+
+               /* flush fifo */
+               tmp = readl(&ep->regs->ctl);
+               tmp |= AMD_BIT(UDC_EPCTL_F);
+               writel(tmp, &ep->regs->ctl);
+
+       /* OUT ep */
+       } else {
+               /* ep ix in UDC CSR register space */
+               udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS;
+
+               /* set max packet size UDC CSR  */
+               tmp = readl(&dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]);
+               tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize,
+                                       UDC_CSR_NE_MAX_PKT);
+               writel(tmp, &dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]);
+
+               if (use_dma && !ep->in) {
+                       /* alloc and init BNA dummy request */
+                       ep->bna_dummy_req = udc_alloc_bna_dummy(ep);
+                       ep->bna_occurred = 0;
+               }
+
+               if (ep->num != UDC_EP0OUT_IX)
+                       dev->data_ep_enabled = 1;
+       }
+
+       /* set ep values */
+       tmp = readl(&dev->csr->ne[udc_csr_epix]);
+       /* max packet */
+       tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_CSR_NE_MAX_PKT);
+       /* ep number */
+       tmp = AMD_ADDBITS(tmp, desc->bEndpointAddress, UDC_CSR_NE_NUM);
+       /* ep direction */
+       tmp = AMD_ADDBITS(tmp, ep->in, UDC_CSR_NE_DIR);
+       /* ep type */
+       tmp = AMD_ADDBITS(tmp, desc->bmAttributes, UDC_CSR_NE_TYPE);
+       /* ep config */
+       tmp = AMD_ADDBITS(tmp, ep->dev->cur_config, UDC_CSR_NE_CFG);
+       /* ep interface */
+       tmp = AMD_ADDBITS(tmp, ep->dev->cur_intf, UDC_CSR_NE_INTF);
+       /* ep alt */
+       tmp = AMD_ADDBITS(tmp, ep->dev->cur_alt, UDC_CSR_NE_ALT);
+       /* write reg */
+       writel(tmp, &dev->csr->ne[udc_csr_epix]);
+
+       /* enable ep irq */
+       tmp = readl(&dev->regs->ep_irqmsk);
+       tmp &= AMD_UNMASK_BIT(ep->num);
+       writel(tmp, &dev->regs->ep_irqmsk);
+
+       /*
+        * clear NAK by writing CNAK
+        * avoid BNA for OUT DMA, don't clear NAK until DMA desc. written
+        */
+       if (!use_dma || ep->in) {
+               tmp = readl(&ep->regs->ctl);
+               tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+               writel(tmp, &ep->regs->ctl);
+               ep->naking = 0;
+               UDC_QUEUE_CNAK(ep, ep->num);
+       }
+       tmp = desc->bEndpointAddress;
+       DBG(dev, "%s enabled\n", usbep->name);
+
+       spin_unlock_irqrestore(&dev->lock, iflags);
+       return 0;
+}
+
+/* Resets endpoint */
+static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep)
+{
+       u32             tmp;
+
+       VDBG(ep->dev, "ep-%d reset\n", ep->num);
+       ep->desc = NULL;
+       ep->ep.ops = &udc_ep_ops;
+       INIT_LIST_HEAD(&ep->queue);
+
+       ep->ep.maxpacket = (u16) ~0;
+       /* set NAK */
+       tmp = readl(&ep->regs->ctl);
+       tmp |= AMD_BIT(UDC_EPCTL_SNAK);
+       writel(tmp, &ep->regs->ctl);
+       ep->naking = 1;
+
+       /* disable interrupt */
+       tmp = readl(&regs->ep_irqmsk);
+       tmp |= AMD_BIT(ep->num);
+       writel(tmp, &regs->ep_irqmsk);
+
+       if (ep->in) {
+               /* unset P and IN bit of potential former DMA */
+               tmp = readl(&ep->regs->ctl);
+               tmp &= AMD_UNMASK_BIT(UDC_EPCTL_P);
+               writel(tmp, &ep->regs->ctl);
+
+               tmp = readl(&ep->regs->sts);
+               tmp |= AMD_BIT(UDC_EPSTS_IN);
+               writel(tmp, &ep->regs->sts);
+
+               /* flush the fifo */
+               tmp = readl(&ep->regs->ctl);
+               tmp |= AMD_BIT(UDC_EPCTL_F);
+               writel(tmp, &ep->regs->ctl);
+
+       }
+       /* reset desc pointer */
+       writel(0, &ep->regs->desptr);
+}
+
+/* Disables endpoint, is called by gadget driver */
+static int udc_ep_disable(struct usb_ep *usbep)
+{
+       struct udc_ep   *ep = NULL;
+       unsigned long   iflags;
+
+       if (!usbep)
+               return -EINVAL;
+
+       ep = container_of(usbep, struct udc_ep, ep);
+       if (usbep->name == ep0_string || !ep->desc)
+               return -EINVAL;
+
+       DBG(ep->dev, "Disable ep-%d\n", ep->num);
+
+       spin_lock_irqsave(&ep->dev->lock, iflags);
+       udc_free_request(&ep->ep, &ep->bna_dummy_req->req);
+       empty_req_queue(ep);
+       ep_init(ep->dev->regs, ep);
+       spin_unlock_irqrestore(&ep->dev->lock, iflags);
+
+       return 0;
+}
+
+/* Allocates request packet, called by gadget driver */
+static struct usb_request *
+udc_alloc_request(struct usb_ep *usbep, gfp_t gfp)
+{
+       struct udc_request      *req;
+       struct udc_data_dma     *dma_desc;
+       struct udc_ep   *ep;
+
+       if (!usbep)
+               return NULL;
+
+       ep = container_of(usbep, struct udc_ep, ep);
+
+       VDBG(ep->dev, "udc_alloc_req(): ep%d\n", ep->num);
+       req = kzalloc(sizeof(struct udc_request), gfp);
+       if (!req)
+               return NULL;
+
+       req->req.dma = DMA_DONT_USE;
+       INIT_LIST_HEAD(&req->queue);
+
+       if (ep->dma) {
+               /* ep0 in requests are allocated from data pool here */
+               dma_desc = pci_pool_alloc(ep->dev->data_requests, gfp,
+                                               &req->td_phys);
+               if (!dma_desc) {
+                       kfree(req);
+                       return NULL;
+               }
+
+               VDBG(ep->dev, "udc_alloc_req: req = %p dma_desc = %p, "
+                               "td_phys = %lx\n",
+                               req, dma_desc,
+                               (unsigned long)req->td_phys);
+               /* prevent from using desc. - set HOST BUSY */
+               dma_desc->status = AMD_ADDBITS(dma_desc->status,
+                                               UDC_DMA_STP_STS_BS_HOST_BUSY,
+                                               UDC_DMA_STP_STS_BS);
+               dma_desc->bufptr = __constant_cpu_to_le32(DMA_DONT_USE);
+               req->td_data = dma_desc;
+               req->td_data_last = NULL;
+               req->chain_len = 1;
+       }
+
+       return &req->req;
+}
+
+/* Frees request packet, called by gadget driver */
+static void
+udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq)
+{
+       struct udc_ep   *ep;
+       struct udc_request      *req;
+
+       if (!usbep || !usbreq)
+               return;
+
+       ep = container_of(usbep, struct udc_ep, ep);
+       req = container_of(usbreq, struct udc_request, req);
+       VDBG(ep->dev, "free_req req=%p\n", req);
+       BUG_ON(!list_empty(&req->queue));
+       if (req->td_data) {
+               VDBG(ep->dev, "req->td_data=%p\n", req->td_data);
+
+               /* free dma chain if created */
+               if (req->chain_len > 1) {
+                       udc_free_dma_chain(ep->dev, req);
+               }
+
+               pci_pool_free(ep->dev->data_requests, req->td_data,
+                                                       req->td_phys);
+       }
+       kfree(req);
+}
+
+/* Init BNA dummy descriptor for HOST BUSY and pointing to itself */
+static void udc_init_bna_dummy(struct udc_request *req)
+{
+       if (req) {
+               /* set last bit */
+               req->td_data->status |= AMD_BIT(UDC_DMA_IN_STS_L);
+               /* set next pointer to itself */
+               req->td_data->next = req->td_phys;
+               /* set HOST BUSY */
+               req->td_data->status
+                       = AMD_ADDBITS(req->td_data->status,
+                                       UDC_DMA_STP_STS_BS_DMA_DONE,
+                                       UDC_DMA_STP_STS_BS);
+#ifdef UDC_VERBOSE
+               pr_debug("bna desc = %p, sts = %08x\n",
+                       req->td_data, req->td_data->status);
+#endif
+       }
+}
+
+/* Allocate BNA dummy descriptor */
+static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep)
+{
+       struct udc_request *req = NULL;
+       struct usb_request *_req = NULL;
+
+       /* alloc the dummy request */
+       _req = udc_alloc_request(&ep->ep, GFP_ATOMIC);
+       if (_req) {
+               req = container_of(_req, struct udc_request, req);
+               ep->bna_dummy_req = req;
+               udc_init_bna_dummy(req);
+       }
+       return req;
+}
+
+/* Write data to TX fifo for IN packets */
+static void
+udc_txfifo_write(struct udc_ep *ep, struct usb_request *req)
+{
+       u8                      *req_buf;
+       u32                     *buf;
+       int                     i, j;
+       unsigned                bytes = 0;
+       unsigned                remaining = 0;
+
+       if (!req || !ep)
+               return;
+
+       req_buf = req->buf + req->actual;
+       prefetch(req_buf);
+       remaining = req->length - req->actual;
+
+       buf = (u32 *) req_buf;
+
+       bytes = ep->ep.maxpacket;
+       if (bytes > remaining)
+               bytes = remaining;
+
+       /* dwords first */
+       for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) {
+               writel(*(buf + i), ep->txfifo);
+       }
+
+       /* remaining bytes must be written by byte access */
+       for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) {
+               writeb((u8)(*(buf + i) >> (j << UDC_BITS_PER_BYTE_SHIFT)),
+                                                       ep->txfifo);
+       }
+
+       /* dummy write confirm */
+       writel(0, &ep->regs->confirm);
+}
+
+/* Read dwords from RX fifo for OUT transfers */
+static int udc_rxfifo_read_dwords(struct udc *dev, u32 *buf, int dwords)
+{
+       int i;
+
+       VDBG(dev, "udc_read_dwords(): %d dwords\n", dwords);
+
+       for (i = 0; i < dwords; i++) {
+               *(buf + i) = readl(dev->rxfifo);
+       }
+       return 0;
+}
+
+/* Read bytes from RX fifo for OUT transfers */
+static int udc_rxfifo_read_bytes(struct udc *dev, u8 *buf, int bytes)
+{
+       int i, j;
+       u32 tmp;
+
+       VDBG(dev, "udc_read_bytes(): %d bytes\n", bytes);
+
+       /* dwords first */
+       for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) {
+               *((u32 *)(buf + (i<<2))) = readl(dev->rxfifo);
+       }
+
+       /* remaining bytes must be read by byte access */
+       if (bytes % UDC_DWORD_BYTES) {
+               tmp = readl(dev->rxfifo);
+               for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) {
+                       *(buf + (i<<2) + j) = (u8)(tmp & UDC_BYTE_MASK);
+                       tmp = tmp >> UDC_BITS_PER_BYTE;
+               }
+       }
+
+       return 0;
+}
+
+/* Read data from RX fifo for OUT transfers */
+static int
+udc_rxfifo_read(struct udc_ep *ep, struct udc_request *req)
+{
+       u8 *buf;
+       unsigned buf_space;
+       unsigned bytes = 0;
+       unsigned finished = 0;
+
+       /* received number bytes */
+       bytes = readl(&ep->regs->sts);
+       bytes = AMD_GETBITS(bytes, UDC_EPSTS_RX_PKT_SIZE);
+
+       buf_space = req->req.length - req->req.actual;
+       buf = req->req.buf + req->req.actual;
+       if (bytes > buf_space) {
+               if ((buf_space % ep->ep.maxpacket) != 0) {
+                       DBG(ep->dev,
+                               "%s: rx %d bytes, rx-buf space = %d bytesn\n",
+                               ep->ep.name, bytes, buf_space);
+                       req->req.status = -EOVERFLOW;
+               }
+               bytes = buf_space;
+       }
+       req->req.actual += bytes;
+
+       /* last packet ? */
+       if (((bytes % ep->ep.maxpacket) != 0) || (!bytes)
+               || ((req->req.actual == req->req.length) && !req->req.zero))
+               finished = 1;
+
+       /* read rx fifo bytes */
+       VDBG(ep->dev, "ep %s: rxfifo read %d bytes\n", ep->ep.name, bytes);
+       udc_rxfifo_read_bytes(ep->dev, buf, bytes);
+
+       return finished;
+}
+
+/* create/re-init a DMA descriptor or a DMA descriptor chain */
+static int prep_dma(struct udc_ep *ep, struct udc_request *req, gfp_t gfp)
+{
+       int     retval = 0;
+       u32     tmp;
+
+       VDBG(ep->dev, "prep_dma\n");
+       VDBG(ep->dev, "prep_dma ep%d req->td_data=%p\n",
+                       ep->num, req->td_data);
+
+       /* set buffer pointer */
+       req->td_data->bufptr = req->req.dma;
+
+       /* set last bit */
+       req->td_data->status |= AMD_BIT(UDC_DMA_IN_STS_L);
+
+       /* build/re-init dma chain if maxpkt scatter mode, not for EP0 */
+       if (use_dma_ppb) {
+
+               retval = udc_create_dma_chain(ep, req, ep->ep.maxpacket, gfp);
+               if (retval != 0) {
+                       if (retval == -ENOMEM)
+                               DBG(ep->dev, "Out of DMA memory\n");
+                       return retval;
+               }
+               if (ep->in) {
+                       if (req->req.length == ep->ep.maxpacket) {
+                               /* write tx bytes */
+                               req->td_data->status =
+                                       AMD_ADDBITS(req->td_data->status,
+                                               ep->ep.maxpacket,
+                                               UDC_DMA_IN_STS_TXBYTES);
+
+                       }
+               }
+
+       }
+
+       if (ep->in) {
+               VDBG(ep->dev, "IN: use_dma_ppb=%d req->req.len=%d "
+                               "maxpacket=%d ep%d\n",
+                               use_dma_ppb, req->req.length,
+                               ep->ep.maxpacket, ep->num);
+               /*
+                * if bytes < max packet then tx bytes must
+                * be written in packet per buffer mode
+                */
+               if (!use_dma_ppb || req->req.length < ep->ep.maxpacket
+                               || ep->num == UDC_EP0OUT_IX
+                               || ep->num == UDC_EP0IN_IX) {
+                       /* write tx bytes */
+                       req->td_data->status =
+                               AMD_ADDBITS(req->td_data->status,
+                                               req->req.length,
+                                               UDC_DMA_IN_STS_TXBYTES);
+                       /* reset frame num */
+                       req->td_data->status =
+                               AMD_ADDBITS(req->td_data->status,
+                                               0,
+                                               UDC_DMA_IN_STS_FRAMENUM);
+               }
+               /* set HOST BUSY */
+               req->td_data->status =
+                       AMD_ADDBITS(req->td_data->status,
+                               UDC_DMA_STP_STS_BS_HOST_BUSY,
+                               UDC_DMA_STP_STS_BS);
+       } else {
+               VDBG(ep->dev, "OUT set host ready\n");
+               /* set HOST READY */
+               req->td_data->status =
+                       AMD_ADDBITS(req->td_data->status,
+                               UDC_DMA_STP_STS_BS_HOST_READY,
+                               UDC_DMA_STP_STS_BS);
+
+
+                       /* clear NAK by writing CNAK */
+                       if (ep->naking) {
+                               tmp = readl(&ep->regs->ctl);
+                               tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+                               writel(tmp, &ep->regs->ctl);
+                               ep->naking = 0;
+                               UDC_QUEUE_CNAK(ep, ep->num);
+                       }
+
+       }
+
+       return retval;
+}
+
+/* Completes request packet ... caller MUST hold lock */
+static void
+complete_req(struct udc_ep *ep, struct udc_request *req, int sts)
+__releases(ep->dev->lock)
+__acquires(ep->dev->lock)
+{
+       struct udc              *dev;
+       unsigned                halted;
+
+       VDBG(ep->dev, "complete_req(): ep%d\n", ep->num);
+
+       dev = ep->dev;
+       /* unmap DMA */
+       if (req->dma_mapping) {
+               if (ep->in)
+                       pci_unmap_single(dev->pdev,
+                                       req->req.dma,
+                                       req->req.length,
+                                       PCI_DMA_TODEVICE);
+               else
+                       pci_unmap_single(dev->pdev,
+                                       req->req.dma,
+                                       req->req.length,
+                                       PCI_DMA_FROMDEVICE);
+               req->dma_mapping = 0;
+               req->req.dma = DMA_DONT_USE;
+       }
+
+       halted = ep->halted;
+       ep->halted = 1;
+
+       /* set new status if pending */
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = sts;
+
+       /* remove from ep queue */
+       list_del_init(&req->queue);
+
+       VDBG(ep->dev, "req %p => complete %d bytes at %s with sts %d\n",
+               &req->req, req->req.length, ep->ep.name, sts);
+
+       spin_unlock(&dev->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&dev->lock);
+       ep->halted = halted;
+}
+
+/* frees pci pool descriptors of a DMA chain */
+static int udc_free_dma_chain(struct udc *dev, struct udc_request *req)
+{
+
+       int ret_val = 0;
+       struct udc_data_dma     *td;
+       struct udc_data_dma     *td_last = NULL;
+       unsigned int i;
+
+       DBG(dev, "free chain req = %p\n", req);
+
+       /* do not free first desc., will be done by free for request */
+       td_last = req->td_data;
+       td = phys_to_virt(td_last->next);
+
+       for (i = 1; i < req->chain_len; i++) {
+
+               pci_pool_free(dev->data_requests, td,
+                               (dma_addr_t) td_last->next);
+               td_last = td;
+               td = phys_to_virt(td_last->next);
+       }
+
+       return ret_val;
+}
+
+/* Iterates to the end of a DMA chain and returns last descriptor */
+static struct udc_data_dma *udc_get_last_dma_desc(struct udc_request *req)
+{
+       struct udc_data_dma     *td;
+
+       td = req->td_data;
+       while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) {
+               td = phys_to_virt(td->next);
+       }
+
+       return td;
+
+}
+
+/* Iterates to the end of a DMA chain and counts bytes received */
+static u32 udc_get_ppbdu_rxbytes(struct udc_request *req)
+{
+       struct udc_data_dma     *td;
+       u32 count;
+
+       td = req->td_data;
+       /* received number bytes */
+       count = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_RXBYTES);
+
+       while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) {
+               td = phys_to_virt(td->next);
+               /* received number bytes */
+               if (td) {
+                       count += AMD_GETBITS(td->status,
+                               UDC_DMA_OUT_STS_RXBYTES);
+               }
+       }
+
+       return count;
+
+}
+
+/* Creates or re-inits a DMA chain */
+static int udc_create_dma_chain(
+       struct udc_ep *ep,
+       struct udc_request *req,
+       unsigned long buf_len, gfp_t gfp_flags
+)
+{
+       unsigned long bytes = req->req.length;
+       unsigned int i;
+       dma_addr_t dma_addr;
+       struct udc_data_dma     *td = NULL;
+       struct udc_data_dma     *last = NULL;
+       unsigned long txbytes;
+       unsigned create_new_chain = 0;
+       unsigned len;
+
+       VDBG(ep->dev, "udc_create_dma_chain: bytes=%ld buf_len=%ld\n",
+                       bytes, buf_len);
+       dma_addr = DMA_DONT_USE;
+
+       /* unset L bit in first desc for OUT */
+       if (!ep->in) {
+               req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
+       }
+
+       /* alloc only new desc's if not already available */
+       len = req->req.length / ep->ep.maxpacket;
+       if (req->req.length % ep->ep.maxpacket) {
+               len++;
+       }
+
+       if (len > req->chain_len) {
+               /* shorter chain already allocated before */
+               if (req->chain_len > 1) {
+                       udc_free_dma_chain(ep->dev, req);
+               }
+               req->chain_len = len;
+               create_new_chain = 1;
+       }
+
+       td = req->td_data;
+       /* gen. required number of descriptors and buffers */
+       for (i = buf_len; i < bytes; i += buf_len) {
+               /* create or determine next desc. */
+               if (create_new_chain) {
+
+                       td = pci_pool_alloc(ep->dev->data_requests,
+                                       gfp_flags, &dma_addr);
+                       if (!td)
+                               return -ENOMEM;
+
+                       td->status = 0;
+               } else if (i == buf_len) {
+                       /* first td */
+                       td = (struct udc_data_dma *) phys_to_virt(
+                                               req->td_data->next);
+                       td->status = 0;
+               } else {
+                       td = (struct udc_data_dma *) phys_to_virt(last->next);
+                       td->status = 0;
+               }
+
+
+               if (td)
+                       td->bufptr = req->req.dma + i; /* assign buffer */
+               else
+                       break;
+
+               /* short packet ? */
+               if ((bytes - i) >= buf_len) {
+                       txbytes = buf_len;
+               } else {
+                       /* short packet */
+                       txbytes = bytes - i;
+               }
+
+               /* link td and assign tx bytes */
+               if (i == buf_len) {
+                       if (create_new_chain) {
+                               req->td_data->next = dma_addr;
+                       } else {
+                               /* req->td_data->next = virt_to_phys(td); */
+                       }
+                       /* write tx bytes */
+                       if (ep->in) {
+                               /* first desc */
+                               req->td_data->status =
+                                       AMD_ADDBITS(req->td_data->status,
+                                                       ep->ep.maxpacket,
+                                                       UDC_DMA_IN_STS_TXBYTES);
+                               /* second desc */
+                               td->status = AMD_ADDBITS(td->status,
+                                                       txbytes,
+                                                       UDC_DMA_IN_STS_TXBYTES);
+                       }
+               } else {
+                       if (create_new_chain) {
+                               last->next = dma_addr;
+                       } else {
+                               /* last->next = virt_to_phys(td); */
+                       }
+                       if (ep->in) {
+                               /* write tx bytes */
+                               td->status = AMD_ADDBITS(td->status,
+                                                       txbytes,
+                                                       UDC_DMA_IN_STS_TXBYTES);
+                       }
+               }
+               last = td;
+       }
+       /* set last bit */
+       if (td) {
+               td->status |= AMD_BIT(UDC_DMA_IN_STS_L);
+               /* last desc. points to itself */
+               req->td_data_last = td;
+       }
+
+       return 0;
+}
+
+/* Enabling RX DMA */
+static void udc_set_rde(struct udc *dev)
+{
+       u32 tmp;
+
+       VDBG(dev, "udc_set_rde()\n");
+       /* stop RDE timer */
+       if (timer_pending(&udc_timer)) {
+               set_rde = 0;
+               mod_timer(&udc_timer, jiffies - 1);
+       }
+       /* set RDE */
+       tmp = readl(&dev->regs->ctl);
+       tmp |= AMD_BIT(UDC_DEVCTL_RDE);
+       writel(tmp, &dev->regs->ctl);
+}
+
+/* Queues a request packet, called by gadget driver */
+static int
+udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
+{
+       int                     retval = 0;
+       u8                      open_rxfifo = 0;
+       unsigned long           iflags;
+       struct udc_ep           *ep;
+       struct udc_request      *req;
+       struct udc              *dev;
+       u32                     tmp;
+
+       /* check the inputs */
+       req = container_of(usbreq, struct udc_request, req);
+
+       if (!usbep || !usbreq || !usbreq->complete || !usbreq->buf
+                       || !list_empty(&req->queue))
+               return -EINVAL;
+
+       ep = container_of(usbep, struct udc_ep, ep);
+       if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
+               return -EINVAL;
+
+       VDBG(ep->dev, "udc_queue(): ep%d-in=%d\n", ep->num, ep->in);
+       dev = ep->dev;
+
+       if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       /* map dma (usually done before) */
+       if (ep->dma && usbreq->length != 0
+                       && (usbreq->dma == DMA_DONT_USE || usbreq->dma == 0)) {
+               VDBG(dev, "DMA map req %p\n", req);
+               if (ep->in)
+                       usbreq->dma = pci_map_single(dev->pdev,
+                                               usbreq->buf,
+                                               usbreq->length,
+                                               PCI_DMA_TODEVICE);
+               else
+                       usbreq->dma = pci_map_single(dev->pdev,
+                                               usbreq->buf,
+                                               usbreq->length,
+                                               PCI_DMA_FROMDEVICE);
+               req->dma_mapping = 1;
+       }
+
+       VDBG(dev, "%s queue req %p, len %d req->td_data=%p buf %p\n",
+                       usbep->name, usbreq, usbreq->length,
+                       req->td_data, usbreq->buf);
+
+       spin_lock_irqsave(&dev->lock, iflags);
+       usbreq->actual = 0;
+       usbreq->status = -EINPROGRESS;
+       req->dma_done = 0;
+
+       /* on empty queue just do first transfer */
+       if (list_empty(&ep->queue)) {
+               /* zlp */
+               if (usbreq->length == 0) {
+                       /* IN zlp's are handled by hardware */
+                       complete_req(ep, req, 0);
+                       VDBG(dev, "%s: zlp\n", ep->ep.name);
+                       /*
+                        * if set_config or set_intf is waiting for ack by zlp
+                        * then set CSR_DONE
+                        */
+                       if (dev->set_cfg_not_acked) {
+                               tmp = readl(&dev->regs->ctl);
+                               tmp |= AMD_BIT(UDC_DEVCTL_CSR_DONE);
+                               writel(tmp, &dev->regs->ctl);
+                               dev->set_cfg_not_acked = 0;
+                       }
+                       /* setup command is ACK'ed now by zlp */
+                       if (dev->waiting_zlp_ack_ep0in) {
+                               /* clear NAK by writing CNAK in EP0_IN */
+                               tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
+                               tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+                               writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
+                               dev->ep[UDC_EP0IN_IX].naking = 0;
+                               UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX],
+                                                       UDC_EP0IN_IX);
+                               dev->waiting_zlp_ack_ep0in = 0;
+                       }
+                       goto finished;
+               }
+               if (ep->dma) {
+                       retval = prep_dma(ep, req, gfp);
+                       if (retval != 0)
+                               goto finished;
+                       /* write desc pointer to enable DMA */
+                       if (ep->in) {
+                               /* set HOST READY */
+                               req->td_data->status =
+                                       AMD_ADDBITS(req->td_data->status,
+                                               UDC_DMA_IN_STS_BS_HOST_READY,
+                                               UDC_DMA_IN_STS_BS);
+                       }
+
+                       /* disabled rx dma while descriptor update */
+                       if (!ep->in) {
+                               /* stop RDE timer */
+                               if (timer_pending(&udc_timer)) {
+                                       set_rde = 0;
+                                       mod_timer(&udc_timer, jiffies - 1);
+                               }
+                               /* clear RDE */
+                               tmp = readl(&dev->regs->ctl);
+                               tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_RDE);
+                               writel(tmp, &dev->regs->ctl);
+                               open_rxfifo = 1;
+
+                               /*
+                                * if BNA occurred then let BNA dummy desc.
+                                * point to current desc.
+                                */
+                               if (ep->bna_occurred) {
+                                       VDBG(dev, "copy to BNA dummy desc.\n");
+                                       memcpy(ep->bna_dummy_req->td_data,
+                                               req->td_data,
+                                               sizeof(struct udc_data_dma));
+                               }
+                       }
+                       /* write desc pointer */
+                       writel(req->td_phys, &ep->regs->desptr);
+
+                       /* clear NAK by writing CNAK */
+                       if (ep->naking) {
+                               tmp = readl(&ep->regs->ctl);
+                               tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+                               writel(tmp, &ep->regs->ctl);
+                               ep->naking = 0;
+                               UDC_QUEUE_CNAK(ep, ep->num);
+                       }
+
+                       if (ep->in) {
+                               /* enable ep irq */
+                               tmp = readl(&dev->regs->ep_irqmsk);
+                               tmp &= AMD_UNMASK_BIT(ep->num);
+                               writel(tmp, &dev->regs->ep_irqmsk);
+                       }
+               }
+
+       } else if (ep->dma) {
+
+               /*
+                * prep_dma not used for OUT ep's, this is not possible
+                * for PPB modes, because of chain creation reasons
+                */
+               if (ep->in) {
+                       retval = prep_dma(ep, req, gfp);
+                       if (retval != 0)
+                               goto finished;
+               }
+       }
+       VDBG(dev, "list_add\n");
+       /* add request to ep queue */
+       if (req) {
+
+               list_add_tail(&req->queue, &ep->queue);
+
+               /* open rxfifo if out data queued */
+               if (open_rxfifo) {
+                       /* enable DMA */
+                       req->dma_going = 1;
+                       udc_set_rde(dev);
+                       if (ep->num != UDC_EP0OUT_IX)
+                               dev->data_ep_queued = 1;
+               }
+               /* stop OUT naking */
+               if (!ep->in) {
+                       if (!use_dma && udc_rxfifo_pending) {
+                               DBG(dev, "udc_queue(): pending bytes in"
+                                       "rxfifo after nyet\n");
+                               /*
+                                * read pending bytes afer nyet:
+                                * referring to isr
+                                */
+                               if (udc_rxfifo_read(ep, req)) {
+                                       /* finish */
+                                       complete_req(ep, req, 0);
+                               }
+                               udc_rxfifo_pending = 0;
+
+                       }
+               }
+       }
+
+finished:
+       spin_unlock_irqrestore(&dev->lock, iflags);
+       return retval;
+}
+
+/* Empty request queue of an endpoint; caller holds spinlock */
+static void empty_req_queue(struct udc_ep *ep)
+{
+       struct udc_request      *req;
+
+       ep->halted = 1;
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next,
+                       struct udc_request,
+                       queue);
+               complete_req(ep, req, -ESHUTDOWN);
+       }
+}
+
+/* Dequeues a request packet, called by gadget driver */
+static int udc_dequeue(struct usb_ep *usbep, struct usb_request *usbreq)
+{
+       struct udc_ep           *ep;
+       struct udc_request      *req;
+       unsigned                halted;
+       unsigned long           iflags;
+
+       ep = container_of(usbep, struct udc_ep, ep);
+       if (!usbep || !usbreq || (!ep->desc && (ep->num != 0
+                               && ep->num != UDC_EP0OUT_IX)))
+               return -EINVAL;
+
+       req = container_of(usbreq, struct udc_request, req);
+
+       spin_lock_irqsave(&ep->dev->lock, iflags);
+       halted = ep->halted;
+       ep->halted = 1;
+       /* request in processing or next one */
+       if (ep->queue.next == &req->queue) {
+               if (ep->dma && req->dma_going) {
+                       if (ep->in)
+                               ep->cancel_transfer = 1;
+                       else {
+                               u32 tmp;
+                               u32 dma_sts;
+                               /* stop potential receive DMA */
+                               tmp = readl(&udc->regs->ctl);
+                               writel(tmp & AMD_UNMASK_BIT(UDC_DEVCTL_RDE),
+                                                       &udc->regs->ctl);
+                               /*
+                                * Cancel transfer later in ISR
+                                * if descriptor was touched.
+                                */
+                               dma_sts = AMD_GETBITS(req->td_data->status,
+                                                       UDC_DMA_OUT_STS_BS);
+                               if (dma_sts != UDC_DMA_OUT_STS_BS_HOST_READY)
+                                       ep->cancel_transfer = 1;
+                               else {
+                                       udc_init_bna_dummy(ep->req);
+                                       writel(ep->bna_dummy_req->td_phys,
+                                               &ep->regs->desptr);
+                               }
+                               writel(tmp, &udc->regs->ctl);
+                       }
+               }
+       }
+       complete_req(ep, req, -ECONNRESET);
+       ep->halted = halted;
+
+       spin_unlock_irqrestore(&ep->dev->lock, iflags);
+       return 0;
+}
+
+/* Halt or clear halt of endpoint */
+static int
+udc_set_halt(struct usb_ep *usbep, int halt)
+{
+       struct udc_ep   *ep;
+       u32 tmp;
+       unsigned long iflags;
+       int retval = 0;
+
+       if (!usbep)
+               return -EINVAL;
+
+       pr_debug("set_halt %s: halt=%d\n", usbep->name, halt);
+
+       ep = container_of(usbep, struct udc_ep, ep);
+       if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
+               return -EINVAL;
+       if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+               return -ESHUTDOWN;
+
+       spin_lock_irqsave(&udc_stall_spinlock, iflags);
+       /* halt or clear halt */
+       if (halt) {
+               if (ep->num == 0)
+                       ep->dev->stall_ep0in = 1;
+               else {
+                       /*
+                        * set STALL
+                        * rxfifo empty not taken into acount
+                        */
+                       tmp = readl(&ep->regs->ctl);
+                       tmp |= AMD_BIT(UDC_EPCTL_S);
+                       writel(tmp, &ep->regs->ctl);
+                       ep->halted = 1;
+
+                       /* setup poll timer */
+                       if (!timer_pending(&udc_pollstall_timer)) {
+                               udc_pollstall_timer.expires = jiffies +
+                                       HZ * UDC_POLLSTALL_TIMER_USECONDS
+                                       / (1000 * 1000);
+                               if (!stop_pollstall_timer) {
+                                       DBG(ep->dev, "start polltimer\n");
+                                       add_timer(&udc_pollstall_timer);
+                               }
+                       }
+               }
+       } else {
+               /* ep is halted by set_halt() before */
+               if (ep->halted) {
+                       tmp = readl(&ep->regs->ctl);
+                       /* clear stall bit */
+                       tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S);
+                       /* clear NAK by writing CNAK */
+                       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+                       writel(tmp, &ep->regs->ctl);
+                       ep->halted = 0;
+                       UDC_QUEUE_CNAK(ep, ep->num);
+               }
+       }
+       spin_unlock_irqrestore(&udc_stall_spinlock, iflags);
+       return retval;
+}
+
+/* gadget interface */
+static const struct usb_ep_ops udc_ep_ops = {
+       .enable         = udc_ep_enable,
+       .disable        = udc_ep_disable,
+
+       .alloc_request  = udc_alloc_request,
+       .free_request   = udc_free_request,
+
+       .queue          = udc_queue,
+       .dequeue        = udc_dequeue,
+
+       .set_halt       = udc_set_halt,
+       /* fifo ops not implemented */
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Get frame counter (not implemented) */
+static int udc_get_frame(struct usb_gadget *gadget)
+{
+       return -EOPNOTSUPP;
+}
+
+/* Remote wakeup gadget interface */
+static int udc_wakeup(struct usb_gadget *gadget)
+{
+       struct udc              *dev;
+
+       if (!gadget)
+               return -EINVAL;
+       dev = container_of(gadget, struct udc, gadget);
+       udc_remote_wakeup(dev);
+
+       return 0;
+}
+
+/* gadget operations */
+static const struct usb_gadget_ops udc_ops = {
+       .wakeup         = udc_wakeup,
+       .get_frame      = udc_get_frame,
+};
+
+/* Setups endpoint parameters, adds endpoints to linked list */
+static void make_ep_lists(struct udc *dev)
+{
+       /* make gadget ep lists */
+       INIT_LIST_HEAD(&dev->gadget.ep_list);
+       list_add_tail(&dev->ep[UDC_EPIN_STATUS_IX].ep.ep_list,
+                                               &dev->gadget.ep_list);
+       list_add_tail(&dev->ep[UDC_EPIN_IX].ep.ep_list,
+                                               &dev->gadget.ep_list);
+       list_add_tail(&dev->ep[UDC_EPOUT_IX].ep.ep_list,
+                                               &dev->gadget.ep_list);
+
+       /* fifo config */
+       dev->ep[UDC_EPIN_STATUS_IX].fifo_depth = UDC_EPIN_SMALLINT_BUFF_SIZE;
+       if (dev->gadget.speed == USB_SPEED_FULL)
+               dev->ep[UDC_EPIN_IX].fifo_depth = UDC_FS_EPIN_BUFF_SIZE;
+       else if (dev->gadget.speed == USB_SPEED_HIGH)
+               dev->ep[UDC_EPIN_IX].fifo_depth = hs_tx_buf;
+       dev->ep[UDC_EPOUT_IX].fifo_depth = UDC_RXFIFO_SIZE;
+}
+
+/* init registers at driver load time */
+static int startup_registers(struct udc *dev)
+{
+       u32 tmp;
+
+       /* init controller by soft reset */
+       udc_soft_reset(dev);
+
+       /* mask not needed interrupts */
+       udc_mask_unused_interrupts(dev);
+
+       /* put into initial config */
+       udc_basic_init(dev);
+       /* link up all endpoints */
+       udc_setup_endpoints(dev);
+
+       /* program speed */
+       tmp = readl(&dev->regs->cfg);
+       if (use_fullspeed) {
+               tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
+       } else {
+               tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);
+       }
+       writel(tmp, &dev->regs->cfg);
+
+       return 0;
+}
+
+/* Inits UDC context */
+static void udc_basic_init(struct udc *dev)
+{
+       u32     tmp;
+
+       DBG(dev, "udc_basic_init()\n");
+
+       dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+       /* stop RDE timer */
+       if (timer_pending(&udc_timer)) {
+               set_rde = 0;
+               mod_timer(&udc_timer, jiffies - 1);
+       }
+       /* stop poll stall timer */
+       if (timer_pending(&udc_pollstall_timer)) {
+               mod_timer(&udc_pollstall_timer, jiffies - 1);
+       }
+       /* disable DMA */
+       tmp = readl(&dev->regs->ctl);
+       tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_RDE);
+       tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_TDE);
+       writel(tmp, &dev->regs->ctl);
+
+       /* enable dynamic CSR programming */
+       tmp = readl(&dev->regs->cfg);
+       tmp |= AMD_BIT(UDC_DEVCFG_CSR_PRG);
+       /* set self powered */
+       tmp |= AMD_BIT(UDC_DEVCFG_SP);
+       /* set remote wakeupable */
+       tmp |= AMD_BIT(UDC_DEVCFG_RWKP);
+       writel(tmp, &dev->regs->cfg);
+
+       make_ep_lists(dev);
+
+       dev->data_ep_enabled = 0;
+       dev->data_ep_queued = 0;
+}
+
+/* Sets initial endpoint parameters */
+static void udc_setup_endpoints(struct udc *dev)
+{
+       struct udc_ep   *ep;
+       u32     tmp;
+       u32     reg;
+
+       DBG(dev, "udc_setup_endpoints()\n");
+
+       /* read enum speed */
+       tmp = readl(&dev->regs->sts);
+       tmp = AMD_GETBITS(tmp, UDC_DEVSTS_ENUM_SPEED);
+       if (tmp == UDC_DEVSTS_ENUM_SPEED_HIGH) {
+               dev->gadget.speed = USB_SPEED_HIGH;
+       } else if (tmp == UDC_DEVSTS_ENUM_SPEED_FULL) {
+               dev->gadget.speed = USB_SPEED_FULL;
+       }
+
+       /* set basic ep parameters */
+       for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
+               ep = &dev->ep[tmp];
+               ep->dev = dev;
+               ep->ep.name = ep_string[tmp];
+               ep->num = tmp;
+               /* txfifo size is calculated at enable time */
+               ep->txfifo = dev->txfifo;
+
+               /* fifo size */
+               if (tmp < UDC_EPIN_NUM) {
+                       ep->fifo_depth = UDC_TXFIFO_SIZE;
+                       ep->in = 1;
+               } else {
+                       ep->fifo_depth = UDC_RXFIFO_SIZE;
+                       ep->in = 0;
+
+               }
+               ep->regs = &dev->ep_regs[tmp];
+               /*
+                * ep will be reset only if ep was not enabled before to avoid
+                * disabling ep interrupts when ENUM interrupt occurs but ep is
+                * not enabled by gadget driver
+                */
+               if (!ep->desc) {
+                       ep_init(dev->regs, ep);
+               }
+
+               if (use_dma) {
+                       /*
+                        * ep->dma is not really used, just to indicate that
+                        * DMA is active: remove this
+                        * dma regs = dev control regs
+                        */
+                       ep->dma = &dev->regs->ctl;
+
+                       /* nak OUT endpoints until enable - not for ep0 */
+                       if (tmp != UDC_EP0IN_IX && tmp != UDC_EP0OUT_IX
+                                               && tmp > UDC_EPIN_NUM) {
+                               /* set NAK */
+                               reg = readl(&dev->ep[tmp].regs->ctl);
+                               reg |= AMD_BIT(UDC_EPCTL_SNAK);
+                               writel(reg, &dev->ep[tmp].regs->ctl);
+                               dev->ep[tmp].naking = 1;
+
+                       }
+               }
+       }
+       /* EP0 max packet */
+       if (dev->gadget.speed == USB_SPEED_FULL) {
+               dev->ep[UDC_EP0IN_IX].ep.maxpacket = UDC_FS_EP0IN_MAX_PKT_SIZE;
+               dev->ep[UDC_EP0OUT_IX].ep.maxpacket =
+                                               UDC_FS_EP0OUT_MAX_PKT_SIZE;
+       } else if (dev->gadget.speed == USB_SPEED_HIGH) {
+               dev->ep[UDC_EP0IN_IX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE;
+               dev->ep[UDC_EP0OUT_IX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE;
+       }
+
+       /*
+        * with suspend bug workaround, ep0 params for gadget driver
+        * are set at gadget driver bind() call
+        */
+       dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IX].ep;
+       dev->ep[UDC_EP0IN_IX].halted = 0;
+       INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+
+       /* init cfg/alt/int */
+       dev->cur_config = 0;
+       dev->cur_intf = 0;
+       dev->cur_alt = 0;
+}
+
+/* Bringup after Connect event, initial bringup to be ready for ep0 events */
+static void usb_connect(struct udc *dev)
+{
+
+       dev_info(&dev->pdev->dev, "USB Connect\n");
+
+       dev->connected = 1;
+
+       /* put into initial config */
+       udc_basic_init(dev);
+
+       /* enable device setup interrupts */
+       udc_enable_dev_setup_interrupts(dev);
+}
+
+/*
+ * Calls gadget with disconnect event and resets the UDC and makes
+ * initial bringup to be ready for ep0 events
+ */
+static void usb_disconnect(struct udc *dev)
+{
+
+       dev_info(&dev->pdev->dev, "USB Disconnect\n");
+
+       dev->connected = 0;
+
+       /* mask interrupts */
+       udc_mask_unused_interrupts(dev);
+
+       /* REVISIT there doesn't seem to be a point to having this
+        * talk to a tasklet ... do it directly, we already hold
+        * the spinlock needed to process the disconnect.
+        */
+
+       tasklet_schedule(&disconnect_tasklet);
+}
+
+/* Tasklet for disconnect to be outside of interrupt context */
+static void udc_tasklet_disconnect(unsigned long par)
+{
+       struct udc *dev = (struct udc *)(*((struct udc **) par));
+       u32 tmp;
+
+       DBG(dev, "Tasklet disconnect\n");
+       spin_lock_irq(&dev->lock);
+
+       if (dev->driver) {
+               spin_unlock(&dev->lock);
+               dev->driver->disconnect(&dev->gadget);
+               spin_lock(&dev->lock);
+
+               /* empty queues */
+               for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
+                       empty_req_queue(&dev->ep[tmp]);
+               }
+
+       }
+
+       /* disable ep0 */
+       ep_init(dev->regs,
+                       &dev->ep[UDC_EP0IN_IX]);
+
+
+       if (!soft_reset_occured) {
+               /* init controller by soft reset */
+               udc_soft_reset(dev);
+               soft_reset_occured++;
+       }
+
+       /* re-enable dev interrupts */
+       udc_enable_dev_setup_interrupts(dev);
+       /* back to full speed ? */
+       if (use_fullspeed) {
+               tmp = readl(&dev->regs->cfg);
+               tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
+               writel(tmp, &dev->regs->cfg);
+       }
+
+       spin_unlock_irq(&dev->lock);
+}
+
+/* Reset the UDC core */
+static void udc_soft_reset(struct udc *dev)
+{
+       unsigned long   flags;
+
+       DBG(dev, "Soft reset\n");
+       /*
+        * reset possible waiting interrupts, because int.
+        * status is lost after soft reset,
+        * ep int. status reset
+        */
+       writel(UDC_EPINT_MSK_DISABLE_ALL, &dev->regs->ep_irqsts);
+       /* device int. status reset */
+       writel(UDC_DEV_MSK_DISABLE, &dev->regs->irqsts);
+
+       spin_lock_irqsave(&udc_irq_spinlock, flags);
+       writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
+       readl(&dev->regs->cfg);
+       spin_unlock_irqrestore(&udc_irq_spinlock, flags);
+
+}
+
+/* RDE timer callback to set RDE bit */
+static void udc_timer_function(unsigned long v)
+{
+       u32 tmp;
+
+       spin_lock_irq(&udc_irq_spinlock);
+
+       if (set_rde > 0) {
+               /*
+                * open the fifo if fifo was filled on last timer call
+                * conditionally
+                */
+               if (set_rde > 1) {
+                       /* set RDE to receive setup data */
+                       tmp = readl(&udc->regs->ctl);
+                       tmp |= AMD_BIT(UDC_DEVCTL_RDE);
+                       writel(tmp, &udc->regs->ctl);
+                       set_rde = -1;
+               } else if (readl(&udc->regs->sts)
+                               & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {
+                       /*
+                        * if fifo empty setup polling, do not just
+                        * open the fifo
+                        */
+                       udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV;
+                       if (!stop_timer) {
+                               add_timer(&udc_timer);
+                       }
+               } else {
+                       /*
+                        * fifo contains data now, setup timer for opening
+                        * the fifo when timer expires to be able to receive
+                        * setup packets, when data packets gets queued by
+                        * gadget layer then timer will forced to expire with
+                        * set_rde=0 (RDE is set in udc_queue())
+                        */
+                       set_rde++;
+                       /* debug: lhadmot_timer_start = 221070 */
+                       udc_timer.expires = jiffies + HZ*UDC_RDE_TIMER_SECONDS;
+                       if (!stop_timer) {
+                               add_timer(&udc_timer);
+                       }
+               }
+
+       } else
+               set_rde = -1; /* RDE was set by udc_queue() */
+       spin_unlock_irq(&udc_irq_spinlock);
+       if (stop_timer)
+               complete(&on_exit);
+
+}
+
+/* Handle halt state, used in stall poll timer */
+static void udc_handle_halt_state(struct udc_ep *ep)
+{
+       u32 tmp;
+       /* set stall as long not halted */
+       if (ep->halted == 1) {
+               tmp = readl(&ep->regs->ctl);
+               /* STALL cleared ? */
+               if (!(tmp & AMD_BIT(UDC_EPCTL_S))) {
+                       /*
+                        * FIXME: MSC spec requires that stall remains
+                        * even on receivng of CLEAR_FEATURE HALT. So
+                        * we would set STALL again here to be compliant.
+                        * But with current mass storage drivers this does
+                        * not work (would produce endless host retries).
+                        * So we clear halt on CLEAR_FEATURE.
+                        *
+                       DBG(ep->dev, "ep %d: set STALL again\n", ep->num);
+                       tmp |= AMD_BIT(UDC_EPCTL_S);
+                       writel(tmp, &ep->regs->ctl);*/
+
+                       /* clear NAK by writing CNAK */
+                       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+                       writel(tmp, &ep->regs->ctl);
+                       ep->halted = 0;
+                       UDC_QUEUE_CNAK(ep, ep->num);
+               }
+       }
+}
+
+/* Stall timer callback to poll S bit and set it again after */
+static void udc_pollstall_timer_function(unsigned long v)
+{
+       struct udc_ep *ep;
+       int halted = 0;
+
+       spin_lock_irq(&udc_stall_spinlock);
+       /*
+        * only one IN and OUT endpoints are handled
+        * IN poll stall
+        */
+       ep = &udc->ep[UDC_EPIN_IX];
+       udc_handle_halt_state(ep);
+       if (ep->halted)
+               halted = 1;
+       /* OUT poll stall */
+       ep = &udc->ep[UDC_EPOUT_IX];
+       udc_handle_halt_state(ep);
+       if (ep->halted)
+               halted = 1;
+
+       /* setup timer again when still halted */
+       if (!stop_pollstall_timer && halted) {
+               udc_pollstall_timer.expires = jiffies +
+                                       HZ * UDC_POLLSTALL_TIMER_USECONDS
+                                       / (1000 * 1000);
+               add_timer(&udc_pollstall_timer);
+       }
+       spin_unlock_irq(&udc_stall_spinlock);
+
+       if (stop_pollstall_timer)
+               complete(&on_pollstall_exit);
+}
+
+/* Inits endpoint 0 so that SETUP packets are processed */
+static void activate_control_endpoints(struct udc *dev)
+{
+       u32 tmp;
+
+       DBG(dev, "activate_control_endpoints\n");
+
+       /* flush fifo */
+       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
+       tmp |= AMD_BIT(UDC_EPCTL_F);
+       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
+
+       /* set ep0 directions */
+       dev->ep[UDC_EP0IN_IX].in = 1;
+       dev->ep[UDC_EP0OUT_IX].in = 0;
+
+       /* set buffer size (tx fifo entries) of EP0_IN */
+       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufin_framenum);
+       if (dev->gadget.speed == USB_SPEED_FULL)
+               tmp = AMD_ADDBITS(tmp, UDC_FS_EPIN0_BUFF_SIZE,
+                                       UDC_EPIN_BUFF_SIZE);
+       else if (dev->gadget.speed == USB_SPEED_HIGH)
+               tmp = AMD_ADDBITS(tmp, UDC_EPIN0_BUFF_SIZE,
+                                       UDC_EPIN_BUFF_SIZE);
+       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufin_framenum);
+
+       /* set max packet size of EP0_IN */
+       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt);
+       if (dev->gadget.speed == USB_SPEED_FULL)
+               tmp = AMD_ADDBITS(tmp, UDC_FS_EP0IN_MAX_PKT_SIZE,
+                                       UDC_EP_MAX_PKT_SIZE);
+       else if (dev->gadget.speed == USB_SPEED_HIGH)
+               tmp = AMD_ADDBITS(tmp, UDC_EP0IN_MAX_PKT_SIZE,
+                               UDC_EP_MAX_PKT_SIZE);
+       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt);
+
+       /* set max packet size of EP0_OUT */
+       tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt);
+       if (dev->gadget.speed == USB_SPEED_FULL)
+               tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE,
+                                       UDC_EP_MAX_PKT_SIZE);
+       else if (dev->gadget.speed == USB_SPEED_HIGH)
+               tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE,
+                                       UDC_EP_MAX_PKT_SIZE);
+       writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt);
+
+       /* set max packet size of EP0 in UDC CSR */
+       tmp = readl(&dev->csr->ne[0]);
+       if (dev->gadget.speed == USB_SPEED_FULL)
+               tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE,
+                                       UDC_CSR_NE_MAX_PKT);
+       else if (dev->gadget.speed == USB_SPEED_HIGH)
+               tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE,
+                                       UDC_CSR_NE_MAX_PKT);
+       writel(tmp, &dev->csr->ne[0]);
+
+       if (use_dma) {
+               dev->ep[UDC_EP0OUT_IX].td->status |=
+                       AMD_BIT(UDC_DMA_OUT_STS_L);
+               /* write dma desc address */
+               writel(dev->ep[UDC_EP0OUT_IX].td_stp_dma,
+                       &dev->ep[UDC_EP0OUT_IX].regs->subptr);
+               writel(dev->ep[UDC_EP0OUT_IX].td_phys,
+                       &dev->ep[UDC_EP0OUT_IX].regs->desptr);
+               /* stop RDE timer */
+               if (timer_pending(&udc_timer)) {
+                       set_rde = 0;
+                       mod_timer(&udc_timer, jiffies - 1);
+               }
+               /* stop pollstall timer */
+               if (timer_pending(&udc_pollstall_timer)) {
+                       mod_timer(&udc_pollstall_timer, jiffies - 1);
+               }
+               /* enable DMA */
+               tmp = readl(&dev->regs->ctl);
+               tmp |= AMD_BIT(UDC_DEVCTL_MODE)
+                               | AMD_BIT(UDC_DEVCTL_RDE)
+                               | AMD_BIT(UDC_DEVCTL_TDE);
+               if (use_dma_bufferfill_mode) {
+                       tmp |= AMD_BIT(UDC_DEVCTL_BF);
+               } else if (use_dma_ppb_du) {
+                       tmp |= AMD_BIT(UDC_DEVCTL_DU);
+               }
+               writel(tmp, &dev->regs->ctl);
+       }
+
+       /* clear NAK by writing CNAK for EP0IN */
+       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
+       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
+       dev->ep[UDC_EP0IN_IX].naking = 0;
+       UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX);
+
+       /* clear NAK by writing CNAK for EP0OUT */
+       tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);
+       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+       writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl);
+       dev->ep[UDC_EP0OUT_IX].naking = 0;
+       UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX);
+}
+
+/* Make endpoint 0 ready for control traffic */
+static int setup_ep0(struct udc *dev)
+{
+       activate_control_endpoints(dev);
+       /* enable ep0 interrupts */
+       udc_enable_ep0_interrupts(dev);
+       /* enable device setup interrupts */
+       udc_enable_dev_setup_interrupts(dev);
+
+       return 0;
+}
+
+/* Called by gadget driver to register itself */
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+       struct udc              *dev = udc;
+       int                     retval;
+       u32 tmp;
+
+       if (!driver || !driver->bind || !driver->setup
+                       || driver->speed != USB_SPEED_HIGH)
+               return -EINVAL;
+       if (!dev)
+               return -ENODEV;
+       if (dev->driver)
+               return -EBUSY;
+
+       driver->driver.bus = NULL;
+       dev->driver = driver;
+       dev->gadget.dev.driver = &driver->driver;
+
+       retval = driver->bind(&dev->gadget);
+
+       /* Some gadget drivers use both ep0 directions.
+        * NOTE: to gadget driver, ep0 is just one endpoint...
+        */
+       dev->ep[UDC_EP0OUT_IX].ep.driver_data =
+               dev->ep[UDC_EP0IN_IX].ep.driver_data;
+
+       if (retval) {
+               DBG(dev, "binding to %s returning %d\n",
+                               driver->driver.name, retval);
+               dev->driver = NULL;
+               dev->gadget.dev.driver = NULL;
+               return retval;
+       }
+
+       /* get ready for ep0 traffic */
+       setup_ep0(dev);
+
+       /* clear SD */
+       tmp = readl(&dev->regs->ctl);
+       tmp = tmp & AMD_CLEAR_BIT(UDC_DEVCTL_SD);
+       writel(tmp, &dev->regs->ctl);
+
+       usb_connect(dev);
+
+       return 0;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+/* shutdown requests and disconnect from gadget */
+static void
+shutdown(struct udc *dev, struct usb_gadget_driver *driver)
+__releases(dev->lock)
+__acquires(dev->lock)
+{
+       int tmp;
+
+       /* empty queues and init hardware */
+       udc_basic_init(dev);
+       for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
+               empty_req_queue(&dev->ep[tmp]);
+       }
+
+       if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
+               spin_unlock(&dev->lock);
+               driver->disconnect(&dev->gadget);
+               spin_lock(&dev->lock);
+       }
+       /* init */
+       udc_setup_endpoints(dev);
+}
+
+/* Called by gadget driver to unregister itself */
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+       struct udc      *dev = udc;
+       unsigned long   flags;
+       u32 tmp;
+
+       if (!dev)
+               return -ENODEV;
+       if (!driver || driver != dev->driver || !driver->unbind)
+               return -EINVAL;
+
+       spin_lock_irqsave(&dev->lock, flags);
+       udc_mask_unused_interrupts(dev);
+       shutdown(dev, driver);
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       driver->unbind(&dev->gadget);
+       dev->driver = NULL;
+
+       /* set SD */
+       tmp = readl(&dev->regs->ctl);
+       tmp |= AMD_BIT(UDC_DEVCTL_SD);
+       writel(tmp, &dev->regs->ctl);
+
+
+       DBG(dev, "%s: unregistered\n", driver->driver.name);
+
+       return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+
+/* Clear pending NAK bits */
+static void udc_process_cnak_queue(struct udc *dev)
+{
+       u32 tmp;
+       u32 reg;
+
+       /* check epin's */
+       DBG(dev, "CNAK pending queue processing\n");
+       for (tmp = 0; tmp < UDC_EPIN_NUM_USED; tmp++) {
+               if (cnak_pending & (1 << tmp)) {
+                       DBG(dev, "CNAK pending for ep%d\n", tmp);
+                       /* clear NAK by writing CNAK */
+                       reg = readl(&dev->ep[tmp].regs->ctl);
+                       reg |= AMD_BIT(UDC_EPCTL_CNAK);
+                       writel(reg, &dev->ep[tmp].regs->ctl);
+                       dev->ep[tmp].naking = 0;
+                       UDC_QUEUE_CNAK(&dev->ep[tmp], dev->ep[tmp].num);
+               }
+       }
+       /* ...  and ep0out */
+       if (cnak_pending & (1 << UDC_EP0OUT_IX)) {
+               DBG(dev, "CNAK pending for ep%d\n", UDC_EP0OUT_IX);
+               /* clear NAK by writing CNAK */
+               reg = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);
+               reg |= AMD_BIT(UDC_EPCTL_CNAK);
+               writel(reg, &dev->ep[UDC_EP0OUT_IX].regs->ctl);
+               dev->ep[UDC_EP0OUT_IX].naking = 0;
+               UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX],
+                               dev->ep[UDC_EP0OUT_IX].num);
+       }
+}
+
+/* Enabling RX DMA after setup packet */
+static void udc_ep0_set_rde(struct udc *dev)
+{
+       if (use_dma) {
+               /*
+                * only enable RXDMA when no data endpoint enabled
+                * or data is queued
+                */
+               if (!dev->data_ep_enabled || dev->data_ep_queued) {
+                       udc_set_rde(dev);
+               } else {
+                       /*
+                        * setup timer for enabling RDE (to not enable
+                        * RXFIFO DMA for data endpoints to early)
+                        */
+                       if (set_rde != 0 && !timer_pending(&udc_timer)) {
+                               udc_timer.expires =
+                                       jiffies + HZ/UDC_RDE_TIMER_DIV;
+                               set_rde = 1;
+                               if (!stop_timer) {
+                                       add_timer(&udc_timer);
+                               }
+                       }
+               }
+       }
+}
+
+
+/* Interrupt handler for data OUT traffic */
+static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
+{
+       irqreturn_t             ret_val = IRQ_NONE;
+       u32                     tmp;
+       struct udc_ep           *ep;
+       struct udc_request      *req;
+       unsigned int            count;
+       struct udc_data_dma     *td = NULL;
+       unsigned                dma_done;
+
+       VDBG(dev, "ep%d irq\n", ep_ix);
+       ep = &dev->ep[ep_ix];
+
+       tmp = readl(&ep->regs->sts);
+       if (use_dma) {
+               /* BNA event ? */
+               if (tmp & AMD_BIT(UDC_EPSTS_BNA)) {
+                       DBG(dev, "BNA ep%dout occured - DESPTR = %x \n",
+                                       ep->num, readl(&ep->regs->desptr));
+                       /* clear BNA */
+                       writel(tmp | AMD_BIT(UDC_EPSTS_BNA), &ep->regs->sts);
+                       if (!ep->cancel_transfer)
+                               ep->bna_occurred = 1;
+                       else
+                               ep->cancel_transfer = 0;
+                       ret_val = IRQ_HANDLED;
+                       goto finished;
+               }
+       }
+       /* HE event ? */
+       if (tmp & AMD_BIT(UDC_EPSTS_HE)) {
+               dev_err(&dev->pdev->dev, "HE ep%dout occured\n", ep->num);
+
+               /* clear HE */
+               writel(tmp | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts);
+               ret_val = IRQ_HANDLED;
+               goto finished;
+       }
+
+       if (!list_empty(&ep->queue)) {
+
+               /* next request */
+               req = list_entry(ep->queue.next,
+                       struct udc_request, queue);
+       } else {
+               req = NULL;
+               udc_rxfifo_pending = 1;
+       }
+       VDBG(dev, "req = %p\n", req);
+       /* fifo mode */
+       if (!use_dma) {
+
+               /* read fifo */
+               if (req && udc_rxfifo_read(ep, req)) {
+                       ret_val = IRQ_HANDLED;
+
+                       /* finish */
+                       complete_req(ep, req, 0);
+                       /* next request */
+                       if (!list_empty(&ep->queue) && !ep->halted) {
+                               req = list_entry(ep->queue.next,
+                                       struct udc_request, queue);
+                       } else
+                               req = NULL;
+               }
+
+       /* DMA */
+       } else if (!ep->cancel_transfer && req != NULL) {
+               ret_val = IRQ_HANDLED;
+
+               /* check for DMA done */
+               if (!use_dma_ppb) {
+                       dma_done = AMD_GETBITS(req->td_data->status,
+                                               UDC_DMA_OUT_STS_BS);
+               /* packet per buffer mode - rx bytes */
+               } else {
+                       /*
+                        * if BNA occurred then recover desc. from
+                        * BNA dummy desc.
+                        */
+                       if (ep->bna_occurred) {
+                               VDBG(dev, "Recover desc. from BNA dummy\n");
+                               memcpy(req->td_data, ep->bna_dummy_req->td_data,
+                                               sizeof(struct udc_data_dma));
+                               ep->bna_occurred = 0;
+                               udc_init_bna_dummy(ep->req);
+                       }
+                       td = udc_get_last_dma_desc(req);
+                       dma_done = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_BS);
+               }
+               if (dma_done == UDC_DMA_OUT_STS_BS_DMA_DONE) {
+                       /* buffer fill mode - rx bytes */
+                       if (!use_dma_ppb) {
+                               /* received number bytes */
+                               count = AMD_GETBITS(req->td_data->status,
+                                               UDC_DMA_OUT_STS_RXBYTES);
+                               VDBG(dev, "rx bytes=%u\n", count);
+                       /* packet per buffer mode - rx bytes */
+                       } else {
+                               VDBG(dev, "req->td_data=%p\n", req->td_data);
+                               VDBG(dev, "last desc = %p\n", td);
+                               /* received number bytes */
+                               if (use_dma_ppb_du) {
+                                       /* every desc. counts bytes */
+                                       count = udc_get_ppbdu_rxbytes(req);
+                               } else {
+                                       /* last desc. counts bytes */
+                                       count = AMD_GETBITS(td->status,
+                                               UDC_DMA_OUT_STS_RXBYTES);
+                                       if (!count && req->req.length
+                                               == UDC_DMA_MAXPACKET) {
+                                               /*
+                                                * on 64k packets the RXBYTES
+                                                * field is zero
+                                                */
+                                               count = UDC_DMA_MAXPACKET;
+                                       }
+                               }
+                               VDBG(dev, "last desc rx bytes=%u\n", count);
+                       }
+
+                       tmp = req->req.length - req->req.actual;
+                       if (count > tmp) {
+                               if ((tmp % ep->ep.maxpacket) != 0) {
+                                       DBG(dev, "%s: rx %db, space=%db\n",
+                                               ep->ep.name, count, tmp);
+                                       req->req.status = -EOVERFLOW;
+                               }
+                               count = tmp;
+                       }
+                       req->req.actual += count;
+                       req->dma_going = 0;
+                       /* complete request */
+                       complete_req(ep, req, 0);
+
+                       /* next request */
+                       if (!list_empty(&ep->queue) && !ep->halted) {
+                               req = list_entry(ep->queue.next,
+                                       struct udc_request,
+                                       queue);
+                               /*
+                                * DMA may be already started by udc_queue()
+                                * called by gadget drivers completion
+                                * routine. This happens when queue
+                                * holds one request only.
+                                */
+                               if (req->dma_going == 0) {
+                                       /* next dma */
+                                       if (prep_dma(ep, req, GFP_ATOMIC) != 0)
+                                               goto finished;
+                                       /* write desc pointer */
+                                       writel(req->td_phys,
+                                               &ep->regs->desptr);
+                                       req->dma_going = 1;
+                                       /* enable DMA */
+                                       udc_set_rde(dev);
+                               }
+                       } else {
+                               /*
+                                * implant BNA dummy descriptor to allow
+                                * RXFIFO opening by RDE
+                                */
+                               if (ep->bna_dummy_req) {
+                                       /* write desc pointer */
+                                       writel(ep->bna_dummy_req->td_phys,
+                                               &ep->regs->desptr);
+                                       ep->bna_occurred = 0;
+                               }
+
+                               /*
+                                * schedule timer for setting RDE if queue
+                                * remains empty to allow ep0 packets pass
+                                * through
+                                */
+                               if (set_rde != 0
+                                               && !timer_pending(&udc_timer)) {
+                                       udc_timer.expires =
+                                               jiffies
+                                               + HZ*UDC_RDE_TIMER_SECONDS;
+                                       set_rde = 1;
+                                       if (!stop_timer) {
+                                               add_timer(&udc_timer);
+                                       }
+                               }
+                               if (ep->num != UDC_EP0OUT_IX)
+                                       dev->data_ep_queued = 0;
+                       }
+
+               } else {
+                       /*
+                       * RX DMA must be reenabled for each desc in PPBDU mode
+                       * and must be enabled for PPBNDU mode in case of BNA
+                       */
+                       udc_set_rde(dev);
+               }
+
+       } else if (ep->cancel_transfer) {
+               ret_val = IRQ_HANDLED;
+               ep->cancel_transfer = 0;
+       }
+
+       /* check pending CNAKS */
+       if (cnak_pending) {
+               /* CNAk processing when rxfifo empty only */
+               if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {
+                       udc_process_cnak_queue(dev);
+               }
+       }
+
+       /* clear OUT bits in ep status */
+       writel(UDC_EPSTS_OUT_CLEAR, &ep->regs->sts);
+finished:
+       return ret_val;
+}
+
+/* Interrupt handler for data IN traffic */
+static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
+{
+       irqreturn_t ret_val = IRQ_NONE;
+       u32 tmp;
+       u32 epsts;
+       struct udc_ep *ep;
+       struct udc_request *req;
+       struct udc_data_dma *td;
+       unsigned dma_done;
+       unsigned len;
+
+       ep = &dev->ep[ep_ix];
+
+       epsts = readl(&ep->regs->sts);
+       if (use_dma) {
+               /* BNA ? */
+               if (epsts & AMD_BIT(UDC_EPSTS_BNA)) {
+                       dev_err(&dev->pdev->dev,
+                               "BNA ep%din occured - DESPTR = %08lx \n",
+                               ep->num,
+                               (unsigned long) readl(&ep->regs->desptr));
+
+                       /* clear BNA */
+                       writel(epsts, &ep->regs->sts);
+                       ret_val = IRQ_HANDLED;
+                       goto finished;
+               }
+       }
+       /* HE event ? */
+       if (epsts & AMD_BIT(UDC_EPSTS_HE)) {
+               dev_err(&dev->pdev->dev,
+                       "HE ep%dn occured - DESPTR = %08lx \n",
+                       ep->num, (unsigned long) readl(&ep->regs->desptr));
+
+               /* clear HE */
+               writel(epsts | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts);
+               ret_val = IRQ_HANDLED;
+               goto finished;
+       }
+
+       /* DMA completion */
+       if (epsts & AMD_BIT(UDC_EPSTS_TDC)) {
+               VDBG(dev, "TDC set- completion\n");
+               ret_val = IRQ_HANDLED;
+               if (!ep->cancel_transfer && !list_empty(&ep->queue)) {
+                       req = list_entry(ep->queue.next,
+                                       struct udc_request, queue);
+                       if (req) {
+                               /*
+                                * length bytes transfered
+                                * check dma done of last desc. in PPBDU mode
+                                */
+                               if (use_dma_ppb_du) {
+                                       td = udc_get_last_dma_desc(req);
+                                       if (td) {
+                                               dma_done =
+                                                       AMD_GETBITS(td->status,
+                                                       UDC_DMA_IN_STS_BS);
+                                               /* don't care DMA done */
+                                               req->req.actual =
+                                                       req->req.length;
+                                       }
+                               } else {
+                                       /* assume all bytes transferred */
+                                       req->req.actual = req->req.length;
+                               }
+
+                               if (req->req.actual == req->req.length) {
+                                       /* complete req */
+                                       complete_req(ep, req, 0);
+                                       req->dma_going = 0;
+                                       /* further request available ? */
+                                       if (list_empty(&ep->queue)) {
+                                               /* disable interrupt */
+                                               tmp = readl(
+                                                       &dev->regs->ep_irqmsk);
+                                               tmp |= AMD_BIT(ep->num);
+                                               writel(tmp,
+                                                       &dev->regs->ep_irqmsk);
+                                       }
+
+                               }
+                       }
+               }
+               ep->cancel_transfer = 0;
+
+       }
+       /*
+        * status reg has IN bit set and TDC not set (if TDC was handled,
+        * IN must not be handled (UDC defect) ?
+        */
+       if ((epsts & AMD_BIT(UDC_EPSTS_IN))
+                       && !(epsts & AMD_BIT(UDC_EPSTS_TDC))) {
+               ret_val = IRQ_HANDLED;
+               if (!list_empty(&ep->queue)) {
+                       /* next request */
+                       req = list_entry(ep->queue.next,
+                                       struct udc_request, queue);
+                       /* FIFO mode */
+                       if (!use_dma) {
+                               /* write fifo */
+                               udc_txfifo_write(ep, &req->req);
+                               len = req->req.length - req->req.actual;
+                                               if (len > ep->ep.maxpacket)
+                                                       len = ep->ep.maxpacket;
+                                               req->req.actual += len;
+                               if (req->req.actual == req->req.length
+                                       || (len != ep->ep.maxpacket)) {
+                                       /* complete req */
+                                       complete_req(ep, req, 0);
+                               }
+                       /* DMA */
+                       } else if (req && !req->dma_going) {
+                               VDBG(dev, "IN DMA : req=%p req->td_data=%p\n",
+                                       req, req->td_data);
+                               if (req->td_data) {
+
+                                       req->dma_going = 1;
+
+                                       /*
+                                        * unset L bit of first desc.
+                                        * for chain
+                                        */
+                                       if (use_dma_ppb && req->req.length >
+                                                       ep->ep.maxpacket) {
+                                               req->td_data->status &=
+                                                       AMD_CLEAR_BIT(
+                                                       UDC_DMA_IN_STS_L);
+                                       }
+
+                                       /* write desc pointer */
+                                       writel(req->td_phys, &ep->regs->desptr);
+
+                                       /* set HOST READY */
+                                       req->td_data->status =
+                                               AMD_ADDBITS(
+                                               req->td_data->status,
+                                               UDC_DMA_IN_STS_BS_HOST_READY,
+                                               UDC_DMA_IN_STS_BS);
+
+                                       /* set poll demand bit */
+                                       tmp = readl(&ep->regs->ctl);
+                                       tmp |= AMD_BIT(UDC_EPCTL_P);
+                                       writel(tmp, &ep->regs->ctl);
+                               }
+                       }
+
+               }
+       }
+       /* clear status bits */
+       writel(epsts, &ep->regs->sts);
+
+finished:
+       return ret_val;
+
+}
+
+/* Interrupt handler for Control OUT traffic */
+static irqreturn_t udc_control_out_isr(struct udc *dev)
+__releases(dev->lock)
+__acquires(dev->lock)
+{
+       irqreturn_t ret_val = IRQ_NONE;
+       u32 tmp;
+       int setup_supported;
+       u32 count;
+       int set = 0;
+       struct udc_ep   *ep;
+       struct udc_ep   *ep_tmp;
+
+       ep = &dev->ep[UDC_EP0OUT_IX];
+
+       /* clear irq */
+       writel(AMD_BIT(UDC_EPINT_OUT_EP0), &dev->regs->ep_irqsts);
+
+       tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->sts);
+       /* check BNA and clear if set */
+       if (tmp & AMD_BIT(UDC_EPSTS_BNA)) {
+               VDBG(dev, "ep0: BNA set\n");
+               writel(AMD_BIT(UDC_EPSTS_BNA),
+                       &dev->ep[UDC_EP0OUT_IX].regs->sts);
+               ep->bna_occurred = 1;
+               ret_val = IRQ_HANDLED;
+               goto finished;
+       }
+
+       /* type of data: SETUP or DATA 0 bytes */
+       tmp = AMD_GETBITS(tmp, UDC_EPSTS_OUT);
+       VDBG(dev, "data_typ = %x\n", tmp);
+
+       /* setup data */
+       if (tmp == UDC_EPSTS_OUT_SETUP) {
+               ret_val = IRQ_HANDLED;
+
+               ep->dev->stall_ep0in = 0;
+               dev->waiting_zlp_ack_ep0in = 0;
+
+               /* set NAK for EP0_IN */
+               tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
+               tmp |= AMD_BIT(UDC_EPCTL_SNAK);
+               writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
+               dev->ep[UDC_EP0IN_IX].naking = 1;
+               /* get setup data */
+               if (use_dma) {
+
+                       /* clear OUT bits in ep status */
+                       writel(UDC_EPSTS_OUT_CLEAR,
+                               &dev->ep[UDC_EP0OUT_IX].regs->sts);
+
+                       setup_data.data[0] =
+                               dev->ep[UDC_EP0OUT_IX].td_stp->data12;
+                       setup_data.data[1] =
+                               dev->ep[UDC_EP0OUT_IX].td_stp->data34;
+                       /* set HOST READY */
+                       dev->ep[UDC_EP0OUT_IX].td_stp->status =
+                                       UDC_DMA_STP_STS_BS_HOST_READY;
+               } else {
+                       /* read fifo */
+                       udc_rxfifo_read_dwords(dev, setup_data.data, 2);
+               }
+
+               /* determine direction of control data */
+               if ((setup_data.request.bRequestType & USB_DIR_IN) != 0) {
+                       dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IX].ep;
+                       /* enable RDE */
+                       udc_ep0_set_rde(dev);
+                       set = 0;
+               } else {
+                       dev->gadget.ep0 = &dev->ep[UDC_EP0OUT_IX].ep;
+                       /*
+                        * implant BNA dummy descriptor to allow RXFIFO opening
+                        * by RDE
+                        */
+                       if (ep->bna_dummy_req) {
+                               /* write desc pointer */
+                               writel(ep->bna_dummy_req->td_phys,
+                                       &dev->ep[UDC_EP0OUT_IX].regs->desptr);
+                               ep->bna_occurred = 0;
+                       }
+
+                       set = 1;
+                       dev->ep[UDC_EP0OUT_IX].naking = 1;
+                       /*
+                        * setup timer for enabling RDE (to not enable
+                        * RXFIFO DMA for data to early)
+                        */
+                       set_rde = 1;
+                       if (!timer_pending(&udc_timer)) {
+                               udc_timer.expires = jiffies +
+                                                       HZ/UDC_RDE_TIMER_DIV;
+                               if (!stop_timer) {
+                                       add_timer(&udc_timer);
+                               }
+                       }
+               }
+
+               /*
+                * mass storage reset must be processed here because
+                * next packet may be a CLEAR_FEATURE HALT which would not
+                * clear the stall bit when no STALL handshake was received
+                * before (autostall can cause this)
+                */
+               if (setup_data.data[0] == UDC_MSCRES_DWORD0
+                               && setup_data.data[1] == UDC_MSCRES_DWORD1) {
+                       DBG(dev, "MSC Reset\n");
+                       /*
+                        * clear stall bits
+                        * only one IN and OUT endpoints are handled
+                        */
+                       ep_tmp = &udc->ep[UDC_EPIN_IX];
+                       udc_set_halt(&ep_tmp->ep, 0);
+                       ep_tmp = &udc->ep[UDC_EPOUT_IX];
+                       udc_set_halt(&ep_tmp->ep, 0);
+               }
+
+               /* call gadget with setup data received */
+               spin_unlock(&dev->lock);
+               setup_supported = dev->driver->setup(&dev->gadget,
+                                               &setup_data.request);
+               spin_lock(&dev->lock);
+
+               tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
+               /* ep0 in returns data (not zlp) on IN phase */
+               if (setup_supported >= 0 && setup_supported <
+                               UDC_EP0IN_MAXPACKET) {
+                       /* clear NAK by writing CNAK in EP0_IN */
+                       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+                       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
+                       dev->ep[UDC_EP0IN_IX].naking = 0;
+                       UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX);
+
+               /* if unsupported request then stall */
+               } else if (setup_supported < 0) {
+                       tmp |= AMD_BIT(UDC_EPCTL_S);
+                       writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);
+               } else
+                       dev->waiting_zlp_ack_ep0in = 1;
+
+
+               /* clear NAK by writing CNAK in EP0_OUT */
+               if (!set) {
+                       tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);
+                       tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+                       writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl);
+                       dev->ep[UDC_EP0OUT_IX].naking = 0;
+                       UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX);
+               }
+
+               if (!use_dma) {
+                       /* clear OUT bits in ep status */
+                       writel(UDC_EPSTS_OUT_CLEAR,
+                               &dev->ep[UDC_EP0OUT_IX].regs->sts);
+               }
+
+       /* data packet 0 bytes */
+       } else if (tmp == UDC_EPSTS_OUT_DATA) {
+               /* clear OUT bits in ep status */
+               writel(UDC_EPSTS_OUT_CLEAR, &dev->ep[UDC_EP0OUT_IX].regs->sts);
+
+               /* get setup data: only 0 packet */
+               if (use_dma) {
+                       /* no req if 0 packet, just reactivate */
+                       if (list_empty(&dev->ep[UDC_EP0OUT_IX].queue)) {
+                               VDBG(dev, "ZLP\n");
+
+                               /* set HOST READY */
+                               dev->ep[UDC_EP0OUT_IX].td->status =
+                                       AMD_ADDBITS(
+                                       dev->ep[UDC_EP0OUT_IX].td->status,
+                                       UDC_DMA_OUT_STS_BS_HOST_READY,
+                                       UDC_DMA_OUT_STS_BS);
+                               /* enable RDE */
+                               udc_ep0_set_rde(dev);
+                               ret_val = IRQ_HANDLED;
+
+                       } else {
+                               /* control write */
+                               ret_val |= udc_data_out_isr(dev, UDC_EP0OUT_IX);
+                               /* re-program desc. pointer for possible ZLPs */
+                               writel(dev->ep[UDC_EP0OUT_IX].td_phys,
+                                       &dev->ep[UDC_EP0OUT_IX].regs->desptr);
+                               /* enable RDE */
+                               udc_ep0_set_rde(dev);
+                       }
+               } else {
+
+                       /* received number bytes */
+                       count = readl(&dev->ep[UDC_EP0OUT_IX].regs->sts);
+                       count = AMD_GETBITS(count, UDC_EPSTS_RX_PKT_SIZE);
+                       /* out data for fifo mode not working */
+                       count = 0;
+
+                       /* 0 packet or real data ? */
+                       if (count != 0) {
+                               ret_val |= udc_data_out_isr(dev, UDC_EP0OUT_IX);
+                       } else {
+                               /* dummy read confirm */
+                               readl(&dev->ep[UDC_EP0OUT_IX].regs->confirm);
+                               ret_val = IRQ_HANDLED;
+                       }
+               }
+       }
+
+       /* check pending CNAKS */
+       if (cnak_pending) {
+               /* CNAk processing when rxfifo empty only */
+               if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {
+                       udc_process_cnak_queue(dev);
+               }
+       }
+
+finished:
+       return ret_val;
+}
+
+/* Interrupt handler for Control IN traffic */
+static irqreturn_t udc_control_in_isr(struct udc *dev)
+{
+       irqreturn_t ret_val = IRQ_NONE;
+       u32 tmp;
+       struct udc_ep *ep;
+       struct udc_request *req;
+       unsigned len;
+
+       ep = &dev->ep[UDC_EP0IN_IX];
+
+       /* clear irq */
+       writel(AMD_BIT(UDC_EPINT_IN_EP0), &dev->regs->ep_irqsts);
+
+       tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->sts);
+       /* DMA completion */
+       if (tmp & AMD_BIT(UDC_EPSTS_TDC)) {
+               VDBG(dev, "isr: TDC clear \n");
+               ret_val = IRQ_HANDLED;
+
+               /* clear TDC bit */
+               writel(AMD_BIT(UDC_EPSTS_TDC),
+                               &dev->ep[UDC_EP0IN_IX].regs->sts);
+
+       /* status reg has IN bit set ? */
+       } else if (tmp & AMD_BIT(UDC_EPSTS_IN)) {
+               ret_val = IRQ_HANDLED;
+
+               if (ep->dma) {
+                       /* clear IN bit */
+                       writel(AMD_BIT(UDC_EPSTS_IN),
+                               &dev->ep[UDC_EP0IN_IX].regs->sts);
+               }
+               if (dev->stall_ep0in) {
+                       DBG(dev, "stall ep0in\n");
+                       /* halt ep0in */
+                       tmp = readl(&ep->regs->ctl);
+                       tmp |= AMD_BIT(UDC_EPCTL_S);
+                       writel(tmp, &ep->regs->ctl);
+               } else {
+                       if (!list_empty(&ep->queue)) {
+                               /* next request */
+                               req = list_entry(ep->queue.next,
+                                               struct udc_request, queue);
+
+                               if (ep->dma) {
+                                       /* write desc pointer */
+                                       writel(req->td_phys, &ep->regs->desptr);
+                                       /* set HOST READY */
+                                       req->td_data->status =
+                                               AMD_ADDBITS(
+                                               req->td_data->status,
+                                               UDC_DMA_STP_STS_BS_HOST_READY,
+                                               UDC_DMA_STP_STS_BS);
+
+                                       /* set poll demand bit */
+                                       tmp =
+                                       readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);
+                                       tmp |= AMD_BIT(UDC_EPCTL_P);
+                                       writel(tmp,
+                                       &dev->ep[UDC_EP0IN_IX].regs->ctl);
+
+                                       /* all bytes will be transferred */
+                                       req->req.actual = req->req.length;
+
+                                       /* complete req */
+                                       complete_req(ep, req, 0);
+
+                               } else {
+                                       /* write fifo */
+                                       udc_txfifo_write(ep, &req->req);
+
+                                       /* lengh bytes transfered */
+                                       len = req->req.length - req->req.actual;
+                                       if (len > ep->ep.maxpacket)
+                                               len = ep->ep.maxpacket;
+
+                                       req->req.actual += len;
+                                       if (req->req.actual == req->req.length
+                                               || (len != ep->ep.maxpacket)) {
+                                               /* complete req */
+                                               complete_req(ep, req, 0);
+                                       }
+                               }
+
+                       }
+               }
+               ep->halted = 0;
+               dev->stall_ep0in = 0;
+               if (!ep->dma) {
+                       /* clear IN bit */
+                       writel(AMD_BIT(UDC_EPSTS_IN),
+                               &dev->ep[UDC_EP0IN_IX].regs->sts);
+               }
+       }
+
+       return ret_val;
+}
+
+
+/* Interrupt handler for global device events */
+static irqreturn_t udc_dev_isr(struct udc *dev, u32 dev_irq)
+__releases(dev->lock)
+__acquires(dev->lock)
+{
+       irqreturn_t ret_val = IRQ_NONE;
+       u32 tmp;
+       u32 cfg;
+       struct udc_ep *ep;
+       u16 i;
+       u8 udc_csr_epix;
+
+       /* SET_CONFIG irq ? */
+       if (dev_irq & AMD_BIT(UDC_DEVINT_SC)) {
+               ret_val = IRQ_HANDLED;
+
+               /* read config value */
+               tmp = readl(&dev->regs->sts);
+               cfg = AMD_GETBITS(tmp, UDC_DEVSTS_CFG);
+               DBG(dev, "SET_CONFIG interrupt: config=%d\n", cfg);
+               dev->cur_config = cfg;
+               dev->set_cfg_not_acked = 1;
+
+               /* make usb request for gadget driver */
+               memset(&setup_data, 0 , sizeof(union udc_setup_data));
+               setup_data.request.bRequest = USB_REQ_SET_CONFIGURATION;
+               setup_data.request.wValue = dev->cur_config;
+
+               /* programm the NE registers */
+               for (i = 0; i < UDC_EP_NUM; i++) {
+                       ep = &dev->ep[i];
+                       if (ep->in) {
+
+                               /* ep ix in UDC CSR register space */
+                               udc_csr_epix = ep->num;
+
+
+                       /* OUT ep */
+                       } else {
+                               /* ep ix in UDC CSR register space */
+                               udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS;
+                       }
+
+                       tmp = readl(&dev->csr->ne[udc_csr_epix]);
+                       /* ep cfg */
+                       tmp = AMD_ADDBITS(tmp, ep->dev->cur_config,
+                                               UDC_CSR_NE_CFG);
+                       /* write reg */
+                       writel(tmp, &dev->csr->ne[udc_csr_epix]);
+
+                       /* clear stall bits */
+                       ep->halted = 0;
+                       tmp = readl(&ep->regs->ctl);
+                       tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S);
+                       writel(tmp, &ep->regs->ctl);
+               }
+               /* call gadget zero with setup data received */
+               spin_unlock(&dev->lock);
+               tmp = dev->driver->setup(&dev->gadget, &setup_data.request);
+               spin_lock(&dev->lock);
+
+       } /* SET_INTERFACE ? */
+       if (dev_irq & AMD_BIT(UDC_DEVINT_SI)) {
+               ret_val = IRQ_HANDLED;
+
+               dev->set_cfg_not_acked = 1;
+               /* read interface and alt setting values */
+               tmp = readl(&dev->regs->sts);
+               dev->cur_alt = AMD_GETBITS(tmp, UDC_DEVSTS_ALT);
+               dev->cur_intf = AMD_GETBITS(tmp, UDC_DEVSTS_INTF);
+
+               /* make usb request for gadget driver */
+               memset(&setup_data, 0 , sizeof(union udc_setup_data));
+               setup_data.request.bRequest = USB_REQ_SET_INTERFACE;
+               setup_data.request.bRequestType = USB_RECIP_INTERFACE;
+               setup_data.request.wValue = dev->cur_alt;
+               setup_data.request.wIndex = dev->cur_intf;
+
+               DBG(dev, "SET_INTERFACE interrupt: alt=%d intf=%d\n",
+                               dev->cur_alt, dev->cur_intf);
+
+               /* programm the NE registers */
+               for (i = 0; i < UDC_EP_NUM; i++) {
+                       ep = &dev->ep[i];
+                       if (ep->in) {
+
+                               /* ep ix in UDC CSR register space */
+                               udc_csr_epix = ep->num;
+
+
+                       /* OUT ep */
+                       } else {
+                               /* ep ix in UDC CSR register space */
+                               udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS;
+                       }
+
+                       /* UDC CSR reg */
+                       /* set ep values */
+                       tmp = readl(&dev->csr->ne[udc_csr_epix]);
+                       /* ep interface */
+                       tmp = AMD_ADDBITS(tmp, ep->dev->cur_intf,
+                                               UDC_CSR_NE_INTF);
+                       /* tmp = AMD_ADDBITS(tmp, 2, UDC_CSR_NE_INTF); */
+                       /* ep alt */
+                       tmp = AMD_ADDBITS(tmp, ep->dev->cur_alt,
+                                               UDC_CSR_NE_ALT);
+                       /* write reg */
+                       writel(tmp, &dev->csr->ne[udc_csr_epix]);
+
+                       /* clear stall bits */
+                       ep->halted = 0;
+                       tmp = readl(&ep->regs->ctl);
+                       tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S);
+                       writel(tmp, &ep->regs->ctl);
+               }
+
+               /* call gadget zero with setup data received */
+               spin_unlock(&dev->lock);
+               tmp = dev->driver->setup(&dev->gadget, &setup_data.request);
+               spin_lock(&dev->lock);
+
+       } /* USB reset */
+       if (dev_irq & AMD_BIT(UDC_DEVINT_UR)) {
+               DBG(dev, "USB Reset interrupt\n");
+               ret_val = IRQ_HANDLED;
+
+               /* allow soft reset when suspend occurs */
+               soft_reset_occured = 0;
+
+               dev->waiting_zlp_ack_ep0in = 0;
+               dev->set_cfg_not_acked = 0;
+
+               /* mask not needed interrupts */
+               udc_mask_unused_interrupts(dev);
+
+               /* call gadget to resume and reset configs etc. */
+               spin_unlock(&dev->lock);
+               if (dev->sys_suspended && dev->driver->resume) {
+                       dev->driver->resume(&dev->gadget);
+                       dev->sys_suspended = 0;
+               }
+               dev->driver->disconnect(&dev->gadget);
+               spin_lock(&dev->lock);
+
+               /* disable ep0 to empty req queue */
+               empty_req_queue(&dev->ep[UDC_EP0IN_IX]);
+               ep_init(dev->regs, &dev->ep[UDC_EP0IN_IX]);
+
+               /* soft reset when rxfifo not empty */
+               tmp = readl(&dev->regs->sts);
+               if (!(tmp & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY))
+                               && !soft_reset_after_usbreset_occured) {
+                       udc_soft_reset(dev);
+                       soft_reset_after_usbreset_occured++;
+               }
+
+               /*
+                * DMA reset to kill potential old DMA hw hang,
+                * POLL bit is already reset by ep_init() through
+                * disconnect()
+                */
+               DBG(dev, "DMA machine reset\n");
+               tmp = readl(&dev->regs->cfg);
+               writel(tmp | AMD_BIT(UDC_DEVCFG_DMARST), &dev->regs->cfg);
+               writel(tmp, &dev->regs->cfg);
+
+               /* put into initial config */
+               udc_basic_init(dev);
+
+               /* enable device setup interrupts */
+               udc_enable_dev_setup_interrupts(dev);
+
+               /* enable suspend interrupt */
+               tmp = readl(&dev->regs->irqmsk);
+               tmp &= AMD_UNMASK_BIT(UDC_DEVINT_US);
+               writel(tmp, &dev->regs->irqmsk);
+
+       } /* USB suspend */
+       if (dev_irq & AMD_BIT(UDC_DEVINT_US)) {
+               DBG(dev, "USB Suspend interrupt\n");
+               ret_val = IRQ_HANDLED;
+               if (dev->driver->suspend) {
+                       spin_unlock(&dev->lock);
+                       dev->sys_suspended = 1;
+                       dev->driver->suspend(&dev->gadget);
+                       spin_lock(&dev->lock);
+               }
+       } /* new speed ? */
+       if (dev_irq & AMD_BIT(UDC_DEVINT_ENUM)) {
+               DBG(dev, "ENUM interrupt\n");
+               ret_val = IRQ_HANDLED;
+               soft_reset_after_usbreset_occured = 0;
+
+               /* disable ep0 to empty req queue */
+               empty_req_queue(&dev->ep[UDC_EP0IN_IX]);
+               ep_init(dev->regs, &dev->ep[UDC_EP0IN_IX]);
+
+               /* link up all endpoints */
+               udc_setup_endpoints(dev);
+               if (dev->gadget.speed == USB_SPEED_HIGH) {
+                       dev_info(&dev->pdev->dev, "Connect: speed = %s\n",
+                               "high");
+               } else if (dev->gadget.speed == USB_SPEED_FULL) {
+                       dev_info(&dev->pdev->dev, "Connect: speed = %s\n",
+                               "full");
+               }
+
+               /* init ep 0 */
+               activate_control_endpoints(dev);
+
+               /* enable ep0 interrupts */
+               udc_enable_ep0_interrupts(dev);
+       }
+       /* session valid change interrupt */
+       if (dev_irq & AMD_BIT(UDC_DEVINT_SVC)) {
+               DBG(dev, "USB SVC interrupt\n");
+               ret_val = IRQ_HANDLED;
+
+               /* check that session is not valid to detect disconnect */
+               tmp = readl(&dev->regs->sts);
+               if (!(tmp & AMD_BIT(UDC_DEVSTS_SESSVLD))) {
+                       /* disable suspend interrupt */
+                       tmp = readl(&dev->regs->irqmsk);
+                       tmp |= AMD_BIT(UDC_DEVINT_US);
+                       writel(tmp, &dev->regs->irqmsk);
+                       DBG(dev, "USB Disconnect (session valid low)\n");
+                       /* cleanup on disconnect */
+                       usb_disconnect(udc);
+               }
+
+       }
+
+       return ret_val;
+}
+
+/* Interrupt Service Routine, see Linux Kernel Doc for parameters */
+static irqreturn_t udc_irq(int irq, void *pdev)
+{
+       struct udc *dev = pdev;
+       u32 reg;
+       u16 i;
+       u32 ep_irq;
+       irqreturn_t ret_val = IRQ_NONE;
+
+       spin_lock(&dev->lock);
+
+       /* check for ep irq */
+       reg = readl(&dev->regs->ep_irqsts);
+       if (reg) {
+               if (reg & AMD_BIT(UDC_EPINT_OUT_EP0))
+                       ret_val |= udc_control_out_isr(dev);
+               if (reg & AMD_BIT(UDC_EPINT_IN_EP0))
+                       ret_val |= udc_control_in_isr(dev);
+
+               /*
+                * data endpoint
+                * iterate ep's
+                */
+               for (i = 1; i < UDC_EP_NUM; i++) {
+                       ep_irq = 1 << i;
+                       if (!(reg & ep_irq) || i == UDC_EPINT_OUT_EP0)
+                               continue;
+
+                       /* clear irq status */
+                       writel(ep_irq, &dev->regs->ep_irqsts);
+
+                       /* irq for out ep ? */
+                       if (i > UDC_EPIN_NUM)
+                               ret_val |= udc_data_out_isr(dev, i);
+                       else
+                               ret_val |= udc_data_in_isr(dev, i);
+               }
+
+       }
+
+
+       /* check for dev irq */
+       reg = readl(&dev->regs->irqsts);
+       if (reg) {
+               /* clear irq */
+               writel(reg, &dev->regs->irqsts);
+               ret_val |= udc_dev_isr(dev, reg);
+       }
+
+
+       spin_unlock(&dev->lock);
+       return ret_val;
+}
+
+/* Tears down device */
+static void gadget_release(struct device *pdev)
+{
+       struct amd5536udc *dev = dev_get_drvdata(pdev);
+       kfree(dev);
+}
+
+/* Cleanup on device remove */
+static void udc_remove(struct udc *dev)
+{
+       /* remove timer */
+       stop_timer++;
+       if (timer_pending(&udc_timer))
+               wait_for_completion(&on_exit);
+       if (udc_timer.data)
+               del_timer_sync(&udc_timer);
+       /* remove pollstall timer */
+       stop_pollstall_timer++;
+       if (timer_pending(&udc_pollstall_timer))
+               wait_for_completion(&on_pollstall_exit);
+       if (udc_pollstall_timer.data)
+               del_timer_sync(&udc_pollstall_timer);
+       udc = NULL;
+}
+
+/* Reset all pci context */
+static void udc_pci_remove(struct pci_dev *pdev)
+{
+       struct udc              *dev;
+
+       dev = pci_get_drvdata(pdev);
+
+       /* gadget driver must not be registered */
+       BUG_ON(dev->driver != NULL);
+
+       /* dma pool cleanup */
+       if (dev->data_requests)
+               pci_pool_destroy(dev->data_requests);
+
+       if (dev->stp_requests) {
+               /* cleanup DMA desc's for ep0in */
+               pci_pool_free(dev->stp_requests,
+                       dev->ep[UDC_EP0OUT_IX].td_stp,
+                       dev->ep[UDC_EP0OUT_IX].td_stp_dma);
+               pci_pool_free(dev->stp_requests,
+                       dev->ep[UDC_EP0OUT_IX].td,
+                       dev->ep[UDC_EP0OUT_IX].td_phys);
+
+               pci_pool_destroy(dev->stp_requests);
+       }
+
+       /* reset controller */
+       writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
+       if (dev->irq_registered)
+               free_irq(pdev->irq, dev);
+       if (dev->regs)
+               iounmap(dev->regs);
+       if (dev->mem_region)
+               release_mem_region(pci_resource_start(pdev, 0),
+                               pci_resource_len(pdev, 0));
+       if (dev->active)
+               pci_disable_device(pdev);
+
+       device_unregister(&dev->gadget.dev);
+       pci_set_drvdata(pdev, NULL);
+
+       udc_remove(dev);
+}
+
+/* create dma pools on init */
+static int init_dma_pools(struct udc *dev)
+{
+       struct udc_stp_dma      *td_stp;
+       struct udc_data_dma     *td_data;
+       int retval;
+
+       /* consistent DMA mode setting ? */
+       if (use_dma_ppb) {
+               use_dma_bufferfill_mode = 0;
+       } else {
+               use_dma_ppb_du = 0;
+               use_dma_bufferfill_mode = 1;
+       }
+
+       /* DMA setup */
+       dev->data_requests = dma_pool_create("data_requests", NULL,
+               sizeof(struct udc_data_dma), 0, 0);
+       if (!dev->data_requests) {
+               DBG(dev, "can't get request data pool\n");
+               retval = -ENOMEM;
+               goto finished;
+       }
+
+       /* EP0 in dma regs = dev control regs */
+       dev->ep[UDC_EP0IN_IX].dma = &dev->regs->ctl;
+
+       /* dma desc for setup data */
+       dev->stp_requests = dma_pool_create("setup requests", NULL,
+               sizeof(struct udc_stp_dma), 0, 0);
+       if (!dev->stp_requests) {
+               DBG(dev, "can't get stp request pool\n");
+               retval = -ENOMEM;
+               goto finished;
+       }
+       /* setup */
+       td_stp = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
+                               &dev->ep[UDC_EP0OUT_IX].td_stp_dma);
+       if (td_stp == NULL) {
+               retval = -ENOMEM;
+               goto finished;
+       }
+       dev->ep[UDC_EP0OUT_IX].td_stp = td_stp;
+
+       /* data: 0 packets !? */
+       td_data = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
+                               &dev->ep[UDC_EP0OUT_IX].td_phys);
+       if (td_data == NULL) {
+               retval = -ENOMEM;
+               goto finished;
+       }
+       dev->ep[UDC_EP0OUT_IX].td = td_data;
+       return 0;
+
+finished:
+       return retval;
+}
+
+/* Called by pci bus driver to init pci context */
+static int udc_pci_probe(
+       struct pci_dev *pdev,
+       const struct pci_device_id *id
+)
+{
+       struct udc              *dev;
+       unsigned long           resource;
+       unsigned long           len;
+       int                     retval = 0;
+
+       /* one udc only */
+       if (udc) {
+               dev_dbg(&pdev->dev, "already probed\n");
+               return -EBUSY;
+       }
+
+       /* init */
+       dev = kzalloc(sizeof(struct udc), GFP_KERNEL);
+       if (!dev) {
+               retval = -ENOMEM;
+               goto finished;
+       }
+       memset(dev, 0, sizeof(struct udc));
+
+       /* pci setup */
+       if (pci_enable_device(pdev) < 0) {
+               retval = -ENODEV;
+               goto finished;
+       }
+       dev->active = 1;
+
+       /* PCI resource allocation */
+       resource = pci_resource_start(pdev, 0);
+       len = pci_resource_len(pdev, 0);
+
+       if (!request_mem_region(resource, len, name)) {
+               dev_dbg(&pdev->dev, "pci device used already\n");
+               retval = -EBUSY;
+               goto finished;
+       }
+       dev->mem_region = 1;
+
+       dev->virt_addr = ioremap_nocache(resource, len);
+       if (dev->virt_addr == NULL) {
+               dev_dbg(&pdev->dev, "start address cannot be mapped\n");
+               retval = -EFAULT;
+               goto finished;
+       }
+
+       if (!pdev->irq) {
+               dev_err(&dev->pdev->dev, "irq not set\n");
+               retval = -ENODEV;
+               goto finished;
+       }
+
+       if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
+               dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq);
+               retval = -EBUSY;
+               goto finished;
+       }
+       dev->irq_registered = 1;
+
+       pci_set_drvdata(pdev, dev);
+
+       /* chip revision */
+       dev->chiprev = 0;
+
+       pci_set_master(pdev);
+       pci_set_mwi(pdev);
+
+       /* chip rev for Hs AMD5536 */
+       pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) &dev->chiprev);
+       /* init dma pools */
+       if (use_dma) {
+               retval = init_dma_pools(dev);
+               if (retval != 0)
+                       goto finished;
+       }
+
+       dev->phys_addr = resource;
+       dev->irq = pdev->irq;
+       dev->pdev = pdev;
+       dev->gadget.dev.parent = &pdev->dev;
+       dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
+
+       /* general probing */
+       if (udc_probe(dev) == 0)
+               return 0;
+
+finished:
+       if (dev)
+               udc_pci_remove(pdev);
+       return retval;
+}
+
+/* general probe */
+static int udc_probe(struct udc *dev)
+{
+       char            tmp[128];
+       u32             reg;
+       int             retval;
+
+       /* mark timer as not initialized */
+       udc_timer.data = 0;
+       udc_pollstall_timer.data = 0;
+
+       /* device struct setup */
+       spin_lock_init(&dev->lock);
+       dev->gadget.ops = &udc_ops;
+
+       strcpy(dev->gadget.dev.bus_id, "gadget");
+       dev->gadget.dev.release = gadget_release;
+       dev->gadget.name = name;
+       dev->gadget.name = name;
+       dev->gadget.is_dualspeed = 1;
+
+       /* udc csr registers base */
+       dev->csr = dev->virt_addr + UDC_CSR_ADDR;
+       /* dev registers base */
+       dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR;
+       /* ep registers base */
+       dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR;
+       /* fifo's base */
+       dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR);
+       dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR);
+
+       /* init registers, interrupts, ... */
+       startup_registers(dev);
+
+       dev_info(&dev->pdev->dev, "%s\n", mod_desc);
+
+       snprintf(tmp, sizeof tmp, "%d", dev->irq);
+       dev_info(&dev->pdev->dev,
+               "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
+               tmp, dev->phys_addr, dev->chiprev,
+               (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1");
+       strcpy(tmp, UDC_DRIVER_VERSION_STRING);
+       if (dev->chiprev == UDC_HSA0_REV) {
+               dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
+               retval = -ENODEV;
+               goto finished;
+       }
+       dev_info(&dev->pdev->dev,
+               "driver version: %s(for Geode5536 B1)\n", tmp);
+       udc = dev;
+
+       retval = device_register(&dev->gadget.dev);
+       if (retval)
+               goto finished;
+
+       /* timer init */
+       init_timer(&udc_timer);
+       udc_timer.function = udc_timer_function;
+       udc_timer.data = 1;
+       /* timer pollstall init */
+       init_timer(&udc_pollstall_timer);
+       udc_pollstall_timer.function = udc_pollstall_timer_function;
+       udc_pollstall_timer.data = 1;
+
+       /* set SD */
+       reg = readl(&dev->regs->ctl);
+       reg |= AMD_BIT(UDC_DEVCTL_SD);
+       writel(reg, &dev->regs->ctl);
+
+       /* print dev register info */
+       print_regs(dev);
+
+       return 0;
+
+finished:
+       return retval;
+}
+
+/* Initiates a remote wakeup */
+static int udc_remote_wakeup(struct udc *dev)
+{
+       unsigned long flags;
+       u32 tmp;
+
+       DBG(dev, "UDC initiates remote wakeup\n");
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       tmp = readl(&dev->regs->ctl);
+       tmp |= AMD_BIT(UDC_DEVCTL_RES);
+       writel(tmp, &dev->regs->ctl);
+       tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES);
+       writel(tmp, &dev->regs->ctl);
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+       return 0;
+}
+
+/* PCI device parameters */
+static const struct pci_device_id pci_id[] = {
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096),
+               .class =        (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class_mask =   0xffffffff,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(pci, pci_id);
+
+/* PCI functions */
+static struct pci_driver udc_pci_driver = {
+       .name =         (char *) name,
+       .id_table =     pci_id,
+       .probe =        udc_pci_probe,
+       .remove =       udc_pci_remove,
+};
+
+/* Inits driver */
+static int __init init(void)
+{
+       return pci_register_driver(&udc_pci_driver);
+}
+module_init(init);
+
+/* Cleans driver */
+static void __exit cleanup(void)
+{
+       pci_unregister_driver(&udc_pci_driver);
+}
+module_exit(cleanup);
+
+MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION);
+MODULE_AUTHOR("Thomas Dahlmann");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/amd5536udc.h
new file mode 100644 (file)
index 0000000..4bbabbb
--- /dev/null
@@ -0,0 +1,626 @@
+/*
+ * amd5536.h -- header for AMD 5536 UDC high/full speed USB device controller
+ *
+ * Copyright (C) 2007 AMD (http://www.amd.com)
+ * Author: Thomas Dahlmann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef AMD5536UDC_H
+#define AMD5536UDC_H
+
+/* various constants */
+#define UDC_RDE_TIMER_SECONDS          1
+#define UDC_RDE_TIMER_DIV              10
+#define UDC_POLLSTALL_TIMER_USECONDS   500
+
+/* Hs AMD5536 chip rev. */
+#define UDC_HSA0_REV 1
+#define UDC_HSB1_REV 2
+
+/*
+ * SETUP usb commands
+ * needed, because some SETUP's are handled in hw, but must be passed to
+ * gadget driver above
+ * SET_CONFIG
+ */
+#define UDC_SETCONFIG_DWORD0                   0x00000900
+#define UDC_SETCONFIG_DWORD0_VALUE_MASK                0xffff0000
+#define UDC_SETCONFIG_DWORD0_VALUE_OFS         16
+
+#define UDC_SETCONFIG_DWORD1                   0x00000000
+
+/* SET_INTERFACE */
+#define UDC_SETINTF_DWORD0                     0x00000b00
+#define UDC_SETINTF_DWORD0_ALT_MASK            0xffff0000
+#define UDC_SETINTF_DWORD0_ALT_OFS             16
+
+#define UDC_SETINTF_DWORD1                     0x00000000
+#define UDC_SETINTF_DWORD1_INTF_MASK           0x0000ffff
+#define UDC_SETINTF_DWORD1_INTF_OFS            0
+
+/* Mass storage reset */
+#define UDC_MSCRES_DWORD0                      0x0000ff21
+#define UDC_MSCRES_DWORD1                      0x00000000
+
+/* Global CSR's -------------------------------------------------------------*/
+#define UDC_CSR_ADDR                           0x500
+
+/* EP NE bits */
+/* EP number */
+#define UDC_CSR_NE_NUM_MASK                    0x0000000f
+#define UDC_CSR_NE_NUM_OFS                     0
+/* EP direction */
+#define UDC_CSR_NE_DIR_MASK                    0x00000010
+#define UDC_CSR_NE_DIR_OFS                     4
+/* EP type */
+#define UDC_CSR_NE_TYPE_MASK                   0x00000060
+#define UDC_CSR_NE_TYPE_OFS                    5
+/* EP config number */
+#define UDC_CSR_NE_CFG_MASK                    0x00000780
+#define UDC_CSR_NE_CFG_OFS                     7
+/* EP interface number */
+#define UDC_CSR_NE_INTF_MASK                   0x00007800
+#define UDC_CSR_NE_INTF_OFS                    11
+/* EP alt setting */
+#define UDC_CSR_NE_ALT_MASK                    0x00078000
+#define UDC_CSR_NE_ALT_OFS                     15
+
+/* max pkt */
+#define UDC_CSR_NE_MAX_PKT_MASK                        0x3ff80000
+#define UDC_CSR_NE_MAX_PKT_OFS                 19
+
+/* Device Config Register ---------------------------------------------------*/
+#define UDC_DEVCFG_ADDR                                0x400
+
+#define UDC_DEVCFG_SOFTRESET                   31
+#define UDC_DEVCFG_HNPSFEN                     30
+#define UDC_DEVCFG_DMARST                      29
+#define UDC_DEVCFG_SET_DESC                    18
+#define UDC_DEVCFG_CSR_PRG                     17
+#define UDC_DEVCFG_STATUS                      7
+#define UDC_DEVCFG_DIR                         6
+#define UDC_DEVCFG_PI                          5
+#define UDC_DEVCFG_SS                          4
+#define UDC_DEVCFG_SP                          3
+#define UDC_DEVCFG_RWKP                                2
+
+#define UDC_DEVCFG_SPD_MASK                    0x3
+#define UDC_DEVCFG_SPD_OFS                     0
+#define UDC_DEVCFG_SPD_HS                      0x0
+#define UDC_DEVCFG_SPD_FS                      0x1
+#define UDC_DEVCFG_SPD_LS                      0x2
+/*#define UDC_DEVCFG_SPD_FS                    0x3*/
+
+
+/* Device Control Register --------------------------------------------------*/
+#define UDC_DEVCTL_ADDR                                0x404
+
+#define UDC_DEVCTL_THLEN_MASK                  0xff000000
+#define UDC_DEVCTL_THLEN_OFS                   24
+
+#define UDC_DEVCTL_BRLEN_MASK                  0x00ff0000
+#define UDC_DEVCTL_BRLEN_OFS                   16
+
+#define UDC_DEVCTL_CSR_DONE                    13
+#define UDC_DEVCTL_DEVNAK                      12
+#define UDC_DEVCTL_SD                          10
+#define UDC_DEVCTL_MODE                                9
+#define UDC_DEVCTL_BREN                                8
+#define UDC_DEVCTL_THE                         7
+#define UDC_DEVCTL_BF                          6
+#define UDC_DEVCTL_BE                          5
+#define UDC_DEVCTL_DU                          4
+#define UDC_DEVCTL_TDE                         3
+#define UDC_DEVCTL_RDE                         2
+#define UDC_DEVCTL_RES                         0
+
+
+/* Device Status Register ---------------------------------------------------*/
+#define UDC_DEVSTS_ADDR                                0x408
+
+#define UDC_DEVSTS_TS_MASK                     0xfffc0000
+#define UDC_DEVSTS_TS_OFS                      18
+
+#define UDC_DEVSTS_SESSVLD                     17
+#define UDC_DEVSTS_PHY_ERROR                   16
+#define UDC_DEVSTS_RXFIFO_EMPTY                        15
+
+#define UDC_DEVSTS_ENUM_SPEED_MASK             0x00006000
+#define UDC_DEVSTS_ENUM_SPEED_OFS              13
+#define UDC_DEVSTS_ENUM_SPEED_FULL             1
+#define UDC_DEVSTS_ENUM_SPEED_HIGH             0
+
+#define UDC_DEVSTS_SUSP                                12
+
+#define UDC_DEVSTS_ALT_MASK                    0x00000f00
+#define UDC_DEVSTS_ALT_OFS                     8
+
+#define UDC_DEVSTS_INTF_MASK                   0x000000f0
+#define UDC_DEVSTS_INTF_OFS                    4
+
+#define UDC_DEVSTS_CFG_MASK                    0x0000000f
+#define UDC_DEVSTS_CFG_OFS                     0
+
+
+/* Device Interrupt Register ------------------------------------------------*/
+#define UDC_DEVINT_ADDR                                0x40c
+
+#define UDC_DEVINT_SVC                         7
+#define UDC_DEVINT_ENUM                                6
+#define UDC_DEVINT_SOF                         5
+#define UDC_DEVINT_US                          4
+#define UDC_DEVINT_UR                          3
+#define UDC_DEVINT_ES                          2
+#define UDC_DEVINT_SI                          1
+#define UDC_DEVINT_SC                          0
+
+/* Device Interrupt Mask Register -------------------------------------------*/
+#define UDC_DEVINT_MSK_ADDR                    0x410
+
+#define UDC_DEVINT_MSK                         0x7f
+
+/* Endpoint Interrupt Register ----------------------------------------------*/
+#define UDC_EPINT_ADDR                         0x414
+
+#define UDC_EPINT_OUT_MASK                     0xffff0000
+#define UDC_EPINT_OUT_OFS                      16
+#define UDC_EPINT_IN_MASK                      0x0000ffff
+#define UDC_EPINT_IN_OFS                       0
+
+#define UDC_EPINT_IN_EP0                       0
+#define UDC_EPINT_IN_EP1                       1
+#define UDC_EPINT_IN_EP2                       2
+#define UDC_EPINT_IN_EP3                       3
+#define UDC_EPINT_OUT_EP0                      16
+#define UDC_EPINT_OUT_EP1                      17
+#define UDC_EPINT_OUT_EP2                      18
+#define UDC_EPINT_OUT_EP3                      19
+
+#define UDC_EPINT_EP0_ENABLE_MSK               0x001e001e
+
+/* Endpoint Interrupt Mask Register -----------------------------------------*/
+#define UDC_EPINT_MSK_ADDR                     0x418
+
+#define UDC_EPINT_OUT_MSK_MASK                 0xffff0000
+#define UDC_EPINT_OUT_MSK_OFS                  16
+#define UDC_EPINT_IN_MSK_MASK                  0x0000ffff
+#define UDC_EPINT_IN_MSK_OFS                   0
+
+#define UDC_EPINT_MSK_DISABLE_ALL              0xffffffff
+/* mask non-EP0 endpoints */
+#define UDC_EPDATAINT_MSK_DISABLE              0xfffefffe
+/* mask all dev interrupts */
+#define UDC_DEV_MSK_DISABLE                    0x7f
+
+/* Endpoint-specific CSR's --------------------------------------------------*/
+#define UDC_EPREGS_ADDR                                0x0
+#define UDC_EPIN_REGS_ADDR                     0x0
+#define UDC_EPOUT_REGS_ADDR                    0x200
+
+#define UDC_EPCTL_ADDR                         0x0
+
+#define UDC_EPCTL_RRDY                         9
+#define UDC_EPCTL_CNAK                         8
+#define UDC_EPCTL_SNAK                         7
+#define UDC_EPCTL_NAK                          6
+
+#define UDC_EPCTL_ET_MASK                      0x00000030
+#define UDC_EPCTL_ET_OFS                       4
+#define UDC_EPCTL_ET_CONTROL                   0
+#define UDC_EPCTL_ET_ISO                       1
+#define UDC_EPCTL_ET_BULK                      2
+#define UDC_EPCTL_ET_INTERRUPT                 3
+
+#define UDC_EPCTL_P                            3
+#define UDC_EPCTL_SN                           2
+#define UDC_EPCTL_F                            1
+#define UDC_EPCTL_S                            0
+
+/* Endpoint Status Registers ------------------------------------------------*/
+#define UDC_EPSTS_ADDR                         0x4
+
+#define UDC_EPSTS_RX_PKT_SIZE_MASK             0x007ff800
+#define UDC_EPSTS_RX_PKT_SIZE_OFS              11
+
+#define UDC_EPSTS_TDC                          10
+#define UDC_EPSTS_HE                           9
+#define UDC_EPSTS_BNA                          7
+#define UDC_EPSTS_IN                           6
+
+#define UDC_EPSTS_OUT_MASK                     0x00000030
+#define UDC_EPSTS_OUT_OFS                      4
+#define UDC_EPSTS_OUT_DATA                     1
+#define UDC_EPSTS_OUT_DATA_CLEAR               0x10
+#define UDC_EPSTS_OUT_SETUP                    2
+#define UDC_EPSTS_OUT_SETUP_CLEAR              0x20
+#define UDC_EPSTS_OUT_CLEAR                    0x30
+
+/* Endpoint Buffer Size IN/ Receive Packet Frame Number OUT Registers ------*/
+#define UDC_EPIN_BUFF_SIZE_ADDR                        0x8
+#define UDC_EPOUT_FRAME_NUMBER_ADDR            0x8
+
+#define UDC_EPIN_BUFF_SIZE_MASK                        0x0000ffff
+#define UDC_EPIN_BUFF_SIZE_OFS                 0
+/* EP0in txfifo = 128 bytes*/
+#define UDC_EPIN0_BUFF_SIZE                    32
+/* EP0in fullspeed txfifo = 128 bytes*/
+#define UDC_FS_EPIN0_BUFF_SIZE                 32
+
+/* fifo size mult = fifo size / max packet */
+#define UDC_EPIN_BUFF_SIZE_MULT                        2
+
+/* EPin data fifo size = 1024 bytes DOUBLE BUFFERING */
+#define UDC_EPIN_BUFF_SIZE                     256
+/* EPin small INT data fifo size = 128 bytes */
+#define UDC_EPIN_SMALLINT_BUFF_SIZE            32
+
+/* EPin fullspeed data fifo size = 128 bytes DOUBLE BUFFERING */
+#define UDC_FS_EPIN_BUFF_SIZE                  32
+
+#define UDC_EPOUT_FRAME_NUMBER_MASK            0x0000ffff
+#define UDC_EPOUT_FRAME_NUMBER_OFS             0
+
+/* Endpoint Buffer Size OUT/Max Packet Size Registers -----------------------*/
+#define UDC_EPOUT_BUFF_SIZE_ADDR               0x0c
+#define UDC_EP_MAX_PKT_SIZE_ADDR               0x0c
+
+#define UDC_EPOUT_BUFF_SIZE_MASK               0xffff0000
+#define UDC_EPOUT_BUFF_SIZE_OFS                        16
+#define UDC_EP_MAX_PKT_SIZE_MASK               0x0000ffff
+#define UDC_EP_MAX_PKT_SIZE_OFS                        0
+/* EP0in max packet size = 64 bytes */
+#define UDC_EP0IN_MAX_PKT_SIZE                 64
+/* EP0out max packet size = 64 bytes */
+#define UDC_EP0OUT_MAX_PKT_SIZE                        64
+/* EP0in fullspeed max packet size = 64 bytes */
+#define UDC_FS_EP0IN_MAX_PKT_SIZE              64
+/* EP0out fullspeed max packet size = 64 bytes */
+#define UDC_FS_EP0OUT_MAX_PKT_SIZE             64
+
+/*
+ * Endpoint dma descriptors ------------------------------------------------
+ *
+ * Setup data, Status dword
+ */
+#define UDC_DMA_STP_STS_CFG_MASK               0x0fff0000
+#define UDC_DMA_STP_STS_CFG_OFS                        16
+#define UDC_DMA_STP_STS_CFG_ALT_MASK           0x000f0000
+#define UDC_DMA_STP_STS_CFG_ALT_OFS            16
+#define UDC_DMA_STP_STS_CFG_INTF_MASK          0x00f00000
+#define UDC_DMA_STP_STS_CFG_INTF_OFS           20
+#define UDC_DMA_STP_STS_CFG_NUM_MASK           0x0f000000
+#define UDC_DMA_STP_STS_CFG_NUM_OFS            24
+#define UDC_DMA_STP_STS_RX_MASK                        0x30000000
+#define UDC_DMA_STP_STS_RX_OFS                 28
+#define UDC_DMA_STP_STS_BS_MASK                        0xc0000000
+#define UDC_DMA_STP_STS_BS_OFS                 30
+#define UDC_DMA_STP_STS_BS_HOST_READY          0
+#define UDC_DMA_STP_STS_BS_DMA_BUSY            1
+#define UDC_DMA_STP_STS_BS_DMA_DONE            2
+#define UDC_DMA_STP_STS_BS_HOST_BUSY           3
+/* IN data, Status dword */
+#define UDC_DMA_IN_STS_TXBYTES_MASK            0x0000ffff
+#define UDC_DMA_IN_STS_TXBYTES_OFS             0
+#define        UDC_DMA_IN_STS_FRAMENUM_MASK            0x07ff0000
+#define UDC_DMA_IN_STS_FRAMENUM_OFS            0
+#define UDC_DMA_IN_STS_L                       27
+#define UDC_DMA_IN_STS_TX_MASK                 0x30000000
+#define UDC_DMA_IN_STS_TX_OFS                  28
+#define UDC_DMA_IN_STS_BS_MASK                 0xc0000000
+#define UDC_DMA_IN_STS_BS_OFS                  30
+#define UDC_DMA_IN_STS_BS_HOST_READY           0
+#define UDC_DMA_IN_STS_BS_DMA_BUSY             1
+#define UDC_DMA_IN_STS_BS_DMA_DONE             2
+#define UDC_DMA_IN_STS_BS_HOST_BUSY            3
+/* OUT data, Status dword */
+#define UDC_DMA_OUT_STS_RXBYTES_MASK           0x0000ffff
+#define UDC_DMA_OUT_STS_RXBYTES_OFS            0
+#define UDC_DMA_OUT_STS_FRAMENUM_MASK          0x07ff0000
+#define UDC_DMA_OUT_STS_FRAMENUM_OFS           0
+#define UDC_DMA_OUT_STS_L                      27
+#define UDC_DMA_OUT_STS_RX_MASK                        0x30000000
+#define UDC_DMA_OUT_STS_RX_OFS                 28
+#define UDC_DMA_OUT_STS_BS_MASK                        0xc0000000
+#define UDC_DMA_OUT_STS_BS_OFS                 30
+#define UDC_DMA_OUT_STS_BS_HOST_READY          0
+#define UDC_DMA_OUT_STS_BS_DMA_BUSY            1
+#define UDC_DMA_OUT_STS_BS_DMA_DONE            2
+#define UDC_DMA_OUT_STS_BS_HOST_BUSY           3
+/* max ep0in packet */
+#define UDC_EP0IN_MAXPACKET                    1000
+/* max dma packet */
+#define UDC_DMA_MAXPACKET                      65536
+
+/* un-usable DMA address */
+#define DMA_DONT_USE                           (~(dma_addr_t) 0 )
+
+/* other Endpoint register addresses and values-----------------------------*/
+#define UDC_EP_SUBPTR_ADDR                     0x10
+#define UDC_EP_DESPTR_ADDR                     0x14
+#define UDC_EP_WRITE_CONFIRM_ADDR              0x1c
+
+/* EP number as layouted in AHB space */
+#define UDC_EP_NUM                             32
+#define UDC_EPIN_NUM                           16
+#define UDC_EPIN_NUM_USED                      5
+#define UDC_EPOUT_NUM                          16
+/* EP number of EP's really used = EP0 + 8 data EP's */
+#define UDC_USED_EP_NUM                                9
+/* UDC CSR regs are aligned but AHB regs not - offset for OUT EP's */
+#define UDC_CSR_EP_OUT_IX_OFS                  12
+
+#define UDC_EP0OUT_IX                          16
+#define UDC_EP0IN_IX                           0
+
+/* Rx fifo address and size = 1k -------------------------------------------*/
+#define UDC_RXFIFO_ADDR                                0x800
+#define UDC_RXFIFO_SIZE                                0x400
+
+/* Tx fifo address and size = 1.5k -----------------------------------------*/
+#define UDC_TXFIFO_ADDR                                0xc00
+#define UDC_TXFIFO_SIZE                                0x600
+
+/* default data endpoints --------------------------------------------------*/
+#define UDC_EPIN_STATUS_IX                     1
+#define UDC_EPIN_IX                            2
+#define UDC_EPOUT_IX                           18
+
+/* general constants -------------------------------------------------------*/
+#define UDC_DWORD_BYTES                                4
+#define UDC_BITS_PER_BYTE_SHIFT                        3
+#define UDC_BYTE_MASK                          0xff
+#define UDC_BITS_PER_BYTE                      8
+
+/*---------------------------------------------------------------------------*/
+/* UDC CSR's */
+struct udc_csrs {
+
+       /* sca - setup command address */
+       u32 sca;
+
+       /* ep ne's */
+       u32 ne[UDC_USED_EP_NUM];
+} __attribute__ ((packed));
+
+/* AHB subsystem CSR registers */
+struct udc_regs {
+
+       /* device configuration */
+       u32 cfg;
+
+       /* device control */
+       u32 ctl;
+
+       /* device status */
+       u32 sts;
+
+       /* device interrupt */
+       u32 irqsts;
+
+       /* device interrupt mask */
+       u32 irqmsk;
+
+       /* endpoint interrupt */
+       u32 ep_irqsts;
+
+       /* endpoint interrupt mask */
+       u32 ep_irqmsk;
+} __attribute__ ((packed));
+
+/* endpoint specific registers */
+struct udc_ep_regs {
+
+       /* endpoint control */
+       u32 ctl;
+
+       /* endpoint status */
+       u32 sts;
+
+       /* endpoint buffer size in/ receive packet frame number out */
+       u32 bufin_framenum;
+
+       /* endpoint buffer size out/max packet size */
+       u32 bufout_maxpkt;
+
+       /* endpoint setup buffer pointer */
+       u32 subptr;
+
+       /* endpoint data descriptor pointer */
+       u32 desptr;
+
+       /* reserverd */
+       u32 reserved;
+
+       /* write/read confirmation */
+       u32 confirm;
+
+} __attribute__ ((packed));
+
+/* control data DMA desc */
+struct udc_stp_dma {
+       /* status quadlet */
+       u32     status;
+       /* reserved */
+       u32     _reserved;
+       /* first setup word */
+       u32     data12;
+       /* second setup word */
+       u32     data34;
+} __attribute__ ((aligned (16)));
+
+/* normal data DMA desc */
+struct udc_data_dma {
+       /* status quadlet */
+       u32     status;
+       /* reserved */
+       u32     _reserved;
+       /* buffer pointer */
+       u32     bufptr;
+       /* next descriptor pointer */
+       u32     next;
+} __attribute__ ((aligned (16)));
+
+/* request packet */
+struct udc_request {
+       /* embedded gadget ep */
+       struct usb_request              req;
+
+       /* flags */
+       unsigned                        dma_going : 1,
+                                       dma_mapping : 1,
+                                       dma_done : 1;
+       /* phys. address */
+       dma_addr_t                      td_phys;
+       /* first dma desc. of chain */
+       struct udc_data_dma             *td_data;
+       /* last dma desc. of chain */
+       struct udc_data_dma             *td_data_last;
+       struct list_head                queue;
+
+       /* chain length */
+       unsigned                        chain_len;
+
+};
+
+/* UDC specific endpoint parameters */
+struct udc_ep {
+       struct usb_ep                   ep;
+       struct udc_ep_regs __iomem      *regs;
+       u32 __iomem                     *txfifo;
+       u32 __iomem                     *dma;
+       dma_addr_t                      td_phys;
+       dma_addr_t                      td_stp_dma;
+       struct udc_stp_dma              *td_stp;
+       struct udc_data_dma             *td;
+       /* temp request */
+       struct udc_request              *req;
+       unsigned                        req_used;
+       unsigned                        req_completed;
+       /* dummy DMA desc for BNA dummy */
+       struct udc_request              *bna_dummy_req;
+       unsigned                        bna_occurred;
+
+       /* NAK state */
+       unsigned                        naking;
+
+       struct udc                      *dev;
+
+       /* queue for requests */
+       struct list_head                queue;
+       const struct usb_endpoint_descriptor    *desc;
+       unsigned                        halted;
+       unsigned                        cancel_transfer;
+       unsigned                        num : 5,
+                                       fifo_depth : 14,
+                                       in : 1;
+};
+
+/* device struct */
+struct udc {
+       struct usb_gadget               gadget;
+       spinlock_t                      lock;   /* protects all state */
+       /* all endpoints */
+       struct udc_ep                   ep[UDC_EP_NUM];
+       struct usb_gadget_driver        *driver;
+       /* operational flags */
+       unsigned                        active : 1,
+                                       stall_ep0in : 1,
+                                       waiting_zlp_ack_ep0in : 1,
+                                       set_cfg_not_acked : 1,
+                                       irq_registered : 1,
+                                       data_ep_enabled : 1,
+                                       data_ep_queued : 1,
+                                       mem_region : 1,
+                                       sys_suspended : 1,
+                                       connected;
+
+       u16                             chiprev;
+
+       /* registers */
+       struct pci_dev                  *pdev;
+       struct udc_csrs __iomem         *csr;
+       struct udc_regs __iomem         *regs;
+       struct udc_ep_regs __iomem      *ep_regs;
+       u32 __iomem                     *rxfifo;
+       u32 __iomem                     *txfifo;
+
+       /* DMA desc pools */
+       struct pci_pool                 *data_requests;
+       struct pci_pool                 *stp_requests;
+
+       /* device data */
+       unsigned long                   phys_addr;
+       void __iomem                    *virt_addr;
+       unsigned                        irq;
+
+       /* states */
+       u16                             cur_config;
+       u16                             cur_intf;
+       u16                             cur_alt;
+};
+
+/* setup request data */
+union udc_setup_data {
+       u32                     data[2];
+       struct usb_ctrlrequest  request;
+};
+
+/*
+ *---------------------------------------------------------------------------
+ * SET and GET bitfields in u32 values
+ * via constants for mask/offset:
+ * <bit_field_stub_name> is the text between
+ * UDC_ and _MASK|_OFS of appropiate
+ * constant
+ *
+ * set bitfield value in u32 u32Val
+ */
+#define AMD_ADDBITS(u32Val, bitfield_val, bitfield_stub_name)          \
+       (((u32Val) & (((u32) ~((u32) bitfield_stub_name##_MASK))))      \
+       | (((bitfield_val) << ((u32) bitfield_stub_name##_OFS))         \
+               & ((u32) bitfield_stub_name##_MASK)))
+
+/*
+ * set bitfield value in zero-initialized u32 u32Val
+ * => bitfield bits in u32Val are all zero
+ */
+#define AMD_INIT_SETBITS(u32Val, bitfield_val, bitfield_stub_name)     \
+       ((u32Val)                                                       \
+       | (((bitfield_val) << ((u32) bitfield_stub_name##_OFS))         \
+               & ((u32) bitfield_stub_name##_MASK)))
+
+/* get bitfield value from u32 u32Val */
+#define AMD_GETBITS(u32Val, bitfield_stub_name)                                \
+       ((u32Val & ((u32) bitfield_stub_name##_MASK))                   \
+               >> ((u32) bitfield_stub_name##_OFS))
+
+/* SET and GET bits in u32 values ------------------------------------------*/
+#define AMD_BIT(bit_stub_name) (1 << bit_stub_name)
+#define AMD_UNMASK_BIT(bit_stub_name) (~AMD_BIT(bit_stub_name))
+#define AMD_CLEAR_BIT(bit_stub_name) (~AMD_BIT(bit_stub_name))
+
+/* debug macros ------------------------------------------------------------*/
+
+#define DBG(udc , args...)     dev_dbg(&(udc)->pdev->dev, args)
+
+#ifdef UDC_VERBOSE
+#define VDBG                   DBG
+#else
+#define VDBG(udc , args...)    do {} while (0)
+#endif
+
+#endif /* #ifdef AMD5536UDC_H */
index dbaf867436dffbc69e3172810fd4b24a89d7c10f..a3376739a81b0cb839ea01f292ca34535ce68197 100644 (file)
@@ -305,6 +305,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
 #define DEV_CONFIG_CDC
 #endif
 
+#ifdef CONFIG_USB_GADGET_AMD5536UDC
+#define        DEV_CONFIG_CDC
+#endif
+
 
 /*-------------------------------------------------------------------------*/
 
index 53e9139ba3886137ac2f642eb72587183251a777..f7f159c1002b76e8e2f2dafd163913f08e009f77 100644 (file)
 #define        gadget_is_net2280(g)    0
 #endif
 
+#ifdef CONFIG_USB_GADGET_AMD5536UDC
+#define        gadget_is_amd5536udc(g) !strcmp("amd5536udc", (g)->name)
+#else
+#define        gadget_is_amd5536udc(g) 0
+#endif
+
 #ifdef CONFIG_USB_GADGET_DUMMY_HCD
 #define        gadget_is_dummy(g)      !strcmp("dummy_udc", (g)->name)
 #else
@@ -202,7 +208,9 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
                return 0x18;
        else if (gadget_is_fsl_usb2(gadget))
                return 0x19;
-       else if (gadget_is_m66592(gadget))
+       else if (gadget_is_amd5536udc(gadget))
                return 0x20;
+       else if (gadget_is_m66592(gadget))
+               return 0x21;
        return -ENOENT;
 }
index 0174a322e007b036646d0eba9d7589b0950e4b7e..700dda8a91579666cf04af70416e2dae6fb01912 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/list.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
+
 #include <linux/usb/ch9.h>
 #include <linux/usb_gadget.h>
 
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-
 #include "m66592-udc.h"
 
-MODULE_DESCRIPTION("M66592 USB gadget driiver");
+
+MODULE_DESCRIPTION("M66592 USB gadget driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Yoshihiro Shimoda");
 
@@ -49,16 +41,21 @@ MODULE_AUTHOR("Yoshihiro Shimoda");
 /* module parameters */
 static unsigned short clock = M66592_XTAL24;
 module_param(clock, ushort, 0644);
-MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0(default=16384)");
+MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 "
+               "(default=16384)");
+
 static unsigned short vif = M66592_LDRV;
 module_param(vif, ushort, 0644);
-MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0(default=32768)");
-static unsigned short endian = 0;
+MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0 (default=32768)");
+
+static unsigned short endian;
 module_param(endian, ushort, 0644);
-MODULE_PARM_DESC(endian, "data endian: big=256, little=0(default=0)");
+MODULE_PARM_DESC(endian, "data endian: big=256, little=0 (default=0)");
+
 static unsigned short irq_sense = M66592_INTL;
 module_param(irq_sense, ushort, 0644);
-MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0(default=2)");
+MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 "
+               "(default=2)");
 
 static const char udc_name[] = "m66592_udc";
 static const char *m66592_ep_name[] = {
@@ -72,8 +69,8 @@ static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
                        gfp_t gfp_flags);
 
 static void transfer_complete(struct m66592_ep *ep,
-                             struct m66592_request *req,
-                             int status);
+               struct m66592_request *req, int status);
+
 /*-------------------------------------------------------------------------*/
 static inline u16 get_usb_speed(struct m66592 *m66592)
 {
@@ -81,25 +78,25 @@ static inline u16 get_usb_speed(struct m66592 *m66592)
 }
 
 static void enable_pipe_irq(struct m66592 *m66592, u16 pipenum,
-                           unsigned long reg)
+               unsigned long reg)
 {
        u16 tmp;
 
        tmp = m66592_read(m66592, M66592_INTENB0);
        m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
-                   M66592_INTENB0);
+                       M66592_INTENB0);
        m66592_bset(m66592, (1 << pipenum), reg);
        m66592_write(m66592, tmp, M66592_INTENB0);
 }
 
 static void disable_pipe_irq(struct m66592 *m66592, u16 pipenum,
-                            unsigned long reg)
+               unsigned long reg)
 {
        u16 tmp;
 
        tmp = m66592_read(m66592, M66592_INTENB0);
        m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
-                   M66592_INTENB0);
+                       M66592_INTENB0);
        m66592_bclr(m66592, (1 << pipenum), reg);
        m66592_write(m66592, tmp, M66592_INTENB0);
 }
@@ -108,17 +105,19 @@ static void m66592_usb_connect(struct m66592 *m66592)
 {
        m66592_bset(m66592, M66592_CTRE, M66592_INTENB0);
        m66592_bset(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
-                   M66592_INTENB0);
+                       M66592_INTENB0);
        m66592_bset(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
 
        m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
 }
 
 static void m66592_usb_disconnect(struct m66592 *m66592)
+__releases(m66592->lock)
+__acquires(m66592->lock)
 {
        m66592_bclr(m66592, M66592_CTRE, M66592_INTENB0);
        m66592_bclr(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
-                   M66592_INTENB0);
+                       M66592_INTENB0);
        m66592_bclr(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
        m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
 
@@ -148,7 +147,7 @@ static inline u16 control_reg_get_pid(struct m66592 *m66592, u16 pipenum)
 }
 
 static inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum,
-                                      u16 pid)
+               u16 pid)
 {
        unsigned long offset;
 
@@ -250,7 +249,7 @@ static inline void pipe_change(struct m66592 *m66592, u16 pipenum)
 }
 
 static int pipe_buffer_setting(struct m66592 *m66592,
-                              struct m66592_pipe_info *info)
+               struct m66592_pipe_info *info)
 {
        u16 bufnum = 0, buf_bsize = 0;
        u16 pipecfg = 0;
@@ -287,7 +286,7 @@ static int pipe_buffer_setting(struct m66592 *m66592,
        }
        if (m66592->bi_bufnum > M66592_MAX_BUFNUM) {
                printk(KERN_ERR "m66592 pipe memory is insufficient(%d)\n",
-                      m66592->bi_bufnum);
+                               m66592->bi_bufnum);
                return -ENOMEM;
        }
 
@@ -328,7 +327,7 @@ static void pipe_buffer_release(struct m66592 *m66592,
                        m66592->bulk--;
        } else
                printk(KERN_ERR "ep_release: unexpect pipenum (%d)\n",
-                      info->pipe);
+                               info->pipe);
 }
 
 static void pipe_initialize(struct m66592_ep *ep)
@@ -350,8 +349,8 @@ static void pipe_initialize(struct m66592_ep *ep)
 }
 
 static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
-                             const struct usb_endpoint_descriptor *desc,
-                             u16 pipenum, int dma)
+               const struct usb_endpoint_descriptor *desc,
+               u16 pipenum, int dma)
 {
        if ((pipenum != 0) && dma) {
                if (m66592->num_dma == 0) {
@@ -385,7 +384,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
 
        ep->pipectr = get_pipectr_addr(pipenum);
        ep->pipenum = pipenum;
-       ep->ep.maxpacket = desc->wMaxPacketSize;
+       ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
        m66592->pipenum2ep[pipenum] = ep;
        m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep;
        INIT_LIST_HEAD(&ep->queue);
@@ -407,7 +406,7 @@ static void m66592_ep_release(struct m66592_ep *ep)
 }
 
 static int alloc_pipe_config(struct m66592_ep *ep,
-                            const struct usb_endpoint_descriptor *desc)
+               const struct usb_endpoint_descriptor *desc)
 {
        struct m66592 *m66592 = ep->m66592;
        struct m66592_pipe_info info;
@@ -419,15 +418,15 @@ static int alloc_pipe_config(struct m66592_ep *ep,
 
        BUG_ON(ep->pipenum);
 
-       switch(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+       switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
        case USB_ENDPOINT_XFER_BULK:
                if (m66592->bulk >= M66592_MAX_NUM_BULK) {
                        if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
                                printk(KERN_ERR "bulk pipe is insufficient\n");
                                return -ENODEV;
                        } else {
-                               info.pipe = M66592_BASE_PIPENUM_ISOC +
-                                           m66592->isochronous;
+                               info.pipe = M66592_BASE_PIPENUM_ISOC
+                                               + m66592->isochronous;
                                counter = &m66592->isochronous;
                        }
                } else {
@@ -462,7 +461,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
        ep->type = info.type;
 
        info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-       info.maxpacket = desc->wMaxPacketSize;
+       info.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
        info.interval = desc->bInterval;
        if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
                info.dir_in = 1;
@@ -525,8 +524,8 @@ static void start_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
 
        pipe_change(m66592, ep->pipenum);
        m66592_mdfy(m66592, M66592_ISEL | M66592_PIPE0,
-                   (M66592_ISEL | M66592_CURPIPE),
-                   M66592_CFIFOSEL);
+                       (M66592_ISEL | M66592_CURPIPE),
+                       M66592_CFIFOSEL);
        m66592_write(m66592, M66592_BCLR, ep->fifoctr);
        if (req->req.length == 0) {
                m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
@@ -561,8 +560,8 @@ static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
 
        if (ep->pipenum == 0) {
                m66592_mdfy(m66592, M66592_PIPE0,
-                           (M66592_ISEL | M66592_CURPIPE),
-                           M66592_CFIFOSEL);
+                               (M66592_ISEL | M66592_CURPIPE),
+                               M66592_CFIFOSEL);
                m66592_write(m66592, M66592_BCLR, ep->fifoctr);
                pipe_start(m66592, pipenum);
                pipe_irq_enable(m66592, pipenum);
@@ -572,8 +571,9 @@ static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
                        pipe_change(m66592, pipenum);
                        m66592_bset(m66592, M66592_TRENB, ep->fifosel);
                        m66592_write(m66592,
-                                    (req->req.length + ep->ep.maxpacket - 1) /
-                                    ep->ep.maxpacket, ep->fifotrn);
+                               (req->req.length + ep->ep.maxpacket - 1)
+                                       / ep->ep.maxpacket,
+                               ep->fifotrn);
                }
                pipe_start(m66592, pipenum);    /* trigger once */
                pipe_irq_enable(m66592, pipenum);
@@ -614,7 +614,7 @@ static void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
 static void init_controller(struct m66592 *m66592)
 {
        m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND),
-                   M66592_PINCFG);
+                       M66592_PINCFG);
        m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);         /* High spd */
        m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL, M66592_SYSCFG);
 
@@ -634,7 +634,7 @@ static void init_controller(struct m66592 *m66592)
 
        m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
        m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
-                    M66592_DMA0CFG);
+                       M66592_DMA0CFG);
 }
 
 static void disable_controller(struct m66592 *m66592)
@@ -659,8 +659,9 @@ static void m66592_start_xclock(struct m66592 *m66592)
 
 /*-------------------------------------------------------------------------*/
 static void transfer_complete(struct m66592_ep *ep,
-                             struct m66592_request *req,
-                             int status)
+               struct m66592_request *req, int status)
+__releases(m66592->lock)
+__acquires(m66592->lock)
 {
        int restart = 0;
 
@@ -680,8 +681,9 @@ static void transfer_complete(struct m66592_ep *ep,
        if (!list_empty(&ep->queue))
                restart = 1;
 
-       if (likely(req->req.complete))
-               req->req.complete(&ep->ep, &req->req);
+       spin_unlock(&ep->m66592->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&ep->m66592->lock);
 
        if (restart) {
                req = list_entry(ep->queue.next, struct m66592_request, queue);
@@ -693,7 +695,7 @@ static void transfer_complete(struct m66592_ep *ep,
 static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
 {
        int i;
-       volatile u16 tmp;
+       u16 tmp;
        unsigned bufsize;
        size_t size;
        void *buf;
@@ -731,8 +733,9 @@ static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
        req->req.actual += size;
 
        /* check transfer finish */
-       if ((!req->req.zero && (req->req.actual == req->req.length)) ||
-           (size % ep->ep.maxpacket) || (size == 0)) {
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
                disable_irq_ready(m66592, pipenum);
                disable_irq_empty(m66592, pipenum);
        } else {
@@ -768,16 +771,19 @@ static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
        /* write fifo */
        if (req->req.buf) {
                m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
-               if ((size == 0) || ((size % ep->ep.maxpacket) != 0) ||
-                   ((bufsize != ep->ep.maxpacket) && (bufsize > size)))
+               if ((size == 0)
+                               || ((size % ep->ep.maxpacket) != 0)
+                               || ((bufsize != ep->ep.maxpacket)
+                                       && (bufsize > size)))
                        m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
        }
 
        /* update parameters */
        req->req.actual += size;
        /* check transfer finish */
-       if ((!req->req.zero && (req->req.actual == req->req.length)) ||
-           (size % ep->ep.maxpacket) || (size == 0)) {
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
                disable_irq_ready(m66592, pipenum);
                enable_irq_empty(m66592, pipenum);
        } else {
@@ -821,8 +827,9 @@ static void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req)
        req->req.actual += size;
 
        /* check transfer finish */
-       if ((!req->req.zero && (req->req.actual == req->req.length)) ||
-           (size % ep->ep.maxpacket) || (size == 0)) {
+       if ((!req->req.zero && (req->req.actual == req->req.length))
+                       || (size % ep->ep.maxpacket)
+                       || (size == 0)) {
                pipe_stop(m66592, pipenum);
                pipe_irq_disable(m66592, pipenum);
                finish = 1;
@@ -850,7 +857,7 @@ static void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb)
        if ((status & M66592_BRDY0) && (enb & M66592_BRDY0)) {
                m66592_write(m66592, ~M66592_BRDY0, M66592_BRDYSTS);
                m66592_mdfy(m66592, M66592_PIPE0, M66592_CURPIPE,
-                           M66592_CFIFOSEL);
+                               M66592_CFIFOSEL);
 
                ep = &m66592->ep[0];
                req = list_entry(ep->queue.next, struct m66592_request, queue);
@@ -909,23 +916,26 @@ static void irq_pipe_empty(struct m66592 *m66592, u16 status, u16 enb)
 }
 
 static void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+__releases(m66592->lock)
+__acquires(m66592->lock)
 {
        struct m66592_ep *ep;
        u16 pid;
        u16 status = 0;
+       u16 w_index = le16_to_cpu(ctrl->wIndex);
 
        switch (ctrl->bRequestType & USB_RECIP_MASK) {
        case USB_RECIP_DEVICE:
-               status = 1;     /* selfpower */
+               status = 1 << USB_DEVICE_SELF_POWERED;
                break;
        case USB_RECIP_INTERFACE:
                status = 0;
                break;
        case USB_RECIP_ENDPOINT:
-               ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+               ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
                pid = control_reg_get_pid(m66592, ep->pipenum);
                if (pid == M66592_PID_STALL)
-                       status = 1;
+                       status = 1 << USB_ENDPOINT_HALT;
                else
                        status = 0;
                break;
@@ -934,11 +944,13 @@ static void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
                return;         /* exit */
        }
 
-       *m66592->ep0_buf = status;
-       m66592->ep0_req->buf = m66592->ep0_buf;
+       m66592->ep0_data = cpu_to_le16(status);
+       m66592->ep0_req->buf = &m66592->ep0_data;
        m66592->ep0_req->length = 2;
        /* AV: what happens if we get called again before that gets through? */
+       spin_unlock(&m66592->lock);
        m66592_queue(m66592->gadget.ep0, m66592->ep0_req, GFP_KERNEL);
+       spin_lock(&m66592->lock);
 }
 
 static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
@@ -953,8 +965,9 @@ static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
        case USB_RECIP_ENDPOINT: {
                struct m66592_ep *ep;
                struct m66592_request *req;
+               u16 w_index = le16_to_cpu(ctrl->wIndex);
 
-               ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+               ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
                pipe_stop(m66592, ep->pipenum);
                control_reg_sqclr(m66592, ep->pipenum);
 
@@ -989,8 +1002,9 @@ static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
                break;
        case USB_RECIP_ENDPOINT: {
                struct m66592_ep *ep;
+               u16 w_index = le16_to_cpu(ctrl->wIndex);
 
-               ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+               ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
                pipe_stall(m66592, ep->pipenum);
 
                control_end(m66592, 1);
@@ -1066,14 +1080,16 @@ static void irq_device_state(struct m66592 *m66592)
        }
        if (m66592->old_dvsq == M66592_DS_CNFG && dvsq != M66592_DS_CNFG)
                m66592_update_usb_speed(m66592);
-       if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS) &&
-           m66592->gadget.speed == USB_SPEED_UNKNOWN)
+       if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS)
+                       && m66592->gadget.speed == USB_SPEED_UNKNOWN)
                m66592_update_usb_speed(m66592);
 
        m66592->old_dvsq = dvsq;
 }
 
 static void irq_control_stage(struct m66592 *m66592)
+__releases(m66592->lock)
+__acquires(m66592->lock)
 {
        struct usb_ctrlrequest ctrl;
        u16 ctsq;
@@ -1095,8 +1111,10 @@ static void irq_control_stage(struct m66592 *m66592)
        case M66592_CS_WRDS:
        case M66592_CS_WRND:
                if (setup_packet(m66592, &ctrl)) {
+                       spin_unlock(&m66592->lock);
                        if (m66592->driver->setup(&m66592->gadget, &ctrl) < 0)
                                pipe_stall(m66592, 0);
+                       spin_lock(&m66592->lock);
                }
                break;
        case M66592_CS_RDSS:
@@ -1119,6 +1137,8 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
        u16 savepipe;
        u16 mask0;
 
+       spin_lock(&m66592->lock);
+
        intsts0 = m66592_read(m66592, M66592_INTSTS0);
        intenb0 = m66592_read(m66592, M66592_INTENB0);
 
@@ -1134,27 +1154,27 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
                bempenb = m66592_read(m66592, M66592_BEMPENB);
 
                if (mask0 & M66592_VBINT) {
-                       m66592_write(m66592, (u16)~M66592_VBINT,
-                                    M66592_INTSTS0);
+                       m66592_write(m66592,  0xffff & ~M66592_VBINT,
+                                       M66592_INTSTS0);
                        m66592_start_xclock(m66592);
 
                        /* start vbus sampling */
                        m66592->old_vbus = m66592_read(m66592, M66592_INTSTS0)
-                                          & M66592_VBSTS;
+                                       & M66592_VBSTS;
                        m66592->scount = M66592_MAX_SAMPLING;
 
                        mod_timer(&m66592->timer,
-                                 jiffies + msecs_to_jiffies(50));
+                                       jiffies + msecs_to_jiffies(50));
                }
                if (intsts0 & M66592_DVSQ)
                        irq_device_state(m66592);
 
-               if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE) &&
-                   (brdysts & brdyenb)) {
+               if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE)
+                               && (brdysts & brdyenb)) {
                        irq_pipe_ready(m66592, brdysts, brdyenb);
                }
-               if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE) &&
-                   (bempsts & bempenb)) {
+               if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE)
+                               && (bempsts & bempenb)) {
                        irq_pipe_empty(m66592, bempsts, bempenb);
                }
 
@@ -1164,6 +1184,7 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
 
        m66592_write(m66592, savepipe, M66592_CFIFOSEL);
 
+       spin_unlock(&m66592->lock);
        return IRQ_HANDLED;
 }
 
@@ -1191,13 +1212,13 @@ static void m66592_timer(unsigned long _m66592)
                                        m66592_usb_disconnect(m66592);
                        } else {
                                mod_timer(&m66592->timer,
-                                         jiffies + msecs_to_jiffies(50));
+                                       jiffies + msecs_to_jiffies(50));
                        }
                } else {
                        m66592->scount = M66592_MAX_SAMPLING;
                        m66592->old_vbus = tmp;
                        mod_timer(&m66592->timer,
-                                 jiffies + msecs_to_jiffies(50));
+                                       jiffies + msecs_to_jiffies(50));
                }
        }
        spin_unlock_irqrestore(&m66592->lock, flags);
@@ -1335,11 +1356,6 @@ out:
        return ret;
 }
 
-static int m66592_fifo_status(struct usb_ep *_ep)
-{
-       return -EOPNOTSUPP;
-}
-
 static void m66592_fifo_flush(struct usb_ep *_ep)
 {
        struct m66592_ep *ep;
@@ -1365,7 +1381,6 @@ static struct usb_ep_ops m66592_ep_ops = {
        .dequeue        = m66592_dequeue,
 
        .set_halt       = m66592_set_halt,
-       .fifo_status    = m66592_fifo_status,
        .fifo_flush     = m66592_fifo_flush,
 };
 
@@ -1377,11 +1392,10 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
        struct m66592 *m66592 = the_controller;
        int retval;
 
-       if (!driver ||
-           driver->speed != USB_SPEED_HIGH ||
-           !driver->bind ||
-           !driver->unbind ||
-           !driver->setup)
+       if (!driver
+                       || driver->speed != USB_SPEED_HIGH
+                       || !driver->bind
+                       || !driver->setup)
                return -EINVAL;
        if (!m66592)
                return -ENODEV;
@@ -1413,8 +1427,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
                m66592->old_vbus = m66592_read(m66592,
                                         M66592_INTSTS0) & M66592_VBSTS;
                m66592->scount = M66592_MAX_SAMPLING;
-               mod_timer(&m66592->timer,
-                         jiffies + msecs_to_jiffies(50));
+               mod_timer(&m66592->timer, jiffies + msecs_to_jiffies(50));
        }
 
        return 0;
@@ -1432,6 +1445,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
        struct m66592 *m66592 = the_controller;
        unsigned long flags;
 
+       if (driver != m66592->driver || !driver->unbind)
+               return -EINVAL;
+
        spin_lock_irqsave(&m66592->lock, flags);
        if (m66592->gadget.speed != USB_SPEED_UNKNOWN)
                m66592_usb_disconnect(m66592);
@@ -1461,46 +1477,35 @@ static struct usb_gadget_ops m66592_gadget_ops = {
        .get_frame              = m66592_get_frame,
 };
 
-#if defined(CONFIG_PM)
-static int m66592_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       pdev->dev.power.power_state = state;
-       return 0;
-}
-
-static int m66592_resume(struct platform_device *pdev)
-{
-       pdev->dev.power.power_state = PMSG_ON;
-       return 0;
-}
-#else  /* if defined(CONFIG_PM) */
-#define m66592_suspend         NULL
-#define m66592_resume          NULL
-#endif
-
-static int __init_or_module m66592_remove(struct platform_device *pdev)
+static int __exit m66592_remove(struct platform_device *pdev)
 {
        struct m66592           *m66592 = dev_get_drvdata(&pdev->dev);
 
        del_timer_sync(&m66592->timer);
        iounmap(m66592->reg);
        free_irq(platform_get_irq(pdev, 0), m66592);
+       m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
        kfree(m66592);
        return 0;
 }
 
+static void nop_completion(struct usb_ep *ep, struct usb_request *r)
+{
+}
+
 #define resource_len(r) (((r)->end - (r)->start) + 1)
+
 static int __init m66592_probe(struct platform_device *pdev)
 {
-       struct resource *res = NULL;
-       int irq = -1;
+       struct resource *res;
+       int irq;
        void __iomem *reg = NULL;
        struct m66592 *m66592 = NULL;
        int ret = 0;
        int i;
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-                                          (char *)udc_name);
+                       (char *)udc_name);
        if (!res) {
                ret = -ENODEV;
                printk(KERN_ERR "platform_get_resource_byname error.\n");
@@ -1548,7 +1553,7 @@ static int __init m66592_probe(struct platform_device *pdev)
        m66592->bi_bufnum = M66592_BASE_BUFNUM;
 
        ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
-                         udc_name, m66592);
+                       udc_name, m66592);
        if (ret < 0) {
                printk(KERN_ERR "request_irq error (%d)\n", ret);
                goto clean_up;
@@ -1563,7 +1568,7 @@ static int __init m66592_probe(struct platform_device *pdev)
                if (i != 0) {
                        INIT_LIST_HEAD(&m66592->ep[i].ep.ep_list);
                        list_add_tail(&m66592->ep[i].ep.ep_list,
-                                     &m66592->gadget.ep_list);
+                                       &m66592->gadget.ep_list);
                }
                ep->m66592 = m66592;
                INIT_LIST_HEAD(&ep->queue);
@@ -1583,20 +1588,18 @@ static int __init m66592_probe(struct platform_device *pdev)
 
        the_controller = m66592;
 
-       /* AV: leaks */
        m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
        if (m66592->ep0_req == NULL)
-               goto clean_up;
-       /* AV: leaks, and do we really need it separately allocated? */
-       m66592->ep0_buf = kzalloc(2, GFP_KERNEL);
-       if (m66592->ep0_buf == NULL)
-               goto clean_up;
+               goto clean_up2;
+       m66592->ep0_req->complete = nop_completion;
 
        init_controller(m66592);
 
-       printk("driver %s, %s\n", udc_name, DRIVER_VERSION);
+       dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
        return 0;
 
+clean_up2:
+       free_irq(irq, m66592);
 clean_up:
        if (m66592) {
                if (m66592->ep0_req)
@@ -1611,10 +1614,7 @@ clean_up:
 
 /*-------------------------------------------------------------------------*/
 static struct platform_driver m66592_driver = {
-       .probe =        m66592_probe,
-       .remove =       m66592_remove,
-       .suspend =      m66592_suspend,
-       .resume =       m66592_resume,
+       .remove =       __exit_p(m66592_remove),
        .driver         = {
                .name = (char *) udc_name,
        },
@@ -1622,7 +1622,7 @@ static struct platform_driver m66592_driver = {
 
 static int __init m66592_udc_init(void)
 {
-       return platform_driver_register(&m66592_driver);
+       return platform_driver_probe(&m66592_driver, m66592_probe);
 }
 module_init(m66592_udc_init);
 
@@ -1631,4 +1631,3 @@ static void __exit m66592_udc_cleanup(void)
        platform_driver_unregister(&m66592_driver);
 }
 module_exit(m66592_udc_cleanup);
-
index 26b54f8b894580227eaac2b5ee6c35291737cf67..bfa0c645f229b97752c5362c8503cf1e8f8e46f3 100644 (file)
 #define __M66592_UDC_H__
 
 #define M66592_SYSCFG          0x00
-#define        M66592_XTAL             0xC000  /* b15-14: Crystal selection */
-#define          M66592_XTAL48          0x8000           /* 48MHz */
-#define   M66592_XTAL24                 0x4000           /* 24MHz */
-#define          M66592_XTAL12          0x0000           /* 12MHz */
-#define        M66592_XCKE             0x2000  /* b13: External clock enable */
-#define        M66592_RCKE             0x1000  /* b12: Register clock enable */
-#define        M66592_PLLC             0x0800  /* b11: PLL control */
-#define        M66592_SCKE             0x0400  /* b10: USB clock enable */
-#define        M66592_ATCKM            0x0100  /* b8: Automatic supply functional enable */
-#define        M66592_HSE              0x0080  /* b7: Hi-speed enable */
-#define        M66592_DCFM             0x0040  /* b6: Controller function select  */
-#define        M66592_DMRPD            0x0020  /* b5: D- pull down control */
-#define        M66592_DPRPU            0x0010  /* b4: D+ pull up control */
-#define        M66592_FSRPC            0x0004  /* b2: Full-speed receiver enable */
-#define        M66592_PCUT             0x0002  /* b1: Low power sleep enable */
-#define        M66592_USBE             0x0001  /* b0: USB module operation enable */
+#define M66592_XTAL            0xC000  /* b15-14: Crystal selection */
+#define   M66592_XTAL48                 0x8000         /* 48MHz */
+#define   M66592_XTAL24                 0x4000         /* 24MHz */
+#define   M66592_XTAL12                 0x0000         /* 12MHz */
+#define M66592_XCKE            0x2000  /* b13: External clock enable */
+#define M66592_RCKE            0x1000  /* b12: Register clock enable */
+#define M66592_PLLC            0x0800  /* b11: PLL control */
+#define M66592_SCKE            0x0400  /* b10: USB clock enable */
+#define M66592_ATCKM           0x0100  /* b8: Automatic clock supply */
+#define M66592_HSE             0x0080  /* b7: Hi-speed enable */
+#define M66592_DCFM            0x0040  /* b6: Controller function select  */
+#define M66592_DMRPD           0x0020  /* b5: D- pull down control */
+#define M66592_DPRPU           0x0010  /* b4: D+ pull up control */
+#define M66592_FSRPC           0x0004  /* b2: Full-speed receiver enable */
+#define M66592_PCUT            0x0002  /* b1: Low power sleep enable */
+#define M66592_USBE            0x0001  /* b0: USB module operation enable */
 
 #define M66592_SYSSTS          0x02
-#define        M66592_LNST             0x0003  /* b1-0: D+, D- line status */
-#define          M66592_SE1             0x0003           /* SE1 */
-#define          M66592_KSTS            0x0002           /* K State */
-#define          M66592_JSTS            0x0001           /* J State */
-#define          M66592_SE0             0x0000           /* SE0 */
+#define M66592_LNST            0x0003  /* b1-0: D+, D- line status */
+#define   M66592_SE1            0x0003         /* SE1 */
+#define   M66592_KSTS           0x0002         /* K State */
+#define   M66592_JSTS           0x0001         /* J State */
+#define   M66592_SE0            0x0000         /* SE0 */
 
 #define M66592_DVSTCTR         0x04
-#define        M66592_WKUP             0x0100  /* b8: Remote wakeup */
-#define        M66592_RWUPE            0x0080  /* b7: Remote wakeup sense */
-#define        M66592_USBRST           0x0040  /* b6: USB reset enable */
-#define        M66592_RESUME           0x0020  /* b5: Resume enable */
-#define        M66592_UACT             0x0010  /* b4: USB bus enable */
-#define        M66592_RHST             0x0003  /* b1-0: Reset handshake status */
-#define          M66592_HSMODE          0x0003           /* Hi-Speed mode */
-#define          M66592_FSMODE          0x0002           /* Full-Speed mode */
-#define          M66592_HSPROC          0x0001           /* HS handshake is processing */
+#define M66592_WKUP            0x0100  /* b8: Remote wakeup */
+#define M66592_RWUPE           0x0080  /* b7: Remote wakeup sense */
+#define M66592_USBRST          0x0040  /* b6: USB reset enable */
+#define M66592_RESUME          0x0020  /* b5: Resume enable */
+#define M66592_UACT            0x0010  /* b4: USB bus enable */
+#define M66592_RHST            0x0003  /* b1-0: Reset handshake status */
+#define   M66592_HSMODE                 0x0003         /* Hi-Speed mode */
+#define   M66592_FSMODE                 0x0002         /* Full-Speed mode */
+#define   M66592_HSPROC                 0x0001         /* HS handshake is processing */
 
 #define M66592_TESTMODE                0x06
-#define        M66592_UTST             0x000F  /* b4-0: Test select */
-#define          M66592_H_TST_PACKET    0x000C           /* HOST TEST Packet */
-#define          M66592_H_TST_SE0_NAK   0x000B           /* HOST TEST SE0 NAK */
-#define          M66592_H_TST_K         0x000A           /* HOST TEST K */
-#define          M66592_H_TST_J         0x0009           /* HOST TEST J */
-#define          M66592_H_TST_NORMAL    0x0000           /* HOST Normal Mode */
-#define          M66592_P_TST_PACKET    0x0004           /* PERI TEST Packet */
-#define          M66592_P_TST_SE0_NAK   0x0003           /* PERI TEST SE0 NAK */
-#define          M66592_P_TST_K         0x0002           /* PERI TEST K */
-#define          M66592_P_TST_J         0x0001           /* PERI TEST J */
-#define          M66592_P_TST_NORMAL    0x0000           /* PERI Normal Mode */
+#define M66592_UTST            0x000F  /* b4-0: Test select */
+#define   M66592_H_TST_PACKET   0x000C         /* HOST TEST Packet */
+#define   M66592_H_TST_SE0_NAK  0x000B         /* HOST TEST SE0 NAK */
+#define   M66592_H_TST_K        0x000A         /* HOST TEST K */
+#define   M66592_H_TST_J        0x0009         /* HOST TEST J */
+#define   M66592_H_TST_NORMAL   0x0000         /* HOST Normal Mode */
+#define   M66592_P_TST_PACKET   0x0004         /* PERI TEST Packet */
+#define   M66592_P_TST_SE0_NAK  0x0003         /* PERI TEST SE0 NAK */
+#define   M66592_P_TST_K        0x0002         /* PERI TEST K */
+#define   M66592_P_TST_J        0x0001         /* PERI TEST J */
+#define   M66592_P_TST_NORMAL   0x0000         /* PERI Normal Mode */
 
 #define M66592_PINCFG          0x0A
-#define        M66592_LDRV             0x8000  /* b15: Drive Current Adjust */
-#define        M66592_BIGEND           0x0100  /* b8: Big endian mode */
+#define M66592_LDRV            0x8000  /* b15: Drive Current Adjust */
+#define M66592_BIGEND          0x0100  /* b8: Big endian mode */
 
 #define M66592_DMA0CFG         0x0C
 #define M66592_DMA1CFG         0x0E
-#define        M66592_DREQA            0x4000  /* b14: Dreq active select */
-#define        M66592_BURST            0x2000  /* b13: Burst mode */
-#define        M66592_DACKA            0x0400  /* b10: Dack active select */
-#define        M66592_DFORM            0x0380  /* b9-7: DMA mode select */
-#define          M66592_CPU_ADR_RD_WR   0x0000           /* Address + RD/WR mode (CPU bus) */
-#define          M66592_CPU_DACK_RD_WR  0x0100           /* DACK + RD/WR mode (CPU bus) */
-#define          M66592_CPU_DACK_ONLY   0x0180           /* DACK only mode (CPU bus) */
-#define          M66592_SPLIT_DACK_ONLY         0x0200           /* DACK only mode (SPLIT bus) */
-#define          M66592_SPLIT_DACK_DSTB         0x0300           /* DACK + DSTB0 mode (SPLIT bus) */
-#define        M66592_DENDA            0x0040  /* b6: Dend active select */
-#define        M66592_PKTM             0x0020  /* b5: Packet mode */
-#define        M66592_DENDE            0x0010  /* b4: Dend enable */
-#define        M66592_OBUS             0x0004  /* b2: OUTbus mode */
+#define M66592_DREQA           0x4000  /* b14: Dreq active select */
+#define M66592_BURST           0x2000  /* b13: Burst mode */
+#define M66592_DACKA           0x0400  /* b10: Dack active select */
+#define M66592_DFORM           0x0380  /* b9-7: DMA mode select */
+#define   M66592_CPU_ADR_RD_WR  0x0000   /* Address + RD/WR mode (CPU bus) */
+#define   M66592_CPU_DACK_RD_WR         0x0100   /* DACK + RD/WR mode (CPU bus) */
+#define   M66592_CPU_DACK_ONLY  0x0180   /* DACK only mode (CPU bus) */
+#define   M66592_SPLIT_DACK_ONLY 0x0200   /* DACK only mode (SPLIT bus) */
+#define   M66592_SPLIT_DACK_DSTB 0x0300   /* DACK + DSTB0 mode (SPLIT bus) */
+#define M66592_DENDA           0x0040  /* b6: Dend active select */
+#define M66592_PKTM            0x0020  /* b5: Packet mode */
+#define M66592_DENDE           0x0010  /* b4: Dend enable */
+#define M66592_OBUS            0x0004  /* b2: OUTbus mode */
 
 #define M66592_CFIFO           0x10
 #define M66592_D0FIFO          0x14
 #define M66592_CFIFOSEL                0x1E
 #define M66592_D0FIFOSEL       0x24
 #define M66592_D1FIFOSEL       0x2A
-#define        M66592_RCNT             0x8000  /* b15: Read count mode */
-#define        M66592_REW              0x4000  /* b14: Buffer rewind */
-#define        M66592_DCLRM            0x2000  /* b13: DMA buffer clear mode */
-#define        M66592_DREQE            0x1000  /* b12: DREQ output enable */
-#define        M66592_MBW              0x0400  /* b10: Maximum bit width for FIFO access */
-#define          M66592_MBW_8           0x0000   /*  8bit */
-#define          M66592_MBW_16          0x0400           /* 16bit */
-#define        M66592_TRENB            0x0200  /* b9: Transaction counter enable */
-#define        M66592_TRCLR            0x0100  /* b8: Transaction counter clear */
-#define        M66592_DEZPM            0x0080  /* b7: Zero-length packet additional mode */
-#define        M66592_ISEL             0x0020  /* b5: DCP FIFO port direction select */
-#define        M66592_CURPIPE          0x0007  /* b2-0: PIPE select */
+#define M66592_RCNT            0x8000  /* b15: Read count mode */
+#define M66592_REW             0x4000  /* b14: Buffer rewind */
+#define M66592_DCLRM           0x2000  /* b13: DMA buffer clear mode */
+#define M66592_DREQE           0x1000  /* b12: DREQ output enable */
+#define M66592_MBW             0x0400  /* b10: Maximum bit width for FIFO */
+#define   M66592_MBW_8          0x0000   /*  8bit */
+#define   M66592_MBW_16                 0x0400   /* 16bit */
+#define M66592_TRENB           0x0200  /* b9: Transaction counter enable */
+#define M66592_TRCLR           0x0100  /* b8: Transaction counter clear */
+#define M66592_DEZPM           0x0080  /* b7: Zero-length packet mode */
+#define M66592_ISEL            0x0020  /* b5: DCP FIFO port direction select */
+#define M66592_CURPIPE         0x0007  /* b2-0: PIPE select */
 
 #define M66592_CFIFOCTR                0x20
 #define M66592_D0FIFOCTR       0x26
 #define M66592_D1FIFOCTR       0x2c
-#define        M66592_BVAL             0x8000  /* b15: Buffer valid flag */
-#define        M66592_BCLR             0x4000  /* b14: Buffer clear */
-#define        M66592_FRDY             0x2000  /* b13: FIFO ready */
-#define        M66592_DTLN             0x0FFF  /* b11-0: FIFO received data length */
+#define M66592_BVAL            0x8000  /* b15: Buffer valid flag */
+#define M66592_BCLR            0x4000  /* b14: Buffer clear */
+#define M66592_FRDY            0x2000  /* b13: FIFO ready */
+#define M66592_DTLN            0x0FFF  /* b11-0: FIFO received data length */
 
 #define M66592_CFIFOSIE                0x22
-#define        M66592_TGL              0x8000  /* b15: Buffer toggle */
-#define        M66592_SCLR             0x4000  /* b14: Buffer clear */
-#define        M66592_SBUSY            0x2000  /* b13: SIE_FIFO busy */
+#define M66592_TGL             0x8000  /* b15: Buffer toggle */
+#define M66592_SCLR            0x4000  /* b14: Buffer clear */
+#define M66592_SBUSY           0x2000  /* b13: SIE_FIFO busy */
 
 #define M66592_D0FIFOTRN       0x28
 #define M66592_D1FIFOTRN       0x2E
-#define        M66592_TRNCNT           0xFFFF  /* b15-0: Transaction counter */
+#define M66592_TRNCNT          0xFFFF  /* b15-0: Transaction counter */
 
 #define M66592_INTENB0 0x30
-#define        M66592_VBSE     0x8000  /* b15: VBUS interrupt */
-#define        M66592_RSME     0x4000  /* b14: Resume interrupt */
-#define        M66592_SOFE     0x2000  /* b13: Frame update interrupt */
-#define        M66592_DVSE     0x1000  /* b12: Device state transition interrupt */
-#define        M66592_CTRE     0x0800  /* b11: Control transfer stage transition interrupt */
-#define        M66592_BEMPE    0x0400  /* b10: Buffer empty interrupt */
-#define        M66592_NRDYE    0x0200  /* b9: Buffer not ready interrupt */
-#define        M66592_BRDYE    0x0100  /* b8: Buffer ready interrupt */
-#define        M66592_URST     0x0080  /* b7: USB reset detected interrupt */
-#define        M66592_SADR     0x0040  /* b6: Set address executed interrupt */
-#define        M66592_SCFG     0x0020  /* b5: Set configuration executed interrupt */
-#define        M66592_SUSP     0x0010  /* b4: Suspend detected interrupt */
-#define        M66592_WDST     0x0008  /* b3: Control write data stage completed interrupt */
-#define        M66592_RDST     0x0004  /* b2: Control read data stage completed interrupt */
-#define        M66592_CMPL     0x0002  /* b1: Control transfer complete interrupt */
-#define        M66592_SERR     0x0001  /* b0: Sequence error interrupt */
+#define M66592_VBSE    0x8000  /* b15: VBUS interrupt */
+#define M66592_RSME    0x4000  /* b14: Resume interrupt */
+#define M66592_SOFE    0x2000  /* b13: Frame update interrupt */
+#define M66592_DVSE    0x1000  /* b12: Device state transition interrupt */
+#define M66592_CTRE    0x0800  /* b11: Control transfer stage transition irq */
+#define M66592_BEMPE   0x0400  /* b10: Buffer empty interrupt */
+#define M66592_NRDYE   0x0200  /* b9: Buffer not ready interrupt */
+#define M66592_BRDYE   0x0100  /* b8: Buffer ready interrupt */
+#define M66592_URST    0x0080  /* b7: USB reset detected interrupt */
+#define M66592_SADR    0x0040  /* b6: Set address executed interrupt */
+#define M66592_SCFG    0x0020  /* b5: Set configuration executed interrupt */
+#define M66592_SUSP    0x0010  /* b4: Suspend detected interrupt */
+#define M66592_WDST    0x0008  /* b3: Control write data stage completed irq */
+#define M66592_RDST    0x0004  /* b2: Control read data stage completed irq */
+#define M66592_CMPL    0x0002  /* b1: Control transfer complete interrupt */
+#define M66592_SERR    0x0001  /* b0: Sequence error interrupt */
 
 #define M66592_INTENB1 0x32
-#define        M66592_BCHGE    0x4000  /* b14: USB us chenge interrupt */
-#define        M66592_DTCHE    0x1000  /* b12: Detach sense interrupt */
-#define        M66592_SIGNE    0x0020  /* b5: SETUP IGNORE interrupt */
-#define        M66592_SACKE    0x0010  /* b4: SETUP ACK interrupt */
-#define        M66592_BRDYM    0x0004  /* b2: BRDY clear timing */
-#define        M66592_INTL     0x0002  /* b1: Interrupt sense select */
-#define        M66592_PCSE     0x0001  /* b0: PCUT enable by CS assert */
+#define M66592_BCHGE   0x4000  /* b14: USB us chenge interrupt */
+#define M66592_DTCHE   0x1000  /* b12: Detach sense interrupt */
+#define M66592_SIGNE   0x0020  /* b5: SETUP IGNORE interrupt */
+#define M66592_SACKE   0x0010  /* b4: SETUP ACK interrupt */
+#define M66592_BRDYM   0x0004  /* b2: BRDY clear timing */
+#define M66592_INTL    0x0002  /* b1: Interrupt sense select */
+#define M66592_PCSE    0x0001  /* b0: PCUT enable by CS assert */
 
 #define M66592_BRDYENB         0x36
 #define M66592_BRDYSTS         0x46
-#define        M66592_BRDY7            0x0080  /* b7: PIPE7 */
-#define        M66592_BRDY6            0x0040  /* b6: PIPE6 */
-#define        M66592_BRDY5            0x0020  /* b5: PIPE5 */
-#define        M66592_BRDY4            0x0010  /* b4: PIPE4 */
-#define        M66592_BRDY3            0x0008  /* b3: PIPE3 */
-#define        M66592_BRDY2            0x0004  /* b2: PIPE2 */
-#define        M66592_BRDY1            0x0002  /* b1: PIPE1 */
-#define        M66592_BRDY0            0x0001  /* b1: PIPE0 */
+#define M66592_BRDY7           0x0080  /* b7: PIPE7 */
+#define M66592_BRDY6           0x0040  /* b6: PIPE6 */
+#define M66592_BRDY5           0x0020  /* b5: PIPE5 */
+#define M66592_BRDY4           0x0010  /* b4: PIPE4 */
+#define M66592_BRDY3           0x0008  /* b3: PIPE3 */
+#define M66592_BRDY2           0x0004  /* b2: PIPE2 */
+#define M66592_BRDY1           0x0002  /* b1: PIPE1 */
+#define M66592_BRDY0           0x0001  /* b1: PIPE0 */
 
 #define M66592_NRDYENB         0x38
 #define M66592_NRDYSTS         0x48
-#define        M66592_NRDY7            0x0080  /* b7: PIPE7 */
-#define        M66592_NRDY6            0x0040  /* b6: PIPE6 */
-#define        M66592_NRDY5            0x0020  /* b5: PIPE5 */
-#define        M66592_NRDY4            0x0010  /* b4: PIPE4 */
-#define        M66592_NRDY3            0x0008  /* b3: PIPE3 */
-#define        M66592_NRDY2            0x0004  /* b2: PIPE2 */
-#define        M66592_NRDY1            0x0002  /* b1: PIPE1 */
-#define        M66592_NRDY0            0x0001  /* b1: PIPE0 */
+#define M66592_NRDY7           0x0080  /* b7: PIPE7 */
+#define M66592_NRDY6           0x0040  /* b6: PIPE6 */
+#define M66592_NRDY5           0x0020  /* b5: PIPE5 */
+#define M66592_NRDY4           0x0010  /* b4: PIPE4 */
+#define M66592_NRDY3           0x0008  /* b3: PIPE3 */
+#define M66592_NRDY2           0x0004  /* b2: PIPE2 */
+#define M66592_NRDY1           0x0002  /* b1: PIPE1 */
+#define M66592_NRDY0           0x0001  /* b1: PIPE0 */
 
 #define M66592_BEMPENB         0x3A
 #define M66592_BEMPSTS         0x4A
-#define        M66592_BEMP7            0x0080  /* b7: PIPE7 */
-#define        M66592_BEMP6            0x0040  /* b6: PIPE6 */
-#define        M66592_BEMP5            0x0020  /* b5: PIPE5 */
-#define        M66592_BEMP4            0x0010  /* b4: PIPE4 */
-#define        M66592_BEMP3            0x0008  /* b3: PIPE3 */
-#define        M66592_BEMP2            0x0004  /* b2: PIPE2 */
-#define        M66592_BEMP1            0x0002  /* b1: PIPE1 */
-#define        M66592_BEMP0            0x0001  /* b0: PIPE0 */
+#define M66592_BEMP7           0x0080  /* b7: PIPE7 */
+#define M66592_BEMP6           0x0040  /* b6: PIPE6 */
+#define M66592_BEMP5           0x0020  /* b5: PIPE5 */
+#define M66592_BEMP4           0x0010  /* b4: PIPE4 */
+#define M66592_BEMP3           0x0008  /* b3: PIPE3 */
+#define M66592_BEMP2           0x0004  /* b2: PIPE2 */
+#define M66592_BEMP1           0x0002  /* b1: PIPE1 */
+#define M66592_BEMP0           0x0001  /* b0: PIPE0 */
 
 #define M66592_SOFCFG          0x3C
-#define        M66592_SOFM             0x000C  /* b3-2: SOF palse mode */
-#define          M66592_SOF_125US       0x0008           /* SOF OUT 125us uFrame Signal */
-#define          M66592_SOF_1MS         0x0004           /* SOF OUT 1ms Frame Signal */
-#define          M66592_SOF_DISABLE     0x0000           /* SOF OUT Disable */
+#define M66592_SOFM            0x000C  /* b3-2: SOF palse mode */
+#define   M66592_SOF_125US      0x0008   /* SOF OUT 125us uFrame Signal */
+#define   M66592_SOF_1MS        0x0004   /* SOF OUT 1ms Frame Signal */
+#define   M66592_SOF_DISABLE    0x0000   /* SOF OUT Disable */
 
 #define M66592_INTSTS0         0x40
-#define        M66592_VBINT            0x8000  /* b15: VBUS interrupt */
-#define        M66592_RESM             0x4000  /* b14: Resume interrupt */
-#define        M66592_SOFR             0x2000  /* b13: SOF frame update interrupt */
-#define        M66592_DVST             0x1000  /* b12: Device state transition interrupt */
-#define        M66592_CTRT             0x0800  /* b11: Control transfer stage transition interrupt */
-#define        M66592_BEMP             0x0400  /* b10: Buffer empty interrupt */
-#define        M66592_NRDY             0x0200  /* b9: Buffer not ready interrupt */
-#define        M66592_BRDY             0x0100  /* b8: Buffer ready interrupt */
-#define        M66592_VBSTS            0x0080  /* b7: VBUS input port */
-#define        M66592_DVSQ             0x0070  /* b6-4: Device state */
-#define          M66592_DS_SPD_CNFG     0x0070           /* Suspend Configured */
-#define          M66592_DS_SPD_ADDR     0x0060           /* Suspend Address */
-#define          M66592_DS_SPD_DFLT     0x0050           /* Suspend Default */
-#define          M66592_DS_SPD_POWR     0x0040           /* Suspend Powered */
-#define          M66592_DS_SUSP         0x0040           /* Suspend */
-#define          M66592_DS_CNFG         0x0030           /* Configured */
-#define          M66592_DS_ADDS         0x0020           /* Address */
-#define          M66592_DS_DFLT         0x0010           /* Default */
-#define          M66592_DS_POWR         0x0000           /* Powered */
-#define        M66592_DVSQS            0x0030  /* b5-4: Device state */
-#define        M66592_VALID            0x0008  /* b3: Setup packet detected flag */
-#define        M66592_CTSQ             0x0007  /* b2-0: Control transfer stage */
-#define          M66592_CS_SQER         0x0006           /* Sequence error */
-#define          M66592_CS_WRND         0x0005           /* Control write nodata status stage */
-#define          M66592_CS_WRSS         0x0004           /* Control write status stage */
-#define          M66592_CS_WRDS         0x0003           /* Control write data stage */
-#define          M66592_CS_RDSS         0x0002           /* Control read status stage */
-#define          M66592_CS_RDDS         0x0001           /* Control read data stage */
-#define          M66592_CS_IDST         0x0000           /* Idle or setup stage */
+#define M66592_VBINT           0x8000  /* b15: VBUS interrupt */
+#define M66592_RESM            0x4000  /* b14: Resume interrupt */
+#define M66592_SOFR            0x2000  /* b13: SOF frame update interrupt */
+#define M66592_DVST            0x1000  /* b12: Device state transition */
+#define M66592_CTRT            0x0800  /* b11: Control stage transition */
+#define M66592_BEMP            0x0400  /* b10: Buffer empty interrupt */
+#define M66592_NRDY            0x0200  /* b9: Buffer not ready interrupt */
+#define M66592_BRDY            0x0100  /* b8: Buffer ready interrupt */
+#define M66592_VBSTS           0x0080  /* b7: VBUS input port */
+#define M66592_DVSQ            0x0070  /* b6-4: Device state */
+#define   M66592_DS_SPD_CNFG    0x0070    /* Suspend Configured */
+#define   M66592_DS_SPD_ADDR    0x0060    /* Suspend Address */
+#define   M66592_DS_SPD_DFLT    0x0050    /* Suspend Default */
+#define   M66592_DS_SPD_POWR    0x0040    /* Suspend Powered */
+#define   M66592_DS_SUSP        0x0040    /* Suspend */
+#define   M66592_DS_CNFG        0x0030    /* Configured */
+#define   M66592_DS_ADDS        0x0020    /* Address */
+#define   M66592_DS_DFLT        0x0010    /* Default */
+#define   M66592_DS_POWR        0x0000    /* Powered */
+#define M66592_DVSQS           0x0030  /* b5-4: Device state */
+#define M66592_VALID           0x0008  /* b3: Setup packet detected flag */
+#define M66592_CTSQ            0x0007  /* b2-0: Control transfer stage */
+#define   M66592_CS_SQER        0x0006   /* Sequence error */
+#define   M66592_CS_WRND        0x0005   /* Control write nodata status */
+#define   M66592_CS_WRSS        0x0004   /* Control write status stage */
+#define   M66592_CS_WRDS        0x0003   /* Control write data stage */
+#define   M66592_CS_RDSS        0x0002   /* Control read status stage */
+#define   M66592_CS_RDDS        0x0001   /* Control read data stage */
+#define   M66592_CS_IDST        0x0000   /* Idle or setup stage */
 
 #define M66592_INTSTS1         0x42
-#define        M66592_BCHG             0x4000  /* b14: USB bus chenge interrupt */
-#define        M66592_DTCH             0x1000  /* b12: Detach sense interrupt */
-#define        M66592_SIGN             0x0020  /* b5: SETUP IGNORE interrupt */
-#define        M66592_SACK             0x0010  /* b4: SETUP ACK interrupt */
+#define M66592_BCHG            0x4000  /* b14: USB bus chenge interrupt */
+#define M66592_DTCH            0x1000  /* b12: Detach sense interrupt */
+#define M66592_SIGN            0x0020  /* b5: SETUP IGNORE interrupt */
+#define M66592_SACK            0x0010  /* b4: SETUP ACK interrupt */
 
 #define M66592_FRMNUM          0x4C
-#define        M66592_OVRN             0x8000  /* b15: Overrun error */
-#define        M66592_CRCE             0x4000  /* b14: Received data error */
-#define        M66592_SOFRM            0x0800  /* b11: SOF output mode */
-#define        M66592_FRNM             0x07FF  /* b10-0: Frame number */
+#define M66592_OVRN            0x8000  /* b15: Overrun error */
+#define M66592_CRCE            0x4000  /* b14: Received data error */
+#define M66592_SOFRM           0x0800  /* b11: SOF output mode */
+#define M66592_FRNM            0x07FF  /* b10-0: Frame number */
 
 #define M66592_UFRMNUM         0x4E
-#define        M66592_UFRNM            0x0007  /* b2-0: Micro frame number */
+#define M66592_UFRNM           0x0007  /* b2-0: Micro frame number */
 
 #define M66592_RECOVER         0x50
-#define        M66592_STSRECOV         0x0700  /* Status recovery */
-#define          M66592_STSR_HI         0x0400           /* FULL(0) or HI(1) Speed */
-#define          M66592_STSR_DEFAULT    0x0100           /* Default state */
-#define          M66592_STSR_ADDRESS    0x0200           /* Address state */
-#define          M66592_STSR_CONFIG     0x0300           /* Configured state */
-#define        M66592_USBADDR          0x007F  /* b6-0: USB address */
+#define M66592_STSRECOV                0x0700  /* Status recovery */
+#define   M66592_STSR_HI        0x0400           /* FULL(0) or HI(1) Speed */
+#define   M66592_STSR_DEFAULT   0x0100           /* Default state */
+#define   M66592_STSR_ADDRESS   0x0200           /* Address state */
+#define   M66592_STSR_CONFIG    0x0300           /* Configured state */
+#define M66592_USBADDR         0x007F  /* b6-0: USB address */
 
 #define M66592_USBREQ                  0x54
-#define        M66592_bRequest                 0xFF00  /* b15-8: bRequest */
-#define          M66592_GET_STATUS              0x0000
-#define          M66592_CLEAR_FEATURE           0x0100
-#define          M66592_ReqRESERVED             0x0200
-#define          M66592_SET_FEATURE             0x0300
-#define          M66592_ReqRESERVED1            0x0400
-#define          M66592_SET_ADDRESS             0x0500
-#define          M66592_GET_DESCRIPTOR          0x0600
-#define          M66592_SET_DESCRIPTOR          0x0700
-#define          M66592_GET_CONFIGURATION       0x0800
-#define          M66592_SET_CONFIGURATION       0x0900
-#define          M66592_GET_INTERFACE           0x0A00
-#define          M66592_SET_INTERFACE           0x0B00
-#define          M66592_SYNCH_FRAME             0x0C00
-#define        M66592_bmRequestType            0x00FF  /* b7-0: bmRequestType */
-#define        M66592_bmRequestTypeDir         0x0080  /* b7  : Data transfer direction */
-#define          M66592_HOST_TO_DEVICE          0x0000
-#define          M66592_DEVICE_TO_HOST          0x0080
-#define        M66592_bmRequestTypeType        0x0060  /* b6-5: Type */
-#define          M66592_STANDARD                0x0000
-#define          M66592_CLASS                   0x0020
-#define          M66592_VENDOR                  0x0040
-#define        M66592_bmRequestTypeRecip       0x001F  /* b4-0: Recipient */
-#define          M66592_DEVICE                  0x0000
-#define          M66592_INTERFACE               0x0001
-#define          M66592_ENDPOINT                0x0002
+#define M66592_bRequest                        0xFF00  /* b15-8: bRequest */
+#define   M66592_GET_STATUS             0x0000
+#define   M66592_CLEAR_FEATURE          0x0100
+#define   M66592_ReqRESERVED            0x0200
+#define   M66592_SET_FEATURE            0x0300
+#define   M66592_ReqRESERVED1           0x0400
+#define   M66592_SET_ADDRESS            0x0500
+#define   M66592_GET_DESCRIPTOR                 0x0600
+#define   M66592_SET_DESCRIPTOR                 0x0700
+#define   M66592_GET_CONFIGURATION      0x0800
+#define   M66592_SET_CONFIGURATION      0x0900
+#define   M66592_GET_INTERFACE          0x0A00
+#define   M66592_SET_INTERFACE          0x0B00
+#define   M66592_SYNCH_FRAME            0x0C00
+#define M66592_bmRequestType           0x00FF  /* b7-0: bmRequestType */
+#define M66592_bmRequestTypeDir                0x0080  /* b7  : Data direction */
+#define   M66592_HOST_TO_DEVICE                 0x0000
+#define   M66592_DEVICE_TO_HOST                 0x0080
+#define M66592_bmRequestTypeType       0x0060  /* b6-5: Type */
+#define   M66592_STANDARD               0x0000
+#define   M66592_CLASS                  0x0020
+#define   M66592_VENDOR                         0x0040
+#define M66592_bmRequestTypeRecip      0x001F  /* b4-0: Recipient */
+#define   M66592_DEVICE                         0x0000
+#define   M66592_INTERFACE              0x0001
+#define   M66592_ENDPOINT               0x0002
 
 #define M66592_USBVAL                          0x56
-#define        M66592_wValue                           0xFFFF  /* b15-0: wValue */
+#define M66592_wValue                          0xFFFF  /* b15-0: wValue */
 /* Standard Feature Selector */
-#define          M66592_ENDPOINT_HALT                  0x0000
-#define          M66592_DEVICE_REMOTE_WAKEUP           0x0001
-#define          M66592_TEST_MODE                      0x0002
+#define   M66592_ENDPOINT_HALT                 0x0000
+#define   M66592_DEVICE_REMOTE_WAKEUP          0x0001
+#define   M66592_TEST_MODE                     0x0002
 /* Descriptor Types */
-#define        M66592_DT_TYPE                          0xFF00
-#define        M66592_GET_DT_TYPE(v)                   (((v) & DT_TYPE) >> 8)
-#define          M66592_DT_DEVICE                      0x01
-#define          M66592_DT_CONFIGURATION               0x02
-#define          M66592_DT_STRING                      0x03
-#define          M66592_DT_INTERFACE                   0x04
-#define          M66592_DT_ENDPOINT                    0x05
-#define          M66592_DT_DEVICE_QUALIFIER            0x06
-#define          M66592_DT_OTHER_SPEED_CONFIGURATION   0x07
-#define          M66592_DT_INTERFACE_POWER             0x08
-#define        M66592_DT_INDEX                         0x00FF
-#define        M66592_CONF_NUM                         0x00FF
-#define        M66592_ALT_SET                          0x00FF
+#define M66592_DT_TYPE                         0xFF00
+#define M66592_GET_DT_TYPE(v)                  (((v) & DT_TYPE) >> 8)
+#define   M66592_DT_DEVICE                     0x01
+#define   M66592_DT_CONFIGURATION              0x02
+#define   M66592_DT_STRING                     0x03
+#define   M66592_DT_INTERFACE                  0x04
+#define   M66592_DT_ENDPOINT                   0x05
+#define   M66592_DT_DEVICE_QUALIFIER           0x06
+#define   M66592_DT_OTHER_SPEED_CONFIGURATION  0x07
+#define   M66592_DT_INTERFACE_POWER            0x08
+#define M66592_DT_INDEX                                0x00FF
+#define M66592_CONF_NUM                                0x00FF
+#define M66592_ALT_SET                         0x00FF
 
 #define M66592_USBINDEX                        0x58
-#define        M66592_wIndex                   0xFFFF  /* b15-0: wIndex */
-#define        M66592_TEST_SELECT              0xFF00  /* b15-b8: Test Mode Selectors */
-#define          M66592_TEST_J                  0x0100           /* Test_J */
-#define          M66592_TEST_K                  0x0200           /* Test_K */
-#define          M66592_TEST_SE0_NAK            0x0300           /* Test_SE0_NAK */
-#define          M66592_TEST_PACKET             0x0400           /* Test_Packet */
-#define          M66592_TEST_FORCE_ENABLE       0x0500           /* Test_Force_Enable */
-#define          M66592_TEST_STSelectors        0x0600           /* Standard test selectors */
-#define          M66592_TEST_Reserved           0x4000           /* Reserved */
-#define          M66592_TEST_VSTModes           0xC000           /* Vendor-specific test modes */
-#define        M66592_EP_DIR                   0x0080  /* b7: Endpoint Direction */
-#define          M66592_EP_DIR_IN               0x0080
-#define          M66592_EP_DIR_OUT              0x0000
+#define M66592_wIndex                  0xFFFF  /* b15-0: wIndex */
+#define M66592_TEST_SELECT             0xFF00  /* b15-b8: Test Mode */
+#define   M66592_TEST_J                         0x0100   /* Test_J */
+#define   M66592_TEST_K                         0x0200   /* Test_K */
+#define   M66592_TEST_SE0_NAK           0x0300   /* Test_SE0_NAK */
+#define   M66592_TEST_PACKET            0x0400   /* Test_Packet */
+#define   M66592_TEST_FORCE_ENABLE      0x0500   /* Test_Force_Enable */
+#define   M66592_TEST_STSelectors       0x0600   /* Standard test selectors */
+#define   M66592_TEST_Reserved          0x4000   /* Reserved */
+#define   M66592_TEST_VSTModes          0xC000   /* Vendor-specific tests */
+#define M66592_EP_DIR                  0x0080  /* b7: Endpoint Direction */
+#define   M66592_EP_DIR_IN              0x0080
+#define   M66592_EP_DIR_OUT             0x0000
 
 #define M66592_USBLENG         0x5A
-#define        M66592_wLength          0xFFFF  /* b15-0: wLength */
+#define M66592_wLength         0xFFFF  /* b15-0: wLength */
 
 #define M66592_DCPCFG          0x5C
-#define        M66592_CNTMD            0x0100  /* b8: Continuous transfer mode select */
-#define        M66592_DIR              0x0010  /* b4: Control transfer DIR select */
+#define M66592_CNTMD           0x0100  /* b8: Continuous transfer mode */
+#define M66592_DIR             0x0010  /* b4: Control transfer DIR select */
 
 #define M66592_DCPMAXP         0x5E
-#define        M66592_DEVSEL           0xC000  /* b15-14: Device address select */
-#define          M66592_DEVICE_0        0x0000           /* Device address 0 */
-#define          M66592_DEVICE_1        0x4000           /* Device address 1 */
-#define          M66592_DEVICE_2        0x8000           /* Device address 2 */
-#define          M66592_DEVICE_3        0xC000           /* Device address 3 */
-#define        M66592_MAXP             0x007F  /* b6-0: Maxpacket size of default control pipe */
+#define M66592_DEVSEL          0xC000  /* b15-14: Device address select */
+#define   M66592_DEVICE_0       0x0000           /* Device address 0 */
+#define   M66592_DEVICE_1       0x4000           /* Device address 1 */
+#define   M66592_DEVICE_2       0x8000           /* Device address 2 */
+#define   M66592_DEVICE_3       0xC000           /* Device address 3 */
+#define M66592_MAXP            0x007F  /* b6-0: Maxpacket size of ep0 */
 
 #define M66592_DCPCTR          0x60
-#define        M66592_BSTS             0x8000  /* b15: Buffer status */
-#define        M66592_SUREQ            0x4000  /* b14: Send USB request  */
-#define        M66592_SQCLR            0x0100  /* b8: Sequence toggle bit clear */
-#define        M66592_SQSET            0x0080  /* b7: Sequence toggle bit set */
-#define        M66592_SQMON            0x0040  /* b6: Sequence toggle bit monitor */
-#define        M66592_CCPL             0x0004  /* b2: Enable control transfer complete */
-#define        M66592_PID              0x0003  /* b1-0: Response PID */
-#define          M66592_PID_STALL       0x0002           /* STALL */
-#define          M66592_PID_BUF         0x0001           /* BUF */
-#define          M66592_PID_NAK         0x0000           /* NAK */
+#define M66592_BSTS            0x8000  /* b15: Buffer status */
+#define M66592_SUREQ           0x4000  /* b14: Send USB request  */
+#define M66592_SQCLR           0x0100  /* b8: Sequence toggle bit clear */
+#define M66592_SQSET           0x0080  /* b7: Sequence toggle bit set */
+#define M66592_SQMON           0x0040  /* b6: Sequence toggle bit monitor */
+#define M66592_CCPL            0x0004  /* b2: control transfer complete */
+#define M66592_PID             0x0003  /* b1-0: Response PID */
+#define   M66592_PID_STALL      0x0002           /* STALL */
+#define   M66592_PID_BUF        0x0001           /* BUF */
+#define   M66592_PID_NAK        0x0000           /* NAK */
 
 #define M66592_PIPESEL         0x64
-#define        M66592_PIPENM           0x0007  /* b2-0: Pipe select */
-#define          M66592_PIPE0           0x0000           /* PIPE 0 */
-#define          M66592_PIPE1           0x0001           /* PIPE 1 */
-#define          M66592_PIPE2           0x0002           /* PIPE 2 */
-#define          M66592_PIPE3           0x0003           /* PIPE 3 */
-#define          M66592_PIPE4           0x0004           /* PIPE 4 */
-#define          M66592_PIPE5           0x0005           /* PIPE 5 */
-#define          M66592_PIPE6           0x0006           /* PIPE 6 */
-#define          M66592_PIPE7           0x0007           /* PIPE 7 */
+#define M66592_PIPENM          0x0007  /* b2-0: Pipe select */
+#define   M66592_PIPE0          0x0000           /* PIPE 0 */
+#define   M66592_PIPE1          0x0001           /* PIPE 1 */
+#define   M66592_PIPE2          0x0002           /* PIPE 2 */
+#define   M66592_PIPE3          0x0003           /* PIPE 3 */
+#define   M66592_PIPE4          0x0004           /* PIPE 4 */
+#define   M66592_PIPE5          0x0005           /* PIPE 5 */
+#define   M66592_PIPE6          0x0006           /* PIPE 6 */
+#define   M66592_PIPE7          0x0007           /* PIPE 7 */
 
 #define M66592_PIPECFG         0x66
-#define        M66592_TYP              0xC000  /* b15-14: Transfer type */
-#define          M66592_ISO             0xC000           /* Isochronous */
-#define          M66592_INT             0x8000           /* Interrupt */
-#define          M66592_BULK            0x4000           /* Bulk */
-#define        M66592_BFRE             0x0400  /* b10: Buffer ready interrupt mode select */
-#define        M66592_DBLB             0x0200  /* b9: Double buffer mode select */
-#define        M66592_CNTMD            0x0100  /* b8: Continuous transfer mode select */
-#define        M66592_SHTNAK           0x0080  /* b7: Transfer end NAK */
-#define        M66592_DIR              0x0010  /* b4: Transfer direction select */
-#define          M66592_DIR_H_OUT       0x0010           /* HOST OUT */
-#define          M66592_DIR_P_IN        0x0010           /* PERI IN */
-#define          M66592_DIR_H_IN        0x0000           /* HOST IN */
-#define          M66592_DIR_P_OUT       0x0000           /* PERI OUT */
-#define        M66592_EPNUM            0x000F  /* b3-0: Eendpoint number select */
-#define          M66592_EP1             0x0001
-#define          M66592_EP2             0x0002
-#define          M66592_EP3             0x0003
-#define          M66592_EP4             0x0004
-#define          M66592_EP5             0x0005
-#define          M66592_EP6             0x0006
-#define          M66592_EP7             0x0007
-#define          M66592_EP8             0x0008
-#define          M66592_EP9             0x0009
-#define          M66592_EP10            0x000A
-#define          M66592_EP11            0x000B
-#define          M66592_EP12            0x000C
-#define          M66592_EP13            0x000D
-#define          M66592_EP14            0x000E
-#define          M66592_EP15            0x000F
+#define M66592_TYP             0xC000  /* b15-14: Transfer type */
+#define   M66592_ISO            0xC000           /* Isochronous */
+#define   M66592_INT            0x8000           /* Interrupt */
+#define   M66592_BULK           0x4000           /* Bulk */
+#define M66592_BFRE            0x0400  /* b10: Buffer ready interrupt mode */
+#define M66592_DBLB            0x0200  /* b9: Double buffer mode select */
+#define M66592_CNTMD           0x0100  /* b8: Continuous transfer mode */
+#define M66592_SHTNAK          0x0080  /* b7: Transfer end NAK */
+#define M66592_DIR             0x0010  /* b4: Transfer direction select */
+#define   M66592_DIR_H_OUT      0x0010           /* HOST OUT */
+#define   M66592_DIR_P_IN       0x0010           /* PERI IN */
+#define   M66592_DIR_H_IN       0x0000           /* HOST IN */
+#define   M66592_DIR_P_OUT      0x0000           /* PERI OUT */
+#define M66592_EPNUM           0x000F  /* b3-0: Eendpoint number select */
+#define   M66592_EP1            0x0001
+#define   M66592_EP2            0x0002
+#define   M66592_EP3            0x0003
+#define   M66592_EP4            0x0004
+#define   M66592_EP5            0x0005
+#define   M66592_EP6            0x0006
+#define   M66592_EP7            0x0007
+#define   M66592_EP8            0x0008
+#define   M66592_EP9            0x0009
+#define   M66592_EP10           0x000A
+#define   M66592_EP11           0x000B
+#define   M66592_EP12           0x000C
+#define   M66592_EP13           0x000D
+#define   M66592_EP14           0x000E
+#define   M66592_EP15           0x000F
 
 #define M66592_PIPEBUF         0x68
-#define        M66592_BUFSIZE          0x7C00  /* b14-10: Pipe buffer size */
-#define        M66592_BUF_SIZE(x)      ((((x) / 64) - 1) << 10)
-#define        M66592_BUFNMB           0x00FF  /* b7-0: Pipe buffer number */
+#define M66592_BUFSIZE         0x7C00  /* b14-10: Pipe buffer size */
+#define M66592_BUF_SIZE(x)     ((((x) / 64) - 1) << 10)
+#define M66592_BUFNMB          0x00FF  /* b7-0: Pipe buffer number */
 
 #define M66592_PIPEMAXP                0x6A
-#define        M66592_MXPS             0x07FF  /* b10-0: Maxpacket size */
+#define M66592_MXPS            0x07FF  /* b10-0: Maxpacket size */
 
 #define M66592_PIPEPERI                0x6C
-#define        M66592_IFIS             0x1000  /* b12: Isochronous in-buffer flush mode select */
-#define        M66592_IITV             0x0007  /* b2-0: Isochronous interval */
+#define M66592_IFIS            0x1000  /* b12: ISO in-buffer flush mode */
+#define M66592_IITV            0x0007  /* b2-0: ISO interval */
 
 #define M66592_PIPE1CTR                0x70
 #define M66592_PIPE2CTR                0x72
 #define M66592_PIPE5CTR                0x78
 #define M66592_PIPE6CTR                0x7A
 #define M66592_PIPE7CTR                0x7C
-#define        M66592_BSTS             0x8000  /* b15: Buffer status */
-#define        M66592_INBUFM           0x4000  /* b14: IN buffer monitor (Only for PIPE1 to 5) */
-#define        M66592_ACLRM            0x0200  /* b9: Out buffer auto clear mode */
-#define        M66592_SQCLR            0x0100  /* b8: Sequence toggle bit clear */
-#define        M66592_SQSET            0x0080  /* b7: Sequence toggle bit set */
-#define        M66592_SQMON            0x0040  /* b6: Sequence toggle bit monitor */
-#define        M66592_PID              0x0003  /* b1-0: Response PID */
+#define M66592_BSTS            0x8000  /* b15: Buffer status */
+#define M66592_INBUFM          0x4000  /* b14: IN buffer monitor (PIPE 1-5) */
+#define M66592_ACLRM           0x0200  /* b9: Out buffer auto clear mode */
+#define M66592_SQCLR           0x0100  /* b8: Sequence toggle bit clear */
+#define M66592_SQSET           0x0080  /* b7: Sequence toggle bit set */
+#define M66592_SQMON           0x0040  /* b6: Sequence toggle bit monitor */
+#define M66592_PID             0x0003  /* b1-0: Response PID */
 
 #define M66592_INVALID_REG     0x7E
 
 
-#define __iomem
-
 #define get_pipectr_addr(pipenum)      (M66592_PIPE1CTR + (pipenum - 1) * 2)
 
 #define M66592_MAX_SAMPLING    10
@@ -449,7 +447,7 @@ struct m66592_ep {
        struct m66592           *m66592;
 
        struct list_head        queue;
-       unsigned                busy:1;
+       unsigned                busy:1;
        unsigned                internal_ccpl:1;        /* use only control */
 
        /* this member can able to after m66592_enable */
@@ -477,7 +475,7 @@ struct m66592 {
        struct m66592_ep        *epaddr2ep[16];
 
        struct usb_request      *ep0_req;       /* for internal request */
-       u16                     *ep0_buf;       /* for internal request */
+       u16                     ep0_data;       /* for internal request */
 
        struct timer_list       timer;
 
@@ -527,8 +525,8 @@ static inline u16 m66592_read(struct m66592 *m66592, unsigned long offset)
 }
 
 static inline void m66592_read_fifo(struct m66592 *m66592,
-                                   unsigned long offset,
-                                   void *buf, unsigned long len)
+               unsigned long offset,
+               void *buf, unsigned long len)
 {
        unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
 
@@ -543,8 +541,8 @@ static inline void m66592_write(struct m66592 *m66592, u16 val,
 }
 
 static inline void m66592_write_fifo(struct m66592 *m66592,
-                                    unsigned long offset,
-                                    void *buf, unsigned long len)
+               unsigned long offset,
+               void *buf, unsigned long len)
 {
        unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
        unsigned long odd = len & 0x0001;
@@ -558,7 +556,7 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
 }
 
 static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
-                              unsigned long offset)
+               unsigned long offset)
 {
        u16 tmp;
        tmp = m66592_read(m66592, offset);
index 38138bb9ddb08835039534ba0b006c40972d353b..9cd98e73dc1d7e5e73876a874b393305e31dcebf 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/device.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
+#include <linux/mutex.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -258,7 +259,7 @@ static const char *EP_IN_NAME;
 static const char *EP_OUT_NAME;
 static const char *EP_NOTIFY_NAME;
 
-static struct semaphore        gs_open_close_sem[GS_NUM_PORTS];
+static struct mutex gs_open_close_lock[GS_NUM_PORTS];
 
 static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE;
 static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE;
@@ -595,7 +596,7 @@ static int __init gs_module_init(void)
        tty_set_operations(gs_tty_driver, &gs_tty_ops);
 
        for (i=0; i < GS_NUM_PORTS; i++)
-               sema_init(&gs_open_close_sem[i], 1);
+               mutex_init(&gs_open_close_lock[i]);
 
        retval = tty_register_driver(gs_tty_driver);
        if (retval) {
@@ -635,7 +636,7 @@ static int gs_open(struct tty_struct *tty, struct file *file)
        struct gs_port *port;
        struct gs_dev *dev;
        struct gs_buf *buf;
-       struct semaphore *sem;
+       struct mutex *mtx;
        int ret;
 
        port_num = tty->index;
@@ -656,10 +657,10 @@ static int gs_open(struct tty_struct *tty, struct file *file)
                return -ENODEV;
        }
 
-       sem = &gs_open_close_sem[port_num];
-       if (down_interruptible(sem)) {
+       mtx = &gs_open_close_lock[port_num];
+       if (mutex_lock_interruptible(mtx)) {
                printk(KERN_ERR
-               "gs_open: (%d,%p,%p) interrupted waiting for semaphore\n",
+               "gs_open: (%d,%p,%p) interrupted waiting for mutex\n",
                        port_num, tty, file);
                return -ERESTARTSYS;
        }
@@ -754,12 +755,12 @@ static int gs_open(struct tty_struct *tty, struct file *file)
 
 exit_unlock_port:
        spin_unlock_irqrestore(&port->port_lock, flags);
-       up(sem);
+       mutex_unlock(mtx);
        return ret;
 
 exit_unlock_dev:
        spin_unlock_irqrestore(&dev->dev_lock, flags);
-       up(sem);
+       mutex_unlock(mtx);
        return ret;
 
 }
@@ -781,7 +782,7 @@ exit_unlock_dev:
 static void gs_close(struct tty_struct *tty, struct file *file)
 {
        struct gs_port *port = tty->driver_data;
-       struct semaphore *sem;
+       struct mutex *mtx;
 
        if (port == NULL) {
                printk(KERN_ERR "gs_close: NULL port pointer\n");
@@ -790,8 +791,8 @@ static void gs_close(struct tty_struct *tty, struct file *file)
 
        gs_debug("gs_close: (%d,%p,%p)\n", port->port_num, tty, file);
 
-       sem = &gs_open_close_sem[port->port_num];
-       down(sem);
+       mtx = &gs_open_close_lock[port->port_num];
+       mutex_lock(mtx);
 
        spin_lock_irq(&port->port_lock);
 
@@ -846,7 +847,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
 
 exit:
        spin_unlock_irq(&port->port_lock);
-       up(sem);
+       mutex_unlock(mtx);
 }
 
 /*
index 46873f2534b5d152d3b277e424a5c046ae402b3f..5c851a36de722e36d67fb65128219213d95d0235 100644 (file)
@@ -228,7 +228,6 @@ static void preproc_atl_queue(struct isp116x *isp116x)
                                   struct urb, urb_list);
                ptd = &ep->ptd;
                len = ep->length;
-               spin_lock(&urb->lock);
                ep->data = (unsigned char *)urb->transfer_buffer
                    + urb->actual_length;
 
@@ -264,7 +263,6 @@ static void preproc_atl_queue(struct isp116x *isp116x)
                    | PTD_EP(ep->epnum);
                ptd->len = PTD_LEN(len) | PTD_DIR(dir);
                ptd->faddr = PTD_FA(usb_pipedevice(urb->pipe));
-               spin_unlock(&urb->lock);
                if (!ep->active) {
                        ptd->mps |= PTD_LAST_MSK;
                        isp116x->atl_last_dir = dir;
@@ -274,6 +272,61 @@ static void preproc_atl_queue(struct isp116x *isp116x)
        }
 }
 
+/*
+  Take done or failed requests out of schedule. Give back
+  processed urbs.
+*/
+static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep,
+                          struct urb *urb)
+__releases(isp116x->lock) __acquires(isp116x->lock)
+{
+       unsigned i;
+
+       urb->hcpriv = NULL;
+       ep->error_count = 0;
+
+       if (usb_pipecontrol(urb->pipe))
+               ep->nextpid = USB_PID_SETUP;
+
+       urb_dbg(urb, "Finish");
+
+       spin_unlock(&isp116x->lock);
+       usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb);
+       spin_lock(&isp116x->lock);
+
+       /* take idle endpoints out of the schedule */
+       if (!list_empty(&ep->hep->urb_list))
+               return;
+
+       /* async deschedule */
+       if (!list_empty(&ep->schedule)) {
+               list_del_init(&ep->schedule);
+               return;
+       }
+
+       /* periodic deschedule */
+       DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);
+       for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) {
+               struct isp116x_ep *temp;
+               struct isp116x_ep **prev = &isp116x->periodic[i];
+
+               while (*prev && ((temp = *prev) != ep))
+                       prev = &temp->next;
+               if (*prev)
+                       *prev = ep->next;
+               isp116x->load[i] -= ep->load;
+       }
+       ep->branch = PERIODIC_SIZE;
+       isp116x_to_hcd(isp116x)->self.bandwidth_allocated -=
+           ep->load / ep->period;
+
+       /* switch irq type? */
+       if (!--isp116x->periodic_count) {
+               isp116x->irqenb &= ~HCuPINT_SOF;
+               isp116x->irqenb |= HCuPINT_ATL;
+       }
+}
+
 /*
   Analyze transfer results, handle partial transfers and errors
 */
@@ -284,6 +337,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
        struct usb_device *udev;
        struct ptd *ptd;
        int short_not_ok;
+       int status;
        u8 cc;
 
        for (ep = isp116x->atl_active; ep; ep = ep->active) {
@@ -294,7 +348,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
                ptd = &ep->ptd;
                cc = PTD_GET_CC(ptd);
                short_not_ok = 1;
-               spin_lock(&urb->lock);
+               status = -EINPROGRESS;
 
                /* Data underrun is special. For allowed underrun
                   we clear the error and continue as normal. For
@@ -302,47 +356,36 @@ static void postproc_atl_queue(struct isp116x *isp116x)
                   immediately while for control transfer,
                   we do a STATUS stage. */
                if (cc == TD_DATAUNDERRUN) {
-                       if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) {
-                               DBG("Allowed data underrun\n");
+                       if (!(urb->transfer_flags & URB_SHORT_NOT_OK) ||
+                                       usb_pipecontrol(urb->pipe)) {
+                               DBG("Allowed or control data underrun\n");
                                cc = TD_CC_NOERROR;
                                short_not_ok = 0;
                        } else {
                                ep->error_count = 1;
-                               if (usb_pipecontrol(urb->pipe))
-                                       ep->nextpid = USB_PID_ACK;
-                               else
-                                       usb_settoggle(udev, ep->epnum,
-                                                     ep->nextpid ==
-                                                     USB_PID_OUT,
-                                                     PTD_GET_TOGGLE(ptd));
+                               usb_settoggle(udev, ep->epnum,
+                                             ep->nextpid == USB_PID_OUT,
+                                             PTD_GET_TOGGLE(ptd));
                                urb->actual_length += PTD_GET_COUNT(ptd);
-                               urb->status = cc_to_error[TD_DATAUNDERRUN];
-                               spin_unlock(&urb->lock);
-                               continue;
+                               status = cc_to_error[TD_DATAUNDERRUN];
+                               goto done;
                        }
                }
-               /* Keep underrun error through the STATUS stage */
-               if (urb->status == cc_to_error[TD_DATAUNDERRUN])
-                       cc = TD_DATAUNDERRUN;
 
                if (cc != TD_CC_NOERROR && cc != TD_NOTACCESSED
                    && (++ep->error_count >= 3 || cc == TD_CC_STALL
                        || cc == TD_DATAOVERRUN)) {
-                       if (urb->status == -EINPROGRESS)
-                               urb->status = cc_to_error[cc];
+                       status = cc_to_error[cc];
                        if (ep->nextpid == USB_PID_ACK)
                                ep->nextpid = 0;
-                       spin_unlock(&urb->lock);
-                       continue;
+                       goto done;
                }
                /* According to usb spec, zero-length Int transfer signals
                   finishing of the urb. Hey, does this apply only
                   for IN endpoints? */
                if (usb_pipeint(urb->pipe) && !PTD_GET_LEN(ptd)) {
-                       if (urb->status == -EINPROGRESS)
-                               urb->status = 0;
-                       spin_unlock(&urb->lock);
-                       continue;
+                       status = 0;
+                       goto done;
                }
 
                /* Relax after previously failed, but later succeeded
@@ -381,8 +424,8 @@ static void postproc_atl_queue(struct isp116x *isp116x)
                        /* All data for this URB is transferred, let's finish */
                        if (usb_pipecontrol(urb->pipe))
                                ep->nextpid = USB_PID_ACK;
-                       else if (urb->status == -EINPROGRESS)
-                               urb->status = 0;
+                       else
+                               status = 0;
                        break;
                case USB_PID_SETUP:
                        if (PTD_GET_ACTIVE(ptd)
@@ -402,69 +445,27 @@ static void postproc_atl_queue(struct isp116x *isp116x)
                        if (PTD_GET_ACTIVE(ptd)
                            || (cc != TD_CC_NOERROR && cc < 0x0E))
                                break;
-                       if (urb->status == -EINPROGRESS)
-                               urb->status = 0;
+                       if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
+                                       urb->actual_length <
+                                               urb->transfer_buffer_length)
+                               status = -EREMOTEIO;
+                       else
+                               status = 0;
                        ep->nextpid = 0;
                        break;
                default:
                        BUG();
                }
-               spin_unlock(&urb->lock);
-       }
-}
-
-/*
-  Take done or failed requests out of schedule. Give back
-  processed urbs.
-*/
-static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep,
-                          struct urb *urb)
-__releases(isp116x->lock) __acquires(isp116x->lock)
-{
-       unsigned i;
-
-       urb->hcpriv = NULL;
-       ep->error_count = 0;
-
-       if (usb_pipecontrol(urb->pipe))
-               ep->nextpid = USB_PID_SETUP;
-
-       urb_dbg(urb, "Finish");
-
-       spin_unlock(&isp116x->lock);
-       usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb);
-       spin_lock(&isp116x->lock);
-
-       /* take idle endpoints out of the schedule */
-       if (!list_empty(&ep->hep->urb_list))
-               return;
-
-       /* async deschedule */
-       if (!list_empty(&ep->schedule)) {
-               list_del_init(&ep->schedule);
-               return;
-       }
 
-       /* periodic deschedule */
-       DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);
-       for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) {
-               struct isp116x_ep *temp;
-               struct isp116x_ep **prev = &isp116x->periodic[i];
-
-               while (*prev && ((temp = *prev) != ep))
-                       prev = &temp->next;
-               if (*prev)
-                       *prev = ep->next;
-               isp116x->load[i] -= ep->load;
-       }
-       ep->branch = PERIODIC_SIZE;
-       isp116x_to_hcd(isp116x)->self.bandwidth_allocated -=
-           ep->load / ep->period;
-
-       /* switch irq type? */
-       if (!--isp116x->periodic_count) {
-               isp116x->irqenb &= ~HCuPINT_SOF;
-               isp116x->irqenb |= HCuPINT_ATL;
+ done:
+               if (status != -EINPROGRESS) {
+                       spin_lock(&urb->lock);
+                       if (urb->status == -EINPROGRESS)
+                               urb->status = status;
+                       spin_unlock(&urb->lock);
+               }
+               if (urb->status != -EINPROGRESS)
+                       finish_request(isp116x, ep, urb);
        }
 }
 
@@ -570,9 +571,6 @@ static void start_atl_transfers(struct isp116x *isp116x)
 */
 static void finish_atl_transfers(struct isp116x *isp116x)
 {
-       struct isp116x_ep *ep;
-       struct urb *urb;
-
        if (!isp116x->atl_active)
                return;
        /* Fifo not ready? */
@@ -582,16 +580,6 @@ static void finish_atl_transfers(struct isp116x *isp116x)
        atomic_inc(&isp116x->atl_finishing);
        unpack_fifo(isp116x);
        postproc_atl_queue(isp116x);
-       for (ep = isp116x->atl_active; ep; ep = ep->active) {
-               urb =
-                   container_of(ep->hep->urb_list.next, struct urb, urb_list);
-               /* USB_PID_ACK check here avoids finishing of
-                  control transfers, for which TD_DATAUNDERRUN
-                  occured, while URB_SHORT_NOT_OK was set */
-               if (urb && urb->status != -EINPROGRESS
-                   && ep->nextpid != USB_PID_ACK)
-                       finish_request(isp116x, ep, urb);
-       }
        atomic_dec(&isp116x->atl_finishing);
 }
 
@@ -821,15 +809,12 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
        }
 
        /* in case of unlink-during-submit */
-       spin_lock(&urb->lock);
        if (urb->status != -EINPROGRESS) {
-               spin_unlock(&urb->lock);
                finish_request(isp116x, ep, urb);
                ret = 0;
                goto fail;
        }
        urb->hcpriv = hep;
-       spin_unlock(&urb->lock);
        start_atl_transfers(isp116x);
 
       fail:
index a7a7070c6e2ac9d9d8c10d815a0c38e3169775ca..d60f1985320cfc630e107e81bd3c406a4229a083 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/usb.h>
 #include <linux/platform_device.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
+#include <linux/io.h>
+#include <linux/irq.h>
 
 #include "../core/hcd.h"
 #include "r8a66597.h"
@@ -54,16 +52,21 @@ static const char hcd_name[] = "r8a66597_hcd";
 /* module parameters */
 static unsigned short clock = XTAL12;
 module_param(clock, ushort, 0644);
-MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0(default=0)");
+MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 "
+               "(default=0)");
+
 static unsigned short vif = LDRV;
 module_param(vif, ushort, 0644);
 MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0(default=32768)");
-static unsigned short endian = 0;
+
+static unsigned short endian;
 module_param(endian, ushort, 0644);
-MODULE_PARM_DESC(endian, "data endian: big=256, little=0(default=0)");
+MODULE_PARM_DESC(endian, "data endian: big=256, little=0 (default=0)");
+
 static unsigned short irq_sense = INTL;
 module_param(irq_sense, ushort, 0644);
-MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=32, falling edge=0(default=32)");
+MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=32, falling edge=0 "
+               "(default=32)");
 
 static void packet_write(struct r8a66597 *r8a66597, u16 pipenum);
 static int r8a66597_get_frame(struct usb_hcd *hcd);
@@ -308,7 +311,7 @@ static int make_r8a66597_device(struct r8a66597 *r8a66597,
        struct r8a66597_device *dev;
        int usb_address = urb->setup_packet[2]; /* urb->pipe is address 0 */
 
-       dev = kzalloc(sizeof(struct r8a66597_device), GFP_KERNEL);
+       dev = kzalloc(sizeof(struct r8a66597_device), GFP_ATOMIC);
        if (dev == NULL)
                return -ENOMEM;
 
@@ -611,33 +614,33 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597,
        u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min;
 
        memset(array, 0, sizeof(array));
-        switch(ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
-        case USB_ENDPOINT_XFER_BULK:
+       switch (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+       case USB_ENDPOINT_XFER_BULK:
                if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
                        array[i++] = 4;
                else {
                        array[i++] = 3;
                        array[i++] = 5;
                }
-                break;
-        case USB_ENDPOINT_XFER_INT:
+               break;
+       case USB_ENDPOINT_XFER_INT:
                if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
                        array[i++] = 6;
                        array[i++] = 7;
                        array[i++] = 8;
                } else
                        array[i++] = 9;
-                break;
-        case USB_ENDPOINT_XFER_ISOC:
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
                if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
                        array[i++] = 2;
                else
                        array[i++] = 1;
-                break;
-        default:
-                err("Illegal type");
-                return 0;
-        }
+               break;
+       default:
+               err("Illegal type");
+               return 0;
+       }
 
        i = 1;
        min = array[0];
@@ -654,7 +657,7 @@ static u16 get_r8a66597_type(__u8 type)
 {
        u16 r8a66597_type;
 
-       switch(type) {
+       switch (type) {
        case USB_ENDPOINT_XFER_BULK:
                r8a66597_type = R8A66597_BULK;
                break;
@@ -874,7 +877,7 @@ static void r8a66597_usb_preconnect(struct r8a66597 *r8a66597, int port)
 {
        r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION)
                                         | (1 << USB_PORT_FEAT_C_CONNECTION);
-       r8a66597_write(r8a66597, (u16)~DTCH, get_intsts_reg(port));
+       r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port));
        r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
 }
 
@@ -917,7 +920,7 @@ static void prepare_setup_packet(struct r8a66597 *r8a66597,
 
        r8a66597_write(r8a66597, make_devsel(td->address) | td->maxpacket,
                       DCPMAXP);
-       r8a66597_write(r8a66597, (u16)~(SIGN | SACK), INTSTS1);
+       r8a66597_write(r8a66597, ~(SIGN | SACK), INTSTS1);
 
        for (i = 0; i < 4; i++) {
                r8a66597_write(r8a66597, p[i], setup_addr);
@@ -948,19 +951,18 @@ static void prepare_packet_read(struct r8a66597 *r8a66597,
                        pipe_irq_disable(r8a66597, td->pipenum);
                        pipe_setting(r8a66597, td);
                        pipe_stop(r8a66597, td->pipe);
-                       r8a66597_write(r8a66597, (u16)~(1 << td->pipenum),
-                                      BRDYSTS);
+                       r8a66597_write(r8a66597, ~(1 << td->pipenum), BRDYSTS);
 
                        if (td->pipe->pipetre) {
                                r8a66597_write(r8a66597, TRCLR,
-                                               td->pipe->pipetre);
+                                               td->pipe->pipetre);
                                r8a66597_write(r8a66597,
-                                              (urb->transfer_buffer_length
-                                              + td->maxpacket - 1)
-                                              / td->maxpacket,
-                                              td->pipe->pipetrn);
+                                               (urb->transfer_buffer_length
+                                               + td->maxpacket - 1)
+                                               / td->maxpacket,
+                                               td->pipe->pipetrn);
                                r8a66597_bset(r8a66597, TRENB,
-                                             td->pipe->pipetre);
+                                               td->pipe->pipetre);
                        }
 
                        pipe_start(r8a66597, td->pipe);
@@ -991,7 +993,7 @@ static void prepare_packet_write(struct r8a66597 *r8a66597,
                if (td->pipe->pipetre)
                        r8a66597_bclr(r8a66597, TRENB, td->pipe->pipetre);
        }
-       r8a66597_write(r8a66597, (u16)~(1 << td->pipenum), BRDYSTS);
+       r8a66597_write(r8a66597, ~(1 << td->pipenum), BRDYSTS);
 
        fifo_change_from_pipe(r8a66597, td->pipe);
        tmp = r8a66597_read(r8a66597, td->pipe->fifoctr);
@@ -1009,21 +1011,21 @@ static void prepare_status_packet(struct r8a66597 *r8a66597,
        struct urb *urb = td->urb;
 
        r8a66597_pipe_toggle(r8a66597, td->pipe, 1);
+       pipe_stop(r8a66597, td->pipe);
 
        if (urb->setup_packet[0] & USB_ENDPOINT_DIR_MASK) {
                r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG);
                r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
                r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
-               r8a66597_write(r8a66597, BVAL | BCLR, CFIFOCTR);
-               r8a66597_write(r8a66597, (u16)~BEMP0, BEMPSTS);
+               r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
+               r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+               r8a66597_write(r8a66597, BVAL, CFIFOCTR);
                enable_irq_empty(r8a66597, 0);
        } else {
                r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
                r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
                r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
                r8a66597_write(r8a66597, BCLR, CFIFOCTR);
-               r8a66597_write(r8a66597, (u16)~BRDY0, BRDYSTS);
-               r8a66597_write(r8a66597, (u16)~BEMP0, BEMPSTS);
                enable_irq_ready(r8a66597, 0);
        }
        enable_irq_nrdy(r8a66597, 0);
@@ -1269,7 +1271,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum)
 
        /* write fifo */
        if (pipenum > 0)
-               r8a66597_write(r8a66597, (u16)~(1 << pipenum), BEMPSTS);
+               r8a66597_write(r8a66597, ~(1 << pipenum), BEMPSTS);
        if (urb->transfer_buffer) {
                r8a66597_write_fifo(r8a66597, td->pipe->fifoaddr, buf, size);
                if (!usb_pipebulk(urb->pipe) || td->maxpacket != size)
@@ -1362,7 +1364,7 @@ static void irq_pipe_ready(struct r8a66597 *r8a66597)
 
        mask = r8a66597_read(r8a66597, BRDYSTS)
               & r8a66597_read(r8a66597, BRDYENB);
-       r8a66597_write(r8a66597, (u16)~mask, BRDYSTS);
+       r8a66597_write(r8a66597, ~mask, BRDYSTS);
        if (mask & BRDY0) {
                td = r8a66597_get_td(r8a66597, 0);
                if (td && td->type == USB_PID_IN)
@@ -1397,7 +1399,7 @@ static void irq_pipe_empty(struct r8a66597 *r8a66597)
 
        mask = r8a66597_read(r8a66597, BEMPSTS)
               & r8a66597_read(r8a66597, BEMPENB);
-       r8a66597_write(r8a66597, (u16)~mask, BEMPSTS);
+       r8a66597_write(r8a66597, ~mask, BEMPSTS);
        if (mask & BEMP0) {
                cfifo_change(r8a66597, 0);
                td = r8a66597_get_td(r8a66597, 0);
@@ -1434,7 +1436,7 @@ static void irq_pipe_nrdy(struct r8a66597 *r8a66597)
 
        mask = r8a66597_read(r8a66597, NRDYSTS)
               & r8a66597_read(r8a66597, NRDYENB);
-       r8a66597_write(r8a66597, (u16)~mask, NRDYSTS);
+       r8a66597_write(r8a66597, ~mask, NRDYSTS);
        if (mask & NRDY0) {
                cfifo_change(r8a66597, 0);
                set_urb_error(r8a66597, 0);
@@ -1488,14 +1490,14 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
        mask0 = intsts0 & intenb0 & (BEMP | NRDY | BRDY);
        if (mask2) {
                if (mask2 & ATTCH) {
-                       r8a66597_write(r8a66597, (u16)~ATTCH, INTSTS2);
+                       r8a66597_write(r8a66597, ~ATTCH, INTSTS2);
                        r8a66597_bclr(r8a66597, ATTCHE, INTENB2);
 
                        /* start usb bus sampling */
                        start_root_hub_sampling(r8a66597, 1);
                }
                if (mask2 & DTCH) {
-                       r8a66597_write(r8a66597, (u16)~DTCH, INTSTS2);
+                       r8a66597_write(r8a66597, ~DTCH, INTSTS2);
                        r8a66597_bclr(r8a66597, DTCHE, INTENB2);
                        r8a66597_usb_disconnect(r8a66597, 1);
                }
@@ -1503,24 +1505,24 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
 
        if (mask1) {
                if (mask1 & ATTCH) {
-                       r8a66597_write(r8a66597, (u16)~ATTCH, INTSTS1);
+                       r8a66597_write(r8a66597, ~ATTCH, INTSTS1);
                        r8a66597_bclr(r8a66597, ATTCHE, INTENB1);
 
                        /* start usb bus sampling */
                        start_root_hub_sampling(r8a66597, 0);
                }
                if (mask1 & DTCH) {
-                       r8a66597_write(r8a66597, (u16)~DTCH, INTSTS1);
+                       r8a66597_write(r8a66597, ~DTCH, INTSTS1);
                        r8a66597_bclr(r8a66597, DTCHE, INTENB1);
                        r8a66597_usb_disconnect(r8a66597, 0);
                }
                if (mask1 & SIGN) {
-                       r8a66597_write(r8a66597, (u16)~SIGN, INTSTS1);
+                       r8a66597_write(r8a66597, ~SIGN, INTSTS1);
                        set_urb_error(r8a66597, 0);
                        check_next_phase(r8a66597);
                }
                if (mask1 & SACK) {
-                       r8a66597_write(r8a66597, (u16)~SACK, INTSTS1);
+                       r8a66597_write(r8a66597, ~SACK, INTSTS1);
                        check_next_phase(r8a66597);
                }
        }
@@ -1663,13 +1665,9 @@ static int check_pipe_config(struct r8a66597 *r8a66597, struct urb *urb)
 static int r8a66597_start(struct usb_hcd *hcd)
 {
        struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
-       int ret;
 
        hcd->state = HC_STATE_RUNNING;
-       if ((ret = enable_controller(r8a66597)) < 0)
-               return ret;
-
-       return 0;
+       return enable_controller(r8a66597);
 }
 
 static void r8a66597_stop(struct usb_hcd *hcd)
@@ -1696,13 +1694,12 @@ static void set_address_zero(struct r8a66597 *r8a66597, struct urb *urb)
 
 static struct r8a66597_td *r8a66597_make_td(struct r8a66597 *r8a66597,
                                            struct urb *urb,
-                                           struct usb_host_endpoint *hep,
-                                           gfp_t mem_flags)
+                                           struct usb_host_endpoint *hep)
 {
        struct r8a66597_td *td;
        u16 pipenum;
 
-       td = kzalloc(sizeof(struct r8a66597_td), mem_flags);
+       td = kzalloc(sizeof(struct r8a66597_td), GFP_ATOMIC);
        if (td == NULL)
                return NULL;
 
@@ -1741,7 +1738,8 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
        }
 
        if (!hep->hcpriv) {
-               hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe), mem_flags);
+               hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe),
+                               GFP_ATOMIC);
                if (!hep->hcpriv) {
                        ret = -ENOMEM;
                        goto error;
@@ -1755,7 +1753,7 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
                init_pipe_config(r8a66597, urb);
 
        set_address_zero(r8a66597, urb);
-       td = r8a66597_make_td(r8a66597, urb, hep, mem_flags);
+       td = r8a66597_make_td(r8a66597, urb, hep);
        if (td == NULL) {
                ret = -ENOMEM;
                goto error;
index 97c2a71ac7a125dd38a4ce245ed2606d8200dfd4..fe9ceb077d9bbddaf38f7dd6998ca73d1bea7b1a 100644 (file)
 #define        DTLN            0x0FFF  /* b11-0: FIFO received data length */
 
 /* Interrupt Enable Register 0 */
-#define        VBSE            0x8000  /* b15: VBUS interrupt */
-#define        RSME            0x4000  /* b14: Resume interrupt */
-#define        SOFE            0x2000  /* b13: Frame update interrupt */
-#define        DVSE            0x1000  /* b12: Device state transition interrupt */
-#define        CTRE            0x0800  /* b11: Control transfer stage transition interrupt */
-#define        BEMPE           0x0400  /* b10: Buffer empty interrupt */
-#define        NRDYE           0x0200  /* b9: Buffer not ready interrupt */
-#define        BRDYE           0x0100  /* b8: Buffer ready interrupt */
+#define        VBSE    0x8000  /* b15: VBUS interrupt */
+#define        RSME    0x4000  /* b14: Resume interrupt */
+#define        SOFE    0x2000  /* b13: Frame update interrupt */
+#define        DVSE    0x1000  /* b12: Device state transition interrupt */
+#define        CTRE    0x0800  /* b11: Control transfer stage transition interrupt */
+#define        BEMPE   0x0400  /* b10: Buffer empty interrupt */
+#define        NRDYE   0x0200  /* b9: Buffer not ready interrupt */
+#define        BRDYE   0x0100  /* b8: Buffer ready interrupt */
 
 /* Interrupt Enable Register 1 */
 #define        OVRCRE          0x8000  /* b15: Over-current interrupt */
 #define          SOF_DISABLE    0x0000   /* SOF OUT Disable */
 
 /* Interrupt Status Register 0 */
-#define        VBINT           0x8000  /* b15: VBUS interrupt */
-#define        RESM            0x4000  /* b14: Resume interrupt */
-#define        SOFR            0x2000  /* b13: SOF frame update interrupt */
-#define        DVST            0x1000  /* b12: Device state transition interrupt */
-#define        CTRT            0x0800  /* b11: Control transfer stage transition interrupt */
-#define        BEMP            0x0400  /* b10: Buffer empty interrupt */
-#define        NRDY            0x0200  /* b9: Buffer not ready interrupt */
-#define        BRDY            0x0100  /* b8: Buffer ready interrupt */
-#define        VBSTS           0x0080  /* b7: VBUS input port */
-#define        DVSQ            0x0070  /* b6-4: Device state */
+#define        VBINT   0x8000  /* b15: VBUS interrupt */
+#define        RESM    0x4000  /* b14: Resume interrupt */
+#define        SOFR    0x2000  /* b13: SOF frame update interrupt */
+#define        DVST    0x1000  /* b12: Device state transition interrupt */
+#define        CTRT    0x0800  /* b11: Control transfer stage transition interrupt */
+#define        BEMP    0x0400  /* b10: Buffer empty interrupt */
+#define        NRDY    0x0200  /* b9: Buffer not ready interrupt */
+#define        BRDY    0x0100  /* b8: Buffer ready interrupt */
+#define        VBSTS   0x0080  /* b7: VBUS input port */
+#define        DVSQ    0x0070  /* b6-4: Device state */
 #define          DS_SPD_CNFG    0x0070   /* Suspend Configured */
 #define          DS_SPD_ADDR    0x0060   /* Suspend Address */
 #define          DS_SPD_DFLT    0x0050   /* Suspend Default */
 /* Micro Frame Number Register */
 #define        UFRNM           0x0007  /* b2-0: Micro frame number */
 
-/* USB Address / Low Power Status Recovery Register */
-//#define      USBADDR         0x007F  /* b6-0: USB address */
-
 /* Default Control Pipe Maxpacket Size Register */
 /* Pipe Maxpacket Size Register */
-#define        DEVSEL          0xF000  /* b15-14: Device address select */
-#define        MAXP            0x007F  /* b6-0: Maxpacket size of default control pipe */
+#define        DEVSEL  0xF000  /* b15-14: Device address select */
+#define        MAXP    0x007F  /* b6-0: Maxpacket size of default control pipe */
 
 /* Default Control Pipe Control Register */
 #define        BSTS            0x8000  /* b15: Buffer status */
 #define        MXPS            0x07FF  /* b10-0: Maxpacket size */
 
 /* Pipe Cycle Configuration Register */
-#define        IFIS            0x1000  /* b12: Isochronous in-buffer flush mode select */
-#define        IITV            0x0007  /* b2-0: Isochronous interval */
+#define        IFIS    0x1000  /* b12: Isochronous in-buffer flush mode select */
+#define        IITV    0x0007  /* b2-0: Isochronous interval */
 
 /* Pipex Control Register */
-#define        BSTS            0x8000  /* b15: Buffer status */
-#define        INBUFM          0x4000  /* b14: IN buffer monitor (Only for PIPE1 to 5) */
-#define        CSCLR           0x2000  /* b13: complete-split status clear */
-#define        CSSTS           0x1000  /* b12: complete-split status */
-#define        ATREPM          0x0400  /* b10: Auto repeat mode */
-#define        ACLRM           0x0200  /* b9: Out buffer auto clear mode */
-#define        SQCLR           0x0100  /* b8: Sequence toggle bit clear */
-#define        SQSET           0x0080  /* b7: Sequence toggle bit set */
-#define        SQMON           0x0040  /* b6: Sequence toggle bit monitor */
-#define        PBUSY           0x0020  /* b5: pipe busy */
-#define        PID             0x0003  /* b1-0: Response PID */
+#define        BSTS    0x8000  /* b15: Buffer status */
+#define        INBUFM  0x4000  /* b14: IN buffer monitor (Only for PIPE1 to 5) */
+#define        CSCLR   0x2000  /* b13: complete-split status clear */
+#define        CSSTS   0x1000  /* b12: complete-split status */
+#define        ATREPM  0x0400  /* b10: Auto repeat mode */
+#define        ACLRM   0x0200  /* b9: Out buffer auto clear mode */
+#define        SQCLR   0x0100  /* b8: Sequence toggle bit clear */
+#define        SQSET   0x0080  /* b7: Sequence toggle bit set */
+#define        SQMON   0x0040  /* b6: Sequence toggle bit monitor */
+#define        PBUSY   0x0020  /* b5: pipe busy */
+#define        PID     0x0003  /* b1-0: Response PID */
 
 /* PIPExTRE */
 #define        TRENB           0x0200  /* b9: Transaction counter enable */
 #define make_devsel(addr)              (addr << 12)
 
 struct r8a66597_pipe_info {
-        u16 pipenum;
-        u16 address;   /* R8A66597 HCD usb addres */
-        u16 epnum;
-        u16 maxpacket;
-        u16 type;
-        u16 bufnum;
-        u16 buf_bsize;
-        u16 interval;
-        u16 dir_in;
+       u16 pipenum;
+       u16 address;    /* R8A66597 HCD usb addres */
+       u16 epnum;
+       u16 maxpacket;
+       u16 type;
+       u16 bufnum;
+       u16 buf_bsize;
+       u16 interval;
+       u16 dir_in;
 };
 
 struct r8a66597_pipe {
index e98df2ee990131643d6e162c67b82145bab018bf..7f765ec038cd4eb3846276c3c1f88879851260c0 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/workqueue.h>
 #include <linux/platform_device.h>
 #include <linux/pci_ids.h>
+#include <linux/mutex.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
@@ -83,7 +84,7 @@ static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
 * u132_module_lock exists to protect access to global variables
 *
 */
-static struct semaphore u132_module_lock;
+static struct mutex u132_module_lock;
 static int u132_exiting = 0;
 static int u132_instances = 0;
 static struct list_head u132_static_list;
@@ -258,10 +259,10 @@ static void u132_hcd_delete(struct kref *kref)
         struct platform_device *pdev = u132->platform_dev;
         struct usb_hcd *hcd = u132_to_hcd(u132);
         u132->going += 1;
-        down(&u132_module_lock);
+        mutex_lock(&u132_module_lock);
         list_del_init(&u132->u132_list);
         u132_instances -= 1;
-        up(&u132_module_lock);
+        mutex_unlock(&u132_module_lock);
         dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13"
                 "2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev);
         usb_put_hcd(hcd);
@@ -3111,10 +3112,10 @@ static int __devinit u132_probe(struct platform_device *pdev)
                 int retval = 0;
                 struct u132 *u132 = hcd_to_u132(hcd);
                 hcd->rsrc_start = 0;
-                down(&u132_module_lock);
+                mutex_lock(&u132_module_lock);
                 list_add_tail(&u132->u132_list, &u132_static_list);
                 u132->sequence_num = ++u132_instances;
-                up(&u132_module_lock);
+                mutex_unlock(&u132_module_lock);
                 u132_u132_init_kref(u132);
                 u132_initialise(u132, pdev);
                 hcd->product_desc = "ELAN U132 Host Controller";
@@ -3216,7 +3217,7 @@ static int __init u132_hcd_init(void)
         INIT_LIST_HEAD(&u132_static_list);
         u132_instances = 0;
         u132_exiting = 0;
-        init_MUTEX(&u132_module_lock);
+        mutex_init(&u132_module_lock);
         if (usb_disabled())
                 return -ENODEV;
         printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__,
@@ -3232,9 +3233,9 @@ static void __exit u132_hcd_exit(void)
 {
         struct u132 *u132;
         struct u132 *temp;
-        down(&u132_module_lock);
+        mutex_lock(&u132_module_lock);
         u132_exiting += 1;
-        up(&u132_module_lock);
+        mutex_unlock(&u132_module_lock);
         list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) {
                 platform_device_unregister(u132->platform_dev);
         } platform_driver_unregister(&u132_platform_driver);
index 4aed305982ec3f8b1c9e90cce2b7b1e0885fe5c4..3bb908ca38e9c91ffd59df6e148608d23ab2d8f9 100644 (file)
@@ -827,8 +827,10 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
         * If direction is "send", change the packet ID from SETUP (0x2D)
         * to OUT (0xE1).  Else change it from SETUP to IN (0x69) and
         * set Short Packet Detect (SPD) for all data packets.
+        *
+        * 0-length transfers always get treated as "send".
         */
-       if (usb_pipeout(urb->pipe))
+       if (usb_pipeout(urb->pipe) || len == 0)
                destination ^= (USB_PID_SETUP ^ USB_PID_OUT);
        else {
                destination ^= (USB_PID_SETUP ^ USB_PID_IN);
@@ -839,7 +841,12 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
         * Build the DATA TDs
         */
        while (len > 0) {
-               int pktsze = min(len, maxsze);
+               int pktsze = maxsze;
+
+               if (len <= pktsze) {            /* The last data packet */
+                       pktsze = len;
+                       status &= ~TD_CTRL_SPD;
+               }
 
                td = uhci_alloc_td(uhci);
                if (!td)
@@ -866,20 +873,10 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
                goto nomem;
        *plink = LINK_TO_TD(td);
 
-       /*
-        * It's IN if the pipe is an output pipe or we're not expecting
-        * data back.
-        */
-       destination &= ~TD_TOKEN_PID_MASK;
-       if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length)
-               destination |= USB_PID_IN;
-       else
-               destination |= USB_PID_OUT;
-
+       /* Change direction for the status transaction */
+       destination ^= (USB_PID_IN ^ USB_PID_OUT);
        destination |= TD_TOKEN_TOGGLE;         /* End in Data1 */
 
-       status &= ~TD_CTRL_SPD;
-
        uhci_add_td_to_urbp(td, urbp);
        uhci_fill_td(td, status | TD_CTRL_IOC,
                        destination | uhci_explen(0), 0);
@@ -1185,10 +1182,18 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
                                }
                        }
 
+               /* Did we receive a short packet? */
                } else if (len < uhci_expected_length(td_token(td))) {
 
-                       /* We received a short packet */
-                       if (urb->transfer_flags & URB_SHORT_NOT_OK)
+                       /* For control transfers, go to the status TD if
+                        * this isn't already the last data TD */
+                       if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
+                               if (td->list.next != urbp->td_list.prev)
+                                       ret = 1;
+                       }
+
+                       /* For bulk and interrupt, this may be an error */
+                       else if (urb->transfer_flags & URB_SHORT_NOT_OK)
                                ret = -EREMOTEIO;
 
                        /* Fixup needed only if this isn't the URB's last TD */
@@ -1208,10 +1213,6 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
 
 err:
        if (ret < 0) {
-               /* In case a control transfer gets an error
-                * during the setup stage */
-               urb->actual_length = max(urb->actual_length, 0);
-
                /* Note that the queue has stopped and save
                 * the next toggle value */
                qh->element = UHCI_PTR_TERM;
@@ -1489,9 +1490,25 @@ __acquires(uhci->lock)
 {
        struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
 
+       if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
+
+               /* urb->actual_length < 0 means the setup transaction didn't
+                * complete successfully.  Either it failed or the URB was
+                * unlinked first.  Regardless, don't confuse people with a
+                * negative length. */
+               urb->actual_length = max(urb->actual_length, 0);
+
+               /* Report erroneous short transfers */
+               if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
+                               urb->actual_length <
+                                       urb->transfer_buffer_length &&
+                               urb->status == 0))
+                       urb->status = -EREMOTEIO;
+       }
+
        /* When giving back the first URB in an Isochronous queue,
         * reinitialize the QH's iso-related members for the next URB. */
-       if (qh->type == USB_ENDPOINT_XFER_ISOC &&
+       else if (qh->type == USB_ENDPOINT_XFER_ISOC &&
                        urbp->node.prev == &qh->queue &&
                        urbp->node.next != &qh->queue) {
                struct urb *nurb = list_entry(urbp->node.next,
index 36502a06f73af9f3fff9d0bcdb453f4d3c4ced1a..d1131a87a5b13ad72e40e4f573a6a7ace8979445 100644 (file)
@@ -284,9 +284,9 @@ static void mdc800_usb_irq (struct urb *urb)
        int data_received=0, wake_up;
        unsigned char* b=urb->transfer_buffer;
        struct mdc800_data* mdc800=urb->context;
+       int status = urb->status;
 
-       if (urb->status >= 0)
-       {
+       if (status >= 0) {
 
                //dbg ("%i %i %i %i %i %i %i %i \n",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]);
 
@@ -324,7 +324,7 @@ static void mdc800_usb_irq (struct urb *urb)
                ||
                        ((mdc800->camera_request_ready == 3) && (mdc800->camera_busy))
                ||
-                       (urb->status < 0)
+                       (status < 0)
                );
 
        if (wake_up)
@@ -376,15 +376,12 @@ static int mdc800_usb_waitForIRQ (int mode, int msec)
 static void mdc800_usb_write_notify (struct urb *urb)
 {
        struct mdc800_data* mdc800=urb->context;
+       int status = urb->status;
 
-       if (urb->status != 0)
-       {
-               err ("writing command fails (status=%i)", urb->status);
-       }
+       if (status != 0)
+               err ("writing command fails (status=%i)", status);
        else
-       {       
                mdc800->state=READY;
-       }
        mdc800->written = 1;
        wake_up (&mdc800->write_wait);
 }
@@ -396,9 +393,9 @@ static void mdc800_usb_write_notify (struct urb *urb)
 static void mdc800_usb_download_notify (struct urb *urb)
 {
        struct mdc800_data* mdc800=urb->context;
+       int status = urb->status;
 
-       if (urb->status == 0)
-       {
+       if (status == 0) {
                /* Fill output buffer with these data */
                memcpy (mdc800->out,  urb->transfer_buffer, 64);
                mdc800->out_count=64;
@@ -408,10 +405,8 @@ static void mdc800_usb_download_notify (struct urb *urb)
                {
                        mdc800->state=READY;
                }
-       }
-       else
-       {
-               err ("request bytes fails (status:%i)", urb->status);
+       } else {
+               err ("request bytes fails (status:%i)", status);
        }
        mdc800->downloaded = 1;
        wake_up (&mdc800->download_wait);
@@ -649,9 +644,9 @@ static int mdc800_device_open (struct inode* inode, struct file *file)
 
        retval=0;
        mdc800->irq_urb->dev = mdc800->dev;
-       if (usb_submit_urb (mdc800->irq_urb, GFP_KERNEL))
-       {
-               err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, mdc800->irq_urb->status);
+       retval = usb_submit_urb (mdc800->irq_urb, GFP_KERNEL);
+       if (retval) {
+               err ("request USB irq fails (submit_retval=%i).", retval);
                errn = -EIO;
                goto error_out;
        }
@@ -698,6 +693,7 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l
 {
        size_t left=len, sts=len; /* single transfer size */
        char __user *ptr = buf;
+       int retval;
 
        mutex_lock(&mdc800->io_lock);
        if (mdc800->state == NOT_CONNECTED)
@@ -737,9 +733,9 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l
 
                                /* Download -> Request new bytes */
                                mdc800->download_urb->dev = mdc800->dev;
-                               if (usb_submit_urb (mdc800->download_urb, GFP_KERNEL))
-                               {
-                                       err ("Can't submit download urb (status=%i)",mdc800->download_urb->status);
+                               retval = usb_submit_urb (mdc800->download_urb, GFP_KERNEL);
+                               if (retval) {
+                                       err ("Can't submit download urb (retval=%i)",retval);
                                        mutex_unlock(&mdc800->io_lock);
                                        return len-left;
                                }
@@ -788,6 +784,7 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l
 static ssize_t mdc800_device_write (struct file *file, const char __user *buf, size_t len, loff_t *pos)
 {
        size_t i=0;
+       int retval;
 
        mutex_lock(&mdc800->io_lock);
        if (mdc800->state != READY)
@@ -854,9 +851,9 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s
                        mdc800->state=WORKING;
                        memcpy (mdc800->write_urb->transfer_buffer, mdc800->in,8);
                        mdc800->write_urb->dev = mdc800->dev;
-                       if (usb_submit_urb (mdc800->write_urb, GFP_KERNEL))
-                       {
-                               err ("submitting write urb fails (status=%i)", mdc800->write_urb->status);
+                       retval = usb_submit_urb (mdc800->write_urb, GFP_KERNEL);
+                       if (retval) {
+                               err ("submitting write urb fails (retval=%i)", retval);
                                mutex_unlock(&mdc800->io_lock);
                                return -EIO;
                        }
index 51bd80d2b8ccb4379756b83d6185e175b2bbd4b8..768b2c11a2311d6efa8237e7868c4c642d8998dc 100644 (file)
@@ -189,7 +189,7 @@ static struct usb_driver mts_usb_driver = {
 #define MTS_DEBUG_INT() \
        do { MTS_DEBUG_GOT_HERE(); \
             MTS_DEBUG("transfer = 0x%x context = 0x%x\n",(int)transfer,(int)context ); \
-            MTS_DEBUG("status = 0x%x data-length = 0x%x sent = 0x%x\n",(int)transfer->status,(int)context->data_length, (int)transfer->actual_length ); \
+            MTS_DEBUG("status = 0x%x data-length = 0x%x sent = 0x%x\n",transfer->status,(int)context->data_length, (int)transfer->actual_length ); \
              mts_debug_dump(context->instance);\
           } while(0)
 #else
@@ -393,8 +393,6 @@ void mts_int_submit_urb (struct urb* transfer,
                      context
                );
 
-       transfer->status = 0;
-
        res = usb_submit_urb( transfer, GFP_ATOMIC );
        if ( unlikely(res) ) {
                MTS_INT_ERROR( "could not submit URB! Error was %d\n",(int)res );
@@ -444,12 +442,13 @@ static void mts_get_status( struct urb *transfer )
 static void mts_data_done( struct urb* transfer )
 /* Interrupt context! */
 {
+       int status = transfer->status;
        MTS_INT_INIT();
 
        if ( context->data_length != transfer->actual_length ) {
                context->srb->resid = context->data_length - transfer->actual_length;
-       } else if ( unlikely(transfer->status) ) {
-               context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
+       } else if ( unlikely(status) ) {
+               context->srb->result = (status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
        }
 
        mts_get_status(transfer);
@@ -461,10 +460,11 @@ static void mts_data_done( struct urb* transfer )
 static void mts_command_done( struct urb *transfer )
 /* Interrupt context! */
 {
+       int status = transfer->status;
        MTS_INT_INIT();
 
-       if ( unlikely(transfer->status) ) {
-               if (transfer->status == -ENOENT) {
+       if ( unlikely(status) ) {
+               if (status == -ENOENT) {
                        /* We are being killed */
                        MTS_DEBUG_GOT_HERE();
                        context->srb->result = DID_ABORT<<16;
@@ -502,12 +502,13 @@ static void mts_command_done( struct urb *transfer )
 static void mts_do_sg (struct urb* transfer)
 {
        struct scatterlist * sg;
+       int status = transfer->status;
        MTS_INT_INIT();
 
        MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg);
 
-       if (unlikely(transfer->status)) {
-                context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
+       if (unlikely(status)) {
+                context->srb->result = (status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
                mts_transfer_cleanup(transfer);
         }
 
index d72c42e5f22d0a8f1434b9d36c864d177bd0c34a..e9fdbc8997b32c2be588a3b52030448c4a689307 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/usb.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_USB_DEBUG
@@ -80,7 +81,7 @@ MODULE_DEVICE_TABLE(usb, device_table);
 
 /* Structure to hold all of our device specific stuff */
 struct adu_device {
-       struct semaphore        sem; /* locks this structure */
+       struct mutex            mtx; /* locks this structure */
        struct usb_device*      udev; /* save off the usb device pointer */
        struct usb_interface*   interface;
        unsigned char           minor; /* the starting minor number for this device */
@@ -178,17 +179,18 @@ static void adu_delete(struct adu_device *dev)
 static void adu_interrupt_in_callback(struct urb *urb)
 {
        struct adu_device *dev = urb->context;
+       int status = urb->status;
 
-       dbg(4," %s : enter, status %d", __FUNCTION__, urb->status);
+       dbg(4," %s : enter, status %d", __FUNCTION__, status);
        adu_debug_data(5, __FUNCTION__, urb->actual_length,
                       urb->transfer_buffer);
 
        spin_lock(&dev->buflock);
 
-       if (urb->status != 0) {
-               if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)) {
+       if (status != 0) {
+               if ((status != -ENOENT) && (status != -ECONNRESET)) {
                        dbg(1," %s : nonzero status received: %d",
-                           __FUNCTION__, urb->status);
+                           __FUNCTION__, status);
                }
                goto exit;
        }
@@ -216,21 +218,22 @@ exit:
        wake_up_interruptible(&dev->read_wait);
        adu_debug_data(5, __FUNCTION__, urb->actual_length,
                       urb->transfer_buffer);
-       dbg(4," %s : leave, status %d", __FUNCTION__, urb->status);
+       dbg(4," %s : leave, status %d", __FUNCTION__, status);
 }
 
 static void adu_interrupt_out_callback(struct urb *urb)
 {
        struct adu_device *dev = urb->context;
+       int status = urb->status;
 
-       dbg(4," %s : enter, status %d", __FUNCTION__, urb->status);
+       dbg(4," %s : enter, status %d", __FUNCTION__, status);
        adu_debug_data(5,__FUNCTION__, urb->actual_length, urb->transfer_buffer);
 
-       if (urb->status != 0) {
-               if ((urb->status != -ENOENT) &&
-                   (urb->status != -ECONNRESET)) {
+       if (status != 0) {
+               if ((status != -ENOENT) &&
+                   (status != -ECONNRESET)) {
                        dbg(1, " %s :nonzero status received: %d",
-                           __FUNCTION__, urb->status);
+                           __FUNCTION__, status);
                }
                goto exit;
        }
@@ -240,7 +243,7 @@ exit:
 
        adu_debug_data(5, __FUNCTION__, urb->actual_length,
                       urb->transfer_buffer);
-       dbg(4," %s : leave, status %d", __FUNCTION__, urb->status);
+       dbg(4," %s : leave, status %d", __FUNCTION__, status);
 }
 
 static int adu_open(struct inode *inode, struct file *file)
@@ -269,8 +272,8 @@ static int adu_open(struct inode *inode, struct file *file)
        }
 
        /* lock this device */
-       if ((retval = down_interruptible(&dev->sem))) {
-               dbg(2, "%s : sem down failed", __FUNCTION__);
+       if ((retval = mutex_lock_interruptible(&dev->mtx))) {
+               dbg(2, "%s : mutex lock failed", __FUNCTION__);
                goto exit_no_device;
        }
 
@@ -299,7 +302,7 @@ static int adu_open(struct inode *inode, struct file *file)
                if (retval)
                        --dev->open_count;
        }
-       up(&dev->sem);
+       mutex_unlock(&dev->mtx);
 
 exit_no_device:
        dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
@@ -347,7 +350,7 @@ static int adu_release(struct inode *inode, struct file *file)
        }
 
        /* lock our device */
-       down(&dev->sem); /* not interruptible */
+       mutex_lock(&dev->mtx); /* not interruptible */
 
        if (dev->open_count <= 0) {
                dbg(1," %s : device not opened", __FUNCTION__);
@@ -357,7 +360,7 @@ static int adu_release(struct inode *inode, struct file *file)
 
        if (dev->udev == NULL) {
                /* the device was unplugged before the file was released */
-               up(&dev->sem);
+               mutex_unlock(&dev->mtx);
                adu_delete(dev);
                dev = NULL;
        } else {
@@ -367,7 +370,7 @@ static int adu_release(struct inode *inode, struct file *file)
 
 exit:
        if (dev)
-               up(&dev->sem);
+               mutex_unlock(&dev->mtx);
        dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
        return retval;
 }
@@ -390,7 +393,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
        dev = file->private_data;
        dbg(2," %s : dev=%p", __FUNCTION__, dev);
        /* lock this object */
-       if (down_interruptible(&dev->sem))
+       if (mutex_lock_interruptible(&dev->mtx))
                return -ERESTARTSYS;
 
        /* verify that the device wasn't unplugged */
@@ -522,7 +525,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
 
 exit:
        /* unlock the device */
-       up(&dev->sem);
+       mutex_unlock(&dev->mtx);
 
        dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
        return retval;
@@ -543,7 +546,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
        dev = file->private_data;
 
        /* lock this object */
-       retval = down_interruptible(&dev->sem);
+       retval = mutex_lock_interruptible(&dev->mtx);
        if (retval)
                goto exit_nolock;
 
@@ -571,9 +574,9 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
                                retval = -EINTR;
                                goto exit;
                        }
-                       up(&dev->sem);
+                       mutex_unlock(&dev->mtx);
                        timeout = interruptible_sleep_on_timeout(&dev->write_wait, timeout);
-                       retval = down_interruptible(&dev->sem);
+                       retval = mutex_lock_interruptible(&dev->mtx);
                        if (retval) {
                                retval = bytes_written ? bytes_written : retval;
                                goto exit_nolock;
@@ -638,7 +641,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
 
 exit:
        /* unlock the device */
-       up(&dev->sem);
+       mutex_unlock(&dev->mtx);
 exit_nolock:
 
        dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
@@ -698,7 +701,7 @@ static int adu_probe(struct usb_interface *interface,
                goto exit;
        }
 
-       init_MUTEX(&dev->sem);
+       mutex_init(&dev->mtx);
        spin_lock_init(&dev->buflock);
        dev->udev = udev;
        init_waitqueue_head(&dev->read_wait);
@@ -835,16 +838,16 @@ static void adu_disconnect(struct usb_interface *interface)
        usb_deregister_dev(interface, &adu_class);
        dev->minor = 0;
 
-       down(&dev->sem); /* not interruptible */
+       mutex_lock(&dev->mtx); /* not interruptible */
 
        /* if the device is not opened, then we clean up right now */
        dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
        if (!dev->open_count) {
-               up(&dev->sem);
+               mutex_unlock(&dev->mtx);
                adu_delete(dev);
        } else {
                dev->udev = NULL;
-               up(&dev->sem);
+               mutex_unlock(&dev->mtx);
        }
 
        dev_info(&interface->dev, "ADU device adutux%d now disconnected",
index cf70c16f0e3f6981af7cd1b7946d9d91a712678e..b09c83568c1a8b455520feb3cd58df8250fe3aef 100644 (file)
@@ -88,9 +88,10 @@ static void appledisplay_complete(struct urb *urb)
 {
        struct appledisplay *pdata = urb->context;
        unsigned long flags;
+       int status = urb->status;
        int retval;
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -102,12 +103,12 @@ static void appledisplay_complete(struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* This urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d",
-                       __FUNCTION__, urb->status);
+               dbg("%s - urb shuttingdown with status: %d",
+                       __FUNCTION__, status);
                return;
        default:
                dbg("%s - nonzero urb status received: %d",
-                       __FUNCTION__, urb->status);
+                       __FUNCTION__, status);
                goto exit;
        }
 
index 42d4e6454a77f3bfec9562bc41b44a85ab42afb8..df7e1ecc810a18acf4f41d8e6d11746fc88873b5 100644 (file)
@@ -862,14 +862,16 @@ static void auerswald_ctrlread_wretcomplete (struct urb * urb)
         pauerbuf_t bp = (pauerbuf_t) urb->context;
         pauerswald_t cp;
        int ret;
+       int status = urb->status;
+
         dbg ("auerswald_ctrlread_wretcomplete called");
-        dbg ("complete with status: %d", urb->status);
+        dbg ("complete with status: %d", status);
        cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
 
        /* check if it is possible to advance */
-       if (!auerswald_status_retry (urb->status) || !cp->usbdev) {
+       if (!auerswald_status_retry(status) || !cp->usbdev) {
                /* reuse the buffer */
-               err ("control dummy: transmission error %d, can not retry", urb->status);
+               err ("control dummy: transmission error %d, can not retry", status);
                auerbuf_releasebuf (bp);
                /* Wake up all processes waiting for a buffer */
                wake_up (&cp->bufferwait);
@@ -902,21 +904,23 @@ static void auerswald_ctrlread_complete (struct urb * urb)
         pauerswald_t  cp;
         pauerscon_t   scp;
         pauerbuf_t    bp  = (pauerbuf_t) urb->context;
+       int status = urb->status;
        int ret;
+
         dbg ("auerswald_ctrlread_complete called");
 
        cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
 
        /* check if there is valid data in this urb */
-        if (urb->status) {
-               dbg ("complete with non-zero status: %d", urb->status);
+        if (status) {
+               dbg ("complete with non-zero status: %d", status);
                /* should we do a retry? */
-               if (!auerswald_status_retry (urb->status)
+               if (!auerswald_status_retry(status)
                 || !cp->usbdev
                 || (cp->version < AUV_RETRY)
                  || (bp->retries >= AU_RETRIES)) {
                        /* reuse the buffer */
-                       err ("control read: transmission error %d, can not retry", urb->status);
+                       err ("control read: transmission error %d, can not retry", status);
                        auerbuf_releasebuf (bp);
                        /* Wake up all processes waiting for a buffer */
                        wake_up (&cp->bufferwait);
@@ -974,12 +978,13 @@ static void auerswald_int_complete (struct urb * urb)
         unsigned  int channelid;
         unsigned  int bytecount;
         int ret;
+       int status = urb->status;
         pauerbuf_t   bp = NULL;
         pauerswald_t cp = (pauerswald_t) urb->context;
 
         dbg ("%s called", __FUNCTION__);
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -987,10 +992,10 @@ static void auerswald_int_complete (struct urb * urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d", __FUNCTION__, status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero urb status received: %d", __FUNCTION__, status);
                goto exit;
        }
 
index e0f122e131d720e0580382f88845c2bf47cde5a7..538b535e955ba0be89303c18a54076bfdc0f2743 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/kref.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 #include <linux/workqueue.h>
@@ -64,7 +65,7 @@ static struct workqueue_struct *respond_queue;
 * ftdi_module_lock exists to protect access to global variables
 *
 */
-static struct semaphore ftdi_module_lock;
+static struct mutex ftdi_module_lock;
 static int ftdi_instances = 0;
 static struct list_head ftdi_static_list;
 /*
@@ -199,10 +200,10 @@ static void ftdi_elan_delete(struct kref *kref)
         dev_warn(&ftdi->udev->dev, "FREEING ftdi=%p\n", ftdi);
         usb_put_dev(ftdi->udev);
         ftdi->disconnected += 1;
-        down(&ftdi_module_lock);
+        mutex_lock(&ftdi_module_lock);
         list_del_init(&ftdi->ftdi_list);
         ftdi_instances -= 1;
-        up(&ftdi_module_lock);
+        mutex_unlock(&ftdi_module_lock);
         kfree(ftdi->bulk_in_buffer);
         ftdi->bulk_in_buffer = NULL;
 }
@@ -746,10 +747,12 @@ static ssize_t ftdi_elan_read(struct file *file, char __user *buffer,
 static void ftdi_elan_write_bulk_callback(struct urb *urb)
 {
         struct usb_ftdi *ftdi = (struct usb_ftdi *)urb->context;
-        if (urb->status && !(urb->status == -ENOENT || urb->status ==
-                -ECONNRESET || urb->status == -ESHUTDOWN)) {
+       int status = urb->status;
+
+       if (status && !(status == -ENOENT || status == -ECONNRESET ||
+           status == -ESHUTDOWN)) {
                 dev_err(&ftdi->udev->dev, "urb=%p write bulk status received: %"
-                        "d\n", urb, urb->status);
+                        "d\n", urb, status);
         }
         usb_buffer_free(urb->dev, urb->transfer_buffer_length,
                 urb->transfer_buffer, urb->transfer_dma);
@@ -2780,10 +2783,10 @@ static int ftdi_elan_probe(struct usb_interface *interface,
                 return -ENOMEM;
         }
         memset(ftdi, 0x00, sizeof(struct usb_ftdi));
-        down(&ftdi_module_lock);
+        mutex_lock(&ftdi_module_lock);
         list_add_tail(&ftdi->ftdi_list, &ftdi_static_list);
         ftdi->sequence_num = ++ftdi_instances;
-        up(&ftdi_module_lock);
+        mutex_unlock(&ftdi_module_lock);
         ftdi_elan_init_kref(ftdi);
         init_MUTEX(&ftdi->sw_lock);
         ftdi->udev = usb_get_dev(interface_to_usbdev(interface));
@@ -2909,7 +2912,7 @@ static int __init ftdi_elan_init(void)
         int result;
         printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name,
               __TIME__, __DATE__);
-        init_MUTEX(&ftdi_module_lock);
+        mutex_init(&ftdi_module_lock);
         INIT_LIST_HEAD(&ftdi_static_list);
         status_queue = create_singlethread_workqueue("ftdi-status-control");
        if (!status_queue)
index 28548d186712ab24872eb15be6d69c86452b8db9..46d9f27ec17380122d0f3db1ef198b04d3fa2696 100644 (file)
@@ -158,9 +158,10 @@ static void iowarrior_callback(struct urb *urb)
        int read_idx;
        int aux_idx;
        int offset;
-       int status;
+       int status = urb->status;
+       int retval;
 
-       switch (urb->status) {
+       switch (status) {
        case 0:
                /* success */
                break;
@@ -213,10 +214,10 @@ static void iowarrior_callback(struct urb *urb)
        wake_up_interruptible(&dev->read_wait);
 
 exit:
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status)
+       retval = usb_submit_urb(urb, GFP_ATOMIC);
+       if (retval)
                dev_err(&dev->interface->dev, "%s - usb_submit_urb failed with result %d",
-                       __FUNCTION__, status);
+                       __FUNCTION__, retval);
 
 }
 
@@ -226,13 +227,15 @@ exit:
 static void iowarrior_write_callback(struct urb *urb)
 {
        struct iowarrior *dev;
+       int status = urb->status;
+
        dev = (struct iowarrior *)urb->context;
        /* sync/async unlink faults aren't errors */
-       if (urb->status &&
-           !(urb->status == -ENOENT ||
-             urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) {
+       if (status &&
+           !(status == -ENOENT ||
+             status == -ECONNRESET || status == -ESHUTDOWN)) {
                dbg("%s - nonzero write bulk status received: %d",
-                   __func__, urb->status);
+                   __func__, status);
        }
        /* free up our allocated buffer */
        usb_buffer_free(urb->dev, urb->transfer_buffer_length,
index 5e950b90c5414900fb1f7f8fe91a750660dda56d..8208496dfc638410ade09db081d0c7c729571d32 100644 (file)
@@ -219,16 +219,17 @@ static void ld_usb_interrupt_in_callback(struct urb *urb)
        struct ld_usb *dev = urb->context;
        size_t *actual_buffer;
        unsigned int next_ring_head;
+       int status = urb->status;
        int retval;
 
-       if (urb->status) {
-               if (urb->status == -ENOENT ||
-                   urb->status == -ECONNRESET ||
-                   urb->status == -ESHUTDOWN) {
+       if (status) {
+               if (status == -ENOENT ||
+                   status == -ECONNRESET ||
+                   status == -ESHUTDOWN) {
                        goto exit;
                } else {
                        dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n",
-                                __FUNCTION__, urb->status);
+                                __FUNCTION__, status);
                        spin_lock(&dev->rbsl);
                        goto resubmit; /* maybe we can recover */
                }
@@ -275,14 +276,15 @@ exit:
 static void ld_usb_interrupt_out_callback(struct urb *urb)
 {
        struct ld_usb *dev = urb->context;
+       int status = urb->status;
 
        /* sync/async unlink faults aren't errors */
-       if (urb->status && !(urb->status == -ENOENT ||
-                            urb->status == -ECONNRESET ||
-                            urb->status == -ESHUTDOWN))
+       if (status && !(status == -ENOENT ||
+                       status == -ECONNRESET ||
+                       status == -ESHUTDOWN))
                dbg_info(&dev->intf->dev,
                         "%s - nonzero write interrupt status received: %d\n",
-                        __FUNCTION__, urb->status);
+                        __FUNCTION__, status);
 
        dev->interrupt_out_busy = 0;
        wake_up_interruptible(&dev->write_wait);
index 2ed0daea894c8c93e5c7313d8dd6558634171095..561970b889a50cefb76626a6227001eb970df774 100644 (file)
@@ -742,19 +742,20 @@ exit:
 static void tower_interrupt_in_callback (struct urb *urb)
 {
        struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
+       int status = urb->status;
        int retval;
 
-       dbg(4, "%s: enter, status %d", __FUNCTION__, urb->status);
+       dbg(4, "%s: enter, status %d", __FUNCTION__, status);
 
        lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
 
-       if (urb->status) {
-               if (urb->status == -ENOENT ||
-                   urb->status == -ECONNRESET ||
-                   urb->status == -ESHUTDOWN) {
+       if (status) {
+               if (status == -ENOENT ||
+                   status == -ECONNRESET ||
+                   status == -ESHUTDOWN) {
                        goto exit;
                } else {
-                       dbg(1, "%s: nonzero status received: %d", __FUNCTION__, urb->status);
+                       dbg(1, "%s: nonzero status received: %d", __FUNCTION__, status);
                        goto resubmit; /* maybe we can recover */
                }
        }
@@ -788,7 +789,7 @@ exit:
        wake_up_interruptible (&dev->read_wait);
 
        lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
-       dbg(4, "%s: leave, status %d", __FUNCTION__, urb->status);
+       dbg(4, "%s: leave, status %d", __FUNCTION__, status);
 }
 
 
@@ -798,23 +799,24 @@ exit:
 static void tower_interrupt_out_callback (struct urb *urb)
 {
        struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
+       int status = urb->status;
 
-       dbg(4, "%s: enter, status %d", __FUNCTION__, urb->status);
+       dbg(4, "%s: enter, status %d", __FUNCTION__, status);
        lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
 
        /* sync/async unlink faults aren't errors */
-       if (urb->status && !(urb->status == -ENOENT ||
-                            urb->status == -ECONNRESET ||
-                            urb->status == -ESHUTDOWN)) {
+       if (status && !(status == -ENOENT ||
+                       status == -ECONNRESET ||
+                       status == -ESHUTDOWN)) {
                dbg(1, "%s - nonzero write bulk status received: %d",
-                   __FUNCTION__, urb->status);
+                   __FUNCTION__, status);
        }
 
        dev->interrupt_out_busy = 0;
        wake_up_interruptible(&dev->write_wait);
 
        lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
-       dbg(4, "%s: leave, status %d", __FUNCTION__, urb->status);
+       dbg(4, "%s: leave, status %d", __FUNCTION__, status);
 }
 
 
index 371bf2b1197db8761ff01e20fe25ea97ce5fbb65..aa9bcceabe744fa213c073456f9cf5d5a6381f3a 100644 (file)
@@ -305,9 +305,10 @@ static void interfacekit_irq(struct urb *urb)
        struct interfacekit *kit = urb->context;
        unsigned char *buffer = kit->data;
        int i, level, sensor;
-       int status;
+       int retval;
+       int status = urb->status;
 
-       switch (urb->status) {
+       switch (status) {
        case 0:                 /* success */
                break;
        case -ECONNRESET:       /* unlink */
@@ -377,11 +378,11 @@ static void interfacekit_irq(struct urb *urb)
                schedule_delayed_work(&kit->do_notify, 0);
 
 resubmit:
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status)
-               err("can't resubmit intr, %s-%s/interfacekit0, status %d",
+       retval = usb_submit_urb(urb, GFP_ATOMIC);
+       if (retval)
+               err("can't resubmit intr, %s-%s/interfacekit0, retval %d",
                        kit->udev->bus->bus_name,
-                       kit->udev->devpath, status);
+                       kit->udev->devpath, retval);
 }
 
 static void do_notify(struct work_struct *work)
index 5727e1ea2f91db1cd454545d16190ad32535779b..df0ebcdb9d6a6fbef91cffd476a0f5151945b324 100644 (file)
@@ -95,9 +95,10 @@ static void motorcontrol_irq(struct urb *urb)
        struct motorcontrol *mc = urb->context;
        unsigned char *buffer = mc->data;
        int i, level;
-       int status;
+       int retval;
+       int status = urb->status;;
 
-       switch (urb->status) {
+       switch (status) {
        case 0:                 /* success */
                break;
        case -ECONNRESET:       /* unlink */
@@ -151,12 +152,12 @@ static void motorcontrol_irq(struct urb *urb)
                schedule_delayed_work(&mc->do_notify, 0);
 
 resubmit:
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status)
+       retval = usb_submit_urb(urb, GFP_ATOMIC);
+       if (retval)
                dev_err(&mc->intf->dev,
-                       "can't resubmit intr, %s-%s/motorcontrol0, status %d",
+                       "can't resubmit intr, %s-%s/motorcontrol0, retval %d",
                        mc->udev->bus->bus_name,
-                       mc->udev->devpath, status);
+                       mc->udev->devpath, retval);
 }
 
 static void do_notify(struct work_struct *work)
index 504f7221b0d095e8847b902cc6e8955c6517172f..719842032712b68c0e42c22b16c58d57332a65a7 100644 (file)
@@ -176,16 +176,17 @@ static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
 static void lcd_write_bulk_callback(struct urb *urb)
 {
        struct usb_lcd *dev;
+       int status = urb->status;
 
        dev = (struct usb_lcd *)urb->context;
 
        /* sync/async unlink faults aren't errors */
-       if (urb->status &&
-           !(urb->status == -ENOENT ||
-             urb->status == -ECONNRESET ||
-              urb->status == -ESHUTDOWN)) {
+       if (status &&
+           !(status == -ENOENT ||
+             status == -ECONNRESET ||
+              status == -ESHUTDOWN)) {
                dbg("USBLCD: %s - nonzero write bulk status received: %d",
-                   __FUNCTION__, urb->status);
+                   __FUNCTION__, status);
        }
 
        /* free up our allocated buffer */
index fb321864a92da4b85e551b9534582c31eecbac0b..e901d31e051b3d579e3dcebdf1e66f161e2a31ba 100644 (file)
@@ -768,8 +768,8 @@ static void ctrl_complete (struct urb *urb)
 
                /* some faults are allowed, not required */
                if (subcase->expected > 0 && (
-                         ((urb->status == -subcase->expected   /* happened */
-                          || urb->status == 0))))              /* didn't */
+                         ((status == -subcase->expected        /* happened */
+                          || status == 0))))                   /* didn't */
                        status = 0;
                /* sometimes more than one fault is allowed */
                else if (subcase->number == 12 && status == -EPIPE)
index 1a60f9c473ada6d7b2506ba015a62c35800c63af..2734fe2b9c43b0443f7ef70b62d886ebe3c785bf 100644 (file)
@@ -111,12 +111,13 @@ static void async_complete(struct urb *urb)
        struct uss720_async_request *rq;
        struct parport *pp;
        struct parport_uss720_private *priv;
+       int status = urb->status;
 
        rq = urb->context;
        priv = rq->priv;
        pp = priv->pp;
-       if (urb->status) {
-               err("async_complete: urb error %d", urb->status);
+       if (status) {
+               err("async_complete: urb error %d", status);
        } else if (rq->dr.bRequest == 3) {
                memcpy(priv->reg, rq->reg, sizeof(priv->reg));
 #if 0
index 0d3903691e8c4a03a048c0c65e8c064e2ed52a49..b8670905bc3ac858d4e30aa91c2191e4c883c88e 100644 (file)
@@ -2794,16 +2794,14 @@ static void edge_shutdown (struct usb_serial *serial)
 
        dbg ("%s", __FUNCTION__);
 
-       for (i=0; i < serial->num_ports; ++i) {
+       for (i = 0; i < serial->num_ports; ++i) {
                edge_port = usb_get_serial_port_data(serial->port[i]);
                edge_remove_sysfs_attrs(edge_port->port);
-               if (edge_port) {
-                       edge_buf_free(edge_port->ep_out_buf);
-                       kfree(edge_port);
-               }
+               edge_buf_free(edge_port->ep_out_buf);
+               kfree(edge_port);
                usb_set_serial_port_data(serial->port[i], NULL);
        }
-       kfree (usb_get_serial_data(serial));
+       kfree(usb_get_serial_data(serial));
        usb_set_serial_data(serial, NULL);
 }
 
index 231b584f6d0f22b5a5e7c27a91289f2d5619e7d6..01e811becec4659055bc27f02ec2693ac66011d2 100644 (file)
@@ -110,11 +110,6 @@ static void mos7720_interrupt_callback(struct urb *urb)
 
        dbg("%s"," : Entering\n");
 
-       if (!urb) {
-               dbg("%s","Invalid Pointer !!!!:\n");
-               return;
-       }
-
        switch (status) {
        case 0:
                /* success */
index 37f41f576d3d9db9d2fee3ec412c69a0ad4441a4..f76480f1455dfddcf8fb53b5fa851b262bbac247 100644 (file)
@@ -436,11 +436,6 @@ static void mos7840_control_callback(struct urb *urb)
        int result = 0;
        int status = urb->status;
 
-       if (!urb) {
-               dbg("%s", "Invalid Pointer !!!!:\n");
-               return;
-       }
-
        mos7840_port = (struct moschip_port *)urb->context;
 
        switch (status) {
@@ -525,10 +520,6 @@ static void mos7840_interrupt_callback(struct urb *urb)
        int status = urb->status;
 
        dbg("%s", " : Entering\n");
-       if (!urb) {
-               dbg("%s", "Invalid Pointer !!!!:\n");
-               return;
-       }
 
        switch (status) {
        case 0:
@@ -676,11 +667,6 @@ static void mos7840_bulk_in_callback(struct urb *urb)
        struct tty_struct *tty;
        int status = urb->status;
 
-       if (!urb) {
-               dbg("%s", "Invalid Pointer !!!!:\n");
-               return;
-       }
-
        if (status) {
                dbg("nonzero read bulk status received: %d", status);
                return;
@@ -753,11 +739,6 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
        int status = urb->status;
        int i;
 
-       if (!urb) {
-               dbg("%s", "Invalid Pointer !!!!:\n");
-               return;
-       }
-
        mos7840_port = (struct moschip_port *)urb->context;
        spin_lock(&mos7840_port->pool_lock);
        for (i = 0; i < NUM_URBS; i++) {
index e7db20343d1a156a898fe51e27754d8929a8f890..0794ccdebfd402a94fd4b71c8f661901dc873e56 100644 (file)
@@ -1,7 +1,7 @@
 /*
   USB Driver for Sierra Wireless
 
-  Copyright (C) 2006  Kevin Lloyd <linux@sierrawireless.com>
+  Copyright (C) 2006, 2007  Kevin Lloyd <linux@sierrawireless.com>
 
   IMPORTANT DISCLAIMER: This driver is not commercially supported by
   Sierra Wireless. Use at your own risk.
 
   Portions based on the option driver by Matthias Urlichs <smurf@smurf.noris.de>
   Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
-
 */
 
-#define DRIVER_VERSION "v.1.0.6"
+#define DRIVER_VERSION "v.1.2.5b"
 #define DRIVER_AUTHOR "Kevin Lloyd <linux@sierrawireless.com>"
 #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
 
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
+#define SWIMS_USB_REQUEST_SetMode      0x0B
+#define SWIMS_USB_REQUEST_TYPE_SetMode 0x40
+#define SWIMS_USB_INDEX_SetMode                0x0000
+#define SWIMS_SET_MODE_Modem           0x0001
+
+/* per port private data */
+#define N_IN_URB       4
+#define N_OUT_URB      4
+#define IN_BUFLEN      4096
+
+static int debug;
+
+enum devicetype {
+       DEVICE_3_PORT =         0,
+       DEVICE_1_PORT =         1,
+       DEVICE_INSTALLER =      2,
+};
+
+int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
+{
+       int result;
+       dev_dbg(&udev->dev, "%s", "SET POWER STATE");
+       result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                       0x00,                   /* __u8 request      */
+                       0x40,                   /* __u8 request type */
+                       swiState,               /* __u16 value       */
+                       0,                      /* __u16 index       */
+                       NULL,                   /* void *data        */
+                       0,                      /* __u16 size        */
+                       USB_CTRL_SET_TIMEOUT);  /* int timeout       */
+       return result;
+}
+
+int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode)
+{
+       int result;
+       dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH");
+       result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                       SWIMS_USB_REQUEST_SetMode,      /* __u8 request      */
+                       SWIMS_USB_REQUEST_TYPE_SetMode, /* __u8 request type */
+                       eSocMode,                       /* __u16 value       */
+                       SWIMS_USB_INDEX_SetMode,        /* __u16 index       */
+                       NULL,                           /* void *data        */
+                       0,                              /* __u16 size        */
+                       USB_CTRL_SET_TIMEOUT);          /* int timeout       */
+       return result;
+}
+
+int sierra_probe(struct usb_interface *iface, const struct usb_device_id *id)
+{
+       int result;
+       struct usb_device *udev;
+
+       udev = usb_get_dev(interface_to_usbdev(iface));
+
+       /* Check if in installer mode */
+       if (id->driver_info == DEVICE_INSTALLER) {
+               dev_dbg(&udev->dev, "%s", "FOUND DEVICE(SW)\n");
+               result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem);
+               /*We do not want to bind to the device when in installer mode*/
+               return -EIO;
+       }
+
+       return usb_serial_probe(iface, id);
+}
 
 static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
        { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
        { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
+       { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */
        { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
        { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
-       { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless AirCard 595U */
        { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
+       { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */
+
        { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
        { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
        { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
-       { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */
+       { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */
        { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
+       { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780*/
+       { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781*/
+       { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */
+       { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */
+       { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */
+       { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881 E */
 
-       { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
-       { USB_DEVICE(0x0F3D, 0x0112) }, /* AirPrime/Sierra PC 5220 */
+       { USB_DEVICE(0x1199, 0x0112), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 580 */
+       { USB_DEVICE(0x0F3D, 0x0112), .driver_info = DEVICE_1_PORT }, /* Airprime/Sierra PC 5220 */
+
+       { USB_DEVICE(0x1199, 0x0FFF), .driver_info = DEVICE_INSTALLER},
        { }
 };
 MODULE_DEVICE_TABLE(usb, id_table);
@@ -58,35 +132,36 @@ static struct usb_device_id id_table_1port [] = {
 static struct usb_device_id id_table_3port [] = {
        { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
        { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
+       { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */
        { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
        { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
        { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
-       { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless AirCard 595U */
        { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
+       { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U*/
+
        { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
        { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
        { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
-       { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */
+       { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */
        { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
+       { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780*/
+       { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781*/
+       { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */
+       { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */
+       { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880E */
+       { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881E */
        { }
 };
 
 static struct usb_driver sierra_driver = {
        .name       = "sierra",
-       .probe      = usb_serial_probe,
+       .probe      = sierra_probe,
        .disconnect = usb_serial_disconnect,
        .id_table   = id_table,
        .no_dynamic_id =        1,
 };
 
 
-static int debug;
-
-/* per port private data */
-#define N_IN_URB       4
-#define N_OUT_URB      4
-#define IN_BUFLEN      4096
-
 struct sierra_port_private {
        spinlock_t lock;        /* lock the structure */
        int outstanding_urbs;   /* number of out urbs in flight */
@@ -421,7 +496,6 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
        int i;
        struct urb *urb;
        int result;
-       __u16 set_mode_dzero = 0x0000;
 
        portdata = usb_get_serial_port_data(port);
 
@@ -457,12 +531,6 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
 
        port->tty->low_latency = 1;
 
-       /* set mode to D0 */
-       result = usb_control_msg(serial->dev,
-                                usb_rcvctrlpipe(serial->dev, 0),
-                                0x00, 0x40, set_mode_dzero, 0, NULL,
-                                0, USB_CTRL_SET_TIMEOUT);
-
        sierra_send_setup(port);
 
        /* start up the interrupt endpoint if we have one */
@@ -510,6 +578,9 @@ static int sierra_startup(struct usb_serial *serial)
 
        dbg("%s", __FUNCTION__);
 
+       /*Set Device mode to D0 */
+       sierra_set_power_state(serial->dev, 0x0000);
+
        /* Now setup per port private data */
        for (i = 0; i < serial->num_ports; i++) {
                port = serial->port[i];
index 1628cb258562845e6ad85daa09eb04c5491aa7aa..9a410b5a6e5b06e946cbf3865faa9961b37cd3a6 100644 (file)
  */
 int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
-  int ret;
+       int ret;
 
-  if(srb == NULL)
-    return USB_STOR_TRANSPORT_ERROR;
+       if (srb == NULL)
+               return USB_STOR_TRANSPORT_ERROR;
 
-  US_DEBUGP("dpcm_transport: LUN=%d\n", srb->device->lun);
+       US_DEBUGP("dpcm_transport: LUN=%d\n", srb->device->lun);
 
-  switch(srb->device->lun) {
-  case 0:
+       switch (srb->device->lun) {
+               case 0:
 
-    /*
-     * LUN 0 corresponds to the CompactFlash card reader.
-     */
-    ret = usb_stor_CB_transport(srb, us);
-    break;
+                       /*
+                        * LUN 0 corresponds to the CompactFlash card reader.
+                        */
+                       ret = usb_stor_CB_transport(srb, us);
+                       break;
 
 #ifdef CONFIG_USB_STORAGE_SDDR09
-  case 1:
+               case 1:
 
-    /*
-     * LUN 1 corresponds to the SmartMedia card reader.
-     */
+                       /*
+                        * LUN 1 corresponds to the SmartMedia card reader.
+                        */
 
-    /*
-     * Set the LUN to 0 (just in case).
-     */
-    srb->device->lun = 0; us->srb->device->lun = 0;
-    ret = sddr09_transport(srb, us);
-    srb->device->lun = 1; us->srb->device->lun = 1;
-    break;
+                       /*
+                        * Set the LUN to 0 (just in case).
+                        */
+                       srb->device->lun = 0; us->srb->device->lun = 0;
+                       ret = sddr09_transport(srb, us);
+                       srb->device->lun = 1; us->srb->device->lun = 1;
+                       break;
 
 #endif
 
-  default:
-    US_DEBUGP("dpcm_transport: Invalid LUN %d\n", srb->device->lun);
-    ret = USB_STOR_TRANSPORT_ERROR;
-    break;
-  }
-  return ret;
+               default:
+                       US_DEBUGP("dpcm_transport: Invalid LUN %d\n", srb->device->lun);
+                       ret = USB_STOR_TRANSPORT_ERROR;
+                       break;
+       }
+       return ret;
 }
index d35369392feda4b8939e5a47f91da758b95f2743..dfd42fe9e5f0567d27e009f5514ab5a70d742b97 100644 (file)
@@ -57,9 +57,10 @@ static void usb_onetouch_irq(struct urb *urb)
        struct usb_onetouch *onetouch = urb->context;
        signed char *data = onetouch->data;
        struct input_dev *dev = onetouch->dev;
-       int status;
+       int status = urb->status;
+       int retval;
 
-       switch (urb->status) {
+       switch (status) {
        case 0:                 /* success */
                break;
        case -ECONNRESET:       /* unlink */
@@ -75,11 +76,11 @@ static void usb_onetouch_irq(struct urb *urb)
        input_sync(dev);
 
 resubmit:
-       status = usb_submit_urb (urb, GFP_ATOMIC);
-       if (status)
-               err ("can't resubmit intr, %s-%s/input0, status %d",
+       retval = usb_submit_urb (urb, GFP_ATOMIC);
+       if (retval)
+               err ("can't resubmit intr, %s-%s/input0, retval %d",
                        onetouch->udev->bus->bus_name,
-                       onetouch->udev->devpath, status);
+                       onetouch->udev->devpath, retval);
 }
 
 static int usb_onetouch_open(struct input_dev *dev)
index b6bf31a97b60d46bff07725cc7eec98b1a5e7c65..a624e72f81dc39a41bf79236d0f24707251b7c41 100644 (file)
@@ -313,6 +313,13 @@ UNUSUAL_DEV(  0x04b0, 0x0301, 0x0010, 0x0010,
                US_SC_DEVICE, US_PR_DEVICE,NULL,
                US_FL_NOT_LOCKABLE ),
 
+/* Reported by Stefan de Konink <skinkie@xs4all.nl> */
+UNUSUAL_DEV(  0x04b0, 0x0401, 0x0200, 0x0200,
+               "NIKON",
+               "NIKON DSC D100",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_FIX_CAPACITY),
+
 /* Reported by Andreas Bockhold <andreas@bockionline.de> */
 UNUSUAL_DEV(  0x04b0, 0x0405, 0x0100, 0x0100,
                "NIKON",
@@ -1384,6 +1391,17 @@ UNUSUAL_DEV(  0x1019, 0x0c55, 0x0000, 0x0110,
                US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init,
                0 ),
 
+/* Reported by Kevin Lloyd <linux@sierrawireless.com>
+ * Entry is needed for the initializer function override,
+ * which instructs the device to load as a modem
+ * device.
+ */
+UNUSUAL_DEV(  0x1199, 0x0fff, 0x0000, 0x9999,
+               "Sierra Wireless",
+               "USB MMC Storage",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_IGNORE_DEVICE),
+
 /* Reported by Jaco Kroon <jaco@kroon.co.za>
  * The usb-storage module found on the Digitech GNX4 (and supposedly other
  * devices) misbehaves and causes a bunch of invalid I/O errors.
index e9bbc3455c94d5ff8c02b7f05cdbd24df46f22be..1b3f6586bc9f433295ccee5bf5c32d5868e6d461 100644 (file)
@@ -174,7 +174,7 @@ static int cr_backlight_probe(struct platform_device *pdev)
        struct cr_panel *crp;
        u8 dev_en;
 
-       crp = kzalloc(sizeof(crp), GFP_KERNEL);
+       crp = kzalloc(sizeof(*crp), GFP_KERNEL);
        if (crp == NULL)
                return -ENOMEM;
 
index 02ebb1f1d3b0e2fa70298d21dbb1b88d4471a65d..0e5ec371ce727e8fcccd79d33108b9aca1f051ca 100644 (file)
@@ -2221,7 +2221,7 @@ block_page_mkwrite(struct vm_area_struct *vma, struct page *page,
        lock_page(page);
        size = i_size_read(inode);
        if ((page->mapping != inode->i_mapping) ||
-           ((page->index << PAGE_CACHE_SHIFT) > size)) {
+           (page_offset(page) > size)) {
                /* page got truncated out from underneath us */
                goto out_unlock;
        }
index 7d5a43cb0d5c81ee470ee8ec9f7a7cabc329b7e7..e4ab7bc14efede18f657dc477d1c92137bc37e27 100644 (file)
@@ -409,8 +409,7 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
        if (!PageUptodate(page))
                rc = ecryptfs_do_readpage(file, page, page->index);
        if (page->index != 0) {
-               loff_t end_of_prev_pg_pos =
-                       (((loff_t)page->index << PAGE_CACHE_SHIFT) - 1);
+               loff_t end_of_prev_pg_pos = page_offset(page) - 1;
 
                if (end_of_prev_pg_pos > i_size_read(page->mapping->host)) {
                        rc = ecryptfs_truncate(file->f_path.dentry,
@@ -736,7 +735,7 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
                goto out;
        }
        inode->i_blocks = lower_inode->i_blocks;
-       pos = (page->index << PAGE_CACHE_SHIFT) + to;
+       pos = page_offset(page) + to;
        if (pos > i_size_read(inode)) {
                i_size_write(inode, pos);
                ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
index ee64749e2eebd55bb1c8ea95d19cfb30a447e0ea..98756156d29878b8df182497214b9640d45ac79d 100644 (file)
@@ -89,7 +89,7 @@ static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
 {
        int ret;
        struct address_space *mapping = inode->i_mapping;
-       loff_t pos = page->index << PAGE_CACHE_SHIFT;
+       loff_t pos = page_offset(page);
        unsigned int len = PAGE_CACHE_SIZE;
        pgoff_t last_index;
        struct page *locked_page = NULL;
index 5e0fcf41804d634a02b9d0d2d53122680b6ecef0..47bb9cf107b7aa4cf1b8935d3a451eb2f5d20313 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/raw_io.h>
 #include <asm/virtconvert.h>
 
+#include <asm-generic/iomap.h>
 
 #ifdef CONFIG_ATARI
 #include <asm/atarihw.h>
@@ -152,6 +153,16 @@ static inline u16 __iomem *isa_itw(unsigned long addr)
     default: return NULL; /* avoid warnings, just in case */
     }
 }
+static inline u32 __iomem *isa_itl(unsigned long addr)
+{
+  switch(ISA_TYPE)
+    {
+#ifdef CONFIG_AMIGA_PCMCIA
+    case AG_ISA: return (u32 __iomem *)AG_ISA_IO_W(addr);
+#endif
+    default: return 0; /* avoid warnings, just in case */
+    }
+}
 static inline u8 __iomem *isa_mtb(unsigned long addr)
 {
   switch(ISA_TYPE)
@@ -188,8 +199,10 @@ static inline u16 __iomem *isa_mtw(unsigned long addr)
 
 #define isa_inb(port)      in_8(isa_itb(port))
 #define isa_inw(port)      (ISA_SEX ? in_be16(isa_itw(port)) : in_le16(isa_itw(port)))
+#define isa_inl(port)      (ISA_SEX ? in_be32(isa_itl(port)) : in_le32(isa_itl(port)))
 #define isa_outb(val,port) out_8(isa_itb(port),(val))
 #define isa_outw(val,port) (ISA_SEX ? out_be16(isa_itw(port),(val)) : out_le16(isa_itw(port),(val)))
+#define isa_outl(val,port) (ISA_SEX ? out_be32(isa_itl(port),(val)) : out_le32(isa_itl(port),(val)))
 
 #define isa_readb(p)       in_8(isa_mtb((unsigned long)(p)))
 #define isa_readw(p)       \
@@ -234,6 +247,15 @@ static inline void isa_delay(void)
 #define isa_outsw(port, buf, nr)    \
        (ISA_SEX ? raw_outsw(isa_itw(port), (u16 *)(buf), (nr)) :  \
                   raw_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)))
+
+#define isa_insl(port, buf, nr)     \
+       (ISA_SEX ? raw_insl(isa_itl(port), (u32 *)(buf), (nr)) :    \
+                  raw_insw_swapw(isa_itw(port), (u16 *)(buf), (nr)<<1))
+
+#define isa_outsl(port, buf, nr)    \
+       (ISA_SEX ? raw_outsl(isa_itl(port), (u32 *)(buf), (nr)) :  \
+                  raw_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)<<1))
+
 #endif  /* CONFIG_ISA */
 
 
@@ -246,14 +268,16 @@ static inline void isa_delay(void)
 #define inw_p   isa_inw_p
 #define outw    isa_outw
 #define outw_p  isa_outw_p
-#define inl     isa_inw
-#define inl_p   isa_inw_p
-#define outl    isa_outw
-#define outl_p  isa_outw_p
+#define inl     isa_inl
+#define inl_p   isa_inl_p
+#define outl    isa_outl
+#define outl_p  isa_outl_p
 #define insb    isa_insb
 #define insw    isa_insw
+#define insl    isa_insl
 #define outsb   isa_outsb
 #define outsw   isa_outsw
+#define outsl   isa_outsl
 #define readb   isa_readb
 #define readw   isa_readw
 #define writeb  isa_writeb
@@ -262,8 +286,6 @@ static inline void isa_delay(void)
 
 #if defined(CONFIG_PCI)
 
-#define inl(port)        in_le32(port)
-#define outl(val,port)   out_le32((port),(val))
 #define readl(addr)      in_le32(addr)
 #define writel(val,addr) out_le32((addr),(val))
 
@@ -282,6 +304,8 @@ static inline void isa_delay(void)
 #define outb(val,port) out_8((port),(val))
 #define inw(port)      in_le16(port)
 #define outw(val,port) out_le16((port),(val))
+#define inl(port)      in_le32(port)
+#define outl(val,port) out_le32((port),(val))
 
 #else
 /*
@@ -306,20 +330,35 @@ static inline void isa_delay(void)
 #endif
 #endif /* CONFIG_PCI */
 
-#if !defined(CONFIG_ISA) && !defined(CONFIG_PCI) && defined(CONFIG_HP300)
+#if !defined(CONFIG_ISA) && !defined(CONFIG_PCI)
 /*
- * We need to define dummy functions otherwise drivers/serial/8250.c doesn't link
+ * We need to define dummy functions for GENERIC_IOMAP support.
  */
-#define inb(port)        0xff
-#define inb_p(port)      0xff
-#define outb(val,port)   do { } while (0)
-#define outb_p(val,port) do { } while (0)
+#define inb(port)          0xff
+#define inb_p(port)        0xff
+#define outb(val,port)     ((void)0)
+#define outb_p(val,port)   ((void)0)
+#define inw(port)          0xffff
+#define outw(val,port)     ((void)0)
+#define inl(port)          0xffffffffUL
+#define outl(val,port)     ((void)0)
+
+#define insb(port,buf,nr)  ((void)0)
+#define outsb(port,buf,nr) ((void)0)
+#define insw(port,buf,nr)  ((void)0)
+#define outsw(port,buf,nr) ((void)0)
+#define insl(port,buf,nr)  ((void)0)
+#define outsl(port,buf,nr) ((void)0)
 
 /*
  * These should be valid on any ioremap()ed region
  */
 #define readb(addr)      in_8(addr)
 #define writeb(val,addr) out_8((addr),(val))
+#define readw(addr)      in_le16(addr)
+#define writew(val,addr) out_le16((addr),(val))
+#endif
+#if !defined(CONFIG_PCI)
 #define readl(addr)      in_le32(addr)
 #define writel(val,addr) out_le32((addr),(val))
 #endif
@@ -351,6 +390,18 @@ extern void dma_cache_wback_inv(unsigned long start, unsigned long size);
 extern void dma_cache_wback(unsigned long start, unsigned long size);
 extern void dma_cache_inv(unsigned long start, unsigned long size);
 
+static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count)
+{
+       __builtin_memset((void __force *) addr, val, count);
+}
+static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, int count)
+{
+       __builtin_memcpy(dst, (void __force *) src, count);
+}
+static inline void memcpy_toio(volatile void __iomem *dst, const void *src, int count)
+{
+       __builtin_memcpy((void __force *) dst, src, count);
+}
 
 #ifndef CONFIG_SUN3
 #define IO_SPACE_LIMIT 0xffff
index 811ccd25d4a6dc9f9a6b7c5890f658f349ed46d4..91c623f0994c958f5fdef6f646314640df10029e 100644 (file)
@@ -49,10 +49,16 @@ extern void __iounmap(void *addr, unsigned long size);
 #define raw_inb in_8
 #define raw_inw in_be16
 #define raw_inl in_be32
+#define __raw_readb in_8
+#define __raw_readw in_be16
+#define __raw_readl in_be32
 
 #define raw_outb(val,port) out_8((port),(val))
 #define raw_outw(val,port) out_be16((port),(val))
 #define raw_outl(val,port) out_be32((port),(val))
+#define __raw_writeb(val,addr) out_8((addr),(val))
+#define __raw_writew(val,addr) out_be16((addr),(val))
+#define __raw_writel(val,addr) out_be32((addr),(val))
 
 static inline void raw_insb(volatile u8 __iomem *port, u8 *buf, unsigned int len)
 {
@@ -336,8 +342,6 @@ static inline void raw_outsw_swapw(volatile u16 __iomem *port, const u16 *buf,
                : "d0", "a0", "a1", "d6");
 }
 
-#define __raw_writel raw_outl
-
 #endif /* __KERNEL__ */
 
 #endif /* _RAW_IO_H */
index 64471bcd96f9caf5d817573a23bb99acff777725..029b3e0d5e4ca3ea71c286da6ab1291311fb866b 100644 (file)
@@ -1,4 +1,3 @@
-/* $Id: unistd.h,v 1.74 2002/02/08 03:57:18 davem Exp $ */
 #ifndef _SPARC_UNISTD_H
 #define _SPARC_UNISTD_H
 
@@ -9,7 +8,7 @@
  * think of right now to force the arguments into fixed registers
  * before the trap into the system call with gcc 'asm' statements.
  *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
  *
  * SunOS compatibility based upon preliminary work which is:
  *
 #define __NR_signalfd          311
 #define __NR_timerfd           312
 #define __NR_eventfd           313
+#define __NR_fallocate         314
 
-#define NR_SYSCALLS            314
+#define NR_SYSCALLS            315
 
 #ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
diff --git a/include/asm-sparc64/power.h b/include/asm-sparc64/power.h
deleted file mode 100644 (file)
index 94495c1..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _SPARC64_POWER_H
-#define _SPARC64_POWER_H
-
-extern void wake_up_powerd(void);
-extern int start_powerd(void);
-
-#endif /* !(_SPARC64_POWER_H) */
index 53e96ed9c0243a49224374ec3dde78a88b91b264..cb751b4d0f564aab760af0f6faff8faeb34748e1 100644 (file)
@@ -1,4 +1,3 @@
-/* $Id: unistd.h,v 1.50 2002/02/08 03:57:18 davem Exp $ */
 #ifndef _SPARC64_UNISTD_H
 #define _SPARC64_UNISTD_H
 
@@ -9,7 +8,7 @@
  * think of right now to force the arguments into fixed registers
  * before the trap into the system call with gcc 'asm' statements.
  *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
  *
  * SunOS compatibility based upon preliminary work which is:
  *
 #define __NR_signalfd          311
 #define __NR_timerfd           312
 #define __NR_eventfd           313
+#define __NR_fallocate         314
 
-#define NR_SYSCALLS            314
+#define NR_SYSCALLS            315
 
 #ifdef __KERNEL__
 /* sysconf options, for SunOS compatibility */
index c0a8d4ed5bcb33669d808b4f1105c1913fe1dfac..f7417e91b1706bb79c438446b8b941e5ddb7c9ef 100644 (file)
@@ -275,6 +275,8 @@ struct vio_dev {
        char                    compat[VIO_MAX_COMPAT_LEN];
        int                     compat_len;
 
+       u64                     dev_no;
+
        unsigned long           channel_id;
 
        unsigned int            tx_irq;
index ff1255079fa196a9d7cdfbe9cfa45fa42f9146a1..bdca3f1b3213ffb4871ed3cc028ae5a1f9257220 100644 (file)
@@ -51,10 +51,6 @@ struct dma_chan_ref {
  * @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a
  * dependency chain
  * @ASYNC_TX_DEP_ACK: ack the dependency descriptor.  Useful for chaining.
- * @ASYNC_TX_KMAP_SRC: if the transaction is to be performed synchronously
- * take an atomic mapping (KM_USER0) on the source page(s)
- * @ASYNC_TX_KMAP_DST: if the transaction is to be performed synchronously
- * take an atomic mapping (KM_USER0) on the dest page(s)
  */
 enum async_tx_flags {
        ASYNC_TX_XOR_ZERO_DST    = (1 << 0),
@@ -62,8 +58,6 @@ enum async_tx_flags {
        ASYNC_TX_ASSUME_COHERENT = (1 << 2),
        ASYNC_TX_ACK             = (1 << 3),
        ASYNC_TX_DEP_ACK         = (1 << 4),
-       ASYNC_TX_KMAP_SRC        = (1 << 5),
-       ASYNC_TX_KMAP_DST        = (1 << 6),
 };
 
 #ifdef CONFIG_DMA_ENGINE
index 07f7e4cbcee3bc375e893b3ecdccdad148905a2a..124270df8734eb2b20e3f36adb115bc356692a15 100644 (file)
@@ -160,7 +160,7 @@ static inline struct kmem_cache *kmalloc_slab(size_t size)
 #define SLUB_DMA __GFP_DMA
 #else
 /* Disable DMA functionality */
-#define SLUB_DMA 0
+#define SLUB_DMA (__force gfp_t)0
 #endif
 
 void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
index 43cb3b3e1679ca4d9574f4a9d333f92b913bfb63..40954fb815988675a8b71c27cbea08c2f13f22e4 100644 (file)
@@ -138,7 +138,7 @@ static unsigned long __meminitdata dma_reserve;
 #endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */
   unsigned long __initdata required_kernelcore;
   unsigned long __initdata required_movablecore;
-  unsigned long __initdata zone_movable_pfn[MAX_NUMNODES];
+  unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES];
 
   /* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */
   int movable_zone;
index b1179dd3d8c30cb6eabce77b7b501b36c4a918c3..ca10df40784f960c820b90ff029a103aeac5185a 100644 (file)
@@ -194,7 +194,7 @@ static struct nf_ct_ext_type helper_extend __read_mostly = {
        .id     = NF_CT_EXT_HELPER,
 };
 
-int nf_conntrack_helper_init()
+int nf_conntrack_helper_init(void)
 {
        int err;
 
@@ -216,7 +216,7 @@ err1:
        return err;
 }
 
-void nf_conntrack_helper_fini()
+void nf_conntrack_helper_fini(void)
 {
        nf_ct_extend_unregister(&helper_extend);
        nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_vmalloc,
index 7d8d8896e309fb62a3585e39f546cb8df6be4d5b..9468ec7971db933e2594171ff66c8dd17c9368c8 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-indent -npro -kr -i8 -ts8 -sob -l80 -ss -ncs "$@"
+indent -npro -kr -i8 -ts8 -sob -l80 -ss -ncs -cp1 "$@"
index 04579a517900c8a53038b690de47ad9b2fb45139..5ab7914d30ef66f9d8880372ed47123a550ae168 100644 (file)
@@ -1076,6 +1076,7 @@ static int initexit_section_ref_ok(const char *name)
                ".plt",                 /* seen on ARCH=um build on x86_64. Harmless */
                ".smp_locks",
                ".stab",
+               ".m68k_fixup",
                NULL
        };
        /* Start of section names */