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

Commit 05a66c6f authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: dfc: Fix flow control issues"

parents 289f176f beda5089
Loading
Loading
Loading
Loading
+21 −9
Original line number Diff line number Diff line
@@ -1072,14 +1072,10 @@ static void dfc_svc_init(struct work_struct *work)
						 svc_arrive);
	struct qmi_info *qmi;

	rc = dfc_init_service(data);
	if (rc < 0)
		goto clean_out;
	if (data->restart_state == 1)
		return;

	trace_dfc_client_state_up(data->index,
			   data->svc.instance,
			   data->svc.ep_type,
			   data->svc.iface_id);
	rc = dfc_init_service(data);

	rtnl_lock();
	qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port);
@@ -1088,7 +1084,17 @@ static void dfc_svc_init(struct work_struct *work)
		goto clean_out;
	}

	qmi->dfc_pending[data->index] = NULL;
	if (rc < 0) {
		rtnl_unlock();
		goto clean_out;
	} else {
		qmi->dfc_clients[data->index] = (void *)data;
		trace_dfc_client_state_up(data->index,
					  data->svc.instance,
					  data->svc.ep_type,
					  data->svc.iface_id);
	}
	rtnl_unlock();

	pr_info("Connection established with the DFC Service\n");
@@ -1139,11 +1145,15 @@ static struct qmi_msg_handler qmi_indication_handler[] = {
	{},
};

int dfc_qmi_client_init(void *port, int index, struct svc_info *psvc)
int dfc_qmi_client_init(void *port, int index, struct svc_info *psvc,
			struct qmi_info *qmi)
{
	struct dfc_qmi_data *data;
	int rc = -ENOMEM;

	if (!port || !qmi)
		return -EINVAL;

