Loading drivers/soc/qcom/dfc_defs.h +5 −2 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019, The Linux Foundation. All rights reserved. * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _DFC_DEFS_H Loading Loading @@ -53,6 +53,8 @@ struct dfc_flow_status_info_type_v01 { u16 seq_num; u8 qos_ids_len; struct dfc_qos_id_type_v01 qos_ids[DFC_MAX_QOS_ID_V01]; u8 rx_bytes_valid; u32 rx_bytes; }; struct dfc_ancillary_info_type_v01 { Loading Loading @@ -88,7 +90,8 @@ struct dfc_tx_link_status_ind_msg_v01 { }; void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc, struct dfc_flow_status_ind_msg_v01 *ind); struct dfc_flow_status_ind_msg_v01 *ind, bool is_query); void dfc_handle_tx_link_status_ind(struct dfc_qmi_data *dfc, struct dfc_tx_link_status_ind_msg_v01 *ind); Loading drivers/soc/qcom/dfc_qmap.c +19 −7 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2019, The Linux Foundation. All rights reserved. * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include <net/pkt_sched.h> Loading Loading @@ -65,13 +65,14 @@ struct qmap_dfc_ind { u8 reserved2; u8 tx_info_valid:1; u8 tx_info:1; u8 reserved3:6; u8 rx_bytes_valid:1; u8 reserved3:5; u8 bearer_id; u8 tcp_bidir:1; u8 bearer_status:3; u8 reserved4:4; __be32 grant; u32 reserved5; __be32 rx_bytes; u32 reserved6; } __aligned(1); Loading @@ -89,11 +90,12 @@ struct qmap_dfc_query_resp { u8 cmd_ver; u8 bearer_id; u8 tcp_bidir:1; u8 reserved:7; u8 rx_bytes_valid:1; u8 reserved:6; u8 invalid:1; u8 reserved2:7; __be32 grant; u32 reserved3; __be32 rx_bytes; u32 reserved4; } __aligned(1); Loading Loading @@ -185,6 +187,11 @@ static int dfc_qmap_handle_ind(struct dfc_qmi_data *dfc, qmap_flow_ind.flow_status[0].num_bytes = ntohl(cmd->grant); qmap_flow_ind.flow_status[0].seq_num = ntohs(cmd->seq_num); if (cmd->rx_bytes_valid) { qmap_flow_ind.flow_status[0].rx_bytes_valid = 1; qmap_flow_ind.flow_status[0].rx_bytes = ntohl(cmd->rx_bytes); } if (cmd->tcp_bidir) { qmap_flow_ind.ancillary_info_valid = 1; qmap_flow_ind.ancillary_info_len = 1; Loading @@ -193,7 +200,7 @@ static int dfc_qmap_handle_ind(struct dfc_qmi_data *dfc, qmap_flow_ind.ancillary_info[0].reserved = DFC_MASK_TCP_BIDIR; } dfc_do_burst_flow_control(dfc, &qmap_flow_ind); dfc_do_burst_flow_control(dfc, &qmap_flow_ind, false); done: return QMAP_CMD_ACK; Loading Loading @@ -221,6 +228,11 @@ static int dfc_qmap_handle_query_resp(struct dfc_qmi_data *dfc, qmap_flow_ind.flow_status[0].num_bytes = ntohl(cmd->grant); qmap_flow_ind.flow_status[0].seq_num = 0xFFFF; if (cmd->rx_bytes_valid) { qmap_flow_ind.flow_status[0].rx_bytes_valid = 1; qmap_flow_ind.flow_status[0].rx_bytes = ntohl(cmd->rx_bytes); } if (cmd->tcp_bidir) { qmap_flow_ind.ancillary_info_valid = 1; qmap_flow_ind.ancillary_info_len = 1; Loading @@ -229,7 +241,7 @@ static int dfc_qmap_handle_query_resp(struct dfc_qmi_data *dfc, qmap_flow_ind.ancillary_info[0].reserved = DFC_MASK_TCP_BIDIR; } dfc_do_burst_flow_control(dfc, &qmap_flow_ind); dfc_do_burst_flow_control(dfc, &qmap_flow_ind, true); return QMAP_CMD_DONE; } Loading drivers/soc/qcom/dfc_qmi.c +63 −10 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include <net/pkt_sched.h> Loading Loading @@ -945,6 +945,7 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev, bearer->tcp_bidir = DFC_IS_TCP_BIDIR(ancillary); bearer->last_grant = fc_info->num_bytes; bearer->last_seq = fc_info->seq_num; bearer->last_adjusted_grant = fc_info->num_bytes; dfc_bearer_flow_ctl(dev, bearer, qos); } Loading @@ -952,13 +953,40 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev, return 0; } static u32 dfc_adjust_grant(struct rmnet_bearer_map *bearer, struct dfc_flow_status_info_type_v01 *fc_info) { u32 grant; if (!fc_info->rx_bytes_valid) return fc_info->num_bytes; if (bearer->bytes_in_flight > fc_info->rx_bytes) bearer->bytes_in_flight -= fc_info->rx_bytes; else bearer->bytes_in_flight = 0; /* Adjusted grant = grant - bytes_in_flight */ if (fc_info->num_bytes > bearer->bytes_in_flight) grant = fc_info->num_bytes - bearer->bytes_in_flight; else grant = 0; trace_dfc_adjust_grant(fc_info->mux_id, fc_info->bearer_id, fc_info->num_bytes, fc_info->rx_bytes, bearer->bytes_in_flight, grant); return grant; } static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, u8 ack_req, u32 ancillary, struct dfc_flow_status_info_type_v01 *fc_info) struct dfc_flow_status_info_type_v01 *fc_info, bool is_query) { struct rmnet_bearer_map *itm = NULL; int rc = 0; bool action = false; u32 adjusted_grant; itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id); if (!itm) Loading @@ -978,8 +1006,16 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, 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)) /* Adjuste grant for query */ if (dfc_qmap && is_query) { adjusted_grant = dfc_adjust_grant(itm, fc_info); } else { adjusted_grant = fc_info->num_bytes; itm->bytes_in_flight = 0; } if ((itm->grant_size == 0 && adjusted_grant > 0) || (itm->grant_size > 0 && adjusted_grant == 0)) action = true; /* This is needed by qmap */ Loading @@ -987,13 +1023,24 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, dfc_qmap_send_ack(qos, itm->bearer_id, itm->seq, DFC_ACK_TYPE_DISABLE); itm->grant_size = fc_info->num_bytes; itm->grant_thresh = qmi_rmnet_grant_per(itm->grant_size); itm->grant_size = adjusted_grant; /* No further query if the adjusted grant is less * than 20% of the original grant */ if (dfc_qmap && is_query && itm->grant_size < (fc_info->num_bytes / 5)) itm->grant_thresh = itm->grant_size; else itm->grant_thresh = qmi_rmnet_grant_per(itm->grant_size); itm->seq = fc_info->seq_num; itm->ack_req = ack_req; itm->tcp_bidir = DFC_IS_TCP_BIDIR(ancillary); itm->last_grant = fc_info->num_bytes; itm->last_seq = fc_info->seq_num; itm->last_adjusted_grant = adjusted_grant; if (action) rc = dfc_bearer_flow_ctl(dev, itm, qos); Loading @@ -1003,7 +1050,8 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, } void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc, struct dfc_flow_status_ind_msg_v01 *ind) struct dfc_flow_status_ind_msg_v01 *ind, bool is_query) { struct net_device *dev; struct qos_info *qos; Loading Loading @@ -1059,7 +1107,8 @@ void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc, dev, qos, ack_req, ancillary, flow_status); else dfc_update_fc_map( dev, qos, ack_req, ancillary, flow_status); dev, qos, ack_req, ancillary, flow_status, is_query); spin_unlock_bh(&qos->qos_lock); } Loading @@ -1085,6 +1134,7 @@ static void dfc_update_tx_link_status(struct net_device *dev, if (itm->grant_size && !tx_status) { itm->grant_size = 0; itm->tcp_bidir = false; itm->bytes_in_flight = 0; dfc_bearer_flow_ctl(dev, itm, qos); } else if (itm->grant_size == 0 && tx_status && !itm->rat_switch) { itm->grant_size = DEFAULT_GRANT; Loading Loading @@ -1162,7 +1212,8 @@ static void dfc_qmi_ind_work(struct work_struct *work) if (!dfc->restart_state) { if (svc_ind->msg_id == QMI_DFC_FLOW_STATUS_IND_V01) dfc_do_burst_flow_control( dfc, &svc_ind->d.dfc_info); dfc, &svc_ind->d.dfc_info, false); else if (svc_ind->msg_id == QMI_DFC_TX_LINK_STATUS_IND_V01) dfc_handle_tx_link_status_ind( Loading Loading @@ -1437,6 +1488,8 @@ void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos, trace_dfc_flow_check(dev->name, bearer->bearer_id, len, mark, bearer->grant_size); bearer->bytes_in_flight += len; if (!bearer->grant_size) goto out; Loading Loading @@ -1490,7 +1543,7 @@ void dfc_qmi_query_flow(void *dfc_data) 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->d.dfc_info); dfc_do_burst_flow_control(data, &svc_ind->d.dfc_info, true); done: kfree(svc_ind); Loading drivers/soc/qcom/qmi_rmnet.c +2 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include <soc/qcom/qmi_rmnet.h> Loading Loading @@ -722,6 +722,7 @@ void qmi_rmnet_enable_all_flows(struct net_device *dev) bearer->grant_thresh = qmi_rmnet_grant_per(DEFAULT_GRANT); bearer->seq = 0; bearer->ack_req = 0; bearer->bytes_in_flight = 0; bearer->tcp_bidir = false; bearer->rat_switch = false; Loading drivers/soc/qcom/qmi_rmnet_i.h +3 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _RMNET_QMI_I_H Loading Loading @@ -36,6 +36,8 @@ struct rmnet_bearer_map { u8 ack_req; u32 last_grant; u16 last_seq; u32 bytes_in_flight; u32 last_adjusted_grant; bool tcp_bidir; bool rat_switch; bool tx_off; Loading Loading
drivers/soc/qcom/dfc_defs.h +5 −2 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019, The Linux Foundation. All rights reserved. * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _DFC_DEFS_H Loading Loading @@ -53,6 +53,8 @@ struct dfc_flow_status_info_type_v01 { u16 seq_num; u8 qos_ids_len; struct dfc_qos_id_type_v01 qos_ids[DFC_MAX_QOS_ID_V01]; u8 rx_bytes_valid; u32 rx_bytes; }; struct dfc_ancillary_info_type_v01 { Loading Loading @@ -88,7 +90,8 @@ struct dfc_tx_link_status_ind_msg_v01 { }; void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc, struct dfc_flow_status_ind_msg_v01 *ind); struct dfc_flow_status_ind_msg_v01 *ind, bool is_query); void dfc_handle_tx_link_status_ind(struct dfc_qmi_data *dfc, struct dfc_tx_link_status_ind_msg_v01 *ind); Loading
drivers/soc/qcom/dfc_qmap.c +19 −7 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2019, The Linux Foundation. All rights reserved. * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include <net/pkt_sched.h> Loading Loading @@ -65,13 +65,14 @@ struct qmap_dfc_ind { u8 reserved2; u8 tx_info_valid:1; u8 tx_info:1; u8 reserved3:6; u8 rx_bytes_valid:1; u8 reserved3:5; u8 bearer_id; u8 tcp_bidir:1; u8 bearer_status:3; u8 reserved4:4; __be32 grant; u32 reserved5; __be32 rx_bytes; u32 reserved6; } __aligned(1); Loading @@ -89,11 +90,12 @@ struct qmap_dfc_query_resp { u8 cmd_ver; u8 bearer_id; u8 tcp_bidir:1; u8 reserved:7; u8 rx_bytes_valid:1; u8 reserved:6; u8 invalid:1; u8 reserved2:7; __be32 grant; u32 reserved3; __be32 rx_bytes; u32 reserved4; } __aligned(1); Loading Loading @@ -185,6 +187,11 @@ static int dfc_qmap_handle_ind(struct dfc_qmi_data *dfc, qmap_flow_ind.flow_status[0].num_bytes = ntohl(cmd->grant); qmap_flow_ind.flow_status[0].seq_num = ntohs(cmd->seq_num); if (cmd->rx_bytes_valid) { qmap_flow_ind.flow_status[0].rx_bytes_valid = 1; qmap_flow_ind.flow_status[0].rx_bytes = ntohl(cmd->rx_bytes); } if (cmd->tcp_bidir) { qmap_flow_ind.ancillary_info_valid = 1; qmap_flow_ind.ancillary_info_len = 1; Loading @@ -193,7 +200,7 @@ static int dfc_qmap_handle_ind(struct dfc_qmi_data *dfc, qmap_flow_ind.ancillary_info[0].reserved = DFC_MASK_TCP_BIDIR; } dfc_do_burst_flow_control(dfc, &qmap_flow_ind); dfc_do_burst_flow_control(dfc, &qmap_flow_ind, false); done: return QMAP_CMD_ACK; Loading Loading @@ -221,6 +228,11 @@ static int dfc_qmap_handle_query_resp(struct dfc_qmi_data *dfc, qmap_flow_ind.flow_status[0].num_bytes = ntohl(cmd->grant); qmap_flow_ind.flow_status[0].seq_num = 0xFFFF; if (cmd->rx_bytes_valid) { qmap_flow_ind.flow_status[0].rx_bytes_valid = 1; qmap_flow_ind.flow_status[0].rx_bytes = ntohl(cmd->rx_bytes); } if (cmd->tcp_bidir) { qmap_flow_ind.ancillary_info_valid = 1; qmap_flow_ind.ancillary_info_len = 1; Loading @@ -229,7 +241,7 @@ static int dfc_qmap_handle_query_resp(struct dfc_qmi_data *dfc, qmap_flow_ind.ancillary_info[0].reserved = DFC_MASK_TCP_BIDIR; } dfc_do_burst_flow_control(dfc, &qmap_flow_ind); dfc_do_burst_flow_control(dfc, &qmap_flow_ind, true); return QMAP_CMD_DONE; } Loading
drivers/soc/qcom/dfc_qmi.c +63 −10 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include <net/pkt_sched.h> Loading Loading @@ -945,6 +945,7 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev, bearer->tcp_bidir = DFC_IS_TCP_BIDIR(ancillary); bearer->last_grant = fc_info->num_bytes; bearer->last_seq = fc_info->seq_num; bearer->last_adjusted_grant = fc_info->num_bytes; dfc_bearer_flow_ctl(dev, bearer, qos); } Loading @@ -952,13 +953,40 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev, return 0; } static u32 dfc_adjust_grant(struct rmnet_bearer_map *bearer, struct dfc_flow_status_info_type_v01 *fc_info) { u32 grant; if (!fc_info->rx_bytes_valid) return fc_info->num_bytes; if (bearer->bytes_in_flight > fc_info->rx_bytes) bearer->bytes_in_flight -= fc_info->rx_bytes; else bearer->bytes_in_flight = 0; /* Adjusted grant = grant - bytes_in_flight */ if (fc_info->num_bytes > bearer->bytes_in_flight) grant = fc_info->num_bytes - bearer->bytes_in_flight; else grant = 0; trace_dfc_adjust_grant(fc_info->mux_id, fc_info->bearer_id, fc_info->num_bytes, fc_info->rx_bytes, bearer->bytes_in_flight, grant); return grant; } static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, u8 ack_req, u32 ancillary, struct dfc_flow_status_info_type_v01 *fc_info) struct dfc_flow_status_info_type_v01 *fc_info, bool is_query) { struct rmnet_bearer_map *itm = NULL; int rc = 0; bool action = false; u32 adjusted_grant; itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id); if (!itm) Loading @@ -978,8 +1006,16 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, 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)) /* Adjuste grant for query */ if (dfc_qmap && is_query) { adjusted_grant = dfc_adjust_grant(itm, fc_info); } else { adjusted_grant = fc_info->num_bytes; itm->bytes_in_flight = 0; } if ((itm->grant_size == 0 && adjusted_grant > 0) || (itm->grant_size > 0 && adjusted_grant == 0)) action = true; /* This is needed by qmap */ Loading @@ -987,13 +1023,24 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, dfc_qmap_send_ack(qos, itm->bearer_id, itm->seq, DFC_ACK_TYPE_DISABLE); itm->grant_size = fc_info->num_bytes; itm->grant_thresh = qmi_rmnet_grant_per(itm->grant_size); itm->grant_size = adjusted_grant; /* No further query if the adjusted grant is less * than 20% of the original grant */ if (dfc_qmap && is_query && itm->grant_size < (fc_info->num_bytes / 5)) itm->grant_thresh = itm->grant_size; else itm->grant_thresh = qmi_rmnet_grant_per(itm->grant_size); itm->seq = fc_info->seq_num; itm->ack_req = ack_req; itm->tcp_bidir = DFC_IS_TCP_BIDIR(ancillary); itm->last_grant = fc_info->num_bytes; itm->last_seq = fc_info->seq_num; itm->last_adjusted_grant = adjusted_grant; if (action) rc = dfc_bearer_flow_ctl(dev, itm, qos); Loading @@ -1003,7 +1050,8 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, } void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc, struct dfc_flow_status_ind_msg_v01 *ind) struct dfc_flow_status_ind_msg_v01 *ind, bool is_query) { struct net_device *dev; struct qos_info *qos; Loading Loading @@ -1059,7 +1107,8 @@ void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc, dev, qos, ack_req, ancillary, flow_status); else dfc_update_fc_map( dev, qos, ack_req, ancillary, flow_status); dev, qos, ack_req, ancillary, flow_status, is_query); spin_unlock_bh(&qos->qos_lock); } Loading @@ -1085,6 +1134,7 @@ static void dfc_update_tx_link_status(struct net_device *dev, if (itm->grant_size && !tx_status) { itm->grant_size = 0; itm->tcp_bidir = false; itm->bytes_in_flight = 0; dfc_bearer_flow_ctl(dev, itm, qos); } else if (itm->grant_size == 0 && tx_status && !itm->rat_switch) { itm->grant_size = DEFAULT_GRANT; Loading Loading @@ -1162,7 +1212,8 @@ static void dfc_qmi_ind_work(struct work_struct *work) if (!dfc->restart_state) { if (svc_ind->msg_id == QMI_DFC_FLOW_STATUS_IND_V01) dfc_do_burst_flow_control( dfc, &svc_ind->d.dfc_info); dfc, &svc_ind->d.dfc_info, false); else if (svc_ind->msg_id == QMI_DFC_TX_LINK_STATUS_IND_V01) dfc_handle_tx_link_status_ind( Loading Loading @@ -1437,6 +1488,8 @@ void dfc_qmi_burst_check(struct net_device *dev, struct qos_info *qos, trace_dfc_flow_check(dev->name, bearer->bearer_id, len, mark, bearer->grant_size); bearer->bytes_in_flight += len; if (!bearer->grant_size) goto out; Loading Loading @@ -1490,7 +1543,7 @@ void dfc_qmi_query_flow(void *dfc_data) 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->d.dfc_info); dfc_do_burst_flow_control(data, &svc_ind->d.dfc_info, true); done: kfree(svc_ind); Loading
drivers/soc/qcom/qmi_rmnet.c +2 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include <soc/qcom/qmi_rmnet.h> Loading Loading @@ -722,6 +722,7 @@ void qmi_rmnet_enable_all_flows(struct net_device *dev) bearer->grant_thresh = qmi_rmnet_grant_per(DEFAULT_GRANT); bearer->seq = 0; bearer->ack_req = 0; bearer->bytes_in_flight = 0; bearer->tcp_bidir = false; bearer->rat_switch = false; Loading
drivers/soc/qcom/qmi_rmnet_i.h +3 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _RMNET_QMI_I_H Loading Loading @@ -36,6 +36,8 @@ struct rmnet_bearer_map { u8 ack_req; u32 last_grant; u16 last_seq; u32 bytes_in_flight; u32 last_adjusted_grant; bool tcp_bidir; bool rat_switch; bool tx_off; Loading