diff mbox series

[03/10] gobi: Explicitly set 802.3 data format

Message ID 20241121152949.56962-3-denkenz@gmail.com (mailing list archive)
State Under Review
Headers show
Series [01/10] qmi: wda: Add qmi_wda_set_data_format utility | expand

Commit Message

Denis Kenzior Nov. 21, 2024, 3:29 p.m. UTC
The current logic relies on querying the current data format, and
setting the qmi_wwan parameters accordingly.  Unfortunately, the logic
does not take data aggregation settings into account and can get
confused if the modem is using such settings.  Fix this by explicitly
setting the WDA data format to 802.3.

While here, add some preparatory logic to support other data modes
easily.  This will be used in the future to support multiple contexts
using RMNet + QMAP.
---
 plugins/gobi.c | 191 ++++++++++++++++++++++++++++---------------------
 1 file changed, 108 insertions(+), 83 deletions(-)
diff mbox series

Patch

diff --git a/plugins/gobi.c b/plugins/gobi.c
index 54b64acb7871..4af3f3846694 100644
--- a/plugins/gobi.c
+++ b/plugins/gobi.c
@@ -45,6 +45,7 @@ 
 #include <drivers/qmimodem/dms.h>
 #include <drivers/qmimodem/wda.h>
 #include <drivers/qmimodem/util.h>
+#include <drivers/qmimodem/common.h>
 
 #define GOBI_DMS	(1 << 0)
 #define GOBI_NAS	(1 << 1)
@@ -57,6 +58,13 @@ 
 
 #define MAX_CONTEXTS 4
 
+#define QMI_WWAN_RAW_IP "/sys/class/net/%s/qmi/raw_ip"
+
+enum wda_data_format {
+	WDA_DATA_FORMAT_UNKNOWN = 0,
+	WDA_DATA_FORMAT_802_3,	/* Last, most compatible legacy fallback */
+};
+
 struct service_request {
 	struct qmi_service **member;
 	uint32_t service_type;
@@ -88,6 +96,7 @@  struct gobi_data {
 	uint8_t interface_number;
 	uint32_t max_aggregation_size;
 	uint32_t set_powered_id;
+	enum wda_data_format data_format;
 	bool using_mux : 1;
 };
 
@@ -105,6 +114,28 @@  static void gobi_io_debug(const char *str, void *user_data)
 	ofono_debug("%s%s", prefix, str);
 }
 
