1*3d6792eaSManish Awasthi // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2*3d6792eaSManish Awasthi /* Copyright (c) 2025, Microsoft Corporation. */ 3*3d6792eaSManish Awasthi #include <linux/module.h> 4*3d6792eaSManish Awasthi #include <linux/bitmap.h> 5*3d6792eaSManish Awasthi #include <linux/cdx/cdx_bus.h> 6*3d6792eaSManish Awasthi #include <linux/msi.h> 7*3d6792eaSManish Awasthi #include <linux/xarray.h> 8*3d6792eaSManish Awasthi 9*3d6792eaSManish Awasthi #include <net/mana/mana.h> 10*3d6792eaSManish Awasthi 11*3d6792eaSManish Awasthi #define MANA_CDX_GDMA_REGS_SIZE (GDMA_REG_SHM_OFFSET + sizeof(u64)) 12*3d6792eaSManish Awasthi 13*3d6792eaSManish Awasthi static int mana_cdx_msix_virq(struct gdma_context *gc, int msi) 14*3d6792eaSManish Awasthi { 15*3d6792eaSManish Awasthi unsigned int virq = msi_get_virq(gc->dev, msi); 16*3d6792eaSManish Awasthi 17*3d6792eaSManish Awasthi /* CDX allocates its whole vector pool in mana_cdx_setup_hwc_irqs(), 18*3d6792eaSManish Awasthi * so a vector with no Linux IRQ was never part of that pool. 19*3d6792eaSManish Awasthi */ 20*3d6792eaSManish Awasthi return virq ? virq : -EINVAL; 21*3d6792eaSManish Awasthi } 22*3d6792eaSManish Awasthi 23*3d6792eaSManish Awasthi static int mana_cdx_dev_reset(struct gdma_context *gc) 24*3d6792eaSManish Awasthi { 25*3d6792eaSManish Awasthi return cdx_dev_reset(gc->dev); 26*3d6792eaSManish Awasthi } 27*3d6792eaSManish Awasthi 28*3d6792eaSManish Awasthi static int mana_cdx_setup_hwc_irqs(struct gdma_context *gc) 29*3d6792eaSManish Awasthi { 30*3d6792eaSManish Awasthi struct cdx_device *cdx_dev = to_cdx_device(gc->dev); 31*3d6792eaSManish Awasthi struct gdma_irq_context *gic; 32*3d6792eaSManish Awasthi unsigned int max_irqs; 33*3d6792eaSManish Awasthi int nvec; 34*3d6792eaSManish Awasthi int err, i = 0, j; 35*3d6792eaSManish Awasthi 36*3d6792eaSManish Awasthi max_irqs = cdx_dev->num_msi; 37*3d6792eaSManish Awasthi 38*3d6792eaSManish Awasthi /* Need 1 IRQ for HWC and at least 1 for the data path queues */ 39*3d6792eaSManish Awasthi if (max_irqs < 2) { 40*3d6792eaSManish Awasthi dev_err(&cdx_dev->dev, "Not enough MSI vectors: %u\n", 41*3d6792eaSManish Awasthi max_irqs); 42*3d6792eaSManish Awasthi return -ENOSPC; 43*3d6792eaSManish Awasthi } 44*3d6792eaSManish Awasthi 45*3d6792eaSManish Awasthi /* Constrain the device to 32-bit DMA addresses, for both the MSI 46*3d6792eaSManish Awasthi * doorbells and the data path buffers, and never widen it afterwards. 47*3d6792eaSManish Awasthi * 48*3d6792eaSManish Awasthi * The MSI doorbell address has to land within the low 4GB. The data 49*3d6792eaSManish Awasthi * path carries a second constraint: the device does not perform 50*3d6792eaSManish Awasthi * writes to the final page of the 48-bit IOVA window, and 51*3d6792eaSManish Awasthi * iommu_dma_alloc_iova() allocates downwards from the top of that 52*3d6792eaSManish Awasthi * window, so the first queue created lands on the unusable page and 53*3d6792eaSManish Awasthi * its event queue stalls permanently. PCI devices are shielded from 54*3d6792eaSManish Awasthi * this by the low-4GB first attempt in iommu_dma_alloc_iova(), but 55*3d6792eaSManish Awasthi * that attempt is gated on dev_is_pci() and CDX devices do not 56*3d6792eaSManish Awasthi * qualify. 57*3d6792eaSManish Awasthi */ 58*3d6792eaSManish Awasthi err = dma_set_mask_and_coherent(gc->dev, DMA_BIT_MASK(32)); 59*3d6792eaSManish Awasthi if (err) { 60*3d6792eaSManish Awasthi dev_err(&cdx_dev->dev, "Failed to set 32-bit DMA mask\n"); 61*3d6792eaSManish Awasthi return err; 62*3d6792eaSManish Awasthi } 63*3d6792eaSManish Awasthi 64*3d6792eaSManish Awasthi /* The PCI path also calls dma_set_max_seg_size(), but that is 65*3d6792eaSManish Awasthi * deliberately omitted here: the CDX core does not attach a 66*3d6792eaSManish Awasthi * dma_parms to the device, so the helper would only WARN, and MANA 67*3d6792eaSManish Awasthi * never builds scatter-gather lists, so the limit is never read. 68*3d6792eaSManish Awasthi */ 69*3d6792eaSManish Awasthi 70*3d6792eaSManish Awasthi err = cdx_enable_msi(cdx_dev); 71*3d6792eaSManish Awasthi if (err) { 72*3d6792eaSManish Awasthi dev_err(&cdx_dev->dev, "Failed to enable MSI\n"); 73*3d6792eaSManish Awasthi return err; 74*3d6792eaSManish Awasthi } 75*3d6792eaSManish Awasthi 76*3d6792eaSManish Awasthi err = msi_domain_alloc_irqs(gc->dev, MSI_DEFAULT_DOMAIN, max_irqs); 77*3d6792eaSManish Awasthi if (err) { 78*3d6792eaSManish Awasthi dev_err(&cdx_dev->dev, "Failed to alloc MSI IRQs\n"); 79*3d6792eaSManish Awasthi cdx_disable_msi(cdx_dev); 80*3d6792eaSManish Awasthi return err; 81*3d6792eaSManish Awasthi } 82*3d6792eaSManish Awasthi 83*3d6792eaSManish Awasthi nvec = max_irqs; 84*3d6792eaSManish Awasthi 85*3d6792eaSManish Awasthi xa_init(&gc->irq_contexts); 86*3d6792eaSManish Awasthi 87*3d6792eaSManish Awasthi /* No IRQ affinity hint is applied here. The PCI transport spreads its 88*3d6792eaSManish Awasthi * vectors over the NUMA node local to the device; the CDX platforms 89*3d6792eaSManish Awasthi * this driver targets are single-node, so there is nothing to spread 90*3d6792eaSManish Awasthi * over. Affinity management can be added when a multi-node CDX host 91*3d6792eaSManish Awasthi * exists to validate it against. 92*3d6792eaSManish Awasthi */ 93*3d6792eaSManish Awasthi for (i = 0; i < nvec; i++) { 94*3d6792eaSManish Awasthi int msi = i; 95*3d6792eaSManish Awasthi 96*3d6792eaSManish Awasthi gic = mana_gd_get_gic(gc, false, &msi); 97*3d6792eaSManish Awasthi if (IS_ERR(gic)) { 98*3d6792eaSManish Awasthi err = PTR_ERR(gic); 99*3d6792eaSManish Awasthi goto free_irq; 100*3d6792eaSManish Awasthi } 101*3d6792eaSManish Awasthi } 102*3d6792eaSManish Awasthi 103*3d6792eaSManish Awasthi gc->max_num_msix = nvec; 104*3d6792eaSManish Awasthi gc->num_msix_usable = nvec; 105*3d6792eaSManish Awasthi 106*3d6792eaSManish Awasthi /* CDX sizes its MSI pool at probe time and cannot grow it later, so 107*3d6792eaSManish Awasthi * never share vectors: vector 0 is reserved for the HWC and each of 108*3d6792eaSManish Awasthi * the remaining nvec - 1 vectors backs exactly one EQ. That bounds 109*3d6792eaSManish Awasthi * the queue count at nvec - 1 and guarantees the HWC vector is never 110*3d6792eaSManish Awasthi * handed out to a data queue. 111*3d6792eaSManish Awasthi */ 112*3d6792eaSManish Awasthi gc->msi_sharing = false; 113*3d6792eaSManish Awasthi 114*3d6792eaSManish Awasthi gc->msi_bitmap = bitmap_zalloc(nvec, GFP_KERNEL); 115*3d6792eaSManish Awasthi if (!gc->msi_bitmap) { 116*3d6792eaSManish Awasthi err = -ENOMEM; 117*3d6792eaSManish Awasthi goto free_irq; 118*3d6792eaSManish Awasthi } 119*3d6792eaSManish Awasthi 120*3d6792eaSManish Awasthi /* Reserve the HWC vector */ 121*3d6792eaSManish Awasthi set_bit(0, gc->msi_bitmap); 122*3d6792eaSManish Awasthi 123*3d6792eaSManish Awasthi return 0; 124*3d6792eaSManish Awasthi 125*3d6792eaSManish Awasthi free_irq: 126*3d6792eaSManish Awasthi for (j = i - 1; j >= 0; j--) 127*3d6792eaSManish Awasthi mana_gd_put_gic(gc, false, j); 128*3d6792eaSManish Awasthi 129*3d6792eaSManish Awasthi xa_destroy(&gc->irq_contexts); 130*3d6792eaSManish Awasthi msi_domain_free_irqs_all(gc->dev, MSI_DEFAULT_DOMAIN); 131*3d6792eaSManish Awasthi cdx_disable_msi(cdx_dev); 132*3d6792eaSManish Awasthi return err; 133*3d6792eaSManish Awasthi } 134*3d6792eaSManish Awasthi 135*3d6792eaSManish Awasthi static void mana_cdx_remove_irqs(struct gdma_context *gc) 136*3d6792eaSManish Awasthi { 137*3d6792eaSManish Awasthi struct cdx_device *cdx_dev = to_cdx_device(gc->dev); 138*3d6792eaSManish Awasthi int i; 139*3d6792eaSManish Awasthi 140*3d6792eaSManish Awasthi if (gc->max_num_msix < 1) 141*3d6792eaSManish Awasthi return; 142*3d6792eaSManish Awasthi 143*3d6792eaSManish Awasthi for (i = 0; i < gc->max_num_msix; i++) { 144*3d6792eaSManish Awasthi if (!xa_load(&gc->irq_contexts, i)) 145*3d6792eaSManish Awasthi continue; 146*3d6792eaSManish Awasthi 147*3d6792eaSManish Awasthi mana_gd_put_gic(gc, false, i); 148*3d6792eaSManish Awasthi } 149*3d6792eaSManish Awasthi 150*3d6792eaSManish Awasthi WARN_ON(!xa_empty(&gc->irq_contexts)); 151*3d6792eaSManish Awasthi 152*3d6792eaSManish Awasthi xa_destroy(&gc->irq_contexts); 153*3d6792eaSManish Awasthi msi_domain_free_irqs_all(gc->dev, MSI_DEFAULT_DOMAIN); 154*3d6792eaSManish Awasthi cdx_disable_msi(cdx_dev); 155*3d6792eaSManish Awasthi 156*3d6792eaSManish Awasthi bitmap_free(gc->msi_bitmap); 157*3d6792eaSManish Awasthi gc->msi_bitmap = NULL; 158*3d6792eaSManish Awasthi gc->max_num_msix = 0; 159*3d6792eaSManish Awasthi gc->num_msix_usable = 0; 160*3d6792eaSManish Awasthi } 161*3d6792eaSManish Awasthi 162*3d6792eaSManish Awasthi static int mana_cdx_setup_remaining_irqs(struct gdma_context *gc) 163*3d6792eaSManish Awasthi { 164*3d6792eaSManish Awasthi unsigned int max_queues_vport; 165*3d6792eaSManish Awasthi 166*3d6792eaSManish Awasthi /* mana_gd_query_max_resources() may turn MSI sharing back on and round 167*3d6792eaSManish Awasthi * the per-vPort queue count up to MANA_DEF_NUM_QUEUES. CDX sizes its 168*3d6792eaSManish Awasthi * vector pool at probe time and cannot grow it later, and the HWC 169*3d6792eaSManish Awasthi * vector must stay private, so give every vPort a private slice of the 170*3d6792eaSManish Awasthi * remaining vectors instead. gc->max_num_queues is already capped at 171*3d6792eaSManish Awasthi * num_msix_usable - 1 by the core. 172*3d6792eaSManish Awasthi */ 173*3d6792eaSManish Awasthi gc->msi_sharing = false; 174*3d6792eaSManish Awasthi max_queues_vport = (gc->num_msix_usable - 1) / gc->num_ports; 175*3d6792eaSManish Awasthi if (!max_queues_vport) { 176*3d6792eaSManish Awasthi dev_err(gc->dev, "%u MSI vectors cannot serve %u vPorts\n", 177*3d6792eaSManish Awasthi gc->num_msix_usable, gc->num_ports); 178*3d6792eaSManish Awasthi return -ENOSPC; 179*3d6792eaSManish Awasthi } 180*3d6792eaSManish Awasthi 181*3d6792eaSManish Awasthi gc->max_num_queues_vport = min(gc->max_num_queues, max_queues_vport); 182*3d6792eaSManish Awasthi 183*3d6792eaSManish Awasthi dev_dbg(gc->dev, "%u MSI vectors, %u vPorts, %u queues, no MSI sharing\n", 184*3d6792eaSManish Awasthi gc->num_msix_usable, gc->num_ports, gc->max_num_queues_vport); 185*3d6792eaSManish Awasthi 186*3d6792eaSManish Awasthi return 0; 187*3d6792eaSManish Awasthi } 188*3d6792eaSManish Awasthi 189*3d6792eaSManish Awasthi static const struct gdma_bus_ops mana_cdx_bus_ops = { 190*3d6792eaSManish Awasthi .bus_name = "cdx", 191*3d6792eaSManish Awasthi .adev_prefix = "mana_cdx", 192*3d6792eaSManish Awasthi .msix_virq = mana_cdx_msix_virq, 193*3d6792eaSManish Awasthi .setup_hwc_irqs = mana_cdx_setup_hwc_irqs, 194*3d6792eaSManish Awasthi .setup_remaining_irqs = mana_cdx_setup_remaining_irqs, 195*3d6792eaSManish Awasthi .remove_irqs = mana_cdx_remove_irqs, 196*3d6792eaSManish Awasthi .dev_reset = mana_cdx_dev_reset, 197*3d6792eaSManish Awasthi }; 198*3d6792eaSManish Awasthi 199*3d6792eaSManish Awasthi static int mana_cdx_gd_probe(struct cdx_device *cdx_dev) 200*3d6792eaSManish Awasthi { 201*3d6792eaSManish Awasthi struct gdma_context *gc; 202*3d6792eaSManish Awasthi void __iomem *bar0_va; 203*3d6792eaSManish Awasthi int err; 204*3d6792eaSManish Awasthi 205*3d6792eaSManish Awasthi /* Each port has 2 CQs, each CQ has at most 1 EQE at a time */ 206*3d6792eaSManish Awasthi BUILD_BUG_ON(2 * MAX_PORTS_IN_MANA_DEV * GDMA_EQE_SIZE > EQ_SIZE); 207*3d6792eaSManish Awasthi 208*3d6792eaSManish Awasthi err = cdx_dev_reset(&cdx_dev->dev); 209*3d6792eaSManish Awasthi if (err) 210*3d6792eaSManish Awasthi return err; 211*3d6792eaSManish Awasthi 212*3d6792eaSManish Awasthi err = cdx_set_master(cdx_dev); 213*3d6792eaSManish Awasthi if (err) 214*3d6792eaSManish Awasthi return err; 215*3d6792eaSManish Awasthi 216*3d6792eaSManish Awasthi gc = vzalloc(sizeof(*gc)); 217*3d6792eaSManish Awasthi if (!gc) { 218*3d6792eaSManish Awasthi err = -ENOMEM; 219*3d6792eaSManish Awasthi goto clear_master; 220*3d6792eaSManish Awasthi } 221*3d6792eaSManish Awasthi 222*3d6792eaSManish Awasthi mutex_init(&gc->eq_test_event_mutex); 223*3d6792eaSManish Awasthi mutex_init(&gc->gic_mutex); 224*3d6792eaSManish Awasthi dev_set_drvdata(&cdx_dev->dev, gc); 225*3d6792eaSManish Awasthi gc->bar0_pa = cdx_resource_start(cdx_dev, 0); 226*3d6792eaSManish Awasthi gc->bar0_size = cdx_resource_len(cdx_dev, 0); 227*3d6792eaSManish Awasthi if (gc->bar0_size < MANA_CDX_GDMA_REGS_SIZE) { 228*3d6792eaSManish Awasthi dev_err(&cdx_dev->dev, "BAR0 size %#llx is too small\n", 229*3d6792eaSManish Awasthi (u64)gc->bar0_size); 230*3d6792eaSManish Awasthi err = -EINVAL; 231*3d6792eaSManish Awasthi goto free_gc; 232*3d6792eaSManish Awasthi } 233*3d6792eaSManish Awasthi 234*3d6792eaSManish Awasthi bar0_va = ioremap(gc->bar0_pa, gc->bar0_size); 235*3d6792eaSManish Awasthi if (!bar0_va) { 236*3d6792eaSManish Awasthi err = -ENOMEM; 237*3d6792eaSManish Awasthi goto free_gc; 238*3d6792eaSManish Awasthi } 239*3d6792eaSManish Awasthi 240*3d6792eaSManish Awasthi gc->numa_node = dev_to_node(&cdx_dev->dev); 241*3d6792eaSManish Awasthi gc->bar0_va = bar0_va; 242*3d6792eaSManish Awasthi gc->dev = &cdx_dev->dev; 243*3d6792eaSManish Awasthi gc->bus_ops = &mana_cdx_bus_ops; 244*3d6792eaSManish Awasthi 245*3d6792eaSManish Awasthi /* gc->is_pf is intentionally left clear: this device uses the VF 246*3d6792eaSManish Awasthi * register layout, and the vPort and MAC filter registration that 247*3d6792eaSManish Awasthi * is_pf selects is not required on this bus. 248*3d6792eaSManish Awasthi */ 249*3d6792eaSManish Awasthi 250*3d6792eaSManish Awasthi err = mana_gd_setup(gc); 251*3d6792eaSManish Awasthi if (err) 252*3d6792eaSManish Awasthi goto unmap_bar; 253*3d6792eaSManish Awasthi 254*3d6792eaSManish Awasthi err = mana_probe(&gc->mana, false); 255*3d6792eaSManish Awasthi if (err) 256*3d6792eaSManish Awasthi goto cleanup_gd; 257*3d6792eaSManish Awasthi 258*3d6792eaSManish Awasthi err = mana_rdma_probe(&gc->mana_ib); 259*3d6792eaSManish Awasthi if (err) 260*3d6792eaSManish Awasthi goto remove_mana; 261*3d6792eaSManish Awasthi 262*3d6792eaSManish Awasthi /* If a hardware reset event arrived over HWC during probe, roll back: 263*3d6792eaSManish Awasthi * the device state the rest of probe observed is no longer valid. 264*3d6792eaSManish Awasthi */ 265*3d6792eaSManish Awasthi if (test_and_set_bit(GC_PROBE_SUCCEEDED, &gc->flags)) { 266*3d6792eaSManish Awasthi err = -EPROTO; 267*3d6792eaSManish Awasthi goto remove_rdma; 268*3d6792eaSManish Awasthi } 269*3d6792eaSManish Awasthi 270*3d6792eaSManish Awasthi return 0; 271*3d6792eaSManish Awasthi 272*3d6792eaSManish Awasthi remove_rdma: 273*3d6792eaSManish Awasthi mana_rdma_remove(&gc->mana_ib); 274*3d6792eaSManish Awasthi remove_mana: 275*3d6792eaSManish Awasthi mana_remove(&gc->mana, false); 276*3d6792eaSManish Awasthi cleanup_gd: 277*3d6792eaSManish Awasthi mana_gd_cleanup(gc); 278*3d6792eaSManish Awasthi unmap_bar: 279*3d6792eaSManish Awasthi iounmap(bar0_va); 280*3d6792eaSManish Awasthi free_gc: 281*3d6792eaSManish Awasthi dev_set_drvdata(&cdx_dev->dev, NULL); 282*3d6792eaSManish Awasthi vfree(gc); 283*3d6792eaSManish Awasthi clear_master: 284*3d6792eaSManish Awasthi cdx_clear_master(cdx_dev); 285*3d6792eaSManish Awasthi return err; 286*3d6792eaSManish Awasthi } 287*3d6792eaSManish Awasthi 288*3d6792eaSManish Awasthi static int mana_cdx_gd_remove(struct cdx_device *cdx_dev) 289*3d6792eaSManish Awasthi { 290*3d6792eaSManish Awasthi struct gdma_context *gc = dev_get_drvdata(&cdx_dev->dev); 291*3d6792eaSManish Awasthi 292*3d6792eaSManish Awasthi mana_rdma_remove(&gc->mana_ib); 293*3d6792eaSManish Awasthi mana_remove(&gc->mana, false); 294*3d6792eaSManish Awasthi 295*3d6792eaSManish Awasthi mana_gd_cleanup(gc); 296*3d6792eaSManish Awasthi cdx_clear_master(cdx_dev); 297*3d6792eaSManish Awasthi 298*3d6792eaSManish Awasthi iounmap(gc->bar0_va); 299*3d6792eaSManish Awasthi 300*3d6792eaSManish Awasthi dev_set_drvdata(&cdx_dev->dev, NULL); 301*3d6792eaSManish Awasthi vfree(gc); 302*3d6792eaSManish Awasthi return 0; 303*3d6792eaSManish Awasthi } 304*3d6792eaSManish Awasthi 305*3d6792eaSManish Awasthi /* Quiesce the device for kexec. This is also called upon reboot/shutdown. */ 306*3d6792eaSManish Awasthi static void mana_cdx_gd_shutdown(struct cdx_device *cdx_dev) 307*3d6792eaSManish Awasthi { 308*3d6792eaSManish Awasthi struct gdma_context *gc = dev_get_drvdata(&cdx_dev->dev); 309*3d6792eaSManish Awasthi 310*3d6792eaSManish Awasthi mana_rdma_remove(&gc->mana_ib); 311*3d6792eaSManish Awasthi mana_remove(&gc->mana, true); 312*3d6792eaSManish Awasthi 313*3d6792eaSManish Awasthi mana_gd_cleanup(gc); 314*3d6792eaSManish Awasthi cdx_clear_master(cdx_dev); 315*3d6792eaSManish Awasthi } 316*3d6792eaSManish Awasthi 317*3d6792eaSManish Awasthi #define CDX_VENDOR_ID_MICROSOFT 0x1414 318*3d6792eaSManish Awasthi static const struct cdx_device_id mana_cdx_table[] = { 319*3d6792eaSManish Awasthi { CDX_DEVICE(CDX_VENDOR_ID_MICROSOFT, MANA_CDX_DEVICE_ID) }, 320*3d6792eaSManish Awasthi {} 321*3d6792eaSManish Awasthi }; 322*3d6792eaSManish Awasthi 323*3d6792eaSManish Awasthi MODULE_DEVICE_TABLE(cdx, mana_cdx_table); 324*3d6792eaSManish Awasthi 325*3d6792eaSManish Awasthi static struct cdx_driver gdma_cdx_driver = { 326*3d6792eaSManish Awasthi .match_id_table = mana_cdx_table, 327*3d6792eaSManish Awasthi .probe = mana_cdx_gd_probe, 328*3d6792eaSManish Awasthi .remove = mana_cdx_gd_remove, 329*3d6792eaSManish Awasthi .shutdown = mana_cdx_gd_shutdown, 330*3d6792eaSManish Awasthi .driver = { 331*3d6792eaSManish Awasthi .name = "mana_cdx", 332*3d6792eaSManish Awasthi }, 333*3d6792eaSManish Awasthi }; 334*3d6792eaSManish Awasthi 335*3d6792eaSManish Awasthi module_driver(gdma_cdx_driver, cdx_driver_register, cdx_driver_unregister); 336*3d6792eaSManish Awasthi 337*3d6792eaSManish Awasthi MODULE_LICENSE("Dual BSD/GPL"); 338*3d6792eaSManish Awasthi MODULE_DESCRIPTION("Microsoft Azure Network Adapter driver for the CDX bus"); 339*3d6792eaSManish Awasthi MODULE_IMPORT_NS("CDX_BUS"); 340*3d6792eaSManish Awasthi MODULE_IMPORT_NS("NET_MANA"); 341