diff options
| author | Ingo Molnar <mingo@elte.hu> | 2011-01-05 14:14:42 +0100 | 
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2011-01-05 14:14:46 +0100 | 
| commit | 27066fd484a32c80630136aa2b91c980f3198f9d (patch) | |
| tree | 78ddabdedbfd7525d13ecd62a745525843f1d0e8 | |
| parent | 101e5f77bf35679809586e250b6c62193d2ed179 (diff) | |
| parent | 3c0eee3fe6a3a1c745379547c7e7c904aa64f6d5 (diff) | |
| download | olio-linux-3.10-27066fd484a32c80630136aa2b91c980f3198f9d.tar.xz olio-linux-3.10-27066fd484a32c80630136aa2b91c980f3198f9d.zip  | |
Merge commit 'v2.6.37' into sched/core
Merge reason: Merge the final .37 tree.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
424 files changed, 4327 insertions, 3089 deletions
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c index a2976a6de03..e9c77788a39 100644 --- a/Documentation/accounting/getdelays.c +++ b/Documentation/accounting/getdelays.c @@ -516,6 +516,7 @@ int main(int argc, char *argv[])  			default:  				fprintf(stderr, "Unknown nla_type %d\n",  					na->nla_type); +			case TASKSTATS_TYPE_NULL:  				break;  			}  			na = (struct nlattr *) (GENLMSG_DATA(&msg) + len); diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index b6426f15b4a..33fa3e5d38f 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -18,7 +18,6 @@ prototypes:  	char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);  locking rules: -	none have BKL  		dcache_lock	rename_lock	->d_lock	may block  d_revalidate:	no		no		no		yes  d_hash		no		no		no		yes @@ -42,18 +41,23 @@ ata *);  	int (*rename) (struct inode *, struct dentry *,  			struct inode *, struct dentry *);  	int (*readlink) (struct dentry *, char __user *,int); -	int (*follow_link) (struct dentry *, struct nameidata *); +	void * (*follow_link) (struct dentry *, struct nameidata *); +	void (*put_link) (struct dentry *, struct nameidata *, void *);  	void (*truncate) (struct inode *);  	int (*permission) (struct inode *, int, struct nameidata *); +	int (*check_acl)(struct inode *, int);  	int (*setattr) (struct dentry *, struct iattr *);  	int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);  	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);  	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);  	ssize_t (*listxattr) (struct dentry *, char *, size_t);  	int (*removexattr) (struct dentry *, const char *); +	void (*truncate_range)(struct inode *, loff_t, loff_t); +	long (*fallocate)(struct inode *inode, int mode, loff_t offset, loff_t len); +	int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);  locking rules: -	all may block, none have BKL +	all may block  		i_mutex(inode)  lookup:		yes  create:		yes @@ -66,19 +70,24 @@ rmdir:		yes (both)	(see below)  rename:		yes (all)	(see below)  readlink:	no  follow_link:	no +put_link:	no  truncate:	yes		(see below)  setattr:	yes  permission:	no +check_acl:	no  getattr:	no  setxattr:	yes  getxattr:	no  listxattr:	no  removexattr:	yes +truncate_range:	yes +fallocate:	no +fiemap:		no  	Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on  victim.  	cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.  	->truncate() is never called directly - it's a callback, not a -method. It's called by vmtruncate() - library function normally used by +method. It's called by vmtruncate() - deprecated library function used by  ->setattr(). Locking information above applies to that call (i.e. is  inherited from ->setattr() - vmtruncate() is used when ATTR_SIZE had been  passed). @@ -91,7 +100,7 @@ prototypes:  	struct inode *(*alloc_inode)(struct super_block *sb);  	void (*destroy_inode)(struct inode *);  	void (*dirty_inode) (struct inode *); -	int (*write_inode) (struct inode *, int); +	int (*write_inode) (struct inode *, struct writeback_control *wbc);  	int (*drop_inode) (struct inode *);  	void (*evict_inode) (struct inode *);  	void (*put_super) (struct super_block *); @@ -105,10 +114,10 @@ prototypes:  	int (*show_options)(struct seq_file *, struct vfsmount *);  	ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);  	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t); +	int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);  locking rules:  	All may block [not true, see below] -	None have BKL  			s_umount  alloc_inode:  destroy_inode: @@ -127,6 +136,7 @@ umount_begin:		no  show_options:		no		(namespace_sem)  quota_read:		no		(see below)  quota_write:		no		(see below) +bdev_try_to_free_page:	no		(see below)  ->statfs() has s_umount (shared) when called by ustat(2) (native or  compat), but that's an accident of bad API; s_umount is used to pin @@ -139,19 +149,25 @@ be the only ones operating on the quota file by the quota code (via  dqio_sem) (unless an admin really wants to screw up something and  writes to quota files with quotas on). For other details about locking  see also dquot_operations section. +->bdev_try_to_free_page is called from the ->releasepage handler of +the block device inode.  See there for more details.  --------------------------- file_system_type ---------------------------  prototypes:  	int (*get_sb) (struct file_system_type *, int,  		       const char *, void *, struct vfsmount *); +	struct dentry *(*mount) (struct file_system_type *, int, +		       const char *, void *);  	void (*kill_sb) (struct super_block *);  locking rules: -		may block	BKL -get_sb		yes		no -kill_sb		yes		no +		may block +get_sb		yes +mount		yes +kill_sb		yes  ->get_sb() returns error or 0 with locked superblock attached to the vfsmount  (exclusive on ->s_umount). +->mount() returns ERR_PTR or the root dentry.  ->kill_sb() takes a write-locked superblock, does all shutdown work on it,  unlocks and drops the reference. @@ -176,27 +192,35 @@ prototypes:  	void (*freepage)(struct page *);  	int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,  			loff_t offset, unsigned long nr_segs); -	int (*launder_page) (struct page *); +	int (*get_xip_mem)(struct address_space *, pgoff_t, int, void **, +				unsigned long *); +	int (*migratepage)(struct address_space *, struct page *, struct page *); +	int (*launder_page)(struct page *); +	int (*is_partially_uptodate)(struct page *, read_descriptor_t *, unsigned long); +	int (*error_remove_page)(struct address_space *, struct page *);  locking rules:  	All except set_page_dirty and freepage may block -			BKL	PageLocked(page)	i_mutex -writepage:		no	yes, unlocks (see below) -readpage:		no	yes, unlocks -sync_page:		no	maybe -writepages:		no -set_page_dirty		no	no -readpages:		no -write_begin:		no	locks the page		yes -write_end:		no	yes, unlocks		yes -perform_write:		no	n/a			yes -bmap:			no -invalidatepage:		no	yes -releasepage:		no	yes -freepage:		no	yes -direct_IO:		no -launder_page:		no	yes +			PageLocked(page)	i_mutex +writepage:		yes, unlocks (see below) +readpage:		yes, unlocks +sync_page:		maybe +writepages: +set_page_dirty		no +readpages: +write_begin:		locks the page		yes +write_end:		yes, unlocks		yes +bmap: +invalidatepage:		yes +releasepage:		yes +freepage:		yes +direct_IO: +get_xip_mem:					maybe +migratepage:		yes (both) +launder_page:		yes +is_partially_uptodate:	yes +error_remove_page:	yes  	->write_begin(), ->write_end(), ->sync_page() and ->readpage()  may be called from the request handler (/dev/loop). @@ -276,9 +300,8 @@ under spinlock (it cannot block) and is sometimes called with the page  not locked.  	->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some -filesystems and by the swapper. The latter will eventually go away. All -instances do not actually need the BKL. Please, keep it that way and don't -breed new callers. +filesystems and by the swapper. The latter will eventually go away.  Please, +keep it that way and don't breed new callers.  	->invalidatepage() is called when the filesystem must attempt to drop  some or all of the buffers from the page when it is being truncated.  It @@ -299,47 +322,37 @@ cleaned, or an error value if not. Note that in order to prevent the page  getting mapped back in and redirtied, it needs to be kept locked  across the entire operation. -	Note: currently almost all instances of address_space methods are -using BKL for internal serialization and that's one of the worst sources -of contention. Normally they are calling library functions (in fs/buffer.c) -and pass foo_get_block() as a callback (on local block-based filesystems, -indeed). BKL is not needed for library stuff and is usually taken by -foo_get_block(). It's an overkill, since block bitmaps can be protected by -internal fs locking and real critical areas are much smaller than the areas -filesystems protect now. -  ----------------------- file_lock_operations ------------------------------  prototypes: -	void (*fl_insert)(struct file_lock *);	/* lock insertion callback */ -	void (*fl_remove)(struct file_lock *);	/* lock removal callback */  	void (*fl_copy_lock)(struct file_lock *, struct file_lock *);  	void (*fl_release_private)(struct file_lock *);  locking rules: -			BKL	may block -fl_insert:		yes	no -fl_remove:		yes	no -fl_copy_lock:		yes	no -fl_release_private:	yes	yes +			file_lock_lock	may block +fl_copy_lock:		yes		no +fl_release_private:	maybe		no  ----------------------- lock_manager_operations ---------------------------  prototypes:  	int (*fl_compare_owner)(struct file_lock *, struct file_lock *);  	void (*fl_notify)(struct file_lock *);  /* unblock callback */ +	int (*fl_grant)(struct file_lock *, struct file_lock *, int);  	void (*fl_release_private)(struct file_lock *);  	void (*fl_break)(struct file_lock *); /* break_lease callback */ +	int (*fl_mylease)(struct file_lock *, struct file_lock *); +	int (*fl_change)(struct file_lock **, int);  locking rules: -			BKL	may block -fl_compare_owner:	yes	no -fl_notify:		yes	no -fl_release_private:	yes	yes -fl_break:		yes	no +			file_lock_lock	may block +fl_compare_owner:	yes		no +fl_notify:		yes		no +fl_grant:		no		no +fl_release_private:	maybe		no +fl_break:		yes		no +fl_mylease:		yes		no +fl_change		yes		no -	Currently only NFSD and NLM provide instances of this class. None of the -them block. If you have out-of-tree instances - please, show up. Locking -in that area will change.  --------------------------- buffer_head -----------------------------------  prototypes:  	void (*b_end_io)(struct buffer_head *bh, int uptodate); @@ -364,17 +377,17 @@ prototypes:  	void (*swap_slot_free_notify) (struct block_device *, unsigned long);  locking rules: -			BKL	bd_mutex -open:			no	yes -release:		no	yes -ioctl:			no	no -compat_ioctl:		no	no -direct_access:		no	no -media_changed:		no	no -unlock_native_capacity:	no	no -revalidate_disk:	no	no -getgeo:			no	no -swap_slot_free_notify:	no	no	(see below) +			bd_mutex +open:			yes +release:		yes +ioctl:			no +compat_ioctl:		no +direct_access:		no +media_changed:		no +unlock_native_capacity:	no +revalidate_disk:	no +getgeo:			no +swap_slot_free_notify:	no	(see below)  media_changed, unlock_native_capacity and revalidate_disk are called only from  check_disk_change(). @@ -413,34 +426,21 @@ prototypes:  	unsigned long (*get_unmapped_area)(struct file *, unsigned long,  			unsigned long, unsigned long, unsigned long);  	int (*check_flags)(int); +	int (*flock) (struct file *, int, struct file_lock *); +	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, +			size_t, unsigned int); +	ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, +			size_t, unsigned int); +	int (*setlease)(struct file *, long, struct file_lock **);  };  locking rules: -	All may block. -			BKL -llseek:			no	(see below) -read:			no -aio_read:		no -write:			no -aio_write:		no -readdir: 		no -poll:			no -unlocked_ioctl:		no -compat_ioctl:		no -mmap:			no -open:			no -flush:			no -release:		no -fsync:			no	(see below) -aio_fsync:		no -fasync:			no -lock:			yes -readv:			no -writev:			no -sendfile:		no -sendpage:		no -get_unmapped_area:	no -check_flags:		no +	All may block except for ->setlease. +	No VFS locks held on entry except for ->fsync and ->setlease. + +->fsync() has i_mutex on inode. + +->setlease has the file_list_lock held and must not sleep.  ->llseek() locking has moved from llseek to the individual llseek  implementations.  If your fs is not using generic_file_llseek, you @@ -450,17 +450,10 @@ mutex or just to use i_size_read() instead.  Note: this does not protect the file->f_pos against concurrent modifications  since this is something the userspace has to take care about. -Note: ext2_release() was *the* source of contention on fs-intensive -loads and dropping BKL on ->release() helps to get rid of that (we still -grab BKL for cases when we close a file that had been opened r/w, but that -can and should be done using the internal locking with smaller critical areas). -Current worst offender is ext2_get_block()... - -->fasync() is called without BKL protection, and is responsible for -maintaining the FASYNC bit in filp->f_flags.  Most instances call -fasync_helper(), which does that maintenance, so it's not normally -something one needs to worry about.  Return values > 0 will be mapped to -zero in the VFS layer. +->fasync() is responsible for maintaining the FASYNC bit in filp->f_flags. +Most instances call fasync_helper(), which does that maintenance, so it's +not normally something one needs to worry about.  Return values > 0 will be +mapped to zero in the VFS layer.  ->readdir() and ->ioctl() on directories must be changed. Ideally we would  move ->readdir() to inode_operations and use a separate method for directory @@ -471,8 +464,6 @@ components. And there are other reasons why the current interface is a mess...  ->read on directories probably must go away - we should just enforce -EISDIR  in sys_read() and friends. -->fsync() has i_mutex on inode. -  --------------------------- dquot_operations -------------------------------  prototypes:  	int (*write_dquot) (struct dquot *); @@ -507,12 +498,12 @@ prototypes:  	int (*access)(struct vm_area_struct *, unsigned long, void*, int, int);  locking rules: -		BKL	mmap_sem	PageLocked(page) -open:		no	yes -close:		no	yes -fault:		no	yes		can return with page locked -page_mkwrite:	no	yes		can return with page locked -access:		no	yes +		mmap_sem	PageLocked(page) +open:		yes +close:		yes +fault:		yes		can return with page locked +page_mkwrite:	yes		can return with page locked +access:		yes  	->fault() is called when a previously not present pte is about  to be faulted in. The filesystem must find and return the page associated @@ -539,6 +530,3 @@ VM_IO | VM_PFNMAP VMAs.  (if you break something or notice that it is broken and do not fix it yourself  - at least put it here) - -ipc/shm.c::shm_delete() - may need BKL. -->read() and ->write() in many drivers are (probably) missing BKL. diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index b79a8fbf0dd..1031923f525 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1761,7 +1761,7 @@ and is between 256 and 4096 characters. It is defined in the file  	nousb		[USB] Disable the USB subsystem -	nowatchdog	[KNL] Disable the lockup detector. +	nowatchdog	[KNL] Disable the lockup detector (NMI watchdog).  	nowb		[ARM] @@ -2177,11 +2177,6 @@ and is between 256 and 4096 characters. It is defined in the file  	reset_devices	[KNL] Force drivers to reset the underlying device  			during initialization. -	resource_alloc_from_bottom -			Allocate new resources from the beginning of available -			space, not the end.  If you need to use this, please -			report a bug. -  	resume=		[SWSUSP]  			Specify the partition device for software suspend diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 489e9bacd16..41cc7b30d7d 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -379,8 +379,8 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:        zero)    bool pm_runtime_suspended(struct device *dev); -    - return true if the device's runtime PM status is 'suspended', or false -      otherwise +    - return true if the device's runtime PM status is 'suspended' and its +      'power.disable_depth' field is equal to zero, or false otherwise    void pm_runtime_allow(struct device *dev);      - set the power.runtime_auto flag for the device and decrease its usage diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt index 570ef2b3d79..df322c10346 100644 --- a/Documentation/scsi/scsi_mid_low_api.txt +++ b/Documentation/scsi/scsi_mid_low_api.txt @@ -1044,9 +1044,9 @@ Details:  /** - *      queuecommand - queue scsi command, invoke 'done' on completion + *      queuecommand - queue scsi command, invoke scp->scsi_done on completion + *      @shost: pointer to the scsi host object   *      @scp: pointer to scsi command object - *      @done: function pointer to be invoked on completion   *   *      Returns 0 on success.   * @@ -1074,42 +1074,45 @@ Details:   *   *      Other types of errors that are detected immediately may be   *      flagged by setting scp->result to an appropriate value, - *      invoking the 'done' callback, and then returning 0 from this - *      function. If the command is not performed immediately (and the - *      LLD is starting (or will start) the given command) then this - *      function should place 0 in scp->result and return 0. + *      invoking the scp->scsi_done callback, and then returning 0 + *      from this function. If the command is not performed + *      immediately (and the LLD is starting (or will start) the given + *      command) then this function should place 0 in scp->result and + *      return 0.   *   *      Command ownership.  If the driver returns zero, it owns the - *      command and must take responsibility for ensuring the 'done' - *      callback is executed.  Note: the driver may call done before - *      returning zero, but after it has called done, it may not - *      return any value other than zero.  If the driver makes a - *      non-zero return, it must not execute the command's done - *      callback at any time. + *      command and must take responsibility for ensuring the + *      scp->scsi_done callback is executed.  Note: the driver may + *      call scp->scsi_done before returning zero, but after it has + *      called scp->scsi_done, it may not return any value other than + *      zero.  If the driver makes a non-zero return, it must not + *      execute the command's scsi_done callback at any time.   * - *      Locks: struct Scsi_Host::host_lock held on entry (with "irqsave") - *             and is expected to be held on return. + *      Locks: up to and including 2.6.36, struct Scsi_Host::host_lock + *             held on entry (with "irqsave") and is expected to be + *             held on return. From 2.6.37 onwards, queuecommand is + *             called without any locks held.   *   *      Calling context: in interrupt (soft irq) or process context   * - *      Notes: This function should be relatively fast. Normally it will - *      not wait for IO to complete. Hence the 'done' callback is invoked  - *      (often directly from an interrupt service routine) some time after - *      this function has returned. In some cases (e.g. pseudo adapter  - *      drivers that manufacture the response to a SCSI INQUIRY) - *      the 'done' callback may be invoked before this function returns. - *      If the 'done' callback is not invoked within a certain period - *      the SCSI mid level will commence error processing. - *      If a status of CHECK CONDITION is placed in "result" when the - *      'done' callback is invoked, then the LLD driver should  - *      perform autosense and fill in the struct scsi_cmnd::sense_buffer + *      Notes: This function should be relatively fast. Normally it + *      will not wait for IO to complete. Hence the scp->scsi_done + *      callback is invoked (often directly from an interrupt service + *      routine) some time after this function has returned. In some + *      cases (e.g. pseudo adapter drivers that manufacture the + *      response to a SCSI INQUIRY) the scp->scsi_done callback may be + *      invoked before this function returns.  If the scp->scsi_done + *      callback is not invoked within a certain period the SCSI mid + *      level will commence error processing.  If a status of CHECK + *      CONDITION is placed in "result" when the scp->scsi_done + *      callback is invoked, then the LLD driver should perform + *      autosense and fill in the struct scsi_cmnd::sense_buffer   *      array. The scsi_cmnd::sense_buffer array is zeroed prior to   *      the mid level queuing a command to an LLD.   *   *      Defined in: LLD   **/ -    int queuecommand(struct scsi_cmnd * scp,  -                     void (*done)(struct scsi_cmnd *)) +    int queuecommand(struct Scsi_Host *shost, struct scsi_cmnd * scp)  /** diff --git a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl index b3e73ddb156..12cecc83cd9 100644 --- a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl +++ b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl @@ -373,9 +373,18 @@ EVENT_PROCESS:  				print "         $regex_lru_isolate/o\n";  				next;  			} +			my $isolate_mode = $1;  			my $nr_scanned = $4;  			my $nr_contig_dirty = $7; -			$perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned; + +			# To closer match vmstat scanning statistics, only count isolate_both +			# and isolate_inactive as scanning. isolate_active is rotation +			# isolate_inactive == 0 +			# isolate_active   == 1 +			# isolate_both     == 2 +			if ($isolate_mode != 1) { +				$perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned; +			}  			$perprocesspid{$process_pid}->{HIGH_NR_CONTIG_DIRTY} += $nr_contig_dirty;  		} elsif ($tracepoint eq "mm_vmscan_lru_shrink_inactive") {  			$details = $5; diff --git a/MAINTAINERS b/MAINTAINERS index 6a588873cf8..7585e9dd835 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -405,7 +405,7 @@ S:	Supported  F:	drivers/usb/gadget/amd5536udc.*  AMD GEODE PROCESSOR/CHIPSET SUPPORT -P:	Jordan Crouse +P:	Andres Salomon <dilinger@queued.net>  L:	linux-geode@lists.infradead.org (moderated for non-subscribers)  W:	http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html  S:	Supported @@ -792,11 +792,14 @@ S:	Maintained  ARM/NOMADIK ARCHITECTURE  M:	Alessandro Rubini <rubini@unipv.it> +M:	Linus Walleij <linus.walleij@stericsson.com>  M:	STEricsson <STEricsson_nomadik_linux@list.st.com>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)  S:	Maintained  F:	arch/arm/mach-nomadik/  F:	arch/arm/plat-nomadik/ +F:	drivers/i2c/busses/i2c-nomadik.c +T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git  ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT  M:	Nelson Castillo <arhuaco@freaks-unidos.net> @@ -998,12 +1001,24 @@ F:	drivers/i2c/busses/i2c-stu300.c  F:	drivers/rtc/rtc-coh901331.c  F:	drivers/watchdog/coh901327_wdt.c  F:	drivers/dma/coh901318* +F:	drivers/mfd/ab3100* +F:	drivers/rtc/rtc-ab3100.c +F:	drivers/rtc/rtc-coh901331.c +T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git -ARM/U8500 ARM ARCHITECTURE +ARM/Ux500 ARM ARCHITECTURE  M:	Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> +M:	Linus Walleij <linus.walleij@stericsson.com>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)  S:	Maintained  F:	arch/arm/mach-ux500/ +F:	drivers/dma/ste_dma40* +F:	drivers/mfd/ab3550* +F:	drivers/mfd/abx500* +F:	drivers/mfd/ab8500* +F:	drivers/mfd/stmpe* +F:	drivers/rtc/rtc-ab8500.c +T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git  ARM/VFP SUPPORT  M:	Russell King <linux@arm.linux.org.uk> @@ -4590,7 +4605,7 @@ F:	drivers/pcmcia/  F:	include/pcmcia/  PCNET32 NETWORK DRIVER -M:	Don Fry <pcnet32@verizon.net> +M:	Don Fry <pcnet32@frontier.com>  L:	netdev@vger.kernel.org  S:	Maintained  F:	drivers/net/pcnet32.c @@ -1,7 +1,7 @@  VERSION = 2  PATCHLEVEL = 6  SUBLEVEL = 37 -EXTRAVERSION = -rc6 +EXTRAVERSION =  NAME = Flesh-Eating Bats with Fangs  # *DOCUMENTATION* diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c index 1bec96e8519..42ff90b46df 100644 --- a/arch/arm/common/it8152.c +++ b/arch/arm/common/it8152.c @@ -352,3 +352,4 @@ struct pci_bus * __init it8152_pci_scan_bus(int nr, struct pci_sys_data *sys)  	return pci_scan_bus(nr, &it8152_ops, sys);  } +EXPORT_SYMBOL(dma_set_coherent_mask); diff --git a/arch/arm/include/asm/hardware/it8152.h b/arch/arm/include/asm/hardware/it8152.h index 21fa272301f..b2f95c72287 100644 --- a/arch/arm/include/asm/hardware/it8152.h +++ b/arch/arm/include/asm/hardware/it8152.h @@ -76,6 +76,7 @@ extern unsigned long it8152_base_address;    IT8152_PD_IRQ(0)  Audio controller (ACR)   */  #define IT8152_IRQ(x)   (IRQ_BOARD_START + (x)) +#define IT8152_LAST_IRQ	(IRQ_BOARD_START + 40)  /* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */  #define IT8152_LD_IRQ_COUNT     9 diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h index 1fc684e70ab..7080e2c8fa6 100644 --- a/arch/arm/include/asm/highmem.h +++ b/arch/arm/include/asm/highmem.h @@ -25,9 +25,6 @@ extern void *kmap_high(struct page *page);  extern void *kmap_high_get(struct page *page);  extern void kunmap_high(struct page *page); -extern void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte); -extern void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte); -  /*   * The following functions are already defined by <linux/highmem.h>   * when CONFIG_HIGHMEM is not set. diff --git a/arch/arm/include/asm/sizes.h b/arch/arm/include/asm/sizes.h index 4fc1565e4f9..316bb2b2be3 100644 --- a/arch/arm/include/asm/sizes.h +++ b/arch/arm/include/asm/sizes.h @@ -13,9 +13,6 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   */ -/* DO NOT EDIT!! - this file automatically generated - *                 from .s file by awk -f s2h.awk - */  /*  Size definitions   *  Copyright (C) ARM Limited 1998. All rights reserved.   */ @@ -25,6 +22,9 @@  /* handy sizes */  #define SZ_16				0x00000010 +#define SZ_32				0x00000020 +#define SZ_64				0x00000040 +#define SZ_128				0x00000080  #define SZ_256				0x00000100  #define SZ_512				0x00000200 diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 1120f18a6b1..80025948b8a 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -150,6 +150,7 @@ extern unsigned int user_debug;  #define rmb()		dmb()  #define wmb()		mb()  #else +#include <asm/memory.h>  #define mb()	do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)  #define rmb()	do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)  #define wmb()	do { if (arch_is_coherent()) dmb(); else barrier(); } while (0) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 8bfa98757cd..80bf8cd88d7 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -29,6 +29,9 @@ ret_fast_syscall:  	ldr	r1, [tsk, #TI_FLAGS]  	tst	r1, #_TIF_WORK_MASK  	bne	fast_work_pending +#if defined(CONFIG_IRQSOFF_TRACER) +	asm_trace_hardirqs_on +#endif  	/* perform architecture specific actions before user return */  	arch_ret_to_user r1, lr @@ -65,6 +68,9 @@ ret_slow_syscall:  	tst	r1, #_TIF_WORK_MASK  	bne	work_pending  no_work_pending: +#if defined(CONFIG_IRQSOFF_TRACER) +	asm_trace_hardirqs_on +#endif  	/* perform architecture specific actions before user return */  	arch_ret_to_user r1, lr diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 8c195959025..9066473c0eb 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -310,7 +310,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)  	 * All kernel threads share the same mm context; grab a  	 * reference and switch to it.  	 */ -	atomic_inc(&mm->mm_users);  	atomic_inc(&mm->mm_count);  	current->active_mm = mm;  	cpumask_set_cpu(cpu, mm_cpumask(mm)); diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 62d686f0b42..d13add71f72 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -65,7 +65,7 @@ obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o  obj-$(CONFIG_MACH_CPU9G20)	+= board-cpu9krea.o  obj-$(CONFIG_MACH_STAMP9G20)	+= board-stamp9g20.o  obj-$(CONFIG_MACH_PORTUXG20)	+= board-stamp9g20.o -obj-$(CONFIG_MACH_PCONTROL_G20)	+= board-pcontrol-g20.o +obj-$(CONFIG_MACH_PCONTROL_G20)	+= board-pcontrol-g20.o board-stamp9g20.o  # AT91SAM9260/AT91SAM9G20 board-specific support  obj-$(CONFIG_MACH_SNAPPER_9260)	+= board-snapper9260.o diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c index bba5a560e02..feb65787c30 100644 --- a/arch/arm/mach-at91/board-pcontrol-g20.c +++ b/arch/arm/mach-at91/board-pcontrol-g20.c @@ -31,6 +31,7 @@  #include <mach/board.h>  #include <mach/at91sam9_smc.h> +#include <mach/stamp9g20.h>  #include "sam9_smc.h"  #include "generic.h" @@ -38,11 +39,7 @@  static void __init pcontrol_g20_map_io(void)  { -	/* Initialize processor: 18.432 MHz crystal */ -	at91sam9260_initialize(18432000); - -	/* DGBU on ttyS0. (Rx, Tx) only TTL -> JTAG connector X7 17,19 ) */ -	at91_register_uart(0, 0, 0); +	stamp9g20_map_io();  	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback  A2 */  	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS @@ -54,9 +51,6 @@ static void __init pcontrol_g20_map_io(void)  	/* USART2 on ttyS3. (Rx, Tx)  9bit-Bus  Multidrop-mode  X4 */  	at91_register_uart(AT91SAM9260_ID_US4, 3, 0); - -	/* set serial console to ttyS0 (ie, DBGU) */ -	at91_set_serial_console(0);  } @@ -66,38 +60,6 @@ static void __init init_irq(void)  } -/* - * NAND flash 512MiB 1,8V 8-bit, sector size 128 KiB - */ -static struct atmel_nand_data __initdata nand_data = { -	.ale		= 21, -	.cle		= 22, -	.rdy_pin	= AT91_PIN_PC13, -	.enable_pin	= AT91_PIN_PC14, -}; - -/* - * Bus timings; unit = 7.57ns - */ -static struct sam9_smc_config __initdata nand_smc_config = { -	.ncs_read_setup		= 0, -	.nrd_setup		= 2, -	.ncs_write_setup	= 0, -	.nwe_setup		= 2, - -	.ncs_read_pulse		= 4, -	.nrd_pulse		= 4, -	.ncs_write_pulse	= 4, -	.nwe_pulse		= 4, - -	.read_cycle		= 7, -	.write_cycle		= 7, - -	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE -			| AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, -	.tdf_cycles		= 3, -}; -  static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {  	.ncs_read_setup		= 16,  	.nrd_setup		= 18, @@ -138,14 +100,6 @@ static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {  	.tdf_cycles		= 1,  } }; -static void __init add_device_nand(void) -{ -	/* configure chip-select 3 (NAND) */ -	sam9_smc_configure(3, &nand_smc_config); -	at91_add_device_nand(&nand_data); -} - -  static void __init add_device_pcontrol(void)  {  	/* configure chip-select 4 (IO compatible to 8051  X4 ) */ @@ -156,23 +110,6 @@ static void __init add_device_pcontrol(void)  /* - * MCI (SD/MMC) - * det_pin, wp_pin and vcc_pin are not connected - */ -#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) -static struct mci_platform_data __initdata mmc_data = { -	.slot[0] = { -		.bus_width	= 4, -	}, -}; -#else -static struct at91_mmc_data __initdata mmc_data = { -	.wire4		= 1, -}; -#endif - - -/*   * USB Host port   */  static struct at91_usbh_data __initdata usbh_data = { @@ -265,42 +202,13 @@ static struct spi_board_info pcontrol_g20_spi_devices[] = {  }; -/* - * Dallas 1-Wire  DS2431 - */ -static struct w1_gpio_platform_data w1_gpio_pdata = { -	.pin		= AT91_PIN_PA29, -	.is_open_drain	= 1, -}; - -static struct platform_device w1_device = { -	.name			= "w1-gpio", -	.id			= -1, -	.dev.platform_data	= &w1_gpio_pdata, -}; - -static void add_wire1(void) -{ -	at91_set_GPIO_periph(w1_gpio_pdata.pin, 1); -	at91_set_multi_drive(w1_gpio_pdata.pin, 1); -	platform_device_register(&w1_device); -} - -  static void __init pcontrol_g20_board_init(void)  { -	at91_add_device_serial(); -	add_device_nand(); -#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) -	at91_add_device_mci(0, &mmc_data); -#else -	at91_add_device_mmc(0, &mmc_data); -#endif +	stamp9g20_board_init();  	at91_add_device_usbh(&usbh_data);  	at91_add_device_eth(&macb_data);  	at91_add_device_i2c(pcontrol_g20_i2c_devices,  		ARRAY_SIZE(pcontrol_g20_i2c_devices)); -	add_wire1();  	add_device_pcontrol();  	at91_add_device_spi(pcontrol_g20_spi_devices,  		ARRAY_SIZE(pcontrol_g20_spi_devices)); diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c index 5206eef4a67..f8902b11896 100644 --- a/arch/arm/mach-at91/board-stamp9g20.c +++ b/arch/arm/mach-at91/board-stamp9g20.c @@ -32,7 +32,7 @@  #include "generic.h" -static void __init portuxg20_map_io(void) +void __init stamp9g20_map_io(void)  {  	/* Initialize processor: 18.432 MHz crystal */  	at91sam9260_initialize(18432000); @@ -40,6 +40,24 @@ static void __init portuxg20_map_io(void)  	/* DGBU on ttyS0. (Rx & Tx only) */  	at91_register_uart(0, 0, 0); +	/* set serial console to ttyS0 (ie, DBGU) */ +	at91_set_serial_console(0); +} + +static void __init stamp9g20evb_map_io(void) +{ +	stamp9g20_map_io(); + +	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ +	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS +						| ATMEL_UART_DTR | ATMEL_UART_DSR +						| ATMEL_UART_DCD | ATMEL_UART_RI); +} + +static void __init portuxg20_map_io(void) +{ +	stamp9g20_map_io(); +  	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */  	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS  						| ATMEL_UART_DTR | ATMEL_UART_DSR @@ -56,26 +74,6 @@ static void __init portuxg20_map_io(void)  	/* USART5 on ttyS6. (Rx, Tx only) */  	at91_register_uart(AT91SAM9260_ID_US5, 6, 0); - -	/* set serial console to ttyS0 (ie, DBGU) */ -	at91_set_serial_console(0); -} - -static void __init stamp9g20_map_io(void) -{ -	/* Initialize processor: 18.432 MHz crystal */ -	at91sam9260_initialize(18432000); - -	/* DGBU on ttyS0. (Rx & Tx only) */ -	at91_register_uart(0, 0, 0); - -	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ -	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS -						| ATMEL_UART_DTR | ATMEL_UART_DSR -						| ATMEL_UART_DCD | ATMEL_UART_RI); - -	/* set serial console to ttyS0 (ie, DBGU) */ -	at91_set_serial_console(0);  }  static void __init init_irq(void) @@ -156,7 +154,7 @@ static struct at91_udc_data __initdata portuxg20_udc_data = {  	.pullup_pin	= 0,		/* pull-up driven by UDC */  }; -static struct at91_udc_data __initdata stamp9g20_udc_data = { +static struct at91_udc_data __initdata stamp9g20evb_udc_data = {  	.vbus_pin	= AT91_PIN_PA22,  	.pullup_pin	= 0,		/* pull-up driven by UDC */  }; @@ -190,7 +188,7 @@ static struct gpio_led portuxg20_leds[] = {  	}  }; -static struct gpio_led stamp9g20_leds[] = { +static struct gpio_led stamp9g20evb_leds[] = {  	{  		.name			= "D8",  		.gpio			= AT91_PIN_PB18, @@ -250,7 +248,7 @@ void add_w1(void)  } -static void __init generic_board_init(void) +void __init stamp9g20_board_init(void)  {  	/* Serial */  	at91_add_device_serial(); @@ -262,34 +260,40 @@ static void __init generic_board_init(void)  #else  	at91_add_device_mmc(0, &mmc_data);  #endif -	/* USB Host */ -	at91_add_device_usbh(&usbh_data); -	/* Ethernet */ -	at91_add_device_eth(&macb_data); -	/* I2C */ -	at91_add_device_i2c(NULL, 0);  	/* W1 */  	add_w1();  }  static void __init portuxg20_board_init(void)  { -	generic_board_init(); -	/* SPI */ -	at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices)); +	stamp9g20_board_init(); +	/* USB Host */ +	at91_add_device_usbh(&usbh_data);  	/* USB Device */  	at91_add_device_udc(&portuxg20_udc_data); +	/* Ethernet */ +	at91_add_device_eth(&macb_data); +	/* I2C */ +	at91_add_device_i2c(NULL, 0); +	/* SPI */ +	at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices));  	/* LEDs */  	at91_gpio_leds(portuxg20_leds, ARRAY_SIZE(portuxg20_leds));  } -static void __init stamp9g20_board_init(void) +static void __init stamp9g20evb_board_init(void)  { -	generic_board_init(); +	stamp9g20_board_init(); +	/* USB Host */ +	at91_add_device_usbh(&usbh_data);  	/* USB Device */ -	at91_add_device_udc(&stamp9g20_udc_data); +	at91_add_device_udc(&stamp9g20evb_udc_data); +	/* Ethernet */ +	at91_add_device_eth(&macb_data); +	/* I2C */ +	at91_add_device_i2c(NULL, 0);  	/* LEDs */ -	at91_gpio_leds(stamp9g20_leds, ARRAY_SIZE(stamp9g20_leds)); +	at91_gpio_leds(stamp9g20evb_leds, ARRAY_SIZE(stamp9g20evb_leds));  }  MACHINE_START(PORTUXG20, "taskit PortuxG20") @@ -305,7 +309,7 @@ MACHINE_START(STAMP9G20, "taskit Stamp9G20")  	/* Maintainer: taskit GmbH */  	.boot_params	= AT91_SDRAM_BASE + 0x100,  	.timer		= &at91sam926x_timer, -	.map_io		= stamp9g20_map_io, +	.map_io		= stamp9g20evb_map_io,  	.init_irq	= init_irq, -	.init_machine	= stamp9g20_board_init, +	.init_machine	= stamp9g20evb_board_init,  MACHINE_END diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 7525cee3983..9113da6845f 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -658,7 +658,7 @@ static void __init at91_upll_usbfs_clock_init(unsigned long main_clock)  	/* Now set uhpck values */  	uhpck.parent = &utmi_clk;  	uhpck.pmc_mask = AT91SAM926x_PMC_UHP; -	uhpck.rate_hz = utmi_clk.parent->rate_hz; +	uhpck.rate_hz = utmi_clk.rate_hz;  	uhpck.rate_hz /= 1 + ((at91_sys_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8);  } diff --git a/arch/arm/mach-at91/include/mach/at91_mci.h b/arch/arm/mach-at91/include/mach/at91_mci.h index 57f8ee15494..27ac6f550fe 100644 --- a/arch/arm/mach-at91/include/mach/at91_mci.h +++ b/arch/arm/mach-at91/include/mach/at91_mci.h @@ -74,6 +74,8 @@  #define			AT91_MCI_TRTYP_BLOCK	(0 << 19)  #define			AT91_MCI_TRTYP_MULTIPLE	(1 << 19)  #define			AT91_MCI_TRTYP_STREAM	(2 << 19) +#define			AT91_MCI_TRTYP_SDIO_BYTE	(4 << 19) +#define			AT91_MCI_TRTYP_SDIO_BLOCK	(5 << 19)  #define AT91_MCI_BLKR		0x18		/* Block Register */  #define		AT91_MCI_BLKR_BCNT(n)	((0xffff & (n)) << 0)	/* Block count */ diff --git a/arch/arm/mach-at91/include/mach/stamp9g20.h b/arch/arm/mach-at91/include/mach/stamp9g20.h new file mode 100644 index 00000000000..6120f9c46d5 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/stamp9g20.h @@ -0,0 +1,7 @@ +#ifndef __MACH_STAMP9G20_H +#define __MACH_STAMP9G20_H + +void stamp9g20_map_io(void); +void stamp9g20_board_init(void); + +#endif diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index 24498a932ba..a54b3db8036 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c @@ -513,4 +513,4 @@ int dma_set_coherent_mask(struct device *dev, u64 mask)  EXPORT_SYMBOL(ixp4xx_pci_read);  EXPORT_SYMBOL(ixp4xx_pci_write); - +EXPORT_SYMBOL(dma_set_coherent_mask); diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index dd235ecc9d6..c93e73d54dd 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -540,6 +540,7 @@ config MACH_ICONTROL  config ARCH_PXA_ESERIES  	bool "PXA based Toshiba e-series PDAs"  	select PXA25x +	select FB_W100  config MACH_E330  	bool "Toshiba e330" diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S index 52c30b01a67..ae008110db4 100644 --- a/arch/arm/mach-pxa/sleep.S +++ b/arch/arm/mach-pxa/sleep.S @@ -353,8 +353,8 @@ resume_turn_on_mmu:  	@ Let us ensure we jump to resume_after_mmu only when the mcr above  	@ actually took effect.  They call it the "cpwait" operation. -	mrc	p15, 0, r1, c2, c0, 0		@ queue a dependency on CP15 -	sub	pc, r2, r1, lsr #32		@ jump to virtual addr +	mrc	p15, 0, r0, c2, c0, 0		@ queue a dependency on CP15 +	sub	pc, r2, r0, lsr #32		@ jump to virtual addr  	nop  	nop  	nop diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig index fa2e5bffbb8..6983cb4d4ca 100644 --- a/arch/arm/mach-s3c2412/Kconfig +++ b/arch/arm/mach-s3c2412/Kconfig @@ -28,9 +28,16 @@ config S3C2412_DMA  config S3C2412_PM  	bool +	select S3C2412_PM_SLEEP  	help  	  Internal config node to apply S3C2412 power management +config S3C2412_PM_SLEEP +	bool +	help +	  Internal config node to apply sleep for S3C2412 power management. +	  Can be selected by another SoCs with similar sleep procedure. +  # Note, the S3C2412 IOtiming support is in plat-s3c24xx  config S3C2412_CPUFREQ diff --git a/arch/arm/mach-s3c2412/Makefile b/arch/arm/mach-s3c2412/Makefile index 530ec46cbae..6c48a91ea39 100644 --- a/arch/arm/mach-s3c2412/Makefile +++ b/arch/arm/mach-s3c2412/Makefile @@ -14,7 +14,8 @@ obj-$(CONFIG_CPU_S3C2412)	+= irq.o  obj-$(CONFIG_CPU_S3C2412)	+= clock.o  obj-$(CONFIG_CPU_S3C2412)	+= gpio.o  obj-$(CONFIG_S3C2412_DMA)	+= dma.o -obj-$(CONFIG_S3C2412_PM)	+= pm.o sleep.o +obj-$(CONFIG_S3C2412_PM)	+= pm.o +obj-$(CONFIG_S3C2412_PM_SLEEP)	+= sleep.o  obj-$(CONFIG_S3C2412_CPUFREQ)	+= cpu-freq.o  # Machine support diff --git a/arch/arm/mach-s3c2416/Kconfig b/arch/arm/mach-s3c2416/Kconfig index 27b3e7c9d61..df8d14974c9 100644 --- a/arch/arm/mach-s3c2416/Kconfig +++ b/arch/arm/mach-s3c2416/Kconfig @@ -27,6 +27,7 @@ config S3C2416_DMA  config S3C2416_PM  	bool +	select S3C2412_PM_SLEEP  	help  	  Internal config node to apply S3C2416 power management diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index 28677caf361..461aa035afc 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c @@ -378,6 +378,12 @@ static struct max8998_regulator_data aquila_regulators[] = {  static struct max8998_platform_data aquila_max8998_pdata = {  	.num_regulators	= ARRAY_SIZE(aquila_regulators),  	.regulators	= aquila_regulators, +	.buck1_set1	= S5PV210_GPH0(3), +	.buck1_set2	= S5PV210_GPH0(4), +	.buck2_set3	= S5PV210_GPH0(5), +	.buck1_max_voltage1 = 1200000, +	.buck1_max_voltage2 = 1200000, +	.buck2_max_voltage = 1200000,  };  #endif diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index b1dcf964a76..e22d5112fd4 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -518,6 +518,12 @@ static struct max8998_regulator_data goni_regulators[] = {  static struct max8998_platform_data goni_max8998_pdata = {  	.num_regulators	= ARRAY_SIZE(goni_regulators),  	.regulators	= goni_regulators, +	.buck1_set1	= S5PV210_GPH0(3), +	.buck1_set2	= S5PV210_GPH0(4), +	.buck2_set3	= S5PV210_GPH0(5), +	.buck1_max_voltage1 = 1200000, +	.buck1_max_voltage2 = 1200000, +	.buck2_max_voltage = 1200000,  };  #endif diff --git a/arch/arm/mach-shmobile/include/mach/entry-macro.S b/arch/arm/mach-shmobile/include/mach/entry-macro.S index a285d13c741..f428c4db2b6 100644 --- a/arch/arm/mach-shmobile/include/mach/entry-macro.S +++ b/arch/arm/mach-shmobile/include/mach/entry-macro.S @@ -1,4 +1,5 @@  /* + * Copyright (C) 2010 Magnus Damm   * Copyright (C) 2008 Renesas Solutions Corp.   *   * This program is free software; you can redistribute it and/or modify @@ -14,24 +15,45 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA   */ -#include <mach/hardware.h>  #include <mach/irqs.h> +#define INTCA_BASE	0xe6980000 +#define INTFLGA_OFFS	0x00000018 /* accept pending interrupt */ +#define INTEVTA_OFFS	0x00000020 /* vector number of accepted interrupt */ +#define INTLVLA_OFFS	0x00000030 /* priority level of accepted interrupt */ +#define INTLVLB_OFFS	0x00000034 /* previous priority level */ +  	.macro  disable_fiq  	.endm  	.macro  get_irqnr_preamble, base, tmp -	ldr     \base, =INTFLGA +	ldr     \base, =INTCA_BASE  	.endm  	.macro  arch_ret_to_user, tmp1, tmp2  	.endm  	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp -	ldr     \irqnr, [\base] +	/* The single INTFLGA read access below results in the following: +	 * +	 * 1. INTLVLB is updated with old priority value from INTLVLA +	 * 2. Highest priority interrupt is accepted +	 * 3. INTLVLA is updated to contain priority of accepted interrupt +	 * 4. Accepted interrupt vector is stored in INTFLGA and INTEVTA +	 */ +	ldr     \irqnr, [\base, #INTFLGA_OFFS] + +	/* Restore INTLVLA with the value saved in INTLVLB. +	 * This is required to support interrupt priorities properly. +	 */ +	ldrb	\tmp, [\base, #INTLVLB_OFFS] +	strb    \tmp, [\base, #INTLVLA_OFFS] + +	/* Handle invalid vector number case */  	cmp	\irqnr, #0  	beq	1000f -	/* intevt to irq number */ + +	/* Convert vector to irq number, same as the evt2irq() macro */  	lsr	\irqnr, \irqnr, #0x5  	subs	\irqnr, \irqnr, #16 diff --git a/arch/arm/mach-shmobile/include/mach/vmalloc.h b/arch/arm/mach-shmobile/include/mach/vmalloc.h index 4aecf6e3a85..2b8fd8b942f 100644 --- a/arch/arm/mach-shmobile/include/mach/vmalloc.h +++ b/arch/arm/mach-shmobile/include/mach/vmalloc.h @@ -2,6 +2,6 @@  #define __ASM_MACH_VMALLOC_H  /* Vmalloc at ... - 0xe5ffffff */ -#define VMALLOC_END 0xe6000000 +#define VMALLOC_END 0xe6000000UL  #endif /* __ASM_MACH_VMALLOC_H */ diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c index 6e77c042d8e..e0b0e7a4ec6 100644 --- a/arch/arm/mm/cache-feroceon-l2.c +++ b/arch/arm/mm/cache-feroceon-l2.c @@ -13,13 +13,9 @@   */  #include <linux/init.h> +#include <linux/highmem.h>  #include <asm/cacheflush.h> -#include <asm/kmap_types.h> -#include <asm/fixmap.h> -#include <asm/pgtable.h> -#include <asm/tlbflush.h>  #include <plat/cache-feroceon-l2.h> -#include "mm.h"  /*   * Low-level cache maintenance operations. @@ -39,27 +35,30 @@   * between which we don't want to be preempted.   */ -static inline unsigned long l2_start_va(unsigned long paddr) +static inline unsigned long l2_get_va(unsigned long paddr)  {  #ifdef CONFIG_HIGHMEM  	/* -	 * Let's do our own fixmap stuff in a minimal way here.  	 * Because range ops can't be done on physical addresses,  	 * we simply install a virtual mapping for it only for the  	 * TLB lookup to occur, hence no need to flush the untouched -	 * memory mapping.  This is protected with the disabling of -	 * interrupts by the caller. +	 * memory mapping afterwards (note: a cache flush may happen +	 * in some circumstances depending on the path taken in kunmap_atomic).  	 */ -	unsigned long idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id(); -	unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); -	set_pte_ext(TOP_PTE(vaddr), pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL), 0); -	local_flush_tlb_kernel_page(vaddr); -	return vaddr + (paddr & ~PAGE_MASK); +	void *vaddr = kmap_atomic_pfn(paddr >> PAGE_SHIFT); +	return (unsigned long)vaddr + (paddr & ~PAGE_MASK);  #else  	return __phys_to_virt(paddr);  #endif  } +static inline void l2_put_va(unsigned long vaddr) +{ +#ifdef CONFIG_HIGHMEM +	kunmap_atomic((void *)vaddr); +#endif +} +  static inline void l2_clean_pa(unsigned long addr)  {  	__asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr)); @@ -76,13 +75,14 @@ static inline void l2_clean_pa_range(unsigned long start, unsigned long end)  	 */  	BUG_ON((start ^ end) >> PAGE_SHIFT); -	raw_local_irq_save(flags); -	va_start = l2_start_va(start); +	va_start = l2_get_va(start);  	va_end = va_start + (end - start); +	raw_local_irq_save(flags);  	__asm__("mcr p15, 1, %0, c15, c9, 4\n\t"  		"mcr p15, 1, %1, c15, c9, 5"  		: : "r" (va_start), "r" (va_end));  	raw_local_irq_restore(flags); +	l2_put_va(va_start);  }  static inline void l2_clean_inv_pa(unsigned long addr) @@ -106,13 +106,14 @@ static inline void l2_inv_pa_range(unsigned long start, unsigned long end)  	 */  	BUG_ON((start ^ end) >> PAGE_SHIFT); -	raw_local_irq_save(flags); -	va_start = l2_start_va(start); +	va_start = l2_get_va(start);  	va_end = va_start + (end - start); +	raw_local_irq_save(flags);  	__asm__("mcr p15, 1, %0, c15, c11, 4\n\t"  		"mcr p15, 1, %1, c15, c11, 5"  		: : "r" (va_start), "r" (va_end));  	raw_local_irq_restore(flags); +	l2_put_va(va_start);  }  static inline void l2_inv_all(void) diff --git a/arch/arm/mm/cache-xsc3l2.c b/arch/arm/mm/cache-xsc3l2.c index c3154928bcc..5a32020471e 100644 --- a/arch/arm/mm/cache-xsc3l2.c +++ b/arch/arm/mm/cache-xsc3l2.c @@ -17,14 +17,10 @@   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA   */  #include <linux/init.h> +#include <linux/highmem.h>  #include <asm/system.h>  #include <asm/cputype.h>  #include <asm/cacheflush.h> -#include <asm/kmap_types.h> -#include <asm/fixmap.h> -#include <asm/pgtable.h> -#include <asm/tlbflush.h> -#include "mm.h"  #define CR_L2	(1 << 26) @@ -71,16 +67,15 @@ static inline void xsc3_l2_inv_all(void)  	dsb();  } +static inline void l2_unmap_va(unsigned long va) +{  #ifdef CONFIG_HIGHMEM -#define l2_map_save_flags(x)		raw_local_save_flags(x) -#define l2_map_restore_flags(x)		raw_local_irq_restore(x) -#else -#define l2_map_save_flags(x)		((x) = 0) -#define l2_map_restore_flags(x)		((void)(x)) +	if (va != -1) +		kunmap_atomic((void *)va);  #endif +} -static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va, -				      unsigned long flags) +static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va)  {  #ifdef CONFIG_HIGHMEM  	unsigned long va = prev_va & PAGE_MASK; @@ -89,17 +84,10 @@ static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,  		/*  		 * Switching to a new page.  Because cache ops are  		 * using virtual addresses only, we must put a mapping -		 * in place for it.  We also enable interrupts for a -		 * short while and disable them again to protect this -		 * mapping. +		 * in place for it.  		 */ -		unsigned long idx; -		raw_local_irq_restore(flags); -		idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id(); -		va = __fix_to_virt(FIX_KMAP_BEGIN + idx); -		raw_local_irq_restore(flags | PSR_I_BIT); -		set_pte_ext(TOP_PTE(va), pfn_pte(pa >> PAGE_SHIFT, PAGE_KERNEL), 0); -		local_flush_tlb_kernel_page(va); +		l2_unmap_va(prev_va); +		va = (unsigned long)kmap_atomic_pfn(pa >> PAGE_SHIFT);  	}  	return va + (pa_offset >> (32 - PAGE_SHIFT));  #else @@ -109,7 +97,7 @@ static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,  static void xsc3_l2_inv_range(unsigned long start, unsigned long end)  { -	unsigned long vaddr, flags; +	unsigned long vaddr;  	if (start == 0 && end == -1ul) {  		xsc3_l2_inv_all(); @@ -117,13 +105,12 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)  	}  	vaddr = -1;  /* to force the first mapping */ -	l2_map_save_flags(flags);  	/*  	 * Clean and invalidate partial first cache line.  	 */  	if (start & (CACHE_LINE_SIZE - 1)) { -		vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr, flags); +		vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr);  		xsc3_l2_clean_mva(vaddr);  		xsc3_l2_inv_mva(vaddr);  		start = (start | (CACHE_LINE_SIZE - 1)) + 1; @@ -133,7 +120,7 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)  	 * Invalidate all full cache lines between 'start' and 'end'.  	 */  	while (start < (end & ~(CACHE_LINE_SIZE - 1))) { -		vaddr = l2_map_va(start, vaddr, flags); +		vaddr = l2_map_va(start, vaddr);  		xsc3_l2_inv_mva(vaddr);  		start += CACHE_LINE_SIZE;  	} @@ -142,31 +129,30 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)  	 * Clean and invalidate partial last cache line.  	 */  	if (start < end) { -		vaddr = l2_map_va(start, vaddr, flags); +		vaddr = l2_map_va(start, vaddr);  		xsc3_l2_clean_mva(vaddr);  		xsc3_l2_inv_mva(vaddr);  	} -	l2_map_restore_flags(flags); +	l2_unmap_va(vaddr);  	dsb();  }  static void xsc3_l2_clean_range(unsigned long start, unsigned long end)  { -	unsigned long vaddr, flags; +	unsigned long vaddr;  	vaddr = -1;  /* to force the first mapping */ -	l2_map_save_flags(flags);  	start &= ~(CACHE_LINE_SIZE - 1);  	while (start < end) { -		vaddr = l2_map_va(start, vaddr, flags); +		vaddr = l2_map_va(start, vaddr);  		xsc3_l2_clean_mva(vaddr);  		start += CACHE_LINE_SIZE;  	} -	l2_map_restore_flags(flags); +	l2_unmap_va(vaddr);  	dsb();  } @@ -193,7 +179,7 @@ static inline void xsc3_l2_flush_all(void)  static void xsc3_l2_flush_range(unsigned long start, unsigned long end)  { -	unsigned long vaddr, flags; +	unsigned long vaddr;  	if (start == 0 && end == -1ul) {  		xsc3_l2_flush_all(); @@ -201,17 +187,16 @@ static void xsc3_l2_flush_range(unsigned long start, unsigned long end)  	}  	vaddr = -1;  /* to force the first mapping */ -	l2_map_save_flags(flags);  	start &= ~(CACHE_LINE_SIZE - 1);  	while (start < end) { -		vaddr = l2_map_va(start, vaddr, flags); +		vaddr = l2_map_va(start, vaddr);  		xsc3_l2_clean_mva(vaddr);  		xsc3_l2_inv_mva(vaddr);  		start += CACHE_LINE_SIZE;  	} -	l2_map_restore_flags(flags); +	l2_unmap_va(vaddr);  	dsb();  } diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index ac6a36142fc..809f1bf9fa2 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -17,6 +17,7 @@  #include <linux/init.h>  #include <linux/device.h>  #include <linux/dma-mapping.h> +#include <linux/highmem.h>  #include <asm/memory.h>  #include <asm/highmem.h> @@ -480,10 +481,10 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,  				op(vaddr, len, dir);  				kunmap_high(page);  			} else if (cache_is_vipt()) { -				pte_t saved_pte; -				vaddr = kmap_high_l1_vipt(page, &saved_pte); +				/* unmapped pages might still be cached */ +				vaddr = kmap_atomic(page);  				op(vaddr + offset, len, dir); -				kunmap_high_l1_vipt(page, saved_pte); +				kunmap_atomic(vaddr);  			}  		} else {  			vaddr = page_address(page) + offset; diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 391ffae7509..c29f2839f1d 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -10,6 +10,7 @@  #include <linux/module.h>  #include <linux/mm.h>  #include <linux/pagemap.h> +#include <linux/highmem.h>  #include <asm/cacheflush.h>  #include <asm/cachetype.h> @@ -180,10 +181,10 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page)  			__cpuc_flush_dcache_area(addr, PAGE_SIZE);  			kunmap_high(page);  		} else if (cache_is_vipt()) { -			pte_t saved_pte; -			addr = kmap_high_l1_vipt(page, &saved_pte); +			/* unmapped pages might still be cached */ +			addr = kmap_atomic(page);  			__cpuc_flush_dcache_area(addr, PAGE_SIZE); -			kunmap_high_l1_vipt(page, saved_pte); +			kunmap_atomic(addr);  		}  	} diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c index c435fd9e1da..807c0573abb 100644 --- a/arch/arm/mm/highmem.c +++ b/arch/arm/mm/highmem.c @@ -140,90 +140,3 @@ struct page *kmap_atomic_to_page(const void *ptr)  	pte = TOP_PTE(vaddr);  	return pte_page(*pte);  } - -#ifdef CONFIG_CPU_CACHE_VIPT - -#include <linux/percpu.h> - -/* - * The VIVT cache of a highmem page is always flushed before the page - * is unmapped. Hence unmapped highmem pages need no cache maintenance - * in that case. - * - * However unmapped pages may still be cached with a VIPT cache, and - * it is not possible to perform cache maintenance on them using physical - * addresses unfortunately.  So we have no choice but to set up a temporary - * virtual mapping for that purpose. - * - * Yet this VIPT cache maintenance may be triggered from DMA support - * functions which are possibly called from interrupt context. As we don't - * want to keep interrupt disabled all the time when such maintenance is - * taking place, we therefore allow for some reentrancy by preserving and - * restoring the previous fixmap entry before the interrupted context is - * resumed.  If the reentrancy depth is 0 then there is no need to restore - * the previous fixmap, and leaving the current one in place allow it to - * be reused the next time without a TLB flush (common with DMA). - */ - -static DEFINE_PER_CPU(int, kmap_high_l1_vipt_depth); - -void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte) -{ -	unsigned int idx, cpu; -	int *depth; -	unsigned long vaddr, flags; -	pte_t pte, *ptep; - -	if (!in_interrupt()) -		preempt_disable(); - -	cpu = smp_processor_id(); -	depth = &per_cpu(kmap_high_l1_vipt_depth, cpu); - -	idx = KM_L1_CACHE + KM_TYPE_NR * cpu; -	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); -	ptep = TOP_PTE(vaddr); -	pte = mk_pte(page, kmap_prot); - -	raw_local_irq_save(flags); -	(*depth)++; -	if (pte_val(*ptep) == pte_val(pte)) { -		*saved_pte = pte; -	} else { -		*saved_pte = *ptep; -		set_pte_ext(ptep, pte, 0); -		local_flush_tlb_kernel_page(vaddr); -	} -	raw_local_irq_restore(flags); - -	return (void *)vaddr; -} - -void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte) -{ -	unsigned int idx, cpu = smp_processor_id(); -	int *depth = &per_cpu(kmap_high_l1_vipt_depth, cpu); -	unsigned long vaddr, flags; -	pte_t pte, *ptep; - -	idx = KM_L1_CACHE + KM_TYPE_NR * cpu; -	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); -	ptep = TOP_PTE(vaddr); -	pte = mk_pte(page, kmap_prot); - -	BUG_ON(pte_val(*ptep) != pte_val(pte)); -	BUG_ON(*depth <= 0); - -	raw_local_irq_save(flags); -	(*depth)--; -	if (*depth != 0 && pte_val(pte) != pte_val(saved_pte)) { -		set_pte_ext(ptep, saved_pte, 0); -		local_flush_tlb_kernel_page(vaddr); -	} -	raw_local_irq_restore(flags); - -	if (!in_interrupt()) -		preempt_enable(); -} - -#endif  /* CONFIG_CPU_CACHE_VIPT */ diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig index 5a27b1b538f..eb105e61c74 100644 --- a/arch/arm/plat-s3c24xx/Kconfig +++ b/arch/arm/plat-s3c24xx/Kconfig @@ -8,7 +8,7 @@ config PLAT_S3C24XX  	default y  	select NO_IOPORT  	select ARCH_REQUIRE_GPIOLIB -	select S3C_DEVICE_NAND +	select S3C_DEV_NAND  	select S3C_GPIO_CFG_S3C24XX  	help  	  Base platform code for any Samsung S3C24XX device diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 67a2fa2caa4..0a9b5b8b2a1 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -19,6 +19,8 @@ config MIPS  	select GENERIC_ATOMIC64 if !64BIT  	select HAVE_DMA_ATTRS  	select HAVE_DMA_API_DEBUG +	select HAVE_GENERIC_HARDIRQS +	select GENERIC_IRQ_PROBE  menu "Machine selection" @@ -1664,6 +1666,28 @@ config PAGE_SIZE_64KB  endchoice +config FORCE_MAX_ZONEORDER +	int "Maximum zone order" +	range 13 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB +	default "13" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB +	range 12 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB +	default "12" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB +	range 11 64 +	default "11" +	help +	  The kernel memory allocator divides physically contiguous memory +	  blocks into "zones", where each zone is a power of two number of +	  pages.  This option selects the largest power of two that the kernel +	  keeps in the memory allocator.  If you need to allocate very large +	  blocks of physically contiguous memory, then you may need to +	  increase this value. + +	  This config option is actually maximum order plus one. For example, +	  a value of 11 means that the largest free memory block is 2^10 pages. + +	  The page size is not necessarily 4KB.  Keep this in mind +	  when choosing a value for this option. +  config BOARD_SCACHE  	bool @@ -1922,20 +1946,6 @@ config CPU_R4400_WORKAROUNDS  	bool  # -# Use the generic interrupt handling code in kernel/irq/: -# -config GENERIC_HARDIRQS -	bool -	default y - -config GENERIC_IRQ_PROBE -	bool -	default y - -config IRQ_PER_CPU -	bool - -#  # - Highmem only makes sense for the 32-bit kernel.  # - The current highmem code will only work properly on physically indexed  #   caches such as R3000, SB1, R7000 or those that look like they're virtually diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index 3691630931d..9e7814db3d0 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c @@ -27,6 +27,7 @@  static void alchemy_8250_pm(struct uart_port *port, unsigned int state,  			    unsigned int old_state)  { +#ifdef CONFIG_SERIAL_8250  	switch (state) {  	case 0:  		if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) { @@ -49,6 +50,7 @@ static void alchemy_8250_pm(struct uart_port *port, unsigned int state,  		serial8250_do_pm(port, state, old_state);  		break;  	} +#endif  }  #define PORT(_base, _irq)					\ diff --git a/arch/mips/alchemy/devboards/prom.c b/arch/mips/alchemy/devboards/prom.c index b30df5c97ad..baeb2138505 100644 --- a/arch/mips/alchemy/devboards/prom.c +++ b/arch/mips/alchemy/devboards/prom.c @@ -54,10 +54,9 @@ void __init prom_init(void)  	prom_init_cmdline();  	memsize_str = prom_getenv("memsize"); -	if (!memsize_str) +	if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize))  		memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE; -	else -		strict_strtoul(memsize_str, 0, &memsize); +  	add_memory_region(0, memsize, BOOT_MEM_RAM);  } diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c index fc0e7154e8d..2ca4ada1c29 100644 --- a/arch/mips/ar7/clock.c +++ b/arch/mips/ar7/clock.c @@ -239,12 +239,12 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,  	calculate(base_clock, frequency, &prediv, &postdiv, &mul);  	writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl); -	msleep(1); +	mdelay(1);  	writel(4, &clock->pll);  	while (readl(&clock->pll) & PLL_STATUS)  		;  	writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll); -	msleep(75); +	mdelay(75);  }  static void __init tnetd7300_init_clocks(void) @@ -456,7 +456,7 @@ void clk_put(struct clk *clk)  }  EXPORT_SYMBOL(clk_put); -int __init ar7_init_clocks(void) +void __init ar7_init_clocks(void)  {  	switch (ar7_chip_id()) {  	case AR7_CHIP_7100: @@ -472,7 +472,4 @@ int __init ar7_init_clocks(void)  	}  	/* adjust vbus clock rate */  	vbus_clk.rate = bus_clk.rate / 2; - -	return 0;  } -arch_initcall(ar7_init_clocks); diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c index 5fb8a013408..22c93213b23 100644 --- a/arch/mips/ar7/time.c +++ b/arch/mips/ar7/time.c @@ -30,6 +30,9 @@ void __init plat_time_init(void)  {  	struct clk *cpu_clk; +	/* Initialize ar7 clocks so the CPU clock frequency is correct */ +	ar7_init_clocks(); +  	cpu_clk = clk_get(NULL, "cpu");  	if (IS_ERR(cpu_clk)) {  		printk(KERN_ERR "unable to get cpu clock\n"); diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index b1aee33efd1..c95f90bf734 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -32,7 +32,6 @@  #include <asm/reboot.h>  #include <asm/time.h>  #include <bcm47xx.h> -#include <asm/fw/cfe/cfe_api.h>  #include <asm/mach-bcm47xx/nvram.h>  struct ssb_bus ssb_bcm47xx; @@ -57,68 +56,112 @@ static void bcm47xx_machine_halt(void)  		cpu_relax();  } -static void str2eaddr(char *str, char *dest) +#define READ_FROM_NVRAM(_outvar, name, buf) \ +	if (nvram_getenv(name, buf, sizeof(buf)) >= 0)\ +		sprom->_outvar = simple_strtoul(buf, NULL, 0); + +static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)  { -	int i = 0; +	char buf[100]; +	u32 boardflags; -	if (str == NULL) { -		memset(dest, 0, 6); -		return; -	} +	memset(sprom, 0, sizeof(struct ssb_sprom)); + +	sprom->revision = 1; /* Fallback: Old hardware does not define this. */ +	READ_FROM_NVRAM(revision, "sromrev", buf); +	if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0) +		nvram_parse_macaddr(buf, sprom->il0mac); +	if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0) +		nvram_parse_macaddr(buf, sprom->et0mac); +	if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0) +		nvram_parse_macaddr(buf, sprom->et1mac); +	READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf); +	READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf); +	READ_FROM_NVRAM(et0mdcport, "et0mdcport", buf); +	READ_FROM_NVRAM(et1mdcport, "et1mdcport", buf); +	READ_FROM_NVRAM(board_rev, "boardrev", buf); +	READ_FROM_NVRAM(country_code, "ccode", buf); +	READ_FROM_NVRAM(ant_available_a, "aa5g", buf); +	READ_FROM_NVRAM(ant_available_bg, "aa2g", buf); +	READ_FROM_NVRAM(pa0b0, "pa0b0", buf); +	READ_FROM_NVRAM(pa0b1, "pa0b1", buf); +	READ_FROM_NVRAM(pa0b2, "pa0b2", buf); +	READ_FROM_NVRAM(pa1b0, "pa1b0", buf); +	READ_FROM_NVRAM(pa1b1, "pa1b1", buf); +	READ_FROM_NVRAM(pa1b2, "pa1b2", buf); +	READ_FROM_NVRAM(pa1lob0, "pa1lob0", buf); +	READ_FROM_NVRAM(pa1lob2, "pa1lob1", buf); +	READ_FROM_NVRAM(pa1lob1, "pa1lob2", buf); +	READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf); +	READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf); +	READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf); +	READ_FROM_NVRAM(gpio0, "wl0gpio0", buf); +	READ_FROM_NVRAM(gpio1, "wl0gpio1", buf); +	READ_FROM_NVRAM(gpio2, "wl0gpio2", buf); +	READ_FROM_NVRAM(gpio3, "wl0gpio3", buf); +	READ_FROM_NVRAM(maxpwr_bg, "pa0maxpwr", buf); +	READ_FROM_NVRAM(maxpwr_al, "pa1lomaxpwr", buf); +	READ_FROM_NVRAM(maxpwr_a, "pa1maxpwr", buf); +	READ_FROM_NVRAM(maxpwr_ah, "pa1himaxpwr", buf); +	READ_FROM_NVRAM(itssi_a, "pa1itssit", buf); +	READ_FROM_NVRAM(itssi_bg, "pa0itssit", buf); +	READ_FROM_NVRAM(tri2g, "tri2g", buf); +	READ_FROM_NVRAM(tri5gl, "tri5gl", buf); +	READ_FROM_NVRAM(tri5g, "tri5g", buf); +	READ_FROM_NVRAM(tri5gh, "tri5gh", buf); +	READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf); +	READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf); +	READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf); +	READ_FROM_NVRAM(rssismc2g, "rssismc2g", buf); +	READ_FROM_NVRAM(rssismf2g, "rssismf2g", buf); +	READ_FROM_NVRAM(bxa2g, "bxa2g", buf); +	READ_FROM_NVRAM(rssisav5g, "rssisav5g", buf); +	READ_FROM_NVRAM(rssismc5g, "rssismc5g", buf); +	READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf); +	READ_FROM_NVRAM(bxa5g, "bxa5g", buf); +	READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf); +	READ_FROM_NVRAM(ofdm2gpo, "ofdm2gpo", buf); +	READ_FROM_NVRAM(ofdm5glpo, "ofdm5glpo", buf); +	READ_FROM_NVRAM(ofdm5gpo, "ofdm5gpo", buf); +	READ_FROM_NVRAM(ofdm5ghpo, "ofdm5ghpo", buf); -	for (;;) { -		dest[i++] = (char) simple_strtoul(str, NULL, 16); -		str += 2; -		if (!*str++ || i == 6) -			break; +	if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0) { +		boardflags = simple_strtoul(buf, NULL, 0); +		if (boardflags) { +			sprom->boardflags_lo = (boardflags & 0x0000FFFFU); +			sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16; +		} +	} +	if (nvram_getenv("boardflags2", buf, sizeof(buf)) >= 0) { +		boardflags = simple_strtoul(buf, NULL, 0); +		if (boardflags) { +			sprom->boardflags2_lo = (boardflags & 0x0000FFFFU); +			sprom->boardflags2_hi = (boardflags & 0xFFFF0000U) >> 16; +		}  	}  }  static int bcm47xx_get_invariants(struct ssb_bus *bus,  				   struct ssb_init_invariants *iv)  { -	char buf[100]; +	char buf[20];  	/* Fill boardinfo structure */  	memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo)); -	if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0) +	if (nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0) +		iv->boardinfo.vendor = (u16)simple_strtoul(buf, NULL, 0); +	else +		iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM; +	if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)  		iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); -	if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("boardtype", buf, sizeof(buf)) >= 0) -		iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); -	if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("boardrev", buf, sizeof(buf)) >= 0) +	if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)  		iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0); -	/* Fill sprom structure */ -	memset(&(iv->sprom), 0, sizeof(struct ssb_sprom)); -	iv->sprom.revision = 3; - -	if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0) -		str2eaddr(buf, iv->sprom.et0mac); +	bcm47xx_fill_sprom(&iv->sprom); -	if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0) -		str2eaddr(buf, iv->sprom.et1mac); - -	if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0) -		iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0); - -	if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0) -		iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0); - -	if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0) -		iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10); - -	if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0) -		iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10); +	if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) +		iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);  	return 0;  } @@ -126,12 +169,28 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,  void __init plat_mem_setup(void)  {  	int err; +	char buf[100]; +	struct ssb_mipscore *mcore;  	err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,  				      bcm47xx_get_invariants);  	if (err)  		panic("Failed to initialize SSB bus (err %d)\n", err); +	mcore = &ssb_bcm47xx.mipscore; +	if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) { +		if (strstr(buf, "console=ttyS1")) { +			struct ssb_serial_port port; + +			printk(KERN_DEBUG "Swapping serial ports!\n"); +			/* swap serial ports */ +			memcpy(&port, &mcore->serial_ports[0], sizeof(port)); +			memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], +			       sizeof(port)); +			memcpy(&mcore->serial_ports[1], &port, sizeof(port)); +		} +	} +  	_machine_restart = bcm47xx_machine_restart;  	_machine_halt = bcm47xx_machine_halt;  	pm_power_off = bcm47xx_machine_halt; diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 06d59dcbe24..86877539c6e 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -111,8 +111,8 @@   * These are the PRID's for when 23:16 == PRID_COMP_BROADCOM   */ -#define PRID_IMP_BMIPS4KC	0x4000 -#define PRID_IMP_BMIPS32	0x8000 +#define PRID_IMP_BMIPS32_REV4	0x4000 +#define PRID_IMP_BMIPS32_REV8	0x8000  #define PRID_IMP_BMIPS3300	0x9000  #define PRID_IMP_BMIPS3300_ALT	0x9100  #define PRID_IMP_BMIPS3300_BUG	0x0000 diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index fd1d39eb743..455c0ac7d4e 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -249,7 +249,8 @@ extern struct mips_abi mips_abi_n32;  #define SET_PERSONALITY(ex)						\  do {									\ -	set_personality(PER_LINUX);					\ +	if (personality(current->personality) != PER_LINUX)		\ +		set_personality(PER_LINUX);				\  									\  	current->thread.abi = &mips_abi;				\  } while (0) @@ -296,6 +297,8 @@ do {									\  #define SET_PERSONALITY(ex)						\  do {									\ +	unsigned int p;							\ +									\  	clear_thread_flag(TIF_32BIT_REGS);				\  	clear_thread_flag(TIF_32BIT_ADDR);				\  									\ @@ -304,7 +307,8 @@ do {									\  	else								\  		current->thread.abi = &mips_abi;			\  									\ -	if (current->personality != PER_LINUX32)			\ +	p = personality(current->personality);				\ +	if (p != PER_LINUX32 && p != PER_LINUX)				\  		set_personality(PER_LINUX);				\  } while (0) diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index c98bf514ec7..5b017f23e24 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -329,10 +329,14 @@ static inline void pfx##write##bwlq(type val,				\  			"dsrl32	%L0, %L0, 0"			"\n\t"	\  			"dsll32	%M0, %M0, 0"			"\n\t"	\  			"or	%L0, %L0, %M0"			"\n\t"	\ +			".set	push"				"\n\t"	\ +			".set	noreorder"			"\n\t"	\ +			".set	nomacro"			"\n\t"	\  			"sd	%L0, %2"			"\n\t"	\ +			".set	pop"				"\n\t"	\  			".set	mips0"				"\n"	\  			: "=r" (__tmp)					\ -			: "0" (__val), "m" (*__mem));			\ +			: "0" (__val), "R" (*__mem));			\  		if (irq)						\  			local_irq_restore(__flags);			\  	} else								\ @@ -355,12 +359,16 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem)	\  			local_irq_save(__flags);			\  		__asm__ __volatile__(					\  			".set	mips3"		"\t\t# __readq"	"\n\t"	\ +			".set	push"				"\n\t"	\ +			".set	noreorder"			"\n\t"	\ +			".set	nomacro"			"\n\t"	\  			"ld	%L0, %1"			"\n\t"	\ +			".set	pop"				"\n\t"	\  			"dsra32	%M0, %L0, 0"			"\n\t"	\  			"sll	%L0, %L0, 0"			"\n\t"	\  			".set	mips0"				"\n"	\  			: "=r" (__val)					\ -			: "m" (*__mem));				\ +			: "R" (*__mem));				\  		if (irq)						\  			local_irq_restore(__flags);			\  	} else {							\ diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h index 7919d76186b..07d3fadb244 100644 --- a/arch/mips/include/asm/mach-ar7/ar7.h +++ b/arch/mips/include/asm/mach-ar7/ar7.h @@ -201,7 +201,6 @@ static inline void ar7_device_off(u32 bit)  }  int __init ar7_gpio_init(void); - -int __init ar7_gpio_init(void); +void __init ar7_init_clocks(void);  #endif /* __AR7_H__ */ diff --git a/arch/mips/include/asm/mach-bcm47xx/nvram.h b/arch/mips/include/asm/mach-bcm47xx/nvram.h index c58ebd8bc15..9759588ba3c 100644 --- a/arch/mips/include/asm/mach-bcm47xx/nvram.h +++ b/arch/mips/include/asm/mach-bcm47xx/nvram.h @@ -12,6 +12,7 @@  #define __NVRAM_H  #include <linux/types.h> +#include <linux/kernel.h>  struct nvram_header {  	u32 magic; @@ -36,4 +37,10 @@ struct nvram_header {  extern int nvram_getenv(char *name, char *val, size_t val_len); +static inline void nvram_parse_macaddr(char *buf, u8 *macaddr) +{ +	sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], &macaddr[1], +	       &macaddr[2], &macaddr[3], &macaddr[4], &macaddr[5]); +} +  #endif diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index 5742bb4d78f..5c0a3575877 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -5,7 +5,7 @@   *   * Copyright (c) 2009 Qi Hardware inc.,   * Author: Xiangfu Liu <xiangfu@qi-hardware.com> - * Copyright 2010, Lars-Petrer Clausen <lars@metafoo.de> + * Copyright 2010, Lars-Peter Clausen <lars@metafoo.de>   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License version 2 or later @@ -235,7 +235,7 @@ static const unsigned int qi_lb60_keypad_rows[] = {  	QI_LB60_GPIO_KEYIN(3),  	QI_LB60_GPIO_KEYIN(4),  	QI_LB60_GPIO_KEYIN(5), -	QI_LB60_GPIO_KEYIN(7), +	QI_LB60_GPIO_KEYIN(6),  	QI_LB60_GPIO_KEYIN8,  }; diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c index 95bc2b5b14f..1cc9e544d16 100644 --- a/arch/mips/jz4740/platform.c +++ b/arch/mips/jz4740/platform.c @@ -208,7 +208,7 @@ struct platform_device jz4740_i2s_device = {  /* PCM */  struct platform_device jz4740_pcm_device = { -	.name		= "jz4740-pcm", +	.name		= "jz4740-pcm-audio",  	.id		= -1,  }; diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c index cfeac15eb2e..4a70407f55b 100644 --- a/arch/mips/jz4740/prom.c +++ b/arch/mips/jz4740/prom.c @@ -23,7 +23,7 @@  #include <asm/bootinfo.h>  #include <asm/mach-jz4740/base.h> -void jz4740_init_cmdline(int argc, char *argv[]) +static __init void jz4740_init_cmdline(int argc, char *argv[])  {  	unsigned int count = COMMAND_LINE_SIZE - 1;  	int i; diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 2f4d7a99bcc..98c5a9737c1 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -32,7 +32,7 @@ static int mips_next_event(unsigned long delta,  	cnt = read_c0_count();  	cnt += delta;  	write_c0_compare(cnt); -	res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0; +	res = ((int)(read_c0_count() - cnt) >= 0) ? -ETIME : 0;  	return res;  } diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 71620e19827..68dae7b6b5d 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -905,7 +905,8 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)  {  	decode_configs(c);  	switch (c->processor_id & 0xff00) { -	case PRID_IMP_BMIPS32: +	case PRID_IMP_BMIPS32_REV4: +	case PRID_IMP_BMIPS32_REV8:  		c->cputype = CPU_BMIPS32;  		__cpu_name[cpu] = "Broadcom BMIPS32";  		break; @@ -933,10 +934,6 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)  		__cpu_name[cpu] = "Broadcom BMIPS5000";  		c->options |= MIPS_CPU_ULRI;  		break; -	case PRID_IMP_BMIPS4KC: -		c->cputype = CPU_4KC; -		__cpu_name[cpu] = "MIPS 4Kc"; -		break;  	}  } diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 6343b4a5b83..876a75cc376 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -251,14 +251,15 @@ SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,  SYSCALL_DEFINE1(32_personality, unsigned long, personality)  { +	unsigned int p = personality & 0xffffffff;  	int ret; -	personality &= 0xffffffff; +  	if (personality(current->personality) == PER_LINUX32 && -	    personality == PER_LINUX) -		personality = PER_LINUX32; -	ret = sys_personality(personality); -	if (ret == PER_LINUX32) -		ret = PER_LINUX; +	    personality(p) == PER_LINUX) +		p = (p & ~PER_MASK) | PER_LINUX32; +	ret = sys_personality(p); +	if (ret != -1 && personality(ret) == PER_LINUX32) +		ret = (ret & ~PER_MASK) | PER_LINUX;  	return ret;  } diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 99960940d4a..ae167df73dd 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -142,7 +142,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,  	childregs->regs[7] = 0;	/* Clear error flag */  	childregs->regs[2] = 0;	/* Child gets zero as return value */ -	regs->regs[2] = p->pid;  	if (childregs->cp0_status & ST0_CU0) {  		childregs->regs[28] = (unsigned long) ti; diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index e000b278f02..9dbe5836895 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -100,7 +100,7 @@ void __init device_tree_init(void)  		return;  	base = virt_to_phys((void *)initial_boot_params); -	size = initial_boot_params->totalsize; +	size = be32_to_cpu(initial_boot_params->totalsize);  	/* Before we do anything, lets reserve the dt blob */  	reserve_mem_mach(base, size); diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 43e7cdc5ded..c0e81418ba2 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -153,7 +153,7 @@ static void __cpuinit vsmp_init_secondary(void)  {  	extern int gic_present; -	/* This is Malta specific: IPI,performance and timer inetrrupts */ +	/* This is Malta specific: IPI,performance and timer interrupts */  	if (gic_present)  		change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 |  					 STATUSF_IP6 | STATUSF_IP7); diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 8e9fbe75894..e9710430254 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -83,7 +83,8 @@ extern asmlinkage void handle_mcheck(void);  extern asmlinkage void handle_reserved(void);  extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, -	struct mips_fpu_struct *ctx, int has_fpu); +				    struct mips_fpu_struct *ctx, int has_fpu, +				    void *__user *fault_addr);  void (*board_be_init)(void);  int (*board_be_handler)(struct pt_regs *regs, int is_fixup); @@ -661,12 +662,36 @@ asmlinkage void do_ov(struct pt_regs *regs)  	force_sig_info(SIGFPE, &info, current);  } +static int process_fpemu_return(int sig, void __user *fault_addr) +{ +	if (sig == SIGSEGV || sig == SIGBUS) { +		struct siginfo si = {0}; +		si.si_addr = fault_addr; +		si.si_signo = sig; +		if (sig == SIGSEGV) { +			if (find_vma(current->mm, (unsigned long)fault_addr)) +				si.si_code = SEGV_ACCERR; +			else +				si.si_code = SEGV_MAPERR; +		} else { +			si.si_code = BUS_ADRERR; +		} +		force_sig_info(sig, &si, current); +		return 1; +	} else if (sig) { +		force_sig(sig, current); +		return 1; +	} else { +		return 0; +	} +} +  /*   * XXX Delayed fp exceptions when doing a lazy ctx switch XXX   */  asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)  { -	siginfo_t info; +	siginfo_t info = {0};  	if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE)  	    == NOTIFY_STOP) @@ -675,6 +700,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)  	if (fcr31 & FPU_CSR_UNI_X) {  		int sig; +		void __user *fault_addr = NULL;  		/*  		 * Unimplemented operation exception.  If we've got the full @@ -690,7 +716,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)  		lose_fpu(1);  		/* Run the emulator */ -		sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1); +		sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, +					       &fault_addr);  		/*  		 * We can't allow the emulated instruction to leave any of @@ -702,8 +729,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)  		own_fpu(1);	/* Using the FPU again.  */  		/* If something went wrong, signal */ -		if (sig) -			force_sig(sig, current); +		process_fpemu_return(sig, fault_addr);  		return;  	} else if (fcr31 & FPU_CSR_INV_X) @@ -996,11 +1022,11 @@ asmlinkage void do_cpu(struct pt_regs *regs)  		if (!raw_cpu_has_fpu) {  			int sig; +			void __user *fault_addr = NULL;  			sig = fpu_emulator_cop1Handler(regs, -						¤t->thread.fpu, 0); -			if (sig) -				force_sig(sig, current); -			else +						       ¤t->thread.fpu, +						       0, &fault_addr); +			if (!process_fpemu_return(sig, fault_addr))  				mt_ase_fp_affinity();  		} diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 3eb3cde2f66..6a1fdfef8fd 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -1092,6 +1092,10 @@ static int vpe_open(struct inode *inode, struct file *filp)  	/* this of-course trashes what was there before... */  	v->pbuffer = vmalloc(P_SIZE); +	if (!v->pbuffer) { +		pr_warning("VPE loader: unable to allocate memory\n"); +		return -ENOMEM; +	}  	v->plen = P_SIZE;  	v->load_addr = NULL;  	v->len = 0; @@ -1149,10 +1153,9 @@ static int vpe_release(struct inode *inode, struct file *filp)  	if (ret < 0)  		v->shared_ptr = NULL; -	// cleanup any temp buffers -	if (v->pbuffer) -		vfree(v->pbuffer); +	vfree(v->pbuffer);  	v->plen = 0; +  	return ret;  } @@ -1169,11 +1172,6 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,  	if (v == NULL)  		return -ENODEV; -	if (v->pbuffer == NULL) { -		printk(KERN_ERR "VPE loader: no buffer for program\n"); -		return -ENOMEM; -	} -  	if ((count + v->len) > v->plen) {  		printk(KERN_WARNING  		       "VPE loader: elf size too big. Perhaps strip uneeded symbols\n"); diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S index 77dc3b20110..606c8a9efe3 100644 --- a/arch/mips/lib/memset.S +++ b/arch/mips/lib/memset.S @@ -161,16 +161,16 @@ FEXPORT(__bzero)  .Lfwd_fixup:  	PTR_L		t0, TI_TASK($28) -	LONG_L		t0, THREAD_BUADDR(t0)  	andi		a2, 0x3f +	LONG_L		t0, THREAD_BUADDR(t0)  	LONG_ADDU	a2, t1  	jr		ra  	 LONG_SUBU	a2, t0  .Lpartial_fixup:  	PTR_L		t0, TI_TASK($28) -	LONG_L		t0, THREAD_BUADDR(t0)  	andi		a2, LONGMASK +	LONG_L		t0, THREAD_BUADDR(t0)  	LONG_ADDU	a2, t1  	jr		ra  	 LONG_SUBU	a2, t0 diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c index ae4cff97a56..11b193f848f 100644 --- a/arch/mips/loongson/common/env.c +++ b/arch/mips/loongson/common/env.c @@ -29,9 +29,9 @@ unsigned long memsize, highmemsize;  #define parse_even_earlier(res, option, p)				\  do {									\ +	int ret;							\  	if (strncmp(option, (char *)p, strlen(option)) == 0)		\ -			strict_strtol((char *)p + strlen(option"="),	\ -					10, &res);			\ +		ret = strict_strtol((char *)p + strlen(option"="), 10, &res); \  } while (0)  void __init prom_init_env(void) diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index b2ad1b0910f..d32cb050311 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -64,7 +64,7 @@ static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,  #if __mips >= 4 && __mips != 32  static int fpux_emu(struct pt_regs *, -	struct mips_fpu_struct *, mips_instruction); +	struct mips_fpu_struct *, mips_instruction, void *__user *);  #endif  /* Further private data for which no space exists in mips_fpu_struct */ @@ -208,16 +208,23 @@ static inline int cop1_64bit(struct pt_regs *xcp)   * Two instructions if the instruction is in a branch delay slot.   */ -static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) +static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, +		       void *__user *fault_addr)  {  	mips_instruction ir;  	unsigned long emulpc, contpc;  	unsigned int cond; -	if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) { +	if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) {  		MIPS_FPU_EMU_INC_STATS(errors); +		*fault_addr = (mips_instruction __user *)xcp->cp0_epc;  		return SIGBUS;  	} +	if (__get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) { +		MIPS_FPU_EMU_INC_STATS(errors); +		*fault_addr = (mips_instruction __user *)xcp->cp0_epc; +		return SIGSEGV; +	}  	/* XXX NEC Vr54xx bug workaround */  	if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir)) @@ -245,10 +252,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)  #endif  			return SIGILL;  		} -		if (get_user(ir, (mips_instruction __user *) emulpc)) { +		if (!access_ok(VERIFY_READ, emulpc, sizeof(mips_instruction))) {  			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = (mips_instruction __user *)emulpc;  			return SIGBUS;  		} +		if (__get_user(ir, (mips_instruction __user *) emulpc)) { +			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = (mips_instruction __user *)emulpc; +			return SIGSEGV; +		}  		/* __compute_return_epc() will have updated cp0_epc */  		contpc = xcp->cp0_epc;  		/* In order not to confuse ptrace() et al, tweak context */ @@ -269,10 +282,17 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)  		u64 val;  		MIPS_FPU_EMU_INC_STATS(loads); -		if (get_user(val, va)) { + +		if (!access_ok(VERIFY_READ, va, sizeof(u64))) {  			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va;  			return SIGBUS;  		} +		if (__get_user(val, va)) { +			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va; +			return SIGSEGV; +		}  		DITOREG(val, MIPSInst_RT(ir));  		break;  	} @@ -284,10 +304,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)  		MIPS_FPU_EMU_INC_STATS(stores);  		DIFROMREG(val, MIPSInst_RT(ir)); -		if (put_user(val, va)) { +		if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) {  			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va;  			return SIGBUS;  		} +		if (__put_user(val, va)) { +			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va; +			return SIGSEGV; +		}  		break;  	} @@ -297,10 +323,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)  		u32 val;  		MIPS_FPU_EMU_INC_STATS(loads); -		if (get_user(val, va)) { +		if (!access_ok(VERIFY_READ, va, sizeof(u32))) {  			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va;  			return SIGBUS;  		} +		if (__get_user(val, va)) { +			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va; +			return SIGSEGV; +		}  		SITOREG(val, MIPSInst_RT(ir));  		break;  	} @@ -312,10 +344,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)  		MIPS_FPU_EMU_INC_STATS(stores);  		SIFROMREG(val, MIPSInst_RT(ir)); -		if (put_user(val, va)) { +		if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) {  			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va;  			return SIGBUS;  		} +		if (__put_user(val, va)) { +			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va; +			return SIGSEGV; +		}  		break;  	} @@ -440,11 +478,18 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)  				contpc = (xcp->cp0_epc +  					(MIPSInst_SIMM(ir) << 2)); -				if (get_user(ir, -				    (mips_instruction __user *) xcp->cp0_epc)) { +				if (!access_ok(VERIFY_READ, xcp->cp0_epc, +					       sizeof(mips_instruction))) {  					MIPS_FPU_EMU_INC_STATS(errors); +					*fault_addr = (mips_instruction __user *)xcp->cp0_epc;  					return SIGBUS;  				} +				if (__get_user(ir, +				    (mips_instruction __user *) xcp->cp0_epc)) { +					MIPS_FPU_EMU_INC_STATS(errors); +					*fault_addr = (mips_instruction __user *)xcp->cp0_epc; +					return SIGSEGV; +				}  				switch (MIPSInst_OPCODE(ir)) {  				case lwc1_op: @@ -506,9 +551,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)  #if __mips >= 4 && __mips != 32  	case cop1x_op:{ -		int sig; - -		if ((sig = fpux_emu(xcp, ctx, ir))) +		int sig = fpux_emu(xcp, ctx, ir, fault_addr); +		if (sig)  			return sig;  		break;  	} @@ -604,7 +648,7 @@ DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);  DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);  static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, -	mips_instruction ir) +	mips_instruction ir, void *__user *fault_addr)  {  	unsigned rcsr = 0;	/* resulting csr */ @@ -624,10 +668,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  				xcp->regs[MIPSInst_FT(ir)]);  			MIPS_FPU_EMU_INC_STATS(loads); -			if (get_user(val, va)) { +			if (!access_ok(VERIFY_READ, va, sizeof(u32))) {  				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va;  				return SIGBUS;  			} +			if (__get_user(val, va)) { +				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va; +				return SIGSEGV; +			}  			SITOREG(val, MIPSInst_FD(ir));  			break; @@ -638,10 +688,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			MIPS_FPU_EMU_INC_STATS(stores);  			SIFROMREG(val, MIPSInst_FS(ir)); -			if (put_user(val, va)) { +			if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) {  				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va;  				return SIGBUS;  			} +			if (put_user(val, va)) { +				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va; +				return SIGSEGV; +			}  			break;  		case madd_s_op: @@ -701,10 +757,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  				xcp->regs[MIPSInst_FT(ir)]);  			MIPS_FPU_EMU_INC_STATS(loads); -			if (get_user(val, va)) { +			if (!access_ok(VERIFY_READ, va, sizeof(u64))) {  				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va;  				return SIGBUS;  			} +			if (__get_user(val, va)) { +				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va; +				return SIGSEGV; +			}  			DITOREG(val, MIPSInst_FD(ir));  			break; @@ -714,10 +776,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			MIPS_FPU_EMU_INC_STATS(stores);  			DIFROMREG(val, MIPSInst_FS(ir)); -			if (put_user(val, va)) { +			if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) {  				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va;  				return SIGBUS;  			} +			if (__put_user(val, va)) { +				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va; +				return SIGSEGV; +			}  			break;  		case madd_d_op: @@ -1242,7 +1310,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  }  int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, -	int has_fpu) +	int has_fpu, void *__user *fault_addr)  {  	unsigned long oldepc, prevepc;  	mips_instruction insn; @@ -1252,10 +1320,16 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  	do {  		prevepc = xcp->cp0_epc; -		if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) { +		if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) {  			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = (mips_instruction __user *)xcp->cp0_epc;  			return SIGBUS;  		} +		if (__get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) { +			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = (mips_instruction __user *)xcp->cp0_epc; +			return SIGSEGV; +		}  		if (insn == 0)  			xcp->cp0_epc += 4;	/* skip nops */  		else { @@ -1267,7 +1341,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			 */  			/* convert to ieee library modes */  			ieee754_csr.rm = ieee_rm[ieee754_csr.rm]; -			sig = cop1Emulate(xcp, ctx); +			sig = cop1Emulate(xcp, ctx, fault_addr);  			/* revert to mips rounding mode */  			ieee754_csr.rm = mips_rm[ieee754_csr.rm];  		} diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 4fc1a0fbe00..21ea14efb83 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -288,7 +288,7 @@ int mips_dma_supported(struct device *dev, u64 mask)  	return plat_dma_supported(dev, mask);  } -void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size, +void dma_cache_sync(struct device *dev, void *vaddr, size_t size,  			 enum dma_data_direction direction)  {  	BUG_ON(direction == DMA_NONE); @@ -298,6 +298,8 @@ void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size,  		__dma_sync((unsigned long)vaddr, size, direction);  } +EXPORT_SYMBOL(dma_cache_sync); +  static struct dma_map_ops mips_default_dma_map_ops = {  	.alloc_coherent = mips_dma_alloc_coherent,  	.free_coherent = mips_dma_free_coherent, diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c index 505fecad468..9cca8de0054 100644 --- a/arch/mips/mm/sc-mips.c +++ b/arch/mips/mm/sc-mips.c @@ -68,6 +68,9 @@ static struct bcache_ops mips_sc_ops = {   */  static inline int mips_sc_is_activated(struct cpuinfo_mips *c)  { +	unsigned int config2 = read_c0_config2(); +	unsigned int tmp; +  	/* Check the bypass bit (L2B) */  	switch (c->cputype) {  	case CPU_34K: @@ -83,6 +86,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)  		c->scache.linesz = 2 << tmp;  	else  		return 0; +	return 1;  }  static inline int __init mips_sc_probe(void) diff --git a/arch/mips/pmc-sierra/yosemite/py-console.c b/arch/mips/pmc-sierra/yosemite/py-console.c index b7f1d9c4a8a..434d7b1a8c6 100644 --- a/arch/mips/pmc-sierra/yosemite/py-console.c +++ b/arch/mips/pmc-sierra/yosemite/py-console.c @@ -65,11 +65,15 @@ static unsigned char readb_outer_space(unsigned long long phys)  	__asm__ __volatile__ (  	"	.set	mips3		\n" +	"	.set	push		\n" +	"	.set	noreorder	\n" +	"	.set	nomacro		\n"  	"	ld	%0, %1		\n" +	"	.set	pop		\n"  	"	lbu	%0, (%0)	\n"  	"	.set	mips0		\n"  	: "=r" (res) -	: "m" (vaddr)); +	: "R" (vaddr));  	write_c0_status(sr);  	ssnop_4(); @@ -89,11 +93,15 @@ static void writeb_outer_space(unsigned long long phys, unsigned char c)  	__asm__ __volatile__ (  	"	.set	mips3		\n" +	"	.set	push		\n" +	"	.set	noreorder	\n" +	"	.set	nomacro		\n"  	"	ld	%0, %1		\n" +	"	.set	pop		\n"  	"	sb	%2, (%0)	\n"  	"	.set	mips0		\n"  	: "=&r" (tmp) -	: "m" (vaddr), "r" (c)); +	: "R" (vaddr), "r" (c));  	write_c0_status(sr);  	ssnop_4(); diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c index c308989fc46..41707a245de 100644 --- a/arch/mips/sibyte/swarm/setup.c +++ b/arch/mips/sibyte/swarm/setup.c @@ -82,7 +82,7 @@ int swarm_be_handler(struct pt_regs *regs, int is_fixup)  enum swarm_rtc_type {  	RTC_NONE,  	RTC_XICOR, -	RTC_M4LT81 +	RTC_M41T81,  };  enum swarm_rtc_type swarm_rtc_type; @@ -96,7 +96,7 @@ void read_persistent_clock(struct timespec *ts)  		sec = xicor_get_time();  		break; -	case RTC_M4LT81: +	case RTC_M41T81:  		sec = m41t81_get_time();  		break; @@ -115,7 +115,7 @@ int rtc_mips_set_time(unsigned long sec)  	case RTC_XICOR:  		return xicor_set_time(sec); -	case RTC_M4LT81: +	case RTC_M41T81:  		return m41t81_set_time(sec);  	case RTC_NONE: @@ -141,7 +141,7 @@ void __init plat_mem_setup(void)  	if (xicor_probe())  		swarm_rtc_type = RTC_XICOR;  	if (m41t81_probe()) -		swarm_rtc_type = RTC_M4LT81; +		swarm_rtc_type = RTC_M41T81;  #ifdef CONFIG_VT  	screen_info = (struct screen_info) { diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index c2e44597c22..ac11754ecec 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c @@ -459,7 +459,7 @@ void migrate_irqs(void)  			tmp = CROSS_GxICR(irq, new);  			x &= GxICR_LEVEL | GxICR_ENABLE; -			if (GxICR(irq) & GxICR_REQUEST) { +			if (GxICR(irq) & GxICR_REQUEST)  				x |= GxICR_REQUEST | GxICR_DETECT;  			CROSS_GxICR(irq, new) = x;  			tmp = CROSS_GxICR(irq, new); diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c index f860a340acc..75da468090b 100644 --- a/arch/mn10300/kernel/time.c +++ b/arch/mn10300/kernel/time.c @@ -40,21 +40,17 @@ unsigned long long sched_clock(void)  		unsigned long long ll;  		unsigned l[2];  	} tsc64, result; -	unsigned long tsc, tmp; +	unsigned long tmp;  	unsigned product[3]; /* 96-bit intermediate value */  	/* cnt32_to_63() is not safe with preemption */  	preempt_disable(); -	/* read the TSC value -	 */ -	tsc = get_cycles(); - -	/* expand to 64-bits. +	/* expand the tsc to 64-bits.  	 * - sched_clock() must be called once a minute or better or the  	 *   following will go horribly wrong - see cnt32_to_63()  	 */ -	tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL; +	tsc64.ll = cnt32_to_63(get_cycles()) & 0x7fffffffffffffffULL;  	preempt_enable(); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index fea833e18ad..e0d703c7fdf 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c @@ -63,6 +63,7 @@  #include <linux/of_gpio.h>  #include <linux/kernel.h>  #include <linux/slab.h> +#include <linux/fs.h>  #include <linux/watchdog.h>  #include <linux/miscdevice.h>  #include <linux/uaccess.h> diff --git a/arch/sh/boards/mach-se/7206/irq.c b/arch/sh/boards/mach-se/7206/irq.c index d961949600f..9070d7e6070 100644 --- a/arch/sh/boards/mach-se/7206/irq.c +++ b/arch/sh/boards/mach-se/7206/irq.c @@ -140,7 +140,7 @@ void __init init_se7206_IRQ(void)  	make_se7206_irq(IRQ1_IRQ); /* ATA */  	make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ -	__raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR); /* ICR1 */ +	__raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR1); /* ICR1 */  	/* FPGA System register setup*/  	__raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */ diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c index b26264dc2ae..c509c40cba4 100644 --- a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c +++ b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c @@ -34,7 +34,7 @@ static const int pfc_divisors[]={1,2,3,4,6,8,12};  static void master_clk_init(struct clk *clk)  { -	return 10000000 * PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007]; +	clk->rate = 10000000 * PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];  }  static struct clk_ops sh7201_master_clk_ops = { diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c index b601fa3978d..6282a839e08 100644 --- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c +++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c @@ -81,8 +81,7 @@ static void shoc_clk_init(struct clk *clk)  	for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) {  		int divisor = frqcr3_divisors[i]; -		if (clk->ops->set_rate(clk, clk->parent->rate / -						divisor, 0) == 0) +		if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0)  			break;  	} diff --git a/arch/tile/include/asm/signal.h b/arch/tile/include/asm/signal.h index c1ee1d61d44..81d92a45cd4 100644 --- a/arch/tile/include/asm/signal.h +++ b/arch/tile/include/asm/signal.h @@ -25,7 +25,7 @@  #if defined(__KERNEL__) && !defined(__ASSEMBLY__)  struct pt_regs; -int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); +int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);  int setup_sigcontext(struct sigcontext __user *, struct pt_regs *);  void do_signal(struct pt_regs *regs);  #endif diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c index 543d6a33aa2..dbb0dfc7bec 100644 --- a/arch/tile/kernel/compat_signal.c +++ b/arch/tile/kernel/compat_signal.c @@ -290,12 +290,12 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,  	return ret;  } +/* The assembly shim for this function arranges to ignore the return value. */  long compat_sys_rt_sigreturn(struct pt_regs *regs)  {  	struct compat_rt_sigframe __user *frame =  		(struct compat_rt_sigframe __user *) compat_ptr(regs->sp);  	sigset_t set; -	long r0;  	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))  		goto badframe; @@ -308,13 +308,13 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs)  	recalc_sigpending();  	spin_unlock_irq(¤t->sighand->siglock); -	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) +	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))  		goto badframe;  	if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)  		goto badframe; -	return r0; +	return 0;  badframe:  	force_sig(SIGSEGV, current); diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index f5821626247..5eed4a02bf6 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S @@ -1342,8 +1342,8 @@ handle_syscall:  	lw      r20, r20  	/* Jump to syscall handler. */ -	jalr    r20; .Lhandle_syscall_link: -	FEEDBACK_REENTER(handle_syscall) +	jalr    r20 +.Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */  	/*  	 * Write our r0 onto the stack so it gets restored instead @@ -1352,6 +1352,9 @@ handle_syscall:  	PTREGS_PTR(r29, PTREGS_OFFSET_REG(0))  	sw      r29, r0 +.Lsyscall_sigreturn_skip: +	FEEDBACK_REENTER(handle_syscall) +  	/* Do syscall trace again, if requested. */  	lw	r30, r31  	andi    r30, r30, _TIF_SYSCALL_TRACE @@ -1536,9 +1539,24 @@ STD_ENTRY_LOCAL(bad_intr)  	};                                              \  	STD_ENDPROC(_##x) +/* + * Special-case sigreturn to not write r0 to the stack on return. + * This is technically more efficient, but it also avoids difficulties + * in the 64-bit OS when handling 32-bit compat code, since we must not + * sign-extend r0 for the sigreturn return-value case. + */ +#define PTREGS_SYSCALL_SIGRETURN(x, reg)                \ +	STD_ENTRY(_##x);                                \ +	addli   lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \ +	{                                               \ +	 PTREGS_PTR(reg, PTREGS_OFFSET_BASE);           \ +	 j      x                                       \ +	};                                              \ +	STD_ENDPROC(_##x) +  PTREGS_SYSCALL(sys_execve, r3)  PTREGS_SYSCALL(sys_sigaltstack, r2) -PTREGS_SYSCALL(sys_rt_sigreturn, r0) +PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)  PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)  /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 8430f45daea..e90eb53173b 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c @@ -212,6 +212,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,  	childregs->sp = sp;  /* override with new user stack pointer */  	/* +	 * If CLONE_SETTLS is set, set "tp" in the new task to "r4", +	 * which is passed in as arg #5 to sys_clone(). +	 */ +	if (clone_flags & CLONE_SETTLS) +		childregs->tp = regs->regs[4]; + +	/*  	 * Copy the callee-saved registers from the passed pt_regs struct  	 * into the context-switch callee-saved registers area.  	 * This way when we start the interrupt-return sequence, the @@ -539,6 +546,7 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,  	return __switch_to(prev, next, next_current_ksp0(next));  } +/* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */  SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,  		void __user *, parent_tidptr, void __user *, child_tidptr,  		struct pt_regs *, regs) diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c index 757407e3669..1260321155f 100644 --- a/arch/tile/kernel/signal.c +++ b/arch/tile/kernel/signal.c @@ -52,7 +52,7 @@ SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,   */  int restore_sigcontext(struct pt_regs *regs, -		       struct sigcontext __user *sc, long *pr0) +		       struct sigcontext __user *sc)  {  	int err = 0;  	int i; @@ -75,17 +75,15 @@ int restore_sigcontext(struct pt_regs *regs,  	regs->faultnum = INT_SWINT_1_SIGRETURN; -	err |= __get_user(*pr0, &sc->gregs[0]);  	return err;  } -/* sigreturn() returns long since it restores r0 in the interrupted code. */ +/* The assembly shim for this function arranges to ignore the return value. */  SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)  {  	struct rt_sigframe __user *frame =  		(struct rt_sigframe __user *)(regs->sp);  	sigset_t set; -	long r0;  	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))  		goto badframe; @@ -98,13 +96,13 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)  	recalc_sigpending();  	spin_unlock_irq(¤t->sighand->siglock); -	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) +	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))  		goto badframe;  	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)  		goto badframe; -	return r0; +	return 0;  badframe:  	force_sig(SIGSEGV, current); diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 23f315c9f21..325c05294fc 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -355,7 +355,7 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,  	if (heap > 0x3fffffffffffUL)  		error("Destination address too large");  #else -	if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff)) +	if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff))  		error("Destination address too large");  #endif  #ifndef CONFIG_RELOCATABLE diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index 5be1542fbfa..e99d55d74df 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -72,6 +72,9 @@ struct e820map {  #define BIOS_BEGIN		0x000a0000  #define BIOS_END		0x00100000 +#define BIOS_ROM_BASE		0xffe00000 +#define BIOS_ROM_END		0xffffffff +  #ifdef __KERNEL__  /* see comment in arch/x86/kernel/e820.c */  extern struct e820map e820; diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 9e6fe391094..f702f82aa1e 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -79,7 +79,7 @@  #define KVM_NUM_MMU_PAGES (1 << KVM_MMU_HASH_SHIFT)  #define KVM_MIN_FREE_MMU_PAGES 5  #define KVM_REFILL_PAGES 25 -#define KVM_MAX_CPUID_ENTRIES 40 +#define KVM_MAX_CPUID_ENTRIES 80  #define KVM_NR_FIXED_MTRR_REGION 88  #define KVM_NR_VAR_MTRR 8 diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 9e13763b609..1e994754d32 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -45,6 +45,7 @@ obj-y			+= pci-dma.o quirks.o i8237.o topology.o kdebugfs.o  obj-y			+= alternative.o i8253.o pci-nommu.o hw_breakpoint.o  obj-y			+= tsc.o io_delay.o rtc.o  obj-y			+= pci-iommu_table.o +obj-y			+= resource.o  obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline.o  obj-y				+= process.o diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 3f838d53739..78218135b48 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1389,6 +1389,14 @@ void __cpuinit end_local_APIC_setup(void)  	setup_apic_nmi_watchdog(NULL);  	apic_pm_activate(); + +	/* +	 * Now that local APIC setup is completed for BP, configure the fault +	 * handling for interrupt remapping. +	 */ +	if (!smp_processor_id() && intr_remapping_enabled) +		enable_drhd_fault_handling(); +  }  #ifdef CONFIG_X86_X2APIC diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 7cc0a721f62..fadcd743a74 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2430,13 +2430,12 @@ static void ack_apic_level(struct irq_data *data)  {  	struct irq_cfg *cfg = data->chip_data;  	int i, do_unmask_irq = 0, irq = data->irq; -	struct irq_desc *desc = irq_to_desc(irq);  	unsigned long v;  	irq_complete_move(cfg);  #ifdef CONFIG_GENERIC_PENDING_IRQ  	/* If we are moving the irq we need to mask it */ -	if (unlikely(desc->status & IRQ_MOVE_PENDING)) { +	if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) {  		do_unmask_irq = 1;  		mask_ioapic(cfg);  	} @@ -3413,6 +3412,7 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,  	msg.data |= MSI_DATA_VECTOR(cfg->vector);  	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;  	msg.address_lo |= MSI_ADDR_DEST_ID(dest); +	msg.address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(dest);  	dmar_msi_write(irq, &msg); diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index f9e4e6a5407..d8c4a6feb28 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c @@ -79,13 +79,6 @@ void __init default_setup_apic_routing(void)  		/* need to update phys_pkg_id */  		apic->phys_pkg_id = apicid_phys_pkg_id;  	} - -	/* -	 * Now that apic routing model is selected, configure the -	 * fault handling for intr remapping. -	 */ -	if (intr_remapping_enabled) -		enable_drhd_fault_handling();  }  /* Same for both flat and physical. */ diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index bcece91dd31..c0dbd9ac24f 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -60,16 +60,18 @@  #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)  #endif +/* Number of possible pages in the lowmem region */ +LOWMEM_PAGES = (((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) +	  /* Enough space to fit pagetables for the low memory linear map */ -MAPPING_BEYOND_END = \ -	PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT +MAPPING_BEYOND_END = PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT  /*   * Worst-case size of the kernel mapping we need to make: - * the worst-case size of the kernel itself, plus the extra we need - * to map for the linear map. + * a relocatable kernel can live anywhere in lowmem, so we need to be able + * to map all of lowmem.   */ -KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT +KERNEL_PAGES = LOWMEM_PAGES  INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm  RESERVE_BRK(pagetables, INIT_MAP_SIZE) @@ -620,13 +622,13 @@ ENTRY(initial_code)  __PAGE_ALIGNED_BSS  	.align PAGE_SIZE_asm  #ifdef CONFIG_X86_PAE -initial_pg_pmd: +ENTRY(initial_pg_pmd)  	.fill 1024*KPMDS,4,0  #else  ENTRY(initial_page_table)  	.fill 1024,4,0  #endif -initial_pg_fixmap: +ENTRY(initial_pg_fixmap)  	.fill 1024,4,0  ENTRY(empty_zero_page)  	.fill 4096,1,0 diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index ae03cab4352..4ff5968f12d 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -27,6 +27,9 @@  #define HPET_DEV_FSB_CAP		0x1000  #define HPET_DEV_PERI_CAP		0x2000 +#define HPET_MIN_CYCLES			128 +#define HPET_MIN_PROG_DELTA		(HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1)) +  #define EVT_TO_HPET_DEV(evt) container_of(evt, struct hpet_dev, evt)  /* @@ -299,8 +302,9 @@ static void hpet_legacy_clockevent_register(void)  	/* Calculate the min / max delta */  	hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,  							   &hpet_clockevent); -	/* 5 usec minimum reprogramming delta. */ -	hpet_clockevent.min_delta_ns = 5000; +	/* Setup minimum reprogramming delta. */ +	hpet_clockevent.min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA, +							   &hpet_clockevent);  	/*  	 * Start hpet with the boot cpu mask and make it @@ -393,22 +397,24 @@ static int hpet_next_event(unsigned long delta,  	 * the wraparound into account) nor a simple count down event  	 * mode. Further the write to the comparator register is  	 * delayed internally up to two HPET clock cycles in certain -	 * chipsets (ATI, ICH9,10). We worked around that by reading -	 * back the compare register, but that required another -	 * workaround for ICH9,10 chips where the first readout after -	 * write can return the old stale value. We already have a -	 * minimum delta of 5us enforced, but a NMI or SMI hitting +	 * chipsets (ATI, ICH9,10). Some newer AMD chipsets have even +	 * longer delays. We worked around that by reading back the +	 * compare register, but that required another workaround for +	 * ICH9,10 chips where the first readout after write can +	 * return the old stale value. We already had a minimum +	 * programming delta of 5us enforced, but a NMI or SMI hitting  	 * between the counter readout and the comparator write can  	 * move us behind that point easily. Now instead of reading  	 * the compare register back several times, we make the ETIME  	 * decision based on the following: Return ETIME if the -	 * counter value after the write is less than 8 HPET cycles +	 * counter value after the write is less than HPET_MIN_CYCLES  	 * away from the event or if the counter is already ahead of -	 * the event. +	 * the event. The minimum programming delta for the generic +	 * clockevents code is set to 1.5 * HPET_MIN_CYCLES.  	 */  	res = (s32)(cnt - hpet_readl(HPET_COUNTER)); -	return res < 8 ? -ETIME : 0; +	return res < HPET_MIN_CYCLES ? -ETIME : 0;  }  static void hpet_legacy_set_mode(enum clock_event_mode mode, diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index dcb65cc0a05..1a1b606d3e9 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -364,8 +364,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,  		/* For performance reasons, reuse mc area when possible */  		if (!mc || mc_size > curr_mc_size) { -			if (mc) -				vfree(mc); +			vfree(mc);  			mc = vmalloc(mc_size);  			if (!mc)  				break; @@ -374,13 +373,11 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,  		if (get_ucode_data(mc, ucode_ptr, mc_size) ||  		    microcode_sanity_check(mc) < 0) { -			vfree(mc);  			break;  		}  		if (get_matching_microcode(&uci->cpu_sig, mc, new_rev)) { -			if (new_mc) -				vfree(new_mc); +			vfree(new_mc);  			new_rev = mc_header.rev;  			new_mc  = mc;  			mc = NULL;	/* trigger new vmalloc */ @@ -390,12 +387,10 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,  		leftover  -= mc_size;  	} -	if (mc) -		vfree(mc); +	vfree(mc);  	if (leftover) { -		if (new_mc) -			vfree(new_mc); +		vfree(new_mc);  		state = UCODE_ERROR;  		goto out;  	} @@ -405,8 +400,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,  		goto out;  	} -	if (uci->mc) -		vfree(uci->mc); +	vfree(uci->mc);  	uci->mc = (struct microcode_intel *)new_mc;  	pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n", diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c new file mode 100644 index 00000000000..2a26819bb6a --- /dev/null +++ b/arch/x86/kernel/resource.c @@ -0,0 +1,48 @@ +#include <linux/ioport.h> +#include <asm/e820.h> + +static void resource_clip(struct resource *res, resource_size_t start, +			  resource_size_t end) +{ +	resource_size_t low = 0, high = 0; + +	if (res->end < start || res->start > end) +		return;		/* no conflict */ + +	if (res->start < start) +		low = start - res->start; + +	if (res->end > end) +		high = res->end - end; + +	/* Keep the area above or below the conflict, whichever is larger */ +	if (low > high) +		res->end = start - 1; +	else +		res->start = end + 1; +} + +static void remove_e820_regions(struct resource *avail) +{ +	int i; +	struct e820entry *entry; + +	for (i = 0; i < e820.nr_map; i++) { +		entry = &e820.map[i]; + +		resource_clip(avail, entry->addr, +			      entry->addr + entry->size - 1); +	} +} + +void arch_remove_reservations(struct resource *avail) +{ +	/* Trim out BIOS areas (low 1MB and high 2MB) and E820 regions */ +	if (avail->flags & IORESOURCE_MEM) { +		if (avail->start < BIOS_END) +			avail->start = BIOS_END; +		resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END); + +		remove_e820_regions(avail); +	} +} diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 21c6746338a..a0f52af256a 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -501,7 +501,18 @@ static inline unsigned long long get_total_mem(void)  	return total << PAGE_SHIFT;  } -#define DEFAULT_BZIMAGE_ADDR_MAX 0x37FFFFFF +/* + * Keep the crash kernel below this limit.  On 32 bits earlier kernels + * would limit the kernel to the low 512 MiB due to mapping restrictions. + * On 64 bits, kexec-tools currently limits us to 896 MiB; increase this + * limit once kexec-tools are fixed. + */ +#ifdef CONFIG_X86_32 +# define CRASH_KERNEL_ADDR_MAX	(512 << 20) +#else +# define CRASH_KERNEL_ADDR_MAX	(896 << 20) +#endif +  static void __init reserve_crashkernel(void)  {  	unsigned long long total_mem; @@ -520,10 +531,10 @@ static void __init reserve_crashkernel(void)  		const unsigned long long alignment = 16<<20;	/* 16M */  		/* -		 *  kexec want bzImage is below DEFAULT_BZIMAGE_ADDR_MAX +		 *  kexec want bzImage is below CRASH_KERNEL_ADDR_MAX  		 */  		crash_base = memblock_find_in_range(alignment, -			       DEFAULT_BZIMAGE_ADDR_MAX, crash_size, alignment); +			       CRASH_KERNEL_ADDR_MAX, crash_size, alignment);  		if (crash_base == MEMBLOCK_ERROR) {  			pr_info("crashkernel reservation failed - No suitable area found.\n"); @@ -769,7 +780,6 @@ void __init setup_arch(char **cmdline_p)  	x86_init.oem.arch_setup(); -	resource_alloc_from_bottom = 0;  	iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1;  	setup_memory_map();  	parse_setup_data(); diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 9c253bd65e2..547128546cc 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -394,7 +394,8 @@ static void __init setup_xstate_init(void)  	 * Setup init_xstate_buf to represent the init state of  	 * all the features managed by the xsave  	 */ -	init_xstate_buf = alloc_bootmem(xstate_size); +	init_xstate_buf = alloc_bootmem_align(xstate_size, +					      __alignof__(struct xsave_struct));  	init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT;  	clts(); diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index f628234fbec..3cece05e4ac 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c @@ -575,6 +575,8 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)  	s->pics[1].elcr_mask = 0xde;  	s->pics[0].pics_state = s;  	s->pics[1].pics_state = s; +	s->pics[0].isr_ack = 0xff; +	s->pics[1].isr_ack = 0xff;  	/*  	 * Initialize PIO device diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index fb8b376bf28..fbb04aee830 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -2394,7 +2394,8 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)  			ASSERT(!VALID_PAGE(root));  			spin_lock(&vcpu->kvm->mmu_lock);  			kvm_mmu_free_some_pages(vcpu); -			sp = kvm_mmu_get_page(vcpu, i << 30, i << 30, +			sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT), +					      i << 30,  					      PT32_ROOT_LEVEL, 1, ACC_ALL,  					      NULL);  			root = __pa(sp->spt); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 1ca12298ffc..b81a9b7c2ca 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3494,6 +3494,10 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu)  static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)  {  	switch (func) { +	case 0x00000001: +		/* Mask out xsave bit as long as it is not supported by SVM */ +		entry->ecx &= ~(bit(X86_FEATURE_XSAVE)); +		break;  	case 0x80000001:  		if (nested)  			entry->ecx |= (1 << 2); /* Set SVM bit */ diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index ff21fdda0c5..81fcbe9515c 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -4227,11 +4227,6 @@ static int vmx_get_lpage_level(void)  		return PT_PDPE_LEVEL;  } -static inline u32 bit(int bitno) -{ -	return 1 << (bitno & 31); -} -  static void vmx_cpuid_update(struct kvm_vcpu *vcpu)  {  	struct kvm_cpuid_entry2 *best; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index cdac9e592aa..b989e1f1e5d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -155,11 +155,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {  u64 __read_mostly host_xcr0; -static inline u32 bit(int bitno) -{ -	return 1 << (bitno & 31); -} -  static void kvm_on_user_return(struct user_return_notifier *urn)  {  	unsigned slot; @@ -4569,9 +4564,11 @@ static void kvm_timer_init(void)  #ifdef CONFIG_CPU_FREQ  		struct cpufreq_policy policy;  		memset(&policy, 0, sizeof(policy)); -		cpufreq_get_policy(&policy, get_cpu()); +		cpu = get_cpu(); +		cpufreq_get_policy(&policy, cpu);  		if (policy.cpuinfo.max_freq)  			max_tsc_khz = policy.cpuinfo.max_freq; +		put_cpu();  #endif  		cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block,  					  CPUFREQ_TRANSITION_NOTIFIER); @@ -5522,6 +5519,8 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,  	mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4;  	kvm_x86_ops->set_cr4(vcpu, sregs->cr4); +	if (sregs->cr4 & X86_CR4_OSXSAVE) +		update_cpuid(vcpu);  	if (!is_long_mode(vcpu) && is_pae(vcpu)) {  		load_pdptrs(vcpu, vcpu->arch.walk_mmu, vcpu->arch.cr3);  		mmu_reset_needed = 1; diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 2cea414489f..c600da830ce 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -70,6 +70,11 @@ static inline int is_paging(struct kvm_vcpu *vcpu)  	return kvm_read_cr0_bits(vcpu, X86_CR0_PG);  } +static inline u32 bit(int bitno) +{ +	return 1 << (bitno & 31); +} +  void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);  void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);  int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq); diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 73b1e1a1f48..4996cf5f73a 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -531,7 +531,10 @@ static void lguest_write_cr3(unsigned long cr3)  {  	lguest_data.pgdir = cr3;  	lazy_hcall1(LHCALL_NEW_PGTABLE, cr3); -	cr3_changed = true; + +	/* These two page tables are simple, linear, and used during boot */ +	if (cr3 != __pa(swapper_pg_dir) && cr3 != __pa(initial_page_table)) +		cr3_changed = true;  }  static unsigned long lguest_read_cr3(void) @@ -703,9 +706,9 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)   * to forget all of them.  Fortunately, this is very rare.   *   * ... except in early boot when the kernel sets up the initial pagetables, - * which makes booting astonishingly slow: 1.83 seconds!  So we don't even tell - * the Host anything changed until we've done the first page table switch, - * which brings boot back to 0.25 seconds. + * which makes booting astonishingly slow: 48 seconds!  So we don't even tell + * the Host anything changed until we've done the first real page table switch, + * which brings boot back to 4.3 seconds.   */  static void lguest_set_pte(pte_t *ptep, pte_t pteval)  { @@ -1002,7 +1005,7 @@ static void lguest_time_init(void)  	clockevents_register_device(&lguest_clockevent);  	/* Finally, we unblock the timer interrupt. */ -	enable_lguest_irq(0); +	clear_bit(0, lguest_data.blocked_interrupts);  }  /* @@ -1349,9 +1352,6 @@ __init void lguest_init(void)  	 */  	switch_to_new_gdt(0); -	/* We actually boot with all memory mapped, but let's say 128MB. */ -	max_pfn_mapped = (128*1024*1024) >> PAGE_SHIFT; -  	/*  	 * The Host<->Guest Switcher lives at the top of our address space, and  	 * the Host told us how big it is when we made LGUEST_INIT hypercall: diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S index 4f420c2f2d5..e7d5382ef26 100644 --- a/arch/x86/lguest/i386_head.S +++ b/arch/x86/lguest/i386_head.S @@ -4,6 +4,7 @@  #include <asm/asm-offsets.h>  #include <asm/thread_info.h>  #include <asm/processor-flags.h> +#include <asm/pgtable.h>  /*G:020   * Our story starts with the kernel booting into startup_32 in @@ -37,9 +38,113 @@ ENTRY(lguest_entry)  	/* Set up the initial stack so we can run C code. */  	movl $(init_thread_union+THREAD_SIZE),%esp +	call init_pagetables +  	/* Jumps are relative: we're running __PAGE_OFFSET too low. */  	jmp lguest_init+__PAGE_OFFSET +/* + * Initialize page tables.  This creates a PDE and a set of page + * tables, which are located immediately beyond __brk_base.  The variable + * _brk_end is set up to point to the first "safe" location. + * Mappings are created both at virtual address 0 (identity mapping) + * and PAGE_OFFSET for up to _end. + * + * FIXME: This code is taken verbatim from arch/x86/kernel/head_32.S: they + * don't have a stack at this point, so we can't just use call and ret. + */ +init_pagetables: +#if PTRS_PER_PMD > 1 +#define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD) +#else +#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD) +#endif +#define pa(X) ((X) - __PAGE_OFFSET) + +/* Enough space to fit pagetables for the low memory linear map */ +MAPPING_BEYOND_END = \ +	PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT +#ifdef CONFIG_X86_PAE + +	/* +	 * In PAE mode initial_page_table is statically defined to contain +	 * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3 +	 * entries). The identity mapping is handled by pointing two PGD entries +	 * to the first kernel PMD. +	 * +	 * Note the upper half of each PMD or PTE are always zero at this stage. +	 */ + +#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */ + +	xorl %ebx,%ebx				/* %ebx is kept at zero */ + +	movl $pa(__brk_base), %edi +	movl $pa(initial_pg_pmd), %edx +	movl $PTE_IDENT_ATTR, %eax +10: +	leal PDE_IDENT_ATTR(%edi),%ecx		/* Create PMD entry */ +	movl %ecx,(%edx)			/* Store PMD entry */ +						/* Upper half already zero */ +	addl $8,%edx +	movl $512,%ecx +11: +	stosl +	xchgl %eax,%ebx +	stosl +	xchgl %eax,%ebx +	addl $0x1000,%eax +	loop 11b + +	/* +	 * End condition: we must map up to the end + MAPPING_BEYOND_END. +	 */ +	movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp +	cmpl %ebp,%eax +	jb 10b +1: +	addl $__PAGE_OFFSET, %edi +	movl %edi, pa(_brk_end) +	shrl $12, %eax +	movl %eax, pa(max_pfn_mapped) + +	/* Do early initialization of the fixmap area */ +	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax +	movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8) +#else	/* Not PAE */ + +page_pde_offset = (__PAGE_OFFSET >> 20); + +	movl $pa(__brk_base), %edi +	movl $pa(initial_page_table), %edx +	movl $PTE_IDENT_ATTR, %eax +10: +	leal PDE_IDENT_ATTR(%edi),%ecx		/* Create PDE entry */ +	movl %ecx,(%edx)			/* Store identity PDE entry */ +	movl %ecx,page_pde_offset(%edx)		/* Store kernel PDE entry */ +	addl $4,%edx +	movl $1024, %ecx +11: +	stosl +	addl $0x1000,%eax +	loop 11b +	/* +	 * End condition: we must map up to the end + MAPPING_BEYOND_END. +	 */ +	movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp +	cmpl %ebp,%eax +	jb 10b +	addl $__PAGE_OFFSET, %edi +	movl %edi, pa(_brk_end) +	shrl $12, %eax +	movl %eax, pa(max_pfn_mapped) + +	/* Do early initialization of the fixmap area */ +	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax +	movl %eax,pa(initial_page_table+0xffc) +#endif +	ret +  /*G:055   * We create a macro which puts the assembler code between lgstart_ and lgend_   * markers.  These templates are put in the .text section: they can't be diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index a011bcc0f94..7d90d47655b 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -630,21 +630,29 @@ static int __init_ibs_nmi(void)  	return 0;  } -/* initialize the APIC for the IBS interrupts if available */ +/* + * check and reserve APIC extended interrupt LVT offset for IBS if + * available + * + * init_ibs() preforms implicitly cpu-local operations, so pin this + * thread to its current CPU + */ +  static void init_ibs(void)  { -	ibs_caps = get_ibs_caps(); +	preempt_disable(); +	ibs_caps = get_ibs_caps();  	if (!ibs_caps) -		return; +		goto out; -	if (__init_ibs_nmi()) { +	if (__init_ibs_nmi() < 0)  		ibs_caps = 0; -		return; -	} +	else +		printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps); -	printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", -	       (unsigned)ibs_caps); +out: +	preempt_enable();  }  static int (*create_arch_files)(struct super_block *sb, struct dentry *root); diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index c4bb261c106..b1805b78842 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -65,21 +65,13 @@ pcibios_align_resource(void *data, const struct resource *res,  			resource_size_t size, resource_size_t align)  {  	struct pci_dev *dev = data; -	resource_size_t start = round_down(res->end - size + 1, align); +	resource_size_t start = res->start;  	if (res->flags & IORESOURCE_IO) { - -		/* -		 * If we're avoiding ISA aliases, the largest contiguous I/O -		 * port space is 256 bytes.  Clearing bits 9 and 10 preserves -		 * all 256-byte and smaller alignments, so the result will -		 * still be correctly aligned. -		 */ -		if (!skip_isa_ioresource_align(dev)) -			start &= ~0x300; -	} else if (res->flags & IORESOURCE_MEM) { -		if (start < BIOS_END) -			start = res->end;	/* fail; no space */ +		if (skip_isa_ioresource_align(dev)) +			return start; +		if (start & 0x300) +			start = (start + 0x3ff) & ~0x3ff;  	}  	return start;  } diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile index 4a2afa1bac5..b6552b189bc 100644 --- a/arch/x86/vdso/Makefile +++ b/arch/x86/vdso/Makefile @@ -25,7 +25,7 @@ targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)  export CPPFLAGS_vdso.lds += -P -C -VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -Wl,-soname=linux-vdso.so.1 \ +VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \  		      	-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096  $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so @@ -69,7 +69,7 @@ vdso32.so-$(VDSO32-y)		+= sysenter  vdso32-images			= $(vdso32.so-y:%=vdso32-%.so)  CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds) -VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1 +VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1  # This makes sure the $(obj) subdirectory exists even though vdso32/  # is not a kbuild sub-make subdirectory. diff --git a/block/blk-map.c b/block/blk-map.c index 5d5dbe47c22..e663ac2d8e6 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -201,12 +201,13 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,  	for (i = 0; i < iov_count; i++) {  		unsigned long uaddr = (unsigned long)iov[i].iov_base; +		if (!iov[i].iov_len) +			return -EINVAL; +  		if (uaddr & queue_dma_alignment(q)) {  			unaligned = 1;  			break;  		} -		if (!iov[i].iov_len) -			return -EINVAL;  	}  	if (unaligned || (q->dma_pad_mask & len) || map_data) diff --git a/block/blk-merge.c b/block/blk-merge.c index 77b7c26df6b..74bc4a768f3 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -21,7 +21,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,  		return 0;  	fbio = bio; -	cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); +	cluster = blk_queue_cluster(q);  	seg_size = 0;  	nr_phys_segs = 0;  	for_each_bio(bio) { @@ -87,7 +87,7 @@ EXPORT_SYMBOL(blk_recount_segments);  static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,  				   struct bio *nxt)  { -	if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags)) +	if (!blk_queue_cluster(q))  		return 0;  	if (bio->bi_seg_back_size + nxt->bi_seg_front_size > @@ -123,7 +123,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,  	int nsegs, cluster;  	nsegs = 0; -	cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); +	cluster = blk_queue_cluster(q);  	/*  	 * for each bio in rq diff --git a/block/blk-settings.c b/block/blk-settings.c index 701859fb964..36c8c1f2af1 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -126,7 +126,7 @@ void blk_set_default_limits(struct queue_limits *lim)  	lim->alignment_offset = 0;  	lim->io_opt = 0;  	lim->misaligned = 0; -	lim->no_cluster = 0; +	lim->cluster = 1;  }  EXPORT_SYMBOL(blk_set_default_limits); @@ -229,8 +229,8 @@ void blk_queue_bounce_limit(struct request_queue *q, u64 dma_mask)  EXPORT_SYMBOL(blk_queue_bounce_limit);  /** - * blk_queue_max_hw_sectors - set max sectors for a request for this queue - * @q:  the request queue for the device + * blk_limits_max_hw_sectors - set hard and soft limit of max sectors for request + * @limits: the queue limits   * @max_hw_sectors:  max hardware sectors in the usual 512b unit   *   * Description: @@ -244,7 +244,7 @@ EXPORT_SYMBOL(blk_queue_bounce_limit);   *    per-device basis in /sys/block/<device>/queue/max_sectors_kb.   *    The soft limit can not exceed max_hw_sectors.   **/ -void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors) +void blk_limits_max_hw_sectors(struct queue_limits *limits, unsigned int max_hw_sectors)  {  	if ((max_hw_sectors << 9) < PAGE_CACHE_SIZE) {  		max_hw_sectors = 1 << (PAGE_CACHE_SHIFT - 9); @@ -252,9 +252,23 @@ void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_secto  		       __func__, max_hw_sectors);  	} -	q->limits.max_hw_sectors = max_hw_sectors; -	q->limits.max_sectors = min_t(unsigned int, max_hw_sectors, -				      BLK_DEF_MAX_SECTORS); +	limits->max_hw_sectors = max_hw_sectors; +	limits->max_sectors = min_t(unsigned int, max_hw_sectors, +				    BLK_DEF_MAX_SECTORS); +} +EXPORT_SYMBOL(blk_limits_max_hw_sectors); + +/** + * blk_queue_max_hw_sectors - set max sectors for a request for this queue + * @q:  the request queue for the device + * @max_hw_sectors:  max hardware sectors in the usual 512b unit + * + * Description: + *    See description for blk_limits_max_hw_sectors(). + **/ +void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors) +{ +	blk_limits_max_hw_sectors(&q->limits, max_hw_sectors);  }  EXPORT_SYMBOL(blk_queue_max_hw_sectors); @@ -464,15 +478,6 @@ EXPORT_SYMBOL(blk_queue_io_opt);  void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)  {  	blk_stack_limits(&t->limits, &b->limits, 0); - -	if (!t->queue_lock) -		WARN_ON_ONCE(1); -	else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) { -		unsigned long flags; -		spin_lock_irqsave(t->queue_lock, flags); -		queue_flag_clear(QUEUE_FLAG_CLUSTER, t); -		spin_unlock_irqrestore(t->queue_lock, flags); -	}  }  EXPORT_SYMBOL(blk_queue_stack_limits); @@ -545,7 +550,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,  	t->io_min = max(t->io_min, b->io_min);  	t->io_opt = lcm(t->io_opt, b->io_opt); -	t->no_cluster |= b->no_cluster; +	t->cluster &= b->cluster;  	t->discard_zeroes_data &= b->discard_zeroes_data;  	/* Physical block size a multiple of the logical block size? */ @@ -641,7 +646,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,  		       sector_t offset)  {  	struct request_queue *t = disk->queue; -	struct request_queue *b = bdev_get_queue(bdev);  	if (bdev_stack_limits(&t->limits, bdev, offset >> 9) < 0) {  		char top[BDEVNAME_SIZE], bottom[BDEVNAME_SIZE]; @@ -652,17 +656,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,  		printk(KERN_NOTICE "%s: Warning: Device %s is misaligned\n",  		       top, bottom);  	} - -	if (!t->queue_lock) -		WARN_ON_ONCE(1); -	else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) { -		unsigned long flags; - -		spin_lock_irqsave(t->queue_lock, flags); -		if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) -			queue_flag_clear(QUEUE_FLAG_CLUSTER, t); -		spin_unlock_irqrestore(t->queue_lock, flags); -	}  }  EXPORT_SYMBOL(disk_stack_limits); diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 013457f47fd..41fb69150b4 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -119,7 +119,7 @@ static ssize_t queue_max_integrity_segments_show(struct request_queue *q, char *  static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page)  { -	if (test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags)) +	if (blk_queue_cluster(q))  		return queue_var_show(queue_max_segment_size(q), (page));  	return queue_var_show(PAGE_CACHE_SIZE, (page)); diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 004be80fd89..381b09bb562 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -355,6 +355,12 @@ throtl_start_new_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)  			tg->slice_end[rw], jiffies);  } +static inline void throtl_set_slice_end(struct throtl_data *td, +		struct throtl_grp *tg, bool rw, unsigned long jiffy_end) +{ +	tg->slice_end[rw] = roundup(jiffy_end, throtl_slice); +} +  static inline void throtl_extend_slice(struct throtl_data *td,  		struct throtl_grp *tg, bool rw, unsigned long jiffy_end)  { @@ -391,6 +397,16 @@ throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)  	if (throtl_slice_used(td, tg, rw))  		return; +	/* +	 * A bio has been dispatched. Also adjust slice_end. It might happen +	 * that initially cgroup limit was very low resulting in high +	 * slice_end, but later limit was bumped up and bio was dispached +	 * sooner, then we need to reduce slice_end. A high bogus slice_end +	 * is bad because it does not allow new slice to start. +	 */ + +	throtl_set_slice_end(td, tg, rw, jiffies + throtl_slice); +  	time_elapsed = jiffies - tg->slice_start[rw];  	nr_slices = time_elapsed / throtl_slice; @@ -709,26 +725,21 @@ static void throtl_process_limit_change(struct throtl_data *td)  	struct throtl_grp *tg;  	struct hlist_node *pos, *n; -	/* -	 * Make sure atomic_inc() effects from -	 * throtl_update_blkio_group_read_bps(), group of functions are -	 * visible. -	 * Is this required or smp_mb__after_atomic_inc() was suffcient -	 * after the atomic_inc(). -	 */ -	smp_rmb();  	if (!atomic_read(&td->limits_changed))  		return;  	throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed)); -	hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) { -		/* -		 * Do I need an smp_rmb() here to make sure tg->limits_changed -		 * update is visible. I am relying on smp_rmb() at the -		 * beginning of function and not putting a new one here. -		 */ +	/* +	 * Make sure updates from throtl_update_blkio_group_read_bps() group +	 * of functions to tg->limits_changed are visible. We do not +	 * want update td->limits_changed to be visible but update to +	 * tg->limits_changed not being visible yet on this cpu. Hence +	 * the read barrier. +	 */ +	smp_rmb(); +	hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {  		if (throtl_tg_on_rr(tg) && tg->limits_changed) {  			throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"  				" riops=%u wiops=%u", tg->bps[READ], diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index 2c7def95f72..4c8dea513b6 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -408,6 +408,9 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,  		return_ACPI_STATUS(AE_OK);  	} +	/* Disable the GPE in case it's been enabled already. */ +	(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); +  	/*  	 * Add the GPE information from above to the gpe_event_info block for  	 * use during dispatch of this GPE. diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 9fb9d5ac939..95649d37307 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -130,8 +130,6 @@ struct acpi_battery {  	unsigned long flags;  }; -static int acpi_battery_update(struct acpi_battery *battery); -  #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);  inline int acpi_battery_present(struct acpi_battery *battery) @@ -186,9 +184,6 @@ static int acpi_battery_get_property(struct power_supply *psy,  	int ret = 0;  	struct acpi_battery *battery = to_acpi_battery(psy); -	if (acpi_battery_update(battery)) -		return -ENODEV; -  	if (acpi_battery_present(battery)) {  		/* run battery update only if it is present */  		acpi_battery_get_state(battery); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 2b6c21d86b9..29ef505c487 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -705,54 +705,85 @@ static int acpi_bus_get_perf_flags(struct acpi_device *device)  }  static acpi_status -acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device, -					     union acpi_object *package) +acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, +					     struct acpi_device_wakeup *wakeup)  { -	int i = 0; +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; +	union acpi_object *package = NULL;  	union acpi_object *element = NULL; +	acpi_status status; +	int i = 0; -	if (!device || !package || (package->package.count < 2)) +	if (!wakeup)  		return AE_BAD_PARAMETER; +	/* _PRW */ +	status = acpi_evaluate_object(handle, "_PRW", NULL, &buffer); +	if (ACPI_FAILURE(status)) { +		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW")); +		return status; +	} + +	package = (union acpi_object *)buffer.pointer; + +	if (!package || (package->package.count < 2)) { +		status = AE_BAD_DATA; +		goto out; +	} +  	element = &(package->package.elements[0]); -	if (!element) -		return AE_BAD_PARAMETER; +	if (!element) { +		status = AE_BAD_DATA; +		goto out; +	}  	if (element->type == ACPI_TYPE_PACKAGE) {  		if ((element->package.count < 2) ||  		    (element->package.elements[0].type !=  		     ACPI_TYPE_LOCAL_REFERENCE) -		    || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) -			return AE_BAD_DATA; -		device->wakeup.gpe_device = +		    || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) { +			status = AE_BAD_DATA; +			goto out; +		} +		wakeup->gpe_device =  		    element->package.elements[0].reference.handle; -		device->wakeup.gpe_number = +		wakeup->gpe_number =  		    (u32) element->package.elements[1].integer.value;  	} else if (element->type == ACPI_TYPE_INTEGER) { -		device->wakeup.gpe_number = element->integer.value; -	} else -		return AE_BAD_DATA; +		wakeup->gpe_device = NULL; +		wakeup->gpe_number = element->integer.value; +	} else { +		status = AE_BAD_DATA; +		goto out; +	}  	element = &(package->package.elements[1]);  	if (element->type != ACPI_TYPE_INTEGER) { -		return AE_BAD_DATA; +		status = AE_BAD_DATA; +		goto out;  	} -	device->wakeup.sleep_state = element->integer.value; +	wakeup->sleep_state = element->integer.value;  	if ((package->package.count - 2) > ACPI_MAX_HANDLES) { -		return AE_NO_MEMORY; +		status = AE_NO_MEMORY; +		goto out;  	} -	device->wakeup.resources.count = package->package.count - 2; -	for (i = 0; i < device->wakeup.resources.count; i++) { +	wakeup->resources.count = package->package.count - 2; +	for (i = 0; i < wakeup->resources.count; i++) {  		element = &(package->package.elements[i + 2]); -		if (element->type != ACPI_TYPE_LOCAL_REFERENCE) -			return AE_BAD_DATA; +		if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { +			status = AE_BAD_DATA; +			goto out; +		} -		device->wakeup.resources.handles[i] = element->reference.handle; +		wakeup->resources.handles[i] = element->reference.handle;  	} -	acpi_gpe_can_wake(device->wakeup.gpe_device, device->wakeup.gpe_number); +	acpi_gpe_can_wake(wakeup->gpe_device, wakeup->gpe_number); -	return AE_OK; + out: +	kfree(buffer.pointer); + +	return status;  }  static void acpi_bus_set_run_wake_flags(struct acpi_device *device) @@ -787,26 +818,15 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)  static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)  {  	acpi_status status = 0; -	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; -	union acpi_object *package = NULL;  	int psw_error; -	/* _PRW */ -	status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); -	if (ACPI_FAILURE(status)) { -		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW")); -		goto end; -	} - -	package = (union acpi_object *)buffer.pointer; -	status = acpi_bus_extract_wakeup_device_power_package(device, package); +	status = acpi_bus_extract_wakeup_device_power_package(device->handle, +							      &device->wakeup);  	if (ACPI_FAILURE(status)) {  		ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));  		goto end;  	} -	kfree(buffer.pointer); -  	device->wakeup.flags.valid = 1;  	device->wakeup.prepare_count = 0;  	acpi_bus_set_run_wake_flags(device); @@ -1351,6 +1371,7 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,  	struct acpi_bus_ops *ops = context;  	int type;  	unsigned long long sta; +	struct acpi_device_wakeup wakeup;  	struct acpi_device *device;  	acpi_status status;  	int result; @@ -1360,8 +1381,10 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,  		return AE_OK;  	if (!(sta & ACPI_STA_DEVICE_PRESENT) && -	    !(sta & ACPI_STA_DEVICE_FUNCTIONING)) +	    !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { +		acpi_bus_extract_wakeup_device_power_package(handle, &wakeup);  		return AE_CTRL_DEPTH; +	}  	/*  	 * We may already have an acpi_device from a previous enumeration.  If diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 11ec911016c..36e2319264b 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -128,16 +128,6 @@ config PDC_ADMA  	  If unsure, say N. -config PATA_MPC52xx -	tristate "Freescale MPC52xx SoC internal IDE" -	depends on PPC_MPC52xx && PPC_BESTCOMM -	select PPC_BESTCOMM_ATA -	help -	  This option enables support for integrated IDE controller -	  of the Freescale MPC52xx SoC. - -	  If unsure, say N. -  config PATA_OCTEON_CF  	tristate "OCTEON Boot Bus Compact Flash support"  	depends on CPU_CAVIUM_OCTEON @@ -366,7 +356,7 @@ config PATA_CS5535  config PATA_CS5536  	tristate "CS5536 PATA support" -	depends on PCI && X86 && !X86_64 +	depends on PCI  	help  	  This option enables support for the AMD CS5536  	  companion chip used with the Geode LX processor family. @@ -491,6 +481,16 @@ config PATA_MARVELL  	  If unsure, say N. +config PATA_MPC52xx +	tristate "Freescale MPC52xx SoC internal IDE" +	depends on PPC_MPC52xx && PPC_BESTCOMM +	select PPC_BESTCOMM_ATA +	help +	  This option enables support for integrated IDE controller +	  of the Freescale MPC52xx SoC. + +	  If unsure, say N. +  config PATA_NETCELL  	tristate "NETCELL Revolution RAID support"  	depends on PCI diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index c501af5b12b..2b67c900a45 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_SATA_DWC)		+= sata_dwc_460ex.o  # SFF w/ custom DMA  obj-$(CONFIG_PDC_ADMA)		+= pdc_adma.o -obj-$(CONFIG_PATA_MPC52xx)	+= pata_mpc52xx.o  obj-$(CONFIG_PATA_OCTEON_CF)	+= pata_octeon_cf.o  obj-$(CONFIG_SATA_QSTOR)	+= sata_qstor.o  obj-$(CONFIG_SATA_SX4)		+= sata_sx4.o @@ -52,6 +51,7 @@ obj-$(CONFIG_PATA_IT821X)	+= pata_it821x.o  obj-$(CONFIG_PATA_JMICRON)	+= pata_jmicron.o  obj-$(CONFIG_PATA_MACIO)	+= pata_macio.o  obj-$(CONFIG_PATA_MARVELL)	+= pata_marvell.o +obj-$(CONFIG_PATA_MPC52xx)	+= pata_mpc52xx.o  obj-$(CONFIG_PATA_NETCELL)	+= pata_netcell.o  obj-$(CONFIG_PATA_NINJA32)	+= pata_ninja32.o  obj-$(CONFIG_PATA_NS87415)	+= pata_ns87415.o diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 7f77c67d267..f23d6d46b95 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4807,9 +4807,6 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc)  {  	struct ata_device *dev = qc->dev; -	if (ata_tag_internal(qc->tag)) -		return; -  	if (ata_is_nodata(qc->tf.protocol))  		return; @@ -4858,14 +4855,23 @@ void ata_qc_complete(struct ata_queued_cmd *qc)  		if (unlikely(qc->err_mask))  			qc->flags |= ATA_QCFLAG_FAILED; -		if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { -			/* always fill result TF for failed qc */ +		/* +		 * Finish internal commands without any further processing +		 * and always with the result TF filled. +		 */ +		if (unlikely(ata_tag_internal(qc->tag))) {  			fill_result_tf(qc); +			__ata_qc_complete(qc); +			return; +		} -			if (!ata_tag_internal(qc->tag)) -				ata_qc_schedule_eh(qc); -			else -				__ata_qc_complete(qc); +		/* +		 * Non-internal qc has failed.  Fill the result TF and +		 * summon EH. +		 */ +		if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { +			fill_result_tf(qc); +			ata_qc_schedule_eh(qc);  			return;  		} diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 5e590504f3a..17a637877d0 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -3275,6 +3275,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,  	struct ata_port *ap = ata_is_host_link(link) ? link->ap : NULL;  	struct ata_eh_context *ehc = &link->eh_context;  	struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL; +	enum ata_lpm_policy old_policy = link->lpm_policy;  	unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;  	unsigned int err_mask;  	int rc; @@ -3338,6 +3339,14 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,  		goto fail;  	} +	/* +	 * Low level driver acked the transition.  Issue DIPM command +	 * with the new policy set. +	 */ +	link->lpm_policy = policy; +	if (ap && ap->slave_link) +		ap->slave_link->lpm_policy = policy; +  	/* host config updated, enable DIPM if transitioning to MIN_POWER */  	ata_for_each_dev(dev, link, ENABLED) {  		if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) { @@ -3353,12 +3362,14 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,  		}  	} -	link->lpm_policy = policy; -	if (ap && ap->slave_link) -		ap->slave_link->lpm_policy = policy;  	return 0;  fail: +	/* restore the old policy */ +	link->lpm_policy = old_policy; +	if (ap && ap->slave_link) +		ap->slave_link->lpm_policy = old_policy; +  	/* if no device or only one more chance is left, disable LPM */  	if (!dev || ehc->tries[dev->devno] <= 2) {  		ata_link_printk(link, KERN_WARNING, diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index d05387d1e14..484697fef38 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -1532,11 +1532,10 @@ static unsigned int __ata_sff_port_intr(struct ata_port *ap,  		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))  			return ata_sff_idle_irq(ap);  		break; -	case HSM_ST: -	case HSM_ST_LAST: -		break; -	default: +	case HSM_ST_IDLE:  		return ata_sff_idle_irq(ap); +	default: +		break;  	}  	/* check main status, clearing INTRQ if needed */ diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c index 21ee23f89e8..628c8fae593 100644 --- a/drivers/ata/pata_cs5536.c +++ b/drivers/ata/pata_cs5536.c @@ -37,10 +37,22 @@  #include <linux/delay.h>  #include <linux/libata.h>  #include <scsi/scsi_host.h> + +#ifdef CONFIG_X86_32  #include <asm/msr.h> +static int use_msr; +module_param_named(msr, use_msr, int, 0644); +MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)"); +#else +#undef rdmsr	/* avoid accidental MSR usage on, e.g. x86-64 */ +#undef wrmsr +#define rdmsr(x, y, z) do { } while (0) +#define wrmsr(x, y, z) do { } while (0) +#define use_msr 0 +#endif  #define DRV_NAME	"pata_cs5536" -#define DRV_VERSION	"0.0.7" +#define DRV_VERSION	"0.0.8"  enum {  	CFG			= 0, @@ -75,8 +87,6 @@ enum {  	IDE_ETC_NODMA		= 0x03,  }; -static int use_msr; -  static const u32 msr_reg[4] = {  	MSR_IDE_CFG, MSR_IDE_DTC, MSR_IDE_CAST, MSR_IDE_ETC,  }; @@ -88,7 +98,7 @@ static const u8 pci_reg[4] = {  static inline int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)  {  	if (unlikely(use_msr)) { -		u32 dummy; +		u32 dummy __maybe_unused;  		rdmsr(msr_reg[reg], *val, dummy);  		return 0; @@ -294,8 +304,6 @@ MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, cs5536);  MODULE_VERSION(DRV_VERSION); -module_param_named(msr, use_msr, int, 0644); -MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");  module_init(cs5536_init);  module_exit(cs5536_exit); diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c index 2b464b631f2..0b0625054a8 100644 --- a/drivers/atm/atmtcp.c +++ b/drivers/atm/atmtcp.c @@ -392,7 +392,10 @@ static int atmtcp_attach(struct atm_vcc *vcc,int itf)  			atm_dev_put(dev);  			return -EMEDIUMTYPE;  		} -		if (PRIV(dev)->vcc) return -EBUSY; +		if (PRIV(dev)->vcc) { +			atm_dev_put(dev); +			return -EBUSY; +		}  	}  	else {  		int error; diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index f291587d753..8e0f9256eb5 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2834,6 +2834,8 @@ static int cciss_revalidate(struct gendisk *disk)  	InquiryData_struct *inq_buff = NULL;  	for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) { +		if (!h->drv[logvol]) +			continue;  		if (memcmp(h->drv[logvol]->LunID, drv->LunID,  			sizeof(drv->LunID)) == 0) {  			FOUND = 1; diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 89d8a7cc405..24487d4fb20 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3627,17 +3627,19 @@ static void drbdd(struct drbd_conf *mdev)  		}  		shs = drbd_cmd_handler[cmd].pkt_size - sizeof(union p_header); -		rv = drbd_recv(mdev, &header->h80.payload, shs); -		if (unlikely(rv != shs)) { -			dev_err(DEV, "short read while reading sub header: rv=%d\n", rv); -			goto err_out; -		} -  		if (packet_size - shs > 0 && !drbd_cmd_handler[cmd].expect_payload) {  			dev_err(DEV, "No payload expected %s l:%d\n", cmdname(cmd), packet_size);  			goto err_out;  		} +		if (shs) { +			rv = drbd_recv(mdev, &header->h80.payload, shs); +			if (unlikely(rv != shs)) { +				dev_err(DEV, "short read while reading sub header: rv=%d\n", rv); +				goto err_out; +			} +		} +  		rv = drbd_cmd_handler[cmd].function(mdev, cmd, packet_size - shs);  		if (unlikely(!rv)) { diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 181ea036482..ab2bd09d54b 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h @@ -339,7 +339,8 @@ static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what)  }  /* completion of master bio is outside of spinlock. - * If you need it irqsave, do it your self! */ + * If you need it irqsave, do it your self! + * Which means: don't use from bio endio callback. */  static inline int req_mod(struct drbd_request *req,  		enum drbd_req_event what)  { diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 47d223c2409..34f224b018b 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -193,8 +193,10 @@ void drbd_endio_sec(struct bio *bio, int error)   */  void drbd_endio_pri(struct bio *bio, int error)  { +	unsigned long flags;  	struct drbd_request *req = bio->bi_private;  	struct drbd_conf *mdev = req->mdev; +	struct bio_and_error m;  	enum drbd_req_event what;  	int uptodate = bio_flagged(bio, BIO_UPTODATE); @@ -220,7 +222,13 @@ void drbd_endio_pri(struct bio *bio, int error)  	bio_put(req->private_bio);  	req->private_bio = ERR_PTR(error); -	req_mod(req, what); +	/* not req_mod(), we need irqsave here! */ +	spin_lock_irqsave(&mdev->req_lock, flags); +	__req_mod(req, what, &m); +	spin_unlock_irqrestore(&mdev->req_lock, flags); + +	if (m.bio) +		complete_master_bio(mdev, &m);  }  int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel) diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 720148294e6..3c6cabcb7d8 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -311,8 +311,10 @@ static void hci_uart_tty_close(struct tty_struct *tty)  		if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {  			hu->proto->close(hu); -			hci_unregister_dev(hdev); -			hci_free_dev(hdev); +			if (hdev) { +				hci_unregister_dev(hdev); +				hci_free_dev(hdev); +			}  		}  	}  } diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 16a2847b7cd..29ac6d499fa 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1192,12 +1192,19 @@ static void i9xx_chipset_flush(void)  		writel(1, intel_private.i9xx_flush_page);  } -static void i965_write_entry(dma_addr_t addr, unsigned int entry, +static void i965_write_entry(dma_addr_t addr, +			     unsigned int entry,  			     unsigned int flags)  { +	u32 pte_flags; + +	pte_flags = I810_PTE_VALID; +	if (flags == AGP_USER_CACHED_MEMORY) +		pte_flags |= I830_PTE_SYSTEM_CACHED; +  	/* Shift high bits down */  	addr |= (addr >> 28) & 0xf0; -	writel(addr | I810_PTE_VALID, intel_private.gtt + entry); +	writel(addr | pte_flags, intel_private.gtt + entry);  }  static bool gen6_check_flags(unsigned int flags) diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c index 73dcb0ee41f..d3d63be2cd3 100644 --- a/drivers/char/ramoops.c +++ b/drivers/char/ramoops.c @@ -29,7 +29,6 @@  #include <linux/ramoops.h>  #define RAMOOPS_KERNMSG_HDR "====" -#define RAMOOPS_HEADER_SIZE   (5 + sizeof(struct timeval))  #define RECORD_SIZE 4096 @@ -65,8 +64,8 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,  			struct ramoops_context, dump);  	unsigned long s1_start, s2_start;  	unsigned long l1_cpy, l2_cpy; -	int res; -	char *buf; +	int res, hdr_size; +	char *buf, *buf_orig;  	struct timeval timestamp;  	/* Only dump oopses if dump_oops is set */ @@ -74,6 +73,8 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,  		return;  	buf = (char *)(cxt->virt_addr + (cxt->count * RECORD_SIZE)); +	buf_orig = buf; +  	memset(buf, '\0', RECORD_SIZE);  	res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);  	buf += res; @@ -81,8 +82,9 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,  	res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec);  	buf += res; -	l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE)); -	l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE) - l2_cpy); +	hdr_size = buf - buf_orig; +	l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - hdr_size)); +	l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - hdr_size) - l2_cpy);  	s2_start = l2 - l2_cpy;  	s1_start = l1 - l1_cpy; diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index d68d3aa1814..f975d24890f 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -283,16 +283,21 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,  	} while (delay);  } -static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) +static void __sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)  { -	unsigned long flags; -  	if (delta > p->max_match_value)  		dev_warn(&p->pdev->dev, "delta out of range\n"); -	spin_lock_irqsave(&p->lock, flags);  	p->next_match_value = delta;  	sh_cmt_clock_event_program_verify(p, 0); +} + +static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) +{ +	unsigned long flags; + +	spin_lock_irqsave(&p->lock, flags); +	__sh_cmt_set_next(p, delta);  	spin_unlock_irqrestore(&p->lock, flags);  } @@ -359,7 +364,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag)  	/* setup timeout if no clockevent */  	if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT))) -		sh_cmt_set_next(p, p->max_match_value); +		__sh_cmt_set_next(p, p->max_match_value);   out:  	spin_unlock_irqrestore(&p->lock, flags); @@ -381,7 +386,7 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag)  	/* adjust the timeout to maximum if only clocksource left */  	if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE)) -		sh_cmt_set_next(p, p->max_match_value); +		__sh_cmt_set_next(p, p->max_match_value);  	spin_unlock_irqrestore(&p->lock, flags);  } diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 411d5bf50fc..a25f5f61e0e 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -449,7 +449,7 @@ mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)  static void mv_xor_tasklet(unsigned long data)  {  	struct mv_xor_chan *chan = (struct mv_xor_chan *) data; -	__mv_xor_slot_cleanup(chan); +	mv_xor_slot_cleanup(chan);  }  static struct mv_xor_desc_slot * diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c index 599f6c9e0fb..d3e55a0ae92 100644 --- a/drivers/gpio/cs5535-gpio.c +++ b/drivers/gpio/cs5535-gpio.c @@ -56,15 +56,26 @@ static struct cs5535_gpio_chip {   * registers, see include/linux/cs5535.h.   */ -static void errata_outl(u32 val, unsigned long addr) +static void errata_outl(struct cs5535_gpio_chip *chip, u32 val, +		unsigned int reg)  { +	unsigned long addr = chip->base + 0x80 + reg; +  	/*  	 * According to the CS5536 errata (#36), after suspend  	 * a write to the high bank GPIO register will clear all  	 * non-selected bits; the recommended workaround is a  	 * read-modify-write operation. +	 * +	 * Don't apply this errata to the edge status GPIOs, as writing +	 * to their lower bits will clear them.  	 */ -	val |= inl(addr); +	if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) { +		if (val & 0xffff) +			val |= (inl(addr) & 0xffff); /* ignore the high bits */ +		else +			val |= (inl(addr) ^ (val >> 16)); +	}  	outl(val, addr);  } @@ -76,7 +87,7 @@ static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset,  		outl(1 << offset, chip->base + reg);  	else  		/* high bank register */ -		errata_outl(1 << (offset - 16), chip->base + 0x80 + reg); +		errata_outl(chip, 1 << (offset - 16), reg);  }  void cs5535_gpio_set(unsigned offset, unsigned int reg) @@ -98,7 +109,7 @@ static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset,  		outl(1 << (offset + 16), chip->base + reg);  	else  		/* high bank register */ -		errata_outl(1 << offset, chip->base + 0x80 + reg); +		errata_outl(chip, 1 << offset, reg);  }  void cs5535_gpio_clear(unsigned offset, unsigned int reg) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 21da9c19a0c..649550e2cae 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1281,6 +1281,9 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)  		err = gpio_direction_output(gpio,  				(flags & GPIOF_INIT_HIGH) ? 1 : 0); +	if (err) +		gpio_free(gpio); +  	return err;  }  EXPORT_SYMBOL_GPL(gpio_request_one); diff --git a/drivers/gpio/rdc321x-gpio.c b/drivers/gpio/rdc321x-gpio.c index 2762698e020..897e0577e65 100644 --- a/drivers/gpio/rdc321x-gpio.c +++ b/drivers/gpio/rdc321x-gpio.c @@ -135,7 +135,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)  	struct rdc321x_gpio *rdc321x_gpio_dev;  	struct rdc321x_gpio_pdata *pdata; -	pdata = pdev->dev.platform_data; +	pdata = platform_get_drvdata(pdev);  	if (!pdata) {  		dev_err(&pdev->dev, "no platform data supplied\n");  		return -ENODEV; diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index bede10a0340..2d4e17a004d 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -241,7 +241,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)  	}  	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { -		if (encoder->crtc && !drm_helper_encoder_in_use(encoder)) { +		if (!drm_helper_encoder_in_use(encoder)) {  			drm_encoder_disable(encoder);  			/* disconnector encoder from any connector */  			encoder->crtc = NULL; @@ -874,7 +874,10 @@ static void output_poll_execute(struct work_struct *work)  			continue;  		connector->status = connector->funcs->detect(connector, false); -		DRM_DEBUG_KMS("connector status updated to %d\n", connector->status); +		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", +			      connector->base.id, +			      drm_get_connector_name(connector), +			      old_status, connector->status);  		if (old_status != connector->status)  			changed = true;  	} diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c index af70337567c..d3e8c540f77 100644 --- a/drivers/gpu/drm/i915/dvo_ch7017.c +++ b/drivers/gpu/drm/i915/dvo_ch7017.c @@ -242,7 +242,7 @@ fail:  static enum drm_connector_status ch7017_detect(struct intel_dvo_device *dvo)  { -	return connector_status_unknown; +	return connector_status_connected;  }  static enum drm_mode_status ch7017_mode_valid(struct intel_dvo_device *dvo, diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index e6800819bca..cb900dc83d9 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -34,6 +34,7 @@  #include "i915_drm.h"  #include "i915_drv.h"  #include "i915_trace.h" +#include "../../../platform/x86/intel_ips.h"  #include <linux/pci.h>  #include <linux/vgaarb.h>  #include <linux/acpi.h> @@ -1871,6 +1872,26 @@ out_unlock:  EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);  /** + * Tells the intel_ips driver that the i915 driver is now loaded, if + * IPS got loaded first. + * + * This awkward dance is so that neither module has to depend on the + * other in order for IPS to do the appropriate communication of + * GPU turbo limits to i915. + */ +static void +ips_ping_for_i915_load(void) +{ +	void (*link)(void); + +	link = symbol_get(ips_link_to_i915_driver); +	if (link) { +		link(); +		symbol_put(ips_link_to_i915_driver); +	} +} + +/**   * i915_driver_load - setup chip and create an initial config   * @dev: DRM device   * @flags: startup flags @@ -2075,6 +2096,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)  	dev_priv->mchdev_lock = &mchdev_lock;  	spin_unlock(&mchdev_lock); +	ips_ping_for_i915_load(); +  	return 0;  out_workqueue_free: diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 878fc766a12..cb8f4342927 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2471,6 +2471,9 @@  # define MARIUNIT_CLOCK_GATE_DISABLE		(1 << 18)  # define SVSMUNIT_CLOCK_GATE_DISABLE		(1 << 1) +#define PCH_3DCGDIS1		0x46024 +# define VFMUNIT_CLOCK_GATE_DISABLE		(1 << 11) +  #define FDI_PLL_FREQ_CTL        0x46030  #define  FDI_PLL_FREQ_CHANGE_REQUEST    (1<<24)  #define  FDI_PLL_FREQ_LOCK_LIMIT_MASK   0xfff00 @@ -2588,6 +2591,13 @@  #define ILK_DISPLAY_CHICKEN2	0x42004  #define  ILK_DPARB_GATE	(1<<22)  #define  ILK_VSDPFD_FULL	(1<<21) +#define ILK_DISPLAY_CHICKEN_FUSES	0x42014 +#define  ILK_INTERNAL_GRAPHICS_DISABLE	(1<<31) +#define  ILK_INTERNAL_DISPLAY_DISABLE	(1<<30) +#define  ILK_DISPLAY_DEBUG_DISABLE	(1<<29) +#define  ILK_HDCP_DISABLE		(1<<25) +#define  ILK_eDP_A_DISABLE		(1<<24) +#define  ILK_DESKTOP			(1<<23)  #define ILK_DSPCLK_GATE		0x42020  #define  ILK_DPARB_CLK_GATE	(1<<5)  /* According to spec this bit 7/8/9 of 0x42020 should be set to enable FBC */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d9b7092439e..fca523288ac 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5379,6 +5379,23 @@ static int intel_encoder_clones(struct drm_device *dev, int type_mask)  	return index_mask;  } +static bool has_edp_a(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; + +	if (!IS_MOBILE(dev)) +		return false; + +	if ((I915_READ(DP_A) & DP_DETECTED) == 0) +		return false; + +	if (IS_GEN5(dev) && +	    (I915_READ(ILK_DISPLAY_CHICKEN_FUSES) & ILK_eDP_A_DISABLE)) +		return false; + +	return true; +} +  static void intel_setup_outputs(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -5396,7 +5413,7 @@ static void intel_setup_outputs(struct drm_device *dev)  	if (HAS_PCH_SPLIT(dev)) {  		dpd_is_edp = intel_dpd_is_edp(dev); -		if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED)) +		if (has_edp_a(dev))  			intel_dp_init(dev, DP_A);  		if (dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED)) @@ -5825,6 +5842,8 @@ void intel_init_clock_gating(struct drm_device *dev)  			I915_WRITE(PCH_3DCGDIS0,  				   MARIUNIT_CLOCK_GATE_DISABLE |  				   SVSMUNIT_CLOCK_GATE_DISABLE); +			I915_WRITE(PCH_3DCGDIS1, +				   VFMUNIT_CLOCK_GATE_DISABLE);  		}  		I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index df648cb4c29..864417cffe9 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -479,6 +479,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,  	uint16_t address = algo_data->address;  	uint8_t msg[5];  	uint8_t reply[2]; +	unsigned retry;  	int msg_bytes;  	int reply_bytes;  	int ret; @@ -513,14 +514,33 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,  		break;  	} -	for (;;) { -	  ret = intel_dp_aux_ch(intel_dp, -				msg, msg_bytes, -				reply, reply_bytes); +	for (retry = 0; retry < 5; retry++) { +		ret = intel_dp_aux_ch(intel_dp, +				      msg, msg_bytes, +				      reply, reply_bytes);  		if (ret < 0) {  			DRM_DEBUG_KMS("aux_ch failed %d\n", ret);  			return ret;  		} + +		switch (reply[0] & AUX_NATIVE_REPLY_MASK) { +		case AUX_NATIVE_REPLY_ACK: +			/* I2C-over-AUX Reply field is only valid +			 * when paired with AUX ACK. +			 */ +			break; +		case AUX_NATIVE_REPLY_NACK: +			DRM_DEBUG_KMS("aux_ch native nack\n"); +			return -EREMOTEIO; +		case AUX_NATIVE_REPLY_DEFER: +			udelay(100); +			continue; +		default: +			DRM_ERROR("aux_ch invalid native reply 0x%02x\n", +				  reply[0]); +			return -EREMOTEIO; +		} +  		switch (reply[0] & AUX_I2C_REPLY_MASK) {  		case AUX_I2C_REPLY_ACK:  			if (mode == MODE_I2C_READ) { @@ -528,17 +548,20 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,  			}  			return reply_bytes - 1;  		case AUX_I2C_REPLY_NACK: -			DRM_DEBUG_KMS("aux_ch nack\n"); +			DRM_DEBUG_KMS("aux_i2c nack\n");  			return -EREMOTEIO;  		case AUX_I2C_REPLY_DEFER: -			DRM_DEBUG_KMS("aux_ch defer\n"); +			DRM_DEBUG_KMS("aux_i2c defer\n");  			udelay(100);  			break;  		default: -			DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]); +			DRM_ERROR("aux_i2c invalid reply 0x%02x\n", reply[0]);  			return -EREMOTEIO;  		}  	} + +	DRM_ERROR("too many retries, giving up\n"); +	return -EREMOTEIO;  }  static int diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 89a65be8a3f..31cd7e33e82 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -696,20 +696,17 @@ int intel_wait_ring_buffer(struct drm_device *dev,  	drm_i915_private_t *dev_priv = dev->dev_private;  	u32 head; -	head = intel_read_status_page(ring, 4); -	if (head) { -		ring->head = head & HEAD_ADDR; -		ring->space = ring->head - (ring->tail + 8); -		if (ring->space < 0) -			ring->space += ring->size; -		if (ring->space >= n) -			return 0; -	} -  	trace_i915_ring_wait_begin (dev);  	end = jiffies + 3 * HZ;  	do { -		ring->head = I915_READ_HEAD(ring) & HEAD_ADDR; +		/* If the reported head position has wrapped or hasn't advanced, +		 * fallback to the slow and accurate path. +		 */ +		head = intel_read_status_page(ring, 4); +		if (head < ring->actual_head) +			head = I915_READ_HEAD(ring); +		ring->actual_head = head; +		ring->head = head & HEAD_ADDR;  		ring->space = ring->head - (ring->tail + 8);  		if (ring->space < 0)  			ring->space += ring->size; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 3126c268198..d2cd0f1efee 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -30,8 +30,9 @@ struct  intel_ring_buffer {  	struct		drm_device *dev;  	struct		drm_gem_object *gem_object; -	unsigned int	head; -	unsigned int	tail; +	u32		actual_head; +	u32		head; +	u32		tail;  	int		space;  	struct intel_hw_status_page status_page; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index d97e6cb52d3..6bc42fa2a6e 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1908,9 +1908,12 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,  		speed = mapping->i2c_speed;  	} -	sdvo->i2c = &dev_priv->gmbus[pin].adapter; -	intel_gmbus_set_speed(sdvo->i2c, speed); -	intel_gmbus_force_bit(sdvo->i2c, true); +	if (pin < GMBUS_NUM_PORTS) { +		sdvo->i2c = &dev_priv->gmbus[pin].adapter; +		intel_gmbus_set_speed(sdvo->i2c, speed); +		intel_gmbus_force_bit(sdvo->i2c, true); +	} else +		sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter;  }  static bool @@ -2037,13 +2040,14 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)  					   SDVO_COLORIMETRY_RGB256);  		connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; -		intel_sdvo_add_hdmi_properties(intel_sdvo_connector);  		intel_sdvo->is_hdmi = true;  	}  	intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |  				       (1 << INTEL_ANALOG_CLONE_BIT));  	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); +	if (intel_sdvo->is_hdmi) +		intel_sdvo_add_hdmi_properties(intel_sdvo_connector);  	return true;  } diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index df2b6f2b35f..9fbabaa6ee4 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -253,7 +253,8 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)  	case DRM_MODE_DPMS_SUSPEND:  	case DRM_MODE_DPMS_OFF:  		drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); -		atombios_blank_crtc(crtc, ATOM_ENABLE); +		if (radeon_crtc->enabled) +			atombios_blank_crtc(crtc, ATOM_ENABLE);  		if (ASIC_IS_DCE3(rdev))  			atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);  		atombios_enable_crtc(crtc, ATOM_DISABLE); @@ -530,7 +531,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,  					dp_clock = dig_connector->dp_clock;  				}  			} - +#if 0 /* doesn't work properly on some laptops */  			/* use recommended ref_div for ss */  			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {  				if (ss_enabled) { @@ -540,7 +541,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,  					}  				}  			} - +#endif  			if (ASIC_IS_AVIVO(rdev)) {  				/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */  				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 4dc5b4714c5..7b337c361a1 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -748,6 +748,8 @@ void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev)  	unsigned i;  	u32 tmp; +	WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); +  	WREG32(VM_CONTEXT0_REQUEST_RESPONSE, REQUEST_TYPE(1));  	for (i = 0; i < rdev->usec_timeout; i++) {  		/* read MC_STATUS */ @@ -1922,7 +1924,6 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev)  static int evergreen_gpu_soft_reset(struct radeon_device *rdev)  {  	struct evergreen_mc_save save; -	u32 srbm_reset = 0;  	u32 grbm_reset = 0;  	dev_info(rdev->dev, "GPU softreset \n"); @@ -1961,16 +1962,6 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev)  	udelay(50);  	WREG32(GRBM_SOFT_RESET, 0);  	(void)RREG32(GRBM_SOFT_RESET); - -	/* reset all the system blocks */ -	srbm_reset = SRBM_SOFT_RESET_ALL_MASK; - -	dev_info(rdev->dev, "  SRBM_SOFT_RESET=0x%08X\n", srbm_reset); -	WREG32(SRBM_SOFT_RESET, srbm_reset); -	(void)RREG32(SRBM_SOFT_RESET); -	udelay(50); -	WREG32(SRBM_SOFT_RESET, 0); -	(void)RREG32(SRBM_SOFT_RESET);  	/* Wait a little for things to settle down */  	udelay(50);  	dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n", @@ -1981,10 +1972,6 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev)  		RREG32(GRBM_STATUS_SE1));  	dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",  		RREG32(SRBM_STATUS)); -	/* After reset we need to reinit the asic as GPU often endup in an -	 * incoherent state. -	 */ -	atom_asic_init(rdev->mode_info.atom_context);  	evergreen_mc_resume(rdev, &save);  	return 0;  } @@ -2596,6 +2583,11 @@ int evergreen_resume(struct radeon_device *rdev)  {  	int r; +	/* reset the asic, the gfx blocks are often in a bad state +	 * after the driver is unloaded or after a resume +	 */ +	if (radeon_asic_reset(rdev)) +		dev_warn(rdev->dev, "GPU reset failed !\n");  	/* Do not reset GPU before posting, on rv770 hw unlike on r500 hw,  	 * posting will perform necessary task to bring back GPU into good  	 * shape. @@ -2712,6 +2704,11 @@ int evergreen_init(struct radeon_device *rdev)  	r = radeon_atombios_init(rdev);  	if (r)  		return r; +	/* reset the asic, the gfx blocks are often in a bad state +	 * after the driver is unloaded or after a resume +	 */ +	if (radeon_asic_reset(rdev)) +		dev_warn(rdev->dev, "GPU reset failed !\n");  	/* Post card if necessary */  	if (!evergreen_card_posted(rdev)) {  		if (!rdev->bios) { diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 113c70cc8b3..a73b53c4435 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -174,6 +174,7 @@  #define	HDP_NONSURFACE_BASE				0x2C04  #define	HDP_NONSURFACE_INFO				0x2C08  #define	HDP_NONSURFACE_SIZE				0x2C0C +#define HDP_MEM_COHERENCY_FLUSH_CNTL			0x5480  #define HDP_REG_COHERENCY_FLUSH_CNTL			0x54A0  #define	HDP_TILING_CONFIG				0x2F3C diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 4d7a2e1bdb9..9c92db7c896 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1342,13 +1342,19 @@ bool r600_gpu_is_lockup(struct radeon_device *rdev)  	u32 srbm_status;  	u32 grbm_status;  	u32 grbm_status2; +	struct r100_gpu_lockup *lockup;  	int r; +	if (rdev->family >= CHIP_RV770) +		lockup = &rdev->config.rv770.lockup; +	else +		lockup = &rdev->config.r600.lockup; +  	srbm_status = RREG32(R_000E50_SRBM_STATUS);  	grbm_status = RREG32(R_008010_GRBM_STATUS);  	grbm_status2 = RREG32(R_008014_GRBM_STATUS2);  	if (!G_008010_GUI_ACTIVE(grbm_status)) { -		r100_gpu_lockup_update(&rdev->config.r300.lockup, &rdev->cp); +		r100_gpu_lockup_update(lockup, &rdev->cp);  		return false;  	}  	/* force CP activities */ @@ -1360,7 +1366,7 @@ bool r600_gpu_is_lockup(struct radeon_device *rdev)  		radeon_ring_unlock_commit(rdev);  	}  	rdev->cp.rptr = RREG32(R600_CP_RB_RPTR); -	return r100_gpu_cp_is_lockup(rdev, &rdev->config.r300.lockup, &rdev->cp); +	return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp);  }  int r600_asic_reset(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 0f90fc3482c..7831e089021 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -315,11 +315,10 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)  		if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {  			/* the initial DDX does bad things with the CB size occasionally */  			/* it rounds up height too far for slice tile max but the BO is smaller */ -			tmp = (height - 7) * 8 * bpe; -			if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { -				dev_warn(p->dev, "%s offset[%d] %d %d %lu too big\n", __func__, i, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i])); -				return -EINVAL; -			} +			/* r600c,g also seem to flush at bad times in some apps resulting in +			 * bogus values here. So for linear just allow anything to avoid breaking +			 * broken userspace. +			 */  		} else {  			dev_warn(p->dev, "%s offset[%d] %d %d %lu too big\n", __func__, i, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i]));  			return -EINVAL; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index e12e79326cb..501966a13f4 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -910,11 +910,6 @@ int radeon_resume_kms(struct drm_device *dev)  	radeon_pm_resume(rdev);  	radeon_restore_bios_scratch_regs(rdev); -	/* turn on display hw */ -	list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); -	} -  	radeon_fbdev_set_suspend(rdev, 0);  	release_console_sem(); @@ -922,6 +917,10 @@ int radeon_resume_kms(struct drm_device *dev)  	radeon_hpd_init(rdev);  	/* blat the mode back in */  	drm_helper_resume_force_mode(dev); +	/* turn on display hw */ +	list_for_each_entry(connector, &dev->mode_config.connector_list, head) { +		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); +	}  	return 0;  } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 88e4ea92590..60e689f2d04 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -232,9 +232,28 @@ static struct drm_driver driver_old = {  static struct drm_driver kms_driver; +static void radeon_kick_out_firmware_fb(struct pci_dev *pdev) +{ +	struct apertures_struct *ap; +	bool primary = false; + +	ap = alloc_apertures(1); +	ap->ranges[0].base = pci_resource_start(pdev, 0); +	ap->ranges[0].size = pci_resource_len(pdev, 0); + +#ifdef CONFIG_X86 +	primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; +#endif +	remove_conflicting_framebuffers(ap, "radeondrmfb", primary); +	kfree(ap); +} +  static int __devinit  radeon_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  { +	/* Get rid of things like offb */ +	radeon_kick_out_firmware_fb(pdev); +  	return drm_get_pci_dev(pdev, ent, &kms_driver);  } diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index efa211898fe..6abea32be5e 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -245,7 +245,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,  		goto out_unref;  	}  	info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base; -	info->apertures->ranges[0].size = rdev->mc.real_vram_size; +	info->apertures->ranges[0].size = rdev->mc.aper_size;  	info->fix.mmio_start = 0;  	info->fix.mmio_len = 0; diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c index 05248f2d758..92b42db43bc 100644 --- a/drivers/hwmon/s3c-hwmon.c +++ b/drivers/hwmon/s3c-hwmon.c @@ -234,7 +234,6 @@ static int s3c_hwmon_create_attr(struct device *dev,  	attr->index = channel;  	attr->dev_attr.attr.name  = attrs->in_name;  	attr->dev_attr.attr.mode  = S_IRUGO; -	attr->dev_attr.attr.owner = THIS_MODULE;  	attr->dev_attr.show = s3c_hwmon_ch_show;  	ret =  device_create_file(dev, &attr->dev_attr); @@ -252,7 +251,6 @@ static int s3c_hwmon_create_attr(struct device *dev,  		attr->index = channel;  		attr->dev_attr.attr.name  = attrs->label_name;  		attr->dev_attr.attr.mode  = S_IRUGO; -		attr->dev_attr.attr.owner = THIS_MODULE;  		attr->dev_attr.show = s3c_hwmon_label_show;  		ret = device_create_file(dev, &attr->dev_attr); diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index e3f7fc6f956..68f09a86843 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -534,76 +534,73 @@ static int handle_eviocgbit(struct input_dev *dev,  }  #undef OLD_KEY_MAX -static int evdev_handle_get_keycode(struct input_dev *dev, -				    void __user *p, size_t size) +static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p)  { -	struct input_keymap_entry ke; +	struct input_keymap_entry ke = { +		.len	= sizeof(unsigned int), +		.flags	= 0, +	}; +	int __user *ip = (int __user *)p;  	int error; -	memset(&ke, 0, sizeof(ke)); - -	if (size == sizeof(unsigned int[2])) { -		/* legacy case */ -		int __user *ip = (int __user *)p; +	/* legacy case */ +	if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) +		return -EFAULT; -		if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) -			return -EFAULT; +	error = input_get_keycode(dev, &ke); +	if (error) +		return error; -		ke.len = sizeof(unsigned int); -		ke.flags = 0; +	if (put_user(ke.keycode, ip + 1)) +		return -EFAULT; -		error = input_get_keycode(dev, &ke); -		if (error) -			return error; +	return 0; +} -		if (put_user(ke.keycode, ip + 1)) -			return -EFAULT; +static int evdev_handle_get_keycode_v2(struct input_dev *dev, void __user *p) +{ +	struct input_keymap_entry ke; +	int error; -	} else { -		size = min(size, sizeof(ke)); +	if (copy_from_user(&ke, p, sizeof(ke))) +		return -EFAULT; -		if (copy_from_user(&ke, p, size)) -			return -EFAULT; +	error = input_get_keycode(dev, &ke); +	if (error) +		return error; -		error = input_get_keycode(dev, &ke); -		if (error) -			return error; +	if (copy_to_user(p, &ke, sizeof(ke))) +		return -EFAULT; -		if (copy_to_user(p, &ke, size)) -			return -EFAULT; -	}  	return 0;  } -static int evdev_handle_set_keycode(struct input_dev *dev, -				    void __user *p, size_t size) +static int evdev_handle_set_keycode(struct input_dev *dev, void __user *p)  { -	struct input_keymap_entry ke; - -	memset(&ke, 0, sizeof(ke)); +	struct input_keymap_entry ke = { +		.len	= sizeof(unsigned int), +		.flags	= 0, +	}; +	int __user *ip = (int __user *)p; -	if (size == sizeof(unsigned int[2])) { -		/* legacy case */ -		int __user *ip = (int __user *)p; +	if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) +		return -EFAULT; -		if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) -			return -EFAULT; +	if (get_user(ke.keycode, ip + 1)) +		return -EFAULT; -		if (get_user(ke.keycode, ip + 1)) -			return -EFAULT; +	return input_set_keycode(dev, &ke); +} -		ke.len = sizeof(unsigned int); -		ke.flags = 0; +static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) +{ +	struct input_keymap_entry ke; -	} else { -		size = min(size, sizeof(ke)); +	if (copy_from_user(&ke, p, sizeof(ke))) +		return -EFAULT; -		if (copy_from_user(&ke, p, size)) -			return -EFAULT; - -		if (ke.len > sizeof(ke.scancode)) -			return -EINVAL; -	} +	if (ke.len > sizeof(ke.scancode)) +		return -EINVAL;  	return input_set_keycode(dev, &ke);  } @@ -669,6 +666,18 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,  			return evdev_grab(evdev, client);  		else  			return evdev_ungrab(evdev, client); + +	case EVIOCGKEYCODE: +		return evdev_handle_get_keycode(dev, p); + +	case EVIOCSKEYCODE: +		return evdev_handle_set_keycode(dev, p); + +	case EVIOCGKEYCODE_V2: +		return evdev_handle_get_keycode_v2(dev, p); + +	case EVIOCSKEYCODE_V2: +		return evdev_handle_set_keycode_v2(dev, p);  	}  	size = _IOC_SIZE(cmd); @@ -708,12 +717,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,  			return -EFAULT;  		return error; - -	case EVIOC_MASK_SIZE(EVIOCGKEYCODE): -		return evdev_handle_get_keycode(dev, p, size); - -	case EVIOC_MASK_SIZE(EVIOCSKEYCODE): -		return evdev_handle_set_keycode(dev, p, size);  	}  	/* Multi-number variable-length handlers */ diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 4852b440960..435b0af401e 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1436,6 +1436,8 @@ static struct wacom_features wacom_features_0xD2 =  	{ "Wacom Bamboo Craft",   WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };  static struct wacom_features wacom_features_0xD3 =  	{ "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023, 63, BAMBOO_PT }; +static const struct wacom_features wacom_features_0xD4 = +	{ "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200,  255, 63, BAMBOO_PT };  static struct wacom_features wacom_features_0xD8 =  	{ "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN,   21648, 13530, 1023, 63, BAMBOO_PT };  static struct wacom_features wacom_features_0xDA = @@ -1510,6 +1512,7 @@ const struct usb_device_id wacom_ids[] = {  	{ USB_DEVICE_WACOM(0xD1) },  	{ USB_DEVICE_WACOM(0xD2) },  	{ USB_DEVICE_WACOM(0xD3) }, +	{ USB_DEVICE_WACOM(0xD4) },  	{ USB_DEVICE_WACOM(0xD8) },  	{ USB_DEVICE_WACOM(0xDA) },  	{ USB_DEVICE_WACOM(0xDB) }, diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index bcc174e4f3b..658e75f18d0 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -1900,6 +1900,7 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,  		if (b3skb == NULL) {  			dev_err(cs->dev, "%s: out of memory\n", __func__);  			send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); +			kfree(b3cmsg);  			return;  		}  		capi_cmsg2message(b3cmsg, diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 211e21f34bd..d5a4ade8899 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -267,7 +267,7 @@ void led_blink_set(struct led_classdev *led_cdev,  		   unsigned long *delay_off)  {  	if (led_cdev->blink_set && -	    led_cdev->blink_set(led_cdev, delay_on, delay_off)) +	    !led_cdev->blink_set(led_cdev, delay_on, delay_off))  		return;  	/* blink with 1 Hz as default if nothing specified */ diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 90267f8d64e..4d705cea0f8 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -517,9 +517,8 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,  	 */  	if (q->merge_bvec_fn && !ti->type->merge) -		limits->max_sectors = -			min_not_zero(limits->max_sectors, -				     (unsigned int) (PAGE_SIZE >> 9)); +		blk_limits_max_hw_sectors(limits, +					  (unsigned int) (PAGE_SIZE >> 9));  	return 0;  }  EXPORT_SYMBOL_GPL(dm_set_device_limits); @@ -1131,11 +1130,6 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,  	 */  	q->limits = *limits; -	if (limits->no_cluster) -		queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q); -	else -		queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); -  	if (!dm_table_supports_discards(t))  		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);  	else diff --git a/drivers/md/md.c b/drivers/md/md.c index e71c5fa527f..175c424f201 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4295,9 +4295,6 @@ static int md_alloc(dev_t dev, char *name)  		goto abort;  	mddev->queue->queuedata = mddev; -	/* Can be unlocked because the queue is new: no concurrency */ -	queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, mddev->queue); -  	blk_queue_make_request(mddev->queue, md_make_request);  	disk = alloc_disk(1 << shift); diff --git a/drivers/media/IR/keymaps/rc-rc6-mce.c b/drivers/media/IR/keymaps/rc-rc6-mce.c index 1b7adabbcee..6da955dfef4 100644 --- a/drivers/media/IR/keymaps/rc-rc6-mce.c +++ b/drivers/media/IR/keymaps/rc-rc6-mce.c @@ -26,8 +26,8 @@ static struct ir_scancode rc6_mce[] = {  	{ 0x800f040a, KEY_DELETE },  	{ 0x800f040b, KEY_ENTER }, -	{ 0x800f040c, KEY_POWER }, -	{ 0x800f040d, KEY_PROG1 }, 		/* Windows MCE button */ +	{ 0x800f040c, KEY_POWER },		/* PC Power */ +	{ 0x800f040d, KEY_PROG1 },		/* Windows MCE button */  	{ 0x800f040e, KEY_MUTE },  	{ 0x800f040f, KEY_INFO }, @@ -56,31 +56,32 @@ static struct ir_scancode rc6_mce[] = {  	{ 0x800f0422, KEY_OK },  	{ 0x800f0423, KEY_EXIT },  	{ 0x800f0424, KEY_DVD }, -	{ 0x800f0425, KEY_TUNER }, 		/* LiveTV */ -	{ 0x800f0426, KEY_EPG }, 		/* Guide */ -	{ 0x800f0427, KEY_ZOOM }, 		/* Aspect */ +	{ 0x800f0425, KEY_TUNER },		/* LiveTV */ +	{ 0x800f0426, KEY_EPG },		/* Guide */ +	{ 0x800f0427, KEY_ZOOM },		/* Aspect */  	{ 0x800f043a, KEY_BRIGHTNESSUP },  	{ 0x800f0446, KEY_TV }, -	{ 0x800f0447, KEY_AUDIO }, 		/* My Music */ -	{ 0x800f0448, KEY_PVR }, 		/* RecordedTV */ +	{ 0x800f0447, KEY_AUDIO },		/* My Music */ +	{ 0x800f0448, KEY_PVR },		/* RecordedTV */  	{ 0x800f0449, KEY_CAMERA },  	{ 0x800f044a, KEY_VIDEO },  	{ 0x800f044c, KEY_LANGUAGE },  	{ 0x800f044d, KEY_TITLE }, -	{ 0x800f044e, KEY_PRINT }, 	/* Print - HP OEM version of remote */ +	{ 0x800f044e, KEY_PRINT },	/* Print - HP OEM version of remote */  	{ 0x800f0450, KEY_RADIO }, -	{ 0x800f045a, KEY_SUBTITLE }, 		/* Caption/Teletext */ +	{ 0x800f045a, KEY_SUBTITLE },		/* Caption/Teletext */  	{ 0x800f045b, KEY_RED },  	{ 0x800f045c, KEY_GREEN },  	{ 0x800f045d, KEY_YELLOW },  	{ 0x800f045e, KEY_BLUE }, +	{ 0x800f0465, KEY_POWER2 },	/* TV Power */  	{ 0x800f046e, KEY_PLAYPAUSE }, -	{ 0x800f046f, KEY_MEDIA }, 	/* Start media application (NEW) */ +	{ 0x800f046f, KEY_MEDIA },	/* Start media application (NEW) */  	{ 0x800f0480, KEY_BRIGHTNESSDOWN },  	{ 0x800f0481, KEY_PLAYPAUSE }, diff --git a/drivers/media/IR/lirc_dev.c b/drivers/media/IR/lirc_dev.c index 8418b14ee4d..756656e17bd 100644 --- a/drivers/media/IR/lirc_dev.c +++ b/drivers/media/IR/lirc_dev.c @@ -522,10 +522,8 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)  	dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor); -	if (!ir->attached) { -		mutex_unlock(&ir->irctl_lock); +	if (!ir->attached)  		return POLLERR; -	}  	poll_wait(file, &ir->buf->wait_poll, wait); @@ -649,18 +647,18 @@ ssize_t lirc_dev_fop_read(struct file *file,  	if (!buf)  		return -ENOMEM; -	if (mutex_lock_interruptible(&ir->irctl_lock)) -		return -ERESTARTSYS; +	if (mutex_lock_interruptible(&ir->irctl_lock)) { +		ret = -ERESTARTSYS; +		goto out_unlocked; +	}  	if (!ir->attached) { -		mutex_unlock(&ir->irctl_lock); -		return -ENODEV; +		ret = -ENODEV; +		goto out_locked;  	}  	if (length % ir->chunk_size) { -		dev_dbg(ir->d.dev, LOGHEAD "read result = -EINVAL\n", -			ir->d.name, ir->d.minor); -		mutex_unlock(&ir->irctl_lock); -		return -EINVAL; +		ret = -EINVAL; +		goto out_locked;  	}  	/* @@ -711,18 +709,23 @@ ssize_t lirc_dev_fop_read(struct file *file,  			lirc_buffer_read(ir->buf, buf);  			ret = copy_to_user((void *)buffer+written, buf,  					   ir->buf->chunk_size); -			written += ir->buf->chunk_size; +			if (!ret) +				written += ir->buf->chunk_size; +			else +				ret = -EFAULT;  		}  	}  	remove_wait_queue(&ir->buf->wait_poll, &wait);  	set_current_state(TASK_RUNNING); + +out_locked:  	mutex_unlock(&ir->irctl_lock);  out_unlocked:  	kfree(buf);  	dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n", -		ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret); +		ir->d.name, ir->d.minor, ret ? "<fail>" : "<ok>", ret);  	return ret ? ret : written;  } diff --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c index 9dce684fd23..392ca24132d 100644 --- a/drivers/media/IR/mceusb.c +++ b/drivers/media/IR/mceusb.c @@ -35,10 +35,10 @@  #include <linux/device.h>  #include <linux/module.h>  #include <linux/slab.h> -#include <linux/usb.h>  #include <linux/input.h> +#include <linux/usb.h> +#include <linux/usb/input.h>  #include <media/ir-core.h> -#include <media/ir-common.h>  #define DRIVER_VERSION	"1.91"  #define DRIVER_AUTHOR	"Jarod Wilson <jarod@wilsonet.com>" @@ -49,6 +49,7 @@  #define USB_BUFLEN		32 /* USB reception buffer length */  #define USB_CTRL_MSG_SZ		2  /* Size of usb ctrl msg on gen1 hw */  #define MCE_G1_INIT_MSGS	40 /* Init messages on gen1 hw to throw out */ +#define MS_TO_NS(msec)		((msec) * 1000)  /* MCE constants */  #define MCE_CMDBUF_SIZE		384  /* MCE Command buffer length */ @@ -74,6 +75,7 @@  #define MCE_PACKET_LENGTH_MASK	0x1f /* Packet length mask */  /* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */ +#define MCE_CMD_SIG_END		0x01	/* End of signal */  #define MCE_CMD_PING		0x03	/* Ping device */  #define MCE_CMD_UNKNOWN		0x04	/* Unknown */  #define MCE_CMD_UNKNOWN2	0x05	/* Unknown */ @@ -91,6 +93,7 @@  #define MCE_CMD_G_TXMASK	0x13	/* Set TX port bitmask */  #define MCE_CMD_S_RXSENSOR	0x14	/* Set RX sensor (std/learning) */  #define MCE_CMD_G_RXSENSOR	0x15	/* Get RX sensor (std/learning) */ +#define MCE_RSP_PULSE_COUNT	0x15	/* RX pulse count (only if learning) */  #define MCE_CMD_TX_PORTS	0x16	/* Get number of TX ports */  #define MCE_CMD_G_WAKESRC	0x17	/* Get wake source */  #define MCE_CMD_UNKNOWN7	0x18	/* Unknown */ @@ -146,14 +149,16 @@ enum mceusb_model_type {  	MCE_GEN3,  	MCE_GEN2_TX_INV,  	POLARIS_EVK, +	CX_HYBRID_TV,  };  struct mceusb_model {  	u32 mce_gen1:1;  	u32 mce_gen2:1;  	u32 mce_gen3:1; -	u32 tx_mask_inverted:1; +	u32 tx_mask_normal:1;  	u32 is_polaris:1; +	u32 no_tx:1;  	const char *rc_map;	/* Allow specify a per-board map */  	const char *name;	/* per-board name */ @@ -162,18 +167,18 @@ struct mceusb_model {  static const struct mceusb_model mceusb_model[] = {  	[MCE_GEN1] = {  		.mce_gen1 = 1, -		.tx_mask_inverted = 1, +		.tx_mask_normal = 1,  	},  	[MCE_GEN2] = {  		.mce_gen2 = 1,  	},  	[MCE_GEN2_TX_INV] = {  		.mce_gen2 = 1, -		.tx_mask_inverted = 1, +		.tx_mask_normal = 1,  	},  	[MCE_GEN3] = {  		.mce_gen3 = 1, -		.tx_mask_inverted = 1, +		.tx_mask_normal = 1,  	},  	[POLARIS_EVK] = {  		.is_polaris = 1, @@ -183,7 +188,12 @@ static const struct mceusb_model mceusb_model[] = {  		 * to allow testing it  		 */  		.rc_map = RC_MAP_RC5_HAUPPAUGE_NEW, -		.name = "cx231xx MCE IR", +		.name = "Conexant Hybrid TV (cx231xx) MCE IR", +	}, +	[CX_HYBRID_TV] = { +		.is_polaris = 1, +		.no_tx = 1, /* tx isn't wired up at all */ +		.name = "Conexant Hybrid TV (cx231xx) MCE IR",  	},  }; @@ -273,6 +283,8 @@ static struct usb_device_id mceusb_dev_table[] = {  	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03c) },  	/* Formosa Industrial Computing */  	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03e) }, +	/* Fintek eHome Infrared Transceiver (HP branded) */ +	{ USB_DEVICE(VENDOR_FINTEK, 0x5168) },  	/* Fintek eHome Infrared Transceiver */  	{ USB_DEVICE(VENDOR_FINTEK, 0x0602) },  	/* Fintek eHome Infrared Transceiver (in the AOpen MP45) */ @@ -292,9 +304,12 @@ static struct usb_device_id mceusb_dev_table[] = {  	{ USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) },  	/* TiVo PC IR Receiver */  	{ USB_DEVICE(VENDOR_TIVO, 0x2000) }, -	/* Conexant SDK */ +	/* Conexant Hybrid TV "Shelby" Polaris SDK */  	{ USB_DEVICE(VENDOR_CONEXANT, 0x58a1),  	  .driver_info = POLARIS_EVK }, +	/* Conexant Hybrid TV RDU253S Polaris */ +	{ USB_DEVICE(VENDOR_CONEXANT, 0x58a5), +	  .driver_info = CX_HYBRID_TV },  	/* Terminating entry */  	{ }  }; @@ -303,7 +318,10 @@ static struct usb_device_id mceusb_dev_table[] = {  struct mceusb_dev {  	/* ir-core bits */  	struct ir_dev_props *props; -	struct ir_raw_event rawir; + +	/* optional features we can enable */ +	bool carrier_report_enabled; +	bool learning_enabled;  	/* core device bits */  	struct device *dev; @@ -318,6 +336,8 @@ struct mceusb_dev {  	/* buffers and dma */  	unsigned char *buf_in;  	unsigned int len_in; +	dma_addr_t dma_in; +	dma_addr_t dma_out;  	enum {  		CMD_HEADER = 0, @@ -325,15 +345,14 @@ struct mceusb_dev {  		CMD_DATA,  		PARSE_IRDATA,  	} parser_state; -	u8 cmd, rem;		/* Remaining IR data bytes in packet */ -	dma_addr_t dma_in; -	dma_addr_t dma_out; +	u8 cmd, rem;		/* Remaining IR data bytes in packet */  	struct {  		u32 connected:1; -		u32 tx_mask_inverted:1; +		u32 tx_mask_normal:1;  		u32 microsoft_gen1:1; +		u32 no_tx:1;  	} flags;  	/* transmit support */ @@ -408,9 +427,10 @@ static int mceusb_cmdsize(u8 cmd, u8 subcmd)  		case MCE_CMD_UNKNOWN:  		case MCE_CMD_S_CARRIER:  		case MCE_CMD_S_TIMEOUT: -		case MCE_CMD_G_RXSENSOR: +		case MCE_RSP_PULSE_COUNT:  			datasize = 2;  			break; +		case MCE_CMD_SIG_END:  		case MCE_CMD_S_TXMASK:  		case MCE_CMD_S_RXSENSOR:  			datasize = 1; @@ -433,7 +453,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,  		return;  	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */ -	if (ir->flags.microsoft_gen1 && !out) +	if (ir->flags.microsoft_gen1 && !out && !offset)  		skip = 2;  	if (len <= skip) @@ -491,6 +511,9 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,  		break;  	case MCE_COMMAND_HEADER:  		switch (subcmd) { +		case MCE_CMD_SIG_END: +			dev_info(dev, "End of signal\n"); +			break;  		case MCE_CMD_PING:  			dev_info(dev, "Ping\n");  			break; @@ -525,10 +548,11 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,  				 inout, data1 == 0x02 ? "short" : "long");  			break;  		case MCE_CMD_G_RXSENSOR: -			if (len == 2) +		/* aka MCE_RSP_PULSE_COUNT */ +			if (out)  				dev_info(dev, "Get receive sensor\n"); -			else -				dev_info(dev, "Received pulse count is %d\n", +			else if (ir->learning_enabled) +				dev_info(dev, "RX pulse count: %d\n",  					 ((data1 << 8) | data2));  			break;  		case MCE_RSP_CMD_INVALID: @@ -724,16 +748,16 @@ out:  	return ret ? ret : n;  } -/* Sets active IR outputs -- mce devices typically (all?) have two */ +/* Sets active IR outputs -- mce devices typically have two */  static int mceusb_set_tx_mask(void *priv, u32 mask)  {  	struct mceusb_dev *ir = priv; -	if (ir->flags.tx_mask_inverted) +	if (ir->flags.tx_mask_normal) +		ir->tx_mask = mask; +	else  		ir->tx_mask = (mask != MCE_DEFAULT_TX_MASK ?  				mask ^ MCE_DEFAULT_TX_MASK : mask) << 1; -	else -		ir->tx_mask = mask;  	return 0;  } @@ -752,7 +776,7 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)  		if (carrier == 0) {  			ir->carrier = carrier; -			cmdbuf[2] = 0x01; +			cmdbuf[2] = MCE_CMD_SIG_END;  			cmdbuf[3] = MCE_IRDATA_TRAILER;  			dev_dbg(ir->dev, "%s: disabling carrier "  				"modulation\n", __func__); @@ -782,6 +806,34 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)  	return carrier;  } +/* + * We don't do anything but print debug spew for many of the command bits + * we receive from the hardware, but some of them are useful information + * we want to store so that we can use them. + */ +static void mceusb_handle_command(struct mceusb_dev *ir, int index) +{ +	u8 hi = ir->buf_in[index + 1] & 0xff; +	u8 lo = ir->buf_in[index + 2] & 0xff; + +	switch (ir->buf_in[index]) { +	/* 2-byte return value commands */ +	case MCE_CMD_S_TIMEOUT: +		ir->props->timeout = MS_TO_NS((hi << 8 | lo) / 2); +		break; + +	/* 1-byte return value commands */ +	case MCE_CMD_S_TXMASK: +		ir->tx_mask = hi; +		break; +	case MCE_CMD_S_RXSENSOR: +		ir->learning_enabled = (hi == 0x02); +		break; +	default: +		break; +	} +} +  static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)  {  	DEFINE_IR_RAW_EVENT(rawir); @@ -791,39 +843,30 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)  	if (ir->flags.microsoft_gen1)  		i = 2; +	/* if there's no data, just return now */ +	if (buf_len <= i) +		return; +  	for (; i < buf_len; i++) {  		switch (ir->parser_state) {  		case SUBCMD:  			ir->rem = mceusb_cmdsize(ir->cmd, ir->buf_in[i]);  			mceusb_dev_printdata(ir, ir->buf_in, i - 1,  					     ir->rem + 2, false); +			mceusb_handle_command(ir, i);  			ir->parser_state = CMD_DATA;  			break;  		case PARSE_IRDATA:  			ir->rem--;  			rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);  			rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK) -					 * MCE_TIME_UNIT * 1000; - -			if ((ir->buf_in[i] & MCE_PULSE_MASK) == 0x7f) { -				if (ir->rawir.pulse == rawir.pulse) { -					ir->rawir.duration += rawir.duration; -				} else { -					ir->rawir.duration = rawir.duration; -					ir->rawir.pulse = rawir.pulse; -				} -				if (ir->rem) -					break; -			} -			rawir.duration += ir->rawir.duration; -			ir->rawir.duration = 0; -			ir->rawir.pulse = rawir.pulse; +					 * MS_TO_NS(MCE_TIME_UNIT);  			dev_dbg(ir->dev, "Storing %s with duration %d\n",  				rawir.pulse ? "pulse" : "space",  				rawir.duration); -			ir_raw_event_store(ir->idev, &rawir); +			ir_raw_event_store_with_filter(ir->idev, &rawir);  			break;  		case CMD_DATA:  			ir->rem--; @@ -839,17 +882,10 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)  				continue;  			}  			ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK); -			mceusb_dev_printdata(ir, ir->buf_in, i, ir->rem + 1, false); -			if (ir->rem) { +			mceusb_dev_printdata(ir, ir->buf_in, +					     i, ir->rem + 1, false); +			if (ir->rem)  				ir->parser_state = PARSE_IRDATA; -				break; -			} -			/* -			 * a package with len=0 (e. g. 0x80) means end of -			 * data. We could use it to do the call to -			 * ir_raw_event_handle(). For now, we don't need to -			 * use it. -			 */  			break;  		} @@ -984,9 +1020,11 @@ static void mceusb_get_parameters(struct mceusb_dev *ir)  	mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ));  	mce_sync_in(ir, NULL, maxp); -	/* get the transmitter bitmask */ -	mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK)); -	mce_sync_in(ir, NULL, maxp); +	if (!ir->flags.no_tx) { +		/* get the transmitter bitmask */ +		mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK)); +		mce_sync_in(ir, NULL, maxp); +	}  	/* get receiver timeout value */  	mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); @@ -1035,12 +1073,18 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)  	props->priv = ir;  	props->driver_type = RC_DRIVER_IR_RAW;  	props->allowed_protos = IR_TYPE_ALL; -	props->s_tx_mask = mceusb_set_tx_mask; -	props->s_tx_carrier = mceusb_set_tx_carrier; -	props->tx_ir = mceusb_tx_ir; +	props->timeout = MS_TO_NS(1000); +	if (!ir->flags.no_tx) { +		props->s_tx_mask = mceusb_set_tx_mask; +		props->s_tx_carrier = mceusb_set_tx_carrier; +		props->tx_ir = mceusb_tx_ir; +	}  	ir->props = props; +	usb_to_input_id(ir->usbdev, &idev->id); +	idev->dev.parent = ir->dev; +  	if (mceusb_model[ir->model].rc_map)  		rc_map = mceusb_model[ir->model].rc_map; @@ -1074,16 +1118,16 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,  	enum mceusb_model_type model = id->driver_info;  	bool is_gen3;  	bool is_microsoft_gen1; -	bool tx_mask_inverted; +	bool tx_mask_normal;  	bool is_polaris; -	dev_dbg(&intf->dev, ": %s called\n", __func__); +	dev_dbg(&intf->dev, "%s called\n", __func__);  	idesc  = intf->cur_altsetting;  	is_gen3 = mceusb_model[model].mce_gen3;  	is_microsoft_gen1 = mceusb_model[model].mce_gen1; -	tx_mask_inverted = mceusb_model[model].tx_mask_inverted; +	tx_mask_normal = mceusb_model[model].tx_mask_normal;  	is_polaris = mceusb_model[model].is_polaris;  	if (is_polaris) { @@ -1107,7 +1151,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,  			ep_in = ep;  			ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;  			ep_in->bInterval = 1; -			dev_dbg(&intf->dev, ": acceptable inbound endpoint " +			dev_dbg(&intf->dev, "acceptable inbound endpoint "  				"found\n");  		} @@ -1122,12 +1166,12 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,  			ep_out = ep;  			ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;  			ep_out->bInterval = 1; -			dev_dbg(&intf->dev, ": acceptable outbound endpoint " +			dev_dbg(&intf->dev, "acceptable outbound endpoint "  				"found\n");  		}  	}  	if (ep_in == NULL) { -		dev_dbg(&intf->dev, ": inbound and/or endpoint not found\n"); +		dev_dbg(&intf->dev, "inbound and/or endpoint not found\n");  		return -ENODEV;  	} @@ -1150,11 +1194,10 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,  	ir->dev = &intf->dev;  	ir->len_in = maxp;  	ir->flags.microsoft_gen1 = is_microsoft_gen1; -	ir->flags.tx_mask_inverted = tx_mask_inverted; +	ir->flags.tx_mask_normal = tx_mask_normal; +	ir->flags.no_tx = mceusb_model[model].no_tx;  	ir->model = model; -	init_ir_raw_event(&ir->rawir); -  	/* Saving usb interface data for use by the transmitter routine */  	ir->usb_ep_in = ep_in;  	ir->usb_ep_out = ep_out; @@ -1191,7 +1234,8 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,  	mceusb_get_parameters(ir); -	mceusb_set_tx_mask(ir, MCE_DEFAULT_TX_MASK); +	if (!ir->flags.no_tx) +		mceusb_set_tx_mask(ir, MCE_DEFAULT_TX_MASK);  	usb_set_intfdata(intf, ir); diff --git a/drivers/media/IR/nuvoton-cir.c b/drivers/media/IR/nuvoton-cir.c index 301be53aee8..acc729c79ce 100644 --- a/drivers/media/IR/nuvoton-cir.c +++ b/drivers/media/IR/nuvoton-cir.c @@ -603,6 +603,8 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)  	count = nvt->pkts;  	nvt_dbg_verbose("Processing buffer of len %d", count); +	init_ir_raw_event(&rawir); +  	for (i = 0; i < count; i++) {  		nvt->pkts--;  		sample = nvt->buf[i]; @@ -643,11 +645,15 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)  		 * indicates end of IR signal, but new data incoming. In both  		 * cases, it means we're ready to call ir_raw_event_handle  		 */ -		if (sample == BUF_PULSE_BIT || ((sample != BUF_LEN_MASK) && -		    (sample & BUF_REPEAT_MASK) == BUF_REPEAT_BYTE)) +		if ((sample == BUF_PULSE_BIT) && nvt->pkts) { +			nvt_dbg("Calling ir_raw_event_handle (signal end)\n");  			ir_raw_event_handle(nvt->rdev); +		}  	} +	nvt_dbg("Calling ir_raw_event_handle (buffer empty)\n"); +	ir_raw_event_handle(nvt->rdev); +  	if (nvt->pkts) {  		nvt_dbg("Odd, pkts should be 0 now... (its %u)", nvt->pkts);  		nvt->pkts = 0; diff --git a/drivers/media/IR/streamzap.c b/drivers/media/IR/streamzap.c index 548381c35bf..3a20aef67d0 100644 --- a/drivers/media/IR/streamzap.c +++ b/drivers/media/IR/streamzap.c @@ -34,8 +34,9 @@  #include <linux/device.h>  #include <linux/module.h>  #include <linux/slab.h> -#include <linux/usb.h>  #include <linux/input.h> +#include <linux/usb.h> +#include <linux/usb/input.h>  #include <media/ir-core.h>  #define DRIVER_VERSION	"1.61" @@ -140,7 +141,9 @@ static struct usb_driver streamzap_driver = {  static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)  { -	ir_raw_event_store(sz->idev, &rawir); +	dev_dbg(sz->dev, "Storing %s with duration %u us\n", +		(rawir.pulse ? "pulse" : "space"), rawir.duration); +	ir_raw_event_store_with_filter(sz->idev, &rawir);  }  static void sz_push_full_pulse(struct streamzap_ir *sz, @@ -167,7 +170,6 @@ static void sz_push_full_pulse(struct streamzap_ir *sz,  			rawir.duration *= 1000;  			rawir.duration &= IR_MAX_DURATION;  		} -		dev_dbg(sz->dev, "ls %u\n", rawir.duration);  		sz_push(sz, rawir);  		sz->idle = false; @@ -180,7 +182,6 @@ static void sz_push_full_pulse(struct streamzap_ir *sz,  	sz->sum += rawir.duration;  	rawir.duration *= 1000;  	rawir.duration &= IR_MAX_DURATION; -	dev_dbg(sz->dev, "p %u\n", rawir.duration);  	sz_push(sz, rawir);  } @@ -200,7 +201,6 @@ static void sz_push_full_space(struct streamzap_ir *sz,  	rawir.duration += SZ_RESOLUTION / 2;  	sz->sum += rawir.duration;  	rawir.duration *= 1000; -	dev_dbg(sz->dev, "s %u\n", rawir.duration);  	sz_push(sz, rawir);  } @@ -221,8 +221,6 @@ static void streamzap_callback(struct urb *urb)  	struct streamzap_ir *sz;  	unsigned int i;  	int len; -	static int timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) & -				IR_MAX_DURATION) | 0x03000000);  	if (!urb)  		return; @@ -246,7 +244,7 @@ static void streamzap_callback(struct urb *urb)  	dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);  	for (i = 0; i < len; i++) { -		dev_dbg(sz->dev, "sz idx %d: %x\n", +		dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n",  			i, (unsigned char)sz->buf_in[i]);  		switch (sz->decoder_state) {  		case PulseSpace: @@ -273,7 +271,7 @@ static void streamzap_callback(struct urb *urb)  				DEFINE_IR_RAW_EVENT(rawir);  				rawir.pulse = false; -				rawir.duration = timeout; +				rawir.duration = sz->props->timeout;  				sz->idle = true;  				if (sz->timeout_enabled)  					sz_push(sz, rawir); @@ -335,6 +333,9 @@ static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz)  	sz->props = props; +	usb_to_input_id(sz->usbdev, &idev->id); +	idev->dev.parent = sz->dev; +  	ret = ir_input_register(idev, RC_MAP_STREAMZAP, props, DRIVER_NAME);  	if (ret < 0) {  		dev_err(dev, "remote input device register failed\n"); @@ -444,6 +445,8 @@ static int __devinit streamzap_probe(struct usb_interface *intf,  	sz->decoder_state = PulseSpace;  	/* FIXME: don't yet have a way to set this */  	sz->timeout_enabled = true; +	sz->props->timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) & +				IR_MAX_DURATION) | 0x03000000);  	#if 0  	/* not yet supported, depends on patches from maxim */  	/* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */ diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c index 05bde9ccb77..1d1d8d20075 100644 --- a/drivers/media/common/saa7146_hlp.c +++ b/drivers/media/common/saa7146_hlp.c @@ -558,7 +558,7 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e  static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)  {  	struct saa7146_vv *vv = dev->vv_data; -	struct saa7146_format *sfmt = format_by_fourcc(dev, pixelformat); +	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pixelformat);  	int b_depth = vv->ov_fmt->depth;  	int b_bpl = vv->ov_fb.fmt.bytesperline; @@ -702,7 +702,7 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71  	struct saa7146_vv *vv = dev->vv_data;  	struct saa7146_video_dma vdma1; -	struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); +	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);  	int width = buf->fmt->width;  	int height = buf->fmt->height; @@ -827,7 +827,7 @@ static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa71  	struct saa7146_video_dma vdma2;  	struct saa7146_video_dma vdma3; -	struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); +	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);  	int width = buf->fmt->width;  	int height = buf->fmt->height; @@ -994,7 +994,7 @@ static void program_capture_engine(struct saa7146_dev *dev, int planar)  void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)  { -	struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); +	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);  	struct saa7146_vv *vv = dev->vv_data;  	u32 vdma1_prot_addr; diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 741c5732b43..d246910129e 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -84,7 +84,7 @@ static struct saa7146_format formats[] = {  static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format); -struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc) +struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc)  {  	int i, j = NUM_FORMATS; @@ -266,7 +266,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu  	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);  	struct scatterlist *list = dma->sglist;  	int length = dma->sglen; -	struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); +	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);  	DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length)); @@ -408,7 +408,7 @@ static int video_begin(struct saa7146_fh *fh)  		}  	} -	fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); +	fmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);  	/* we need to have a valid format set here */  	BUG_ON(NULL == fmt); @@ -460,7 +460,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file)  		return -EBUSY;  	} -	fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); +	fmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);  	/* we need to have a valid format set here */  	BUG_ON(NULL == fmt); @@ -536,7 +536,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f  		return -EPERM;  	/* check args */ -	fmt = format_by_fourcc(dev, fb->fmt.pixelformat); +	fmt = saa7146_format_by_fourcc(dev, fb->fmt.pixelformat);  	if (NULL == fmt)  		return -EINVAL; @@ -760,7 +760,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma  	DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh)); -	fmt = format_by_fourcc(dev, f->fmt.pix.pixelformat); +	fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);  	if (NULL == fmt)  		return -EINVAL; @@ -1264,7 +1264,7 @@ static int buffer_prepare(struct videobuf_queue *q,  		buf->fmt       = &fh->video_fmt;  		buf->vb.field  = fh->video_fmt.field; -		sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); +		sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);  		release_all_pagetables(dev, buf);  		if( 0 != IS_PLANAR(sfmt->trans)) { @@ -1378,7 +1378,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file)  	fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24;  	fh->video_fmt.bytesperline = 0;  	fh->video_fmt.field = V4L2_FIELD_ANY; -	sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); +	sfmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);  	fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;  	videobuf_queue_sg_init(&fh->video_q, &video_qops, diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 5bf4985daed..05e832f61c3 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -361,7 +361,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations rtrack_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops rtrack_ioctl_ops = { @@ -412,13 +412,6 @@ static int __init rtrack_init(void)  	rt->vdev.release = video_device_release_empty;  	video_set_drvdata(&rt->vdev, rt); -	if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -		v4l2_device_unregister(&rt->v4l2_dev); -		release_region(rt->io, 2); -		return -EINVAL; -	} -	v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n"); -  	/* Set up the I/O locking */  	mutex_init(&rt->lock); @@ -430,6 +423,13 @@ static int __init rtrack_init(void)  	sleep_delay(2000000);	/* make sure it's totally down	*/  	outb(0xc0, rt->io);		/* steady volume, mute card	*/ +	if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +		v4l2_device_unregister(&rt->v4l2_dev); +		release_region(rt->io, 2); +		return -EINVAL; +	} +	v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n"); +  	return 0;  } diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index c2231139362..dd8a6ab0d43 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c @@ -324,7 +324,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,  static const struct v4l2_file_operations aztech_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops aztech_ioctl_ops = { @@ -375,6 +375,8 @@ static int __init aztech_init(void)  	az->vdev.ioctl_ops = &aztech_ioctl_ops;  	az->vdev.release = video_device_release_empty;  	video_set_drvdata(&az->vdev, az); +	/* mute card - prevents noisy bootups */ +	outb(0, az->io);  	if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {  		v4l2_device_unregister(v4l2_dev); @@ -383,8 +385,6 @@ static int __init aztech_init(void)  	}  	v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); -	/* mute card - prevents noisy bootups */ -	outb(0, az->io);  	return 0;  } diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index b701ea6e7c7..bc9ad0897c5 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -328,11 +328,10 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo  	unsigned char readbuf[RDS_BUFFER];  	int i = 0; +	mutex_lock(&dev->lock);  	if (dev->rdsstat == 0) { -		mutex_lock(&dev->lock);  		dev->rdsstat = 1;  		outb(0x80, dev->io);        /* Select RDS fifo */ -		mutex_unlock(&dev->lock);  		init_timer(&dev->readtimer);  		dev->readtimer.function = cadet_handler;  		dev->readtimer.data = (unsigned long)dev; @@ -340,12 +339,15 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo  		add_timer(&dev->readtimer);  	}  	if (dev->rdsin == dev->rdsout) { +		mutex_unlock(&dev->lock);  		if (file->f_flags & O_NONBLOCK)  			return -EWOULDBLOCK;  		interruptible_sleep_on(&dev->read_queue); +		mutex_lock(&dev->lock);  	}  	while (i < count && dev->rdsin != dev->rdsout)  		readbuf[i++] = dev->rdsbuf[dev->rdsout++]; +	mutex_unlock(&dev->lock);  	if (copy_to_user(data, readbuf, i))  		return -EFAULT; @@ -525,9 +527,11 @@ static int cadet_open(struct file *file)  {  	struct cadet *dev = video_drvdata(file); +	mutex_lock(&dev->lock);  	dev->users++;  	if (1 == dev->users)  		init_waitqueue_head(&dev->read_queue); +	mutex_unlock(&dev->lock);  	return 0;  } @@ -535,11 +539,13 @@ static int cadet_release(struct file *file)  {  	struct cadet *dev = video_drvdata(file); +	mutex_lock(&dev->lock);  	dev->users--;  	if (0 == dev->users) {  		del_timer_sync(&dev->readtimer);  		dev->rdsstat = 0;  	} +	mutex_unlock(&dev->lock);  	return 0;  } @@ -559,7 +565,7 @@ static const struct v4l2_file_operations cadet_fops = {  	.open		= cadet_open,  	.release       	= cadet_release,  	.read		= cadet_read, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  	.poll		= cadet_poll,  }; diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index 79039674a0e..28fa85ba208 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c @@ -361,7 +361,7 @@ MODULE_DEVICE_TABLE(pci, gemtek_pci_id);  static const struct v4l2_file_operations gemtek_pci_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = { @@ -422,11 +422,11 @@ static int __devinit gemtek_pci_probe(struct pci_dev *pdev, const struct pci_dev  	card->vdev.release = video_device_release_empty;  	video_set_drvdata(&card->vdev, card); +	gemtek_pci_mute(card); +  	if (video_register_device(&card->vdev, VFL_TYPE_RADIO, nr_radio) < 0)  		goto err_video; -	gemtek_pci_mute(card); -  	v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",  		pdev->revision, card->iobase, card->iobase + card->length - 1); diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index 73985f641f0..259936422e4 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c @@ -378,7 +378,7 @@ static int gemtek_probe(struct gemtek *gt)  static const struct v4l2_file_operations gemtek_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static int vidioc_querycap(struct file *file, void *priv, @@ -577,12 +577,6 @@ static int __init gemtek_init(void)  	gt->vdev.release = video_device_release_empty;  	video_set_drvdata(>->vdev, gt); -	if (video_register_device(>->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -		v4l2_device_unregister(v4l2_dev); -		release_region(gt->io, 1); -		return -EBUSY; -	} -  	/* Set defaults */  	gt->lastfreq = GEMTEK_LOWFREQ;  	gt->bu2614data = 0; @@ -590,6 +584,12 @@ static int __init gemtek_init(void)  	if (initmute)  		gemtek_mute(gt); +	if (video_register_device(>->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +		v4l2_device_unregister(v4l2_dev); +		release_region(gt->io, 1); +		return -EBUSY; +	} +  	return 0;  } diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 08f1051979c..6af61bfeb17 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -299,7 +299,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations maestro_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops maestro_ioctl_ops = { @@ -383,22 +383,20 @@ static int __devinit maestro_probe(struct pci_dev *pdev,  	dev->vdev.release = video_device_release_empty;  	video_set_drvdata(&dev->vdev, dev); +	if (!radio_power_on(dev)) { +		retval = -EIO; +		goto errfr1; +	} +  	retval = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr);  	if (retval) {  		v4l2_err(v4l2_dev, "can't register video device!\n");  		goto errfr1;  	} -	if (!radio_power_on(dev)) { -		retval = -EIO; -		goto errunr; -	} -  	v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n");  	return 0; -errunr: -	video_unregister_device(&dev->vdev);  errfr1:  	v4l2_device_unregister(v4l2_dev);  errfr: diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 255d40df4b4..6459a220b0d 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -346,7 +346,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,  static const struct v4l2_file_operations maxiradio_fops = {  	.owner		= THIS_MODULE, -	.ioctl          = video_ioctl2, +	.unlocked_ioctl = video_ioctl2,  };  static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c index 4ff885445fd..3fb76e3834c 100644 --- a/drivers/media/radio/radio-miropcm20.c +++ b/drivers/media/radio/radio-miropcm20.c @@ -33,6 +33,7 @@ struct pcm20 {  	unsigned long freq;  	int muted;  	struct snd_miro_aci *aci; +	struct mutex lock;  };  static struct pcm20 pcm20_card = { @@ -72,7 +73,7 @@ static int pcm20_setfreq(struct pcm20 *dev, unsigned long freq)  static const struct v4l2_file_operations pcm20_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static int vidioc_querycap(struct file *file, void *priv, @@ -229,7 +230,7 @@ static int __init pcm20_init(void)  		return -ENODEV;  	}  	strlcpy(v4l2_dev->name, "miropcm20", sizeof(v4l2_dev->name)); - +	mutex_init(&dev->lock);  	res = v4l2_device_register(NULL, v4l2_dev);  	if (res < 0) { @@ -242,6 +243,7 @@ static int __init pcm20_init(void)  	dev->vdev.fops = &pcm20_fops;  	dev->vdev.ioctl_ops = &pcm20_ioctl_ops;  	dev->vdev.release = video_device_release_empty; +	dev->vdev.lock = &dev->lock;  	video_set_drvdata(&dev->vdev, dev);  	if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index a79296aac9a..8d6ea591bd1 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c @@ -266,7 +266,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations rtrack2_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = { @@ -315,6 +315,10 @@ static int __init rtrack2_init(void)  	dev->vdev.release = video_device_release_empty;  	video_set_drvdata(&dev->vdev, dev); +	/* mute card - prevents noisy bootups */ +	outb(1, dev->io); +	dev->muted = 1; +  	mutex_init(&dev->lock);  	if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {  		v4l2_device_unregister(v4l2_dev); @@ -324,10 +328,6 @@ static int __init rtrack2_init(void)  	v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n"); -	/* mute card - prevents noisy bootups */ -	outb(1, dev->io); -	dev->muted = 1; -  	return 0;  } diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 985359d18aa..b5a5f89e238 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -260,7 +260,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations fmi_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops fmi_ioctl_ops = { @@ -382,6 +382,9 @@ static int __init fmi_init(void)  	mutex_init(&fmi->lock); +	/* mute card - prevents noisy bootups */ +	fmi_mute(fmi); +  	if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {  		v4l2_device_unregister(v4l2_dev);  		release_region(fmi->io, 2); @@ -391,8 +394,6 @@ static int __init fmi_init(void)  	}  	v4l2_info(v4l2_dev, "card driver at 0x%x\n", fmi->io); -	/* mute card - prevents noisy bootups */ -	fmi_mute(fmi);  	return 0;  } diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 52c7bbb32b8..dc3f04c52d5 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -376,7 +376,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations fmr2_fops = {  	.owner          = THIS_MODULE, -	.ioctl          = video_ioctl2, +	.unlocked_ioctl = video_ioctl2,  };  static const struct v4l2_ioctl_ops fmr2_ioctl_ops = { @@ -424,6 +424,10 @@ static int __init fmr2_init(void)  	fmr2->vdev.release = video_device_release_empty;  	video_set_drvdata(&fmr2->vdev, fmr2); +	/* mute card - prevents noisy bootups */ +	fmr2_mute(fmr2->io); +	fmr2_product_info(fmr2); +  	if (video_register_device(&fmr2->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {  		v4l2_device_unregister(v4l2_dev);  		release_region(fmr2->io, 2); @@ -431,11 +435,6 @@ static int __init fmr2_init(void)  	}  	v4l2_info(v4l2_dev, "SF16FMR2 radio card driver at 0x%x.\n", fmr2->io); -	/* mute card - prevents noisy bootups */ -	mutex_lock(&fmr2->lock); -	fmr2_mute(fmr2->io); -	fmr2_product_info(fmr2); -	mutex_unlock(&fmr2->lock);  	debug_print((KERN_DEBUG "card_type %d\n", fmr2->card_type));  	return 0;  } diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c index 03829e6818b..726d367ad8d 100644 --- a/drivers/media/radio/radio-si4713.c +++ b/drivers/media/radio/radio-si4713.c @@ -53,7 +53,8 @@ struct radio_si4713_device {  /* radio_si4713_fops - file operations interface */  static const struct v4l2_file_operations radio_si4713_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	/* Note: locking is done at the subdev level in the i2c driver. */ +	.unlocked_ioctl	= video_ioctl2,  };  /* Video4Linux Interface */ diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 789d2ec66e1..0e71d816c72 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -142,7 +142,6 @@ struct tea5764_device {  	struct video_device		*videodev;  	struct tea5764_regs		regs;  	struct mutex			mutex; -	int				users;  };  /* I2C code related */ @@ -458,41 +457,10 @@ static int vidioc_s_audio(struct file *file, void *priv,  	return 0;  } -static int tea5764_open(struct file *file) -{ -	/* Currently we support only one device */ -	struct tea5764_device *radio = video_drvdata(file); - -	mutex_lock(&radio->mutex); -	/* Only exclusive access */ -	if (radio->users) { -		mutex_unlock(&radio->mutex); -		return -EBUSY; -	} -	radio->users++; -	mutex_unlock(&radio->mutex); -	file->private_data = radio; -	return 0; -} - -static int tea5764_close(struct file *file) -{ -	struct tea5764_device *radio = video_drvdata(file); - -	if (!radio) -		return -ENODEV; -	mutex_lock(&radio->mutex); -	radio->users--; -	mutex_unlock(&radio->mutex); -	return 0; -} -  /* File system interface */  static const struct v4l2_file_operations tea5764_fops = {  	.owner		= THIS_MODULE, -	.open           = tea5764_open, -	.release        = tea5764_close, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops tea5764_ioctl_ops = { @@ -527,7 +495,7 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,  	int ret;  	PDEBUG("probe"); -	radio = kmalloc(sizeof(struct tea5764_device), GFP_KERNEL); +	radio = kzalloc(sizeof(struct tea5764_device), GFP_KERNEL);  	if (!radio)  		return -ENOMEM; @@ -555,12 +523,7 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,  	i2c_set_clientdata(client, radio);  	video_set_drvdata(radio->videodev, radio); - -	ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); -	if (ret < 0) { -		PWARN("Could not register video device!"); -		goto errrel; -	} +	radio->videodev->lock = &radio->mutex;  	/* initialize and power off the chip */  	tea5764_i2c_read(radio); @@ -568,6 +531,12 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,  	tea5764_mute(radio, 1);  	tea5764_power_down(radio); +	ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); +	if (ret < 0) { +		PWARN("Could not register video device!"); +		goto errrel; +	} +  	PINFO("registered.");  	return 0;  errrel: diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index fc1c860fd43..a3266391705 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c @@ -338,7 +338,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations terratec_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops terratec_ioctl_ops = { @@ -389,6 +389,9 @@ static int __init terratec_init(void)  	mutex_init(&tt->lock); +	/* mute card - prevents noisy bootups */ +	tt_write_vol(tt, 0); +  	if (video_register_device(&tt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {  		v4l2_device_unregister(&tt->v4l2_dev);  		release_region(tt->io, 2); @@ -396,9 +399,6 @@ static int __init terratec_init(void)  	}  	v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver.\n"); - -	/* mute card - prevents noisy bootups */ -	tt_write_vol(tt, 0);  	return 0;  } diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c index b8bb3ef47df..a185610b376 100644 --- a/drivers/media/radio/radio-timb.c +++ b/drivers/media/radio/radio-timb.c @@ -34,6 +34,7 @@ struct timbradio {  	struct v4l2_subdev	*sd_dsp;  	struct video_device	video_dev;  	struct v4l2_device	v4l2_dev; +	struct mutex		lock;  }; @@ -142,7 +143,7 @@ static const struct v4l2_ioctl_ops timbradio_ioctl_ops = {  static const struct v4l2_file_operations timbradio_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static int __devinit timbradio_probe(struct platform_device *pdev) @@ -164,6 +165,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev)  	}  	tr->pdata = *pdata; +	mutex_init(&tr->lock);  	strlcpy(tr->video_dev.name, "Timberdale Radio",  		sizeof(tr->video_dev.name)); @@ -171,6 +173,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev)  	tr->video_dev.ioctl_ops = &timbradio_ioctl_ops;  	tr->video_dev.release = video_device_release_empty;  	tr->video_dev.minor = -1; +	tr->video_dev.lock = &tr->lock;  	strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));  	err = v4l2_device_register(NULL, &tr->v4l2_dev); diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c index 9d6dcf8af5b..22fa9cc28ab 100644 --- a/drivers/media/radio/radio-trust.c +++ b/drivers/media/radio/radio-trust.c @@ -344,7 +344,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations trust_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops trust_ioctl_ops = { @@ -396,14 +396,6 @@ static int __init trust_init(void)  	tr->vdev.release = video_device_release_empty;  	video_set_drvdata(&tr->vdev, tr); -	if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -		v4l2_device_unregister(v4l2_dev); -		release_region(tr->io, 2); -		return -EINVAL; -	} - -	v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n"); -  	write_i2c(tr, 2, TDA7318_ADDR, 0x80);	/* speaker att. LF = 0 dB */  	write_i2c(tr, 2, TDA7318_ADDR, 0xa0);	/* speaker att. RF = 0 dB */  	write_i2c(tr, 2, TDA7318_ADDR, 0xc0);	/* speaker att. LR = 0 dB */ @@ -418,6 +410,14 @@ static int __init trust_init(void)  	/* mute card - prevents noisy bootups */  	tr_setmute(tr, 1); +	if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +		v4l2_device_unregister(v4l2_dev); +		release_region(tr->io, 2); +		return -EINVAL; +	} + +	v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n"); +  	return 0;  } diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index b1f630527dc..8dbbf08f220 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -317,7 +317,7 @@ static int vidioc_log_status(struct file *file, void *priv)  static const struct v4l2_file_operations typhoon_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops typhoon_ioctl_ops = { @@ -344,18 +344,18 @@ static int __init typhoon_init(void)  	strlcpy(v4l2_dev->name, "typhoon", sizeof(v4l2_dev->name));  	dev->io = io; -	dev->curfreq = dev->mutefreq = mutefreq;  	if (dev->io == -1) {  		v4l2_err(v4l2_dev, "You must set an I/O address with io=0x316 or io=0x336\n");  		return -EINVAL;  	} -	if (dev->mutefreq < 87000 || dev->mutefreq > 108500) { +	if (mutefreq < 87000 || mutefreq > 108500) {  		v4l2_err(v4l2_dev, "You must set a frequency (in kHz) used when muting the card,\n");  		v4l2_err(v4l2_dev, "e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n");  		return -EINVAL;  	} +	dev->curfreq = dev->mutefreq = mutefreq << 4;  	mutex_init(&dev->lock);  	if (!request_region(dev->io, 8, "typhoon")) { @@ -378,17 +378,17 @@ static int __init typhoon_init(void)  	dev->vdev.ioctl_ops = &typhoon_ioctl_ops;  	dev->vdev.release = video_device_release_empty;  	video_set_drvdata(&dev->vdev, dev); + +	/* mute card - prevents noisy bootups */ +	typhoon_mute(dev); +  	if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {  		v4l2_device_unregister(&dev->v4l2_dev);  		release_region(dev->io, 8);  		return -EINVAL;  	}  	v4l2_info(v4l2_dev, "port 0x%x.\n", dev->io); -	v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", dev->mutefreq); -	dev->mutefreq <<= 4; - -	/* mute card - prevents noisy bootups */ -	typhoon_mute(dev); +	v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", mutefreq);  	return 0;  } diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index f31eab99c94..af99c5bd88c 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -377,7 +377,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations zoltrix_fops =  {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = { @@ -424,20 +424,6 @@ static int __init zoltrix_init(void)  		return res;  	} -	strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name)); -	zol->vdev.v4l2_dev = v4l2_dev; -	zol->vdev.fops = &zoltrix_fops; -	zol->vdev.ioctl_ops = &zoltrix_ioctl_ops; -	zol->vdev.release = video_device_release_empty; -	video_set_drvdata(&zol->vdev, zol); - -	if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -		v4l2_device_unregister(v4l2_dev); -		release_region(zol->io, 2); -		return -EINVAL; -	} -	v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n"); -  	mutex_init(&zol->lock);  	/* mute card - prevents noisy bootups */ @@ -452,6 +438,20 @@ static int __init zoltrix_init(void)  	zol->curvol = 0;  	zol->stereo = 1; +	strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name)); +	zol->vdev.v4l2_dev = v4l2_dev; +	zol->vdev.fops = &zoltrix_fops; +	zol->vdev.ioctl_ops = &zoltrix_ioctl_ops; +	zol->vdev.release = video_device_release_empty; +	video_set_drvdata(&zol->vdev, zol); + +	if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +		v4l2_device_unregister(v4l2_dev); +		release_region(zol->io, 2); +		return -EINVAL; +	} +	v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n"); +  	return 0;  } diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 31e7a123d19..f989f2820d8 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -712,7 +712,7 @@ static int ar_initialize(struct ar *ar)  static const struct v4l2_file_operations ar_fops = {  	.owner		= THIS_MODULE,  	.read		= ar_read, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops ar_ioctl_ops = { diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index a529619e51f..0902ec041c7 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -854,7 +854,6 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)  		xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;  	/* is it free? */ -	mutex_lock(&btv->lock);  	if (btv->resources & xbits) {  		/* no, someone else uses it */  		goto fail; @@ -884,11 +883,9 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)  	/* it's free, grab it */  	fh->resources  |= bit;  	btv->resources |= bit; -	mutex_unlock(&btv->lock);  	return 1;   fail: -	mutex_unlock(&btv->lock);  	return 0;  } @@ -940,7 +937,6 @@ void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)  		/* trying to free ressources not allocated by us ... */  		printk("bttv: BUG! (btres)\n");  	} -	mutex_lock(&btv->lock);  	fh->resources  &= ~bits;  	btv->resources &= ~bits; @@ -951,8 +947,6 @@ void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)  	if (0 == (bits & VBI_RESOURCES))  		disclaim_vbi_lines(btv); - -	mutex_unlock(&btv->lock);  }  /* ----------------------------------------------------------------------- */ @@ -1713,28 +1707,20 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,  		/* Make sure tvnorm and vbi_end remain consistent  		   until we're done. */ -		mutex_lock(&btv->lock);  		norm = btv->tvnorm;  		/* In this mode capturing always starts at defrect.top  		   (default VDELAY), ignoring cropping parameters. */  		if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) { -			mutex_unlock(&btv->lock);  			return -EINVAL;  		} -		mutex_unlock(&btv->lock); -  		c.rect = bttv_tvnorms[norm].cropcap.defrect;  	} else { -		mutex_lock(&btv->lock); -  		norm = btv->tvnorm;  		c = btv->crop[!!fh->do_crop]; -		mutex_unlock(&btv->lock); -  		if (width < c.min_scaled_width ||  		    width > c.max_scaled_width ||  		    height < c.min_scaled_height) @@ -1858,7 +1844,6 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)  	unsigned int i;  	int err; -	mutex_lock(&btv->lock);  	err = v4l2_prio_check(&btv->prio, fh->prio);  	if (err)  		goto err; @@ -1874,7 +1859,6 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)  	set_tvnorm(btv, i);  err: -	mutex_unlock(&btv->lock);  	return err;  } @@ -1898,7 +1882,6 @@ static int bttv_enum_input(struct file *file, void *priv,  	struct bttv *btv = fh->btv;  	int rc = 0; -	mutex_lock(&btv->lock);  	if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {  		rc = -EINVAL;  		goto err; @@ -1928,7 +1911,6 @@ static int bttv_enum_input(struct file *file, void *priv,  	i->std = BTTV_NORMS;  err: -	mutex_unlock(&btv->lock);  	return rc;  } @@ -1938,9 +1920,7 @@ static int bttv_g_input(struct file *file, void *priv, unsigned int *i)  	struct bttv_fh *fh = priv;  	struct bttv *btv = fh->btv; -	mutex_lock(&btv->lock);  	*i = btv->input; -	mutex_unlock(&btv->lock);  	return 0;  } @@ -1952,7 +1932,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)  	int err; -	mutex_lock(&btv->lock);  	err = v4l2_prio_check(&btv->prio, fh->prio);  	if (unlikely(err))  		goto err; @@ -1965,7 +1944,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)  	set_input(btv, i, btv->tvnorm);  err: -	mutex_unlock(&btv->lock);  	return 0;  } @@ -1979,7 +1957,6 @@ static int bttv_s_tuner(struct file *file, void *priv,  	if (unlikely(0 != t->index))  		return -EINVAL; -	mutex_lock(&btv->lock);  	if (unlikely(btv->tuner_type == TUNER_ABSENT)) {  		err = -EINVAL;  		goto err; @@ -1995,7 +1972,6 @@ static int bttv_s_tuner(struct file *file, void *priv,  		btv->audio_mode_gpio(btv, t, 1);  err: -	mutex_unlock(&btv->lock);  	return 0;  } @@ -2006,10 +1982,8 @@ static int bttv_g_frequency(struct file *file, void *priv,  	struct bttv_fh *fh  = priv;  	struct bttv *btv = fh->btv; -	mutex_lock(&btv->lock);  	f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;  	f->frequency = btv->freq; -	mutex_unlock(&btv->lock);  	return 0;  } @@ -2024,7 +1998,6 @@ static int bttv_s_frequency(struct file *file, void *priv,  	if (unlikely(f->tuner != 0))  		return -EINVAL; -	mutex_lock(&btv->lock);  	err = v4l2_prio_check(&btv->prio, fh->prio);  	if (unlikely(err))  		goto err; @@ -2039,7 +2012,6 @@ static int bttv_s_frequency(struct file *file, void *priv,  	if (btv->has_matchbox && btv->radio_user)  		tea5757_set_freq(btv, btv->freq);  err: -	mutex_unlock(&btv->lock);  	return 0;  } @@ -2172,7 +2144,6 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,  	/* Make sure tvnorm, vbi_end and the current cropping parameters  	   remain consistent until we're done. */ -	mutex_lock(&btv->lock);  	b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds; @@ -2250,7 +2221,6 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,  	rc = 0; /* success */   fail: -	mutex_unlock(&btv->lock);  	return rc;  } @@ -2282,9 +2252,7 @@ verify_window_lock		(struct bttv_fh *               fh,  	if (V4L2_FIELD_ANY == field) {  		__s32 height2; -		mutex_lock(&fh->btv->lock);  		height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1; -		mutex_unlock(&fh->btv->lock);  		field = (win->w.height > height2)  			? V4L2_FIELD_INTERLACED  			: V4L2_FIELD_TOP; @@ -2360,7 +2328,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,  		}  	} -	mutex_lock(&fh->cap.vb_lock);  	/* clip against screen */  	if (NULL != btv->fbuf.base)  		n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height, @@ -2391,13 +2358,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,  	fh->ov.field    = win->field;  	fh->ov.setup_ok = 1; -	/* -	 * FIXME: btv is protected by btv->lock mutex, while btv->init -	 *	  is protected by fh->cap.vb_lock. This seems to open the -	 *	  possibility for some race situations. Maybe the better would -	 *	  be to unify those locks or to use another way to store the -	 *	  init values that will be consumed by videobuf callbacks -	 */  	btv->init.ov.w.width   = win->w.width;  	btv->init.ov.w.height  = win->w.height;  	btv->init.ov.field     = win->field; @@ -2412,7 +2372,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,  		bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);  		retval = bttv_switch_overlay(btv,fh,new);  	} -	mutex_unlock(&fh->cap.vb_lock);  	return retval;  } @@ -2526,9 +2485,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,  	if (V4L2_FIELD_ANY == field) {  		__s32 height2; -		mutex_lock(&btv->lock);  		height2 = btv->crop[!!fh->do_crop].rect.height >> 1; -		mutex_unlock(&btv->lock);  		field = (f->fmt.pix.height > height2)  			? V4L2_FIELD_INTERLACED  			: V4L2_FIELD_BOTTOM; @@ -2614,7 +2571,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv,  	fmt = format_by_fourcc(f->fmt.pix.pixelformat);  	/* update our state informations */ -	mutex_lock(&fh->cap.vb_lock);  	fh->fmt              = fmt;  	fh->cap.field        = f->fmt.pix.field;  	fh->cap.last         = V4L2_FIELD_NONE; @@ -2623,7 +2579,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv,  	btv->init.fmt        = fmt;  	btv->init.width      = f->fmt.pix.width;  	btv->init.height     = f->fmt.pix.height; -	mutex_unlock(&fh->cap.vb_lock);  	return 0;  } @@ -2649,11 +2604,9 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)  	unsigned int i;  	struct bttv_fh *fh = priv; -	mutex_lock(&fh->cap.vb_lock);  	retval = __videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,  				     V4L2_MEMORY_MMAP);  	if (retval < 0) { -		mutex_unlock(&fh->cap.vb_lock);  		return retval;  	} @@ -2665,7 +2618,6 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)  	for (i = 0; i < gbuffers; i++)  		mbuf->offsets[i] = i * gbufsize; -	mutex_unlock(&fh->cap.vb_lock);  	return 0;  }  #endif @@ -2775,10 +2727,8 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)  	int retval = 0;  	if (on) { -		mutex_lock(&fh->cap.vb_lock);  		/* verify args */  		if (unlikely(!btv->fbuf.base)) { -			mutex_unlock(&fh->cap.vb_lock);  			return -EINVAL;  		}  		if (unlikely(!fh->ov.setup_ok)) { @@ -2787,13 +2737,11 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)  		}  		if (retval)  			return retval; -		mutex_unlock(&fh->cap.vb_lock);  	}  	if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))  		return -EBUSY; -	mutex_lock(&fh->cap.vb_lock);  	if (on) {  		fh->ov.tvnorm = btv->tvnorm;  		new = videobuf_sg_alloc(sizeof(*new)); @@ -2805,7 +2753,6 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)  	/* switch over */  	retval = bttv_switch_overlay(btv, fh, new); -	mutex_unlock(&fh->cap.vb_lock);  	return retval;  } @@ -2844,7 +2791,6 @@ static int bttv_s_fbuf(struct file *file, void *f,  	}  	/* ok, accept it */ -	mutex_lock(&fh->cap.vb_lock);  	btv->fbuf.base       = fb->base;  	btv->fbuf.fmt.width  = fb->fmt.width;  	btv->fbuf.fmt.height = fb->fmt.height; @@ -2876,7 +2822,6 @@ static int bttv_s_fbuf(struct file *file, void *f,  			retval = bttv_switch_overlay(btv, fh, new);  		}  	} -	mutex_unlock(&fh->cap.vb_lock);  	return retval;  } @@ -2955,7 +2900,6 @@ static int bttv_queryctrl(struct file *file, void *priv,  	     c->id >= V4L2_CID_PRIVATE_LASTP1))  		return -EINVAL; -	mutex_lock(&btv->lock);  	if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))  		*c = no_ctl;  	else { @@ -2963,7 +2907,6 @@ static int bttv_queryctrl(struct file *file, void *priv,  		*c = (NULL != ctrl) ? *ctrl : no_ctl;  	} -	mutex_unlock(&btv->lock);  	return 0;  } @@ -2974,10 +2917,8 @@ static int bttv_g_parm(struct file *file, void *f,  	struct bttv_fh *fh = f;  	struct bttv *btv = fh->btv; -	mutex_lock(&btv->lock);  	v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,  				    &parm->parm.capture.timeperframe); -	mutex_unlock(&btv->lock);  	return 0;  } @@ -2993,7 +2934,6 @@ static int bttv_g_tuner(struct file *file, void *priv,  	if (0 != t->index)  		return -EINVAL; -	mutex_lock(&btv->lock);  	t->rxsubchans = V4L2_TUNER_SUB_MONO;  	bttv_call_all(btv, tuner, g_tuner, t);  	strcpy(t->name, "Television"); @@ -3005,7 +2945,6 @@ static int bttv_g_tuner(struct file *file, void *priv,  	if (btv->audio_mode_gpio)  		btv->audio_mode_gpio(btv, t, 0); -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3014,9 +2953,7 @@ static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)  	struct bttv_fh *fh = f;  	struct bttv *btv = fh->btv; -	mutex_lock(&btv->lock);  	*p = v4l2_prio_max(&btv->prio); -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3028,9 +2965,7 @@ static int bttv_s_priority(struct file *file, void *f,  	struct bttv *btv = fh->btv;  	int	rc; -	mutex_lock(&btv->lock);  	rc = v4l2_prio_change(&btv->prio, &fh->prio, prio); -	mutex_unlock(&btv->lock);  	return rc;  } @@ -3045,9 +2980,7 @@ static int bttv_cropcap(struct file *file, void *priv,  	    cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)  		return -EINVAL; -	mutex_lock(&btv->lock);  	*cap = bttv_tvnorms[btv->tvnorm].cropcap; -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3065,9 +2998,7 @@ static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)  	   inconsistent with fh->width or fh->height and apps  	   do not expect a change here. */ -	mutex_lock(&btv->lock);  	crop->c = btv->crop[!!fh->do_crop].rect; -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3091,17 +3022,14 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)  	/* Make sure tvnorm, vbi_end and the current cropping  	   parameters remain consistent until we're done. Note  	   read() may change vbi_end in check_alloc_btres_lock(). */ -	mutex_lock(&btv->lock);  	retval = v4l2_prio_check(&btv->prio, fh->prio);  	if (0 != retval) { -		mutex_unlock(&btv->lock);  		return retval;  	}  	retval = -EBUSY;  	if (locked_btres(fh->btv, VIDEO_RESOURCES)) { -		mutex_unlock(&btv->lock);  		return retval;  	} @@ -3113,7 +3041,6 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)  	b_top = max(b->top, btv->vbi_end);  	if (b_top + 32 >= b_bottom) { -		mutex_unlock(&btv->lock);  		return retval;  	} @@ -3136,12 +3063,8 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)  	btv->crop[1] = c; -	mutex_unlock(&btv->lock); -  	fh->do_crop = 1; -	mutex_lock(&fh->cap.vb_lock); -  	if (fh->width < c.min_scaled_width) {  		fh->width = c.min_scaled_width;  		btv->init.width = c.min_scaled_width; @@ -3158,8 +3081,6 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)  		btv->init.height = c.max_scaled_height;  	} -	mutex_unlock(&fh->cap.vb_lock); -  	return 0;  } @@ -3227,7 +3148,6 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)  		return videobuf_poll_stream(file, &fh->vbi, wait);  	} -	mutex_lock(&fh->cap.vb_lock);  	if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {  		/* streaming capture */  		if (list_empty(&fh->cap.stream)) @@ -3262,7 +3182,6 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)  	else  		rc = 0;  err: -	mutex_unlock(&fh->cap.vb_lock);  	return rc;  } @@ -3293,23 +3212,11 @@ static int bttv_open(struct file *file)  		return -ENOMEM;  	file->private_data = fh; -	/* -	 * btv is protected by btv->lock mutex, while btv->init and other -	 * streaming vars are protected by fh->cap.vb_lock. We need to take -	 * care of both locks to avoid troubles. However, vb_lock is used also -	 * inside videobuf, without calling buf->lock. So, it is a very bad -	 * idea to hold both locks at the same time. -	 * Let's first copy btv->init at fh, holding cap.vb_lock, and then work -	 * with the rest of init, holding btv->lock. -	 */ -	mutex_lock(&fh->cap.vb_lock);  	*fh = btv->init; -	mutex_unlock(&fh->cap.vb_lock);  	fh->type = type;  	fh->ov.setup_ok = 0; -	mutex_lock(&btv->lock);  	v4l2_prio_open(&btv->prio, &fh->prio);  	videobuf_queue_sg_init(&fh->cap, &bttv_video_qops, @@ -3317,13 +3224,13 @@ static int bttv_open(struct file *file)  			    V4L2_BUF_TYPE_VIDEO_CAPTURE,  			    V4L2_FIELD_INTERLACED,  			    sizeof(struct bttv_buffer), -			    fh, NULL); +			    fh, &btv->lock);  	videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,  			    &btv->c.pci->dev, &btv->s_lock,  			    V4L2_BUF_TYPE_VBI_CAPTURE,  			    V4L2_FIELD_SEQ_TB,  			    sizeof(struct bttv_buffer), -			    fh, NULL); +			    fh, &btv->lock);  	set_tvnorm(btv,btv->tvnorm);  	set_input(btv, btv->input, btv->tvnorm); @@ -3346,7 +3253,6 @@ static int bttv_open(struct file *file)  	bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);  	bttv_field_count(btv); -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3355,7 +3261,6 @@ static int bttv_release(struct file *file)  	struct bttv_fh *fh = file->private_data;  	struct bttv *btv = fh->btv; -	mutex_lock(&btv->lock);  	/* turn off overlay */  	if (check_btres(fh, RESOURCE_OVERLAY))  		bttv_switch_overlay(btv,fh,NULL); @@ -3381,14 +3286,8 @@ static int bttv_release(struct file *file)  	/* free stuff */ -	/* -	 * videobuf uses cap.vb_lock - we should avoid holding btv->lock, -	 * otherwise we may have dead lock conditions -	 */ -	mutex_unlock(&btv->lock);  	videobuf_mmap_free(&fh->cap);  	videobuf_mmap_free(&fh->vbi); -	mutex_lock(&btv->lock);  	v4l2_prio_close(&btv->prio, fh->prio);  	file->private_data = NULL;  	kfree(fh); @@ -3398,7 +3297,6 @@ static int bttv_release(struct file *file)  	if (!btv->users)  		audio_mute(btv, 1); -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3502,11 +3400,8 @@ static int radio_open(struct file *file)  	if (unlikely(!fh))  		return -ENOMEM;  	file->private_data = fh; -	mutex_lock(&fh->cap.vb_lock);  	*fh = btv->init; -	mutex_unlock(&fh->cap.vb_lock); -	mutex_lock(&btv->lock);  	v4l2_prio_open(&btv->prio, &fh->prio);  	btv->radio_user++; @@ -3514,7 +3409,6 @@ static int radio_open(struct file *file)  	bttv_call_all(btv, tuner, s_radio);  	audio_input(btv,TVAUDIO_INPUT_RADIO); -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3524,7 +3418,6 @@ static int radio_release(struct file *file)  	struct bttv *btv = fh->btv;  	struct rds_command cmd; -	mutex_lock(&btv->lock);  	v4l2_prio_close(&btv->prio, fh->prio);  	file->private_data = NULL;  	kfree(fh); @@ -3532,7 +3425,6 @@ static int radio_release(struct file *file)  	btv->radio_user--;  	bttv_call_all(btv, core, ioctl, RDS_CMD_CLOSE, &cmd); -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3561,7 +3453,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)  		return -EINVAL;  	if (0 != t->index)  		return -EINVAL; -	mutex_lock(&btv->lock);  	strcpy(t->name, "Radio");  	t->type = V4L2_TUNER_RADIO; @@ -3570,8 +3461,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)  	if (btv->audio_mode_gpio)  		btv->audio_mode_gpio(btv, t, 0); -	mutex_unlock(&btv->lock); -  	return 0;  } @@ -3692,7 +3581,7 @@ static const struct v4l2_file_operations radio_fops =  	.open	  = radio_open,  	.read     = radio_read,  	.release  = radio_release, -	.ioctl	  = video_ioctl2, +	.unlocked_ioctl = video_ioctl2,  	.poll     = radio_poll,  }; diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 935e0c9a967..c1193506131 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -860,7 +860,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,  static const struct v4l2_file_operations qcam_fops = {  	.owner		= THIS_MODULE, -	.ioctl          = video_ioctl2, +	.unlocked_ioctl = video_ioctl2,  	.read		= qcam_read,  }; diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 6e4b19698c1..24fc00965a1 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -718,7 +718,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,  static const struct v4l2_file_operations qcam_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  	.read		= qcam_read,  }; diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 260c666ce93..0dfff50891e 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -1775,7 +1775,7 @@ static const struct v4l2_file_operations cafe_v4l_fops = {  	.read = cafe_v4l_read,  	.poll = cafe_v4l_poll,  	.mmap = cafe_v4l_mmap, -	.ioctl = video_ioctl2, +	.unlocked_ioctl = video_ioctl2,  };  static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = { diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.c b/drivers/media/video/cx18/cx18-alsa-pcm.c index 8f55692db36..82d195be919 100644 --- a/drivers/media/video/cx18/cx18-alsa-pcm.c +++ b/drivers/media/video/cx18/cx18-alsa-pcm.c @@ -218,7 +218,13 @@ static int snd_cx18_pcm_capture_close(struct snd_pcm_substream *substream)  static int snd_cx18_pcm_ioctl(struct snd_pcm_substream *substream,  		     unsigned int cmd, void *arg)  { -	return snd_pcm_lib_ioctl(substream, cmd, arg); +	struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); +	int ret; + +	snd_cx18_lock(cxsc); +	ret = snd_pcm_lib_ioctl(substream, cmd, arg); +	snd_cx18_unlock(cxsc); +	return ret;  } diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 9045f1ece0e..ab461e27d9d 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -41,7 +41,7 @@ static struct v4l2_file_operations cx18_v4l2_enc_fops = {  	.read = cx18_v4l2_read,  	.open = cx18_v4l2_open,  	/* FIXME change to video_ioctl2 if serialization lock can be removed */ -	.ioctl = cx18_v4l2_ioctl, +	.unlocked_ioctl = cx18_v4l2_ioctl,  	.release = cx18_v4l2_close,  	.poll = cx18_v4l2_enc_poll,  }; diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index dfb198d0415..f16461844c5 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1989,8 +1989,23 @@ static int cx25840_probe(struct i2c_client *client,  	v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,  			V4L2_CID_HUE, -128, 127, 1, 0);  	if (!is_cx2583x(state)) { -		default_volume = 228 - cx25840_read(client, 0x8d4); -		default_volume = ((default_volume / 2) + 23) << 9; +		default_volume = cx25840_read(client, 0x8d4); +		/* +		 * Enforce the legacy PVR-350/MSP3400 to PVR-150/CX25843 volume +		 * scale mapping limits to avoid -ERANGE errors when +		 * initializing the volume control +		 */ +		if (default_volume > 228) { +			/* Bottom out at -96 dB, v4l2 vol range 0x2e00-0x2fff */ +			default_volume = 228; +			cx25840_write(client, 0x8d4, 228); +		} +		else if (default_volume < 20) { +			/* Top out at + 8 dB, v4l2 vol range 0xfe00-0xffff */ +			default_volume = 20; +			cx25840_write(client, 0x8d4, 20); +		} +		default_volume = (((228 - default_volume) >> 1) + 23) << 9;  		state->volume = v4l2_ctrl_new_std(&state->hdl,  			&cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME, diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 4aaa47c0eab..54b7fcd469a 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -40,7 +40,6 @@  #include <sound/control.h>  #include <sound/initval.h>  #include <sound/tlv.h> -#include <media/wm8775.h>  #include "cx88.h"  #include "cx88-reg.h" @@ -587,47 +586,26 @@ static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol,  	int left, right, v, b;  	int changed = 0;  	u32 old; -	struct v4l2_control client_ctl; - -	/* Pass volume & balance onto any WM8775 */ -	if (value->value.integer.value[0] >= value->value.integer.value[1]) { -		v = value->value.integer.value[0] << 10; -		b = value->value.integer.value[0] ? -			(0x8000 * value->value.integer.value[1]) / value->value.integer.value[0] : -			0x8000; -	} else { -		v = value->value.integer.value[1] << 10; -		b = value->value.integer.value[1] ? -		0xffff - (0x8000 * value->value.integer.value[0]) / value->value.integer.value[1] : -		0x8000; -	} -	client_ctl.value = v; -	client_ctl.id = V4L2_CID_AUDIO_VOLUME; -	call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); - -	client_ctl.value = b; -	client_ctl.id = V4L2_CID_AUDIO_BALANCE; -	call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);  	left = value->value.integer.value[0] & 0x3f;  	right = value->value.integer.value[1] & 0x3f;  	b = right - left;  	if (b < 0) { -		v = 0x3f - left; -		b = (-b) | 0x40; +	    v = 0x3f - left; +	    b = (-b) | 0x40;  	} else { -		v = 0x3f - right; +	    v = 0x3f - right;  	}  	/* Do we really know this will always be called with IRQs on? */  	spin_lock_irq(&chip->reg_lock);  	old = cx_read(AUD_VOL_CTL);  	if (v != (old & 0x3f)) { -		cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v); -		changed = 1; +	    cx_write(AUD_VOL_CTL, (old & ~0x3f) | v); +	    changed = 1;  	} -	if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) { -		cx_write(AUD_BAL_CTL, b); -		changed = 1; +	if (cx_read(AUD_BAL_CTL) != b) { +	    cx_write(AUD_BAL_CTL, b); +	    changed = 1;  	}  	spin_unlock_irq(&chip->reg_lock); @@ -640,7 +618,7 @@ static const struct snd_kcontrol_new snd_cx88_volume = {  	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,  	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |  		  SNDRV_CTL_ELEM_ACCESS_TLV_READ, -	.name = "Analog-TV Volume", +	.name = "Playback Volume",  	.info = snd_cx88_volume_info,  	.get = snd_cx88_volume_get,  	.put = snd_cx88_volume_put, @@ -671,14 +649,7 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,  	vol = cx_read(AUD_VOL_CTL);  	if (value->value.integer.value[0] != !(vol & bit)) {  		vol ^= bit; -		cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol); -		/* Pass mute onto any WM8775 */ -		if ((1<<6) == bit) { -			struct v4l2_control client_ctl; -			client_ctl.value = 0 != (vol & bit); -			client_ctl.id = V4L2_CID_AUDIO_MUTE; -			call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); -		} +		cx_write(AUD_VOL_CTL, vol);  		ret = 1;  	}  	spin_unlock_irq(&chip->reg_lock); @@ -687,7 +658,7 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,  static const struct snd_kcontrol_new snd_cx88_dac_switch = {  	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, -	.name = "Audio-Out Switch", +	.name = "Playback Switch",  	.info = snd_ctl_boolean_mono_info,  	.get = snd_cx88_switch_get,  	.put = snd_cx88_switch_put, @@ -696,49 +667,13 @@ static const struct snd_kcontrol_new snd_cx88_dac_switch = {  static const struct snd_kcontrol_new snd_cx88_source_switch = {  	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, -	.name = "Analog-TV Switch", +	.name = "Capture Switch",  	.info = snd_ctl_boolean_mono_info,  	.get = snd_cx88_switch_get,  	.put = snd_cx88_switch_put,  	.private_value = (1<<6),  }; -static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol, -			       struct snd_ctl_elem_value *value) -{ -	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); -	struct cx88_core *core = chip->core; -	struct v4l2_control client_ctl; - -	client_ctl.id = V4L2_CID_AUDIO_LOUDNESS; -	call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl); -	value->value.integer.value[0] = client_ctl.value ? 1 : 0; - -	return 0; -} - -static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol, -				       struct snd_ctl_elem_value *value) -{ -	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); -	struct cx88_core *core = chip->core; -	struct v4l2_control client_ctl; - -	client_ctl.value = 0 != value->value.integer.value[0]; -	client_ctl.id = V4L2_CID_AUDIO_LOUDNESS; -	call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); - -	return 0; -} - -static struct snd_kcontrol_new snd_cx88_alc_switch = { -	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, -	.name = "Line-In ALC Switch", -	.info = snd_ctl_boolean_mono_info, -	.get = snd_cx88_alc_get, -	.put = snd_cx88_alc_put, -}; -  /****************************************************************************  			Basic Flow for Sound Devices   ****************************************************************************/ @@ -860,7 +795,6 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,  {  	struct snd_card  *card;  	snd_cx88_card_t  *chip; -	struct v4l2_subdev *sd;  	int              err;  	if (devno >= SNDRV_CARDS) @@ -896,15 +830,6 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,  	if (err < 0)  		goto error; -	/* If there's a wm8775 then add a Line-In ALC switch */ -	list_for_each_entry(sd, &chip->core->v4l2_dev.subdevs, list) { -		if (WM8775_GID == sd->grp_id) { -			snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, -						       chip)); -			break; -		} -	} -  	strcpy (card->driver, "CX88x");  	sprintf(card->shortname, "Conexant CX%x", pci->device);  	sprintf(card->longname, "%s at %#llx", diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 9b9e169cce9..0ccc2afd726 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1007,15 +1007,22 @@ static const struct cx88_board cx88_boards[] = {  		.radio_type	= UNSET,  		.tuner_addr	= ADDR_UNSET,  		.radio_addr	= ADDR_UNSET, +		.audio_chip = V4L2_IDENT_WM8775,  		.input		= {{  			.type	= CX88_VMUX_DVB,  			.vmux	= 0, +			/* 2: Line-In */ +			.audioroute = 2,  		},{  			.type	= CX88_VMUX_COMPOSITE1,  			.vmux	= 1, +			/* 2: Line-In */ +			.audioroute = 2,  		},{  			.type	= CX88_VMUX_SVIDEO,  			.vmux	= 2, +			/* 2: Line-In */ +			.audioroute = 2,  		}},  		.mpeg           = CX88_MPEG_DVB,  	}, diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 62cea954940..d9249e5a04c 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -40,7 +40,6 @@  #include "cx88.h"  #include <media/v4l2-common.h>  #include <media/v4l2-ioctl.h> -#include <media/wm8775.h>  MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");  MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); @@ -977,7 +976,6 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)  	const struct cx88_ctrl *c = NULL;  	u32 value,mask;  	int i; -	struct v4l2_control client_ctl;  	for (i = 0; i < CX8800_CTLS; i++) {  		if (cx8800_ctls[i].v.id == ctl->id) { @@ -991,27 +989,6 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)  		ctl->value = c->v.minimum;  	if (ctl->value > c->v.maximum)  		ctl->value = c->v.maximum; - -	/* Pass changes onto any WM8775 */ -	client_ctl.id = ctl->id; -	switch (ctl->id) { -	case V4L2_CID_AUDIO_MUTE: -		client_ctl.value = ctl->value; -		break; -	case V4L2_CID_AUDIO_VOLUME: -		client_ctl.value = (ctl->value) ? -			(0x90 + ctl->value) << 8 : 0; -		break; -	case V4L2_CID_AUDIO_BALANCE: -		client_ctl.value = ctl->value << 9; -		break; -	default: -		client_ctl.id = 0; -		break; -	} -	if (client_ctl.id) -		call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); -  	mask=c->mask;  	switch (ctl->id) {  	case V4L2_CID_AUDIO_BALANCE: @@ -1558,9 +1535,7 @@ static int radio_queryctrl (struct file *file, void *priv,  	if (c->id <  V4L2_CID_BASE ||  		c->id >= V4L2_CID_LASTP1)  		return -EINVAL; -	if (c->id == V4L2_CID_AUDIO_MUTE || -		c->id == V4L2_CID_AUDIO_VOLUME || -		c->id == V4L2_CID_AUDIO_BALANCE) { +	if (c->id == V4L2_CID_AUDIO_MUTE) {  		for (i = 0; i < CX8800_CTLS; i++) {  			if (cx8800_ctls[i].v.id == c->id)  				break; diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index e8c732e7ae4..c9981e77416 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -398,19 +398,17 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)  	return container_of(v4l2_dev, struct cx88_core, v4l2_dev);  } -#define call_hw(core, grpid, o, f, args...) \ +#define call_all(core, o, f, args...) 				\  	do {							\  		if (!core->i2c_rc) {				\  			if (core->gate_ctrl)			\  				core->gate_ctrl(core, 1);	\ -			v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \ +			v4l2_device_call_all(&core->v4l2_dev, 0, o, f, ##args); \  			if (core->gate_ctrl)			\  				core->gate_ctrl(core, 0);	\  		}						\  	} while (0) -#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args) -  struct cx8800_dev;  struct cx8802_dev; diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 908e3bc8830..2c300728003 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -2377,7 +2377,7 @@ static const struct v4l2_file_operations radio_fops = {  	.owner         = THIS_MODULE,  	.open          = em28xx_v4l2_open,  	.release       = em28xx_v4l2_close, -	.ioctl	       = video_ioctl2, +	.unlocked_ioctl = video_ioctl2,  };  static const struct v4l2_ioctl_ops radio_ioctl_ops = { diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index a5cfc76b40b..bb164099ea2 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -2530,7 +2530,7 @@ static const struct v4l2_file_operations et61x251_fops = {  	.owner = THIS_MODULE,  	.open =    et61x251_open,  	.release = et61x251_release, -	.ioctl =   et61x251_ioctl, +	.unlocked_ioctl =   et61x251_ioctl,  	.read =    et61x251_read,  	.poll =    et61x251_poll,  	.mmap =    et61x251_mmap, diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 330dadc0010..e23de57e2c7 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -63,7 +63,10 @@ struct sd {  #define QUALITY_DEF 80  	u8 jpegqual;			/* webcam quality */ +	u8 reg01; +	u8 reg17;  	u8 reg18; +	u8 flags;  	s8 ag_cnt;  #define AG_CNT_START 13 @@ -96,6 +99,22 @@ enum sensors {  	SENSOR_SP80708,  }; +/* device flags */ +#define PDN_INV	1		/* inverse pin S_PWR_DN / sn_xxx tables */ + +/* sn9c1xx definitions */ +/* register 0x01 */ +#define S_PWR_DN	0x01	/* sensor power down */ +#define S_PDN_INV	0x02	/* inverse pin S_PWR_DN */ +#define V_TX_EN		0x04	/* video transfer enable */ +#define LED		0x08	/* output to pin LED */ +#define SCL_SEL_OD	0x20	/* open-drain mode */ +#define SYS_SEL_48M	0x40	/* system clock 0: 24MHz, 1: 48MHz */ +/* register 0x17 */ +#define MCK_SIZE_MASK	0x1f	/* sensor master clock */ +#define SEN_CLK_EN	0x20	/* enable sensor clock */ +#define DEF_EN		0x80	/* defect pixel by 0: soft, 1: hard */ +  /* V4L2 controls supported by the driver */  static void setbrightness(struct gspca_dev *gspca_dev);  static void setcontrast(struct gspca_dev *gspca_dev); @@ -1755,141 +1774,6 @@ static void po2030n_probe(struct gspca_dev *gspca_dev)  	}  } -static void bridge_init(struct gspca_dev *gspca_dev, -			  const u8 *sn9c1xx) -{ -	struct sd *sd = (struct sd *) gspca_dev; -	u8 reg0102[2]; -	const u8 *reg9a; -	static const u8 reg9a_def[] = -		{0x00, 0x40, 0x20, 0x00, 0x00, 0x00}; -	static const u8 reg9a_spec[] = -		{0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; -	static const u8 regd4[] = {0x60, 0x00, 0x00}; - -	/* sensor clock already enabled in sd_init */ -	/* reg_w1(gspca_dev, 0xf1, 0x00); */ -	reg_w1(gspca_dev, 0x01, sn9c1xx[1]); - -	/* configure gpio */ -	reg0102[0] = sn9c1xx[1]; -	reg0102[1] = sn9c1xx[2]; -	if (gspca_dev->audio) -		reg0102[1] |= 0x04;	/* keep the audio connection */ -	reg_w(gspca_dev, 0x01, reg0102, 2); -	reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); -	reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); -	switch (sd->sensor) { -	case SENSOR_GC0307: -	case SENSOR_OV7660: -	case SENSOR_PO1030: -	case SENSOR_PO2030N: -	case SENSOR_SOI768: -	case SENSOR_SP80708: -		reg9a = reg9a_spec; -		break; -	default: -		reg9a = reg9a_def; -		break; -	} -	reg_w(gspca_dev, 0x9a, reg9a, 6); - -	reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); - -	reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); - -	switch (sd->sensor) { -	case SENSOR_ADCM1700: -		reg_w1(gspca_dev, 0x01, 0x43); -		reg_w1(gspca_dev, 0x17, 0x62); -		reg_w1(gspca_dev, 0x01, 0x42); -		reg_w1(gspca_dev, 0x01, 0x42); -		break; -	case SENSOR_GC0307: -		msleep(50); -		reg_w1(gspca_dev, 0x01, 0x61); -		reg_w1(gspca_dev, 0x17, 0x22); -		reg_w1(gspca_dev, 0x01, 0x60); -		reg_w1(gspca_dev, 0x01, 0x40); -		msleep(50); -		break; -	case SENSOR_MI0360B: -		reg_w1(gspca_dev, 0x01, 0x61); -		reg_w1(gspca_dev, 0x17, 0x60); -		reg_w1(gspca_dev, 0x01, 0x60); -		reg_w1(gspca_dev, 0x01, 0x40); -		break; -	case SENSOR_MT9V111: -		reg_w1(gspca_dev, 0x01, 0x61); -		reg_w1(gspca_dev, 0x17, 0x61); -		reg_w1(gspca_dev, 0x01, 0x60); -		reg_w1(gspca_dev, 0x01, 0x40); -		break; -	case SENSOR_OM6802: -		msleep(10); -		reg_w1(gspca_dev, 0x02, 0x73); -		reg_w1(gspca_dev, 0x17, 0x60); -		reg_w1(gspca_dev, 0x01, 0x22); -		msleep(100); -		reg_w1(gspca_dev, 0x01, 0x62); -		reg_w1(gspca_dev, 0x17, 0x64); -		reg_w1(gspca_dev, 0x17, 0x64); -		reg_w1(gspca_dev, 0x01, 0x42); -		msleep(10); -		reg_w1(gspca_dev, 0x01, 0x42); -		i2c_w8(gspca_dev, om6802_init0[0]); -		i2c_w8(gspca_dev, om6802_init0[1]); -		msleep(15); -		reg_w1(gspca_dev, 0x02, 0x71); -		msleep(150); -		break; -	case SENSOR_OV7630: -		reg_w1(gspca_dev, 0x01, 0x61); -		reg_w1(gspca_dev, 0x17, 0xe2); -		reg_w1(gspca_dev, 0x01, 0x60); -		reg_w1(gspca_dev, 0x01, 0x40); -		break; -	case SENSOR_OV7648: -		reg_w1(gspca_dev, 0x01, 0x63); -		reg_w1(gspca_dev, 0x17, 0x20); -		reg_w1(gspca_dev, 0x01, 0x62); -		reg_w1(gspca_dev, 0x01, 0x42); -		break; -	case SENSOR_PO1030: -	case SENSOR_SOI768: -		reg_w1(gspca_dev, 0x01, 0x61); -		reg_w1(gspca_dev, 0x17, 0x20); -		reg_w1(gspca_dev, 0x01, 0x60); -		reg_w1(gspca_dev, 0x01, 0x40); -		break; -	case SENSOR_PO2030N: -	case SENSOR_OV7660: -		reg_w1(gspca_dev, 0x01, 0x63); -		reg_w1(gspca_dev, 0x17, 0x20); -		reg_w1(gspca_dev, 0x01, 0x62); -		reg_w1(gspca_dev, 0x01, 0x42); -		break; -	case SENSOR_SP80708: -		reg_w1(gspca_dev, 0x01, 0x63); -		reg_w1(gspca_dev, 0x17, 0x20); -		reg_w1(gspca_dev, 0x01, 0x62); -		reg_w1(gspca_dev, 0x01, 0x42); -		msleep(100); -		reg_w1(gspca_dev, 0x02, 0x62); -		break; -	default: -/*	case SENSOR_HV7131R: */ -/*	case SENSOR_MI0360: */ -/*	case SENSOR_MO4000: */ -		reg_w1(gspca_dev, 0x01, 0x43); -		reg_w1(gspca_dev, 0x17, 0x61); -		reg_w1(gspca_dev, 0x01, 0x42); -		if (sd->sensor == SENSOR_HV7131R) -			hv7131r_probe(gspca_dev); -		break; -	} -} -  /* this function is called at probe time */  static int sd_config(struct gspca_dev *gspca_dev,  			const struct usb_device_id *id) @@ -1898,7 +1782,8 @@ static int sd_config(struct gspca_dev *gspca_dev,  	struct cam *cam;  	sd->bridge = id->driver_info >> 16; -	sd->sensor = id->driver_info; +	sd->sensor = id->driver_info >> 8; +	sd->flags = id->driver_info;  	cam = &gspca_dev->cam;  	if (sd->sensor == SENSOR_ADCM1700) { @@ -1929,7 +1814,7 @@ static int sd_init(struct gspca_dev *gspca_dev)  	/* setup a selector by bridge */  	reg_w1(gspca_dev, 0xf1, 0x01);  	reg_r(gspca_dev, 0x00, 1); -	reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]); +	reg_w1(gspca_dev, 0xf1, 0x00);  	reg_r(gspca_dev, 0x00, 1);		/* get sonix chip id */  	regF1 = gspca_dev->usb_buf[0];  	if (gspca_dev->usb_err < 0) @@ -2423,10 +2308,17 @@ static int sd_start(struct gspca_dev *gspca_dev)  {  	struct sd *sd = (struct sd *) gspca_dev;  	int i; -	u8 reg1, reg17; +	u8 reg01, reg17; +	u8 reg0102[2];  	const u8 *sn9c1xx;  	const u8 (*init)[8]; +	const u8 *reg9a;  	int mode; +	static const u8 reg9a_def[] = +		{0x00, 0x40, 0x20, 0x00, 0x00, 0x00}; +	static const u8 reg9a_spec[] = +		{0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; +	static const u8 regd4[] = {0x60, 0x00, 0x00};  	static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };  	static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };  	static const u8 CA_adcm1700[] = @@ -2448,7 +2340,85 @@ static int sd_start(struct gspca_dev *gspca_dev)  	/* initialize the bridge */  	sn9c1xx = sn_tb[sd->sensor]; -	bridge_init(gspca_dev, sn9c1xx); + +	/* sensor clock already enabled in sd_init */ +	/* reg_w1(gspca_dev, 0xf1, 0x00); */ +	reg01 = sn9c1xx[1]; +	if (sd->flags & PDN_INV) +		reg01 ^= S_PDN_INV;		/* power down inverted */ +	reg_w1(gspca_dev, 0x01, reg01); + +	/* configure gpio */ +	reg0102[0] = reg01; +	reg0102[1] = sn9c1xx[2]; +	if (gspca_dev->audio) +		reg0102[1] |= 0x04;	/* keep the audio connection */ +	reg_w(gspca_dev, 0x01, reg0102, 2); +	reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); +	reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); +	switch (sd->sensor) { +	case SENSOR_GC0307: +	case SENSOR_OV7660: +	case SENSOR_PO1030: +	case SENSOR_PO2030N: +	case SENSOR_SOI768: +	case SENSOR_SP80708: +		reg9a = reg9a_spec; +		break; +	default: +		reg9a = reg9a_def; +		break; +	} +	reg_w(gspca_dev, 0x9a, reg9a, 6); + +	reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); + +	reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); + +	reg17 = sn9c1xx[0x17]; +	switch (sd->sensor) { +	case SENSOR_GC0307: +		msleep(50);		/*fixme: is it useful? */ +		break; +	case SENSOR_OM6802: +		msleep(10); +		reg_w1(gspca_dev, 0x02, 0x73); +		reg17 |= SEN_CLK_EN; +		reg_w1(gspca_dev, 0x17, reg17); +		reg_w1(gspca_dev, 0x01, 0x22); +		msleep(100); +		reg01 = SCL_SEL_OD | S_PDN_INV; +		reg17 &= MCK_SIZE_MASK; +		reg17 |= 0x04;		/* clock / 4 */ +		break; +	} +	reg01 |= SYS_SEL_48M; +	reg_w1(gspca_dev, 0x01, reg01); +	reg17 |= SEN_CLK_EN; +	reg_w1(gspca_dev, 0x17, reg17); +	reg01 &= ~S_PWR_DN;		/* sensor power on */ +	reg_w1(gspca_dev, 0x01, reg01); +	reg01 &= ~SYS_SEL_48M; +	reg_w1(gspca_dev, 0x01, reg01); + +	switch (sd->sensor) { +	case SENSOR_HV7131R: +		hv7131r_probe(gspca_dev);	/*fixme: is it useful? */ +		break; +	case SENSOR_OM6802: +		msleep(10); +		reg_w1(gspca_dev, 0x01, reg01); +		i2c_w8(gspca_dev, om6802_init0[0]); +		i2c_w8(gspca_dev, om6802_init0[1]); +		msleep(15); +		reg_w1(gspca_dev, 0x02, 0x71); +		msleep(150); +		break; +	case SENSOR_SP80708: +		msleep(100); +		reg_w1(gspca_dev, 0x02, 0x62); +		break; +	}  	/* initialize the sensor */  	i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); @@ -2476,30 +2446,11 @@ static int sd_start(struct gspca_dev *gspca_dev)  	}  	reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);  	switch (sd->sensor) { -	case SENSOR_GC0307: -		reg17 = 0xa2; -		break; -	case SENSOR_MT9V111: -	case SENSOR_MI0360B: -		reg17 = 0xe0; -		break; -	case SENSOR_ADCM1700: -	case SENSOR_OV7630: -		reg17 = 0xe2; -		break; -	case SENSOR_OV7648: -		reg17 = 0x20; -		break; -	case SENSOR_OV7660: -	case SENSOR_SOI768: -		reg17 = 0xa0; -		break; -	case SENSOR_PO1030: -	case SENSOR_PO2030N: -		reg17 = 0xa0; +	case SENSOR_OM6802: +/*	case SENSOR_OV7648:		* fixme: sometimes */  		break;  	default: -		reg17 = 0x60; +		reg17 |= DEF_EN;  		break;  	}  	reg_w1(gspca_dev, 0x17, reg17); @@ -2546,95 +2497,67 @@ static int sd_start(struct gspca_dev *gspca_dev)  	init = NULL;  	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; -	if (mode) -		reg1 = 0x46;	/* 320x240: clk 48Mhz, video trf enable */ -	else -		reg1 = 0x06;	/* 640x480: clk 24Mhz, video trf enable */ -	reg17 = 0x61;		/* 0x:20: enable sensor clock */ +	reg01 |= SYS_SEL_48M | V_TX_EN; +	reg17 &= ~MCK_SIZE_MASK; +	reg17 |= 0x02;			/* clock / 2 */  	switch (sd->sensor) {  	case SENSOR_ADCM1700:  		init = adcm1700_sensor_param1; -		reg1 = 0x46; -		reg17 = 0xe2;  		break;  	case SENSOR_GC0307:  		init = gc0307_sensor_param1; -		reg17 = 0xa2; -		reg1 = 0x44; +		break; +	case SENSOR_HV7131R: +	case SENSOR_MI0360: +		if (mode) +			reg01 |= SYS_SEL_48M;	/* 320x240: clk 48Mhz */ +		else +			reg01 &= ~SYS_SEL_48M;	/* 640x480: clk 24Mhz */ +		reg17 &= ~MCK_SIZE_MASK; +		reg17 |= 0x01;			/* clock / 1 */  		break;  	case SENSOR_MI0360B:  		init = mi0360b_sensor_param1; -		reg1 &= ~0x02;		/* don't inverse pin S_PWR_DN */ -		reg17 = 0xe2;  		break;  	case SENSOR_MO4000: -		if (mode) { -/*			reg1 = 0x46;	 * 320 clk 48Mhz 60fp/s */ -			reg1 = 0x06;	/* clk 24Mz */ -		} else { -			reg17 = 0x22;	/* 640 MCKSIZE */ -/*			reg1 = 0x06;	 * 640 clk 24Mz (done) */ +		if (mode) {			/* if 320x240 */ +			reg01 &= ~SYS_SEL_48M;	/* clk 24Mz */ +			reg17 &= ~MCK_SIZE_MASK; +			reg17 |= 0x01;		/* clock / 1 */  		}  		break;  	case SENSOR_MT9V111:  		init = mt9v111_sensor_param1; -		if (mode) { -			reg1 = 0x04;	/* 320 clk 48Mhz */ -		} else { -/*			reg1 = 0x06;	 * 640 clk 24Mz (done) */ -			reg17 = 0xc2; -		}  		break;  	case SENSOR_OM6802:  		init = om6802_sensor_param1; -		reg17 = 0x64;		/* 640 MCKSIZE */ +		if (!mode) {			/* if 640x480 */ +			reg17 &= ~MCK_SIZE_MASK; +			reg17 |= 0x01;		/* clock / 4 */ +		}  		break;  	case SENSOR_OV7630:  		init = ov7630_sensor_param1; -		reg17 = 0xe2; -		reg1 = 0x44;  		break;  	case SENSOR_OV7648:  		init = ov7648_sensor_param1; -		reg17 = 0x21; -/*		reg1 = 0x42;		 * 42 - 46? */ +		reg17 &= ~MCK_SIZE_MASK; +		reg17 |= 0x01;			/* clock / 1 */  		break;  	case SENSOR_OV7660:  		init = ov7660_sensor_param1; -		if (sd->bridge == BRIDGE_SN9C120) { -			if (mode) {		/* 320x240 - 160x120 */ -				reg17 = 0xa2; -				reg1 = 0x44;	/* 48 Mhz, video trf eneble */ -			} -		} else { -			reg17 = 0x22; -			reg1 = 0x06;	/* 24 Mhz, video trf eneble -					 * inverse power down */ -		}  		break;  	case SENSOR_PO1030:  		init = po1030_sensor_param1; -		reg17 = 0xa2; -		reg1 = 0x44;  		break;  	case SENSOR_PO2030N:  		init = po2030n_sensor_param1; -		reg1 = 0x46; -		reg17 = 0xa2;  		break;  	case SENSOR_SOI768:  		init = soi768_sensor_param1; -		reg1 = 0x44; -		reg17 = 0xa2;  		break;  	case SENSOR_SP80708:  		init = sp80708_sensor_param1; -		if (mode) { -/*??			reg1 = 0x04;	 * 320 clk 48Mhz */ -		} else { -			reg1 = 0x46;	 /* 640 clk 48Mz */ -			reg17 = 0xa2; -		}  		break;  	} @@ -2684,7 +2607,9 @@ static int sd_start(struct gspca_dev *gspca_dev)  	setjpegqual(gspca_dev);  	reg_w1(gspca_dev, 0x17, reg17); -	reg_w1(gspca_dev, 0x01, reg1); +	reg_w1(gspca_dev, 0x01, reg01); +	sd->reg01 = reg01; +	sd->reg17 = reg17;  	sethvflip(gspca_dev);  	setbrightness(gspca_dev); @@ -2706,41 +2631,64 @@ static void sd_stopN(struct gspca_dev *gspca_dev)  		{ 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };  	static const u8 stopsoi768[] =  		{ 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 }; -	u8 data; -	const u8 *sn9c1xx; +	u8 reg01; +	u8 reg17; -	data = 0x0b; +	reg01 = sd->reg01; +	reg17 = sd->reg17 & ~SEN_CLK_EN;  	switch (sd->sensor) { +	case SENSOR_ADCM1700:  	case SENSOR_GC0307: -		data = 0x29; +	case SENSOR_PO2030N: +	case SENSOR_SP80708: +		reg01 |= LED; +		reg_w1(gspca_dev, 0x01, reg01); +		reg01 &= ~(LED | V_TX_EN); +		reg_w1(gspca_dev, 0x01, reg01); +/*		reg_w1(gspca_dev, 0x02, 0x??);	 * LED off ? */  		break;  	case SENSOR_HV7131R: +		reg01 &= ~V_TX_EN; +		reg_w1(gspca_dev, 0x01, reg01);  		i2c_w8(gspca_dev, stophv7131); -		data = 0x2b;  		break;  	case SENSOR_MI0360:  	case SENSOR_MI0360B: +		reg01 &= ~V_TX_EN; +		reg_w1(gspca_dev, 0x01, reg01); +/*		reg_w1(gspca_dev, 0x02, 0x40);	  * LED off ? */  		i2c_w8(gspca_dev, stopmi0360); -		data = 0x29;  		break; -	case SENSOR_OV7648: -		i2c_w8(gspca_dev, stopov7648); -		/* fall thru */  	case SENSOR_MT9V111: -	case SENSOR_OV7630: +	case SENSOR_OM6802:  	case SENSOR_PO1030: -		data = 0x29; +		reg01 &= ~V_TX_EN; +		reg_w1(gspca_dev, 0x01, reg01); +		break; +	case SENSOR_OV7630: +	case SENSOR_OV7648: +		reg01 &= ~V_TX_EN; +		reg_w1(gspca_dev, 0x01, reg01); +		i2c_w8(gspca_dev, stopov7648); +		break; +	case SENSOR_OV7660: +		reg01 &= ~V_TX_EN; +		reg_w1(gspca_dev, 0x01, reg01);  		break;  	case SENSOR_SOI768:  		i2c_w8(gspca_dev, stopsoi768); -		data = 0x29;  		break;  	} -	sn9c1xx = sn_tb[sd->sensor]; -	reg_w1(gspca_dev, 0x01, sn9c1xx[1]); -	reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]); -	reg_w1(gspca_dev, 0x01, sn9c1xx[1]); -	reg_w1(gspca_dev, 0x01, data); + +	reg01 |= SCL_SEL_OD; +	reg_w1(gspca_dev, 0x01, reg01); +	reg01 |= S_PWR_DN;		/* sensor power down */ +	reg_w1(gspca_dev, 0x01, reg01); +	reg_w1(gspca_dev, 0x17, reg17); +	reg01 &= ~SYS_SEL_48M;		/* clock 24MHz */ +	reg_w1(gspca_dev, 0x01, reg01); +	reg01 |= LED; +	reg_w1(gspca_dev, 0x01, reg01);  	/* Don't disable sensor clock as that disables the button on the cam */  	/* reg_w1(gspca_dev, 0xf1, 0x01); */  } @@ -2954,14 +2902,18 @@ static const struct sd_desc sd_desc = {  /* -- module initialisation -- */  #define BS(bridge, sensor) \  	.driver_info = (BRIDGE_ ## bridge << 16) \ -			| SENSOR_ ## sensor +			| (SENSOR_ ## sensor << 8) +#define BSF(bridge, sensor, flags) \ +	.driver_info = (BRIDGE_ ## bridge << 16) \ +			| (SENSOR_ ## sensor << 8) \ +			| (flags)  static const __devinitdata struct usb_device_id device_table[] = {  #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE  	{USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)},  	{USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},  #endif -	{USB_DEVICE(0x045e, 0x00f5), BS(SN9C105, OV7660)}, -	{USB_DEVICE(0x045e, 0x00f7), BS(SN9C105, OV7660)}, +	{USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, PDN_INV)}, +	{USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, PDN_INV)},  	{USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},  	{USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},  	{USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)}, diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 2be23bccd3c..48d2c2419c1 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1659,7 +1659,7 @@ static const struct v4l2_file_operations meye_fops = {  	.open		= meye_open,  	.release	= meye_release,  	.mmap		= meye_mmap, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  	.poll		= meye_poll,  }; @@ -1831,12 +1831,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,  	msleep(1);  	mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK); -	if (video_register_device(meye.vdev, VFL_TYPE_GRABBER, -				  video_nr) < 0) { -		v4l2_err(v4l2_dev, "video_register_device failed\n"); -		goto outvideoreg; -	} -  	mutex_init(&meye.lock);  	init_waitqueue_head(&meye.proc_list);  	meye.brightness = 32 << 10; @@ -1858,6 +1852,12 @@ static int __devinit meye_probe(struct pci_dev *pcidev,  	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0);  	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48); +	if (video_register_device(meye.vdev, VFL_TYPE_GRABBER, +				  video_nr) < 0) { +		v4l2_err(v4l2_dev, "video_register_device failed\n"); +		goto outvideoreg; +	} +  	v4l2_info(v4l2_dev, "Motion Eye Camera Driver v%s.\n",  	       MEYE_DRIVER_VERSION);  	v4l2_info(v4l2_dev, "mchip KL5A72002 rev. %d, base %lx, irq %d\n", diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index 072bd2d1cfa..13565cba237 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c @@ -807,8 +807,6 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd,  	if (common_flags & SOCAM_PCLK_SAMPLE_RISING)  		csicr1 |= CSICR1_REDGE; -	if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) -		csicr1 |= CSICR1_INV_PCLK;  	if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH)  		csicr1 |= CSICR1_SOF_POL;  	if (common_flags & SOCAM_HSYNC_ACTIVE_HIGH) diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 7129b50757d..7551907f8c2 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -932,7 +932,7 @@ static ssize_t pms_read(struct file *file, char __user *buf,  static const struct v4l2_file_operations pms_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  	.read           = pms_read,  }; diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 1b93207c89e..2f500809f53 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -522,6 +522,7 @@ static int fimc_cap_streamon(struct file *file, void *priv,  	INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);  	fimc->vid_cap.active_buf_cnt = 0;  	fimc->vid_cap.frame_count = 0; +	fimc->vid_cap.buf_index = fimc_hw_get_frame_index(fimc);  	set_bit(ST_CAPT_PEND, &fimc->state);  	ret = videobuf_streamon(&fimc->vid_cap.vbq); @@ -652,6 +653,50 @@ static int fimc_cap_s_ctrl(struct file *file, void *priv,  	return ret;  } +static int fimc_cap_cropcap(struct file *file, void *fh, +			    struct v4l2_cropcap *cr) +{ +	struct fimc_frame *f; +	struct fimc_ctx *ctx = fh; +	struct fimc_dev *fimc = ctx->fimc_dev; + +	if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) +		return -EINVAL; + +	if (mutex_lock_interruptible(&fimc->lock)) +		return -ERESTARTSYS; + +	f = &ctx->s_frame; +	cr->bounds.left		= 0; +	cr->bounds.top		= 0; +	cr->bounds.width	= f->o_width; +	cr->bounds.height	= f->o_height; +	cr->defrect		= cr->bounds; + +	mutex_unlock(&fimc->lock); +	return 0; +} + +static int fimc_cap_g_crop(struct file *file, void *fh, struct v4l2_crop *cr) +{ +	struct fimc_frame *f; +	struct fimc_ctx *ctx = file->private_data; +	struct fimc_dev *fimc = ctx->fimc_dev; + + +	if (mutex_lock_interruptible(&fimc->lock)) +		return -ERESTARTSYS; + +	f = &ctx->s_frame; +	cr->c.left	= f->offs_h; +	cr->c.top	= f->offs_v; +	cr->c.width	= f->width; +	cr->c.height	= f->height; + +	mutex_unlock(&fimc->lock); +	return 0; +} +  static int fimc_cap_s_crop(struct file *file, void *fh,  			       struct v4l2_crop *cr)  { @@ -716,9 +761,9 @@ static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {  	.vidioc_g_ctrl			= fimc_vidioc_g_ctrl,  	.vidioc_s_ctrl			= fimc_cap_s_ctrl, -	.vidioc_g_crop			= fimc_vidioc_g_crop, +	.vidioc_g_crop			= fimc_cap_g_crop,  	.vidioc_s_crop			= fimc_cap_s_crop, -	.vidioc_cropcap			= fimc_vidioc_cropcap, +	.vidioc_cropcap			= fimc_cap_cropcap,  	.vidioc_enum_input		= fimc_cap_enum_input,  	.vidioc_s_input			= fimc_cap_s_input, @@ -785,7 +830,7 @@ int fimc_register_capture_device(struct fimc_dev *fimc)  	videobuf_queue_dma_contig_init(&vid_cap->vbq, &fimc_qops,  		vid_cap->v4l2_dev.dev, &fimc->irqlock,  		V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, -		sizeof(struct fimc_vid_buffer), (void *)ctx); +		sizeof(struct fimc_vid_buffer), (void *)ctx, NULL);  	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);  	if (ret) { diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index 2e7c547894b..bb99f2d805d 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -50,8 +50,8 @@ static struct fimc_fmt fimc_formats[] = {  		.planes_cnt = 1,  		.flags = FMT_FLAGS_M2M,  	}, { -		.name = "XRGB-8-8-8-8, 24 bpp", -		.fourcc	= V4L2_PIX_FMT_RGB24, +		.name = "XRGB-8-8-8-8, 32 bpp", +		.fourcc	= V4L2_PIX_FMT_RGB32,  		.depth = 32,  		.color	= S5P_FIMC_RGB888,  		.buff_cnt = 1, @@ -983,6 +983,7 @@ int fimc_vidioc_queryctrl(struct file *file, void *priv,  {  	struct fimc_ctx *ctx = priv;  	struct v4l2_queryctrl *c; +	int ret = -EINVAL;  	c = get_ctrl(qc->id);  	if (c) { @@ -990,10 +991,14 @@ int fimc_vidioc_queryctrl(struct file *file, void *priv,  		return 0;  	} -	if (ctx->state & FIMC_CTX_CAP) -		return v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd, +	if (ctx->state & FIMC_CTX_CAP) { +		if (mutex_lock_interruptible(&ctx->fimc_dev->lock)) +			return -ERESTARTSYS; +		ret = v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,  					core, queryctrl, qc); -	return -EINVAL; +		mutex_unlock(&ctx->fimc_dev->lock); +	} +	return ret;  }  int fimc_vidioc_g_ctrl(struct file *file, void *priv, @@ -1115,7 +1120,7 @@ static int fimc_m2m_s_ctrl(struct file *file, void *priv,  	return 0;  } -int fimc_vidioc_cropcap(struct file *file, void *fh, +static int fimc_m2m_cropcap(struct file *file, void *fh,  			struct v4l2_cropcap *cr)  {  	struct fimc_frame *frame; @@ -1139,7 +1144,7 @@ int fimc_vidioc_cropcap(struct file *file, void *fh,  	return 0;  } -int fimc_vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *cr) +static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)  {  	struct fimc_frame *frame;  	struct fimc_ctx *ctx = file->private_data; @@ -1167,22 +1172,22 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)  	struct fimc_frame *f;  	u32 min_size, halign; -	f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ? -		&ctx->s_frame : &ctx->d_frame; -  	if (cr->c.top < 0 || cr->c.left < 0) {  		v4l2_err(&fimc->m2m.v4l2_dev,  			"doesn't support negative values for top & left\n");  		return -EINVAL;  	} -	f = ctx_get_frame(ctx, cr->type); -	if (IS_ERR(f)) -		return PTR_ERR(f); +	if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) +		f = (ctx->state & FIMC_CTX_CAP) ? &ctx->s_frame : &ctx->d_frame; +	else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && +		 ctx->state & FIMC_CTX_M2M) +		f = &ctx->s_frame; +	else +		return -EINVAL; -	min_size = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) -		? fimc->variant->min_inp_pixsize -		: fimc->variant->min_out_pixsize; +	min_size = (f == &ctx->s_frame) ? +		fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize;  	if (ctx->state & FIMC_CTX_M2M) {  		if (fimc->id == 1 && fimc->variant->pix_hoff) @@ -1233,6 +1238,9 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)  	f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ?  		&ctx->s_frame : &ctx->d_frame; +	if (mutex_lock_interruptible(&fimc->lock)) +		return -ERESTARTSYS; +  	spin_lock_irqsave(&ctx->slock, flags);  	if (~ctx->state & (FIMC_SRC_FMT | FIMC_DST_FMT)) {  		/* Check to see if scaling ratio is within supported range */ @@ -1241,9 +1249,9 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)  		else  			ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame);  		if (ret) { -			spin_unlock_irqrestore(&ctx->slock, flags);  			v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range"); -			return -EINVAL; +			ret = -EINVAL; +			goto scr_unlock;  		}  	}  	ctx->state |= FIMC_PARAMS; @@ -1253,7 +1261,9 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)  	f->width  = cr->c.width;  	f->height = cr->c.height; +scr_unlock:  	spin_unlock_irqrestore(&ctx->slock, flags); +	mutex_unlock(&fimc->lock);  	return 0;  } @@ -1285,9 +1295,9 @@ static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {  	.vidioc_g_ctrl			= fimc_vidioc_g_ctrl,  	.vidioc_s_ctrl			= fimc_m2m_s_ctrl, -	.vidioc_g_crop			= fimc_vidioc_g_crop, +	.vidioc_g_crop			= fimc_m2m_g_crop,  	.vidioc_s_crop			= fimc_m2m_s_crop, -	.vidioc_cropcap			= fimc_vidioc_cropcap +	.vidioc_cropcap			= fimc_m2m_cropcap  }; @@ -1396,7 +1406,7 @@ static const struct v4l2_file_operations fimc_m2m_fops = {  	.open		= fimc_m2m_open,  	.release	= fimc_m2m_release,  	.poll		= fimc_m2m_poll, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  	.mmap		= fimc_m2m_mmap,  }; @@ -1736,6 +1746,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv310 = {  	.pix_hoff	 = 1,  	.has_inp_rot	 = 1,  	.has_out_rot	 = 1, +	.has_cistatus2	 = 1,  	.min_inp_pixsize = 16,  	.min_out_pixsize = 16,  	.hor_offs_align	 = 1, @@ -1745,6 +1756,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv310 = {  static struct samsung_fimc_variant fimc2_variant_s5pv310 = {  	.pix_hoff	 = 1, +	.has_cistatus2	 = 1,  	.min_inp_pixsize = 16,  	.min_out_pixsize = 16,  	.hor_offs_align	 = 1, diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h index 3e107851656..4f047d35f8a 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.h +++ b/drivers/media/video/s5p-fimc/fimc-core.h @@ -13,13 +13,15 @@  /*#define DEBUG*/ +#include <linux/sched.h>  #include <linux/types.h> +#include <linux/videodev2.h>  #include <media/videobuf-core.h>  #include <media/v4l2-device.h>  #include <media/v4l2-mem2mem.h>  #include <media/v4l2-mediabus.h>  #include <media/s3c_fimc.h> -#include <linux/videodev2.h> +  #include "regs-fimc.h"  #define err(fmt, args...) \ @@ -369,6 +371,7 @@ struct fimc_pix_limit {   * @pix_hoff: indicate whether horizontal offset is in pixels or in bytes   * @has_inp_rot: set if has input rotator   * @has_out_rot: set if has output rotator + * @has_cistatus2: 1 if CISTATUS2 register is present in this IP revision   * @pix_limit: pixel size constraints for the scaler   * @min_inp_pixsize: minimum input pixel size   * @min_out_pixsize: minimum output pixel size @@ -379,6 +382,7 @@ struct samsung_fimc_variant {  	unsigned int	pix_hoff:1;  	unsigned int	has_inp_rot:1;  	unsigned int	has_out_rot:1; +	unsigned int	has_cistatus2:1;  	struct fimc_pix_limit *pix_limit;  	u16		min_inp_pixsize;  	u16		min_out_pixsize; @@ -554,11 +558,19 @@ static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx,  	return frame;  } +/* Return an index to the buffer actually being written. */  static inline u32 fimc_hw_get_frame_index(struct fimc_dev *dev)  { -	u32 reg = readl(dev->regs + S5P_CISTATUS); -	return (reg & S5P_CISTATUS_FRAMECNT_MASK) >> -		S5P_CISTATUS_FRAMECNT_SHIFT; +	u32 reg; + +	if (dev->variant->has_cistatus2) { +		reg = readl(dev->regs + S5P_CISTATUS2) & 0x3F; +		return reg > 0 ? --reg : reg; +	} else { +		reg = readl(dev->regs + S5P_CISTATUS); +		return (reg & S5P_CISTATUS_FRAMECNT_MASK) >> +			S5P_CISTATUS_FRAMECNT_SHIFT; +	}  }  /* -----------------------------------------------------*/ @@ -594,10 +606,6 @@ int fimc_vidioc_g_fmt(struct file *file, void *priv,  		      struct v4l2_format *f);  int fimc_vidioc_try_fmt(struct file *file, void *priv,  			struct v4l2_format *f); -int fimc_vidioc_g_crop(struct file *file, void *fh, -		       struct v4l2_crop *cr); -int fimc_vidioc_cropcap(struct file *file, void *fh, -			struct v4l2_cropcap *cr);  int fimc_vidioc_queryctrl(struct file *file, void *priv,  			  struct v4l2_queryctrl *qc);  int fimc_vidioc_g_ctrl(struct file *file, void *priv, diff --git a/drivers/media/video/s5p-fimc/regs-fimc.h b/drivers/media/video/s5p-fimc/regs-fimc.h index a57daedb5b5..57e33f84fcf 100644 --- a/drivers/media/video/s5p-fimc/regs-fimc.h +++ b/drivers/media/video/s5p-fimc/regs-fimc.h @@ -165,6 +165,9 @@  #define S5P_CISTATUS_VVALID_A		(1 << 15)  #define S5P_CISTATUS_VVALID_B		(1 << 14) +/* Indexes to the last and the currently processed buffer. */ +#define S5P_CISTATUS2			0x68 +  /* Image capture control */  #define S5P_CIIMGCPT			0xc0  #define S5P_CIIMGCPT_IMGCPTEN		(1 << 31) diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 5c209afb0ac..2486520582f 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -1980,7 +1980,7 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev)  		 * we complete the completion.  		 */ -		if (!csi2->driver || !csi2->driver->owner) { +		if (!csi2->driver) {  			complete(&wait.completion);  			/* Either too late, or probing failed */  			bus_unregister_notifier(&platform_bus_type, &wait.notifier); diff --git a/drivers/media/video/sh_vou.c b/drivers/media/video/sh_vou.c index 4e5a8cf76de..07cf0c6c7c1 100644 --- a/drivers/media/video/sh_vou.c +++ b/drivers/media/video/sh_vou.c @@ -75,6 +75,7 @@ struct sh_vou_device {  	int pix_idx;  	struct videobuf_buffer *active;  	enum sh_vou_status status; +	struct mutex fop_lock;  };  struct sh_vou_file { @@ -235,7 +236,7 @@ static void free_buffer(struct videobuf_queue *vq, struct videobuf_buffer *vb)  	vb->state = VIDEOBUF_NEEDS_INIT;  } -/* Locking: caller holds vq->vb_lock mutex */ +/* Locking: caller holds fop_lock mutex */  static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count,  			    unsigned int *size)  { @@ -257,7 +258,7 @@ static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count,  	return 0;  } -/* Locking: caller holds vq->vb_lock mutex */ +/* Locking: caller holds fop_lock mutex */  static int sh_vou_buf_prepare(struct videobuf_queue *vq,  			      struct videobuf_buffer *vb,  			      enum v4l2_field field) @@ -306,7 +307,7 @@ static int sh_vou_buf_prepare(struct videobuf_queue *vq,  	return 0;  } -/* Locking: caller holds vq->vb_lock mutex and vq->irqlock spinlock */ +/* Locking: caller holds fop_lock mutex and vq->irqlock spinlock */  static void sh_vou_buf_queue(struct videobuf_queue *vq,  			     struct videobuf_buffer *vb)  { @@ -1190,7 +1191,7 @@ static int sh_vou_open(struct file *file)  				       V4L2_BUF_TYPE_VIDEO_OUTPUT,  				       V4L2_FIELD_NONE,  				       sizeof(struct videobuf_buffer), vdev, -				       NULL); +				       &vou_dev->fop_lock);  	return 0;  } @@ -1292,7 +1293,7 @@ static const struct v4l2_file_operations sh_vou_fops = {  	.owner		= THIS_MODULE,  	.open		= sh_vou_open,  	.release	= sh_vou_release, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  	.mmap		= sh_vou_mmap,  	.poll		= sh_vou_poll,  }; @@ -1331,6 +1332,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)  	INIT_LIST_HEAD(&vou_dev->queue);  	spin_lock_init(&vou_dev->lock); +	mutex_init(&vou_dev->fop_lock);  	atomic_set(&vou_dev->use_count, 0);  	vou_dev->pdata = vou_pdata;  	vou_dev->status = SH_VOU_IDLE; @@ -1388,6 +1390,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)  		vdev->tvnorms |= V4L2_STD_PAL;  	vdev->v4l2_dev = &vou_dev->v4l2_dev;  	vdev->release = video_device_release; +	vdev->lock = &vou_dev->fop_lock;  	vou_dev->vdev = vdev;  	video_set_drvdata(vdev, vou_dev); diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 28e19daadec..f49fbfb7dc1 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -3238,7 +3238,7 @@ static const struct v4l2_file_operations sn9c102_fops = {  	.owner = THIS_MODULE,  	.open = sn9c102_open,  	.release = sn9c102_release, -	.ioctl = sn9c102_ioctl, +	.unlocked_ioctl = sn9c102_ioctl,  	.read = sn9c102_read,  	.poll = sn9c102_poll,  	.mmap = sn9c102_mmap, diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 335120c2021..052bd6dfa5a 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -405,13 +405,13 @@ static int soc_camera_open(struct file *file)  		ret = soc_camera_set_fmt(icd, &f);  		if (ret < 0)  			goto esfmt; + +		ici->ops->init_videobuf(&icd->vb_vidq, icd);  	}  	file->private_data = icd;  	dev_dbg(&icd->dev, "camera device open\n"); -	ici->ops->init_videobuf(&icd->vb_vidq, icd); -  	mutex_unlock(&icd->video_lock);  	return 0; diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index f169f773667..59f8a9ad379 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -785,7 +785,7 @@ static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id,  	}  } -struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, +static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,  	__u32 v4l2_id, struct uvc_control_mapping **mapping)  {  	struct uvc_control *ctrl = NULL; @@ -944,6 +944,52 @@ done:  	return ret;  } +/* + * Mapping V4L2 controls to UVC controls can be straighforward if done well. + * Most of the UVC controls exist in V4L2, and can be mapped directly. Some + * must be grouped (for instance the Red Balance, Blue Balance and Do White + * Balance V4L2 controls use the White Balance Component UVC control) or + * otherwise translated. The approach we take here is to use a translation + * table for the controls that can be mapped directly, and handle the others + * manually. + */ +int uvc_query_v4l2_menu(struct uvc_video_chain *chain, +	struct v4l2_querymenu *query_menu) +{ +	struct uvc_menu_info *menu_info; +	struct uvc_control_mapping *mapping; +	struct uvc_control *ctrl; +	u32 index = query_menu->index; +	u32 id = query_menu->id; +	int ret; + +	memset(query_menu, 0, sizeof(*query_menu)); +	query_menu->id = id; +	query_menu->index = index; + +	ret = mutex_lock_interruptible(&chain->ctrl_mutex); +	if (ret < 0) +		return -ERESTARTSYS; + +	ctrl = uvc_find_control(chain, query_menu->id, &mapping); +	if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) { +		ret = -EINVAL; +		goto done; +	} + +	if (query_menu->index >= mapping->menu_count) { +		ret = -EINVAL; +		goto done; +	} + +	menu_info = &mapping->menu_info[query_menu->index]; +	strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name); + +done: +	mutex_unlock(&chain->ctrl_mutex); +	return ret; +} +  /* --------------------------------------------------------------------------   * Control transactions diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index ed6d5449741..f14581bd707 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -90,6 +90,39 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,  }  /* + * Free the video buffers. + * + * This function must be called with the queue lock held. + */ +static int __uvc_free_buffers(struct uvc_video_queue *queue) +{ +	unsigned int i; + +	for (i = 0; i < queue->count; ++i) { +		if (queue->buffer[i].vma_use_count != 0) +			return -EBUSY; +	} + +	if (queue->count) { +		vfree(queue->mem); +		queue->count = 0; +	} + +	return 0; +} + +int uvc_free_buffers(struct uvc_video_queue *queue) +{ +	int ret; + +	mutex_lock(&queue->mutex); +	ret = __uvc_free_buffers(queue); +	mutex_unlock(&queue->mutex); + +	return ret; +} + +/*   * Allocate the video buffers.   *   * Pages are reserved to make sure they will not be swapped, as they will be @@ -110,7 +143,7 @@ int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,  	mutex_lock(&queue->mutex); -	if ((ret = uvc_free_buffers(queue)) < 0) +	if ((ret = __uvc_free_buffers(queue)) < 0)  		goto done;  	/* Bail out if no buffers should be allocated. */ @@ -152,28 +185,6 @@ done:  }  /* - * Free the video buffers. - * - * This function must be called with the queue lock held. - */ -int uvc_free_buffers(struct uvc_video_queue *queue) -{ -	unsigned int i; - -	for (i = 0; i < queue->count; ++i) { -		if (queue->buffer[i].vma_use_count != 0) -			return -EBUSY; -	} - -	if (queue->count) { -		vfree(queue->mem); -		queue->count = 0; -	} - -	return 0; -} - -/*   * Check if buffers have been allocated.   */  int uvc_queue_allocated(struct uvc_video_queue *queue) @@ -369,6 +380,82 @@ done:  }  /* + * VMA operations. + */ +static void uvc_vm_open(struct vm_area_struct *vma) +{ +	struct uvc_buffer *buffer = vma->vm_private_data; +	buffer->vma_use_count++; +} + +static void uvc_vm_close(struct vm_area_struct *vma) +{ +	struct uvc_buffer *buffer = vma->vm_private_data; +	buffer->vma_use_count--; +} + +static const struct vm_operations_struct uvc_vm_ops = { +	.open		= uvc_vm_open, +	.close		= uvc_vm_close, +}; + +/* + * Memory-map a video buffer. + * + * This function implements video buffers memory mapping and is intended to be + * used by the device mmap handler. + */ +int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) +{ +	struct uvc_buffer *uninitialized_var(buffer); +	struct page *page; +	unsigned long addr, start, size; +	unsigned int i; +	int ret = 0; + +	start = vma->vm_start; +	size = vma->vm_end - vma->vm_start; + +	mutex_lock(&queue->mutex); + +	for (i = 0; i < queue->count; ++i) { +		buffer = &queue->buffer[i]; +		if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) +			break; +	} + +	if (i == queue->count || size != queue->buf_size) { +		ret = -EINVAL; +		goto done; +	} + +	/* +	 * VM_IO marks the area as being an mmaped region for I/O to a +	 * device. It also prevents the region from being core dumped. +	 */ +	vma->vm_flags |= VM_IO; + +	addr = (unsigned long)queue->mem + buffer->buf.m.offset; +	while (size > 0) { +		page = vmalloc_to_page((void *)addr); +		if ((ret = vm_insert_page(vma, start, page)) < 0) +			goto done; + +		start += PAGE_SIZE; +		addr += PAGE_SIZE; +		size -= PAGE_SIZE; +	} + +	vma->vm_ops = &uvc_vm_ops; +	vma->vm_private_data = buffer; +	uvc_vm_open(vma); + +done: +	mutex_unlock(&queue->mutex); +	return ret; +} + +/*   * Poll the video queue.   *   * This function implements video queue polling and is intended to be used by diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 6d15de9b520..8cf61e8a634 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -101,40 +101,6 @@ done:   */  /* - * Mapping V4L2 controls to UVC controls can be straighforward if done well. - * Most of the UVC controls exist in V4L2, and can be mapped directly. Some - * must be grouped (for instance the Red Balance, Blue Balance and Do White - * Balance V4L2 controls use the White Balance Component UVC control) or - * otherwise translated. The approach we take here is to use a translation - * table for the controls that can be mapped directly, and handle the others - * manually. - */ -static int uvc_v4l2_query_menu(struct uvc_video_chain *chain, -	struct v4l2_querymenu *query_menu) -{ -	struct uvc_menu_info *menu_info; -	struct uvc_control_mapping *mapping; -	struct uvc_control *ctrl; -	u32 index = query_menu->index; -	u32 id = query_menu->id; - -	ctrl = uvc_find_control(chain, query_menu->id, &mapping); -	if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) -		return -EINVAL; - -	if (query_menu->index >= mapping->menu_count) -		return -EINVAL; - -	memset(query_menu, 0, sizeof(*query_menu)); -	query_menu->id = id; -	query_menu->index = index; - -	menu_info = &mapping->menu_info[query_menu->index]; -	strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name); -	return 0; -} - -/*   * Find the frame interval closest to the requested frame interval for the   * given frame format and size. This should be done by the device as part of   * the Video Probe and Commit negotiation, but some hardware don't implement @@ -260,12 +226,14 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,  	 * developers test their webcams with the Linux driver as well as with  	 * the Windows driver).  	 */ +	mutex_lock(&stream->mutex);  	if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)  		probe->dwMaxVideoFrameSize =  			stream->ctrl.dwMaxVideoFrameSize;  	/* Probe the device. */  	ret = uvc_probe_video(stream, probe); +	mutex_unlock(&stream->mutex);  	if (ret < 0)  		goto done; @@ -289,14 +257,21 @@ done:  static int uvc_v4l2_get_format(struct uvc_streaming *stream,  	struct v4l2_format *fmt)  { -	struct uvc_format *format = stream->cur_format; -	struct uvc_frame *frame = stream->cur_frame; +	struct uvc_format *format; +	struct uvc_frame *frame; +	int ret = 0;  	if (fmt->type != stream->type)  		return -EINVAL; -	if (format == NULL || frame == NULL) -		return -EINVAL; +	mutex_lock(&stream->mutex); +	format = stream->cur_format; +	frame = stream->cur_frame; + +	if (format == NULL || frame == NULL) { +		ret = -EINVAL; +		goto done; +	}  	fmt->fmt.pix.pixelformat = format->fcc;  	fmt->fmt.pix.width = frame->wWidth; @@ -307,7 +282,9 @@ static int uvc_v4l2_get_format(struct uvc_streaming *stream,  	fmt->fmt.pix.colorspace = format->colorspace;  	fmt->fmt.pix.priv = 0; -	return 0; +done: +	mutex_unlock(&stream->mutex); +	return ret;  }  static int uvc_v4l2_set_format(struct uvc_streaming *stream, @@ -321,18 +298,24 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream,  	if (fmt->type != stream->type)  		return -EINVAL; -	if (uvc_queue_allocated(&stream->queue)) -		return -EBUSY; -  	ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);  	if (ret < 0)  		return ret; +	mutex_lock(&stream->mutex); + +	if (uvc_queue_allocated(&stream->queue)) { +		ret = -EBUSY; +		goto done; +	} +  	memcpy(&stream->ctrl, &probe, sizeof probe);  	stream->cur_format = format;  	stream->cur_frame = frame; -	return 0; +done: +	mutex_unlock(&stream->mutex); +	return ret;  }  static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, @@ -343,7 +326,10 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,  	if (parm->type != stream->type)  		return -EINVAL; +	mutex_lock(&stream->mutex);  	numerator = stream->ctrl.dwFrameInterval; +	mutex_unlock(&stream->mutex); +  	denominator = 10000000;  	uvc_simplify_fraction(&numerator, &denominator, 8, 333); @@ -370,7 +356,6 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,  static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,  		struct v4l2_streamparm *parm)  { -	struct uvc_frame *frame = stream->cur_frame;  	struct uvc_streaming_control probe;  	struct v4l2_fract timeperframe;  	uint32_t interval; @@ -379,28 +364,36 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,  	if (parm->type != stream->type)  		return -EINVAL; -	if (uvc_queue_streaming(&stream->queue)) -		return -EBUSY; -  	if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)  		timeperframe = parm->parm.capture.timeperframe;  	else  		timeperframe = parm->parm.output.timeperframe; -	memcpy(&probe, &stream->ctrl, sizeof probe);  	interval = uvc_fraction_to_interval(timeperframe.numerator,  		timeperframe.denominator); -  	uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n",  		timeperframe.numerator, timeperframe.denominator, interval); -	probe.dwFrameInterval = uvc_try_frame_interval(frame, interval); + +	mutex_lock(&stream->mutex); + +	if (uvc_queue_streaming(&stream->queue)) { +		mutex_unlock(&stream->mutex); +		return -EBUSY; +	} + +	memcpy(&probe, &stream->ctrl, sizeof probe); +	probe.dwFrameInterval = +		uvc_try_frame_interval(stream->cur_frame, interval);  	/* Probe the device with the new settings. */  	ret = uvc_probe_video(stream, &probe); -	if (ret < 0) +	if (ret < 0) { +		mutex_unlock(&stream->mutex);  		return ret; +	}  	memcpy(&stream->ctrl, &probe, sizeof probe); +	mutex_unlock(&stream->mutex);  	/* Return the actual frame period. */  	timeperframe.numerator = probe.dwFrameInterval; @@ -528,11 +521,9 @@ static int uvc_v4l2_release(struct file *file)  	if (uvc_has_privileges(handle)) {  		uvc_video_enable(stream, 0); -		mutex_lock(&stream->queue.mutex);  		if (uvc_free_buffers(&stream->queue) < 0)  			uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to "  					"free buffers.\n"); -		mutex_unlock(&stream->queue.mutex);  	}  	/* Release the file handle. */ @@ -624,7 +615,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  	}  	case VIDIOC_QUERYMENU: -		return uvc_v4l2_query_menu(chain, arg); +		return uvc_query_v4l2_menu(chain, arg);  	case VIDIOC_G_EXT_CTRLS:  	{ @@ -905,15 +896,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  	case VIDIOC_CROPCAP:  	{  		struct v4l2_cropcap *ccap = arg; -		struct uvc_frame *frame = stream->cur_frame;  		if (ccap->type != stream->type)  			return -EINVAL;  		ccap->bounds.left = 0;  		ccap->bounds.top = 0; -		ccap->bounds.width = frame->wWidth; -		ccap->bounds.height = frame->wHeight; + +		mutex_lock(&stream->mutex); +		ccap->bounds.width = stream->cur_frame->wWidth; +		ccap->bounds.height = stream->cur_frame->wHeight; +		mutex_unlock(&stream->mutex);  		ccap->defrect = ccap->bounds; @@ -930,8 +923,6 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  	case VIDIOC_REQBUFS:  	{  		struct v4l2_requestbuffers *rb = arg; -		unsigned int bufsize = -			stream->ctrl.dwMaxVideoFrameSize;  		if (rb->type != stream->type ||  		    rb->memory != V4L2_MEMORY_MMAP) @@ -940,7 +931,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  		if ((ret = uvc_acquire_privileges(handle)) < 0)  			return ret; -		ret = uvc_alloc_buffers(&stream->queue, rb->count, bufsize); +		mutex_lock(&stream->mutex); +		ret = uvc_alloc_buffers(&stream->queue, rb->count, +					stream->ctrl.dwMaxVideoFrameSize); +		mutex_unlock(&stream->mutex);  		if (ret < 0)  			return ret; @@ -988,7 +982,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  		if (!uvc_has_privileges(handle))  			return -EBUSY; +		mutex_lock(&stream->mutex);  		ret = uvc_video_enable(stream, 1); +		mutex_unlock(&stream->mutex);  		if (ret < 0)  			return ret;  		break; @@ -1068,79 +1064,14 @@ static ssize_t uvc_v4l2_read(struct file *file, char __user *data,  	return -EINVAL;  } -/* - * VMA operations. - */ -static void uvc_vm_open(struct vm_area_struct *vma) -{ -	struct uvc_buffer *buffer = vma->vm_private_data; -	buffer->vma_use_count++; -} - -static void uvc_vm_close(struct vm_area_struct *vma) -{ -	struct uvc_buffer *buffer = vma->vm_private_data; -	buffer->vma_use_count--; -} - -static const struct vm_operations_struct uvc_vm_ops = { -	.open		= uvc_vm_open, -	.close		= uvc_vm_close, -}; -  static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)  {  	struct uvc_fh *handle = file->private_data;  	struct uvc_streaming *stream = handle->stream; -	struct uvc_video_queue *queue = &stream->queue; -	struct uvc_buffer *uninitialized_var(buffer); -	struct page *page; -	unsigned long addr, start, size; -	unsigned int i; -	int ret = 0;  	uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n"); -	start = vma->vm_start; -	size = vma->vm_end - vma->vm_start; - -	mutex_lock(&queue->mutex); - -	for (i = 0; i < queue->count; ++i) { -		buffer = &queue->buffer[i]; -		if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) -			break; -	} - -	if (i == queue->count || size != queue->buf_size) { -		ret = -EINVAL; -		goto done; -	} - -	/* -	 * VM_IO marks the area as being an mmaped region for I/O to a -	 * device. It also prevents the region from being core dumped. -	 */ -	vma->vm_flags |= VM_IO; - -	addr = (unsigned long)queue->mem + buffer->buf.m.offset; -	while (size > 0) { -		page = vmalloc_to_page((void *)addr); -		if ((ret = vm_insert_page(vma, start, page)) < 0) -			goto done; - -		start += PAGE_SIZE; -		addr += PAGE_SIZE; -		size -= PAGE_SIZE; -	} - -	vma->vm_ops = &uvc_vm_ops; -	vma->vm_private_data = buffer; -	uvc_vm_open(vma); - -done: -	mutex_unlock(&queue->mutex); -	return ret; +	return uvc_queue_mmap(&stream->queue, vma);  }  static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) @@ -1157,7 +1088,7 @@ const struct v4l2_file_operations uvc_fops = {  	.owner		= THIS_MODULE,  	.open		= uvc_v4l2_open,  	.release	= uvc_v4l2_release, -	.ioctl		= uvc_v4l2_ioctl, +	.unlocked_ioctl	= uvc_v4l2_ioctl,  	.read		= uvc_v4l2_read,  	.mmap		= uvc_v4l2_mmap,  	.poll		= uvc_v4l2_poll, diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 5555f010283..5673d673504 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -293,8 +293,6 @@ int uvc_probe_video(struct uvc_streaming *stream,  	unsigned int i;  	int ret; -	mutex_lock(&stream->mutex); -  	/* Perform probing. The device should adjust the requested values  	 * according to its capabilities. However, some devices, namely the  	 * first generation UVC Logitech webcams, don't implement the Video @@ -346,7 +344,6 @@ int uvc_probe_video(struct uvc_streaming *stream,  	}  done: -	mutex_unlock(&stream->mutex);  	return ret;  } diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index d97cf6d6a4f..45f01e7e13d 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -436,7 +436,9 @@ struct uvc_streaming {  	struct uvc_streaming_control ctrl;  	struct uvc_format *cur_format;  	struct uvc_frame *cur_frame; - +	/* Protect access to ctrl, cur_format, cur_frame and hardware video +	 * probe control. +	 */  	struct mutex mutex;  	unsigned int frozen : 1; @@ -574,6 +576,8 @@ extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);  extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);  extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,  		struct uvc_buffer *buf); +extern int uvc_queue_mmap(struct uvc_video_queue *queue, +		struct vm_area_struct *vma);  extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,  		struct file *file, poll_table *wait);  extern int uvc_queue_allocated(struct uvc_video_queue *queue); @@ -606,10 +610,10 @@ extern int uvc_status_suspend(struct uvc_device *dev);  extern int uvc_status_resume(struct uvc_device *dev);  /* Controls */ -extern struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, -		__u32 v4l2_id, struct uvc_control_mapping **mapping);  extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,  		struct v4l2_queryctrl *v4l2_ctrl); +extern int uvc_query_v4l2_menu(struct uvc_video_chain *chain, +		struct v4l2_querymenu *query_menu);  extern int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,  		const struct uvc_control_mapping *mapping); diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 03f7f4670e9..359e23290a7 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -186,12 +186,12 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf,  		size_t sz, loff_t *off)  {  	struct video_device *vdev = video_devdata(filp); -	int ret = -EIO; +	int ret = -ENODEV;  	if (!vdev->fops->read)  		return -EINVAL; -	if (vdev->lock) -		mutex_lock(vdev->lock); +	if (vdev->lock && mutex_lock_interruptible(vdev->lock)) +		return -ERESTARTSYS;  	if (video_is_registered(vdev))  		ret = vdev->fops->read(filp, buf, sz, off);  	if (vdev->lock) @@ -203,12 +203,12 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,  		size_t sz, loff_t *off)  {  	struct video_device *vdev = video_devdata(filp); -	int ret = -EIO; +	int ret = -ENODEV;  	if (!vdev->fops->write)  		return -EINVAL; -	if (vdev->lock) -		mutex_lock(vdev->lock); +	if (vdev->lock && mutex_lock_interruptible(vdev->lock)) +		return -ERESTARTSYS;  	if (video_is_registered(vdev))  		ret = vdev->fops->write(filp, buf, sz, off);  	if (vdev->lock) @@ -219,10 +219,10 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,  static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)  {  	struct video_device *vdev = video_devdata(filp); -	int ret = DEFAULT_POLLMASK; +	int ret = POLLERR | POLLHUP;  	if (!vdev->fops->poll) -		return ret; +		return DEFAULT_POLLMASK;  	if (vdev->lock)  		mutex_lock(vdev->lock);  	if (video_is_registered(vdev)) @@ -238,20 +238,45 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  	int ret = -ENODEV;  	if (vdev->fops->unlocked_ioctl) { -		if (vdev->lock) -			mutex_lock(vdev->lock); +		if (vdev->lock && mutex_lock_interruptible(vdev->lock)) +			return -ERESTARTSYS;  		if (video_is_registered(vdev))  			ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);  		if (vdev->lock)  			mutex_unlock(vdev->lock);  	} else if (vdev->fops->ioctl) { -		/* TODO: convert all drivers to unlocked_ioctl */ +		/* This code path is a replacement for the BKL. It is a major +		 * hack but it will have to do for those drivers that are not +		 * yet converted to use unlocked_ioctl. +		 * +		 * There are two options: if the driver implements struct +		 * v4l2_device, then the lock defined there is used to +		 * serialize the ioctls. Otherwise the v4l2 core lock defined +		 * below is used. This lock is really bad since it serializes +		 * completely independent devices. +		 * +		 * Both variants suffer from the same problem: if the driver +		 * sleeps, then it blocks all ioctls since the lock is still +		 * held. This is very common for VIDIOC_DQBUF since that +		 * normally waits for a frame to arrive. As a result any other +		 * ioctl calls will proceed very, very slowly since each call +		 * will have to wait for the VIDIOC_QBUF to finish. Things that +		 * should take 0.01s may now take 10-20 seconds. +		 * +		 * The workaround is to *not* take the lock for VIDIOC_DQBUF. +		 * This actually works OK for videobuf-based drivers, since +		 * videobuf will take its own internal lock. +		 */  		static DEFINE_MUTEX(v4l2_ioctl_mutex); +		struct mutex *m = vdev->v4l2_dev ? +			&vdev->v4l2_dev->ioctl_lock : &v4l2_ioctl_mutex; -		mutex_lock(&v4l2_ioctl_mutex); +		if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m)) +			return -ERESTARTSYS;  		if (video_is_registered(vdev))  			ret = vdev->fops->ioctl(filp, cmd, arg); -		mutex_unlock(&v4l2_ioctl_mutex); +		if (cmd != VIDIOC_DQBUF) +			mutex_unlock(m);  	} else  		ret = -ENOTTY; @@ -265,8 +290,8 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)  	if (!vdev->fops->mmap)  		return ret; -	if (vdev->lock) -		mutex_lock(vdev->lock); +	if (vdev->lock && mutex_lock_interruptible(vdev->lock)) +		return -ERESTARTSYS;  	if (video_is_registered(vdev))  		ret = vdev->fops->mmap(filp, vm);  	if (vdev->lock) @@ -284,7 +309,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)  	mutex_lock(&videodev_lock);  	vdev = video_devdata(filp);  	/* return ENODEV if the video device has already been removed. */ -	if (vdev == NULL) { +	if (vdev == NULL || !video_is_registered(vdev)) {  		mutex_unlock(&videodev_lock);  		return -ENODEV;  	} @@ -292,8 +317,10 @@ static int v4l2_open(struct inode *inode, struct file *filp)  	video_get(vdev);  	mutex_unlock(&videodev_lock);  	if (vdev->fops->open) { -		if (vdev->lock) -			mutex_lock(vdev->lock); +		if (vdev->lock && mutex_lock_interruptible(vdev->lock)) { +			ret = -ERESTARTSYS; +			goto err; +		}  		if (video_is_registered(vdev))  			ret = vdev->fops->open(filp);  		else @@ -302,6 +329,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)  			mutex_unlock(vdev->lock);  	} +err:  	/* decrease the refcount in case of an error */  	if (ret)  		video_put(vdev); @@ -596,7 +624,12 @@ void video_unregister_device(struct video_device *vdev)  	if (!vdev || !video_is_registered(vdev))  		return; +	mutex_lock(&videodev_lock); +	/* This must be in a critical section to prevent a race with v4l2_open. +	 * Once this bit has been cleared video_get may never be called again. +	 */  	clear_bit(V4L2_FL_REGISTERED, &vdev->flags); +	mutex_unlock(&videodev_lock);  	device_unregister(&vdev->dev);  }  EXPORT_SYMBOL(video_unregister_device); diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index 0b08f96b74a..7fe6f92af48 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -35,6 +35,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)  	INIT_LIST_HEAD(&v4l2_dev->subdevs);  	spin_lock_init(&v4l2_dev->lock); +	mutex_init(&v4l2_dev->ioctl_lock);  	v4l2_dev->dev = dev;  	if (dev == NULL) {  		/* If dev == NULL, then name must be filled in by the caller */ diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 635420d8d84..019ee206cbe 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -815,7 +815,7 @@ out:  static const struct v4l2_file_operations w9966_fops = {  	.owner		= THIS_MODULE, -	.ioctl          = video_ioctl2, +	.unlocked_ioctl = video_ioctl2,  	.read           = w9966_v4l_read,  }; diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 13552564908..fe8ef6419f8 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c @@ -35,7 +35,6 @@  #include <media/v4l2-device.h>  #include <media/v4l2-chip-ident.h>  #include <media/v4l2-ctrls.h> -#include <media/wm8775.h>  MODULE_DESCRIPTION("wm8775 driver");  MODULE_AUTHOR("Ulf Eklund, Hans Verkuil"); @@ -51,16 +50,10 @@ enum {  	TOT_REGS  }; -#define ALC_HOLD 0x85 /* R17: use zero cross detection, ALC hold time 42.6 ms */ -#define ALC_EN 0x100  /* R17: ALC enable */ -  struct wm8775_state {  	struct v4l2_subdev sd;  	struct v4l2_ctrl_handler hdl;  	struct v4l2_ctrl *mute; -	struct v4l2_ctrl *vol; -	struct v4l2_ctrl *bal; -	struct v4l2_ctrl *loud;  	u8 input;		/* Last selected input (0-0xf) */  }; @@ -92,30 +85,6 @@ static int wm8775_write(struct v4l2_subdev *sd, int reg, u16 val)  	return -1;  } -static void wm8775_set_audio(struct v4l2_subdev *sd, int quietly) -{ -	struct wm8775_state *state = to_state(sd); -	u8 vol_l, vol_r; -	int muted = 0 != state->mute->val; -	u16 volume = (u16)state->vol->val; -	u16 balance = (u16)state->bal->val; - -	/* normalize ( 65535 to 0 -> 255 to 0 (+24dB to -103dB) ) */ -	vol_l = (min(65536 - balance, 32768) * volume) >> 23; -	vol_r = (min(balance, (u16)32768) * volume) >> 23; - -	/* Mute */ -	if (muted || quietly) -		wm8775_write(sd, R21, 0x0c0 | state->input); - -	wm8775_write(sd, R14, vol_l | 0x100); /* 0x100= Left channel ADC zero cross enable */ -	wm8775_write(sd, R15, vol_r | 0x100); /* 0x100= Right channel ADC zero cross enable */ - -	/* Un-mute */ -	if (!muted) -		wm8775_write(sd, R21, state->input); -} -  static int wm8775_s_routing(struct v4l2_subdev *sd,  			    u32 input, u32 output, u32 config)  { @@ -133,26 +102,25 @@ static int wm8775_s_routing(struct v4l2_subdev *sd,  	state->input = input;  	if (!v4l2_ctrl_g_ctrl(state->mute))  		return 0; -	if (!v4l2_ctrl_g_ctrl(state->vol)) -		return 0; -	if (!v4l2_ctrl_g_ctrl(state->bal)) -		return 0; -	wm8775_set_audio(sd, 1); +	wm8775_write(sd, R21, 0x0c0); +	wm8775_write(sd, R14, 0x1d4); +	wm8775_write(sd, R15, 0x1d4); +	wm8775_write(sd, R21, 0x100 + state->input);  	return 0;  }  static int wm8775_s_ctrl(struct v4l2_ctrl *ctrl)  {  	struct v4l2_subdev *sd = to_sd(ctrl); +	struct wm8775_state *state = to_state(sd);  	switch (ctrl->id) {  	case V4L2_CID_AUDIO_MUTE: -	case V4L2_CID_AUDIO_VOLUME: -	case V4L2_CID_AUDIO_BALANCE: -		wm8775_set_audio(sd, 0); -		return 0; -	case V4L2_CID_AUDIO_LOUDNESS: -		wm8775_write(sd, R17, (ctrl->val ? ALC_EN : 0) | ALC_HOLD); +		wm8775_write(sd, R21, 0x0c0); +		wm8775_write(sd, R14, 0x1d4); +		wm8775_write(sd, R15, 0x1d4); +		if (!ctrl->val) +			wm8775_write(sd, R21, 0x100 + state->input);  		return 0;  	}  	return -EINVAL; @@ -176,7 +144,16 @@ static int wm8775_log_status(struct v4l2_subdev *sd)  static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)  { -	wm8775_set_audio(sd, 0); +	struct wm8775_state *state = to_state(sd); + +	/* If I remove this, then it can happen that I have no +	   sound the first time I tune from static to a valid channel. +	   It's difficult to reproduce and is almost certainly related +	   to the zero cross detect circuit. */ +	wm8775_write(sd, R21, 0x0c0); +	wm8775_write(sd, R14, 0x1d4); +	wm8775_write(sd, R15, 0x1d4); +	wm8775_write(sd, R21, 0x100 + state->input);  	return 0;  } @@ -226,7 +203,6 @@ static int wm8775_probe(struct i2c_client *client,  {  	struct wm8775_state *state;  	struct v4l2_subdev *sd; -	int err;  	/* Check if the adapter supports the needed features */  	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -240,21 +216,15 @@ static int wm8775_probe(struct i2c_client *client,  		return -ENOMEM;  	sd = &state->sd;  	v4l2_i2c_subdev_init(sd, client, &wm8775_ops); -	sd->grp_id = WM8775_GID; /* subdev group id */  	state->input = 2; -	v4l2_ctrl_handler_init(&state->hdl, 4); +	v4l2_ctrl_handler_init(&state->hdl, 1);  	state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,  			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); -	state->vol = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops, -			V4L2_CID_AUDIO_VOLUME, 0, 65535, (65535+99)/100, 0xCF00); /* 0dB*/ -	state->bal = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops, -			V4L2_CID_AUDIO_BALANCE, 0, 65535, (65535+99)/100, 32768); -	state->loud = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops, -			V4L2_CID_AUDIO_LOUDNESS, 0, 1, 1, 1);  	sd->ctrl_handler = &state->hdl; -	err = state->hdl.error; -	if (err) { +	if (state->hdl.error) { +		int err = state->hdl.error; +  		v4l2_ctrl_handler_free(&state->hdl);  		kfree(state);  		return err; @@ -266,25 +236,29 @@ static int wm8775_probe(struct i2c_client *client,  	wm8775_write(sd, R23, 0x000);  	/* Disable zero cross detect timeout */  	wm8775_write(sd, R7, 0x000); -	/* HPF enable, I2S mode, 24-bit */ -	wm8775_write(sd, R11, 0x022); +	/* Left justified, 24-bit mode */ +	wm8775_write(sd, R11, 0x021);  	/* Master mode, clock ratio 256fs */  	wm8775_write(sd, R12, 0x102);  	/* Powered up */  	wm8775_write(sd, R13, 0x000); -	/* ALC stereo, ALC target level -5dB FS, ALC max gain +8dB */ -	wm8775_write(sd, R16, 0x1bb); -	/* Set ALC mode and hold time */ -	wm8775_write(sd, R17, (state->loud->val ? ALC_EN : 0) | ALC_HOLD); +	/* ADC gain +2.5dB, enable zero cross */ +	wm8775_write(sd, R14, 0x1d4); +	/* ADC gain +2.5dB, enable zero cross */ +	wm8775_write(sd, R15, 0x1d4); +	/* ALC Stereo, ALC target level -1dB FS max gain +8dB */ +	wm8775_write(sd, R16, 0x1bf); +	/* Enable gain control, use zero cross detection, +	   ALC hold time 42.6 ms */ +	wm8775_write(sd, R17, 0x185);  	/* ALC gain ramp up delay 34 s, ALC gain ramp down delay 33 ms */  	wm8775_write(sd, R18, 0x0a2);  	/* Enable noise gate, threshold -72dBfs */  	wm8775_write(sd, R19, 0x005); -	/* Transient window 4ms, ALC min gain -5dB  */ -	wm8775_write(sd, R20, 0x0fb); - -	wm8775_set_audio(sd, 1);      /* set volume/mute/mux */ - +	/* Transient window 4ms, lower PGA gain limit -1dB */ +	wm8775_write(sd, R20, 0x07a); +	/* LRBOTH = 1, use input 2. */ +	wm8775_write(sd, R21, 0x102);  	return 0;  } diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index dbe1c93c1af..d9640a623ff 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -303,7 +303,7 @@ static irqreturn_t ab8500_irq(int irq, void *dev)  			continue;  		do { -			int bit = __ffs(status); +			int bit = __ffs(value);  			int line = i * 8 + bit;  			handle_nested_irq(ab8500->irq_base + line); diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 7d2563fc15c..76cadcf3b1f 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -1455,7 +1455,11 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)  		dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);  		goto err;  	} -	if (ret != 0x6204) { +	switch (ret) { +	case 0x6204: +	case 0x6246: +		break; +	default:  		dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);  		ret = -EINVAL;  		goto err; @@ -1620,7 +1624,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)  	case WM8325:  		ret = mfd_add_devices(wm831x->dev, -1,  				      wm8320_devs, ARRAY_SIZE(wm8320_devs), -				      NULL, 0); +				      NULL, wm831x->irq_base);  		break;  	default: diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 31ae07a3657..57dcf8fa774 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1773,6 +1773,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,  	case PM_POST_SUSPEND:  	case PM_POST_HIBERNATION: +	case PM_POST_RESTORE:  		spin_lock_irqsave(&host->lock, flags);  		host->rescan_disable = 0; diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index 591ab540b40..d3e6a962f42 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c @@ -69,6 +69,7 @@  #include <linux/highmem.h>  #include <linux/mmc/host.h> +#include <linux/mmc/sdio.h>  #include <asm/io.h>  #include <asm/irq.h> @@ -493,10 +494,14 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command  		else if (data->flags & MMC_DATA_WRITE)  			cmdr |= AT91_MCI_TRCMD_START; -		if (data->flags & MMC_DATA_STREAM) -			cmdr |= AT91_MCI_TRTYP_STREAM; -		if (data->blocks > 1) -			cmdr |= AT91_MCI_TRTYP_MULTIPLE; +		if (cmd->opcode == SD_IO_RW_EXTENDED) { +			cmdr |= AT91_MCI_TRTYP_SDIO_BLOCK; +		} else { +			if (data->flags & MMC_DATA_STREAM) +				cmdr |= AT91_MCI_TRTYP_STREAM; +			if (data->blocks > 1) +				cmdr |= AT91_MCI_TRTYP_MULTIPLE; +		}  	}  	else {  		block_length = 0; diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 301351a5d83..ad2a7a032cd 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -26,6 +26,7 @@  #include <linux/stat.h>  #include <linux/mmc/host.h> +#include <linux/mmc/sdio.h>  #include <mach/atmel-mci.h>  #include <linux/atmel-mci.h> @@ -532,12 +533,17 @@ static u32 atmci_prepare_command(struct mmc_host *mmc,  	data = cmd->data;  	if (data) {  		cmdr |= MCI_CMDR_START_XFER; -		if (data->flags & MMC_DATA_STREAM) -			cmdr |= MCI_CMDR_STREAM; -		else if (data->blocks > 1) -			cmdr |= MCI_CMDR_MULTI_BLOCK; -		else -			cmdr |= MCI_CMDR_BLOCK; + +		if (cmd->opcode == SD_IO_RW_EXTENDED) { +			cmdr |= MCI_CMDR_SDIO_BLOCK; +		} else { +			if (data->flags & MMC_DATA_STREAM) +				cmdr |= MCI_CMDR_STREAM; +			else if (data->blocks > 1) +				cmdr |= MCI_CMDR_MULTI_BLOCK; +			else +				cmdr |= MCI_CMDR_BLOCK; +		}  		if (data->flags & MMC_DATA_READ)  			cmdr |= MCI_CMDR_TRDIR_READ; diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 09b099bfab2..bdf11d89a49 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -702,6 +702,7 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)  	adapter->wol = 0; +	device_set_wakeup_enable(&pdev->dev, false);  	adapter->link_speed = SPEED_0;  	adapter->link_duplex = FULL_DUPLEX;  	adapter->num_rx_queues = AT_DEF_RECEIVE_QUEUE; @@ -2444,8 +2445,9 @@ static int atl1c_close(struct net_device *netdev)  	return 0;  } -static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state) +static int atl1c_suspend(struct device *dev)  { +	struct pci_dev *pdev = to_pci_dev(dev);  	struct net_device *netdev = pci_get_drvdata(pdev);  	struct atl1c_adapter *adapter = netdev_priv(netdev);  	struct atl1c_hw *hw = &adapter->hw; @@ -2454,7 +2456,6 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)  	u32 wol_ctrl_data = 0;  	u16 mii_intr_status_data = 0;  	u32 wufc = adapter->wol; -	int retval = 0;  	atl1c_disable_l0s_l1(hw);  	if (netif_running(netdev)) { @@ -2462,9 +2463,6 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)  		atl1c_down(adapter);  	}  	netif_device_detach(netdev); -	retval = pci_save_state(pdev); -	if (retval) -		return retval;  	if (wufc)  		if (atl1c_phy_power_saving(hw) != 0) @@ -2525,12 +2523,8 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)  		AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);  		AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); -		/* pcie patch */ -		device_set_wakeup_enable(&pdev->dev, 1); -  		AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |  			GPHY_CTRL_EXT_RESET); -		pci_prepare_to_sleep(pdev);  	} else {  		AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_POWER_SAVING);  		master_ctrl_data |= MASTER_CTRL_CLK_SEL_DIS; @@ -2540,25 +2534,17 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)  		AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);  		AT_WRITE_REG(hw, REG_WOL_CTRL, 0);  		hw->phy_configured = false; /* re-init PHY when resume */ -		pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);  	} -	pci_disable_device(pdev); -	pci_set_power_state(pdev, pci_choose_state(pdev, state)); -  	return 0;  } -static int atl1c_resume(struct pci_dev *pdev) +static int atl1c_resume(struct device *dev)  { +	struct pci_dev *pdev = to_pci_dev(dev);  	struct net_device *netdev = pci_get_drvdata(pdev);  	struct atl1c_adapter *adapter = netdev_priv(netdev); -	pci_set_power_state(pdev, PCI_D0); -	pci_restore_state(pdev); -	pci_enable_wake(pdev, PCI_D3hot, 0); -	pci_enable_wake(pdev, PCI_D3cold, 0); -  	AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);  	atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE |  			ATL1C_PCIE_PHY_RESET); @@ -2582,7 +2568,12 @@ static int atl1c_resume(struct pci_dev *pdev)  static void atl1c_shutdown(struct pci_dev *pdev)  { -	atl1c_suspend(pdev, PMSG_SUSPEND); +	struct net_device *netdev = pci_get_drvdata(pdev); +	struct atl1c_adapter *adapter = netdev_priv(netdev); + +	atl1c_suspend(&pdev->dev); +	pci_wake_from_d3(pdev, adapter->wol); +	pci_set_power_state(pdev, PCI_D3hot);  }  static const struct net_device_ops atl1c_netdev_ops = { @@ -2886,16 +2877,16 @@ static struct pci_error_handlers atl1c_err_handler = {  	.resume = atl1c_io_resume,  }; +static SIMPLE_DEV_PM_OPS(atl1c_pm_ops, atl1c_suspend, atl1c_resume); +  static struct pci_driver atl1c_driver = {  	.name     = atl1c_driver_name,  	.id_table = atl1c_pci_tbl,  	.probe    = atl1c_probe,  	.remove   = __devexit_p(atl1c_remove), -	/* Power Managment Hooks */ -	.suspend  = atl1c_suspend, -	.resume   = atl1c_resume,  	.shutdown = atl1c_shutdown, -	.err_handler = &atl1c_err_handler +	.err_handler = &atl1c_err_handler, +	.driver.pm = &atl1c_pm_ops,  };  /* diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 53363108994..3acf5123a6e 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -3504,6 +3504,8 @@ static int atl1_set_ringparam(struct net_device *netdev,  	struct atl1_rfd_ring rfd_old, rfd_new;  	struct atl1_rrd_ring rrd_old, rrd_new;  	struct atl1_ring_header rhdr_old, rhdr_new; +	struct atl1_smb smb; +	struct atl1_cmb cmb;  	int err;  	tpd_old = adapter->tpd_ring; @@ -3544,11 +3546,19 @@ static int atl1_set_ringparam(struct net_device *netdev,  		adapter->rrd_ring = rrd_old;  		adapter->tpd_ring = tpd_old;  		adapter->ring_header = rhdr_old; +		/* +		 * Save SMB and CMB, since atl1_free_ring_resources +		 * will clear them. +		 */ +		smb = adapter->smb; +		cmb = adapter->cmb;  		atl1_free_ring_resources(adapter);  		adapter->rfd_ring = rfd_new;  		adapter->rrd_ring = rrd_new;  		adapter->tpd_ring = tpd_new;  		adapter->ring_header = rhdr_new; +		adapter->smb = smb; +		adapter->cmb = cmb;  		err = atl1_up(adapter);  		if (err) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 4594a28b1f6..d64313b7090 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -234,7 +234,7 @@ struct be_adapter {  	u8 __iomem *db;		/* Door Bell */  	u8 __iomem *pcicfg;	/* PCI config space */ -	spinlock_t mbox_lock;	/* For serializing mbox cmds to BE card */ +	struct mutex mbox_lock; /* For serializing mbox cmds to BE card */  	struct be_dma_mem mbox_mem;  	/* Mbox mem is adjusted to align to 16 bytes. The allocated addr  	 * is stored for freeing purpose */ diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index e4465d222a7..1c8c79c9d21 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -462,7 +462,8 @@ int be_cmd_fw_init(struct be_adapter *adapter)  	u8 *wrb;  	int status; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = (u8 *)wrb_from_mbox(adapter);  	*wrb++ = 0xFF; @@ -476,7 +477,7 @@ int be_cmd_fw_init(struct be_adapter *adapter)  	status = be_mbox_notify_wait(adapter); -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  } @@ -491,7 +492,8 @@ int be_cmd_fw_clean(struct be_adapter *adapter)  	if (adapter->eeh_err)  		return -EIO; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = (u8 *)wrb_from_mbox(adapter);  	*wrb++ = 0xFF; @@ -505,7 +507,7 @@ int be_cmd_fw_clean(struct be_adapter *adapter)  	status = be_mbox_notify_wait(adapter); -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  }  int be_cmd_eq_create(struct be_adapter *adapter, @@ -516,7 +518,8 @@ int be_cmd_eq_create(struct be_adapter *adapter,  	struct be_dma_mem *q_mem = &eq->dma_mem;  	int status; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = wrb_from_mbox(adapter);  	req = embedded_payload(wrb); @@ -546,7 +549,7 @@ int be_cmd_eq_create(struct be_adapter *adapter,  		eq->created = true;  	} -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  } @@ -558,7 +561,8 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,  	struct be_cmd_req_mac_query *req;  	int status; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = wrb_from_mbox(adapter);  	req = embedded_payload(wrb); @@ -583,7 +587,7 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,  		memcpy(mac_addr, resp->mac.addr, ETH_ALEN);  	} -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  } @@ -667,7 +671,8 @@ int be_cmd_cq_create(struct be_adapter *adapter,  	void *ctxt;  	int status; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = wrb_from_mbox(adapter);  	req = embedded_payload(wrb); @@ -701,7 +706,7 @@ int be_cmd_cq_create(struct be_adapter *adapter,  		cq->created = true;  	} -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  } @@ -724,7 +729,8 @@ int be_cmd_mccq_create(struct be_adapter *adapter,  	void *ctxt;  	int status; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = wrb_from_mbox(adapter);  	req = embedded_payload(wrb); @@ -754,7 +760,7 @@ int be_cmd_mccq_create(struct be_adapter *adapter,  		mccq->id = le16_to_cpu(resp->id);  		mccq->created = true;  	} -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  } @@ -769,7 +775,8 @@ int be_cmd_txq_create(struct be_adapter *adapter,  	void *ctxt;  	int status; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = wrb_from_mbox(adapter);  	req = embedded_payload(wrb); @@ -801,7 +808,7 @@ int be_cmd_txq_create(struct be_adapter *adapter,  		txq->created = true;  	} -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  } @@ -816,7 +823,8 @@ int be_cmd_rxq_create(struct be_adapter *adapter,  	struct be_dma_mem *q_mem = &rxq->dma_mem;  	int status; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = wrb_from_mbox(adapter);  	req = embedded_payload(wrb); @@ -843,7 +851,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter,  		*rss_id = resp->rss_id;  	} -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  } @@ -862,7 +870,8 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,  	if (adapter->eeh_err)  		return -EIO; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = wrb_from_mbox(adapter);  	req = embedded_payload(wrb); @@ -899,7 +908,7 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,  	status = be_mbox_notify_wait(adapter); -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  } @@ -915,7 +924,8 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,  	struct be_cmd_req_if_create *req;  	int status; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = wrb_from_mbox(adapter);  	req = embedded_payload(wrb); @@ -941,7 +951,7 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,  			*pmac_id = le32_to_cpu(resp->pmac_id);  	} -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  } @@ -955,7 +965,8 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)  	if (adapter->eeh_err)  		return -EIO; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = wrb_from_mbox(adapter);  	req = embedded_payload(wrb); @@ -970,7 +981,7 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)  	status = be_mbox_notify_wait(adapter); -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  } @@ -1060,7 +1071,8 @@ int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)  	struct be_cmd_req_get_fw_version *req;  	int status; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = wrb_from_mbox(adapter);  	req = embedded_payload(wrb); @@ -1077,7 +1089,7 @@ int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)  		strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN);  	} -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  } @@ -1322,7 +1334,8 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,  	struct be_cmd_req_query_fw_cfg *req;  	int status; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = wrb_from_mbox(adapter);  	req = embedded_payload(wrb); @@ -1341,7 +1354,7 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,  		*caps = le32_to_cpu(resp->function_caps);  	} -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  } @@ -1352,7 +1365,8 @@ int be_cmd_reset_function(struct be_adapter *adapter)  	struct be_cmd_req_hdr *req;  	int status; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = wrb_from_mbox(adapter);  	req = embedded_payload(wrb); @@ -1365,7 +1379,7 @@ int be_cmd_reset_function(struct be_adapter *adapter)  	status = be_mbox_notify_wait(adapter); -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  } @@ -1376,7 +1390,8 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size)  	u32 myhash[10];  	int status; -	spin_lock(&adapter->mbox_lock); +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1;  	wrb = wrb_from_mbox(adapter);  	req = embedded_payload(wrb); @@ -1396,7 +1411,7 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size)  	status = be_mbox_notify_wait(adapter); -	spin_unlock(&adapter->mbox_lock); +	mutex_unlock(&adapter->mbox_lock);  	return status;  } diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 93354eee2cf..fd251b59b7f 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -2677,7 +2677,7 @@ static int be_ctrl_init(struct be_adapter *adapter)  	}  	memset(mc_cmd_mem->va, 0, mc_cmd_mem->size); -	spin_lock_init(&adapter->mbox_lock); +	mutex_init(&adapter->mbox_lock);  	spin_lock_init(&adapter->mcc_lock);  	spin_lock_init(&adapter->mcc_cq_lock); diff --git a/drivers/net/bonding/bond_ipv6.c b/drivers/net/bonding/bond_ipv6.c index 121b073a6c3..84fbd4ebd77 100644 --- a/drivers/net/bonding/bond_ipv6.c +++ b/drivers/net/bonding/bond_ipv6.c @@ -88,7 +88,12 @@ static void bond_na_send(struct net_device *slave_dev,  	}  	if (vlan_id) { -		skb = vlan_put_tag(skb, vlan_id); +		/* The Ethernet header is not present yet, so it is +		 * too early to insert a VLAN tag.  Force use of an +		 * out-of-line tag here and let dev_hard_start_xmit() +		 * insert it if the slave hardware can't. +		 */ +		skb = __vlan_hwaccel_put_tag(skb, vlan_id);  		if (!skb) {  			pr_err("failed to insert VLAN tag\n");  			return; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index d0ea760ce41..3b16c34ed86 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -418,36 +418,11 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr)   * @bond: bond device that got this skb for tx.   * @skb: hw accel VLAN tagged skb to transmit   * @slave_dev: slave that is supposed to xmit this skbuff - * - * When the bond gets an skb to transmit that is - * already hardware accelerated VLAN tagged, and it - * needs to relay this skb to a slave that is not - * hw accel capable, the skb needs to be "unaccelerated", - * i.e. strip the hwaccel tag and re-insert it as part - * of the payload.   */  int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,  			struct net_device *slave_dev)  { -	unsigned short uninitialized_var(vlan_id); - -	/* Test vlan_list not vlgrp to catch and handle 802.1p tags */ -	if (!list_empty(&bond->vlan_list) && -	    !(slave_dev->features & NETIF_F_HW_VLAN_TX) && -	    vlan_get_tag(skb, &vlan_id) == 0) { -		skb->dev = slave_dev; -		skb = vlan_put_tag(skb, vlan_id); -		if (!skb) { -			/* vlan_put_tag() frees the skb in case of error, -			 * so return success here so the calling functions -			 * won't attempt to free is again. -			 */ -			return 0; -		} -	} else { -		skb->dev = slave_dev; -	} - +	skb->dev = slave_dev;  	skb->priority = 1;  #ifdef CONFIG_NET_POLL_CONTROLLER  	if (unlikely(bond->dev->priv_flags & IFF_IN_NETPOLL)) { @@ -1203,11 +1178,13 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)  				bond_do_fail_over_mac(bond, new_active,  						      old_active); -			bond->send_grat_arp = bond->params.num_grat_arp; -			bond_send_gratuitous_arp(bond); +			if (netif_running(bond->dev)) { +				bond->send_grat_arp = bond->params.num_grat_arp; +				bond_send_gratuitous_arp(bond); -			bond->send_unsol_na = bond->params.num_unsol_na; -			bond_send_unsolicited_na(bond); +				bond->send_unsol_na = bond->params.num_unsol_na; +				bond_send_unsolicited_na(bond); +			}  			write_unlock_bh(&bond->curr_slave_lock);  			read_unlock(&bond->lock); @@ -1221,8 +1198,9 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)  	/* resend IGMP joins since active slave has changed or  	 * all were sent on curr_active_slave */ -	if ((USES_PRIMARY(bond->params.mode) && new_active) || -	    bond->params.mode == BOND_MODE_ROUNDROBIN) { +	if (((USES_PRIMARY(bond->params.mode) && new_active) || +	     bond->params.mode == BOND_MODE_ROUNDROBIN) && +	    netif_running(bond->dev)) {  		bond->igmp_retrans = bond->params.resend_igmp;  		queue_delayed_work(bond->wq, &bond->mcast_work, 0);  	} diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index c2f081352a0..4feeb2d650a 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -269,11 +269,11 @@ static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct n  	bond_for_each_slave(bond, slave, i) {  		if (slave->dev == slave_dev) { -			break; +			return slave;  		}  	} -	return slave; +	return 0;  }  static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 92bac19ad60..6dff32196c9 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -940,7 +940,7 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)  					   &udev->l2_ring_map,  					   GFP_KERNEL | __GFP_COMP);  	if (!udev->l2_ring) -		return -ENOMEM; +		goto err_udev;  	udev->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size;  	udev->l2_buf_size = PAGE_ALIGN(udev->l2_buf_size); @@ -948,7 +948,7 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)  					  &udev->l2_buf_map,  					  GFP_KERNEL | __GFP_COMP);  	if (!udev->l2_buf) -		return -ENOMEM; +		goto err_dma;  	write_lock(&cnic_dev_lock);  	list_add(&udev->list, &cnic_udev_list); @@ -959,6 +959,12 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)  	cp->udev = udev;  	return 0; + err_dma: +	dma_free_coherent(&udev->pdev->dev, udev->l2_ring_size, +			  udev->l2_ring, udev->l2_ring_map); + err_udev: +	kfree(udev); +	return -ENOMEM;  }  static int cnic_init_uio(struct cnic_dev *dev) diff --git a/drivers/net/ehea/ehea_ethtool.c b/drivers/net/ehea/ehea_ethtool.c index 1f37ee6b2a2..d6cf502906c 100644 --- a/drivers/net/ehea/ehea_ethtool.c +++ b/drivers/net/ehea/ehea_ethtool.c @@ -263,6 +263,13 @@ static void ehea_get_ethtool_stats(struct net_device *dev,  static int ehea_set_flags(struct net_device *dev, u32 data)  { +	/* Avoid changing the VLAN flags */ +	if ((data & (ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN)) != +	    (ethtool_op_get_flags(dev) & (ETH_FLAG_RXVLAN | +					  ETH_FLAG_TXVLAN))){ +		return -EINVAL; +	} +  	return ethtool_op_set_flags(dev, data, ETH_FLAG_LRO  					| ETH_FLAG_TXVLAN  					| ETH_FLAG_RXVLAN); diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index aa56963ad55..c353bf3113c 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -935,7 +935,7 @@ static void epic_init_ring(struct net_device *dev)  	/* Fill in the Rx buffers.  Handle allocation failure gracefully. */  	for (i = 0; i < RX_RING_SIZE; i++) { -		struct sk_buff *skb = dev_alloc_skb(ep->rx_buf_sz); +		struct sk_buff *skb = dev_alloc_skb(ep->rx_buf_sz + 2);  		ep->rx_skbuff[i] = skb;  		if (skb == NULL)  			break; @@ -1233,7 +1233,7 @@ static int epic_rx(struct net_device *dev, int budget)  		entry = ep->dirty_rx % RX_RING_SIZE;  		if (ep->rx_skbuff[entry] == NULL) {  			struct sk_buff *skb; -			skb = ep->rx_skbuff[entry] = dev_alloc_skb(ep->rx_buf_sz); +			skb = ep->rx_skbuff[entry] = dev_alloc_skb(ep->rx_buf_sz + 2);  			if (skb == NULL)  				break;  			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */ diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 9a6485892b3..80d25ed5334 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -1202,7 +1202,7 @@ static void hamachi_init_ring(struct net_device *dev)  	}  	/* Fill in the Rx buffers.  Handle allocation failure gracefully. */  	for (i = 0; i < RX_RING_SIZE; i++) { -		struct sk_buff *skb = dev_alloc_skb(hmp->rx_buf_sz); +		struct sk_buff *skb = dev_alloc_skb(hmp->rx_buf_sz + 2);  		hmp->rx_skbuff[i] = skb;  		if (skb == NULL)  			break; @@ -1669,7 +1669,7 @@ static int hamachi_rx(struct net_device *dev)  		entry = hmp->dirty_rx % RX_RING_SIZE;  		desc = &(hmp->rx_ring[entry]);  		if (hmp->rx_skbuff[entry] == NULL) { -			struct sk_buff *skb = dev_alloc_skb(hmp->rx_buf_sz); +			struct sk_buff *skb = dev_alloc_skb(hmp->rx_buf_sz + 2);  			hmp->rx_skbuff[entry] = skb;  			if (skb == NULL) diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 8a4d19e5de0..f1047dd8a52 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -690,6 +690,7 @@ static void block_output(struct net_device *dev, int count,  static struct pcmcia_device_id axnet_ids[] = {  	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x016c, 0x0081),  	PCMCIA_DEVICE_MANF_CARD(0x018a, 0x0301), +	PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328),  	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0301),  	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0303),  	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309), diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index d05c44692f0..2c158910f7e 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1493,7 +1493,6 @@ static struct pcmcia_device_id pcnet_ids[] = {  	PCMCIA_DEVICE_MANF_CARD(0x0149, 0x4530),  	PCMCIA_DEVICE_MANF_CARD(0x0149, 0xc1ab),  	PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0110), -	PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328),  	PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x8041),  	PCMCIA_DEVICE_MANF_CARD(0x0213, 0x2452),  	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0300), diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 39659976a1a..89294b43c4a 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1285,6 +1285,11 @@ ppp_push(struct ppp *ppp)  }  #ifdef CONFIG_PPP_MULTILINK +static bool mp_protocol_compress __read_mostly = true; +module_param(mp_protocol_compress, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(mp_protocol_compress, +		 "compress protocol id in multilink fragments"); +  /*   * Divide a packet to be transmitted into fragments and   * send them out the individual links. @@ -1347,10 +1352,10 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)  	if (nfree == 0 || nfree < navail / 2)  		return 0; /* can't take now, leave it in xmit_pending */ -	/* Do protocol field compression (XXX this should be optional) */ +	/* Do protocol field compression */  	p = skb->data;  	len = skb->len; -	if (*p == 0) { +	if (*p == 0 && mp_protocol_compress) {  		++p;  		--len;  	} diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index 0a66fed52e8..16c62659cdd 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -412,7 +412,7 @@ static  int skfp_driver_init(struct net_device *dev)  		bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev,  							 bp->SharedMemSize,  							 &bp->SharedMemDMA); -		if (!bp->SharedMemSize) { +		if (!bp->SharedMemAddr) {  			printk("could not allocate mem for ");  			printk("hardware module: %ld byte\n",  			       bp->SharedMemSize); diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 4adf1242278..a4f2bd52e54 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -148,7 +148,7 @@ static int full_duplex[MAX_UNITS] = {0, };   * This SUCKS.   * We need a much better method to determine if dma_addr_t is 64-bit.   */ -#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) || (defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT)) +#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || (defined(CONFIG_MIPS) && ((defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) || defined(CONFIG_64BIT))) || (defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT))  /* 64-bit dma_addr_t */  #define ADDR_64BITS	/* This chip uses 64 bit addresses. */  #define netdrv_addr_t __le64 diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 3ed2a67bd6d..b409d7ec4ac 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -1016,7 +1016,7 @@ static void init_ring(struct net_device *dev)  	/* Fill in the Rx buffers.  Handle allocation failure gracefully. */  	for (i = 0; i < RX_RING_SIZE; i++) { -		struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz); +		struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz + 2);  		np->rx_skbuff[i] = skb;  		if (skb == NULL)  			break; @@ -1407,7 +1407,7 @@ static void refill_rx (struct net_device *dev)  		struct sk_buff *skb;  		entry = np->dirty_rx % RX_RING_SIZE;  		if (np->rx_skbuff[entry] == NULL) { -			skb = dev_alloc_skb(np->rx_buf_sz); +			skb = dev_alloc_skb(np->rx_buf_sz + 2);  			np->rx_skbuff[entry] = skb;  			if (skb == NULL)  				break;		/* Better luck next round. */ diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 8b3dc1eb401..296000bf5a2 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -324,7 +324,7 @@ static int bdx_fw_load(struct bdx_priv *priv)  	ENTER;  	master = READ_REG(priv, regINIT_SEMAPHORE);  	if (!READ_REG(priv, regINIT_STATUS) && master) { -		rc = request_firmware(&fw, "tehuti/firmware.bin", &priv->pdev->dev); +		rc = request_firmware(&fw, "tehuti/bdx.bin", &priv->pdev->dev);  		if (rc)  			goto out;  		bdx_tx_push_desc_safe(priv, (char *)fw->data, fw->size); @@ -2510,4 +2510,4 @@ module_exit(bdx_module_exit);  MODULE_LICENSE("GPL");  MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(BDX_DRV_DESC); -MODULE_FIRMWARE("tehuti/firmware.bin"); +MODULE_FIRMWARE("tehuti/bdx.bin"); diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 30ccbb6d097..6f97b7bbcbf 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -12658,7 +12658,7 @@ static void __devinit tg3_read_vpd(struct tg3 *tp)  			cnt = pci_read_vpd(tp->pdev, pos,  					   TG3_NVM_VPD_LEN - pos,  					   &vpd_data[pos]); -			if (cnt == -ETIMEDOUT || -EINTR) +			if (cnt == -ETIMEDOUT || cnt == -EINTR)  				cnt = 0;  			else if (cnt < 0)  				goto out_not_found; diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 5b83c3f35f4..a3c46f6a15e 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -1004,7 +1004,6 @@ typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)  	}  	strcpy(info->driver, KBUILD_MODNAME); -	strcpy(info->version, UTS_RELEASE);  	strcpy(info->bus_info, pci_name(pci_dev));  } diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index aea4645be7f..6140b56cce5 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -1508,6 +1508,10 @@ static const struct usb_device_id	products [] = {  	USB_DEVICE (0x0b95, 0x1780),  	.driver_info = (unsigned long) &ax88178_info,  }, { +	// Logitec LAN-GTJ/U2A +	USB_DEVICE (0x0789, 0x0160), +	.driver_info = (unsigned long) &ax88178_info, +}, {  	// Linksys USB200M Rev 2  	USB_DEVICE (0x13b1, 0x0018),  	.driver_info = (unsigned long) &ax88772_info, diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index a6281e3987b..2b791392e78 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -1,5 +1,5 @@  /* - * MOSCHIP MCS7830 based USB 2.0 Ethernet Devices + * MOSCHIP MCS7830 based (7730/7830/7832) USB 2.0 Ethernet Devices   *   * based on usbnet.c, asix.c and the vendor provided mcs7830 driver   * @@ -11,6 +11,9 @@   *   * Definitions gathered from MOSCHIP, Data Sheet_7830DA.pdf (thanks!).   * + * 2010-12-19: add 7832 USB PID ("functionality same as MCS7830"), + *             per active notification by manufacturer + *   * TODO:   * - support HIF_REG_CONFIG_SLEEPMODE/HIF_REG_CONFIG_TXENABLE (via autopm?)   * - implement ethtool_ops get_pauseparam/set_pauseparam @@ -60,6 +63,7 @@  #define MCS7830_MAX_MCAST	64  #define MCS7830_VENDOR_ID	0x9710 +#define MCS7832_PRODUCT_ID	0x7832  #define MCS7830_PRODUCT_ID	0x7830  #define MCS7730_PRODUCT_ID	0x7730 @@ -351,7 +355,7 @@ static int mcs7830_set_autoneg(struct usbnet *dev, int ptrUserPhyMode)  	if (!ret)  		ret = mcs7830_write_phy(dev, MII_BMCR,  				BMCR_ANENABLE | BMCR_ANRESTART	); -	return ret < 0 ? : 0; +	return ret;  } @@ -626,7 +630,7 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb)  }  static const struct driver_info moschip_info = { -	.description	= "MOSCHIP 7830/7730 usb-NET adapter", +	.description	= "MOSCHIP 7830/7832/7730 usb-NET adapter",  	.bind		= mcs7830_bind,  	.rx_fixup	= mcs7830_rx_fixup,  	.flags		= FLAG_ETHER, @@ -645,6 +649,10 @@ static const struct driver_info sitecom_info = {  static const struct usb_device_id products[] = {  	{ +		USB_DEVICE(MCS7830_VENDOR_ID, MCS7832_PRODUCT_ID), +		.driver_info = (unsigned long) &moschip_info, +	}, +	{  		USB_DEVICE(MCS7830_VENDOR_ID, MCS7830_PRODUCT_ID),  		.driver_info = (unsigned long) &moschip_info,  	}, diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 0bbc0c32313..cc83fa71c3f 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -166,7 +166,9 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)  	if (!(rcv->flags & IFF_UP))  		goto tx_drop; -	if (dev->features & NETIF_F_NO_CSUM) +	/* don't change ip_summed == CHECKSUM_PARTIAL, as that +	   will cause bad checksum on forwarded packets */ +	if (skb->ip_summed == CHECKSUM_NONE)  		skb->ip_summed = rcv_priv->ip_summed;  	length = skb->len + ETH_HLEN; diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 25a2722c8a9..1d9aed64572 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c @@ -891,7 +891,6 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local,  	SET_ETHTOOL_OPS(dev, &prism2_ethtool_ops); -	netif_stop_queue(dev);  }  static int hostap_enable_hostapd(local_info_t *local, int rtnl_locked) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index db540910b11..0e027f787fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -315,6 +315,7 @@ struct iwl_cfg iwl100_bgn_cfg = {  	.mod_params = &iwlagn_mod_params,  	.base_params = &iwl1000_base_params,  	.ht_params = &iwl1000_ht_params, +	.use_new_eeprom_reading = true,  };  struct iwl_cfg iwl100_bg_cfg = { @@ -330,6 +331,7 @@ struct iwl_cfg iwl100_bg_cfg = {  	.ops = &iwl1000_ops,  	.mod_params = &iwlagn_mod_params,  	.base_params = &iwl1000_base_params, +	.use_new_eeprom_reading = true,  };  MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 11e6532fc57..0ceeaac85ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -561,6 +561,7 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = {  	.ht_params = &iwl6000_ht_params,  	.need_dc_calib = true,  	.need_temp_offset_calib = true, +	.use_new_eeprom_reading = true,  };  struct iwl_cfg iwl6000g2a_2abg_cfg = { @@ -578,6 +579,7 @@ struct iwl_cfg iwl6000g2a_2abg_cfg = {  	.base_params = &iwl6000_base_params,  	.need_dc_calib = true,  	.need_temp_offset_calib = true, +	.use_new_eeprom_reading = true,  };  struct iwl_cfg iwl6000g2a_2bg_cfg = { @@ -595,6 +597,7 @@ struct iwl_cfg iwl6000g2a_2bg_cfg = {  	.base_params = &iwl6000_base_params,  	.need_dc_calib = true,  	.need_temp_offset_calib = true, +	.use_new_eeprom_reading = true,  };  struct iwl_cfg iwl6000g2b_2agn_cfg = { @@ -616,6 +619,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = {  	.need_temp_offset_calib = true,  	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */  	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, +	.use_new_eeprom_reading = true,  };  struct iwl_cfg iwl6000g2b_2abg_cfg = { @@ -636,6 +640,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = {  	.need_temp_offset_calib = true,  	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */  	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, +	.use_new_eeprom_reading = true,  };  struct iwl_cfg iwl6000g2b_2bgn_cfg = { @@ -657,6 +662,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = {  	.need_temp_offset_calib = true,  	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */  	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, +	.use_new_eeprom_reading = true,  };  struct iwl_cfg iwl6000g2b_2bg_cfg = { @@ -677,6 +683,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = {  	.need_temp_offset_calib = true,  	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */  	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, +	.use_new_eeprom_reading = true,  };  struct iwl_cfg iwl6000g2b_bgn_cfg = { @@ -698,6 +705,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = {  	.need_temp_offset_calib = true,  	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */  	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, +	.use_new_eeprom_reading = true,  };  struct iwl_cfg iwl6000g2b_bg_cfg = { @@ -718,6 +726,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = {  	.need_temp_offset_calib = true,  	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */  	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, +	.use_new_eeprom_reading = true,  };  /* @@ -804,6 +813,7 @@ struct iwl_cfg iwl6050g2_bgn_cfg = {  	.base_params = &iwl6050_base_params,  	.ht_params = &iwl6000_ht_params,  	.need_dc_calib = true, +	.use_new_eeprom_reading = true,  };  struct iwl_cfg iwl6050_2abg_cfg = { @@ -857,6 +867,7 @@ struct iwl_cfg iwl130_bgn_cfg = {  	.need_dc_calib = true,  	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */  	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, +	.use_new_eeprom_reading = true,  };  struct iwl_cfg iwl130_bg_cfg = { @@ -876,6 +887,7 @@ struct iwl_cfg iwl130_bg_cfg = {  	.need_dc_calib = true,  	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */  	.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, +	.use_new_eeprom_reading = true,  };  MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c index a650baba080..9eeeda18748 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c @@ -392,7 +392,7 @@ static s8 iwl_update_channel_txpower(struct iwl_priv *priv,  /**   * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info   */ -void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) +static void iwlcore_eeprom_enhanced_txpower_old(struct iwl_priv *priv)  {  	int eeprom_section_count = 0;  	int section, element; @@ -419,7 +419,8 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)  		 * always check for valid entry before process  		 * the information  		 */ -		if (!enhanced_txpower->common || enhanced_txpower->reserved) +		if (!(enhanced_txpower->flags || enhanced_txpower->channel) || +		    enhanced_txpower->delta_20_in_40)  			continue;  		for (element = 0; element < eeprom_section_count; element++) { @@ -452,3 +453,86 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)  		}  	}  } + +static void +iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv, +				    struct iwl_eeprom_enhanced_txpwr *txp, +				    s8 max_txpower_avg) +{ +	int ch_idx; +	bool is_ht40 = txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ; +	enum ieee80211_band band; + +	band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ? +		IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; + +	for (ch_idx = 0; ch_idx < priv->channel_count; ch_idx++) { +		struct iwl_channel_info *ch_info = &priv->channel_info[ch_idx]; + +		/* update matching channel or from common data only */ +		if (txp->channel != 0 && ch_info->channel != txp->channel) +			continue; + +		/* update matching band only */ +		if (band != ch_info->band) +			continue; + +		if (ch_info->max_power_avg < max_txpower_avg && !is_ht40) { +			ch_info->max_power_avg = max_txpower_avg; +			ch_info->curr_txpow = max_txpower_avg; +			ch_info->scan_power = max_txpower_avg; +		} + +		if (is_ht40 && ch_info->ht40_max_power_avg < max_txpower_avg) +			ch_info->ht40_max_power_avg = max_txpower_avg; +	} +} + +#define EEPROM_TXP_OFFS	(0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT) +#define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr) +#define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE) + +static void iwlcore_eeprom_enhanced_txpower_new(struct iwl_priv *priv) +{ +	struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; +	int idx, entries; +	__le16 *txp_len; +	s8 max_txp_avg, max_txp_avg_halfdbm; + +	BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8); + +	/* the length is in 16-bit words, but we want entries */ +	txp_len = (__le16 *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS); +	entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; + +	txp_array = (void *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_OFFS); +	for (idx = 0; idx < entries; idx++) { +		txp = &txp_array[idx]; + +		/* skip invalid entries */ +		if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID)) +			continue; + +		max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx, +						      &max_txp_avg_halfdbm); + +		/* +		 * Update the user limit values values to the highest +		 * power supported by any channel +		 */ +		if (max_txp_avg > priv->tx_power_user_lmt) +			priv->tx_power_user_lmt = max_txp_avg; +		if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm) +			priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm; + +		iwlcore_eeprom_enh_txp_read_element(priv, txp, max_txp_avg); +	} +} + +void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) +{ +	if (priv->cfg->use_new_eeprom_reading) +		iwlcore_eeprom_enhanced_txpower_new(priv); +	else +		iwlcore_eeprom_enhanced_txpower_old(priv); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index b555edd5335..554afb7d967 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -569,6 +569,12 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)  	case INDIRECT_REGULATORY:  		offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY);  		break; +	case INDIRECT_TXP_LIMIT: +		offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT); +		break; +	case INDIRECT_TXP_LIMIT_SIZE: +		offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT_SIZE); +		break;  	case INDIRECT_CALIBRATION:  		offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION);  		break; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 64527def059..954ecc2c34c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -390,6 +390,7 @@ struct iwl_cfg {  	const bool need_temp_offset_calib; /* if used set to true */  	u8 scan_rx_antennas[IEEE80211_NUM_BANDS];  	u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; +	const bool use_new_eeprom_reading; /* temporary, remove later */  };  /*************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index d9b590625ae..e3a279d2d0b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -120,6 +120,17 @@ struct iwl_eeprom_channel {  	s8 max_power_avg;	/* max power (dBm) on this chnl, limit 31 */  } __packed; +enum iwl_eeprom_enhanced_txpwr_flags { +	IWL_EEPROM_ENH_TXP_FL_VALID		= BIT(0), +	IWL_EEPROM_ENH_TXP_FL_BAND_52G		= BIT(1), +	IWL_EEPROM_ENH_TXP_FL_OFDM		= BIT(2), +	IWL_EEPROM_ENH_TXP_FL_40MHZ		= BIT(3), +	IWL_EEPROM_ENH_TXP_FL_HT_AP		= BIT(4), +	IWL_EEPROM_ENH_TXP_FL_RES1		= BIT(5), +	IWL_EEPROM_ENH_TXP_FL_RES2		= BIT(6), +	IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE	= BIT(7), +}; +  /**   * iwl_eeprom_enhanced_txpwr structure   *    This structure presents the enhanced regulatory tx power limit layout @@ -127,21 +138,23 @@ struct iwl_eeprom_channel {   *    Enhanced regulatory tx power portion of eeprom image can be broken down   *    into individual structures; each one is 8 bytes in size and contain the   *    following information - * @common: (desc + channel) not used by driver, should _NOT_ be "zero" + * @flags: entry flags + * @channel: channel number   * @chain_a_max_pwr: chain a max power in 1/2 dBm   * @chain_b_max_pwr: chain b max power in 1/2 dBm   * @chain_c_max_pwr: chain c max power in 1/2 dBm - * @reserved: not used, should be "zero" + * @delta_20_in_40: 20-in-40 deltas (hi/lo)   * @mimo2_max_pwr: mimo2 max power in 1/2 dBm   * @mimo3_max_pwr: mimo3 max power in 1/2 dBm   *   */  struct iwl_eeprom_enhanced_txpwr { -	__le16 common; +	u8 flags; +	u8 channel;  	s8 chain_a_max;  	s8 chain_b_max;  	s8 chain_c_max; -	s8 reserved; +	u8 delta_20_in_40;  	s8 mimo2_max;  	s8 mimo3_max;  } __packed; @@ -186,6 +199,8 @@ struct iwl_eeprom_enhanced_txpwr {  #define EEPROM_LINK_CALIBRATION      (2*0x67)  #define EEPROM_LINK_PROCESS_ADJST    (2*0x68)  #define EEPROM_LINK_OTHERS           (2*0x69) +#define EEPROM_LINK_TXP_LIMIT        (2*0x6a) +#define EEPROM_LINK_TXP_LIMIT_SIZE   (2*0x6b)  /* agn regulatory - indirect access */  #define EEPROM_REG_BAND_1_CHANNELS       ((0x08)\ @@ -389,6 +404,8 @@ struct iwl_eeprom_calib_info {  #define INDIRECT_CALIBRATION        0x00040000  #define INDIRECT_PROCESS_ADJST      0x00050000  #define INDIRECT_OTHERS             0x00060000 +#define INDIRECT_TXP_LIMIT          0x00070000 +#define INDIRECT_TXP_LIMIT_SIZE     0x00080000  #define INDIRECT_ADDRESS            0x00100000  /* General */ diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 373930afc26..113f4f20465 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -619,7 +619,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,  				     print_ssid(ssid_buf, ssid, ssid_len),  				     LBS_SCAN_RSSI_TO_MBM(rssi)/100); -			if (channel || +			if (channel &&  			    !(channel->flags & IEEE80211_CHAN_DISABLED))  				cfg80211_inform_bss(wiphy, channel,  					bssid, le64_to_cpu(*(__le64 *)tsfdesc), diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index d5bc21e5a02..2325e56a9b0 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -43,6 +43,7 @@ MODULE_FIRMWARE("isl3887usb");  static struct usb_device_id p54u_table[] __devinitdata = {  	/* Version 1 devices (pci chip + net2280) */ +	{USB_DEVICE(0x0411, 0x0050)},	/* Buffalo WLI2-USB2-G54 */  	{USB_DEVICE(0x045e, 0x00c2)},	/* Microsoft MN-710 */  	{USB_DEVICE(0x0506, 0x0a11)},	/* 3COM 3CRWE254G72 */  	{USB_DEVICE(0x06b9, 0x0120)},	/* Thomson SpeedTouch 120g */ @@ -56,9 +57,13 @@ static struct usb_device_id p54u_table[] __devinitdata = {  	{USB_DEVICE(0x0846, 0x4220)},	/* Netgear WG111 */  	{USB_DEVICE(0x09aa, 0x1000)},	/* Spinnaker Proto board */  	{USB_DEVICE(0x0cde, 0x0006)},	/* Medion 40900, Roper Europe */ +	{USB_DEVICE(0x0db0, 0x6826)},	/* MSI UB54G (MS-6826) */  	{USB_DEVICE(0x107b, 0x55f2)},	/* Gateway WGU-210 (Gemtek) */  	{USB_DEVICE(0x124a, 0x4023)},	/* Shuttle PN15, Airvast WM168g, IOGear GWU513 */ +	{USB_DEVICE(0x1435, 0x0210)},	/* Inventel UR054G */ +	{USB_DEVICE(0x15a9, 0x0002)},	/* Gemtek WUBI-100GW 802.11g */  	{USB_DEVICE(0x1630, 0x0005)},	/* 2Wire 802.11g USB (v1) / Z-Com */ +	{USB_DEVICE(0x182d, 0x096b)},	/* Sitecom WL-107 */  	{USB_DEVICE(0x1915, 0x2234)},	/* Linksys WUSB54G OEM */  	{USB_DEVICE(0x1915, 0x2235)},	/* Linksys WUSB54G Portable OEM */  	{USB_DEVICE(0x2001, 0x3701)},	/* DLink DWL-G120 Spinnaker */ @@ -94,6 +99,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {  	{USB_DEVICE(0x1435, 0x0427)},	/* Inventel UR054G */  	{USB_DEVICE(0x1668, 0x1050)},	/* Actiontec 802UIG-1 */  	{USB_DEVICE(0x2001, 0x3704)},	/* DLink DWL-G122 rev A2 */ +	{USB_DEVICE(0x2001, 0x3705)},	/* D-Link DWL-G120 rev C1 */  	{USB_DEVICE(0x413c, 0x5513)},	/* Dell WLA3310 USB Wireless Adapter */  	{USB_DEVICE(0x413c, 0x8102)},	/* Spinnaker DUT */  	{USB_DEVICE(0x413c, 0x8104)},	/* Cohiba Proto board */ diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index b2673953598..09a67905c23 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -912,6 +912,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)  	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);  	__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);  	__set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags); +	__set_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags);  	if (!modparam_nohwcrypt)  		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);  	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 94fe589acfa..ab43e7ca2a2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -664,6 +664,7 @@ enum rt2x00_flags {  	DRIVER_REQUIRE_COPY_IV,  	DRIVER_REQUIRE_L2PAD,  	DRIVER_REQUIRE_TXSTATUS_FIFO, +	DRIVER_REQUIRE_TASKLET_CONTEXT,  	/*  	 * Driver features diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 5ba79b935f0..d019830ca84 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -390,9 +390,12 @@ void rt2x00lib_txdone(struct queue_entry *entry,  	 * through a mac80211 library call (RTS/CTS) then we should not  	 * send the status report back.  	 */ -	if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) -		ieee80211_tx_status(rt2x00dev->hw, entry->skb); -	else +	if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) { +		if (test_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags)) +			ieee80211_tx_status(rt2x00dev->hw, entry->skb); +		else +			ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb); +	} else  		dev_kfree_skb_any(entry->skb);  	/* diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index cd1b3dcd61d..ec47e22fa18 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -744,7 +744,7 @@ static int yellowfin_init_ring(struct net_device *dev)  	}  	for (i = 0; i < RX_RING_SIZE; i++) { -		struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz); +		struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz + 2);  		yp->rx_skbuff[i] = skb;  		if (skb == NULL)  			break; @@ -1157,7 +1157,7 @@ static int yellowfin_rx(struct net_device *dev)  	for (; yp->cur_rx - yp->dirty_rx > 0; yp->dirty_rx++) {  		entry = yp->dirty_rx % RX_RING_SIZE;  		if (yp->rx_skbuff[entry] == NULL) { -			struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz); +			struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz + 2);  			if (skb == NULL)  				break;				/* Better luck next round. */  			yp->rx_skbuff[entry] = skb; diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c index c85d3c7421f..f37fbeb66a4 100644 --- a/drivers/of/of_i2c.c +++ b/drivers/of/of_i2c.c @@ -61,7 +61,7 @@ void of_i2c_register_devices(struct i2c_adapter *adap)  		info.of_node = of_node_get(node);  		info.archdata = &dev_ad; -		request_module("%s", info.type); +		request_module("%s%s", I2C_MODULE_PREFIX, info.type);  		result = i2c_new_device(adap, &info);  		if (result == NULL) { diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 003170ea2e3..69546e9213d 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -64,77 +64,6 @@ void pci_bus_remove_resources(struct pci_bus *bus)  	}  } -static bool pci_bus_resource_better(struct resource *res1, bool pos1, -				    struct resource *res2, bool pos2) -{ -	/* If exactly one is positive decode, always prefer that one */ -	if (pos1 != pos2) -		return pos1 ? true : false; - -	/* Prefer the one that contains the highest address */ -	if (res1->end != res2->end) -		return (res1->end > res2->end) ? true : false; - -	/* Otherwise, prefer the one with highest "center of gravity" */ -	if (res1->start != res2->start) -		return (res1->start > res2->start) ? true : false; - -	/* Otherwise, choose one arbitrarily (but consistently) */ -	return (res1 > res2) ? true : false; -} - -static bool pci_bus_resource_positive(struct pci_bus *bus, struct resource *res) -{ -	struct pci_bus_resource *bus_res; - -	/* -	 * This relies on the fact that pci_bus.resource[] refers to P2P or -	 * CardBus bridge base/limit registers, which are always positively -	 * decoded.  The pci_bus.resources list contains host bridge or -	 * subtractively decoded resources. -	 */ -	list_for_each_entry(bus_res, &bus->resources, list) { -		if (bus_res->res == res) -			return (bus_res->flags & PCI_SUBTRACTIVE_DECODE) ? -				false : true; -	} -	return true; -} - -/* - * Find the next-best bus resource after the cursor "res".  If the cursor is - * NULL, return the best resource.  "Best" means that we prefer positive - * decode regions over subtractive decode, then those at higher addresses. - */ -static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus, -						   unsigned int type, -						   struct resource *res) -{ -	bool res_pos, r_pos, prev_pos = false; -	struct resource *r, *prev = NULL; -	int i; - -	res_pos = pci_bus_resource_positive(bus, res); -	pci_bus_for_each_resource(bus, r, i) { -		if (!r) -			continue; - -		if ((r->flags & IORESOURCE_TYPE_BITS) != type) -			continue; - -		r_pos = pci_bus_resource_positive(bus, r); -		if (!res || pci_bus_resource_better(res, res_pos, r, r_pos)) { -			if (!prev || pci_bus_resource_better(r, r_pos, -							     prev, prev_pos)) { -				prev = r; -				prev_pos = r_pos; -			} -		} -	} - -	return prev; -} -  /**   * pci_bus_alloc_resource - allocate a resource from a parent bus   * @bus: PCI bus @@ -160,10 +89,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,  					  resource_size_t),  		void *alignf_data)  { -	int ret = -ENOMEM; +	int i, ret = -ENOMEM;  	struct resource *r;  	resource_size_t max = -1; -	unsigned int type = res->flags & IORESOURCE_TYPE_BITS;  	type_mask |= IORESOURCE_IO | IORESOURCE_MEM; @@ -171,9 +99,10 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,  	if (!(res->flags & IORESOURCE_MEM_64))  		max = PCIBIOS_MAX_MEM_32; -	/* Look for space at highest addresses first */ -	r = pci_bus_find_resource_prev(bus, type, NULL); -	for ( ; r; r = pci_bus_find_resource_prev(bus, type, r)) { +	pci_bus_for_each_resource(bus, r, i) { +		if (!r) +			continue; +  		/* type_mask must match */  		if ((res->flags ^ r->flags) & type_mask)  			continue; diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 0157708d474..09933eb9126 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -1417,6 +1417,11 @@ int __init enable_drhd_fault_handling(void)  			       (unsigned long long)drhd->reg_base_addr, ret);  			return -1;  		} + +		/* +		 * Clear any previous faults. +		 */ +		dmar_fault(iommu->irq, iommu);  	}  	return 0; diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c index 2574700db46..5f7226223a6 100644 --- a/drivers/pci/hotplug/pciehp_acpi.c +++ b/drivers/pci/hotplug/pciehp_acpi.c @@ -115,7 +115,8 @@ static struct pcie_port_service_driver __initdata dummy_driver = {  static int __init select_detection_mode(void)  {  	struct dummy_slot *slot, *tmp; -	pcie_port_service_register(&dummy_driver); +	if (pcie_port_service_register(&dummy_driver)) +		return PCIEHP_DETECT_ACPI;  	pcie_port_service_unregister(&dummy_driver);  	list_for_each_entry_safe(slot, tmp, &dummy_slots, list) {  		list_del(&slot->list); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 6f9350cabbd..53a786fd0d4 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2329,6 +2329,9 @@ static void __devinit nvbridge_check_legacy_irq_routing(struct pci_dev *dev)  {  	u32 cfg; +	if (!pci_find_capability(dev, PCI_CAP_ID_HT)) +		return; +  	pci_read_config_dword(dev, 0x74, &cfg);  	if (cfg & ((1 << 2) | (1 << 15))) { @@ -2764,6 +2767,29 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_m  DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);  #endif /*CONFIG_MMC_RICOH_MMC*/ +#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP) +#define VTUNCERRMSK_REG	0x1ac +#define VTD_MSK_SPEC_ERRORS	(1 << 31) +/* + * This is a quirk for masking vt-d spec defined errors to platform error + * handling logic. With out this, platforms using Intel 7500, 5500 chipsets + * (and the derivative chipsets like X58 etc) seem to generate NMI/SMI (based + * on the RAS config settings of the platform) when a vt-d fault happens. + * The resulting SMI caused the system to hang. + * + * VT-d spec related errors are already handled by the VT-d OS code, so no + * need to report the same error through other channels. + */ +static void vtd_mask_spec_errors(struct pci_dev *dev) +{ +	u32 word; + +	pci_read_config_dword(dev, VTUNCERRMSK_REG, &word); +	pci_write_config_dword(dev, VTUNCERRMSK_REG, word | VTD_MSK_SPEC_ERRORS); +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, vtd_mask_spec_errors); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors); +#endif  static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,  			  struct pci_fixup *end) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index c44a5e8b8b8..f0b3ad13c27 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -75,6 +75,7 @@  #include <drm/i915_drm.h>  #include <asm/msr.h>  #include <asm/processor.h> +#include "intel_ips.h"  #define PCI_DEVICE_ID_INTEL_THERMAL_SENSOR 0x3b32 @@ -245,6 +246,7 @@  #define thm_writel(off, val) writel((val), ips->regmap + (off))  static const int IPS_ADJUST_PERIOD = 5000; /* ms */ +static bool late_i915_load = false;  /* For initial average collection */  static const int IPS_SAMPLE_PERIOD = 200; /* ms */ @@ -339,6 +341,9 @@ struct ips_driver {  	u64 orig_turbo_ratios;  }; +static bool +ips_gpu_turbo_enabled(struct ips_driver *ips); +  /**   * ips_cpu_busy - is CPU busy?   * @ips: IPS driver struct @@ -517,7 +522,7 @@ static void ips_disable_cpu_turbo(struct ips_driver *ips)   */  static bool ips_gpu_busy(struct ips_driver *ips)  { -	if (!ips->gpu_turbo_enabled) +	if (!ips_gpu_turbo_enabled(ips))  		return false;  	return ips->gpu_busy(); @@ -532,7 +537,7 @@ static bool ips_gpu_busy(struct ips_driver *ips)   */  static void ips_gpu_raise(struct ips_driver *ips)  { -	if (!ips->gpu_turbo_enabled) +	if (!ips_gpu_turbo_enabled(ips))  		return;  	if (!ips->gpu_raise()) @@ -549,7 +554,7 @@ static void ips_gpu_raise(struct ips_driver *ips)   */  static void ips_gpu_lower(struct ips_driver *ips)  { -	if (!ips->gpu_turbo_enabled) +	if (!ips_gpu_turbo_enabled(ips))  		return;  	if (!ips->gpu_lower()) @@ -1454,6 +1459,31 @@ out_err:  	return false;  } +static bool +ips_gpu_turbo_enabled(struct ips_driver *ips) +{ +	if (!ips->gpu_busy && late_i915_load) { +		if (ips_get_i915_syms(ips)) { +			dev_info(&ips->dev->dev, +				 "i915 driver attached, reenabling gpu turbo\n"); +			ips->gpu_turbo_enabled = !(thm_readl(THM_HTS) & HTS_GTD_DIS); +		} +	} + +	return ips->gpu_turbo_enabled; +} + +void +ips_link_to_i915_driver() +{ +	/* We can't cleanly get at the various ips_driver structs from +	 * this caller (the i915 driver), so just set a flag saying +	 * that it's time to try getting the symbols again. +	 */ +	late_i915_load = true; +} +EXPORT_SYMBOL_GPL(ips_link_to_i915_driver); +  static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = {  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL,  		     PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), }, diff --git a/drivers/platform/x86/intel_ips.h b/drivers/platform/x86/intel_ips.h new file mode 100644 index 00000000000..73299beff5b --- /dev/null +++ b/drivers/platform/x86/intel_ips.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2010 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + */ + +void ips_link_to_i915_driver(void); diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 90cf0a6ff23..dd14e202c2c 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -207,7 +207,7 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)  static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)  {  	struct rs5c372	*rs5c = i2c_get_clientdata(client); -	unsigned char	buf[8]; +	unsigned char	buf[7];  	int		addr;  	dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index c94502dfac6..045d7e87b63 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -677,7 +677,7 @@ bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,  	bfa_trc(fabric->fcs, event);  	wwn2str(pwwn_ptr, fabric->bport.port_cfg.pwwn); -	BFA_LOG(KERN_INFO, bfad, log_level, +	BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"Port is isolated due to VF_ID mismatch. "  		"PWWN: %s Port VF_ID: %04x switch port VF_ID: %04x.",  		pwwn_ptr, fabric->fcs->port_vfid, @@ -1411,7 +1411,7 @@ bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,  		wwn2str(pwwn_ptr, bfa_fcs_lport_get_pwwn(&fabric->bport));  		wwn2str(fwwn_ptr,  			bfa_fcs_lport_get_fabric_name(&fabric->bport)); -		BFA_LOG(KERN_WARNING, bfad, log_level, +		BFA_LOG(KERN_WARNING, bfad, bfa_log_level,  			"Base port WWN = %s Fabric WWN = %s\n",  			pwwn_ptr, fwwn_ptr);  	} diff --git a/drivers/scsi/bfa/bfa_fcs_fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c index 9662bcdeb41..413b58eef93 100644 --- a/drivers/scsi/bfa/bfa_fcs_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c @@ -261,7 +261,7 @@ bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,  		bfa_fcb_itnim_online(itnim->itnim_drv);  		wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));  		wwn2str(rpwwn_buf, itnim->rport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"Target (WWN = %s) is online for initiator (WWN = %s)\n",  		rpwwn_buf, lpwwn_buf);  		break; @@ -301,11 +301,11 @@ bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,  		wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));  		wwn2str(rpwwn_buf, itnim->rport->pwwn);  		if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE) -			BFA_LOG(KERN_ERR, bfad, log_level, +			BFA_LOG(KERN_ERR, bfad, bfa_log_level,  			"Target (WWN = %s) connectivity lost for "  			"initiator (WWN = %s)\n", rpwwn_buf, lpwwn_buf);  		else -			BFA_LOG(KERN_INFO, bfad, log_level, +			BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Target (WWN = %s) offlined by initiator (WWN = %s)\n",  			rpwwn_buf, lpwwn_buf);  		break; diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 377cbfff6f2..8d651309302 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -491,7 +491,7 @@ bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)  	__port_action[port->fabric->fab_type].online(port);  	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); -	BFA_LOG(KERN_INFO, bfad, log_level, +	BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"Logical port online: WWN = %s Role = %s\n",  		lpwwn_buf, "Initiator"); @@ -512,11 +512,11 @@ bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)  	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));  	if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE) -		BFA_LOG(KERN_ERR, bfad, log_level, +		BFA_LOG(KERN_ERR, bfad, bfa_log_level,  		"Logical port lost fabric connectivity: WWN = %s Role = %s\n",  		lpwwn_buf, "Initiator");  	else -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"Logical port taken offline: WWN = %s Role = %s\n",  		lpwwn_buf, "Initiator"); @@ -573,7 +573,7 @@ bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)  	char    lpwwn_buf[BFA_STRING_32];  	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); -	BFA_LOG(KERN_INFO, bfad, log_level, +	BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"Logical port deleted: WWN = %s Role = %s\n",  		lpwwn_buf, "Initiator"); @@ -878,7 +878,7 @@ bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,  					vport ? vport->vport_drv : NULL);  	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport)); -	BFA_LOG(KERN_INFO, bfad, log_level, +	BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"New logical port created: WWN = %s Role = %s\n",  		lpwwn_buf, "Initiator"); diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index 47f35c0ef29..cf4a6e73e60 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -2056,7 +2056,7 @@ bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)  	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));  	wwn2str(rpwwn_buf, rport->pwwn);  	if (!BFA_FCS_PID_IS_WKA(rport->pid)) -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"Remote port (WWN = %s) online for logical port (WWN = %s)\n",  		rpwwn_buf, lpwwn_buf);  } @@ -2075,12 +2075,12 @@ bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)  	wwn2str(rpwwn_buf, rport->pwwn);  	if (!BFA_FCS_PID_IS_WKA(rport->pid)) {  		if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE) -			BFA_LOG(KERN_ERR, bfad, log_level, +			BFA_LOG(KERN_ERR, bfad, bfa_log_level,  				"Remote port (WWN = %s) connectivity lost for "  				"logical port (WWN = %s)\n",  				rpwwn_buf, lpwwn_buf);  		else -			BFA_LOG(KERN_INFO, bfad, log_level, +			BFA_LOG(KERN_INFO, bfad, bfa_log_level,  				"Remote port (WWN = %s) offlined by "  				"logical port (WWN = %s)\n",  				rpwwn_buf, lpwwn_buf); diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 54475b53a5a..9f4aa391ea9 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -402,7 +402,7 @@ bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)  	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);  	bfa_ioc_hb_monitor(ioc); -	BFA_LOG(KERN_INFO, bfad, log_level, "IOC enabled\n"); +	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC enabled\n");  }  static void @@ -444,7 +444,7 @@ bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)  {  	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;  	bfa_iocpf_disable(ioc); -	BFA_LOG(KERN_INFO, bfad, log_level, "IOC disabled\n"); +	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC disabled\n");  }  /* @@ -565,7 +565,7 @@ bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)  		notify->cbfn(notify->cbarg);  	} -	BFA_LOG(KERN_CRIT, bfad, log_level, +	BFA_LOG(KERN_CRIT, bfad, bfa_log_level,  		"Heart Beat of IOC has failed\n");  } @@ -1812,7 +1812,7 @@ bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)  	 * Provide enable completion callback.  	 */  	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); -	BFA_LOG(KERN_WARNING, bfad, log_level, +	BFA_LOG(KERN_WARNING, bfad, bfa_log_level,  		"Running firmware version is incompatible "  		"with the driver version\n");  } diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index c768143f480..37e16ac8f24 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -2138,7 +2138,7 @@ bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,  		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");  		wwn2str(pwwn_buf, fcport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port disabled: WWN = %s\n", pwwn_buf);  		break; @@ -2198,7 +2198,7 @@ bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,  		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");  		wwn2str(pwwn_buf, fcport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port disabled: WWN = %s\n", pwwn_buf);  		break; @@ -2251,7 +2251,7 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,  		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);  		wwn2str(pwwn_buf, fcport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port online: WWN = %s\n", pwwn_buf);  		break; @@ -2277,7 +2277,7 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,  		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");  		wwn2str(pwwn_buf, fcport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port disabled: WWN = %s\n", pwwn_buf);  		break; @@ -2322,9 +2322,9 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,  		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");  		wwn2str(pwwn_buf, fcport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port offline: WWN = %s\n", pwwn_buf); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port disabled: WWN = %s\n", pwwn_buf);  		break; @@ -2336,10 +2336,10 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,  				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");  		wwn2str(pwwn_buf, fcport->pwwn);  		if (BFA_PORT_IS_DISABLED(fcport->bfa)) -			BFA_LOG(KERN_INFO, bfad, log_level, +			BFA_LOG(KERN_INFO, bfad, bfa_log_level,  				"Base port offline: WWN = %s\n", pwwn_buf);  		else -			BFA_LOG(KERN_ERR, bfad, log_level, +			BFA_LOG(KERN_ERR, bfad, bfa_log_level,  				"Base port (WWN = %s) "  				"lost fabric connectivity\n", pwwn_buf);  		break; @@ -2349,10 +2349,10 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,  		bfa_fcport_reset_linkinfo(fcport);  		wwn2str(pwwn_buf, fcport->pwwn);  		if (BFA_PORT_IS_DISABLED(fcport->bfa)) -			BFA_LOG(KERN_INFO, bfad, log_level, +			BFA_LOG(KERN_INFO, bfad, bfa_log_level,  				"Base port offline: WWN = %s\n", pwwn_buf);  		else -			BFA_LOG(KERN_ERR, bfad, log_level, +			BFA_LOG(KERN_ERR, bfad, bfa_log_level,  				"Base port (WWN = %s) "  				"lost fabric connectivity\n", pwwn_buf);  		break; @@ -2363,10 +2363,10 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,  		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);  		wwn2str(pwwn_buf, fcport->pwwn);  		if (BFA_PORT_IS_DISABLED(fcport->bfa)) -			BFA_LOG(KERN_INFO, bfad, log_level, +			BFA_LOG(KERN_INFO, bfad, bfa_log_level,  				"Base port offline: WWN = %s\n", pwwn_buf);  		else -			BFA_LOG(KERN_ERR, bfad, log_level, +			BFA_LOG(KERN_ERR, bfad, bfa_log_level,  				"Base port (WWN = %s) "  				"lost fabric connectivity\n", pwwn_buf);  		break; @@ -2497,7 +2497,7 @@ bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,  		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");  		wwn2str(pwwn_buf, fcport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port enabled: WWN = %s\n", pwwn_buf);  		break; @@ -2551,7 +2551,7 @@ bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,  		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");  		wwn2str(pwwn_buf, fcport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port enabled: WWN = %s\n", pwwn_buf);  		break; diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 1f938974b84..6797720213b 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -50,7 +50,7 @@ int		reqq_size, rspq_size, num_sgpgs;  int		rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT;  int		bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH;  int		bfa_io_max_sge = BFAD_IO_MAX_SGE; -int		log_level = 3; /* WARNING log level */ +int		bfa_log_level = 3; /* WARNING log level */  int		ioc_auto_recover = BFA_TRUE;  int		bfa_linkup_delay = -1;  int		fdmi_enable = BFA_TRUE; @@ -108,8 +108,8 @@ module_param(bfa_lun_queue_depth, int, S_IRUGO | S_IWUSR);  MODULE_PARM_DESC(bfa_lun_queue_depth, "Lun queue depth, default=32, Range[>0]");  module_param(bfa_io_max_sge, int, S_IRUGO | S_IWUSR);  MODULE_PARM_DESC(bfa_io_max_sge, "Max io scatter/gather elements, default=255"); -module_param(log_level, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(log_level, "Driver log level, default=3, " +module_param(bfa_log_level, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(bfa_log_level, "Driver log level, default=3, "  				"Range[Critical:1|Error:2|Warning:3|Info:4]");  module_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR);  MODULE_PARM_DESC(ioc_auto_recover, "IOC auto recovery, default=1, " @@ -1112,7 +1112,7 @@ bfad_start_ops(struct bfad_s *bfad) {  	} else  		bfad_os_rport_online_wait(bfad); -	BFA_LOG(KERN_INFO, bfad, log_level, "bfa device claimed\n"); +	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "bfa device claimed\n");  	return BFA_STATUS_OK;  } diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index 97f9b6c0937..d5ce2349ac5 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h @@ -337,7 +337,7 @@ extern int	num_sgpgs;  extern int      rport_del_timeout;  extern int      bfa_lun_queue_depth;  extern int      bfa_io_max_sge; -extern int      log_level; +extern int      bfa_log_level;  extern int      ioc_auto_recover;  extern int      bfa_linkup_delay;  extern int      msix_disable_cb; diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 8ca967dee66..fbad5e9b240 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -225,7 +225,8 @@ bfad_im_abort_handler(struct scsi_cmnd *cmnd)  	}  	bfa_trc(bfad, hal_io->iotag); -	BFA_LOG(KERN_INFO, bfad, log_level, "scsi%d: abort cmnd %p iotag %x\n", +	BFA_LOG(KERN_INFO, bfad, bfa_log_level, +		"scsi%d: abort cmnd %p iotag %x\n",  		im_port->shost->host_no, cmnd, hal_io->iotag);  	(void) bfa_ioim_abort(hal_io);  	spin_unlock_irqrestore(&bfad->bfad_lock, flags); @@ -241,7 +242,7 @@ bfad_im_abort_handler(struct scsi_cmnd *cmnd)  	cmnd->scsi_done(cmnd);  	bfa_trc(bfad, hal_io->iotag); -	BFA_LOG(KERN_INFO, bfad, log_level, +	BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"scsi%d: complete abort 0x%p iotag 0x%x\n",  		im_port->shost->host_no, cmnd, hal_io->iotag);  	return SUCCESS; @@ -260,7 +261,7 @@ bfad_im_target_reset_send(struct bfad_s *bfad, struct scsi_cmnd *cmnd,  	tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);  	if (!tskim) { -		BFA_LOG(KERN_ERR, bfad, log_level, +		BFA_LOG(KERN_ERR, bfad, bfa_log_level,  			"target reset, fail to allocate tskim\n");  		rc = BFA_STATUS_FAILED;  		goto out; @@ -311,7 +312,7 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd)  	tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);  	if (!tskim) { -		BFA_LOG(KERN_ERR, bfad, log_level, +		BFA_LOG(KERN_ERR, bfad, bfa_log_level,  				"LUN reset, fail to allocate tskim");  		spin_unlock_irqrestore(&bfad->bfad_lock, flags);  		rc = FAILED; @@ -336,7 +337,7 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd)  	task_status = cmnd->SCp.Status >> 1;  	if (task_status != BFI_TSKIM_STS_OK) { -		BFA_LOG(KERN_ERR, bfad, log_level, +		BFA_LOG(KERN_ERR, bfad, bfa_log_level,  			"LUN reset failure, status: %d\n", task_status);  		rc = FAILED;  	} @@ -380,7 +381,7 @@ bfad_im_reset_bus_handler(struct scsi_cmnd *cmnd)  			task_status = cmnd->SCp.Status >> 1;  			if (task_status != BFI_TSKIM_STS_OK) { -				BFA_LOG(KERN_ERR, bfad, log_level, +				BFA_LOG(KERN_ERR, bfad, bfa_log_level,  					"target reset failure,"  					" status: %d\n", task_status);  				err_cnt++; @@ -460,7 +461,7 @@ bfa_fcb_itnim_free(struct bfad_s *bfad, struct bfad_itnim_s *itnim_drv)  	fcid = bfa_fcs_itnim_get_fcid(&itnim_drv->fcs_itnim);  	wwn2str(wwpn_str, wwpn);  	fcid2str(fcid_str, fcid); -	BFA_LOG(KERN_INFO, bfad, log_level, +	BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"ITNIM FREE scsi%d: FCID: %s WWPN: %s\n",  		port->im_port->shost->host_no,  		fcid_str, wwpn_str); @@ -589,7 +590,7 @@ void  bfad_im_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)  {  	bfa_trc(bfad, bfad->inst_no); -	BFA_LOG(KERN_INFO, bfad, log_level, "Free scsi%d\n", +	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "Free scsi%d\n",  			im_port->shost->host_no);  	fc_remove_host(im_port->shost); @@ -1048,7 +1049,7 @@ bfad_im_itnim_work_handler(struct work_struct *work)  			fcid2str(fcid_str, fcid);  			list_add_tail(&itnim->list_entry,  				&im_port->itnim_mapped_list); -			BFA_LOG(KERN_INFO, bfad, log_level, +			BFA_LOG(KERN_INFO, bfad, bfa_log_level,  				"ITNIM ONLINE Target: %d:0:%d "  				"FCID: %s WWPN: %s\n",  				im_port->shost->host_no, @@ -1081,7 +1082,7 @@ bfad_im_itnim_work_handler(struct work_struct *work)  			wwn2str(wwpn_str, wwpn);  			fcid2str(fcid_str, fcid);  			list_del(&itnim->list_entry); -			BFA_LOG(KERN_INFO, bfad, log_level, +			BFA_LOG(KERN_INFO, bfad, bfa_log_level,  				"ITNIM OFFLINE Target: %d:0:%d "  				"FCID: %s WWPN: %s\n",  				im_port->shost->host_no, diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 5b6bbaea59f..4a3842212c5 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1637,9 +1637,8 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,  	blk_queue_max_segment_size(q, dma_get_max_seg_size(dev)); -	/* New queue, no concurrency on queue_flags */  	if (!shost->use_clustering) -		queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q); +		q->limits.cluster = 0;  	/*  	 * set a reasonable default alignment on word boundaries: the diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c index e5e9e6735f7..9739431092d 100644 --- a/drivers/sh/intc/core.c +++ b/drivers/sh/intc/core.c @@ -198,6 +198,7 @@ int __init register_intc_controller(struct intc_desc *desc)  	list_add_tail(&d->list, &intc_list);  	raw_spin_lock_init(&d->lock); +	INIT_RADIX_TREE(&d->tree, GFP_ATOMIC);  	d->index = nr_intc_controllers; diff --git a/drivers/spi/coldfire_qspi.c b/drivers/spi/coldfire_qspi.c index 052b3c7fa6a..8856bcca9d2 100644 --- a/drivers/spi/coldfire_qspi.c +++ b/drivers/spi/coldfire_qspi.c @@ -317,7 +317,7 @@ static void mcfqspi_work(struct work_struct *work)  		msg = container_of(mcfqspi->msgq.next, struct spi_message,  				   queue); -		list_del_init(&mcfqspi->msgq); +		list_del_init(&msg->queue);  		spin_unlock_irqrestore(&mcfqspi->lock, flags);  		spi = msg->spi; diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c index ec9f0b1bf86..84439f65560 100644 --- a/drivers/spi/mpc52xx_spi.c +++ b/drivers/spi/mpc52xx_spi.c @@ -563,7 +563,7 @@ static struct of_platform_driver mpc52xx_spi_of_driver = {  		.of_match_table = mpc52xx_spi_match,  	},  	.probe = mpc52xx_spi_probe, -	.remove = __exit_p(mpc52xx_spi_remove), +	.remove = __devexit_p(mpc52xx_spi_remove),  };  static int __init mpc52xx_spi_init(void) diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index 2a651e61bfb..951a160fc27 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c @@ -1305,10 +1305,49 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)  /* work with hotplug and coldplug */  MODULE_ALIAS("platform:omap2_mcspi"); +#ifdef	CONFIG_SUSPEND +/* + * When SPI wake up from off-mode, CS is in activate state. If it was in + * unactive state when driver was suspend, then force it to unactive state at + * wake up. + */ +static int omap2_mcspi_resume(struct device *dev) +{ +	struct spi_master	*master = dev_get_drvdata(dev); +	struct omap2_mcspi	*mcspi = spi_master_get_devdata(master); +	struct omap2_mcspi_cs *cs; + +	omap2_mcspi_enable_clocks(mcspi); +	list_for_each_entry(cs, &omap2_mcspi_ctx[master->bus_num - 1].cs, +			    node) { +		if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) { + +			/* +			 * We need to toggle CS state for OMAP take this +			 * change in account. +			 */ +			MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 1); +			__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); +			MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 0); +			__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); +		} +	} +	omap2_mcspi_disable_clocks(mcspi); +	return 0; +} +#else +#define	omap2_mcspi_resume	NULL +#endif + +static const struct dev_pm_ops omap2_mcspi_pm_ops = { +	.resume = omap2_mcspi_resume, +}; +  static struct platform_driver omap2_mcspi_driver = {  	.driver = {  		.name =		"omap2_mcspi",  		.owner =	THIS_MODULE, +		.pm =		&omap2_mcspi_pm_ops  	},  	.remove =	__exit_p(omap2_mcspi_remove),  }; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 709c836607d..b02d0cbce89 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -584,8 +584,7 @@ void spi_unregister_master(struct spi_master *master)  	list_del(&master->list);  	mutex_unlock(&board_lock); -	dummy = device_for_each_child(master->dev.parent, &master->dev, -					__unregister); +	dummy = device_for_each_child(&master->dev, NULL, __unregister);  	device_unregister(&master->dev);  }  EXPORT_SYMBOL_GPL(spi_unregister_master); diff --git a/drivers/spi/spi_fsl_espi.c b/drivers/spi/spi_fsl_espi.c index e3b4f645196..a99e2333b94 100644 --- a/drivers/spi/spi_fsl_espi.c +++ b/drivers/spi/spi_fsl_espi.c @@ -258,18 +258,18 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)  	return mpc8xxx_spi->count;  } -static void fsl_espi_addr2cmd(unsigned int addr, u8 *cmd) +static inline void fsl_espi_addr2cmd(unsigned int addr, u8 *cmd)  { -	if (cmd[1] && cmd[2] && cmd[3]) { +	if (cmd) {  		cmd[1] = (u8)(addr >> 16);  		cmd[2] = (u8)(addr >> 8);  		cmd[3] = (u8)(addr >> 0);  	}  } -static unsigned int fsl_espi_cmd2addr(u8 *cmd) +static inline unsigned int fsl_espi_cmd2addr(u8 *cmd)  { -	if (cmd[1] && cmd[2] && cmd[3]) +	if (cmd)  		return cmd[1] << 16 | cmd[2] << 8 | cmd[3] << 0;  	return 0; @@ -395,9 +395,11 @@ static void fsl_espi_rw_trans(struct spi_message *m,  			}  		} -		addr = fsl_espi_cmd2addr(local_buf); -		addr += pos; -		fsl_espi_addr2cmd(addr, local_buf); +		if (pos > 0) { +			addr = fsl_espi_cmd2addr(local_buf); +			addr += pos; +			fsl_espi_addr2cmd(addr, local_buf); +		}  		espi_trans->n_tx = n_tx;  		espi_trans->n_rx = trans_len; @@ -507,16 +509,29 @@ void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)  	/* We need handle RX first */  	if (events & SPIE_NE) { -		u32 rx_data; +		u32 rx_data, tmp; +		u8 rx_data_8;  		/* Spin until RX is done */  		while (SPIE_RXCNT(events) < min(4, mspi->len)) {  			cpu_relax();  			events = mpc8xxx_spi_read_reg(®_base->event);  		} -		mspi->len -= 4; -		rx_data = mpc8xxx_spi_read_reg(®_base->receive); +		if (mspi->len >= 4) { +			rx_data = mpc8xxx_spi_read_reg(®_base->receive); +		} else { +			tmp = mspi->len; +			rx_data = 0; +			while (tmp--) { +				rx_data_8 = in_8((u8 *)®_base->receive); +				rx_data |= (rx_data_8 << (tmp * 8)); +			} + +			rx_data <<= (4 - mspi->len) * 8; +		} + +		mspi->len -= 4;  		if (mspi->rx)  			mspi->get_rx(rx_data, mspi); diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c index e7f1d5778ce..52389308f33 100644 --- a/drivers/staging/cx25821/cx25821-video.c +++ b/drivers/staging/cx25821/cx25821-video.c @@ -92,7 +92,7 @@ int cx25821_get_format_size(void)  	return ARRAY_SIZE(formats);  } -struct cx25821_fmt *format_by_fourcc(unsigned int fourcc) +struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc)  {  	unsigned int i; @@ -848,7 +848,7 @@ static int video_open(struct file *file)         pix_format =  	   (dev->channels[ch_id].pixel_formats ==  	    PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; -       fh->fmt = format_by_fourcc(pix_format); +       fh->fmt = cx25821_format_by_fourcc(pix_format);         v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio); @@ -1010,7 +1010,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,         if (0 != err)  	       return err; -       fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); +       fh->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);         fh->vidq.field = f->fmt.pix.field;         /* check if width and height is valid based on set standard */ @@ -1119,7 +1119,7 @@ int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fo  	enum v4l2_field field;  	unsigned int maxw, maxh; -	fmt = format_by_fourcc(f->fmt.pix.pixelformat); +	fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);  	if (NULL == fmt)  		return -EINVAL; diff --git a/drivers/staging/cx25821/cx25821-video.h b/drivers/staging/cx25821/cx25821-video.h index cc6034b1a95..a2415d33235 100644 --- a/drivers/staging/cx25821/cx25821-video.h +++ b/drivers/staging/cx25821/cx25821-video.h @@ -87,7 +87,7 @@ extern unsigned int vid_limit;  #define FORMAT_FLAGS_PACKED       0x01  extern struct cx25821_fmt formats[]; -extern struct cx25821_fmt *format_by_fourcc(unsigned int fourcc); +extern struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc);  extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM];  extern void cx25821_dump_video_queue(struct cx25821_dev *dev, diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 8c3c057aa84..d0e9e020753 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -435,12 +435,6 @@ static int zram_make_request(struct request_queue *queue, struct bio *bio)  	int ret = 0;  	struct zram *zram = queue->queuedata; -	if (unlikely(!zram->init_done)) { -		set_bit(BIO_UPTODATE, &bio->bi_flags); -		bio_endio(bio, 0); -		return 0; -	} -  	if (!valid_io_request(zram, bio)) {  		zram_stat64_inc(zram, &zram->stats.invalid_io);  		bio_io_error(bio); diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 81b46585edf..c5f8e5bda2b 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -716,8 +716,8 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)  		if (msg->len < 128)  			*--dp = (msg->len << 1) | EA;  		else { -			*--dp = ((msg->len & 127) << 1) | EA; -			*--dp = (msg->len >> 6) & 0xfe; +			*--dp = (msg->len >> 7);	/* bits 7 - 15 */ +			*--dp = (msg->len & 127) << 1;	/* bits 0 - 6 */  		}  	} @@ -968,6 +968,8 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, u8 *data,  {  	struct gsm_msg *msg;  	msg = gsm_data_alloc(gsm, 0, dlen + 2, gsm->ftype); +	if (msg == NULL) +		return;  	msg->data[0] = (cmd & 0xFE) << 1 | EA;	/* Clear C/R */  	msg->data[1] = (dlen << 1) | EA;  	memcpy(msg->data + 2, data, dlen); diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 44447f54942..99ac70e3255 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -2206,8 +2206,11 @@ static int uea_boot(struct uea_softc *sc)  		goto err1;  	} -	sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm"); -	if (sc->kthread == ERR_PTR(-ENOMEM)) { +	/* Create worker thread, but don't start it here.  Start it after +	 * all usbatm generic initialization is done. +	 */ +	sc->kthread = kthread_create(uea_kthread, sc, "ueagle-atm"); +	if (IS_ERR(sc->kthread)) {  		uea_err(INS_TO_USBDEV(sc), "failed to create thread\n");  		goto err2;  	} @@ -2624,6 +2627,7 @@ static struct usbatm_driver uea_usbatm_driver = {  static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)  {  	struct usb_device *usb = interface_to_usbdev(intf); +	int ret;  	uea_enters(usb);  	uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) Rev (%#X): %s\n", @@ -2637,7 +2641,19 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)  	if (UEA_IS_PREFIRM(id))  		return uea_load_firmware(usb, UEA_CHIP_VERSION(id)); -	return usbatm_usb_probe(intf, id, &uea_usbatm_driver); +	ret = usbatm_usb_probe(intf, id, &uea_usbatm_driver); +	if (ret == 0) { +		struct usbatm_data *usbatm = usb_get_intfdata(intf); +		struct uea_softc *sc = usbatm->driver_data; + +		/* Ensure carrier is initialized to off as early as possible */ +		UPDATE_ATM_SIGNAL(ATM_PHY_SIG_LOST); + +		/* Only start the worker thread when all init is done */ +		wake_up_process(sc->kthread); +	} + +	return ret;  }  static void uea_disconnect(struct usb_interface *intf) diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 9eed5b52d9d..bcc24779ba0 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -107,11 +107,19 @@ config USB_SUSPEND  	  If you are unsure about this, say N here.  config USB_OTG -	bool +	bool "OTG support"  	depends on USB && EXPERIMENTAL  	depends on USB_SUSPEND  	default n +	help +	  The most notable feature of USB OTG is support for a +	  "Dual-Role" device, which can act as either a device +	  or a host. The initial role is decided by the type of +	  plug inserted and can be changed later when two dual +	  role devices talk to each other. +	  Select this only if your board has Mini-AB/Micro-AB +	  connector.  config USB_OTG_WHITELIST  	bool "Rely on OTG Targeted Peripherals List" diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 7b5cc16e4a0..8572dad5ecb 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1047,9 +1047,9 @@ composite_unbind(struct usb_gadget *gadget)  		kfree(cdev->req->buf);  		usb_ep_free_request(gadget->ep0, cdev->req);  	} +	device_remove_file(&gadget->dev, &dev_attr_suspended);  	kfree(cdev);  	set_gadget_data(gadget, NULL); -	device_remove_file(&gadget->dev, &dev_attr_suspended);  	composite = NULL;  } @@ -1107,14 +1107,6 @@ static int composite_bind(struct usb_gadget *gadget)  	 */  	usb_ep_autoconfig_reset(cdev->gadget); -	/* standardized runtime overrides for device ID data */ -	if (idVendor) -		cdev->desc.idVendor = cpu_to_le16(idVendor); -	if (idProduct) -		cdev->desc.idProduct = cpu_to_le16(idProduct); -	if (bcdDevice) -		cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); -  	/* composite gadget needs to assign strings for whole device (like  	 * serial number), register function drivers, potentially update  	 * power state and consumption, etc @@ -1126,6 +1118,14 @@ static int composite_bind(struct usb_gadget *gadget)  	cdev->desc = *composite->dev;  	cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket; +	/* standardized runtime overrides for device ID data */ +	if (idVendor) +		cdev->desc.idVendor = cpu_to_le16(idVendor); +	if (idProduct) +		cdev->desc.idProduct = cpu_to_le16(idProduct); +	if (bcdDevice) +		cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); +  	/* stirng overrides */  	if (iManufacturer || !cdev->desc.iManufacturer) {  		if (!iManufacturer && !composite->iManufacturer && diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 0fae58ef8af..1d0f45f0e7a 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1680,6 +1680,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,  				xhci->port_array[i] = (u8) -1;  			}  			/* FIXME: Should we disable the port? */ +			continue;  		}  		xhci->port_array[i] = major_revision;  		if (major_revision == 0x03) @@ -1758,16 +1759,20 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)  			return -ENOMEM;  		port_index = 0; -		for (i = 0; i < num_ports; i++) -			if (xhci->port_array[i] != 0x03) { -				xhci->usb2_ports[port_index] = -					&xhci->op_regs->port_status_base + -					NUM_PORT_REGS*i; -				xhci_dbg(xhci, "USB 2.0 port at index %u, " -						"addr = %p\n", i, -						xhci->usb2_ports[port_index]); -				port_index++; -			} +		for (i = 0; i < num_ports; i++) { +			if (xhci->port_array[i] == 0x03 || +					xhci->port_array[i] == 0 || +					xhci->port_array[i] == -1) +				continue; + +			xhci->usb2_ports[port_index] = +				&xhci->op_regs->port_status_base + +				NUM_PORT_REGS*i; +			xhci_dbg(xhci, "USB 2.0 port at index %u, " +					"addr = %p\n", i, +					xhci->usb2_ports[port_index]); +			port_index++; +		}  	}  	if (xhci->num_usb3_ports) {  		xhci->usb3_ports = kmalloc(sizeof(*xhci->usb3_ports)* diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 796e2f68f74..4ff21587ab0 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -3,7 +3,7 @@  /*   *	uss720.c  --  USS720 USB Parport Cable.   * - *	Copyright (C) 1999, 2005 + *	Copyright (C) 1999, 2005, 2010   *	    Thomas Sailer (t.sailer@alumni.ethz.ch)   *   *	This program is free software; you can redistribute it and/or modify @@ -776,6 +776,8 @@ static const struct usb_device_id uss720_table[] = {  	{ USB_DEVICE(0x0557, 0x2001) },  	{ USB_DEVICE(0x0729, 0x1284) },  	{ USB_DEVICE(0x1293, 0x0002) }, +	{ USB_DEVICE(0x1293, 0x0002) }, +	{ USB_DEVICE(0x050d, 0x0002) },  	{ }						/* Terminating entry */  }; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 6a50965e23f..2dec5001352 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -796,6 +796,7 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, +	{ USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },  	{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),  		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },  	{ },					/* Optional parameter entry */ diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 1286f1e23d8..bf086728548 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1081,6 +1081,11 @@  #define MJSG_HD_RADIO_PID	0x937C  /* + * D.O.Tec products (http://www.directout.eu) + */ +#define FTDI_DOTEC_PID 0x9868 + +/*   * Xverve Signalyzer tools (http://www.signalyzer.com/)   */  #define XVERVE_SIGNALYZER_ST_PID	0xBCA0 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 6ccdd3dd525..fcc1e32ce25 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -481,6 +481,13 @@ UNUSUAL_DEV(  0x04e8, 0x507c, 0x0220, 0x0220,  		USB_SC_DEVICE, USB_PR_DEVICE, NULL,  		US_FL_MAX_SECTORS_64), +/* Reported by Vitaly Kuznetsov <vitty@altlinux.ru> */ +UNUSUAL_DEV(  0x04e8, 0x5122, 0x0000, 0x9999, +		"Samsung", +		"YP-CP3", +		USB_SC_DEVICE, USB_PR_DEVICE, NULL, +		US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG), +  /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.   * Device uses standards-violating 32-byte Bulk Command Block Wrappers and   * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011. diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c index a4f4546f0be..397d15eb1ea 100644 --- a/drivers/video/backlight/cr_bllcd.c +++ b/drivers/video/backlight/cr_bllcd.c @@ -242,6 +242,7 @@ static int cr_backlight_remove(struct platform_device *pdev)  	backlight_device_unregister(crp->cr_backlight_device);  	lcd_device_unregister(crp->cr_lcd_device);  	pci_dev_put(lpc_dev); +	kfree(crp);  	return 0;  } diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 0e6aa3d96a4..4ac1201ad6c 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1458,7 +1458,7 @@ static bool apertures_overlap(struct aperture *gen, struct aperture *hw)  	if (gen->base == hw->base)  		return true;  	/* is the generic aperture base inside the hw base->hw base+size */ -	if (gen->base > hw->base && gen->base <= hw->base + hw->size) +	if (gen->base > hw->base && gen->base < hw->base + hw->size)  		return true;  	return false;  } diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 5c363d026f6..1ab2c258867 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -53,11 +53,8 @@  #define LCDC_SIZE	0x04  #define SIZE_XMAX(x)	((((x) >> 4) & 0x3f) << 20) -#ifdef CONFIG_ARCH_MX1 -#define SIZE_YMAX(y)	((y) & 0x1ff) -#else -#define SIZE_YMAX(y)	((y) & 0x3ff) -#endif +#define YMAX_MASK       (cpu_is_mx1() ? 0x1ff : 0x3ff) +#define SIZE_YMAX(y)	((y) & YMAX_MASK)  #define LCDC_VPW	0x08  #define VPW_VPW(x)	((x) & 0x3ff) @@ -623,7 +620,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf  	if (var->right_margin > 255)  		printk(KERN_ERR "%s: invalid right_margin %d\n",  			info->fix.id, var->right_margin); -	if (var->yres < 1 || var->yres > 511) +	if (var->yres < 1 || var->yres > YMAX_MASK)  		printk(KERN_ERR "%s: invalid yres %d\n",  			info->fix.id, var->yres);  	if (var->vsync_len > 100) diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 455c6055325..083c8fe53e2 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -1,7 +1,7 @@  config FB_OMAP  	tristate "OMAP frame buffer support (EXPERIMENTAL)" -	depends on FB && ARCH_OMAP && (OMAP2_DSS = "n") - +	depends on FB && (OMAP2_DSS = "n") +	depends on ARCH_OMAP1 || ARCH_OMAP2 || ARCH_OMAP3  	select FB_CFB_FILLRECT  	select FB_CFB_COPYAREA  	select FB_CFB_IMAGEBLIT diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c index 2fd7e5271be..9441e2eb3de 100644 --- a/drivers/video/omap2/vram.c +++ b/drivers/video/omap2/vram.c @@ -551,7 +551,7 @@ void __init omap_vram_reserve_sdram_memblock(void)  	if (!size)  		return; -	size = PAGE_ALIGN(size); +	size = ALIGN(size, SZ_2M);  	if (paddr) {  		if (paddr & ~PAGE_MASK) { @@ -576,7 +576,7 @@ void __init omap_vram_reserve_sdram_memblock(void)  			return;  		}  	} else { -		paddr = memblock_alloc(size, PAGE_SIZE); +		paddr = memblock_alloc(size, SZ_2M);  	}  	memblock_free(paddr, size); diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index d7df10315d8..fcda0e97011 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c @@ -787,6 +787,9 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)  		found_rate_error = rate_error;  	} +	hdmi->var.width = hdmi->monspec.max_x * 10; +	hdmi->var.height = hdmi->monspec.max_y * 10; +  	/*  	 * TODO 1: if no ->info is present, postpone running the config until  	 * after ->info first gets registered. @@ -960,8 +963,12 @@ static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi)  	dev_dbg(info->dev, "Old %ux%u, new %ux%u\n",  		mode1.xres, mode1.yres, mode2.xres, mode2.yres); -	if (fb_mode_is_equal(&mode1, &mode2)) +	if (fb_mode_is_equal(&mode1, &mode2)) { +		/* It can be a different monitor with an equal video-mode */ +		old_var->width = new_var->width; +		old_var->height = new_var->height;  		return false; +	}  	dev_dbg(info->dev, "Switching %u -> %u lines\n",  		mode1.yres, mode2.yres); @@ -1057,8 +1064,11 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)  			 * on, if we run a resume here, the logo disappears  			 */  			if (lock_fb_info(hdmi->info)) { -				sh_hdmi_display_on(hdmi, hdmi->info); -				unlock_fb_info(hdmi->info); +				struct fb_info *info = hdmi->info; +				info->var.width = hdmi->var.width; +				info->var.height = hdmi->var.height; +				sh_hdmi_display_on(hdmi, info); +				unlock_fb_info(info);  			}  		} else {  			/* New monitor or have to wake up */ diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index b02d97a879d..c05326b6123 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -54,8 +54,8 @@ static int lcdc_shared_regs[] = {  };  #define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) -#define DEFAULT_XRES 1280 -#define DEFAULT_YRES 1024 +#define MAX_XRES 1920 +#define MAX_YRES 1080  static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {  	[LDDCKPAT1R] = 0x400, @@ -914,22 +914,12 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in  {  	struct sh_mobile_lcdc_chan *ch = info->par; -	if (var->xres < 160 || var->xres > 1920 || -	    var->yres < 120 || var->yres > 1080 || -	    var->left_margin < 32 || var->left_margin > 320 || -	    var->right_margin < 12 || var->right_margin > 240 || -	    var->upper_margin < 12 || var->upper_margin > 120 || -	    var->lower_margin < 1 || var->lower_margin > 64 || -	    var->hsync_len < 32 || var->hsync_len > 240 || -	    var->vsync_len < 2 || var->vsync_len > 64 || -	    var->pixclock < 6000 || var->pixclock > 40000 || +	if (var->xres > MAX_XRES || var->yres > MAX_YRES ||  	    var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) { -		dev_warn(info->dev, "Invalid info: %u %u %u %u %u %u %u %u %u!\n", -			 var->xres, var->yres, -			 var->left_margin, var->right_margin, -			 var->upper_margin, var->lower_margin, -			 var->hsync_len, var->vsync_len, -			 var->pixclock); +		dev_warn(info->dev, "Invalid info: %u-%u-%u-%u x %u-%u-%u-%u @ %ukHz!\n", +			 var->left_margin, var->xres, var->right_margin, var->hsync_len, +			 var->upper_margin, var->yres, var->lower_margin, var->vsync_len, +			 PICOS2KHZ(var->pixclock));  		return -EINVAL;  	}  	return 0; @@ -1226,7 +1216,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)  		}  		if (!mode) -			max_size = DEFAULT_XRES * DEFAULT_YRES; +			max_size = MAX_XRES * MAX_YRES;  		else if (max_cfg)  			dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n",  				max_cfg->xres, max_cfg->yres); @@ -1238,12 +1228,14 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)  			mode = &default_720p;  			num_cfg = 1;  		} else { -			num_cfg = ch->cfg.num_cfg; +			num_cfg = cfg->num_cfg;  		}  		fb_videomode_to_modelist(mode, num_cfg, &info->modelist);  		fb_videomode_to_var(var, mode); +		var->width = cfg->lcd_size_cfg.width; +		var->height = cfg->lcd_size_cfg.height;  		/* Default Y virtual resolution is 2x panel size */  		var->yres_virtual = var->yres * 2;  		var->activate = FB_ACTIVATE_NOW; diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c index 428f8a1583e..3939e53f5f9 100644 --- a/drivers/watchdog/rdc321x_wdt.c +++ b/drivers/watchdog/rdc321x_wdt.c @@ -231,7 +231,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)  	struct resource *r;  	struct rdc321x_wdt_pdata *pdata; -	pdata = pdev->dev.platform_data; +	pdata = platform_get_drvdata(pdev);  	if (!pdata) {  		dev_err(&pdev->dev, "no platform data supplied\n");  		return -ENODEV; diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c index 6f044447359..659f532d26a 100644 --- a/fs/btrfs/export.c +++ b/fs/btrfs/export.c @@ -166,7 +166,7 @@ static struct dentry *btrfs_fh_to_dentry(struct super_block *sb, struct fid *fh,  static struct dentry *btrfs_get_parent(struct dentry *child)  {  	struct inode *dir = child->d_inode; -	static struct dentry *dentry; +	struct dentry *dentry;  	struct btrfs_root *root = BTRFS_I(dir)->root;  	struct btrfs_path *path;  	struct extent_buffer *leaf; diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 158c700fdca..d902948a90d 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -40,7 +40,8 @@ int ceph_init_dentry(struct dentry *dentry)  	if (dentry->d_fsdata)  		return 0; -	if (ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP) +	if (dentry->d_parent == NULL ||   /* nfs fh_to_dentry */ +	    ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)  		dentry->d_op = &ceph_dentry_ops;  	else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)  		dentry->d_op = &ceph_snapdir_dentry_ops; diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 8d79b8912e3..7d0e4a82d89 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -282,7 +282,8 @@ int ceph_release(struct inode *inode, struct file *file)  static int striped_read(struct inode *inode,  			u64 off, u64 len,  			struct page **pages, int num_pages, -			int *checkeof, bool align_to_pages) +			int *checkeof, bool align_to_pages, +			unsigned long buf_align)  {  	struct ceph_fs_client *fsc = ceph_inode_to_client(inode);  	struct ceph_inode_info *ci = ceph_inode(inode); @@ -307,7 +308,7 @@ static int striped_read(struct inode *inode,  more:  	if (align_to_pages) -		page_align = (pos - io_align) & ~PAGE_MASK; +		page_align = (pos - io_align + buf_align) & ~PAGE_MASK;  	else  		page_align = pos & ~PAGE_MASK;  	this_len = left; @@ -376,16 +377,18 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,  	struct inode *inode = file->f_dentry->d_inode;  	struct page **pages;  	u64 off = *poff; -	int num_pages = calc_pages_for(off, len); -	int ret; +	int num_pages, ret;  	dout("sync_read on file %p %llu~%u %s\n", file, off, len,  	     (file->f_flags & O_DIRECT) ? "O_DIRECT" : ""); -	if (file->f_flags & O_DIRECT) -		pages = ceph_get_direct_page_vector(data, num_pages); -	else +	if (file->f_flags & O_DIRECT) { +		num_pages = calc_pages_for((unsigned long)data, len); +		pages = ceph_get_direct_page_vector(data, num_pages, true); +	} else { +		num_pages = calc_pages_for(off, len);  		pages = ceph_alloc_page_vector(num_pages, GFP_NOFS); +	}  	if (IS_ERR(pages))  		return PTR_ERR(pages); @@ -400,7 +403,8 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,  		goto done;  	ret = striped_read(inode, off, len, pages, num_pages, checkeof, -			   file->f_flags & O_DIRECT); +			   file->f_flags & O_DIRECT, +			   (unsigned long)data & ~PAGE_MASK);  	if (ret >= 0 && (file->f_flags & O_DIRECT) == 0)  		ret = ceph_copy_page_vector_to_user(pages, data, off, ret); @@ -409,7 +413,7 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,  done:  	if (file->f_flags & O_DIRECT) -		ceph_put_page_vector(pages, num_pages); +		ceph_put_page_vector(pages, num_pages, true);  	else  		ceph_release_page_vector(pages, num_pages);  	dout("sync_read result %d\n", ret); @@ -456,6 +460,7 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,  	int do_sync = 0;  	int check_caps = 0;  	int page_align, io_align; +	unsigned long buf_align;  	int ret;  	struct timespec mtime = CURRENT_TIME; @@ -471,6 +476,7 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,  		pos = *offset;  	io_align = pos & ~PAGE_MASK; +	buf_align = (unsigned long)data & ~PAGE_MASK;  	ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left);  	if (ret < 0) @@ -496,12 +502,15 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,  	 */  more:  	len = left; -	if (file->f_flags & O_DIRECT) +	if (file->f_flags & O_DIRECT) {  		/* write from beginning of first page, regardless of  		   io alignment */ -		page_align = (pos - io_align) & ~PAGE_MASK; -	else +		page_align = (pos - io_align + buf_align) & ~PAGE_MASK; +		num_pages = calc_pages_for((unsigned long)data, len); +	} else {  		page_align = pos & ~PAGE_MASK; +		num_pages = calc_pages_for(pos, len); +	}  	req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,  				    ceph_vino(inode), pos, &len,  				    CEPH_OSD_OP_WRITE, flags, @@ -512,10 +521,8 @@ more:  	if (!req)  		return -ENOMEM; -	num_pages = calc_pages_for(pos, len); -  	if (file->f_flags & O_DIRECT) { -		pages = ceph_get_direct_page_vector(data, num_pages); +		pages = ceph_get_direct_page_vector(data, num_pages, false);  		if (IS_ERR(pages)) {  			ret = PTR_ERR(pages);  			goto out; @@ -565,7 +572,7 @@ more:  	}  	if (file->f_flags & O_DIRECT) -		ceph_put_page_vector(pages, num_pages); +		ceph_put_page_vector(pages, num_pages, false);  	else if (file->f_flags & O_SYNC)  		ceph_release_page_vector(pages, num_pages); diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index dc963929de6..981c8477ada 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -232,6 +232,8 @@ static int setup_new_group_blocks(struct super_block *sb,  			       GFP_NOFS);  	if (err)  		goto exit_bh; +	for (i = 0, bit = gdblocks + 1; i < reserved_gdb; i++, bit++) +		ext4_set_bit(bit, bh->b_data);  	ext4_debug("mark block bitmap %#04llx (+%llu)\n", input->block_bitmap,  		   input->block_bitmap - start); @@ -247,6 +249,9 @@ static int setup_new_group_blocks(struct super_block *sb,  	err = sb_issue_zeroout(sb, block, sbi->s_itb_per_group, GFP_NOFS);  	if (err)  		goto exit_bh; +	for (i = 0, bit = input->inode_table - start; +	     i < sbi->s_itb_per_group; i++, bit++) +		ext4_set_bit(bit, bh->b_data);  	if ((err = extend_or_restart_transaction(handle, 2, bh)))  		goto exit_bh; diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c index f46ee8b0e13..9da29706f91 100644 --- a/fs/logfs/journal.c +++ b/fs/logfs/journal.c @@ -828,7 +828,7 @@ void do_logfs_journal_wl_pass(struct super_block *sb)  		super->s_journal_seg[i] = segno;  		super->s_journal_ec[i] = ec;  		logfs_set_segment_reserved(sb, segno); -		err = btree_insert32(head, segno, (void *)1, GFP_KERNEL); +		err = btree_insert32(head, segno, (void *)1, GFP_NOFS);  		BUG_ON(err); /* mempool should prevent this */  		err = logfs_erase_segment(sb, segno, 1);  		BUG_ON(err); /* FIXME: remount-ro would be nicer */ diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index 6127baf0e18..ee99a9f5dfd 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c @@ -1994,6 +1994,9 @@ static int do_write_inode(struct inode *inode)  	/* FIXME: transaction is part of logfs_block now.  Is that enough? */  	err = logfs_write_buf(master_inode, page, 0); +	if (err) +		move_page_to_inode(inode, page); +  	logfs_put_write_page(page);  	return err;  } diff --git a/fs/namei.c b/fs/namei.c index 5362af9b737..4ff7ca53053 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1748,6 +1748,9 @@ struct file *do_filp_open(int dfd, const char *pathname,  	if (!(open_flag & O_CREAT))  		mode = 0; +	/* Must never be set by userspace */ +	open_flag &= ~FMODE_NONOTIFY; +  	/*  	 * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only  	 * check for O_DSYNC if the need any syncing at all we enforce it's diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c index 33ad25ddd5c..caf9a6a3fb5 100644 --- a/fs/nilfs2/gcinode.c +++ b/fs/nilfs2/gcinode.c @@ -176,7 +176,6 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh)  int nilfs_init_gcinode(struct inode *inode)  {  	struct nilfs_inode_info *ii = NILFS_I(inode); -	struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;  	inode->i_mode = S_IFREG;  	mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); @@ -186,14 +185,6 @@ int nilfs_init_gcinode(struct inode *inode)  	ii->i_flags = 0;  	nilfs_bmap_init_gc(ii->i_bmap); -	/* -	 * Add the inode to GC inode list. Garbage Collection -	 * is serialized and no two processes manipulate the -	 * list simultaneously. -	 */ -	igrab(inode); -	list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes); -  	return 0;  } diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index e00d9457c25..b185e937a33 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -337,6 +337,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,  				   struct nilfs_argv *argv, void *buf)  {  	size_t nmembs = argv->v_nmembs; +	struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;  	struct inode *inode;  	struct nilfs_vdesc *vdesc;  	struct buffer_head *bh, *n; @@ -353,6 +354,17 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,  			ret = PTR_ERR(inode);  			goto failed;  		} +		if (list_empty(&NILFS_I(inode)->i_dirty)) { +			/* +			 * Add the inode to GC inode list. Garbage Collection +			 * is serialized and no two processes manipulate the +			 * list simultaneously. +			 */ +			igrab(inode); +			list_add(&NILFS_I(inode)->i_dirty, +				 &nilfs->ns_gc_inodes); +		} +  		do {  			ret = nilfs_ioctl_move_inode_block(inode, vdesc,  							   &buffers); diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index b04f88eed09..f35794b97e8 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -92,7 +92,11 @@ static int fanotify_get_response_from_access(struct fsnotify_group *group,  	pr_debug("%s: group=%p event=%p\n", __func__, group, event); -	wait_event(group->fanotify_data.access_waitq, event->response); +	wait_event(group->fanotify_data.access_waitq, event->response || +				atomic_read(&group->fanotify_data.bypass_perm)); + +	if (!event->response) /* bypass_perm set */ +		return 0;  	/* userspace responded, convert to something usable */  	spin_lock(&event->lock); diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 063224812b7..8b61220cffc 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -106,20 +106,29 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)  	return client_fd;  } -static ssize_t fill_event_metadata(struct fsnotify_group *group, +static int fill_event_metadata(struct fsnotify_group *group,  				   struct fanotify_event_metadata *metadata,  				   struct fsnotify_event *event)  { +	int ret = 0; +  	pr_debug("%s: group=%p metadata=%p event=%p\n", __func__,  		 group, metadata, event);  	metadata->event_len = FAN_EVENT_METADATA_LEN; +	metadata->metadata_len = FAN_EVENT_METADATA_LEN;  	metadata->vers = FANOTIFY_METADATA_VERSION;  	metadata->mask = event->mask & FAN_ALL_OUTGOING_EVENTS;  	metadata->pid = pid_vnr(event->tgid); -	metadata->fd = create_fd(group, event); +	if (unlikely(event->mask & FAN_Q_OVERFLOW)) +		metadata->fd = FAN_NOFD; +	else { +		metadata->fd = create_fd(group, event); +		if (metadata->fd < 0) +			ret = metadata->fd; +	} -	return metadata->fd; +	return ret;  }  #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS @@ -200,7 +209,7 @@ static int prepare_for_access_response(struct fsnotify_group *group,  	mutex_lock(&group->fanotify_data.access_mutex); -	if (group->fanotify_data.bypass_perm) { +	if (atomic_read(&group->fanotify_data.bypass_perm)) {  		mutex_unlock(&group->fanotify_data.access_mutex);  		kmem_cache_free(fanotify_response_event_cache, re);  		event->response = FAN_ALLOW; @@ -257,24 +266,34 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,  	pr_debug("%s: group=%p event=%p\n", __func__, group, event); -	fd = fill_event_metadata(group, &fanotify_event_metadata, event); -	if (fd < 0) -		return fd; +	ret = fill_event_metadata(group, &fanotify_event_metadata, event); +	if (ret < 0) +		goto out; +	fd = fanotify_event_metadata.fd;  	ret = prepare_for_access_response(group, event, fd);  	if (ret)  		goto out_close_fd;  	ret = -EFAULT; -	if (copy_to_user(buf, &fanotify_event_metadata, FAN_EVENT_METADATA_LEN)) +	if (copy_to_user(buf, &fanotify_event_metadata, +			 fanotify_event_metadata.event_len))  		goto out_kill_access_response; -	return FAN_EVENT_METADATA_LEN; +	return fanotify_event_metadata.event_len;  out_kill_access_response:  	remove_access_response(group, event, fd);  out_close_fd: -	sys_close(fd); +	if (fd != FAN_NOFD) +		sys_close(fd); +out: +#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS +	if (event->mask & FAN_ALL_PERM_EVENTS) { +		event->response = FAN_DENY; +		wake_up(&group->fanotify_data.access_waitq); +	} +#endif  	return ret;  } @@ -382,7 +401,7 @@ static int fanotify_release(struct inode *ignored, struct file *file)  	mutex_lock(&group->fanotify_data.access_mutex); -	group->fanotify_data.bypass_perm = true; +	atomic_inc(&group->fanotify_data.bypass_perm);  	list_for_each_entry_safe(re, lre, &group->fanotify_data.access_list, list) {  		pr_debug("%s: found group=%p re=%p event=%p\n", __func__, group, @@ -586,11 +605,10 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,  {  	struct fsnotify_mark *fsn_mark;  	__u32 added; +	int ret = 0;  	fsn_mark = fsnotify_find_vfsmount_mark(group, mnt);  	if (!fsn_mark) { -		int ret; -  		if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)  			return -ENOSPC; @@ -600,17 +618,16 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,  		fsnotify_init_mark(fsn_mark, fanotify_free_mark);  		ret = fsnotify_add_mark(fsn_mark, group, NULL, mnt, 0); -		if (ret) { -			fanotify_free_mark(fsn_mark); -			return ret; -		} +		if (ret) +			goto err;  	}  	added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); -	fsnotify_put_mark(fsn_mark); +  	if (added & ~mnt->mnt_fsnotify_mask)  		fsnotify_recalc_vfsmount_mask(mnt); - -	return 0; +err: +	fsnotify_put_mark(fsn_mark); +	return ret;  }  static int fanotify_add_inode_mark(struct fsnotify_group *group, @@ -619,6 +636,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,  {  	struct fsnotify_mark *fsn_mark;  	__u32 added; +	int ret = 0;  	pr_debug("%s: group=%p inode=%p\n", __func__, group, inode); @@ -634,8 +652,6 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,  	fsn_mark = fsnotify_find_inode_mark(group, inode);  	if (!fsn_mark) { -		int ret; -  		if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)  			return -ENOSPC; @@ -645,16 +661,16 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,  		fsnotify_init_mark(fsn_mark, fanotify_free_mark);  		ret = fsnotify_add_mark(fsn_mark, group, inode, NULL, 0); -		if (ret) { -			fanotify_free_mark(fsn_mark); -			return ret; -		} +		if (ret) +			goto err;  	}  	added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); -	fsnotify_put_mark(fsn_mark); +  	if (added & ~inode->i_fsnotify_mask)  		fsnotify_recalc_inode_mask(inode); -	return 0; +err: +	fsnotify_put_mark(fsn_mark); +	return ret;  }  /* fanotify syscalls */ @@ -687,8 +703,10 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)  	/* fsnotify_alloc_group takes a ref.  Dropped in fanotify_release */  	group = fsnotify_alloc_group(&fanotify_fsnotify_ops); -	if (IS_ERR(group)) +	if (IS_ERR(group)) { +		free_uid(user);  		return PTR_ERR(group); +	}  	group->fanotify_data.user = user;  	atomic_inc(&user->fanotify_listeners); @@ -698,6 +716,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)  	mutex_init(&group->fanotify_data.access_mutex);  	init_waitqueue_head(&group->fanotify_data.access_waitq);  	INIT_LIST_HEAD(&group->fanotify_data.access_list); +	atomic_set(&group->fanotify_data.bypass_perm, 0);  #endif  	switch (flags & FAN_ALL_CLASS_BITS) {  	case FAN_CLASS_NOTIF: @@ -764,8 +783,10 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,  	if (flags & ~FAN_ALL_MARK_FLAGS)  		return -EINVAL;  	switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) { -	case FAN_MARK_ADD: +	case FAN_MARK_ADD:		/* fallthrough */  	case FAN_MARK_REMOVE: +		if (!mask) +			return -EINVAL;  	case FAN_MARK_FLUSH:  		break;  	default: diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 444c305a468..4cd5d5d78f9 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -752,6 +752,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)  	if (ret >= 0)  		return ret; +	fsnotify_put_group(group);  	atomic_dec(&user->inotify_devs);  out_free_uid:  	free_uid(user); diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index f1e962cb3b7..0d7c5540ad6 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -573,11 +573,14 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,  	/* this io's submitter should not have unlocked this before we could */  	BUG_ON(!ocfs2_iocb_is_rw_locked(iocb)); +	if (ocfs2_iocb_is_sem_locked(iocb)) { +		up_read(&inode->i_alloc_sem); +		ocfs2_iocb_clear_sem_locked(iocb); +	} +  	ocfs2_iocb_clear_rw_locked(iocb);  	level = ocfs2_iocb_rw_locked_level(iocb); -	if (!level) -		up_read(&inode->i_alloc_sem);  	ocfs2_rw_unlock(inode, level);  	if (is_async) diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h index 76bfdfda691..eceb456037c 100644 --- a/fs/ocfs2/aops.h +++ b/fs/ocfs2/aops.h @@ -68,8 +68,27 @@ static inline void ocfs2_iocb_set_rw_locked(struct kiocb *iocb, int level)  	else  		clear_bit(1, (unsigned long *)&iocb->private);  } + +/* + * Using a named enum representing lock types in terms of #N bit stored in + * iocb->private, which is going to be used for communication bewteen + * ocfs2_dio_end_io() and ocfs2_file_aio_write/read(). + */ +enum ocfs2_iocb_lock_bits { +	OCFS2_IOCB_RW_LOCK = 0, +	OCFS2_IOCB_RW_LOCK_LEVEL, +	OCFS2_IOCB_SEM, +	OCFS2_IOCB_NUM_LOCKS +}; +  #define ocfs2_iocb_clear_rw_locked(iocb) \ -	clear_bit(0, (unsigned long *)&iocb->private) +	clear_bit(OCFS2_IOCB_RW_LOCK, (unsigned long *)&iocb->private)  #define ocfs2_iocb_rw_locked_level(iocb) \ -	test_bit(1, (unsigned long *)&iocb->private) +	test_bit(OCFS2_IOCB_RW_LOCK_LEVEL, (unsigned long *)&iocb->private) +#define ocfs2_iocb_set_sem_locked(iocb) \ +	set_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private) +#define ocfs2_iocb_clear_sem_locked(iocb) \ +	clear_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private) +#define ocfs2_iocb_is_sem_locked(iocb) \ +	test_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private)  #endif /* OCFS2_FILE_H */ diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index c7fba396392..6c61771469a 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -113,10 +113,11 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {  	define_mask(QUOTA),  	define_mask(REFCOUNT),  	define_mask(BASTS), +	define_mask(RESERVATIONS), +	define_mask(CLUSTER),  	define_mask(ERROR),  	define_mask(NOTICE),  	define_mask(KTHREAD), -	define_mask(RESERVATIONS),  };  static struct attribute *mlog_attr_ptrs[MLOG_MAX_BITS] = {NULL, }; diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index ea2ed9f56c9..34d6544357d 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -81,7 +81,7 @@  #include <linux/sched.h>  /* bits that are frequently given and infrequently matched in the low word */ -/* NOTE: If you add a flag, you need to also update mlog.c! */ +/* NOTE: If you add a flag, you need to also update masklog.c! */  #define ML_ENTRY	0x0000000000000001ULL /* func call entry */  #define ML_EXIT		0x0000000000000002ULL /* func call exit */  #define ML_TCP		0x0000000000000004ULL /* net cluster/tcp.c */ @@ -114,13 +114,14 @@  #define ML_XATTR	0x0000000020000000ULL /* ocfs2 extended attributes */  #define ML_QUOTA	0x0000000040000000ULL /* ocfs2 quota operations */  #define ML_REFCOUNT	0x0000000080000000ULL /* refcount tree operations */ -#define ML_BASTS	0x0000001000000000ULL /* dlmglue asts and basts */ +#define ML_BASTS	0x0000000100000000ULL /* dlmglue asts and basts */ +#define ML_RESERVATIONS	0x0000000200000000ULL /* ocfs2 alloc reservations */ +#define ML_CLUSTER	0x0000000400000000ULL /* cluster stack */ +  /* bits that are infrequently given and frequently matched in the high word */ -#define ML_ERROR	0x0000000100000000ULL /* sent to KERN_ERR */ -#define ML_NOTICE	0x0000000200000000ULL /* setn to KERN_NOTICE */ -#define ML_KTHREAD	0x0000000400000000ULL /* kernel thread activity */ -#define ML_RESERVATIONS	0x0000000800000000ULL /* ocfs2 alloc reservations */ -#define ML_CLUSTER	0x0000001000000000ULL /* cluster stack */ +#define ML_ERROR	0x1000000000000000ULL /* sent to KERN_ERR */ +#define ML_NOTICE	0x2000000000000000ULL /* setn to KERN_NOTICE */ +#define ML_KTHREAD	0x4000000000000000ULL /* kernel thread activity */  #define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE)  #define MLOG_INITIAL_NOT_MASK (ML_ENTRY|ML_EXIT) diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index c49f6de0e7a..d417b3f9b0c 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -2461,8 +2461,10 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,  	di->i_dx_root = cpu_to_le64(dr_blkno); +	spin_lock(&OCFS2_I(dir)->ip_lock);  	OCFS2_I(dir)->ip_dyn_features |= OCFS2_INDEXED_DIR_FL;  	di->i_dyn_features = cpu_to_le16(OCFS2_I(dir)->ip_dyn_features); +	spin_unlock(&OCFS2_I(dir)->ip_lock);  	ocfs2_journal_dirty(handle, di_bh); @@ -4466,8 +4468,10 @@ static int ocfs2_dx_dir_remove_index(struct inode *dir,  		goto out_commit;  	} +	spin_lock(&OCFS2_I(dir)->ip_lock);  	OCFS2_I(dir)->ip_dyn_features &= ~OCFS2_INDEXED_DIR_FL;  	di->i_dyn_features = cpu_to_le16(OCFS2_I(dir)->ip_dyn_features); +	spin_unlock(&OCFS2_I(dir)->ip_lock);  	di->i_dx_root = cpu_to_le64(0ULL);  	ocfs2_journal_dirty(handle, di_bh); diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index f564b0e5f80..59f0f6bdfc6 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -2346,7 +2346,8 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data)   */  static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,  				      struct dlm_lock_resource *res, -				      int *numlocks) +				      int *numlocks, +				      int *hasrefs)  {  	int ret;  	int i; @@ -2356,6 +2357,9 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,  	assert_spin_locked(&res->spinlock); +	*numlocks = 0; +	*hasrefs = 0; +  	ret = -EINVAL;  	if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {  		mlog(0, "cannot migrate lockres with unknown owner!\n"); @@ -2386,7 +2390,13 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,  	}  	*numlocks = count; -	mlog(0, "migrateable lockres having %d locks\n", *numlocks); + +	count = find_next_bit(res->refmap, O2NM_MAX_NODES, 0); +	if (count < O2NM_MAX_NODES) +		*hasrefs = 1; + +	mlog(0, "%s: res %.*s, Migrateable, locks %d, refs %d\n", dlm->name, +	     res->lockname.len, res->lockname.name, *numlocks, *hasrefs);  leave:  	return ret; @@ -2408,7 +2418,7 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,  	const char *name;  	unsigned int namelen;  	int mle_added = 0; -	int numlocks; +	int numlocks, hasrefs;  	int wake = 0;  	if (!dlm_grab(dlm)) @@ -2417,13 +2427,13 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,  	name = res->lockname.name;  	namelen = res->lockname.len; -	mlog(0, "migrating %.*s to %u\n", namelen, name, target); +	mlog(0, "%s: Migrating %.*s to %u\n", dlm->name, namelen, name, target);  	/*  	 * ensure this lockres is a proper candidate for migration  	 */  	spin_lock(&res->spinlock); -	ret = dlm_is_lockres_migrateable(dlm, res, &numlocks); +	ret = dlm_is_lockres_migrateable(dlm, res, &numlocks, &hasrefs);  	if (ret < 0) {  		spin_unlock(&res->spinlock);  		goto leave; @@ -2431,10 +2441,8 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,  	spin_unlock(&res->spinlock);  	/* no work to do */ -	if (numlocks == 0) { -		mlog(0, "no locks were found on this lockres! done!\n"); +	if (numlocks == 0 && !hasrefs)  		goto leave; -	}  	/*  	 * preallocate up front @@ -2459,14 +2467,14 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,  	 * find a node to migrate the lockres to  	 */ -	mlog(0, "picking a migration node\n");  	spin_lock(&dlm->spinlock);  	/* pick a new node */  	if (!test_bit(target, dlm->domain_map) ||  	    target >= O2NM_MAX_NODES) {  		target = dlm_pick_migration_target(dlm, res);  	} -	mlog(0, "node %u chosen for migration\n", target); +	mlog(0, "%s: res %.*s, Node %u chosen for migration\n", dlm->name, +	     namelen, name, target);  	if (target >= O2NM_MAX_NODES ||  	    !test_bit(target, dlm->domain_map)) { @@ -2667,7 +2675,7 @@ int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)  {  	int ret;  	int lock_dropped = 0; -	int numlocks; +	int numlocks, hasrefs;  	spin_lock(&res->spinlock);  	if (res->owner != dlm->node_num) { @@ -2681,8 +2689,8 @@ int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)  	}  	/* No need to migrate a lockres having no locks */ -	ret = dlm_is_lockres_migrateable(dlm, res, &numlocks); -	if (ret >= 0 && numlocks == 0) { +	ret = dlm_is_lockres_migrateable(dlm, res, &numlocks, &hasrefs); +	if (ret >= 0 && numlocks == 0 && !hasrefs) {  		spin_unlock(&res->spinlock);  		goto leave;  	} @@ -2915,6 +2923,12 @@ static u8 dlm_pick_migration_target(struct dlm_ctxt *dlm,  		}  		queue++;  	} + +	nodenum = find_next_bit(res->refmap, O2NM_MAX_NODES, 0); +	if (nodenum < O2NM_MAX_NODES) { +		spin_unlock(&res->spinlock); +		return nodenum; +	}  	spin_unlock(&res->spinlock);  	mlog(0, "have not found a suitable target yet! checking domain map\n"); diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 77b4c04a280..f6cba566429 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -2241,11 +2241,15 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,  	mutex_lock(&inode->i_mutex); +	ocfs2_iocb_clear_sem_locked(iocb); +  relock:  	/* to match setattr's i_mutex -> i_alloc_sem -> rw_lock ordering */  	if (direct_io) {  		down_read(&inode->i_alloc_sem);  		have_alloc_sem = 1; +		/* communicate with ocfs2_dio_end_io */ +		ocfs2_iocb_set_sem_locked(iocb);  	}  	/* @@ -2382,8 +2386,10 @@ out:  		ocfs2_rw_unlock(inode, rw_level);  out_sems: -	if (have_alloc_sem) +	if (have_alloc_sem) {  		up_read(&inode->i_alloc_sem); +		ocfs2_iocb_clear_sem_locked(iocb); +	}  	mutex_unlock(&inode->i_mutex); @@ -2527,6 +2533,8 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,  		goto bail;  	} +	ocfs2_iocb_clear_sem_locked(iocb); +  	/*  	 * buffered reads protect themselves in ->readpage().  O_DIRECT reads  	 * need locks to protect pending reads from racing with truncate. @@ -2534,6 +2542,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,  	if (filp->f_flags & O_DIRECT) {  		down_read(&inode->i_alloc_sem);  		have_alloc_sem = 1; +		ocfs2_iocb_set_sem_locked(iocb);  		ret = ocfs2_rw_lock(inode, 0);  		if (ret < 0) { @@ -2575,8 +2584,10 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,  	}  bail: -	if (have_alloc_sem) +	if (have_alloc_sem) {  		up_read(&inode->i_alloc_sem); +		ocfs2_iocb_clear_sem_locked(iocb); +	}  	if (rw_level != -1)  		ocfs2_rw_unlock(inode, rw_level);  	mlog_exit(ret); diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index c2e4f8222e2..bf2e7764920 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h @@ -350,7 +350,7 @@ enum {  #define OCFS2_LAST_LOCAL_SYSTEM_INODE LOCAL_GROUP_QUOTA_SYSTEM_INODE  	NUM_SYSTEM_INODES  }; -#define NUM_GLOBAL_SYSTEM_INODES OCFS2_LAST_GLOBAL_SYSTEM_INODE +#define NUM_GLOBAL_SYSTEM_INODES OCFS2_FIRST_LOCAL_SYSTEM_INODE  #define NUM_LOCAL_SYSTEM_INODES	\  		(NUM_SYSTEM_INODES - OCFS2_FIRST_LOCAL_SYSTEM_INODE) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index aae86fd10c4..36ab42c9bb9 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -250,7 +250,7 @@ struct queue_limits {  	unsigned char		misaligned;  	unsigned char		discard_misaligned; -	unsigned char		no_cluster; +	unsigned char		cluster;  	signed char		discard_zeroes_data;  }; @@ -380,7 +380,6 @@ struct request_queue  #endif  }; -#define QUEUE_FLAG_CLUSTER	0	/* cluster several segments into 1 */  #define QUEUE_FLAG_QUEUED	1	/* uses generic tag queueing */  #define QUEUE_FLAG_STOPPED	2	/* queue is stopped */  #define	QUEUE_FLAG_SYNCFULL	3	/* read queue has been filled */ @@ -403,7 +402,6 @@ struct request_queue  #define QUEUE_FLAG_SECDISCARD  19	/* supports SECDISCARD */  #define QUEUE_FLAG_DEFAULT	((1 << QUEUE_FLAG_IO_STAT) |		\ -				 (1 << QUEUE_FLAG_CLUSTER) |		\  				 (1 << QUEUE_FLAG_STACKABLE)	|	\  				 (1 << QUEUE_FLAG_SAME_COMP)	|	\  				 (1 << QUEUE_FLAG_ADD_RANDOM)) @@ -510,6 +508,11 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q)  #define rq_data_dir(rq)		((rq)->cmd_flags & 1) +static inline unsigned int blk_queue_cluster(struct request_queue *q) +{ +	return q->limits.cluster; +} +  /*   * We regard a request as sync, if either a read or a sync write   */ @@ -805,6 +808,7 @@ extern struct request_queue *blk_init_allocated_queue(struct request_queue *,  extern void blk_cleanup_queue(struct request_queue *);  extern void blk_queue_make_request(struct request_queue *, make_request_fn *);  extern void blk_queue_bounce_limit(struct request_queue *, u64); +extern void blk_limits_max_hw_sectors(struct queue_limits *, unsigned int);  extern void blk_queue_max_hw_sectors(struct request_queue *, unsigned int);  extern void blk_queue_max_segments(struct request_queue *, unsigned short);  extern void blk_queue_max_segment_size(struct request_queue *, unsigned int); diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index 266ab929123..499dfe982a0 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -105,6 +105,8 @@ extern void *__alloc_bootmem_low_node(pg_data_t *pgdat,  #define alloc_bootmem(x) \  	__alloc_bootmem(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) +#define alloc_bootmem_align(x, align) \ +	__alloc_bootmem(x, align, __pa(MAX_DMA_ADDRESS))  #define alloc_bootmem_nopanic(x) \  	__alloc_bootmem_nopanic(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))  #define alloc_bootmem_pages(x) \ diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h index 9e76d35670d..72c72bfccb8 100644 --- a/include/linux/ceph/libceph.h +++ b/include/linux/ceph/libceph.h @@ -227,8 +227,10 @@ extern int ceph_open_session(struct ceph_client *client);  extern void ceph_release_page_vector(struct page **pages, int num_pages);  extern struct page **ceph_get_direct_page_vector(const char __user *data, -						 int num_pages); -extern void ceph_put_page_vector(struct page **pages, int num_pages); +						 int num_pages, +						 bool write_page); +extern void ceph_put_page_vector(struct page **pages, int num_pages, +				 bool dirty);  extern void ceph_release_page_vector(struct page **pages, int num_pages);  extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);  extern int ceph_copy_user_to_page_vector(struct page **pages, diff --git a/include/linux/cnt32_to_63.h b/include/linux/cnt32_to_63.h index 7605fdd1eb6..e3d8bf26e5e 100644 --- a/include/linux/cnt32_to_63.h +++ b/include/linux/cnt32_to_63.h @@ -61,13 +61,31 @@ union cnt32_to_63 {   *   * 2) this code must not be preempted for a duration longer than the   *    32-bit counter half period minus the longest period between two - *    calls to this code. + *    calls to this code;   *   * Those requirements ensure proper update to the state bit in memory.   * This is usually not a problem in practice, but if it is then a kernel   * timer should be scheduled to manage for this code to be executed often   * enough.   * + * And finally: + * + * 3) the cnt_lo argument must be seen as a globally incrementing value, + *    meaning that it should be a direct reference to the counter data which + *    can be evaluated according to a specific ordering within the macro, + *    and not the result of a previous evaluation stored in a variable. + * + * For example, this is wrong: + * + *	u32 partial = get_hw_count(); + *	u64 full = cnt32_to_63(partial); + *	return full; + * + * This is fine: + * + *	u64 full = cnt32_to_63(get_hw_count()); + *	return full; + *   * Note that the top bit (bit 63) in the returned value should be considered   * as garbage.  It is not cleared here because callers are likely to use a   * multiplier on the returned value which can get rid of the top bit diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 9d8688b92d8..8cd00ad98d3 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -824,6 +824,8 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);  #ifdef CONFIG_DMA_ENGINE  enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);  void dma_issue_pending_all(void); +struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param); +void dma_release_channel(struct dma_chan *chan);  #else  static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)  { @@ -831,7 +833,14 @@ static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descript  }  static inline void dma_issue_pending_all(void)  { -	do { } while (0); +} +static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, +					      dma_filter_fn fn, void *fn_param) +{ +	return NULL; +} +static inline void dma_release_channel(struct dma_chan *chan) +{  }  #endif @@ -842,8 +851,6 @@ void dma_async_device_unregister(struct dma_device *device);  void dma_run_dependencies(struct dma_async_tx_descriptor *tx);  struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type);  #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y) -struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param); -void dma_release_channel(struct dma_chan *chan);  /* --- Helper iov-locking functions --- */ diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index 0f0121467fc..6c6133f76e1 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -83,11 +83,13 @@  				 FAN_ALL_PERM_EVENTS |\  				 FAN_Q_OVERFLOW) -#define FANOTIFY_METADATA_VERSION	2 +#define FANOTIFY_METADATA_VERSION	3  struct fanotify_event_metadata {  	__u32 event_len; -	__u32 vers; +	__u8 vers; +	__u8 reserved; +	__u16 metadata_len;  	__aligned_u64 mask;  	__s32 fd;  	__s32 pid; @@ -96,11 +98,13 @@ struct fanotify_event_metadata {  struct fanotify_response {  	__s32 fd;  	__u32 response; -} __attribute__ ((packed)); +};  /* Legit userspace responses to a _PERM event */  #define FAN_ALLOW	0x01  #define FAN_DENY	0x02 +/* No fd set in event */ +#define FAN_NOFD	-1  /* Helper functions to deal with fanotify_event_metadata buffers */  #define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata)) diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 5c185fa2708..b10bcdeaef7 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -235,9 +235,6 @@ static inline void fsnotify_open(struct file *file)  	if (S_ISDIR(inode->i_mode))  		mask |= FS_ISDIR; -	/* FMODE_NONOTIFY must never be set from user */ -	file->f_mode &= ~FMODE_NONOTIFY; -  	fsnotify_parent(path, NULL, mask);  	fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);  } diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 0a68f924f06..7380763595d 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -166,7 +166,7 @@ struct fsnotify_group {  			struct mutex access_mutex;  			struct list_head access_list;  			wait_queue_head_t access_waitq; -			bool bypass_perm; /* protected by access_mutex */ +			atomic_t bypass_perm;  #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */  			int f_flags;  			unsigned int max_marks; diff --git a/include/linux/input.h b/include/linux/input.h index a8af21d42bc..9777668883b 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -104,8 +104,10 @@ struct input_keymap_entry {  #define EVIOCGREP		_IOR('E', 0x03, unsigned int[2])	/* get repeat settings */  #define EVIOCSREP		_IOW('E', 0x03, unsigned int[2])	/* set repeat settings */ -#define EVIOCGKEYCODE		_IOR('E', 0x04, struct input_keymap_entry)	/* get keycode */ -#define EVIOCSKEYCODE		_IOW('E', 0x04, struct input_keymap_entry)	/* set keycode */ +#define EVIOCGKEYCODE		_IOR('E', 0x04, unsigned int[2])        /* get keycode */ +#define EVIOCGKEYCODE_V2	_IOR('E', 0x04, struct input_keymap_entry) +#define EVIOCSKEYCODE		_IOW('E', 0x04, unsigned int[2])        /* set keycode */ +#define EVIOCSKEYCODE_V2	_IOW('E', 0x04, struct input_keymap_entry)  #define EVIOCGNAME(len)		_IOC(_IOC_READ, 'E', 0x06, len)		/* get device name */  #define EVIOCGPHYS(len)		_IOC(_IOC_READ, 'E', 0x07, len)		/* get physical location */ diff --git a/include/linux/ioport.h b/include/linux/ioport.h index d377ea815d4..e9bb22cba76 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -112,7 +112,6 @@ struct resource_list {  /* PC/ISA/whatever - the normal PC address spaces: IO and memory */  extern struct resource ioport_resource;  extern struct resource iomem_resource; -extern int resource_alloc_from_bottom;  extern struct resource *request_resource_conflict(struct resource *root, struct resource *new);  extern int request_resource(struct resource *root, struct resource *new); @@ -124,6 +123,7 @@ extern void reserve_region_with_split(struct resource *root,  extern struct resource *insert_resource_conflict(struct resource *parent, struct resource *new);  extern int insert_resource(struct resource *parent, struct resource *new);  extern void insert_resource_expand_to_fit(struct resource *root, struct resource *new); +extern void arch_remove_reservations(struct resource *avail);  extern int allocate_resource(struct resource *root, struct resource *new,  			     resource_size_t size, resource_size_t min,  			     resource_size_t max, resource_size_t align, diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 685ea65eb80..ce0775aa64c 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -81,16 +81,41 @@ struct kthread_work {  #define DEFINE_KTHREAD_WORK(work, fn)					\  	struct kthread_work work = KTHREAD_WORK_INIT(work, fn) -static inline void init_kthread_worker(struct kthread_worker *worker) -{ -	*worker = (struct kthread_worker)KTHREAD_WORKER_INIT(*worker); -} +/* + * kthread_worker.lock and kthread_work.done need their own lockdep class + * keys if they are defined on stack with lockdep enabled.  Use the + * following macros when defining them on stack. + */ +#ifdef CONFIG_LOCKDEP +# define KTHREAD_WORKER_INIT_ONSTACK(worker)				\ +	({ init_kthread_worker(&worker); worker; }) +# define DEFINE_KTHREAD_WORKER_ONSTACK(worker)				\ +	struct kthread_worker worker = KTHREAD_WORKER_INIT_ONSTACK(worker) +# define KTHREAD_WORK_INIT_ONSTACK(work, fn)				\ +	({ init_kthread_work((&work), fn); work; }) +# define DEFINE_KTHREAD_WORK_ONSTACK(work, fn)				\ +	struct kthread_work work = KTHREAD_WORK_INIT_ONSTACK(work, fn) +#else +# define DEFINE_KTHREAD_WORKER_ONSTACK(worker) DEFINE_KTHREAD_WORKER(worker) +# define DEFINE_KTHREAD_WORK_ONSTACK(work, fn) DEFINE_KTHREAD_WORK(work, fn) +#endif + +extern void __init_kthread_worker(struct kthread_worker *worker, +			const char *name, struct lock_class_key *key); + +#define init_kthread_worker(worker)					\ +	do {								\ +		static struct lock_class_key __key;			\ +		__init_kthread_worker((worker), "("#worker")->lock", &__key); \ +	} while (0) -static inline void init_kthread_work(struct kthread_work *work, -				     kthread_work_func_t fn) -{ -	*work = (struct kthread_work)KTHREAD_WORK_INIT(*work, fn); -} +#define init_kthread_work(work, fn)					\ +	do {								\ +		memset((work), 0, sizeof(struct kthread_work));		\ +		INIT_LIST_HEAD(&(work)->node);				\ +		(work)->func = (fn);					\ +		init_waitqueue_head(&(work)->done);			\ +	} while (0)  int kthread_worker_fn(void *worker_ptr); diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 123566912d7..e2b9e63afa6 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -70,7 +70,7 @@ struct nlmsghdr {     Check		NLM_F_EXCL   */ -#define NLMSG_ALIGNTO	4 +#define NLMSG_ALIGNTO	4U  #define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )  #define NLMSG_HDRLEN	 ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))  #define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN)) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index de2c41758e2..4f1279e105e 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -887,6 +887,7 @@ struct perf_cpu_context {  	int				exclusive;  	struct list_head		rotation_list;  	int				jiffies_interval; +	struct pmu			*active_pmu;  };  struct perf_output_handle { diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 3ec2358f869..d19f1cca7f7 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -77,7 +77,8 @@ static inline void device_set_run_wake(struct device *dev, bool enable)  static inline bool pm_runtime_suspended(struct device *dev)  { -	return dev->power.runtime_status == RPM_SUSPENDED; +	return dev->power.runtime_status == RPM_SUSPENDED +		&& !dev->power.disable_depth;  }  static inline void pm_runtime_mark_last_busy(struct device *dev) diff --git a/include/linux/sched.h b/include/linux/sched.h index 4f92a239c14..883ad10eadb 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -143,7 +143,7 @@ extern unsigned long nr_iowait_cpu(int cpu);  extern unsigned long this_cpu_load(void); -extern void calc_global_load(void); +extern void calc_global_load(unsigned long ticks);  extern unsigned long get_parent_ip(unsigned long addr); diff --git a/include/linux/ssb/ssb_driver_gige.h b/include/linux/ssb/ssb_driver_gige.h index 942e3873690..eba52a10053 100644 --- a/include/linux/ssb/ssb_driver_gige.h +++ b/include/linux/ssb/ssb_driver_gige.h @@ -96,16 +96,21 @@ static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)  	return 0;  } -extern char * nvram_get(const char *name); +#ifdef CONFIG_BCM47XX +#include <asm/mach-bcm47xx/nvram.h>  /* Get the device MAC address */  static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)  { -#ifdef CONFIG_BCM47XX -	char *res = nvram_get("et0macaddr"); -	if (res) -		memcpy(macaddr, res, 6); -#endif +	char buf[20]; +	if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0) +		return; +	nvram_parse_macaddr(buf, macaddr);  } +#else +static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr) +{ +} +#endif  extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,  					  struct pci_dev *pdev); diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h index 341dddb5509..2466e550a41 100644 --- a/include/linux/taskstats.h +++ b/include/linux/taskstats.h @@ -33,7 +33,7 @@   */ -#define TASKSTATS_VERSION	7 +#define TASKSTATS_VERSION	8  #define TS_COMM_LEN		32	/* should be >= TASK_COMM_LEN  					 * in linux/sched.h */ @@ -188,6 +188,7 @@ enum {  	TASKSTATS_TYPE_STATS,		/* taskstats structure */  	TASKSTATS_TYPE_AGGR_PID,	/* contains pid + stats */  	TASKSTATS_TYPE_AGGR_TGID,	/* contains tgid + stats */ +	TASKSTATS_TYPE_NULL,		/* contains nothing */  	__TASKSTATS_TYPE_MAX,  }; diff --git a/include/linux/unaligned/packed_struct.h b/include/linux/unaligned/packed_struct.h index 2498bb9fe00..c9a6abd972a 100644 --- a/include/linux/unaligned/packed_struct.h +++ b/include/linux/unaligned/packed_struct.h @@ -3,9 +3,9 @@  #include <linux/kernel.h> -struct __una_u16 { u16 x __attribute__((packed)); }; -struct __una_u32 { u32 x __attribute__((packed)); }; -struct __una_u64 { u64 x __attribute__((packed)); }; +struct __una_u16 { u16 x; } __attribute__((packed)); +struct __una_u32 { u32 x; } __attribute__((packed)); +struct __una_u64 { u64 x; } __attribute__((packed));  static inline u16 __get_unaligned_cpu16(const void *p)  { diff --git a/include/media/saa7146.h b/include/media/saa7146.h index 7a9f76ecbbb..ac7ce00f39c 100644 --- a/include/media/saa7146.h +++ b/include/media/saa7146.h @@ -161,7 +161,7 @@ extern struct list_head saa7146_devices;  extern struct mutex saa7146_devices_lock;  int saa7146_register_extension(struct saa7146_extension*);  int saa7146_unregister_extension(struct saa7146_extension*); -struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc); +struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc);  int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt);  void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt);  int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length ); diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h index 6648036b728..b16f307d471 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h @@ -51,6 +51,8 @@ struct v4l2_device {  			unsigned int notification, void *arg);  	/* The control handler. May be NULL. */  	struct v4l2_ctrl_handler *ctrl_handler; +	/* BKL replacement mutex. Temporary solution only. */ +	struct mutex ioctl_lock;  };  /* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev. diff --git a/include/media/wm8775.h b/include/media/wm8775.h index a1c4d417dfa..60739c5a23a 100644 --- a/include/media/wm8775.h +++ b/include/media/wm8775.h @@ -32,7 +32,4 @@  #define WM8775_AIN3 4  #define WM8775_AIN4 8 -/* subdev group ID */ -#define WM8775_GID (1 << 0) -  #endif diff --git a/include/net/flow.h b/include/net/flow.h index 0ac3fb5e097..bb08692a20b 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -49,7 +49,6 @@ struct flowi {  	__u8	proto;  	__u8	flags;  #define FLOWI_FLAG_ANYSRC 0x01 -#define FLOWI_FLAG_MATCH_ANY_IIF 0x02  	union {  		struct {  			__be16	sport; diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 278312c95f9..2ab926860cd 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -164,5 +164,15 @@ static inline int ipv6_unicast_destination(struct sk_buff *skb)  	return rt->rt6i_flags & RTF_LOCAL;  } +int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); + +static inline int ip6_skb_dst_mtu(struct sk_buff *skb) +{ +	struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; + +	return (np && np->pmtudisc == IPV6_PMTUDISC_PROBE) ? +	       skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); +} +  #endif  #endif diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9fdf982d128..365359b2417 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2024,8 +2024,8 @@ static inline void ieee80211_rx_ni(struct ieee80211_hw *hw,   *   * This function may not be called in IRQ context. Calls to this function   * for a single hardware must be synchronized against each other. Calls - * to this function and ieee80211_tx_status_irqsafe() may not be mixed - * for a single hardware. + * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe() + * may not be mixed for a single hardware.   *   * @hw: the hardware the frame was transmitted by   * @skb: the frame that was transmitted, owned by mac80211 after this call @@ -2034,13 +2034,33 @@ void ieee80211_tx_status(struct ieee80211_hw *hw,  			 struct sk_buff *skb);  /** + * ieee80211_tx_status_ni - transmit status callback (in process context) + * + * Like ieee80211_tx_status() but can be called in process context. + * + * Calls to this function, ieee80211_tx_status() and + * ieee80211_tx_status_irqsafe() may not be mixed + * for a single hardware. + * + * @hw: the hardware the frame was transmitted by + * @skb: the frame that was transmitted, owned by mac80211 after this call + */ +static inline void ieee80211_tx_status_ni(struct ieee80211_hw *hw, +					  struct sk_buff *skb) +{ +	local_bh_disable(); +	ieee80211_tx_status(hw, skb); +	local_bh_enable(); +} + +/**   * ieee80211_tx_status_irqsafe - IRQ-safe transmit status callback   *   * Like ieee80211_tx_status() but can be called in IRQ context   * (internally defers to a tasklet.)   * - * Calls to this function and ieee80211_tx_status() may not be mixed for a - * single hardware. + * Calls to this function, ieee80211_tx_status() and + * ieee80211_tx_status_ni() may not be mixed for a single hardware.   *   * @hw: the hardware the frame was transmitted by   * @skb: the frame that was transmitted, owned by mac80211 after this call diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index dd3031aed9d..9fcc680ab6b 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h @@ -323,7 +323,9 @@ static inline unsigned char * tcf_get_base_ptr(struct sk_buff *skb, int layer)  static inline int tcf_valid_offset(const struct sk_buff *skb,  				   const unsigned char *ptr, const int len)  { -	return unlikely((ptr + len) < skb_tail_pointer(skb) && ptr > skb->head); +	return likely((ptr + len) <= skb_tail_pointer(skb) && +		      ptr >= skb->head && +		      (ptr <= (ptr + len)));  }  #ifdef CONFIG_NET_CLS_IND diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index ea1f8a83160..79f34e2b752 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -610,11 +610,7 @@ static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask,  {  	struct sk_buff *n; -	if ((action == TC_ACT_STOLEN || action == TC_ACT_QUEUED) && -	    !skb_shared(skb)) -		n = skb_get(skb); -	else -		n = skb_clone(skb, gfp_mask); +	n = skb_clone(skb, gfp_mask);  	if (n) {  		n->tc_verd = SET_TC_VERD(n->tc_verd, 0); diff --git a/include/net/sock.h b/include/net/sock.h index 659d968d95c..7d3f7ce239b 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -754,6 +754,7 @@ struct proto {  	void			(*unhash)(struct sock *sk);  	void			(*rehash)(struct sock *sk);  	int			(*get_port)(struct sock *sk, unsigned short snum); +	void			(*clear_sk)(struct sock *sk, int size);  	/* Keeping track of sockets in use */  #ifdef CONFIG_PROC_FS @@ -852,6 +853,8 @@ static inline void __sk_prot_rehash(struct sock *sk)  	sk->sk_prot->hash(sk);  } +void sk_prot_clear_portaddr_nulls(struct sock *sk, int size); +  /* About 10 seconds */  #define SOCK_DESTROY_TIME (10*HZ) diff --git a/init/do_mounts.c b/init/do_mounts.c index 830aaec9c7d..2b54bef33b5 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -93,7 +93,7 @@ no_match:   *   * Returns the matching dev_t on success or 0 on failure.   */ -static dev_t __init devt_from_partuuid(char *uuid_str) +static dev_t devt_from_partuuid(char *uuid_str)  {  	dev_t res = 0;  	struct device *dev = NULL; diff --git a/kernel/fork.c b/kernel/fork.c index 06724449596..7d164e25b0f 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -275,6 +275,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)  	setup_thread_stack(tsk, orig);  	clear_user_return_notifier(tsk); +	clear_tsk_need_resched(tsk);  	stackend = end_of_stack(tsk);  	*stackend = STACK_END_MAGIC;	/* for overflow detection */ diff --git a/kernel/kthread.c b/kernel/kthread.c index 74cf6f5e7ad..5355cfd44a3 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -265,6 +265,17 @@ int kthreadd(void *unused)  	return 0;  } +void __init_kthread_worker(struct kthread_worker *worker, +				const char *name, +				struct lock_class_key *key) +{ +	spin_lock_init(&worker->lock); +	lockdep_set_class_and_name(&worker->lock, key, name); +	INIT_LIST_HEAD(&worker->work_list); +	worker->task = NULL; +} +EXPORT_SYMBOL_GPL(__init_kthread_worker); +  /**   * kthread_worker_fn - kthread function to process kthread_worker   * @worker_ptr: pointer to initialized kthread_worker diff --git a/kernel/perf_event.c b/kernel/perf_event.c index eac7e336433..2870feee81d 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -3824,6 +3824,8 @@ static void perf_event_task_event(struct perf_task_event *task_event)  	rcu_read_lock();  	list_for_each_entry_rcu(pmu, &pmus, entry) {  		cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); +		if (cpuctx->active_pmu != pmu) +			goto next;  		perf_event_task_ctx(&cpuctx->ctx, task_event);  		ctx = task_event->task_ctx; @@ -3959,6 +3961,8 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)  	rcu_read_lock();  	list_for_each_entry_rcu(pmu, &pmus, entry) {  		cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); +		if (cpuctx->active_pmu != pmu) +			goto next;  		perf_event_comm_ctx(&cpuctx->ctx, comm_event);  		ctxn = pmu->task_ctx_nr; @@ -4144,6 +4148,8 @@ got_name:  	rcu_read_lock();  	list_for_each_entry_rcu(pmu, &pmus, entry) {  		cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); +		if (cpuctx->active_pmu != pmu) +			goto next;  		perf_event_mmap_ctx(&cpuctx->ctx, mmap_event,  					vma->vm_flags & VM_EXEC); @@ -4713,7 +4719,7 @@ static int perf_swevent_init(struct perf_event *event)  		break;  	} -	if (event_id > PERF_COUNT_SW_MAX) +	if (event_id >= PERF_COUNT_SW_MAX)  		return -ENOENT;  	if (!event->parent) { @@ -5145,20 +5151,36 @@ static void *find_pmu_context(int ctxn)  	return NULL;  } -static void free_pmu_context(void * __percpu cpu_context) +static void update_pmu_context(struct pmu *pmu, struct pmu *old_pmu)  { -	struct pmu *pmu; +	int cpu; + +	for_each_possible_cpu(cpu) { +		struct perf_cpu_context *cpuctx; + +		cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); + +		if (cpuctx->active_pmu == old_pmu) +			cpuctx->active_pmu = pmu; +	} +} + +static void free_pmu_context(struct pmu *pmu) +{ +	struct pmu *i;  	mutex_lock(&pmus_lock);  	/*  	 * Like a real lame refcount.  	 */ -	list_for_each_entry(pmu, &pmus, entry) { -		if (pmu->pmu_cpu_context == cpu_context) +	list_for_each_entry(i, &pmus, entry) { +		if (i->pmu_cpu_context == pmu->pmu_cpu_context) { +			update_pmu_context(i, pmu);  			goto out; +		}  	} -	free_percpu(cpu_context); +	free_percpu(pmu->pmu_cpu_context);  out:  	mutex_unlock(&pmus_lock);  } @@ -5190,6 +5212,7 @@ int perf_pmu_register(struct pmu *pmu)  		cpuctx->ctx.pmu = pmu;  		cpuctx->jiffies_interval = 1;  		INIT_LIST_HEAD(&cpuctx->rotation_list); +		cpuctx->active_pmu = pmu;  	}  got_cpu_context: @@ -5241,7 +5264,7 @@ void perf_pmu_unregister(struct pmu *pmu)  	synchronize_rcu();  	free_percpu(pmu->pmu_disable_count); -	free_pmu_context(pmu->pmu_cpu_context); +	free_pmu_context(pmu);  }  struct pmu *perf_init_event(struct perf_event *event) diff --git a/kernel/power/swap.c b/kernel/power/swap.c index baf667bb279..8c7e4832b9b 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -30,7 +30,7 @@  #include "power.h" -#define HIBERNATE_SIG	"LINHIB0001" +#define HIBERNATE_SIG	"S1SUSPEND"  /*   *	The swap map is a data structure used for keeping track of each page diff --git a/kernel/power/user.c b/kernel/power/user.c index 1b2ea31e6bd..c36c3b9e8a8 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -137,7 +137,7 @@ static int snapshot_release(struct inode *inode, struct file *filp)  	free_all_swap_pages(data->swap);  	if (data->frozen)  		thaw_processes(); -	pm_notifier_call_chain(data->mode == O_WRONLY ? +	pm_notifier_call_chain(data->mode == O_RDONLY ?  			PM_POST_HIBERNATION : PM_POST_RESTORE);  	atomic_inc(&snapshot_device_available); diff --git a/kernel/resource.c b/kernel/resource.c index 9fad33efd0d..798e2fae2a0 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -40,23 +40,6 @@ EXPORT_SYMBOL(iomem_resource);  static DEFINE_RWLOCK(resource_lock); -/* - * By default, we allocate free space bottom-up.  The architecture can request - * top-down by clearing this flag.  The user can override the architecture's - * choice with the "resource_alloc_from_bottom" kernel boot option, but that - * should only be a debugging tool. - */ -int resource_alloc_from_bottom = 1; - -static __init int setup_alloc_from_bottom(char *s) -{ -	printk(KERN_INFO -	       "resource: allocating from bottom-up; please report a bug\n"); -	resource_alloc_from_bottom = 1; -	return 0; -} -early_param("resource_alloc_from_bottom", setup_alloc_from_bottom); -  static void *r_next(struct seq_file *m, void *v, loff_t *pos)  {  	struct resource *p = v; @@ -374,6 +357,10 @@ int __weak page_is_ram(unsigned long pfn)  	return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1;  } +void __weak arch_remove_reservations(struct resource *avail) +{ +} +  static resource_size_t simple_align_resource(void *data,  					     const struct resource *avail,  					     resource_size_t size, @@ -397,74 +384,7 @@ static bool resource_contains(struct resource *res1, struct resource *res2)  }  /* - * Find the resource before "child" in the sibling list of "root" children. - */ -static struct resource *find_sibling_prev(struct resource *root, struct resource *child) -{ -	struct resource *this; - -	for (this = root->child; this; this = this->sibling) -		if (this->sibling == child) -			return this; - -	return NULL; -} - -/*   * Find empty slot in the resource tree given range and alignment. - * This version allocates from the end of the root resource first. - */ -static int find_resource_from_top(struct resource *root, struct resource *new, -				  resource_size_t size, resource_size_t min, -				  resource_size_t max, resource_size_t align, -				  resource_size_t (*alignf)(void *, -						   const struct resource *, -						   resource_size_t, -						   resource_size_t), -				  void *alignf_data) -{ -	struct resource *this; -	struct resource tmp, avail, alloc; - -	tmp.start = root->end; -	tmp.end = root->end; - -	this = find_sibling_prev(root, NULL); -	for (;;) { -		if (this) { -			if (this->end < root->end) -				tmp.start = this->end + 1; -		} else -			tmp.start = root->start; - -		resource_clip(&tmp, min, max); - -		/* Check for overflow after ALIGN() */ -		avail = *new; -		avail.start = ALIGN(tmp.start, align); -		avail.end = tmp.end; -		if (avail.start >= tmp.start) { -			alloc.start = alignf(alignf_data, &avail, size, align); -			alloc.end = alloc.start + size - 1; -			if (resource_contains(&avail, &alloc)) { -				new->start = alloc.start; -				new->end = alloc.end; -				return 0; -			} -		} - -		if (!this || this->start == root->start) -			break; - -		tmp.end = this->start - 1; -		this = find_sibling_prev(root, this); -	} -	return -EBUSY; -} - -/* - * Find empty slot in the resource tree given range and alignment. - * This version allocates from the beginning of the root resource first.   */  static int find_resource(struct resource *root, struct resource *new,  			 resource_size_t size, resource_size_t min, @@ -478,23 +398,24 @@ static int find_resource(struct resource *root, struct resource *new,  	struct resource *this = root->child;  	struct resource tmp = *new, avail, alloc; +	tmp.flags = new->flags;  	tmp.start = root->start;  	/* -	 * Skip past an allocated resource that starts at 0, since the -	 * assignment of this->start - 1 to tmp->end below would cause an -	 * underflow. +	 * Skip past an allocated resource that starts at 0, since the assignment +	 * of this->start - 1 to tmp->end below would cause an underflow.  	 */  	if (this && this->start == 0) {  		tmp.start = this->end + 1;  		this = this->sibling;  	} -	for (;;) { +	for(;;) {  		if (this)  			tmp.end = this->start - 1;  		else  			tmp.end = root->end;  		resource_clip(&tmp, min, max); +		arch_remove_reservations(&tmp);  		/* Check for overflow after ALIGN() */  		avail = *new; @@ -509,10 +430,8 @@ static int find_resource(struct resource *root, struct resource *new,  				return 0;  			}  		} -  		if (!this)  			break; -  		tmp.start = this->end + 1;  		this = this->sibling;  	} @@ -545,10 +464,7 @@ int allocate_resource(struct resource *root, struct resource *new,  		alignf = simple_align_resource;  	write_lock(&resource_lock); -	if (resource_alloc_from_bottom) -		err = find_resource(root, new, size, min, max, align, alignf, alignf_data); -	else -		err = find_resource_from_top(root, new, size, min, max, align, alignf, alignf_data); +	err = find_resource(root, new, size, min, max, align, alignf, alignf_data);  	if (err >= 0 && __request_resource(root, new))  		err = -EBUSY;  	write_unlock(&resource_lock); diff --git a/kernel/sched.c b/kernel/sched.c index 9f9dd8dda53..f2f914e0c47 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -642,22 +642,18 @@ static inline struct task_group *task_group(struct task_struct *p)  #endif /* CONFIG_CGROUP_SCHED */ -static u64 irq_time_cpu(int cpu); -static void sched_irq_time_avg_update(struct rq *rq, u64 irq_time); +static void update_rq_clock_task(struct rq *rq, s64 delta); -inline void update_rq_clock(struct rq *rq) +static void update_rq_clock(struct rq *rq)  { -	if (!rq->skip_clock_update) { -		int cpu = cpu_of(rq); -		u64 irq_time; +	s64 delta; -		rq->clock = sched_clock_cpu(cpu); -		irq_time = irq_time_cpu(cpu); -		if (rq->clock - irq_time > rq->clock_task) -			rq->clock_task = rq->clock - irq_time; +	if (rq->skip_clock_update) +		return; -		sched_irq_time_avg_update(rq, irq_time); -	} +	delta = sched_clock_cpu(cpu_of(rq)) - rq->clock; +	rq->clock += delta; +	update_rq_clock_task(rq, delta);  }  /* @@ -1795,10 +1791,9 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int flags)   * They are read and saved off onto struct rq in update_rq_clock().   * This may result in other CPU reading this CPU's irq time and can   * race with irq/account_system_vtime on this CPU. We would either get old - * or new value (or semi updated value on 32 bit) with a side effect of - * accounting a slice of irq time to wrong task when irq is in progress - * while we read rq->clock. That is a worthy compromise in place of having - * locks on each irq in account_system_time. + * or new value with a side effect of accounting a slice of irq time to wrong + * task when irq is in progress while we read rq->clock. That is a worthy + * compromise in place of having locks on each irq in account_system_time.   */  static DEFINE_PER_CPU(u64, cpu_hardirq_time);  static DEFINE_PER_CPU(u64, cpu_softirq_time); @@ -1816,19 +1811,58 @@ void disable_sched_clock_irqtime(void)  	sched_clock_irqtime = 0;  } -static u64 irq_time_cpu(int cpu) +#ifndef CONFIG_64BIT +static DEFINE_PER_CPU(seqcount_t, irq_time_seq); + +static inline void irq_time_write_begin(void)  { -	if (!sched_clock_irqtime) -		return 0; +	__this_cpu_inc(irq_time_seq.sequence); +	smp_wmb(); +} + +static inline void irq_time_write_end(void) +{ +	smp_wmb(); +	__this_cpu_inc(irq_time_seq.sequence); +} + +static inline u64 irq_time_read(int cpu) +{ +	u64 irq_time; +	unsigned seq; +	do { +		seq = read_seqcount_begin(&per_cpu(irq_time_seq, cpu)); +		irq_time = per_cpu(cpu_softirq_time, cpu) + +			   per_cpu(cpu_hardirq_time, cpu); +	} while (read_seqcount_retry(&per_cpu(irq_time_seq, cpu), seq)); + +	return irq_time; +} +#else /* CONFIG_64BIT */ +static inline void irq_time_write_begin(void) +{ +} + +static inline void irq_time_write_end(void) +{ +} + +static inline u64 irq_time_read(int cpu) +{  	return per_cpu(cpu_softirq_time, cpu) + per_cpu(cpu_hardirq_time, cpu);  } +#endif /* CONFIG_64BIT */ +/* + * Called before incrementing preempt_count on {soft,}irq_enter + * and before decrementing preempt_count on {soft,}irq_exit. + */  void account_system_vtime(struct task_struct *curr)  {  	unsigned long flags; +	s64 delta;  	int cpu; -	u64 now, delta;  	if (!sched_clock_irqtime)  		return; @@ -1836,9 +1870,10 @@ void account_system_vtime(struct task_struct *curr)  	local_irq_save(flags);  	cpu = smp_processor_id(); -	now = sched_clock_cpu(cpu); -	delta = now - per_cpu(irq_start_time, cpu); -	per_cpu(irq_start_time, cpu) = now; +	delta = sched_clock_cpu(cpu) - __this_cpu_read(irq_start_time); +	__this_cpu_add(irq_start_time, delta); + +	irq_time_write_begin();  	/*  	 * We do not account for softirq time from ksoftirqd here.  	 * We want to continue accounting softirq time to ksoftirqd thread @@ -1846,33 +1881,55 @@ void account_system_vtime(struct task_struct *curr)  	 * that do not consume any time, but still wants to run.  	 */  	if (hardirq_count()) -		per_cpu(cpu_hardirq_time, cpu) += delta; +		__this_cpu_add(cpu_hardirq_time, delta);  	else if (in_serving_softirq() && !(curr->flags & PF_KSOFTIRQD)) -		per_cpu(cpu_softirq_time, cpu) += delta; +		__this_cpu_add(cpu_softirq_time, delta); +	irq_time_write_end();  	local_irq_restore(flags);  }  EXPORT_SYMBOL_GPL(account_system_vtime); -static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) +static void update_rq_clock_task(struct rq *rq, s64 delta)  { -	if (sched_clock_irqtime && sched_feat(NONIRQ_POWER)) { -		u64 delta_irq = curr_irq_time - rq->prev_irq_time; -		rq->prev_irq_time = curr_irq_time; -		sched_rt_avg_update(rq, delta_irq); -	} +	s64 irq_delta; + +	irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time; + +	/* +	 * Since irq_time is only updated on {soft,}irq_exit, we might run into +	 * this case when a previous update_rq_clock() happened inside a +	 * {soft,}irq region. +	 * +	 * When this happens, we stop ->clock_task and only update the +	 * prev_irq_time stamp to account for the part that fit, so that a next +	 * update will consume the rest. This ensures ->clock_task is +	 * monotonic. +	 * +	 * It does however cause some slight miss-attribution of {soft,}irq +	 * time, a more accurate solution would be to update the irq_time using +	 * the current rq->clock timestamp, except that would require using +	 * atomic ops. +	 */ +	if (irq_delta > delta) +		irq_delta = delta; + +	rq->prev_irq_time += irq_delta; +	delta -= irq_delta; +	rq->clock_task += delta; + +	if (irq_delta && sched_feat(NONIRQ_POWER)) +		sched_rt_avg_update(rq, irq_delta);  } -#else +#else /* CONFIG_IRQ_TIME_ACCOUNTING */ -static u64 irq_time_cpu(int cpu) +static void update_rq_clock_task(struct rq *rq, s64 delta)  { -	return 0; +	rq->clock_task += delta;  } -static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) { } - -#endif +#endif /* CONFIG_IRQ_TIME_ACCOUNTING */  #include "sched_idletask.c"  #include "sched_fair.c" @@ -2001,7 +2058,7 @@ static void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)  	 * A queue event has occurred, and we're going to schedule.  In  	 * this case, we can save a useless back to back clock update.  	 */ -	if (test_tsk_need_resched(rq->curr)) +	if (rq->curr->se.on_rq && test_tsk_need_resched(rq->curr))  		rq->skip_clock_update = 1;  } @@ -2988,6 +3045,15 @@ static long calc_load_fold_active(struct rq *this_rq)  	return delta;  } +static unsigned long +calc_load(unsigned long load, unsigned long exp, unsigned long active) +{ +	load *= exp; +	load += active * (FIXED_1 - exp); +	load += 1UL << (FSHIFT - 1); +	return load >> FSHIFT; +} +  #ifdef CONFIG_NO_HZ  /*   * For NO_HZ we delay the active fold to the next LOAD_FREQ update. @@ -3017,6 +3083,128 @@ static long calc_load_fold_idle(void)  	return delta;  } + +/** + * fixed_power_int - compute: x^n, in O(log n) time + * + * @x:         base of the power + * @frac_bits: fractional bits of @x + * @n:         power to raise @x to. + * + * By exploiting the relation between the definition of the natural power + * function: x^n := x*x*...*x (x multiplied by itself for n times), and + * the binary encoding of numbers used by computers: n := \Sum n_i * 2^i, + * (where: n_i \elem {0, 1}, the binary vector representing n), + * we find: x^n := x^(\Sum n_i * 2^i) := \Prod x^(n_i * 2^i), which is + * of course trivially computable in O(log_2 n), the length of our binary + * vector. + */ +static unsigned long +fixed_power_int(unsigned long x, unsigned int frac_bits, unsigned int n) +{ +	unsigned long result = 1UL << frac_bits; + +	if (n) for (;;) { +		if (n & 1) { +			result *= x; +			result += 1UL << (frac_bits - 1); +			result >>= frac_bits; +		} +		n >>= 1; +		if (!n) +			break; +		x *= x; +		x += 1UL << (frac_bits - 1); +		x >>= frac_bits; +	} + +	return result; +} + +/* + * a1 = a0 * e + a * (1 - e) + * + * a2 = a1 * e + a * (1 - e) + *    = (a0 * e + a * (1 - e)) * e + a * (1 - e) + *    = a0 * e^2 + a * (1 - e) * (1 + e) + * + * a3 = a2 * e + a * (1 - e) + *    = (a0 * e^2 + a * (1 - e) * (1 + e)) * e + a * (1 - e) + *    = a0 * e^3 + a * (1 - e) * (1 + e + e^2) + * + *  ... + * + * an = a0 * e^n + a * (1 - e) * (1 + e + ... + e^n-1) [1] + *    = a0 * e^n + a * (1 - e) * (1 - e^n)/(1 - e) + *    = a0 * e^n + a * (1 - e^n) + * + * [1] application of the geometric series: + * + *              n         1 - x^(n+1) + *     S_n := \Sum x^i = ------------- + *             i=0          1 - x + */ +static unsigned long +calc_load_n(unsigned long load, unsigned long exp, +	    unsigned long active, unsigned int n) +{ + +	return calc_load(load, fixed_power_int(exp, FSHIFT, n), active); +} + +/* + * NO_HZ can leave us missing all per-cpu ticks calling + * calc_load_account_active(), but since an idle CPU folds its delta into + * calc_load_tasks_idle per calc_load_account_idle(), all we need to do is fold + * in the pending idle delta if our idle period crossed a load cycle boundary. + * + * Once we've updated the global active value, we need to apply the exponential + * weights adjusted to the number of cycles missed. + */ +static void calc_global_nohz(unsigned long ticks) +{ +	long delta, active, n; + +	if (time_before(jiffies, calc_load_update)) +		return; + +	/* +	 * If we crossed a calc_load_update boundary, make sure to fold +	 * any pending idle changes, the respective CPUs might have +	 * missed the tick driven calc_load_account_active() update +	 * due to NO_HZ. +	 */ +	delta = calc_load_fold_idle(); +	if (delta) +		atomic_long_add(delta, &calc_load_tasks); + +	/* +	 * If we were idle for multiple load cycles, apply them. +	 */ +	if (ticks >= LOAD_FREQ) { +		n = ticks / LOAD_FREQ; + +		active = atomic_long_read(&calc_load_tasks); +		active = active > 0 ? active * FIXED_1 : 0; + +		avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n); +		avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n); +		avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n); + +		calc_load_update += n * LOAD_FREQ; +	} + +	/* +	 * Its possible the remainder of the above division also crosses +	 * a LOAD_FREQ period, the regular check in calc_global_load() +	 * which comes after this will take care of that. +	 * +	 * Consider us being 11 ticks before a cycle completion, and us +	 * sleeping for 4*LOAD_FREQ + 22 ticks, then the above code will +	 * age us 4 cycles, and the test in calc_global_load() will +	 * pick up the final one. +	 */ +}  #else  static void calc_load_account_idle(struct rq *this_rq)  { @@ -3026,6 +3214,10 @@ static inline long calc_load_fold_idle(void)  {  	return 0;  } + +static void calc_global_nohz(unsigned long ticks) +{ +}  #endif  /** @@ -3043,24 +3235,17 @@ void get_avenrun(unsigned long *loads, unsigned long offset, int shift)  	loads[2] = (avenrun[2] + offset) << shift;  } -static unsigned long -calc_load(unsigned long load, unsigned long exp, unsigned long active) -{ -	load *= exp; -	load += active * (FIXED_1 - exp); -	return load >> FSHIFT; -} -  /*   * calc_load - update the avenrun load estimates 10 ticks after the   * CPUs have updated calc_load_tasks.   */ -void calc_global_load(void) +void calc_global_load(unsigned long ticks)  { -	unsigned long upd = calc_load_update + 10;  	long active; -	if (time_before(jiffies, upd)) +	calc_global_nohz(ticks); + +	if (time_before(jiffies, calc_load_update + 10))  		return;  	active = atomic_long_read(&calc_load_tasks); @@ -3714,7 +3899,6 @@ static void put_prev_task(struct rq *rq, struct task_struct *prev)  {  	if (prev->se.on_rq)  		update_rq_clock(rq); -	rq->skip_clock_update = 0;  	prev->sched_class->put_prev_task(rq, prev);  } @@ -3772,7 +3956,6 @@ need_resched_nonpreemptible:  		hrtick_clear(rq);  	raw_spin_lock_irq(&rq->lock); -	clear_tsk_need_resched(prev);  	switch_count = &prev->nivcsw;  	if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { @@ -3804,6 +3987,8 @@ need_resched_nonpreemptible:  	put_prev_task(rq, prev);  	next = pick_next_task(rq); +	clear_tsk_need_resched(prev); +	rq->skip_clock_update = 0;  	if (likely(prev != next)) {  		sched_info_switch(prev, next); diff --git a/kernel/taskstats.c b/kernel/taskstats.c index c8231fb1570..3308fd7f1b5 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -349,25 +349,47 @@ static int parse(struct nlattr *na, struct cpumask *mask)  	return ret;  } +#ifdef CONFIG_IA64 +#define TASKSTATS_NEEDS_PADDING 1 +#endif +  static struct taskstats *mk_reply(struct sk_buff *skb, int type, u32 pid)  {  	struct nlattr *na, *ret;  	int aggr; -	/* If we don't pad, we end up with alignment on a 4 byte boundary. -	 * This causes lots of runtime warnings on systems requiring 8 byte -	 * alignment */ -	u32 pids[2] = { pid, 0 }; -	int pid_size = ALIGN(sizeof(pid), sizeof(long)); -  	aggr = (type == TASKSTATS_TYPE_PID)  			? TASKSTATS_TYPE_AGGR_PID  			: TASKSTATS_TYPE_AGGR_TGID; +	/* +	 * The taskstats structure is internally aligned on 8 byte +	 * boundaries but the layout of the aggregrate reply, with +	 * two NLA headers and the pid (each 4 bytes), actually +	 * force the entire structure to be unaligned. This causes +	 * the kernel to issue unaligned access warnings on some +	 * architectures like ia64. Unfortunately, some software out there +	 * doesn't properly unroll the NLA packet and assumes that the start +	 * of the taskstats structure will always be 20 bytes from the start +	 * of the netlink payload. Aligning the start of the taskstats +	 * structure breaks this software, which we don't want. So, for now +	 * the alignment only happens on architectures that require it +	 * and those users will have to update to fixed versions of those +	 * packages. Space is reserved in the packet only when needed. +	 * This ifdef should be removed in several years e.g. 2012 once +	 * we can be confident that fixed versions are installed on most +	 * systems. We add the padding before the aggregate since the +	 * aggregate is already a defined type. +	 */ +#ifdef TASKSTATS_NEEDS_PADDING +	if (nla_put(skb, TASKSTATS_TYPE_NULL, 0, NULL) < 0) +		goto err; +#endif  	na = nla_nest_start(skb, aggr);  	if (!na)  		goto err; -	if (nla_put(skb, type, pid_size, pids) < 0) + +	if (nla_put(skb, type, sizeof(pid), &pid) < 0)  		goto err;  	ret = nla_reserve(skb, TASKSTATS_TYPE_STATS, sizeof(struct taskstats));  	if (!ret) @@ -456,6 +478,18 @@ out:  	return rc;  } +static size_t taskstats_packet_size(void) +{ +	size_t size; + +	size = nla_total_size(sizeof(u32)) + +		nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); +#ifdef TASKSTATS_NEEDS_PADDING +	size += nla_total_size(0); /* Padding for alignment */ +#endif +	return size; +} +  static int cmd_attr_pid(struct genl_info *info)  {  	struct taskstats *stats; @@ -464,8 +498,7 @@ static int cmd_attr_pid(struct genl_info *info)  	u32 pid;  	int rc; -	size = nla_total_size(sizeof(u32)) + -		nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); +	size = taskstats_packet_size();  	rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, size);  	if (rc < 0) @@ -494,8 +527,7 @@ static int cmd_attr_tgid(struct genl_info *info)  	u32 tgid;  	int rc; -	size = nla_total_size(sizeof(u32)) + -		nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); +	size = taskstats_packet_size();  	rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, size);  	if (rc < 0) @@ -570,8 +602,7 @@ void taskstats_exit(struct task_struct *tsk, int group_dead)  	/*  	 * Size includes space for nested attributes  	 */ -	size = nla_total_size(sizeof(u32)) + -		nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); +	size = taskstats_packet_size();  	is_thread_group = !!taskstats_tgid_alloc(tsk);  	if (is_thread_group) { diff --git a/kernel/timer.c b/kernel/timer.c index 68a9ae7679b..353b9227c2e 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1252,6 +1252,12 @@ unsigned long get_next_timer_interrupt(unsigned long now)  	struct tvec_base *base = __get_cpu_var(tvec_bases);  	unsigned long expires; +	/* +	 * Pretend that there is no timer pending if the cpu is offline. +	 * Possible pending timers will be migrated later to an active cpu. +	 */ +	if (cpu_is_offline(smp_processor_id())) +		return now + NEXT_TIMER_MAX_DELTA;  	spin_lock(&base->lock);  	if (time_before_eq(base->next_timer, base->timer_jiffies))  		base->next_timer = __next_timer_interrupt(base); @@ -1319,7 +1325,7 @@ void do_timer(unsigned long ticks)  {  	jiffies_64 += ticks;  	update_wall_time(); -	calc_global_load(); +	calc_global_load(ticks);  }  #ifdef __ARCH_WANT_SYS_ALARM diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 9ed509a015d..bd1c35a4fbc 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -3853,6 +3853,13 @@ int ring_buffer_read_page(struct ring_buffer *buffer,  		/* Need to copy one event at a time */  		do { +			/* We need the size of one event, because +			 * rb_advance_reader only advances by one event, +			 * whereas rb_event_ts_length may include the size of +			 * one or two events. +			 * We have already ensured there's enough space if this +			 * is a time extend. */ +			size = rb_event_length(event);  			memcpy(bpage->data + pos, rpage->data + rpos, size);  			len -= size; @@ -3867,7 +3874,7 @@ int ring_buffer_read_page(struct ring_buffer *buffer,  			event = rb_reader_event(cpu_buffer);  			/* Always keep the time extend and data together */  			size = rb_event_ts_length(event); -		} while (len > size); +		} while (len >= size);  		/* update bpage */  		local_set(&bpage->commit, pos); diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index c380612273b..f8cf959bad4 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2338,11 +2338,19 @@ tracing_write_stub(struct file *filp, const char __user *ubuf,  	return count;  } +static loff_t tracing_seek(struct file *file, loff_t offset, int origin) +{ +	if (file->f_mode & FMODE_READ) +		return seq_lseek(file, offset, origin); +	else +		return 0; +} +  static const struct file_operations tracing_fops = {  	.open		= tracing_open,  	.read		= seq_read,  	.write		= tracing_write_stub, -	.llseek		= seq_lseek, +	.llseek		= tracing_seek,  	.release	= tracing_release,  }; diff --git a/kernel/user.c b/kernel/user.c index 2c7d8d5914b..5c598ca781d 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -158,6 +158,7 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid)  		spin_lock_irq(&uidhash_lock);  		up = uid_hash_find(uid, hashent);  		if (up) { +			put_user_ns(ns);  			key_put(new->uid_keyring);  			key_put(new->session_keyring);  			kmem_cache_free(uid_cachep, new); diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 14b8120d523..c812c4927ca 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -364,7 +364,8 @@ static int watchdog_nmi_enable(int cpu)  		goto out_save;  	} -	printk(KERN_ERR "NMI watchdog failed to create perf event on cpu%i: %p\n", cpu, event); +	printk(KERN_ERR "NMI watchdog disabled for cpu%i: unable to create perf event: %ld\n", +	       cpu, PTR_ERR(event));  	return PTR_ERR(event);  	/* success path */ diff --git a/mm/compaction.c b/mm/compaction.c index 4d709ee5901..1a8894eadf7 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -279,7 +279,6 @@ static unsigned long isolate_migratepages(struct zone *zone,  		/* Successfully isolated */  		del_page_from_lru_list(zone, page, page_lru(page));  		list_add(&page->lru, migratelist); -		mem_cgroup_del_lru(page);  		cc->nr_migratepages++;  		/* Avoid isolating too much */ diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 7a22b412921..00bb8a64d02 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1925,19 +1925,18 @@ again:  		rcu_read_lock();  		p = rcu_dereference(mm->owner); -		VM_BUG_ON(!p);  		/* -		 * because we don't have task_lock(), "p" can exit while -		 * we're here. In that case, "mem" can point to root -		 * cgroup but never be NULL. (and task_struct itself is freed -		 * by RCU, cgroup itself is RCU safe.) Then, we have small -		 * risk here to get wrong cgroup. But such kind of mis-account -		 * by race always happens because we don't have cgroup_mutex(). -		 * It's overkill and we allow that small race, here. +		 * Because we don't have task_lock(), "p" can exit. +		 * In that case, "mem" can point to root or p can be NULL with +		 * race with swapoff. Then, we have small risk of mis-accouning. +		 * But such kind of mis-account by race always happens because +		 * we don't have cgroup_mutex(). It's overkill and we allo that +		 * small race, here. +		 * (*) swapoff at el will charge against mm-struct not against +		 * task-struct. So, mm->owner can be NULL.  		 */  		mem = mem_cgroup_from_task(p); -		VM_BUG_ON(!mem); -		if (mem_cgroup_is_root(mem)) { +		if (!mem || mem_cgroup_is_root(mem)) {  			rcu_read_unlock();  			goto done;  		} diff --git a/mm/migrate.c b/mm/migrate.c index fe5a3c6a542..6ae8a66a704 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -35,6 +35,8 @@  #include <linux/hugetlb.h>  #include <linux/gfp.h> +#include <asm/tlbflush.h> +  #include "internal.h"  #define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru)) diff --git a/mm/nommu.c b/mm/nommu.c index 27a9ac58851..ef4045d010d 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -10,7 +10,7 @@   *  Copyright (c) 2000-2003 David McCullough <davidm@snapgear.com>   *  Copyright (c) 2000-2001 D Jeff Dionne <jeff@uClinux.org>   *  Copyright (c) 2002      Greg Ungerer <gerg@snapgear.com> - *  Copyright (c) 2007-2009 Paul Mundt <lethal@linux-sh.org> + *  Copyright (c) 2007-2010 Paul Mundt <lethal@linux-sh.org>   */  #include <linux/module.h> @@ -328,6 +328,7 @@ void *vmalloc_node(unsigned long size, int node)  {  	return vmalloc(size);  } +EXPORT_SYMBOL(vmalloc_node);  /**   * vzalloc_node - allocate memory on a specific node with zero fill @@ -440,6 +441,31 @@ void  __attribute__((weak)) vmalloc_sync_all(void)  {  } +/** + *	alloc_vm_area - allocate a range of kernel address space + *	@size:		size of the area + * + *	Returns:	NULL on failure, vm_struct on success + * + *	This function reserves a range of kernel address space, and + *	allocates pagetables to map that range.  No actual mappings + *	are created.  If the kernel address space is not shared + *	between processes, it syncs the pagetable across all + *	processes. + */ +struct vm_struct *alloc_vm_area(size_t size) +{ +	BUG(); +	return NULL; +} +EXPORT_SYMBOL_GPL(alloc_vm_area); + +void free_vm_area(struct vm_struct *area) +{ +	BUG(); +} +EXPORT_SYMBOL_GPL(free_vm_area); +  int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,  		   struct page *page)  { diff --git a/mm/page-writeback.c b/mm/page-writeback.c index b840afa8976..b4edfe7ce06 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -563,7 +563,7 @@ static void balance_dirty_pages(struct address_space *mapping,  				break;		/* We've done our duty */  		}  		trace_wbc_balance_dirty_wait(&wbc, bdi); -		__set_current_state(TASK_INTERRUPTIBLE); +		__set_current_state(TASK_UNINTERRUPTIBLE);  		io_schedule_timeout(pause);  		/* diff --git a/mm/percpu.c b/mm/percpu.c index efe816856a9..02ba91230b9 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -1268,7 +1268,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,  	/* we're done parsing the input, undefine BUG macro and dump config */  #undef PCPU_SETUP_BUG_ON -	pcpu_dump_alloc_info(KERN_INFO, ai); +	pcpu_dump_alloc_info(KERN_DEBUG, ai);  	pcpu_nr_groups = ai->nr_groups;  	pcpu_group_offsets = group_offsets; diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index fa642aa652b..432a9a633e8 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -311,6 +311,7 @@ static void rfcomm_dlc_clear_state(struct rfcomm_dlc *d)  	d->state      = BT_OPEN;  	d->flags      = 0;  	d->mscex      = 0; +	d->sec_level  = BT_SECURITY_LOW;  	d->mtu        = RFCOMM_DEFAULT_MTU;  	d->v24_sig    = RFCOMM_V24_RTC | RFCOMM_V24_RTR | RFCOMM_V24_DV; diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index eb5b256ffc8..543b3262d00 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -437,7 +437,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,  	ip6h = ipv6_hdr(skb);  	*(__force __be32 *)ip6h = htonl(0x60000000); -	ip6h->payload_len = 8 + sizeof(*mldq); +	ip6h->payload_len = htons(8 + sizeof(*mldq));  	ip6h->nexthdr = IPPROTO_HOPOPTS;  	ip6h->hop_limit = 1;  	ipv6_addr_set(&ip6h->saddr, 0, 0, 0, 0); @@ -1430,7 +1430,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,  				 struct net_bridge_port *port,  				 struct sk_buff *skb)  { -	struct sk_buff *skb2 = skb; +	struct sk_buff *skb2;  	struct ipv6hdr *ip6h;  	struct icmp6hdr *icmp6h;  	u8 nexthdr; @@ -1469,15 +1469,15 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,  	if (!skb2)  		return -ENOMEM; +	err = -EINVAL; +	if (!pskb_may_pull(skb2, offset + sizeof(struct icmp6hdr))) +		goto out; +  	len -= offset - skb_network_offset(skb2);  	__skb_pull(skb2, offset);  	skb_reset_transport_header(skb2); -	err = -EINVAL; -	if (!pskb_may_pull(skb2, sizeof(*icmp6h))) -		goto out; -  	icmp6h = icmp6_hdr(skb2);  	switch (icmp6h->icmp6_type) { @@ -1516,7 +1516,12 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,  	switch (icmp6h->icmp6_type) {  	case ICMPV6_MGM_REPORT:  	    { -		struct mld_msg *mld = (struct mld_msg *)icmp6h; +		struct mld_msg *mld; +		if (!pskb_may_pull(skb2, sizeof(*mld))) { +			err = -EINVAL; +			goto out; +		} +		mld = (struct mld_msg *)skb_transport_header(skb2);  		BR_INPUT_SKB_CB(skb2)->mrouters_only = 1;  		err = br_ip6_multicast_add_group(br, port, &mld->mld_mca);  		break; @@ -1529,15 +1534,18 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,  		break;  	case ICMPV6_MGM_REDUCTION:  	    { -		struct mld_msg *mld = (struct mld_msg *)icmp6h; +		struct mld_msg *mld; +		if (!pskb_may_pull(skb2, sizeof(*mld))) { +			err = -EINVAL; +			goto out; +		} +		mld = (struct mld_msg *)skb_transport_header(skb2);  		br_ip6_multicast_leave_group(br, port, &mld->mld_mca);  	    }  	}  out: -	__skb_push(skb2, offset); -	if (skb2 != skb) -		kfree_skb(skb2); +	kfree_skb(skb2);  	return err;  }  #endif diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index 35cf27087b5..e3d7aefa918 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c @@ -50,6 +50,8 @@ static void br_send_bpdu(struct net_bridge_port *p,  	llc_mac_hdr_init(skb, p->dev->dev_addr, p->br->group_addr); +	skb_reset_mac_header(skb); +  	NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,  		dev_queue_xmit);  } diff --git a/net/can/bcm.c b/net/can/bcm.c index 6faa8256e10..9d5e8accfab 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -125,7 +125,7 @@ struct bcm_sock {  	struct list_head tx_ops;  	unsigned long dropped_usr_msgs;  	struct proc_dir_entry *bcm_proc_read; -	char procname [20]; /* pointer printed in ASCII with \0 */ +	char procname [32]; /* inode number in decimal with \0 */  };  static inline struct bcm_sock *bcm_sk(const struct sock *sk) @@ -1521,7 +1521,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,  	if (proc_dir) {  		/* unique socket address as filename */ -		sprintf(bo->procname, "%p", sock); +		sprintf(bo->procname, "%lu", sock_i_ino(sk));  		bo->bcm_proc_read = proc_create_data(bo->procname, 0644,  						     proc_dir,  						     &bcm_proc_fops, sk); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 1c7a2ec4f3c..b6ff4a1519a 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -97,11 +97,9 @@ struct workqueue_struct *ceph_msgr_wq;  int ceph_msgr_init(void)  {  	ceph_msgr_wq = create_workqueue("ceph-msgr"); -	if (IS_ERR(ceph_msgr_wq)) { -		int ret = PTR_ERR(ceph_msgr_wq); -		pr_err("msgr_init failed to create workqueue: %d\n", ret); -		ceph_msgr_wq = NULL; -		return ret; +	if (!ceph_msgr_wq) { +		pr_err("msgr_init failed to create workqueue\n"); +		return -ENOMEM;  	}  	return 0;  } diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c index ac34feeb2b3..1a040e64c69 100644 --- a/net/ceph/pagevec.c +++ b/net/ceph/pagevec.c @@ -13,7 +13,7 @@   * build a vector of user pages   */  struct page **ceph_get_direct_page_vector(const char __user *data, -					  int num_pages) +					  int num_pages, bool write_page)  {  	struct page **pages;  	int rc; @@ -24,24 +24,27 @@ struct page **ceph_get_direct_page_vector(const char __user *data,  	down_read(¤t->mm->mmap_sem);  	rc = get_user_pages(current, current->mm, (unsigned long)data, -			    num_pages, 0, 0, pages, NULL); +			    num_pages, write_page, 0, pages, NULL);  	up_read(¤t->mm->mmap_sem); -	if (rc < 0) +	if (rc < num_pages)  		goto fail;  	return pages;  fail: -	kfree(pages); +	ceph_put_page_vector(pages, rc > 0 ? rc : 0, false);  	return ERR_PTR(rc);  }  EXPORT_SYMBOL(ceph_get_direct_page_vector); -void ceph_put_page_vector(struct page **pages, int num_pages) +void ceph_put_page_vector(struct page **pages, int num_pages, bool dirty)  {  	int i; -	for (i = 0; i < num_pages; i++) +	for (i = 0; i < num_pages; i++) { +		if (dirty) +			set_page_dirty_lock(pages[i]);  		put_page(pages[i]); +	}  	kfree(pages);  }  EXPORT_SYMBOL(ceph_put_page_vector); diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 82a4369ae15..a20e5d3bbfa 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -181,8 +181,7 @@ static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,  {  	int ret = 0; -	if (rule->iifindex && (rule->iifindex != fl->iif) && -	    !(fl->flags & FLOWI_FLAG_MATCH_ANY_IIF)) +	if (rule->iifindex && (rule->iifindex != fl->iif))  		goto out;  	if (rule->oifindex && (rule->oifindex != fl->oif)) diff --git a/net/core/sock.c b/net/core/sock.c index fb608011146..e5af8d5d5b5 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1009,6 +1009,36 @@ static void sock_copy(struct sock *nsk, const struct sock *osk)  #endif  } +/* + * caches using SLAB_DESTROY_BY_RCU should let .next pointer from nulls nodes + * un-modified. Special care is taken when initializing object to zero. + */ +static inline void sk_prot_clear_nulls(struct sock *sk, int size) +{ +	if (offsetof(struct sock, sk_node.next) != 0) +		memset(sk, 0, offsetof(struct sock, sk_node.next)); +	memset(&sk->sk_node.pprev, 0, +	       size - offsetof(struct sock, sk_node.pprev)); +} + +void sk_prot_clear_portaddr_nulls(struct sock *sk, int size) +{ +	unsigned long nulls1, nulls2; + +	nulls1 = offsetof(struct sock, __sk_common.skc_node.next); +	nulls2 = offsetof(struct sock, __sk_common.skc_portaddr_node.next); +	if (nulls1 > nulls2) +		swap(nulls1, nulls2); + +	if (nulls1 != 0) +		memset((char *)sk, 0, nulls1); +	memset((char *)sk + nulls1 + sizeof(void *), 0, +	       nulls2 - nulls1 - sizeof(void *)); +	memset((char *)sk + nulls2 + sizeof(void *), 0, +	       size - nulls2 - sizeof(void *)); +} +EXPORT_SYMBOL(sk_prot_clear_portaddr_nulls); +  static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,  		int family)  { @@ -1021,19 +1051,12 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,  		if (!sk)  			return sk;  		if (priority & __GFP_ZERO) { -			/* -			 * caches using SLAB_DESTROY_BY_RCU should let -			 * sk_node.next un-modified. Special care is taken -			 * when initializing object to zero. -			 */ -			if (offsetof(struct sock, sk_node.next) != 0) -				memset(sk, 0, offsetof(struct sock, sk_node.next)); -			memset(&sk->sk_node.pprev, 0, -			       prot->obj_size - offsetof(struct sock, -							 sk_node.pprev)); +			if (prot->clear_sk) +				prot->clear_sk(sk, prot->obj_size); +			else +				sk_prot_clear_nulls(sk, prot->obj_size);  		} -	} -	else +	} else  		sk = kmalloc(prot->obj_size, priority);  	if (sk != NULL) { diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index eb6f69a8f27..c19c1f739fb 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -163,13 +163,19 @@ struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)  				.daddr = addr  			}  		}, -		.flags = FLOWI_FLAG_MATCH_ANY_IIF  	};  	struct fib_result res = { 0 };  	struct net_device *dev = NULL; +	struct fib_table *local_table; + +#ifdef CONFIG_IP_MULTIPLE_TABLES +	res.r = NULL; +#endif  	rcu_read_lock(); -	if (fib_lookup(net, &fl, &res)) { +	local_table = fib_get_table(net, RT_TABLE_LOCAL); +	if (!local_table || +	    fib_table_lookup(local_table, &fl, &res, FIB_LOOKUP_NOREF)) {  		rcu_read_unlock();  		return NULL;  	} diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 987bf9adb31..93bfd95584f 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2585,9 +2585,10 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,  			goto out;  		/* RACE: Check return value of inet_select_addr instead. */ -		if (rcu_dereference(dev_out->ip_ptr) == NULL) -			goto out;	/* Wrong error code */ - +		if (!(dev_out->flags & IFF_UP) || !__in_dev_get_rcu(dev_out)) { +			err = -ENETUNREACH; +			goto out; +		}  		if (ipv4_is_local_multicast(oldflp->fl4_dst) ||  		    ipv4_is_lbcast(oldflp->fl4_dst)) {  			if (!fl.fl4_src) @@ -2648,8 +2649,12 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,  	}  	if (res.type == RTN_LOCAL) { -		if (!fl.fl4_src) -			fl.fl4_src = fl.fl4_dst; +		if (!fl.fl4_src) { +			if (res.fi->fib_prefsrc) +				fl.fl4_src = res.fi->fib_prefsrc; +			else +				fl.fl4_src = fl.fl4_dst; +		}  		dev_out = net->loopback_dev;  		fl.oif = dev_out->ifindex;  		res.fi = NULL; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index e13da6de1fc..d978bb2f748 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2030,7 +2030,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)  get_req:  			req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket];  		} -		sk	  = sk_next(st->syn_wait_sk); +		sk	  = sk_nulls_next(st->syn_wait_sk);  		st->state = TCP_SEQ_STATE_LISTENING;  		read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);  	} else { @@ -2039,7 +2039,7 @@ get_req:  		if (reqsk_queue_len(&icsk->icsk_accept_queue))  			goto start_req;  		read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock); -		sk = sk_next(sk); +		sk = sk_nulls_next(sk);  	}  get_sk:  	sk_nulls_for_each_from(sk, node) { diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 5e0a3a582a5..2d3ded4d078 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1899,6 +1899,7 @@ struct proto udp_prot = {  	.compat_setsockopt = compat_udp_setsockopt,  	.compat_getsockopt = compat_udp_getsockopt,  #endif +	.clear_sk	   = sk_prot_clear_portaddr_nulls,  };  EXPORT_SYMBOL(udp_prot); diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c index ab76aa928fa..aee9963f7f5 100644 --- a/net/ipv4/udplite.c +++ b/net/ipv4/udplite.c @@ -57,6 +57,7 @@ struct proto 	udplite_prot = {  	.compat_setsockopt = compat_udp_setsockopt,  	.compat_getsockopt = compat_udp_getsockopt,  #endif +	.clear_sk	   = sk_prot_clear_portaddr_nulls,  };  EXPORT_SYMBOL(udplite_prot); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 93b7a933a77..848b3559104 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2669,7 +2669,9 @@ static int addrconf_ifdown(struct net_device *dev, int how)  	ASSERT_RTNL(); -	rt6_ifdown(net, dev); +	/* Flush routes if device is being removed or it is not loopback */ +	if (how || !(dev->flags & IFF_LOOPBACK)) +		rt6_ifdown(net, dev);  	neigh_ifdown(&nd_tbl, dev);  	idev = __in6_dev_get(dev); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 99157b4cd56..94b5bf132b2 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -56,7 +56,7 @@  #include <net/checksum.h>  #include <linux/mroute6.h> -static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); +int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));  int __ip6_local_out(struct sk_buff *skb)  { @@ -145,14 +145,6 @@ static int ip6_finish_output2(struct sk_buff *skb)  	return -EINVAL;  } -static inline int ip6_skb_dst_mtu(struct sk_buff *skb) -{ -	struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; - -	return (np && np->pmtudisc == IPV6_PMTUDISC_PROBE) ? -	       skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); -} -  static int ip6_finish_output(struct sk_buff *skb)  {  	if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || @@ -601,7 +593,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)  	return offset;  } -static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) +int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))  {  	struct sk_buff *frag;  	struct rt6_info *rt = (struct rt6_info*)skb_dst(skb); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 96455ffb76f..7659d6f16e6 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1565,11 +1565,16 @@ static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr,  {  	struct rt6_info *rt, *nrt;  	int allfrag = 0; - +again:  	rt = rt6_lookup(net, daddr, saddr, ifindex, 0);  	if (rt == NULL)  		return; +	if (rt6_check_expired(rt)) { +		ip6_del_rt(rt); +		goto again; +	} +  	if (pmtu >= dst_mtu(&rt->dst))  		goto out; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 91def93bec8..cd6cb7c3e56 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1477,6 +1477,7 @@ struct proto udpv6_prot = {  	.compat_setsockopt = compat_udpv6_setsockopt,  	.compat_getsockopt = compat_udpv6_getsockopt,  #endif +	.clear_sk	   = sk_prot_clear_portaddr_nulls,  };  static struct inet_protosw udpv6_protosw = { diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index 5f48fadc27f..986c4de5292 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c @@ -55,6 +55,7 @@ struct proto udplitev6_prot = {  	.compat_setsockopt = compat_udpv6_setsockopt,  	.compat_getsockopt = compat_udpv6_getsockopt,  #endif +	.clear_sk	   = sk_prot_clear_portaddr_nulls,  };  static struct inet_protosw udplite6_protosw = { diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 6434bd5ce08..8e688b3de9a 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -17,6 +17,7 @@  #include <linux/netfilter_ipv6.h>  #include <net/dst.h>  #include <net/ipv6.h> +#include <net/ip6_route.h>  #include <net/xfrm.h>  int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, @@ -88,8 +89,21 @@ static int xfrm6_output_finish(struct sk_buff *skb)  	return xfrm_output(skb);  } +static int __xfrm6_output(struct sk_buff *skb) +{ +	struct dst_entry *dst = skb_dst(skb); +	struct xfrm_state *x = dst->xfrm; + +	if ((x && x->props.mode == XFRM_MODE_TUNNEL) && +	    ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || +		dst_allfrag(skb_dst(skb)))) { +			return ip6_fragment(skb, xfrm6_output_finish); +	} +	return xfrm6_output_finish(skb); +} +  int xfrm6_output(struct sk_buff *skb)  {  	return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, -		       skb_dst(skb)->dev, xfrm6_output_finish); +		       skb_dst(skb)->dev, __xfrm6_output);  } diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index a6de3059746..c9890e25cd4 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -2280,6 +2280,16 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,  	switch (optname) {  	case IRLMP_ENUMDEVICES: + +		/* Offset to first device entry */ +		offset = sizeof(struct irda_device_list) - +			sizeof(struct irda_device_info); + +		if (len < offset) { +			err = -EINVAL; +			goto out; +		} +  		/* Ask lmp for the current discovery log */  		discoveries = irlmp_get_discoveries(&list.len, self->mask.word,  						    self->nslots); @@ -2290,15 +2300,9 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,  		}  		/* Write total list length back to client */ -		if (copy_to_user(optval, &list, -				 sizeof(struct irda_device_list) - -				 sizeof(struct irda_device_info))) +		if (copy_to_user(optval, &list, offset))  			err = -EFAULT; -		/* Offset to first device entry */ -		offset = sizeof(struct irda_device_list) - -			sizeof(struct irda_device_info); -  		/* Copy the list itself - watch for overflow */  		if (list.len > 2048) {  			err = -EINVAL; diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 239c4836a94..077a93dd167 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -780,6 +780,9 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,  	mutex_lock(&sdata->u.ibss.mtx); +	if (!sdata->u.ibss.ssid_len) +		goto mgmt_out; /* not ready to merge yet */ +  	switch (fc & IEEE80211_FCTL_STYPE) {  	case IEEE80211_STYPE_PROBE_REQ:  		ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len); @@ -797,6 +800,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,  		break;  	} + mgmt_out:  	mutex_unlock(&sdata->u.ibss.mtx);  } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 54fb4a0e76f..b01e467b76c 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1788,9 +1788,11 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)  			fwd_skb = skb_copy(skb, GFP_ATOMIC); -			if (!fwd_skb && net_ratelimit()) +			if (!fwd_skb && net_ratelimit()) {  				printk(KERN_DEBUG "%s: failed to clone mesh frame\n",  						   sdata->name); +				goto out; +			}  			fwd_hdr =  (struct ieee80211_hdr *) fwd_skb->data;  			memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); @@ -1828,6 +1830,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)  		}  	} + out:  	if (is_multicast_ether_addr(hdr->addr1) ||  	    sdata->dev->flags & IFF_PROMISC)  		return RX_CONTINUE; diff --git a/net/mac80211/work.c b/net/mac80211/work.c index ae344d1ba05..146097cb43a 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -1051,11 +1051,13 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)  {  	struct ieee80211_local *local = sdata->local;  	struct ieee80211_work *wk; +	bool cleanup = false;  	mutex_lock(&local->mtx);  	list_for_each_entry(wk, &local->work_list, list) {  		if (wk->sdata != sdata)  			continue; +		cleanup = true;  		wk->type = IEEE80211_WORK_ABORT;  		wk->started = true;  		wk->timeout = jiffies; @@ -1063,7 +1065,8 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)  	mutex_unlock(&local->mtx);  	/* run cleanups etc. */ -	ieee80211_work_work(&local->work_work); +	if (cleanup) +		ieee80211_work_work(&local->work_work);  	mutex_lock(&local->mtx);  	list_for_each_entry(wk, &local->work_list, list) { diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 3cf478d012d..7150705f1d0 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -270,7 +270,6 @@ static unsigned int sfq_drop(struct Qdisc *sch)  		/* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */  		d = q->next[q->tail];  		q->next[q->tail] = q->next[d]; -		q->allot[q->next[d]] += q->quantum;  		skb = q->qs[d].prev;  		len = qdisc_pkt_len(skb);  		__skb_unlink(skb, &q->qs[d]); @@ -321,14 +320,13 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)  	sfq_inc(q, x);  	if (q->qs[x].qlen == 1) {		/* The flow is new */  		if (q->tail == SFQ_DEPTH) {	/* It is the first flow */ -			q->tail = x;  			q->next[x] = x; -			q->allot[x] = q->quantum;  		} else {  			q->next[x] = q->next[q->tail];  			q->next[q->tail] = x; -			q->tail = x;  		} +		q->tail = x; +		q->allot[x] = q->quantum;  	}  	if (++sch->q.qlen <= q->limit) {  		sch->bstats.bytes += qdisc_pkt_len(skb); @@ -359,13 +357,13 @@ sfq_dequeue(struct Qdisc *sch)  {  	struct sfq_sched_data *q = qdisc_priv(sch);  	struct sk_buff *skb; -	sfq_index a, old_a; +	sfq_index a, next_a;  	/* No active slots */  	if (q->tail == SFQ_DEPTH)  		return NULL; -	a = old_a = q->next[q->tail]; +	a = q->next[q->tail];  	/* Grab packet */  	skb = __skb_dequeue(&q->qs[a]); @@ -376,17 +374,15 @@ sfq_dequeue(struct Qdisc *sch)  	/* Is the slot empty? */  	if (q->qs[a].qlen == 0) {  		q->ht[q->hash[a]] = SFQ_DEPTH; -		a = q->next[a]; -		if (a == old_a) { +		next_a = q->next[a]; +		if (a == next_a) {  			q->tail = SFQ_DEPTH;  			return skb;  		} -		q->next[q->tail] = a; -		q->allot[a] += q->quantum; +		q->next[q->tail] = next_a;  	} else if ((q->allot[a] -= qdisc_pkt_len(skb)) <= 0) { -		q->tail = a; -		a = q->next[a];  		q->allot[a] += q->quantum; +		q->tail = a;  	}  	return skb;  } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 0b9ee34ad35..fff0926b111 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -5053,7 +5053,7 @@ static int sctp_getsockopt_partial_delivery_point(struct sock *sk, int len,  	if (copy_to_user(optval, &val, len))  		return -EFAULT; -	return -ENOTSUPP; +	return 0;  }  /* diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index b9d9aa18e6d..5f77dcb8977 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -140,6 +140,20 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e  		}  		if (current_entry->prompt && current_entry != &rootmenu)  			prop_warn(prop, "prompt redefined"); + +		/* Apply all upper menus' visibilities to actual prompts. */ +		if(type == P_PROMPT) { +			struct menu *menu = current_entry; + +			while ((menu = menu->parent) != NULL) { +				if (!menu->visibility) +					continue; +				prop->visible.expr +					= expr_alloc_and(prop->visible.expr, +							 menu->visibility); +			} +		} +  		current_entry->prompt = prop;  	}  	prop->text = prompt; diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h index 58e933a2054..39667174971 100644 --- a/scripts/recordmcount.h +++ b/scripts/recordmcount.h @@ -119,7 +119,7 @@ static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM;  static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)  { -	rp->r_info = ELF_R_INFO(sym, type); +	rp->r_info = _w(ELF_R_INFO(sym, type));  }  static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO; diff --git a/scripts/tags.sh b/scripts/tags.sh index 8509bb51293..bbbe584d449 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -125,7 +125,9 @@ exuberant()  	-I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \  	--extra=+f --c-kinds=-px                                \  	--regex-asm='/^ENTRY\(([^)]*)\).*/\1/'                  \ -	--regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' +	--regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ +	--regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/'		\ +	--regex-c++='/^DEFINE_EVENT\(([^,)]*).*/trace_\1/'  	all_kconfigs | xargs $1 -a                              \  	--langdef=kconfig --language-force=kconfig              \ diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index aef8c0a923a..d661afbe474 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -253,6 +253,8 @@ static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry,  	result = security_filter_rule_init(entry->lsm[lsm_rule].type,  					   Audit_equal, args,  					   &entry->lsm[lsm_rule].rule); +	if (!entry->lsm[lsm_rule].rule) +		return -EINVAL;  	return result;  } diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 0088dd8bf68..0ea52d25a6b 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -403,7 +403,6 @@ link_check_failed:  	return ret;  link_prealloc_failed: -	up_write(&dest_keyring->sem);  	mutex_unlock(&user->cons_lock);  	kleave(" = %d [prelink]", ret);  	return ret; diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index b75db8e9cc0..11446a1506d 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1070,8 +1070,10 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,  		struct snd_pcm_hw_rule *new;  		unsigned int new_rules = constrs->rules_all + 16;  		new = kcalloc(new_rules, sizeof(*c), GFP_KERNEL); -		if (!new) +		if (!new) { +			va_end(args);  			return -ENOMEM; +		}  		if (constrs->rules) {  			memcpy(new, constrs->rules,  			       constrs->rules_num * sizeof(*c)); @@ -1087,8 +1089,10 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,  	c->private = private;  	k = 0;  	while (1) { -		if (snd_BUG_ON(k >= ARRAY_SIZE(c->deps))) +		if (snd_BUG_ON(k >= ARRAY_SIZE(c->deps))) { +			va_end(args);  			return -EINVAL; +		}  		c->deps[k++] = dep;  		if (dep < 0)  			break; @@ -1097,7 +1101,7 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,  	constrs->rules_num++;  	va_end(args);  	return 0; -}				     +}  EXPORT_SYMBOL(snd_pcm_hw_rule_add); diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index 46c0d03dbec..fcb14a09982 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c @@ -87,7 +87,7 @@ int *load_mixer_volumes(char *name, int *levels, int present)  	int             i, n;  	for (i = 0; i < num_mixer_volumes; i++) { -		if (strcmp(name, mixer_vols[i].name) == 0) { +		if (strncmp(name, mixer_vols[i].name, 32) == 0) {  			if (present)  				mixer_vols[i].num = i;  			return mixer_vols[i].levels; @@ -99,7 +99,7 @@ int *load_mixer_volumes(char *name, int *levels, int present)  	}  	n = num_mixer_volumes++; -	strcpy(mixer_vols[n].name, name); +	strncpy(mixer_vols[n].name, name, 32);  	if (present)  		mixer_vols[n].num = n; diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 644e3f14f8c..98b6d02a36c 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1919,6 +1919,16 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,  }  EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); +static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name) +{ +	int idx; +	for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */ +		if (!_snd_hda_find_mixer_ctl(codec, name, idx)) +			return idx; +	} +	return -EBUSY; +} +  /**   * snd_hda_ctl_add - Add a control element and assign to the codec   * @codec: HD-audio codec @@ -2654,8 +2664,6 @@ static struct snd_kcontrol_new dig_mixes[] = {  	{ } /* end */  }; -#define SPDIF_MAX_IDX	4	/* 4 instances should be enough to probe */ -  /**   * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls   * @codec: the HDA codec @@ -2673,12 +2681,8 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)  	struct snd_kcontrol_new *dig_mix;  	int idx; -	for (idx = 0; idx < SPDIF_MAX_IDX; idx++) { -		if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch", -					     idx)) -			break; -	} -	if (idx >= SPDIF_MAX_IDX) { +	idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch"); +	if (idx < 0) {  		printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");  		return -EBUSY;  	} @@ -2829,12 +2833,8 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)  	struct snd_kcontrol_new *dig_mix;  	int idx; -	for (idx = 0; idx < SPDIF_MAX_IDX; idx++) { -		if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch", -					     idx)) -			break; -	} -	if (idx >= SPDIF_MAX_IDX) { +	idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch"); +	if (idx < 0) {  		printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");  		return -EBUSY;  	} @@ -3808,21 +3808,32 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)  	for (; knew->name; knew++) {  		struct snd_kcontrol *kctl; +		int addr = 0, idx = 0;  		if (knew->iface == -1)	/* skip this codec private value */  			continue; -		kctl = snd_ctl_new1(knew, codec); -		if (!kctl) -			return -ENOMEM; -		err = snd_hda_ctl_add(codec, 0, kctl); -		if (err < 0) { -			if (!codec->addr) -				return err; +		for (;;) {  			kctl = snd_ctl_new1(knew, codec);  			if (!kctl)  				return -ENOMEM; -			kctl->id.device = codec->addr; +			if (addr > 0) +				kctl->id.device = addr; +			if (idx > 0) +				kctl->id.index = idx;  			err = snd_hda_ctl_add(codec, 0, kctl); -			if (err < 0) +			if (!err) +				break; +			/* try first with another device index corresponding to +			 * the codec addr; if it still fails (or it's the +			 * primary codec), then try another control index +			 */ +			if (!addr && codec->addr) +				addr = codec->addr; +			else if (!idx && !knew->index) { +				idx = find_empty_mixer_ctl_idx(codec, +							       knew->name); +				if (idx <= 0) +					return err; +			} else  				return err;  		}  	} diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index b030c8eba21..a1c4008af89 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2300,6 +2300,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {  	SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),  	SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),  	SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB), +	SND_PCI_QUIRK(0x1028, 0x0470, "Dell Inspiron 1120", POS_FIX_LPIB),  	SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),  	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),  	SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2d7d7de8498..552a09e9211 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -10830,7 +10830,8 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)  {  	struct alc_spec *spec = codec->spec;  	struct auto_pin_cfg *cfg = &spec->autocfg; -	int i, err; +	int i, err, type; +	int type_idx = 0;  	hda_nid_t nid;  	for (i = 0; i < cfg->num_inputs; i++) { @@ -10839,9 +10840,15 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)  		nid = cfg->inputs[i].pin;  		if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {  			char label[32]; +			type = cfg->inputs[i].type; +			if (i > 0 && type == cfg->inputs[i - 1].type) +				type_idx++; +			else +				type_idx = 0;  			snprintf(label, sizeof(label), "%s Boost",  				 hda_get_autocfg_input_label(codec, cfg, i)); -			err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0, +			err = add_control(spec, ALC_CTL_WIDGET_VOL, label, +					  type_idx,  				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));  			if (err < 0)  				return err; @@ -14799,7 +14806,10 @@ static int alc269_resume(struct hda_codec *codec)  enum {  	ALC269_FIXUP_SONY_VAIO, +	ALC275_FIX_SONY_VAIO_GPIO2,  	ALC269_FIXUP_DELL_M101Z, +	ALC269_FIXUP_SKU_IGNORE, +	ALC269_FIXUP_ASUS_G73JW,  };  static const struct alc_fixup alc269_fixups[] = { @@ -14809,6 +14819,14 @@ static const struct alc_fixup alc269_fixups[] = {  			{}  		}  	}, +	[ALC275_FIX_SONY_VAIO_GPIO2] = { +		.verbs = (const struct hda_verb[]) { +			{0x01, AC_VERB_SET_GPIO_MASK, 0x04}, +			{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04}, +			{0x01, AC_VERB_SET_GPIO_DATA, 0x00}, +			{ } +		} +	},  	[ALC269_FIXUP_DELL_M101Z] = {  		.verbs = (const struct hda_verb[]) {  			/* Enables internal speaker */ @@ -14817,11 +14835,26 @@ static const struct alc_fixup alc269_fixups[] = {  			{}  		}  	}, +	[ALC269_FIXUP_SKU_IGNORE] = { +		.sku = ALC_FIXUP_SKU_IGNORE, +	}, +	[ALC269_FIXUP_ASUS_G73JW] = { +		.pins = (const struct alc_pincfg[]) { +			{ 0x17, 0x99130111 }, /* subwoofer */ +			{ } +		} +	},  };  static struct snd_pci_quirk alc269_fixup_tbl[] = { +	SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIX_SONY_VAIO_GPIO2), +	SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIX_SONY_VAIO_GPIO2), +	SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIX_SONY_VAIO_GPIO2),  	SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),  	SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), +	SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), +	SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), +	SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),  	{}  }; @@ -15071,28 +15104,29 @@ static int patch_alc269(struct hda_codec *codec)  	alc_auto_parse_customize_define(codec); -	coef = alc_read_coef_idx(codec, 0); -	if ((coef & 0x00f0) == 0x0010) { -		if (codec->bus->pci->subsystem_vendor == 0x1025 && -		    spec->cdefine.platform_type == 1) { -			alc_codec_rename(codec, "ALC271X"); -			spec->codec_variant = ALC269_TYPE_ALC271X; -		} else if ((coef & 0xf000) == 0x1000) { -			spec->codec_variant = ALC269_TYPE_ALC270; -		} else if ((coef & 0xf000) == 0x2000) { -			alc_codec_rename(codec, "ALC259"); -			spec->codec_variant = ALC269_TYPE_ALC259; -		} else if ((coef & 0xf000) == 0x3000) { -			alc_codec_rename(codec, "ALC258"); -			spec->codec_variant = ALC269_TYPE_ALC258; -		} else { -			alc_codec_rename(codec, "ALC269VB"); -			spec->codec_variant = ALC269_TYPE_ALC269VB; -		} -	} else -		alc_fix_pll_init(codec, 0x20, 0x04, 15); - -	alc269_fill_coef(codec); +	if (codec->vendor_id == 0x10ec0269) { +		coef = alc_read_coef_idx(codec, 0); +		if ((coef & 0x00f0) == 0x0010) { +			if (codec->bus->pci->subsystem_vendor == 0x1025 && +			    spec->cdefine.platform_type == 1) { +				alc_codec_rename(codec, "ALC271X"); +				spec->codec_variant = ALC269_TYPE_ALC271X; +			} else if ((coef & 0xf000) == 0x1000) { +				spec->codec_variant = ALC269_TYPE_ALC270; +			} else if ((coef & 0xf000) == 0x2000) { +				alc_codec_rename(codec, "ALC259"); +				spec->codec_variant = ALC269_TYPE_ALC259; +			} else if ((coef & 0xf000) == 0x3000) { +				alc_codec_rename(codec, "ALC258"); +				spec->codec_variant = ALC269_TYPE_ALC258; +			} else { +				alc_codec_rename(codec, "ALC269VB"); +				spec->codec_variant = ALC269_TYPE_ALC269VB; +			} +		} else +			alc_fix_pll_init(codec, 0x20, 0x04, 15); +		alc269_fill_coef(codec); +	}  	board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,  						  alc269_models, diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index efa4225f5fd..f03b2ff9049 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -3481,6 +3481,8 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,  		label = hda_get_input_pin_label(codec, nid, 1);  		snd_hda_add_imux_item(dimux, label, index, &type_idx); +		if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) +			snd_hda_add_imux_item(imux, label, index, &type_idx);  		err = create_elem_capture_vol(codec, nid, label, type_idx,  					      HDA_INPUT); @@ -3492,9 +3494,6 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,  			if (err < 0)  				return err;  		} - -		if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) -			snd_hda_add_imux_item(imux, label, index, NULL);  	}  	return 0; diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index d63e28773eb..6447dbb2f12 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -40,7 +40,6 @@ struct max98088_cdata {  };  struct max98088_priv { -       u8 reg_cache[M98088_REG_CNT];         enum max98088_type devtype;         void *control_data;         struct max98088_pdata *pdata; @@ -1588,7 +1587,7 @@ static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai,  static void max98088_sync_cache(struct snd_soc_codec *codec)  { -       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); +       u16 *reg_cache = codec->reg_cache;         int i;         if (!codec->cache_sync) @@ -1599,14 +1598,14 @@ static void max98088_sync_cache(struct snd_soc_codec *codec)         /* write back cached values if they're writeable and          * different from the hardware default.          */ -       for (i = 1; i < ARRAY_SIZE(max98088->reg_cache); i++) { +       for (i = 1; i < codec->driver->reg_cache_size; i++) {                 if (!max98088_access[i].writable)                         continue; -               if (max98088->reg_cache[i] == max98088_reg[i]) +               if (reg_cache[i] == max98088_reg[i])                         continue; -               snd_soc_write(codec, i, max98088->reg_cache[i]); +               snd_soc_write(codec, i, reg_cache[i]);         }         codec->cache_sync = 0; @@ -1951,7 +1950,6 @@ static int max98088_probe(struct snd_soc_codec *codec)         int ret = 0;         codec->cache_sync = 1; -       memcpy(codec->reg_cache, max98088_reg, sizeof(max98088_reg));         ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);         if (ret != 0) { diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 9a433a5396c..deca79ea2b4 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -41,7 +41,6 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {  /* codec private data */  struct wm8523_priv {  	enum snd_soc_control_type control_type; -	u16 reg_cache[WM8523_REGISTER_COUNT];  	struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];  	unsigned int sysclk;  	unsigned int rate_constraint_list[WM8523_NUM_RATES]; @@ -314,6 +313,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec,  				 enum snd_soc_bias_level level)  {  	struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); +	u16 *reg_cache = codec->reg_cache;  	int ret, i;  	switch (level) { @@ -344,7 +344,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec,  			/* Sync back default/cached values */  			for (i = WM8523_AIF_CTRL1;  			     i < WM8523_MAX_REGISTER; i++) -				snd_soc_write(codec, i, wm8523->reg_cache[i]); +				snd_soc_write(codec, i, reg_cache[i]);  			msleep(100); @@ -414,6 +414,7 @@ static int wm8523_resume(struct snd_soc_codec *codec)  static int wm8523_probe(struct snd_soc_codec *codec)  {  	struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); +	u16 *reg_cache = codec->reg_cache;  	int ret, i;  	codec->hw_write = (hw_write_t)i2c_master_send; @@ -470,8 +471,8 @@ static int wm8523_probe(struct snd_soc_codec *codec)  	}  	/* Change some default settings - latch VU and enable ZC */ -	wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; -	wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; +	reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; +	reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;  	wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 879dff2714d..8725d4e7543 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -161,7 +161,7 @@  static const u16 wm8580_reg[] = {  	0x0121, 0x017e, 0x007d, 0x0014, /*R3*/  	0x0121, 0x017e, 0x007d, 0x0194, /*R7*/ -	0x001c, 0x0002, 0x0002, 0x00c2, /*R11*/ +	0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/  	0x0182, 0x0082, 0x000a, 0x0024, /*R15*/  	0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/  	0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/ diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 90e31e9aa6f..aea60ef8aba 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -41,7 +41,6 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = {  /* codec private data */  struct wm8741_priv {  	enum snd_soc_control_type control_type; -	u16 reg_cache[WM8741_REGISTER_COUNT];  	struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];  	unsigned int sysclk;  	struct snd_pcm_hw_constraint_list *sysclk_constraints; @@ -422,6 +421,7 @@ static int wm8741_resume(struct snd_soc_codec *codec)  static int wm8741_probe(struct snd_soc_codec *codec)  {  	struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); +	u16 *reg_cache = codec->reg_cache;  	int ret = 0;  	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); @@ -437,10 +437,10 @@ static int wm8741_probe(struct snd_soc_codec *codec)  	}  	/* Change some default settings - latch VU */ -	wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; -	wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; -	wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; -	wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; +	reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; +	reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; +	reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; +	reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;  	snd_soc_add_controls(codec, wm8741_snd_controls,  			     ARRAY_SIZE(wm8741_snd_controls)); diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 8f679a13f2b..87caae59e93 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -65,22 +65,22 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec,   * are using 2 wire for device control, so we cache them instead.   */  static const u16 wm8753_reg[] = { -	0x0008, 0x0000, 0x000a, 0x000a, -	0x0033, 0x0000, 0x0007, 0x00ff, -	0x00ff, 0x000f, 0x000f, 0x007b, -	0x0000, 0x0032, 0x0000, 0x00c3, -	0x00c3, 0x00c0, 0x0000, 0x0000, +	0x0000, 0x0008, 0x0000, 0x000a, +	0x000a, 0x0033, 0x0000, 0x0007, +	0x00ff, 0x00ff, 0x000f, 0x000f, +	0x007b, 0x0000, 0x0032, 0x0000, +	0x00c3, 0x00c3, 0x00c0, 0x0000,  	0x0000, 0x0000, 0x0000, 0x0000,  	0x0000, 0x0000, 0x0000, 0x0000, -	0x0000, 0x0000, 0x0000, 0x0055, -	0x0005, 0x0050, 0x0055, 0x0050, -	0x0055, 0x0050, 0x0055, 0x0079, -	0x0079, 0x0079, 0x0079, 0x0079,  	0x0000, 0x0000, 0x0000, 0x0000, -	0x0097, 0x0097, 0x0000, 0x0004, -	0x0000, 0x0083, 0x0024, 0x01ba, -	0x0000, 0x0083, 0x0024, 0x01ba, -	0x0000, 0x0000, 0x0000 +	0x0055, 0x0005, 0x0050, 0x0055, +	0x0050, 0x0055, 0x0050, 0x0055, +	0x0079, 0x0079, 0x0079, 0x0079, +	0x0079, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0097, 0x0097, 0x0000, +	0x0004, 0x0000, 0x0083, 0x0024, +	0x01ba, 0x0000, 0x0083, 0x0024, +	0x01ba, 0x0000, 0x0000, 0x0000  };  /* codec private data */ @@ -88,57 +88,10 @@ struct wm8753_priv {  	enum snd_soc_control_type control_type;  	unsigned int sysclk;  	unsigned int pcmclk; -	u16 reg_cache[ARRAY_SIZE(wm8753_reg)];  	int dai_func;  }; -/* - * read wm8753 register cache - */ -static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec, -	unsigned int reg) -{ -	u16 *cache = codec->reg_cache; -	if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1)) -		return -1; -	return cache[reg - 1]; -} - -/* - * write wm8753 register cache - */ -static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec, -	unsigned int reg, unsigned int value) -{ -	u16 *cache = codec->reg_cache; -	if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1)) -		return; -	cache[reg - 1] = value; -} - -/* - * write to the WM8753 register space - */ -static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg, -	unsigned int value) -{ -	u8 data[2]; - -	/* data is -	 *   D15..D9 WM8753 register offset -	 *   D8...D0 register data -	 */ -	data[0] = (reg << 1) | ((value >> 8) & 0x0001); -	data[1] = value & 0x00ff; - -	wm8753_write_reg_cache(codec, reg, value); -	if (codec->hw_write(codec->control_data, data, 2) == 2) -		return 0; -	else -		return -EIO; -} - -#define wm8753_reset(c) wm8753_write(c, WM8753_RESET, 0) +#define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0)  /*   * WM8753 Controls @@ -218,7 +171,7 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol,  	struct snd_ctl_elem_value *ucontrol)  {  	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol); -	int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); +	int mode = snd_soc_read(codec, WM8753_IOCTL);  	ucontrol->value.integer.value[0] = (mode & 0xc) >> 2;  	return 0; @@ -228,7 +181,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,  	struct snd_ctl_elem_value *ucontrol)  {  	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol); -	int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); +	int mode = snd_soc_read(codec, WM8753_IOCTL);  	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);  	if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) @@ -738,17 +691,17 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,  	if (pll_id == WM8753_PLL1) {  		offset = 0;  		enable = 0x10; -		reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xffef; +		reg = snd_soc_read(codec, WM8753_CLOCK) & 0xffef;  	} else {  		offset = 4;  		enable = 0x8; -		reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfff7; +		reg = snd_soc_read(codec, WM8753_CLOCK) & 0xfff7;  	}  	if (!freq_in || !freq_out) {  		/* disable PLL  */ -		wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0026); -		wm8753_write(codec, WM8753_CLOCK, reg); +		snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0026); +		snd_soc_write(codec, WM8753_CLOCK, reg);  		return 0;  	} else {  		u16 value = 0; @@ -759,20 +712,20 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,  		/* set up N and K PLL divisor ratios */  		/* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */  		value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18); -		wm8753_write(codec, WM8753_PLL1CTL2 + offset, value); +		snd_soc_write(codec, WM8753_PLL1CTL2 + offset, value);  		/* bits 8:0 = PLL_K[17:9] */  		value = (pll_div.k & 0x03fe00) >> 9; -		wm8753_write(codec, WM8753_PLL1CTL3 + offset, value); +		snd_soc_write(codec, WM8753_PLL1CTL3 + offset, value);  		/* bits 8:0 = PLL_K[8:0] */  		value = pll_div.k & 0x0001ff; -		wm8753_write(codec, WM8753_PLL1CTL4 + offset, value); +		snd_soc_write(codec, WM8753_PLL1CTL4 + offset, value);  		/* set PLL as input and enable */ -		wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 | +		snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 |  			(pll_div.div2 << 3)); -		wm8753_write(codec, WM8753_CLOCK, reg | enable); +		snd_soc_write(codec, WM8753_CLOCK, reg | enable);  	}  	return 0;  } @@ -879,7 +832,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,  		unsigned int fmt)  {  	struct snd_soc_codec *codec = codec_dai->codec; -	u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01ec; +	u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01ec;  	/* interface format */  	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -901,7 +854,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,  		return -EINVAL;  	} -	wm8753_write(codec, WM8753_PCM, voice); +	snd_soc_write(codec, WM8753_PCM, voice);  	return 0;  } @@ -922,8 +875,8 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,  	struct snd_soc_pcm_runtime *rtd = substream->private_data;  	struct snd_soc_codec *codec = rtd->codec;  	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); -	u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; -	u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; +	u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01f3; +	u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x017f;  	/* bit size */  	switch (params_format(params)) { @@ -943,9 +896,9 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,  	/* sample rate */  	if (params_rate(params) * 384 == wm8753->pcmclk)  		srate |= 0x80; -	wm8753_write(codec, WM8753_SRATE1, srate); +	snd_soc_write(codec, WM8753_SRATE1, srate); -	wm8753_write(codec, WM8753_PCM, voice); +	snd_soc_write(codec, WM8753_PCM, voice);  	return 0;  } @@ -958,8 +911,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,  	struct snd_soc_codec *codec = codec_dai->codec;  	u16 voice, ioctl; -	voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x011f; -	ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x015d; +	voice = snd_soc_read(codec, WM8753_PCM) & 0x011f; +	ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x015d;  	/* set master/slave audio interface */  	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1013,8 +966,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,  		return -EINVAL;  	} -	wm8753_write(codec, WM8753_PCM, voice); -	wm8753_write(codec, WM8753_IOCTL, ioctl); +	snd_soc_write(codec, WM8753_PCM, voice); +	snd_soc_write(codec, WM8753_IOCTL, ioctl);  	return 0;  } @@ -1026,16 +979,16 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai,  	switch (div_id) {  	case WM8753_PCMDIV: -		reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f; -		wm8753_write(codec, WM8753_CLOCK, reg | div); +		reg = snd_soc_read(codec, WM8753_CLOCK) & 0x003f; +		snd_soc_write(codec, WM8753_CLOCK, reg | div);  		break;  	case WM8753_BCLKDIV: -		reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7; -		wm8753_write(codec, WM8753_SRATE2, reg | div); +		reg = snd_soc_read(codec, WM8753_SRATE2) & 0x01c7; +		snd_soc_write(codec, WM8753_SRATE2, reg | div);  		break;  	case WM8753_VXCLKDIV: -		reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x003f; -		wm8753_write(codec, WM8753_SRATE2, reg | div); +		reg = snd_soc_read(codec, WM8753_SRATE2) & 0x003f; +		snd_soc_write(codec, WM8753_SRATE2, reg | div);  		break;  	default:  		return -EINVAL; @@ -1050,7 +1003,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,  		unsigned int fmt)  {  	struct snd_soc_codec *codec = codec_dai->codec; -	u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01e0; +	u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01e0;  	/* interface format */  	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -1072,7 +1025,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,  		return -EINVAL;  	} -	wm8753_write(codec, WM8753_HIFI, hifi); +	snd_soc_write(codec, WM8753_HIFI, hifi);  	return 0;  } @@ -1085,8 +1038,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,  	struct snd_soc_codec *codec = codec_dai->codec;  	u16 ioctl, hifi; -	hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x011f; -	ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00ae; +	hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f; +	ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x00ae;  	/* set master/slave audio interface */  	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1140,8 +1093,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,  		return -EINVAL;  	} -	wm8753_write(codec, WM8753_HIFI, hifi); -	wm8753_write(codec, WM8753_IOCTL, ioctl); +	snd_soc_write(codec, WM8753_HIFI, hifi); +	snd_soc_write(codec, WM8753_IOCTL, ioctl);  	return 0;  } @@ -1162,8 +1115,8 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,  	struct snd_soc_pcm_runtime *rtd = substream->private_data;  	struct snd_soc_codec *codec = rtd->codec;  	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); -	u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; -	u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; +	u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x01c0; +	u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01f3;  	int coeff;  	/* is digital filter coefficient valid ? */ @@ -1172,7 +1125,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,  		printk(KERN_ERR "wm8753 invalid MCLK or rate\n");  		return coeff;  	} -	wm8753_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) | +	snd_soc_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) |  		coeff_div[coeff].usb);  	/* bit size */ @@ -1190,7 +1143,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,  		break;  	} -	wm8753_write(codec, WM8753_HIFI, hifi); +	snd_soc_write(codec, WM8753_HIFI, hifi);  	return 0;  } @@ -1201,8 +1154,8 @@ static int wm8753_mode1v_set_dai_fmt(struct snd_soc_dai *codec_dai,  	u16 clock;  	/* set clk source as pcmclk */ -	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; -	wm8753_write(codec, WM8753_CLOCK, clock); +	clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; +	snd_soc_write(codec, WM8753_CLOCK, clock);  	if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)  		return -EINVAL; @@ -1224,8 +1177,8 @@ static int wm8753_mode2_set_dai_fmt(struct snd_soc_dai *codec_dai,  	u16 clock;  	/* set clk source as pcmclk */ -	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; -	wm8753_write(codec, WM8753_CLOCK, clock); +	clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; +	snd_soc_write(codec, WM8753_CLOCK, clock);  	if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)  		return -EINVAL; @@ -1239,8 +1192,8 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai,  	u16 clock;  	/* set clk source as mclk */ -	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; -	wm8753_write(codec, WM8753_CLOCK, clock | 0x4); +	clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; +	snd_soc_write(codec, WM8753_CLOCK, clock | 0x4);  	if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0)  		return -EINVAL; @@ -1252,19 +1205,19 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai,  static int wm8753_mute(struct snd_soc_dai *dai, int mute)  {  	struct snd_soc_codec *codec = dai->codec; -	u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; +	u16 mute_reg = snd_soc_read(codec, WM8753_DAC) & 0xfff7;  	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);  	/* the digital mute covers the HiFi and Voice DAC's on the WM8753.  	 * make sure we check if they are not both active when we mute */  	if (mute && wm8753->dai_func == 1) {  		if (!codec->active) -			wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); +			snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);  	} else {  		if (mute) -			wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); +			snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);  		else -			wm8753_write(codec, WM8753_DAC, mute_reg); +			snd_soc_write(codec, WM8753_DAC, mute_reg);  	}  	return 0; @@ -1273,23 +1226,23 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)  static int wm8753_set_bias_level(struct snd_soc_codec *codec,  				 enum snd_soc_bias_level level)  { -	u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e; +	u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e;  	switch (level) {  	case SND_SOC_BIAS_ON:  		/* set vmid to 50k and unmute dac */ -		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); +		snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);  		break;  	case SND_SOC_BIAS_PREPARE:  		/* set vmid to 5k for quick power up */ -		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); +		snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);  		break;  	case SND_SOC_BIAS_STANDBY:  		/* mute dac and set vmid to 500k, enable VREF */ -		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141); +		snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141);  		break;  	case SND_SOC_BIAS_OFF: -		wm8753_write(codec, WM8753_PWR1, 0x0001); +		snd_soc_write(codec, WM8753_PWR1, 0x0001);  		break;  	}  	codec->bias_level = level; @@ -1477,7 +1430,7 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec,  		else  			dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1];  	} -	wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func); +	snd_soc_write(codec, WM8753_IOCTL, wm8753->dai_func);  }  static void wm8753_work(struct work_struct *work) @@ -1495,22 +1448,19 @@ static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)  static int wm8753_resume(struct snd_soc_codec *codec)  { +	u16 *reg_cache = codec->reg_cache;  	int i; -	u8 data[2]; -	u16 *cache = codec->reg_cache;  	/* Sync reg_cache with the hardware */ -	for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) { -		if (i + 1 == WM8753_RESET) +	for (i = 1; i < ARRAY_SIZE(wm8753_reg); i++) { +		if (i == WM8753_RESET)  			continue;  		/* No point in writing hardware default values back */ -		if (cache[i] == wm8753_reg[i]) +		if (reg_cache[i] == wm8753_reg[i])  			continue; -		data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001); -		data[1] = cache[i] & 0x00ff; -		codec->hw_write(codec->control_data, data, 2); +		snd_soc_write(codec, i, reg_cache[i]);  	}  	wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -1548,7 +1498,7 @@ static int run_delayed_work(struct delayed_work *dwork)  static int wm8753_probe(struct snd_soc_codec *codec)  {  	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); -	int ret = 0, reg; +	int ret;  	INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); @@ -1573,26 +1523,16 @@ static int wm8753_probe(struct snd_soc_codec *codec)  			      msecs_to_jiffies(caps_charge));  	/* set the update bits */ -	reg = wm8753_read_reg_cache(codec, WM8753_LDAC); -	wm8753_write(codec, WM8753_LDAC, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_RDAC); -	wm8753_write(codec, WM8753_RDAC, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_LADC); -	wm8753_write(codec, WM8753_LADC, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_RADC); -	wm8753_write(codec, WM8753_RADC, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V); -	wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V); -	wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V); -	wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V); -	wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_LINVOL); -	wm8753_write(codec, WM8753_LINVOL, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); -	wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); +	snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_ROUT2V, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_LINVOL, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_RINVOL, 0x0100, 0x0100);  	snd_soc_add_controls(codec, wm8753_snd_controls,  			     ARRAY_SIZE(wm8753_snd_controls)); diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index fca60a0b57b..1ec12eff062 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -50,8 +50,6 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {  /* codec private data */  struct wm8904_priv { -	u16 reg_cache[WM8904_MAX_REGISTER + 1]; -  	enum wm8904_type devtype;  	void *control_data; @@ -818,7 +816,8 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol,  	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);  	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); -	return wm8904->deemph; +	ucontrol->value.enumerated.item[0] = wm8904->deemph; +	return 0;  }  static int wm8904_put_deemph(struct snd_kcontrol *kcontrol, @@ -2093,7 +2092,7 @@ static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute)  static void wm8904_sync_cache(struct snd_soc_codec *codec)  { -	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); +	u16 *reg_cache = codec->reg_cache;  	int i;  	if (!codec->cache_sync) @@ -2104,14 +2103,14 @@ static void wm8904_sync_cache(struct snd_soc_codec *codec)  	/* Sync back cached values if they're different from the  	 * hardware default.  	 */ -	for (i = 1; i < ARRAY_SIZE(wm8904->reg_cache); i++) { +	for (i = 1; i < codec->driver->reg_cache_size; i++) {  		if (!wm8904_access[i].writable)  			continue; -		if (wm8904->reg_cache[i] == wm8904_reg[i]) +		if (reg_cache[i] == wm8904_reg[i])  			continue; -		snd_soc_write(codec, i, wm8904->reg_cache[i]); +		snd_soc_write(codec, i, reg_cache[i]);  	}  	codec->cache_sync = 0; @@ -2370,6 +2369,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)  {  	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);  	struct wm8904_pdata *pdata = wm8904->pdata; +	u16 *reg_cache = codec->reg_cache;  	int ret, i;  	codec->cache_sync = 1; @@ -2436,19 +2436,19 @@ static int wm8904_probe(struct snd_soc_codec *codec)  	}  	/* Change some default settings - latch VU and enable ZC */ -	wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; -	wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; -	wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; -	wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; -	wm8904->reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU | +	reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; +	reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; +	reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; +	reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; +	reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU |  		WM8904_HPOUTLZC; -	wm8904->reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU | +	reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU |  		WM8904_HPOUTRZC; -	wm8904->reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU | +	reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU |  		WM8904_LINEOUTLZC; -	wm8904->reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU | +	reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU |  		WM8904_LINEOUTRZC; -	wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; +	reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE;  	/* Apply configuration from the platform data. */  	if (wm8904->pdata) { @@ -2456,23 +2456,23 @@ static int wm8904_probe(struct snd_soc_codec *codec)  			if (!pdata->gpio_cfg[i])  				continue; -			wm8904->reg_cache[WM8904_GPIO_CONTROL_1 + i] +			reg_cache[WM8904_GPIO_CONTROL_1 + i]  				= pdata->gpio_cfg[i] & 0xffff;  		}  		/* Zero is the default value for these anyway */  		for (i = 0; i < WM8904_MIC_REGS; i++) -			wm8904->reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i] +			reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i]  				= pdata->mic_cfg[i];  	}  	/* Set Class W by default - this will be managed by the Class  	 * G widget at runtime where bypass paths are available.  	 */ -	wm8904->reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR; +	reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR;  	/* Use normal bias source */ -	wm8904->reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL; +	reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL;  	wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 2cb16f895c4..23086e2c976 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -768,6 +768,7 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,  	i2c_set_clientdata(i2c, wm8940);  	wm8940->control_data = i2c; +	wm8940->control_type = SND_SOC_I2C;  	ret = snd_soc_register_codec(&i2c->dev,  			&soc_codec_dev_wm8940, &wm8940_dai, 1); diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index f89ad6c9a80..2ac35b0be86 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -42,8 +42,6 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {  struct wm8955_priv {  	enum snd_soc_control_type control_type; -	u16 reg_cache[WM8955_MAX_REGISTER + 1]; -  	unsigned int mclk_rate;  	int deemph; @@ -380,7 +378,8 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol,  	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);  	struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); -	return wm8955->deemph; +	ucontrol->value.enumerated.item[0] = wm8955->deemph; +	return 0;  }  static int wm8955_put_deemph(struct snd_kcontrol *kcontrol, @@ -767,6 +766,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,  				 enum snd_soc_bias_level level)  {  	struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); +	u16 *reg_cache = codec->reg_cache;  	int ret, i;  	switch (level) { @@ -799,14 +799,14 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,  			/* Sync back cached values if they're  			 * different from the hardware default.  			 */ -			for (i = 0; i < ARRAY_SIZE(wm8955->reg_cache); i++) { +			for (i = 0; i < codec->driver->reg_cache_size; i++) {  				if (i == WM8955_RESET)  					continue; -				if (wm8955->reg_cache[i] == wm8955_reg[i]) +				if (reg_cache[i] == wm8955_reg[i])  					continue; -				snd_soc_write(codec, i, wm8955->reg_cache[i]); +				snd_soc_write(codec, i, reg_cache[i]);  			}  			/* Enable VREF and VMID */ @@ -901,6 +901,7 @@ static int wm8955_probe(struct snd_soc_codec *codec)  {  	struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);  	struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); +	u16 *reg_cache = codec->reg_cache;  	int ret, i;  	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type); @@ -933,25 +934,25 @@ static int wm8955_probe(struct snd_soc_codec *codec)  	}  	/* Change some default settings - latch VU and enable ZC */ -	wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; -	wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; -	wm8955->reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC; -	wm8955->reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC; -	wm8955->reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC; -	wm8955->reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC; -	wm8955->reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC; +	reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; +	reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; +	reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC; +	reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC; +	reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC; +	reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC; +	reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC;  	/* Also enable adaptive bass boost by default */ -	wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; +	reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;  	/* Set platform data values */  	if (pdata) {  		if (pdata->out2_speaker) -			wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2] +			reg_cache[WM8955_ADDITIONAL_CONTROL_2]  				|= WM8955_ROUT2INV;  		if (pdata->monoin_diff) -			wm8955->reg_cache[WM8955_MONO_OUT_MIX_1] +			reg_cache[WM8955_MONO_OUT_MIX_1]  				|= WM8955_DMEN;  	} @@ -1002,6 +1003,7 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,  		return -ENOMEM;  	i2c_set_clientdata(i2c, wm8955); +	wm8955->control_type = SND_SOC_I2C;  	ret = snd_soc_register_codec(&i2c->dev,  			&soc_codec_dev_wm8955, &wm8955_dai, 1); diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 8d5efb333c3..ff6ff2f529d 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -138,7 +138,8 @@ static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,  	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);  	struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); -	return wm8960->deemph; +	ucontrol->value.enumerated.item[0] = wm8960->deemph; +	return 0;  }  static int wm8960_put_deemph(struct snd_kcontrol *kcontrol, @@ -1012,6 +1013,7 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,  		return -ENOMEM;  	i2c_set_clientdata(i2c, wm8960); +	wm8960->control_type = SND_SOC_I2C;  	wm8960->control_data = i2c;  	ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 1304ca91a11..7c421cc837b 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -52,8 +52,6 @@ static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = {  struct wm8962_priv {  	struct snd_soc_codec *codec; -	u16 reg_cache[WM8962_MAX_REGISTER + 1]; -  	int sysclk;  	int sysclk_rate; @@ -1991,8 +1989,7 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,  			    struct snd_ctl_elem_value *ucontrol)  {  	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); -	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); -	u16 *reg_cache = wm8962->reg_cache; +	u16 *reg_cache = codec->reg_cache;  	int ret;  	/* Apply the update (if any) */ @@ -2020,8 +2017,7 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,  			    struct snd_ctl_elem_value *ucontrol)  {  	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); -	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); -	u16 *reg_cache = wm8962->reg_cache; +	u16 *reg_cache = codec->reg_cache;  	int ret;  	/* Apply the update (if any) */ @@ -2329,8 +2325,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,  			 struct snd_kcontrol *kcontrol, int event)  {  	struct snd_soc_codec *codec = w->codec; -	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); -	u16 *reg_cache = wm8962->reg_cache; +	u16 *reg_cache = codec->reg_cache;  	int reg;  	switch (w->shift) { @@ -2719,7 +2714,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec)  static void wm8962_sync_cache(struct snd_soc_codec *codec)  { -	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); +	u16 *reg_cache = codec->reg_cache;  	int i;  	if (!codec->cache_sync) @@ -2732,13 +2727,13 @@ static void wm8962_sync_cache(struct snd_soc_codec *codec)  	/* Sync back cached values if they're different from the  	 * hardware default.  	 */ -	for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) { +	for (i = 1; i < codec->driver->reg_cache_size; i++) {  		if (i == WM8962_SOFTWARE_RESET)  			continue; -		if (wm8962->reg_cache[i] == wm8962_reg[i]) +		if (reg_cache[i] == wm8962_reg[i])  			continue; -		snd_soc_write(codec, i, wm8962->reg_cache[i]); +		snd_soc_write(codec, i, reg_cache[i]);  	}  	codec->cache_sync = 0; @@ -3406,12 +3401,11 @@ EXPORT_SYMBOL_GPL(wm8962_mic_detect);  #ifdef CONFIG_PM  static int wm8962_resume(struct snd_soc_codec *codec)  { -	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);  	u16 *reg_cache = codec->reg_cache;  	int i;  	/* Restore the registers */ -	for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) { +	for (i = 1; i < codec->driver->reg_cache_size; i++) {  		switch (i) {  		case WM8962_SOFTWARE_RESET:  			continue; @@ -3705,6 +3699,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)  	struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);  	struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,  					      dev); +	u16 *reg_cache = codec->reg_cache;  	int i, trigger, irq_pol;  	wm8962->codec = codec; @@ -3804,7 +3799,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)  		/* Put the speakers into mono mode? */  		if (pdata->spk_mono) -			wm8962->reg_cache[WM8962_CLASS_D_CONTROL_2] +			reg_cache[WM8962_CLASS_D_CONTROL_2]  				|= WM8962_SPK_MONO;  		/* Micbias setup, detection enable and detection @@ -3819,16 +3814,16 @@ static int wm8962_probe(struct snd_soc_codec *codec)  	}  	/* Latch volume update bits */ -	wm8962->reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU; -	wm8962->reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU; -	wm8962->reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU; -	wm8962->reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU;	 -	wm8962->reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU; -	wm8962->reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU; -	wm8962->reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU; -	wm8962->reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU; -	wm8962->reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU; -	wm8962->reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU; +	reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU; +	reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU; +	reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU; +	reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU; +	reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU; +	reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU; +	reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU; +	reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU; +	reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU; +	reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU;  	wm8962_add_widgets(codec); diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 63f6dbf5d07..9f18db6e167 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -718,6 +718,7 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,  	if (wm8971 == NULL)  		return -ENOMEM; +	wm8971->control_type = SND_SOC_I2C;  	i2c_set_clientdata(i2c, wm8971);  	ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index ecc7c37180c..a486670966b 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -1335,6 +1335,7 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,  		return -ENOMEM;  	i2c_set_clientdata(i2c, wm9081); +	wm9081->control_type = SND_SOC_I2C;  	wm9081->control_data = i2c;  	ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 99c046ba46b..6e5f64f627c 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -141,7 +141,6 @@ static const u16 wm9090_reg_defaults[] = {  /* This struct is used to save the context */  struct wm9090_priv {  	struct mutex mutex; -	u16 reg_cache[WM9090_MAX_REGISTER + 1];  	struct wm9090_platform_data pdata;  	void *control_data;  }; @@ -552,6 +551,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,  static int wm9090_probe(struct snd_soc_codec *codec)  {  	struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); +	u16 *reg_cache = codec->reg_cache;  	int ret;  	codec->control_data = wm9090->control_data; @@ -576,22 +576,22 @@ static int wm9090_probe(struct snd_soc_codec *codec)  	/* Configure some defaults; they will be written out when we  	 * bring the bias up.  	 */ -	wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU +	reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU  		| WM9090_IN1A_ZC; -	wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU +	reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU  		| WM9090_IN1B_ZC; -	wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU +	reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU  		| WM9090_IN2A_ZC; -	wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU +	reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU  		| WM9090_IN2B_ZC; -	wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= +	reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=  		WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; -	wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= +	reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=  		WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; -	wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= +	reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=  		WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; -	wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; +	reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;  	wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 75ed6491222..c721502833b 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -944,6 +944,9 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)  		case SND_SOC_DAPM_STREAM_RESUME:  			sys_power = 1;  			break; +		case SND_SOC_DAPM_STREAM_STOP: +			sys_power = !!codec->active; +			break;  		case SND_SOC_DAPM_STREAM_SUSPEND:  			sys_power = 0;  			break; diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index 44a47e13bd6..c49837de7d3 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c @@ -36,7 +36,6 @@ static const struct option options[] = {  static int __cmd_buildid_list(void)  { -	int err = -1;  	struct perf_session *session;  	session = perf_session__new(input_name, O_RDONLY, force, false); @@ -49,7 +48,7 @@ static int __cmd_buildid_list(void)  	perf_session__fprintf_dsos_buildid(session, stdout, with_hits);  	perf_session__delete(session); -	return err; +	return 0;  }  int cmd_buildid_list(int argc, const char **argv, const char *prefix __used) diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 2e000c068cc..add163c9f0e 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -249,6 +249,11 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)  	     !params.show_lines))  		usage_with_options(probe_usage, options); +	/* +	 * Only consider the user's kernel image path if given. +	 */ +	symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); +  	if (params.list_events) {  		if (params.mod_events) {  			pr_err("  Error: Don't use --list with --add/--del.\n"); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 64a85bafde6..7cba0551a56 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -265,15 +265,16 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,  			  const char *name, bool is_kallsyms)  {  	const size_t size = PATH_MAX; -	char *filename = malloc(size), +	char *realname = realpath(name, NULL), +	     *filename = malloc(size),  	     *linkname = malloc(size), *targetname;  	int len, err = -1; -	if (filename == NULL || linkname == NULL) +	if (realname == NULL || filename == NULL || linkname == NULL)  		goto out_free;  	len = snprintf(filename, size, "%s%s%s", -		       debugdir, is_kallsyms ? "/" : "", name); +		       debugdir, is_kallsyms ? "/" : "", realname);  	if (mkdir_p(filename, 0755))  		goto out_free; @@ -283,7 +284,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,  		if (is_kallsyms) {  			 if (copyfile("/proc/kallsyms", filename))  				goto out_free; -		} else if (link(name, filename) && copyfile(name, filename)) +		} else if (link(realname, filename) && copyfile(name, filename))  			goto out_free;  	} @@ -300,6 +301,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,  	if (symlink(targetname, linkname) == 0)  		err = 0;  out_free: +	free(realname);  	free(filename);  	free(linkname);  	return err; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 2022e874099..76bcc35cf9b 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -356,7 +356,7 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,  static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,  				     int depth, int depth_mask, int period, -				     u64 total_samples, int hits, +				     u64 total_samples, u64 hits,  				     int left_margin)  {  	int i; diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 3b6a5297bf1..61191c6cbe7 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -114,6 +114,8 @@ static struct symbol *__find_kernel_function_by_name(const char *name,  const char *kernel_get_module_path(const char *module)  {  	struct dso *dso; +	struct map *map; +	const char *vmlinux_name;  	if (module) {  		list_for_each_entry(dso, &machine.kernel_dsos, node) { @@ -123,10 +125,17 @@ const char *kernel_get_module_path(const char *module)  		}  		pr_debug("Failed to find module %s.\n", module);  		return NULL; +	} + +	map = machine.vmlinux_maps[MAP__FUNCTION]; +	dso = map->dso; + +	vmlinux_name = symbol_conf.vmlinux_name; +	if (vmlinux_name) { +		if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0) +			return NULL;  	} else { -		dso = machine.vmlinux_maps[MAP__FUNCTION]->dso; -		if (dso__load_vmlinux_path(dso, -			 machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) { +		if (dso__load_vmlinux_path(dso, map, NULL) <= 0) {  			pr_debug("Failed to load kernel map.\n");  			return NULL;  		} diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 3991d73d1cf..ddf4d455632 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -117,28 +117,6 @@ static void line_list__free(struct list_head *head)  }  /* Dwarf FL wrappers */ - -static int __linux_kernel_find_elf(Dwfl_Module *mod, -				   void **userdata, -				   const char *module_name, -				   Dwarf_Addr base, -				   char **file_name, Elf **elfp) -{ -	int fd; -	const char *path = kernel_get_module_path(module_name); - -	if (path) { -		fd = open(path, O_RDONLY); -		if (fd >= 0) { -			*file_name = strdup(path); -			return fd; -		} -	} -	/* If failed, try to call standard method */ -	return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base, -					  file_name, elfp); -} -  static char *debuginfo_path;	/* Currently dummy */  static const Dwfl_Callbacks offline_callbacks = { @@ -151,14 +129,6 @@ static const Dwfl_Callbacks offline_callbacks = {  	.find_elf = dwfl_build_id_find_elf,  }; -static const Dwfl_Callbacks kernel_callbacks = { -	.find_debuginfo = dwfl_standard_find_debuginfo, -	.debuginfo_path = &debuginfo_path, - -	.find_elf = __linux_kernel_find_elf, -	.section_address = dwfl_linux_kernel_module_section_address, -}; -  /* Get a Dwarf from offline image */  static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias)  { @@ -185,6 +155,38 @@ error:  	return dbg;  } +#if _ELFUTILS_PREREQ(0, 148) +/* This method is buggy if elfutils is older than 0.148 */ +static int __linux_kernel_find_elf(Dwfl_Module *mod, +				   void **userdata, +				   const char *module_name, +				   Dwarf_Addr base, +				   char **file_name, Elf **elfp) +{ +	int fd; +	const char *path = kernel_get_module_path(module_name); + +	pr_debug2("Use file %s for %s\n", path, module_name); +	if (path) { +		fd = open(path, O_RDONLY); +		if (fd >= 0) { +			*file_name = strdup(path); +			return fd; +		} +	} +	/* If failed, try to call standard method */ +	return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base, +					  file_name, elfp); +} + +static const Dwfl_Callbacks kernel_callbacks = { +	.find_debuginfo = dwfl_standard_find_debuginfo, +	.debuginfo_path = &debuginfo_path, + +	.find_elf = __linux_kernel_find_elf, +	.section_address = dwfl_linux_kernel_module_section_address, +}; +  /* Get a Dwarf from live kernel image */  static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp,  					  Dwarf_Addr *bias) @@ -205,11 +207,34 @@ static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp,  	dbg = dwfl_addrdwarf(*dwflp, addr, bias);  	/* Here, check whether we could get a real dwarf */  	if (!dbg) { +		pr_debug("Failed to find kernel dwarf at %lx\n", +			 (unsigned long)addr);  		dwfl_end(*dwflp);  		*dwflp = NULL;  	}  	return dbg;  } +#else +/* With older elfutils, this just support kernel module... */ +static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr __used, Dwfl **dwflp, +					  Dwarf_Addr *bias) +{ +	int fd; +	const char *path = kernel_get_module_path("kernel"); + +	if (!path) { +		pr_err("Failed to find vmlinux path\n"); +		return NULL; +	} + +	pr_debug2("Use file %s for debuginfo\n", path); +	fd = open(path, O_RDONLY); +	if (fd < 0) +		return NULL; + +	return dwfl_init_offline_dwarf(fd, dwflp, bias); +} +#endif  /* Dwarf wrappers */ diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index 0409fc7c005..8fc0bd3a3a4 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -259,7 +259,7 @@ static bool __match_glob(const char *str, const char *pat, bool ignore_space)  		if (!*pat)	/* Tail wild card matches all */  			return true;  		while (*str) -			if (strglobmatch(str++, pat)) +			if (__match_glob(str++, pat, ignore_space))  				return true;  	}  	return !*str && !*pat; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index d628c8d1cf5..439ab947daf 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1780,8 +1780,8 @@ out_failure:  	return -1;  } -static int dso__load_vmlinux(struct dso *self, struct map *map, -			     const char *vmlinux, symbol_filter_t filter) +int dso__load_vmlinux(struct dso *self, struct map *map, +		      const char *vmlinux, symbol_filter_t filter)  {  	int err = -1, fd; diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 038f2201ee0..6c6eafdb932 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -166,6 +166,8 @@ void dso__sort_by_name(struct dso *self, enum map_type type);  struct dso *__dsos__findnew(struct list_head *head, const char *name);  int dso__load(struct dso *self, struct map *map, symbol_filter_t filter); +int dso__load_vmlinux(struct dso *self, struct map *map, +		      const char *vmlinux, symbol_filter_t filter);  int dso__load_vmlinux_path(struct dso *self, struct map *map,  			   symbol_filter_t filter);  int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map,  |