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 */
ixd_remove(struct pci_dev * pdev)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 */
ixd_shutdown(struct pci_dev * pdev)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 */
ixd_iomap_regions(struct ixd_adapter * adapter)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 */
ixd_probe(struct pci_dev * pdev,const struct pci_device_id * ent)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