Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+33 −11
Original line number Diff line number Diff line
@@ -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
 * @adap: Handle to I2C bus
@@ -1308,8 +1339,7 @@ module_exit(i2c_exit);
 */
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
	unsigned long orig_jiffies;
	int ret, try;
	int ret;

	/* 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)
			i2c_lock_adapter(adap);
		}

		/* 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;
		}
		ret = __i2c_transfer(adap, msgs, num);
		i2c_unlock_adapter(adap);

		return ret;
+3 −0
Original line number Diff line number Diff line
@@ -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,
			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
   want to use this, though; one of the functions below may be much easier,