summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/intel/ixd/ixd_main.c
blob: 5db992d4f9fb2d3d6427f7c545cc75ac30dccded (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2025 Intel Corporation */

#include "ixd.h"
#include "ixd_ctlq.h"
#include "ixd_lan_regs.h"
#include "ixd_devlink.h"

MODULE_DESCRIPTION("Intel(R) Control Plane Function Device Driver");
MODULE_IMPORT_NS("LIBIE_CP");
MODULE_IMPORT_NS("LIBIE_PCI");
MODULE_LICENSE("GPL");

/**
 * ixd_remove - remove a CPF PCI device
 * @pdev: PCI device being removed
 */
static void ixd_remove(struct pci_dev *pdev)
{
	struct ixd_adapter *adapter = pci_get_drvdata(pdev);

	/* Do not mix removal with (re)initialization */
	cancel_delayed_work_sync(&adapter->init_task.init_work);

	ixd_devlink_unregister(adapter);

	/* Leave the device clean on exit */
	if (adapter->xnm)
		libie_ctlq_xn_shutdown(adapter->xnm);
	ixd_trigger_reset(adapter);
	ixd_deinit_dflt_mbx(adapter);

	libie_pci_unmap_all_mmio_regions(&adapter->cp_ctx.mmio_info);
	ixd_devlink_free(adapter);
}

/**
 * ixd_shutdown - shut down a CPF PCI device
 * @pdev: PCI device being shut down
 */
static void ixd_shutdown(struct pci_dev *pdev)
{
	ixd_remove(pdev);

	if (system_state == SYSTEM_POWER_OFF)
		pci_set_power_state(pdev, PCI_D3hot);
}

/**
 * ixd_iomap_regions - iomap PCI BARs
 * @adapter: adapter to map memory regions for
 *
 * Returns: %0 on success, negative on failure
 */
static int ixd_iomap_regions(struct ixd_adapter *adapter)
{
	const struct ixd_bar_region regions[] = {
		{
			.offset = PFGEN_RTRIG,
			.size = PFGEN_RTRIG_REG_LEN,
		},
		{
			.offset = PF_FW_MBX,
			.size = PF_FW_MBX_REG_LEN,
		},
	};

	for (int i = 0; i < ARRAY_SIZE(regions); i++) {
		struct libie_mmio_info *mmio_info = &adapter->cp_ctx.mmio_info;
		bool map_ok;

		map_ok = libie_pci_map_mmio_region(mmio_info,
						   regions[i].offset,
						   regions[i].size);
		if (!map_ok) {
			dev_err(ixd_to_dev(adapter),
				"Failed to map PCI device MMIO region\n");

			libie_pci_unmap_all_mmio_regions(mmio_info);
			return -EIO;
		}
	}

	return 0;
}

/**
 * ixd_probe - probe a CPF PCI device
 * @pdev: corresponding PCI device
 * @ent: entry in ixd_pci_tbl
 *
 * Returns: %0 on success, negative errno code on failure
 */
static int ixd_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	struct ixd_adapter *adapter;
	int err;

	adapter = ixd_adapter_alloc(&pdev->dev);
	if (!adapter)
		return -ENOMEM;

	adapter->cp_ctx.mmio_info.pdev = pdev;
	INIT_LIST_HEAD(&adapter->cp_ctx.mmio_info.mmio_list);

	err = libie_pci_init_dev(pdev);
	if (err)
		goto free_adapter;

	pci_set_drvdata(pdev, adapter);

	err = ixd_iomap_regions(adapter);
	if (err)
		goto free_adapter;

	INIT_DELAYED_WORK(&adapter->init_task.init_work,
			  ixd_init_task);
	INIT_DELAYED_WORK(&adapter->mbx_task, ixd_ctlq_rx_task);

	ixd_trigger_reset(adapter);
	queue_delayed_work(system_dfl_wq, &adapter->init_task.init_work,
			   IXD_INIT_TASK_DELAY_JIFFIES);

	return 0;

free_adapter:
	ixd_devlink_free(adapter);
	return err;
}

static const struct pci_device_id ixd_pci_tbl[] = {
	{ PCI_VDEVICE(INTEL, IXD_DEV_ID_CPF) },
	{ }
};
MODULE_DEVICE_TABLE(pci, ixd_pci_tbl);

static struct pci_driver ixd_driver = {
	.name			= KBUILD_MODNAME,
	.id_table		= ixd_pci_tbl,
	.probe			= ixd_probe,
	.remove			= ixd_remove,
	.shutdown		= ixd_shutdown,
};
module_pci_driver(ixd_driver);