Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'mlx5-esw-qos-refactor-and-shampo-cleanup'

Tariq Toukan says:

====================
mlx5 esw qos refactor and SHAMPO cleanup

This patchset for the mlx5 core and Eth drivers consists of 3 parts.

First patch by Patrisious improves the E-switch mode change operation.

The following 6 patches by Carolina introduce further refactoring for
the QoS handling, to set the foundation for future extensions.

In the following 5 patches by Dragos, we enhance the SHAMPO datapath
flow by simplifying some logic, and cleaning up the implementation.
====================

Link: https://patch.msgid.link/20241107194357.683732-1-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+305 -441
+2 -3
drivers/net/ethernet/mellanox/mlx5/core/en.h
··· 83 83 #define MLX5E_SHAMPO_LOG_HEADER_ENTRY_SIZE (8) 84 84 #define MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE (9) 85 85 #define MLX5E_SHAMPO_WQ_HEADER_PER_PAGE (PAGE_SIZE >> MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE) 86 + #define MLX5E_SHAMPO_LOG_WQ_HEADER_PER_PAGE (PAGE_SHIFT - MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE) 86 87 #define MLX5E_SHAMPO_WQ_BASE_HEAD_ENTRY_SIZE (64) 87 88 #define MLX5E_SHAMPO_WQ_RESRV_SIZE (64 * 1024) 88 89 #define MLX5E_SHAMPO_WQ_BASE_RESRV_SIZE (4096) ··· 625 624 626 625 struct mlx5e_shampo_hd { 627 626 u32 mkey; 628 - struct mlx5e_dma_info *info; 629 627 struct mlx5e_frag_page *pages; 630 - u16 curr_page_index; 631 628 u32 hd_per_wq; 632 629 u16 hd_per_wqe; 630 + u16 pages_per_wq; 633 631 unsigned long *bitmap; 634 632 u16 pi; 635 633 u16 ci; 636 634 __be32 key; 637 - u64 last_addr; 638 635 }; 639 636 640 637 struct mlx5e_hw_gro_data {
+4 -11
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
··· 350 350 351 351 shampo->bitmap = bitmap_zalloc_node(shampo->hd_per_wq, GFP_KERNEL, 352 352 node); 353 - shampo->info = kvzalloc_node(array_size(shampo->hd_per_wq, 354 - sizeof(*shampo->info)), 355 - GFP_KERNEL, node); 356 353 shampo->pages = kvzalloc_node(array_size(shampo->hd_per_wq, 357 354 sizeof(*shampo->pages)), 358 355 GFP_KERNEL, node); 359 - if (!shampo->bitmap || !shampo->info || !shampo->pages) 356 + if (!shampo->bitmap || !shampo->pages) 360 357 goto err_nomem; 361 358 362 359 return 0; 363 360 364 361 err_nomem: 365 - kvfree(shampo->info); 366 362 kvfree(shampo->bitmap); 367 363 kvfree(shampo->pages); 368 364 ··· 368 372 static void mlx5e_rq_shampo_hd_info_free(struct mlx5e_rq *rq) 369 373 { 370 374 kvfree(rq->mpwqe.shampo->bitmap); 371 - kvfree(rq->mpwqe.shampo->info); 372 375 kvfree(rq->mpwqe.shampo->pages); 373 376 } 374 377 ··· 762 767 u32 *pool_size, 763 768 int node) 764 769 { 765 - void *wqc = MLX5_ADDR_OF(rqc, rqp->rqc, wq); 766 - int wq_size; 767 770 int err; 768 771 769 772 if (!test_bit(MLX5E_RQ_STATE_SHAMPO, &rq->state)) ··· 786 793 cpu_to_be32(rq->mpwqe.shampo->mkey); 787 794 rq->mpwqe.shampo->hd_per_wqe = 788 795 mlx5e_shampo_hd_per_wqe(mdev, params, rqp); 789 - wq_size = BIT(MLX5_GET(wq, wqc, log_wq_sz)); 790 - *pool_size += (rq->mpwqe.shampo->hd_per_wqe * wq_size) / 791 - MLX5E_SHAMPO_WQ_HEADER_PER_PAGE; 796 + rq->mpwqe.shampo->pages_per_wq = 797 + rq->mpwqe.shampo->hd_per_wq / MLX5E_SHAMPO_WQ_HEADER_PER_PAGE; 798 + *pool_size += rq->mpwqe.shampo->pages_per_wq; 792 799 return 0; 793 800 794 801 err_hw_gro_data:
+61 -62
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
··· 643 643 umr_wqe->uctrl.mkey_mask = cpu_to_be64(MLX5_MKEY_MASK_FREE); 644 644 } 645 645 646 + static struct mlx5e_frag_page *mlx5e_shampo_hd_to_frag_page(struct mlx5e_rq *rq, int header_index) 647 + { 648 + BUILD_BUG_ON(MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE > PAGE_SHIFT); 649 + 650 + return &rq->mpwqe.shampo->pages[header_index >> MLX5E_SHAMPO_LOG_WQ_HEADER_PER_PAGE]; 651 + } 652 + 653 + static u64 mlx5e_shampo_hd_offset(int header_index) 654 + { 655 + return (header_index & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1)) << 656 + MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE; 657 + } 658 + 659 + static void mlx5e_free_rx_shampo_hd_entry(struct mlx5e_rq *rq, u16 header_index); 660 + 646 661 static int mlx5e_build_shampo_hd_umr(struct mlx5e_rq *rq, 647 662 struct mlx5e_icosq *sq, 648 663 u16 ksm_entries, u16 index) 649 664 { 650 665 struct mlx5e_shampo_hd *shampo = rq->mpwqe.shampo; 651 - u16 entries, pi, header_offset, err, wqe_bbs, new_entries; 666 + u16 pi, header_offset, err, wqe_bbs; 652 667 u32 lkey = rq->mdev->mlx5e_res.hw_objs.mkey; 653 - u16 page_index = shampo->curr_page_index; 654 - struct mlx5e_frag_page *frag_page; 655 - u64 addr = shampo->last_addr; 656 - struct mlx5e_dma_info *dma_info; 657 668 struct mlx5e_umr_wqe *umr_wqe; 658 - int headroom, i; 669 + int headroom, i = 0; 659 670 660 671 headroom = rq->buff.headroom; 661 - new_entries = ksm_entries - (shampo->pi & (MLX5_UMR_KSM_NUM_ENTRIES_ALIGNMENT - 1)); 662 - entries = ALIGN(ksm_entries, MLX5_UMR_KSM_NUM_ENTRIES_ALIGNMENT); 663 - wqe_bbs = MLX5E_KSM_UMR_WQEBBS(entries); 672 + wqe_bbs = MLX5E_KSM_UMR_WQEBBS(ksm_entries); 664 673 pi = mlx5e_icosq_get_next_pi(sq, wqe_bbs); 665 674 umr_wqe = mlx5_wq_cyc_get_wqe(&sq->wq, pi); 666 - build_ksm_umr(sq, umr_wqe, shampo->key, index, entries); 675 + build_ksm_umr(sq, umr_wqe, shampo->key, index, ksm_entries); 667 676 668 - frag_page = &shampo->pages[page_index]; 677 + WARN_ON_ONCE(ksm_entries & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1)); 678 + while (i < ksm_entries) { 679 + struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, index); 680 + u64 addr; 669 681 670 - for (i = 0; i < entries; i++, index++) { 671 - dma_info = &shampo->info[index]; 672 - if (i >= ksm_entries || (index < shampo->pi && shampo->pi - index < 673 - MLX5_UMR_KSM_NUM_ENTRIES_ALIGNMENT)) 674 - goto update_ksm; 675 - header_offset = (index & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1)) << 676 - MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE; 677 - if (!(header_offset & (PAGE_SIZE - 1))) { 678 - page_index = (page_index + 1) & (shampo->hd_per_wq - 1); 679 - frag_page = &shampo->pages[page_index]; 682 + err = mlx5e_page_alloc_fragmented(rq, frag_page); 683 + if (unlikely(err)) 684 + goto err_unmap; 680 685 681 - err = mlx5e_page_alloc_fragmented(rq, frag_page); 682 - if (unlikely(err)) 683 - goto err_unmap; 684 686 685 - addr = page_pool_get_dma_addr(frag_page->page); 687 + addr = page_pool_get_dma_addr(frag_page->page); 686 688 687 - dma_info->addr = addr; 688 - dma_info->frag_page = frag_page; 689 - } else { 690 - dma_info->addr = addr + header_offset; 691 - dma_info->frag_page = frag_page; 689 + for (int j = 0; j < MLX5E_SHAMPO_WQ_HEADER_PER_PAGE; j++) { 690 + header_offset = mlx5e_shampo_hd_offset(index++); 691 + 692 + umr_wqe->inline_ksms[i++] = (struct mlx5_ksm) { 693 + .key = cpu_to_be32(lkey), 694 + .va = cpu_to_be64(addr + header_offset + headroom), 695 + }; 692 696 } 693 - 694 - update_ksm: 695 - umr_wqe->inline_ksms[i] = (struct mlx5_ksm) { 696 - .key = cpu_to_be32(lkey), 697 - .va = cpu_to_be64(dma_info->addr + headroom), 698 - }; 699 697 } 700 698 701 699 sq->db.wqe_info[pi] = (struct mlx5e_icosq_wqe_info) { 702 700 .wqe_type = MLX5E_ICOSQ_WQE_SHAMPO_HD_UMR, 703 701 .num_wqebbs = wqe_bbs, 704 - .shampo.len = new_entries, 702 + .shampo.len = ksm_entries, 705 703 }; 706 704 707 - shampo->pi = (shampo->pi + new_entries) & (shampo->hd_per_wq - 1); 708 - shampo->curr_page_index = page_index; 709 - shampo->last_addr = addr; 705 + shampo->pi = (shampo->pi + ksm_entries) & (shampo->hd_per_wq - 1); 710 706 sq->pc += wqe_bbs; 711 707 sq->doorbell_cseg = &umr_wqe->ctrl; 712 708 713 709 return 0; 714 710 715 711 err_unmap: 716 - while (--i >= 0) { 717 - dma_info = &shampo->info[--index]; 718 - if (!(i & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1))) { 719 - dma_info->addr = ALIGN_DOWN(dma_info->addr, PAGE_SIZE); 720 - mlx5e_page_release_fragmented(rq, dma_info->frag_page); 712 + while (--i) { 713 + --index; 714 + header_offset = mlx5e_shampo_hd_offset(index); 715 + if (!header_offset) { 716 + struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, index); 717 + 718 + mlx5e_page_release_fragmented(rq, frag_page); 721 719 } 722 720 } 721 + 723 722 rq->stats->buff_alloc_err++; 724 723 return err; 725 724 } ··· 730 731 struct mlx5e_icosq *sq = rq->icosq; 731 732 int i, err, max_ksm_entries, len; 732 733 733 - max_ksm_entries = MLX5E_MAX_KSM_PER_WQE(rq->mdev); 734 + max_ksm_entries = ALIGN_DOWN(MLX5E_MAX_KSM_PER_WQE(rq->mdev), 735 + MLX5E_SHAMPO_WQ_HEADER_PER_PAGE); 734 736 ksm_entries = bitmap_find_window(shampo->bitmap, 735 737 shampo->hd_per_wqe, 736 738 shampo->hd_per_wq, shampo->pi); ··· 739 739 if (!ksm_entries) 740 740 return 0; 741 741 742 - ksm_entries += (shampo->pi & (MLX5_UMR_KSM_NUM_ENTRIES_ALIGNMENT - 1)); 743 - index = ALIGN_DOWN(shampo->pi, MLX5_UMR_KSM_NUM_ENTRIES_ALIGNMENT); 742 + /* pi is aligned to MLX5E_SHAMPO_WQ_HEADER_PER_PAGE */ 743 + index = shampo->pi; 744 744 entries_before = shampo->hd_per_wq - index; 745 745 746 746 if (unlikely(entries_before < ksm_entries)) ··· 851 851 mlx5e_free_rx_shampo_hd_entry(struct mlx5e_rq *rq, u16 header_index) 852 852 { 853 853 struct mlx5e_shampo_hd *shampo = rq->mpwqe.shampo; 854 - u64 addr = shampo->info[header_index].addr; 855 854 856 855 if (((header_index + 1) & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1)) == 0) { 857 - struct mlx5e_dma_info *dma_info = &shampo->info[header_index]; 856 + struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, header_index); 858 857 859 - dma_info->addr = ALIGN_DOWN(addr, PAGE_SIZE); 860 - mlx5e_page_release_fragmented(rq, dma_info->frag_page); 858 + mlx5e_page_release_fragmented(rq, frag_page); 861 859 } 862 860 clear_bit(header_index, shampo->bitmap); 863 861 } ··· 1209 1211 1210 1212 static void *mlx5e_shampo_get_packet_hd(struct mlx5e_rq *rq, u16 header_index) 1211 1213 { 1212 - struct mlx5e_dma_info *last_head = &rq->mpwqe.shampo->info[header_index]; 1213 - u16 head_offset = (last_head->addr & (PAGE_SIZE - 1)) + rq->buff.headroom; 1214 + struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, header_index); 1215 + u16 head_offset = mlx5e_shampo_hd_offset(header_index) + rq->buff.headroom; 1214 1216 1215 - return page_address(last_head->frag_page->page) + head_offset; 1217 + return page_address(frag_page->page) + head_offset; 1216 1218 } 1217 1219 1218 1220 static void mlx5e_shampo_update_ipv4_udp_hdr(struct mlx5e_rq *rq, struct iphdr *ipv4) ··· 2183 2185 mlx5e_skb_from_cqe_shampo(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi, 2184 2186 struct mlx5_cqe64 *cqe, u16 header_index) 2185 2187 { 2186 - struct mlx5e_dma_info *head = &rq->mpwqe.shampo->info[header_index]; 2187 - u16 head_offset = head->addr & (PAGE_SIZE - 1); 2188 + struct mlx5e_frag_page *frag_page = mlx5e_shampo_hd_to_frag_page(rq, header_index); 2189 + dma_addr_t page_dma_addr = page_pool_get_dma_addr(frag_page->page); 2190 + u16 head_offset = mlx5e_shampo_hd_offset(header_index); 2191 + dma_addr_t dma_addr = page_dma_addr + head_offset; 2188 2192 u16 head_size = cqe->shampo.header_size; 2189 2193 u16 rx_headroom = rq->buff.headroom; 2190 2194 struct sk_buff *skb = NULL; 2191 2195 void *hdr, *data; 2192 2196 u32 frag_size; 2193 2197 2194 - hdr = page_address(head->frag_page->page) + head_offset; 2198 + hdr = page_address(frag_page->page) + head_offset; 2195 2199 data = hdr + rx_headroom; 2196 2200 frag_size = MLX5_SKB_FRAG_SZ(rx_headroom + head_size); 2197 2201 2198 2202 if (likely(frag_size <= BIT(MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE))) { 2199 2203 /* build SKB around header */ 2200 - dma_sync_single_range_for_cpu(rq->pdev, head->addr, 0, frag_size, rq->buff.map_dir); 2204 + dma_sync_single_range_for_cpu(rq->pdev, dma_addr, 0, frag_size, rq->buff.map_dir); 2201 2205 net_prefetchw(hdr); 2202 2206 net_prefetch(data); 2203 2207 skb = mlx5e_build_linear_skb(rq, hdr, frag_size, rx_headroom, head_size, 0); 2204 - 2205 2208 if (unlikely(!skb)) 2206 2209 return NULL; 2207 2210 2208 - head->frag_page->frags++; 2211 + frag_page->frags++; 2209 2212 } else { 2210 2213 /* allocate SKB and copy header for large header */ 2211 2214 rq->stats->gro_large_hds++; ··· 2218 2219 } 2219 2220 2220 2221 net_prefetchw(skb->data); 2221 - mlx5e_copy_skb_header(rq, skb, head->frag_page->page, head->addr, 2222 + mlx5e_copy_skb_header(rq, skb, frag_page->page, dma_addr, 2222 2223 head_offset + rx_headroom, 2223 2224 rx_headroom, head_size); 2224 2225 /* skb linear part was allocated with headlen and aligned to long */
+211 -351
drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
··· 101 101 node->esw = parent->esw; 102 102 } 103 103 104 + void mlx5_esw_qos_vport_qos_free(struct mlx5_vport *vport) 105 + { 106 + kfree(vport->qos.sched_node); 107 + memset(&vport->qos, 0, sizeof(vport->qos)); 108 + } 109 + 104 110 u32 mlx5_esw_qos_vport_get_sched_elem_ix(const struct mlx5_vport *vport) 105 111 { 106 112 if (!vport->qos.sched_node) ··· 124 118 return vport->qos.sched_node->parent; 125 119 } 126 120 127 - static void esw_qos_sched_elem_config_warn(struct mlx5_esw_sched_node *node, int err) 121 + static void esw_qos_sched_elem_warn(struct mlx5_esw_sched_node *node, int err, const char *op) 128 122 { 129 123 if (node->vport) { 130 124 esw_warn(node->esw->dev, 131 - "E-Switch modify %s scheduling element failed (vport=%d,err=%d)\n", 132 - sched_node_type_str[node->type], node->vport->vport, err); 125 + "E-Switch %s %s scheduling element failed (vport=%d,err=%d)\n", 126 + op, sched_node_type_str[node->type], node->vport->vport, err); 133 127 return; 134 128 } 135 129 136 130 esw_warn(node->esw->dev, 137 - "E-Switch modify %s scheduling element failed (err=%d)\n", 138 - sched_node_type_str[node->type], err); 131 + "E-Switch %s %s scheduling element failed (err=%d)\n", 132 + op, sched_node_type_str[node->type], err); 133 + } 134 + 135 + static int esw_qos_node_create_sched_element(struct mlx5_esw_sched_node *node, void *ctx, 136 + struct netlink_ext_ack *extack) 137 + { 138 + int err; 139 + 140 + err = mlx5_create_scheduling_element_cmd(node->esw->dev, SCHEDULING_HIERARCHY_E_SWITCH, ctx, 141 + &node->ix); 142 + if (err) { 143 + esw_qos_sched_elem_warn(node, err, "create"); 144 + NL_SET_ERR_MSG_MOD(extack, "E-Switch create scheduling element failed"); 145 + } 146 + 147 + return err; 148 + } 149 + 150 + static int esw_qos_node_destroy_sched_element(struct mlx5_esw_sched_node *node, 151 + struct netlink_ext_ack *extack) 152 + { 153 + int err; 154 + 155 + err = mlx5_destroy_scheduling_element_cmd(node->esw->dev, 156 + SCHEDULING_HIERARCHY_E_SWITCH, 157 + node->ix); 158 + if (err) { 159 + esw_qos_sched_elem_warn(node, err, "destroy"); 160 + NL_SET_ERR_MSG_MOD(extack, "E-Switch destroying scheduling element failed."); 161 + } 162 + 163 + return err; 139 164 } 140 165 141 166 static int esw_qos_sched_elem_config(struct mlx5_esw_sched_node *node, u32 max_rate, u32 bw_share, ··· 180 143 if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling)) 181 144 return -EOPNOTSUPP; 182 145 183 - MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_rate); 184 - MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share); 185 - bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW; 186 - bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE; 146 + if (bw_share && (!MLX5_CAP_QOS(dev, esw_bw_share) || 147 + MLX5_CAP_QOS(dev, max_tsar_bw_share) < MLX5_MIN_BW_SHARE)) 148 + return -EOPNOTSUPP; 149 + 150 + if (node->max_rate == max_rate && node->bw_share == bw_share) 151 + return 0; 152 + 153 + if (node->max_rate != max_rate) { 154 + MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_rate); 155 + bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW; 156 + } 157 + if (node->bw_share != bw_share) { 158 + MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share); 159 + bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE; 160 + } 187 161 188 162 err = mlx5_modify_scheduling_element_cmd(dev, 189 163 SCHEDULING_HIERARCHY_E_SWITCH, ··· 202 154 node->ix, 203 155 bitmask); 204 156 if (err) { 205 - esw_qos_sched_elem_config_warn(node, err); 157 + esw_qos_sched_elem_warn(node, err, "modify"); 206 158 NL_SET_ERR_MSG_MOD(extack, "E-Switch modify scheduling element failed"); 207 159 208 160 return err; 209 161 } 210 162 163 + node->max_rate = max_rate; 164 + node->bw_share = bw_share; 211 165 if (node->type == SCHED_NODE_TYPE_VPORTS_TSAR) 212 166 trace_mlx5_esw_node_qos_config(dev, node, node->ix, bw_share, max_rate); 213 167 else if (node->type == SCHED_NODE_TYPE_VPORT) ··· 258 208 return min_t(u32, max_t(u32, DIV_ROUND_UP(min_rate, divider), MLX5_MIN_BW_SHARE), fw_max); 259 209 } 260 210 261 - static int esw_qos_update_sched_node_bw_share(struct mlx5_esw_sched_node *node, 262 - u32 divider, 263 - struct netlink_ext_ack *extack) 211 + static void esw_qos_update_sched_node_bw_share(struct mlx5_esw_sched_node *node, 212 + u32 divider, 213 + struct netlink_ext_ack *extack) 264 214 { 265 215 u32 fw_max_bw_share = MLX5_CAP_QOS(node->esw->dev, max_tsar_bw_share); 266 216 u32 bw_share; 267 - int err; 268 217 269 218 bw_share = esw_qos_calc_bw_share(node->min_rate, divider, fw_max_bw_share); 270 219 271 - if (bw_share == node->bw_share) 272 - return 0; 273 - 274 - err = esw_qos_sched_elem_config(node, node->max_rate, bw_share, extack); 275 - if (err) 276 - return err; 277 - 278 - node->bw_share = bw_share; 279 - 280 - return err; 220 + esw_qos_sched_elem_config(node, node->max_rate, bw_share, extack); 281 221 } 282 222 283 - static int esw_qos_normalize_min_rate(struct mlx5_eswitch *esw, 284 - struct mlx5_esw_sched_node *parent, 285 - struct netlink_ext_ack *extack) 223 + static void esw_qos_normalize_min_rate(struct mlx5_eswitch *esw, 224 + struct mlx5_esw_sched_node *parent, 225 + struct netlink_ext_ack *extack) 286 226 { 287 227 struct list_head *nodes = parent ? &parent->children : &esw->qos.domain->nodes; 288 228 u32 divider = esw_qos_calculate_min_rate_divider(esw, parent); 289 229 struct mlx5_esw_sched_node *node; 290 230 291 231 list_for_each_entry(node, nodes, entry) { 292 - int err; 293 - 294 232 if (node->esw != esw || node->ix == esw->qos.root_tsar_ix) 295 233 continue; 296 234 297 - err = esw_qos_update_sched_node_bw_share(node, divider, extack); 298 - if (err) 299 - return err; 235 + esw_qos_update_sched_node_bw_share(node, divider, extack); 300 236 301 237 if (list_empty(&node->children)) 302 238 continue; 303 239 304 - err = esw_qos_normalize_min_rate(node->esw, node, extack); 305 - if (err) 306 - return err; 240 + esw_qos_normalize_min_rate(node->esw, node, extack); 307 241 } 308 - 309 - return 0; 310 - } 311 - 312 - static int esw_qos_set_vport_min_rate(struct mlx5_vport *vport, 313 - u32 min_rate, struct netlink_ext_ack *extack) 314 - { 315 - struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node; 316 - u32 fw_max_bw_share, previous_min_rate; 317 - bool min_rate_supported; 318 - int err; 319 - 320 - esw_assert_qos_lock_held(vport_node->esw); 321 - fw_max_bw_share = MLX5_CAP_QOS(vport->dev, max_tsar_bw_share); 322 - min_rate_supported = MLX5_CAP_QOS(vport->dev, esw_bw_share) && 323 - fw_max_bw_share >= MLX5_MIN_BW_SHARE; 324 - if (min_rate && !min_rate_supported) 325 - return -EOPNOTSUPP; 326 - if (min_rate == vport_node->min_rate) 327 - return 0; 328 - 329 - previous_min_rate = vport_node->min_rate; 330 - vport_node->min_rate = min_rate; 331 - err = esw_qos_normalize_min_rate(vport_node->parent->esw, vport_node->parent, extack); 332 - if (err) 333 - vport_node->min_rate = previous_min_rate; 334 - 335 - return err; 336 - } 337 - 338 - static int esw_qos_set_vport_max_rate(struct mlx5_vport *vport, 339 - u32 max_rate, struct netlink_ext_ack *extack) 340 - { 341 - struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node; 342 - u32 act_max_rate = max_rate; 343 - bool max_rate_supported; 344 - int err; 345 - 346 - esw_assert_qos_lock_held(vport_node->esw); 347 - max_rate_supported = MLX5_CAP_QOS(vport->dev, esw_rate_limit); 348 - 349 - if (max_rate && !max_rate_supported) 350 - return -EOPNOTSUPP; 351 - if (max_rate == vport_node->max_rate) 352 - return 0; 353 - 354 - /* Use parent node limit if new max rate is 0. */ 355 - if (!max_rate) 356 - act_max_rate = vport_node->parent->max_rate; 357 - 358 - err = esw_qos_sched_elem_config(vport_node, act_max_rate, vport_node->bw_share, extack); 359 - if (!err) 360 - vport_node->max_rate = max_rate; 361 - 362 - return err; 363 242 } 364 243 365 244 static int esw_qos_set_node_min_rate(struct mlx5_esw_sched_node *node, 366 245 u32 min_rate, struct netlink_ext_ack *extack) 367 246 { 368 247 struct mlx5_eswitch *esw = node->esw; 369 - u32 previous_min_rate; 370 - int err; 371 - 372 - if (!MLX5_CAP_QOS(esw->dev, esw_bw_share) || 373 - MLX5_CAP_QOS(esw->dev, max_tsar_bw_share) < MLX5_MIN_BW_SHARE) 374 - return -EOPNOTSUPP; 375 248 376 249 if (min_rate == node->min_rate) 377 250 return 0; 378 251 379 - previous_min_rate = node->min_rate; 380 252 node->min_rate = min_rate; 381 - err = esw_qos_normalize_min_rate(esw, NULL, extack); 382 - if (err) { 383 - NL_SET_ERR_MSG_MOD(extack, "E-Switch node min rate setting failed"); 253 + esw_qos_normalize_min_rate(esw, node->parent, extack); 384 254 385 - /* Attempt restoring previous configuration */ 386 - node->min_rate = previous_min_rate; 387 - if (esw_qos_normalize_min_rate(esw, NULL, extack)) 388 - NL_SET_ERR_MSG_MOD(extack, "E-Switch BW share restore failed"); 389 - } 390 - 391 - return err; 392 - } 393 - 394 - static int esw_qos_set_node_max_rate(struct mlx5_esw_sched_node *node, 395 - u32 max_rate, struct netlink_ext_ack *extack) 396 - { 397 - struct mlx5_esw_sched_node *vport_node; 398 - int err; 399 - 400 - if (node->max_rate == max_rate) 401 - return 0; 402 - 403 - err = esw_qos_sched_elem_config(node, max_rate, node->bw_share, extack); 404 - if (err) 405 - return err; 406 - 407 - node->max_rate = max_rate; 408 - 409 - /* Any unlimited vports in the node should be set with the value of the node. */ 410 - list_for_each_entry(vport_node, &node->children, entry) { 411 - if (vport_node->max_rate) 412 - continue; 413 - 414 - err = esw_qos_sched_elem_config(vport_node, max_rate, vport_node->bw_share, extack); 415 - if (err) 416 - NL_SET_ERR_MSG_MOD(extack, 417 - "E-Switch vport implicit rate limit setting failed"); 418 - } 419 - 420 - return err; 255 + return 0; 421 256 } 422 257 423 258 static int esw_qos_create_node_sched_elem(struct mlx5_core_dev *dev, u32 parent_element_id, ··· 332 397 tsar_ix); 333 398 } 334 399 335 - static int 336 - esw_qos_vport_create_sched_element(struct mlx5_vport *vport, struct mlx5_esw_sched_node *parent, 337 - u32 max_rate, u32 bw_share, u32 *sched_elem_ix) 400 + static int esw_qos_vport_create_sched_element(struct mlx5_esw_sched_node *vport_node, 401 + struct netlink_ext_ack *extack) 338 402 { 339 403 u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {}; 340 - struct mlx5_core_dev *dev = parent->esw->dev; 404 + struct mlx5_core_dev *dev = vport_node->esw->dev; 341 405 void *attr; 342 - int err; 343 406 344 407 if (!mlx5_qos_element_type_supported(dev, 345 408 SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT, ··· 347 414 MLX5_SET(scheduling_context, sched_ctx, element_type, 348 415 SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT); 349 416 attr = MLX5_ADDR_OF(scheduling_context, sched_ctx, element_attributes); 350 - MLX5_SET(vport_element, attr, vport_number, vport->vport); 351 - MLX5_SET(scheduling_context, sched_ctx, parent_element_id, parent->ix); 352 - MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_rate); 353 - MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share); 417 + MLX5_SET(vport_element, attr, vport_number, vport_node->vport->vport); 418 + MLX5_SET(scheduling_context, sched_ctx, parent_element_id, vport_node->parent->ix); 419 + MLX5_SET(scheduling_context, sched_ctx, max_average_bw, vport_node->max_rate); 354 420 355 - err = mlx5_create_scheduling_element_cmd(dev, 356 - SCHEDULING_HIERARCHY_E_SWITCH, 357 - sched_ctx, 358 - sched_elem_ix); 359 - if (err) { 360 - esw_warn(dev, 361 - "E-Switch create vport scheduling element failed (vport=%d,err=%d)\n", 362 - vport->vport, err); 363 - return err; 364 - } 365 - 366 - return 0; 367 - } 368 - 369 - static int esw_qos_update_node_scheduling_element(struct mlx5_vport *vport, 370 - struct mlx5_esw_sched_node *curr_node, 371 - struct mlx5_esw_sched_node *new_node, 372 - struct netlink_ext_ack *extack) 373 - { 374 - struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node; 375 - u32 max_rate; 376 - int err; 377 - 378 - err = mlx5_destroy_scheduling_element_cmd(curr_node->esw->dev, 379 - SCHEDULING_HIERARCHY_E_SWITCH, 380 - vport_node->ix); 381 - if (err) { 382 - NL_SET_ERR_MSG_MOD(extack, "E-Switch destroy vport scheduling element failed"); 383 - return err; 384 - } 385 - 386 - /* Use new node max rate if vport max rate is unlimited. */ 387 - max_rate = vport_node->max_rate ? vport_node->max_rate : new_node->max_rate; 388 - err = esw_qos_vport_create_sched_element(vport, new_node, max_rate, 389 - vport_node->bw_share, 390 - &vport_node->ix); 391 - if (err) { 392 - NL_SET_ERR_MSG_MOD(extack, "E-Switch vport node set failed."); 393 - goto err_sched; 394 - } 395 - 396 - esw_qos_node_set_parent(vport->qos.sched_node, new_node); 397 - 398 - return 0; 399 - 400 - err_sched: 401 - max_rate = vport_node->max_rate ? vport_node->max_rate : curr_node->max_rate; 402 - if (esw_qos_vport_create_sched_element(vport, curr_node, max_rate, 403 - vport_node->bw_share, 404 - &vport_node->ix)) 405 - esw_warn(curr_node->esw->dev, "E-Switch vport node restore failed (vport=%d)\n", 406 - vport->vport); 407 - 408 - return err; 409 - } 410 - 411 - static int esw_qos_vport_update_node(struct mlx5_vport *vport, 412 - struct mlx5_esw_sched_node *node, 413 - struct netlink_ext_ack *extack) 414 - { 415 - struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node; 416 - struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 417 - struct mlx5_esw_sched_node *new_node, *curr_node; 418 - int err; 419 - 420 - esw_assert_qos_lock_held(esw); 421 - curr_node = vport_node->parent; 422 - new_node = node ?: esw->qos.node0; 423 - if (curr_node == new_node) 424 - return 0; 425 - 426 - err = esw_qos_update_node_scheduling_element(vport, curr_node, new_node, extack); 427 - if (err) 428 - return err; 429 - 430 - /* Recalculate bw share weights of old and new nodes */ 431 - if (vport_node->bw_share || new_node->bw_share) { 432 - esw_qos_normalize_min_rate(curr_node->esw, curr_node, extack); 433 - esw_qos_normalize_min_rate(new_node->esw, new_node, extack); 434 - } 435 - 436 - return 0; 421 + return esw_qos_node_create_sched_element(vport_node, sched_ctx, extack); 437 422 } 438 423 439 424 static struct mlx5_esw_sched_node * ··· 382 531 kfree(node); 383 532 } 384 533 534 + static void esw_qos_destroy_node(struct mlx5_esw_sched_node *node, struct netlink_ext_ack *extack) 535 + { 536 + esw_qos_node_destroy_sched_element(node, extack); 537 + __esw_qos_free_node(node); 538 + } 539 + 385 540 static struct mlx5_esw_sched_node * 386 541 __esw_qos_create_vports_sched_node(struct mlx5_eswitch *esw, struct mlx5_esw_sched_node *parent, 387 542 struct netlink_ext_ack *extack) ··· 409 552 goto err_alloc_node; 410 553 } 411 554 412 - err = esw_qos_normalize_min_rate(esw, NULL, extack); 413 - if (err) { 414 - NL_SET_ERR_MSG_MOD(extack, "E-Switch nodes normalization failed"); 415 - goto err_min_rate; 416 - } 555 + esw_qos_normalize_min_rate(esw, NULL, extack); 417 556 trace_mlx5_esw_node_qos_create(esw->dev, node, node->ix); 418 557 419 558 return node; 420 559 421 - err_min_rate: 422 - __esw_qos_free_node(node); 423 560 err_alloc_node: 424 561 if (mlx5_destroy_scheduling_element_cmd(esw->dev, 425 562 SCHEDULING_HIERARCHY_E_SWITCH, ··· 446 595 return node; 447 596 } 448 597 449 - static int __esw_qos_destroy_node(struct mlx5_esw_sched_node *node, struct netlink_ext_ack *extack) 598 + static void __esw_qos_destroy_node(struct mlx5_esw_sched_node *node, struct netlink_ext_ack *extack) 450 599 { 451 600 struct mlx5_eswitch *esw = node->esw; 452 - int err; 453 601 454 602 trace_mlx5_esw_node_qos_destroy(esw->dev, node, node->ix); 455 - 456 - err = mlx5_destroy_scheduling_element_cmd(esw->dev, 457 - SCHEDULING_HIERARCHY_E_SWITCH, 458 - node->ix); 459 - if (err) 460 - NL_SET_ERR_MSG_MOD(extack, "E-Switch destroy TSAR_ID failed"); 461 - __esw_qos_free_node(node); 462 - 463 - err = esw_qos_normalize_min_rate(esw, NULL, extack); 464 - if (err) 465 - NL_SET_ERR_MSG_MOD(extack, "E-Switch nodes normalization failed"); 466 - 467 - 468 - return err; 603 + esw_qos_destroy_node(node, extack); 604 + esw_qos_normalize_min_rate(esw, NULL, extack); 469 605 } 470 606 471 607 static int esw_qos_create(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack) ··· 537 699 esw_qos_destroy(esw); 538 700 } 539 701 540 - static int esw_qos_vport_enable(struct mlx5_vport *vport, 541 - u32 max_rate, u32 bw_share, struct netlink_ext_ack *extack) 702 + static void esw_qos_vport_disable(struct mlx5_vport *vport, struct netlink_ext_ack *extack) 703 + { 704 + struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node; 705 + struct mlx5_esw_sched_node *parent = vport_node->parent; 706 + 707 + esw_qos_node_destroy_sched_element(vport_node, extack); 708 + 709 + vport_node->bw_share = 0; 710 + list_del_init(&vport_node->entry); 711 + esw_qos_normalize_min_rate(parent->esw, parent, extack); 712 + 713 + trace_mlx5_esw_vport_qos_destroy(vport_node->esw->dev, vport); 714 + } 715 + 716 + static int esw_qos_vport_enable(struct mlx5_vport *vport, struct mlx5_esw_sched_node *parent, 717 + struct netlink_ext_ack *extack) 718 + { 719 + int err; 720 + 721 + esw_assert_qos_lock_held(vport->dev->priv.eswitch); 722 + 723 + esw_qos_node_set_parent(vport->qos.sched_node, parent); 724 + err = esw_qos_vport_create_sched_element(vport->qos.sched_node, extack); 725 + if (err) 726 + return err; 727 + 728 + esw_qos_normalize_min_rate(parent->esw, parent, extack); 729 + 730 + return 0; 731 + } 732 + 733 + static int mlx5_esw_qos_vport_enable(struct mlx5_vport *vport, enum sched_node_type type, 734 + struct mlx5_esw_sched_node *parent, u32 max_rate, 735 + u32 min_rate, struct netlink_ext_ack *extack) 542 736 { 543 737 struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 544 - u32 sched_elem_ix; 738 + struct mlx5_esw_sched_node *sched_node; 545 739 int err; 546 740 547 741 esw_assert_qos_lock_held(esw); 548 - if (vport->qos.sched_node) 549 - return 0; 550 - 551 742 err = esw_qos_get(esw, extack); 552 743 if (err) 553 744 return err; 554 745 555 - err = esw_qos_vport_create_sched_element(vport, esw->qos.node0, max_rate, bw_share, 556 - &sched_elem_ix); 746 + parent = parent ?: esw->qos.node0; 747 + sched_node = __esw_qos_alloc_node(parent->esw, 0, type, parent); 748 + if (!sched_node) 749 + return -ENOMEM; 750 + 751 + sched_node->max_rate = max_rate; 752 + sched_node->min_rate = min_rate; 753 + sched_node->vport = vport; 754 + vport->qos.sched_node = sched_node; 755 + err = esw_qos_vport_enable(vport, parent, extack); 557 756 if (err) 558 - goto err_out; 559 - 560 - vport->qos.sched_node = __esw_qos_alloc_node(esw, sched_elem_ix, SCHED_NODE_TYPE_VPORT, 561 - esw->qos.node0); 562 - if (!vport->qos.sched_node) { 563 - err = -ENOMEM; 564 - goto err_alloc; 565 - } 566 - 567 - vport->qos.sched_node->vport = vport; 568 - 569 - trace_mlx5_esw_vport_qos_create(vport->dev, vport, bw_share, max_rate); 570 - 571 - return 0; 572 - 573 - err_alloc: 574 - if (mlx5_destroy_scheduling_element_cmd(esw->dev, 575 - SCHEDULING_HIERARCHY_E_SWITCH, sched_elem_ix)) 576 - esw_warn(esw->dev, "E-Switch destroy vport scheduling element failed.\n"); 577 - err_out: 578 - esw_qos_put(esw); 757 + esw_qos_put(esw); 579 758 580 759 return err; 581 760 } ··· 600 745 void mlx5_esw_qos_vport_disable(struct mlx5_vport *vport) 601 746 { 602 747 struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 603 - struct mlx5_esw_sched_node *vport_node; 604 - struct mlx5_core_dev *dev; 605 - int err; 748 + struct mlx5_esw_sched_node *parent; 606 749 607 750 lockdep_assert_held(&esw->state_lock); 608 751 esw_qos_lock(esw); 609 - vport_node = vport->qos.sched_node; 610 - if (!vport_node) 752 + if (!vport->qos.sched_node) 611 753 goto unlock; 612 - WARN(vport_node->parent != esw->qos.node0, 613 - "Disabling QoS on port before detaching it from node"); 614 754 615 - dev = vport_node->esw->dev; 616 - trace_mlx5_esw_vport_qos_destroy(dev, vport); 755 + parent = vport->qos.sched_node->parent; 756 + WARN(parent != esw->qos.node0, "Disabling QoS on port before detaching it from node"); 617 757 618 - err = mlx5_destroy_scheduling_element_cmd(dev, 619 - SCHEDULING_HIERARCHY_E_SWITCH, 620 - vport_node->ix); 621 - if (err) 622 - esw_warn(dev, 623 - "E-Switch destroy vport scheduling element failed (vport=%d,err=%d)\n", 624 - vport->vport, err); 625 - 626 - __esw_qos_free_node(vport_node); 627 - memset(&vport->qos, 0, sizeof(vport->qos)); 628 - 758 + esw_qos_vport_disable(vport, NULL); 759 + mlx5_esw_qos_vport_qos_free(vport); 629 760 esw_qos_put(esw); 630 761 unlock: 631 762 esw_qos_unlock(esw); 763 + } 764 + 765 + static int mlx5_esw_qos_set_vport_max_rate(struct mlx5_vport *vport, u32 max_rate, 766 + struct netlink_ext_ack *extack) 767 + { 768 + struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node; 769 + 770 + esw_assert_qos_lock_held(vport->dev->priv.eswitch); 771 + 772 + if (!vport_node) 773 + return mlx5_esw_qos_vport_enable(vport, SCHED_NODE_TYPE_VPORT, NULL, max_rate, 0, 774 + extack); 775 + else 776 + return esw_qos_sched_elem_config(vport_node, max_rate, vport_node->bw_share, 777 + extack); 778 + } 779 + 780 + static int mlx5_esw_qos_set_vport_min_rate(struct mlx5_vport *vport, u32 min_rate, 781 + struct netlink_ext_ack *extack) 782 + { 783 + struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node; 784 + 785 + esw_assert_qos_lock_held(vport->dev->priv.eswitch); 786 + 787 + if (!vport_node) 788 + return mlx5_esw_qos_vport_enable(vport, SCHED_NODE_TYPE_VPORT, NULL, 0, min_rate, 789 + extack); 790 + else 791 + return esw_qos_set_node_min_rate(vport_node, min_rate, extack); 632 792 } 633 793 634 794 int mlx5_esw_qos_set_vport_rate(struct mlx5_vport *vport, u32 max_rate, u32 min_rate) ··· 652 782 int err; 653 783 654 784 esw_qos_lock(esw); 655 - err = esw_qos_vport_enable(vport, 0, 0, NULL); 656 - if (err) 657 - goto unlock; 658 - 659 - err = esw_qos_set_vport_min_rate(vport, min_rate, NULL); 785 + err = mlx5_esw_qos_set_vport_min_rate(vport, min_rate, NULL); 660 786 if (!err) 661 - err = esw_qos_set_vport_max_rate(vport, max_rate, NULL); 662 - unlock: 787 + err = mlx5_esw_qos_set_vport_max_rate(vport, max_rate, NULL); 663 788 esw_qos_unlock(esw); 664 789 return err; 665 790 } ··· 672 807 } 673 808 esw_qos_unlock(esw); 674 809 return enabled; 810 + } 811 + 812 + static int esw_qos_vport_update_parent(struct mlx5_vport *vport, struct mlx5_esw_sched_node *parent, 813 + struct netlink_ext_ack *extack) 814 + { 815 + struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 816 + struct mlx5_esw_sched_node *curr_parent; 817 + int err; 818 + 819 + esw_assert_qos_lock_held(esw); 820 + curr_parent = vport->qos.sched_node->parent; 821 + parent = parent ?: esw->qos.node0; 822 + if (curr_parent == parent) 823 + return 0; 824 + 825 + esw_qos_vport_disable(vport, extack); 826 + 827 + err = esw_qos_vport_enable(vport, parent, extack); 828 + if (err) { 829 + if (esw_qos_vport_enable(vport, curr_parent, NULL)) 830 + esw_warn(parent->esw->dev, "vport restore QoS failed (vport=%d)\n", 831 + vport->vport); 832 + } 833 + 834 + return err; 675 835 } 676 836 677 837 static u32 mlx5_esw_qos_lag_link_speed_get_locked(struct mlx5_core_dev *mdev) ··· 765 875 766 876 int mlx5_esw_qos_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num, u32 rate_mbps) 767 877 { 768 - u32 ctx[MLX5_ST_SZ_DW(scheduling_context)] = {}; 769 878 struct mlx5_vport *vport; 770 879 u32 link_speed_max; 771 - u32 bitmask; 772 880 int err; 773 881 774 882 vport = mlx5_eswitch_get_vport(esw, vport_num); ··· 785 897 } 786 898 787 899 esw_qos_lock(esw); 788 - if (!vport->qos.sched_node) { 789 - /* Eswitch QoS wasn't enabled yet. Enable it and vport QoS. */ 790 - err = esw_qos_vport_enable(vport, rate_mbps, 0, NULL); 791 - } else { 792 - struct mlx5_core_dev *dev = vport->qos.sched_node->parent->esw->dev; 793 - 794 - MLX5_SET(scheduling_context, ctx, max_average_bw, rate_mbps); 795 - bitmask = MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW; 796 - err = mlx5_modify_scheduling_element_cmd(dev, 797 - SCHEDULING_HIERARCHY_E_SWITCH, 798 - ctx, 799 - vport->qos.sched_node->ix, 800 - bitmask); 801 - } 900 + err = mlx5_esw_qos_set_vport_max_rate(vport, rate_mbps, NULL); 802 901 esw_qos_unlock(esw); 803 902 804 903 return err; ··· 856 981 return err; 857 982 858 983 esw_qos_lock(esw); 859 - err = esw_qos_vport_enable(vport, 0, 0, extack); 860 - if (err) 861 - goto unlock; 862 - 863 - err = esw_qos_set_vport_min_rate(vport, tx_share, extack); 864 - unlock: 984 + err = mlx5_esw_qos_set_vport_min_rate(vport, tx_share, extack); 865 985 esw_qos_unlock(esw); 866 986 return err; 867 987 } ··· 877 1007 return err; 878 1008 879 1009 esw_qos_lock(esw); 880 - err = esw_qos_vport_enable(vport, 0, 0, extack); 881 - if (err) 882 - goto unlock; 883 - 884 - err = esw_qos_set_vport_max_rate(vport, tx_max, extack); 885 - unlock: 1010 + err = mlx5_esw_qos_set_vport_max_rate(vport, tx_max, extack); 886 1011 esw_qos_unlock(esw); 887 1012 return err; 888 1013 } ··· 911 1046 return err; 912 1047 913 1048 esw_qos_lock(esw); 914 - err = esw_qos_set_node_max_rate(node, tx_max, extack); 1049 + err = esw_qos_sched_elem_config(node, tx_max, node->bw_share, extack); 915 1050 esw_qos_unlock(esw); 916 1051 return err; 917 1052 } ··· 952 1087 { 953 1088 struct mlx5_esw_sched_node *node = priv; 954 1089 struct mlx5_eswitch *esw = node->esw; 955 - int err; 956 1090 957 1091 esw_qos_lock(esw); 958 - err = __esw_qos_destroy_node(node, extack); 1092 + __esw_qos_destroy_node(node, extack); 959 1093 esw_qos_put(esw); 960 1094 esw_qos_unlock(esw); 961 - return err; 1095 + return 0; 962 1096 } 963 1097 964 - int mlx5_esw_qos_vport_update_node(struct mlx5_vport *vport, 965 - struct mlx5_esw_sched_node *node, 966 - struct netlink_ext_ack *extack) 1098 + int mlx5_esw_qos_vport_update_parent(struct mlx5_vport *vport, struct mlx5_esw_sched_node *parent, 1099 + struct netlink_ext_ack *extack) 967 1100 { 968 1101 struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 969 1102 int err = 0; 970 1103 971 - if (node && node->esw != esw) { 1104 + if (parent && parent->esw != esw) { 972 1105 NL_SET_ERR_MSG_MOD(extack, "Cross E-Switch scheduling is not supported"); 973 1106 return -EOPNOTSUPP; 974 1107 } 975 1108 976 1109 esw_qos_lock(esw); 977 - if (!vport->qos.sched_node && !node) 978 - goto unlock; 979 - 980 - err = esw_qos_vport_enable(vport, 0, 0, extack); 981 - if (!err) 982 - err = esw_qos_vport_update_node(vport, node, extack); 983 - unlock: 1110 + if (!vport->qos.sched_node && parent) 1111 + err = mlx5_esw_qos_vport_enable(vport, SCHED_NODE_TYPE_VPORT, parent, 0, 0, extack); 1112 + else if (vport->qos.sched_node) 1113 + err = esw_qos_vport_update_parent(vport, parent, extack); 984 1114 esw_qos_unlock(esw); 985 1115 return err; 986 1116 } ··· 989 1129 struct mlx5_vport *vport = priv; 990 1130 991 1131 if (!parent) 992 - return mlx5_esw_qos_vport_update_node(vport, NULL, extack); 1132 + return mlx5_esw_qos_vport_update_parent(vport, NULL, extack); 993 1133 994 1134 node = parent_priv; 995 - return mlx5_esw_qos_vport_update_node(vport, node, extack); 1135 + return mlx5_esw_qos_vport_update_parent(vport, node, extack); 996 1136 }
+1
drivers/net/ethernet/mellanox/mlx5/core/esw/qos.h
··· 13 13 bool mlx5_esw_qos_get_vport_rate(struct mlx5_vport *vport, u32 *max_rate, u32 *min_rate); 14 14 void mlx5_esw_qos_vport_disable(struct mlx5_vport *vport); 15 15 16 + void mlx5_esw_qos_vport_qos_free(struct mlx5_vport *vport); 16 17 u32 mlx5_esw_qos_vport_get_sched_elem_ix(const struct mlx5_vport *vport); 17 18 struct mlx5_esw_sched_node *mlx5_esw_qos_vport_get_parent(const struct mlx5_vport *vport); 18 19
+2 -5
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
··· 1061 1061 unsigned long i; 1062 1062 1063 1063 mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) { 1064 - kfree(vport->qos.sched_node); 1065 - memset(&vport->qos, 0, sizeof(vport->qos)); 1064 + mlx5_esw_qos_vport_qos_free(vport); 1066 1065 memset(&vport->info, 0, sizeof(vport->info)); 1067 1066 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; 1068 1067 } ··· 1073 1074 unsigned long i; 1074 1075 1075 1076 mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) { 1076 - kfree(vport->qos.sched_node); 1077 - memset(&vport->qos, 0, sizeof(vport->qos)); 1077 + mlx5_esw_qos_vport_qos_free(vport); 1078 1078 memset(&vport->info, 0, sizeof(vport->info)); 1079 1079 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; 1080 1080 } ··· 1488 1490 if (esw->mode == MLX5_ESWITCH_LEGACY) { 1489 1491 err = esw_legacy_enable(esw); 1490 1492 } else { 1491 - mlx5_rescan_drivers(esw->dev); 1492 1493 err = esw_offloads_enable(esw); 1493 1494 } 1494 1495
+2 -3
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
··· 427 427 u16 vport_num, bool setting); 428 428 int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport, 429 429 u32 max_rate, u32 min_rate); 430 - int mlx5_esw_qos_vport_update_node(struct mlx5_vport *vport, 431 - struct mlx5_esw_sched_node *node, 432 - struct netlink_ext_ack *extack); 430 + int mlx5_esw_qos_vport_update_parent(struct mlx5_vport *vport, struct mlx5_esw_sched_node *node, 431 + struct netlink_ext_ack *extack); 433 432 int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting); 434 433 int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting); 435 434 int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
+21 -5
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
··· 2332 2332 return err; 2333 2333 } 2334 2334 2335 + static void esw_mode_change(struct mlx5_eswitch *esw, u16 mode) 2336 + { 2337 + mlx5_devcom_comp_lock(esw->dev->priv.hca_devcom_comp); 2338 + 2339 + if (esw->dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_IB_ADEV) { 2340 + esw->mode = mode; 2341 + mlx5_devcom_comp_unlock(esw->dev->priv.hca_devcom_comp); 2342 + return; 2343 + } 2344 + 2345 + esw->dev->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 2346 + mlx5_rescan_drivers_locked(esw->dev); 2347 + esw->mode = mode; 2348 + esw->dev->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 2349 + mlx5_rescan_drivers_locked(esw->dev); 2350 + mlx5_devcom_comp_unlock(esw->dev->priv.hca_devcom_comp); 2351 + } 2352 + 2335 2353 static int esw_offloads_start(struct mlx5_eswitch *esw, 2336 2354 struct netlink_ext_ack *extack) 2337 2355 { 2338 2356 int err; 2339 2357 2340 - esw->mode = MLX5_ESWITCH_OFFLOADS; 2358 + esw_mode_change(esw, MLX5_ESWITCH_OFFLOADS); 2341 2359 err = mlx5_eswitch_enable_locked(esw, esw->dev->priv.sriov.num_vfs); 2342 2360 if (err) { 2343 2361 NL_SET_ERR_MSG_MOD(extack, 2344 2362 "Failed setting eswitch to offloads"); 2345 - esw->mode = MLX5_ESWITCH_LEGACY; 2346 - mlx5_rescan_drivers(esw->dev); 2363 + esw_mode_change(esw, MLX5_ESWITCH_LEGACY); 2347 2364 return err; 2348 2365 } 2349 2366 if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) { ··· 3601 3584 { 3602 3585 int err; 3603 3586 3604 - esw->mode = MLX5_ESWITCH_LEGACY; 3587 + esw_mode_change(esw, MLX5_ESWITCH_LEGACY); 3605 3588 3606 3589 /* If changing from switchdev to legacy mode without sriov enabled, 3607 3590 * no need to create legacy fdb. ··· 3787 3770 err = esw_offloads_start(esw, extack); 3788 3771 } else if (mode == DEVLINK_ESWITCH_MODE_LEGACY) { 3789 3772 err = esw_offloads_stop(esw, extack); 3790 - mlx5_rescan_drivers(esw->dev); 3791 3773 } else { 3792 3774 err = -EINVAL; 3793 3775 }