summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/s390/defconfig54
-rw-r--r--arch/s390/include/asm/bitops.h6
-rw-r--r--arch/s390/kernel/process.c4
-rw-r--r--arch/s390/kernel/smp.c2
-rw-r--r--drivers/s390/block/dasd.c5
-rw-r--r--drivers/s390/block/dasd_eckd.h2
-rw-r--r--drivers/s390/block/dasd_eer.c3
-rw-r--r--drivers/s390/block/dcssblk.c4
-rw-r--r--drivers/s390/char/tape_char.c2
-rw-r--r--drivers/s390/char/tape_std.c2
-rw-r--r--drivers/s390/cio/ccwgroup.c20
-rw-r--r--drivers/s390/cio/css.c1
-rw-r--r--drivers/s390/cio/device.c40
-rw-r--r--drivers/s390/cio/device.h2
-rw-r--r--drivers/s390/cio/device_fsm.c31
-rw-r--r--drivers/s390/cio/qdio_debug.h6
-rw-r--r--drivers/s390/cio/qdio_main.c74
-rw-r--r--drivers/s390/cio/qdio_setup.c6
-rw-r--r--drivers/s390/cio/qdio_thinint.c6
-rw-r--r--drivers/usb/class/cdc-acm.c5
-rw-r--r--drivers/usb/core/driver.c96
-rw-r--r--drivers/usb/core/hcd.c9
-rw-r--r--drivers/usb/core/hcd.h4
-rw-r--r--drivers/usb/core/hub.c9
-rw-r--r--drivers/usb/core/urb.c9
-rw-r--r--drivers/usb/core/usb.c73
-rw-r--r--drivers/usb/core/usb.h3
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c2
-rw-r--r--drivers/usb/host/isp1760-hcd.c2
-rw-r--r--drivers/usb/host/ohci-at91.c1
-rw-r--r--drivers/usb/host/ohci-au1xxx.c1
-rw-r--r--drivers/usb/host/ohci-ep93xx.c1
-rw-r--r--drivers/usb/host/ohci-hub.c53
-rw-r--r--drivers/usb/host/ohci-lh7a404.c1
-rw-r--r--drivers/usb/host/ohci-omap.c1
-rw-r--r--drivers/usb/host/ohci-pci.c1
-rw-r--r--drivers/usb/host/ohci-pnx4008.c1
-rw-r--r--drivers/usb/host/ohci-pnx8550.c1
-rw-r--r--drivers/usb/host/ohci-ppc-of.c1
-rw-r--r--drivers/usb/host/ohci-ppc-soc.c1
-rw-r--r--drivers/usb/host/ohci-ps3.c1
-rw-r--r--drivers/usb/host/ohci-pxa27x.c1
-rw-r--r--drivers/usb/host/ohci-s3c2410.c1
-rw-r--r--drivers/usb/host/ohci-sa1111.c1
-rw-r--r--drivers/usb/host/ohci-sh.c1
-rw-r--r--drivers/usb/host/ohci-sm501.c1
-rw-r--r--drivers/usb/host/ohci-ssb.c1
-rw-r--r--drivers/usb/host/u132-hcd.c11
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c1
-rw-r--r--drivers/usb/musb/Kconfig13
-rw-r--r--drivers/usb/musb/Makefile21
-rw-r--r--drivers/usb/musb/musb_core.c38
-rw-r--r--drivers/usb/musb/musb_core.h19
-rw-r--r--drivers/usb/musb/musb_debug.h4
-rw-r--r--drivers/usb/musb/musb_gadget_ep0.c2
-rw-r--r--drivers/usb/musb/musb_procfs.c830
-rw-r--r--drivers/usb/serial/option.c2
-rw-r--r--include/linux/usb.h3
58 files changed, 345 insertions, 1151 deletions
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index c5cdb975d590..9b0bc2c9fba0 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc4
-# Fri May 30 09:49:33 2008
+# Linux kernel version: 2.6.27-rc4
+# Thu Aug 21 19:43:29 2008
#
CONFIG_SCHED_MC=y
CONFIG_MMU=y
@@ -68,7 +68,6 @@ 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
@@ -93,11 +92,17 @@ 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
@@ -113,6 +118,7 @@ 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
#
@@ -175,6 +181,8 @@ 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
@@ -185,8 +193,12 @@ 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
@@ -198,6 +210,7 @@ CONFIG_VIRT_TO_BUS=y
CONFIG_MACHCHK_WARNING=y
CONFIG_QDIO=y
# CONFIG_QDIO_DEBUG is not set
+CONFIG_CHSC_SCH=m
#
# Misc
@@ -206,6 +219,7 @@ 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
@@ -226,10 +240,6 @@ CONFIG_S390_HYPFS_FS=y
CONFIG_KEXEC=y
# CONFIG_ZFCPDUMP is not set
CONFIG_S390_GUEST=y
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -364,7 +374,6 @@ 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
@@ -430,7 +439,9 @@ CONFIG_CCW=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_DEBUG_DEVRES is not set
CONFIG_SYS_HYPERVISOR=y
@@ -507,6 +518,11 @@ 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
@@ -522,14 +538,10 @@ CONFIG_DM_CRYPT=y
CONFIG_DM_SNAPSHOT=y
CONFIG_DM_MIRROR=y
CONFIG_DM_ZERO=y
-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_MULTIPATH=m
# 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
@@ -544,7 +556,6 @@ 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
@@ -576,7 +587,10 @@ 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
@@ -616,6 +630,7 @@ 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
#
@@ -693,6 +708,7 @@ 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
@@ -712,7 +728,6 @@ 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
@@ -780,6 +795,7 @@ 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
@@ -789,6 +805,7 @@ CONFIG_DEBUG_BUGVERBOSE=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
@@ -847,6 +864,10 @@ 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
@@ -895,6 +916,7 @@ 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/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index b4eb24ab5af9..8e9243ae0c19 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/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(0, *p >> bit) + bit;
+ set = __ffz_word(bit, *p >> 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(__load_ulong_le(p, 0) >> bit) + bit;
+ set = __ffz_word(bit, __load_ulong_le(p, 0) >> 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(__load_ulong_le(p, 0) >> bit) + bit;
+ set = __ffs_word(0, __load_ulong_le(p, 0) & (~0UL << bit));
if (set >= size)
return size + offset;
if (set < __BITOPS_WORDSIZE)
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 9839767d0842..3e2c05cb6a87 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -75,7 +75,9 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
return sf->gprs[8];
}
-DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
+DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = {
+ .lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock)
+};
static int s390_idle_enter(void)
{
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index b795b3e24afd..00b9b4dec5eb 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -610,7 +610,6 @@ 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)
@@ -845,7 +844,6 @@ 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/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 1b6c52ef7339..acb78017e7d0 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -2333,13 +2333,11 @@ 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(cdev);
+ device = dasd_device_from_cdev_locked(cdev);
if (IS_ERR(device))
return 0;
- spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
ret = 0;
switch (event) {
case CIO_GONE:
@@ -2369,7 +2367,6 @@ 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/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index 4bf0aa5112c1..2476f87d21d0 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/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[9];
+ unsigned char varies[5];
} __attribute__ ((packed));
/*
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 29da4413ad43..bf512ac75b9e 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -16,6 +16,7 @@
#include <linux/poll.h>
#include <linux/mutex.h>
#include <linux/smp_lock.h>
+#include <linux/err.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
@@ -457,7 +458,7 @@ int dasd_eer_enable(struct dasd_device *device)
cqr = dasd_kmalloc_request("ECKD", 1 /* SNSS */,
SNSS_DATA_SIZE, device);
- if (!cqr)
+ if (IS_ERR(cqr))
return -ENOMEM;
cqr->startdev = device;
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 01fcdd91b846..db85f1fb131e 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -384,6 +384,10 @@ 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/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 687720b552d1..be0ce2215c8d 100644
--- a/drivers/s390/char/tape_char.c
+++ b/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 (new == NULL)
+ if (IS_ERR(new))
return -ENOMEM;
if (device->char_data.idal_buf != NULL)
diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c
index 2a1af4e60be0..cc8fd781ee22 100644
--- a/drivers/s390/char/tape_std.c
+++ b/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 (new == NULL)
+ if (IS_ERR(new))
return -ENOMEM;
if (device->char_data.idal_buf != NULL)
idal_buffer_free(device->char_data.idal_buf);
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 26a930e832bd..e0ce65fca4e7 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -112,8 +112,10 @@ ccwgroup_release (struct device *dev)
gdev = to_ccwgroupdev(dev);
for (i = 0; i < gdev->count; i++) {
- dev_set_drvdata(&gdev->cdev[i]->dev, NULL);
- put_device(&gdev->cdev[i]->dev);
+ if (gdev->cdev[i]) {
+ dev_set_drvdata(&gdev->cdev[i]->dev, NULL);
+ put_device(&gdev->cdev[i]->dev);
+ }
}
kfree(gdev);
}
@@ -221,6 +223,13 @@ 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);
@@ -258,16 +267,11 @@ 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_register(&gdev->dev);
+ rc = device_add(&gdev->dev);
if (rc)
goto error;
get_device(&gdev->dev);
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 46c021d880dc..51489eff6b0b 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -477,7 +477,6 @@ 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/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index e818d0c54c09..28221030b886 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -150,7 +150,6 @@ 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;
@@ -168,11 +167,6 @@ 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 ? */
@@ -192,8 +186,6 @@ 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;
@@ -204,7 +196,6 @@ 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);
}
@@ -1496,11 +1487,22 @@ 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 } action;
+ enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE, DISC } action;
struct ccw_device *cdev;
spin_lock_irqsave(sch->lock, flags);
@@ -1535,16 +1537,11 @@ 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. */
- action = UNREGISTER;
- spin_unlock_irqrestore(sch->lock, flags);
- ret = io_subchannel_notify(sch, event);
- spin_lock_irqsave(sch->lock, flags);
- if (ret)
- action = NONE;
+ if (io_subchannel_notify(sch, event))
+ action = DISC;
+ else
+ action = UNREGISTER;
break;
case CIO_REVALIDATE:
/* Device will be removed, so no notify necessary. */
@@ -1565,6 +1562,7 @@ 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);
@@ -1577,6 +1575,9 @@ 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;
}
@@ -1828,5 +1829,4 @@ 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/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 9800a8335a3f..6f5c3f2b3587 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -72,7 +72,6 @@ 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;
@@ -120,6 +119,7 @@ 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/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 8b5fe57fb2f3..550508df952b 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -337,26 +337,34 @@ 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
-ccw_device_oper_notify(struct work_struct *work)
+static void cmf_reenable_delayed(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;
- ret = ccw_device_notify(cdev, CIO_OPER);
- if (ret) {
+ cmf_reenable(cdev);
+}
+
+static void ccw_device_oper_notify(struct ccw_device *cdev)
+{
+ if (ccw_device_notify(cdev, CIO_OPER)) {
/* Reenable channel measurements, if needed. */
- cmf_reenable(cdev);
- wake_up(&cdev->private->wait_q);
- } else
- /* Driver doesn't want device back. */
- ccw_device_do_unreg_rereg(work);
+ 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);
}
/*
@@ -386,8 +394,7 @@ ccw_device_done(struct ccw_device *cdev, int state)
if (cdev->private->flags.donotify) {
cdev->private->flags.donotify = 0;
- PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify);
- queue_work(ccw_device_notify_work, &cdev->private->kick_work);
+ ccw_device_oper_notify(cdev);
}
wake_up(&cdev->private->wait_q);
diff --git a/drivers/s390/cio/qdio_debug.h b/drivers/s390/cio/qdio_debug.h
index 8484b83698e1..5a4d85b829ad 100644
--- a/drivers/s390/cio/qdio_debug.h
+++ b/drivers/s390/cio/qdio_debug.h
@@ -61,18 +61,18 @@
/* s390dbf views */
#define QDIO_DBF_SETUP_LEN 8
-#define QDIO_DBF_SETUP_PAGES 4
+#define QDIO_DBF_SETUP_PAGES 8
#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 16
+#define QDIO_DBF_TRACE_PAGES 32
#define QDIO_DBF_SETUP_LEVEL 6
#define QDIO_DBF_TRACE_LEVEL 4
#else /* !CONFIG_QDIO_DEBUG */
-#define QDIO_DBF_TRACE_PAGES 4
+#define QDIO_DBF_TRACE_PAGES 8
#define QDIO_DBF_SETUP_LEVEL 2
#define QDIO_DBF_TRACE_LEVEL 2
#endif /* CONFIG_QDIO_DEBUG */
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index d15648514a0f..e6eabc853422 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -330,6 +330,7 @@ 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 *));
@@ -338,6 +339,9 @@ 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)
@@ -748,16 +752,18 @@ 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
- 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);
+ 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);
+ }
#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):
@@ -1066,14 +1072,12 @@ 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",
- cdev->private->schid.sch_no);
+ sprintf(dbf_text, "ierr%4x", irq_ptr->schid.sch_no);
QDIO_DBF_TEXT2(1, setup, dbf_text);
qdio_int_error(cdev);
return;
case -ETIMEDOUT:
- sprintf(dbf_text, "qtoh%4x",
- cdev->private->schid.sch_no);
+ sprintf(dbf_text, "qtoh%4x", irq_ptr->schid.sch_no);
QDIO_DBF_TEXT2(1, setup, dbf_text);
qdio_int_error(cdev);
return;
@@ -1124,8 +1128,10 @@ 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];
- QDIO_DBF_TEXT0(0, setup, "getssqd");
+ sprintf(dbf_text, "qssq%4x", cdev->private->schid.sch_no);
+ QDIO_DBF_TEXT0(0, setup, dbf_text);
irq_ptr = cdev->private->qdio_data;
if (!irq_ptr)
@@ -1149,14 +1155,13 @@ 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);
@@ -1191,6 +1196,9 @@ 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;
@@ -1205,10 +1213,6 @@ 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);
@@ -1247,7 +1251,6 @@ no_cleanup:
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;
@@ -1263,16 +1266,14 @@ 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);
@@ -1295,7 +1296,6 @@ 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,7 +1319,6 @@ 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))
@@ -1389,6 +1388,9 @@ 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;
@@ -1396,13 +1398,6 @@ 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);
@@ -1472,6 +1467,9 @@ 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;
@@ -1485,10 +1483,6 @@ 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;
@@ -1663,7 +1657,7 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
#ifdef CONFIG_QDIO_DEBUG
char dbf_text[20];
- sprintf(dbf_text, "doQD%04x", cdev->private->schid.sch_no);
+ sprintf(dbf_text, "doQD%4x", cdev->private->schid.sch_no);
QDIO_DBF_TEXT3(0, trace, dbf_text);
#endif /* CONFIG_QDIO_DEBUG */
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index 1bd2a208db28..1679e2f91c94 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/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, "qfqs%4x", qdio_init->cdev->private->schid.sch_no);
+ sprintf(dbf_text, "qset%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, "schno%x", irq_ptr->schid.sch_no);
+ sprintf(dbf_text, "schn%4x", 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 ", cdev->dev.bus_id);
+ sprintf(s, "%s sc:%x ", cdev->dev.bus_id, irq_ptr->schid.sch_no);
switch (irq_ptr->qib.qfmt) {
case QDIO_QETH_QFMT:
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 9291a771d812..ea7f61400267 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -113,7 +113,11 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
struct qdio_q *q;
int i;
- for_each_input_queue(irq_ptr, q, 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;
list_del_rcu(&q->entry);
synchronize_rcu();
}
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index efc4373ededb..c257453fa9de 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/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:
-err_out:
mutex_unlock(&acm->mutex);
+err_out:
mutex_unlock(&open_mutex);
return rv;
@@ -1362,6 +1362,9 @@ 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/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 2be37fe466f2..5a7fa6f09958 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -230,6 +230,13 @@ 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);
@@ -266,8 +273,17 @@ static int usb_unbind_interface(struct device *dev)
driver->disconnect(intf);
- /* reset other interface state */
- usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
+ /* 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;
usb_set_intfdata(intf, NULL);
intf->condition = USB_INTERFACE_UNBOUND;
@@ -798,7 +814,8 @@ 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.
*
- * FIXME: The caller must block system sleep transitions.
+ * Note: Rebinds will be skipped if a system sleep transition is in
+ * progress and the PM "complete" callback hasn't occurred yet.
*/
void usb_rebind_intf(struct usb_interface *intf)
{
@@ -814,10 +831,12 @@ void usb_rebind_intf(struct usb_interface *intf)
}
/* Try to rebind the interface */
- intf->needs_binding = 0;
- rc = device_attach(&intf->dev);
- if (rc < 0)
- dev_warn(&intf->dev, "rebind failed: %d\n", rc);
+ 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);
+ }
}
#ifdef CONFIG_PM
@@ -829,7 +848,6 @@ 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)
{
@@ -851,22 +869,8 @@ static void do_unbind_rebind(struct usb_device *udev, int action)
}
break;
case DO_REBIND:
- 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;
-
+ if (intf->needs_binding)
usb_rebind_intf(intf);
- }
break;
}
}
@@ -926,14 +930,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_interface *intf, pm_message_t msg)
+static int usb_suspend_interface(struct usb_device *udev,
+ 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 (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
- !is_active(intf))
+ if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf))
goto done;
if (intf->condition == USB_INTERFACE_UNBOUND) /* This can't happen */
@@ -944,7 +948,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
status = driver->suspend(intf, msg);
if (status == 0)
mark_quiesced(intf);
- else if (!interface_to_usbdev(intf)->auto_pm)
+ else if (!udev->auto_pm)
dev_err(&intf->dev, "%s error %d\n",
"suspend", status);
} else {
@@ -961,13 +965,13 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
}
/* Caller has locked intf's usb_device's pm_mutex */
-static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
+static int usb_resume_interface(struct usb_device *udev,
+ struct usb_interface *intf, int reset_resume)
{
struct usb_driver *driver;
int status = 0;
- if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
- is_active(intf))
+ if (udev->state == USB_STATE_NOTATTACHED || is_active(intf))
goto done;
/* Don't let autoresume interfere with unbinding */
@@ -975,8 +979,17 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
goto done;
/* Can't resume it if it doesn't have a driver. */
- if (intf->condition == USB_INTERFACE_UNBOUND)
+ 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;
+ }
goto done;
+ }
/* Don't resume if the interface is marked for rebinding */
if (intf->needs_binding)
@@ -1151,7 +1164,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(intf, msg);
+ status = usb_suspend_interface(udev, intf, msg);
if (status != 0)
break;
}
@@ -1163,7 +1176,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(intf, 0);
+ usb_resume_interface(udev, intf, 0);
}
/* Try another autosuspend when the interfaces aren't busy */
@@ -1276,7 +1289,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(intf, udev->reset_resume);
+ usb_resume_interface(udev, intf, udev->reset_resume);
}
}
@@ -1605,12 +1618,10 @@ int usb_external_resume_device(struct usb_device *udev)
return status;
}
-static int usb_suspend(struct device *dev, pm_message_t message)
+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
@@ -1629,12 +1640,10 @@ static int usb_suspend(struct device *dev, pm_message_t message)
return usb_external_suspend_device(udev, message);
}
-static int usb_resume(struct device *dev)
+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
@@ -1646,17 +1655,10 @@ static 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/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index f7bfd72ef115..8abd4e59bf4a 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -924,15 +924,6 @@ 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/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 5b0b59b0d89b..e710ce04e228 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -212,8 +212,6 @@ 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);
@@ -379,8 +377,6 @@ 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/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 107e1d25ddec..6a5cb018383d 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2102,8 +2102,6 @@ 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);
@@ -3081,11 +3079,6 @@ 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))
@@ -3311,8 +3304,6 @@ 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/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index c0b1ae25ae2a..47111e88f791 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -601,15 +601,20 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
void usb_unlink_anchored_urbs(struct usb_anchor *anchor)
{
struct urb *victim;
+ unsigned long flags;
- spin_lock_irq(&anchor->lock);
+ spin_lock_irqsave(&anchor->lock, flags);
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_irq(&anchor->lock);
+ spin_unlock_irqrestore(&anchor->lock, flags);
}
EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 84fcaa6a21ec..be1fa0723f2c 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -219,12 +219,6 @@ 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)
@@ -244,13 +238,80 @@ 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/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index d9a6e16dbf84..9a1a45ac3add 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -41,6 +41,9 @@ 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/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index a28513ecbe5b..7cbc78a6853d 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/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/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
index d22a84f86a33..8017f1cf78e2 100644
--- a/drivers/usb/host/isp1760-hcd.c
+++ b/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 = 92ns)
+ * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 109ns)
*/
isp1760_writel(payload + ISP_BANK(1), usb_hcd->regs +
HC_MEMORY_REG);
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 6db7a2889e66..4ed228a89943 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -260,7 +260,6 @@ 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/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index c0948008fe3d..2ac4e022a13f 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -163,7 +163,6 @@ 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/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index cb0b506f8259..fb3055f084b5 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -134,7 +134,6 @@ 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/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 439beb784f3e..7ea9a7b31155 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -36,18 +36,6 @@
/*-------------------------------------------------------------------------*/
-/* 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)
@@ -374,18 +362,28 @@ 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:
- /* keep on polling until we know a device is connected
- * and RHSC is enabled */
+ /* 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.
+ */
if (!ohci->autostop) {
if (any_connected ||
!device_may_wakeup(&ohci_to_hcd(ohci)
->self.root_hub->dev)) {
- if (ohci_readl(ohci, &ohci->regs->intrenable) &
- OHCI_INTR_RHSC)
+ if (rhsc)
poll_rh = 0;
} else {
ohci->autostop = 1;
@@ -398,12 +396,13 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
ohci->autostop = 0;
ohci->next_statechange = jiffies +
STATECHANGE_DELAY;
- } else if (time_after_eq(jiffies,
+ } else if (rhsc && 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;
@@ -417,6 +416,12 @@ 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;
}
@@ -438,12 +443,16 @@ 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)
{
- int poll_rh = 1;
-
- /* keep on polling until RHSC is enabled */
+ /* If RHSC is enabled, don't poll */
if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
- poll_rh = 0;
- return poll_rh;
+ return 0;
+
+ /* 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;
}
#endif /* CONFIG_PM */
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
index 9e31d440d115..de42283149c7 100644
--- a/drivers/usb/host/ohci-lh7a404.c
+++ b/drivers/usb/host/ohci-lh7a404.c
@@ -193,7 +193,6 @@ 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/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 3d532b709670..1eb64d08b60a 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -470,7 +470,6 @@ 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/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 083e8df0a817..a9c2ae36c7ad 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -459,7 +459,6 @@ 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/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
index b02cd0761977..658a2a978c32 100644
--- a/drivers/usb/host/ohci-pnx4008.c
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -277,7 +277,6 @@ 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/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
index 605d59cba28e..28467e288a93 100644
--- a/drivers/usb/host/ohci-pnx8550.c
+++ b/drivers/usb/host/ohci-pnx8550.c
@@ -201,7 +201,6 @@ 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/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index 91e6e101a4cc..7ac53264ead3 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -72,7 +72,6 @@ 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/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index 523c30125577..cd3398b675b2 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -172,7 +172,6 @@ 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/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
index 55c95647f008..2089d8a46c4b 100644
--- a/drivers/usb/host/ohci-ps3.c
+++ b/drivers/usb/host/ohci-ps3.c
@@ -68,7 +68,6 @@ 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/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 8c9c4849db6e..7f0f35c78185 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -298,7 +298,6 @@ 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/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 9e3dc4069e8b..f46af7a718d4 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -466,7 +466,6 @@ 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/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index 4626b002e670..e4bbe8e188e4 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -231,7 +231,6 @@ 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/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
index e7ee607278fe..60f03cc7ec4f 100644
--- a/drivers/usb/host/ohci-sh.c
+++ b/drivers/usb/host/ohci-sh.c
@@ -68,7 +68,6 @@ 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/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index 21b164e4abeb..cff23637cfcc 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -75,7 +75,6 @@ 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/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
index 3660c83d80af..23fd6a886bdd 100644
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -81,7 +81,6 @@ 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/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index 20ad3c48fcb2..228f2b070f2b 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -2934,16 +2934,6 @@ 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)
@@ -2995,7 +2985,6 @@ 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/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index fbace41a7cba..69c34a58e205 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -3270,6 +3270,7 @@ 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/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index faca4333f27a..a0017486ad4e 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -165,12 +165,11 @@ config USB_TUSB_OMAP_DMA
help
Enable DMA transfers on TUSB 6010 when OMAP DMA is available.
-config USB_MUSB_LOGLEVEL
+config USB_MUSB_DEBUG
depends on USB_MUSB_HDRC
- int 'Logging Level (0 - none / 3 - annoying / ... )'
- default 0
+ bool "Enable debugging messages"
+ default n
help
- 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.
+ 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.
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 88eb67de08ae..b6af0d687a73 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -64,23 +64,6 @@ endif
# Debugging
-MUSB_DEBUG:=$(CONFIG_USB_MUSB_LOGLEVEL)
-
-ifeq ("$(strip $(MUSB_DEBUG))","")
- ifdef CONFIG_USB_DEBUG
- MUSB_DEBUG:=1
- else
- MUSB_DEBUG:=0
- endif
+ifeq ($(CONFIG_USB_MUSB_DEBUG),y)
+ EXTRA_CFLAGS += -DDEBUG
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/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index d68ec6daf335..c5b8f0296fcf 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -114,23 +114,14 @@
-#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
+unsigned debug;
+module_param(debug, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug message level. Default = 0");
#define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
#define DRIVER_DESC "Inventra Dual-Role USB Controller Driver"
-#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 MUSB_VERSION "6.0"
#define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION
@@ -2037,6 +2028,8 @@ bad_config:
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,
@@ -2051,6 +2044,8 @@ bad_config:
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",
@@ -2059,16 +2054,14 @@ bad_config:
}
- if (status == 0)
- musb_debug_create("driver/musb_hdrc", musb);
- else {
+ return 0;
+
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);
@@ -2131,7 +2124,6 @@ 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/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index eade46d81708..82227251931b 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -485,23 +485,4 @@ 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/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h
index 3bdb311e820d..4d2794441b15 100644
--- a/drivers/usb/musb/musb_debug.h
+++ b/drivers/usb/musb/musb_debug.h
@@ -48,11 +48,7 @@
__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/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index 48d7d3ccb243..a57652fff39c 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -476,6 +476,7 @@ static void ep0_rxstate(struct musb *musb)
return;
musb->ackpend = 0;
}
+ musb_ep_select(musb->mregs, 0);
musb_writew(regs, MUSB_CSR0, tmp);
}
@@ -528,6 +529,7 @@ 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/drivers/usb/musb/musb_procfs.c b/drivers/usb/musb/musb_procfs.c
deleted file mode 100644
index 55e6b78bdccc..000000000000
--- a/drivers/usb/musb/musb_procfs.c
+++ /dev/null
@@ -1,830 +0,0 @@
-/*
- * 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 <linux/kernel.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h> /* FIXME remove procfs writes */
-#include <asm/arch/hardware.h>
-
-#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<num> 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/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index e143198aeb02..9f9cd36455f4 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -173,6 +173,7 @@ 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
@@ -318,6 +319,7 @@ 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/include/linux/usb.h b/include/linux/usb.h
index 0924cd9c30f6..94ac74aba6b6 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -110,6 +110,8 @@ 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
@@ -162,6 +164,7 @@ 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 */