Loading drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c +3 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ #include "rmnet_vnd.h" #include <soc/qcom/qmi_rmnet.h> #define CREATE_TRACE_POINTS #include <trace/events/rmnet.h> /* RX/TX Fixup */ Loading Loading @@ -62,6 +64,7 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, priv = netdev_priv(dev); if (priv->real_dev) { trace_rmnet_xmit_skb(skb); qmi_rmnet_burst_fc_check(dev, skb); rmnet_egress_handler(skb); } else { Loading drivers/soc/qcom/dfc_qmi.c +91 −97 Original line number Diff line number Diff line Loading @@ -18,23 +18,20 @@ #include <linux/ip.h> #include "qmi_rmnet_i.h" #define CREATE_TRACE_POINTS #include <trace/events/dfc.h> #define DFC_MAX_BEARERS_V01 16 #define DFC_MAX_QOS_ID_V01 2 #define DEFAULT_FLOW_ID 0 /* bearer list update result */ #define NO_BEARER 0 #define NO_CHANGE 1 #define UPDATED 2 struct dfc_qmi_data { void *rmnet_port; struct workqueue_struct *dfc_wq; struct work_struct svc_arrive; struct qmi_handle handle; struct sockaddr_qrtr ssctl; int modem; int index; }; struct dfc_svc_ind { Loading Loading @@ -512,98 +509,94 @@ static int dfc_init_service(struct dfc_qmi_data *data, struct qmi_info *qmi) int rc; rc = dfc_bind_client_req(&data->handle, &data->ssctl, &qmi->fc_info[data->modem].svc); &qmi->fc_info[data->index].svc); if (rc < 0) return rc; return dfc_indication_register_req(&data->handle, &data->ssctl, 1); } static int dfc_disable_bearer_flows(struct net_device *dev, u8 bearer_id) static int dfc_bearer_flow_ctl(struct net_device *dev, struct qos_info *qos, u8 bearer_id, u32 grant_size, int enable) { struct qos_info *qos = (struct qos_info *)rmnet_get_qos_pt(dev); struct list_head *p; struct rmnet_flow_map *itm; int rc = 0; if (!qos) return 0; int rc = 0, qlen; list_for_each(p, &qos->flow_head) { itm = list_entry(p, struct rmnet_flow_map, list); if (unlikely(!itm)) return 0; if (itm->bearer_id == bearer_id) { tc_qdisc_flow_control(dev, itm->tcm_handle, 0); qlen = tc_qdisc_flow_control(dev, itm->tcm_handle, enable); trace_dfc_qmi_tc(itm->bearer_id, itm->flow_id, grant_size, qlen, itm->tcm_handle, enable); rc++; } } return rc; } static int dfc_update_fc_map(struct qos_info *qos, u8 ack_req, static int dfc_all_bearer_flow_ctl(struct net_device *dev, struct qos_info *qos, u8 ack_req, struct dfc_flow_status_info_type_v01 *fc_info) { struct rmnet_bearer_map *itm = NULL; int rc = NO_BEARER; struct list_head *p; struct rmnet_flow_map *flow_itm; struct rmnet_bearer_map *bearer_itm; int enable; int rc = 0, len; itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id); if (itm) { if ((itm->grant_size == fc_info->num_bytes) && (itm->counter > 0)) { /*flow is enabled and grant_size is the same*/ rc = NO_CHANGE; } else { itm->grant_size = fc_info->num_bytes; itm->seq = fc_info->seq_num; itm->ack_req = ack_req; rc = UPDATED; list_for_each(p, &qos->bearer_head) { bearer_itm = list_entry(p, struct rmnet_bearer_map, list); bearer_itm->grant_size = fc_info->num_bytes; bearer_itm->seq = fc_info->seq_num; bearer_itm->ack_req = ack_req; } itm->counter = 0; enable = fc_info->num_bytes > 0 ? 1 : 0; list_for_each(p, &qos->flow_head) { flow_itm = list_entry(p, struct rmnet_flow_map, list); len = tc_qdisc_flow_control(dev, flow_itm->tcm_handle, enable); trace_dfc_qmi_tc(flow_itm->bearer_id, flow_itm->flow_id, fc_info->num_bytes, len, flow_itm->tcm_handle, enable); rc++; } return rc; } static int dfc_do_fc(struct net_device *dev, u32 flow_id, int ip_type, int enable) static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, u8 ack_req, struct dfc_flow_status_info_type_v01 *fc_info) { struct qos_info *qos = (struct qos_info *)rmnet_get_qos_pt(dev); struct rmnet_flow_map *itm = NULL; int len = 0; if (!qos) return 0; struct rmnet_bearer_map *itm = NULL; int rc = 0; int action = -1; itm = qmi_rmnet_get_flow_map(qos, flow_id, ip_type); itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id); if (itm) { len = tc_qdisc_flow_control(dev, itm->tcm_handle, enable); } return len; } if (itm->grant_size == 0 && fc_info->num_bytes > 0) action = 1; else if (itm->grant_size > 0 && fc_info->num_bytes == 0) action = 0; static void dfc_do_flow_controls(struct net_device *dev, struct dfc_flow_status_info_type_v01 *flow) { int i; int enable = (flow->num_bytes > 0) ? 1 : 0; int qdisc_len; itm->grant_size = fc_info->num_bytes; itm->seq = fc_info->seq_num; itm->ack_req = ack_req; for (i = 0; i < flow->qos_ids_len; i++) { /* do flow control per specified flow */ if (flow->qos_ids[i].ip_type == DFC_IPV4_TYPE_V01) { qdisc_len = dfc_do_fc(dev, flow->qos_ids[i].qos_id, AF_INET, enable); pr_debug("%s() qdisc_len=%d\n", __func__, qdisc_len); } else if (flow->qos_ids[i].ip_type == DFC_IPV6_TYPE_V01) { qdisc_len = dfc_do_fc(dev, flow->qos_ids[i].qos_id, AF_INET6, enable); if (action != -1) rc = dfc_bearer_flow_ctl(dev, qos, fc_info->bearer_id, itm->grant_size, action); } else { pr_err("%s() ip type[%d] not supported\n", __func__, flow->qos_ids[i].ip_type); } pr_debug("grant %u before flow activate", fc_info->num_bytes); qos->default_grant = fc_info->num_bytes; } return rc; } static void dfc_do_burst_flow_control(struct work_struct *work) Loading Loading @@ -636,6 +629,12 @@ static void dfc_do_burst_flow_control(struct work_struct *work) for (i = 0; i < ind->flow_status_len; i++) { flow_status = &ind->flow_status[i]; trace_dfc_flow_ind(svc_ind->data->index, i, flow_status->mux_id, flow_status->bearer_id, flow_status->num_bytes, flow_status->seq_num, ack_req); dev = rmnet_get_rmnet_dev(svc_ind->data->rmnet_port, flow_status->mux_id); if (!dev) Loading @@ -645,22 +644,11 @@ static void dfc_do_burst_flow_control(struct work_struct *work) if (!qos) continue; rc = dfc_update_fc_map(qos, ack_req, flow_status); if (rc == NO_BEARER) { pr_debug("%s: num_bytes[%u]\n", __func__, flow_status->num_bytes); qos->default_grant = flow_status->num_bytes; continue; } else if (rc == NO_CHANGE) { continue; } else { if ((flow_status->num_bytes > 0) || (flow_status->bearer_id != 0xFF)) dfc_do_flow_controls(dev, flow_status); if (unlikely(flow_status->bearer_id == 0xFF)) rc = dfc_all_bearer_flow_ctl( dev, qos, ack_req, flow_status); else netif_stop_queue(dev); } rc = dfc_update_fc_map(dev, qos, ack_req, flow_status); } clean_out: Loading Loading @@ -729,7 +717,11 @@ static void dfc_svc_init(struct work_struct *work) return; } qmi->fc_info[data->modem].dfc_client = (void *)data; qmi->fc_info[data->index].dfc_client = (void *)data; trace_dfc_client_state_up(data->index, qmi->fc_info[data->index].svc.instance, qmi->fc_info[data->index].svc.ep_type, qmi->fc_info[data->index].svc.iface_id); } static int dfc_svc_arrive(struct qmi_handle *qmi, struct qmi_service *svc) Loading @@ -753,9 +745,10 @@ static void dfc_svc_exit(struct qmi_handle *qmi, struct qmi_service *svc) struct qmi_info *qmi_pt; int client; trace_dfc_client_state_down(data->index, 1); qmi_pt = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); if (qmi_pt) { for (client = 0; client < 2; client++) { for (client = 0; client < MAX_CLIENT_NUM; client++) { if (qmi_pt->fc_info[client].dfc_client == (void *)data) qmi_pt->fc_info[client].dfc_client = NULL; break; Loading @@ -781,7 +774,7 @@ static struct qmi_msg_handler qmi_indication_handler[] = { {}, }; int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi) int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi) { struct dfc_qmi_data *data; int rc = -ENOMEM; Loading @@ -791,7 +784,7 @@ int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi) return -ENOMEM; data->rmnet_port = port; data->modem = modem; data->index = index; data->dfc_wq = create_singlethread_workqueue("dfc_wq"); if (!data->dfc_wq) { Loading @@ -810,7 +803,7 @@ int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi) rc = qmi_add_lookup(&data->handle, DFC_SERVICE_ID_V01, DFC_SERVICE_VERS_V01, qmi->fc_info[modem].svc.instance); qmi->fc_info[index].svc.instance); if (rc < 0) { pr_err("%s: failed qmi_add_lookup - rc[%d]\n", __func__, rc); goto err2; Loading @@ -834,7 +827,7 @@ void dfc_qmi_client_exit(void *dfc_data) /* Skip this call for now due to error in qmi layer * qmi_handle_release(&data->handle); */ trace_dfc_client_state_down(data->index, 0); drain_workqueue(data->dfc_wq); destroy_workqueue(data->dfc_wq); kfree(data); Loading Loading @@ -862,18 +855,19 @@ void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos, return; } bearer->counter += skb->len; if (bearer->counter >= bearer->grant_size) { bearer->counter = 0; trace_dfc_flow_check(bearer->bearer_id, skb->len, bearer->grant_size); dfc_disable_bearer_flows(dev, bearer->bearer_id); rtnl_unlock(); if (skb->len >= bearer->grant_size) { bearer->grant_size = 0; dfc_bearer_flow_ctl(dev, qos, bearer->bearer_id, bearer->grant_size, 0); } else { rtnl_unlock(); bearer->grant_size -= skb->len; } } else { rtnl_unlock(); } rtnl_unlock(); } void dfc_reset_port_pt(void *dfc_data) Loading drivers/soc/qcom/qmi_rmnet.c +7 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/rtnetlink.h> #include <uapi/linux/rtnetlink.h> #include "qmi_rmnet_i.h" #include <trace/events/dfc.h> #define NLMSG_FLOW_ACTIVATE 1 #define NLMSG_FLOW_DEACTIVATE 2 Loading Loading @@ -148,6 +149,8 @@ static int qmi_rmnet_add_flow(struct net_device *dev, struct tcmsg *tcm) new_map.flow_id = tcm->tcm_parent; new_map.ip_type = tcm->tcm_ifindex; new_map.tcm_handle = tcm->tcm_handle; trace_dfc_flow_info(new_map.bearer_id, new_map.flow_id, new_map.ip_type, new_map.tcm_handle, 1); itm = qmi_rmnet_get_flow_map(qos_info, new_map.flow_id, new_map.ip_type); Loading Loading @@ -202,8 +205,11 @@ qmi_rmnet_del_flow(struct net_device *dev, struct tcmsg *tcm) new_map.ip_type = tcm->tcm_ifindex; itm = qmi_rmnet_get_flow_map(qos_info, new_map.flow_id, new_map.ip_type); if (itm) if (itm) { trace_dfc_flow_info(new_map.bearer_id, new_map.flow_id, new_map.ip_type, itm->tcm_handle, 0); list_del(&itm->list); } /*clear bearer map*/ bearer = qmi_rmnet_get_bearer_map(qos_info, new_map.bearer_id); Loading drivers/soc/qcom/qmi_rmnet_i.h +1 −2 Original line number Diff line number Diff line Loading @@ -35,7 +35,6 @@ struct rmnet_bearer_map { u8 bearer_id; int flow_ref; u32 grant_size; u32 counter; u16 seq; u8 ack_req; }; Loading Loading @@ -91,7 +90,7 @@ qmi_rmnet_get_flow_map(struct qos_info *qos_info, struct rmnet_bearer_map * qmi_rmnet_get_bearer_map(struct qos_info *qos_info, u8 bearer_id); int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi); int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi); void dfc_qmi_client_exit(void *dfc_data); Loading include/trace/events/dfc.h 0 → 100644 +185 −0 Original line number Diff line number Diff line /* Copyright (c) 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #undef TRACE_SYSTEM #define TRACE_SYSTEM dfc #if !defined(_TRACE_DFC_H) || defined(TRACE_HEADER_MULTI_READ) #define _TRACE_DFC_H #include <linux/tracepoint.h> TRACE_EVENT(dfc_qmi_tc, TP_PROTO(u8 bearer_id, u32 flow_id, u32 grant, int qlen, u32 tcm_handle, int enable), TP_ARGS(bearer_id, flow_id, grant, qlen, tcm_handle, enable), TP_STRUCT__entry( __field(u8, bid) __field(u32, fid) __field(u32, grant) __field(int, qlen) __field(u32, tcm_handle) __field(int, enable) ), TP_fast_assign( __entry->bid = bearer_id; __entry->fid = flow_id; __entry->grant = grant; __entry->qlen = qlen; __entry->tcm_handle = tcm_handle; __entry->enable = enable; ), TP_printk("bearer_id=%u grant=%u qdisc_len=%d flow_id=%u " "tcm_handle=0x%x %s", __entry->bid, __entry->grant, __entry->qlen, __entry->fid, __entry->tcm_handle, __entry->enable ? "enable" : "disable") ); TRACE_EVENT(dfc_flow_ind, TP_PROTO(int src, int idx, u8 mux_id, u8 bearer_id, u32 grant, u16 seq_num, u8 ack_req), TP_ARGS(src, idx, mux_id, bearer_id, grant, seq_num, ack_req), TP_STRUCT__entry( __field(int, src) __field(int, idx) __field(u8, mid) __field(u8, bid) __field(u32, grant) __field(u16, seq) __field(u8, ack_req) ), TP_fast_assign( __entry->src = src; __entry->idx = idx; __entry->mid = mux_id; __entry->bid = bearer_id; __entry->grant = grant; __entry->seq = seq_num; __entry->ack_req = ack_req; ), TP_printk("src=%d idx[%d]: mux_id=%u bearer_id=%u grant=%u " "seq_num=%u ack_req=%u", __entry->src, __entry->idx, __entry->mid, __entry->bid, __entry->grant, __entry->seq, __entry->ack_req) ); TRACE_EVENT(dfc_flow_check, TP_PROTO(u8 bearer_id, unsigned int len, u32 grant), TP_ARGS(bearer_id, len, grant), TP_STRUCT__entry( __field(u8, bearer_id) __field(unsigned int, len) __field(u32, grant) ), TP_fast_assign( __entry->bearer_id = bearer_id; __entry->len = len; __entry->grant = grant; ), TP_printk("bearer_id=%u skb_len=%u current_grant=%u", __entry->bearer_id, __entry->len, __entry->grant) ); TRACE_EVENT(dfc_flow_info, TP_PROTO(u8 bearer_id, u32 flow_id, int ip_type, u32 handle, int add), TP_ARGS(bearer_id, flow_id, ip_type, handle, add), TP_STRUCT__entry( __field(u8, bid) __field(u32, fid) __field(int, ip) __field(u32, handle) __field(int, action) ), TP_fast_assign( __entry->bid = bearer_id; __entry->fid = flow_id; __entry->ip = ip_type; __entry->handle = handle; __entry->action = add; ), TP_printk("%s: bearer_id=%u flow_id=%u ip_type=%d tcm_handle=0x%x", __entry->action ? "add flow" : "delete flow", __entry->bid, __entry->fid, __entry->ip, __entry->handle) ); TRACE_EVENT(dfc_client_state_up, TP_PROTO(int idx, u32 instance, u32 ep_type, u32 iface), TP_ARGS(idx, instance, ep_type, iface), TP_STRUCT__entry( __field(int, idx) __field(u32, instance) __field(u32, ep_type) __field(u32, iface) ), TP_fast_assign( __entry->idx = idx; __entry->instance = instance; __entry->ep_type = ep_type; __entry->iface = iface; ), TP_printk("Client[%d]: Connection established with DFC Service " "instance=%u ep_type=%u iface_id=%u", __entry->idx, __entry->instance, __entry->ep_type, __entry->iface) ); TRACE_EVENT(dfc_client_state_down, TP_PROTO(int idx, int from_cb), TP_ARGS(idx, from_cb), TP_STRUCT__entry( __field(int, idx) __field(int, from_cb) ), TP_fast_assign( __entry->idx = idx; __entry->from_cb = from_cb; ), TP_printk("Client[%d]: Connection with DFC service lost. " "Exit by callback %d", __entry->idx, __entry->from_cb) ); #endif /* _TRACE_DFC_H */ /* This part must be outside protection */ #include <trace/define_trace.h> Loading
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c +3 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ #include "rmnet_vnd.h" #include <soc/qcom/qmi_rmnet.h> #define CREATE_TRACE_POINTS #include <trace/events/rmnet.h> /* RX/TX Fixup */ Loading Loading @@ -62,6 +64,7 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, priv = netdev_priv(dev); if (priv->real_dev) { trace_rmnet_xmit_skb(skb); qmi_rmnet_burst_fc_check(dev, skb); rmnet_egress_handler(skb); } else { Loading
drivers/soc/qcom/dfc_qmi.c +91 −97 Original line number Diff line number Diff line Loading @@ -18,23 +18,20 @@ #include <linux/ip.h> #include "qmi_rmnet_i.h" #define CREATE_TRACE_POINTS #include <trace/events/dfc.h> #define DFC_MAX_BEARERS_V01 16 #define DFC_MAX_QOS_ID_V01 2 #define DEFAULT_FLOW_ID 0 /* bearer list update result */ #define NO_BEARER 0 #define NO_CHANGE 1 #define UPDATED 2 struct dfc_qmi_data { void *rmnet_port; struct workqueue_struct *dfc_wq; struct work_struct svc_arrive; struct qmi_handle handle; struct sockaddr_qrtr ssctl; int modem; int index; }; struct dfc_svc_ind { Loading Loading @@ -512,98 +509,94 @@ static int dfc_init_service(struct dfc_qmi_data *data, struct qmi_info *qmi) int rc; rc = dfc_bind_client_req(&data->handle, &data->ssctl, &qmi->fc_info[data->modem].svc); &qmi->fc_info[data->index].svc); if (rc < 0) return rc; return dfc_indication_register_req(&data->handle, &data->ssctl, 1); } static int dfc_disable_bearer_flows(struct net_device *dev, u8 bearer_id) static int dfc_bearer_flow_ctl(struct net_device *dev, struct qos_info *qos, u8 bearer_id, u32 grant_size, int enable) { struct qos_info *qos = (struct qos_info *)rmnet_get_qos_pt(dev); struct list_head *p; struct rmnet_flow_map *itm; int rc = 0; if (!qos) return 0; int rc = 0, qlen; list_for_each(p, &qos->flow_head) { itm = list_entry(p, struct rmnet_flow_map, list); if (unlikely(!itm)) return 0; if (itm->bearer_id == bearer_id) { tc_qdisc_flow_control(dev, itm->tcm_handle, 0); qlen = tc_qdisc_flow_control(dev, itm->tcm_handle, enable); trace_dfc_qmi_tc(itm->bearer_id, itm->flow_id, grant_size, qlen, itm->tcm_handle, enable); rc++; } } return rc; } static int dfc_update_fc_map(struct qos_info *qos, u8 ack_req, static int dfc_all_bearer_flow_ctl(struct net_device *dev, struct qos_info *qos, u8 ack_req, struct dfc_flow_status_info_type_v01 *fc_info) { struct rmnet_bearer_map *itm = NULL; int rc = NO_BEARER; struct list_head *p; struct rmnet_flow_map *flow_itm; struct rmnet_bearer_map *bearer_itm; int enable; int rc = 0, len; itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id); if (itm) { if ((itm->grant_size == fc_info->num_bytes) && (itm->counter > 0)) { /*flow is enabled and grant_size is the same*/ rc = NO_CHANGE; } else { itm->grant_size = fc_info->num_bytes; itm->seq = fc_info->seq_num; itm->ack_req = ack_req; rc = UPDATED; list_for_each(p, &qos->bearer_head) { bearer_itm = list_entry(p, struct rmnet_bearer_map, list); bearer_itm->grant_size = fc_info->num_bytes; bearer_itm->seq = fc_info->seq_num; bearer_itm->ack_req = ack_req; } itm->counter = 0; enable = fc_info->num_bytes > 0 ? 1 : 0; list_for_each(p, &qos->flow_head) { flow_itm = list_entry(p, struct rmnet_flow_map, list); len = tc_qdisc_flow_control(dev, flow_itm->tcm_handle, enable); trace_dfc_qmi_tc(flow_itm->bearer_id, flow_itm->flow_id, fc_info->num_bytes, len, flow_itm->tcm_handle, enable); rc++; } return rc; } static int dfc_do_fc(struct net_device *dev, u32 flow_id, int ip_type, int enable) static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, u8 ack_req, struct dfc_flow_status_info_type_v01 *fc_info) { struct qos_info *qos = (struct qos_info *)rmnet_get_qos_pt(dev); struct rmnet_flow_map *itm = NULL; int len = 0; if (!qos) return 0; struct rmnet_bearer_map *itm = NULL; int rc = 0; int action = -1; itm = qmi_rmnet_get_flow_map(qos, flow_id, ip_type); itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id); if (itm) { len = tc_qdisc_flow_control(dev, itm->tcm_handle, enable); } return len; } if (itm->grant_size == 0 && fc_info->num_bytes > 0) action = 1; else if (itm->grant_size > 0 && fc_info->num_bytes == 0) action = 0; static void dfc_do_flow_controls(struct net_device *dev, struct dfc_flow_status_info_type_v01 *flow) { int i; int enable = (flow->num_bytes > 0) ? 1 : 0; int qdisc_len; itm->grant_size = fc_info->num_bytes; itm->seq = fc_info->seq_num; itm->ack_req = ack_req; for (i = 0; i < flow->qos_ids_len; i++) { /* do flow control per specified flow */ if (flow->qos_ids[i].ip_type == DFC_IPV4_TYPE_V01) { qdisc_len = dfc_do_fc(dev, flow->qos_ids[i].qos_id, AF_INET, enable); pr_debug("%s() qdisc_len=%d\n", __func__, qdisc_len); } else if (flow->qos_ids[i].ip_type == DFC_IPV6_TYPE_V01) { qdisc_len = dfc_do_fc(dev, flow->qos_ids[i].qos_id, AF_INET6, enable); if (action != -1) rc = dfc_bearer_flow_ctl(dev, qos, fc_info->bearer_id, itm->grant_size, action); } else { pr_err("%s() ip type[%d] not supported\n", __func__, flow->qos_ids[i].ip_type); } pr_debug("grant %u before flow activate", fc_info->num_bytes); qos->default_grant = fc_info->num_bytes; } return rc; } static void dfc_do_burst_flow_control(struct work_struct *work) Loading Loading @@ -636,6 +629,12 @@ static void dfc_do_burst_flow_control(struct work_struct *work) for (i = 0; i < ind->flow_status_len; i++) { flow_status = &ind->flow_status[i]; trace_dfc_flow_ind(svc_ind->data->index, i, flow_status->mux_id, flow_status->bearer_id, flow_status->num_bytes, flow_status->seq_num, ack_req); dev = rmnet_get_rmnet_dev(svc_ind->data->rmnet_port, flow_status->mux_id); if (!dev) Loading @@ -645,22 +644,11 @@ static void dfc_do_burst_flow_control(struct work_struct *work) if (!qos) continue; rc = dfc_update_fc_map(qos, ack_req, flow_status); if (rc == NO_BEARER) { pr_debug("%s: num_bytes[%u]\n", __func__, flow_status->num_bytes); qos->default_grant = flow_status->num_bytes; continue; } else if (rc == NO_CHANGE) { continue; } else { if ((flow_status->num_bytes > 0) || (flow_status->bearer_id != 0xFF)) dfc_do_flow_controls(dev, flow_status); if (unlikely(flow_status->bearer_id == 0xFF)) rc = dfc_all_bearer_flow_ctl( dev, qos, ack_req, flow_status); else netif_stop_queue(dev); } rc = dfc_update_fc_map(dev, qos, ack_req, flow_status); } clean_out: Loading Loading @@ -729,7 +717,11 @@ static void dfc_svc_init(struct work_struct *work) return; } qmi->fc_info[data->modem].dfc_client = (void *)data; qmi->fc_info[data->index].dfc_client = (void *)data; trace_dfc_client_state_up(data->index, qmi->fc_info[data->index].svc.instance, qmi->fc_info[data->index].svc.ep_type, qmi->fc_info[data->index].svc.iface_id); } static int dfc_svc_arrive(struct qmi_handle *qmi, struct qmi_service *svc) Loading @@ -753,9 +745,10 @@ static void dfc_svc_exit(struct qmi_handle *qmi, struct qmi_service *svc) struct qmi_info *qmi_pt; int client; trace_dfc_client_state_down(data->index, 1); qmi_pt = (struct qmi_info *)rmnet_get_qmi_pt(data->rmnet_port); if (qmi_pt) { for (client = 0; client < 2; client++) { for (client = 0; client < MAX_CLIENT_NUM; client++) { if (qmi_pt->fc_info[client].dfc_client == (void *)data) qmi_pt->fc_info[client].dfc_client = NULL; break; Loading @@ -781,7 +774,7 @@ static struct qmi_msg_handler qmi_indication_handler[] = { {}, }; int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi) int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi) { struct dfc_qmi_data *data; int rc = -ENOMEM; Loading @@ -791,7 +784,7 @@ int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi) return -ENOMEM; data->rmnet_port = port; data->modem = modem; data->index = index; data->dfc_wq = create_singlethread_workqueue("dfc_wq"); if (!data->dfc_wq) { Loading @@ -810,7 +803,7 @@ int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi) rc = qmi_add_lookup(&data->handle, DFC_SERVICE_ID_V01, DFC_SERVICE_VERS_V01, qmi->fc_info[modem].svc.instance); qmi->fc_info[index].svc.instance); if (rc < 0) { pr_err("%s: failed qmi_add_lookup - rc[%d]\n", __func__, rc); goto err2; Loading @@ -834,7 +827,7 @@ void dfc_qmi_client_exit(void *dfc_data) /* Skip this call for now due to error in qmi layer * qmi_handle_release(&data->handle); */ trace_dfc_client_state_down(data->index, 0); drain_workqueue(data->dfc_wq); destroy_workqueue(data->dfc_wq); kfree(data); Loading Loading @@ -862,18 +855,19 @@ void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos, return; } bearer->counter += skb->len; if (bearer->counter >= bearer->grant_size) { bearer->counter = 0; trace_dfc_flow_check(bearer->bearer_id, skb->len, bearer->grant_size); dfc_disable_bearer_flows(dev, bearer->bearer_id); rtnl_unlock(); if (skb->len >= bearer->grant_size) { bearer->grant_size = 0; dfc_bearer_flow_ctl(dev, qos, bearer->bearer_id, bearer->grant_size, 0); } else { rtnl_unlock(); bearer->grant_size -= skb->len; } } else { rtnl_unlock(); } rtnl_unlock(); } void dfc_reset_port_pt(void *dfc_data) Loading
drivers/soc/qcom/qmi_rmnet.c +7 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/rtnetlink.h> #include <uapi/linux/rtnetlink.h> #include "qmi_rmnet_i.h" #include <trace/events/dfc.h> #define NLMSG_FLOW_ACTIVATE 1 #define NLMSG_FLOW_DEACTIVATE 2 Loading Loading @@ -148,6 +149,8 @@ static int qmi_rmnet_add_flow(struct net_device *dev, struct tcmsg *tcm) new_map.flow_id = tcm->tcm_parent; new_map.ip_type = tcm->tcm_ifindex; new_map.tcm_handle = tcm->tcm_handle; trace_dfc_flow_info(new_map.bearer_id, new_map.flow_id, new_map.ip_type, new_map.tcm_handle, 1); itm = qmi_rmnet_get_flow_map(qos_info, new_map.flow_id, new_map.ip_type); Loading Loading @@ -202,8 +205,11 @@ qmi_rmnet_del_flow(struct net_device *dev, struct tcmsg *tcm) new_map.ip_type = tcm->tcm_ifindex; itm = qmi_rmnet_get_flow_map(qos_info, new_map.flow_id, new_map.ip_type); if (itm) if (itm) { trace_dfc_flow_info(new_map.bearer_id, new_map.flow_id, new_map.ip_type, itm->tcm_handle, 0); list_del(&itm->list); } /*clear bearer map*/ bearer = qmi_rmnet_get_bearer_map(qos_info, new_map.bearer_id); Loading
drivers/soc/qcom/qmi_rmnet_i.h +1 −2 Original line number Diff line number Diff line Loading @@ -35,7 +35,6 @@ struct rmnet_bearer_map { u8 bearer_id; int flow_ref; u32 grant_size; u32 counter; u16 seq; u8 ack_req; }; Loading Loading @@ -91,7 +90,7 @@ qmi_rmnet_get_flow_map(struct qos_info *qos_info, struct rmnet_bearer_map * qmi_rmnet_get_bearer_map(struct qos_info *qos_info, u8 bearer_id); int dfc_qmi_client_init(void *port, int modem, struct qmi_info *qmi); int dfc_qmi_client_init(void *port, int index, struct qmi_info *qmi); void dfc_qmi_client_exit(void *dfc_data); Loading
include/trace/events/dfc.h 0 → 100644 +185 −0 Original line number Diff line number Diff line /* Copyright (c) 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #undef TRACE_SYSTEM #define TRACE_SYSTEM dfc #if !defined(_TRACE_DFC_H) || defined(TRACE_HEADER_MULTI_READ) #define _TRACE_DFC_H #include <linux/tracepoint.h> TRACE_EVENT(dfc_qmi_tc, TP_PROTO(u8 bearer_id, u32 flow_id, u32 grant, int qlen, u32 tcm_handle, int enable), TP_ARGS(bearer_id, flow_id, grant, qlen, tcm_handle, enable), TP_STRUCT__entry( __field(u8, bid) __field(u32, fid) __field(u32, grant) __field(int, qlen) __field(u32, tcm_handle) __field(int, enable) ), TP_fast_assign( __entry->bid = bearer_id; __entry->fid = flow_id; __entry->grant = grant; __entry->qlen = qlen; __entry->tcm_handle = tcm_handle; __entry->enable = enable; ), TP_printk("bearer_id=%u grant=%u qdisc_len=%d flow_id=%u " "tcm_handle=0x%x %s", __entry->bid, __entry->grant, __entry->qlen, __entry->fid, __entry->tcm_handle, __entry->enable ? "enable" : "disable") ); TRACE_EVENT(dfc_flow_ind, TP_PROTO(int src, int idx, u8 mux_id, u8 bearer_id, u32 grant, u16 seq_num, u8 ack_req), TP_ARGS(src, idx, mux_id, bearer_id, grant, seq_num, ack_req), TP_STRUCT__entry( __field(int, src) __field(int, idx) __field(u8, mid) __field(u8, bid) __field(u32, grant) __field(u16, seq) __field(u8, ack_req) ), TP_fast_assign( __entry->src = src; __entry->idx = idx; __entry->mid = mux_id; __entry->bid = bearer_id; __entry->grant = grant; __entry->seq = seq_num; __entry->ack_req = ack_req; ), TP_printk("src=%d idx[%d]: mux_id=%u bearer_id=%u grant=%u " "seq_num=%u ack_req=%u", __entry->src, __entry->idx, __entry->mid, __entry->bid, __entry->grant, __entry->seq, __entry->ack_req) ); TRACE_EVENT(dfc_flow_check, TP_PROTO(u8 bearer_id, unsigned int len, u32 grant), TP_ARGS(bearer_id, len, grant), TP_STRUCT__entry( __field(u8, bearer_id) __field(unsigned int, len) __field(u32, grant) ), TP_fast_assign( __entry->bearer_id = bearer_id; __entry->len = len; __entry->grant = grant; ), TP_printk("bearer_id=%u skb_len=%u current_grant=%u", __entry->bearer_id, __entry->len, __entry->grant) ); TRACE_EVENT(dfc_flow_info, TP_PROTO(u8 bearer_id, u32 flow_id, int ip_type, u32 handle, int add), TP_ARGS(bearer_id, flow_id, ip_type, handle, add), TP_STRUCT__entry( __field(u8, bid) __field(u32, fid) __field(int, ip) __field(u32, handle) __field(int, action) ), TP_fast_assign( __entry->bid = bearer_id; __entry->fid = flow_id; __entry->ip = ip_type; __entry->handle = handle; __entry->action = add; ), TP_printk("%s: bearer_id=%u flow_id=%u ip_type=%d tcm_handle=0x%x", __entry->action ? "add flow" : "delete flow", __entry->bid, __entry->fid, __entry->ip, __entry->handle) ); TRACE_EVENT(dfc_client_state_up, TP_PROTO(int idx, u32 instance, u32 ep_type, u32 iface), TP_ARGS(idx, instance, ep_type, iface), TP_STRUCT__entry( __field(int, idx) __field(u32, instance) __field(u32, ep_type) __field(u32, iface) ), TP_fast_assign( __entry->idx = idx; __entry->instance = instance; __entry->ep_type = ep_type; __entry->iface = iface; ), TP_printk("Client[%d]: Connection established with DFC Service " "instance=%u ep_type=%u iface_id=%u", __entry->idx, __entry->instance, __entry->ep_type, __entry->iface) ); TRACE_EVENT(dfc_client_state_down, TP_PROTO(int idx, int from_cb), TP_ARGS(idx, from_cb), TP_STRUCT__entry( __field(int, idx) __field(int, from_cb) ), TP_fast_assign( __entry->idx = idx; __entry->from_cb = from_cb; ), TP_printk("Client[%d]: Connection with DFC service lost. " "Exit by callback %d", __entry->idx, __entry->from_cb) ); #endif /* _TRACE_DFC_H */ /* This part must be outside protection */ #include <trace/define_trace.h>