ice_sched.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (c) 2018, Intel Corporation. */
  3. #include "ice_sched.h"
  4. /**
  5. * ice_sched_add_root_node - Insert the Tx scheduler root node in SW DB
  6. * @pi: port information structure
  7. * @info: Scheduler element information from firmware
  8. *
  9. * This function inserts the root node of the scheduling tree topology
  10. * to the SW DB.
  11. */
  12. static enum ice_status
  13. ice_sched_add_root_node(struct ice_port_info *pi,
  14. struct ice_aqc_txsched_elem_data *info)
  15. {
  16. struct ice_sched_node *root;
  17. struct ice_hw *hw;
  18. u16 max_children;
  19. if (!pi)
  20. return ICE_ERR_PARAM;
  21. hw = pi->hw;
  22. root = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*root), GFP_KERNEL);
  23. if (!root)
  24. return ICE_ERR_NO_MEMORY;
  25. max_children = le16_to_cpu(hw->layer_info[0].max_children);
  26. root->children = devm_kcalloc(ice_hw_to_dev(hw), max_children,
  27. sizeof(*root), GFP_KERNEL);
  28. if (!root->children) {
  29. devm_kfree(ice_hw_to_dev(hw), root);
  30. return ICE_ERR_NO_MEMORY;
  31. }
  32. memcpy(&root->info, info, sizeof(*info));
  33. pi->root = root;
  34. return 0;
  35. }
  36. /**
  37. * ice_sched_find_node_by_teid - Find the Tx scheduler node in SW DB
  38. * @start_node: pointer to the starting ice_sched_node struct in a sub-tree
  39. * @teid: node teid to search
  40. *
  41. * This function searches for a node matching the teid in the scheduling tree
  42. * from the SW DB. The search is recursive and is restricted by the number of
  43. * layers it has searched through; stopping at the max supported layer.
  44. *
  45. * This function needs to be called when holding the port_info->sched_lock
  46. */
  47. struct ice_sched_node *
  48. ice_sched_find_node_by_teid(struct ice_sched_node *start_node, u32 teid)
  49. {
  50. u16 i;
  51. /* The TEID is same as that of the start_node */
  52. if (ICE_TXSCHED_GET_NODE_TEID(start_node) == teid)
  53. return start_node;
  54. /* The node has no children or is at the max layer */
  55. if (!start_node->num_children ||
  56. start_node->tx_sched_layer >= ICE_AQC_TOPO_MAX_LEVEL_NUM ||
  57. start_node->info.data.elem_type == ICE_AQC_ELEM_TYPE_LEAF)
  58. return NULL;
  59. /* Check if teid matches to any of the children nodes */
  60. for (i = 0; i < start_node->num_children; i++)
  61. if (ICE_TXSCHED_GET_NODE_TEID(start_node->children[i]) == teid)
  62. return start_node->children[i];
  63. /* Search within each child's sub-tree */
  64. for (i = 0; i < start_node->num_children; i++) {
  65. struct ice_sched_node *tmp;
  66. tmp = ice_sched_find_node_by_teid(start_node->children[i],
  67. teid);
  68. if (tmp)
  69. return tmp;
  70. }
  71. return NULL;
  72. }
  73. /**
  74. * ice_sched_add_node - Insert the Tx scheduler node in SW DB
  75. * @pi: port information structure
  76. * @layer: Scheduler layer of the node
  77. * @info: Scheduler element information from firmware
  78. *
  79. * This function inserts a scheduler node to the SW DB.
  80. */
  81. enum ice_status
  82. ice_sched_add_node(struct ice_port_info *pi, u8 layer,
  83. struct ice_aqc_txsched_elem_data *info)
  84. {
  85. struct ice_sched_node *parent;
  86. struct ice_sched_node *node;
  87. struct ice_hw *hw;
  88. u16 max_children;
  89. if (!pi)
  90. return ICE_ERR_PARAM;
  91. hw = pi->hw;
  92. /* A valid parent node should be there */
  93. parent = ice_sched_find_node_by_teid(pi->root,
  94. le32_to_cpu(info->parent_teid));
  95. if (!parent) {
  96. ice_debug(hw, ICE_DBG_SCHED,
  97. "Parent Node not found for parent_teid=0x%x\n",
  98. le32_to_cpu(info->parent_teid));
  99. return ICE_ERR_PARAM;
  100. }
  101. node = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*node), GFP_KERNEL);
  102. if (!node)
  103. return ICE_ERR_NO_MEMORY;
  104. max_children = le16_to_cpu(hw->layer_info[layer].max_children);
  105. if (max_children) {
  106. node->children = devm_kcalloc(ice_hw_to_dev(hw), max_children,
  107. sizeof(*node), GFP_KERNEL);
  108. if (!node->children) {
  109. devm_kfree(ice_hw_to_dev(hw), node);
  110. return ICE_ERR_NO_MEMORY;
  111. }
  112. }
  113. node->in_use = true;
  114. node->parent = parent;
  115. node->tx_sched_layer = layer;
  116. parent->children[parent->num_children++] = node;
  117. memcpy(&node->info, info, sizeof(*info));
  118. return 0;
  119. }
  120. /**
  121. * ice_aq_delete_sched_elems - delete scheduler elements
  122. * @hw: pointer to the hw struct
  123. * @grps_req: number of groups to delete
  124. * @buf: pointer to buffer
  125. * @buf_size: buffer size in bytes
  126. * @grps_del: returns total number of elements deleted
  127. * @cd: pointer to command details structure or NULL
  128. *
  129. * Delete scheduling elements (0x040F)
  130. */
  131. static enum ice_status
  132. ice_aq_delete_sched_elems(struct ice_hw *hw, u16 grps_req,
  133. struct ice_aqc_delete_elem *buf, u16 buf_size,
  134. u16 *grps_del, struct ice_sq_cd *cd)
  135. {
  136. struct ice_aqc_add_move_delete_elem *cmd;
  137. struct ice_aq_desc desc;
  138. enum ice_status status;
  139. cmd = &desc.params.add_move_delete_elem;
  140. ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_delete_sched_elems);
  141. desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
  142. cmd->num_grps_req = cpu_to_le16(grps_req);
  143. status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
  144. if (!status && grps_del)
  145. *grps_del = le16_to_cpu(cmd->num_grps_updated);
  146. return status;
  147. }
  148. /**
  149. * ice_sched_remove_elems - remove nodes from hw
  150. * @hw: pointer to the hw struct
  151. * @parent: pointer to the parent node
  152. * @num_nodes: number of nodes
  153. * @node_teids: array of node teids to be deleted
  154. *
  155. * This function remove nodes from hw
  156. */
  157. static enum ice_status
  158. ice_sched_remove_elems(struct ice_hw *hw, struct ice_sched_node *parent,
  159. u16 num_nodes, u32 *node_teids)
  160. {
  161. struct ice_aqc_delete_elem *buf;
  162. u16 i, num_groups_removed = 0;
  163. enum ice_status status;
  164. u16 buf_size;
  165. buf_size = sizeof(*buf) + sizeof(u32) * (num_nodes - 1);
  166. buf = devm_kzalloc(ice_hw_to_dev(hw), buf_size, GFP_KERNEL);
  167. if (!buf)
  168. return ICE_ERR_NO_MEMORY;
  169. buf->hdr.parent_teid = parent->info.node_teid;
  170. buf->hdr.num_elems = cpu_to_le16(num_nodes);
  171. for (i = 0; i < num_nodes; i++)
  172. buf->teid[i] = cpu_to_le32(node_teids[i]);
  173. status = ice_aq_delete_sched_elems(hw, 1, buf, buf_size,
  174. &num_groups_removed, NULL);
  175. if (status || num_groups_removed != 1)
  176. ice_debug(hw, ICE_DBG_SCHED, "remove elements failed\n");
  177. devm_kfree(ice_hw_to_dev(hw), buf);
  178. return status;
  179. }
  180. /**
  181. * ice_sched_get_first_node - get the first node of the given layer
  182. * @hw: pointer to the hw struct
  183. * @parent: pointer the base node of the subtree
  184. * @layer: layer number
  185. *
  186. * This function retrieves the first node of the given layer from the subtree
  187. */
  188. static struct ice_sched_node *
  189. ice_sched_get_first_node(struct ice_hw *hw, struct ice_sched_node *parent,
  190. u8 layer)
  191. {
  192. u8 i;
  193. if (layer < hw->sw_entry_point_layer)
  194. return NULL;
  195. for (i = 0; i < parent->num_children; i++) {
  196. struct ice_sched_node *node = parent->children[i];
  197. if (node) {
  198. if (node->tx_sched_layer == layer)
  199. return node;
  200. /* this recursion is intentional, and wouldn't
  201. * go more than 9 calls
  202. */
  203. return ice_sched_get_first_node(hw, node, layer);
  204. }
  205. }
  206. return NULL;
  207. }
  208. /**
  209. * ice_sched_get_tc_node - get pointer to TC node
  210. * @pi: port information structure
  211. * @tc: TC number
  212. *
  213. * This function returns the TC node pointer
  214. */
  215. struct ice_sched_node *ice_sched_get_tc_node(struct ice_port_info *pi, u8 tc)
  216. {
  217. u8 i;
  218. if (!pi)
  219. return NULL;
  220. for (i = 0; i < pi->root->num_children; i++)
  221. if (pi->root->children[i]->tc_num == tc)
  222. return pi->root->children[i];
  223. return NULL;
  224. }
  225. /**
  226. * ice_free_sched_node - Free a Tx scheduler node from SW DB
  227. * @pi: port information structure
  228. * @node: pointer to the ice_sched_node struct
  229. *
  230. * This function frees up a node from SW DB as well as from HW
  231. *
  232. * This function needs to be called with the port_info->sched_lock held
  233. */
  234. void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)
  235. {
  236. struct ice_sched_node *parent;
  237. struct ice_hw *hw = pi->hw;
  238. u8 i, j;
  239. /* Free the children before freeing up the parent node
  240. * The parent array is updated below and that shifts the nodes
  241. * in the array. So always pick the first child if num children > 0
  242. */
  243. while (node->num_children)
  244. ice_free_sched_node(pi, node->children[0]);
  245. /* Leaf, TC and root nodes can't be deleted by SW */
  246. if (node->tx_sched_layer >= hw->sw_entry_point_layer &&
  247. node->info.data.elem_type != ICE_AQC_ELEM_TYPE_TC &&
  248. node->info.data.elem_type != ICE_AQC_ELEM_TYPE_ROOT_PORT &&
  249. node->info.data.elem_type != ICE_AQC_ELEM_TYPE_LEAF) {
  250. u32 teid = le32_to_cpu(node->info.node_teid);
  251. enum ice_status status;
  252. status = ice_sched_remove_elems(hw, node->parent, 1, &teid);
  253. if (status)
  254. ice_debug(hw, ICE_DBG_SCHED,
  255. "remove element failed %d\n", status);
  256. }
  257. parent = node->parent;
  258. /* root has no parent */
  259. if (parent) {
  260. struct ice_sched_node *p, *tc_node;
  261. /* update the parent */
  262. for (i = 0; i < parent->num_children; i++)
  263. if (parent->children[i] == node) {
  264. for (j = i + 1; j < parent->num_children; j++)
  265. parent->children[j - 1] =
  266. parent->children[j];
  267. parent->num_children--;
  268. break;
  269. }
  270. /* search for previous sibling that points to this node and
  271. * remove the reference
  272. */
  273. tc_node = ice_sched_get_tc_node(pi, node->tc_num);
  274. if (!tc_node) {
  275. ice_debug(hw, ICE_DBG_SCHED,
  276. "Invalid TC number %d\n", node->tc_num);
  277. goto err_exit;
  278. }
  279. p = ice_sched_get_first_node(hw, tc_node, node->tx_sched_layer);
  280. while (p) {
  281. if (p->sibling == node) {
  282. p->sibling = node->sibling;
  283. break;
  284. }
  285. p = p->sibling;
  286. }
  287. }
  288. err_exit:
  289. /* leaf nodes have no children */
  290. if (node->children)
  291. devm_kfree(ice_hw_to_dev(hw), node->children);
  292. devm_kfree(ice_hw_to_dev(hw), node);
  293. }
  294. /**
  295. * ice_aq_get_dflt_topo - gets default scheduler topology
  296. * @hw: pointer to the hw struct
  297. * @lport: logical port number
  298. * @buf: pointer to buffer
  299. * @buf_size: buffer size in bytes
  300. * @num_branches: returns total number of queue to port branches
  301. * @cd: pointer to command details structure or NULL
  302. *
  303. * Get default scheduler topology (0x400)
  304. */
  305. static enum ice_status
  306. ice_aq_get_dflt_topo(struct ice_hw *hw, u8 lport,
  307. struct ice_aqc_get_topo_elem *buf, u16 buf_size,
  308. u8 *num_branches, struct ice_sq_cd *cd)
  309. {
  310. struct ice_aqc_get_topo *cmd;
  311. struct ice_aq_desc desc;
  312. enum ice_status status;
  313. cmd = &desc.params.get_topo;
  314. ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_dflt_topo);
  315. cmd->port_num = lport;
  316. status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
  317. if (!status && num_branches)
  318. *num_branches = cmd->num_branches;
  319. return status;
  320. }
  321. /**
  322. * ice_aq_query_sched_res - query scheduler resource
  323. * @hw: pointer to the hw struct
  324. * @buf_size: buffer size in bytes
  325. * @buf: pointer to buffer
  326. * @cd: pointer to command details structure or NULL
  327. *
  328. * Query scheduler resource allocation (0x0412)
  329. */
  330. static enum ice_status
  331. ice_aq_query_sched_res(struct ice_hw *hw, u16 buf_size,
  332. struct ice_aqc_query_txsched_res_resp *buf,
  333. struct ice_sq_cd *cd)
  334. {
  335. struct ice_aq_desc desc;
  336. ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_query_sched_res);
  337. return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
  338. }
  339. /**
  340. * ice_sched_clear_tx_topo - clears the schduler tree nodes
  341. * @pi: port information structure
  342. *
  343. * This function removes all the nodes from HW as well as from SW DB.
  344. */
  345. static void ice_sched_clear_tx_topo(struct ice_port_info *pi)
  346. {
  347. struct ice_sched_agg_info *agg_info;
  348. struct ice_sched_vsi_info *vsi_elem;
  349. struct ice_sched_agg_info *atmp;
  350. struct ice_sched_vsi_info *tmp;
  351. struct ice_hw *hw;
  352. if (!pi)
  353. return;
  354. hw = pi->hw;
  355. list_for_each_entry_safe(agg_info, atmp, &pi->agg_list, list_entry) {
  356. struct ice_sched_agg_vsi_info *agg_vsi_info;
  357. struct ice_sched_agg_vsi_info *vtmp;
  358. list_for_each_entry_safe(agg_vsi_info, vtmp,
  359. &agg_info->agg_vsi_list, list_entry) {
  360. list_del(&agg_vsi_info->list_entry);
  361. devm_kfree(ice_hw_to_dev(hw), agg_vsi_info);
  362. }
  363. }
  364. /* remove the vsi list */
  365. list_for_each_entry_safe(vsi_elem, tmp, &pi->vsi_info_list,
  366. list_entry) {
  367. list_del(&vsi_elem->list_entry);
  368. devm_kfree(ice_hw_to_dev(hw), vsi_elem);
  369. }
  370. if (pi->root) {
  371. ice_free_sched_node(pi, pi->root);
  372. pi->root = NULL;
  373. }
  374. }
  375. /**
  376. * ice_sched_clear_port - clear the scheduler elements from SW DB for a port
  377. * @pi: port information structure
  378. *
  379. * Cleanup scheduling elements from SW DB
  380. */
  381. static void ice_sched_clear_port(struct ice_port_info *pi)
  382. {
  383. if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
  384. return;
  385. pi->port_state = ICE_SCHED_PORT_STATE_INIT;
  386. mutex_lock(&pi->sched_lock);
  387. ice_sched_clear_tx_topo(pi);
  388. mutex_unlock(&pi->sched_lock);
  389. mutex_destroy(&pi->sched_lock);
  390. }
  391. /**
  392. * ice_sched_cleanup_all - cleanup scheduler elements from SW DB for all ports
  393. * @hw: pointer to the hw struct
  394. *
  395. * Cleanup scheduling elements from SW DB for all the ports
  396. */
  397. void ice_sched_cleanup_all(struct ice_hw *hw)
  398. {
  399. if (!hw || !hw->port_info)
  400. return;
  401. if (hw->layer_info)
  402. devm_kfree(ice_hw_to_dev(hw), hw->layer_info);
  403. ice_sched_clear_port(hw->port_info);
  404. hw->num_tx_sched_layers = 0;
  405. hw->num_tx_sched_phys_layers = 0;
  406. hw->flattened_layers = 0;
  407. hw->max_cgds = 0;
  408. }
  409. /**
  410. * ice_sched_get_qgrp_layer - get the current queue group layer number
  411. * @hw: pointer to the hw struct
  412. *
  413. * This function returns the current queue group layer number
  414. */
  415. static u8 ice_sched_get_qgrp_layer(struct ice_hw *hw)
  416. {
  417. /* It's always total layers - 1, the array is 0 relative so -2 */
  418. return hw->num_tx_sched_layers - ICE_QGRP_LAYER_OFFSET;
  419. }
  420. /**
  421. * ice_rm_dflt_leaf_node - remove the default leaf node in the tree
  422. * @pi: port information structure
  423. *
  424. * This function removes the leaf node that was created by the FW
  425. * during initialization
  426. */
  427. static void
  428. ice_rm_dflt_leaf_node(struct ice_port_info *pi)
  429. {
  430. struct ice_sched_node *node;
  431. node = pi->root;
  432. while (node) {
  433. if (!node->num_children)
  434. break;
  435. node = node->children[0];
  436. }
  437. if (node && node->info.data.elem_type == ICE_AQC_ELEM_TYPE_LEAF) {
  438. u32 teid = le32_to_cpu(node->info.node_teid);
  439. enum ice_status status;
  440. /* remove the default leaf node */
  441. status = ice_sched_remove_elems(pi->hw, node->parent, 1, &teid);
  442. if (!status)
  443. ice_free_sched_node(pi, node);
  444. }
  445. }
  446. /**
  447. * ice_sched_rm_dflt_nodes - free the default nodes in the tree
  448. * @pi: port information structure
  449. *
  450. * This function frees all the nodes except root and TC that were created by
  451. * the FW during initialization
  452. */
  453. static void
  454. ice_sched_rm_dflt_nodes(struct ice_port_info *pi)
  455. {
  456. struct ice_sched_node *node;
  457. ice_rm_dflt_leaf_node(pi);
  458. /* remove the default nodes except TC and root nodes */
  459. node = pi->root;
  460. while (node) {
  461. if (node->tx_sched_layer >= pi->hw->sw_entry_point_layer &&
  462. node->info.data.elem_type != ICE_AQC_ELEM_TYPE_TC &&
  463. node->info.data.elem_type != ICE_AQC_ELEM_TYPE_ROOT_PORT) {
  464. ice_free_sched_node(pi, node);
  465. break;
  466. }
  467. if (!node->num_children)
  468. break;
  469. node = node->children[0];
  470. }
  471. }
  472. /**
  473. * ice_sched_init_port - Initialize scheduler by querying information from FW
  474. * @pi: port info structure for the tree to cleanup
  475. *
  476. * This function is the initial call to find the total number of Tx scheduler
  477. * resources, default topology created by firmware and storing the information
  478. * in SW DB.
  479. */
  480. enum ice_status ice_sched_init_port(struct ice_port_info *pi)
  481. {
  482. struct ice_aqc_get_topo_elem *buf;
  483. enum ice_status status;
  484. struct ice_hw *hw;
  485. u8 num_branches;
  486. u16 num_elems;
  487. u8 i, j;
  488. if (!pi)
  489. return ICE_ERR_PARAM;
  490. hw = pi->hw;
  491. /* Query the Default Topology from FW */
  492. buf = devm_kcalloc(ice_hw_to_dev(hw), ICE_TXSCHED_MAX_BRANCHES,
  493. sizeof(*buf), GFP_KERNEL);
  494. if (!buf)
  495. return ICE_ERR_NO_MEMORY;
  496. /* Query default scheduling tree topology */
  497. status = ice_aq_get_dflt_topo(hw, pi->lport, buf,
  498. sizeof(*buf) * ICE_TXSCHED_MAX_BRANCHES,
  499. &num_branches, NULL);
  500. if (status)
  501. goto err_init_port;
  502. /* num_branches should be between 1-8 */
  503. if (num_branches < 1 || num_branches > ICE_TXSCHED_MAX_BRANCHES) {
  504. ice_debug(hw, ICE_DBG_SCHED, "num_branches unexpected %d\n",
  505. num_branches);
  506. status = ICE_ERR_PARAM;
  507. goto err_init_port;
  508. }
  509. /* get the number of elements on the default/first branch */
  510. num_elems = le16_to_cpu(buf[0].hdr.num_elems);
  511. /* num_elems should always be between 1-9 */
  512. if (num_elems < 1 || num_elems > ICE_AQC_TOPO_MAX_LEVEL_NUM) {
  513. ice_debug(hw, ICE_DBG_SCHED, "num_elems unexpected %d\n",
  514. num_elems);
  515. status = ICE_ERR_PARAM;
  516. goto err_init_port;
  517. }
  518. /* If the last node is a leaf node then the index of the Q group
  519. * layer is two less than the number of elements.
  520. */
  521. if (num_elems > 2 && buf[0].generic[num_elems - 1].data.elem_type ==
  522. ICE_AQC_ELEM_TYPE_LEAF)
  523. pi->last_node_teid =
  524. le32_to_cpu(buf[0].generic[num_elems - 2].node_teid);
  525. else
  526. pi->last_node_teid =
  527. le32_to_cpu(buf[0].generic[num_elems - 1].node_teid);
  528. /* Insert the Tx Sched root node */
  529. status = ice_sched_add_root_node(pi, &buf[0].generic[0]);
  530. if (status)
  531. goto err_init_port;
  532. /* Parse the default tree and cache the information */
  533. for (i = 0; i < num_branches; i++) {
  534. num_elems = le16_to_cpu(buf[i].hdr.num_elems);
  535. /* Skip root element as already inserted */
  536. for (j = 1; j < num_elems; j++) {
  537. /* update the sw entry point */
  538. if (buf[0].generic[j].data.elem_type ==
  539. ICE_AQC_ELEM_TYPE_ENTRY_POINT)
  540. hw->sw_entry_point_layer = j;
  541. status = ice_sched_add_node(pi, j, &buf[i].generic[j]);
  542. if (status)
  543. goto err_init_port;
  544. }
  545. }
  546. /* Remove the default nodes. */
  547. if (pi->root)
  548. ice_sched_rm_dflt_nodes(pi);
  549. /* initialize the port for handling the scheduler tree */
  550. pi->port_state = ICE_SCHED_PORT_STATE_READY;
  551. mutex_init(&pi->sched_lock);
  552. INIT_LIST_HEAD(&pi->agg_list);
  553. INIT_LIST_HEAD(&pi->vsi_info_list);
  554. err_init_port:
  555. if (status && pi->root) {
  556. ice_free_sched_node(pi, pi->root);
  557. pi->root = NULL;
  558. }
  559. devm_kfree(ice_hw_to_dev(hw), buf);
  560. return status;
  561. }
  562. /**
  563. * ice_sched_query_res_alloc - query the FW for num of logical sched layers
  564. * @hw: pointer to the HW struct
  565. *
  566. * query FW for allocated scheduler resources and store in HW struct
  567. */
  568. enum ice_status ice_sched_query_res_alloc(struct ice_hw *hw)
  569. {
  570. struct ice_aqc_query_txsched_res_resp *buf;
  571. enum ice_status status = 0;
  572. if (hw->layer_info)
  573. return status;
  574. buf = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*buf), GFP_KERNEL);
  575. if (!buf)
  576. return ICE_ERR_NO_MEMORY;
  577. status = ice_aq_query_sched_res(hw, sizeof(*buf), buf, NULL);
  578. if (status)
  579. goto sched_query_out;
  580. hw->num_tx_sched_layers = le16_to_cpu(buf->sched_props.logical_levels);
  581. hw->num_tx_sched_phys_layers =
  582. le16_to_cpu(buf->sched_props.phys_levels);
  583. hw->flattened_layers = buf->sched_props.flattening_bitmap;
  584. hw->max_cgds = buf->sched_props.max_pf_cgds;
  585. hw->layer_info = devm_kmemdup(ice_hw_to_dev(hw), buf->layer_props,
  586. (hw->num_tx_sched_layers *
  587. sizeof(*hw->layer_info)),
  588. GFP_KERNEL);
  589. if (!hw->layer_info) {
  590. status = ICE_ERR_NO_MEMORY;
  591. goto sched_query_out;
  592. }
  593. sched_query_out:
  594. devm_kfree(ice_hw_to_dev(hw), buf);
  595. return status;
  596. }
  597. /**
  598. * ice_sched_get_vsi_info_entry - Get the vsi entry list for given vsi_id
  599. * @pi: port information structure
  600. * @vsi_id: vsi id
  601. *
  602. * This function retrieves the vsi list for the given vsi id
  603. */
  604. static struct ice_sched_vsi_info *
  605. ice_sched_get_vsi_info_entry(struct ice_port_info *pi, u16 vsi_id)
  606. {
  607. struct ice_sched_vsi_info *list_elem;
  608. if (!pi)
  609. return NULL;
  610. list_for_each_entry(list_elem, &pi->vsi_info_list, list_entry)
  611. if (list_elem->vsi_id == vsi_id)
  612. return list_elem;
  613. return NULL;
  614. }
  615. /**
  616. * ice_sched_find_node_in_subtree - Find node in part of base node subtree
  617. * @hw: pointer to the hw struct
  618. * @base: pointer to the base node
  619. * @node: pointer to the node to search
  620. *
  621. * This function checks whether a given node is part of the base node
  622. * subtree or not
  623. */
  624. static bool
  625. ice_sched_find_node_in_subtree(struct ice_hw *hw, struct ice_sched_node *base,
  626. struct ice_sched_node *node)
  627. {
  628. u8 i;
  629. for (i = 0; i < base->num_children; i++) {
  630. struct ice_sched_node *child = base->children[i];
  631. if (node == child)
  632. return true;
  633. if (child->tx_sched_layer > node->tx_sched_layer)
  634. return false;
  635. /* this recursion is intentional, and wouldn't
  636. * go more than 8 calls
  637. */
  638. if (ice_sched_find_node_in_subtree(hw, child, node))
  639. return true;
  640. }
  641. return false;
  642. }
  643. /**
  644. * ice_sched_get_free_qparent - Get a free lan or rdma q group node
  645. * @pi: port information structure
  646. * @vsi_id: vsi id
  647. * @tc: branch number
  648. * @owner: lan or rdma
  649. *
  650. * This function retrieves a free lan or rdma q group node
  651. */
  652. struct ice_sched_node *
  653. ice_sched_get_free_qparent(struct ice_port_info *pi, u16 vsi_id, u8 tc,
  654. u8 owner)
  655. {
  656. struct ice_sched_node *vsi_node, *qgrp_node = NULL;
  657. struct ice_sched_vsi_info *list_elem;
  658. u16 max_children;
  659. u8 qgrp_layer;
  660. qgrp_layer = ice_sched_get_qgrp_layer(pi->hw);
  661. max_children = le16_to_cpu(pi->hw->layer_info[qgrp_layer].max_children);
  662. list_elem = ice_sched_get_vsi_info_entry(pi, vsi_id);
  663. if (!list_elem)
  664. goto lan_q_exit;
  665. vsi_node = list_elem->vsi_node[tc];
  666. /* validate invalid VSI id */
  667. if (!vsi_node)
  668. goto lan_q_exit;
  669. /* get the first q group node from VSI sub-tree */
  670. qgrp_node = ice_sched_get_first_node(pi->hw, vsi_node, qgrp_layer);
  671. while (qgrp_node) {
  672. /* make sure the qgroup node is part of the VSI subtree */
  673. if (ice_sched_find_node_in_subtree(pi->hw, vsi_node, qgrp_node))
  674. if (qgrp_node->num_children < max_children &&
  675. qgrp_node->owner == owner)
  676. break;
  677. qgrp_node = qgrp_node->sibling;
  678. }
  679. lan_q_exit:
  680. return qgrp_node;
  681. }