FILE
hinic3_hw_cfg.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.c
1// SPDX-License-Identifier: GPL-2.0 2// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. 3 4#include <linux/device.h> 5 6#include "hinic3_hw_cfg.h" 7#include "hinic3_hwdev.h" 8#include "hinic3_hwif.h" 9#include "hinic3_mbox.h" 10 11#define HINIC3_CFG_MAX_QP 256 12 13static void hinic3_parse_pub_res_cap(struct hinic3_hwdev *hwdev, 14 struct hinic3_dev_cap *cap, 15 const struct cfg_cmd_dev_cap *dev_cap, 16 enum hinic3_func_type type) 17{ 18 cap->port_id = dev_cap->port_id; 19 cap->supp_svcs_bitmap = dev_cap->svc_cap_en; 20} 21 22static void hinic3_parse_l2nic_res_cap(struct hinic3_hwdev *hwdev, 23 struct hinic3_dev_cap *cap, 24 const struct cfg_cmd_dev_cap *dev_cap, 25 enum hinic3_func_type type) 26{ 27 struct hinic3_nic_service_cap *nic_svc_cap = &cap->nic_svc_cap; 28 29 nic_svc_cap->max_sqs = min(dev_cap->nic_max_sq_id + 1, 30 HINIC3_CFG_MAX_QP); 31} 32 33static void hinic3_parse_dev_cap(struct hinic3_hwdev *hwdev, 34 const struct cfg_cmd_dev_cap *dev_cap, 35 enum hinic3_func_type type) 36{ 37 struct hinic3_dev_cap *cap = &hwdev->cfg_mgmt->cap; 38 39 /* Public resource */ 40 hinic3_parse_pub_res_cap(hwdev, cap, dev_cap, type); 41 42 /* L2 NIC resource */ 43 if (hinic3_support_nic(hwdev)) 44 hinic3_parse_l2nic_res_cap(hwdev, cap, dev_cap, type); 45} 46 47static int get_cap_from_fw(struct hinic3_hwdev *hwdev, 48 enum hinic3_func_type type) 49{ 50 struct mgmt_msg_params msg_params = {}; 51 struct cfg_cmd_dev_cap dev_cap = {}; 52 int err; 53 54 dev_cap.func_id = hinic3_global_func_id(hwdev); 55 56 mgmt_msg_params_init_default(&msg_params, &dev_cap, sizeof(dev_cap)); 57 58 err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_CFGM, 59 CFG_CMD_GET_DEV_CAP, &msg_params); 60 if (err || dev_cap.head.status) { 61 dev_err(hwdev->dev, 62 "Failed to get capability from FW, err: %d, status: 0x%x\n", 63 err, dev_cap.head.status); 64 return -EIO; 65 } 66 67 hinic3_parse_dev_cap(hwdev, &dev_cap, type); 68 69 return 0; 70} 71 72static int hinic3_init_irq_info(struct hinic3_hwdev *hwdev) 73{ 74 struct hinic3_cfg_mgmt_info *cfg_mgmt = hwdev->cfg_mgmt; 75 struct hinic3_hwif *hwif = hwdev->hwif; 76 u16 intr_num = hwif->attr.num_irqs; 77 struct hinic3_irq_info *irq_info; 78 u16 intr_needed; 79 80 intr_needed = hwif->attr.msix_flex_en ? (hwif->attr.num_aeqs + 81 hwif->attr.num_ceqs + hwif->attr.num_sq) : intr_num; 82 if (intr_needed > intr_num) { 83 dev_warn(hwdev->dev, "Irq num cfg %d is less than the needed irq num %d msix_flex_en %d\n", 84 intr_num, intr_needed, hwdev->hwif->attr.msix_flex_en); 85 intr_needed = intr_num; 86 } 87 88 irq_info = &cfg_mgmt->irq_info; 89 irq_info->irq = kcalloc(intr_num, sizeof(struct hinic3_irq), 90 GFP_KERNEL); 91 if (!irq_info->irq) 92 return -ENOMEM; 93 94 irq_info->num_irq_hw = intr_needed; 95 mutex_init(&irq_info->irq_mutex); 96 97 return 0; 98} 99 100static int hinic3_init_irq_alloc_info(struct hinic3_hwdev *hwdev) 101{ 102 struct hinic3_cfg_mgmt_info *cfg_mgmt = hwdev->cfg_mgmt; 103 struct hinic3_irq *irq = cfg_mgmt->irq_info.irq; 104 u16 nreq = cfg_mgmt->irq_info.num_irq_hw; 105 struct pci_dev *pdev = hwdev->pdev; 106 int actual_irq; 107 u16 i; 108 109 actual_irq = pci_alloc_irq_vectors(pdev, 2, nreq, PCI_IRQ_MSIX); 110 if (actual_irq < 0) { 111 dev_err(hwdev->dev, "Alloc msix entries with threshold 2 failed. actual_irq: %d\n", 112 actual_irq); 113 return -ENOMEM; 114 } 115 116 nreq = actual_irq; 117 cfg_mgmt->irq_info.num_irq = nreq; 118 119 for (i = 0; i < nreq; ++i) { 120 irq[i].msix_entry_idx = i; 121 irq[i].irq_id = pci_irq_vector(pdev, i); 122 irq[i].allocated = false; 123 } 124 125 return 0; 126} 127 128int hinic3_init_cfg_mgmt(struct hinic3_hwdev *hwdev) 129{ 130 struct hinic3_cfg_mgmt_info *cfg_mgmt; 131 int err; 132 133 cfg_mgmt = kzalloc(sizeof(*cfg_mgmt), GFP_KERNEL); 134 if (!cfg_mgmt) 135 return -ENOMEM; 136 137 hwdev->cfg_mgmt = cfg_mgmt; 138 139 err = hinic3_init_irq_info(hwdev); 140 if (err) { 141 dev_err(hwdev->dev, "Failed to init hinic3_irq_mgmt_info, err: %d\n", 142 err); 143 goto err_free_cfg_mgmt; 144 } 145 146 err = hinic3_init_irq_alloc_info(hwdev); 147 if (err) { 148 dev_err(hwdev->dev, "Failed to init hinic3_irq_info, err: %d\n", 149 err); 150 goto err_free_irq_info; 151 } 152 153 return 0; 154 155err_free_irq_info: 156 kfree(cfg_mgmt->irq_info.irq); 157 cfg_mgmt->irq_info.irq = NULL; 158err_free_cfg_mgmt: 159 kfree(cfg_mgmt); 160 161 return err; 162} 163 164void hinic3_free_cfg_mgmt(struct hinic3_hwdev *hwdev) 165{ 166 struct hinic3_cfg_mgmt_info *cfg_mgmt = hwdev->cfg_mgmt; 167 168 pci_free_irq_vectors(hwdev->pdev); 169 kfree(cfg_mgmt->irq_info.irq); 170 cfg_mgmt->irq_info.irq = NULL; 171 kfree(cfg_mgmt); 172} 173 174int hinic3_alloc_irqs(struct hinic3_hwdev *hwdev, u16 num, 175 struct msix_entry *alloc_arr, u16 *act_num) 176{ 177 struct hinic3_irq_info *irq_info; 178 struct hinic3_irq *curr; 179 u16 i, found = 0; 180 181 irq_info = &hwdev->cfg_mgmt->irq_info; 182 mutex_lock(&irq_info->irq_mutex); 183 for (i = 0; i < irq_info->num_irq && found < num; i++) { 184 curr = irq_info->irq + i; 185 if (curr->allocated) 186 continue; 187 curr->allocated = true; 188 alloc_arr[found].vector = curr->irq_id; 189 alloc_arr[found].entry = curr->msix_entry_idx; 190 found++; 191 } 192 mutex_unlock(&irq_info->irq_mutex); 193 194 *act_num = found; 195 196 return found == 0 ? -ENOMEM : 0; 197} 198 199void hinic3_free_irq(struct hinic3_hwdev *hwdev, u32 irq_id) 200{ 201 struct hinic3_irq_info *irq_info; 202 struct hinic3_irq *curr; 203 u16 i; 204 205 irq_info = &hwdev->cfg_mgmt->irq_info; 206 mutex_lock(&irq_info->irq_mutex); 207 for (i = 0; i < irq_info->num_irq; i++) { 208 curr = irq_info->irq + i; 209 if (curr->irq_id == irq_id) { 210 curr->allocated = false; 211 break; 212 } 213 } 214 mutex_unlock(&irq_info->irq_mutex); 215} 216 217int hinic3_init_capability(struct hinic3_hwdev *hwdev) 218{ 219 return get_cap_from_fw(hwdev, HINIC3_FUNC_TYPE_VF); 220} 221 222bool hinic3_support_nic(struct hinic3_hwdev *hwdev) 223{ 224 return hwdev->cfg_mgmt->cap.supp_svcs_bitmap & 225 BIT(HINIC3_SERVICE_T_NIC); 226} 227 228u16 hinic3_func_max_qnum(struct hinic3_hwdev *hwdev) 229{ 230 return hwdev->cfg_mgmt->cap.nic_svc_cap.max_sqs; 231} 232 233u8 hinic3_physical_port_id(struct hinic3_hwdev *hwdev) 234{ 235 return hwdev->cfg_mgmt->cap.port_id; 236}
~/
Read-only file preview.