forked from mirrors/linux
		
	i2c: Support i2c_transfer in atomic contexts
Allow i2c_transfer to be called in contexts where sleeping is not allowed. It is the reponsability of the caller to ensure that the underlying i2c bus driver will not sleep either. Signed-off-by: Mike Rapoport <mike@compulab.co.il> Signed-off-by: Jean Delvare <khali@linux-fr.org>
This commit is contained in:
		
							parent
							
								
									5271071b20
								
							
						
					
					
						commit
						cea443a81c
					
				
					 1 changed files with 11 additions and 1 deletions
				
			
		|  | @ -33,6 +33,8 @@ | ||||||
| #include <linux/platform_device.h> | #include <linux/platform_device.h> | ||||||
| #include <linux/mutex.h> | #include <linux/mutex.h> | ||||||
| #include <linux/completion.h> | #include <linux/completion.h> | ||||||
|  | #include <linux/hardirq.h> | ||||||
|  | #include <linux/irqflags.h> | ||||||
| #include <asm/uaccess.h> | #include <asm/uaccess.h> | ||||||
| #include <asm/semaphore.h> | #include <asm/semaphore.h> | ||||||
| 
 | 
 | ||||||
|  | @ -861,7 +863,15 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) | ||||||
| 		} | 		} | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 		mutex_lock_nested(&adap->bus_lock, adap->level); | 		if (in_atomic() || irqs_disabled()) { | ||||||
|  | 			ret = mutex_trylock(&adap->bus_lock); | ||||||
|  | 			if (!ret) | ||||||
|  | 				/* I2C activity is ongoing. */ | ||||||
|  | 				return -EAGAIN; | ||||||
|  | 		} else { | ||||||
|  | 			mutex_lock_nested(&adap->bus_lock, adap->level); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		ret = adap->algo->master_xfer(adap,msgs,num); | 		ret = adap->algo->master_xfer(adap,msgs,num); | ||||||
| 		mutex_unlock(&adap->bus_lock); | 		mutex_unlock(&adap->bus_lock); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Mike Rapoport
						Mike Rapoport