1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (C) 2025 Intel Corporation */ 3 4 #include "ixd.h" 5 #include "ixd_ctlq.h" 6 #include "ixd_lan_regs.h" 7 #include "ixd_devlink.h" 8 9 MODULE_DESCRIPTION("Intel(R) Control Plane Function Device Driver"); 10 MODULE_IMPORT_NS("LIBIE_CP"); 11 MODULE_IMPORT_NS("LIBIE_PCI"); 12 MODULE_LICENSE("GPL"); 13 14 /** 15 * ixd_remove - remove a CPF PCI device 16 * @pdev: PCI device being removed 17 */ 18 static void ixd_remove(struct pci_dev *pdev) 19 { 20 struct ixd_adapter *adapter = pci_get_drvdata(pdev); 21 22 /* Do not mix removal with (re)initialization */ 23 cancel_delayed_work_sync(&adapter->init_task.init_work); 24 25 ixd_devlink_unregister(adapter); 26 27 /* Leave the device clean on exit */ 28 if (adapter->xnm) 29 libie_ctlq_xn_shutdown(adapter->xnm); 30 ixd_trigger_reset(adapter); 31 ixd_deinit_dflt_mbx(adapter); 32 33 libie_pci_unmap_all_mmio_regions(&adapter->cp_ctx.mmio_info); 34 ixd_devlink_free(adapter); 35 } 36 37 /** 38 * ixd_shutdown - shut down a CPF PCI device 39 * @pdev: PCI device being shut down 40 */ 41 static void ixd_shutdown(struct pci_dev *pdev) 42 { 43 ixd_remove(pdev); 44 45 if (system_state == SYSTEM_POWER_OFF) 46 pci_set_power_state(pdev, PCI_D3hot); 47 } 48 49 /** 50 * ixd_iomap_regions - iomap PCI BARs 51 * @adapter: adapter to map memory regions for 52 * 53 * Returns: %0 on success, negative on failure 54 */ 55 static int ixd_iomap_regions(struct ixd_adapter *adapter) 56 { 57 const struct ixd_bar_region regions[] = { 58 { 59 .offset = PFGEN_RTRIG, 60 .size = PFGEN_RTRIG_REG_LEN, 61 }, 62 { 63 .offset = PF_FW_MBX, 64 .size = PF_FW_MBX_REG_LEN, 65 }, 66 }; 67 68 for (int i = 0; i < ARRAY_SIZE(regions); i++) { 69 struct libie_mmio_info *mmio_info = &adapter->cp_ctx.mmio_info; 70 bool map_ok; 71 72 map_ok = libie_pci_map_mmio_region(mmio_info, 73 regions[i].offset, 74 regions[i].size); 75 if (!map_ok) { 76 dev_err(ixd_to_dev(adapter), 77 "Failed to map PCI device MMIO region\n"); 78 79 libie_pci_unmap_all_mmio_regions(mmio_info); 80 return -EIO; 81 } 82 } 83 84 return 0; 85 } 86 87 /** 88 * ixd_probe - probe a CPF PCI device 89 * @pdev: corresponding PCI device 90 * @ent: entry in ixd_pci_tbl 91 * 92 * Returns: %0 on success, negative errno code on failure 93 */ 94 static int ixd_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 95 { 96 struct ixd_adapter *adapter; 97 int err; 98 99 adapter = ixd_adapter_alloc(&pdev->dev); 100 if (!adapter) 101 return -ENOMEM; 102 103 adapter->cp_ctx.mmio_info.pdev = pdev; 104 INIT_LIST_HEAD(&adapter->cp_ctx.mmio_info.mmio_list); 105 106 err = libie_pci_init_dev(pdev); 107 if (err) 108 goto free_adapter; 109 110 pci_set_drvdata(pdev, adapter); 111 112 err = ixd_iomap_regions(adapter); 113 if (err) 114 goto free_adapter; 115 116 INIT_DELAYED_WORK(&adapter->init_task.init_work, 117 ixd_init_task); 118 INIT_DELAYED_WORK(&adapter->mbx_task, ixd_ctlq_rx_task); 119 120 ixd_trigger_reset(adapter); 121 queue_delayed_work(system_dfl_wq, &adapter->init_task.init_work, 122 IXD_INIT_TASK_DELAY_JIFFIES); 123 124 return 0; 125 126 free_adapter: 127 ixd_devlink_free(adapter); 128 return err; 129 } 130 131 static const struct pci_device_id ixd_pci_tbl[] = { 132 { PCI_VDEVICE(INTEL, IXD_DEV_ID_CPF) }, 133 { } 134 }; 135 MODULE_DEVICE_TABLE(pci, ixd_pci_tbl); 136 137 static struct pci_driver ixd_driver = { 138 .name = KBUILD_MODNAME, 139 .id_table = ixd_pci_tbl, 140 .probe = ixd_probe, 141 .remove = ixd_remove, 142 .shutdown = ixd_shutdown, 143 }; 144 module_pci_driver(ixd_driver); 145