ice_sched.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  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_rm_dflt_leaf_node - remove the default leaf node in the tree
  411. * @pi: port information structure
  412. *
  413. * This function removes the leaf node that was created by the FW
  414. * during initialization
  415. */
  416. static void
  417. ice_rm_dflt_leaf_node(struct ice_port_info *pi)
  418. {
  419. struct ice_sched_node *node;
  420. node = pi->root;
  421. while (node) {
  422. if (!node->num_children)
  423. break;
  424. node = node->children[0];
  425. }
  426. if (node && node->info.data.elem_type == ICE_AQC_ELEM_TYPE_LEAF) {
  427. u32 teid = le32_to_cpu(node->info.node_teid);
  428. enum ice_status status;
  429. /* remove the default leaf node */
  430. status = ice_sched_remove_elems(pi->hw, node->parent, 1, &teid);
  431. if (!status)
  432. ice_free_sched_node(pi, node);
  433. }
  434. }
  435. /**
  436. * ice_sched_rm_dflt_nodes - free the default nodes in the tree
  437. * @pi: port information structure
  438. *
  439. * This function frees all the nodes except root and TC that were created by
  440. * the FW during initialization
  441. */
  442. static void
  443. ice_sched_rm_dflt_nodes(struct ice_port_info *pi)
  444. {
  445. struct ice_sched_node *node;
  446. ice_rm_dflt_leaf_node(pi);
  447. /* remove the default nodes except TC and root nodes */
  448. node = pi->root;
  449. while (node) {
  450. if (node->tx_sched_layer >= pi->hw->sw_entry_point_layer &&
  451. node->info.data.elem_type != ICE_AQC_ELEM_TYPE_TC &&
  452. node->info.data.elem_type != ICE_AQC_ELEM_TYPE_ROOT_PORT) {
  453. ice_free_sched_node(pi, node);
  454. break;
  455. }
  456. if (!node->num_children)
  457. break;
  458. node = node->children[0];
  459. }
  460. }
  461. /**
  462. * ice_sched_init_port - Initialize scheduler by querying information from FW
  463. * @pi: port info structure for the tree to cleanup
  464. *
  465. * This function is the initial call to find the total number of Tx scheduler
  466. * resources, default topology created by firmware and storing the information
  467. * in SW DB.
  468. */
  469. enum ice_status ice_sched_init_port(struct ice_port_info *pi)
  470. {
  471. struct ice_aqc_get_topo_elem *buf;
  472. enum ice_status status;
  473. struct ice_hw *hw;
  474. u8 num_branches;
  475. u16 num_elems;
  476. u8 i, j;
  477. if (!pi)
  478. return ICE_ERR_PARAM;
  479. hw = pi->hw;
  480. /* Query the Default Topology from FW */
  481. buf = devm_kcalloc(ice_hw_to_dev(hw), ICE_TXSCHED_MAX_BRANCHES,
  482. sizeof(*buf), GFP_KERNEL);
  483. if (!buf)
  484. return ICE_ERR_NO_MEMORY;
  485. /* Query default scheduling tree topology */
  486. status = ice_aq_get_dflt_topo(hw, pi->lport, buf,
  487. sizeof(*buf) * ICE_TXSCHED_MAX_BRANCHES,
  488. &num_branches, NULL);
  489. if (status)
  490. goto err_init_port;
  491. /* num_branches should be between 1-8 */
  492. if (num_branches < 1 || num_branches > ICE_TXSCHED_MAX_BRANCHES) {
  493. ice_debug(hw, ICE_DBG_SCHED, "num_branches unexpected %d\n",
  494. num_branches);
  495. status = ICE_ERR_PARAM;
  496. goto err_init_port;
  497. }
  498. /* get the number of elements on the default/first branch */
  499. num_elems = le16_to_cpu(buf[0].hdr.num_elems);
  500. /* num_elems should always be between 1-9 */
  501. if (num_elems < 1 || num_elems > ICE_AQC_TOPO_MAX_LEVEL_NUM) {
  502. ice_debug(hw, ICE_DBG_SCHED, "num_elems unexpected %d\n",
  503. num_elems);
  504. status = ICE_ERR_PARAM;
  505. goto err_init_port;
  506. }
  507. /* If the last node is a leaf node then the index of the Q group
  508. * layer is two less than the number of elements.
  509. */
  510. if (num_elems > 2 && buf[0].generic[num_elems - 1].data.elem_type ==
  511. ICE_AQC_ELEM_TYPE_LEAF)
  512. pi->last_node_teid =
  513. le32_to_cpu(buf[0].generic[num_elems - 2].node_teid);
  514. else
  515. pi->last_node_teid =
  516. le32_to_cpu(buf[0].generic[num_elems - 1].node_teid);
  517. /* Insert the Tx Sched root node */
  518. status = ice_sched_add_root_node(pi, &buf[0].generic[0]);
  519. if (status)
  520. goto err_init_port;
  521. /* Parse the default tree and cache the information */
  522. for (i = 0; i < num_branches; i++) {
  523. num_elems = le16_to_cpu(buf[i].hdr.num_elems);
  524. /* Skip root element as already inserted */
  525. for (j = 1; j < num_elems; j++) {
  526. /* update the sw entry point */
  527. if (buf[0].generic[j].data.elem_type ==
  528. ICE_AQC_ELEM_TYPE_ENTRY_POINT)
  529. hw->sw_entry_point_layer = j;
  530. status = ice_sched_add_node(pi, j, &buf[i].generic[j]);
  531. if (status)
  532. goto err_init_port;
  533. }
  534. }
  535. /* Remove the default nodes. */
  536. if (pi->root)
  537. ice_sched_rm_dflt_nodes(pi);
  538. /* initialize the port for handling the scheduler tree */
  539. pi->port_state = ICE_SCHED_PORT_STATE_READY;
  540. mutex_init(&pi->sched_lock);
  541. INIT_LIST_HEAD(&pi->agg_list);
  542. INIT_LIST_HEAD(&pi->vsi_info_list);
  543. err_init_port:
  544. if (status && pi->root) {
  545. ice_free_sched_node(pi, pi->root);
  546. pi->root = NULL;
  547. }
  548. devm_kfree(ice_hw_to_dev(hw), buf);
  549. return status;
  550. }
  551. /**
  552. * ice_sched_query_res_alloc - query the FW for num of logical sched layers
  553. * @hw: pointer to the HW struct
  554. *
  555. * query FW for allocated scheduler resources and store in HW struct
  556. */
  557. enum ice_status ice_sched_query_res_alloc(struct ice_hw *hw)
  558. {
  559. struct ice_aqc_query_txsched_res_resp *buf;
  560. enum ice_status status = 0;
  561. if (hw->layer_info)
  562. return status;
  563. buf = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*buf), GFP_KERNEL);
  564. if (!buf)
  565. return ICE_ERR_NO_MEMORY;
  566. status = ice_aq_query_sched_res(hw, sizeof(*buf), buf, NULL);
  567. if (status)
  568. goto sched_query_out;
  569. hw->num_tx_sched_layers = le16_to_cpu(buf->sched_props.logical_levels);
  570. hw->num_tx_sched_phys_layers =
  571. le16_to_cpu(buf->sched_props.phys_levels);
  572. hw->flattened_layers = buf->sched_props.flattening_bitmap;
  573. hw->max_cgds = buf->sched_props.max_pf_cgds;
  574. hw->layer_info = devm_kmemdup(ice_hw_to_dev(hw), buf->layer_props,
  575. (hw->num_tx_sched_layers *
  576. sizeof(*hw->layer_info)),
  577. GFP_KERNEL);
  578. if (!hw->layer_info) {
  579. status = ICE_ERR_NO_MEMORY;
  580. goto sched_query_out;
  581. }
  582. sched_query_out:
  583. devm_kfree(ice_hw_to_dev(hw), buf);
  584. return status;
  585. }