Commit b37d2a3a authored by Jean Delvare's avatar Jean Delvare Committed by Mauro Carvalho Chehab

[media] i2c: Export an unlocked flavor of i2c_transfer

Some drivers (in particular for TV cards) need exclusive access to
their I2C buses for specific operations. Export an unlocked flavor
of i2c_transfer to give them full control.

The unlocked flavor has the following limitations:
* Obviously, caller must hold the i2c adapter lock.
* No debug messages are logged. We don't want to log messages while
  holding a rt_mutex.
* No check is done on the existence of adap->algo->master_xfer. It
  is thus the caller's responsibility to ensure that the function is
  OK to call.
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent a99817ca
...@@ -1294,6 +1294,37 @@ module_exit(i2c_exit); ...@@ -1294,6 +1294,37 @@ module_exit(i2c_exit);
* ---------------------------------------------------- * ----------------------------------------------------
*/ */
/**
* __i2c_transfer - unlocked flavor of i2c_transfer
* @adap: Handle to I2C bus
* @msgs: One or more messages to execute before STOP is issued to
* terminate the operation; each message begins with a START.
* @num: Number of messages to be executed.
*
* Returns negative errno, else the number of messages executed.
*
* Adapter lock must be held when calling this function. No debug logging
* takes place. adap->algo->master_xfer existence isn't checked.
*/
int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
unsigned long orig_jiffies;
int ret, try;
/* Retry automatically on arbitration loss */
orig_jiffies = jiffies;
for (ret = 0, try = 0; try <= adap->retries; try++) {
ret = adap->algo->master_xfer(adap, msgs, num);
if (ret != -EAGAIN)
break;
if (time_after(jiffies, orig_jiffies + adap->timeout))
break;
}
return ret;
}
EXPORT_SYMBOL(__i2c_transfer);
/** /**
* i2c_transfer - execute a single or combined I2C message * i2c_transfer - execute a single or combined I2C message
* @adap: Handle to I2C bus * @adap: Handle to I2C bus
...@@ -1308,8 +1339,7 @@ module_exit(i2c_exit); ...@@ -1308,8 +1339,7 @@ module_exit(i2c_exit);
*/ */
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{ {
unsigned long orig_jiffies; int ret;
int ret, try;
/* REVISIT the fault reporting model here is weak: /* REVISIT the fault reporting model here is weak:
* *
...@@ -1347,15 +1377,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ...@@ -1347,15 +1377,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
i2c_lock_adapter(adap); i2c_lock_adapter(adap);
} }
/* Retry automatically on arbitration loss */ ret = __i2c_transfer(adap, msgs, num);
orig_jiffies = jiffies;
for (ret = 0, try = 0; try <= adap->retries; try++) {
ret = adap->algo->master_xfer(adap, msgs, num);
if (ret != -EAGAIN)
break;
if (time_after(jiffies, orig_jiffies + adap->timeout))
break;
}
i2c_unlock_adapter(adap); i2c_unlock_adapter(adap);
return ret; return ret;
......
...@@ -68,6 +68,9 @@ extern int i2c_master_recv(const struct i2c_client *client, char *buf, ...@@ -68,6 +68,9 @@ extern int i2c_master_recv(const struct i2c_client *client, char *buf,
*/ */
extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num); int num);
/* Unlocked flavor */
extern int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num);
/* This is the very generalized SMBus access routine. You probably do not /* This is the very generalized SMBus access routine. You probably do not
want to use this, though; one of the functions below may be much easier, want to use this, though; one of the functions below may be much easier,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment