ipahal_hw_stats.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
  4. */
  5. #include "ipahal.h"
  6. #include "ipahal_hw_stats.h"
  7. #include "ipahal_hw_stats_i.h"
  8. #include "ipahal_i.h"
  9. struct ipahal_hw_stats_obj {
  10. struct ipahal_stats_init_pyld *(*generate_init_pyld)(void *params,
  11. bool is_atomic_ctx);
  12. int (*get_offset)(void *params, struct ipahal_stats_offset *out);
  13. int (*parse_stats)(void *init_params, void *raw_stats,
  14. void *parsed_stats);
  15. };
  16. static int _count_ones(u32 number)
  17. {
  18. int count = 0;
  19. while (number) {
  20. count++;
  21. number = number & (number - 1);
  22. }
  23. return count;
  24. }
  25. static struct ipahal_stats_init_pyld *ipahal_generate_init_pyld_quota(
  26. void *params, bool is_atomic_ctx)
  27. {
  28. struct ipahal_stats_init_pyld *pyld;
  29. struct ipahal_stats_init_quota *in =
  30. (struct ipahal_stats_init_quota *)params;
  31. int entries = _count_ones(in->enabled_bitmask);
  32. IPAHAL_DBG_LOW("entries = %d\n", entries);
  33. pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) +
  34. entries * sizeof(struct ipahal_stats_quota_hw), is_atomic_ctx);
  35. if (!pyld) {
  36. IPAHAL_ERR("no mem\n");
  37. return NULL;
  38. }
  39. pyld->len = entries * sizeof(struct ipahal_stats_quota_hw);
  40. return pyld;
  41. }
  42. static int ipahal_get_offset_quota(void *params,
  43. struct ipahal_stats_offset *out)
  44. {
  45. struct ipahal_stats_get_offset_quota *in =
  46. (struct ipahal_stats_get_offset_quota *)params;
  47. int entries = _count_ones(in->init.enabled_bitmask);
  48. IPAHAL_DBG_LOW("\n");
  49. out->offset = 0;
  50. out->size = entries * sizeof(struct ipahal_stats_quota_hw);
  51. return 0;
  52. }
  53. static int ipahal_parse_stats_quota(void *init_params, void *raw_stats,
  54. void *parsed_stats)
  55. {
  56. struct ipahal_stats_init_quota *init =
  57. (struct ipahal_stats_init_quota *)init_params;
  58. struct ipahal_stats_quota_hw *raw_hw =
  59. (struct ipahal_stats_quota_hw *)raw_stats;
  60. struct ipahal_stats_quota_all *out =
  61. (struct ipahal_stats_quota_all *)parsed_stats;
  62. int stat_idx = 0;
  63. int i;
  64. memset(out, 0, sizeof(*out));
  65. IPAHAL_DBG_LOW("\n");
  66. for (i = 0; i < IPAHAL_MAX_PIPES; i++) {
  67. if (init->enabled_bitmask & (1 << i)) {
  68. IPAHAL_DBG_LOW("pipe %d stat_idx %d\n", i, stat_idx);
  69. out->stats[i].num_ipv4_bytes =
  70. raw_hw[stat_idx].num_ipv4_bytes;
  71. out->stats[i].num_ipv4_pkts =
  72. raw_hw[stat_idx].num_ipv4_pkts;
  73. out->stats[i].num_ipv6_pkts =
  74. raw_hw[stat_idx].num_ipv6_pkts;
  75. out->stats[i].num_ipv6_bytes =
  76. raw_hw[stat_idx].num_ipv6_bytes;
  77. stat_idx++;
  78. }
  79. }
  80. return 0;
  81. }
  82. static struct ipahal_stats_init_pyld *ipahal_generate_init_pyld_tethering(
  83. void *params, bool is_atomic_ctx)
  84. {
  85. struct ipahal_stats_init_pyld *pyld;
  86. struct ipahal_stats_init_tethering *in =
  87. (struct ipahal_stats_init_tethering *)params;
  88. int hdr_entries = _count_ones(in->prod_bitmask);
  89. int entries = 0;
  90. int i;
  91. void *pyld_ptr;
  92. u32 incremental_offset;
  93. IPAHAL_DBG_LOW("prod entries = %d\n", hdr_entries);
  94. for (i = 0; i < sizeof(in->prod_bitmask) * 8; i++) {
  95. if (in->prod_bitmask & (1 << i)) {
  96. if (in->cons_bitmask[i] == 0) {
  97. IPAHAL_ERR("no cons bitmask for prod %d\n", i);
  98. return NULL;
  99. }
  100. entries += _count_ones(in->cons_bitmask[i]);
  101. }
  102. }
  103. IPAHAL_DBG_LOW("sum all entries = %d\n", entries);
  104. pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) +
  105. hdr_entries * sizeof(struct ipahal_stats_tethering_hdr_hw) +
  106. entries * sizeof(struct ipahal_stats_tethering_hw),
  107. is_atomic_ctx);
  108. if (!pyld)
  109. return NULL;
  110. pyld->len = hdr_entries * sizeof(struct ipahal_stats_tethering_hdr_hw) +
  111. entries * sizeof(struct ipahal_stats_tethering_hw);
  112. pyld_ptr = pyld->data;
  113. incremental_offset =
  114. (hdr_entries * sizeof(struct ipahal_stats_tethering_hdr_hw))
  115. / 8;
  116. for (i = 0; i < sizeof(in->prod_bitmask) * 8; i++) {
  117. if (in->prod_bitmask & (1 << i)) {
  118. struct ipahal_stats_tethering_hdr_hw *hdr = pyld_ptr;
  119. hdr->dst_mask = in->cons_bitmask[i];
  120. hdr->offset = incremental_offset;
  121. IPAHAL_DBG_LOW("hdr->dst_mask=0x%x\n", hdr->dst_mask);
  122. IPAHAL_DBG_LOW("hdr->offset=0x%x\n", hdr->offset);
  123. /* add the stats entry */
  124. incremental_offset += _count_ones(in->cons_bitmask[i]) *
  125. sizeof(struct ipahal_stats_tethering_hw) / 8;
  126. pyld_ptr += sizeof(*hdr);
  127. }
  128. }
  129. return pyld;
  130. }
  131. static int ipahal_get_offset_tethering(void *params,
  132. struct ipahal_stats_offset *out)
  133. {
  134. struct ipahal_stats_get_offset_tethering *in =
  135. (struct ipahal_stats_get_offset_tethering *)params;
  136. int entries = 0;
  137. int i;
  138. for (i = 0; i < sizeof(in->init.prod_bitmask) * 8; i++) {
  139. if (in->init.prod_bitmask & (1 << i)) {
  140. if (in->init.cons_bitmask[i] == 0) {
  141. IPAHAL_ERR("no cons bitmask for prod %d\n", i);
  142. return -EPERM;
  143. }
  144. entries += _count_ones(in->init.cons_bitmask[i]);
  145. }
  146. }
  147. IPAHAL_DBG_LOW("sum all entries = %d\n", entries);
  148. /* skip the header */
  149. out->offset = _count_ones(in->init.prod_bitmask) *
  150. sizeof(struct ipahal_stats_tethering_hdr_hw);
  151. out->size = entries * sizeof(struct ipahal_stats_tethering_hw);
  152. return 0;
  153. }
  154. static int ipahal_parse_stats_tethering(void *init_params, void *raw_stats,
  155. void *parsed_stats)
  156. {
  157. struct ipahal_stats_init_tethering *init =
  158. (struct ipahal_stats_init_tethering *)init_params;
  159. struct ipahal_stats_tethering_hw *raw_hw =
  160. (struct ipahal_stats_tethering_hw *)raw_stats;
  161. struct ipahal_stats_tethering_all *out =
  162. (struct ipahal_stats_tethering_all *)parsed_stats;
  163. int i, j;
  164. int stat_idx = 0;
  165. memset(out, 0, sizeof(*out));
  166. IPAHAL_DBG_LOW("\n");
  167. for (i = 0; i < IPAHAL_MAX_PIPES; i++) {
  168. for (j = 0; j < IPAHAL_MAX_PIPES; j++) {
  169. if ((init->prod_bitmask & (1 << i)) &&
  170. init->cons_bitmask[i] & (1 << j)) {
  171. IPAHAL_DBG_LOW("prod %d cons %d\n", i, j);
  172. IPAHAL_DBG_LOW("stat_idx %d\n", stat_idx);
  173. out->stats[i][j].num_ipv4_bytes =
  174. raw_hw[stat_idx].num_ipv4_bytes;
  175. IPAHAL_DBG_LOW("num_ipv4_bytes %lld\n",
  176. out->stats[i][j].num_ipv4_bytes);
  177. out->stats[i][j].num_ipv4_pkts =
  178. raw_hw[stat_idx].num_ipv4_pkts;
  179. IPAHAL_DBG_LOW("num_ipv4_pkts %lld\n",
  180. out->stats[i][j].num_ipv4_pkts);
  181. out->stats[i][j].num_ipv6_pkts =
  182. raw_hw[stat_idx].num_ipv6_pkts;
  183. IPAHAL_DBG_LOW("num_ipv6_pkts %lld\n",
  184. out->stats[i][j].num_ipv6_pkts);
  185. out->stats[i][j].num_ipv6_bytes =
  186. raw_hw[stat_idx].num_ipv6_bytes;
  187. IPAHAL_DBG_LOW("num_ipv6_bytes %lld\n",
  188. out->stats[i][j].num_ipv6_bytes);
  189. stat_idx++;
  190. }
  191. }
  192. }
  193. return 0;
  194. }
  195. static struct ipahal_stats_init_pyld *ipahal_generate_init_pyld_flt_rt_v4_5(
  196. void *params, bool is_atomic_ctx)
  197. {
  198. struct ipahal_stats_init_pyld *pyld;
  199. int num = (int)(params);
  200. if (num > IPA_MAX_FLT_RT_CNT_INDEX ||
  201. num <= 0) {
  202. IPAHAL_ERR("num %d not valid\n", num);
  203. return NULL;
  204. }
  205. pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) +
  206. num *
  207. sizeof(struct ipahal_stats_flt_rt_v4_5_hw),
  208. is_atomic_ctx);
  209. if (!pyld)
  210. return NULL;
  211. pyld->len = num *
  212. sizeof(struct ipahal_stats_flt_rt_v4_5_hw);
  213. return pyld;
  214. }
  215. static int ipahal_get_offset_flt_rt_v4_5(void *params,
  216. struct ipahal_stats_offset *out)
  217. {
  218. struct ipahal_stats_get_offset_flt_rt_v4_5 *in =
  219. (struct ipahal_stats_get_offset_flt_rt_v4_5 *)params;
  220. int num;
  221. out->offset = (in->start_id - 1) *
  222. sizeof(struct ipahal_stats_flt_rt_v4_5);
  223. num = in->end_id - in->start_id + 1;
  224. out->size = num * sizeof(struct ipahal_stats_flt_rt_v4_5);
  225. return 0;
  226. }
  227. static int ipahal_parse_stats_flt_rt_v4_5(void *init_params,
  228. void *raw_stats, void *parsed_stats)
  229. {
  230. struct ipahal_stats_flt_rt_v4_5_hw *raw_hw =
  231. (struct ipahal_stats_flt_rt_v4_5_hw *)raw_stats;
  232. struct ipa_ioc_flt_rt_query *query =
  233. (struct ipa_ioc_flt_rt_query *)parsed_stats;
  234. int num, i;
  235. num = query->end_id - query->start_id + 1;
  236. IPAHAL_DBG_LOW("\n");
  237. for (i = 0; i < num; i++) {
  238. ((struct ipa_flt_rt_stats *)
  239. query->stats)[i].num_bytes =
  240. raw_hw[i].num_bytes;
  241. ((struct ipa_flt_rt_stats *)
  242. query->stats)[i].num_pkts_hash =
  243. raw_hw[i].num_packets_hash;
  244. ((struct ipa_flt_rt_stats *)
  245. query->stats)[i].num_pkts =
  246. raw_hw[i].num_packets;
  247. }
  248. return 0;
  249. }
  250. static struct ipahal_stats_init_pyld *ipahal_generate_init_pyld_flt_rt(
  251. void *params, bool is_atomic_ctx)
  252. {
  253. struct ipahal_stats_init_pyld *pyld;
  254. struct ipahal_stats_init_flt_rt *in =
  255. (struct ipahal_stats_init_flt_rt *)params;
  256. int hdr_entries;
  257. int num_rules = 0;
  258. int i, start_entry;
  259. void *pyld_ptr;
  260. u32 incremental_offset;
  261. for (i = 0; i < IPAHAL_MAX_RULE_ID_32; i++)
  262. num_rules += _count_ones(in->rule_id_bitmask[i]);
  263. if (num_rules == 0) {
  264. IPAHAL_ERR("no rule ids provided\n");
  265. return NULL;
  266. }
  267. IPAHAL_DBG_LOW("num_rules = %d\n", num_rules);
  268. hdr_entries = IPAHAL_MAX_RULE_ID_32;
  269. for (i = 0; i < IPAHAL_MAX_RULE_ID_32; i++) {
  270. if (in->rule_id_bitmask[i] != 0)
  271. break;
  272. hdr_entries--;
  273. }
  274. start_entry = i;
  275. for (i = IPAHAL_MAX_RULE_ID_32 - 1; i >= start_entry; i--) {
  276. if (in->rule_id_bitmask[i] != 0)
  277. break;
  278. hdr_entries--;
  279. }
  280. IPAHAL_DBG_LOW("hdr_entries = %d\n", hdr_entries);
  281. pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) +
  282. hdr_entries * sizeof(struct ipahal_stats_flt_rt_hdr_hw) +
  283. num_rules * sizeof(struct ipahal_stats_flt_rt_hw),
  284. is_atomic_ctx);
  285. if (!pyld) {
  286. IPAHAL_ERR("no mem\n");
  287. return NULL;
  288. }
  289. pyld->len = hdr_entries * sizeof(struct ipahal_stats_flt_rt_hdr_hw) +
  290. num_rules * sizeof(struct ipahal_stats_flt_rt_hw);
  291. pyld_ptr = pyld->data;
  292. incremental_offset =
  293. (hdr_entries * sizeof(struct ipahal_stats_flt_rt_hdr_hw))
  294. / 8;
  295. for (i = start_entry; i < hdr_entries; i++) {
  296. struct ipahal_stats_flt_rt_hdr_hw *hdr = pyld_ptr;
  297. hdr->en_mask = in->rule_id_bitmask[i];
  298. hdr->cnt_offset = incremental_offset;
  299. /* add the stats entry */
  300. incremental_offset += _count_ones(in->rule_id_bitmask[i]) *
  301. sizeof(struct ipahal_stats_flt_rt_hw) / 8;
  302. pyld_ptr += sizeof(*hdr);
  303. }
  304. return pyld;
  305. }
  306. static int ipahal_get_offset_flt_rt(void *params,
  307. struct ipahal_stats_offset *out)
  308. {
  309. struct ipahal_stats_get_offset_flt_rt *in =
  310. (struct ipahal_stats_get_offset_flt_rt *)params;
  311. int i;
  312. int hdr_entries;
  313. int skip_rules = 0;
  314. int start_entry;
  315. int rule_bit = in->rule_id % 32;
  316. int rule_idx = in->rule_id / 32;
  317. if (rule_idx >= IPAHAL_MAX_RULE_ID_32) {
  318. IPAHAL_ERR("invalid rule_id %d\n", in->rule_id);
  319. return -EPERM;
  320. }
  321. hdr_entries = IPAHAL_MAX_RULE_ID_32;
  322. for (i = 0; i < IPAHAL_MAX_RULE_ID_32; i++) {
  323. if (in->init.rule_id_bitmask[i] != 0)
  324. break;
  325. hdr_entries--;
  326. }
  327. if (hdr_entries == 0) {
  328. IPAHAL_ERR("no rule ids provided\n");
  329. return -EPERM;
  330. }
  331. start_entry = i;
  332. for (i = IPAHAL_MAX_RULE_ID_32 - 1; i >= 0; i--) {
  333. if (in->init.rule_id_bitmask[i] != 0)
  334. break;
  335. hdr_entries--;
  336. }
  337. IPAHAL_DBG_LOW("hdr_entries = %d\n", hdr_entries);
  338. /* skip the header */
  339. out->offset = hdr_entries * sizeof(struct ipahal_stats_flt_rt_hdr_hw);
  340. /* skip the previous rules */
  341. for (i = start_entry; i < rule_idx; i++)
  342. skip_rules += _count_ones(in->init.rule_id_bitmask[i]);
  343. for (i = 0; i < rule_bit; i++)
  344. if (in->init.rule_id_bitmask[rule_idx] & (1 << i))
  345. skip_rules++;
  346. out->offset += skip_rules * sizeof(struct ipahal_stats_flt_rt_hw);
  347. out->size = sizeof(struct ipahal_stats_flt_rt_hw);
  348. return 0;
  349. }
  350. static int ipahal_parse_stats_flt_rt(void *init_params, void *raw_stats,
  351. void *parsed_stats)
  352. {
  353. struct ipahal_stats_flt_rt_hw *raw_hw =
  354. (struct ipahal_stats_flt_rt_hw *)raw_stats;
  355. struct ipahal_stats_flt_rt *out =
  356. (struct ipahal_stats_flt_rt *)parsed_stats;
  357. memset(out, 0, sizeof(*out));
  358. IPAHAL_DBG_LOW("\n");
  359. out->num_packets = raw_hw->num_packets;
  360. out->num_packets_hash = raw_hw->num_packets_hash;
  361. return 0;
  362. }
  363. static struct ipahal_stats_init_pyld *ipahal_generate_init_pyld_drop(
  364. void *params, bool is_atomic_ctx)
  365. {
  366. struct ipahal_stats_init_pyld *pyld;
  367. struct ipahal_stats_init_drop *in =
  368. (struct ipahal_stats_init_drop *)params;
  369. int entries = _count_ones(in->enabled_bitmask);
  370. IPAHAL_DBG_LOW("entries = %d\n", entries);
  371. pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) +
  372. entries * sizeof(struct ipahal_stats_drop_hw), is_atomic_ctx);
  373. if (!pyld)
  374. return NULL;
  375. pyld->len = entries * sizeof(struct ipahal_stats_drop_hw);
  376. return pyld;
  377. }
  378. static int ipahal_get_offset_drop(void *params,
  379. struct ipahal_stats_offset *out)
  380. {
  381. struct ipahal_stats_get_offset_drop *in =
  382. (struct ipahal_stats_get_offset_drop *)params;
  383. int entries = _count_ones(in->init.enabled_bitmask);
  384. IPAHAL_DBG_LOW("\n");
  385. out->offset = 0;
  386. out->size = entries * sizeof(struct ipahal_stats_drop_hw);
  387. return 0;
  388. }
  389. static int ipahal_parse_stats_drop(void *init_params, void *raw_stats,
  390. void *parsed_stats)
  391. {
  392. struct ipahal_stats_init_drop *init =
  393. (struct ipahal_stats_init_drop *)init_params;
  394. struct ipahal_stats_drop_hw *raw_hw =
  395. (struct ipahal_stats_drop_hw *)raw_stats;
  396. struct ipahal_stats_drop_all *out =
  397. (struct ipahal_stats_drop_all *)parsed_stats;
  398. int stat_idx = 0;
  399. int i;
  400. memset(out, 0, sizeof(*out));
  401. IPAHAL_DBG_LOW("\n");
  402. for (i = 0; i < IPAHAL_MAX_PIPES; i++) {
  403. if (init->enabled_bitmask & (1 << i)) {
  404. out->stats[i].drop_byte_cnt =
  405. raw_hw[stat_idx].drop_byte_cnt;
  406. out->stats[i].drop_packet_cnt =
  407. raw_hw[stat_idx].drop_packet_cnt;
  408. stat_idx++;
  409. }
  410. }
  411. return 0;
  412. }
  413. static struct ipahal_hw_stats_obj
  414. ipahal_hw_stats_objs[IPA_HW_MAX][IPAHAL_HW_STATS_MAX] = {
  415. /* IPAv4 */
  416. [IPA_HW_v4_0][IPAHAL_HW_STATS_QUOTA] = {
  417. ipahal_generate_init_pyld_quota,
  418. ipahal_get_offset_quota,
  419. ipahal_parse_stats_quota
  420. },
  421. [IPA_HW_v4_0][IPAHAL_HW_STATS_TETHERING] = {
  422. ipahal_generate_init_pyld_tethering,
  423. ipahal_get_offset_tethering,
  424. ipahal_parse_stats_tethering
  425. },
  426. [IPA_HW_v4_0][IPAHAL_HW_STATS_FNR] = {
  427. ipahal_generate_init_pyld_flt_rt,
  428. ipahal_get_offset_flt_rt,
  429. ipahal_parse_stats_flt_rt
  430. },
  431. [IPA_HW_v4_0][IPAHAL_HW_STATS_DROP] = {
  432. ipahal_generate_init_pyld_drop,
  433. ipahal_get_offset_drop,
  434. ipahal_parse_stats_drop
  435. },
  436. [IPA_HW_v4_5][IPAHAL_HW_STATS_QUOTA] = {
  437. ipahal_generate_init_pyld_quota,
  438. ipahal_get_offset_quota,
  439. ipahal_parse_stats_quota
  440. },
  441. [IPA_HW_v4_5][IPAHAL_HW_STATS_FNR] = {
  442. ipahal_generate_init_pyld_flt_rt_v4_5,
  443. ipahal_get_offset_flt_rt_v4_5,
  444. ipahal_parse_stats_flt_rt_v4_5
  445. },
  446. [IPA_HW_v4_5][IPAHAL_HW_STATS_TETHERING] = {
  447. ipahal_generate_init_pyld_tethering,
  448. ipahal_get_offset_tethering,
  449. ipahal_parse_stats_tethering
  450. },
  451. [IPA_HW_v4_5][IPAHAL_HW_STATS_DROP] = {
  452. ipahal_generate_init_pyld_drop,
  453. ipahal_get_offset_drop,
  454. ipahal_parse_stats_drop
  455. },
  456. };
  457. int ipahal_hw_stats_init(enum ipa_hw_type ipa_hw_type)
  458. {
  459. int i;
  460. int j;
  461. struct ipahal_hw_stats_obj zero_obj;
  462. struct ipahal_hw_stats_obj *hw_stat_ptr;
  463. IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
  464. if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
  465. IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
  466. return -EINVAL;
  467. }
  468. memset(&zero_obj, 0, sizeof(zero_obj));
  469. for (i = IPA_HW_v4_0 ; i < ipa_hw_type ; i++) {
  470. for (j = 0; j < IPAHAL_HW_STATS_MAX; j++) {
  471. if (!memcmp(&ipahal_hw_stats_objs[i + 1][j], &zero_obj,
  472. sizeof(struct ipahal_hw_stats_obj))) {
  473. memcpy(&ipahal_hw_stats_objs[i + 1][j],
  474. &ipahal_hw_stats_objs[i][j],
  475. sizeof(struct ipahal_hw_stats_obj));
  476. } else {
  477. /*
  478. * explicitly overridden stat.
  479. * Check validity
  480. */
  481. hw_stat_ptr = &ipahal_hw_stats_objs[i + 1][j];
  482. if (!hw_stat_ptr->get_offset) {
  483. IPAHAL_ERR(
  484. "stat=%d get_offset null ver=%d\n",
  485. j, i+1);
  486. WARN_ON(1);
  487. }
  488. if (!hw_stat_ptr->parse_stats) {
  489. IPAHAL_ERR(
  490. "stat=%d parse_stats null ver=%d\n",
  491. j, i + 1);
  492. WARN_ON(1);
  493. }
  494. }
  495. }
  496. }
  497. return 0;
  498. }
  499. int ipahal_stats_get_offset(enum ipahal_hw_stats_type type, void *params,
  500. struct ipahal_stats_offset *out)
  501. {
  502. if (type < 0 || type >= IPAHAL_HW_STATS_MAX) {
  503. IPAHAL_ERR("Invalid type stat=%d\n", type);
  504. WARN_ON(1);
  505. return -EFAULT;
  506. }
  507. if (!params || !out) {
  508. IPAHAL_ERR("Null arg\n");
  509. WARN_ON(1);
  510. return -EFAULT;
  511. }
  512. return ipahal_hw_stats_objs[ipahal_ctx->hw_type][type].get_offset(
  513. params, out);
  514. }
  515. struct ipahal_stats_init_pyld *ipahal_stats_generate_init_pyld(
  516. enum ipahal_hw_stats_type type, void *params, bool is_atomic_ctx)
  517. {
  518. struct ipahal_hw_stats_obj *hw_obj_ptr;
  519. if (type < 0 || type >= IPAHAL_HW_STATS_MAX) {
  520. IPAHAL_ERR("Invalid type stat=%d\n", type);
  521. WARN_ON(1);
  522. return NULL;
  523. }
  524. hw_obj_ptr = &ipahal_hw_stats_objs[ipahal_ctx->hw_type][type];
  525. return hw_obj_ptr->generate_init_pyld(params, is_atomic_ctx);
  526. }
  527. int ipahal_parse_stats(enum ipahal_hw_stats_type type, void *init_params,
  528. void *raw_stats, void *parsed_stats)
  529. {
  530. if (WARN((type < 0 || type >= IPAHAL_HW_STATS_MAX),
  531. "Invalid type stat = %d\n", type))
  532. return -EFAULT;
  533. if (WARN((!raw_stats || !parsed_stats), "Null arg\n"))
  534. return -EFAULT;
  535. return ipahal_hw_stats_objs[ipahal_ctx->hw_type][type].parse_stats(
  536. init_params, raw_stats, parsed_stats);
  537. }
  538. void ipahal_set_flt_rt_sw_stats(void *raw_stats,
  539. struct ipa_flt_rt_stats sw_stats)
  540. {
  541. struct ipahal_stats_flt_rt_v4_5_hw *raw_hw =
  542. (struct ipahal_stats_flt_rt_v4_5_hw *)raw_stats;
  543. IPAHAL_DBG_LOW("\n");
  544. raw_hw->num_bytes = sw_stats.num_bytes;
  545. raw_hw->num_packets_hash = sw_stats.num_pkts_hash;
  546. raw_hw->num_packets = sw_stats.num_pkts;
  547. }