From eacb86f026d54053ff86954d1a4b3d9fb2d4e8ca Mon Sep 17 00:00:00 2001 From: Ingo Oeser Date: Wed, 23 Jul 2008 01:25:01 +0200 Subject: [PATCH] --- yaml --- r: 108983 b: refs/heads/master c: 25fdeb3f4468595ab2885687b13515fa848731c2 h: refs/heads/master i: 108981: 48363f373da65fa9e9974c96ac18430f9d643796 108979: 261b5d7848020c8680513b9e02787150cb1a1364 108975: c29b5cf30201f9c7c25fa7df27db8f46207baf41 v: v3 --- [refs] | 2 +- trunk/arch/s390/defconfig | 54 +- trunk/arch/s390/include/asm/bitops.h | 6 +- trunk/arch/s390/kernel/process.c | 4 +- trunk/arch/s390/kernel/smp.c | 2 + trunk/drivers/s390/block/dasd.c | 5 +- trunk/drivers/s390/block/dasd_eckd.h | 2 +- trunk/drivers/s390/block/dasd_eer.c | 3 +- trunk/drivers/s390/block/dcssblk.c | 4 - trunk/drivers/s390/char/tape_char.c | 2 +- trunk/drivers/s390/char/tape_std.c | 2 +- trunk/drivers/s390/cio/ccwgroup.c | 20 +- trunk/drivers/s390/cio/css.c | 1 + trunk/drivers/s390/cio/device.c | 40 +- trunk/drivers/s390/cio/device.h | 2 +- trunk/drivers/s390/cio/device_fsm.c | 31 +- trunk/drivers/s390/cio/qdio_debug.h | 6 +- trunk/drivers/s390/cio/qdio_main.c | 74 +- trunk/drivers/s390/cio/qdio_setup.c | 6 +- trunk/drivers/s390/cio/qdio_thinint.c | 6 +- trunk/drivers/usb/class/cdc-acm.c | 5 +- trunk/drivers/usb/core/driver.c | 96 ++- trunk/drivers/usb/core/hcd.c | 9 + trunk/drivers/usb/core/hcd.h | 4 + trunk/drivers/usb/core/hub.c | 9 + trunk/drivers/usb/core/urb.c | 9 +- trunk/drivers/usb/core/usb.c | 73 +- trunk/drivers/usb/core/usb.h | 3 - trunk/drivers/usb/gadget/pxa27x_udc.c | 2 +- trunk/drivers/usb/host/isp1760-hcd.c | 2 +- trunk/drivers/usb/host/ohci-at91.c | 1 + trunk/drivers/usb/host/ohci-au1xxx.c | 1 + trunk/drivers/usb/host/ohci-ep93xx.c | 1 + trunk/drivers/usb/host/ohci-hub.c | 53 +- trunk/drivers/usb/host/ohci-lh7a404.c | 1 + trunk/drivers/usb/host/ohci-omap.c | 1 + trunk/drivers/usb/host/ohci-pci.c | 1 + trunk/drivers/usb/host/ohci-pnx4008.c | 1 + trunk/drivers/usb/host/ohci-pnx8550.c | 1 + trunk/drivers/usb/host/ohci-ppc-of.c | 1 + trunk/drivers/usb/host/ohci-ppc-soc.c | 1 + trunk/drivers/usb/host/ohci-ps3.c | 1 + trunk/drivers/usb/host/ohci-pxa27x.c | 1 + trunk/drivers/usb/host/ohci-s3c2410.c | 1 + trunk/drivers/usb/host/ohci-sa1111.c | 1 + trunk/drivers/usb/host/ohci-sh.c | 1 + trunk/drivers/usb/host/ohci-sm501.c | 1 + trunk/drivers/usb/host/ohci-ssb.c | 1 + trunk/drivers/usb/host/u132-hcd.c | 11 + trunk/drivers/usb/misc/sisusbvga/sisusb.c | 1 - trunk/drivers/usb/musb/Kconfig | 13 +- trunk/drivers/usb/musb/Makefile | 21 +- trunk/drivers/usb/musb/musb_core.c | 38 +- trunk/drivers/usb/musb/musb_core.h | 19 + trunk/drivers/usb/musb/musb_debug.h | 4 + trunk/drivers/usb/musb/musb_gadget_ep0.c | 2 - trunk/drivers/usb/musb/musb_procfs.c | 830 ++++++++++++++++++++++ trunk/drivers/usb/serial/option.c | 2 - trunk/include/linux/usb.h | 3 - trunk/lib/kobject.c | 3 +- 60 files changed, 1153 insertions(+), 348 deletions(-) create mode 100644 trunk/drivers/usb/musb/musb_procfs.c diff --git a/[refs] b/[refs] index d90047e831d7..2a1b4e56d8d4 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 691a55998cc2fc645b51d28edb4f4d36b512826e +refs/heads/master: 25fdeb3f4468595ab2885687b13515fa848731c2 diff --git a/trunk/arch/s390/defconfig b/trunk/arch/s390/defconfig index 9b0bc2c9fba0..c5cdb975d590 100644 --- a/trunk/arch/s390/defconfig +++ b/trunk/arch/s390/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.27-rc4 -# Thu Aug 21 19:43:29 2008 +# Linux kernel version: 2.6.26-rc4 +# Fri May 30 09:49:33 2008 # CONFIG_SCHED_MC=y CONFIG_MMU=y @@ -68,6 +68,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_SYSCTL_SYSCALL=y +CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -92,17 +93,11 @@ CONFIG_SLAB=y # CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y CONFIG_KPROBES=y -# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set CONFIG_KRETPROBES=y -# CONFIG_HAVE_IOREMAP_PROT is not set CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y -# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set -# CONFIG_USE_GENERIC_SMP_HELPERS is not set -# CONFIG_HAVE_CLK is not set CONFIG_PROC_PAGE_MONITOR=y -# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -118,7 +113,6 @@ CONFIG_STOP_MACHINE=y CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set CONFIG_BLK_DEV_BSG=y -# CONFIG_BLK_DEV_INTEGRITY is not set CONFIG_BLOCK_COMPAT=y # @@ -181,8 +175,6 @@ CONFIG_PREEMPT=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y -CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_FLATMEM_MANUAL is not set # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -193,12 +185,8 @@ CONFIG_HAVE_MEMORY_PRESENT=y CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_MEMORY_HOTPLUG=y -CONFIG_MEMORY_HOTPLUG_SPARSE=y -CONFIG_MEMORY_HOTREMOVE=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_MIGRATION=y CONFIG_RESOURCES_64BIT=y CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y @@ -210,7 +198,6 @@ CONFIG_VIRT_TO_BUS=y CONFIG_MACHCHK_WARNING=y CONFIG_QDIO=y # CONFIG_QDIO_DEBUG is not set -CONFIG_CHSC_SCH=m # # Misc @@ -219,7 +206,6 @@ CONFIG_IPL=y # CONFIG_IPL_TAPE is not set CONFIG_IPL_VM=y CONFIG_BINFMT_ELF=y -CONFIG_COMPAT_BINFMT_ELF=y CONFIG_BINFMT_MISC=m CONFIG_FORCE_MAX_ZONEORDER=9 # CONFIG_PROCESS_DEBUG is not set @@ -240,6 +226,10 @@ CONFIG_S390_HYPFS_FS=y CONFIG_KEXEC=y # CONFIG_ZFCPDUMP is not set CONFIG_S390_GUEST=y + +# +# Networking +# CONFIG_NET=y # @@ -374,6 +364,7 @@ CONFIG_NET_SCH_CBQ=m # CONFIG_NET_SCH_HTB is not set # CONFIG_NET_SCH_HFSC is not set CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RR=m CONFIG_NET_SCH_RED=m CONFIG_NET_SCH_SFQ=m CONFIG_NET_SCH_TEQL=m @@ -439,9 +430,7 @@ CONFIG_CCW=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y -# CONFIG_FIRMWARE_IN_KERNEL is not set -CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER is not set # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set CONFIG_SYS_HYPERVISOR=y @@ -518,11 +507,6 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set # CONFIG_SCSI_DEBUG is not set CONFIG_ZFCP=y -CONFIG_SCSI_DH=m -CONFIG_SCSI_DH_RDAC=m -CONFIG_SCSI_DH_HP_SW=m -CONFIG_SCSI_DH_EMC=m -CONFIG_SCSI_DH_ALUA=m CONFIG_MD=y CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=m @@ -538,10 +522,14 @@ CONFIG_DM_CRYPT=y CONFIG_DM_SNAPSHOT=y CONFIG_DM_MIRROR=y CONFIG_DM_ZERO=y -CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH=y +# CONFIG_DM_MULTIPATH_EMC is not set +# CONFIG_DM_MULTIPATH_RDAC is not set +# CONFIG_DM_MULTIPATH_HP is not set # CONFIG_DM_DELAY is not set # CONFIG_DM_UEVENT is not set CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set # CONFIG_IFB is not set CONFIG_DUMMY=m CONFIG_BONDING=m @@ -556,6 +544,7 @@ CONFIG_NET_ETHERNET=y # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set CONFIG_NETDEV_1000=y +# CONFIG_E1000E_ENABLED is not set CONFIG_NETDEV_10000=y # CONFIG_TR is not set # CONFIG_WAN is not set @@ -587,10 +576,7 @@ CONFIG_DEVKMEM=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -CONFIG_HVC_DRIVER=y -CONFIG_VIRTIO_CONSOLE=y CONFIG_HW_RANDOM=m -CONFIG_HW_RANDOM_VIRTIO=m # CONFIG_R3964 is not set CONFIG_RAW_DRIVER=m CONFIG_MAX_RAW_DEVS=256 @@ -630,7 +616,6 @@ CONFIG_MONWRITER=m CONFIG_S390_VMUR=m # CONFIG_POWER_SUPPLY is not set # CONFIG_THERMAL is not set -# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # @@ -708,7 +693,6 @@ CONFIG_CONFIGFS_FS=m # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set -# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -728,6 +712,7 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y +# CONFIG_SUNRPC_BIND34 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -795,7 +780,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_WRITECOUNT is not set -CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set # CONFIG_FRAME_POINTER is not set @@ -805,7 +789,6 @@ CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_SAMPLES=y # CONFIG_SAMPLE_KOBJECT is not set # CONFIG_SAMPLE_KPROBES is not set @@ -864,10 +847,6 @@ CONFIG_CRYPTO_HMAC=m # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=m # CONFIG_CRYPTO_MICHAEL_MIC is not set -CONFIG_CRYPTO_RMD128=m -CONFIG_CRYPTO_RMD160=m -CONFIG_CRYPTO_RMD256=m -CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA1=m # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set @@ -916,7 +895,6 @@ CONFIG_BITREVERSE=m # CONFIG_GENERIC_FIND_NEXT_BIT is not set # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set -CONFIG_CRC_T10DIF=y # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=m CONFIG_CRC7=m diff --git a/trunk/arch/s390/include/asm/bitops.h b/trunk/arch/s390/include/asm/bitops.h index 8e9243ae0c19..b4eb24ab5af9 100644 --- a/trunk/arch/s390/include/asm/bitops.h +++ b/trunk/arch/s390/include/asm/bitops.h @@ -709,7 +709,7 @@ static inline int find_next_zero_bit (const unsigned long * addr, * __ffz_word returns __BITOPS_WORDSIZE * if no zero bit is present in the word. */ - set = __ffz_word(bit, *p >> bit); + set = __ffz_word(0, *p >> bit) + bit; if (set >= size) return size + offset; if (set < __BITOPS_WORDSIZE) @@ -824,7 +824,7 @@ static inline int ext2_find_next_zero_bit(void *vaddr, unsigned long size, * s390 version of ffz returns __BITOPS_WORDSIZE * if no zero bit is present in the word. */ - set = __ffz_word(bit, __load_ulong_le(p, 0) >> bit); + set = ffz(__load_ulong_le(p, 0) >> bit) + bit; if (set >= size) return size + offset; if (set < __BITOPS_WORDSIZE) @@ -865,7 +865,7 @@ static inline int ext2_find_next_bit(void *vaddr, unsigned long size, * s390 version of ffz returns __BITOPS_WORDSIZE * if no zero bit is present in the word. */ - set = __ffs_word(0, __load_ulong_le(p, 0) & (~0UL << bit)); + set = ffs(__load_ulong_le(p, 0) >> bit) + bit; if (set >= size) return size + offset; if (set < __BITOPS_WORDSIZE) diff --git a/trunk/arch/s390/kernel/process.c b/trunk/arch/s390/kernel/process.c index 3e2c05cb6a87..9839767d0842 100644 --- a/trunk/arch/s390/kernel/process.c +++ b/trunk/arch/s390/kernel/process.c @@ -75,9 +75,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk) return sf->gprs[8]; } -DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = { - .lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock) -}; +DEFINE_PER_CPU(struct s390_idle_data, s390_idle); static int s390_idle_enter(void) { diff --git a/trunk/arch/s390/kernel/smp.c b/trunk/arch/s390/kernel/smp.c index 00b9b4dec5eb..b795b3e24afd 100644 --- a/trunk/arch/s390/kernel/smp.c +++ b/trunk/arch/s390/kernel/smp.c @@ -610,6 +610,7 @@ static void __init smp_create_idle(unsigned int cpu) if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); current_set[cpu] = p; + spin_lock_init(&(&per_cpu(s390_idle, cpu))->lock); } static int __cpuinit smp_alloc_lowcore(int cpu) @@ -844,6 +845,7 @@ void __init smp_prepare_boot_cpu(void) current_set[0] = current; smp_cpu_state[0] = CPU_STATE_CONFIGURED; smp_cpu_polarization[0] = POLARIZATION_UNKNWN; + spin_lock_init(&(&__get_cpu_var(s390_idle))->lock); } void __init smp_cpus_done(unsigned int max_cpus) diff --git a/trunk/drivers/s390/block/dasd.c b/trunk/drivers/s390/block/dasd.c index acb78017e7d0..1b6c52ef7339 100644 --- a/trunk/drivers/s390/block/dasd.c +++ b/trunk/drivers/s390/block/dasd.c @@ -2333,11 +2333,13 @@ int dasd_generic_notify(struct ccw_device *cdev, int event) { struct dasd_device *device; struct dasd_ccw_req *cqr; + unsigned long flags; int ret; - device = dasd_device_from_cdev_locked(cdev); + device = dasd_device_from_cdev(cdev); if (IS_ERR(device)) return 0; + spin_lock_irqsave(get_ccwdev_lock(cdev), flags); ret = 0; switch (event) { case CIO_GONE: @@ -2367,6 +2369,7 @@ int dasd_generic_notify(struct ccw_device *cdev, int event) ret = 1; break; } + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); dasd_put_device(device); return ret; } diff --git a/trunk/drivers/s390/block/dasd_eckd.h b/trunk/drivers/s390/block/dasd_eckd.h index 2476f87d21d0..4bf0aa5112c1 100644 --- a/trunk/drivers/s390/block/dasd_eckd.h +++ b/trunk/drivers/s390/block/dasd_eckd.h @@ -308,7 +308,7 @@ struct dasd_psf_prssd_data { unsigned char flags; unsigned char reserved[4]; unsigned char suborder; - unsigned char varies[5]; + unsigned char varies[9]; } __attribute__ ((packed)); /* diff --git a/trunk/drivers/s390/block/dasd_eer.c b/trunk/drivers/s390/block/dasd_eer.c index bf512ac75b9e..29da4413ad43 100644 --- a/trunk/drivers/s390/block/dasd_eer.c +++ b/trunk/drivers/s390/block/dasd_eer.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -458,7 +457,7 @@ int dasd_eer_enable(struct dasd_device *device) cqr = dasd_kmalloc_request("ECKD", 1 /* SNSS */, SNSS_DATA_SIZE, device); - if (IS_ERR(cqr)) + if (!cqr) return -ENOMEM; cqr->startdev = device; diff --git a/trunk/drivers/s390/block/dcssblk.c b/trunk/drivers/s390/block/dcssblk.c index db85f1fb131e..01fcdd91b846 100644 --- a/trunk/drivers/s390/block/dcssblk.c +++ b/trunk/drivers/s390/block/dcssblk.c @@ -384,10 +384,6 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char * get minor, add to list */ down_write(&dcssblk_devices_sem); - if (dcssblk_get_segment_by_name(local_buf)) { - rc = -EEXIST; - goto release_gd; - } rc = dcssblk_assign_free_minor(dev_info); if (rc) { up_write(&dcssblk_devices_sem); diff --git a/trunk/drivers/s390/char/tape_char.c b/trunk/drivers/s390/char/tape_char.c index be0ce2215c8d..687720b552d1 100644 --- a/trunk/drivers/s390/char/tape_char.c +++ b/trunk/drivers/s390/char/tape_char.c @@ -109,7 +109,7 @@ tapechar_check_idalbuffer(struct tape_device *device, size_t block_size) /* The current idal buffer is not correct. Allocate a new one. */ new = idal_buffer_alloc(block_size, 0); - if (IS_ERR(new)) + if (new == NULL) return -ENOMEM; if (device->char_data.idal_buf != NULL) diff --git a/trunk/drivers/s390/char/tape_std.c b/trunk/drivers/s390/char/tape_std.c index cc8fd781ee22..2a1af4e60be0 100644 --- a/trunk/drivers/s390/char/tape_std.c +++ b/trunk/drivers/s390/char/tape_std.c @@ -248,7 +248,7 @@ tape_std_mtsetblk(struct tape_device *device, int count) /* Allocate a new idal buffer. */ new = idal_buffer_alloc(count, 0); - if (IS_ERR(new)) + if (new == NULL) return -ENOMEM; if (device->char_data.idal_buf != NULL) idal_buffer_free(device->char_data.idal_buf); diff --git a/trunk/drivers/s390/cio/ccwgroup.c b/trunk/drivers/s390/cio/ccwgroup.c index e0ce65fca4e7..26a930e832bd 100644 --- a/trunk/drivers/s390/cio/ccwgroup.c +++ b/trunk/drivers/s390/cio/ccwgroup.c @@ -112,10 +112,8 @@ ccwgroup_release (struct device *dev) gdev = to_ccwgroupdev(dev); for (i = 0; i < gdev->count; i++) { - if (gdev->cdev[i]) { - dev_set_drvdata(&gdev->cdev[i]->dev, NULL); - put_device(&gdev->cdev[i]->dev); - } + dev_set_drvdata(&gdev->cdev[i]->dev, NULL); + put_device(&gdev->cdev[i]->dev); } kfree(gdev); } @@ -223,13 +221,6 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, atomic_set(&gdev->onoff, 0); mutex_init(&gdev->reg_mutex); mutex_lock(&gdev->reg_mutex); - gdev->creator_id = creator_id; - gdev->count = num_devices; - gdev->dev.bus = &ccwgroup_bus_type; - gdev->dev.parent = root; - gdev->dev.release = ccwgroup_release; - device_initialize(&gdev->dev); - curr_buf = buf; for (i = 0; i < num_devices && curr_buf; i++) { rc = __get_next_bus_id(&curr_buf, tmp_bus_id); @@ -267,11 +258,16 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, rc = -EINVAL; goto error; } + gdev->creator_id = creator_id; + gdev->count = num_devices; + gdev->dev.bus = &ccwgroup_bus_type; + gdev->dev.parent = root; + gdev->dev.release = ccwgroup_release; snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s", gdev->cdev[0]->dev.bus_id); - rc = device_add(&gdev->dev); + rc = device_register(&gdev->dev); if (rc) goto error; get_device(&gdev->dev); diff --git a/trunk/drivers/s390/cio/css.c b/trunk/drivers/s390/cio/css.c index 51489eff6b0b..46c021d880dc 100644 --- a/trunk/drivers/s390/cio/css.c +++ b/trunk/drivers/s390/cio/css.c @@ -477,6 +477,7 @@ void css_schedule_eval_all(void) void css_wait_for_slow_path(void) { + flush_workqueue(ccw_device_notify_work); flush_workqueue(slow_path_wq); } diff --git a/trunk/drivers/s390/cio/device.c b/trunk/drivers/s390/cio/device.c index 28221030b886..e818d0c54c09 100644 --- a/trunk/drivers/s390/cio/device.c +++ b/trunk/drivers/s390/cio/device.c @@ -150,6 +150,7 @@ static struct css_driver io_subchannel_driver = { }; struct workqueue_struct *ccw_device_work; +struct workqueue_struct *ccw_device_notify_work; wait_queue_head_t ccw_device_init_wq; atomic_t ccw_device_init_count; @@ -167,6 +168,11 @@ init_ccw_bus_type (void) ccw_device_work = create_singlethread_workqueue("cio"); if (!ccw_device_work) return -ENOMEM; /* FIXME: better errno ? */ + ccw_device_notify_work = create_singlethread_workqueue("cio_notify"); + if (!ccw_device_notify_work) { + ret = -ENOMEM; /* FIXME: better errno ? */ + goto out_err; + } slow_path_wq = create_singlethread_workqueue("kslowcrw"); if (!slow_path_wq) { ret = -ENOMEM; /* FIXME: better errno ? */ @@ -186,6 +192,8 @@ init_ccw_bus_type (void) out_err: if (ccw_device_work) destroy_workqueue(ccw_device_work); + if (ccw_device_notify_work) + destroy_workqueue(ccw_device_notify_work); if (slow_path_wq) destroy_workqueue(slow_path_wq); return ret; @@ -196,6 +204,7 @@ cleanup_ccw_bus_type (void) { css_driver_unregister(&io_subchannel_driver); bus_unregister(&ccw_bus_type); + destroy_workqueue(ccw_device_notify_work); destroy_workqueue(ccw_device_work); } @@ -1487,22 +1496,11 @@ static void device_set_disconnected(struct ccw_device *cdev) ccw_device_schedule_recovery(); } -void ccw_device_set_notoper(struct ccw_device *cdev) -{ - struct subchannel *sch = to_subchannel(cdev->dev.parent); - - CIO_TRACE_EVENT(2, "notoper"); - CIO_TRACE_EVENT(2, sch->dev.bus_id); - ccw_device_set_timeout(cdev, 0); - cio_disable_subchannel(sch); - cdev->private->state = DEV_STATE_NOT_OPER; -} - static int io_subchannel_sch_event(struct subchannel *sch, int slow) { int event, ret, disc; unsigned long flags; - enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE, DISC } action; + enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE } action; struct ccw_device *cdev; spin_lock_irqsave(sch->lock, flags); @@ -1537,11 +1535,16 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow) } /* fall through */ case CIO_GONE: + /* Prevent unwanted effects when opening lock. */ + cio_disable_subchannel(sch); + device_set_disconnected(cdev); /* Ask driver what to do with device. */ - if (io_subchannel_notify(sch, event)) - action = DISC; - else - action = UNREGISTER; + action = UNREGISTER; + spin_unlock_irqrestore(sch->lock, flags); + ret = io_subchannel_notify(sch, event); + spin_lock_irqsave(sch->lock, flags); + if (ret) + action = NONE; break; case CIO_REVALIDATE: /* Device will be removed, so no notify necessary. */ @@ -1562,7 +1565,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow) switch (action) { case UNREGISTER: case UNREGISTER_PROBE: - ccw_device_set_notoper(cdev); /* Unregister device (will use subchannel lock). */ spin_unlock_irqrestore(sch->lock, flags); css_sch_device_unregister(sch); @@ -1575,9 +1577,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow) case REPROBE: ccw_device_trigger_reprobe(cdev); break; - case DISC: - device_set_disconnected(cdev); - break; default: break; } @@ -1829,4 +1828,5 @@ EXPORT_SYMBOL(ccw_driver_unregister); EXPORT_SYMBOL(get_ccwdev_by_busid); EXPORT_SYMBOL(ccw_bus_type); EXPORT_SYMBOL(ccw_device_work); +EXPORT_SYMBOL(ccw_device_notify_work); EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id); diff --git a/trunk/drivers/s390/cio/device.h b/trunk/drivers/s390/cio/device.h index 6f5c3f2b3587..9800a8335a3f 100644 --- a/trunk/drivers/s390/cio/device.h +++ b/trunk/drivers/s390/cio/device.h @@ -72,6 +72,7 @@ dev_fsm_final_state(struct ccw_device *cdev) } extern struct workqueue_struct *ccw_device_work; +extern struct workqueue_struct *ccw_device_notify_work; extern wait_queue_head_t ccw_device_init_wq; extern atomic_t ccw_device_init_count; @@ -119,7 +120,6 @@ int ccw_device_stlck(struct ccw_device *); void ccw_device_trigger_reprobe(struct ccw_device *); void ccw_device_kill_io(struct ccw_device *); int ccw_device_notify(struct ccw_device *, int); -void ccw_device_set_notoper(struct ccw_device *cdev); /* qdio needs this. */ void ccw_device_set_timeout(struct ccw_device *, int); diff --git a/trunk/drivers/s390/cio/device_fsm.c b/trunk/drivers/s390/cio/device_fsm.c index 550508df952b..8b5fe57fb2f3 100644 --- a/trunk/drivers/s390/cio/device_fsm.c +++ b/trunk/drivers/s390/cio/device_fsm.c @@ -337,34 +337,26 @@ int ccw_device_notify(struct ccw_device *cdev, int event) return 0; if (!cdev->online) return 0; - CIO_MSG_EVENT(2, "notify called for 0.%x.%04x, event=%d\n", - cdev->private->dev_id.ssid, cdev->private->dev_id.devno, - event); return cdev->drv->notify ? cdev->drv->notify(cdev, event) : 0; } -static void cmf_reenable_delayed(struct work_struct *work) +static void +ccw_device_oper_notify(struct work_struct *work) { struct ccw_device_private *priv; struct ccw_device *cdev; + int ret; priv = container_of(work, struct ccw_device_private, kick_work); cdev = priv->cdev; - cmf_reenable(cdev); -} - -static void ccw_device_oper_notify(struct ccw_device *cdev) -{ - if (ccw_device_notify(cdev, CIO_OPER)) { + ret = ccw_device_notify(cdev, CIO_OPER); + if (ret) { /* Reenable channel measurements, if needed. */ - PREPARE_WORK(&cdev->private->kick_work, cmf_reenable_delayed); - queue_work(ccw_device_work, &cdev->private->kick_work); - return; - } - /* Driver doesn't want device back. */ - ccw_device_set_notoper(cdev); - PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unreg_rereg); - queue_work(ccw_device_work, &cdev->private->kick_work); + cmf_reenable(cdev); + wake_up(&cdev->private->wait_q); + } else + /* Driver doesn't want device back. */ + ccw_device_do_unreg_rereg(work); } /* @@ -394,7 +386,8 @@ ccw_device_done(struct ccw_device *cdev, int state) if (cdev->private->flags.donotify) { cdev->private->flags.donotify = 0; - ccw_device_oper_notify(cdev); + PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify); + queue_work(ccw_device_notify_work, &cdev->private->kick_work); } wake_up(&cdev->private->wait_q); diff --git a/trunk/drivers/s390/cio/qdio_debug.h b/trunk/drivers/s390/cio/qdio_debug.h index 5a4d85b829ad..8484b83698e1 100644 --- a/trunk/drivers/s390/cio/qdio_debug.h +++ b/trunk/drivers/s390/cio/qdio_debug.h @@ -61,18 +61,18 @@ /* s390dbf views */ #define QDIO_DBF_SETUP_LEN 8 -#define QDIO_DBF_SETUP_PAGES 8 +#define QDIO_DBF_SETUP_PAGES 4 #define QDIO_DBF_SETUP_NR_AREAS 1 #define QDIO_DBF_TRACE_LEN 8 #define QDIO_DBF_TRACE_NR_AREAS 2 #ifdef CONFIG_QDIO_DEBUG -#define QDIO_DBF_TRACE_PAGES 32 +#define QDIO_DBF_TRACE_PAGES 16 #define QDIO_DBF_SETUP_LEVEL 6 #define QDIO_DBF_TRACE_LEVEL 4 #else /* !CONFIG_QDIO_DEBUG */ -#define QDIO_DBF_TRACE_PAGES 8 +#define QDIO_DBF_TRACE_PAGES 4 #define QDIO_DBF_SETUP_LEVEL 2 #define QDIO_DBF_TRACE_LEVEL 2 #endif /* CONFIG_QDIO_DEBUG */ diff --git a/trunk/drivers/s390/cio/qdio_main.c b/trunk/drivers/s390/cio/qdio_main.c index e6eabc853422..d15648514a0f 100644 --- a/trunk/drivers/s390/cio/qdio_main.c +++ b/trunk/drivers/s390/cio/qdio_main.c @@ -330,7 +330,6 @@ static int qdio_siga_output(struct qdio_q *q) int cc; u32 busy_bit; u64 start_time = 0; - char dbf_text[15]; QDIO_DBF_TEXT5(0, trace, "sigaout"); QDIO_DBF_HEX5(0, trace, &q, sizeof(void *)); @@ -339,9 +338,6 @@ static int qdio_siga_output(struct qdio_q *q) again: cc = qdio_do_siga_output(q, &busy_bit); if (queue_type(q) == QDIO_IQDIO_QFMT && cc == 2 && busy_bit) { - sprintf(dbf_text, "bb%4x%2x", q->irq_ptr->schid.sch_no, q->nr); - QDIO_DBF_TEXT3(0, trace, dbf_text); - if (!start_time) start_time = get_usecs(); else if ((get_usecs() - start_time) < QDIO_BUSY_BIT_PATIENCE) @@ -752,18 +748,16 @@ static void qdio_kick_outbound_q(struct qdio_q *q) rc = qdio_siga_output(q); switch (rc) { case 0: + /* went smooth this time, reset timestamp */ + q->u.out.timestamp = 0; + /* TODO: improve error handling for CC=0 case */ #ifdef CONFIG_QDIO_DEBUG - if (q->u.out.timestamp) { - QDIO_DBF_TEXT3(0, trace, "cc2reslv"); - sprintf(dbf_text, "%4x%2x%2x", q->irq_ptr->schid.sch_no, - q->nr, - atomic_read(&q->u.out.busy_siga_counter)); - QDIO_DBF_TEXT3(0, trace, dbf_text); - } + QDIO_DBF_TEXT3(0, trace, "cc2reslv"); + sprintf(dbf_text, "%4x%2x%2x", q->irq_ptr->schid.sch_no, q->nr, + atomic_read(&q->u.out.busy_siga_counter)); + QDIO_DBF_TEXT3(0, trace, dbf_text); #endif /* CONFIG_QDIO_DEBUG */ - /* went smooth this time, reset timestamp */ - q->u.out.timestamp = 0; break; /* cc=2 and busy bit */ case (2 | QDIO_ERROR_SIGA_BUSY): @@ -1072,12 +1066,14 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, if (IS_ERR(irb)) { switch (PTR_ERR(irb)) { case -EIO: - sprintf(dbf_text, "ierr%4x", irq_ptr->schid.sch_no); + sprintf(dbf_text, "ierr%4x", + cdev->private->schid.sch_no); QDIO_DBF_TEXT2(1, setup, dbf_text); qdio_int_error(cdev); return; case -ETIMEDOUT: - sprintf(dbf_text, "qtoh%4x", irq_ptr->schid.sch_no); + sprintf(dbf_text, "qtoh%4x", + cdev->private->schid.sch_no); QDIO_DBF_TEXT2(1, setup, dbf_text); qdio_int_error(cdev); return; @@ -1128,10 +1124,8 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, struct qdio_ssqd_desc *qdio_get_ssqd_desc(struct ccw_device *cdev) { struct qdio_irq *irq_ptr; - char dbf_text[15]; - sprintf(dbf_text, "qssq%4x", cdev->private->schid.sch_no); - QDIO_DBF_TEXT0(0, setup, dbf_text); + QDIO_DBF_TEXT0(0, setup, "getssqd"); irq_ptr = cdev->private->qdio_data; if (!irq_ptr) @@ -1155,13 +1149,14 @@ int qdio_cleanup(struct ccw_device *cdev, int how) char dbf_text[15]; int rc; - sprintf(dbf_text, "qcln%4x", cdev->private->schid.sch_no); - QDIO_DBF_TEXT0(0, setup, dbf_text); - irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; + sprintf(dbf_text, "qcln%4x", irq_ptr->schid.sch_no); + QDIO_DBF_TEXT1(0, trace, dbf_text); + QDIO_DBF_TEXT0(0, setup, dbf_text); + rc = qdio_shutdown(cdev, how); if (rc == 0) rc = qdio_free(cdev); @@ -1196,9 +1191,6 @@ int qdio_shutdown(struct ccw_device *cdev, int how) unsigned long flags; char dbf_text[15]; - sprintf(dbf_text, "qshu%4x", cdev->private->schid.sch_no); - QDIO_DBF_TEXT0(0, setup, dbf_text); - irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; @@ -1213,6 +1205,10 @@ int qdio_shutdown(struct ccw_device *cdev, int how) return 0; } + sprintf(dbf_text, "qsqs%4x", irq_ptr->schid.sch_no); + QDIO_DBF_TEXT1(0, trace, dbf_text); + QDIO_DBF_TEXT0(0, setup, dbf_text); + tiqdio_remove_input_queues(irq_ptr); qdio_shutdown_queues(cdev); qdio_shutdown_debug_entries(irq_ptr, cdev); @@ -1251,6 +1247,7 @@ int qdio_shutdown(struct ccw_device *cdev, int how) qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE); mutex_unlock(&irq_ptr->setup_mutex); + module_put(THIS_MODULE); if (rc) return rc; return 0; @@ -1266,14 +1263,16 @@ int qdio_free(struct ccw_device *cdev) struct qdio_irq *irq_ptr; char dbf_text[15]; - sprintf(dbf_text, "qfre%4x", cdev->private->schid.sch_no); - QDIO_DBF_TEXT0(0, setup, dbf_text); - irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; mutex_lock(&irq_ptr->setup_mutex); + + sprintf(dbf_text, "qfqs%4x", irq_ptr->schid.sch_no); + QDIO_DBF_TEXT1(0, trace, dbf_text); + QDIO_DBF_TEXT0(0, setup, dbf_text); + cdev->private->qdio_data = NULL; mutex_unlock(&irq_ptr->setup_mutex); @@ -1296,6 +1295,7 @@ int qdio_initialize(struct qdio_initialize *init_data) sprintf(dbf_text, "qini%4x", init_data->cdev->private->schid.sch_no); QDIO_DBF_TEXT0(0, setup, dbf_text); + QDIO_DBF_TEXT0(0, trace, dbf_text); rc = qdio_allocate(init_data); if (rc) @@ -1319,6 +1319,7 @@ int qdio_allocate(struct qdio_initialize *init_data) sprintf(dbf_text, "qalc%4x", init_data->cdev->private->schid.sch_no); QDIO_DBF_TEXT0(0, setup, dbf_text); + QDIO_DBF_TEXT0(0, trace, dbf_text); if ((init_data->no_input_qs && !init_data->input_handler) || (init_data->no_output_qs && !init_data->output_handler)) @@ -1388,9 +1389,6 @@ int qdio_establish(struct qdio_initialize *init_data) unsigned long saveflags; int rc; - sprintf(dbf_text, "qest%4x", cdev->private->schid.sch_no); - QDIO_DBF_TEXT0(0, setup, dbf_text); - irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; @@ -1398,6 +1396,13 @@ int qdio_establish(struct qdio_initialize *init_data) if (cdev->private->state != DEV_STATE_ONLINE) return -EINVAL; + if (!try_module_get(THIS_MODULE)) + return -EINVAL; + + sprintf(dbf_text, "qest%4x", cdev->private->schid.sch_no); + QDIO_DBF_TEXT0(0, setup, dbf_text); + QDIO_DBF_TEXT0(0, trace, dbf_text); + mutex_lock(&irq_ptr->setup_mutex); qdio_setup_irq(init_data); @@ -1467,9 +1472,6 @@ int qdio_activate(struct ccw_device *cdev) unsigned long saveflags; char dbf_text[20]; - sprintf(dbf_text, "qact%4x", cdev->private->schid.sch_no); - QDIO_DBF_TEXT0(0, setup, dbf_text); - irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; @@ -1483,6 +1485,10 @@ int qdio_activate(struct ccw_device *cdev) goto out; } + sprintf(dbf_text, "qact%4x", irq_ptr->schid.sch_no); + QDIO_DBF_TEXT2(0, setup, dbf_text); + QDIO_DBF_TEXT2(0, trace, dbf_text); + irq_ptr->ccw.cmd_code = irq_ptr->aqueue.cmd; irq_ptr->ccw.flags = CCW_FLAG_SLI; irq_ptr->ccw.count = irq_ptr->aqueue.count; @@ -1657,7 +1663,7 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, #ifdef CONFIG_QDIO_DEBUG char dbf_text[20]; - sprintf(dbf_text, "doQD%4x", cdev->private->schid.sch_no); + sprintf(dbf_text, "doQD%04x", cdev->private->schid.sch_no); QDIO_DBF_TEXT3(0, trace, dbf_text); #endif /* CONFIG_QDIO_DEBUG */ diff --git a/trunk/drivers/s390/cio/qdio_setup.c b/trunk/drivers/s390/cio/qdio_setup.c index 1679e2f91c94..1bd2a208db28 100644 --- a/trunk/drivers/s390/cio/qdio_setup.c +++ b/trunk/drivers/s390/cio/qdio_setup.c @@ -165,7 +165,7 @@ static void setup_queues(struct qdio_irq *irq_ptr, void **output_sbal_array = qdio_init->output_sbal_addr_array; int i; - sprintf(dbf_text, "qset%4x", qdio_init->cdev->private->schid.sch_no); + sprintf(dbf_text, "qfqs%4x", qdio_init->cdev->private->schid.sch_no); QDIO_DBF_TEXT0(0, setup, dbf_text); for_each_input_queue(irq_ptr, q, i) { @@ -285,7 +285,7 @@ void qdio_setup_ssqd_info(struct qdio_irq *irq_ptr) rc = __get_ssqd_info(irq_ptr); if (rc) { QDIO_DBF_TEXT2(0, setup, "ssqdasig"); - sprintf(dbf_text, "schn%4x", irq_ptr->schid.sch_no); + sprintf(dbf_text, "schno%x", irq_ptr->schid.sch_no); QDIO_DBF_TEXT2(0, setup, dbf_text); sprintf(dbf_text, "rc:%d", rc); QDIO_DBF_TEXT2(0, setup, dbf_text); @@ -447,7 +447,7 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, { char s[80]; - sprintf(s, "%s sc:%x ", cdev->dev.bus_id, irq_ptr->schid.sch_no); + sprintf(s, "%s ", cdev->dev.bus_id); switch (irq_ptr->qib.qfmt) { case QDIO_QETH_QFMT: diff --git a/trunk/drivers/s390/cio/qdio_thinint.c b/trunk/drivers/s390/cio/qdio_thinint.c index ea7f61400267..9291a771d812 100644 --- a/trunk/drivers/s390/cio/qdio_thinint.c +++ b/trunk/drivers/s390/cio/qdio_thinint.c @@ -113,11 +113,7 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) struct qdio_q *q; int i; - for (i = 0; i < irq_ptr->nr_input_qs; i++) { - q = irq_ptr->input_qs[i]; - /* if establish triggered an error */ - if (!q || !q->entry.prev || !q->entry.next) - continue; + for_each_input_queue(irq_ptr, q, i) { list_del_rcu(&q->entry); synchronize_rcu(); } diff --git a/trunk/drivers/usb/class/cdc-acm.c b/trunk/drivers/usb/class/cdc-acm.c index c257453fa9de..efc4373ededb 100644 --- a/trunk/drivers/usb/class/cdc-acm.c +++ b/trunk/drivers/usb/class/cdc-acm.c @@ -589,8 +589,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) tasklet_schedule(&acm->urb_task); done: - mutex_unlock(&acm->mutex); err_out: + mutex_unlock(&acm->mutex); mutex_unlock(&open_mutex); return rv; @@ -1362,9 +1362,6 @@ static struct usb_device_id acm_ids[] = { { USB_DEVICE(0x0803, 0x3095), /* Zoom Telephonics Model 3095F USB MODEM */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, - { USB_DEVICE(0x0572, 0x1321), /* Conexant USB MODEM CX93010 */ - .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ - }, /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, diff --git a/trunk/drivers/usb/core/driver.c b/trunk/drivers/usb/core/driver.c index 5a7fa6f09958..2be37fe466f2 100644 --- a/trunk/drivers/usb/core/driver.c +++ b/trunk/drivers/usb/core/driver.c @@ -230,13 +230,6 @@ static int usb_probe_interface(struct device *dev) */ intf->pm_usage_cnt = !(driver->supports_autosuspend); - /* Carry out a deferred switch to altsetting 0 */ - if (intf->needs_altsetting0) { - usb_set_interface(udev, intf->altsetting[0]. - desc.bInterfaceNumber, 0); - intf->needs_altsetting0 = 0; - } - error = driver->probe(intf, id); if (error) { mark_quiesced(intf); @@ -273,17 +266,8 @@ static int usb_unbind_interface(struct device *dev) driver->disconnect(intf); - /* Reset other interface state. - * We cannot do a Set-Interface if the device is suspended or - * if it is prepared for a system sleep (since installing a new - * altsetting means creating new endpoint device entries). - * When either of these happens, defer the Set-Interface. - */ - if (!error && intf->dev.power.status == DPM_ON) - usb_set_interface(udev, intf->altsetting[0]. - desc.bInterfaceNumber, 0); - else - intf->needs_altsetting0 = 1; + /* reset other interface state */ + usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0); usb_set_intfdata(intf, NULL); intf->condition = USB_INTERFACE_UNBOUND; @@ -814,8 +798,7 @@ void usb_forced_unbind_intf(struct usb_interface *intf) * The caller must hold @intf's device's lock, but not its pm_mutex * and not @intf->dev.sem. * - * Note: Rebinds will be skipped if a system sleep transition is in - * progress and the PM "complete" callback hasn't occurred yet. + * FIXME: The caller must block system sleep transitions. */ void usb_rebind_intf(struct usb_interface *intf) { @@ -831,12 +814,10 @@ void usb_rebind_intf(struct usb_interface *intf) } /* Try to rebind the interface */ - if (intf->dev.power.status == DPM_ON) { - intf->needs_binding = 0; - rc = device_attach(&intf->dev); - if (rc < 0) - dev_warn(&intf->dev, "rebind failed: %d\n", rc); - } + intf->needs_binding = 0; + rc = device_attach(&intf->dev); + if (rc < 0) + dev_warn(&intf->dev, "rebind failed: %d\n", rc); } #ifdef CONFIG_PM @@ -848,6 +829,7 @@ void usb_rebind_intf(struct usb_interface *intf) * or rebind interfaces that have been unbound, according to @action. * * The caller must hold @udev's device lock. + * FIXME: For rebinds, the caller must block system sleep transitions. */ static void do_unbind_rebind(struct usb_device *udev, int action) { @@ -869,8 +851,22 @@ static void do_unbind_rebind(struct usb_device *udev, int action) } break; case DO_REBIND: - if (intf->needs_binding) + if (intf->needs_binding) { + + /* FIXME: The next line is needed because we are going to probe + * the interface, but as far as the PM core is concerned the + * interface is still suspended. The problem wouldn't exist + * if we could rebind the interface during the interface's own + * resume() call, but at the time the usb_device isn't locked! + * + * The real solution will be to carry this out during the device's + * complete() callback. Until that is implemented, we have to + * use this hack. + */ +// intf->dev.power.sleeping = 0; + usb_rebind_intf(intf); + } break; } } @@ -930,14 +926,14 @@ static int usb_resume_device(struct usb_device *udev) } /* Caller has locked intf's usb_device's pm mutex */ -static int usb_suspend_interface(struct usb_device *udev, - struct usb_interface *intf, pm_message_t msg) +static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg) { struct usb_driver *driver; int status = 0; /* with no hardware, USB interfaces only use FREEZE and ON states */ - if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf)) + if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED || + !is_active(intf)) goto done; if (intf->condition == USB_INTERFACE_UNBOUND) /* This can't happen */ @@ -948,7 +944,7 @@ static int usb_suspend_interface(struct usb_device *udev, status = driver->suspend(intf, msg); if (status == 0) mark_quiesced(intf); - else if (!udev->auto_pm) + else if (!interface_to_usbdev(intf)->auto_pm) dev_err(&intf->dev, "%s error %d\n", "suspend", status); } else { @@ -965,13 +961,13 @@ static int usb_suspend_interface(struct usb_device *udev, } /* Caller has locked intf's usb_device's pm_mutex */ -static int usb_resume_interface(struct usb_device *udev, - struct usb_interface *intf, int reset_resume) +static int usb_resume_interface(struct usb_interface *intf, int reset_resume) { struct usb_driver *driver; int status = 0; - if (udev->state == USB_STATE_NOTATTACHED || is_active(intf)) + if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED || + is_active(intf)) goto done; /* Don't let autoresume interfere with unbinding */ @@ -979,17 +975,8 @@ static int usb_resume_interface(struct usb_device *udev, goto done; /* Can't resume it if it doesn't have a driver. */ - if (intf->condition == USB_INTERFACE_UNBOUND) { - - /* Carry out a deferred switch to altsetting 0 */ - if (intf->needs_altsetting0 && - intf->dev.power.status == DPM_ON) { - usb_set_interface(udev, intf->altsetting[0]. - desc.bInterfaceNumber, 0); - intf->needs_altsetting0 = 0; - } + if (intf->condition == USB_INTERFACE_UNBOUND) goto done; - } /* Don't resume if the interface is marked for rebinding */ if (intf->needs_binding) @@ -1164,7 +1151,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) if (udev->actconfig) { for (; i < udev->actconfig->desc.bNumInterfaces; i++) { intf = udev->actconfig->interface[i]; - status = usb_suspend_interface(udev, intf, msg); + status = usb_suspend_interface(intf, msg); if (status != 0) break; } @@ -1176,7 +1163,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) if (status != 0) { while (--i >= 0) { intf = udev->actconfig->interface[i]; - usb_resume_interface(udev, intf, 0); + usb_resume_interface(intf, 0); } /* Try another autosuspend when the interfaces aren't busy */ @@ -1289,7 +1276,7 @@ static int usb_resume_both(struct usb_device *udev) if (status == 0 && udev->actconfig) { for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { intf = udev->actconfig->interface[i]; - usb_resume_interface(udev, intf, udev->reset_resume); + usb_resume_interface(intf, udev->reset_resume); } } @@ -1618,10 +1605,12 @@ int usb_external_resume_device(struct usb_device *udev) return status; } -int usb_suspend(struct device *dev, pm_message_t message) +static int usb_suspend(struct device *dev, pm_message_t message) { struct usb_device *udev; + if (!is_usb_device(dev)) /* Ignore PM for interfaces */ + return 0; udev = to_usb_device(dev); /* If udev is already suspended, we can skip this suspend and @@ -1640,10 +1629,12 @@ int usb_suspend(struct device *dev, pm_message_t message) return usb_external_suspend_device(udev, message); } -int usb_resume(struct device *dev) +static int usb_resume(struct device *dev) { struct usb_device *udev; + if (!is_usb_device(dev)) /* Ignore PM for interfaces */ + return 0; udev = to_usb_device(dev); /* If udev->skip_sys_resume is set then udev was already suspended @@ -1655,10 +1646,17 @@ int usb_resume(struct device *dev) return usb_external_resume_device(udev); } +#else + +#define usb_suspend NULL +#define usb_resume NULL + #endif /* CONFIG_PM */ struct bus_type usb_bus_type = { .name = "usb", .match = usb_device_match, .uevent = usb_uevent, + .suspend = usb_suspend, + .resume = usb_resume, }; diff --git a/trunk/drivers/usb/core/hcd.c b/trunk/drivers/usb/core/hcd.c index 8abd4e59bf4a..f7bfd72ef115 100644 --- a/trunk/drivers/usb/core/hcd.c +++ b/trunk/drivers/usb/core/hcd.c @@ -924,6 +924,15 @@ static int register_root_hub(struct usb_hcd *hcd) return retval; } +void usb_enable_root_hub_irq (struct usb_bus *bus) +{ + struct usb_hcd *hcd; + + hcd = container_of (bus, struct usb_hcd, self); + if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT) + hcd->driver->hub_irq_enable (hcd); +} + /*-------------------------------------------------------------------------*/ diff --git a/trunk/drivers/usb/core/hcd.h b/trunk/drivers/usb/core/hcd.h index e710ce04e228..5b0b59b0d89b 100644 --- a/trunk/drivers/usb/core/hcd.h +++ b/trunk/drivers/usb/core/hcd.h @@ -212,6 +212,8 @@ struct hc_driver { int (*bus_suspend)(struct usb_hcd *); int (*bus_resume)(struct usb_hcd *); int (*start_port_reset)(struct usb_hcd *, unsigned port_num); + void (*hub_irq_enable)(struct usb_hcd *); + /* Needed only if port-change IRQs are level-triggered */ /* force handover of high-speed port to full-speed companion */ void (*relinquish_port)(struct usb_hcd *, int); @@ -377,6 +379,8 @@ extern struct list_head usb_bus_list; extern struct mutex usb_bus_list_lock; extern wait_queue_head_t usb_kill_urb_queue; +extern void usb_enable_root_hub_irq(struct usb_bus *bus); + extern int usb_find_interface_driver(struct usb_device *dev, struct usb_interface *interface); diff --git a/trunk/drivers/usb/core/hub.c b/trunk/drivers/usb/core/hub.c index 6a5cb018383d..107e1d25ddec 100644 --- a/trunk/drivers/usb/core/hub.c +++ b/trunk/drivers/usb/core/hub.c @@ -2102,6 +2102,8 @@ int usb_port_resume(struct usb_device *udev) } clear_bit(port1, hub->busy_bits); + if (!hub->hdev->parent && !hub->busy_bits[0]) + usb_enable_root_hub_irq(hub->hdev->bus); status = check_port_resume_type(udev, hub, port1, status, portchange, portstatus); @@ -3079,6 +3081,11 @@ static void hub_events(void) } } + /* If this is a root hub, tell the HCD it's okay to + * re-enable port-change interrupts now. */ + if (!hdev->parent && !hub->busy_bits[0]) + usb_enable_root_hub_irq(hdev->bus); + loop_autopm: /* Allow autosuspend if we're not going to run again */ if (list_empty(&hub->event_list)) @@ -3304,6 +3311,8 @@ static int usb_reset_and_verify_device(struct usb_device *udev) break; } clear_bit(port1, parent_hub->busy_bits); + if (!parent_hdev->parent && !parent_hub->busy_bits[0]) + usb_enable_root_hub_irq(parent_hdev->bus); if (ret < 0) goto re_enumerate; diff --git a/trunk/drivers/usb/core/urb.c b/trunk/drivers/usb/core/urb.c index 47111e88f791..c0b1ae25ae2a 100644 --- a/trunk/drivers/usb/core/urb.c +++ b/trunk/drivers/usb/core/urb.c @@ -601,20 +601,15 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs); void usb_unlink_anchored_urbs(struct usb_anchor *anchor) { struct urb *victim; - unsigned long flags; - spin_lock_irqsave(&anchor->lock, flags); + spin_lock_irq(&anchor->lock); while (!list_empty(&anchor->urb_list)) { victim = list_entry(anchor->urb_list.prev, struct urb, anchor_list); - usb_get_urb(victim); - spin_unlock_irqrestore(&anchor->lock, flags); /* this will unanchor the URB */ usb_unlink_urb(victim); - usb_put_urb(victim); - spin_lock_irqsave(&anchor->lock, flags); } - spin_unlock_irqrestore(&anchor->lock, flags); + spin_unlock_irq(&anchor->lock); } EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs); diff --git a/trunk/drivers/usb/core/usb.c b/trunk/drivers/usb/core/usb.c index be1fa0723f2c..84fcaa6a21ec 100644 --- a/trunk/drivers/usb/core/usb.c +++ b/trunk/drivers/usb/core/usb.c @@ -219,6 +219,12 @@ static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env) } #endif /* CONFIG_HOTPLUG */ +struct device_type usb_device_type = { + .name = "usb_device", + .release = usb_release_dev, + .uevent = usb_dev_uevent, +}; + #ifdef CONFIG_PM static int ksuspend_usb_init(void) @@ -238,80 +244,13 @@ static void ksuspend_usb_cleanup(void) destroy_workqueue(ksuspend_usb_wq); } -/* USB device Power-Management thunks. - * There's no need to distinguish here between quiescing a USB device - * and powering it down; the generic_suspend() routine takes care of - * it by skipping the usb_port_suspend() call for a quiesce. And for - * USB interfaces there's no difference at all. - */ - -static int usb_dev_prepare(struct device *dev) -{ - return 0; /* Implement eventually? */ -} - -static void usb_dev_complete(struct device *dev) -{ - /* Currently used only for rebinding interfaces */ - usb_resume(dev); /* Implement eventually? */ -} - -static int usb_dev_suspend(struct device *dev) -{ - return usb_suspend(dev, PMSG_SUSPEND); -} - -static int usb_dev_resume(struct device *dev) -{ - return usb_resume(dev); -} - -static int usb_dev_freeze(struct device *dev) -{ - return usb_suspend(dev, PMSG_FREEZE); -} - -static int usb_dev_thaw(struct device *dev) -{ - return usb_resume(dev); -} - -static int usb_dev_poweroff(struct device *dev) -{ - return usb_suspend(dev, PMSG_HIBERNATE); -} - -static int usb_dev_restore(struct device *dev) -{ - return usb_resume(dev); -} - -static struct pm_ops usb_device_pm_ops = { - .prepare = usb_dev_prepare, - .complete = usb_dev_complete, - .suspend = usb_dev_suspend, - .resume = usb_dev_resume, - .freeze = usb_dev_freeze, - .thaw = usb_dev_thaw, - .poweroff = usb_dev_poweroff, - .restore = usb_dev_restore, -}; - #else #define ksuspend_usb_init() 0 #define ksuspend_usb_cleanup() do {} while (0) -#define usb_device_pm_ops (*(struct pm_ops *)0) #endif /* CONFIG_PM */ -struct device_type usb_device_type = { - .name = "usb_device", - .release = usb_release_dev, - .uevent = usb_dev_uevent, - .pm = &usb_device_pm_ops, -}; - /* Returns 1 if @usb_bus is WUSB, 0 otherwise */ static unsigned usb_bus_is_wusb(struct usb_bus *bus) diff --git a/trunk/drivers/usb/core/usb.h b/trunk/drivers/usb/core/usb.h index 9a1a45ac3add..d9a6e16dbf84 100644 --- a/trunk/drivers/usb/core/usb.h +++ b/trunk/drivers/usb/core/usb.h @@ -41,9 +41,6 @@ extern void usb_host_cleanup(void); #ifdef CONFIG_PM -extern int usb_suspend(struct device *dev, pm_message_t msg); -extern int usb_resume(struct device *dev); - extern void usb_autosuspend_work(struct work_struct *work); extern int usb_port_suspend(struct usb_device *dev); extern int usb_port_resume(struct usb_device *dev); diff --git a/trunk/drivers/usb/gadget/pxa27x_udc.c b/trunk/drivers/usb/gadget/pxa27x_udc.c index 7cbc78a6853d..a28513ecbe5b 100644 --- a/trunk/drivers/usb/gadget/pxa27x_udc.c +++ b/trunk/drivers/usb/gadget/pxa27x_udc.c @@ -1622,7 +1622,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) struct pxa_udc *udc = the_controller; int retval; - if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind + if (!driver || driver->speed != USB_SPEED_FULL || !driver->bind || !driver->disconnect || !driver->setup) return -EINVAL; if (!udc) diff --git a/trunk/drivers/usb/host/isp1760-hcd.c b/trunk/drivers/usb/host/isp1760-hcd.c index 8017f1cf78e2..d22a84f86a33 100644 --- a/trunk/drivers/usb/host/isp1760-hcd.c +++ b/trunk/drivers/usb/host/isp1760-hcd.c @@ -988,7 +988,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd) /* * write bank1 address twice to ensure the 90ns delay (time * between BANK0 write and the priv_read_copy() call is at - * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 109ns) + * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 92ns) */ isp1760_writel(payload + ISP_BANK(1), usb_hcd->regs + HC_MEMORY_REG); diff --git a/trunk/drivers/usb/host/ohci-at91.c b/trunk/drivers/usb/host/ohci-at91.c index 4ed228a89943..6db7a2889e66 100644 --- a/trunk/drivers/usb/host/ohci-at91.c +++ b/trunk/drivers/usb/host/ohci-at91.c @@ -260,6 +260,7 @@ static const struct hc_driver ohci_at91_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-au1xxx.c b/trunk/drivers/usb/host/ohci-au1xxx.c index 2ac4e022a13f..c0948008fe3d 100644 --- a/trunk/drivers/usb/host/ohci-au1xxx.c +++ b/trunk/drivers/usb/host/ohci-au1xxx.c @@ -163,6 +163,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-ep93xx.c b/trunk/drivers/usb/host/ohci-ep93xx.c index fb3055f084b5..cb0b506f8259 100644 --- a/trunk/drivers/usb/host/ohci-ep93xx.c +++ b/trunk/drivers/usb/host/ohci-ep93xx.c @@ -134,6 +134,7 @@ static struct hc_driver ohci_ep93xx_hc_driver = { .get_frame_number = ohci_get_frame, .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-hub.c b/trunk/drivers/usb/host/ohci-hub.c index 7ea9a7b31155..439beb784f3e 100644 --- a/trunk/drivers/usb/host/ohci-hub.c +++ b/trunk/drivers/usb/host/ohci-hub.c @@ -36,6 +36,18 @@ /*-------------------------------------------------------------------------*/ +/* hcd->hub_irq_enable() */ +static void ohci_rhsc_enable (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + + spin_lock_irq(&ohci->lock); + if (!ohci->autostop) + del_timer(&hcd->rh_timer); /* Prevent next poll */ + ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); + spin_unlock_irq(&ohci->lock); +} + #define OHCI_SCHED_ENABLES \ (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) @@ -362,28 +374,18 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, int any_connected) { int poll_rh = 1; - int rhsc; - rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC; switch (ohci->hc_control & OHCI_CTRL_HCFS) { case OHCI_USB_OPER: - /* If no status changes are pending, enable status-change - * interrupts. - */ - if (!rhsc && !changed) { - rhsc = OHCI_INTR_RHSC; - ohci_writel(ohci, rhsc, &ohci->regs->intrenable); - } - - /* Keep on polling until we know a device is connected - * and RHSC is enabled, or until we autostop. - */ + /* keep on polling until we know a device is connected + * and RHSC is enabled */ if (!ohci->autostop) { if (any_connected || !device_may_wakeup(&ohci_to_hcd(ohci) ->self.root_hub->dev)) { - if (rhsc) + if (ohci_readl(ohci, &ohci->regs->intrenable) & + OHCI_INTR_RHSC) poll_rh = 0; } else { ohci->autostop = 1; @@ -396,13 +398,12 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, ohci->autostop = 0; ohci->next_statechange = jiffies + STATECHANGE_DELAY; - } else if (rhsc && time_after_eq(jiffies, + } else if (time_after_eq(jiffies, ohci->next_statechange) && !ohci->ed_rm_list && !(ohci->hc_control & OHCI_SCHED_ENABLES)) { ohci_rh_suspend(ohci, 1); - poll_rh = 0; } } break; @@ -416,12 +417,6 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, else usb_hcd_resume_root_hub(ohci_to_hcd(ohci)); } else { - if (!rhsc && (ohci->autostop || - ohci_to_hcd(ohci)->self.root_hub-> - do_remote_wakeup)) - ohci_writel(ohci, OHCI_INTR_RHSC, - &ohci->regs->intrenable); - /* everything is idle, no need for polling */ poll_rh = 0; } @@ -443,16 +438,12 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci) static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, int any_connected) { - /* If RHSC is enabled, don't poll */ - if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC) - return 0; + int poll_rh = 1; - /* If no status changes are pending, enable status-change interrupts */ - if (!changed) { - ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); - return 0; - } - return 1; + /* keep on polling until RHSC is enabled */ + if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC) + poll_rh = 0; + return poll_rh; } #endif /* CONFIG_PM */ diff --git a/trunk/drivers/usb/host/ohci-lh7a404.c b/trunk/drivers/usb/host/ohci-lh7a404.c index de42283149c7..9e31d440d115 100644 --- a/trunk/drivers/usb/host/ohci-lh7a404.c +++ b/trunk/drivers/usb/host/ohci-lh7a404.c @@ -193,6 +193,7 @@ static const struct hc_driver ohci_lh7a404_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-omap.c b/trunk/drivers/usb/host/ohci-omap.c index 1eb64d08b60a..3d532b709670 100644 --- a/trunk/drivers/usb/host/ohci-omap.c +++ b/trunk/drivers/usb/host/ohci-omap.c @@ -470,6 +470,7 @@ static const struct hc_driver ohci_omap_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-pci.c b/trunk/drivers/usb/host/ohci-pci.c index a9c2ae36c7ad..083e8df0a817 100644 --- a/trunk/drivers/usb/host/ohci-pci.c +++ b/trunk/drivers/usb/host/ohci-pci.c @@ -459,6 +459,7 @@ static const struct hc_driver ohci_pci_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-pnx4008.c b/trunk/drivers/usb/host/ohci-pnx4008.c index 658a2a978c32..b02cd0761977 100644 --- a/trunk/drivers/usb/host/ohci-pnx4008.c +++ b/trunk/drivers/usb/host/ohci-pnx4008.c @@ -277,6 +277,7 @@ static const struct hc_driver ohci_pnx4008_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-pnx8550.c b/trunk/drivers/usb/host/ohci-pnx8550.c index 28467e288a93..605d59cba28e 100644 --- a/trunk/drivers/usb/host/ohci-pnx8550.c +++ b/trunk/drivers/usb/host/ohci-pnx8550.c @@ -201,6 +201,7 @@ static const struct hc_driver ohci_pnx8550_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-ppc-of.c b/trunk/drivers/usb/host/ohci-ppc-of.c index 7ac53264ead3..91e6e101a4cc 100644 --- a/trunk/drivers/usb/host/ohci-ppc-of.c +++ b/trunk/drivers/usb/host/ohci-ppc-of.c @@ -72,6 +72,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-ppc-soc.c b/trunk/drivers/usb/host/ohci-ppc-soc.c index cd3398b675b2..523c30125577 100644 --- a/trunk/drivers/usb/host/ohci-ppc-soc.c +++ b/trunk/drivers/usb/host/ohci-ppc-soc.c @@ -172,6 +172,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-ps3.c b/trunk/drivers/usb/host/ohci-ps3.c index 2089d8a46c4b..55c95647f008 100644 --- a/trunk/drivers/usb/host/ohci-ps3.c +++ b/trunk/drivers/usb/host/ohci-ps3.c @@ -68,6 +68,7 @@ static const struct hc_driver ps3_ohci_hc_driver = { .get_frame_number = ohci_get_frame, .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, .start_port_reset = ohci_start_port_reset, #if defined(CONFIG_PM) .bus_suspend = ohci_bus_suspend, diff --git a/trunk/drivers/usb/host/ohci-pxa27x.c b/trunk/drivers/usb/host/ohci-pxa27x.c index 7f0f35c78185..8c9c4849db6e 100644 --- a/trunk/drivers/usb/host/ohci-pxa27x.c +++ b/trunk/drivers/usb/host/ohci-pxa27x.c @@ -298,6 +298,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-s3c2410.c b/trunk/drivers/usb/host/ohci-s3c2410.c index f46af7a718d4..9e3dc4069e8b 100644 --- a/trunk/drivers/usb/host/ohci-s3c2410.c +++ b/trunk/drivers/usb/host/ohci-s3c2410.c @@ -466,6 +466,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = { */ .hub_status_data = ohci_s3c2410_hub_status_data, .hub_control = ohci_s3c2410_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-sa1111.c b/trunk/drivers/usb/host/ohci-sa1111.c index e4bbe8e188e4..4626b002e670 100644 --- a/trunk/drivers/usb/host/ohci-sa1111.c +++ b/trunk/drivers/usb/host/ohci-sa1111.c @@ -231,6 +231,7 @@ static const struct hc_driver ohci_sa1111_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-sh.c b/trunk/drivers/usb/host/ohci-sh.c index 60f03cc7ec4f..e7ee607278fe 100644 --- a/trunk/drivers/usb/host/ohci-sh.c +++ b/trunk/drivers/usb/host/ohci-sh.c @@ -68,6 +68,7 @@ static const struct hc_driver ohci_sh_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-sm501.c b/trunk/drivers/usb/host/ohci-sm501.c index cff23637cfcc..21b164e4abeb 100644 --- a/trunk/drivers/usb/host/ohci-sm501.c +++ b/trunk/drivers/usb/host/ohci-sm501.c @@ -75,6 +75,7 @@ static const struct hc_driver ohci_sm501_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/ohci-ssb.c b/trunk/drivers/usb/host/ohci-ssb.c index 23fd6a886bdd..3660c83d80af 100644 --- a/trunk/drivers/usb/host/ohci-ssb.c +++ b/trunk/drivers/usb/host/ohci-ssb.c @@ -81,6 +81,7 @@ static const struct hc_driver ssb_ohci_hc_driver = { .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/trunk/drivers/usb/host/u132-hcd.c b/trunk/drivers/usb/host/u132-hcd.c index 228f2b070f2b..20ad3c48fcb2 100644 --- a/trunk/drivers/usb/host/u132-hcd.c +++ b/trunk/drivers/usb/host/u132-hcd.c @@ -2934,6 +2934,16 @@ static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num) return 0; } +static void u132_hub_irq_enable(struct usb_hcd *hcd) +{ + struct u132 *u132 = hcd_to_u132(hcd); + if (u132->going > 1) { + dev_err(&u132->platform_dev->dev, "device has been removed %d\n" + , u132->going); + } else if (u132->going > 0) + dev_err(&u132->platform_dev->dev, "device is being removed\n"); +} + #ifdef CONFIG_PM static int u132_bus_suspend(struct usb_hcd *hcd) @@ -2985,6 +2995,7 @@ static struct hc_driver u132_hc_driver = { .bus_suspend = u132_bus_suspend, .bus_resume = u132_bus_resume, .start_port_reset = u132_start_port_reset, + .hub_irq_enable = u132_hub_irq_enable, }; /* diff --git a/trunk/drivers/usb/misc/sisusbvga/sisusb.c b/trunk/drivers/usb/misc/sisusbvga/sisusb.c index 69c34a58e205..fbace41a7cba 100644 --- a/trunk/drivers/usb/misc/sisusbvga/sisusb.c +++ b/trunk/drivers/usb/misc/sisusbvga/sisusb.c @@ -3270,7 +3270,6 @@ static struct usb_device_id sisusb_table [] = { { USB_DEVICE(0x0711, 0x0900) }, { USB_DEVICE(0x0711, 0x0901) }, { USB_DEVICE(0x0711, 0x0902) }, - { USB_DEVICE(0x0711, 0x0918) }, { USB_DEVICE(0x182d, 0x021c) }, { USB_DEVICE(0x182d, 0x0269) }, { } diff --git a/trunk/drivers/usb/musb/Kconfig b/trunk/drivers/usb/musb/Kconfig index a0017486ad4e..faca4333f27a 100644 --- a/trunk/drivers/usb/musb/Kconfig +++ b/trunk/drivers/usb/musb/Kconfig @@ -165,11 +165,12 @@ config USB_TUSB_OMAP_DMA help Enable DMA transfers on TUSB 6010 when OMAP DMA is available. -config USB_MUSB_DEBUG +config USB_MUSB_LOGLEVEL depends on USB_MUSB_HDRC - bool "Enable debugging messages" - default n + int 'Logging Level (0 - none / 3 - annoying / ... )' + default 0 help - This enables musb debugging. To set the logging level use the debug - module parameter. Starting at level 3, per-transfer (urb, usb_request, - packet, or dma transfer) tracing may kick in. + Set the logging level. 0 disables the debugging altogether, + although when USB_DEBUG is set the value is at least 1. + Starting at level 3, per-transfer (urb, usb_request, packet, + or dma transfer) tracing may kick in. diff --git a/trunk/drivers/usb/musb/Makefile b/trunk/drivers/usb/musb/Makefile index b6af0d687a73..88eb67de08ae 100644 --- a/trunk/drivers/usb/musb/Makefile +++ b/trunk/drivers/usb/musb/Makefile @@ -64,6 +64,23 @@ endif # Debugging -ifeq ($(CONFIG_USB_MUSB_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG +MUSB_DEBUG:=$(CONFIG_USB_MUSB_LOGLEVEL) + +ifeq ("$(strip $(MUSB_DEBUG))","") + ifdef CONFIG_USB_DEBUG + MUSB_DEBUG:=1 + else + MUSB_DEBUG:=0 + endif endif + +ifneq ($(MUSB_DEBUG),0) + EXTRA_CFLAGS += -DDEBUG + + ifeq ($(CONFIG_PROC_FS),y) + musb_hdrc-objs += musb_procfs.o + endif + +endif + +EXTRA_CFLAGS += -DMUSB_DEBUG=$(MUSB_DEBUG) diff --git a/trunk/drivers/usb/musb/musb_core.c b/trunk/drivers/usb/musb/musb_core.c index c5b8f0296fcf..d68ec6daf335 100644 --- a/trunk/drivers/usb/musb/musb_core.c +++ b/trunk/drivers/usb/musb/musb_core.c @@ -114,14 +114,23 @@ -unsigned debug; -module_param(debug, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug message level. Default = 0"); +#if MUSB_DEBUG > 0 +unsigned debug = MUSB_DEBUG; +module_param(debug, uint, 0); +MODULE_PARM_DESC(debug, "initial debug message level"); + +#define MUSB_VERSION_SUFFIX "/dbg" +#endif #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" #define DRIVER_DESC "Inventra Dual-Role USB Controller Driver" -#define MUSB_VERSION "6.0" +#define MUSB_VERSION_BASE "6.0" + +#ifndef MUSB_VERSION_SUFFIX +#define MUSB_VERSION_SUFFIX "" +#endif +#define MUSB_VERSION MUSB_VERSION_BASE MUSB_VERSION_SUFFIX #define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION @@ -2028,8 +2037,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb->xceiv.state = OTG_STATE_A_IDLE; status = usb_add_hcd(musb_to_hcd(musb), -1, 0); - if (status) - goto fail; DBG(1, "%s mode, status %d, devctl %02x %c\n", "HOST", status, @@ -2044,8 +2051,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb->xceiv.state = OTG_STATE_B_IDLE; status = musb_gadget_setup(musb); - if (status) - goto fail; DBG(1, "%s mode, status %d, dev%02x\n", is_otg_enabled(musb) ? "OTG" : "PERIPHERAL", @@ -2054,14 +2059,16 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) } - return 0; - + if (status == 0) + musb_debug_create("driver/musb_hdrc", musb); + else { fail: - if (musb->clock) - clk_put(musb->clock); - device_init_wakeup(dev, 0); - musb_free(musb); - return status; + if (musb->clock) + clk_put(musb->clock); + device_init_wakeup(dev, 0); + musb_free(musb); + return status; + } #ifdef CONFIG_SYSFS status = device_create_file(dev, &dev_attr_mode); @@ -2124,6 +2131,7 @@ static int __devexit musb_remove(struct platform_device *pdev) * - OTG mode: both roles are deactivated (or never-activated) */ musb_shutdown(pdev); + musb_debug_delete("driver/musb_hdrc", musb); #ifdef CONFIG_USB_MUSB_HDRC_HCD if (musb->board_mode == MUSB_HOST) usb_remove_hcd(musb_to_hcd(musb)); diff --git a/trunk/drivers/usb/musb/musb_core.h b/trunk/drivers/usb/musb/musb_core.h index 82227251931b..eade46d81708 100644 --- a/trunk/drivers/usb/musb/musb_core.h +++ b/trunk/drivers/usb/musb/musb_core.h @@ -485,4 +485,23 @@ extern int musb_platform_get_vbus_status(struct musb *musb); extern int __init musb_platform_init(struct musb *musb); extern int musb_platform_exit(struct musb *musb); +/*-------------------------- ProcFS definitions ---------------------*/ + +struct proc_dir_entry; + +#if (MUSB_DEBUG > 0) && defined(MUSB_CONFIG_PROC_FS) +extern struct proc_dir_entry *musb_debug_create(char *name, struct musb *data); +extern void musb_debug_delete(char *name, struct musb *data); + +#else +static inline struct proc_dir_entry * +musb_debug_create(char *name, struct musb *data) +{ + return NULL; +} +static inline void musb_debug_delete(char *name, struct musb *data) +{ +} +#endif + #endif /* __MUSB_CORE_H__ */ diff --git a/trunk/drivers/usb/musb/musb_debug.h b/trunk/drivers/usb/musb/musb_debug.h index 4d2794441b15..3bdb311e820d 100644 --- a/trunk/drivers/usb/musb/musb_debug.h +++ b/trunk/drivers/usb/musb/musb_debug.h @@ -48,7 +48,11 @@ __func__, __LINE__ , ## args); \ } } while (0) +#if MUSB_DEBUG > 0 extern unsigned debug; +#else +#define debug 0 +#endif static inline int _dbg_level(unsigned l) { diff --git a/trunk/drivers/usb/musb/musb_gadget_ep0.c b/trunk/drivers/usb/musb/musb_gadget_ep0.c index a57652fff39c..48d7d3ccb243 100644 --- a/trunk/drivers/usb/musb/musb_gadget_ep0.c +++ b/trunk/drivers/usb/musb/musb_gadget_ep0.c @@ -476,7 +476,6 @@ static void ep0_rxstate(struct musb *musb) return; musb->ackpend = 0; } - musb_ep_select(musb->mregs, 0); musb_writew(regs, MUSB_CSR0, tmp); } @@ -529,7 +528,6 @@ static void ep0_txstate(struct musb *musb) } /* send it out, triggering a "txpktrdy cleared" irq */ - musb_ep_select(musb->mregs, 0); musb_writew(regs, MUSB_CSR0, csr); } diff --git a/trunk/drivers/usb/musb/musb_procfs.c b/trunk/drivers/usb/musb/musb_procfs.c new file mode 100644 index 000000000000..55e6b78bdccc --- /dev/null +++ b/trunk/drivers/usb/musb/musb_procfs.c @@ -0,0 +1,830 @@ +/* + * MUSB OTG driver debug support + * + * Copyright 2005 Mentor Graphics Corporation + * Copyright (C) 2005-2006 by Texas Instruments + * Copyright (C) 2006-2007 Nokia Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include /* FIXME remove procfs writes */ +#include + +#include "musb_core.h" + +#include "davinci.h" + +#ifdef CONFIG_USB_MUSB_HDRC_HCD + +static int dump_qh(struct musb_qh *qh, char *buf, unsigned max) +{ + int count; + int tmp; + struct usb_host_endpoint *hep = qh->hep; + struct urb *urb; + + count = snprintf(buf, max, " qh %p dev%d ep%d%s max%d\n", + qh, qh->dev->devnum, qh->epnum, + ({ char *s; switch (qh->type) { + case USB_ENDPOINT_XFER_BULK: + s = "-bulk"; break; + case USB_ENDPOINT_XFER_INT: + s = "-int"; break; + case USB_ENDPOINT_XFER_CONTROL: + s = ""; break; + default: + s = "iso"; break; + }; s; }), + qh->maxpacket); + if (count <= 0) + return 0; + buf += count; + max -= count; + + list_for_each_entry(urb, &hep->urb_list, urb_list) { + tmp = snprintf(buf, max, "\t%s urb %p %d/%d\n", + usb_pipein(urb->pipe) ? "in" : "out", + urb, urb->actual_length, + urb->transfer_buffer_length); + if (tmp <= 0) + break; + tmp = min(tmp, (int)max); + count += tmp; + buf += tmp; + max -= tmp; + } + return count; +} + +static int +dump_queue(struct list_head *q, char *buf, unsigned max) +{ + int count = 0; + struct musb_qh *qh; + + list_for_each_entry(qh, q, ring) { + int tmp; + + tmp = dump_qh(qh, buf, max); + if (tmp <= 0) + break; + tmp = min(tmp, (int)max); + count += tmp; + buf += tmp; + max -= tmp; + } + return count; +} + +#endif /* HCD */ + +#ifdef CONFIG_USB_GADGET_MUSB_HDRC +static int dump_ep(struct musb_ep *ep, char *buffer, unsigned max) +{ + char *buf = buffer; + int code = 0; + void __iomem *regs = ep->hw_ep->regs; + char *mode = "1buf"; + + if (ep->is_in) { + if (ep->hw_ep->tx_double_buffered) + mode = "2buf"; + } else { + if (ep->hw_ep->rx_double_buffered) + mode = "2buf"; + } + + do { + struct usb_request *req; + + code = snprintf(buf, max, + "\n%s (hw%d): %s%s, csr %04x maxp %04x\n", + ep->name, ep->current_epnum, + mode, ep->dma ? " dma" : "", + musb_readw(regs, + (ep->is_in || !ep->current_epnum) + ? MUSB_TXCSR + : MUSB_RXCSR), + musb_readw(regs, ep->is_in + ? MUSB_TXMAXP + : MUSB_RXMAXP) + ); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + + if (is_cppi_enabled() && ep->current_epnum) { + unsigned cppi = ep->current_epnum - 1; + void __iomem *base = ep->musb->ctrl_base; + unsigned off1 = cppi << 2; + void __iomem *ram = base; + char tmp[16]; + + if (ep->is_in) { + ram += DAVINCI_TXCPPI_STATERAM_OFFSET(cppi); + tmp[0] = 0; + } else { + ram += DAVINCI_RXCPPI_STATERAM_OFFSET(cppi); + snprintf(tmp, sizeof tmp, "%d left, ", + musb_readl(base, + DAVINCI_RXCPPI_BUFCNT0_REG + off1)); + } + + code = snprintf(buf, max, "%cX DMA%d: %s" + "%08x %08x, %08x %08x; " + "%08x %08x %08x .. %08x\n", + ep->is_in ? 'T' : 'R', + ep->current_epnum - 1, tmp, + musb_readl(ram, 0 * 4), + musb_readl(ram, 1 * 4), + musb_readl(ram, 2 * 4), + musb_readl(ram, 3 * 4), + musb_readl(ram, 4 * 4), + musb_readl(ram, 5 * 4), + musb_readl(ram, 6 * 4), + musb_readl(ram, 7 * 4)); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + } + + if (list_empty(&ep->req_list)) { + code = snprintf(buf, max, "\t(queue empty)\n"); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + break; + } + list_for_each_entry(req, &ep->req_list, list) { + code = snprintf(buf, max, "\treq %p, %s%s%d/%d\n", + req, + req->zero ? "zero, " : "", + req->short_not_ok ? "!short, " : "", + req->actual, req->length); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + } + } while (0); + return buf - buffer; +} +#endif + +static int +dump_end_info(struct musb *musb, u8 epnum, char *aBuffer, unsigned max) +{ + int code = 0; + char *buf = aBuffer; + struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; + + do { + musb_ep_select(musb->mregs, epnum); +#ifdef CONFIG_USB_MUSB_HDRC_HCD + if (is_host_active(musb)) { + int dump_rx, dump_tx; + void __iomem *regs = hw_ep->regs; + + /* TEMPORARY (!) until we have a real periodic + * schedule tree ... + */ + if (!epnum) { + /* control is shared, uses RX queue + * but (mostly) shadowed tx registers + */ + dump_tx = !list_empty(&musb->control); + dump_rx = 0; + } else if (hw_ep == musb->bulk_ep) { + dump_tx = !list_empty(&musb->out_bulk); + dump_rx = !list_empty(&musb->in_bulk); + } else if (musb->periodic[epnum]) { + struct usb_host_endpoint *hep; + + hep = musb->periodic[epnum]->hep; + dump_rx = hep->desc.bEndpointAddress + & USB_ENDPOINT_DIR_MASK; + dump_tx = !dump_rx; + } else + break; + /* END TEMPORARY */ + + + if (dump_rx) { + code = snprintf(buf, max, + "\nRX%d: %s rxcsr %04x interval %02x " + "max %04x type %02x; " + "dev %d hub %d port %d" + "\n", + epnum, + hw_ep->rx_double_buffered + ? "2buf" : "1buf", + musb_readw(regs, MUSB_RXCSR), + musb_readb(regs, MUSB_RXINTERVAL), + musb_readw(regs, MUSB_RXMAXP), + musb_readb(regs, MUSB_RXTYPE), + /* FIXME: assumes multipoint */ + musb_readb(musb->mregs, + MUSB_BUSCTL_OFFSET(epnum, + MUSB_RXFUNCADDR)), + musb_readb(musb->mregs, + MUSB_BUSCTL_OFFSET(epnum, + MUSB_RXHUBADDR)), + musb_readb(musb->mregs, + MUSB_BUSCTL_OFFSET(epnum, + MUSB_RXHUBPORT)) + ); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + + if (is_cppi_enabled() + && epnum + && hw_ep->rx_channel) { + unsigned cppi = epnum - 1; + unsigned off1 = cppi << 2; + void __iomem *base; + void __iomem *ram; + char tmp[16]; + + base = musb->ctrl_base; + ram = DAVINCI_RXCPPI_STATERAM_OFFSET( + cppi) + base; + snprintf(tmp, sizeof tmp, "%d left, ", + musb_readl(base, + DAVINCI_RXCPPI_BUFCNT0_REG + + off1)); + + code = snprintf(buf, max, + " rx dma%d: %s" + "%08x %08x, %08x %08x; " + "%08x %08x %08x .. %08x\n", + cppi, tmp, + musb_readl(ram, 0 * 4), + musb_readl(ram, 1 * 4), + musb_readl(ram, 2 * 4), + musb_readl(ram, 3 * 4), + musb_readl(ram, 4 * 4), + musb_readl(ram, 5 * 4), + musb_readl(ram, 6 * 4), + musb_readl(ram, 7 * 4)); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + } + + if (hw_ep == musb->bulk_ep + && !list_empty( + &musb->in_bulk)) { + code = dump_queue(&musb->in_bulk, + buf, max); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + } else if (musb->periodic[epnum]) { + code = dump_qh(musb->periodic[epnum], + buf, max); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + } + } + + if (dump_tx) { + code = snprintf(buf, max, + "\nTX%d: %s txcsr %04x interval %02x " + "max %04x type %02x; " + "dev %d hub %d port %d" + "\n", + epnum, + hw_ep->tx_double_buffered + ? "2buf" : "1buf", + musb_readw(regs, MUSB_TXCSR), + musb_readb(regs, MUSB_TXINTERVAL), + musb_readw(regs, MUSB_TXMAXP), + musb_readb(regs, MUSB_TXTYPE), + /* FIXME: assumes multipoint */ + musb_readb(musb->mregs, + MUSB_BUSCTL_OFFSET(epnum, + MUSB_TXFUNCADDR)), + musb_readb(musb->mregs, + MUSB_BUSCTL_OFFSET(epnum, + MUSB_TXHUBADDR)), + musb_readb(musb->mregs, + MUSB_BUSCTL_OFFSET(epnum, + MUSB_TXHUBPORT)) + ); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + + if (is_cppi_enabled() + && epnum + && hw_ep->tx_channel) { + unsigned cppi = epnum - 1; + void __iomem *base; + void __iomem *ram; + + base = musb->ctrl_base; + ram = DAVINCI_RXCPPI_STATERAM_OFFSET( + cppi) + base; + code = snprintf(buf, max, + " tx dma%d: " + "%08x %08x, %08x %08x; " + "%08x %08x %08x .. %08x\n", + cppi, + musb_readl(ram, 0 * 4), + musb_readl(ram, 1 * 4), + musb_readl(ram, 2 * 4), + musb_readl(ram, 3 * 4), + musb_readl(ram, 4 * 4), + musb_readl(ram, 5 * 4), + musb_readl(ram, 6 * 4), + musb_readl(ram, 7 * 4)); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + } + + if (hw_ep == musb->control_ep + && !list_empty( + &musb->control)) { + code = dump_queue(&musb->control, + buf, max); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + } else if (hw_ep == musb->bulk_ep + && !list_empty( + &musb->out_bulk)) { + code = dump_queue(&musb->out_bulk, + buf, max); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + } else if (musb->periodic[epnum]) { + code = dump_qh(musb->periodic[epnum], + buf, max); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + } + } + } +#endif +#ifdef CONFIG_USB_GADGET_MUSB_HDRC + if (is_peripheral_active(musb)) { + code = 0; + + if (hw_ep->ep_in.desc || !epnum) { + code = dump_ep(&hw_ep->ep_in, buf, max); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + } + if (hw_ep->ep_out.desc) { + code = dump_ep(&hw_ep->ep_out, buf, max); + if (code <= 0) + break; + code = min(code, (int) max); + buf += code; + max -= code; + } + } +#endif + } while (0); + + return buf - aBuffer; +} + +/* Dump the current status and compile options. + * @param musb the device driver instance + * @param buffer where to dump the status; it must be big enough to hold the + * result otherwise "BAD THINGS HAPPENS(TM)". + */ +static int dump_header_stats(struct musb *musb, char *buffer) +{ + int code, count = 0; + const void __iomem *mbase = musb->mregs; + + *buffer = 0; + count = sprintf(buffer, "Status: %sHDRC, Mode=%s " + "(Power=%02x, DevCtl=%02x)\n", + (musb->is_multipoint ? "M" : ""), MUSB_MODE(musb), + musb_readb(mbase, MUSB_POWER), + musb_readb(mbase, MUSB_DEVCTL)); + if (count <= 0) + return 0; + buffer += count; + + code = sprintf(buffer, "OTG state: %s; %sactive\n", + otg_state_string(musb), + musb->is_active ? "" : "in"); + if (code <= 0) + goto done; + buffer += code; + count += code; + + code = sprintf(buffer, + "Options: " +#ifdef CONFIG_MUSB_PIO_ONLY + "pio" +#elif defined(CONFIG_USB_TI_CPPI_DMA) + "cppi-dma" +#elif defined(CONFIG_USB_INVENTRA_DMA) + "musb-dma" +#elif defined(CONFIG_USB_TUSB_OMAP_DMA) + "tusb-omap-dma" +#else + "?dma?" +#endif + ", " +#ifdef CONFIG_USB_MUSB_OTG + "otg (peripheral+host)" +#elif defined(CONFIG_USB_GADGET_MUSB_HDRC) + "peripheral" +#elif defined(CONFIG_USB_MUSB_HDRC_HCD) + "host" +#endif + ", debug=%d [eps=%d]\n", + debug, + musb->nr_endpoints); + if (code <= 0) + goto done; + count += code; + buffer += code; + +#ifdef CONFIG_USB_GADGET_MUSB_HDRC + code = sprintf(buffer, "Peripheral address: %02x\n", + musb_readb(musb->ctrl_base, MUSB_FADDR)); + if (code <= 0) + goto done; + buffer += code; + count += code; +#endif + +#ifdef CONFIG_USB_MUSB_HDRC_HCD + code = sprintf(buffer, "Root port status: %08x\n", + musb->port1_status); + if (code <= 0) + goto done; + buffer += code; + count += code; +#endif + +#ifdef CONFIG_ARCH_DAVINCI + code = sprintf(buffer, + "DaVinci: ctrl=%02x stat=%1x phy=%03x\n" + "\trndis=%05x auto=%04x intsrc=%08x intmsk=%08x" + "\n", + musb_readl(musb->ctrl_base, DAVINCI_USB_CTRL_REG), + musb_readl(musb->ctrl_base, DAVINCI_USB_STAT_REG), + __raw_readl((void __force __iomem *) + IO_ADDRESS(USBPHY_CTL_PADDR)), + musb_readl(musb->ctrl_base, DAVINCI_RNDIS_REG), + musb_readl(musb->ctrl_base, DAVINCI_AUTOREQ_REG), + musb_readl(musb->ctrl_base, + DAVINCI_USB_INT_SOURCE_REG), + musb_readl(musb->ctrl_base, + DAVINCI_USB_INT_MASK_REG)); + if (code <= 0) + goto done; + count += code; + buffer += code; +#endif /* DAVINCI */ + +#ifdef CONFIG_USB_TUSB6010 + code = sprintf(buffer, + "TUSB6010: devconf %08x, phy enable %08x drive %08x" + "\n\totg %03x timer %08x" + "\n\tprcm conf %08x mgmt %08x; int src %08x mask %08x" + "\n", + musb_readl(musb->ctrl_base, TUSB_DEV_CONF), + musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL_ENABLE), + musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL), + musb_readl(musb->ctrl_base, TUSB_DEV_OTG_STAT), + musb_readl(musb->ctrl_base, TUSB_DEV_OTG_TIMER), + musb_readl(musb->ctrl_base, TUSB_PRCM_CONF), + musb_readl(musb->ctrl_base, TUSB_PRCM_MNGMT), + musb_readl(musb->ctrl_base, TUSB_INT_SRC), + musb_readl(musb->ctrl_base, TUSB_INT_MASK)); + if (code <= 0) + goto done; + count += code; + buffer += code; +#endif /* DAVINCI */ + + if (is_cppi_enabled() && musb->dma_controller) { + code = sprintf(buffer, + "CPPI: txcr=%d txsrc=%01x txena=%01x; " + "rxcr=%d rxsrc=%01x rxena=%01x " + "\n", + musb_readl(musb->ctrl_base, + DAVINCI_TXCPPI_CTRL_REG), + musb_readl(musb->ctrl_base, + DAVINCI_TXCPPI_RAW_REG), + musb_readl(musb->ctrl_base, + DAVINCI_TXCPPI_INTENAB_REG), + musb_readl(musb->ctrl_base, + DAVINCI_RXCPPI_CTRL_REG), + musb_readl(musb->ctrl_base, + DAVINCI_RXCPPI_RAW_REG), + musb_readl(musb->ctrl_base, + DAVINCI_RXCPPI_INTENAB_REG)); + if (code <= 0) + goto done; + count += code; + buffer += code; + } + +#ifdef CONFIG_USB_GADGET_MUSB_HDRC + if (is_peripheral_enabled(musb)) { + code = sprintf(buffer, "Gadget driver: %s\n", + musb->gadget_driver + ? musb->gadget_driver->driver.name + : "(none)"); + if (code <= 0) + goto done; + count += code; + buffer += code; + } +#endif + +done: + return count; +} + +/* Write to ProcFS + * + * C soft-connect + * c soft-disconnect + * I enable HS + * i disable HS + * s stop session + * F force session (OTG-unfriendly) + * E rElinquish bus (OTG) + * H request host mode + * h cancel host request + * T start sending TEST_PACKET + * D set/query the debug level + */ +static int musb_proc_write(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + char cmd; + u8 reg; + struct musb *musb = (struct musb *)data; + void __iomem *mbase = musb->mregs; + + /* MOD_INC_USE_COUNT; */ + + if (unlikely(copy_from_user(&cmd, buffer, 1))) + return -EFAULT; + + switch (cmd) { + case 'C': + if (mbase) { + reg = musb_readb(mbase, MUSB_POWER) + | MUSB_POWER_SOFTCONN; + musb_writeb(mbase, MUSB_POWER, reg); + } + break; + + case 'c': + if (mbase) { + reg = musb_readb(mbase, MUSB_POWER) + & ~MUSB_POWER_SOFTCONN; + musb_writeb(mbase, MUSB_POWER, reg); + } + break; + + case 'I': + if (mbase) { + reg = musb_readb(mbase, MUSB_POWER) + | MUSB_POWER_HSENAB; + musb_writeb(mbase, MUSB_POWER, reg); + } + break; + + case 'i': + if (mbase) { + reg = musb_readb(mbase, MUSB_POWER) + & ~MUSB_POWER_HSENAB; + musb_writeb(mbase, MUSB_POWER, reg); + } + break; + + case 'F': + reg = musb_readb(mbase, MUSB_DEVCTL); + reg |= MUSB_DEVCTL_SESSION; + musb_writeb(mbase, MUSB_DEVCTL, reg); + break; + + case 'H': + if (mbase) { + reg = musb_readb(mbase, MUSB_DEVCTL); + reg |= MUSB_DEVCTL_HR; + musb_writeb(mbase, MUSB_DEVCTL, reg); + /* MUSB_HST_MODE( ((struct musb*)data) ); */ + /* WARNING("Host Mode\n"); */ + } + break; + + case 'h': + if (mbase) { + reg = musb_readb(mbase, MUSB_DEVCTL); + reg &= ~MUSB_DEVCTL_HR; + musb_writeb(mbase, MUSB_DEVCTL, reg); + } + break; + + case 'T': + if (mbase) { + musb_load_testpacket(musb); + musb_writeb(mbase, MUSB_TESTMODE, + MUSB_TEST_PACKET); + } + break; + +#if (MUSB_DEBUG > 0) + /* set/read debug level */ + case 'D':{ + if (count > 1) { + char digits[8], *p = digits; + int i = 0, level = 0, sign = 1; + int len = min(count - 1, (unsigned long)8); + + if (copy_from_user(&digits, &buffer[1], len)) + return -EFAULT; + + /* optional sign */ + if (*p == '-') { + len -= 1; + sign = -sign; + p++; + } + + /* read it */ + while (i++ < len && *p > '0' && *p < '9') { + level = level * 10 + (*p - '0'); + p++; + } + + level *= sign; + DBG(1, "debug level %d\n", level); + debug = level; + } + } + break; + + + case '?': + INFO("?: you are seeing it\n"); + INFO("C/c: soft connect enable/disable\n"); + INFO("I/i: hispeed enable/disable\n"); + INFO("F: force session start\n"); + INFO("H: host mode\n"); + INFO("T: start sending TEST_PACKET\n"); + INFO("D: set/read dbug level\n"); + break; +#endif + + default: + ERR("Command %c not implemented\n", cmd); + break; + } + + musb_platform_try_idle(musb, 0); + + return count; +} + +static int musb_proc_read(char *page, char **start, + off_t off, int count, int *eof, void *data) +{ + char *buffer = page; + int code = 0; + unsigned long flags; + struct musb *musb = data; + unsigned epnum; + + count -= off; + count -= 1; /* for NUL at end */ + if (count <= 0) + return -EINVAL; + + spin_lock_irqsave(&musb->lock, flags); + + code = dump_header_stats(musb, buffer); + if (code > 0) { + buffer += code; + count -= code; + } + + /* generate the report for the end points */ + /* REVISIT ... not unless something's connected! */ + for (epnum = 0; count >= 0 && epnum < musb->nr_endpoints; + epnum++) { + code = dump_end_info(musb, epnum, buffer, count); + if (code > 0) { + buffer += code; + count -= code; + } + } + + musb_platform_try_idle(musb, 0); + + spin_unlock_irqrestore(&musb->lock, flags); + *eof = 1; + + return buffer - page; +} + +void __devexit musb_debug_delete(char *name, struct musb *musb) +{ + if (musb->proc_entry) + remove_proc_entry(name, NULL); +} + +struct proc_dir_entry *__init +musb_debug_create(char *name, struct musb *data) +{ + struct proc_dir_entry *pde; + + /* FIXME convert everything to seq_file; then later, debugfs */ + + if (!name) + return NULL; + + pde = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, NULL); + data->proc_entry = pde; + if (pde) { + pde->data = data; + /* pde->owner = THIS_MODULE; */ + + pde->read_proc = musb_proc_read; + pde->write_proc = musb_proc_write; + + pde->size = 0; + + pr_debug("Registered /proc/%s\n", name); + } else { + pr_debug("Cannot create a valid proc file entry"); + } + + return pde; +} diff --git a/trunk/drivers/usb/serial/option.c b/trunk/drivers/usb/serial/option.c index 9f9cd36455f4..e143198aeb02 100644 --- a/trunk/drivers/usb/serial/option.c +++ b/trunk/drivers/usb/serial/option.c @@ -173,7 +173,6 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po #define KYOCERA_PRODUCT_KPC680 0x180a #define ANYDATA_VENDOR_ID 0x16d5 -#define ANYDATA_PRODUCT_ADU_620UW 0x6202 #define ANYDATA_PRODUCT_ADU_E100A 0x6501 #define ANYDATA_PRODUCT_ADU_500A 0x6502 @@ -319,7 +318,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, 0x8138) }, /* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, - { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) }, { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) }, { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) }, diff --git a/trunk/include/linux/usb.h b/trunk/include/linux/usb.h index 94ac74aba6b6..0924cd9c30f6 100644 --- a/trunk/include/linux/usb.h +++ b/trunk/include/linux/usb.h @@ -110,8 +110,6 @@ enum usb_interface_condition { * @sysfs_files_created: sysfs attributes exist * @needs_remote_wakeup: flag set when the driver requires remote-wakeup * capability during autosuspend. - * @needs_altsetting0: flag set when a set-interface request for altsetting 0 - * has been deferred. * @needs_binding: flag set when the driver should be re-probed or unbound * following a reset or suspend operation it doesn't support. * @dev: driver model's view of this device @@ -164,7 +162,6 @@ struct usb_interface { unsigned is_active:1; /* the interface is not suspended */ unsigned sysfs_files_created:1; /* the sysfs attributes exist */ unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */ - unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */ unsigned needs_binding:1; /* needs delayed unbind/rebind */ struct device dev; /* interface specific device info */ diff --git a/trunk/lib/kobject.c b/trunk/lib/kobject.c index bd732ffebc85..fbf0ae282376 100644 --- a/trunk/lib/kobject.c +++ b/trunk/lib/kobject.c @@ -223,8 +223,7 @@ static int kobject_set_name_vargs(struct kobject *kobj, const char *fmt, return -ENOMEM; /* ewww... some of these buggers have '/' in the name ... */ - s = strchr(kobj->name, '/'); - if (s) + while ((s = strchr(kobj->name, '/'))) s[0] = '!'; kfree(old_name);