+static bool wda_get_data_format(struct gobi_data *data,
+				struct qmi_wda_data_format *out_format)
+{
+	if (data->data_format == WDA_DATA_FORMAT_UNKNOWN ||
+			data->data_format > WDA_DATA_FORMAT_802_3)
+		return false;
+
+	memset(out_format, 0, sizeof(struct qmi_wda_data_format));
+
+	if (data->data_format == WDA_DATA_FORMAT_802_3) {
+		out_format->ll_protocol = QMI_WDA_DATA_LINK_PROTOCOL_802_3;
+		return true;
+	}
+
+	return false;
+}
+
+static int qmi_wwan_set_raw_ip(const char *interface, char value)
+{
+	return l_sysctl_set_char(value, QMI_WWAN_RAW_IP, interface);
+}
+
 /*
  * Probe the modem.  The following modem properties are expected to be set
  * in order to initialize the driver properly:
@@ -159,11 +190,8 @@  static int gobi_probe(struct ofono_modem *modem)
 		return -EINVAL;
 
 	data = l_new(struct gobi_data, 1);
-	data->main_net_ifindex =
-		ofono_modem_get_integer(modem, "NetworkInterfaceIndex");
-	l_strlcpy(data->main_net_name,
-			ofono_modem_get_string(modem, "NetworkInterface"),
-			sizeof(data->main_net_name));
+	data->main_net_ifindex = ifindex;
+	l_strlcpy(data->main_net_name, ifname, sizeof(data->main_net_name));
 	data->interface_number = interface_number;
 
 	ofono_modem_set_data(modem, data);
@@ -252,6 +280,7 @@  static void __shutdown_device(struct ofono_modem *modem)
 	data->cur_service_request = 0;
 	data->num_service_requests = 0;
 	data->features = 0;
+	data->data_format = WDA_DATA_FORMAT_UNKNOWN;
 
 	qmi_qmux_device_free(data->device);
 	data->device = NULL;
@@ -376,126 +405,113 @@  error:
 	shutdown_device(modem);
 }
 
-static void setup_qmi_wwan(const char *interface, uint32_t llproto)
-{
-	char raw_ip;
-	char new_raw_ip;
-
-	if (l_sysctl_get_char(&raw_ip, "/sys/class/net/%s/qmi/raw_ip",
-				interface) < 0) {
-		DBG("Couldn't query raw_ip setting");
-		return;
-	}
-
-	if (raw_ip != 'Y' && raw_ip != 'N') {
-		DBG("Unexpected value: %c", raw_ip);
-		return;
-	}
-
-	switch (llproto) {
-	case QMI_WDA_DATA_LINK_PROTOCOL_802_3:
-		new_raw_ip = 'N';
-		break;
-	case QMI_WDA_DATA_LINK_PROTOCOL_RAW_IP:
-		new_raw_ip = 'Y';
-		break;
-	default:
-		DBG("Unknown WDA Link Protocol");
-		return;
-	}
-
-	DBG("raw_ip: %c, want: %c", raw_ip, new_raw_ip);
-
-	if (raw_ip == new_raw_ip)
-		return;
-
-	if (l_sysctl_set_char(new_raw_ip, "/sys/class/net/%s/qmi/raw_ip",
-				interface) < 0)
-		DBG("Fail to set raw_ip to %c", new_raw_ip);
-}
-
-static void get_data_format_cb(struct qmi_result *result, void *user_data)
+static void request_service_cb(struct qmi_service *service, void *user_data)
 {
 	struct ofono_modem *modem = user_data;
 	struct gobi_data *data = ofono_modem_get_data(modem);
-	uint32_t llproto;
+	struct service_request *req =
+		&data->service_requests[data->cur_service_request];
 
 	DBG("");
 
-	if (qmi_result_set_error(result, NULL))
-		goto done;
+	if (!service)
+		goto error;
 
-	if (!qmi_result_get_uint32(result, QMI_WDA_LL_PROTOCOL, &llproto))
-		goto done;
+	*req->member = service;
 
-	setup_qmi_wwan(data->main_net_name, llproto);
+	data->cur_service_request += 1;
+	if (data->cur_service_request == data->num_service_requests) {
+		DBG("All services requested, query DMS Capabilities");
 
-done:
-	if (qmi_service_send(data->dms, QMI_DMS_GET_CAPS, NULL,
+		if (qmi_service_send(data->dms, QMI_DMS_GET_CAPS, NULL,
 						get_caps_cb, modem, NULL) > 0)
+			return;
+
+		goto error;
+	}
+
+	req = &data->service_requests[data->cur_service_request];
+	DBG("Requesting: %u", req->service_type);
+
+	if (qmi_qmux_device_create_client(data->device, req->service_type,
+					request_service_cb, modem, NULL))
 		return;
 
+error:
 	shutdown_device(modem);
 }
 
-static void create_wda_cb(struct qmi_service *service, void *user_data)
+static void set_data_format_cb(struct qmi_result *result, void *user_data)
 {
 	struct ofono_modem *modem = user_data;
 	struct gobi_data *data = ofono_modem_get_data(modem);
+	struct qmi_endpoint_info endpoint_info = {
+		.endpoint_type = QMI_DATA_ENDPOINT_TYPE_HSUSB,
+		.interface_number = data->interface_number,
+	};
+	struct qmi_wda_data_format format;
 
 	DBG("");
 
-	if (!service) {
-		DBG("Failed to request WDA service, continue initialization");
+	if (!qmi_result_set_error(result, NULL))
+		goto done;
+
+	if (data->data_format == WDA_DATA_FORMAT_802_3)
 		goto error;
-	}
 
-	data->wda = service;
+	DBG("Trying next data format");
+	data->data_format += 1;
 
-	if (qmi_service_send(data->wda, QMI_WDA_GET_DATA_FORMAT, NULL,
-				get_data_format_cb, modem, NULL) > 0)
-		return;
+	if (!wda_get_data_format(data, &format))
+		goto error;
 
-error:
-	if (qmi_service_send(data->dms, QMI_DMS_GET_CAPS, NULL,
-						get_caps_cb, modem, NULL) > 0)
+	if (qmi_wda_set_data_format(data->wda, &endpoint_info, &format,
+					set_data_format_cb, modem, NULL) > 0)
 		return;
 
+	goto error;
+
+done:
+	DBG("Set Data Format succeeded, proceeding to create services");
+
+	if (qmi_qmux_device_create_client(data->device, QMI_SERVICE_DMS,
+				request_service_cb, modem, NULL) > 0)
+		return;
+error:
 	shutdown_device(modem);
 }
 
-static void request_service_cb(struct qmi_service *service, void *user_data)
+static void create_wda_cb(struct qmi_service *service, void *user_data)
 {
 	struct ofono_modem *modem = user_data;
 	struct gobi_data *data = ofono_modem_get_data(modem);
-	struct service_request *req =
-		&data->service_requests[data->cur_service_request];
+	struct qmi_endpoint_info endpoint_info = {
+		.endpoint_type = QMI_DATA_ENDPOINT_TYPE_HSUSB,
+		.interface_number = data->interface_number,
+	};
+	struct qmi_wda_data_format format;
 
 	DBG("");
 
-	if (!service)
-		goto error;
-
-	*req->member = service;
-
-	data->cur_service_request += 1;
-	if (data->cur_service_request == data->num_service_requests) {
-		DBG("All services requested, proceeding to create WDA");
+	if (!service) {
+		DBG("Failed to request WDA service, assume 802.3");
 
-		if (qmi_qmux_device_create_client(data->device, QMI_SERVICE_WDA,
-						create_wda_cb, modem, NULL))
+		if (qmi_qmux_device_create_client(data->device, QMI_SERVICE_DMS,
+					request_service_cb, modem, NULL) > 0)
 			return;
 
 		goto error;
 	}
 
-	req = &data->service_requests[data->cur_service_request];
-	DBG("Requesting: %u", req->service_type);
+	data->wda = service;
+	data->data_format = WDA_DATA_FORMAT_UNKNOWN + 1;
 
-	if (qmi_qmux_device_create_client(data->device, req->service_type,
-					request_service_cb, modem, NULL))
-		return;
+	if (!wda_get_data_format(data, &format))
+		goto error;
 
+	if (qmi_wda_set_data_format(data->wda, &endpoint_info, &format,
+					set_data_format_cb, modem, NULL) > 0)
+		return;
 error:
 	shutdown_device(modem);
 }
@@ -563,9 +579,10 @@  static void discover_cb(void *user_data)
 							QMI_SERVICE_WDS);
 	}
 
-	if (qmi_qmux_device_create_client(data->device, QMI_SERVICE_DMS,
-					request_service_cb, modem, NULL) > 0)
+	if (qmi_qmux_device_create_client(data->device, QMI_SERVICE_WDA,
+						create_wda_cb, modem, NULL))
 		return;
+
 error:
 	shutdown_device(modem);
 }
@@ -585,6 +602,14 @@  static void init_powered_down_cb(int error, uint16_t type,
 	if (error)
 		goto error;
 
+	DBG("Setting QMI_WWAN to 802.3 mode");
+
+	r = qmi_wwan_set_raw_ip(data->main_net_name, 'N');
+	if (r < 0) {
+		ofono_warn("Unable to reset raw_ip");
+		goto error;
+	}
+
 	r = qmi_qmux_device_discover(data->device, discover_cb, modem, NULL);
 	if (!r)
 		return;