summaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2016-07-12 11:10:42 -0300
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2016-07-13 07:59:30 -0300
commit980e0b36b55985dd0a37acd25d29c8f21482db32 (patch)
tree4c4e44239d8e0ca2a8579bc9bf1673403348bf81 /drivers/staging
parent52d802d65b56a399aa67a9d3f26f232116d3e256 (diff)
[media] cec: split the timestamp into an rx and tx timestamp
When transmitting a message and waiting for a reply it would be good to know the time between when the message was transmitted and when the reply arrived. With only one timestamp field it was set to when the reply arrived and the original transmit time was overwritten. Just taking the timestamp in userspace right before CEC_TRANSMIT is called is not reliable, since the actual transmit can be delayed if the CEC bus is busy. Only the driver can fill this in accurately. So split up the ts field into an rx_ts and a tx_ts. Also move the status fields to after the 'reply' field: they were placed in a strange position and make much more sense when grouped with the other status-related fields. This patch also makes sure that the timestamp is taken as soon as possible. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/media/cec/cec-adap.c24
1 files changed, 12 insertions, 12 deletions
diff --git a/drivers/staging/media/cec/cec-adap.c b/drivers/staging/media/cec/cec-adap.c
index 3925e0ae62a5..ca34339e3eba 100644
--- a/drivers/staging/media/cec/cec-adap.c
+++ b/drivers/staging/media/cec/cec-adap.c
@@ -284,7 +284,7 @@ static void cec_data_cancel(struct cec_data *data)
list_del_init(&data->list);
/* Mark it as an error */
- data->msg.ts = ktime_get_ns();
+ data->msg.tx_ts = ktime_get_ns();
data->msg.tx_status = CEC_TX_STATUS_ERROR |
CEC_TX_STATUS_MAX_RETRIES;
data->attempts = 0;
@@ -459,6 +459,7 @@ void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt,
{
struct cec_data *data;
struct cec_msg *msg;
+ u64 ts = ktime_get_ns();
dprintk(2, "cec_transmit_done %02x\n", status);
mutex_lock(&adap->lock);
@@ -477,7 +478,7 @@ void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt,
/* Drivers must fill in the status! */
WARN_ON(status == 0);
- msg->ts = ktime_get_ns();
+ msg->tx_ts = ts;
msg->tx_status |= status;
msg->tx_arb_lost_cnt += arb_lost_cnt;
msg->tx_nack_cnt += nack_cnt;
@@ -561,7 +562,7 @@ static void cec_wait_timeout(struct work_struct *work)
/* Mark the message as timed out */
list_del_init(&data->list);
- data->msg.ts = ktime_get_ns();
+ data->msg.rx_ts = ktime_get_ns();
data->msg.rx_status = CEC_RX_STATUS_TIMEOUT;
cec_data_completed(data);
unlock:
@@ -766,13 +767,14 @@ void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg)
if (WARN_ON(!msg->len || msg->len > CEC_MAX_MSG_SIZE))
return;
- mutex_lock(&adap->lock);
- msg->ts = ktime_get_ns();
+ msg->rx_ts = ktime_get_ns();
msg->rx_status = CEC_RX_STATUS_OK;
- msg->tx_status = 0;
msg->sequence = msg->reply = msg->timeout = 0;
+ msg->tx_status = 0;
+ msg->tx_ts = 0;
msg->flags = 0;
+ mutex_lock(&adap->lock);
dprintk(2, "cec_received_msg: %*ph\n", msg->len, msg->msg);
/* Check if this message was for us (directed or broadcast). */
@@ -794,7 +796,6 @@ void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg)
*/
list_for_each_entry(data, &adap->wait_queue, list) {
struct cec_msg *dst = &data->msg;
- u8 dst_reply;
/* Does the command match? */
if ((abort && cmd != dst->msg[1]) ||
@@ -807,11 +808,10 @@ void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg)
continue;
/* We got a reply */
- msg->sequence = dst->sequence;
- msg->tx_status = dst->tx_status;
- dst_reply = dst->reply;
- *dst = *msg;
- dst->reply = dst_reply;
+ memcpy(dst->msg, msg->msg, msg->len);
+ dst->len = msg->len;
+ dst->rx_ts = msg->rx_ts;
+ dst->rx_status = msg->rx_status;
if (abort) {
dst->reply = 0;
dst->rx_status |= CEC_RX_STATUS_FEATURE_ABORT;