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

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

Merge "soc: qcom: dfc: Fix qmi indication size"

parents ba23760b 1d535d55
Loading
Loading
Loading
Loading
+285 −16
Original line number Diff line number Diff line
@@ -77,11 +77,11 @@ static void dfc_svc_init(struct work_struct *work);

#define QMI_DFC_INDICATION_REGISTER_REQ_V01 0x0001
#define QMI_DFC_INDICATION_REGISTER_RESP_V01 0x0001
#define QMI_DFC_INDICATION_REGISTER_REQ_V01_MAX_MSG_LEN 4
#define QMI_DFC_INDICATION_REGISTER_REQ_V01_MAX_MSG_LEN 8
#define QMI_DFC_INDICATION_REGISTER_RESP_V01_MAX_MSG_LEN 7

#define QMI_DFC_FLOW_STATUS_IND_V01 0x0022
#define QMI_DFC_FLOW_STATUS_IND_V01_MAX_MSG_LEN 540
#define QMI_DFC_TX_LINK_STATUS_IND_V01 0x0024

#define QMI_DFC_GET_FLOW_STATUS_REQ_V01 0x0023
#define QMI_DFC_GET_FLOW_STATUS_RESP_V01 0x0023
@@ -100,6 +100,8 @@ struct dfc_bind_client_resp_msg_v01 {
struct dfc_indication_register_req_msg_v01 {
	u8 report_flow_status_valid;
	u8 report_flow_status;
	u8 report_tx_link_status_valid;
	u8 report_tx_link_status;
};

struct dfc_indication_register_resp_msg_v01 {
@@ -311,6 +313,20 @@ struct dfc_flow_status_ind_msg_v01 {
	struct dfc_ancillary_info_type_v01 ancillary_info[DFC_MAX_BEARERS_V01];
};

struct dfc_bearer_info_type_v01 {
	u8 subs_id;
	u8 mux_id;
	u8 bearer_id;
	enum dfc_ip_type_enum_v01 ip_type;
};

struct dfc_tx_link_status_ind_msg_v01 {
	u8 tx_status;
	u8 bearer_info_valid;
	u8 bearer_info_len;
	struct dfc_bearer_info_type_v01 bearer_info[DFC_MAX_BEARERS_V01];
};

struct dfc_get_flow_status_req_msg_v01 {
	u8 bearer_id_list_valid;
	u8 bearer_id_list_len;
@@ -326,7 +342,11 @@ struct dfc_get_flow_status_resp_msg_v01 {

struct dfc_svc_ind {
	struct list_head list;
	u16 msg_id;
	union {
		struct dfc_flow_status_ind_msg_v01 dfc_info;
		struct dfc_tx_link_status_ind_msg_v01 tx_status;
	} d;
};

static struct qmi_elem_info dfc_bind_client_req_msg_v01_ei[] = {
@@ -398,6 +418,28 @@ static struct qmi_elem_info dfc_indication_register_req_msg_v01_ei[] = {
					   report_flow_status),
		.ei_array	= NULL,
	},
	{
		.data_type	= QMI_OPT_FLAG,
		.elem_len	= 1,
		.elem_size	= sizeof(u8),
		.array_type	= NO_ARRAY,
		.tlv_type	= 0x11,
		.offset		= offsetof(struct
					   dfc_indication_register_req_msg_v01,
					   report_tx_link_status_valid),
		.ei_array	= NULL,
	},
	{
		.data_type	= QMI_UNSIGNED_1_BYTE,
		.elem_len	= 1,
		.elem_size	= sizeof(u8),
		.array_type	= NO_ARRAY,
		.tlv_type	= 0x11,
		.offset		= offsetof(struct
					   dfc_indication_register_req_msg_v01,
					   report_tx_link_status),
		.ei_array	= NULL,
	},
	{
		.data_type	= QMI_EOTI,
		.array_type	= NO_ARRAY,
@@ -616,6 +658,111 @@ static struct qmi_elem_info dfc_get_flow_status_resp_msg_v01_ei[] = {
	},
};

static struct qmi_elem_info dfc_bearer_info_type_v01_ei[] = {
	{
		.data_type	= QMI_UNSIGNED_1_BYTE,
		.elem_len	= 1,
		.elem_size	= sizeof(u8),
		.array_type	= NO_ARRAY,
		.tlv_type	= QMI_COMMON_TLV_TYPE,
		.offset		= offsetof(struct
					   dfc_bearer_info_type_v01,
					   subs_id),
		.ei_array	= NULL,
	},
	{
		.data_type	= QMI_UNSIGNED_1_BYTE,
		.elem_len	= 1,
		.elem_size	= sizeof(u8),
		.array_type	= NO_ARRAY,
		.tlv_type	= QMI_COMMON_TLV_TYPE,
		.offset		= offsetof(struct
					   dfc_bearer_info_type_v01,
					   mux_id),
		.ei_array	= NULL,
	},
	{
		.data_type	= QMI_UNSIGNED_1_BYTE,
		.elem_len	= 1,
		.elem_size	= sizeof(u8),
		.array_type	= NO_ARRAY,
		.tlv_type	= QMI_COMMON_TLV_TYPE,
		.offset		= offsetof(struct
					   dfc_bearer_info_type_v01,
					   bearer_id),
		.ei_array	= NULL,
	},
	{
		.data_type	= QMI_SIGNED_4_BYTE_ENUM,
		.elem_len	= 1,
		.elem_size	= sizeof(enum dfc_ip_type_enum_v01),
		.array_type	= NO_ARRAY,
		.tlv_type	= QMI_COMMON_TLV_TYPE,
		.offset		= offsetof(struct
					   dfc_bearer_info_type_v01,
					   ip_type),
		.ei_array	= NULL,
	},
	{
		.data_type	= QMI_EOTI,
		.array_type	= NO_ARRAY,
		.tlv_type	= QMI_COMMON_TLV_TYPE,
	},
};

static struct qmi_elem_info dfc_tx_link_status_ind_v01_ei[] = {
	{
		.data_type	= QMI_UNSIGNED_1_BYTE,
		.elem_len	= 1,
		.elem_size	= sizeof(u8),
		.array_type	= NO_ARRAY,
		.tlv_type	= 0x01,
		.offset		= offsetof(struct
					   dfc_tx_link_status_ind_msg_v01,
					   tx_status),
		.ei_array	= NULL,
	},
	{
		.data_type	= QMI_OPT_FLAG,
		.elem_len	= 1,
		.elem_size	= sizeof(u8),
		.array_type	= NO_ARRAY,
		.tlv_type	= 0x10,
		.offset		= offsetof(struct
					   dfc_tx_link_status_ind_msg_v01,
					   bearer_info_valid),
		.ei_array	= NULL,
	},
	{
		.data_type	= QMI_DATA_LEN,
		.elem_len	= 1,
		.elem_size	= sizeof(u8),
		.array_type	= NO_ARRAY,
		.tlv_type	= 0x10,
		.offset		= offsetof(struct
					   dfc_tx_link_status_ind_msg_v01,
					   bearer_info_len),
		.ei_array	= NULL,
	},
	{
		.data_type	= QMI_STRUCT,
		.elem_len	= DFC_MAX_BEARERS_V01,
		.elem_size	= sizeof(struct
					 dfc_bearer_info_type_v01),
		.array_type	= VAR_LEN_ARRAY,
		.tlv_type	= 0x10,
		.offset		= offsetof(struct
					   dfc_tx_link_status_ind_msg_v01,
					   bearer_info),
		.ei_array	= dfc_bearer_info_type_v01_ei,
	},
	{
		.data_type	= QMI_EOTI,
		.array_type	= NO_ARRAY,
		.tlv_type	= QMI_COMMON_TLV_TYPE,
	},
};

static int
dfc_bind_client_req(struct qmi_handle *dfc_handle,
		    struct sockaddr_qrtr *ssctl, struct svc_info *svc)
@@ -702,6 +849,9 @@ dfc_indication_register_req(struct qmi_handle *dfc_handle,

	req->report_flow_status_valid = 1;
	req->report_flow_status = reg;
	req->report_tx_link_status_valid = 1;
	req->report_tx_link_status = reg;

	ret = qmi_send_request(dfc_handle, ssctl, &txn,
			       QMI_DFC_INDICATION_REGISTER_REQ_V01,
			       QMI_DFC_INDICATION_REGISTER_REQ_V01_MAX_MSG_LEN,
@@ -834,7 +984,7 @@ dfc_send_ack(struct net_device *dev, u8 bearer_id, u16 seq, u8 mux_id, u8 type)
	rmnet_map_tx_qmap_cmd(skb);
}

static int dfc_bearer_flow_ctl(struct net_device *dev,
int dfc_bearer_flow_ctl(struct net_device *dev,
			struct rmnet_bearer_map *bearer,
			struct qos_info *qos)
{
@@ -928,6 +1078,10 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,
			if (itm->rat_switch)
				return 0;

		/* If TX is OFF but we received grant, ignore it */
		if (itm->tx_off  && fc_info->num_bytes > 0)
			return 0;

		if ((itm->grant_size == 0 && fc_info->num_bytes > 0) ||
		    (itm->grant_size > 0 && fc_info->num_bytes == 0))
			action = true;
@@ -951,7 +1105,7 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,
static void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc,
				      struct dfc_svc_ind *svc_ind)
{
	struct dfc_flow_status_ind_msg_v01 *ind = &svc_ind->dfc_info;
	struct dfc_flow_status_ind_msg_v01 *ind = &svc_ind->d.dfc_info;
	struct net_device *dev;
	struct qos_info *qos;
	struct dfc_flow_status_info_type_v01 *flow_status;
@@ -1015,6 +1169,71 @@ static void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc,
	rcu_read_unlock();
}

static void dfc_update_tx_link_status(struct net_device *dev,
				      struct qos_info *qos, u8 tx_status,
				      struct dfc_bearer_info_type_v01 *binfo)
{
	struct rmnet_bearer_map *itm = NULL;

	itm = qmi_rmnet_get_bearer_map(qos, binfo->bearer_id);
	if (!itm)
		return;

	if (itm->grant_size && !tx_status) {
		itm->grant_size = 0;
		itm->tcp_bidir = false;
		dfc_bearer_flow_ctl(dev, itm, qos);
	} else if (itm->grant_size == 0 && tx_status && !itm->rat_switch) {
		itm->grant_size = DEFAULT_GRANT;
		itm->grant_thresh = DEFAULT_GRANT;
		itm->seq = 0;
		itm->ack_req = 0;
		dfc_bearer_flow_ctl(dev, itm, qos);
	}

	itm->tx_off = !tx_status;
}

static void dfc_handle_tx_link_status_ind(struct dfc_qmi_data *dfc,
					  struct dfc_svc_ind *svc_ind)
{
	struct dfc_tx_link_status_ind_msg_v01 *ind = &svc_ind->d.tx_status;
	struct net_device *dev;
	struct qos_info *qos;
	struct dfc_bearer_info_type_v01 *bearer_info;
	int i;

	rcu_read_lock();

	for (i = 0; i < ind->bearer_info_len; i++) {
		bearer_info = &ind->bearer_info[i];

		trace_dfc_tx_link_status_ind(dfc->index, i,
					     ind->tx_status,
					     bearer_info->mux_id,
					     bearer_info->bearer_id);

		dev = rmnet_get_rmnet_dev(dfc->rmnet_port,
					  bearer_info->mux_id);
		if (!dev)
			goto clean_out;

		qos = (struct qos_info *)rmnet_get_qos_pt(dev);
		if (!qos)
			continue;

		spin_lock_bh(&qos->qos_lock);

		dfc_update_tx_link_status(
			dev, qos, ind->tx_status, bearer_info);

		spin_unlock_bh(&qos->qos_lock);
	}

clean_out:
	rcu_read_unlock();
}

static void dfc_qmi_ind_work(struct work_struct *work)
{
	struct dfc_qmi_data *dfc = container_of(work, struct dfc_qmi_data,
@@ -1035,12 +1254,18 @@ static void dfc_qmi_ind_work(struct work_struct *work)
			list_del(&svc_ind->list);
		spin_unlock_irqrestore(&dfc->qmi_ind_lock, flags);

		if (svc_ind) {
			if (!dfc->restart_state)
		if (!svc_ind)
			break;

		if (!dfc->restart_state) {
			if (svc_ind->msg_id == QMI_DFC_FLOW_STATUS_IND_V01)
				dfc_do_burst_flow_control(dfc, svc_ind);
			kfree(svc_ind);
			else if (svc_ind->msg_id ==
					QMI_DFC_TX_LINK_STATUS_IND_V01)
				dfc_handle_tx_link_status_ind(dfc, svc_ind);
		}
	} while (svc_ind != NULL);
		kfree(svc_ind);
	} while (1);

	local_bh_enable();

@@ -1071,7 +1296,44 @@ static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
		if (!svc_ind)
			return;

		memcpy(&svc_ind->dfc_info, ind_msg, sizeof(*ind_msg));
		svc_ind->msg_id = QMI_DFC_FLOW_STATUS_IND_V01;
		memcpy(&svc_ind->d.dfc_info, ind_msg, sizeof(*ind_msg));

		spin_lock_irqsave(&dfc->qmi_ind_lock, flags);
		list_add_tail(&svc_ind->list, &dfc->qmi_ind_q);
		spin_unlock_irqrestore(&dfc->qmi_ind_lock, flags);

		queue_work(dfc->dfc_wq, &dfc->qmi_ind_work);
	}
}

static void dfc_tx_link_status_ind_cb(struct qmi_handle *qmi,
				      struct sockaddr_qrtr *sq,
				      struct qmi_txn *txn, const void *data)
{
	struct dfc_qmi_data *dfc = container_of(qmi, struct dfc_qmi_data,
						handle);
	struct dfc_tx_link_status_ind_msg_v01 *ind_msg;
	struct dfc_svc_ind *svc_ind;
	unsigned long flags;

	if (qmi != &dfc->handle)
		return;

	ind_msg = (struct dfc_tx_link_status_ind_msg_v01 *)data;
	if (ind_msg->bearer_info_valid) {
		if (ind_msg->bearer_info_len > DFC_MAX_BEARERS_V01) {
			pr_err("%s() Invalid bearer info len: %d\n",
			       __func__, ind_msg->bearer_info_len);
			return;
		}

		svc_ind = kzalloc(sizeof(struct dfc_svc_ind), GFP_ATOMIC);
		if (!svc_ind)
			return;

		svc_ind->msg_id = QMI_DFC_TX_LINK_STATUS_IND_V01;
		memcpy(&svc_ind->d.tx_status, ind_msg, sizeof(*ind_msg));

		spin_lock_irqsave(&dfc->qmi_ind_lock, flags);
		list_add_tail(&svc_ind->list, &dfc->qmi_ind_q);
@@ -1156,9 +1418,16 @@ static struct qmi_msg_handler qmi_indication_handler[] = {
		.type = QMI_INDICATION,
		.msg_id = QMI_DFC_FLOW_STATUS_IND_V01,
		.ei = dfc_flow_status_ind_v01_ei,
		.decoded_size = QMI_DFC_FLOW_STATUS_IND_V01_MAX_MSG_LEN,
		.decoded_size = sizeof(struct dfc_flow_status_ind_msg_v01),
		.fn = dfc_clnt_ind_cb,
	},
	{
		.type = QMI_INDICATION,
		.msg_id = QMI_DFC_TX_LINK_STATUS_IND_V01,
		.ei = dfc_tx_link_status_ind_v01_ei,
		.decoded_size = sizeof(struct dfc_tx_link_status_ind_msg_v01),
		.fn = dfc_tx_link_status_ind_cb,
	},
	{},
};

@@ -1307,9 +1576,9 @@ void dfc_qmi_query_flow(void *dfc_data)
	    resp->flow_status_len > DFC_MAX_BEARERS_V01)
		goto done;

	svc_ind->dfc_info.flow_status_valid = resp->flow_status_valid;
	svc_ind->dfc_info.flow_status_len = resp->flow_status_len;
	memcpy(&svc_ind->dfc_info.flow_status, resp->flow_status,
	svc_ind->d.dfc_info.flow_status_valid = resp->flow_status_valid;
	svc_ind->d.dfc_info.flow_status_len = resp->flow_status_len;
	memcpy(&svc_ind->d.dfc_info.flow_status, resp->flow_status,
		sizeof(resp->flow_status[0]) * resp->flow_status_len);
	dfc_do_burst_flow_control(data, svc_ind);

+6 −7
Original line number Diff line number Diff line
@@ -575,7 +575,7 @@ void qmi_rmnet_enable_all_flows(struct net_device *dev)
{
	struct qos_info *qos;
	struct rmnet_bearer_map *bearer;
	bool do_wake = false;
	bool do_wake;

	qos = (struct qos_info *)rmnet_get_qos_pt(dev);
	if (!qos)
@@ -584,19 +584,18 @@ void qmi_rmnet_enable_all_flows(struct net_device *dev)
	spin_lock_bh(&qos->qos_lock);

	list_for_each_entry(bearer, &qos->bearer_head, list) {
		if (!bearer->grant_size)
			do_wake = true;
		if (bearer->tx_off)
			continue;
		do_wake = !bearer->grant_size;
		bearer->grant_size = DEFAULT_GRANT;
		bearer->grant_thresh = DEFAULT_GRANT;
		bearer->seq = 0;
		bearer->ack_req = 0;
		bearer->tcp_bidir = false;
		bearer->rat_switch = false;
	}

	if (do_wake) {
		netif_tx_wake_all_queues(dev);
		trace_dfc_qmi_tc(dev->name, 0xFF, 0, DEFAULT_GRANT, 0, 0, 1);
		if (do_wake)
			dfc_bearer_flow_ctl(dev, bearer, qos);
	}

	spin_unlock_bh(&qos->qos_lock);
+13 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ struct rmnet_bearer_map {
	u16 last_seq;
	bool tcp_bidir;
	bool rat_switch;
	bool tx_off;
};

struct svc_info {
@@ -113,6 +114,10 @@ void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos,
int qmi_rmnet_flow_control(struct net_device *dev, u32 tcm_handle, int enable);

void dfc_qmi_query_flow(void *dfc_data);

int dfc_bearer_flow_ctl(struct net_device *dev,
			struct rmnet_bearer_map *bearer,
			struct qos_info *qos);
#else
static inline struct rmnet_flow_map *
qmi_rmnet_get_flow_map(struct qos_info *qos_info,
@@ -148,6 +153,14 @@ static inline void
dfc_qmi_query_flow(void *dfc_data)
{
}

static inline int
dfc_bearer_flow_ctl(struct net_device *dev,
		    struct rmnet_bearer_map *bearer,
		    struct qos_info *qos)
{
	return 0;
}
#endif

#ifdef CONFIG_QCOM_QMI_POWER_COLLAPSE
+27 −0
Original line number Diff line number Diff line
@@ -208,6 +208,33 @@ TRACE_EVENT(dfc_qmap_cmd,
		__entry->type, __entry->tran)
);

TRACE_EVENT(dfc_tx_link_status_ind,

	TP_PROTO(int src, int idx, u8 status, u8 mux_id, u8 bearer_id),

	TP_ARGS(src, idx, status, mux_id, bearer_id),

	TP_STRUCT__entry(
		__field(int, src)
		__field(int, idx)
		__field(u8, status)
		__field(u8, mid)
		__field(u8, bid)
	),

	TP_fast_assign(
		__entry->src = src;
		__entry->idx = idx;
		__entry->status = status;
		__entry->mid = mux_id;
		__entry->bid = bearer_id;
	),

	TP_printk("src=%d [%d]: status=%u mux_id=%u bearer_id=%u",
		__entry->src, __entry->idx, __entry->status,
		__entry->mid, __entry->bid)
);

#endif /* _TRACE_DFC_H */

/* This part must be outside protection */