Loading drivers/platform/msm/ipa/ipa_v3/ipa.c +2 −2 Original line number Original line Diff line number Diff line Loading @@ -4515,8 +4515,6 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, IPADBG("teth_bridge initialized"); IPADBG("teth_bridge initialized"); } } ipa3_debugfs_init(); result = ipa3_uc_interface_init(); result = ipa3_uc_interface_init(); if (result) if (result) IPAERR(":ipa Uc interface init failed (%d)\n", -result); IPAERR(":ipa Uc interface init failed (%d)\n", -result); Loading Loading @@ -4554,6 +4552,8 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, complete_all(&ipa3_ctx->init_completion_obj); complete_all(&ipa3_ctx->init_completion_obj); pr_info("IPA driver initialization was successful.\n"); pr_info("IPA driver initialization was successful.\n"); ipa3_debugfs_init(); return 0; return 0; fail_teth_bridge_driver_init: fail_teth_bridge_driver_init: Loading drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c +146 −39 Original line number Original line Diff line number Diff line /* Copyright (c) 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and Loading @@ -24,12 +24,63 @@ int ipa_hw_stats_init(void) int ipa_hw_stats_init(void) { { int ret = 0, ep_index; struct ipa_teth_stats_endpoints *teth_stats_init; if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) return 0; return 0; /* initialize stats here */ /* initialize stats here */ ipa3_ctx->hw_stats.enabled = true; ipa3_ctx->hw_stats.enabled = true; return 0; teth_stats_init = kzalloc(sizeof(*teth_stats_init), GFP_KERNEL); if (!teth_stats_init) { IPAERR("mem allocated failed!\n"); return -ENOMEM; } /* enable prod mask */ teth_stats_init->prod_mask = ( IPA_CLIENT_BIT_32(IPA_CLIENT_Q6_WAN_PROD) | IPA_CLIENT_BIT_32(IPA_CLIENT_USB_PROD) | IPA_CLIENT_BIT_32(IPA_CLIENT_WLAN1_PROD)); if (IPA_CLIENT_BIT_32(IPA_CLIENT_Q6_WAN_PROD)) { ep_index = ipa3_get_ep_mapping(IPA_CLIENT_Q6_WAN_PROD); if (ep_index == -1) { IPAERR("Invalid client.\n"); kfree(teth_stats_init); return -EINVAL; } teth_stats_init->dst_ep_mask[ep_index] = (IPA_CLIENT_BIT_32(IPA_CLIENT_WLAN1_CONS) | IPA_CLIENT_BIT_32(IPA_CLIENT_USB_CONS)); } if (IPA_CLIENT_BIT_32(IPA_CLIENT_USB_PROD)) { ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB_PROD); if (ep_index == -1) { IPAERR("Invalid client.\n"); kfree(teth_stats_init); return -EINVAL; } teth_stats_init->dst_ep_mask[ep_index] = IPA_CLIENT_BIT_32(IPA_CLIENT_Q6_WAN_CONS); } if (IPA_CLIENT_BIT_32(IPA_CLIENT_WLAN1_PROD)) { ep_index = ipa3_get_ep_mapping(IPA_CLIENT_WLAN1_PROD); if (ep_index == -1) { IPAERR("Invalid client.\n"); kfree(teth_stats_init); return -EINVAL; } teth_stats_init->dst_ep_mask[ep_index] = IPA_CLIENT_BIT_32(IPA_CLIENT_Q6_WAN_CONS); } ret = ipa_init_teth_stats(teth_stats_init); kfree(teth_stats_init); return ret; } } int ipa_init_quota_stats(u32 pipe_bitmask) int ipa_init_quota_stats(u32 pipe_bitmask) Loading Loading @@ -348,9 +399,12 @@ int ipa_init_teth_stats(struct ipa_teth_stats_endpoints *in) /* reset driver's cache */ /* reset driver's cache */ memset(&ipa3_ctx->hw_stats.teth.init, 0, memset(&ipa3_ctx->hw_stats.teth.init, 0, sizeof(ipa3_ctx->hw_stats.teth.init)); sizeof(ipa3_ctx->hw_stats.teth.init)); for (i = 0; i < IPA_CLIENT_MAX; i++) for (i = 0; i < IPA_CLIENT_MAX; i++) { memset(&ipa3_ctx->hw_stats.teth.prod_stats_sum[i], 0, sizeof(ipa3_ctx->hw_stats.teth.prod_stats_sum[i])); memset(&ipa3_ctx->hw_stats.teth.prod_stats[i], 0, memset(&ipa3_ctx->hw_stats.teth.prod_stats[i], 0, sizeof(ipa3_ctx->hw_stats.teth.prod_stats[i])); sizeof(ipa3_ctx->hw_stats.teth.prod_stats[i])); } ipa3_ctx->hw_stats.teth.init.prod_bitmask = in->prod_mask; ipa3_ctx->hw_stats.teth.init.prod_bitmask = in->prod_mask; memcpy(ipa3_ctx->hw_stats.teth.init.cons_bitmask, in->dst_ep_mask, memcpy(ipa3_ctx->hw_stats.teth.init.cons_bitmask, in->dst_ep_mask, sizeof(ipa3_ctx->hw_stats.teth.init.cons_bitmask)); sizeof(ipa3_ctx->hw_stats.teth.init.cons_bitmask)); Loading Loading @@ -458,8 +512,7 @@ int ipa_init_teth_stats(struct ipa_teth_stats_endpoints *in) return ret; return ret; } } int ipa_get_teth_stats(enum ipa_client_type prod, int ipa_get_teth_stats(void) struct ipa_quota_stats_all *out) { { int i, j; int i, j; int ret; int ret; Loading @@ -470,15 +523,14 @@ int ipa_get_teth_stats(enum ipa_client_type prod, struct ipa_mem_buffer mem; struct ipa_mem_buffer mem; struct ipa3_desc desc = { 0 }; struct ipa3_desc desc = { 0 }; struct ipahal_stats_tethering_all *stats; struct ipahal_stats_tethering_all *stats; struct ipa_hw_stats_teth *sw_stats = &ipa3_ctx->hw_stats.teth; struct ipahal_stats_init_tethering *init = (struct ipahal_stats_init_tethering *) &ipa3_ctx->hw_stats.teth.init; if (!ipa3_ctx->hw_stats.enabled) if (!ipa3_ctx->hw_stats.enabled) return 0; return 0; if (!IPA_CLIENT_IS_PROD(prod) || ipa3_get_ep_mapping(prod) == -1) { IPAERR("invalid prod %d\n", prod); return -EINVAL; } get_offset.init = ipa3_ctx->hw_stats.teth.init; get_offset.init = ipa3_ctx->hw_stats.teth.init; ret = ipahal_stats_get_offset(IPAHAL_HW_STATS_TETHERING, &get_offset, ret = ipahal_stats_get_offset(IPAHAL_HW_STATS_TETHERING, &get_offset, &offset); &offset); Loading Loading @@ -539,6 +591,12 @@ int ipa_get_teth_stats(enum ipa_client_type prod, goto free_stats; goto free_stats; } } /* reset prod_stats cache */ for (i = 0; i < IPA_CLIENT_MAX; i++) { memset(&ipa3_ctx->hw_stats.teth.prod_stats[i], 0, sizeof(ipa3_ctx->hw_stats.teth.prod_stats[i])); } /* /* * update driver cache. * update driver cache. * the stats were read from hardware with clear_after_read meaning * the stats were read from hardware with clear_after_read meaning Loading @@ -546,8 +604,6 @@ int ipa_get_teth_stats(enum ipa_client_type prod, */ */ for (i = 0; i < IPA_CLIENT_MAX; i++) { for (i = 0; i < IPA_CLIENT_MAX; i++) { for (j = 0; j < IPA_CLIENT_MAX; j++) { for (j = 0; j < IPA_CLIENT_MAX; j++) { struct ipa_hw_stats_teth *sw_stats = &ipa3_ctx->hw_stats.teth; int prod_idx = ipa3_get_ep_mapping(i); int prod_idx = ipa3_get_ep_mapping(i); int cons_idx = ipa3_get_ep_mapping(j); int cons_idx = ipa3_get_ep_mapping(j); Loading @@ -557,29 +613,64 @@ int ipa_get_teth_stats(enum ipa_client_type prod, if (cons_idx == -1 || cons_idx >= IPA3_MAX_NUM_PIPES) if (cons_idx == -1 || cons_idx >= IPA3_MAX_NUM_PIPES) continue; continue; if (ipa3_ctx->ep[prod_idx].client != i || /* save hw-query result */ ipa3_ctx->ep[cons_idx].client != j) if ((init->prod_bitmask & (1 << prod_idx)) && continue; (init->cons_bitmask[prod_idx] & (1 << cons_idx))) { sw_stats->prod_stats[i].client[j].num_ipv4_bytes += IPADBG_LOW("prod %d cons %d\n", stats->stats[prod_idx][cons_idx].num_ipv4_bytes; prod_idx, cons_idx); sw_stats->prod_stats[i].client[j].num_ipv4_pkts += IPADBG_LOW("num_ipv4_bytes %lld\n", stats->stats[prod_idx][cons_idx].num_ipv4_pkts; stats->stats[prod_idx][cons_idx]. sw_stats->prod_stats[i].client[j].num_ipv6_bytes += num_ipv4_bytes); stats->stats[prod_idx][cons_idx].num_ipv6_bytes; IPADBG_LOW("num_ipv4_pkts %lld\n", sw_stats->prod_stats[i].client[j].num_ipv6_pkts += stats->stats[prod_idx][cons_idx]. stats->stats[prod_idx][cons_idx].num_ipv6_pkts; num_ipv4_pkts); IPADBG_LOW("num_ipv6_pkts %lld\n", stats->stats[prod_idx][cons_idx]. num_ipv6_pkts); IPADBG_LOW("num_ipv6_bytes %lld\n", stats->stats[prod_idx][cons_idx]. num_ipv6_bytes); /* update stats*/ sw_stats->prod_stats[i]. client[j].num_ipv4_bytes = stats->stats[prod_idx][cons_idx]. num_ipv4_bytes; sw_stats->prod_stats[i]. client[j].num_ipv4_pkts = stats->stats[prod_idx][cons_idx]. num_ipv4_pkts; sw_stats->prod_stats[i]. client[j].num_ipv6_bytes = stats->stats[prod_idx][cons_idx]. num_ipv6_bytes; sw_stats->prod_stats[i]. client[j].num_ipv6_pkts = stats->stats[prod_idx][cons_idx]. num_ipv6_pkts; /* Accumulated stats */ sw_stats->prod_stats_sum[i]. client[j].num_ipv4_bytes += stats->stats[prod_idx][cons_idx]. num_ipv4_bytes; sw_stats->prod_stats_sum[i]. client[j].num_ipv4_pkts += stats->stats[prod_idx][cons_idx]. num_ipv4_pkts; sw_stats->prod_stats_sum[i]. client[j].num_ipv6_bytes += stats->stats[prod_idx][cons_idx]. num_ipv6_bytes; sw_stats->prod_stats_sum[i]. client[j].num_ipv6_pkts += stats->stats[prod_idx][cons_idx]. num_ipv6_pkts; } } } } if (!out) { ret = 0; goto free_stats; } } /* copy results to out parameter */ *out = ipa3_ctx->hw_stats.teth.prod_stats[prod]; ret = 0; ret = 0; free_stats: free_stats: kfree(stats); kfree(stats); Loading @@ -591,6 +682,22 @@ int ipa_get_teth_stats(enum ipa_client_type prod, } } int ipa_query_teth_stats(enum ipa_client_type prod, struct ipa_quota_stats_all *out, bool reset) { if (!IPA_CLIENT_IS_PROD(prod) || ipa3_get_ep_mapping(prod) == -1) { IPAERR("invalid prod %d\n", prod); return -EINVAL; } /* copy results to out parameter */ if (reset) *out = ipa3_ctx->hw_stats.teth.prod_stats[prod]; else *out = ipa3_ctx->hw_stats.teth.prod_stats_sum[prod]; return 0; } int ipa_reset_teth_stats(enum ipa_client_type prod, enum ipa_client_type cons) int ipa_reset_teth_stats(enum ipa_client_type prod, enum ipa_client_type cons) { { int ret; int ret; Loading @@ -605,14 +712,14 @@ int ipa_reset_teth_stats(enum ipa_client_type prod, enum ipa_client_type cons) } } /* reading stats will reset them in hardware */ /* reading stats will reset them in hardware */ ret = ipa_get_teth_stats(prod, NULL); ret = ipa_get_teth_stats(); if (ret) { if (ret) { IPAERR("ipa_get_teth_stats failed %d\n", ret); IPAERR("ipa_get_teth_stats failed %d\n", ret); return ret; return ret; } } /* reset driver's cache */ /* reset driver's cache */ stats = &ipa3_ctx->hw_stats.teth.prod_stats[prod].client[cons]; stats = &ipa3_ctx->hw_stats.teth.prod_stats_sum[prod].client[cons]; memset(stats, 0, sizeof(*stats)); memset(stats, 0, sizeof(*stats)); return 0; return 0; } } Loading @@ -632,7 +739,7 @@ int ipa_reset_all_cons_teth_stats(enum ipa_client_type prod) } } /* reading stats will reset them in hardware */ /* reading stats will reset them in hardware */ ret = ipa_get_teth_stats(prod, NULL); ret = ipa_get_teth_stats(); if (ret) { if (ret) { IPAERR("ipa_get_teth_stats failed %d\n", ret); IPAERR("ipa_get_teth_stats failed %d\n", ret); return ret; return ret; Loading @@ -640,7 +747,7 @@ int ipa_reset_all_cons_teth_stats(enum ipa_client_type prod) /* reset driver's cache */ /* reset driver's cache */ for (i = 0; i < IPA_CLIENT_MAX; i++) { for (i = 0; i < IPA_CLIENT_MAX; i++) { stats = &ipa3_ctx->hw_stats.teth.prod_stats[prod].client[i]; stats = &ipa3_ctx->hw_stats.teth.prod_stats_sum[prod].client[i]; memset(stats, 0, sizeof(*stats)); memset(stats, 0, sizeof(*stats)); } } Loading @@ -659,7 +766,7 @@ int ipa_reset_all_teth_stats(void) /* reading stats will reset them in hardware */ /* reading stats will reset them in hardware */ for (i = 0; i < IPA_CLIENT_MAX; i++) { for (i = 0; i < IPA_CLIENT_MAX; i++) { if (IPA_CLIENT_IS_PROD(i) && ipa3_get_ep_mapping(i) != -1) { if (IPA_CLIENT_IS_PROD(i) && ipa3_get_ep_mapping(i) != -1) { ret = ipa_get_teth_stats(i, NULL); ret = ipa_get_teth_stats(); if (ret) { if (ret) { IPAERR("ipa_get_teth_stats failed %d\n", ret); IPAERR("ipa_get_teth_stats failed %d\n", ret); return ret; return ret; Loading @@ -671,7 +778,7 @@ int ipa_reset_all_teth_stats(void) /* reset driver's cache */ /* reset driver's cache */ for (i = 0; i < IPA_CLIENT_MAX; i++) { for (i = 0; i < IPA_CLIENT_MAX; i++) { stats = &ipa3_ctx->hw_stats.teth.prod_stats[i]; stats = &ipa3_ctx->hw_stats.teth.prod_stats_sum[i]; memset(stats, 0, sizeof(*stats)); memset(stats, 0, sizeof(*stats)); } } Loading Loading @@ -1566,7 +1673,7 @@ static ssize_t ipa_debugfs_print_tethering_stats(struct file *file, (1 << ep_idx))) (1 << ep_idx))) continue; continue; res = ipa_get_teth_stats(i, out); res = ipa_get_teth_stats(); if (res) { if (res) { mutex_unlock(&ipa3_ctx->lock); mutex_unlock(&ipa3_ctx->lock); kfree(out); kfree(out); Loading drivers/platform/msm/ipa/ipa_v3/ipa_i.h +5 −2 Original line number Original line Diff line number Diff line Loading @@ -1124,6 +1124,7 @@ struct ipa_hw_stats_quota { struct ipa_hw_stats_teth { struct ipa_hw_stats_teth { struct ipahal_stats_init_tethering init; struct ipahal_stats_init_tethering init; struct ipa_quota_stats_all prod_stats_sum[IPA_CLIENT_MAX]; struct ipa_quota_stats_all prod_stats[IPA_CLIENT_MAX]; struct ipa_quota_stats_all prod_stats[IPA_CLIENT_MAX]; }; }; Loading Loading @@ -2251,8 +2252,10 @@ int ipa_reset_all_drop_stats(void); int ipa_init_teth_stats(struct ipa_teth_stats_endpoints *in); int ipa_init_teth_stats(struct ipa_teth_stats_endpoints *in); int ipa_get_teth_stats(enum ipa_client_type prod, int ipa_get_teth_stats(void); struct ipa_quota_stats_all *out); int ipa_query_teth_stats(enum ipa_client_type prod, struct ipa_quota_stats_all *out, bool reset); int ipa_reset_teth_stats(enum ipa_client_type prod, enum ipa_client_type cons); int ipa_reset_teth_stats(enum ipa_client_type prod, enum ipa_client_type cons); Loading drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +148 −9 Original line number Original line Diff line number Diff line Loading @@ -3183,9 +3183,6 @@ static int rmnet_ipa3_query_tethering_stats_modem( req->reset_stats_valid = true; req->reset_stats_valid = true; req->reset_stats = true; req->reset_stats = true; IPAWANDBG("reset the pipe stats\n"); IPAWANDBG("reset the pipe stats\n"); } else { /* print tethered-client enum */ IPAWANDBG("Tethered-client enum(%d)\n", data->ipa_client); } } rc = ipa3_qmi_get_data_stats(req, resp); rc = ipa3_qmi_get_data_stats(req, resp); Loading Loading @@ -3277,7 +3274,7 @@ static int rmnet_ipa3_query_tethering_stats_modem( if (data->ipa_client == ipa_get_client(resp-> if (data->ipa_client == ipa_get_client(resp-> ul_src_pipe_stats_list[pipe_len]. ul_src_pipe_stats_list[pipe_len]. pipe_index)) { pipe_index)) { /* update the DL stats */ /* update the UL stats */ data->ipv4_tx_packets += resp-> data->ipv4_tx_packets += resp-> ul_src_pipe_stats_list[pipe_len]. ul_src_pipe_stats_list[pipe_len]. num_ipv4_packets; num_ipv4_packets; Loading @@ -3304,6 +3301,133 @@ static int rmnet_ipa3_query_tethering_stats_modem( return 0; return 0; } } static int rmnet_ipa3_query_tethering_stats_hw( struct wan_ioctl_query_tether_stats *data, bool reset) { int rc = 0; struct ipa_quota_stats_all *con_stats; if (reset) { IPAWANERR("only reset the pipe stats without returning stats"); rc = ipa_get_teth_stats(); if (rc) { IPAWANERR("ipa_get_teth_stats failed %d,\n", rc); return rc; } return 0; } /* qet HW-stats */ rc = ipa_get_teth_stats(); if (rc) { IPAWANDBG("ipa_get_teth_stats failed %d,\n", rc); return rc; } /* query DL stats */ IPAWANDBG("reset the pipe stats? (%d)\n", reset); con_stats = kzalloc(sizeof(*con_stats), GFP_KERNEL); if (!con_stats) { IPAWANERR("no memory\n"); return -ENOMEM; } rc = ipa_query_teth_stats(IPA_CLIENT_Q6_WAN_PROD, con_stats, reset); if (rc) { IPAERR("IPA_CLIENT_Q6_WAN_PROD query failed %d,\n", rc); kfree(con_stats); return rc; } IPAWANDBG("wlan: v4_rx_p(%d) b(%lld) v6_rx_p(%d) b(%lld)\n", con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv4_pkts, con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv4_bytes, con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv6_pkts, con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv6_bytes); IPAWANDBG("usb: v4_rx_p(%d) b(%lld) v6_rx_p(%d) b(%lld)\n", con_stats->client[IPA_CLIENT_USB_CONS].num_ipv4_pkts, con_stats->client[IPA_CLIENT_USB_CONS].num_ipv4_bytes, con_stats->client[IPA_CLIENT_USB_CONS].num_ipv6_pkts, con_stats->client[IPA_CLIENT_USB_CONS].num_ipv6_bytes); /* update the DL stats */ data->ipv4_rx_packets = con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv4_pkts + con_stats->client[IPA_CLIENT_USB_CONS].num_ipv4_pkts; data->ipv6_rx_packets = con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv6_pkts + con_stats->client[IPA_CLIENT_USB_CONS].num_ipv6_pkts; data->ipv4_rx_bytes = con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv4_bytes + con_stats->client[IPA_CLIENT_USB_CONS].num_ipv4_bytes; data->ipv6_rx_bytes = con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv6_bytes + con_stats->client[IPA_CLIENT_USB_CONS].num_ipv6_bytes; IPAWANDBG("v4_rx_p(%lu) v6_rx_p(%lu) v4_rx_b(%lu) v6_rx_b(%lu)\n", (unsigned long int) data->ipv4_rx_packets, (unsigned long int) data->ipv6_rx_packets, (unsigned long int) data->ipv4_rx_bytes, (unsigned long int) data->ipv6_rx_bytes); /* query USB UL stats */ memset(con_stats, 0, sizeof(struct ipa_quota_stats_all)); rc = ipa_query_teth_stats(IPA_CLIENT_USB_PROD, con_stats, reset); if (rc) { IPAERR("IPA_CLIENT_USB_PROD query failed %d\n", rc); kfree(con_stats); return rc; } IPAWANDBG("usb: v4_tx_p(%d) b(%lld) v6_tx_p(%d) b(%lld)\n", con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_pkts, con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_bytes, con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_pkts, con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_bytes); /* update the USB UL stats */ data->ipv4_tx_packets = con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_pkts; data->ipv6_tx_packets = con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_pkts; data->ipv4_tx_bytes = con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_bytes; data->ipv6_tx_bytes = con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_bytes; /* query WLAN UL stats */ memset(con_stats, 0, sizeof(struct ipa_quota_stats_all)); rc = ipa_query_teth_stats(IPA_CLIENT_WLAN1_PROD, con_stats, reset); if (rc) { IPAERR("IPA_CLIENT_WLAN1_PROD query failed %d\n", rc); kfree(con_stats); return rc; } IPAWANDBG("wlan: v4_tx_p(%d) b(%lld) v6_tx_p(%d) b(%lld)\n", con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_pkts, con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_bytes, con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_pkts, con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_bytes); /* update the wlan UL stats */ data->ipv4_tx_packets += con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_pkts; data->ipv6_tx_packets += con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_pkts; data->ipv4_tx_bytes += con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_bytes; data->ipv6_tx_bytes += con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_bytes; IPAWANDBG("v4_tx_p(%lu) v6_tx_p(%lu) v4_tx_b(%lu) v6_tx_b(%lu)\n", (unsigned long int) data->ipv4_tx_packets, (unsigned long int) data->ipv6_tx_packets, (unsigned long int) data->ipv4_tx_bytes, (unsigned long int) data->ipv6_tx_bytes); kfree(con_stats); return rc; } int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data, int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data, bool reset) bool reset) { { Loading Loading @@ -3373,12 +3497,27 @@ int rmnet_ipa3_query_tethering_stats_all( } else { } else { IPAWANDBG_LOW(" query modem-backhaul stats\n"); IPAWANDBG_LOW(" query modem-backhaul stats\n"); tether_stats.ipa_client = data->ipa_client; tether_stats.ipa_client = data->ipa_client; if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0 || !ipa3_ctx->hw_stats.enabled) { IPAWANDBG("hw version %d,hw_stats.enabled %d\n", ipa3_ctx->ipa_hw_type, ipa3_ctx->hw_stats.enabled); /* get modem stats from QMI */ rc = rmnet_ipa3_query_tethering_stats_modem( rc = rmnet_ipa3_query_tethering_stats_modem( &tether_stats, data->reset_stats); &tether_stats, data->reset_stats); if (rc) { if (rc) { IPAWANERR("modem WAN_IOC_QUERY_TETHER_STATS failed\n"); IPAWANERR("modem QUERY_TETHER_STATS failed\n"); return rc; return rc; } } } else { /* get modem stats from IPA-HW counters */ rc = rmnet_ipa3_query_tethering_stats_hw( &tether_stats, data->reset_stats); if (rc) { IPAWANERR("modem QUERY_TETHER_STATS failed\n"); return rc; } } data->tx_bytes = tether_stats.ipv4_tx_bytes data->tx_bytes = tether_stats.ipv4_tx_bytes + tether_stats.ipv6_tx_bytes; + tether_stats.ipv6_tx_bytes; data->rx_bytes = tether_stats.ipv4_rx_bytes data->rx_bytes = tether_stats.ipv4_rx_bytes Loading Loading
drivers/platform/msm/ipa/ipa_v3/ipa.c +2 −2 Original line number Original line Diff line number Diff line Loading @@ -4515,8 +4515,6 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, IPADBG("teth_bridge initialized"); IPADBG("teth_bridge initialized"); } } ipa3_debugfs_init(); result = ipa3_uc_interface_init(); result = ipa3_uc_interface_init(); if (result) if (result) IPAERR(":ipa Uc interface init failed (%d)\n", -result); IPAERR(":ipa Uc interface init failed (%d)\n", -result); Loading Loading @@ -4554,6 +4552,8 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, complete_all(&ipa3_ctx->init_completion_obj); complete_all(&ipa3_ctx->init_completion_obj); pr_info("IPA driver initialization was successful.\n"); pr_info("IPA driver initialization was successful.\n"); ipa3_debugfs_init(); return 0; return 0; fail_teth_bridge_driver_init: fail_teth_bridge_driver_init: Loading
drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c +146 −39 Original line number Original line Diff line number Diff line /* Copyright (c) 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and Loading @@ -24,12 +24,63 @@ int ipa_hw_stats_init(void) int ipa_hw_stats_init(void) { { int ret = 0, ep_index; struct ipa_teth_stats_endpoints *teth_stats_init; if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) return 0; return 0; /* initialize stats here */ /* initialize stats here */ ipa3_ctx->hw_stats.enabled = true; ipa3_ctx->hw_stats.enabled = true; return 0; teth_stats_init = kzalloc(sizeof(*teth_stats_init), GFP_KERNEL); if (!teth_stats_init) { IPAERR("mem allocated failed!\n"); return -ENOMEM; } /* enable prod mask */ teth_stats_init->prod_mask = ( IPA_CLIENT_BIT_32(IPA_CLIENT_Q6_WAN_PROD) | IPA_CLIENT_BIT_32(IPA_CLIENT_USB_PROD) | IPA_CLIENT_BIT_32(IPA_CLIENT_WLAN1_PROD)); if (IPA_CLIENT_BIT_32(IPA_CLIENT_Q6_WAN_PROD)) { ep_index = ipa3_get_ep_mapping(IPA_CLIENT_Q6_WAN_PROD); if (ep_index == -1) { IPAERR("Invalid client.\n"); kfree(teth_stats_init); return -EINVAL; } teth_stats_init->dst_ep_mask[ep_index] = (IPA_CLIENT_BIT_32(IPA_CLIENT_WLAN1_CONS) | IPA_CLIENT_BIT_32(IPA_CLIENT_USB_CONS)); } if (IPA_CLIENT_BIT_32(IPA_CLIENT_USB_PROD)) { ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB_PROD); if (ep_index == -1) { IPAERR("Invalid client.\n"); kfree(teth_stats_init); return -EINVAL; } teth_stats_init->dst_ep_mask[ep_index] = IPA_CLIENT_BIT_32(IPA_CLIENT_Q6_WAN_CONS); } if (IPA_CLIENT_BIT_32(IPA_CLIENT_WLAN1_PROD)) { ep_index = ipa3_get_ep_mapping(IPA_CLIENT_WLAN1_PROD); if (ep_index == -1) { IPAERR("Invalid client.\n"); kfree(teth_stats_init); return -EINVAL; } teth_stats_init->dst_ep_mask[ep_index] = IPA_CLIENT_BIT_32(IPA_CLIENT_Q6_WAN_CONS); } ret = ipa_init_teth_stats(teth_stats_init); kfree(teth_stats_init); return ret; } } int ipa_init_quota_stats(u32 pipe_bitmask) int ipa_init_quota_stats(u32 pipe_bitmask) Loading Loading @@ -348,9 +399,12 @@ int ipa_init_teth_stats(struct ipa_teth_stats_endpoints *in) /* reset driver's cache */ /* reset driver's cache */ memset(&ipa3_ctx->hw_stats.teth.init, 0, memset(&ipa3_ctx->hw_stats.teth.init, 0, sizeof(ipa3_ctx->hw_stats.teth.init)); sizeof(ipa3_ctx->hw_stats.teth.init)); for (i = 0; i < IPA_CLIENT_MAX; i++) for (i = 0; i < IPA_CLIENT_MAX; i++) { memset(&ipa3_ctx->hw_stats.teth.prod_stats_sum[i], 0, sizeof(ipa3_ctx->hw_stats.teth.prod_stats_sum[i])); memset(&ipa3_ctx->hw_stats.teth.prod_stats[i], 0, memset(&ipa3_ctx->hw_stats.teth.prod_stats[i], 0, sizeof(ipa3_ctx->hw_stats.teth.prod_stats[i])); sizeof(ipa3_ctx->hw_stats.teth.prod_stats[i])); } ipa3_ctx->hw_stats.teth.init.prod_bitmask = in->prod_mask; ipa3_ctx->hw_stats.teth.init.prod_bitmask = in->prod_mask; memcpy(ipa3_ctx->hw_stats.teth.init.cons_bitmask, in->dst_ep_mask, memcpy(ipa3_ctx->hw_stats.teth.init.cons_bitmask, in->dst_ep_mask, sizeof(ipa3_ctx->hw_stats.teth.init.cons_bitmask)); sizeof(ipa3_ctx->hw_stats.teth.init.cons_bitmask)); Loading Loading @@ -458,8 +512,7 @@ int ipa_init_teth_stats(struct ipa_teth_stats_endpoints *in) return ret; return ret; } } int ipa_get_teth_stats(enum ipa_client_type prod, int ipa_get_teth_stats(void) struct ipa_quota_stats_all *out) { { int i, j; int i, j; int ret; int ret; Loading @@ -470,15 +523,14 @@ int ipa_get_teth_stats(enum ipa_client_type prod, struct ipa_mem_buffer mem; struct ipa_mem_buffer mem; struct ipa3_desc desc = { 0 }; struct ipa3_desc desc = { 0 }; struct ipahal_stats_tethering_all *stats; struct ipahal_stats_tethering_all *stats; struct ipa_hw_stats_teth *sw_stats = &ipa3_ctx->hw_stats.teth; struct ipahal_stats_init_tethering *init = (struct ipahal_stats_init_tethering *) &ipa3_ctx->hw_stats.teth.init; if (!ipa3_ctx->hw_stats.enabled) if (!ipa3_ctx->hw_stats.enabled) return 0; return 0; if (!IPA_CLIENT_IS_PROD(prod) || ipa3_get_ep_mapping(prod) == -1) { IPAERR("invalid prod %d\n", prod); return -EINVAL; } get_offset.init = ipa3_ctx->hw_stats.teth.init; get_offset.init = ipa3_ctx->hw_stats.teth.init; ret = ipahal_stats_get_offset(IPAHAL_HW_STATS_TETHERING, &get_offset, ret = ipahal_stats_get_offset(IPAHAL_HW_STATS_TETHERING, &get_offset, &offset); &offset); Loading Loading @@ -539,6 +591,12 @@ int ipa_get_teth_stats(enum ipa_client_type prod, goto free_stats; goto free_stats; } } /* reset prod_stats cache */ for (i = 0; i < IPA_CLIENT_MAX; i++) { memset(&ipa3_ctx->hw_stats.teth.prod_stats[i], 0, sizeof(ipa3_ctx->hw_stats.teth.prod_stats[i])); } /* /* * update driver cache. * update driver cache. * the stats were read from hardware with clear_after_read meaning * the stats were read from hardware with clear_after_read meaning Loading @@ -546,8 +604,6 @@ int ipa_get_teth_stats(enum ipa_client_type prod, */ */ for (i = 0; i < IPA_CLIENT_MAX; i++) { for (i = 0; i < IPA_CLIENT_MAX; i++) { for (j = 0; j < IPA_CLIENT_MAX; j++) { for (j = 0; j < IPA_CLIENT_MAX; j++) { struct ipa_hw_stats_teth *sw_stats = &ipa3_ctx->hw_stats.teth; int prod_idx = ipa3_get_ep_mapping(i); int prod_idx = ipa3_get_ep_mapping(i); int cons_idx = ipa3_get_ep_mapping(j); int cons_idx = ipa3_get_ep_mapping(j); Loading @@ -557,29 +613,64 @@ int ipa_get_teth_stats(enum ipa_client_type prod, if (cons_idx == -1 || cons_idx >= IPA3_MAX_NUM_PIPES) if (cons_idx == -1 || cons_idx >= IPA3_MAX_NUM_PIPES) continue; continue; if (ipa3_ctx->ep[prod_idx].client != i || /* save hw-query result */ ipa3_ctx->ep[cons_idx].client != j) if ((init->prod_bitmask & (1 << prod_idx)) && continue; (init->cons_bitmask[prod_idx] & (1 << cons_idx))) { sw_stats->prod_stats[i].client[j].num_ipv4_bytes += IPADBG_LOW("prod %d cons %d\n", stats->stats[prod_idx][cons_idx].num_ipv4_bytes; prod_idx, cons_idx); sw_stats->prod_stats[i].client[j].num_ipv4_pkts += IPADBG_LOW("num_ipv4_bytes %lld\n", stats->stats[prod_idx][cons_idx].num_ipv4_pkts; stats->stats[prod_idx][cons_idx]. sw_stats->prod_stats[i].client[j].num_ipv6_bytes += num_ipv4_bytes); stats->stats[prod_idx][cons_idx].num_ipv6_bytes; IPADBG_LOW("num_ipv4_pkts %lld\n", sw_stats->prod_stats[i].client[j].num_ipv6_pkts += stats->stats[prod_idx][cons_idx]. stats->stats[prod_idx][cons_idx].num_ipv6_pkts; num_ipv4_pkts); IPADBG_LOW("num_ipv6_pkts %lld\n", stats->stats[prod_idx][cons_idx]. num_ipv6_pkts); IPADBG_LOW("num_ipv6_bytes %lld\n", stats->stats[prod_idx][cons_idx]. num_ipv6_bytes); /* update stats*/ sw_stats->prod_stats[i]. client[j].num_ipv4_bytes = stats->stats[prod_idx][cons_idx]. num_ipv4_bytes; sw_stats->prod_stats[i]. client[j].num_ipv4_pkts = stats->stats[prod_idx][cons_idx]. num_ipv4_pkts; sw_stats->prod_stats[i]. client[j].num_ipv6_bytes = stats->stats[prod_idx][cons_idx]. num_ipv6_bytes; sw_stats->prod_stats[i]. client[j].num_ipv6_pkts = stats->stats[prod_idx][cons_idx]. num_ipv6_pkts; /* Accumulated stats */ sw_stats->prod_stats_sum[i]. client[j].num_ipv4_bytes += stats->stats[prod_idx][cons_idx]. num_ipv4_bytes; sw_stats->prod_stats_sum[i]. client[j].num_ipv4_pkts += stats->stats[prod_idx][cons_idx]. num_ipv4_pkts; sw_stats->prod_stats_sum[i]. client[j].num_ipv6_bytes += stats->stats[prod_idx][cons_idx]. num_ipv6_bytes; sw_stats->prod_stats_sum[i]. client[j].num_ipv6_pkts += stats->stats[prod_idx][cons_idx]. num_ipv6_pkts; } } } } if (!out) { ret = 0; goto free_stats; } } /* copy results to out parameter */ *out = ipa3_ctx->hw_stats.teth.prod_stats[prod]; ret = 0; ret = 0; free_stats: free_stats: kfree(stats); kfree(stats); Loading @@ -591,6 +682,22 @@ int ipa_get_teth_stats(enum ipa_client_type prod, } } int ipa_query_teth_stats(enum ipa_client_type prod, struct ipa_quota_stats_all *out, bool reset) { if (!IPA_CLIENT_IS_PROD(prod) || ipa3_get_ep_mapping(prod) == -1) { IPAERR("invalid prod %d\n", prod); return -EINVAL; } /* copy results to out parameter */ if (reset) *out = ipa3_ctx->hw_stats.teth.prod_stats[prod]; else *out = ipa3_ctx->hw_stats.teth.prod_stats_sum[prod]; return 0; } int ipa_reset_teth_stats(enum ipa_client_type prod, enum ipa_client_type cons) int ipa_reset_teth_stats(enum ipa_client_type prod, enum ipa_client_type cons) { { int ret; int ret; Loading @@ -605,14 +712,14 @@ int ipa_reset_teth_stats(enum ipa_client_type prod, enum ipa_client_type cons) } } /* reading stats will reset them in hardware */ /* reading stats will reset them in hardware */ ret = ipa_get_teth_stats(prod, NULL); ret = ipa_get_teth_stats(); if (ret) { if (ret) { IPAERR("ipa_get_teth_stats failed %d\n", ret); IPAERR("ipa_get_teth_stats failed %d\n", ret); return ret; return ret; } } /* reset driver's cache */ /* reset driver's cache */ stats = &ipa3_ctx->hw_stats.teth.prod_stats[prod].client[cons]; stats = &ipa3_ctx->hw_stats.teth.prod_stats_sum[prod].client[cons]; memset(stats, 0, sizeof(*stats)); memset(stats, 0, sizeof(*stats)); return 0; return 0; } } Loading @@ -632,7 +739,7 @@ int ipa_reset_all_cons_teth_stats(enum ipa_client_type prod) } } /* reading stats will reset them in hardware */ /* reading stats will reset them in hardware */ ret = ipa_get_teth_stats(prod, NULL); ret = ipa_get_teth_stats(); if (ret) { if (ret) { IPAERR("ipa_get_teth_stats failed %d\n", ret); IPAERR("ipa_get_teth_stats failed %d\n", ret); return ret; return ret; Loading @@ -640,7 +747,7 @@ int ipa_reset_all_cons_teth_stats(enum ipa_client_type prod) /* reset driver's cache */ /* reset driver's cache */ for (i = 0; i < IPA_CLIENT_MAX; i++) { for (i = 0; i < IPA_CLIENT_MAX; i++) { stats = &ipa3_ctx->hw_stats.teth.prod_stats[prod].client[i]; stats = &ipa3_ctx->hw_stats.teth.prod_stats_sum[prod].client[i]; memset(stats, 0, sizeof(*stats)); memset(stats, 0, sizeof(*stats)); } } Loading @@ -659,7 +766,7 @@ int ipa_reset_all_teth_stats(void) /* reading stats will reset them in hardware */ /* reading stats will reset them in hardware */ for (i = 0; i < IPA_CLIENT_MAX; i++) { for (i = 0; i < IPA_CLIENT_MAX; i++) { if (IPA_CLIENT_IS_PROD(i) && ipa3_get_ep_mapping(i) != -1) { if (IPA_CLIENT_IS_PROD(i) && ipa3_get_ep_mapping(i) != -1) { ret = ipa_get_teth_stats(i, NULL); ret = ipa_get_teth_stats(); if (ret) { if (ret) { IPAERR("ipa_get_teth_stats failed %d\n", ret); IPAERR("ipa_get_teth_stats failed %d\n", ret); return ret; return ret; Loading @@ -671,7 +778,7 @@ int ipa_reset_all_teth_stats(void) /* reset driver's cache */ /* reset driver's cache */ for (i = 0; i < IPA_CLIENT_MAX; i++) { for (i = 0; i < IPA_CLIENT_MAX; i++) { stats = &ipa3_ctx->hw_stats.teth.prod_stats[i]; stats = &ipa3_ctx->hw_stats.teth.prod_stats_sum[i]; memset(stats, 0, sizeof(*stats)); memset(stats, 0, sizeof(*stats)); } } Loading Loading @@ -1566,7 +1673,7 @@ static ssize_t ipa_debugfs_print_tethering_stats(struct file *file, (1 << ep_idx))) (1 << ep_idx))) continue; continue; res = ipa_get_teth_stats(i, out); res = ipa_get_teth_stats(); if (res) { if (res) { mutex_unlock(&ipa3_ctx->lock); mutex_unlock(&ipa3_ctx->lock); kfree(out); kfree(out); Loading
drivers/platform/msm/ipa/ipa_v3/ipa_i.h +5 −2 Original line number Original line Diff line number Diff line Loading @@ -1124,6 +1124,7 @@ struct ipa_hw_stats_quota { struct ipa_hw_stats_teth { struct ipa_hw_stats_teth { struct ipahal_stats_init_tethering init; struct ipahal_stats_init_tethering init; struct ipa_quota_stats_all prod_stats_sum[IPA_CLIENT_MAX]; struct ipa_quota_stats_all prod_stats[IPA_CLIENT_MAX]; struct ipa_quota_stats_all prod_stats[IPA_CLIENT_MAX]; }; }; Loading Loading @@ -2251,8 +2252,10 @@ int ipa_reset_all_drop_stats(void); int ipa_init_teth_stats(struct ipa_teth_stats_endpoints *in); int ipa_init_teth_stats(struct ipa_teth_stats_endpoints *in); int ipa_get_teth_stats(enum ipa_client_type prod, int ipa_get_teth_stats(void); struct ipa_quota_stats_all *out); int ipa_query_teth_stats(enum ipa_client_type prod, struct ipa_quota_stats_all *out, bool reset); int ipa_reset_teth_stats(enum ipa_client_type prod, enum ipa_client_type cons); int ipa_reset_teth_stats(enum ipa_client_type prod, enum ipa_client_type cons); Loading
drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +148 −9 Original line number Original line Diff line number Diff line Loading @@ -3183,9 +3183,6 @@ static int rmnet_ipa3_query_tethering_stats_modem( req->reset_stats_valid = true; req->reset_stats_valid = true; req->reset_stats = true; req->reset_stats = true; IPAWANDBG("reset the pipe stats\n"); IPAWANDBG("reset the pipe stats\n"); } else { /* print tethered-client enum */ IPAWANDBG("Tethered-client enum(%d)\n", data->ipa_client); } } rc = ipa3_qmi_get_data_stats(req, resp); rc = ipa3_qmi_get_data_stats(req, resp); Loading Loading @@ -3277,7 +3274,7 @@ static int rmnet_ipa3_query_tethering_stats_modem( if (data->ipa_client == ipa_get_client(resp-> if (data->ipa_client == ipa_get_client(resp-> ul_src_pipe_stats_list[pipe_len]. ul_src_pipe_stats_list[pipe_len]. pipe_index)) { pipe_index)) { /* update the DL stats */ /* update the UL stats */ data->ipv4_tx_packets += resp-> data->ipv4_tx_packets += resp-> ul_src_pipe_stats_list[pipe_len]. ul_src_pipe_stats_list[pipe_len]. num_ipv4_packets; num_ipv4_packets; Loading @@ -3304,6 +3301,133 @@ static int rmnet_ipa3_query_tethering_stats_modem( return 0; return 0; } } static int rmnet_ipa3_query_tethering_stats_hw( struct wan_ioctl_query_tether_stats *data, bool reset) { int rc = 0; struct ipa_quota_stats_all *con_stats; if (reset) { IPAWANERR("only reset the pipe stats without returning stats"); rc = ipa_get_teth_stats(); if (rc) { IPAWANERR("ipa_get_teth_stats failed %d,\n", rc); return rc; } return 0; } /* qet HW-stats */ rc = ipa_get_teth_stats(); if (rc) { IPAWANDBG("ipa_get_teth_stats failed %d,\n", rc); return rc; } /* query DL stats */ IPAWANDBG("reset the pipe stats? (%d)\n", reset); con_stats = kzalloc(sizeof(*con_stats), GFP_KERNEL); if (!con_stats) { IPAWANERR("no memory\n"); return -ENOMEM; } rc = ipa_query_teth_stats(IPA_CLIENT_Q6_WAN_PROD, con_stats, reset); if (rc) { IPAERR("IPA_CLIENT_Q6_WAN_PROD query failed %d,\n", rc); kfree(con_stats); return rc; } IPAWANDBG("wlan: v4_rx_p(%d) b(%lld) v6_rx_p(%d) b(%lld)\n", con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv4_pkts, con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv4_bytes, con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv6_pkts, con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv6_bytes); IPAWANDBG("usb: v4_rx_p(%d) b(%lld) v6_rx_p(%d) b(%lld)\n", con_stats->client[IPA_CLIENT_USB_CONS].num_ipv4_pkts, con_stats->client[IPA_CLIENT_USB_CONS].num_ipv4_bytes, con_stats->client[IPA_CLIENT_USB_CONS].num_ipv6_pkts, con_stats->client[IPA_CLIENT_USB_CONS].num_ipv6_bytes); /* update the DL stats */ data->ipv4_rx_packets = con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv4_pkts + con_stats->client[IPA_CLIENT_USB_CONS].num_ipv4_pkts; data->ipv6_rx_packets = con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv6_pkts + con_stats->client[IPA_CLIENT_USB_CONS].num_ipv6_pkts; data->ipv4_rx_bytes = con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv4_bytes + con_stats->client[IPA_CLIENT_USB_CONS].num_ipv4_bytes; data->ipv6_rx_bytes = con_stats->client[IPA_CLIENT_WLAN1_CONS].num_ipv6_bytes + con_stats->client[IPA_CLIENT_USB_CONS].num_ipv6_bytes; IPAWANDBG("v4_rx_p(%lu) v6_rx_p(%lu) v4_rx_b(%lu) v6_rx_b(%lu)\n", (unsigned long int) data->ipv4_rx_packets, (unsigned long int) data->ipv6_rx_packets, (unsigned long int) data->ipv4_rx_bytes, (unsigned long int) data->ipv6_rx_bytes); /* query USB UL stats */ memset(con_stats, 0, sizeof(struct ipa_quota_stats_all)); rc = ipa_query_teth_stats(IPA_CLIENT_USB_PROD, con_stats, reset); if (rc) { IPAERR("IPA_CLIENT_USB_PROD query failed %d\n", rc); kfree(con_stats); return rc; } IPAWANDBG("usb: v4_tx_p(%d) b(%lld) v6_tx_p(%d) b(%lld)\n", con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_pkts, con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_bytes, con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_pkts, con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_bytes); /* update the USB UL stats */ data->ipv4_tx_packets = con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_pkts; data->ipv6_tx_packets = con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_pkts; data->ipv4_tx_bytes = con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_bytes; data->ipv6_tx_bytes = con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_bytes; /* query WLAN UL stats */ memset(con_stats, 0, sizeof(struct ipa_quota_stats_all)); rc = ipa_query_teth_stats(IPA_CLIENT_WLAN1_PROD, con_stats, reset); if (rc) { IPAERR("IPA_CLIENT_WLAN1_PROD query failed %d\n", rc); kfree(con_stats); return rc; } IPAWANDBG("wlan: v4_tx_p(%d) b(%lld) v6_tx_p(%d) b(%lld)\n", con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_pkts, con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_bytes, con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_pkts, con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_bytes); /* update the wlan UL stats */ data->ipv4_tx_packets += con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_pkts; data->ipv6_tx_packets += con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_pkts; data->ipv4_tx_bytes += con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv4_bytes; data->ipv6_tx_bytes += con_stats->client[IPA_CLIENT_Q6_WAN_CONS].num_ipv6_bytes; IPAWANDBG("v4_tx_p(%lu) v6_tx_p(%lu) v4_tx_b(%lu) v6_tx_b(%lu)\n", (unsigned long int) data->ipv4_tx_packets, (unsigned long int) data->ipv6_tx_packets, (unsigned long int) data->ipv4_tx_bytes, (unsigned long int) data->ipv6_tx_bytes); kfree(con_stats); return rc; } int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data, int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data, bool reset) bool reset) { { Loading Loading @@ -3373,12 +3497,27 @@ int rmnet_ipa3_query_tethering_stats_all( } else { } else { IPAWANDBG_LOW(" query modem-backhaul stats\n"); IPAWANDBG_LOW(" query modem-backhaul stats\n"); tether_stats.ipa_client = data->ipa_client; tether_stats.ipa_client = data->ipa_client; if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0 || !ipa3_ctx->hw_stats.enabled) { IPAWANDBG("hw version %d,hw_stats.enabled %d\n", ipa3_ctx->ipa_hw_type, ipa3_ctx->hw_stats.enabled); /* get modem stats from QMI */ rc = rmnet_ipa3_query_tethering_stats_modem( rc = rmnet_ipa3_query_tethering_stats_modem( &tether_stats, data->reset_stats); &tether_stats, data->reset_stats); if (rc) { if (rc) { IPAWANERR("modem WAN_IOC_QUERY_TETHER_STATS failed\n"); IPAWANERR("modem QUERY_TETHER_STATS failed\n"); return rc; return rc; } } } else { /* get modem stats from IPA-HW counters */ rc = rmnet_ipa3_query_tethering_stats_hw( &tether_stats, data->reset_stats); if (rc) { IPAWANERR("modem QUERY_TETHER_STATS failed\n"); return rc; } } data->tx_bytes = tether_stats.ipv4_tx_bytes data->tx_bytes = tether_stats.ipv4_tx_bytes + tether_stats.ipv6_tx_bytes; + tether_stats.ipv6_tx_bytes; data->rx_bytes = tether_stats.ipv4_rx_bytes data->rx_bytes = tether_stats.ipv4_rx_bytes Loading