Blame view

drivers/pci/hotplug/rpadlpar_core.c 9.72 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /*
   * Interface for Dynamic Logical Partitioning of I/O Slots on
   * RPA-compliant PPC64 platform.
   *
   * John Rose <johnrose@austin.ibm.com>
   * Linda Xie <lxie@us.ibm.com>
   *
   * October 2003
   *
   * Copyright (C) 2003 IBM.
   *
   *      This program is free software; you can redistribute it and/or
   *      modify it under the terms of the GNU General Public License
   *      as published by the Free Software Foundation; either version
   *      2 of the License, or (at your option) any later version.
   */
  #include <linux/init.h>
  #include <linux/pci.h>
4e57b6817   Tim Schmielau   [PATCH] fix missi...
19
  #include <linux/string.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #include <asm/pci-bridge.h>
14cc3e2b6   Ingo Molnar   [PATCH] sem2mutex...
21
  #include <linux/mutex.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #include <asm/rtas.h>
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
23
  #include <asm/vio.h>
4e57b6817   Tim Schmielau   [PATCH] fix missi...
24

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
  #include "../pci.h"
  #include "rpaphp.h"
  #include "rpadlpar.h"
14cc3e2b6   Ingo Molnar   [PATCH] sem2mutex...
28
  static DEFINE_MUTEX(rpadlpar_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29

56d8456b0   John Rose   [PATCH] PCI Hotpl...
30
  #define DLPAR_MODULE_NAME "rpadlpar_io"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
33
  #define NODE_TYPE_VIO  1
  #define NODE_TYPE_SLOT 2
  #define NODE_TYPE_PHB  3
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
34
  static struct device_node *find_vio_slot_node(char *drc_name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
  	struct device_node *parent = of_find_node_by_name(NULL, "vdevice");
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
37
38
39
  	struct device_node *dn = NULL;
  	char *name;
  	int rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
  
  	if (!parent)
  		return NULL;
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
43
44
45
46
  	while ((dn = of_get_next_child(parent, dn))) {
  		rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL);
  		if ((rc == 0) && (!strcmp(drc_name, name)))
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
  	}
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
48
  	return dn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
53
54
55
56
57
58
  }
  
  /* Find dlpar-capable pci node that contains the specified name and type */
  static struct device_node *find_php_slot_pci_node(char *drc_name,
  						  char *drc_type)
  {
  	struct device_node *np = NULL;
  	char *name;
  	char *type;
  	int rc;
a57ed79ef   John Rose   PCI: rpaphp: chan...
59
  	while ((np = of_find_node_by_name(np, "pci"))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
64
65
66
67
  		rc = rpaphp_get_drc_props(np, NULL, &name, &type, NULL);
  		if (rc == 0)
  			if (!strcmp(drc_name, name) && !strcmp(drc_type, type))
  				break;
  	}
  
  	return np;
  }
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
68
  static struct device_node *find_dlpar_node(char *drc_name, int *node_type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  {
  	struct device_node *dn;
  
  	dn = find_php_slot_pci_node(drc_name, "SLOT");
  	if (dn) {
  		*node_type = NODE_TYPE_SLOT;
  		return dn;
  	}
  
  	dn = find_php_slot_pci_node(drc_name, "PHB");
  	if (dn) {
  		*node_type = NODE_TYPE_PHB;
  		return dn;
  	}
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
83
  	dn = find_vio_slot_node(drc_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
86
87
88
89
90
  	if (dn) {
  		*node_type = NODE_TYPE_VIO;
  		return dn;
  	}
  
  	return NULL;
  }
56d8456b0   John Rose   [PATCH] PCI Hotpl...
91
  static struct slot *find_slot(struct device_node *dn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
94
  {
  	struct list_head *tmp, *n;
  	struct slot *slot;
8737d6a90   Linas Vepstas   [PATCH] powerpc/P...
95
96
97
98
99
  	list_for_each_safe(tmp, n, &rpaphp_slot_head) {
  		slot = list_entry(tmp, struct slot, rpaphp_slot_list);
  		if (slot->dn == dn)
  			return slot;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100

8737d6a90   Linas Vepstas   [PATCH] powerpc/P...
101
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
  }
0945cd5f9   John Rose   [PATCH] PCI Hotpl...
103
104
105
106
107
108
109
110
111
112
113
114
115
  static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
  					struct device_node *dev_dn)
  {
  	struct pci_dev *tmp = NULL;
  	struct device_node *child_dn;
  
  	list_for_each_entry(tmp, &parent->devices, bus_list) {
  		child_dn = pci_device_to_OF_node(tmp);
  		if (child_dn == dev_dn)
  			return tmp;
  	}
  	return NULL;
  }
8737d6a90   Linas Vepstas   [PATCH] powerpc/P...
116
  static void dlpar_pci_add_bus(struct device_node *dn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
  {
8737d6a90   Linas Vepstas   [PATCH] powerpc/P...
118
  	struct pci_dn *pdn = PCI_DN(dn);
5fa80fcdc   John Rose   [PATCH] dlpar reg...
119
  	struct pci_controller *phb = pdn->phb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
  	struct pci_dev *dev = NULL;
d681db4ae   Linas Vepstas   [PATCH] PCI Hotpl...
121
  	eeh_add_device_tree_early(dn);
5fa80fcdc   John Rose   [PATCH] dlpar reg...
122
123
124
125
126
127
  	/* Add EADS device to PHB bus, adding new entry to bus->devices */
  	dev = of_create_pci_dev(dn, phb->bus, pdn->devfn);
  	if (!dev) {
  		printk(KERN_ERR "%s: failed to create pci dev for %s
  ",
  				__FUNCTION__, dn->full_name);
8737d6a90   Linas Vepstas   [PATCH] powerpc/P...
128
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  	}
5fa80fcdc   John Rose   [PATCH] dlpar reg...
130
131
132
  	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
  	    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
  		of_scan_pci_bridge(dn, dev);
eca845c71   Linas Vepstas   [PATCH] powerpc/P...
133
  	pcibios_fixup_new_pci_devices(dev->subordinate,0);
5fa80fcdc   John Rose   [PATCH] dlpar reg...
134
135
  
  	/* Claim new bus resources */
cd5b50be8   Linas Vepstas   [PATCH] PCI Hotpl...
136
  	pcibios_claim_one_bus(dev->bus);
5fa80fcdc   John Rose   [PATCH] dlpar reg...
137
138
  
  	/* ioremap() for child bus, which may or may not succeed */
3c0c64418   Linas Vepstas   [PATCH] PCI Hotpl...
139
  	remap_bus_range(dev->subordinate);
5fa80fcdc   John Rose   [PATCH] dlpar reg...
140

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  	/* Add new devices to global lists.  Register in proc, sysfs. */
5fa80fcdc   John Rose   [PATCH] dlpar reg...
142
  	pci_bus_add_devices(phb->bus);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
  }
940903c5a   John Rose   [PATCH] PCI Hotpl...
144
  static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
  {
  	struct pci_dev *dev;
8737d6a90   Linas Vepstas   [PATCH] powerpc/P...
147
  	struct pci_controller *phb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148

01657868b   Linas Vepstas   [PATCH] powerpc/P...
149
  	if (pcibios_find_pci_bus(dn))
56d8456b0   John Rose   [PATCH] PCI Hotpl...
150
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
  	/* Add pci bus */
8737d6a90   Linas Vepstas   [PATCH] powerpc/P...
152
153
154
155
156
  	dlpar_pci_add_bus(dn);
  
  	/* Confirm new bridge dev was created */
  	phb = PCI_DN(dn)->phb;
  	dev = dlpar_find_new_dev(phb->bus, dn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
158
159
160
161
162
  	if (!dev) {
  		printk(KERN_ERR "%s: unable to add bus %s
  ", __FUNCTION__,
  			drc_name);
  		return -EIO;
  	}
8737d6a90   Linas Vepstas   [PATCH] powerpc/P...
163
164
165
166
167
168
  	if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
  		printk(KERN_ERR "%s: unexpected header type %d, unable to add bus %s
  ",
  			__FUNCTION__, dev->hdr_type, drc_name);
  		return -EIO;
  	}
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
169
170
171
172
173
174
175
  	/* Add hotplug slot */
  	if (rpaphp_add_slot(dn)) {
  		printk(KERN_ERR "%s: unable to add hotplug slot %s
  ",
  			__FUNCTION__, drc_name);
  		return -EIO;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
  	return 0;
  }
  
  static int dlpar_remove_root_bus(struct pci_controller *phb)
  {
  	struct pci_bus *phb_bus;
  	int rc;
  
  	phb_bus = phb->bus;
  	if (!(list_empty(&phb_bus->children) &&
  	      list_empty(&phb_bus->devices))) {
  		return -EBUSY;
  	}
  
  	rc = pcibios_remove_root_bus(phb);
  	if (rc)
  		return -EIO;
  
  	device_unregister(phb_bus->bridge);
  	pci_remove_bus(phb_bus);
  
  	return 0;
  }
56d8456b0   John Rose   [PATCH] PCI Hotpl...
199
  static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  {
56d8456b0   John Rose   [PATCH] PCI Hotpl...
201
  	struct slot *slot;
1635317fa   Paul Mackerras   [PATCH] Separate ...
202
  	struct pci_dn *pdn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
  	int rc = 0;
01657868b   Linas Vepstas   [PATCH] powerpc/P...
204
  	if (!pcibios_find_pci_bus(dn))
56d8456b0   John Rose   [PATCH] PCI Hotpl...
205
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206

56d8456b0   John Rose   [PATCH] PCI Hotpl...
207
208
209
  	slot = find_slot(dn);
  	if (slot) {
  		/* Remove hotplug slot */
f6afbad82   Linas Vepstas   [PATCH] powerpc/P...
210
  		if (rpaphp_deregister_slot(slot)) {
56d8456b0   John Rose   [PATCH] PCI Hotpl...
211
212
213
214
215
216
  			printk(KERN_ERR
  				"%s: unable to remove hotplug slot %s
  ",
  				__FUNCTION__, drc_name);
  			return -EIO;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
  	}
1635317fa   Paul Mackerras   [PATCH] Separate ...
218
219
220
  	pdn = dn->data;
  	BUG_ON(!pdn || !pdn->phb);
  	rc = dlpar_remove_root_bus(pdn->phb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
  	if (rc < 0)
  		return rc;
1635317fa   Paul Mackerras   [PATCH] Separate ...
223
  	pdn->phb = NULL;
56d8456b0   John Rose   [PATCH] PCI Hotpl...
224

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
  	return 0;
  }
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
227
  static int dlpar_add_phb(char *drc_name, struct device_node *dn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
  {
  	struct pci_controller *phb;
fe98aeab8   Linas Vepstas   [PATCH] ppc64: bu...
230
  	if (PCI_DN(dn) && PCI_DN(dn)->phb) {
56d8456b0   John Rose   [PATCH] PCI Hotpl...
231
232
233
  		/* PHB already exists */
  		return -EINVAL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
  	phb = init_phb_dynamic(dn);
  	if (!phb)
56d8456b0   John Rose   [PATCH] PCI Hotpl...
236
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237

5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
238
239
240
241
242
243
  	if (rpaphp_add_slot(dn)) {
  		printk(KERN_ERR "%s: unable to add hotplug slot %s
  ",
  			__FUNCTION__, drc_name);
  		return -EIO;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
245
  	return 0;
  }
56d8456b0   John Rose   [PATCH] PCI Hotpl...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn)
  {
  	if (vio_find_node(dn))
  		return -EINVAL;
  
  	if (!vio_register_device_node(dn)) {
  		printk(KERN_ERR
  			"%s: failed to register vio node %s
  ",
  			__FUNCTION__, drc_name);
  		return -EIO;
  	}
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
  /**
   * dlpar_add_slot - DLPAR add an I/O Slot
   * @drc_name: drc-name of newly added slot
   *
   * Make the hotplug module and the kernel aware
   * of a newly added I/O Slot.
   * Return Codes -
   * 0			Success
   * -ENODEV		Not a valid drc_name
   * -EINVAL		Slot already added
   * -ERESTARTSYS		Signalled before obtaining lock
   * -EIO			Internal PCI Error
   */
  int dlpar_add_slot(char *drc_name)
  {
  	struct device_node *dn = NULL;
  	int node_type;
56d8456b0   John Rose   [PATCH] PCI Hotpl...
277
  	int rc = -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278

14cc3e2b6   Ingo Molnar   [PATCH] sem2mutex...
279
  	if (mutex_lock_interruptible(&rpadlpar_mutex))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
  		return -ERESTARTSYS;
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
281
282
  	/* Find newly added node */
  	dn = find_dlpar_node(drc_name, &node_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
284
285
286
287
288
289
  	if (!dn) {
  		rc = -ENODEV;
  		goto exit;
  	}
  
  	switch (node_type) {
  		case NODE_TYPE_VIO:
56d8456b0   John Rose   [PATCH] PCI Hotpl...
290
  			rc = dlpar_add_vio_slot(drc_name, dn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
292
293
294
295
  			break;
  		case NODE_TYPE_SLOT:
  			rc = dlpar_add_pci_slot(drc_name, dn);
  			break;
  		case NODE_TYPE_PHB:
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
296
  			rc = dlpar_add_phb(drc_name, dn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
  	}
56d8456b0   John Rose   [PATCH] PCI Hotpl...
299
300
  	printk(KERN_INFO "%s: slot %s added
  ", DLPAR_MODULE_NAME, drc_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
  exit:
14cc3e2b6   Ingo Molnar   [PATCH] sem2mutex...
302
  	mutex_unlock(&rpadlpar_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
304
305
306
307
308
309
310
311
312
313
  	return rc;
  }
  
  /**
   * dlpar_remove_vio_slot - DLPAR remove a virtual I/O Slot
   * @drc_name: drc-name of newly added slot
   *
   * Remove the kernel and hotplug representations
   * of an I/O Slot.
   * Return Codes:
   * 0			Success
56d8456b0   John Rose   [PATCH] PCI Hotpl...
314
   * -EINVAL		Vio dev doesn't exist
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
   */
56d8456b0   John Rose   [PATCH] PCI Hotpl...
316
  static int dlpar_remove_vio_slot(char *drc_name, struct device_node *dn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
  {
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
318
  	struct vio_dev *vio_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319

5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
320
  	vio_dev = vio_find_node(dn);
56d8456b0   John Rose   [PATCH] PCI Hotpl...
321
322
  	if (!vio_dev)
  		return -EINVAL;
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
323
324
  
  	vio_unregister_device(vio_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  	return 0;
  }
  
  /**
   * dlpar_remove_slot - DLPAR remove a PCI I/O Slot
   * @drc_name: drc-name of newly added slot
   *
   * Remove the kernel and hotplug representations
   * of a PCI I/O Slot.
   * Return Codes:
   * 0			Success
   * -ENODEV		Not a valid drc_name
   * -EIO			Internal PCI Error
   */
56d8456b0   John Rose   [PATCH] PCI Hotpl...
339
  int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
  {
56d8456b0   John Rose   [PATCH] PCI Hotpl...
341
342
  	struct pci_bus *bus;
  	struct slot *slot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343

01657868b   Linas Vepstas   [PATCH] powerpc/P...
344
  	bus = pcibios_find_pci_bus(dn);
56d8456b0   John Rose   [PATCH] PCI Hotpl...
345
346
347
348
349
350
  	if (!bus)
  		return -EINVAL;
  
  	slot = find_slot(dn);
  	if (slot) {
  		/* Remove hotplug slot */
f6afbad82   Linas Vepstas   [PATCH] powerpc/P...
351
  		if (rpaphp_deregister_slot(slot)) {
56d8456b0   John Rose   [PATCH] PCI Hotpl...
352
353
354
355
356
357
  			printk(KERN_ERR
  				"%s: unable to remove hotplug slot %s
  ",
  				__FUNCTION__, drc_name);
  			return -EIO;
  		}
5fa80fcdc   John Rose   [PATCH] dlpar reg...
358
  	} else {
8fe64399c   Linas Vepstas   [PATCH] powerpc/P...
359
360
361
362
363
  		struct pci_dev *dev, *tmp;
  		list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
  			eeh_remove_bus_device(dev);
  			pci_remove_bus_device(dev);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
  	}
9c209c919   John Rose   [PATCH] PCI Hotpl...
365
366
367
368
369
  	if (unmap_bus_range(bus)) {
  		printk(KERN_ERR "%s: failed to unmap bus range
  ",
  			__FUNCTION__);
  		return -ERANGE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  	}
9c209c919   John Rose   [PATCH] PCI Hotpl...
371
372
373
  
  	BUG_ON(!bus->self);
  	pci_remove_bus_device(bus->self);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
  	return 0;
  }
  
  /**
   * dlpar_remove_slot - DLPAR remove an I/O Slot
   * @drc_name: drc-name of newly added slot
   *
   * Remove the kernel and hotplug representations
   * of an I/O Slot.
   * Return Codes:
   * 0			Success
   * -ENODEV		Not a valid drc_name
   * -EINVAL		Slot already removed
   * -ERESTARTSYS		Signalled before obtaining lock
   * -EIO			Internal Error
   */
  int dlpar_remove_slot(char *drc_name)
  {
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
392
  	struct device_node *dn;
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
393
  	int node_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
  	int rc = 0;
14cc3e2b6   Ingo Molnar   [PATCH] sem2mutex...
395
  	if (mutex_lock_interruptible(&rpadlpar_mutex))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
  		return -ERESTARTSYS;
5eeb8c63a   John Rose   [PATCH] PCI Hotpl...
397
398
  	dn = find_dlpar_node(drc_name, &node_type);
  	if (!dn) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
400
401
  		rc = -ENODEV;
  		goto exit;
  	}
56d8456b0   John Rose   [PATCH] PCI Hotpl...
402
403
404
405
406
407
408
409
410
411
  	switch (node_type) {
  		case NODE_TYPE_VIO:
  			rc = dlpar_remove_vio_slot(drc_name, dn);
  			break;
  		case NODE_TYPE_PHB:
  			rc = dlpar_remove_phb(drc_name, dn);
  			break;
  		case NODE_TYPE_SLOT:
  			rc = dlpar_remove_pci_slot(drc_name, dn);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
  	}
56d8456b0   John Rose   [PATCH] PCI Hotpl...
413
414
  	printk(KERN_INFO "%s: slot %s removed
  ", DLPAR_MODULE_NAME, drc_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
  exit:
14cc3e2b6   Ingo Molnar   [PATCH] sem2mutex...
416
  	mutex_unlock(&rpadlpar_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
  	return rc;
  }
  
  static inline int is_dlpar_capable(void)
  {
  	int rc = rtas_token("ibm,configure-connector");
  
  	return (int) (rc != RTAS_UNKNOWN_SERVICE);
  }
  
  int __init rpadlpar_io_init(void)
  {
  	int rc = 0;
  
  	if (!is_dlpar_capable()) {
  		printk(KERN_WARNING "%s: partition not DLPAR capable
  ",
  			__FUNCTION__);
  		return -EPERM;
  	}
  
  	rc = dlpar_sysfs_init();
  	return rc;
  }
  
  void rpadlpar_io_exit(void)
  {
  	dlpar_sysfs_exit();
  	return;
  }
  
  module_init(rpadlpar_io_init);
  module_exit(rpadlpar_io_exit);
  MODULE_LICENSE("GPL");