xref: /linux/drivers/net/ethernet/intel/ixd/ixd_main.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
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