FILE
bnge_core.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/broadcom/bnge/bnge_core.c
1// SPDX-License-Identifier: GPL-2.0 2// Copyright (c) 2025 Broadcom. 3 4#include <linux/init.h> 5#include <linux/crash_dump.h> 6#include <linux/module.h> 7#include <linux/pci.h> 8 9#include "bnge.h" 10#include "bnge_devlink.h" 11#include "bnge_hwrm.h" 12#include "bnge_hwrm_lib.h" 13 14MODULE_LICENSE("GPL"); 15MODULE_DESCRIPTION(DRV_SUMMARY); 16 17char bnge_driver_name[] = DRV_NAME; 18 19static const struct { 20 char *name; 21} board_info[] = { 22 [BCM57708] = { "Broadcom BCM57708 ThorUltra 50Gb/100Gb/200Gb/400Gb/800Gb Ethernet" }, 23}; 24 25static const struct pci_device_id bnge_pci_tbl[] = { 26 { PCI_VDEVICE(BROADCOM, 0x1780), .driver_data = BCM57708 }, 27 /* Required last entry */ 28 {0, } 29}; 30MODULE_DEVICE_TABLE(pci, bnge_pci_tbl); 31 32static void bnge_print_device_info(struct pci_dev *pdev, enum board_idx idx) 33{ 34 struct device *dev = &pdev->dev; 35 36 dev_info(dev, "%s found at mem %lx\n", board_info[idx].name, 37 (long)pci_resource_start(pdev, 0)); 38 39 pcie_print_link_status(pdev); 40} 41 42bool bnge_aux_registered(struct bnge_dev *bd) 43{ 44 struct bnge_auxr_dev *ba_dev = bd->auxr_dev; 45 46 if (ba_dev && ba_dev->auxr_info->msix_requested) 47 return true; 48 49 return false; 50} 51 52static void bnge_nvm_cfg_ver_get(struct bnge_dev *bd) 53{ 54 struct hwrm_nvm_get_dev_info_output nvm_info; 55 56 if (!bnge_hwrm_nvm_dev_info(bd, &nvm_info)) 57 snprintf(bd->nvm_cfg_ver, FW_VER_STR_LEN, "%d.%d.%d", 58 nvm_info.nvm_cfg_ver_maj, nvm_info.nvm_cfg_ver_min, 59 nvm_info.nvm_cfg_ver_upd); 60} 61 62static int bnge_func_qcaps(struct bnge_dev *bd) 63{ 64 int rc; 65 66 rc = bnge_hwrm_func_qcaps(bd); 67 if (rc) 68 return rc; 69 70 rc = bnge_hwrm_queue_qportcfg(bd); 71 if (rc) { 72 dev_err(bd->dev, "query qportcfg failure rc: %d\n", rc); 73 return rc; 74 } 75 76 rc = bnge_hwrm_func_resc_qcaps(bd); 77 if (rc) { 78 dev_err(bd->dev, "query resc caps failure rc: %d\n", rc); 79 return rc; 80 } 81 82 rc = bnge_hwrm_func_qcfg(bd); 83 if (rc) { 84 dev_err(bd->dev, "query config failure rc: %d\n", rc); 85 return rc; 86 } 87 88 rc = bnge_hwrm_vnic_qcaps(bd); 89 if (rc) { 90 dev_err(bd->dev, "vnic caps failure rc: %d\n", rc); 91 return rc; 92 } 93 94 return 0; 95} 96 97static void bnge_fw_unregister_dev(struct bnge_dev *bd) 98{ 99 /* ctx mem free after unrgtr only */ 100 bnge_hwrm_func_drv_unrgtr(bd); 101 bnge_free_ctx_mem(bd); 102} 103 104static void bnge_set_dflt_rss_hash_type(struct bnge_dev *bd) 105{ 106 bd->rss_hash_cfg = VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4 | 107 VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4 | 108 VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6 | 109 VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6 | 110 VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4 | 111 VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6; 112} 113 114static int bnge_fw_register_dev(struct bnge_dev *bd) 115{ 116 int rc; 117 118 bd->fw_cap = 0; 119 rc = bnge_hwrm_ver_get(bd); 120 if (rc) { 121 dev_err(bd->dev, "Get Version command failed rc: %d\n", rc); 122 return rc; 123 } 124 125 bnge_nvm_cfg_ver_get(bd); 126 127 rc = bnge_hwrm_func_reset(bd); 128 if (rc) { 129 dev_err(bd->dev, "Failed to reset function rc: %d\n", rc); 130 return rc; 131 } 132 133 bnge_hwrm_fw_set_time(bd); 134 135 rc = bnge_hwrm_func_drv_rgtr(bd); 136 if (rc) { 137 dev_err(bd->dev, "Failed to rgtr with firmware rc: %d\n", rc); 138 return rc; 139 } 140 141 rc = bnge_alloc_ctx_mem(bd); 142 if (rc) { 143 dev_err(bd->dev, "Failed to allocate ctx mem rc: %d\n", rc); 144 goto err_func_unrgtr; 145 } 146 147 /* Get the resources and configuration from firmware */ 148 rc = bnge_func_qcaps(bd); 149 if (rc) { 150 dev_err(bd->dev, "Failed initial configuration rc: %d\n", rc); 151 rc = -ENODEV; 152 goto err_func_unrgtr; 153 } 154 155 bnge_set_dflt_rss_hash_type(bd); 156 157 return 0; 158 159err_func_unrgtr: 160 bnge_fw_unregister_dev(bd); 161 return rc; 162} 163 164static void bnge_pci_disable(struct pci_dev *pdev) 165{ 166 pci_release_regions(pdev); 167 if (pci_is_enabled(pdev)) 168 pci_disable_device(pdev); 169} 170 171static int bnge_pci_enable(struct pci_dev *pdev) 172{ 173 int rc; 174 175 rc = pci_enable_device(pdev); 176 if (rc) { 177 dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n"); 178 return rc; 179 } 180 181 if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { 182 dev_err(&pdev->dev, 183 "Cannot find PCI device base address, aborting\n"); 184 rc = -ENODEV; 185 goto err_pci_disable; 186 } 187 188 rc = pci_request_regions(pdev, bnge_driver_name); 189 if (rc) { 190 dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n"); 191 goto err_pci_disable; 192 } 193 194 dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 195 196 pci_set_master(pdev); 197 198 return 0; 199 200err_pci_disable: 201 pci_disable_device(pdev); 202 return rc; 203} 204 205static void bnge_unmap_bars(struct pci_dev *pdev) 206{ 207 struct bnge_dev *bd = pci_get_drvdata(pdev); 208 209 if (bd->bar1) { 210 pci_iounmap(pdev, bd->bar1); 211 bd->bar1 = NULL; 212 } 213 214 if (bd->bar0) { 215 pci_iounmap(pdev, bd->bar0); 216 bd->bar0 = NULL; 217 } 218} 219 220static void bnge_set_max_func_irqs(struct bnge_dev *bd, 221 unsigned int max_irqs) 222{ 223 bd->hw_resc.max_irqs = max_irqs; 224} 225 226static int bnge_get_max_irq(struct pci_dev *pdev) 227{ 228 u16 ctrl; 229 230 pci_read_config_word(pdev, pdev->msix_cap + PCI_MSIX_FLAGS, &ctrl); 231 return (ctrl & PCI_MSIX_FLAGS_QSIZE) + 1; 232} 233 234static int bnge_map_db_bar(struct bnge_dev *bd) 235{ 236 if (!bd->db_size) 237 return -ENODEV; 238 239 bd->bar1 = pci_iomap(bd->pdev, 2, bd->db_size); 240 if (!bd->bar1) 241 return -ENOMEM; 242 243 return 0; 244} 245 246static int bnge_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) 247{ 248 unsigned int max_irqs; 249 struct bnge_dev *bd; 250 int rc; 251 252 if (pci_is_bridge(pdev)) 253 return -ENODEV; 254 255 if (!pdev->msix_cap) { 256 dev_err(&pdev->dev, "MSIX capability missing, aborting\n"); 257 return -ENODEV; 258 } 259 260 if (is_kdump_kernel()) { 261 pci_clear_master(pdev); 262 pcie_flr(pdev); 263 } 264 265 rc = bnge_pci_enable(pdev); 266 if (rc) 267 return rc; 268 269 bnge_print_device_info(pdev, ent->driver_data); 270 271 bd = bnge_devlink_alloc(pdev); 272 if (!bd) { 273 dev_err(&pdev->dev, "Devlink allocation failed\n"); 274 rc = -ENOMEM; 275 goto err_pci_disable; 276 } 277 278 bd->bar0 = pci_ioremap_bar(pdev, 0); 279 if (!bd->bar0) { 280 dev_err(&pdev->dev, "Failed mapping BAR-0, aborting\n"); 281 rc = -ENOMEM; 282 goto err_devl_free; 283 } 284 285 rc = bnge_init_hwrm_resources(bd); 286 if (rc) 287 goto err_bar_unmap; 288 289 rc = bnge_fw_register_dev(bd); 290 if (rc) { 291 dev_err(&pdev->dev, "Failed to register with firmware rc = %d\n", rc); 292 goto err_hwrm_cleanup; 293 } 294 295 bnge_devlink_register(bd); 296 297 max_irqs = bnge_get_max_irq(pdev); 298 bnge_set_max_func_irqs(bd, max_irqs); 299 300 bnge_aux_init_dflt_config(bd); 301 302 rc = bnge_net_init_dflt_config(bd); 303 if (rc) { 304 dev_err(&pdev->dev, "Error setting up default cfg to netdev rc = %d\n", 305 rc); 306 goto err_fw_reg; 307 } 308 309 rc = bnge_map_db_bar(bd); 310 if (rc) { 311 dev_err(&pdev->dev, "Failed mapping doorbell BAR rc = %d, aborting\n", 312 rc); 313 goto err_config_uninit; 314 } 315 316#if BITS_PER_LONG == 32 317 spin_lock_init(&bd->db_lock); 318#endif 319 320 bnge_rdma_aux_device_init(bd); 321 322 rc = bnge_alloc_irqs(bd); 323 if (rc) { 324 dev_err(&pdev->dev, "Error IRQ allocation rc = %d\n", rc); 325 goto err_uninit_auxr; 326 } 327 328 rc = bnge_netdev_alloc(bd, max_irqs); 329 if (rc) 330 goto err_free_irq; 331 332 bnge_rdma_aux_device_add(bd); 333 334 pci_save_state(pdev); 335 336 return 0; 337 338err_free_irq: 339 bnge_free_irqs(bd); 340 341err_uninit_auxr: 342 bnge_rdma_aux_device_uninit(bd); 343 344err_config_uninit: 345 bnge_net_uninit_dflt_config(bd); 346 347err_fw_reg: 348 bnge_devlink_unregister(bd); 349 bnge_fw_unregister_dev(bd); 350 351err_hwrm_cleanup: 352 bnge_cleanup_hwrm_resources(bd); 353 354err_bar_unmap: 355 bnge_unmap_bars(pdev); 356 357err_devl_free: 358 bnge_devlink_free(bd); 359 360err_pci_disable: 361 bnge_pci_disable(pdev); 362 return rc; 363} 364 365static void bnge_remove_one(struct pci_dev *pdev) 366{ 367 struct bnge_dev *bd = pci_get_drvdata(pdev); 368 369 bnge_rdma_aux_device_del(bd); 370 371 bnge_netdev_free(bd); 372 373 bnge_free_irqs(bd); 374 375 bnge_rdma_aux_device_uninit(bd); 376 377 bnge_net_uninit_dflt_config(bd); 378 379 bnge_devlink_unregister(bd); 380 381 bnge_fw_unregister_dev(bd); 382 383 bnge_cleanup_hwrm_resources(bd); 384 385 bnge_unmap_bars(pdev); 386 387 bnge_devlink_free(bd); 388 389 bnge_pci_disable(pdev); 390} 391 392static void bnge_shutdown(struct pci_dev *pdev) 393{ 394 pci_disable_device(pdev); 395 396 if (system_state == SYSTEM_POWER_OFF) { 397 pci_wake_from_d3(pdev, 0); 398 pci_set_power_state(pdev, PCI_D3hot); 399 } 400} 401 402static struct pci_driver bnge_driver = { 403 .name = bnge_driver_name, 404 .id_table = bnge_pci_tbl, 405 .probe = bnge_probe_one, 406 .remove = bnge_remove_one, 407 .shutdown = bnge_shutdown, 408}; 409 410static int __init bnge_init_module(void) 411{ 412 return pci_register_driver(&bnge_driver); 413} 414module_init(bnge_init_module); 415 416static void __exit bnge_exit_module(void) 417{ 418 pci_unregister_driver(&bnge_driver); 419} 420module_exit(bnge_exit_module);
~/
Read-only file preview.