diff mbox series

[v5,4/7] qmi: Implement QMI service request rate limiting in 'can_write_data'.

Message ID 06f2aab8af4cfd8b660bb9b1c65897618ef0ad74.1739822462.git.gerickson@nuovations.com (mailing list archive)
State Under Review
Headers show
Series Add QMI Device Service Request Rate-limit Option | expand

Commit Message

Grant Erickson Feb. 17, 2025, 8:01 p.m. UTC
Determine if we need to rate-limit QMI services requests to a
transport-specific minimum request period. If so, return true so that
the queue can be retried again later.

Adds the following data members to 'qmi_transport':

  * Minimum request period
    - The minimum period, in microseconds, for back-to-back QMI
      service requests.

  * Last request time
    - Time, in microseconds, when the last QMI service request was
      sent.

to support the implementation.
---
 drivers/qmimodem/qmi.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)
diff mbox series

Patch

diff --git a/drivers/qmimodem/qmi.c b/drivers/qmimodem/qmi.c
index bbe6440abe0f..a9ea88d31c36 100644
--- a/drivers/qmimodem/qmi.c
+++ b/drivers/qmimodem/qmi.c
@@ -92,6 +92,18 @@  struct qmi_transport {
 	const struct qmi_transport_ops *ops;
 	struct debug_data debug;
 	bool writer_active : 1;
+
+	/**
+	 *  If specified via qmi_qmux_device_options, the minimum period
+	 *  for back-to-back QMI service requests.
+	 */
+	unsigned int min_req_period_us;
+
+	/**
+	 *  The time, in microseconds, when the last QMI service request
+	 *  was sent.
+	 */
+	uint64_t last_req_sent_time_us;
 };
 
 struct qmi_qmux_device {
@@ -653,8 +665,28 @@  static bool can_write_data(struct l_io *io, void *user_data)
 {
 	struct qmi_transport *transport = user_data;
 	struct qmi_request *req;
+	const bool throttle_enabled = transport->min_req_period_us > 0;
+	uint64_t now;
 	int r;
 
+	/*
+	 * Determine if we need to rate-limit commands to a
+	 * transport-specific minimum request period. If so,
+	 * return true so that the queue can be retried again
+	 * later.
+	 */
+	if (throttle_enabled) {
+		now = l_time_now();
+
+		if (transport->last_req_sent_time_us != 0) {
+			const uint64_t delta = l_time_diff(now,
+				transport->last_req_sent_time_us);
+
+			if (delta < transport->min_req_period_us)
+				return true;
+		}
+	}
+
 	req = l_queue_pop_head(transport->req_queue);
 	if (!req)
 		return false;
@@ -665,6 +697,12 @@  static bool can_write_data(struct l_io *io, void *user_data)
 		return false;
 	}
 
+_Pragma("GCC diagnostic push")
+_Pragma("GCC diagnostic ignored \"-Wconditional-uninitialized\"")
+	if (throttle_enabled)
+		transport->last_req_sent_time_us = now;
+_Pragma("GCC diagnostic pop")
+
 	if (l_queue_length(transport->req_queue) > 0)
 		return true;