xref: /linux/drivers/pci/hotplug/rpadlpar_core.c (revision 2b1333b80885b896807ffb6ccf4bc21d29aa65e0)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Interface for Dynamic Logical Partitioning of I/O Slots on
4  * RPA-compliant PPC64 platform.
5  *
6  * John Rose <johnrose@austin.ibm.com>
7  * Linda Xie <lxie@us.ibm.com>
8  *
9  * October 2003
10  *
11  * Copyright (C) 2003 IBM.
12  */
13 
14 #undef DEBUG
15 
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/of.h>
19 #include <linux/pci.h>
20 #include <linux/string.h>
21 #include <linux/vmalloc.h>
22 
23 #include <asm/pci-bridge.h>
24 #include <linux/mutex.h>
25 #include <asm/rtas.h>
26 #include <asm/vio.h>
27 #include <linux/firmware.h>
28 
29 #include "../pci.h"
30 #include "rpaphp.h"
31 #include "rpadlpar.h"
32 
33 static DEFINE_MUTEX(rpadlpar_mutex);
34 
35 #define DLPAR_MODULE_NAME "rpadlpar_io"
36 
37 #define NODE_TYPE_VIO  1
38 #define NODE_TYPE_SLOT 2
39 #define NODE_TYPE_PHB  3
40 
41 static struct device_node *find_vio_slot_node(char *drc_name)
42 {
43 	struct device_node *parent = of_find_node_by_name(NULL, "vdevice");
44 	struct device_node *dn;
45 	int rc;
46 
47 	if (!parent)
48 		return NULL;
49 
50 	for_each_child_of_node(parent, dn) {
51 		rc = rpaphp_check_drc_props(dn, drc_name, NULL);
52 		if (rc == 0)
53 			break;
54 	}
55 	of_node_put(parent);
56 
57 	return dn;
58 }
59 
60 /* Find dlpar-capable pci node that contains the specified name and type */
61 static struct device_node *find_php_slot_pci_node(char *drc_name,
62 						  char *drc_type)
63 {
64 	struct device_node *np;
65 	int rc;
66 
67 	for_each_node_by_name(np, "pci") {
68 		rc = rpaphp_check_drc_props(np, drc_name, drc_type);
69 		if (rc == 0)
70 			break;
71 	}
72 
73 	return np;
74 }
75 
76 /* Returns a device_node with its reference count incremented */
77 static struct device_node *find_dlpar_node(char *drc_name, int *node_type)
78 {
79 	struct device_node *dn;
80 
81 	dn = find_php_slot_pci_node(drc_name, "SLOT");
82 	if (dn) {
83 		*node_type = NODE_TYPE_SLOT;
84 		return dn;
85 	}
86 
87 	dn = find_php_slot_pci_node(drc_name, "PHB");
88 	if (dn) {
89 		*node_type = NODE_TYPE_PHB;
90 		return dn;
91 	}
92 
93 	dn = find_vio_slot_node(drc_name);
94 	if (dn) {
95 		*node_type = NODE_TYPE_VIO;
96 		return dn;
97 	}
98 
99 	return NULL;
100 }
101 
102 /**
103  * find_php_slot - return hotplug slot structure for device node
104  * @dn: target &device_node
105  *
106  * This routine will return the hotplug slot structure
107  * for a given device node. Note that built-in PCI slots
108  * may be dlpar-able, but not hot-pluggable, so this routine
109  * will return NULL for built-in PCI slots.
110  */
111 static struct slot *find_php_slot(struct device_node *dn)
112 {
113 	struct slot *slot, *next;
114 
115 	list_for_each_entry_safe(slot, next, &rpaphp_slot_head,
116 				 rpaphp_slot_list) {
117 		if (slot->dn == dn)
118 			return slot;
119 	}
120 
121 	return NULL;
122 }
123 
124 static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
125 					struct device_node *dev_dn)
126 {
127 	struct pci_dev *tmp = NULL;
128 	struct device_node *child_dn;
129 
130 	list_for_each_entry(tmp, &parent->devices, bus_list) {
131 		child_dn = pci_device_to_OF_node(tmp);
132 		if (child_dn == dev_dn)
133 			return tmp;
134 	}
135 	return NULL;
136 }
137 
138 static void dlpar_pci_add_bus(struct device_node *dn)
139 {
140 	struct pci_dn *pdn = PCI_DN(dn);
141 	struct pci_controller *phb = pdn->phb;
142 	struct pci_dev *dev = NULL;
143 
144 	pseries_eeh_init_edev_recursive(pdn);
145 
146 	/* Add EADS device to PHB bus, adding new entry to bus->devices */
147 	dev = of_create_pci_dev(dn, phb->bus, pdn->devfn);
148 	if (!dev) {
149 		printk(KERN_ERR "%s: failed to create pci dev for %pOF\n",
150 				__func__, dn);
151 		return;
152 	}
153 
154 	/* Scan below the new bridge */
155 	if (pci_is_bridge(dev))
156 		of_scan_pci_bridge(dev);
157 
158 	/* Map IO space for child bus, which may or may not succeed */
159 	pcibios_map_io_space(dev->subordinate);
160 
161 	/* Finish adding it : resource allocation, adding devices, etc...
162 	 * Note that we need to perform the finish pass on the -parent-
163 	 * bus of the EADS bridge so the bridge device itself gets
164 	 * properly added
165 	 */
166 	pcibios_finish_adding_to_bus(phb->bus);
167 }
168 
169 static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
170 {
171 	struct pci_dev *dev;
172 	struct pci_controller *phb;
173 
174 	if (pci_find_bus_by_node(dn))
175 		return -EINVAL;
176 
177 	/* Add pci bus */
178 	dlpar_pci_add_bus(dn);
179 
180 	/* Confirm new bridge dev was created */
181 	phb = PCI_DN(dn)->phb;
182 	dev = dlpar_find_new_dev(phb->bus, dn);
183 
184 	if (!dev) {
185 		printk(KERN_ERR "%s: unable to add bus %s\n", __func__,
186 			drc_name);
187 		return -EIO;
188 	}
189 
190 	if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
191 		printk(KERN_ERR "%s: unexpected header type %d, unable to add bus %s\n",
192 			__func__, dev->hdr_type, drc_name);
193 		return -EIO;
194 	}
195 
196 	/* Add hotplug slot */
197 	if (rpaphp_add_slot(dn)) {
198 		printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
199 			__func__, drc_name);
200 		return -EIO;
201 	}
202 	return 0;
203 }
204 
205 static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
206 {
207 	struct slot *slot;
208 	struct pci_dn *pdn;
209 	int rc = 0;
210 
211 	if (!pci_find_bus_by_node(dn))
212 		return -EINVAL;
213 
214 	/* If pci slot is hotpluggable, use hotplug to remove it */
215 	slot = find_php_slot(dn);
216 	if (slot && rpaphp_deregister_slot(slot)) {
217 		printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
218 		       __func__, drc_name);
219 		return -EIO;
220 	}
221 
222 	pdn = dn->data;
223 	BUG_ON(!pdn || !pdn->phb);
224 	rc = remove_phb_dynamic(pdn->phb);
225 	if (rc < 0)
226 		return rc;
227 
228 	pdn->phb = NULL;
229 
230 	return 0;
231 }
232 
233 static int dlpar_add_phb(char *drc_name, struct device_node *dn)
234 {
235 	struct pci_controller *phb;
236 
237 	if (PCI_DN(dn) && PCI_DN(dn)->phb) {
238 		/* PHB already exists */
239 		return -EINVAL;
240 	}
241 
242 	phb = init_phb_dynamic(dn);
243 	if (!phb)
244 		return -EIO;
245 
246 	if (rpaphp_add_slot(dn)) {
247 		printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
248 			__func__, drc_name);
249 		return -EIO;
250 	}
251 	return 0;
252 }
253 
254 static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn)
255 {
256 	struct vio_dev *vio_dev;
257 
258 	vio_dev = vio_find_node(dn);
259 	if (vio_dev) {
260 		put_device(&vio_dev->dev);
261 		return -EINVAL;
262 	}
263 
264 	if (!vio_register_device_node(dn)) {
265 		printk(KERN_ERR
266 			"%s: failed to register vio node %s\n",
267 			__func__, drc_name);
268 		return -EIO;
269 	}
270 	return 0;
271 }
272 
273 /**
274  * dlpar_add_slot - DLPAR add an I/O Slot
275  * @drc_name: drc-name of newly added slot
276  *
277  * Make the hotplug module and the kernel aware of a newly added I/O Slot.
278  * Return Codes:
279  * 0			Success
280  * -ENODEV		Not a valid drc_name
281  * -EINVAL		Slot already added
282  * -ERESTARTSYS		Signalled before obtaining lock
283  * -EIO			Internal PCI Error
284  */
285 int dlpar_add_slot(char *drc_name)
286 {
287 	struct device_node *dn = NULL;
288 	int node_type;
289 	int rc = -EIO;
290 
291 	if (mutex_lock_interruptible(&rpadlpar_mutex))
292 		return -ERESTARTSYS;
293 
294 	/* Find newly added node */
295 	dn = find_dlpar_node(drc_name, &node_type);
296 	if (!dn) {
297 		rc = -ENODEV;
298 		goto exit;
299 	}
300 
301 	switch (node_type) {
302 		case NODE_TYPE_VIO:
303 			rc = dlpar_add_vio_slot(drc_name, dn);
304 			break;
305 		case NODE_TYPE_SLOT:
306 			rc = dlpar_add_pci_slot(drc_name, dn);
307 			break;
308 		case NODE_TYPE_PHB:
309 			rc = dlpar_add_phb(drc_name, dn);
310 			break;
311 	}
312 	of_node_put(dn);
313 
314 	printk(KERN_INFO "%s: slot %s added\n", DLPAR_MODULE_NAME, drc_name);
315 exit:
316 	mutex_unlock(&rpadlpar_mutex);
317 	return rc;
318 }
319 
320 /**
321  * dlpar_remove_vio_slot - DLPAR remove a virtual I/O Slot
322  * @drc_name: drc-name of newly added slot
323  * @dn: &device_node
324  *
325  * Remove the kernel and hotplug representations of an I/O Slot.
326  * Return Codes:
327  * 0			Success
328  * -EINVAL		Vio dev doesn't exist
329  */
330 static int dlpar_remove_vio_slot(char *drc_name, struct device_node *dn)
331 {
332 	struct vio_dev *vio_dev;
333 
334 	vio_dev = vio_find_node(dn);
335 	if (!vio_dev)
336 		return -EINVAL;
337 
338 	vio_unregister_device(vio_dev);
339 
340 	put_device(&vio_dev->dev);
341 
342 	return 0;
343 }
344 
345 /**
346  * dlpar_remove_pci_slot - DLPAR remove a PCI I/O Slot
347  * @drc_name: drc-name of newly added slot
348  * @dn: &device_node
349  *
350  * Remove the kernel and hotplug representations of a PCI I/O Slot.
351  * Return Codes:
352  * 0			Success
353  * -ENODEV		Not a valid drc_name
354  * -EIO			Internal PCI Error
355  */
356 static int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
357 {
358 	struct pci_bus *bus;
359 	struct slot *slot;
360 	int ret = 0;
361 
362 	pci_lock_rescan_remove();
363 
364 	bus = pci_find_bus_by_node(dn);
365 	if (!bus) {
366 		ret = -EINVAL;
367 		goto out;
368 	}
369 
370 	pr_debug("PCI: Removing PCI slot below EADS bridge %s\n",
371 		 bus->self ? pci_name(bus->self) : "<!PHB!>");
372 
373 	slot = find_php_slot(dn);
374 	if (slot) {
375 		pr_debug("PCI: Removing hotplug slot for %04x:%02x...\n",
376 			 pci_domain_nr(bus), bus->number);
377 
378 		if (rpaphp_deregister_slot(slot)) {
379 			printk(KERN_ERR
380 				"%s: unable to remove hotplug slot %s\n",
381 				__func__, drc_name);
382 			ret = -EIO;
383 			goto out;
384 		}
385 	}
386 
387 	/* Remove all devices below slot */
388 	pci_hp_remove_devices(bus);
389 
390 	/* Unmap PCI IO space */
391 	if (pcibios_unmap_io_space(bus)) {
392 		printk(KERN_ERR "%s: failed to unmap bus range\n",
393 			__func__);
394 		ret = -ERANGE;
395 		goto out;
396 	}
397 
398 	/* Remove the EADS bridge device itself */
399 	BUG_ON(!bus->self);
400 	pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self));
401 	pci_stop_and_remove_bus_device(bus->self);
402 
403  out:
404 	pci_unlock_rescan_remove();
405 	return ret;
406 }
407 
408 /**
409  * dlpar_remove_slot - DLPAR remove an I/O Slot
410  * @drc_name: drc-name of newly added slot
411  *
412  * Remove the kernel and hotplug representations of an I/O Slot.
413  * Return Codes:
414  * 0			Success
415  * -ENODEV		Not a valid drc_name
416  * -EINVAL		Slot already removed
417  * -ERESTARTSYS		Signalled before obtaining lock
418  * -EIO			Internal Error
419  */
420 int dlpar_remove_slot(char *drc_name)
421 {
422 	struct device_node *dn;
423 	int node_type;
424 	int rc = 0;
425 
426 	if (mutex_lock_interruptible(&rpadlpar_mutex))
427 		return -ERESTARTSYS;
428 
429 	dn = find_dlpar_node(drc_name, &node_type);
430 	if (!dn) {
431 		rc = -ENODEV;
432 		goto exit;
433 	}
434 
435 	switch (node_type) {
436 		case NODE_TYPE_VIO:
437 			rc = dlpar_remove_vio_slot(drc_name, dn);
438 			break;
439 		case NODE_TYPE_PHB:
440 			rc = dlpar_remove_phb(drc_name, dn);
441 			break;
442 		case NODE_TYPE_SLOT:
443 			rc = dlpar_remove_pci_slot(drc_name, dn);
444 			break;
445 	}
446 	of_node_put(dn);
447 	vm_unmap_aliases();
448 
449 	printk(KERN_INFO "%s: slot %s removed\n", DLPAR_MODULE_NAME, drc_name);
450 exit:
451 	mutex_unlock(&rpadlpar_mutex);
452 	return rc;
453 }
454 
455 static inline int is_dlpar_capable(void)
456 {
457 	int rc = rtas_token("ibm,configure-connector");
458 
459 	return (int) (rc != RTAS_UNKNOWN_SERVICE);
460 }
461 
462 static int __init rpadlpar_io_init(void)
463 {
464 
465 	if (!is_dlpar_capable()) {
466 		printk(KERN_WARNING "%s: partition not DLPAR capable\n",
467 			__func__);
468 		return -EPERM;
469 	}
470 
471 	return dlpar_sysfs_init();
472 }
473 
474 static void __exit rpadlpar_io_exit(void)
475 {
476 	dlpar_sysfs_exit();
477 }
478 
479 module_init(rpadlpar_io_init);
480 module_exit(rpadlpar_io_exit);
481 MODULE_LICENSE("GPL");
482 MODULE_DESCRIPTION("RPA Dynamic Logical Partitioning driver for I/O slots");
483