list_add_tail(&entry->list, &fh->msgs);
/*
- * if the queue now has more than CEC_MAX_MSG_QUEUE_SZ
+ * if the queue now has more than CEC_MAX_MSG_RX_QUEUE_SZ
* messages, drop the oldest one and send a lost message event.
*/
- if (fh->queued_msgs == CEC_MAX_MSG_QUEUE_SZ) {
+ if (fh->queued_msgs == CEC_MAX_MSG_RX_QUEUE_SZ) {
list_del(&entry->list);
goto lost_msgs;
}
* It's either the current transmit, or it is a pending
* transmit. Take the appropriate action to clear it.
*/
- if (data->adap->transmitting == data)
+ if (data->adap->transmitting == data) {
data->adap->transmitting = NULL;
- else
+ } else {
list_del_init(&data->list);
+ if (!(data->msg.tx_status & CEC_TX_STATUS_OK))
+ data->adap->transmit_queue_sz--;
+ }
/* Mark it as an error */
data->msg.tx_ts = ktime_get_ns();
data = list_first_entry(&adap->transmit_queue,
struct cec_data, list);
list_del_init(&data->list);
+ adap->transmit_queue_sz--;
/* Make this the current transmitting message */
adap->transmitting = data;
data->attempts--;
/* Add the message in front of the transmit queue */
list_add(&data->list, &adap->transmit_queue);
+ adap->transmit_queue_sz++;
goto wake_thread;
}
if (!adap->is_configured && !adap->is_configuring)
return -ENONET;
+ if (adap->transmit_queue_sz >= CEC_MAX_MSG_TX_QUEUE_SZ)
+ return -EBUSY;
+
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
if (fh)
list_add_tail(&data->xfer_list, &fh->xfer_list);
list_add_tail(&data->list, &adap->transmit_queue);
+ adap->transmit_queue_sz++;
if (!adap->transmitting)
wake_up_interruptible(&adap->kthread_waitq);
adap->monitor_all_cnt);
data = adap->transmitting;
if (data)
- seq_printf(file, "transmitting message: %*ph (reply: %02x)\n",
- data->msg.len, data->msg.msg, data->msg.reply);
+ seq_printf(file, "transmitting message: %*ph (reply: %02x, timeout: %ums)\n",
+ data->msg.len, data->msg.msg, data->msg.reply,
+ data->msg.timeout);
+ seq_printf(file, "pending transmits: %u\n", adap->transmit_queue_sz);
list_for_each_entry(data, &adap->transmit_queue, list) {
- seq_printf(file, "queued tx message: %*ph (reply: %02x)\n",
- data->msg.len, data->msg.msg, data->msg.reply);
+ seq_printf(file, "queued tx message: %*ph (reply: %02x, timeout: %ums)\n",
+ data->msg.len, data->msg.msg, data->msg.reply,
+ data->msg.timeout);
}
list_for_each_entry(data, &adap->wait_queue, list) {
- seq_printf(file, "message waiting for reply: %*ph (reply: %02x)\n",
- data->msg.len, data->msg.msg, data->msg.reply);
+ seq_printf(file, "message waiting for reply: %*ph (reply: %02x, timeout: %ums)\n",
+ data->msg.len, data->msg.msg, data->msg.reply,
+ data->msg.timeout);
}
call_void_op(adap, adap_status, file);
* With a transfer rate of at most 36 bytes per second this makes 18 messages
* per second worst case.
*
- * We queue at most 3 seconds worth of messages. The CEC specification requires
- * that messages are replied to within a second, so 3 seconds should give more
- * than enough margin. Since most messages are actually more than 2 bytes, this
- * is in practice a lot more than 3 seconds.
+ * We queue at most 3 seconds worth of received messages. The CEC specification
+ * requires that messages are replied to within a second, so 3 seconds should
+ * give more than enough margin. Since most messages are actually more than 2
+ * bytes, this is in practice a lot more than 3 seconds.
*/
-#define CEC_MAX_MSG_QUEUE_SZ (18 * 3)
+#define CEC_MAX_MSG_RX_QUEUE_SZ (18 * 3)
+
+/*
+ * The transmit queue is limited to 1 second worth of messages (worst case).
+ * Messages can be transmitted by userspace and kernel space. But for both it
+ * makes no sense to have a lot of messages queued up. One second seems
+ * reasonable.
+ */
+#define CEC_MAX_MSG_TX_QUEUE_SZ (18 * 1)
struct cec_adapter {
struct module *owner;
struct rc_dev *rc;
struct list_head transmit_queue;
+ unsigned int transmit_queue_sz;
struct list_head wait_queue;
struct cec_data *transmitting;