diff options
147 files changed, 1692 insertions, 1497 deletions
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl index 54883de5d5f..ac3d0018140 100644 --- a/Documentation/DocBook/uio-howto.tmpl +++ b/Documentation/DocBook/uio-howto.tmpl @@ -521,6 +521,11 @@ Here's a description of the fields of <varname>struct uio_mem</varname>:  <itemizedlist>  <listitem><para> +<varname>const char *name</varname>: Optional. Set this to help identify +the memory region, it will show up in the corresponding sysfs node. +</para></listitem> + +<listitem><para>  <varname>int memtype</varname>: Required if the mapping is used. Set this to  <varname>UIO_MEM_PHYS</varname> if you you have physical memory on your  card to be mapped. Use <varname>UIO_MEM_LOGICAL</varname> for logical @@ -553,7 +558,7 @@ instead to remember such an address.  </itemizedlist>  <para> -Please do not touch the <varname>kobj</varname> element of +Please do not touch the <varname>map</varname> element of  <varname>struct uio_mem</varname>! It is used by the UIO framework  to set up sysfs files for this mapping. Simply leave it alone.  </para> diff --git a/Documentation/i2c/ten-bit-addresses b/Documentation/i2c/ten-bit-addresses index e9890709c50..cdfe13901b9 100644 --- a/Documentation/i2c/ten-bit-addresses +++ b/Documentation/i2c/ten-bit-addresses @@ -1,22 +1,24 @@  The I2C protocol knows about two kinds of device addresses: normal 7 bit  addresses, and an extended set of 10 bit addresses. The sets of addresses  do not intersect: the 7 bit address 0x10 is not the same as the 10 bit -address 0x10 (though a single device could respond to both of them). You -select a 10 bit address by adding an extra byte after the address -byte: -  S Addr7 Rd/Wr .... -becomes -  S 11110 Addr10 Rd/Wr -S is the start bit, Rd/Wr the read/write bit, and if you count the number -of bits, you will see the there are 8 after the S bit for 7 bit addresses, -and 16 after the S bit for 10 bit addresses. +address 0x10 (though a single device could respond to both of them). -WARNING! The current 10 bit address support is EXPERIMENTAL. There are -several places in the code that will cause SEVERE PROBLEMS with 10 bit -addresses, even though there is some basic handling and hooks. Also, -almost no supported adapter handles the 10 bit addresses correctly. +I2C messages to and from 10-bit address devices have a different format. +See the I2C specification for the details. -As soon as a real 10 bit address device is spotted 'in the wild', we -can and will add proper support. Right now, 10 bit address devices -are defined by the I2C protocol, but we have never seen a single device -which supports them. +The current 10 bit address support is minimal. It should work, however +you can expect some problems along the way: +* Not all bus drivers support 10-bit addresses. Some don't because the +  hardware doesn't support them (SMBus doesn't require 10-bit address +  support for example), some don't because nobody bothered adding the +  code (or it's there but not working properly.) Software implementation +  (i2c-algo-bit) is known to work. +* Some optional features do not support 10-bit addresses. This is the +  case of automatic detection and instantiation of devices by their, +  drivers, for example. +* Many user-space packages (for example i2c-tools) lack support for +  10-bit addresses. + +Note that 10-bit address devices are still pretty rare, so the limitations +listed above could stay for a long time, maybe even forever if nobody +needs them to be fixed. diff --git a/Documentation/serial/serial-rs485.txt b/Documentation/serial/serial-rs485.txt index 079cb3df62c..41c8378c0b2 100644 --- a/Documentation/serial/serial-rs485.txt +++ b/Documentation/serial/serial-rs485.txt @@ -97,15 +97,23 @@  	struct serial_rs485 rs485conf; -	/* Set RS485 mode: */ +	/* Enable RS485 mode: */  	rs485conf.flags |= SER_RS485_ENABLED; +	/* Set logical level for RTS pin equal to 1 when sending: */ +	rs485conf.flags |= SER_RS485_RTS_ON_SEND; +	/* or, set logical level for RTS pin equal to 0 when sending: */ +	rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND); + +	/* Set logical level for RTS pin equal to 1 after sending: */ +	rs485conf.flags |= SER_RS485_RTS_AFTER_SEND; +	/* or, set logical level for RTS pin equal to 0 after sending: */ +	rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND); +  	/* Set rts delay before send, if needed: */ -	rs485conf.flags |= SER_RS485_RTS_BEFORE_SEND;  	rs485conf.delay_rts_before_send = ...;  	/* Set rts delay after send, if needed: */ -	rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;  	rs485conf.delay_rts_after_send = ...;  	/* Set this flag if you want to receive data even whilst sending data */ diff --git a/MAINTAINERS b/MAINTAINERS index 29f9948b2cc..3523ab000f1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1789,6 +1789,14 @@ F:	include/net/cfg80211.h  F:	net/wireless/*  X:	net/wireless/wext* +CHAR and MISC DRIVERS +M:	Arnd Bergmann <arnd@arndb.de> +M:	Greg Kroah-Hartman <greg@kroah.com> +T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git +S:	Maintained +F:	drivers/char/* +F:	drivers/misc/* +  CHECKPATCH  M:	Andy Whitcroft <apw@canonical.com>  S:	Supported @@ -3720,7 +3728,7 @@ F:	fs/jbd2/  F:	include/linux/jbd2.h  JSM Neo PCI based serial card -M:	Breno Leitao <leitao@linux.vnet.ibm.com> +M:	Lucas Tavares <lucaskt@linux.vnet.ibm.com>  L:	linux-serial@vger.kernel.org  S:	Maintained  F:	drivers/tty/serial/jsm/ diff --git a/arch/microblaze/include/asm/namei.h b/arch/microblaze/include/asm/namei.h deleted file mode 100644 index 61d60b8a07d..00000000000 --- a/arch/microblaze/include/asm/namei.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_NAMEI_H -#define _ASM_MICROBLAZE_NAMEI_H - -#ifdef __KERNEL__ - -/* This dummy routine maybe changed to something useful - * for /usr/gnemul/ emulation stuff. - * Look at asm-sparc/namei.h for details. - */ -#define __emul_prefix() NULL - -#endif /* __KERNEL__ */ - -#endif /* _ASM_MICROBLAZE_NAMEI_H */ diff --git a/arch/x86/um/asm/processor.h b/arch/x86/um/asm/processor.h index 118c143a9cb..2c32df6fe23 100644 --- a/arch/x86/um/asm/processor.h +++ b/arch/x86/um/asm/processor.h @@ -11,7 +11,7 @@  #endif  #define KSTK_EIP(tsk) KSTK_REG(tsk, HOST_IP) -#define KSTK_ESP(tsk) KSTK_REG(tsk, HOST_IP) +#define KSTK_ESP(tsk) KSTK_REG(tsk, HOST_SP)  #define KSTK_EBP(tsk) KSTK_REG(tsk, HOST_BP)  #define ARCH_IS_STACKGROW(address) \ diff --git a/drivers/base/node.c b/drivers/base/node.c index 793f796c4da..5693ecee9a4 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -127,12 +127,13 @@ static ssize_t node_read_meminfo(struct sys_device * dev,  		       nid, K(node_page_state(nid, NR_WRITEBACK)),  		       nid, K(node_page_state(nid, NR_FILE_PAGES)),  		       nid, K(node_page_state(nid, NR_FILE_MAPPED)), -		       nid, K(node_page_state(nid, NR_ANON_PAGES)  #ifdef CONFIG_TRANSPARENT_HUGEPAGE +		       nid, K(node_page_state(nid, NR_ANON_PAGES)  			+ node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) * -			HPAGE_PMD_NR +			HPAGE_PMD_NR), +#else +		       nid, K(node_page_state(nid, NR_ANON_PAGES)),  #endif -		       ),  		       nid, K(node_page_state(nid, NR_SHMEM)),  		       nid, node_page_state(nid, NR_KERNEL_STACK) *  				THREAD_SIZE / 1024, @@ -143,13 +144,14 @@ static ssize_t node_read_meminfo(struct sys_device * dev,  		       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE) +  				node_page_state(nid, NR_SLAB_UNRECLAIMABLE)),  		       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE)), -		       nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))  #ifdef CONFIG_TRANSPARENT_HUGEPAGE +		       nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))  			, nid,  			K(node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) * -			HPAGE_PMD_NR) +			HPAGE_PMD_NR)); +#else +		       nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE)));  #endif -		       );  	n += hugetlb_report_node_meminfo(nid, buf + n);  	return n;  } diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 405c63b9d53..8323fc38984 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1873,6 +1873,10 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,  	}  	if (num_clips && clips_ptr) { +		if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) { +			ret = -EINVAL; +			goto out_err1; +		}  		clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);  		if (!clips) {  			ret = -ENOMEM; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4f40f1ce1d8..d09a6e02dc9 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -636,11 +636,16 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)  	struct drm_device *dev = node->minor->dev;  	drm_i915_private_t *dev_priv = dev->dev_private;  	struct intel_ring_buffer *ring; +	int ret;  	ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];  	if (ring->size == 0)  		return 0; +	ret = mutex_lock_interruptible(&dev->struct_mutex); +	if (ret) +		return ret; +  	seq_printf(m, "Ring %s:\n", ring->name);  	seq_printf(m, "  Head :    %08x\n", I915_READ_HEAD(ring) & HEAD_ADDR);  	seq_printf(m, "  Tail :    %08x\n", I915_READ_TAIL(ring) & TAIL_ADDR); @@ -654,6 +659,8 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)  	seq_printf(m, "  Control : %08x\n", I915_READ_CTL(ring));  	seq_printf(m, "  Start :   %08x\n", I915_READ_START(ring)); +	mutex_unlock(&dev->struct_mutex); +  	return 0;  } @@ -842,7 +849,16 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused)  	struct drm_info_node *node = (struct drm_info_node *) m->private;  	struct drm_device *dev = node->minor->dev;  	drm_i915_private_t *dev_priv = dev->dev_private; -	u16 crstanddelay = I915_READ16(CRSTANDVID); +	u16 crstanddelay; +	int ret; + +	ret = mutex_lock_interruptible(&dev->struct_mutex); +	if (ret) +		return ret; + +	crstanddelay = I915_READ16(CRSTANDVID); + +	mutex_unlock(&dev->struct_mutex);  	seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f)); @@ -940,7 +956,11 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)  	struct drm_device *dev = node->minor->dev;  	drm_i915_private_t *dev_priv = dev->dev_private;  	u32 delayfreq; -	int i; +	int ret, i; + +	ret = mutex_lock_interruptible(&dev->struct_mutex); +	if (ret) +		return ret;  	for (i = 0; i < 16; i++) {  		delayfreq = I915_READ(PXVFREQ_BASE + i * 4); @@ -948,6 +968,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)  			   (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);  	} +	mutex_unlock(&dev->struct_mutex); +  	return 0;  } @@ -962,13 +984,19 @@ static int i915_inttoext_table(struct seq_file *m, void *unused)  	struct drm_device *dev = node->minor->dev;  	drm_i915_private_t *dev_priv = dev->dev_private;  	u32 inttoext; -	int i; +	int ret, i; + +	ret = mutex_lock_interruptible(&dev->struct_mutex); +	if (ret) +		return ret;  	for (i = 1; i <= 32; i++) {  		inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);  		seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);  	} +	mutex_unlock(&dev->struct_mutex); +  	return 0;  } @@ -977,9 +1005,19 @@ static int i915_drpc_info(struct seq_file *m, void *unused)  	struct drm_info_node *node = (struct drm_info_node *) m->private;  	struct drm_device *dev = node->minor->dev;  	drm_i915_private_t *dev_priv = dev->dev_private; -	u32 rgvmodectl = I915_READ(MEMMODECTL); -	u32 rstdbyctl = I915_READ(RSTDBYCTL); -	u16 crstandvid = I915_READ16(CRSTANDVID); +	u32 rgvmodectl, rstdbyctl; +	u16 crstandvid; +	int ret; + +	ret = mutex_lock_interruptible(&dev->struct_mutex); +	if (ret) +		return ret; + +	rgvmodectl = I915_READ(MEMMODECTL); +	rstdbyctl = I915_READ(RSTDBYCTL); +	crstandvid = I915_READ16(CRSTANDVID); + +	mutex_unlock(&dev->struct_mutex);  	seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?  		   "yes" : "no"); @@ -1167,9 +1205,16 @@ static int i915_gfxec(struct seq_file *m, void *unused)  	struct drm_info_node *node = (struct drm_info_node *) m->private;  	struct drm_device *dev = node->minor->dev;  	drm_i915_private_t *dev_priv = dev->dev_private; +	int ret; + +	ret = mutex_lock_interruptible(&dev->struct_mutex); +	if (ret) +		return ret;  	seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4)); +	mutex_unlock(&dev->struct_mutex); +  	return 0;  } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e9c2cfe45da..15bfa9145d2 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -68,7 +68,7 @@ module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);  MODULE_PARM_DESC(i915_enable_rc6,  		"Enable power-saving render C-state 6 (default: true)"); -unsigned int i915_enable_fbc __read_mostly = -1; +int i915_enable_fbc __read_mostly = -1;  module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);  MODULE_PARM_DESC(i915_enable_fbc,  		"Enable frame buffer compression for power savings " @@ -80,7 +80,7 @@ MODULE_PARM_DESC(lvds_downclock,  		"Use panel (LVDS/eDP) downclocking for power savings "  		"(default: false)"); -unsigned int i915_panel_use_ssc __read_mostly = -1; +int i915_panel_use_ssc __read_mostly = -1;  module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);  MODULE_PARM_DESC(lvds_use_ssc,  		"Use Spread Spectrum Clock with panels [LVDS/eDP] " @@ -107,7 +107,7 @@ static struct drm_driver driver;  extern int intel_agp_enabled;  #define INTEL_VGA_DEVICE(id, info) {		\ -	.class = PCI_CLASS_DISPLAY_VGA << 8,	\ +	.class = PCI_BASE_CLASS_DISPLAY << 16,	\  	.class_mask = 0xff0000,			\  	.vendor = 0x8086,			\  	.device = id,				\ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 06a37f4fd74..4a9c1b97980 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -126,6 +126,9 @@ struct drm_i915_master_private {  	struct _drm_i915_sarea *sarea_priv;  };  #define I915_FENCE_REG_NONE -1 +#define I915_MAX_NUM_FENCES 16 +/* 16 fences + sign bit for FENCE_REG_NONE */ +#define I915_MAX_NUM_FENCE_BITS 5  struct drm_i915_fence_reg {  	struct list_head lru_list; @@ -168,7 +171,7 @@ struct drm_i915_error_state {  	u32 instdone1;  	u32 seqno;  	u64 bbaddr; -	u64 fence[16]; +	u64 fence[I915_MAX_NUM_FENCES];  	struct timeval time;  	struct drm_i915_error_object {  		int page_count; @@ -182,7 +185,7 @@ struct drm_i915_error_state {  		u32 gtt_offset;  		u32 read_domains;  		u32 write_domain; -		s32 fence_reg:5; +		s32 fence_reg:I915_MAX_NUM_FENCE_BITS;  		s32 pinned:2;  		u32 tiling:2;  		u32 dirty:1; @@ -375,7 +378,7 @@ typedef struct drm_i915_private {  	struct notifier_block lid_notifier;  	int crt_ddc_pin; -	struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ +	struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */  	int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */  	int num_fence_regs; /* 8 on pre-965, 16 otherwise */ @@ -506,7 +509,7 @@ typedef struct drm_i915_private {  	u8 saveAR[21];  	u8 saveDACMASK;  	u8 saveCR[37]; -	uint64_t saveFENCE[16]; +	uint64_t saveFENCE[I915_MAX_NUM_FENCES];  	u32 saveCURACNTR;  	u32 saveCURAPOS;  	u32 saveCURABASE; @@ -777,10 +780,8 @@ struct drm_i915_gem_object {  	 * Fence register bits (if any) for this object.  Will be set  	 * as needed when mapped into the GTT.  	 * Protected by dev->struct_mutex. -	 * -	 * Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE)  	 */ -	signed int fence_reg:5; +	signed int fence_reg:I915_MAX_NUM_FENCE_BITS;  	/**  	 * Advice: are the backing pages purgeable? @@ -999,10 +1000,10 @@ extern int i915_panel_ignore_lid __read_mostly;  extern unsigned int i915_powersave __read_mostly;  extern unsigned int i915_semaphores __read_mostly;  extern unsigned int i915_lvds_downclock __read_mostly; -extern unsigned int i915_panel_use_ssc __read_mostly; +extern int i915_panel_use_ssc __read_mostly;  extern int i915_vbt_sdvo_panel_type __read_mostly;  extern unsigned int i915_enable_rc6 __read_mostly; -extern unsigned int i915_enable_fbc __read_mostly; +extern int i915_enable_fbc __read_mostly;  extern bool i915_enable_hangcheck __read_mostly;  extern int i915_suspend(struct drm_device *dev, pm_message_t state); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d18b07adcff..8359dc77704 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1745,7 +1745,7 @@ static void i915_gem_reset_fences(struct drm_device *dev)  	struct drm_i915_private *dev_priv = dev->dev_private;  	int i; -	for (i = 0; i < 16; i++) { +	for (i = 0; i < dev_priv->num_fence_regs; i++) {  		struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];  		struct drm_i915_gem_object *obj = reg->obj; @@ -3512,9 +3512,11 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,  			 * so emit a request to do so.  			 */  			request = kzalloc(sizeof(*request), GFP_KERNEL); -			if (request) +			if (request) {  				ret = i915_add_request(obj->ring, NULL, request); -			else +				if (ret) +					kfree(request); +			} else  				ret = -ENOMEM;  		} @@ -3613,7 +3615,7 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,  	obj->base.write_domain = I915_GEM_DOMAIN_CPU;  	obj->base.read_domains = I915_GEM_DOMAIN_CPU; -	if (IS_GEN6(dev)) { +	if (IS_GEN6(dev) || IS_GEN7(dev)) {  		/* On Gen6, we can have the GPU use the LLC (the CPU  		 * cache) for about a 10% performance improvement  		 * compared to uncached.  Graphics requests other than @@ -3877,7 +3879,7 @@ i915_gem_load(struct drm_device *dev)  	INIT_LIST_HEAD(&dev_priv->mm.gtt_list);  	for (i = 0; i < I915_NUM_RINGS; i++)  		init_ring_lists(&dev_priv->ring[i]); -	for (i = 0; i < 16; i++) +	for (i = 0; i < I915_MAX_NUM_FENCES; i++)  		INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);  	INIT_DELAYED_WORK(&dev_priv->mm.retire_work,  			  i915_gem_retire_work_handler); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 9ee2729fe5c..b40004b5597 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -824,6 +824,7 @@ static void i915_gem_record_fences(struct drm_device *dev,  	/* Fences */  	switch (INTEL_INFO(dev)->gen) { +	case 7:  	case 6:  		for (i = 0; i < 16; i++)  			error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5a09416e611..b080cc82400 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1553,12 +1553,21 @@   */  #define   PP_READY		(1 << 30)  #define   PP_SEQUENCE_NONE	(0 << 28) -#define   PP_SEQUENCE_ON	(1 << 28) -#define   PP_SEQUENCE_OFF	(2 << 28) -#define   PP_SEQUENCE_MASK	0x30000000 +#define   PP_SEQUENCE_POWER_UP	(1 << 28) +#define   PP_SEQUENCE_POWER_DOWN (2 << 28) +#define   PP_SEQUENCE_MASK	(3 << 28) +#define   PP_SEQUENCE_SHIFT	28  #define   PP_CYCLE_DELAY_ACTIVE	(1 << 27) -#define   PP_SEQUENCE_STATE_ON_IDLE (1 << 3)  #define   PP_SEQUENCE_STATE_MASK 0x0000000f +#define   PP_SEQUENCE_STATE_OFF_IDLE	(0x0 << 0) +#define   PP_SEQUENCE_STATE_OFF_S0_1	(0x1 << 0) +#define   PP_SEQUENCE_STATE_OFF_S0_2	(0x2 << 0) +#define   PP_SEQUENCE_STATE_OFF_S0_3	(0x3 << 0) +#define   PP_SEQUENCE_STATE_ON_IDLE	(0x8 << 0) +#define   PP_SEQUENCE_STATE_ON_S1_0	(0x9 << 0) +#define   PP_SEQUENCE_STATE_ON_S1_2	(0xa << 0) +#define   PP_SEQUENCE_STATE_ON_S1_3	(0xb << 0) +#define   PP_SEQUENCE_STATE_RESET	(0xf << 0)  #define PP_CONTROL	0x61204  #define   POWER_TARGET_ON	(1 << 0)  #define PP_ON_DELAYS	0x61208 @@ -3444,6 +3453,10 @@  #define  GT_FIFO_FREE_ENTRIES			0x120008  #define    GT_FIFO_NUM_RESERVED_ENTRIES		20 +#define GEN6_UCGCTL2				0x9404 +# define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE		(1 << 12) +# define GEN6_RCCUNIT_CLOCK_GATE_DISABLE		(1 << 11) +  #define GEN6_RPNSWREQ				0xA008  #define   GEN6_TURBO_DISABLE			(1<<31)  #define   GEN6_FREQUENCY(x)			((x)<<25) diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index f8f602d7665..7886e4fb60e 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -370,6 +370,7 @@ static void i915_save_modeset_reg(struct drm_device *dev)  	/* Fences */  	switch (INTEL_INFO(dev)->gen) { +	case 7:  	case 6:  		for (i = 0; i < 16; i++)  			dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); @@ -404,6 +405,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev)  	/* Fences */  	switch (INTEL_INFO(dev)->gen) { +	case 7:  	case 6:  		for (i = 0; i < 16; i++)  			I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 981b1f1c04d..e77a863a383 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2933,7 +2933,8 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)  	/* For PCH DP, enable TRANS_DP_CTL */  	if (HAS_PCH_CPT(dev) && -	    intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { +	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || +	     intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {  		u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) >> 5;  		reg = TRANS_DP_CTL(pipe);  		temp = I915_READ(reg); @@ -4711,7 +4712,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,  				lvds_bpc = 6;  			if (lvds_bpc < display_bpc) { -				DRM_DEBUG_DRIVER("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc); +				DRM_DEBUG_KMS("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);  				display_bpc = lvds_bpc;  			}  			continue; @@ -4722,7 +4723,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,  			unsigned int edp_bpc = dev_priv->edp.bpp / 3;  			if (edp_bpc < display_bpc) { -				DRM_DEBUG_DRIVER("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); +				DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);  				display_bpc = edp_bpc;  			}  			continue; @@ -4737,7 +4738,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,  			/* Don't use an invalid EDID bpc value */  			if (connector->display_info.bpc &&  			    connector->display_info.bpc < display_bpc) { -				DRM_DEBUG_DRIVER("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc); +				DRM_DEBUG_KMS("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);  				display_bpc = connector->display_info.bpc;  			}  		} @@ -4748,10 +4749,10 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,  		 */  		if (intel_encoder->type == INTEL_OUTPUT_HDMI) {  			if (display_bpc > 8 && display_bpc < 12) { -				DRM_DEBUG_DRIVER("forcing bpc to 12 for HDMI\n"); +				DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n");  				display_bpc = 12;  			} else { -				DRM_DEBUG_DRIVER("forcing bpc to 8 for HDMI\n"); +				DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n");  				display_bpc = 8;  			}  		} @@ -4789,8 +4790,8 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,  	display_bpc = min(display_bpc, bpc); -	DRM_DEBUG_DRIVER("setting pipe bpc to %d (max display bpc %d)\n", -			 bpc, display_bpc); +	DRM_DEBUG_KMS("setting pipe bpc to %d (max display bpc %d)\n", +		      bpc, display_bpc);  	*pipe_bpp = display_bpc * 3; @@ -5671,7 +5672,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,  	pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;  	if ((is_lvds && dev_priv->lvds_dither) || dither) {  		pipeconf |= PIPECONF_DITHER_EN; -		pipeconf |= PIPECONF_DITHER_TYPE_ST1; +		pipeconf |= PIPECONF_DITHER_TYPE_SP;  	}  	if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {  		intel_dp_set_m_n(crtc, mode, adjusted_mode); @@ -8148,6 +8149,20 @@ static void gen6_init_clock_gating(struct drm_device *dev)  	I915_WRITE(WM2_LP_ILK, 0);  	I915_WRITE(WM1_LP_ILK, 0); +	/* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock +	 * gating disable must be set.  Failure to set it results in +	 * flickering pixels due to Z write ordering failures after +	 * some amount of runtime in the Mesa "fire" demo, and Unigine +	 * Sanctuary and Tropics, and apparently anything else with +	 * alpha test or pixel discard. +	 * +	 * According to the spec, bit 11 (RCCUNIT) must also be set, +	 * but we didn't debug actual testcases to find it out. +	 */ +	I915_WRITE(GEN6_UCGCTL2, +		   GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | +		   GEN6_RCCUNIT_CLOCK_GATE_DISABLE); +  	/*  	 * According to the spec the following bits should be  	 * set in order to enable memory self-refresh and fbc: diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 09b318b0227..4d0358fad93 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -59,7 +59,6 @@ struct intel_dp {  	struct i2c_algo_dp_aux_data algo;  	bool is_pch_edp;  	uint8_t	train_set[4]; -	uint8_t link_status[DP_LINK_STATUS_SIZE];  	int panel_power_up_delay;  	int panel_power_down_delay;  	int panel_power_cycle_delay; @@ -68,7 +67,6 @@ struct intel_dp {  	struct drm_display_mode *panel_fixed_mode;  /* for eDP */  	struct delayed_work panel_vdd_work;  	bool want_panel_vdd; -	unsigned long panel_off_jiffies;  };  /** @@ -157,16 +155,12 @@ intel_edp_link_config(struct intel_encoder *intel_encoder,  static int  intel_dp_max_lane_count(struct intel_dp *intel_dp)  { -	int max_lane_count = 4; - -	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) { -		max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f; -		switch (max_lane_count) { -		case 1: case 2: case 4: -			break; -		default: -			max_lane_count = 4; -		} +	int max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f; +	switch (max_lane_count) { +	case 1: case 2: case 4: +		break; +	default: +		max_lane_count = 4;  	}  	return max_lane_count;  } @@ -768,12 +762,11 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,  			continue;  		intel_dp = enc_to_intel_dp(encoder); -		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) { +		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || +		    intel_dp->base.type == INTEL_OUTPUT_EDP) +		{  			lane_count = intel_dp->lane_count;  			break; -		} else if (is_edp(intel_dp)) { -			lane_count = dev_priv->edp.lanes; -			break;  		}  	} @@ -810,6 +803,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,  		  struct drm_display_mode *adjusted_mode)  {  	struct drm_device *dev = encoder->dev; +	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);  	struct drm_crtc *crtc = intel_dp->base.base.crtc;  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -822,18 +816,31 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,  			ironlake_edp_pll_off(encoder);  	} -	intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; -	intel_dp->DP |= intel_dp->color_range; +	/* +	 * There are three kinds of DP registers: +	 * +	 * 	IBX PCH +	 * 	CPU +	 * 	CPT PCH +	 * +	 * IBX PCH and CPU are the same for almost everything, +	 * except that the CPU DP PLL is configured in this +	 * register +	 * +	 * CPT PCH is quite different, having many bits moved +	 * to the TRANS_DP_CTL register instead. That +	 * configuration happens (oddly) in ironlake_pch_enable +	 */ -	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) -		intel_dp->DP |= DP_SYNC_HS_HIGH; -	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) -		intel_dp->DP |= DP_SYNC_VS_HIGH; +	/* Preserve the BIOS-computed detected bit. This is +	 * supposed to be read-only. +	 */ +	intel_dp->DP = I915_READ(intel_dp->output_reg) & DP_DETECTED; +	intel_dp->DP |=  DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; -	if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) -		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; -	else -		intel_dp->DP |= DP_LINK_TRAIN_OFF; +	/* Handle DP bits in common between all three register formats */ + +	intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;  	switch (intel_dp->lane_count) {  	case 1: @@ -852,59 +859,106 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,  		intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;  		intel_write_eld(encoder, adjusted_mode);  	} -  	memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);  	intel_dp->link_configuration[0] = intel_dp->link_bw;  	intel_dp->link_configuration[1] = intel_dp->lane_count;  	intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B; -  	/*  	 * Check for DPCD version > 1.1 and enhanced framing support  	 */  	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&  	    (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {  		intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; -		intel_dp->DP |= DP_ENHANCED_FRAMING;  	} -	/* CPT DP's pipe select is decided in TRANS_DP_CTL */ -	if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev)) -		intel_dp->DP |= DP_PIPEB_SELECT; +	/* Split out the IBX/CPU vs CPT settings */ -	if (is_cpu_edp(intel_dp)) { -		/* don't miss out required setting for eDP */ -		intel_dp->DP |= DP_PLL_ENABLE; -		if (adjusted_mode->clock < 200000) -			intel_dp->DP |= DP_PLL_FREQ_160MHZ; -		else -			intel_dp->DP |= DP_PLL_FREQ_270MHZ; +	if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) { +		intel_dp->DP |= intel_dp->color_range; + +		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) +			intel_dp->DP |= DP_SYNC_HS_HIGH; +		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) +			intel_dp->DP |= DP_SYNC_VS_HIGH; +		intel_dp->DP |= DP_LINK_TRAIN_OFF; + +		if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN) +			intel_dp->DP |= DP_ENHANCED_FRAMING; + +		if (intel_crtc->pipe == 1) +			intel_dp->DP |= DP_PIPEB_SELECT; + +		if (is_cpu_edp(intel_dp)) { +			/* don't miss out required setting for eDP */ +			intel_dp->DP |= DP_PLL_ENABLE; +			if (adjusted_mode->clock < 200000) +				intel_dp->DP |= DP_PLL_FREQ_160MHZ; +			else +				intel_dp->DP |= DP_PLL_FREQ_270MHZ; +		} +	} else { +		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;  	}  } -static void ironlake_wait_panel_off(struct intel_dp *intel_dp) +#define IDLE_ON_MASK		(PP_ON | 0 	  | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK) +#define IDLE_ON_VALUE   	(PP_ON | 0 	  | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE) + +#define IDLE_OFF_MASK		(PP_ON | 0        | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK) +#define IDLE_OFF_VALUE		(0     | 0        | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE) + +#define IDLE_CYCLE_MASK		(PP_ON | 0        | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK) +#define IDLE_CYCLE_VALUE	(0     | 0        | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE) + +static void ironlake_wait_panel_status(struct intel_dp *intel_dp, +				       u32 mask, +				       u32 value)  { -	unsigned long	off_time; -	unsigned long	delay; +	struct drm_device *dev = intel_dp->base.base.dev; +	struct drm_i915_private *dev_priv = dev->dev_private; -	DRM_DEBUG_KMS("Wait for panel power off time\n"); +	DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n", +		      mask, value, +		      I915_READ(PCH_PP_STATUS), +		      I915_READ(PCH_PP_CONTROL)); -	if (ironlake_edp_have_panel_power(intel_dp) || -	    ironlake_edp_have_panel_vdd(intel_dp)) -	{ -		DRM_DEBUG_KMS("Panel still on, no delay needed\n"); -		return; +	if (_wait_for((I915_READ(PCH_PP_STATUS) & mask) == value, 5000, 10)) { +		DRM_ERROR("Panel status timeout: status %08x control %08x\n", +			  I915_READ(PCH_PP_STATUS), +			  I915_READ(PCH_PP_CONTROL));  	} +} -	off_time = intel_dp->panel_off_jiffies + msecs_to_jiffies(intel_dp->panel_power_down_delay); -	if (time_after(jiffies, off_time)) { -		DRM_DEBUG_KMS("Time already passed"); -		return; -	} -	delay = jiffies_to_msecs(off_time - jiffies); -	if (delay > intel_dp->panel_power_down_delay) -		delay = intel_dp->panel_power_down_delay; -	DRM_DEBUG_KMS("Waiting an additional %ld ms\n", delay); -	msleep(delay); +static void ironlake_wait_panel_on(struct intel_dp *intel_dp) +{ +	DRM_DEBUG_KMS("Wait for panel power on\n"); +	ironlake_wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE); +} + +static void ironlake_wait_panel_off(struct intel_dp *intel_dp) +{ +	DRM_DEBUG_KMS("Wait for panel power off time\n"); +	ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE); +} + +static void ironlake_wait_panel_power_cycle(struct intel_dp *intel_dp) +{ +	DRM_DEBUG_KMS("Wait for panel power cycle\n"); +	ironlake_wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE); +} + + +/* Read the current pp_control value, unlocking the register if it + * is locked + */ + +static  u32 ironlake_get_pp_control(struct drm_i915_private *dev_priv) +{ +	u32	control = I915_READ(PCH_PP_CONTROL); + +	control &= ~PANEL_UNLOCK_MASK; +	control |= PANEL_UNLOCK_REGS; +	return control;  }  static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) @@ -921,15 +975,16 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)  	     "eDP VDD already requested on\n");  	intel_dp->want_panel_vdd = true; +  	if (ironlake_edp_have_panel_vdd(intel_dp)) {  		DRM_DEBUG_KMS("eDP VDD already on\n");  		return;  	} -	ironlake_wait_panel_off(intel_dp); -	pp = I915_READ(PCH_PP_CONTROL); -	pp &= ~PANEL_UNLOCK_MASK; -	pp |= PANEL_UNLOCK_REGS; +	if (!ironlake_edp_have_panel_power(intel_dp)) +		ironlake_wait_panel_power_cycle(intel_dp); + +	pp = ironlake_get_pp_control(dev_priv);  	pp |= EDP_FORCE_VDD;  	I915_WRITE(PCH_PP_CONTROL, pp);  	POSTING_READ(PCH_PP_CONTROL); @@ -952,9 +1007,7 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)  	u32 pp;  	if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) { -		pp = I915_READ(PCH_PP_CONTROL); -		pp &= ~PANEL_UNLOCK_MASK; -		pp |= PANEL_UNLOCK_REGS; +		pp = ironlake_get_pp_control(dev_priv);  		pp &= ~EDP_FORCE_VDD;  		I915_WRITE(PCH_PP_CONTROL, pp);  		POSTING_READ(PCH_PP_CONTROL); @@ -962,7 +1015,8 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)  		/* Make sure sequencer is idle before allowing subsequent activity */  		DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",  			      I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL)); -		intel_dp->panel_off_jiffies = jiffies; + +		msleep(intel_dp->panel_power_down_delay);  	}  } @@ -972,9 +1026,9 @@ static void ironlake_panel_vdd_work(struct work_struct *__work)  						 struct intel_dp, panel_vdd_work);  	struct drm_device *dev = intel_dp->base.base.dev; -	mutex_lock(&dev->struct_mutex); +	mutex_lock(&dev->mode_config.mutex);  	ironlake_panel_vdd_off_sync(intel_dp); -	mutex_unlock(&dev->struct_mutex); +	mutex_unlock(&dev->mode_config.mutex);  }  static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) @@ -984,7 +1038,7 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)  	DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd);  	WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on"); -	 +  	intel_dp->want_panel_vdd = false;  	if (sync) { @@ -1000,23 +1054,25 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)  	}  } -/* Returns true if the panel was already on when called */  static void ironlake_edp_panel_on(struct intel_dp *intel_dp)  {  	struct drm_device *dev = intel_dp->base.base.dev;  	struct drm_i915_private *dev_priv = dev->dev_private; -	u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE; +	u32 pp;  	if (!is_edp(intel_dp))  		return; -	if (ironlake_edp_have_panel_power(intel_dp)) + +	DRM_DEBUG_KMS("Turn eDP power on\n"); + +	if (ironlake_edp_have_panel_power(intel_dp)) { +		DRM_DEBUG_KMS("eDP power already on\n");  		return; +	} -	ironlake_wait_panel_off(intel_dp); -	pp = I915_READ(PCH_PP_CONTROL); -	pp &= ~PANEL_UNLOCK_MASK; -	pp |= PANEL_UNLOCK_REGS; +	ironlake_wait_panel_power_cycle(intel_dp); +	pp = ironlake_get_pp_control(dev_priv);  	if (IS_GEN5(dev)) {  		/* ILK workaround: disable reset around power sequence */  		pp &= ~PANEL_POWER_RESET; @@ -1025,13 +1081,13 @@ static void ironlake_edp_panel_on(struct intel_dp *intel_dp)  	}  	pp |= POWER_TARGET_ON; +	if (!IS_GEN5(dev)) +		pp |= PANEL_POWER_RESET; +  	I915_WRITE(PCH_PP_CONTROL, pp);  	POSTING_READ(PCH_PP_CONTROL); -	if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on_mask, -		     5000)) -		DRM_ERROR("panel on wait timed out: 0x%08x\n", -			  I915_READ(PCH_PP_STATUS)); +	ironlake_wait_panel_on(intel_dp);  	if (IS_GEN5(dev)) {  		pp |= PANEL_POWER_RESET; /* restore panel reset bit */ @@ -1040,46 +1096,25 @@ static void ironlake_edp_panel_on(struct intel_dp *intel_dp)  	}  } -static void ironlake_edp_panel_off(struct drm_encoder *encoder) +static void ironlake_edp_panel_off(struct intel_dp *intel_dp)  { -	struct intel_dp *intel_dp = enc_to_intel_dp(encoder); -	struct drm_device *dev = encoder->dev; +	struct drm_device *dev = intel_dp->base.base.dev;  	struct drm_i915_private *dev_priv = dev->dev_private; -	u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK | -		PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK; +	u32 pp;  	if (!is_edp(intel_dp))  		return; -	pp = I915_READ(PCH_PP_CONTROL); -	pp &= ~PANEL_UNLOCK_MASK; -	pp |= PANEL_UNLOCK_REGS; -	if (IS_GEN5(dev)) { -		/* ILK workaround: disable reset around power sequence */ -		pp &= ~PANEL_POWER_RESET; -		I915_WRITE(PCH_PP_CONTROL, pp); -		POSTING_READ(PCH_PP_CONTROL); -	} +	DRM_DEBUG_KMS("Turn eDP power off\n"); -	intel_dp->panel_off_jiffies = jiffies; +	WARN(intel_dp->want_panel_vdd, "Cannot turn power off while VDD is on\n"); -	if (IS_GEN5(dev)) { -		pp &= ~POWER_TARGET_ON; -		I915_WRITE(PCH_PP_CONTROL, pp); -		POSTING_READ(PCH_PP_CONTROL); -		pp &= ~POWER_TARGET_ON; -		I915_WRITE(PCH_PP_CONTROL, pp); -		POSTING_READ(PCH_PP_CONTROL); -		msleep(intel_dp->panel_power_cycle_delay); - -		if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000)) -			DRM_ERROR("panel off wait timed out: 0x%08x\n", -				  I915_READ(PCH_PP_STATUS)); +	pp = ironlake_get_pp_control(dev_priv); +	pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE); +	I915_WRITE(PCH_PP_CONTROL, pp); +	POSTING_READ(PCH_PP_CONTROL); -		pp |= PANEL_POWER_RESET; /* restore panel reset bit */ -		I915_WRITE(PCH_PP_CONTROL, pp); -		POSTING_READ(PCH_PP_CONTROL); -	} +	ironlake_wait_panel_off(intel_dp);  }  static void ironlake_edp_backlight_on(struct intel_dp *intel_dp) @@ -1099,9 +1134,7 @@ static void ironlake_edp_backlight_on(struct intel_dp *intel_dp)  	 * allowing it to appear.  	 */  	msleep(intel_dp->backlight_on_delay); -	pp = I915_READ(PCH_PP_CONTROL); -	pp &= ~PANEL_UNLOCK_MASK; -	pp |= PANEL_UNLOCK_REGS; +	pp = ironlake_get_pp_control(dev_priv);  	pp |= EDP_BLC_ENABLE;  	I915_WRITE(PCH_PP_CONTROL, pp);  	POSTING_READ(PCH_PP_CONTROL); @@ -1117,9 +1150,7 @@ static void ironlake_edp_backlight_off(struct intel_dp *intel_dp)  		return;  	DRM_DEBUG_KMS("\n"); -	pp = I915_READ(PCH_PP_CONTROL); -	pp &= ~PANEL_UNLOCK_MASK; -	pp |= PANEL_UNLOCK_REGS; +	pp = ironlake_get_pp_control(dev_priv);  	pp &= ~EDP_BLC_ENABLE;  	I915_WRITE(PCH_PP_CONTROL, pp);  	POSTING_READ(PCH_PP_CONTROL); @@ -1187,17 +1218,18 @@ static void intel_dp_prepare(struct drm_encoder *encoder)  {  	struct intel_dp *intel_dp = enc_to_intel_dp(encoder); +	ironlake_edp_backlight_off(intel_dp); +	ironlake_edp_panel_off(intel_dp); +  	/* Wake up the sink first */  	ironlake_edp_panel_vdd_on(intel_dp);  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); +	intel_dp_link_down(intel_dp);  	ironlake_edp_panel_vdd_off(intel_dp, false);  	/* Make sure the panel is off before trying to  	 * change the mode  	 */ -	ironlake_edp_backlight_off(intel_dp); -	intel_dp_link_down(intel_dp); -	ironlake_edp_panel_off(encoder);  }  static void intel_dp_commit(struct drm_encoder *encoder) @@ -1211,7 +1243,6 @@ static void intel_dp_commit(struct drm_encoder *encoder)  	intel_dp_start_link_train(intel_dp);  	ironlake_edp_panel_on(intel_dp);  	ironlake_edp_panel_vdd_off(intel_dp, true); -  	intel_dp_complete_link_train(intel_dp);  	ironlake_edp_backlight_on(intel_dp); @@ -1230,16 +1261,20 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)  	uint32_t dp_reg = I915_READ(intel_dp->output_reg);  	if (mode != DRM_MODE_DPMS_ON) { +		ironlake_edp_backlight_off(intel_dp); +		ironlake_edp_panel_off(intel_dp); +  		ironlake_edp_panel_vdd_on(intel_dp); -		if (is_edp(intel_dp)) -			ironlake_edp_backlight_off(intel_dp);  		intel_dp_sink_dpms(intel_dp, mode);  		intel_dp_link_down(intel_dp); -		ironlake_edp_panel_off(encoder); -		if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) -			ironlake_edp_pll_off(encoder);  		ironlake_edp_panel_vdd_off(intel_dp, false); + +		if (is_cpu_edp(intel_dp)) +			ironlake_edp_pll_off(encoder);  	} else { +		if (is_cpu_edp(intel_dp)) +			ironlake_edp_pll_on(encoder); +  		ironlake_edp_panel_vdd_on(intel_dp);  		intel_dp_sink_dpms(intel_dp, mode);  		if (!(dp_reg & DP_PORT_EN)) { @@ -1247,7 +1282,6 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)  			ironlake_edp_panel_on(intel_dp);  			ironlake_edp_panel_vdd_off(intel_dp, true);  			intel_dp_complete_link_train(intel_dp); -			ironlake_edp_backlight_on(intel_dp);  		} else  			ironlake_edp_panel_vdd_off(intel_dp, false);  		ironlake_edp_backlight_on(intel_dp); @@ -1285,11 +1319,11 @@ intel_dp_aux_native_read_retry(struct intel_dp *intel_dp, uint16_t address,   * link status information   */  static bool -intel_dp_get_link_status(struct intel_dp *intel_dp) +intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])  {  	return intel_dp_aux_native_read_retry(intel_dp,  					      DP_LANE0_1_STATUS, -					      intel_dp->link_status, +					      link_status,  					      DP_LINK_STATUS_SIZE);  } @@ -1301,27 +1335,25 @@ intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE],  }  static uint8_t -intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE], +intel_get_adjust_request_voltage(uint8_t adjust_request[2],  				 int lane)  { -	int	    i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);  	int	    s = ((lane & 1) ?  			 DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :  			 DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); -	uint8_t l = intel_dp_link_status(link_status, i); +	uint8_t l = adjust_request[lane>>1];  	return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;  }  static uint8_t -intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE], +intel_get_adjust_request_pre_emphasis(uint8_t adjust_request[2],  				      int lane)  { -	int	    i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);  	int	    s = ((lane & 1) ?  			 DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :  			 DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); -	uint8_t l = intel_dp_link_status(link_status, i); +	uint8_t l = adjust_request[lane>>1];  	return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;  } @@ -1344,6 +1376,7 @@ static char	*link_train_names[] = {   * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB   */  #define I830_DP_VOLTAGE_MAX	    DP_TRAIN_VOLTAGE_SWING_800 +#define I830_DP_VOLTAGE_MAX_CPT	    DP_TRAIN_VOLTAGE_SWING_1200  static uint8_t  intel_dp_pre_emphasis_max(uint8_t voltage_swing) @@ -1362,15 +1395,18 @@ intel_dp_pre_emphasis_max(uint8_t voltage_swing)  }  static void -intel_get_adjust_train(struct intel_dp *intel_dp) +intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])  { +	struct drm_device *dev = intel_dp->base.base.dev;  	uint8_t v = 0;  	uint8_t p = 0;  	int lane; +	uint8_t	*adjust_request = link_status + (DP_ADJUST_REQUEST_LANE0_1 - DP_LANE0_1_STATUS); +	int voltage_max;  	for (lane = 0; lane < intel_dp->lane_count; lane++) { -		uint8_t this_v = intel_get_adjust_request_voltage(intel_dp->link_status, lane); -		uint8_t this_p = intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane); +		uint8_t this_v = intel_get_adjust_request_voltage(adjust_request, lane); +		uint8_t this_p = intel_get_adjust_request_pre_emphasis(adjust_request, lane);  		if (this_v > v)  			v = this_v; @@ -1378,8 +1414,12 @@ intel_get_adjust_train(struct intel_dp *intel_dp)  			p = this_p;  	} -	if (v >= I830_DP_VOLTAGE_MAX) -		v = I830_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED; +	if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) +		voltage_max = I830_DP_VOLTAGE_MAX_CPT; +	else +		voltage_max = I830_DP_VOLTAGE_MAX; +	if (v >= voltage_max) +		v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;  	if (p >= intel_dp_pre_emphasis_max(v))  		p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; @@ -1389,7 +1429,7 @@ intel_get_adjust_train(struct intel_dp *intel_dp)  }  static uint32_t -intel_dp_signal_levels(uint8_t train_set, int lane_count) +intel_dp_signal_levels(uint8_t train_set)  {  	uint32_t	signal_levels = 0; @@ -1458,9 +1498,8 @@ static uint8_t  intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],  		      int lane)  { -	int i = DP_LANE0_1_STATUS + (lane >> 1);  	int s = (lane & 1) * 4; -	uint8_t l = intel_dp_link_status(link_status, i); +	uint8_t l = link_status[lane>>1];  	return (l >> s) & 0xf;  } @@ -1485,18 +1524,18 @@ intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count  			 DP_LANE_CHANNEL_EQ_DONE|\  			 DP_LANE_SYMBOL_LOCKED)  static bool -intel_channel_eq_ok(struct intel_dp *intel_dp) +intel_channel_eq_ok(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])  {  	uint8_t lane_align;  	uint8_t lane_status;  	int lane; -	lane_align = intel_dp_link_status(intel_dp->link_status, +	lane_align = intel_dp_link_status(link_status,  					  DP_LANE_ALIGN_STATUS_UPDATED);  	if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)  		return false;  	for (lane = 0; lane < intel_dp->lane_count; lane++) { -		lane_status = intel_get_lane_status(intel_dp->link_status, lane); +		lane_status = intel_get_lane_status(link_status, lane);  		if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)  			return false;  	} @@ -1521,8 +1560,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,  	ret = intel_dp_aux_native_write(intel_dp,  					DP_TRAINING_LANE0_SET, -					intel_dp->train_set, 4); -	if (ret != 4) +					intel_dp->train_set, +					intel_dp->lane_count); +	if (ret != intel_dp->lane_count)  		return false;  	return true; @@ -1538,7 +1578,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)  	int i;  	uint8_t voltage;  	bool clock_recovery = false; -	int tries; +	int voltage_tries, loop_tries;  	u32 reg;  	uint32_t DP = intel_dp->DP; @@ -1565,16 +1605,20 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)  		DP &= ~DP_LINK_TRAIN_MASK;  	memset(intel_dp->train_set, 0, 4);  	voltage = 0xff; -	tries = 0; +	voltage_tries = 0; +	loop_tries = 0;  	clock_recovery = false;  	for (;;) {  		/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ +		uint8_t	    link_status[DP_LINK_STATUS_SIZE];  		uint32_t    signal_levels; -		if (IS_GEN6(dev) && is_edp(intel_dp)) { + +		if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {  			signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);  			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;  		} else { -			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count); +			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]); +			DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", signal_levels);  			DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;  		} @@ -1590,10 +1634,13 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)  		/* Set training pattern 1 */  		udelay(100); -		if (!intel_dp_get_link_status(intel_dp)) +		if (!intel_dp_get_link_status(intel_dp, link_status)) { +			DRM_ERROR("failed to get link status\n");  			break; +		} -		if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { +		if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) { +			DRM_DEBUG_KMS("clock recovery OK\n");  			clock_recovery = true;  			break;  		} @@ -1602,20 +1649,30 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)  		for (i = 0; i < intel_dp->lane_count; i++)  			if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)  				break; -		if (i == intel_dp->lane_count) -			break; +		if (i == intel_dp->lane_count) { +			++loop_tries; +			if (loop_tries == 5) { +				DRM_DEBUG_KMS("too many full retries, give up\n"); +				break; +			} +			memset(intel_dp->train_set, 0, 4); +			voltage_tries = 0; +			continue; +		}  		/* Check to see if we've tried the same voltage 5 times */  		if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { -			++tries; -			if (tries == 5) +			++voltage_tries; +			if (voltage_tries == 5) { +				DRM_DEBUG_KMS("too many voltage retries, give up\n");  				break; +			}  		} else -			tries = 0; +			voltage_tries = 0;  		voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;  		/* Compute new intel_dp->train_set as requested by target */ -		intel_get_adjust_train(intel_dp); +		intel_get_adjust_train(intel_dp, link_status);  	}  	intel_dp->DP = DP; @@ -1638,6 +1695,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)  	for (;;) {  		/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */  		uint32_t    signal_levels; +		uint8_t	    link_status[DP_LINK_STATUS_SIZE];  		if (cr_tries > 5) {  			DRM_ERROR("failed to train DP, aborting\n"); @@ -1645,11 +1703,11 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)  			break;  		} -		if (IS_GEN6(dev) && is_edp(intel_dp)) { +		if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {  			signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);  			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;  		} else { -			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count); +			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]);  			DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;  		} @@ -1665,17 +1723,17 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)  			break;  		udelay(400); -		if (!intel_dp_get_link_status(intel_dp)) +		if (!intel_dp_get_link_status(intel_dp, link_status))  			break;  		/* Make sure clock is still ok */ -		if (!intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { +		if (!intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {  			intel_dp_start_link_train(intel_dp);  			cr_tries++;  			continue;  		} -		if (intel_channel_eq_ok(intel_dp)) { +		if (intel_channel_eq_ok(intel_dp, link_status)) {  			channel_eq = true;  			break;  		} @@ -1690,7 +1748,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)  		}  		/* Compute new intel_dp->train_set as requested by target */ -		intel_get_adjust_train(intel_dp); +		intel_get_adjust_train(intel_dp, link_status);  		++tries;  	} @@ -1735,8 +1793,12 @@ intel_dp_link_down(struct intel_dp *intel_dp)  	msleep(17); -	if (is_edp(intel_dp)) -		DP |= DP_LINK_TRAIN_OFF; +	if (is_edp(intel_dp)) { +		if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) +			DP |= DP_LINK_TRAIN_OFF_CPT; +		else +			DP |= DP_LINK_TRAIN_OFF; +	}  	if (!HAS_PCH_CPT(dev) &&  	    I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) { @@ -1822,6 +1884,7 @@ static void  intel_dp_check_link_status(struct intel_dp *intel_dp)  {  	u8 sink_irq_vector; +	u8 link_status[DP_LINK_STATUS_SIZE];  	if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON)  		return; @@ -1830,7 +1893,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)  		return;  	/* Try to read receiver status if the link appears to be up */ -	if (!intel_dp_get_link_status(intel_dp)) { +	if (!intel_dp_get_link_status(intel_dp, link_status)) {  		intel_dp_link_down(intel_dp);  		return;  	} @@ -1855,7 +1918,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)  			DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");  	} -	if (!intel_channel_eq_ok(intel_dp)) { +	if (!intel_channel_eq_ok(intel_dp, link_status)) {  		DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",  			      drm_get_encoder_name(&intel_dp->base.base));  		intel_dp_start_link_train(intel_dp); @@ -2179,7 +2242,8 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc)  			continue;  		intel_dp = enc_to_intel_dp(encoder); -		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) +		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || +		    intel_dp->base.type == INTEL_OUTPUT_EDP)  			return intel_dp->output_reg;  	} @@ -2321,7 +2385,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)  		cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >>  			PANEL_LIGHT_ON_DELAY_SHIFT; -		 +  		cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >>  			PANEL_LIGHT_OFF_DELAY_SHIFT; @@ -2354,11 +2418,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)  		DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",  			      intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); -		intel_dp->panel_off_jiffies = jiffies - intel_dp->panel_power_down_delay; -  		ironlake_edp_panel_vdd_on(intel_dp);  		ret = intel_dp_get_dpcd(intel_dp);  		ironlake_edp_panel_vdd_off(intel_dp, false); +  		if (ret) {  			if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)  				dev_priv->no_aux_handshake = diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 499d4c0dbee..21f60b7d69a 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -326,7 +326,8 @@ static int intel_panel_update_status(struct backlight_device *bd)  static int intel_panel_get_brightness(struct backlight_device *bd)  {  	struct drm_device *dev = bl_get_data(bd); -	return intel_panel_get_backlight(dev); +	struct drm_i915_private *dev_priv = dev->dev_private; +	return dev_priv->backlight_level;  }  static const struct backlight_ops intel_panel_bl_ops = { diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 7fdfa8ea757..38e1bda73d3 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -480,21 +480,23 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)  		}  		break;  	case DB_Z_INFO: -		r = evergreen_cs_packet_next_reloc(p, &reloc); -		if (r) { -			dev_warn(p->dev, "bad SET_CONTEXT_REG " -					"0x%04X\n", reg); -			return -EINVAL; -		}  		track->db_z_info = radeon_get_ib_value(p, idx); -		ib[idx] &= ~Z_ARRAY_MODE(0xf); -		track->db_z_info &= ~Z_ARRAY_MODE(0xf); -		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { -			ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1); -			track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1); -		} else { -			ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1); -			track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1); +		if (!p->keep_tiling_flags) { +			r = evergreen_cs_packet_next_reloc(p, &reloc); +			if (r) { +				dev_warn(p->dev, "bad SET_CONTEXT_REG " +						"0x%04X\n", reg); +				return -EINVAL; +			} +			ib[idx] &= ~Z_ARRAY_MODE(0xf); +			track->db_z_info &= ~Z_ARRAY_MODE(0xf); +			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { +				ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1); +				track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1); +			} else { +				ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1); +				track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1); +			}  		}  		break;  	case DB_STENCIL_INFO: @@ -607,40 +609,44 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)  	case CB_COLOR5_INFO:  	case CB_COLOR6_INFO:  	case CB_COLOR7_INFO: -		r = evergreen_cs_packet_next_reloc(p, &reloc); -		if (r) { -			dev_warn(p->dev, "bad SET_CONTEXT_REG " -					"0x%04X\n", reg); -			return -EINVAL; -		}  		tmp = (reg - CB_COLOR0_INFO) / 0x3c;  		track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); -		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { -			ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); -			track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); -		} else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { -			ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); -			track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); +		if (!p->keep_tiling_flags) { +			r = evergreen_cs_packet_next_reloc(p, &reloc); +			if (r) { +				dev_warn(p->dev, "bad SET_CONTEXT_REG " +						"0x%04X\n", reg); +				return -EINVAL; +			} +			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { +				ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); +				track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); +			} else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { +				ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); +				track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); +			}  		}  		break;  	case CB_COLOR8_INFO:  	case CB_COLOR9_INFO:  	case CB_COLOR10_INFO:  	case CB_COLOR11_INFO: -		r = evergreen_cs_packet_next_reloc(p, &reloc); -		if (r) { -			dev_warn(p->dev, "bad SET_CONTEXT_REG " -					"0x%04X\n", reg); -			return -EINVAL; -		}  		tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;  		track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); -		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { -			ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); -			track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); -		} else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { -			ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); -			track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); +		if (!p->keep_tiling_flags) { +			r = evergreen_cs_packet_next_reloc(p, &reloc); +			if (r) { +				dev_warn(p->dev, "bad SET_CONTEXT_REG " +						"0x%04X\n", reg); +				return -EINVAL; +			} +			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { +				ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); +				track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); +			} else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { +				ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); +				track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); +			}  		}  		break;  	case CB_COLOR0_PITCH: @@ -1311,10 +1317,12 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,  					return -EINVAL;  				}  				ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); -				if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) -					ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1); -				else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) -					ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1); +				if (!p->keep_tiling_flags) { +					if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) +						ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1); +					else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) +						ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1); +				}  				texture = reloc->robj;  				/* tex mip base */  				r = evergreen_cs_packet_next_reloc(p, &reloc); diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 400b26df652..c93bc64707e 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -701,16 +701,21 @@ static int r300_packet0_check(struct radeon_cs_parser *p,  			return r;  		} -		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) -			tile_flags |= R300_TXO_MACRO_TILE; -		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) -			tile_flags |= R300_TXO_MICRO_TILE; -		else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) -			tile_flags |= R300_TXO_MICRO_TILE_SQUARE; +		if (p->keep_tiling_flags) { +			ib[idx] = (idx_value & 31) | /* keep the 1st 5 bits */ +				  ((idx_value & ~31) + (u32)reloc->lobj.gpu_offset); +		} else { +			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) +				tile_flags |= R300_TXO_MACRO_TILE; +			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) +				tile_flags |= R300_TXO_MICRO_TILE; +			else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) +				tile_flags |= R300_TXO_MICRO_TILE_SQUARE; -		tmp = idx_value + ((u32)reloc->lobj.gpu_offset); -		tmp |= tile_flags; -		ib[idx] = tmp; +			tmp = idx_value + ((u32)reloc->lobj.gpu_offset); +			tmp |= tile_flags; +			ib[idx] = tmp; +		}  		track->textures[i].robj = reloc->robj;  		track->tex_dirty = true;  		break; @@ -760,24 +765,26 @@ static int r300_packet0_check(struct radeon_cs_parser *p,  		/* RB3D_COLORPITCH1 */  		/* RB3D_COLORPITCH2 */  		/* RB3D_COLORPITCH3 */ -		r = r100_cs_packet_next_reloc(p, &reloc); -		if (r) { -			DRM_ERROR("No reloc for ib[%d]=0x%04X\n", -				  idx, reg); -			r100_cs_dump_packet(p, pkt); -			return r; -		} +		if (!p->keep_tiling_flags) { +			r = r100_cs_packet_next_reloc(p, &reloc); +			if (r) { +				DRM_ERROR("No reloc for ib[%d]=0x%04X\n", +					  idx, reg); +				r100_cs_dump_packet(p, pkt); +				return r; +			} -		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) -			tile_flags |= R300_COLOR_TILE_ENABLE; -		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) -			tile_flags |= R300_COLOR_MICROTILE_ENABLE; -		else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) -			tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE; +			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) +				tile_flags |= R300_COLOR_TILE_ENABLE; +			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) +				tile_flags |= R300_COLOR_MICROTILE_ENABLE; +			else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) +				tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE; -		tmp = idx_value & ~(0x7 << 16); -		tmp |= tile_flags; -		ib[idx] = tmp; +			tmp = idx_value & ~(0x7 << 16); +			tmp |= tile_flags; +			ib[idx] = tmp; +		}  		i = (reg - 0x4E38) >> 2;  		track->cb[i].pitch = idx_value & 0x3FFE;  		switch (((idx_value >> 21) & 0xF)) { @@ -843,25 +850,26 @@ static int r300_packet0_check(struct radeon_cs_parser *p,  		break;  	case 0x4F24:  		/* ZB_DEPTHPITCH */ -		r = r100_cs_packet_next_reloc(p, &reloc); -		if (r) { -			DRM_ERROR("No reloc for ib[%d]=0x%04X\n", -				  idx, reg); -			r100_cs_dump_packet(p, pkt); -			return r; -		} - -		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) -			tile_flags |= R300_DEPTHMACROTILE_ENABLE; -		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) -			tile_flags |= R300_DEPTHMICROTILE_TILED; -		else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) -			tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE; +		if (!p->keep_tiling_flags) { +			r = r100_cs_packet_next_reloc(p, &reloc); +			if (r) { +				DRM_ERROR("No reloc for ib[%d]=0x%04X\n", +					  idx, reg); +				r100_cs_dump_packet(p, pkt); +				return r; +			} -		tmp = idx_value & ~(0x7 << 16); -		tmp |= tile_flags; -		ib[idx] = tmp; +			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) +				tile_flags |= R300_DEPTHMACROTILE_ENABLE; +			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) +				tile_flags |= R300_DEPTHMICROTILE_TILED; +			else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE) +				tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE; +			tmp = idx_value & ~(0x7 << 16); +			tmp |= tile_flags; +			ib[idx] = tmp; +		}  		track->zb.pitch = idx_value & 0x3FFC;  		track->zb_dirty = true;  		break; diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 0a2e023c155..cb1acffd243 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -941,7 +941,8 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)  		track->db_depth_control = radeon_get_ib_value(p, idx);  		break;  	case R_028010_DB_DEPTH_INFO: -		if (r600_cs_packet_next_is_pkt3_nop(p)) { +		if (!p->keep_tiling_flags && +		    r600_cs_packet_next_is_pkt3_nop(p)) {  			r = r600_cs_packet_next_reloc(p, &reloc);  			if (r) {  				dev_warn(p->dev, "bad SET_CONTEXT_REG " @@ -992,7 +993,8 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)  	case R_0280B4_CB_COLOR5_INFO:  	case R_0280B8_CB_COLOR6_INFO:  	case R_0280BC_CB_COLOR7_INFO: -		if (r600_cs_packet_next_is_pkt3_nop(p)) { +		if (!p->keep_tiling_flags && +		     r600_cs_packet_next_is_pkt3_nop(p)) {  			r = r600_cs_packet_next_reloc(p, &reloc);  			if (r) {  				dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); @@ -1291,10 +1293,12 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,  	mip_offset <<= 8;  	word0 = radeon_get_ib_value(p, idx + 0); -	if (tiling_flags & RADEON_TILING_MACRO) -		word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); -	else if (tiling_flags & RADEON_TILING_MICRO) -		word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); +	if (!p->keep_tiling_flags) { +		if (tiling_flags & RADEON_TILING_MACRO) +			word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); +		else if (tiling_flags & RADEON_TILING_MICRO) +			word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); +	}  	word1 = radeon_get_ib_value(p, idx + 1);  	w0 = G_038000_TEX_WIDTH(word0) + 1;  	h0 = G_038004_TEX_HEIGHT(word1) + 1; @@ -1621,10 +1625,12 @@ static int r600_packet3_check(struct radeon_cs_parser *p,  					return -EINVAL;  				}  				base_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); -				if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) -					ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); -				else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) -					ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); +				if (!p->keep_tiling_flags) { +					if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) +						ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1); +					else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) +						ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1); +				}  				texture = reloc->robj;  				/* tex mip base */  				r = r600_cs_packet_next_reloc(p, &reloc); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index fc5a1d642cb..8227e76b5c7 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -611,7 +611,8 @@ struct radeon_cs_parser {  	struct radeon_ib	*ib;  	void			*track;  	unsigned		family; -	int parser_error; +	int			parser_error; +	bool			keep_tiling_flags;  };  extern int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx); diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index fecd705a1a5..d24baf30efc 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -62,6 +62,87 @@ union atom_supported_devices {  	struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;  }; +static void radeon_lookup_i2c_gpio_quirks(struct radeon_device *rdev, +					  ATOM_GPIO_I2C_ASSIGMENT *gpio, +					  u8 index) +{ +	/* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */ +	if ((rdev->family == CHIP_R420) || +	    (rdev->family == CHIP_R423) || +	    (rdev->family == CHIP_RV410)) { +		if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) || +		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) || +		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) { +			gpio->ucClkMaskShift = 0x19; +			gpio->ucDataMaskShift = 0x18; +		} +	} + +	/* some evergreen boards have bad data for this entry */ +	if (ASIC_IS_DCE4(rdev)) { +		if ((index == 7) && +		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) && +		    (gpio->sucI2cId.ucAccess == 0)) { +			gpio->sucI2cId.ucAccess = 0x97; +			gpio->ucDataMaskShift = 8; +			gpio->ucDataEnShift = 8; +			gpio->ucDataY_Shift = 8; +			gpio->ucDataA_Shift = 8; +		} +	} + +	/* some DCE3 boards have bad data for this entry */ +	if (ASIC_IS_DCE3(rdev)) { +		if ((index == 4) && +		    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) && +		    (gpio->sucI2cId.ucAccess == 0x94)) +			gpio->sucI2cId.ucAccess = 0x14; +	} +} + +static struct radeon_i2c_bus_rec radeon_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio) +{ +	struct radeon_i2c_bus_rec i2c; + +	memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); + +	i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; +	i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; +	i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; +	i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; +	i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; +	i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; +	i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; +	i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; +	i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); +	i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); +	i2c.en_clk_mask = (1 << gpio->ucClkEnShift); +	i2c.en_data_mask = (1 << gpio->ucDataEnShift); +	i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); +	i2c.y_data_mask = (1 << gpio->ucDataY_Shift); +	i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); +	i2c.a_data_mask = (1 << gpio->ucDataA_Shift); + +	if (gpio->sucI2cId.sbfAccess.bfHW_Capable) +		i2c.hw_capable = true; +	else +		i2c.hw_capable = false; + +	if (gpio->sucI2cId.ucAccess == 0xa0) +		i2c.mm_i2c = true; +	else +		i2c.mm_i2c = false; + +	i2c.i2c_id = gpio->sucI2cId.ucAccess; + +	if (i2c.mask_clk_reg) +		i2c.valid = true; +	else +		i2c.valid = false; + +	return i2c; +} +  static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,  							       uint8_t id)  { @@ -85,71 +166,10 @@ static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rd  		for (i = 0; i < num_indices; i++) {  			gpio = &i2c_info->asGPIO_Info[i]; -			/* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */ -			if ((rdev->family == CHIP_R420) || -			    (rdev->family == CHIP_R423) || -			    (rdev->family == CHIP_RV410)) { -				if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) || -				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) || -				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) { -					gpio->ucClkMaskShift = 0x19; -					gpio->ucDataMaskShift = 0x18; -				} -			} - -			/* some evergreen boards have bad data for this entry */ -			if (ASIC_IS_DCE4(rdev)) { -				if ((i == 7) && -				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) && -				    (gpio->sucI2cId.ucAccess == 0)) { -					gpio->sucI2cId.ucAccess = 0x97; -					gpio->ucDataMaskShift = 8; -					gpio->ucDataEnShift = 8; -					gpio->ucDataY_Shift = 8; -					gpio->ucDataA_Shift = 8; -				} -			} - -			/* some DCE3 boards have bad data for this entry */ -			if (ASIC_IS_DCE3(rdev)) { -				if ((i == 4) && -				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) && -				    (gpio->sucI2cId.ucAccess == 0x94)) -					gpio->sucI2cId.ucAccess = 0x14; -			} +			radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);  			if (gpio->sucI2cId.ucAccess == id) { -				i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; -				i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; -				i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; -				i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; -				i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; -				i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; -				i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; -				i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; -				i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); -				i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); -				i2c.en_clk_mask = (1 << gpio->ucClkEnShift); -				i2c.en_data_mask = (1 << gpio->ucDataEnShift); -				i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); -				i2c.y_data_mask = (1 << gpio->ucDataY_Shift); -				i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); -				i2c.a_data_mask = (1 << gpio->ucDataA_Shift); - -				if (gpio->sucI2cId.sbfAccess.bfHW_Capable) -					i2c.hw_capable = true; -				else -					i2c.hw_capable = false; - -				if (gpio->sucI2cId.ucAccess == 0xa0) -					i2c.mm_i2c = true; -				else -					i2c.mm_i2c = false; - -				i2c.i2c_id = gpio->sucI2cId.ucAccess; - -				if (i2c.mask_clk_reg) -					i2c.valid = true; +				i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);  				break;  			}  		} @@ -169,8 +189,6 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev)  	int i, num_indices;  	char stmp[32]; -	memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); -  	if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {  		i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset); @@ -179,60 +197,12 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev)  		for (i = 0; i < num_indices; i++) {  			gpio = &i2c_info->asGPIO_Info[i]; -			i2c.valid = false; - -			/* some evergreen boards have bad data for this entry */ -			if (ASIC_IS_DCE4(rdev)) { -				if ((i == 7) && -				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) && -				    (gpio->sucI2cId.ucAccess == 0)) { -					gpio->sucI2cId.ucAccess = 0x97; -					gpio->ucDataMaskShift = 8; -					gpio->ucDataEnShift = 8; -					gpio->ucDataY_Shift = 8; -					gpio->ucDataA_Shift = 8; -				} -			} -			/* some DCE3 boards have bad data for this entry */ -			if (ASIC_IS_DCE3(rdev)) { -				if ((i == 4) && -				    (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) && -				    (gpio->sucI2cId.ucAccess == 0x94)) -					gpio->sucI2cId.ucAccess = 0x14; -			} - -			i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; -			i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; -			i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; -			i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; -			i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; -			i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; -			i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; -			i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; -			i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); -			i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); -			i2c.en_clk_mask = (1 << gpio->ucClkEnShift); -			i2c.en_data_mask = (1 << gpio->ucDataEnShift); -			i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); -			i2c.y_data_mask = (1 << gpio->ucDataY_Shift); -			i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); -			i2c.a_data_mask = (1 << gpio->ucDataA_Shift); - -			if (gpio->sucI2cId.sbfAccess.bfHW_Capable) -				i2c.hw_capable = true; -			else -				i2c.hw_capable = false; - -			if (gpio->sucI2cId.ucAccess == 0xa0) -				i2c.mm_i2c = true; -			else -				i2c.mm_i2c = false; +			radeon_lookup_i2c_gpio_quirks(rdev, gpio, i); -			i2c.i2c_id = gpio->sucI2cId.ucAccess; +			i2c = radeon_get_bus_rec_for_i2c_gpio(gpio); -			if (i2c.mask_clk_reg) { -				i2c.valid = true; +			if (i2c.valid) {  				sprintf(stmp, "0x%x", i2c.i2c_id);  				rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp);  			} diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index ccaa243c144..29afd71e084 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -93,7 +93,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)  {  	struct drm_radeon_cs *cs = data;  	uint64_t *chunk_array_ptr; -	unsigned size, i; +	unsigned size, i, flags = 0;  	if (!cs->num_chunks) {  		return 0; @@ -140,6 +140,10 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)  			if (p->chunks[i].length_dw == 0)  				return -EINVAL;  		} +		if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS && +		    !p->chunks[i].length_dw) { +			return -EINVAL; +		}  		p->chunks[i].length_dw = user_chunk.length_dw;  		p->chunks[i].user_ptr = (void __user *)(unsigned long)user_chunk.chunk_data; @@ -155,6 +159,9 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)  					       p->chunks[i].user_ptr, size)) {  				return -EFAULT;  			} +			if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) { +				flags = p->chunks[i].kdata[0]; +			}  		} else {  			p->chunks[i].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);  			p->chunks[i].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL); @@ -174,6 +181,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)  			  p->chunks[p->chunk_ib_idx].length_dw);  		return -EINVAL;  	} + +	p->keep_tiling_flags = (flags & RADEON_CS_KEEP_TILING_FLAGS) != 0;  	return 0;  } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index a0b35e90948..71499fc3daf 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -53,9 +53,10 @@   *   2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query   *   2.10.0 - fusion 2D tiling   *   2.11.0 - backend map, initial compute support for the CS checker + *   2.12.0 - RADEON_CS_KEEP_TILING_FLAGS   */  #define KMS_DRIVER_MAJOR	2 -#define KMS_DRIVER_MINOR	11 +#define KMS_DRIVER_MINOR	12  #define KMS_DRIVER_PATCHLEVEL	0  int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);  int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 617b64678fc..0bb0f5f713e 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -574,10 +574,16 @@ retry:  		return ret;  	spin_lock(&glob->lru_lock); + +	if (unlikely(list_empty(&bo->ddestroy))) { +		spin_unlock(&glob->lru_lock); +		return 0; +	} +  	ret = ttm_bo_reserve_locked(bo, interruptible,  				    no_wait_reserve, false, 0); -	if (unlikely(ret != 0) || list_empty(&bo->ddestroy)) { +	if (unlikely(ret != 0)) {  		spin_unlock(&glob->lru_lock);  		return ret;  	} diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c index bdde899af72..111d956d8e7 100644 --- a/drivers/gpu/vga/vgaarb.c +++ b/drivers/gpu/vga/vgaarb.c @@ -991,14 +991,20 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,  				uc = &priv->cards[i];  		} -		if (!uc) -			return -EINVAL; +		if (!uc) { +			ret_val = -EINVAL; +			goto done; +		} -		if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0) -			return -EINVAL; +		if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0) { +			ret_val = -EINVAL; +			goto done; +		} -		if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0) -			return -EINVAL; +		if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0) { +			ret_val = -EINVAL; +			goto done; +		}  		vga_put(pdev, io_state); diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index 85584a547c2..525c7345fa0 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -488,7 +488,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)  	if (flags & I2C_M_TEN) {  		/* a ten bit address */ -		addr = 0xf0 | ((msg->addr >> 7) & 0x03); +		addr = 0xf0 | ((msg->addr >> 7) & 0x06);  		bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);  		/* try extended address code...*/  		ret = try_address(i2c_adap, addr, retries); @@ -498,7 +498,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)  			return -ENXIO;  		}  		/* the remaining 8 bit address */ -		ret = i2c_outb(i2c_adap, msg->addr & 0x7f); +		ret = i2c_outb(i2c_adap, msg->addr & 0xff);  		if ((ret != 1) && !nak_ok) {  			/* the chip did not ack / xmission error occurred */  			dev_err(&i2c_adap->dev, "died at 2nd address code\n"); diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 131079a3e29..1e5606185b4 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -539,8 +539,10 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)  	client->dev.type = &i2c_client_type;  	client->dev.of_node = info->of_node; +	/* For 10-bit clients, add an arbitrary offset to avoid collisions */  	dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), -		     client->addr); +		     client->addr | ((client->flags & I2C_CLIENT_TEN) +				     ? 0xa000 : 0));  	status = device_register(&client->dev);  	if (status)  		goto out_err; diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index c90ce50b619..57a45ce84b2 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -579,7 +579,7 @@ static int i2cdev_detach_adapter(struct device *dev, void *dummy)  	return 0;  } -int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action, +static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,  			 void *data)  {  	struct device *dev = data; diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 09b93b11a27..e2a9867c19d 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1210,18 +1210,28 @@ static int elantech_reconnect(struct psmouse *psmouse)   */  static int elantech_set_properties(struct elantech_data *etd)  { +	/* This represents the version of IC body. */  	int ver = (etd->fw_version & 0x0f0000) >> 16; +	/* Early version of Elan touchpads doesn't obey the rule. */  	if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600)  		etd->hw_version = 1; -	else if (etd->fw_version < 0x150600) -		etd->hw_version = 2; -	else if (ver == 5) -		etd->hw_version = 3; -	else if (ver == 6) -		etd->hw_version = 4; -	else -		return -1; +	else { +		switch (ver) { +		case 2: +		case 4: +			etd->hw_version = 2; +			break; +		case 5: +			etd->hw_version = 3; +			break; +		case 6: +			etd->hw_version = 4; +			break; +		default: +			return -1; +		} +	}  	/*  	 * Turn on packet checking by default. diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c index 4b2a42f9f0b..d4d08bd9205 100644 --- a/drivers/input/serio/ams_delta_serio.c +++ b/drivers/input/serio/ams_delta_serio.c @@ -24,6 +24,7 @@  #include <linux/irq.h>  #include <linux/serio.h>  #include <linux/slab.h> +#include <linux/module.h>  #include <asm/mach-types.h>  #include <plat/board-ams-delta.h> diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index bb9f5d31f0d..b4cfc6c8be8 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -431,6 +431,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {  			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),  		},  	}, +	{ +		/* Newer HP Pavilion dv4 models */ +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), +			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"), +		}, +	},  	{ }  }; @@ -560,6 +567,13 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {  			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),  		},  	}, +	{ +		/* Newer HP Pavilion dv4 models */ +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), +			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"), +		}, +	},  	{ }  }; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index d593878d66d..5664696f2d3 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -472,7 +472,7 @@ config BMP085  	  module will be called bmp085.  config PCH_PHUB -	tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB" +	tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB"  	depends on PCI  	help  	  This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of @@ -480,12 +480,13 @@ config PCH_PHUB  	  processor. The Topcliff has MAC address and Option ROM data in SROM.  	  This driver can access MAC address and Option ROM data in SROM. -	  This driver also can be used for OKI SEMICONDUCTOR IOH(Input/ -	  Output Hub), ML7213 and ML7223. -	  ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is -	  for MP(Media Phone) use. -	  ML7213/ML7223 is companion chip for Intel Atom E6xx series. -	  ML7213/ML7223 is completely compatible for Intel EG20T PCH. +	  This driver also can be used for LAPIS Semiconductor's IOH, +	  ML7213/ML7223/ML7831. +	  ML7213 which is for IVI(In-Vehicle Infotainment) use. +	  ML7223 IOH is for MP(Media Phone) use. +	  ML7831 IOH is for general purpose use. +	  ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series. +	  ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH.  	  To compile this driver as a module, choose M here: the module will  	  be called pch_phub. diff --git a/drivers/misc/ad525x_dpot.h b/drivers/misc/ad525x_dpot.h index a662f5987b6..82b2cb77ae1 100644 --- a/drivers/misc/ad525x_dpot.h +++ b/drivers/misc/ad525x_dpot.h @@ -100,7 +100,7 @@ enum dpot_devid {  	AD5293_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 27),  	AD7376_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,  			BRDAC0, 7, 28), -	AD8400_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT, +	AD8400_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,  			BRDAC0, 8, 29),  	AD8402_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,  			BRDAC0 | BRDAC1, 8, 30), diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index dee33addcae..10fc4785dba 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c @@ -1,5 +1,5 @@  /* - * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD. + * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by @@ -41,10 +41,10 @@  #define PCH_PHUB_ROM_START_ADDR_EG20T 0x80 /* ROM data area start address offset  					      (Intel EG20T PCH)*/  #define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address -						offset(OKI SEMICONDUCTOR ML7213) +						offset(LAPIS Semicon ML7213)  					      */  #define PCH_PHUB_ROM_START_ADDR_ML7223 0x400 /* ROM data area start address -						offset(OKI SEMICONDUCTOR ML7223) +						offset(LAPIS Semicon ML7223)  					      */  /* MAX number of INT_REDUCE_CONTROL registers */ @@ -73,6 +73,9 @@  #define PCI_DEVICE_ID_ROHM_ML7223_mPHUB	0x8012 /* for Bus-m */  #define PCI_DEVICE_ID_ROHM_ML7223_nPHUB	0x8002 /* for Bus-n */ +/* Macros for ML7831 */ +#define PCI_DEVICE_ID_ROHM_ML7831_PHUB 0x8801 +  /* SROM ACCESS Macro */  #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1)) @@ -115,6 +118,7 @@   * @pch_mac_start_address:		MAC address area start address   * @pch_opt_rom_start_address:		Option ROM start address   * @ioh_type:				Save IOH type + * @pdev:				pointer to pci device struct   */  struct pch_phub_reg {  	u32 phub_id_reg; @@ -136,6 +140,7 @@ struct pch_phub_reg {  	u32 pch_mac_start_address;  	u32 pch_opt_rom_start_address;  	int ioh_type; +	struct pci_dev *pdev;  };  /* SROM SPEC for MAC address assignment offset */ @@ -471,7 +476,7 @@ static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)  	int retval;  	int i; -	if (chip->ioh_type == 1) /* EG20T */ +	if ((chip->ioh_type == 1) || (chip->ioh_type == 5)) /* EG20T or ML7831*/  		retval = pch_phub_gbe_serial_rom_conf(chip);  	else	/* ML7223 */  		retval = pch_phub_gbe_serial_rom_conf_mp(chip); @@ -498,6 +503,7 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,  	unsigned int orom_size;  	int ret;  	int err; +	ssize_t rom_size;  	struct pch_phub_reg *chip =  		dev_get_drvdata(container_of(kobj, struct device, kobj)); @@ -509,6 +515,10 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,  	}  	/* Get Rom signature */ +	chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size); +	if (!chip->pch_phub_extrom_base_address) +		goto exrom_map_err; +  	pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address,  				(unsigned char *)&rom_signature);  	rom_signature &= 0xff; @@ -539,10 +549,13 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,  		goto return_err;  	}  return_ok: +	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);  	mutex_unlock(&pch_phub_mutex);  	return addr_offset;  return_err: +	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address); +exrom_map_err:  	mutex_unlock(&pch_phub_mutex);  return_err_nomutex:  	return err; @@ -555,6 +568,7 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,  	int err;  	unsigned int addr_offset;  	int ret; +	ssize_t rom_size;  	struct pch_phub_reg *chip =  		dev_get_drvdata(container_of(kobj, struct device, kobj)); @@ -571,6 +585,12 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,  		goto return_ok;  	} +	chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size); +	if (!chip->pch_phub_extrom_base_address) { +		err = -ENOMEM; +		goto exrom_map_err; +	} +  	for (addr_offset = 0; addr_offset < count; addr_offset++) {  		if (PCH_PHUB_OROM_SIZE < off + addr_offset)  			goto return_ok; @@ -585,10 +605,14 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,  	}  return_ok: +	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);  	mutex_unlock(&pch_phub_mutex);  	return addr_offset;  return_err: +	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address); + +exrom_map_err:  	mutex_unlock(&pch_phub_mutex);  	return err;  } @@ -598,8 +622,14 @@ static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr,  {  	u8 mac[8];  	struct pch_phub_reg *chip = dev_get_drvdata(dev); +	ssize_t rom_size; + +	chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size); +	if (!chip->pch_phub_extrom_base_address) +		return -ENOMEM;  	pch_phub_read_gbe_mac_addr(chip, mac); +	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);  	return sprintf(buf, "%pM\n", mac);  } @@ -608,6 +638,7 @@ static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,  			     const char *buf, size_t count)  {  	u8 mac[6]; +	ssize_t rom_size;  	struct pch_phub_reg *chip = dev_get_drvdata(dev);  	if (count != 18) @@ -617,7 +648,12 @@ static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,  		(u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3],  		(u32 *)&mac[4], (u32 *)&mac[5]); +	chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size); +	if (!chip->pch_phub_extrom_base_address) +		return -ENOMEM; +  	pch_phub_write_gbe_mac_addr(chip, mac); +	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);  	return count;  } @@ -640,7 +676,6 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,  	int retval;  	int ret; -	ssize_t rom_size;  	struct pch_phub_reg *chip;  	chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL); @@ -677,19 +712,7 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,  		"in pch_phub_base_address variable is %p\n", __func__,  		chip->pch_phub_base_address); -	if (id->driver_data != 3) { -		chip->pch_phub_extrom_base_address =\ -						   pci_map_rom(pdev, &rom_size); -		if (chip->pch_phub_extrom_base_address == 0) { -			dev_err(&pdev->dev, "%s: pci_map_rom FAILED", __func__); -			ret = -ENOMEM; -			goto err_pci_map; -		} -		dev_dbg(&pdev->dev, "%s : " -			"pci_map_rom SUCCESS and value in " -			"pch_phub_extrom_base_address variable is %p\n", -			__func__, chip->pch_phub_extrom_base_address); -	} +	chip->pdev = pdev; /* Save pci device struct */  	if (id->driver_data == 1) { /* EG20T PCH */  		const char *board_name; @@ -763,6 +786,22 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,  		chip->pch_opt_rom_start_address =\  						 PCH_PHUB_ROM_START_ADDR_ML7223;  		chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; +	} else if (id->driver_data == 5) { /* ML7831 */ +		retval = sysfs_create_file(&pdev->dev.kobj, +					   &dev_attr_pch_mac.attr); +		if (retval) +			goto err_sysfs_create; + +		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); +		if (retval) +			goto exit_bin_attr; + +		/* set the prefech value */ +		iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14); +		/* set the interrupt delay value */ +		iowrite32(0x25, chip->pch_phub_base_address + 0x44); +		chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T; +		chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T;  	}  	chip->ioh_type = id->driver_data; @@ -773,8 +812,6 @@ exit_bin_attr:  	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);  err_sysfs_create: -	pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address); -err_pci_map:  	pci_iounmap(pdev, chip->pch_phub_base_address);  err_pci_iomap:  	pci_release_regions(pdev); @@ -792,7 +829,6 @@ static void __devexit pch_phub_remove(struct pci_dev *pdev)  	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);  	sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr); -	pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);  	pci_iounmap(pdev, chip->pch_phub_base_address);  	pci_release_regions(pdev);  	pci_disable_device(pdev); @@ -847,6 +883,7 @@ static struct pci_device_id pch_phub_pcidev_id[] = {  	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2,  },  	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_mPHUB), 3,  },  	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_nPHUB), 4,  }, +	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7831_PHUB), 5,  },  	{ }  };  MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id); @@ -873,5 +910,5 @@ static void __exit pch_phub_pci_exit(void)  module_init(pch_phub_pci_init);  module_exit(pch_phub_pci_exit); -MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB"); +MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7223) PHUB");  MODULE_LICENSE("GPL"); diff --git a/drivers/misc/spear13xx_pcie_gadget.c b/drivers/misc/spear13xx_pcie_gadget.c index cfbddbef11d..43d073bc1d9 100644 --- a/drivers/misc/spear13xx_pcie_gadget.c +++ b/drivers/misc/spear13xx_pcie_gadget.c @@ -903,6 +903,6 @@ static void __exit spear_pcie_gadget_exit(void)  }  module_exit(spear_pcie_gadget_exit); -MODULE_ALIAS("pcie-gadget-spear"); +MODULE_ALIAS("platform:pcie-gadget-spear");  MODULE_AUTHOR("Pratyush Anand");  MODULE_LICENSE("GPL"); diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 6d3dd3988d0..791270b8bd1 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -60,27 +60,27 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);   */  struct device_node *of_irq_find_parent(struct device_node *child)  { -	struct device_node *p, *c = child; +	struct device_node *p;  	const __be32 *parp; -	if (!of_node_get(c)) +	if (!of_node_get(child))  		return NULL;  	do { -		parp = of_get_property(c, "interrupt-parent", NULL); +		parp = of_get_property(child, "interrupt-parent", NULL);  		if (parp == NULL) -			p = of_get_parent(c); +			p = of_get_parent(child);  		else {  			if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)  				p = of_node_get(of_irq_dflt_pic);  			else  				p = of_find_node_by_phandle(be32_to_cpup(parp));  		} -		of_node_put(c); -		c = p; +		of_node_put(child); +		child = p;  	} while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL); -	return (p == child) ? NULL : p; +	return p;  }  /** diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 66d2d60b436..b552aae55b4 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -664,10 +664,10 @@ static int tps65910_set_voltage_dcdc(struct regulator_dev *dev,  	switch (id) {  	case TPS65910_REG_VDD1: -		dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1; +		dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;  		if (dcdc_mult == 1)  			dcdc_mult--; -		vsel = (selector % VDD1_2_NUM_VOLTS) + 3; +		vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;  		tps65910_modify_bits(pmic, TPS65910_VDD1,  				(dcdc_mult << VDD1_VGAIN_SEL_SHIFT), @@ -675,10 +675,10 @@ static int tps65910_set_voltage_dcdc(struct regulator_dev *dev,  		tps65910_reg_write(pmic, TPS65910_VDD1_OP, vsel);  		break;  	case TPS65910_REG_VDD2: -		dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1; +		dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;  		if (dcdc_mult == 1)  			dcdc_mult--; -		vsel = (selector % VDD1_2_NUM_VOLTS) + 3; +		vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;  		tps65910_modify_bits(pmic, TPS65910_VDD2,  				(dcdc_mult << VDD2_VGAIN_SEL_SHIFT), @@ -756,9 +756,9 @@ static int tps65910_list_voltage_dcdc(struct regulator_dev *dev,  	switch (id) {  	case TPS65910_REG_VDD1:  	case TPS65910_REG_VDD2: -		mult = (selector / VDD1_2_NUM_VOLTS) + 1; +		mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;  		volt = VDD1_2_MIN_VOLT + -				(selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET; +				(selector % VDD1_2_NUM_VOLT_FINE) * VDD1_2_OFFSET;  		break;  	case TPS65911_REG_VDDCTRL:  		volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET); @@ -947,6 +947,8 @@ static __devinit int tps65910_probe(struct platform_device *pdev)  		if (i == TPS65910_REG_VDD1 || i == TPS65910_REG_VDD2) {  			pmic->desc[i].ops = &tps65910_ops_dcdc; +			pmic->desc[i].n_voltages = VDD1_2_NUM_VOLT_FINE * +							VDD1_2_NUM_VOLT_COARSE;  		} else if (i == TPS65910_REG_VDD3) {  			if (tps65910_chip_id(tps65910) == TPS65910)  				pmic->desc[i].ops = &tps65910_ops_vdd3; diff --git a/drivers/staging/et131x/Kconfig b/drivers/staging/et131x/Kconfig index 9e1864c6dfd..8190f2aaf53 100644 --- a/drivers/staging/et131x/Kconfig +++ b/drivers/staging/et131x/Kconfig @@ -1,6 +1,7 @@  config ET131X  	tristate "Agere ET-1310 Gigabit Ethernet support" -	depends on PCI +	depends on PCI && NET && NETDEVICES +	select PHYLIB  	default n  	---help---  	  This driver supports Agere ET-1310 ethernet adapters. diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index f5f44a02456..0c1c6ca8c37 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -4469,6 +4469,12 @@ static int et131x_resume(struct device *dev)  	return 0;  } +static SIMPLE_DEV_PM_OPS(et131x_pm_ops, et131x_suspend, et131x_resume); +#define ET131X_PM_OPS (&et131x_pm_ops) +#else +#define ET131X_PM_OPS NULL +#endif +  /* ISR functions */  /** @@ -5470,12 +5476,6 @@ err_out:  	return result;  } -static SIMPLE_DEV_PM_OPS(et131x_pm_ops, et131x_suspend, et131x_resume); -#define ET131X_PM_OPS (&et131x_pm_ops) -#else -#define ET131X_PM_OPS NULL -#endif -  static DEFINE_PCI_DEVICE_TABLE(et131x_pci_table) = {  	{ PCI_VDEVICE(ATT, ET131X_PCI_DEVICE_ID_GIG), 0UL},  	{ PCI_VDEVICE(ATT, ET131X_PCI_DEVICE_ID_FAST), 0UL}, diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 326e967d54e..26564094e33 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -242,6 +242,8 @@ static const struct file_operations iio_event_chrdev_fileops = {  static int iio_event_getfd(struct iio_dev *indio_dev)  { +	int fd; +  	if (indio_dev->event_interface == NULL)  		return -ENODEV; @@ -252,9 +254,15 @@ static int iio_event_getfd(struct iio_dev *indio_dev)  		return -EBUSY;  	}  	mutex_unlock(&indio_dev->event_interface->event_list_lock); -	return anon_inode_getfd("iio:event", +	fd = anon_inode_getfd("iio:event",  				&iio_event_chrdev_fileops,  				indio_dev->event_interface, O_RDONLY); +	if (fd < 0) { +		mutex_lock(&indio_dev->event_interface->event_list_lock); +		clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); +		mutex_unlock(&indio_dev->event_interface->event_list_lock); +	} +	return fd;  }  static int __init iio_init(void) diff --git a/drivers/staging/slicoss/Kconfig b/drivers/staging/slicoss/Kconfig index 5cde96b2e6e..5c2a15b42df 100644 --- a/drivers/staging/slicoss/Kconfig +++ b/drivers/staging/slicoss/Kconfig @@ -1,6 +1,6 @@  config SLICOSS  	tristate "Alacritech Gigabit IS-NIC support" -	depends on PCI && X86 +	depends on PCI && X86 && NET  	default n  	help  	  This driver supports Alacritech's IS-NIC gigabit ethernet cards. diff --git a/drivers/tty/hvc/hvc_dcc.c b/drivers/tty/hvc/hvc_dcc.c index 435f6facbc2..44fbebab507 100644 --- a/drivers/tty/hvc/hvc_dcc.c +++ b/drivers/tty/hvc/hvc_dcc.c @@ -46,6 +46,7 @@ static inline char __dcc_getchar(void)  	asm volatile("mrc p14, 0, %0, c0, c5, 0	@ read comms data reg"  		: "=r" (__c)); +	isb();  	return __c;  } @@ -55,6 +56,7 @@ static inline void __dcc_putchar(char c)  	asm volatile("mcr p14, 0, %0, c0, c5, 0	@ write a char"  		: /* no output register */  		: "r" (c)); +	isb();  }  static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 5f479dada6f..925a1e547a8 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1560,7 +1560,7 @@ config SERIAL_IFX6X60  	  Support for the IFX6x60 modem devices on Intel MID platforms.  config SERIAL_PCH_UART -	tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) UART" +	tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) UART"  	depends on PCI  	select SERIAL_CORE  	help @@ -1568,12 +1568,12 @@ config SERIAL_PCH_UART  	  which is an IOH(Input/Output Hub) for x86 embedded processor.  	  Enabling PCH_DMA, this PCH UART works as DMA mode. -	  This driver also can be used for OKI SEMICONDUCTOR IOH(Input/ -	  Output Hub), ML7213 and ML7223. -	  ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is -	  for MP(Media Phone) use. -	  ML7213/ML7223 is companion chip for Intel Atom E6xx series. -	  ML7213/ML7223 is completely compatible for Intel EG20T PCH. +	  This driver also can be used for LAPIS Semiconductor IOH(Input/ +	  Output Hub), ML7213, ML7223 and ML7831. +	  ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is +	  for MP(Media Phone) use and ML7831 IOH is for general purpose use. +	  ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series. +	  ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH.  config SERIAL_MSM_SMD  	bool "Enable tty device interface for some SMD ports" diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 4a0f86fa1e9..4c823f341d9 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -228,7 +228,7 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)  	if (rs485conf->flags & SER_RS485_ENABLED) {  		dev_dbg(port->dev, "Setting UART to RS485\n");  		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; -		if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND) +		if ((rs485conf->delay_rts_after_send) > 0)  			UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);  		mode |= ATMEL_US_USMODE_RS485;  	} else { @@ -304,7 +304,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)  	if (atmel_port->rs485.flags & SER_RS485_ENABLED) {  		dev_dbg(port->dev, "Setting UART to RS485\n"); -		if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND) +		if ((atmel_port->rs485.delay_rts_after_send) > 0)  			UART_PUT_TTGR(port,  					atmel_port->rs485.delay_rts_after_send);  		mode |= ATMEL_US_USMODE_RS485; @@ -1228,7 +1228,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,  	if (atmel_port->rs485.flags & SER_RS485_ENABLED) {  		dev_dbg(port->dev, "Setting UART to RS485\n"); -		if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND) +		if ((atmel_port->rs485.delay_rts_after_send) > 0)  			UART_PUT_TTGR(port,  					atmel_port->rs485.delay_rts_after_send);  		mode |= ATMEL_US_USMODE_RS485; @@ -1447,16 +1447,6 @@ static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port,  		rs485conf->delay_rts_after_send = rs485_delay[1];  		rs485conf->flags = 0; -		if (rs485conf->delay_rts_before_send == 0 && -		    rs485conf->delay_rts_after_send == 0) { -			rs485conf->flags |= SER_RS485_RTS_ON_SEND; -		} else { -			if (rs485conf->delay_rts_before_send) -				rs485conf->flags |= SER_RS485_RTS_BEFORE_SEND; -			if (rs485conf->delay_rts_after_send) -				rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; -		} -  		if (of_get_property(np, "rs485-rx-during-tx", NULL))  			rs485conf->flags |= SER_RS485_RX_DURING_TX; diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index b7435043f2f..1dfba7b779c 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -3234,9 +3234,8 @@ rs_write(struct tty_struct *tty,  		e100_disable_rx(info);  		e100_enable_rx_irq(info);  #endif -		if ((info->rs485.flags & SER_RS485_RTS_BEFORE_SEND) && -			(info->rs485.delay_rts_before_send > 0)) -				msleep(info->rs485.delay_rts_before_send); +		if (info->rs485.delay_rts_before_send > 0) +			msleep(info->rs485.delay_rts_before_send);  	}  #endif /* CONFIG_ETRAX_RS485 */ @@ -3693,10 +3692,6 @@ rs_ioctl(struct tty_struct *tty,  		rs485data.delay_rts_before_send = rs485ctrl.delay_rts_before_send;  		rs485data.flags = 0; -		if (rs485data.delay_rts_before_send != 0) -			rs485data.flags |= SER_RS485_RTS_BEFORE_SEND; -		else -			rs485data.flags &= ~(SER_RS485_RTS_BEFORE_SEND);  		if (rs485ctrl.enabled)  			rs485data.flags |= SER_RS485_ENABLED; @@ -4531,7 +4526,6 @@ static int __init rs_init(void)  		/* Set sane defaults */  		info->rs485.flags &= ~(SER_RS485_RTS_ON_SEND);  		info->rs485.flags |= SER_RS485_RTS_AFTER_SEND; -		info->rs485.flags &= ~(SER_RS485_RTS_BEFORE_SEND);  		info->rs485.delay_rts_before_send = 0;  		info->rs485.flags &= ~(SER_RS485_ENABLED);  #endif diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index 286c386d9c4..e272d3919c6 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c @@ -884,7 +884,6 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,  {  	struct uart_hsu_port *up =  			container_of(port, struct uart_hsu_port, port); -	struct tty_struct *tty = port->state->port.tty;  	unsigned char cval, fcr = 0;  	unsigned long flags;  	unsigned int baud, quot; @@ -907,8 +906,7 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,  	}  	/* CMSPAR isn't supported by this driver */ -	if (tty) -		tty->termios->c_cflag &= ~CMSPAR; +	termios->c_cflag &= ~CMSPAR;  	if (termios->c_cflag & CSTOPB)  		cval |= UART_LCR_STOP; diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 21febef926a..d6aba8c087e 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1,5 +1,5 @@  /* - *Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD. + *Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.   *   *This program is free software; you can redistribute it and/or modify   *it under the terms of the GNU General Public License as published by @@ -46,8 +46,8 @@ enum {  /* Set the max number of UART port   * Intel EG20T PCH: 4 port - * OKI SEMICONDUCTOR ML7213 IOH: 3 port - * OKI SEMICONDUCTOR ML7223 IOH: 2 port + * LAPIS Semiconductor ML7213 IOH: 3 port + * LAPIS Semiconductor ML7223 IOH: 2 port  */  #define PCH_UART_NR	4 @@ -258,6 +258,8 @@ enum pch_uart_num_t {  	pch_ml7213_uart2,  	pch_ml7223_uart0,  	pch_ml7223_uart1, +	pch_ml7831_uart0, +	pch_ml7831_uart1,  };  static struct pch_uart_driver_data drv_dat[] = { @@ -270,6 +272,8 @@ static struct pch_uart_driver_data drv_dat[] = {  	[pch_ml7213_uart2] = {PCH_UART_2LINE, 2},  	[pch_ml7223_uart0] = {PCH_UART_8LINE, 0},  	[pch_ml7223_uart1] = {PCH_UART_2LINE, 1}, +	[pch_ml7831_uart0] = {PCH_UART_8LINE, 0}, +	[pch_ml7831_uart1] = {PCH_UART_2LINE, 1},  };  static unsigned int default_baud = 9600; @@ -628,6 +632,7 @@ static void pch_request_dma(struct uart_port *port)  		dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Rx)\n",  			__func__);  		dma_release_channel(priv->chan_tx); +		priv->chan_tx = NULL;  		return;  	} @@ -1215,8 +1220,7 @@ static void pch_uart_shutdown(struct uart_port *port)  		dev_err(priv->port.dev,  			"pch_uart_hal_set_fifo Failed(ret=%d)\n", ret); -	if (priv->use_dma_flag) -		pch_free_dma(port); +	pch_free_dma(port);  	free_irq(priv->port.irq, priv);  } @@ -1280,6 +1284,7 @@ static void pch_uart_set_termios(struct uart_port *port,  	if (rtn)  		goto out; +	pch_uart_set_mctrl(&priv->port, priv->port.mctrl);  	/* Don't rewrite B0 */  	if (tty_termios_baud_rate(termios))  		tty_termios_encode_baud_rate(termios, baud, baud); @@ -1552,6 +1557,10 @@ static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = {  	 .driver_data = pch_ml7223_uart0},  	{PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800D),  	 .driver_data = pch_ml7223_uart1}, +	{PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8811), +	 .driver_data = pch_ml7831_uart0}, +	{PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8812), +	 .driver_data = pch_ml7831_uart1},  	{0,},  }; diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 512c49f98e8..8e0924f5544 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -36,6 +36,7 @@  #include <linux/kmod.h>  #include <linux/nsproxy.h> +#include <linux/ratelimit.h>  /*   *	This guards the refcounted line discipline lists. The lock @@ -547,15 +548,16 @@ static void tty_ldisc_flush_works(struct tty_struct *tty)  /**   *	tty_ldisc_wait_idle	-	wait for the ldisc to become idle   *	@tty: tty to wait for + *	@timeout: for how long to wait at most   *   *	Wait for the line discipline to become idle. The discipline must   *	have been halted for this to guarantee it remains idle.   */ -static int tty_ldisc_wait_idle(struct tty_struct *tty) +static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)  { -	int ret; +	long ret;  	ret = wait_event_timeout(tty_ldisc_idle, -			atomic_read(&tty->ldisc->users) == 1, 5 * HZ); +			atomic_read(&tty->ldisc->users) == 1, timeout);  	if (ret < 0)  		return ret;  	return ret > 0 ? 0 : -EBUSY; @@ -665,7 +667,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)  	tty_ldisc_flush_works(tty); -	retval = tty_ldisc_wait_idle(tty); +	retval = tty_ldisc_wait_idle(tty, 5 * HZ);  	tty_lock();  	mutex_lock(&tty->ldisc_mutex); @@ -762,8 +764,6 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)  	if (IS_ERR(ld))  		return -1; -	WARN_ON_ONCE(tty_ldisc_wait_idle(tty)); -  	tty_ldisc_close(tty, tty->ldisc);  	tty_ldisc_put(tty->ldisc);  	tty->ldisc = NULL; @@ -838,7 +838,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)  	tty_unlock();  	cancel_work_sync(&tty->buf.work);  	mutex_unlock(&tty->ldisc_mutex); - +retry:  	tty_lock();  	mutex_lock(&tty->ldisc_mutex); @@ -847,6 +847,22 @@ void tty_ldisc_hangup(struct tty_struct *tty)  	   it means auditing a lot of other paths so this is  	   a FIXME */  	if (tty->ldisc) {	/* Not yet closed */ +		if (atomic_read(&tty->ldisc->users) != 1) { +			char cur_n[TASK_COMM_LEN], tty_n[64]; +			long timeout = 3 * HZ; +			tty_unlock(); + +			while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { +				timeout = MAX_SCHEDULE_TIMEOUT; +				printk_ratelimited(KERN_WARNING +					"%s: waiting (%s) for %s took too long, but we keep waiting...\n", +					__func__, get_task_comm(cur_n, current), +					tty_name(tty, tty_n)); +			} +			mutex_unlock(&tty->ldisc_mutex); +			goto retry; +		} +  		if (reset == 0) {  			if (!tty_ldisc_reinit(tty, tty->termios->c_line)) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 6960715c506..e8c564a5334 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -539,7 +539,6 @@ static void acm_port_down(struct acm *acm)  {  	int i; -	mutex_lock(&open_mutex);  	if (acm->dev) {  		usb_autopm_get_interface(acm->control);  		acm_set_control(acm, acm->ctrlout = 0); @@ -551,14 +550,15 @@ static void acm_port_down(struct acm *acm)  		acm->control->needs_remote_wakeup = 0;  		usb_autopm_put_interface(acm->control);  	} -	mutex_unlock(&open_mutex);  }  static void acm_tty_hangup(struct tty_struct *tty)  {  	struct acm *acm = tty->driver_data;  	tty_port_hangup(&acm->port); +	mutex_lock(&open_mutex);  	acm_port_down(acm); +	mutex_unlock(&open_mutex);  }  static void acm_tty_close(struct tty_struct *tty, struct file *filp) @@ -569,8 +569,9 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)  	   shutdown */  	if (!acm)  		return; + +	mutex_lock(&open_mutex);  	if (tty_port_close_start(&acm->port, tty, filp) == 0) { -		mutex_lock(&open_mutex);  		if (!acm->dev) {  			tty_port_tty_set(&acm->port, NULL);  			acm_tty_unregister(acm); @@ -582,6 +583,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)  	acm_port_down(acm);  	tty_port_close_end(&acm->port, tty);  	tty_port_tty_set(&acm->port, NULL); +	mutex_unlock(&open_mutex);  }  static int acm_tty_write(struct tty_struct *tty, diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 96f05b29c9a..79781461eec 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -813,6 +813,12 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)  					USB_PORT_FEAT_C_PORT_LINK_STATE);  		} +		if ((portchange & USB_PORT_STAT_C_BH_RESET) && +				hub_is_superspeed(hub->hdev)) { +			need_debounce_delay = true; +			clear_port_feature(hub->hdev, port1, +					USB_PORT_FEAT_C_BH_PORT_RESET); +		}  		/* We can forget about a "removed" device when there's a  		 * physical disconnect or the connect status changes.  		 */ diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index d6a8d8269bf..ecf12e15a7e 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -50,15 +50,42 @@ static const struct usb_device_id usb_quirk_list[] = {  	/* Logitech Webcam B/C500 */  	{ USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME }, +	/* Logitech Webcam C600 */ +	{ USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME }, +  	/* Logitech Webcam Pro 9000 */  	{ USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, +	/* Logitech Webcam C905 */ +	{ USB_DEVICE(0x046d, 0x080a), .driver_info = USB_QUIRK_RESET_RESUME }, + +	/* Logitech Webcam C210 */ +	{ USB_DEVICE(0x046d, 0x0819), .driver_info = USB_QUIRK_RESET_RESUME }, + +	/* Logitech Webcam C260 */ +	{ USB_DEVICE(0x046d, 0x081a), .driver_info = USB_QUIRK_RESET_RESUME }, +  	/* Logitech Webcam C310 */  	{ USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME }, +	/* Logitech Webcam C910 */ +	{ USB_DEVICE(0x046d, 0x0821), .driver_info = USB_QUIRK_RESET_RESUME }, + +	/* Logitech Webcam C160 */ +	{ USB_DEVICE(0x046d, 0x0824), .driver_info = USB_QUIRK_RESET_RESUME }, +  	/* Logitech Webcam C270 */  	{ USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, +	/* Logitech Quickcam Pro 9000 */ +	{ USB_DEVICE(0x046d, 0x0990), .driver_info = USB_QUIRK_RESET_RESUME }, + +	/* Logitech Quickcam E3500 */ +	{ USB_DEVICE(0x046d, 0x09a4), .driver_info = USB_QUIRK_RESET_RESUME }, + +	/* Logitech Quickcam Vision Pro */ +	{ USB_DEVICE(0x046d, 0x09a6), .driver_info = USB_QUIRK_RESET_RESUME }, +  	/* Logitech Harmony 700-series */  	{ USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index fa824cfdd2e..25dbd8614e7 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1284,6 +1284,7 @@ static int __devinit dwc3_gadget_init_endpoints(struct dwc3 *dwc)  			int		ret;  			dep->endpoint.maxpacket = 1024; +			dep->endpoint.max_streams = 15;  			dep->endpoint.ops = &dwc3_gadget_ep_ops;  			list_add_tail(&dep->endpoint.ep_list,  					&dwc->gadget.ep_list); diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index b21cd376c11..23a447373c5 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -469,7 +469,7 @@ config USB_LANGWELL  	   gadget drivers to also be dynamically linked.  config USB_EG20T -	tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH UDC" +	tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"  	depends on PCI  	select USB_GADGET_DUALSPEED  	help @@ -485,10 +485,11 @@ config USB_EG20T  	  This driver dose not support interrupt transfer or isochronous  	  transfer modes. -	  This driver also can be used for OKI SEMICONDUCTOR's ML7213 which is +	  This driver also can be used for LAPIS Semiconductor's ML7213 which is  	  for IVI(In-Vehicle Infotainment) use. -	  ML7213 is companion chip for Intel Atom E6xx series. -	  ML7213 is completely compatible for Intel EG20T PCH. +	  ML7831 is for general purpose use. +	  ML7213/ML7831 is companion chip for Intel Atom E6xx series. +	  ML7213/ML7831 is completely compatible for Intel EG20T PCH.  config USB_CI13XXX_MSM  	tristate "MIPS USB CI13xxx for MSM" diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c index 4eedfe55715..1fc612914c5 100644 --- a/drivers/usb/gadget/ci13xxx_msm.c +++ b/drivers/usb/gadget/ci13xxx_msm.c @@ -122,3 +122,5 @@ static int __init ci13xxx_msm_init(void)  	return platform_driver_register(&ci13xxx_msm_driver);  }  module_init(ci13xxx_msm_init); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 83428f56253..9a0c3979ff4 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -71,6 +71,9 @@  /******************************************************************************   * DEFINE   *****************************************************************************/ + +#define DMA_ADDR_INVALID	(~(dma_addr_t)0) +  /* ctrl register bank access */  static DEFINE_SPINLOCK(udc_lock); @@ -1434,7 +1437,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)  		return -EALREADY;  	mReq->req.status = -EALREADY; -	if (length && !mReq->req.dma) { +	if (length && mReq->req.dma == DMA_ADDR_INVALID) {  		mReq->req.dma = \  			dma_map_single(mEp->device, mReq->req.buf,  				       length, mEp->dir ? DMA_TO_DEVICE : @@ -1453,7 +1456,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)  				dma_unmap_single(mEp->device, mReq->req.dma,  					length, mEp->dir ? DMA_TO_DEVICE :  					DMA_FROM_DEVICE); -				mReq->req.dma = 0; +				mReq->req.dma = DMA_ADDR_INVALID;  				mReq->map     = 0;  			}  			return -ENOMEM; @@ -1549,7 +1552,7 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)  	if (mReq->map) {  		dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,  				 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE); -		mReq->req.dma = 0; +		mReq->req.dma = DMA_ADDR_INVALID;  		mReq->map     = 0;  	} @@ -1610,7 +1613,6 @@ __acquires(mEp->lock)   * @gadget: gadget   *   * This function returns an error code - * Caller must hold lock   */  static int _gadget_stop_activity(struct usb_gadget *gadget)  { @@ -2189,6 +2191,7 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)  	mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);  	if (mReq != NULL) {  		INIT_LIST_HEAD(&mReq->queue); +		mReq->req.dma = DMA_ADDR_INVALID;  		mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,  					   &mReq->dma); @@ -2328,7 +2331,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)  	if (mReq->map) {  		dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,  				 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE); -		mReq->req.dma = 0; +		mReq->req.dma = DMA_ADDR_INVALID;  		mReq->map     = 0;  	}  	req->status = -ECONNRESET; @@ -2500,12 +2503,12 @@ static int ci13xxx_wakeup(struct usb_gadget *_gadget)  	spin_lock_irqsave(udc->lock, flags);  	if (!udc->remote_wakeup) {  		ret = -EOPNOTSUPP; -		dbg_trace("remote wakeup feature is not enabled\n"); +		trace("remote wakeup feature is not enabled\n");  		goto out;  	}  	if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {  		ret = -EINVAL; -		dbg_trace("port is not suspended\n"); +		trace("port is not suspended\n");  		goto out;  	}  	hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR); @@ -2703,7 +2706,9 @@ static int ci13xxx_stop(struct usb_gadget_driver *driver)  		if (udc->udc_driver->notify_event)  			udc->udc_driver->notify_event(udc,  			CI13XXX_CONTROLLER_STOPPED_EVENT); +		spin_unlock_irqrestore(udc->lock, flags);  		_gadget_stop_activity(&udc->gadget); +		spin_lock_irqsave(udc->lock, flags);  		pm_runtime_put(&udc->gadget.dev);  	} @@ -2850,7 +2855,7 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,  	struct ci13xxx *udc;  	int retval = 0; -	trace("%p, %p, %p", dev, regs, name); +	trace("%p, %p, %p", dev, regs, driver->name);  	if (dev == NULL || regs == NULL || driver == NULL ||  			driver->name == NULL) diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 52583a23533..c39d58860fa 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -624,7 +624,8 @@ static int fsg_setup(struct usb_function *f,  		if (ctrl->bRequestType !=  		    (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE))  			break; -		if (w_index != fsg->interface_number || w_value != 0) +		if (w_index != fsg->interface_number || w_value != 0 || +				w_length != 0)  			return -EDOM;  		/* @@ -639,7 +640,8 @@ static int fsg_setup(struct usb_function *f,  		if (ctrl->bRequestType !=  		    (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE))  			break; -		if (w_index != fsg->interface_number || w_value != 0) +		if (w_index != fsg->interface_number || w_value != 0 || +				w_length != 1)  			return -EDOM;  		VDBG(fsg, "get max LUN\n");  		*(u8 *)req->buf = fsg->common->nluns - 1; diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c index 67b222908cf..3797b3d6c62 100644 --- a/drivers/usb/gadget/f_midi.c +++ b/drivers/usb/gadget/f_midi.c @@ -95,7 +95,6 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req);  DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);  DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); -DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(16);  DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16);  /* B.3.1  Standard AC Interface Descriptor */ @@ -140,26 +139,6 @@ static struct usb_ms_header_descriptor ms_header_desc __initdata = {  	/* .wTotalLength =	DYNAMIC */  }; -/* B.4.3  Embedded MIDI IN Jack Descriptor */ -static struct usb_midi_in_jack_descriptor jack_in_emb_desc = { -	.bLength =	      USB_DT_MIDI_IN_SIZE, -	.bDescriptorType =      USB_DT_CS_INTERFACE, -	.bDescriptorSubtype =   USB_MS_MIDI_IN_JACK, -	.bJackType =	    USB_MS_EMBEDDED, -	/* .bJackID =		DYNAMIC */ -}; - -/* B.4.4  Embedded MIDI OUT Jack Descriptor */ -static struct usb_midi_out_jack_descriptor_16 jack_out_emb_desc = { -	/* .bLength =		DYNAMIC */ -	.bDescriptorType =	USB_DT_CS_INTERFACE, -	.bDescriptorSubtype =	USB_MS_MIDI_OUT_JACK, -	.bJackType =		USB_MS_EMBEDDED, -	/* .bJackID =		DYNAMIC */ -	/* .bNrInputPins =	DYNAMIC */ -	/* .pins =		DYNAMIC */ -}; -  /* B.5.1  Standard Bulk OUT Endpoint Descriptor */  static struct usb_endpoint_descriptor bulk_out_desc = {  	.bLength =		USB_DT_ENDPOINT_AUDIO_SIZE, @@ -758,9 +737,11 @@ fail:  static int __init  f_midi_bind(struct usb_configuration *c, struct usb_function *f)  { -	struct usb_descriptor_header *midi_function[(MAX_PORTS * 2) + 12]; +	struct usb_descriptor_header **midi_function;  	struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS]; +	struct usb_midi_in_jack_descriptor jack_in_emb_desc[MAX_PORTS];  	struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc[MAX_PORTS]; +	struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc[MAX_PORTS];  	struct usb_composite_dev *cdev = c->cdev;  	struct f_midi *midi = func_to_midi(f);  	int status, n, jack = 1, i = 0; @@ -798,6 +779,14 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)  		goto fail;  	midi->out_ep->driver_data = cdev;	/* claim */ +	/* allocate temporary function list */ +	midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(midi_function), +				GFP_KERNEL); +	if (!midi_function) { +		status = -ENOMEM; +		goto fail; +	} +  	/*  	 * construct the function's descriptor set. As the number of  	 * input and output MIDI ports is configurable, we have to do @@ -811,73 +800,74 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)  	/* calculate the header's wTotalLength */  	n = USB_DT_MS_HEADER_SIZE -		+ (1 + midi->in_ports) * USB_DT_MIDI_IN_SIZE -		+ (1 + midi->out_ports) * USB_DT_MIDI_OUT_SIZE(1); +		+ (midi->in_ports + midi->out_ports) * +			(USB_DT_MIDI_IN_SIZE + USB_DT_MIDI_OUT_SIZE(1));  	ms_header_desc.wTotalLength = cpu_to_le16(n);  	midi_function[i++] = (struct usb_descriptor_header *) &ms_header_desc; -	/* we have one embedded IN jack */ -	jack_in_emb_desc.bJackID = jack++; -	midi_function[i++] = (struct usb_descriptor_header *) &jack_in_emb_desc; - -	/* and a dynamic amount of external IN jacks */ +	/* configure the external IN jacks, each linked to an embedded OUT jack */  	for (n = 0; n < midi->in_ports; n++) { -		struct usb_midi_in_jack_descriptor *ext = &jack_in_ext_desc[n]; +		struct usb_midi_in_jack_descriptor *in_ext = &jack_in_ext_desc[n]; +		struct usb_midi_out_jack_descriptor_1 *out_emb = &jack_out_emb_desc[n]; -		ext->bLength =			USB_DT_MIDI_IN_SIZE; -		ext->bDescriptorType =		USB_DT_CS_INTERFACE; -		ext->bDescriptorSubtype =	USB_MS_MIDI_IN_JACK; -		ext->bJackType =		USB_MS_EXTERNAL; -		ext->bJackID =			jack++; -		ext->iJack =			0; +		in_ext->bLength			= USB_DT_MIDI_IN_SIZE; +		in_ext->bDescriptorType		= USB_DT_CS_INTERFACE; +		in_ext->bDescriptorSubtype	= USB_MS_MIDI_IN_JACK; +		in_ext->bJackType		= USB_MS_EXTERNAL; +		in_ext->bJackID			= jack++; +		in_ext->iJack			= 0; +		midi_function[i++] = (struct usb_descriptor_header *) in_ext; -		midi_function[i++] = (struct usb_descriptor_header *) ext; -	} +		out_emb->bLength		= USB_DT_MIDI_OUT_SIZE(1); +		out_emb->bDescriptorType	= USB_DT_CS_INTERFACE; +		out_emb->bDescriptorSubtype	= USB_MS_MIDI_OUT_JACK; +		out_emb->bJackType		= USB_MS_EMBEDDED; +		out_emb->bJackID		= jack++; +		out_emb->bNrInputPins		= 1; +		out_emb->pins[0].baSourcePin	= 1; +		out_emb->pins[0].baSourceID	= in_ext->bJackID; +		out_emb->iJack			= 0; +		midi_function[i++] = (struct usb_descriptor_header *) out_emb; -	/* one embedded OUT jack ... */ -	jack_out_emb_desc.bLength = USB_DT_MIDI_OUT_SIZE(midi->in_ports); -	jack_out_emb_desc.bJackID = jack++; -	jack_out_emb_desc.bNrInputPins = midi->in_ports; -	/* ... which referencess all external IN jacks */ -	for (n = 0; n < midi->in_ports; n++) { -		jack_out_emb_desc.pins[n].baSourceID = jack_in_ext_desc[n].bJackID; -		jack_out_emb_desc.pins[n].baSourcePin =	1; +		/* link it to the endpoint */ +		ms_in_desc.baAssocJackID[n] = out_emb->bJackID;  	} -	midi_function[i++] = (struct usb_descriptor_header *) &jack_out_emb_desc; - -	/* and multiple external OUT jacks ... */ +	/* configure the external OUT jacks, each linked to an embedded IN jack */  	for (n = 0; n < midi->out_ports; n++) { -		struct usb_midi_out_jack_descriptor_1 *ext = &jack_out_ext_desc[n]; -		int m; +		struct usb_midi_in_jack_descriptor *in_emb = &jack_in_emb_desc[n]; +		struct usb_midi_out_jack_descriptor_1 *out_ext = &jack_out_ext_desc[n]; -		ext->bLength =			USB_DT_MIDI_OUT_SIZE(1); -		ext->bDescriptorType =		USB_DT_CS_INTERFACE; -		ext->bDescriptorSubtype =	USB_MS_MIDI_OUT_JACK; -		ext->bJackType =		USB_MS_EXTERNAL; -		ext->bJackID =			jack++; -		ext->bNrInputPins =		1; -		ext->iJack =			0; -		/* ... which all reference the same embedded IN jack */ -		for (m = 0; m < midi->out_ports; m++) { -			ext->pins[m].baSourceID =	jack_in_emb_desc.bJackID; -			ext->pins[m].baSourcePin =	1; -		} +		in_emb->bLength			= USB_DT_MIDI_IN_SIZE; +		in_emb->bDescriptorType		= USB_DT_CS_INTERFACE; +		in_emb->bDescriptorSubtype	= USB_MS_MIDI_IN_JACK; +		in_emb->bJackType		= USB_MS_EMBEDDED; +		in_emb->bJackID			= jack++; +		in_emb->iJack			= 0; +		midi_function[i++] = (struct usb_descriptor_header *) in_emb; -		midi_function[i++] = (struct usb_descriptor_header *) ext; +		out_ext->bLength =		USB_DT_MIDI_OUT_SIZE(1); +		out_ext->bDescriptorType =	USB_DT_CS_INTERFACE; +		out_ext->bDescriptorSubtype =	USB_MS_MIDI_OUT_JACK; +		out_ext->bJackType =		USB_MS_EXTERNAL; +		out_ext->bJackID =		jack++; +		out_ext->bNrInputPins =		1; +		out_ext->iJack =		0; +		out_ext->pins[0].baSourceID =	in_emb->bJackID; +		out_ext->pins[0].baSourcePin =	1; +		midi_function[i++] = (struct usb_descriptor_header *) out_ext; + +		/* link it to the endpoint */ +		ms_out_desc.baAssocJackID[n] = in_emb->bJackID;  	}  	/* configure the endpoint descriptors ... */  	ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports);  	ms_out_desc.bNumEmbMIDIJack = midi->in_ports; -	for (n = 0; n < midi->in_ports; n++) -		ms_out_desc.baAssocJackID[n] = jack_in_emb_desc.bJackID;  	ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports);  	ms_in_desc.bNumEmbMIDIJack = midi->out_ports; -	for (n = 0; n < midi->out_ports; n++) -		ms_in_desc.baAssocJackID[n] = jack_out_emb_desc.bJackID;  	/* ... and add them to the list */  	midi_function[i++] = (struct usb_descriptor_header *) &bulk_out_desc; @@ -901,6 +891,8 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)  		f->descriptors = usb_copy_descriptors(midi_function);  	} +	kfree(midi_function); +  	return 0;  fail: diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index f7e39b0365c..11b5196284a 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -859,7 +859,7 @@ static int class_setup_req(struct fsg_dev *fsg,  			if (ctrl->bRequestType != (USB_DIR_OUT |  					USB_TYPE_CLASS | USB_RECIP_INTERFACE))  				break; -			if (w_index != 0 || w_value != 0) { +			if (w_index != 0 || w_value != 0 || w_length != 0) {  				value = -EDOM;  				break;  			} @@ -875,7 +875,7 @@ static int class_setup_req(struct fsg_dev *fsg,  			if (ctrl->bRequestType != (USB_DIR_IN |  					USB_TYPE_CLASS | USB_RECIP_INTERFACE))  				break; -			if (w_index != 0 || w_value != 0) { +			if (w_index != 0 || w_value != 0 || w_length != 1) {  				value = -EDOM;  				break;  			} diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index d786ba31fc0..b3b3d83b7c3 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -2480,8 +2480,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)  #ifndef CONFIG_ARCH_MXC  	if (pdata->have_sysif_regs) -		usb_sys_regs = (struct usb_sys_interface *) -				((u32)dr_regs + USB_DR_SYS_OFFSET); +		usb_sys_regs = (void *)dr_regs + USB_DR_SYS_OFFSET;  #endif  	/* Initialize USB clocks */ diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index a392ec0d2d5..6ccae2707e5 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1730,8 +1730,9 @@ static void  gadgetfs_disconnect (struct usb_gadget *gadget)  {  	struct dev_data		*dev = get_gadget_data (gadget); +	unsigned long		flags; -	spin_lock (&dev->lock); +	spin_lock_irqsave (&dev->lock, flags);  	if (dev->state == STATE_DEV_UNCONNECTED)  		goto exit;  	dev->state = STATE_DEV_UNCONNECTED; @@ -1740,7 +1741,7 @@ gadgetfs_disconnect (struct usb_gadget *gadget)  	next_event (dev, GADGETFS_DISCONNECT);  	ep0_readable (dev);  exit: -	spin_unlock (&dev->lock); +	spin_unlock_irqrestore (&dev->lock, flags);  }  static void diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 550d6dcdf10..5048a0c0764 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -1,5 +1,5 @@  /* - * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD. + * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by @@ -354,6 +354,7 @@ struct pch_udc_dev {  #define PCI_DEVICE_ID_INTEL_EG20T_UDC	0x8808  #define PCI_VENDOR_ID_ROHM		0x10DB  #define PCI_DEVICE_ID_ML7213_IOH_UDC	0x801D +#define PCI_DEVICE_ID_ML7831_IOH_UDC	0x8808  static const char	ep0_string[] = "ep0in";  static DEFINE_SPINLOCK(udc_stall_spinlock);	/* stall spin lock */ @@ -2970,6 +2971,11 @@ static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = {  		.class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,  		.class_mask = 0xffffffff,  	}, +	{ +		PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7831_IOH_UDC), +		.class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, +		.class_mask = 0xffffffff, +	},  	{ 0 },  }; @@ -2999,5 +3005,5 @@ static void __exit pch_udc_pci_exit(void)  module_exit(pch_udc_pci_exit);  MODULE_DESCRIPTION("Intel EG20T USB Device Controller"); -MODULE_AUTHOR("OKI SEMICONDUCTOR, <toshiharu-linux@dsn.okisemi.com>"); +MODULE_AUTHOR("LAPIS Semiconductor, <tomoya-linux@dsn.lapis-semi.com>");  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index 68a826a1b86..24f84b210ce 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -1718,6 +1718,8 @@ static void r8a66597_fifo_flush(struct usb_ep *_ep)  	if (list_empty(&ep->queue) && !ep->busy) {  		pipe_stop(ep->r8a66597, ep->pipenum);  		r8a66597_bclr(ep->r8a66597, BCLR, ep->fifoctr); +		r8a66597_write(ep->r8a66597, ACLRM, ep->pipectr); +		r8a66597_write(ep->r8a66597, 0, ep->pipectr);  	}  	spin_unlock_irqrestore(&ep->r8a66597->lock, flags);  } @@ -1742,7 +1744,6 @@ static int r8a66597_start(struct usb_gadget *gadget,  		struct usb_gadget_driver *driver)  {  	struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget); -	int retval;  	if (!driver  			|| driver->speed != USB_SPEED_HIGH @@ -1752,16 +1753,7 @@ static int r8a66597_start(struct usb_gadget *gadget,  		return -ENODEV;  	/* hook up the driver */ -	driver->driver.bus = NULL;  	r8a66597->driver = driver; -	r8a66597->gadget.dev.driver = &driver->driver; - -	retval = device_add(&r8a66597->gadget.dev); -	if (retval) { -		dev_err(r8a66597_to_dev(r8a66597), "device_add error (%d)\n", -			retval); -		goto error; -	}  	init_controller(r8a66597);  	r8a66597_bset(r8a66597, VBSE, INTENB0); @@ -1775,12 +1767,6 @@ static int r8a66597_start(struct usb_gadget *gadget,  	}  	return 0; - -error: -	r8a66597->driver = NULL; -	r8a66597->gadget.dev.driver = NULL; - -	return retval;  }  static int r8a66597_stop(struct usb_gadget *gadget, @@ -1794,7 +1780,6 @@ static int r8a66597_stop(struct usb_gadget *gadget,  	disable_controller(r8a66597);  	spin_unlock_irqrestore(&r8a66597->lock, flags); -	device_del(&r8a66597->gadget.dev);  	r8a66597->driver = NULL;  	return 0;  } @@ -1845,6 +1830,7 @@ static int __exit r8a66597_remove(struct platform_device *pdev)  		clk_put(r8a66597->clk);  	}  #endif +	device_unregister(&r8a66597->gadget.dev);  	kfree(r8a66597);  	return 0;  } @@ -1924,13 +1910,17 @@ static int __init r8a66597_probe(struct platform_device *pdev)  	r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;  	r8a66597->gadget.ops = &r8a66597_gadget_ops; -	device_initialize(&r8a66597->gadget.dev);  	dev_set_name(&r8a66597->gadget.dev, "gadget");  	r8a66597->gadget.is_dualspeed = 1;  	r8a66597->gadget.dev.parent = &pdev->dev;  	r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask;  	r8a66597->gadget.dev.release = pdev->dev.release;  	r8a66597->gadget.name = udc_name; +	ret = device_register(&r8a66597->gadget.dev); +	if (ret < 0) { +		dev_err(&pdev->dev, "device_register failed\n"); +		goto clean_up; +	}  	init_timer(&r8a66597->timer);  	r8a66597->timer.function = r8a66597_timer; @@ -1945,7 +1935,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)  			dev_err(&pdev->dev, "cannot get clock \"%s\"\n",  				clk_name);  			ret = PTR_ERR(r8a66597->clk); -			goto clean_up; +			goto clean_up_dev;  		}  		clk_enable(r8a66597->clk);  	} @@ -2014,7 +2004,9 @@ clean_up2:  		clk_disable(r8a66597->clk);  		clk_put(r8a66597->clk);  	} +clean_up_dev:  #endif +	device_unregister(&r8a66597->gadget.dev);  clean_up:  	if (r8a66597) {  		if (r8a66597->sudmac_reg) diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 022baeca7c9..6939e17f458 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -210,10 +210,10 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)  	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);  	if (udc_is_newstyle(udc)) { -		usb_gadget_disconnect(udc->gadget); +		udc->driver->disconnect(udc->gadget);  		udc->driver->unbind(udc->gadget);  		usb_gadget_udc_stop(udc->gadget, udc->driver); - +		usb_gadget_disconnect(udc->gadget);  	} else {  		usb_gadget_stop(udc->gadget, udc->driver);  	} @@ -344,7 +344,7 @@ EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver);  static ssize_t usb_udc_srp_store(struct device *dev,  		struct device_attribute *attr, const char *buf, size_t n)  { -	struct usb_udc		*udc = dev_get_drvdata(dev); +	struct usb_udc		*udc = container_of(dev, struct usb_udc, dev);  	if (sysfs_streq(buf, "1"))  		usb_gadget_wakeup(udc->gadget); @@ -378,7 +378,7 @@ static ssize_t usb_udc_speed_show(struct device *dev,  	return snprintf(buf, PAGE_SIZE, "%s\n",  			usb_speed_string(udc->gadget->speed));  } -static DEVICE_ATTR(speed, S_IRUSR, usb_udc_speed_show, NULL); +static DEVICE_ATTR(speed, S_IRUGO, usb_udc_speed_show, NULL);  #define USB_UDC_ATTR(name)					\  ssize_t usb_udc_##name##_show(struct device *dev,		\ @@ -389,7 +389,7 @@ ssize_t usb_udc_##name##_show(struct device *dev,		\  								\  	return snprintf(buf, PAGE_SIZE, "%d\n", gadget->name);	\  }								\ -static DEVICE_ATTR(name, S_IRUSR, usb_udc_##name##_show, NULL) +static DEVICE_ATTR(name, S_IRUGO, usb_udc_##name##_show, NULL)  static USB_UDC_ATTR(is_dualspeed);  static USB_UDC_ATTR(is_otg); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 2e829fae648..56a32033adb 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1479,10 +1479,15 @@ iso_stream_schedule (  		/* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */ -		/* find a uframe slot with enough bandwidth */ -		next = start + period; -		for (; start < next; start++) { - +		/* find a uframe slot with enough bandwidth. +		 * Early uframes are more precious because full-speed +		 * iso IN transfers can't use late uframes, +		 * and therefore they should be allocated last. +		 */ +		next = start; +		start += period; +		do { +			start--;  			/* check schedule: enough space? */  			if (stream->highspeed) {  				if (itd_slot_ok(ehci, mod, start, @@ -1495,7 +1500,7 @@ iso_stream_schedule (  						start, sched, period))  					break;  			} -		} +		} while (start > next);  		/* no room in the schedule */  		if (start == next) { diff --git a/drivers/usb/host/ehci-xls.c b/drivers/usb/host/ehci-xls.c index fe74bd67601..b4fb511d24b 100644 --- a/drivers/usb/host/ehci-xls.c +++ b/drivers/usb/host/ehci-xls.c @@ -19,7 +19,7 @@ static int ehci_xls_setup(struct usb_hcd *hcd)  	ehci->caps = hcd->regs;  	ehci->regs = hcd->regs + -		HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); +		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));  	dbg_hcs_params(ehci, "reset");  	dbg_hcc_params(ehci, "reset"); diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index ba3a46b78b7..95a9fec38e8 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -223,6 +223,9 @@ static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int  	if (port < 0 || port >= 2)  		return; +	if (pdata->vbus_pin[port] <= 0) +		return; +  	gpio_set_value(pdata->vbus_pin[port], !pdata->vbus_pin_inverted ^ enable);  } @@ -231,6 +234,9 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)  	if (port < 0 || port >= 2)  		return -EINVAL; +	if (pdata->vbus_pin[port] <= 0) +		return -EINVAL; +  	return gpio_get_value(pdata->vbus_pin[port]) ^ !pdata->vbus_pin_inverted;  } diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 34efd479e06..b2639191549 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -389,17 +389,14 @@ ohci_shutdown (struct usb_hcd *hcd)  	struct ohci_hcd *ohci;  	ohci = hcd_to_ohci (hcd); -	ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); -	ohci->hc_control = ohci_readl(ohci, &ohci->regs->control); +	ohci_writel(ohci, (u32) ~0, &ohci->regs->intrdisable); -	/* If the SHUTDOWN quirk is set, don't put the controller in RESET */ -	ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ? -			OHCI_CTRL_RWC | OHCI_CTRL_HCFS : -			OHCI_CTRL_RWC); -	ohci_writel(ohci, ohci->hc_control, &ohci->regs->control); +	/* Software reset, after which the controller goes into SUSPEND */ +	ohci_writel(ohci, OHCI_HCR, &ohci->regs->cmdstatus); +	ohci_readl(ohci, &ohci->regs->cmdstatus);	/* flush the writes */ +	udelay(10); -	/* flush the writes */ -	(void) ohci_readl (ohci, &ohci->regs->control); +	ohci_writel(ohci, ohci->fminterval, &ohci->regs->fminterval);  }  static int check_ed(struct ohci_hcd *ohci, struct ed *ed) diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index ad8166c681e..bc01b064585 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -175,28 +175,6 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)  	return 0;  } -/* nVidia controllers continue to drive Reset signalling on the bus - * even after system shutdown, wasting power.  This flag tells the - * shutdown routine to leave the controller OPERATIONAL instead of RESET. - */ -static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd) -{ -	struct pci_dev *pdev = to_pci_dev(hcd->self.controller); -	struct ohci_hcd	*ohci = hcd_to_ohci(hcd); - -	/* Evidently nVidia fixed their later hardware; this is a guess at -	 * the changeover point. -	 */ -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB		0x026d - -	if (pdev->device < PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB) { -		ohci->flags |= OHCI_QUIRK_SHUTDOWN; -		ohci_dbg(ohci, "enabled nVidia shutdown quirk\n"); -	} - -	return 0; -} -  static void sb800_prefetch(struct ohci_hcd *ohci, int on)  {  	struct pci_dev *pdev; @@ -260,10 +238,6 @@ static const struct pci_device_id ohci_pci_quirks[] = {  		PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),  		.driver_data = (unsigned long)ohci_quirk_amd700,  	}, -	{ -		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), -		.driver_data = (unsigned long) ohci_quirk_nvidia_shutdown, -	},  	/* FIXME for some of the early AMD 760 southbridges, OHCI  	 * won't work at all.  blacklist them. diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 35e5fd640ce..0795b934d00 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -403,7 +403,6 @@ struct ohci_hcd {  #define	OHCI_QUIRK_HUB_POWER	0x100			/* distrust firmware power/oc setup */  #define	OHCI_QUIRK_AMD_PLL	0x200			/* AMD PLL quirk*/  #define	OHCI_QUIRK_AMD_PREFETCH	0x400			/* pre-fetch for ISO transfer */ -#define	OHCI_QUIRK_SHUTDOWN	0x800			/* nVidia power bug */  	// there are also chip quirks/bugs in init logic  	struct work_struct	nec_work;	/* Worker for NEC quirk */ diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 27a3dec32fa..caf87428ca4 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -37,6 +37,7 @@  #define OHCI_INTRENABLE		0x10  #define OHCI_INTRDISABLE	0x14  #define OHCI_FMINTERVAL		0x34 +#define OHCI_HCFS		(3 << 6)	/* hc functional state */  #define OHCI_HCR		(1 << 0)	/* host controller reset */  #define OHCI_OCR		(1 << 3)	/* ownership change request */  #define OHCI_CTRL_RWC		(1 << 9)	/* remote wakeup connected */ @@ -466,6 +467,8 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)  {  	void __iomem *base;  	u32 control; +	u32 fminterval; +	int cnt;  	if (!mmio_resource_enabled(pdev, 0))  		return; @@ -498,41 +501,32 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)  	}  #endif -	/* reset controller, preserving RWC (and possibly IR) */ -	writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL); -	readl(base + OHCI_CONTROL); +	/* disable interrupts */ +	writel((u32) ~0, base + OHCI_INTRDISABLE); -	/* Some NVIDIA controllers stop working if kept in RESET for too long */ -	if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) { -		u32 fminterval; -		int cnt; +	/* Reset the USB bus, if the controller isn't already in RESET */ +	if (control & OHCI_HCFS) { +		/* Go into RESET, preserving RWC (and possibly IR) */ +		writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL); +		readl(base + OHCI_CONTROL); -		/* drive reset for at least 50 ms (7.1.7.5) */ +		/* drive bus reset for at least 50 ms (7.1.7.5) */  		msleep(50); +	} -		/* software reset of the controller, preserving HcFmInterval */ -		fminterval = readl(base + OHCI_FMINTERVAL); -		writel(OHCI_HCR, base + OHCI_CMDSTATUS); +	/* software reset of the controller, preserving HcFmInterval */ +	fminterval = readl(base + OHCI_FMINTERVAL); +	writel(OHCI_HCR, base + OHCI_CMDSTATUS); -		/* reset requires max 10 us delay */ -		for (cnt = 30; cnt > 0; --cnt) {	/* ... allow extra time */ -			if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0) -				break; -			udelay(1); -		} -		writel(fminterval, base + OHCI_FMINTERVAL); - -		/* Now we're in the SUSPEND state with all devices reset -		 * and wakeups and interrupts disabled -		 */ +	/* reset requires max 10 us delay */ +	for (cnt = 30; cnt > 0; --cnt) {	/* ... allow extra time */ +		if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0) +			break; +		udelay(1);  	} +	writel(fminterval, base + OHCI_FMINTERVAL); -	/* -	 * disable interrupts -	 */ -	writel(~(u32)0, base + OHCI_INTRDISABLE); -	writel(~(u32)0, base + OHCI_INTRSTATUS); - +	/* Now the controller is safely in SUSPEND and nothing can wake it up */  	iounmap(base);  } @@ -627,7 +621,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)  	void __iomem *base, *op_reg_base;  	u32	hcc_params, cap, val;  	u8	offset, cap_length; -	int	wait_time, delta, count = 256/4; +	int	wait_time, count = 256/4;  	if (!mmio_resource_enabled(pdev, 0))  		return; @@ -673,11 +667,10 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)  		writel(val, op_reg_base + EHCI_USBCMD);  		wait_time = 2000; -		delta = 100;  		do {  			writel(0x3f, op_reg_base + EHCI_USBSTS); -			udelay(delta); -			wait_time -= delta; +			udelay(100); +			wait_time -= 100;  			val = readl(op_reg_base + EHCI_USBSTS);  			if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) {  				break; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 42a22b8e692..0e4b25fa3bc 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -982,7 +982,6 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud  	struct xhci_virt_device *dev;  	struct xhci_ep_ctx	*ep0_ctx;  	struct xhci_slot_ctx    *slot_ctx; -	struct xhci_input_control_ctx *ctrl_ctx;  	u32			port_num;  	struct usb_device *top_dev; @@ -994,12 +993,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud  		return -EINVAL;  	}  	ep0_ctx = xhci_get_ep_ctx(xhci, dev->in_ctx, 0); -	ctrl_ctx = xhci_get_input_control_ctx(xhci, dev->in_ctx);  	slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx); -	/* 2) New slot context and endpoint 0 context are valid*/ -	ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); -  	/* 3) Only the control endpoint is valid - one endpoint context */  	slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | udev->route);  	switch (udev->speed) { diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 940321b3ec6..9f1d4b15d81 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -816,23 +816,24 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)  	struct xhci_ring *ring;  	struct xhci_td *cur_td;  	int ret, i, j; +	unsigned long flags;  	ep = (struct xhci_virt_ep *) arg;  	xhci = ep->xhci; -	spin_lock(&xhci->lock); +	spin_lock_irqsave(&xhci->lock, flags);  	ep->stop_cmds_pending--;  	if (xhci->xhc_state & XHCI_STATE_DYING) {  		xhci_dbg(xhci, "Stop EP timer ran, but another timer marked "  				"xHCI as DYING, exiting.\n"); -		spin_unlock(&xhci->lock); +		spin_unlock_irqrestore(&xhci->lock, flags);  		return;  	}  	if (!(ep->stop_cmds_pending == 0 && (ep->ep_state & EP_HALT_PENDING))) {  		xhci_dbg(xhci, "Stop EP timer ran, but no command pending, "  				"exiting.\n"); -		spin_unlock(&xhci->lock); +		spin_unlock_irqrestore(&xhci->lock, flags);  		return;  	} @@ -844,11 +845,11 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)  	xhci->xhc_state |= XHCI_STATE_DYING;  	/* Disable interrupts from the host controller and start halting it */  	xhci_quiesce(xhci); -	spin_unlock(&xhci->lock); +	spin_unlock_irqrestore(&xhci->lock, flags);  	ret = xhci_halt(xhci); -	spin_lock(&xhci->lock); +	spin_lock_irqsave(&xhci->lock, flags);  	if (ret < 0) {  		/* This is bad; the host is not responding to commands and it's  		 * not allowing itself to be halted.  At least interrupts are @@ -896,7 +897,7 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)  			}  		}  	} -	spin_unlock(&xhci->lock); +	spin_unlock_irqrestore(&xhci->lock, flags);  	xhci_dbg(xhci, "Calling usb_hc_died()\n");  	usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);  	xhci_dbg(xhci, "xHCI host controller is dead.\n"); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 1ff95a0df57..aa94c019579 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -799,7 +799,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)  	u32			command, temp = 0;  	struct usb_hcd		*hcd = xhci_to_hcd(xhci);  	struct usb_hcd		*secondary_hcd; -	int			retval; +	int			retval = 0;  	/* Wait a bit if either of the roothubs need to settle from the  	 * transition into bus suspend. @@ -809,6 +809,9 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)  				xhci->bus_state[1].next_statechange))  		msleep(100); +	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); +	set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); +  	spin_lock_irq(&xhci->lock);  	if (xhci->quirks & XHCI_RESET_ON_RESUME)  		hibernated = true; @@ -878,20 +881,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)  			return retval;  		xhci_dbg(xhci, "Start the primary HCD\n");  		retval = xhci_run(hcd->primary_hcd); -		if (retval) -			goto failed_restart; - -		xhci_dbg(xhci, "Start the secondary HCD\n"); -		retval = xhci_run(secondary_hcd);  		if (!retval) { -			set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); -			set_bit(HCD_FLAG_HW_ACCESSIBLE, -					&xhci->shared_hcd->flags); +			xhci_dbg(xhci, "Start the secondary HCD\n"); +			retval = xhci_run(secondary_hcd);  		} -failed_restart:  		hcd->state = HC_STATE_SUSPENDED;  		xhci->shared_hcd->state = HC_STATE_SUSPENDED; -		return retval; +		goto done;  	}  	/* step 4: set Run/Stop bit */ @@ -910,11 +906,14 @@ failed_restart:  	 * Running endpoints by ringing their doorbells  	 */ -	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); -	set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); -  	spin_unlock_irq(&xhci->lock); -	return 0; + + done: +	if (retval == 0) { +		usb_hcd_resume_root_hub(hcd); +		usb_hcd_resume_root_hub(xhci->shared_hcd); +	} +	return retval;  }  #endif	/* CONFIG_PM */ @@ -3504,6 +3503,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)  	/* Otherwise, update the control endpoint ring enqueue pointer. */  	else  		xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev); +	ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); +	ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); +	ctrl_ctx->drop_flags = 0; +  	xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);  	xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); @@ -3585,7 +3588,6 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)  	virt_dev->address = (le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK)  		+ 1;  	/* Zero the input context control for later use */ -	ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);  	ctrl_ctx->add_flags = 0;  	ctrl_ctx->drop_flags = 0; diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index fc34b8b1191..07a03460a59 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -11,6 +11,7 @@ config USB_MUSB_HDRC  	select TWL4030_USB if MACH_OMAP_3430SDP  	select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA  	select USB_OTG_UTILS +	select USB_GADGET_DUALSPEED  	tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'  	help  	  Say Y here if your system has a dual role high speed USB @@ -60,7 +61,7 @@ config USB_MUSB_BLACKFIN  config USB_MUSB_UX500  	tristate "U8500 and U5500" -	depends on (ARCH_U8500 && AB8500_USB) || (ARCH_U5500) +	depends on (ARCH_U8500 && AB8500_USB)  endchoice diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 08f1d0b662a..e233d2b7d33 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -27,6 +27,7 @@   */  #include <linux/init.h> +#include <linux/module.h>  #include <linux/clk.h>  #include <linux/io.h>  #include <linux/platform_device.h> diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 4da7492ddbd..2613bfdb09b 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -27,6 +27,7 @@   */  #include <linux/init.h> +#include <linux/module.h>  #include <linux/clk.h>  #include <linux/io.h>  #include <linux/platform_device.h> diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 20a28731c33..c1fa12ec7a9 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1477,8 +1477,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)  /*-------------------------------------------------------------------------*/  #if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \ -	defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500) || \ -	defined(CONFIG_ARCH_U5500) +	defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500)  static irqreturn_t generic_interrupt(int irq, void *__hci)  { diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index ae4a20acef6..d51043acfe1 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1999,10 +1999,6 @@ static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)  					nuke(&hw_ep->ep_out, -ESHUTDOWN);  			}  		} - -		spin_unlock(&musb->lock); -		driver->disconnect(&musb->g); -		spin_lock(&musb->lock);  	}  } diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index d2e2efaba65..08c679c0dde 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -405,7 +405,7 @@ int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev)  /*   *		platform functions   */ -static int __devinit usbhs_probe(struct platform_device *pdev) +static int usbhs_probe(struct platform_device *pdev)  {  	struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;  	struct renesas_usbhs_driver_callback *dfunc; diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 8da685e796d..ffdf5d15085 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -820,7 +820,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)  	if (len % 4) /* 32bit alignment */  		goto usbhsf_pio_prepare_push; -	if ((*(u32 *) pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ +	if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */  		goto usbhsf_pio_prepare_push;  	/* get enable DMA fifo */ @@ -897,7 +897,7 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)  	if (!fifo)  		goto usbhsf_pio_prepare_pop; -	if ((*(u32 *) pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ +	if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */  		goto usbhsf_pio_prepare_pop;  	ret = usbhsf_fifo_select(pipe, fifo, 0); diff --git a/drivers/usb/renesas_usbhs/mod.h b/drivers/usb/renesas_usbhs/mod.h index 8ae3733031c..6c6875533f0 100644 --- a/drivers/usb/renesas_usbhs/mod.h +++ b/drivers/usb/renesas_usbhs/mod.h @@ -143,8 +143,8 @@ void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod);   */  #if	defined(CONFIG_USB_RENESAS_USBHS_HCD) || \  	defined(CONFIG_USB_RENESAS_USBHS_HCD_MODULE) -extern int __devinit usbhs_mod_host_probe(struct usbhs_priv *priv); -extern int __devexit usbhs_mod_host_remove(struct usbhs_priv *priv); +extern int usbhs_mod_host_probe(struct usbhs_priv *priv); +extern int usbhs_mod_host_remove(struct usbhs_priv *priv);  #else  static inline int usbhs_mod_host_probe(struct usbhs_priv *priv)  { @@ -157,8 +157,8 @@ static inline void usbhs_mod_host_remove(struct usbhs_priv *priv)  #if	defined(CONFIG_USB_RENESAS_USBHS_UDC) || \  	defined(CONFIG_USB_RENESAS_USBHS_UDC_MODULE) -extern int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv); -extern void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv); +extern int usbhs_mod_gadget_probe(struct usbhs_priv *priv); +extern void usbhs_mod_gadget_remove(struct usbhs_priv *priv);  #else  static inline int usbhs_mod_gadget_probe(struct usbhs_priv *priv)  { diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 4cc7ee0babc..d9717e0bc1f 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -830,7 +830,7 @@ static int usbhsg_stop(struct usbhs_priv *priv)  	return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);  } -int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv) +int usbhs_mod_gadget_probe(struct usbhs_priv *priv)  {  	struct usbhsg_gpriv *gpriv;  	struct usbhsg_uep *uep; @@ -927,7 +927,7 @@ usbhs_mod_gadget_probe_err_gpriv:  	return ret;  } -void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv) +void usbhs_mod_gadget_remove(struct usbhs_priv *priv)  {  	struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 1a7208a50af..bade761a1e5 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -103,7 +103,7 @@ struct usbhsh_hpriv {  	u32	port_stat;	/* USB_PORT_STAT_xxx */ -	struct completion	*done; +	struct completion	setup_ack_done;  	/* see usbhsh_req_alloc/free */  	struct list_head	ureq_link_active; @@ -355,6 +355,7 @@ static void usbhsh_device_free(struct usbhsh_hpriv *hpriv,  struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,  					struct usbhsh_device *udev,  					struct usb_host_endpoint *ep, +					int dir_in_req,  					gfp_t mem_flags)  {  	struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); @@ -364,27 +365,38 @@ struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,  	struct usbhs_pipe *pipe, *best_pipe;  	struct device *dev = usbhsh_hcd_to_dev(hcd);  	struct usb_endpoint_descriptor *desc = &ep->desc; -	int type, i; +	int type, i, dir_in;  	unsigned int min_usr; +	dir_in_req = !!dir_in_req; +  	uep = kzalloc(sizeof(struct usbhsh_ep), mem_flags);  	if (!uep) {  		dev_err(dev, "usbhsh_ep alloc fail\n");  		return NULL;  	} -	type = usb_endpoint_type(desc); + +	if (usb_endpoint_xfer_control(desc)) { +		best_pipe = usbhsh_hpriv_to_dcp(hpriv); +		goto usbhsh_endpoint_alloc_find_pipe; +	}  	/*  	 * find best pipe for endpoint  	 * see  	 *	HARDWARE LIMITATION  	 */ +	type = usb_endpoint_type(desc);  	min_usr = ~0;  	best_pipe = NULL; -	usbhs_for_each_pipe_with_dcp(pipe, priv, i) { +	usbhs_for_each_pipe(pipe, priv, i) {  		if (!usbhs_pipe_type_is(pipe, type))  			continue; +		dir_in = !!usbhs_pipe_is_dir_in(pipe); +		if (0 != (dir_in - dir_in_req)) +			continue; +  		info = usbhsh_pipe_info(pipe);  		if (min_usr > info->usr_cnt) { @@ -398,7 +410,7 @@ struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,  		kfree(uep);  		return NULL;  	} - +usbhsh_endpoint_alloc_find_pipe:  	/*  	 * init uep  	 */ @@ -423,6 +435,7 @@ struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,  	 * see  	 *  DCPMAXP/PIPEMAXP  	 */ +	usbhs_pipe_sequence_data0(uep->pipe);  	usbhs_pipe_config_update(uep->pipe,  				 usbhsh_device_number(hpriv, udev),  				 usb_endpoint_num(desc), @@ -430,7 +443,7 @@ struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,  	dev_dbg(dev, "%s [%d-%s](%p)\n", __func__,  		usbhsh_device_number(hpriv, udev), -		usbhs_pipe_name(pipe), uep); +		usbhs_pipe_name(uep->pipe), uep);  	return uep;  } @@ -549,8 +562,7 @@ static void usbhsh_setup_stage_packet_push(struct usbhsh_hpriv *hpriv,  	 *	usbhsh_irq_setup_ack()  	 *	usbhsh_irq_setup_err()  	 */ -	DECLARE_COMPLETION(done); -	hpriv->done = &done; +	init_completion(&hpriv->setup_ack_done);  	/* copy original request */  	memcpy(&req, urb->setup_packet, sizeof(struct usb_ctrlrequest)); @@ -572,8 +584,7 @@ static void usbhsh_setup_stage_packet_push(struct usbhsh_hpriv *hpriv,  	/*  	 * wait setup packet ACK  	 */ -	wait_for_completion(&done); -	hpriv->done = NULL; +	wait_for_completion(&hpriv->setup_ack_done);  	dev_dbg(dev, "%s done\n", __func__);  } @@ -724,11 +735,11 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,  	struct usbhsh_device *udev, *new_udev = NULL;  	struct usbhs_pipe *pipe;  	struct usbhsh_ep *uep; +	int is_dir_in = usb_pipein(urb->pipe);  	int ret; -	dev_dbg(dev, "%s (%s)\n", -		__func__, usb_pipein(urb->pipe) ? "in" : "out"); +	dev_dbg(dev, "%s (%s)\n", __func__, is_dir_in ? "in" : "out");  	ret = usb_hcd_link_urb_to_ep(hcd, urb);  	if (ret) @@ -751,7 +762,8 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,  	 */  	uep = usbhsh_ep_to_uep(ep);  	if (!uep) { -		uep = usbhsh_endpoint_alloc(hpriv, udev, ep, mem_flags); +		uep = usbhsh_endpoint_alloc(hpriv, udev, ep, +					    is_dir_in, mem_flags);  		if (!uep)  			goto usbhsh_urb_enqueue_error_free_device;  	} @@ -1095,10 +1107,7 @@ static int usbhsh_irq_setup_ack(struct usbhs_priv *priv,  	dev_dbg(dev, "setup packet OK\n"); -	if (unlikely(!hpriv->done)) -		dev_err(dev, "setup ack happen without necessary data\n"); -	else -		complete(hpriv->done); /* see usbhsh_urb_enqueue() */ +	complete(&hpriv->setup_ack_done); /* see usbhsh_urb_enqueue() */  	return 0;  } @@ -1111,10 +1120,7 @@ static int usbhsh_irq_setup_err(struct usbhs_priv *priv,  	dev_dbg(dev, "setup packet Err\n"); -	if (unlikely(!hpriv->done)) -		dev_err(dev, "setup err happen without necessary data\n"); -	else -		complete(hpriv->done); /* see usbhsh_urb_enqueue() */ +	complete(&hpriv->setup_ack_done); /* see usbhsh_urb_enqueue() */  	return 0;  } @@ -1221,8 +1227,18 @@ static int usbhsh_stop(struct usbhs_priv *priv)  {  	struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv);  	struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); +	struct usbhs_mod *mod = usbhs_mod_get_current(priv);  	struct device *dev = usbhs_priv_to_dev(priv); +	/* +	 * disable irq callback +	 */ +	mod->irq_attch	= NULL; +	mod->irq_dtch	= NULL; +	mod->irq_sack	= NULL; +	mod->irq_sign	= NULL; +	usbhs_irq_callback_update(priv, mod); +  	usb_remove_hcd(hcd);  	/* disable sys */ @@ -1235,7 +1251,7 @@ static int usbhsh_stop(struct usbhs_priv *priv)  	return 0;  } -int __devinit usbhs_mod_host_probe(struct usbhs_priv *priv) +int usbhs_mod_host_probe(struct usbhs_priv *priv)  {  	struct usbhsh_hpriv *hpriv;  	struct usb_hcd *hcd; @@ -1279,7 +1295,6 @@ int __devinit usbhs_mod_host_probe(struct usbhs_priv *priv)  	hpriv->mod.stop		= usbhsh_stop;  	hpriv->pipe_info	= pipe_info;  	hpriv->pipe_size	= pipe_size; -	hpriv->done		= NULL;  	usbhsh_req_list_init(hpriv);  	usbhsh_port_stat_init(hpriv); @@ -1299,7 +1314,7 @@ usbhs_mod_host_probe_err:  	return -ENOMEM;  } -int __devexit usbhs_mod_host_remove(struct usbhs_priv *priv) +int usbhs_mod_host_remove(struct usbhs_priv *priv)  {  	struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv);  	struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 5cdb9d91227..18e875b92e0 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -42,7 +42,7 @@ static int debug;   * Version information   */ -#define DRIVER_VERSION "v0.6" +#define DRIVER_VERSION "v0.7"  #define DRIVER_AUTHOR "Bart Hartgers <bart.hartgers+ark3116@gmail.com>"  #define DRIVER_DESC "USB ARK3116 serial/IrDA driver"  #define DRIVER_DEV_DESC "ARK3116 RS232/IrDA" @@ -380,10 +380,6 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)  		goto err_out;  	} -	/* setup termios */ -	if (tty) -		ark3116_set_termios(tty, port, NULL); -  	/* remove any data still left: also clears error state */  	ark3116_read_reg(serial, UART_RX, buf); @@ -406,6 +402,10 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)  	/* enable DMA */  	ark3116_write_reg(port->serial, UART_FCR, UART_FCR_DMA_SELECT); +	/* setup termios */ +	if (tty) +		ark3116_set_termios(tty, port, NULL); +  err_out:  	kfree(buf);  	return result; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 8fe034d2d3e..bd4298bb675 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2104,13 +2104,19 @@ static void ftdi_set_termios(struct tty_struct *tty,  	cflag = termios->c_cflag; -	/* FIXME -For this cut I don't care if the line is really changing or -	   not  - so just do the change regardless  - should be able to -	   compare old_termios and tty->termios */ +	if (old_termios->c_cflag == termios->c_cflag +	    && old_termios->c_ispeed == termios->c_ispeed +	    && old_termios->c_ospeed == termios->c_ospeed) +		goto no_c_cflag_changes; +  	/* NOTE These routines can get interrupted by  	   ftdi_sio_read_bulk_callback  - need to examine what this means -  	   don't see any problems yet */ +	if ((old_termios->c_cflag & (CSIZE|PARODD|PARENB|CMSPAR|CSTOPB)) == +	    (termios->c_cflag & (CSIZE|PARODD|PARENB|CMSPAR|CSTOPB))) +		goto no_data_parity_stop_changes; +  	/* Set number of data bits, parity, stop bits */  	urb_value = 0; @@ -2151,6 +2157,7 @@ static void ftdi_set_termios(struct tty_struct *tty,  	}  	/* Now do the baudrate */ +no_data_parity_stop_changes:  	if ((cflag & CBAUD) == B0) {  		/* Disable flow control */  		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), @@ -2178,6 +2185,7 @@ static void ftdi_set_termios(struct tty_struct *tty,  	/* Set flow control */  	/* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */ +no_c_cflag_changes:  	if (cflag & CRTSCTS) {  		dbg("%s Setting to CRTSCTS flow control", __func__);  		if (usb_control_msg(dev, diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 89ae1f65e1b..d865878c9f9 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -156,6 +156,7 @@ static void option_instat_callback(struct urb *urb);  #define HUAWEI_PRODUCT_K4511			0x14CC  #define HUAWEI_PRODUCT_ETS1220			0x1803  #define HUAWEI_PRODUCT_E353			0x1506 +#define HUAWEI_PRODUCT_E173S			0x1C05  #define QUANTA_VENDOR_ID			0x0408  #define QUANTA_PRODUCT_Q101			0xEA02 @@ -316,6 +317,9 @@ static void option_instat_callback(struct urb *urb);  #define ZTE_PRODUCT_AC8710			0xfff1  #define ZTE_PRODUCT_AC2726			0xfff5  #define ZTE_PRODUCT_AC8710T			0xffff +#define ZTE_PRODUCT_MC2718			0xffe8 +#define ZTE_PRODUCT_AD3812			0xffeb +#define ZTE_PRODUCT_MC2716			0xffed  #define BENQ_VENDOR_ID				0x04a5  #define BENQ_PRODUCT_H10			0x4068 @@ -468,6 +472,10 @@ static void option_instat_callback(struct urb *urb);  #define YUGA_PRODUCT_CLU528			0x260D  #define YUGA_PRODUCT_CLU526			0x260F +/* Viettel products */ +#define VIETTEL_VENDOR_ID			0x2262 +#define VIETTEL_PRODUCT_VT1000			0x0002 +  /* some devices interfaces need special handling due to a number of reasons */  enum option_blacklist_reason {  		OPTION_BLACKLIST_NONE = 0, @@ -500,6 +508,18 @@ static const struct option_blacklist_info zte_k3765_z_blacklist = {  	.reserved = BIT(4),  }; +static const struct option_blacklist_info zte_ad3812_z_blacklist = { +	.sendsetup = BIT(0) | BIT(1) | BIT(2), +}; + +static const struct option_blacklist_info zte_mc2718_z_blacklist = { +	.sendsetup = BIT(1) | BIT(2) | BIT(3) | BIT(4), +}; + +static const struct option_blacklist_info zte_mc2716_z_blacklist = { +	.sendsetup = BIT(1) | BIT(2) | BIT(3), +}; +  static const struct option_blacklist_info huawei_cdc12_blacklist = {  	.reserved = BIT(1) | BIT(2),  }; @@ -622,6 +642,7 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff),  		.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff), @@ -1043,6 +1064,12 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2718, 0xff, 0xff, 0xff), +	 .driver_info = (kernel_ulong_t)&zte_mc2718_z_blacklist }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AD3812, 0xff, 0xff, 0xff), +	 .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff), +	 .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },  	{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },  	{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },  	{ USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */ @@ -1141,6 +1168,7 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU516) },  	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) },  	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) },  	{ } /* Terminating entry */  };  MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 9083d1e616b..fc2d66f7f4e 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -91,7 +91,6 @@ static const struct usb_device_id id_table[] = {  	{ USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },  	{ USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },  	{ USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) }, -	{ USB_DEVICE(WINCHIPHEAD_VENDOR_ID, WINCHIPHEAD_USBSER_PRODUCT_ID) },  	{ USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) },  	{ }					/* Terminating entry */  }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 3d10d7f0207..c38b8c00c06 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -145,10 +145,6 @@  #define ADLINK_VENDOR_ID		0x0b63  #define ADLINK_ND6530_PRODUCT_ID	0x6530 -/* WinChipHead USB->RS 232 adapter */ -#define WINCHIPHEAD_VENDOR_ID		0x4348 -#define WINCHIPHEAD_USBSER_PRODUCT_ID	0x5523 -  /* SMART USB Serial Adapter */  #define SMART_VENDOR_ID	0x0b8c  #define SMART_PRODUCT_ID	0x2303 diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index 4dca3ef0668..9fbe742343c 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -1762,10 +1762,9 @@ static int ms_scsi_write(struct us_data *us, struct scsi_cmnd *srb)  		result = ene_send_scsi_cmd(us, FDIR_WRITE, scsi_sglist(srb), 1);  	} else {  		void *buf; -		int offset; +		int offset = 0;  		u16 PhyBlockAddr;  		u8 PageNum; -		u32 result;  		u16 len, oldphy, newphy;  		buf = kmalloc(blenByte, GFP_KERNEL); diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index 93c1a4d86f5..82dd834709c 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c @@ -59,7 +59,9 @@  void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)  { -	/* Pad the SCSI command with zeros out to 12 bytes +	/* +	 * Pad the SCSI command with zeros out to 12 bytes.  If the +	 * command already is 12 bytes or longer, leave it alone.  	 *  	 * NOTE: This only works because a scsi_cmnd struct field contains  	 * a unsigned char cmnd[16], so we know we have storage available @@ -67,9 +69,6 @@ void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)  	for (; srb->cmd_len<12; srb->cmd_len++)  		srb->cmnd[srb->cmd_len] = 0; -	/* set command length to 12 bytes */ -	srb->cmd_len = 12; -  	/* send the command to the transport layer */  	usb_stor_invoke_transport(srb, us);  } diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 6285867a935..79fd606b7cd 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -314,13 +314,6 @@ config NUC900_WATCHDOG  	  To compile this driver as a module, choose M here: the  	  module will be called nuc900_wdt. -config ADX_WATCHDOG -	tristate "Avionic Design Xanthos watchdog" -	depends on ARCH_PXA_ADX -	help -	  Say Y here if you want support for the watchdog timer on Avionic -	  Design Xanthos boards. -  config TS72XX_WATCHDOG  	tristate "TS-72XX SBC Watchdog"  	depends on MACH_TS72XX diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 55bd5740e91..fe893e91935 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -51,7 +51,6 @@ obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o  obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o  obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o  obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o -obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o  obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o  obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o diff --git a/drivers/watchdog/adx_wdt.c b/drivers/watchdog/adx_wdt.c deleted file mode 100644 index af6e6b16475..00000000000 --- a/drivers/watchdog/adx_wdt.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (C) 2008-2009 Avionic Design GmbH - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/fs.h> -#include <linux/gfp.h> -#include <linux/io.h> -#include <linux/miscdevice.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/types.h> -#include <linux/uaccess.h> -#include <linux/watchdog.h> - -#define WATCHDOG_NAME "adx-wdt" - -/* register offsets */ -#define	ADX_WDT_CONTROL		0x00 -#define	ADX_WDT_CONTROL_ENABLE	(1 << 0) -#define	ADX_WDT_CONTROL_nRESET	(1 << 1) -#define	ADX_WDT_TIMEOUT		0x08 - -static struct platform_device *adx_wdt_dev; -static unsigned long driver_open; - -#define	WDT_STATE_STOP	0 -#define	WDT_STATE_START	1 - -struct adx_wdt { -	void __iomem *base; -	unsigned long timeout; -	unsigned int state; -	unsigned int wake; -	spinlock_t lock; -}; - -static const struct watchdog_info adx_wdt_info = { -	.identity = "Avionic Design Xanthos Watchdog", -	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, -}; - -static void adx_wdt_start_locked(struct adx_wdt *wdt) -{ -	u32 ctrl; - -	ctrl = readl(wdt->base + ADX_WDT_CONTROL); -	ctrl |= ADX_WDT_CONTROL_ENABLE; -	writel(ctrl, wdt->base + ADX_WDT_CONTROL); -	wdt->state = WDT_STATE_START; -} - -static void adx_wdt_start(struct adx_wdt *wdt) -{ -	unsigned long flags; - -	spin_lock_irqsave(&wdt->lock, flags); -	adx_wdt_start_locked(wdt); -	spin_unlock_irqrestore(&wdt->lock, flags); -} - -static void adx_wdt_stop_locked(struct adx_wdt *wdt) -{ -	u32 ctrl; - -	ctrl = readl(wdt->base + ADX_WDT_CONTROL); -	ctrl &= ~ADX_WDT_CONTROL_ENABLE; -	writel(ctrl, wdt->base + ADX_WDT_CONTROL); -	wdt->state = WDT_STATE_STOP; -} - -static void adx_wdt_stop(struct adx_wdt *wdt) -{ -	unsigned long flags; - -	spin_lock_irqsave(&wdt->lock, flags); -	adx_wdt_stop_locked(wdt); -	spin_unlock_irqrestore(&wdt->lock, flags); -} - -static void adx_wdt_set_timeout(struct adx_wdt *wdt, unsigned long seconds) -{ -	unsigned long timeout = seconds * 1000; -	unsigned long flags; -	unsigned int state; - -	spin_lock_irqsave(&wdt->lock, flags); -	state = wdt->state; -	adx_wdt_stop_locked(wdt); -	writel(timeout, wdt->base + ADX_WDT_TIMEOUT); - -	if (state == WDT_STATE_START) -		adx_wdt_start_locked(wdt); - -	wdt->timeout = timeout; -	spin_unlock_irqrestore(&wdt->lock, flags); -} - -static void adx_wdt_get_timeout(struct adx_wdt *wdt, unsigned long *seconds) -{ -	*seconds = wdt->timeout / 1000; -} - -static void adx_wdt_keepalive(struct adx_wdt *wdt) -{ -	unsigned long flags; - -	spin_lock_irqsave(&wdt->lock, flags); -	writel(wdt->timeout, wdt->base + ADX_WDT_TIMEOUT); -	spin_unlock_irqrestore(&wdt->lock, flags); -} - -static int adx_wdt_open(struct inode *inode, struct file *file) -{ -	struct adx_wdt *wdt = platform_get_drvdata(adx_wdt_dev); - -	if (test_and_set_bit(0, &driver_open)) -		return -EBUSY; - -	file->private_data = wdt; -	adx_wdt_set_timeout(wdt, 30); -	adx_wdt_start(wdt); - -	return nonseekable_open(inode, file); -} - -static int adx_wdt_release(struct inode *inode, struct file *file) -{ -	struct adx_wdt *wdt = file->private_data; - -	adx_wdt_stop(wdt); -	clear_bit(0, &driver_open); - -	return 0; -} - -static long adx_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ -	struct adx_wdt *wdt = file->private_data; -	void __user *argp = (void __user *)arg; -	unsigned long __user *p = argp; -	unsigned long seconds = 0; -	unsigned int options; -	long ret = -EINVAL; - -	switch (cmd) { -	case WDIOC_GETSUPPORT: -		if (copy_to_user(argp, &adx_wdt_info, sizeof(adx_wdt_info))) -			return -EFAULT; -		else -			return 0; - -	case WDIOC_GETSTATUS: -	case WDIOC_GETBOOTSTATUS: -		return put_user(0, p); - -	case WDIOC_KEEPALIVE: -		adx_wdt_keepalive(wdt); -		return 0; - -	case WDIOC_SETTIMEOUT: -		if (get_user(seconds, p)) -			return -EFAULT; - -		adx_wdt_set_timeout(wdt, seconds); - -		/* fallthrough */ -	case WDIOC_GETTIMEOUT: -		adx_wdt_get_timeout(wdt, &seconds); -		return put_user(seconds, p); - -	case WDIOC_SETOPTIONS: -		if (copy_from_user(&options, argp, sizeof(options))) -			return -EFAULT; - -		if (options & WDIOS_DISABLECARD) { -			adx_wdt_stop(wdt); -			ret = 0; -		} - -		if (options & WDIOS_ENABLECARD) { -			adx_wdt_start(wdt); -			ret = 0; -		} - -		return ret; - -	default: -		break; -	} - -	return -ENOTTY; -} - -static ssize_t adx_wdt_write(struct file *file, const char __user *data, -		size_t len, loff_t *ppos) -{ -	struct adx_wdt *wdt = file->private_data; - -	if (len) -		adx_wdt_keepalive(wdt); - -	return len; -} - -static const struct file_operations adx_wdt_fops = { -	.owner = THIS_MODULE, -	.llseek = no_llseek, -	.open = adx_wdt_open, -	.release = adx_wdt_release, -	.unlocked_ioctl = adx_wdt_ioctl, -	.write = adx_wdt_write, -}; - -static struct miscdevice adx_wdt_miscdev = { -	.minor = WATCHDOG_MINOR, -	.name = "watchdog", -	.fops = &adx_wdt_fops, -}; - -static int __devinit adx_wdt_probe(struct platform_device *pdev) -{ -	struct resource *res; -	struct adx_wdt *wdt; -	int ret = 0; -	u32 ctrl; - -	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); -	if (!wdt) { -		dev_err(&pdev->dev, "cannot allocate WDT structure\n"); -		return -ENOMEM; -	} - -	spin_lock_init(&wdt->lock); - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(&pdev->dev, "cannot obtain I/O memory region\n"); -		return -ENXIO; -	} - -	res = devm_request_mem_region(&pdev->dev, res->start, -			resource_size(res), res->name); -	if (!res) { -		dev_err(&pdev->dev, "cannot request I/O memory region\n"); -		return -ENXIO; -	} - -	wdt->base = devm_ioremap_nocache(&pdev->dev, res->start, -			resource_size(res)); -	if (!wdt->base) { -		dev_err(&pdev->dev, "cannot remap I/O memory region\n"); -		return -ENXIO; -	} - -	/* disable watchdog and reboot on timeout */ -	ctrl = readl(wdt->base + ADX_WDT_CONTROL); -	ctrl &= ~ADX_WDT_CONTROL_ENABLE; -	ctrl &= ~ADX_WDT_CONTROL_nRESET; -	writel(ctrl, wdt->base + ADX_WDT_CONTROL); - -	platform_set_drvdata(pdev, wdt); -	adx_wdt_dev = pdev; - -	ret = misc_register(&adx_wdt_miscdev); -	if (ret) { -		dev_err(&pdev->dev, "cannot register miscdev on minor %d " -				"(err=%d)\n", WATCHDOG_MINOR, ret); -		return ret; -	} - -	return 0; -} - -static int __devexit adx_wdt_remove(struct platform_device *pdev) -{ -	struct adx_wdt *wdt = platform_get_drvdata(pdev); - -	misc_deregister(&adx_wdt_miscdev); -	adx_wdt_stop(wdt); -	platform_set_drvdata(pdev, NULL); - -	return 0; -} - -static void adx_wdt_shutdown(struct platform_device *pdev) -{ -	struct adx_wdt *wdt = platform_get_drvdata(pdev); -	adx_wdt_stop(wdt); -} - -#ifdef CONFIG_PM -static int adx_wdt_suspend(struct device *dev) -{ -	struct platform_device *pdev = to_platform_device(dev); -	struct adx_wdt *wdt = platform_get_drvdata(pdev); - -	wdt->wake = (wdt->state == WDT_STATE_START) ? 1 : 0; -	adx_wdt_stop(wdt); - -	return 0; -} - -static int adx_wdt_resume(struct device *dev) -{ -	struct platform_device *pdev = to_platform_device(dev); -	struct adx_wdt *wdt = platform_get_drvdata(pdev); - -	if (wdt->wake) -		adx_wdt_start(wdt); - -	return 0; -} - -static const struct dev_pm_ops adx_wdt_pm_ops = { -	.suspend = adx_wdt_suspend, -	.resume = adx_wdt_resume, -}; - -#  define ADX_WDT_PM_OPS	(&adx_wdt_pm_ops) -#else -#  define ADX_WDT_PM_OPS	NULL -#endif - -static struct platform_driver adx_wdt_driver = { -	.probe = adx_wdt_probe, -	.remove = __devexit_p(adx_wdt_remove), -	.shutdown = adx_wdt_shutdown, -	.driver = { -		.name = WATCHDOG_NAME, -		.owner = THIS_MODULE, -		.pm = ADX_WDT_PM_OPS, -	}, -}; - -static int __init adx_wdt_init(void) -{ -	return platform_driver_register(&adx_wdt_driver); -} - -static void __exit adx_wdt_exit(void) -{ -	platform_driver_unregister(&adx_wdt_driver); -} - -module_init(adx_wdt_init); -module_exit(adx_wdt_exit); - -MODULE_DESCRIPTION("Avionic Design Xanthos Watchdog Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 5de7e4fa5b8..a79e3840782 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -401,8 +401,8 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)  	dev_info(dev, "watchdog %sactive, reset %sabled, irq %sabled\n",  		 (wtcon & S3C2410_WTCON_ENABLE) ?  "" : "in", -		 (wtcon & S3C2410_WTCON_RSTEN) ? "" : "dis", -		 (wtcon & S3C2410_WTCON_INTEN) ? "" : "en"); +		 (wtcon & S3C2410_WTCON_RSTEN) ? "en" : "dis", +		 (wtcon & S3C2410_WTCON_INTEN) ? "en" : "dis");  	return 0; diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c index 7be38556aed..e789a47db41 100644 --- a/drivers/watchdog/wm831x_wdt.c +++ b/drivers/watchdog/wm831x_wdt.c @@ -150,7 +150,7 @@ static int wm831x_wdt_set_timeout(struct watchdog_device *wdt_dev,  		if (wm831x_wdt_cfgs[i].time == timeout)  			break;  	if (i == ARRAY_SIZE(wm831x_wdt_cfgs)) -		ret = -EINVAL; +		return -EINVAL;  	ret = wm831x_reg_unlock(wm831x);  	if (ret == 0) { diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 8855aad3929..22c64fff1bd 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -683,7 +683,7 @@ static int inode_to_path(u64 inum, struct btrfs_inode_ref *iref,  		return PTR_ERR(fspath);  	if (fspath > fspath_min) { -		ipath->fspath->val[i] = (u64)fspath; +		ipath->fspath->val[i] = (u64)(unsigned long)fspath;  		++ipath->fspath->elem_cnt;  		ipath->fspath->bytes_left = fspath - fspath_min;  	} else { diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 0fe615e4ea3..dede441bdee 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -514,10 +514,25 @@ static inline int should_cow_block(struct btrfs_trans_handle *trans,  				   struct btrfs_root *root,  				   struct extent_buffer *buf)  { +	/* ensure we can see the force_cow */ +	smp_rmb(); + +	/* +	 * We do not need to cow a block if +	 * 1) this block is not created or changed in this transaction; +	 * 2) this block does not belong to TREE_RELOC tree; +	 * 3) the root is not forced COW. +	 * +	 * What is forced COW: +	 *    when we create snapshot during commiting the transaction, +	 *    after we've finished coping src root, we must COW the shared +	 *    block to ensure the metadata consistency. +	 */  	if (btrfs_header_generation(buf) == trans->transid &&  	    !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN) &&  	    !(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID && -	      btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC))) +	      btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC)) && +	    !root->force_cow)  		return 0;  	return 1;  } diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index b9ba59ff929..04a5dfcee5a 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -848,7 +848,8 @@ struct btrfs_free_cluster {  enum btrfs_caching_type {  	BTRFS_CACHE_NO		= 0,  	BTRFS_CACHE_STARTED	= 1, -	BTRFS_CACHE_FINISHED	= 2, +	BTRFS_CACHE_FAST	= 2, +	BTRFS_CACHE_FINISHED	= 3,  };  enum btrfs_disk_cache_state { @@ -1271,6 +1272,8 @@ struct btrfs_root {  	 * for stat.  It may be used for more later  	 */  	dev_t anon_dev; + +	int force_cow;  };  struct btrfs_ioctl_defrag_range_args { diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 622654fe051..b0917590152 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -620,7 +620,7 @@ out:  static int btree_io_failed_hook(struct bio *failed_bio,  			 struct page *page, u64 start, u64 end, -			 u64 mirror_num, struct extent_state *state) +			 int mirror_num, struct extent_state *state)  {  	struct extent_io_tree *tree;  	unsigned long len; @@ -2569,22 +2569,10 @@ static int write_dev_supers(struct btrfs_device *device,  	int errors = 0;  	u32 crc;  	u64 bytenr; -	int last_barrier = 0;  	if (max_mirrors == 0)  		max_mirrors = BTRFS_SUPER_MIRROR_MAX; -	/* make sure only the last submit_bh does a barrier */ -	if (do_barriers) { -		for (i = 0; i < max_mirrors; i++) { -			bytenr = btrfs_sb_offset(i); -			if (bytenr + BTRFS_SUPER_INFO_SIZE >= -			    device->total_bytes) -				break; -			last_barrier = i; -		} -	} -  	for (i = 0; i < max_mirrors; i++) {  		bytenr = btrfs_sb_offset(i);  		if (bytenr + BTRFS_SUPER_INFO_SIZE >= device->total_bytes) @@ -2630,17 +2618,136 @@ static int write_dev_supers(struct btrfs_device *device,  			bh->b_end_io = btrfs_end_buffer_write_sync;  		} -		if (i == last_barrier && do_barriers) -			ret = submit_bh(WRITE_FLUSH_FUA, bh); -		else -			ret = submit_bh(WRITE_SYNC, bh); - +		/* +		 * we fua the first super.  The others we allow +		 * to go down lazy. +		 */ +		ret = submit_bh(WRITE_FUA, bh);  		if (ret)  			errors++;  	}  	return errors < i ? 0 : -1;  } +/* + * endio for the write_dev_flush, this will wake anyone waiting + * for the barrier when it is done + */ +static void btrfs_end_empty_barrier(struct bio *bio, int err) +{ +	if (err) { +		if (err == -EOPNOTSUPP) +			set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); +		clear_bit(BIO_UPTODATE, &bio->bi_flags); +	} +	if (bio->bi_private) +		complete(bio->bi_private); +	bio_put(bio); +} + +/* + * trigger flushes for one the devices.  If you pass wait == 0, the flushes are + * sent down.  With wait == 1, it waits for the previous flush. + * + * any device where the flush fails with eopnotsupp are flagged as not-barrier + * capable + */ +static int write_dev_flush(struct btrfs_device *device, int wait) +{ +	struct bio *bio; +	int ret = 0; + +	if (device->nobarriers) +		return 0; + +	if (wait) { +		bio = device->flush_bio; +		if (!bio) +			return 0; + +		wait_for_completion(&device->flush_wait); + +		if (bio_flagged(bio, BIO_EOPNOTSUPP)) { +			printk("btrfs: disabling barriers on dev %s\n", +			       device->name); +			device->nobarriers = 1; +		} +		if (!bio_flagged(bio, BIO_UPTODATE)) { +			ret = -EIO; +		} + +		/* drop the reference from the wait == 0 run */ +		bio_put(bio); +		device->flush_bio = NULL; + +		return ret; +	} + +	/* +	 * one reference for us, and we leave it for the +	 * caller +	 */ +	device->flush_bio = NULL;; +	bio = bio_alloc(GFP_NOFS, 0); +	if (!bio) +		return -ENOMEM; + +	bio->bi_end_io = btrfs_end_empty_barrier; +	bio->bi_bdev = device->bdev; +	init_completion(&device->flush_wait); +	bio->bi_private = &device->flush_wait; +	device->flush_bio = bio; + +	bio_get(bio); +	submit_bio(WRITE_FLUSH, bio); + +	return 0; +} + +/* + * send an empty flush down to each device in parallel, + * then wait for them + */ +static int barrier_all_devices(struct btrfs_fs_info *info) +{ +	struct list_head *head; +	struct btrfs_device *dev; +	int errors = 0; +	int ret; + +	/* send down all the barriers */ +	head = &info->fs_devices->devices; +	list_for_each_entry_rcu(dev, head, dev_list) { +		if (!dev->bdev) { +			errors++; +			continue; +		} +		if (!dev->in_fs_metadata || !dev->writeable) +			continue; + +		ret = write_dev_flush(dev, 0); +		if (ret) +			errors++; +	} + +	/* wait for all the barriers */ +	list_for_each_entry_rcu(dev, head, dev_list) { +		if (!dev->bdev) { +			errors++; +			continue; +		} +		if (!dev->in_fs_metadata || !dev->writeable) +			continue; + +		ret = write_dev_flush(dev, 1); +		if (ret) +			errors++; +	} +	if (errors) +		return -EIO; +	return 0; +} +  int write_all_supers(struct btrfs_root *root, int max_mirrors)  {  	struct list_head *head; @@ -2662,6 +2769,10 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors)  	mutex_lock(&root->fs_info->fs_devices->device_list_mutex);  	head = &root->fs_info->fs_devices->devices; + +	if (do_barriers) +		barrier_all_devices(root->fs_info); +  	list_for_each_entry_rcu(dev, head, dev_list) {  		if (!dev->bdev) {  			total_errors++; diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index b232150b5b6..930ae894973 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -467,13 +467,59 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,  			     struct btrfs_root *root,  			     int load_cache_only)  { +	DEFINE_WAIT(wait);  	struct btrfs_fs_info *fs_info = cache->fs_info;  	struct btrfs_caching_control *caching_ctl;  	int ret = 0; -	smp_mb(); -	if (cache->cached != BTRFS_CACHE_NO) +	caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS); +	BUG_ON(!caching_ctl); + +	INIT_LIST_HEAD(&caching_ctl->list); +	mutex_init(&caching_ctl->mutex); +	init_waitqueue_head(&caching_ctl->wait); +	caching_ctl->block_group = cache; +	caching_ctl->progress = cache->key.objectid; +	atomic_set(&caching_ctl->count, 1); +	caching_ctl->work.func = caching_thread; + +	spin_lock(&cache->lock); +	/* +	 * This should be a rare occasion, but this could happen I think in the +	 * case where one thread starts to load the space cache info, and then +	 * some other thread starts a transaction commit which tries to do an +	 * allocation while the other thread is still loading the space cache +	 * info.  The previous loop should have kept us from choosing this block +	 * group, but if we've moved to the state where we will wait on caching +	 * block groups we need to first check if we're doing a fast load here, +	 * so we can wait for it to finish, otherwise we could end up allocating +	 * from a block group who's cache gets evicted for one reason or +	 * another. +	 */ +	while (cache->cached == BTRFS_CACHE_FAST) { +		struct btrfs_caching_control *ctl; + +		ctl = cache->caching_ctl; +		atomic_inc(&ctl->count); +		prepare_to_wait(&ctl->wait, &wait, TASK_UNINTERRUPTIBLE); +		spin_unlock(&cache->lock); + +		schedule(); + +		finish_wait(&ctl->wait, &wait); +		put_caching_control(ctl); +		spin_lock(&cache->lock); +	} + +	if (cache->cached != BTRFS_CACHE_NO) { +		spin_unlock(&cache->lock); +		kfree(caching_ctl);  		return 0; +	} +	WARN_ON(cache->caching_ctl); +	cache->caching_ctl = caching_ctl; +	cache->cached = BTRFS_CACHE_FAST; +	spin_unlock(&cache->lock);  	/*  	 * We can't do the read from on-disk cache during a commit since we need @@ -484,56 +530,51 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,  	if (trans && (!trans->transaction->in_commit) &&  	    (root && root != root->fs_info->tree_root) &&  	    btrfs_test_opt(root, SPACE_CACHE)) { -		spin_lock(&cache->lock); -		if (cache->cached != BTRFS_CACHE_NO) { -			spin_unlock(&cache->lock); -			return 0; -		} -		cache->cached = BTRFS_CACHE_STARTED; -		spin_unlock(&cache->lock); -  		ret = load_free_space_cache(fs_info, cache);  		spin_lock(&cache->lock);  		if (ret == 1) { +			cache->caching_ctl = NULL;  			cache->cached = BTRFS_CACHE_FINISHED;  			cache->last_byte_to_unpin = (u64)-1;  		} else { -			cache->cached = BTRFS_CACHE_NO; +			if (load_cache_only) { +				cache->caching_ctl = NULL; +				cache->cached = BTRFS_CACHE_NO; +			} else { +				cache->cached = BTRFS_CACHE_STARTED; +			}  		}  		spin_unlock(&cache->lock); +		wake_up(&caching_ctl->wait);  		if (ret == 1) { +			put_caching_control(caching_ctl);  			free_excluded_extents(fs_info->extent_root, cache);  			return 0;  		} +	} else { +		/* +		 * We are not going to do the fast caching, set cached to the +		 * appropriate value and wakeup any waiters. +		 */ +		spin_lock(&cache->lock); +		if (load_cache_only) { +			cache->caching_ctl = NULL; +			cache->cached = BTRFS_CACHE_NO; +		} else { +			cache->cached = BTRFS_CACHE_STARTED; +		} +		spin_unlock(&cache->lock); +		wake_up(&caching_ctl->wait);  	} -	if (load_cache_only) -		return 0; - -	caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS); -	BUG_ON(!caching_ctl); - -	INIT_LIST_HEAD(&caching_ctl->list); -	mutex_init(&caching_ctl->mutex); -	init_waitqueue_head(&caching_ctl->wait); -	caching_ctl->block_group = cache; -	caching_ctl->progress = cache->key.objectid; -	/* one for caching kthread, one for caching block group list */ -	atomic_set(&caching_ctl->count, 2); -	caching_ctl->work.func = caching_thread; - -	spin_lock(&cache->lock); -	if (cache->cached != BTRFS_CACHE_NO) { -		spin_unlock(&cache->lock); -		kfree(caching_ctl); +	if (load_cache_only) { +		put_caching_control(caching_ctl);  		return 0;  	} -	cache->caching_ctl = caching_ctl; -	cache->cached = BTRFS_CACHE_STARTED; -	spin_unlock(&cache->lock);  	down_write(&fs_info->extent_commit_sem); +	atomic_inc(&caching_ctl->count);  	list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups);  	up_write(&fs_info->extent_commit_sem); @@ -5178,13 +5219,15 @@ search:  		}  have_block_group: -		if (unlikely(block_group->cached == BTRFS_CACHE_NO)) { +		cached = block_group_cache_done(block_group); +		if (unlikely(!cached)) {  			u64 free_percent; +			found_uncached_bg = true;  			ret = cache_block_group(block_group, trans,  						orig_root, 1);  			if (block_group->cached == BTRFS_CACHE_FINISHED) -				goto have_block_group; +				goto alloc;  			free_percent = btrfs_block_group_used(&block_group->item);  			free_percent *= 100; @@ -5206,7 +5249,6 @@ have_block_group:  							orig_root, 0);  				BUG_ON(ret);  			} -			found_uncached_bg = true;  			/*  			 * If loop is set for cached only, try the next block @@ -5216,10 +5258,7 @@ have_block_group:  				goto loop;  		} -		cached = block_group_cache_done(block_group); -		if (unlikely(!cached)) -			found_uncached_bg = true; - +alloc:  		if (unlikely(block_group->ro))  			goto loop; diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 1f87c4d0e7a..9472d3de5e5 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2285,8 +2285,8 @@ static void end_bio_extent_readpage(struct bio *bio, int err)  				clean_io_failure(start, page);  		}  		if (!uptodate) { -			u64 failed_mirror; -			failed_mirror = (u64)bio->bi_bdev; +			int failed_mirror; +			failed_mirror = (int)(unsigned long)bio->bi_bdev;  			if (tree->ops && tree->ops->readpage_io_failed_hook)  				ret = tree->ops->readpage_io_failed_hook(  						bio, page, start, end, @@ -3366,6 +3366,9 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,  		return -ENOMEM;  	path->leave_spinning = 1; +	start = ALIGN(start, BTRFS_I(inode)->root->sectorsize); +	len = ALIGN(len, BTRFS_I(inode)->root->sectorsize); +  	/*  	 * lookup the last file extent.  We're not using i_size here  	 * because there might be preallocation past i_size @@ -3413,7 +3416,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,  	lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len, 0,  			 &cached_state, GFP_NOFS); -	em = get_extent_skip_holes(inode, off, last_for_get_extent, +	em = get_extent_skip_holes(inode, start, last_for_get_extent,  				   get_extent);  	if (!em)  		goto out; diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index feb9be0e23b..7604c300132 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -70,7 +70,7 @@ struct extent_io_ops {  			      unsigned long bio_flags);  	int (*readpage_io_hook)(struct page *page, u64 start, u64 end);  	int (*readpage_io_failed_hook)(struct bio *bio, struct page *page, -				       u64 start, u64 end, u64 failed_mirror, +				       u64 start, u64 end, int failed_mirror,  				       struct extent_state *state);  	int (*writepage_io_failed_hook)(struct bio *bio, struct page *page,  					u64 start, u64 end, diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 181760f9d2a..6e5b7e46369 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -351,6 +351,11 @@ static int io_ctl_prepare_pages(struct io_ctl *io_ctl, struct inode *inode,  		}  	} +	for (i = 0; i < io_ctl->num_pages; i++) { +		clear_page_dirty_for_io(io_ctl->pages[i]); +		set_page_extent_mapped(io_ctl->pages[i]); +	} +  	return 0;  } @@ -1844,7 +1849,13 @@ again:  		info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset),  					  1, 0);  		if (!info) { -			WARN_ON(1); +			/* the tree logging code might be calling us before we +			 * have fully loaded the free space rbtree for this +			 * block group.  So it is possible the entry won't +			 * be in the rbtree yet at all.  The caching code +			 * will make sure not to put it in the rbtree if +			 * the logging code has pinned it. +			 */  			goto out_lock;  		}  	} @@ -2451,16 +2462,23 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,  {  	struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;  	struct btrfs_free_space *entry; -	struct rb_node *node;  	int ret = -ENOSPC; +	u64 bitmap_offset = offset_to_bitmap(ctl, offset);  	if (ctl->total_bitmaps == 0)  		return -ENOSPC;  	/* -	 * First check our cached list of bitmaps and see if there is an entry -	 * here that will work. +	 * The bitmap that covers offset won't be in the list unless offset +	 * is just its start offset.  	 */ +	entry = list_first_entry(bitmaps, struct btrfs_free_space, list); +	if (entry->offset != bitmap_offset) { +		entry = tree_search_offset(ctl, bitmap_offset, 1, 0); +		if (entry && list_empty(&entry->list)) +			list_add(&entry->list, bitmaps); +	} +  	list_for_each_entry(entry, bitmaps, list) {  		if (entry->bytes < min_bytes)  			continue; @@ -2471,38 +2489,10 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,  	}  	/* -	 * If we do have entries on our list and we are here then we didn't find -	 * anything, so go ahead and get the next entry after the last entry in -	 * this list and start the search from there. +	 * The bitmaps list has all the bitmaps that record free space +	 * starting after offset, so no more search is required.  	 */ -	if (!list_empty(bitmaps)) { -		entry = list_entry(bitmaps->prev, struct btrfs_free_space, -				   list); -		node = rb_next(&entry->offset_index); -		if (!node) -			return -ENOSPC; -		entry = rb_entry(node, struct btrfs_free_space, offset_index); -		goto search; -	} - -	entry = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 0, 1); -	if (!entry) -		return -ENOSPC; - -search: -	node = &entry->offset_index; -	do { -		entry = rb_entry(node, struct btrfs_free_space, offset_index); -		node = rb_next(&entry->offset_index); -		if (!entry->bitmap) -			continue; -		if (entry->bytes < min_bytes) -			continue; -		ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset, -					   bytes, min_bytes); -	} while (ret && node); - -	return ret; +	return -ENOSPC;  }  /* @@ -2520,8 +2510,8 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,  			     u64 offset, u64 bytes, u64 empty_size)  {  	struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; -	struct list_head bitmaps;  	struct btrfs_free_space *entry, *tmp; +	LIST_HEAD(bitmaps);  	u64 min_bytes;  	int ret; @@ -2560,7 +2550,6 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,  		goto out;  	} -	INIT_LIST_HEAD(&bitmaps);  	ret = setup_cluster_no_bitmap(block_group, cluster, &bitmaps, offset,  				      bytes, min_bytes);  	if (ret) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 116ab67a06d..526dd51a196 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6794,11 +6794,13 @@ static int btrfs_getattr(struct vfsmount *mnt,  			 struct dentry *dentry, struct kstat *stat)  {  	struct inode *inode = dentry->d_inode; +	u32 blocksize = inode->i_sb->s_blocksize; +  	generic_fillattr(inode, stat);  	stat->dev = BTRFS_I(inode)->root->anon_dev;  	stat->blksize = PAGE_CACHE_SIZE; -	stat->blocks = (inode_get_bytes(inode) + -			BTRFS_I(inode)->delalloc_bytes) >> 9; +	stat->blocks = (ALIGN(inode_get_bytes(inode), blocksize) + +		ALIGN(BTRFS_I(inode)->delalloc_bytes, blocksize)) >> 9;  	return 0;  } diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 4a34c472f12..a90e749ed6d 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1216,12 +1216,12 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,  		*devstr = '\0';  		devstr = vol_args->name;  		devid = simple_strtoull(devstr, &end, 10); -		printk(KERN_INFO "resizing devid %llu\n", +		printk(KERN_INFO "btrfs: resizing devid %llu\n",  		       (unsigned long long)devid);  	}  	device = btrfs_find_device(root, devid, NULL, NULL);  	if (!device) { -		printk(KERN_INFO "resizer unable to find device %llu\n", +		printk(KERN_INFO "btrfs: resizer unable to find device %llu\n",  		       (unsigned long long)devid);  		ret = -EINVAL;  		goto out_unlock; @@ -1267,7 +1267,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,  	do_div(new_size, root->sectorsize);  	new_size *= root->sectorsize; -	printk(KERN_INFO "new size for %s is %llu\n", +	printk(KERN_INFO "btrfs: new size for %s is %llu\n",  		device->name, (unsigned long long)new_size);  	if (new_size > old_size) { @@ -2930,11 +2930,13 @@ static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg)  		goto out;  	for (i = 0; i < ipath->fspath->elem_cnt; ++i) { -		rel_ptr = ipath->fspath->val[i] - (u64)ipath->fspath->val; +		rel_ptr = ipath->fspath->val[i] - +			  (u64)(unsigned long)ipath->fspath->val;  		ipath->fspath->val[i] = rel_ptr;  	} -	ret = copy_to_user((void *)ipa->fspath, (void *)ipath->fspath, size); +	ret = copy_to_user((void *)(unsigned long)ipa->fspath, +			   (void *)(unsigned long)ipath->fspath, size);  	if (ret) {  		ret = -EFAULT;  		goto out; @@ -3017,7 +3019,8 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,  	if (ret < 0)  		goto out; -	ret = copy_to_user((void *)loi->inodes, (void *)inodes, size); +	ret = copy_to_user((void *)(unsigned long)loi->inodes, +			   (void *)(unsigned long)inodes, size);  	if (ret)  		ret = -EFAULT; diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index f4190f22edf..fab420db512 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -272,7 +272,7 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 root, void *ctx)  			swarn->logical, swarn->dev->name,  			(unsigned long long)swarn->sector, root, inum, offset,  			min(isize - offset, (u64)PAGE_SIZE), nlink, -			(char *)ipath->fspath->val[i]); +			(char *)(unsigned long)ipath->fspath->val[i]);  	free_ipath(ipath);  	return 0; diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 6a0574e923b..81376d94cd3 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -785,6 +785,10 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans,  			btrfs_save_ino_cache(root, trans); +			/* see comments in should_cow_block() */ +			root->force_cow = 0; +			smp_wmb(); +  			if (root->commit_root != root->node) {  				mutex_lock(&root->fs_commit_mutex);  				switch_commit_root(root); @@ -947,6 +951,10 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,  	btrfs_tree_unlock(old);  	free_extent_buffer(old); +	/* see comments in should_cow_block() */ +	root->force_cow = 1; +	smp_wmb(); +  	btrfs_set_root_node(new_root_item, tmp);  	/* record when the snapshot was created in key.offset */  	key.offset = trans->transid; diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index ab5b1c49f35..78f2d4d4f37 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -100,6 +100,12 @@ struct btrfs_device {  	struct reada_zone *reada_curr_zone;  	struct radix_tree_root reada_zones;  	struct radix_tree_root reada_extents; + +	/* for sending down flush barriers */ +	struct bio *flush_bio; +	struct completion flush_wait; +	int nobarriers; +  };  struct btrfs_fs_devices { diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 2abd0dfad7f..bca3948e9db 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -1143,7 +1143,7 @@ static void ceph_d_prune(struct dentry *dentry)  {  	struct ceph_dentry_info *di; -	dout("d_release %p\n", dentry); +	dout("ceph_d_prune %p\n", dentry);  	/* do we have a valid parent? */  	if (!dentry->d_parent || IS_ROOT(dentry)) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index e392bfce84a..116f36502f1 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1328,12 +1328,13 @@ int ceph_inode_set_size(struct inode *inode, loff_t size)   */  void ceph_queue_writeback(struct inode *inode)  { +	ihold(inode);  	if (queue_work(ceph_inode_to_client(inode)->wb_wq,  		       &ceph_inode(inode)->i_wb_work)) {  		dout("ceph_queue_writeback %p\n", inode); -		ihold(inode);  	} else {  		dout("ceph_queue_writeback %p failed\n", inode); +		iput(inode);  	}  } @@ -1353,12 +1354,13 @@ static void ceph_writeback_work(struct work_struct *work)   */  void ceph_queue_invalidate(struct inode *inode)  { +	ihold(inode);  	if (queue_work(ceph_inode_to_client(inode)->pg_inv_wq,  		       &ceph_inode(inode)->i_pg_inv_work)) {  		dout("ceph_queue_invalidate %p\n", inode); -		ihold(inode);  	} else {  		dout("ceph_queue_invalidate %p failed\n", inode); +		iput(inode);  	}  } @@ -1434,13 +1436,14 @@ void ceph_queue_vmtruncate(struct inode *inode)  {  	struct ceph_inode_info *ci = ceph_inode(inode); +	ihold(inode);  	if (queue_work(ceph_sb_to_client(inode->i_sb)->trunc_wq,  		       &ci->i_vmtruncate_work)) {  		dout("ceph_queue_vmtruncate %p\n", inode); -		ihold(inode);  	} else {  		dout("ceph_queue_vmtruncate %p failed, pending=%d\n",  		     inode, ci->i_truncate_pending); +		iput(inode);  	}  } diff --git a/fs/ceph/super.c b/fs/ceph/super.c index a90846fac75..8dc73a594a9 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -638,10 +638,12 @@ static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,  	if (err == 0) {  		dout("open_root_inode success\n");  		if (ceph_ino(req->r_target_inode) == CEPH_INO_ROOT && -		    fsc->sb->s_root == NULL) +		    fsc->sb->s_root == NULL) {  			root = d_alloc_root(req->r_target_inode); -		else +			ceph_init_dentry(root); +		} else {  			root = d_obtain_alias(req->r_target_inode); +		}  		req->r_target_inode = NULL;  		dout("open_root_inode success, root dentry is %p\n", root);  	} else { diff --git a/fs/dcache.c b/fs/dcache.c index a901c6901bc..10ba92def3f 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -36,6 +36,7 @@  #include <linux/bit_spinlock.h>  #include <linux/rculist_bl.h>  #include <linux/prefetch.h> +#include <linux/ratelimit.h>  #include "internal.h"  /* @@ -2383,8 +2384,16 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)  				actual = __d_unalias(inode, dentry, alias);  			}  			write_sequnlock(&rename_lock); -			if (IS_ERR(actual)) +			if (IS_ERR(actual)) { +				if (PTR_ERR(actual) == -ELOOP) +					pr_warn_ratelimited( +						"VFS: Lookup of '%s' in %s %s" +						" would have caused loop\n", +						dentry->d_name.name, +						inode->i_sb->s_type->name, +						inode->i_sb->s_id);  				dput(alias); +			}  			goto out_nolock;  		}  	} diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index f6dba4505f1..12ccacda44e 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -565,7 +565,7 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb)  	brelse(bitmap_bh);  	printk(KERN_DEBUG "ext4_count_free_clusters: stored = %llu"  	       ", computed = %llu, %llu\n", -	       EXT4_B2C(sbi, ext4_free_blocks_count(es)), +	       EXT4_B2C(EXT4_SB(sb), ext4_free_blocks_count(es)),  	       desc_count, bitmap_count);  	return bitmap_count;  #else diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 240f6e2dc7e..fffec40d599 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2270,6 +2270,7 @@ retry:  			ext4_msg(inode->i_sb, KERN_CRIT, "%s: jbd2_start: "  			       "%ld pages, ino %lu; err %d", __func__,  				wbc->nr_to_write, inode->i_ino, ret); +			blk_finish_plug(&plug);  			goto out_writepages;  		} diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 877350ef025..1c7bbd00e7e 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1683,7 +1683,9 @@ static int parse_options(char *options, struct super_block *sb,  			data_opt = EXT4_MOUNT_WRITEBACK_DATA;  		datacheck:  			if (is_remount) { -				if (test_opt(sb, DATA_FLAGS) != data_opt) { +				if (!sbi->s_journal) +					ext4_msg(sb, KERN_WARNING, "Remounting file system with no journal so ignoring journalled data option"); +				else if (test_opt(sb, DATA_FLAGS) != data_opt) {  					ext4_msg(sb, KERN_ERR,  						"Cannot change data mode on remount");  					return 0; @@ -3098,8 +3100,6 @@ static void ext4_destroy_lazyinit_thread(void)  }  static int ext4_fill_super(struct super_block *sb, void *data, int silent) -				__releases(kernel_lock) -				__acquires(kernel_lock)  {  	char *orig_data = kstrdup(data, GFP_KERNEL);  	struct buffer_head *bh; diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index 3f32bcb0d9b..ef175cb8cfd 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c @@ -16,38 +16,26 @@  #include <linux/bitops.h>  #include <linux/sched.h> -static const int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 }; -  static DEFINE_SPINLOCK(bitmap_lock); -static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, __u32 numbits) +/* + * bitmap consists of blocks filled with 16bit words + * bit set == busy, bit clear == free + * endianness is a mess, but for counting zero bits it really doesn't matter... + */ +static __u32 count_free(struct buffer_head *map[], unsigned blocksize, __u32 numbits)  { -	unsigned i, j, sum = 0; -	struct buffer_head *bh; -   -	for (i=0; i<numblocks-1; i++) { -		if (!(bh=map[i]))  -			return(0); -		for (j=0; j<bh->b_size; j++) -			sum += nibblemap[bh->b_data[j] & 0xf] -				+ nibblemap[(bh->b_data[j]>>4) & 0xf]; -	} +	__u32 sum = 0; +	unsigned blocks = DIV_ROUND_UP(numbits, blocksize * 8); -	if (numblocks==0 || !(bh=map[numblocks-1])) -		return(0); -	i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2; -	for (j=0; j<i; j++) { -		sum += nibblemap[bh->b_data[j] & 0xf] -			+ nibblemap[(bh->b_data[j]>>4) & 0xf]; +	while (blocks--) { +		unsigned words = blocksize / 2; +		__u16 *p = (__u16 *)(*map++)->b_data; +		while (words--) +			sum += 16 - hweight16(*p++);  	} -	i = numbits%16; -	if (i!=0) { -		i = *(__u16 *)(&bh->b_data[j]) | ~((1<<i) - 1); -		sum += nibblemap[i & 0xf] + nibblemap[(i>>4) & 0xf]; -		sum += nibblemap[(i>>8) & 0xf] + nibblemap[(i>>12) & 0xf]; -	} -	return(sum); +	return sum;  }  void minix_free_block(struct inode *inode, unsigned long block) @@ -105,10 +93,12 @@ int minix_new_block(struct inode * inode)  	return 0;  } -unsigned long minix_count_free_blocks(struct minix_sb_info *sbi) +unsigned long minix_count_free_blocks(struct super_block *sb)  { -	return (count_free(sbi->s_zmap, sbi->s_zmap_blocks, -		sbi->s_nzones - sbi->s_firstdatazone + 1) +	struct minix_sb_info *sbi = minix_sb(sb); +	u32 bits = sbi->s_nzones - (sbi->s_firstdatazone + 1); + +	return (count_free(sbi->s_zmap, sb->s_blocksize, bits)  		<< sbi->s_log_zone_size);  } @@ -273,7 +263,10 @@ struct inode *minix_new_inode(const struct inode *dir, int mode, int *error)  	return inode;  } -unsigned long minix_count_free_inodes(struct minix_sb_info *sbi) +unsigned long minix_count_free_inodes(struct super_block *sb)  { -	return count_free(sbi->s_imap, sbi->s_imap_blocks, sbi->s_ninodes + 1); +	struct minix_sb_info *sbi = minix_sb(sb); +	u32 bits = sbi->s_ninodes + 1; + +	return count_free(sbi->s_imap, sb->s_blocksize, bits);  } diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 64cdcd662ff..1d9e33966db 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -279,6 +279,27 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)   	else if (sbi->s_mount_state & MINIX_ERROR_FS)  		printk("MINIX-fs: mounting file system with errors, "  			"running fsck is recommended\n"); + +	/* Apparently minix can create filesystems that allocate more blocks for +	 * the bitmaps than needed.  We simply ignore that, but verify it didn't +	 * create one with not enough blocks and bail out if so. +	 */ +	block = minix_blocks_needed(sbi->s_ninodes, s->s_blocksize); +	if (sbi->s_imap_blocks < block) { +		printk("MINIX-fs: file system does not have enough " +				"imap blocks allocated.  Refusing to mount\n"); +		goto out_iput; +	} + +	block = minix_blocks_needed( +			(sbi->s_nzones - (sbi->s_firstdatazone + 1)), +			s->s_blocksize); +	if (sbi->s_zmap_blocks < block) { +		printk("MINIX-fs: file system does not have enough " +				"zmap blocks allocated.  Refusing to mount.\n"); +		goto out_iput; +	} +  	return 0;  out_iput: @@ -339,10 +360,10 @@ static int minix_statfs(struct dentry *dentry, struct kstatfs *buf)  	buf->f_type = sb->s_magic;  	buf->f_bsize = sb->s_blocksize;  	buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size; -	buf->f_bfree = minix_count_free_blocks(sbi); +	buf->f_bfree = minix_count_free_blocks(sb);  	buf->f_bavail = buf->f_bfree;  	buf->f_files = sbi->s_ninodes; -	buf->f_ffree = minix_count_free_inodes(sbi); +	buf->f_ffree = minix_count_free_inodes(sb);  	buf->f_namelen = sbi->s_namelen;  	buf->f_fsid.val[0] = (u32)id;  	buf->f_fsid.val[1] = (u32)(id >> 32); diff --git a/fs/minix/minix.h b/fs/minix/minix.h index 341e2122879..26bbd55e82e 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h @@ -48,10 +48,10 @@ extern struct minix_inode * minix_V1_raw_inode(struct super_block *, ino_t, stru  extern struct minix2_inode * minix_V2_raw_inode(struct super_block *, ino_t, struct buffer_head **);  extern struct inode * minix_new_inode(const struct inode *, int, int *);  extern void minix_free_inode(struct inode * inode); -extern unsigned long minix_count_free_inodes(struct minix_sb_info *sbi); +extern unsigned long minix_count_free_inodes(struct super_block *sb);  extern int minix_new_block(struct inode * inode);  extern void minix_free_block(struct inode *inode, unsigned long block); -extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi); +extern unsigned long minix_count_free_blocks(struct super_block *sb);  extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *);  extern int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len); @@ -88,6 +88,11 @@ static inline struct minix_inode_info *minix_i(struct inode *inode)  	return list_entry(inode, struct minix_inode_info, vfs_inode);  } +static inline unsigned minix_blocks_needed(unsigned bits, unsigned blocksize) +{ +	return DIV_ROUND_UP(bits, blocksize * 8); +} +  #if defined(CONFIG_MINIX_FS_NATIVE_ENDIAN) && \  	defined(CONFIG_MINIX_FS_BIG_ENDIAN_16BIT_INDEXED) @@ -125,7 +130,7 @@ static inline int minix_find_first_zero_bit(const void *vaddr, unsigned size)  	if (!size)  		return 0; -	size = (size >> 4) + ((size & 15) > 0); +	size >>= 4;  	while (*p++ == 0xffff) {  		if (--size == 0)  			return (p - addr) << 4; diff --git a/fs/namespace.c b/fs/namespace.c index 50ee30345b4..6d3a1963879 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2493,6 +2493,7 @@ EXPORT_SYMBOL(create_mnt_ns);  struct dentry *mount_subtree(struct vfsmount *mnt, const char *name)  {  	struct mnt_namespace *ns; +	struct super_block *s;  	struct path path;  	int err; @@ -2509,10 +2510,11 @@ struct dentry *mount_subtree(struct vfsmount *mnt, const char *name)  		return ERR_PTR(err);  	/* trade a vfsmount reference for active sb one */ -	atomic_inc(&path.mnt->mnt_sb->s_active); +	s = path.mnt->mnt_sb; +	atomic_inc(&s->s_active);  	mntput(path.mnt);  	/* lock the sucker */ -	down_write(&path.mnt->mnt_sb->s_umount); +	down_write(&s->s_umount);  	/* ... and return the root of (sub)tree on it */  	return path.dentry;  } diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index b238d95ac48..ac289909814 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1468,12 +1468,12 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry  				res = NULL;  				goto out;  			/* This turned out not to be a regular file */ +			case -EISDIR:  			case -ENOTDIR:  				goto no_open;  			case -ELOOP:  				if (!(nd->intent.open.flags & O_NOFOLLOW))  					goto no_open; -			/* case -EISDIR: */  			/* case -EINVAL: */  			default:  				res = ERR_CAST(inode); diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 0a1f8312b4d..eca56d4b39c 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -40,48 +40,8 @@  #define NFSDBG_FACILITY		NFSDBG_FILE -static int nfs_file_open(struct inode *, struct file *); -static int nfs_file_release(struct inode *, struct file *); -static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin); -static int  nfs_file_mmap(struct file *, struct vm_area_struct *); -static ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos, -					struct pipe_inode_info *pipe, -					size_t count, unsigned int flags); -static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov, -				unsigned long nr_segs, loff_t pos); -static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, -					struct file *filp, loff_t *ppos, -					size_t count, unsigned int flags); -static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov, -				unsigned long nr_segs, loff_t pos); -static int  nfs_file_flush(struct file *, fl_owner_t id); -static int  nfs_file_fsync(struct file *, loff_t, loff_t, int datasync); -static int nfs_check_flags(int flags); -static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); -static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); -static int nfs_setlease(struct file *file, long arg, struct file_lock **fl); -  static const struct vm_operations_struct nfs_file_vm_ops; -const struct file_operations nfs_file_operations = { -	.llseek		= nfs_file_llseek, -	.read		= do_sync_read, -	.write		= do_sync_write, -	.aio_read	= nfs_file_read, -	.aio_write	= nfs_file_write, -	.mmap		= nfs_file_mmap, -	.open		= nfs_file_open, -	.flush		= nfs_file_flush, -	.release	= nfs_file_release, -	.fsync		= nfs_file_fsync, -	.lock		= nfs_lock, -	.flock		= nfs_flock, -	.splice_read	= nfs_file_splice_read, -	.splice_write	= nfs_file_splice_write, -	.check_flags	= nfs_check_flags, -	.setlease	= nfs_setlease, -}; -  const struct inode_operations nfs_file_inode_operations = {  	.permission	= nfs_permission,  	.getattr	= nfs_getattr, @@ -886,3 +846,54 @@ static int nfs_setlease(struct file *file, long arg, struct file_lock **fl)  			file->f_path.dentry->d_name.name, arg);  	return -EINVAL;  } + +const struct file_operations nfs_file_operations = { +	.llseek		= nfs_file_llseek, +	.read		= do_sync_read, +	.write		= do_sync_write, +	.aio_read	= nfs_file_read, +	.aio_write	= nfs_file_write, +	.mmap		= nfs_file_mmap, +	.open		= nfs_file_open, +	.flush		= nfs_file_flush, +	.release	= nfs_file_release, +	.fsync		= nfs_file_fsync, +	.lock		= nfs_lock, +	.flock		= nfs_flock, +	.splice_read	= nfs_file_splice_read, +	.splice_write	= nfs_file_splice_write, +	.check_flags	= nfs_check_flags, +	.setlease	= nfs_setlease, +}; + +#ifdef CONFIG_NFS_V4 +static int +nfs4_file_open(struct inode *inode, struct file *filp) +{ +	/* +	 * NFSv4 opens are handled in d_lookup and d_revalidate. If we get to +	 * this point, then something is very wrong +	 */ +	dprintk("NFS: %s called! inode=%p filp=%p\n", __func__, inode, filp); +	return -ENOTDIR; +} + +const struct file_operations nfs4_file_operations = { +	.llseek		= nfs_file_llseek, +	.read		= do_sync_read, +	.write		= do_sync_write, +	.aio_read	= nfs_file_read, +	.aio_write	= nfs_file_write, +	.mmap		= nfs_file_mmap, +	.open		= nfs4_file_open, +	.flush		= nfs_file_flush, +	.release	= nfs_file_release, +	.fsync		= nfs_file_fsync, +	.lock		= nfs_lock, +	.flock		= nfs_flock, +	.splice_read	= nfs_file_splice_read, +	.splice_write	= nfs_file_splice_write, +	.check_flags	= nfs_check_flags, +	.setlease	= nfs_setlease, +}; +#endif /* CONFIG_NFS_V4 */ diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index c07a55aec83..50a15fa8cf9 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -291,7 +291,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)  		 */  		inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->file_inode_ops;  		if (S_ISREG(inode->i_mode)) { -			inode->i_fop = &nfs_file_operations; +			inode->i_fop = NFS_SB(sb)->nfs_client->rpc_ops->file_ops;  			inode->i_data.a_ops = &nfs_file_aops;  			inode->i_data.backing_dev_info = &NFS_SB(sb)->backing_dev_info;  		} else if (S_ISDIR(inode->i_mode)) { diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index c1a1bd8ddf1..3f4d95751d5 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -299,6 +299,8 @@ extern void nfs_read_prepare(struct rpc_task *task, void *calldata);  extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,  		struct list_head *head); +extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, +		struct inode *inode);  extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);  extern void nfs_readdata_release(struct nfs_read_data *rdata); diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 85f1690ca08..d4bc9ed9174 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -853,6 +853,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {  	.dentry_ops	= &nfs_dentry_operations,  	.dir_inode_ops	= &nfs3_dir_inode_operations,  	.file_inode_ops	= &nfs3_file_inode_operations, +	.file_ops	= &nfs_file_operations,  	.getroot	= nfs3_proc_get_root,  	.getattr	= nfs3_proc_getattr,  	.setattr	= nfs3_proc_setattr, diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index b60fddf606f..be2bbac1381 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2464,8 +2464,7 @@ static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qst  		case -NFS4ERR_BADNAME:  			return -ENOENT;  		case -NFS4ERR_MOVED: -			err = nfs4_get_referral(dir, name, fattr, fhandle); -			break; +			return nfs4_get_referral(dir, name, fattr, fhandle);  		case -NFS4ERR_WRONGSEC:  			nfs_fixup_secinfo_attributes(fattr, fhandle);  		} @@ -6253,6 +6252,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {  	.dentry_ops	= &nfs4_dentry_operations,  	.dir_inode_ops	= &nfs4_dir_inode_operations,  	.file_inode_ops	= &nfs4_file_inode_operations, +	.file_ops	= &nfs4_file_operations,  	.getroot	= nfs4_proc_get_root,  	.getattr	= nfs4_proc_getattr,  	.setattr	= nfs4_proc_setattr, diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index baf73536bc0..8e672a2b2d6 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -1260,6 +1260,25 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)  }  EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages); +static void pnfs_ld_handle_read_error(struct nfs_read_data *data) +{ +	struct nfs_pageio_descriptor pgio; + +	put_lseg(data->lseg); +	data->lseg = NULL; +	dprintk("pnfs write error = %d\n", data->pnfs_error); + +	nfs_pageio_init_read_mds(&pgio, data->inode); + +	while (!list_empty(&data->pages)) { +		struct nfs_page *req = nfs_list_entry(data->pages.next); + +		nfs_list_remove_request(req); +		nfs_pageio_add_request(&pgio, req); +	} +	nfs_pageio_complete(&pgio); +} +  /*   * Called by non rpc-based layout drivers   */ @@ -1268,11 +1287,8 @@ void pnfs_ld_read_done(struct nfs_read_data *data)  	if (likely(!data->pnfs_error)) {  		__nfs4_read_done_cb(data);  		data->mds_ops->rpc_call_done(&data->task, data); -	} else { -		put_lseg(data->lseg); -		data->lseg = NULL; -		dprintk("pnfs write error = %d\n", data->pnfs_error); -	} +	} else +		pnfs_ld_handle_read_error(data);  	data->mds_ops->rpc_release(data);  }  EXPORT_SYMBOL_GPL(pnfs_ld_read_done); diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index ac40b8535d7..f48125da198 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -710,6 +710,7 @@ const struct nfs_rpc_ops nfs_v2_clientops = {  	.dentry_ops	= &nfs_dentry_operations,  	.dir_inode_ops	= &nfs_dir_inode_operations,  	.file_inode_ops	= &nfs_file_inode_operations, +	.file_ops	= &nfs_file_operations,  	.getroot	= nfs_proc_get_root,  	.getattr	= nfs_proc_getattr,  	.setattr	= nfs_proc_setattr, diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 8b48ec63f72..cfa175c223d 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -109,7 +109,7 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data)  	}  } -static void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, +void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,  		struct inode *inode)  {  	nfs_pageio_init(pgio, inode, &nfs_pageio_read_ops, @@ -534,23 +534,13 @@ static void nfs_readpage_result_full(struct rpc_task *task, void *calldata)  static void nfs_readpage_release_full(void *calldata)  {  	struct nfs_read_data *data = calldata; -	struct nfs_pageio_descriptor pgio; -	if (data->pnfs_error) { -		nfs_pageio_init_read_mds(&pgio, data->inode); -		pgio.pg_recoalesce = 1; -	}  	while (!list_empty(&data->pages)) {  		struct nfs_page *req = nfs_list_entry(data->pages.next);  		nfs_list_remove_request(req); -		if (!data->pnfs_error) -			nfs_readpage_release(req); -		else -			nfs_pageio_add_request(&pgio, req); +		nfs_readpage_release(req);  	} -	if (data->pnfs_error) -		nfs_pageio_complete(&pgio);  	nfs_readdata_release(calldata);  } diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index d30bedfeb7e..ddd46db65b5 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -235,6 +235,8 @@ struct drm_mode_fb_cmd {  #define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02  #define DRM_MODE_FB_DIRTY_FLAGS         0x03 +#define DRM_MODE_FB_DIRTY_MAX_CLIPS     256 +  /*   * Mark a region of a framebuffer as dirty.   * diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index b65be6054a1..be94be6d6f1 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -874,6 +874,10 @@ struct drm_radeon_gem_pwrite {  #define RADEON_CHUNK_ID_RELOCS	0x01  #define RADEON_CHUNK_ID_IB	0x02 +#define RADEON_CHUNK_ID_FLAGS	0x03 + +/* The first dword of RADEON_CHUNK_ID_FLAGS is a uint32 of these flags: */ +#define RADEON_CS_KEEP_TILING_FLAGS 0x01  struct drm_radeon_cs_chunk {  	uint32_t		chunk_id; diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h index f88eacb111d..7c05ac202d9 100644 --- a/include/linux/ceph/osd_client.h +++ b/include/linux/ceph/osd_client.h @@ -10,6 +10,12 @@  #include "osdmap.h"  #include "messenger.h" +/*  + * Maximum object name size  + * (must be at least as big as RBD_MAX_MD_NAME_LEN -- currently 100)  + */ +#define MAX_OBJ_NAME_SIZE 100 +  struct ceph_msg;  struct ceph_snap_context;  struct ceph_osd_request; @@ -75,7 +81,7 @@ struct ceph_osd_request {  	struct inode *r_inode;         	      /* for use by callbacks */  	void *r_priv;			      /* ditto */ -	char              r_oid[40];          /* object name */ +	char              r_oid[MAX_OBJ_NAME_SIZE];          /* object name */  	int               r_oid_len;  	unsigned long     r_stamp;            /* send OR check time */ diff --git a/include/linux/device.h b/include/linux/device.h index 52b3a4111df..3136ede5a1e 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -69,7 +69,7 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *);   * @resume:	Called to bring a device on this bus out of sleep mode.   * @pm:		Power management operations of this bus, callback the specific   *		device driver's pm-ops. - * @iommu_ops   IOMMU specific operations for this bus, used to attach IOMMU + * @iommu_ops:  IOMMU specific operations for this bus, used to attach IOMMU   *              driver implementations to a bus and allow the driver to do   *              bus-specific setup   * @p:		The private data of the driver core, only the driver core can diff --git a/include/linux/i2c.h b/include/linux/i2c.h index a81bf6d23b3..07d103a06d6 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -432,9 +432,6 @@ void i2c_unlock_adapter(struct i2c_adapter *);  /* Internal numbers to terminate lists */  #define I2C_CLIENT_END		0xfffeU -/* The numbers to use to set I2C bus address */ -#define ANY_I2C_BUS		0xffff -  /* Construct an I2C_CLIENT_END-terminated array of i2c addresses */  #define I2C_ADDRS(addr, addrs...) \  	((const unsigned short []){ addr, ## addrs, I2C_CLIENT_END }) diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 08ffab01e76..94b1e356c02 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -184,7 +184,6 @@ extern struct cred init_cred;  		[PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),		\  	},								\  	.thread_group	= LIST_HEAD_INIT(tsk.thread_group),		\ -	.dirties = INIT_PROP_LOCAL_SINGLE(dirties),			\  	INIT_IDS							\  	INIT_PERF_EVENTS(tsk)						\  	INIT_TRACE_IRQFLAGS						\ diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index 82b4c8801a4..8bf2cb9502d 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h @@ -243,7 +243,8 @@  /*Registers VDD1, VDD2 voltage values definitions */ -#define VDD1_2_NUM_VOLTS				73 +#define VDD1_2_NUM_VOLT_FINE				73 +#define VDD1_2_NUM_VOLT_COARSE				3  #define VDD1_2_MIN_VOLT					6000  #define VDD1_2_OFFSET					125 diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index ab2c6343361..92ecf5585fa 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -410,6 +410,9 @@ extern const struct inode_operations nfs_file_inode_operations;  extern const struct inode_operations nfs3_file_inode_operations;  #endif /* CONFIG_NFS_V3 */  extern const struct file_operations nfs_file_operations; +#ifdef CONFIG_NFS_V4 +extern const struct file_operations nfs4_file_operations; +#endif /* CONFIG_NFS_V4 */  extern const struct address_space_operations nfs_file_aops;  extern const struct address_space_operations nfs_dir_aops; diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index c74595ba709..2a7c533be5d 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -1192,6 +1192,7 @@ struct nfs_rpc_ops {  	const struct dentry_operations *dentry_ops;  	const struct inode_operations *dir_inode_ops;  	const struct inode_operations *file_inode_ops; +	const struct file_operations *file_ops;  	int	(*getroot) (struct nfs_server *, struct nfs_fh *,  			    struct nfs_fsinfo *); diff --git a/include/linux/sched.h b/include/linux/sched.h index 2f90470ad84..d81cce93386 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1521,7 +1521,6 @@ struct task_struct {  #ifdef CONFIG_FAULT_INJECTION  	int make_it_fail;  #endif -	struct prop_local_single dirties;  	/*  	 * when (nr_dirtied >= nr_dirtied_pause), it's time to call  	 * balance_dirty_pages() for some dirty throttling pause diff --git a/include/linux/serial.h b/include/linux/serial.h index 97ff8e27a6c..3d86517fe7d 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h @@ -207,13 +207,15 @@ struct serial_icounter_struct {  struct serial_rs485 {  	__u32	flags;			/* RS485 feature flags */ -#define SER_RS485_ENABLED		(1 << 0) -#define SER_RS485_RTS_ON_SEND		(1 << 1) -#define SER_RS485_RTS_AFTER_SEND	(1 << 2) -#define SER_RS485_RTS_BEFORE_SEND	(1 << 3) +#define SER_RS485_ENABLED		(1 << 0)	/* If enabled */ +#define SER_RS485_RTS_ON_SEND		(1 << 1)	/* Logical level for +							   RTS pin when +							   sending */ +#define SER_RS485_RTS_AFTER_SEND	(1 << 2)	/* Logical level for +							   RTS pin after sent*/  #define SER_RS485_RX_DURING_TX		(1 << 4) -	__u32	delay_rts_before_send;	/* Milliseconds */ -	__u32	delay_rts_after_send;	/* Milliseconds */ +	__u32	delay_rts_before_send;	/* Delay before send (milliseconds) */ +	__u32	delay_rts_after_send;	/* Delay after send (milliseconds) */  	__u32	padding[5];		/* Memory is cheap, new structs  					   are a royal PITA .. */  }; diff --git a/kernel/fork.c b/kernel/fork.c index d53316e88d9..82780861384 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -162,7 +162,6 @@ static void account_kernel_stack(struct thread_info *ti, int account)  void free_task(struct task_struct *tsk)  { -	prop_local_destroy_single(&tsk->dirties);  	account_kernel_stack(tsk->stack, -1);  	free_thread_info(tsk->stack);  	rt_mutex_debug_task_free(tsk); @@ -274,10 +273,6 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)  	tsk->stack = ti; -	err = prop_local_init_single(&tsk->dirties); -	if (err) -		goto out; -  	setup_thread_stack(tsk, orig);  	clear_user_return_notifier(tsk);  	clear_tsk_need_resched(tsk); diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index ba2319ffc86..e7ffa895208 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -347,7 +347,7 @@ int hibernation_snapshot(int platform_mode)  	error = freeze_kernel_threads();  	if (error) -		goto Close; +		goto Cleanup;  	if (hibernation_test(TEST_FREEZER) ||  		hibernation_testmode(HIBERNATION_TESTPROC)) { @@ -357,12 +357,14 @@ int hibernation_snapshot(int platform_mode)  		 * successful freezer test.  		 */  		freezer_test_done = true; -		goto Close; +		goto Cleanup;  	}  	error = dpm_prepare(PMSG_FREEZE); -	if (error) -		goto Complete_devices; +	if (error) { +		dpm_complete(msg); +		goto Cleanup; +	}  	suspend_console();  	pm_restrict_gfp_mask(); @@ -391,8 +393,6 @@ int hibernation_snapshot(int platform_mode)  		pm_restore_gfp_mask();  	resume_console(); - - Complete_devices:  	dpm_complete(msg);   Close: @@ -402,6 +402,10 @@ int hibernation_snapshot(int platform_mode)   Recover_platform:  	platform_recover(platform_mode);  	goto Resume_devices; + + Cleanup: +	swsusp_free(); +	goto Close;  }  /** diff --git a/mm/page-writeback.c b/mm/page-writeback.c index a3278f00523..71252486bc6 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -128,7 +128,6 @@ unsigned long global_dirty_limit;   *   */  static struct prop_descriptor vm_completions; -static struct prop_descriptor vm_dirties;  /*   * couple the period to the dirty_ratio: @@ -154,7 +153,6 @@ static void update_completion_period(void)  {  	int shift = calc_period_shift();  	prop_change_shift(&vm_completions, shift); -	prop_change_shift(&vm_dirties, shift);  	writeback_set_ratelimit();  } @@ -235,11 +233,6 @@ void bdi_writeout_inc(struct backing_dev_info *bdi)  }  EXPORT_SYMBOL_GPL(bdi_writeout_inc); -void task_dirty_inc(struct task_struct *tsk) -{ -	prop_inc_single(&vm_dirties, &tsk->dirties); -} -  /*   * Obtain an accurate fraction of the BDI's portion.   */ @@ -1133,17 +1126,17 @@ pause:  					  pages_dirtied,  					  pause,  					  start_time); -		__set_current_state(TASK_UNINTERRUPTIBLE); +		__set_current_state(TASK_KILLABLE);  		io_schedule_timeout(pause); -		dirty_thresh = hard_dirty_limit(dirty_thresh);  		/* -		 * max-pause area. If dirty exceeded but still within this -		 * area, no need to sleep for more than 200ms: (a) 8 pages per -		 * 200ms is typically more than enough to curb heavy dirtiers; -		 * (b) the pause time limit makes the dirtiers more responsive. +		 * This is typically equal to (nr_dirty < dirty_thresh) and can +		 * also keep "1000+ dd on a slow USB stick" under control.  		 */ -		if (nr_dirty < dirty_thresh) +		if (task_ratelimit) +			break; + +		if (fatal_signal_pending(current))  			break;  	} @@ -1395,7 +1388,6 @@ void __init page_writeback_init(void)  	shift = calc_period_shift();  	prop_descriptor_init(&vm_completions, shift); -	prop_descriptor_init(&vm_dirties, shift);  }  /** @@ -1724,7 +1716,6 @@ void account_page_dirtied(struct page *page, struct address_space *mapping)  		__inc_zone_page_state(page, NR_DIRTIED);  		__inc_bdi_stat(mapping->backing_dev_info, BDI_RECLAIMABLE);  		__inc_bdi_stat(mapping->backing_dev_info, BDI_DIRTIED); -		task_dirty_inc(current);  		task_io_account_write(PAGE_CACHE_SIZE);  	}  } diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 733e46008b8..f4f3f58f523 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -244,7 +244,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,  		ceph_pagelist_init(req->r_trail);  	}  	/* create request message; allow space for oid */ -	msg_size += 40; +	msg_size += MAX_OBJ_NAME_SIZE;  	if (snapc)  		msg_size += sizeof(u64) * snapc->num_snaps;  	if (use_mempool) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index d7f97ef2659..2d78d95955a 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -2530,8 +2530,10 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args,  		int err;  		err = xs_init_anyaddr(args->dstaddr->sa_family,  					(struct sockaddr *)&new->srcaddr); -		if (err != 0) +		if (err != 0) { +			xprt_free(xprt);  			return ERR_PTR(err); +		}  	}  	return xprt; diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 30e2befd6f2..8b4c2535b26 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -747,6 +747,18 @@ sub __eval_option {      # Add space to evaluate the character before $      $option = " $option";      my $retval = ""; +    my $repeated = 0; +    my $parent = 0; + +    foreach my $test (keys %repeat_tests) { +	if ($i >= $test && +	    $i < $test + $repeat_tests{$test}) { + +	    $repeated = 1; +	    $parent = $test; +	    last; +	} +    }      while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {  	my $start = $1; @@ -760,10 +772,14 @@ sub __eval_option {  	# otherwise see if the default OPT (without [$i]) exists.  	my $o = "$var\[$i\]"; +	my $parento = "$var\[$parent\]";  	if (defined($opt{$o})) {  	    $o = $opt{$o};  	    $retval = "$retval$o"; +	} elsif ($repeated && defined($opt{$parento})) { +	    $o = $opt{$parento}; +	    $retval = "$retval$o";  	} elsif (defined($opt{$var})) {  	    $o = $opt{$var};  	    $retval = "$retval$o";  |