1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (C) 2024 Marvell. */
4 #include <linux/cleanup.h>
5 #include <linux/container_of.h>
6 #include <linux/delay.h>
7 #include <linux/dev_printk.h>
8 #include <linux/init.h>
9 #include <linux/interrupt.h>
10 #include <linux/io-64-nonatomic-lo-hi.h>
11 #include <linux/kernel.h>
12 #include <linux/list.h>
13 #include <linux/module.h>
14 #include <linux/mutex.h>
15 #include <linux/pci.h>
16 #include <linux/pci_hotplug.h>
17 #include <linux/slab.h>
18 #include <linux/spinlock.h>
19 #include <linux/workqueue.h>
21 #define OCTEP_HP_INTR_OFFSET(x) (0x20400 + ((x) << 4))
22 #define OCTEP_HP_INTR_VECTOR(x) (16 + (x))
23 #define OCTEP_HP_DRV_NAME "octep_hp"
26 * Type of MSI-X interrupts. OCTEP_HP_INTR_VECTOR() and
27 * OCTEP_HP_INTR_OFFSET() generate the vector and offset for an interrupt
30 enum octep_hp_intr_type
{
31 OCTEP_HP_INTR_INVALID
= -1,
32 OCTEP_HP_INTR_ENA
= 0,
33 OCTEP_HP_INTR_DIS
= 1,
34 OCTEP_HP_INTR_MAX
= 2,
38 struct list_head list
;
39 enum octep_hp_intr_type intr_type
;
43 struct octep_hp_slot
{
44 struct list_head list
;
45 struct hotplug_slot slot
;
47 struct pci_dev
*hp_pdev
;
48 unsigned int hp_devfn
;
49 struct octep_hp_controller
*ctrl
;
52 struct octep_hp_intr_info
{
53 enum octep_hp_intr_type type
;
58 struct octep_hp_controller
{
61 struct octep_hp_intr_info intr
[OCTEP_HP_INTR_MAX
];
62 struct work_struct work
;
63 struct list_head slot_list
;
64 struct mutex slot_lock
; /* Protects slot_list */
65 struct list_head hp_cmd_list
;
66 spinlock_t hp_cmd_lock
; /* Protects hp_cmd_list */
69 static void octep_hp_enable_pdev(struct octep_hp_controller
*hp_ctrl
,
70 struct octep_hp_slot
*hp_slot
)
72 guard(mutex
)(&hp_ctrl
->slot_lock
);
73 if (hp_slot
->hp_pdev
) {
74 pci_dbg(hp_slot
->hp_pdev
, "Slot %s is already enabled\n",
75 hotplug_slot_name(&hp_slot
->slot
));
79 /* Scan the device and add it to the bus */
80 hp_slot
->hp_pdev
= pci_scan_single_device(hp_ctrl
->pdev
->bus
,
82 pci_bus_assign_resources(hp_ctrl
->pdev
->bus
);
83 pci_bus_add_device(hp_slot
->hp_pdev
);
85 dev_dbg(&hp_slot
->hp_pdev
->dev
, "Enabled slot %s\n",
86 hotplug_slot_name(&hp_slot
->slot
));
89 static void octep_hp_disable_pdev(struct octep_hp_controller
*hp_ctrl
,
90 struct octep_hp_slot
*hp_slot
)
92 guard(mutex
)(&hp_ctrl
->slot_lock
);
93 if (!hp_slot
->hp_pdev
) {
94 pci_dbg(hp_ctrl
->pdev
, "Slot %s is already disabled\n",
95 hotplug_slot_name(&hp_slot
->slot
));
99 pci_dbg(hp_slot
->hp_pdev
, "Disabling slot %s\n",
100 hotplug_slot_name(&hp_slot
->slot
));
102 /* Remove the device from the bus */
103 pci_stop_and_remove_bus_device_locked(hp_slot
->hp_pdev
);
104 hp_slot
->hp_pdev
= NULL
;
107 static int octep_hp_enable_slot(struct hotplug_slot
*slot
)
109 struct octep_hp_slot
*hp_slot
=
110 container_of(slot
, struct octep_hp_slot
, slot
);
112 octep_hp_enable_pdev(hp_slot
->ctrl
, hp_slot
);
116 static int octep_hp_disable_slot(struct hotplug_slot
*slot
)
118 struct octep_hp_slot
*hp_slot
=
119 container_of(slot
, struct octep_hp_slot
, slot
);
121 octep_hp_disable_pdev(hp_slot
->ctrl
, hp_slot
);
125 static struct hotplug_slot_ops octep_hp_slot_ops
= {
126 .enable_slot
= octep_hp_enable_slot
,
127 .disable_slot
= octep_hp_disable_slot
,
130 #define SLOT_NAME_SIZE 16
131 static struct octep_hp_slot
*
132 octep_hp_register_slot(struct octep_hp_controller
*hp_ctrl
,
133 struct pci_dev
*pdev
, u16 slot_number
)
135 char slot_name
[SLOT_NAME_SIZE
];
136 struct octep_hp_slot
*hp_slot
;
139 hp_slot
= kzalloc(sizeof(*hp_slot
), GFP_KERNEL
);
141 return ERR_PTR(-ENOMEM
);
143 hp_slot
->ctrl
= hp_ctrl
;
144 hp_slot
->hp_pdev
= pdev
;
145 hp_slot
->hp_devfn
= pdev
->devfn
;
146 hp_slot
->slot_number
= slot_number
;
147 hp_slot
->slot
.ops
= &octep_hp_slot_ops
;
149 snprintf(slot_name
, sizeof(slot_name
), "octep_hp_%u", slot_number
);
150 ret
= pci_hp_register(&hp_slot
->slot
, hp_ctrl
->pdev
->bus
,
151 PCI_SLOT(pdev
->devfn
), slot_name
);
157 pci_info(pdev
, "Registered slot %s for device %s\n",
158 slot_name
, pci_name(pdev
));
160 list_add_tail(&hp_slot
->list
, &hp_ctrl
->slot_list
);
161 octep_hp_disable_pdev(hp_ctrl
, hp_slot
);
166 static void octep_hp_deregister_slot(void *data
)
168 struct octep_hp_slot
*hp_slot
= data
;
169 struct octep_hp_controller
*hp_ctrl
= hp_slot
->ctrl
;
171 pci_hp_deregister(&hp_slot
->slot
);
172 octep_hp_enable_pdev(hp_ctrl
, hp_slot
);
173 list_del(&hp_slot
->list
);
177 static const char *octep_hp_cmd_name(enum octep_hp_intr_type type
)
180 case OCTEP_HP_INTR_ENA
:
181 return "hotplug enable";
182 case OCTEP_HP_INTR_DIS
:
183 return "hotplug disable";
189 static void octep_hp_cmd_handler(struct octep_hp_controller
*hp_ctrl
,
190 struct octep_hp_cmd
*hp_cmd
)
192 struct octep_hp_slot
*hp_slot
;
195 * Enable or disable the slots based on the slot mask.
196 * intr_val is a bit mask where each bit represents a slot.
198 list_for_each_entry(hp_slot
, &hp_ctrl
->slot_list
, list
) {
199 if (!(hp_cmd
->intr_val
& BIT(hp_slot
->slot_number
)))
202 pci_info(hp_ctrl
->pdev
, "Received %s command for slot %s\n",
203 octep_hp_cmd_name(hp_cmd
->intr_type
),
204 hotplug_slot_name(&hp_slot
->slot
));
206 switch (hp_cmd
->intr_type
) {
207 case OCTEP_HP_INTR_ENA
:
208 octep_hp_enable_pdev(hp_ctrl
, hp_slot
);
210 case OCTEP_HP_INTR_DIS
:
211 octep_hp_disable_pdev(hp_ctrl
, hp_slot
);
219 static void octep_hp_work_handler(struct work_struct
*work
)
221 struct octep_hp_controller
*hp_ctrl
;
222 struct octep_hp_cmd
*hp_cmd
;
225 hp_ctrl
= container_of(work
, struct octep_hp_controller
, work
);
227 /* Process all the hotplug commands */
228 spin_lock_irqsave(&hp_ctrl
->hp_cmd_lock
, flags
);
229 while (!list_empty(&hp_ctrl
->hp_cmd_list
)) {
230 hp_cmd
= list_first_entry(&hp_ctrl
->hp_cmd_list
,
231 struct octep_hp_cmd
, list
);
232 list_del(&hp_cmd
->list
);
233 spin_unlock_irqrestore(&hp_ctrl
->hp_cmd_lock
, flags
);
235 octep_hp_cmd_handler(hp_ctrl
, hp_cmd
);
238 spin_lock_irqsave(&hp_ctrl
->hp_cmd_lock
, flags
);
240 spin_unlock_irqrestore(&hp_ctrl
->hp_cmd_lock
, flags
);
243 static enum octep_hp_intr_type
octep_hp_intr_type(struct octep_hp_intr_info
*intr
,
246 enum octep_hp_intr_type type
;
248 for (type
= OCTEP_HP_INTR_ENA
; type
< OCTEP_HP_INTR_MAX
; type
++) {
249 if (intr
[type
].number
== irq
)
253 return OCTEP_HP_INTR_INVALID
;
256 static irqreturn_t
octep_hp_intr_handler(int irq
, void *data
)
258 struct octep_hp_controller
*hp_ctrl
= data
;
259 struct pci_dev
*pdev
= hp_ctrl
->pdev
;
260 enum octep_hp_intr_type type
;
261 struct octep_hp_cmd
*hp_cmd
;
264 type
= octep_hp_intr_type(hp_ctrl
->intr
, irq
);
265 if (type
== OCTEP_HP_INTR_INVALID
) {
266 pci_err(pdev
, "Invalid interrupt %d\n", irq
);
270 /* Read and clear the interrupt */
271 intr_val
= readq(hp_ctrl
->base
+ OCTEP_HP_INTR_OFFSET(type
));
272 writeq(intr_val
, hp_ctrl
->base
+ OCTEP_HP_INTR_OFFSET(type
));
274 hp_cmd
= kzalloc(sizeof(*hp_cmd
), GFP_ATOMIC
);
278 hp_cmd
->intr_val
= intr_val
;
279 hp_cmd
->intr_type
= type
;
281 /* Add the command to the list and schedule the work */
282 spin_lock(&hp_ctrl
->hp_cmd_lock
);
283 list_add_tail(&hp_cmd
->list
, &hp_ctrl
->hp_cmd_list
);
284 spin_unlock(&hp_ctrl
->hp_cmd_lock
);
285 schedule_work(&hp_ctrl
->work
);
290 static void octep_hp_irq_cleanup(void *data
)
292 struct octep_hp_controller
*hp_ctrl
= data
;
294 pci_free_irq_vectors(hp_ctrl
->pdev
);
295 flush_work(&hp_ctrl
->work
);
298 static int octep_hp_request_irq(struct octep_hp_controller
*hp_ctrl
,
299 enum octep_hp_intr_type type
)
301 struct pci_dev
*pdev
= hp_ctrl
->pdev
;
302 struct octep_hp_intr_info
*intr
;
305 irq
= pci_irq_vector(pdev
, OCTEP_HP_INTR_VECTOR(type
));
309 intr
= &hp_ctrl
->intr
[type
];
312 snprintf(intr
->name
, sizeof(intr
->name
), "octep_hp_%d", type
);
314 return devm_request_irq(&pdev
->dev
, irq
, octep_hp_intr_handler
,
315 IRQF_SHARED
, intr
->name
, hp_ctrl
);
318 static int octep_hp_controller_setup(struct pci_dev
*pdev
,
319 struct octep_hp_controller
*hp_ctrl
)
321 struct device
*dev
= &pdev
->dev
;
322 enum octep_hp_intr_type type
;
325 ret
= pcim_enable_device(pdev
);
327 return dev_err_probe(dev
, ret
, "Failed to enable PCI device\n");
329 hp_ctrl
->base
= pcim_iomap_region(pdev
, 0, OCTEP_HP_DRV_NAME
);
330 if (IS_ERR(hp_ctrl
->base
))
331 return dev_err_probe(dev
, PTR_ERR(hp_ctrl
->base
),
332 "Failed to map PCI device region\n");
334 pci_set_master(pdev
);
335 pci_set_drvdata(pdev
, hp_ctrl
);
337 INIT_LIST_HEAD(&hp_ctrl
->slot_list
);
338 INIT_LIST_HEAD(&hp_ctrl
->hp_cmd_list
);
339 mutex_init(&hp_ctrl
->slot_lock
);
340 spin_lock_init(&hp_ctrl
->hp_cmd_lock
);
341 INIT_WORK(&hp_ctrl
->work
, octep_hp_work_handler
);
342 hp_ctrl
->pdev
= pdev
;
344 ret
= pci_alloc_irq_vectors(pdev
, 1,
345 OCTEP_HP_INTR_VECTOR(OCTEP_HP_INTR_MAX
),
348 return dev_err_probe(dev
, ret
, "Failed to alloc MSI-X vectors\n");
350 ret
= devm_add_action(&pdev
->dev
, octep_hp_irq_cleanup
, hp_ctrl
);
352 return dev_err_probe(&pdev
->dev
, ret
, "Failed to add IRQ cleanup action\n");
354 for (type
= OCTEP_HP_INTR_ENA
; type
< OCTEP_HP_INTR_MAX
; type
++) {
355 ret
= octep_hp_request_irq(hp_ctrl
, type
);
357 return dev_err_probe(dev
, ret
,
358 "Failed to request IRQ for vector %d\n",
359 OCTEP_HP_INTR_VECTOR(type
));
365 static int octep_hp_pci_probe(struct pci_dev
*pdev
,
366 const struct pci_device_id
*id
)
368 struct octep_hp_controller
*hp_ctrl
;
369 struct pci_dev
*tmp_pdev
, *next
;
370 struct octep_hp_slot
*hp_slot
;
374 hp_ctrl
= devm_kzalloc(&pdev
->dev
, sizeof(*hp_ctrl
), GFP_KERNEL
);
378 ret
= octep_hp_controller_setup(pdev
, hp_ctrl
);
383 * Register all hotplug slots. Hotplug controller is the first function
384 * of the PCI device. The hotplug slots are the remaining functions of
385 * the PCI device. The hotplug slot functions are logically removed from
386 * the bus during probing and are re-enabled by the driver when a
387 * hotplug event is received.
389 list_for_each_entry_safe(tmp_pdev
, next
, &pdev
->bus
->devices
, bus_list
) {
390 if (tmp_pdev
== pdev
)
393 hp_slot
= octep_hp_register_slot(hp_ctrl
, tmp_pdev
, slot_number
);
395 return dev_err_probe(&pdev
->dev
, PTR_ERR(hp_slot
),
396 "Failed to register hotplug slot %u\n",
399 ret
= devm_add_action(&pdev
->dev
, octep_hp_deregister_slot
,
402 return dev_err_probe(&pdev
->dev
, ret
,
403 "Failed to add action for deregistering slot %u\n",
411 #define PCI_DEVICE_ID_CAVIUM_OCTEP_HP_CTLR 0xa0e3
412 static struct pci_device_id octep_hp_pci_map
[] = {
413 { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM
, PCI_DEVICE_ID_CAVIUM_OCTEP_HP_CTLR
) },
417 static struct pci_driver octep_hp
= {
418 .name
= OCTEP_HP_DRV_NAME
,
419 .id_table
= octep_hp_pci_map
,
420 .probe
= octep_hp_pci_probe
,
423 module_pci_driver(octep_hp
);
425 MODULE_LICENSE("GPL");
426 MODULE_AUTHOR("Marvell");
427 MODULE_DESCRIPTION("Marvell OCTEON PCI Hotplug driver");