	data = kzalloc(sizeof(struct dfc_qmi_data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;
@@ -1180,6 +1190,8 @@ int dfc_qmi_client_init(void *port, int index, struct svc_info *psvc)
		goto err2;
	}

	qmi->dfc_pending[index] = (void *)data;

	return 0;

err2:
+53 −15
Original line number Diff line number Diff line
@@ -103,6 +103,22 @@ qmi_rmnet_has_client(struct qmi_info *qmi)
	return qmi_rmnet_has_dfc_client(qmi) ? 1 : 0;
}

static int
qmi_rmnet_has_pending(struct qmi_info *qmi)
{
	int i;

	if (qmi->wda_pending)
		return 1;

	for (i = 0; i < MAX_CLIENT_NUM; i++) {
		if (qmi->dfc_pending[i])
			return 1;
	}

	return 0;
}

#ifdef CONFIG_QCOM_QMI_DFC
static void
qmi_rmnet_clean_flow_list(struct qmi_info *qmi, struct net_device *dev,
@@ -311,12 +327,12 @@ qmi_rmnet_del_flow(struct net_device *dev, struct tcmsg *tcm,

static void qmi_rmnet_query_flows(struct qmi_info *qmi)
{
	void *dfc_data = qmi_rmnet_has_dfc_client(qmi);

	if (!dfc_data)
		return;
	int i;

	dfc_qmi_query_flow(dfc_data);
	for (i = 0; i < MAX_CLIENT_NUM; i++) {
		if (qmi->dfc_clients[i])
			dfc_qmi_query_flow(qmi->dfc_clients[i]);
	}
}

static int qmi_rmnet_set_scale_factor(const char *val,
@@ -403,15 +419,15 @@ qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm)
	svc.iface_id = tcm->tcm_parent;

	if (((tcm->tcm_ifindex & FLAG_DFC_MASK) == DFC_MODE_MULTIQ) &&
	    (qmi->dfc_clients[idx] == NULL)) {
		rc = dfc_qmi_client_init(port, idx, &svc);
	    !qmi->dfc_clients[idx] && !qmi->dfc_pending[idx]) {
		rc = dfc_qmi_client_init(port, idx, &svc, qmi);
		if (rc < 0)
			err = rc;
	}

	if ((tcm->tcm_ifindex & FLAG_POWERSAVE_MASK) &&
	    (idx == 0) && (qmi->wda_client == NULL)) {
		rc = wda_qmi_client_init(port, &svc);
	    (idx == 0) && !qmi->wda_client && !qmi->wda_pending) {
		rc = wda_qmi_client_init(port, &svc, qmi);
		if (rc < 0)
			err = rc;
	}
@@ -422,11 +438,19 @@ qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm)
static int
__qmi_rmnet_delete_client(void *port, struct qmi_info *qmi, int idx)
{
	void *data = NULL;

	ASSERT_RTNL();

	if (qmi->dfc_clients[idx]) {
		dfc_qmi_client_exit(qmi->dfc_clients[idx]);
	if (qmi->dfc_clients[idx])
		data = qmi->dfc_clients[idx];
	else if (qmi->dfc_pending[idx])
		data = qmi->dfc_pending[idx];

	if (data) {
		dfc_qmi_client_exit(data);
		qmi->dfc_clients[idx] = NULL;
		qmi->dfc_pending[idx] = NULL;
	}

	if (!qmi_rmnet_has_client(qmi)) {
@@ -442,15 +466,21 @@ static void
qmi_rmnet_delete_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm)
{
	int idx;
	void *data = NULL;

	/* client delete: tcm->tcm_handle - instance*/
	idx = (tcm->tcm_handle == 0) ? 0 : 1;

	ASSERT_RTNL();
	if (qmi->wda_client)
		data = qmi->wda_client;
	else if (qmi->wda_pending)
		data = qmi->wda_pending;

	if ((idx == 0) && qmi->wda_client) {
		wda_qmi_client_exit(qmi->wda_client);
	if ((idx == 0) && data) {
		wda_qmi_client_exit(data);
		qmi->wda_client = NULL;
		qmi->wda_pending = NULL;
	}

	__qmi_rmnet_delete_client(port, qmi, idx);
@@ -481,7 +511,8 @@ void qmi_rmnet_change_link(struct net_device *dev, void *port, void *tcm_pt)
			return;

		if (qmi_rmnet_setup_client(port, qmi, tcm) < 0) {
			if (!qmi_rmnet_has_client(qmi)) {
			if (!qmi_rmnet_has_client(qmi) &&
			    !qmi_rmnet_has_pending(qmi)) {
				kfree(qmi);
				rmnet_reset_qmi_pt(port);
			}
@@ -511,6 +542,7 @@ void qmi_rmnet_qmi_exit(void *qmi_pt, void *port)
{
	struct qmi_info *qmi = (struct qmi_info *)qmi_pt;
	int i;
	void *data = NULL;

	if (!qmi)
		return;
@@ -519,9 +551,15 @@ void qmi_rmnet_qmi_exit(void *qmi_pt, void *port)

	qmi_rmnet_work_exit(port);

	if (qmi->wda_client) {
	if (qmi->wda_client)
		data = qmi->wda_client;
	else if (qmi->wda_pending)
		data = qmi->wda_pending;

	if (data) {
		wda_qmi_client_exit(qmi->wda_client);
		qmi->wda_client = NULL;
		qmi->wda_pending = NULL;
	}

	for (i = 0; i < MAX_CLIENT_NUM; i++) {
+10 −4
Original line number Diff line number Diff line
@@ -70,7 +70,9 @@ struct flow_info {
struct qmi_info {
	int flag;
	void *wda_client;
	void *wda_pending;
	void *dfc_clients[MAX_CLIENT_NUM];
	void *dfc_pending[MAX_CLIENT_NUM];
	unsigned long ps_work_active;
	int ps_enabled;
};
@@ -105,7 +107,8 @@ qmi_rmnet_get_bearer_map(struct qos_info *qos_info, u8 bearer_id);

unsigned int qmi_rmnet_grant_per(unsigned int grant);

int dfc_qmi_client_init(void *port, int index, struct svc_info *psvc);
int dfc_qmi_client_init(void *port, int index, struct svc_info *psvc,
			struct qmi_info *qmi);

void dfc_qmi_client_exit(void *dfc_data);

@@ -132,7 +135,8 @@ qmi_rmnet_get_bearer_map(struct qos_info *qos_info, u8 bearer_id)
}

static inline int
dfc_qmi_client_init(void *port, int index, struct svc_info *psvc)
dfc_qmi_client_init(void *port, int index, struct svc_info *psvc,
		    struct qmi_info *qmi)
{
	return -EINVAL;
}
@@ -159,11 +163,13 @@ dfc_qmi_query_flow(void *dfc_data)
#endif

#ifdef CONFIG_QCOM_QMI_POWER_COLLAPSE
int wda_qmi_client_init(void *port, struct svc_info *psvc);
int
wda_qmi_client_init(void *port, struct svc_info *psvc, struct qmi_info *qmi);
void wda_qmi_client_exit(void *wda_data);
int wda_set_powersave_mode(void *wda_data, u8 enable);
#else
static inline int wda_qmi_client_init(void *port, struct svc_info *psvc)
static inline int
wda_qmi_client_init(void *port, struct svc_info *psvc, struct qmi_info *qmi)
{
	return -EINVAL;
}
+29 −21
Original line number Diff line number Diff line
@@ -319,16 +319,10 @@ static void wda_svc_config(struct work_struct *work)
	struct wda_qmi_data *data = container_of(work, struct wda_qmi_data,
						 svc_arrive);
	struct qmi_info *qmi;
	int rc;

	if (wda_set_powersave_config_req(&data->handle) < 0) {
		pr_err("%s() failed, qmi handle pt: %p\n",
			__func__, &data->handle);
		goto clean_out;
	}
	rc = wda_set_powersave_config_req(&data->handle);

	trace_wda_client_state_up(data->svc.instance,
				  data->svc.ep_type,
				  data->svc.iface_id);
	rtnl_lock();
	qmi = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port);
	if (!qmi) {
@@ -336,7 +330,17 @@ static void wda_svc_config(struct work_struct *work)
		goto clean_out;
	}

	qmi->wda_pending = NULL;
	if (rc < 0) {
		rtnl_unlock();
		goto clean_out;
	} else {
		qmi->wda_client = (void *)data;
		trace_wda_client_state_up(data->svc.instance,
					  data->svc.ep_type,
					  data->svc.iface_id);

	}
	rtnl_unlock();

	pr_info("Connection established with the WDA Service\n");
@@ -376,16 +380,15 @@ static struct qmi_ops server_ops = {
	.del_server = wda_svc_exit,
};

int wda_qmi_client_init(void *port, struct svc_info *psvc)
int
wda_qmi_client_init(void *port, struct svc_info *psvc, struct qmi_info *qmi)
{
	struct wda_qmi_data *data;
	int rc = 0;
	int rc = -ENOMEM;

	if (!port)
	if (!port || !qmi)
		return -EINVAL;

	pr_info("%s\n", __func__);

	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;
@@ -393,8 +396,7 @@ int wda_qmi_client_init(void *port, struct svc_info *psvc)
	data->wda_wq = create_singlethread_workqueue("wda_wq");
	if (!data->wda_wq) {
		pr_err("%s Could not create workqueue\n", __func__);
		kfree(data);
		return -ENOMEM;
		goto err0;
	}

	data->rmnet_port = port;
@@ -406,19 +408,25 @@ int wda_qmi_client_init(void *port, struct svc_info *psvc)
			     &server_ops, NULL);
	if (rc < 0) {
		pr_err("%s: Failed qmi_handle_init, err: %d\n", __func__, rc);
		kfree(data);
		return rc;
		goto err1;
	}

	rc = qmi_add_lookup(&data->handle, WDA_SERVICE_ID_V01,
			    WDA_SERVICE_VERS_V01, psvc->instance);
	if (rc < 0) {
		pr_err("%s(): Failed qmi_add_lookup, err: %d\n", __func__, rc);
		goto err2;
	}

	qmi->wda_pending = (void *)data;
	return 0;

err2:
	qmi_handle_release(&data->handle);
err1:
	destroy_workqueue(data->wda_wq);
err0:
	kfree(data);
	}

	return rc;
}