2 * PCI Hot Plug Controller Driver for System z
4 * Copyright 2012 IBM Corp.
7 * Jan Glauber <jang@linux.vnet.ibm.com>
10 #define COMPONENT "zPCI hpc"
11 #define pr_fmt(fmt) COMPONENT ": " fmt
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/slab.h>
16 #include <linux/pci.h>
17 #include <linux/pci_hotplug.h>
18 #include <linux/init.h>
21 #define SLOT_NAME_SIZE 10
22 static LIST_HEAD(s390_hotplug_slot_list
);
24 MODULE_AUTHOR("Jan Glauber <jang@linux.vnet.ibm.com");
25 MODULE_DESCRIPTION("Hot Plug PCI Controller for System z");
26 MODULE_LICENSE("GPL");
28 static int zpci_fn_configured(enum zpci_state state
)
30 return state
== ZPCI_FN_STATE_CONFIGURED
||
31 state
== ZPCI_FN_STATE_ONLINE
;
35 * struct slot - slot information for each *physical* slot
38 struct list_head slot_list
;
39 struct hotplug_slot
*hotplug_slot
;
40 struct zpci_dev
*zdev
;
43 static int enable_slot(struct hotplug_slot
*hotplug_slot
)
45 struct slot
*slot
= hotplug_slot
->private;
48 if (slot
->zdev
->state
!= ZPCI_FN_STATE_STANDBY
)
51 rc
= sclp_pci_configure(slot
->zdev
->fid
);
53 slot
->zdev
->state
= ZPCI_FN_STATE_CONFIGURED
;
54 /* automatically scan the device after is was configured */
55 zpci_enable_device(slot
->zdev
);
56 zpci_scan_device(slot
->zdev
);
61 static int disable_slot(struct hotplug_slot
*hotplug_slot
)
63 struct slot
*slot
= hotplug_slot
->private;
66 if (!zpci_fn_configured(slot
->zdev
->state
))
69 /* TODO: we rely on the user to unbind/remove the device, is that plausible
70 * or do we need to trigger that here?
72 rc
= sclp_pci_deconfigure(slot
->zdev
->fid
);
74 /* Fixme: better call List-PCI to find the disabled FH
75 for the FID since the FH should be opaque... */
76 slot
->zdev
->fh
&= 0x7fffffff;
77 slot
->zdev
->state
= ZPCI_FN_STATE_STANDBY
;
82 static int get_power_status(struct hotplug_slot
*hotplug_slot
, u8
*value
)
84 struct slot
*slot
= hotplug_slot
->private;
86 switch (slot
->zdev
->state
) {
87 case ZPCI_FN_STATE_STANDBY
:
97 static int get_adapter_status(struct hotplug_slot
*hotplug_slot
, u8
*value
)
99 /* if the slot exits it always contains a function */
104 static void release_slot(struct hotplug_slot
*hotplug_slot
)
106 struct slot
*slot
= hotplug_slot
->private;
108 pr_debug("%s - physical_slot = %s\n", __func__
, hotplug_slot_name(hotplug_slot
));
109 kfree(slot
->hotplug_slot
->info
);
110 kfree(slot
->hotplug_slot
);
114 static struct hotplug_slot_ops s390_hotplug_slot_ops
= {
115 .enable_slot
= enable_slot
,
116 .disable_slot
= disable_slot
,
117 .get_power_status
= get_power_status
,
118 .get_adapter_status
= get_adapter_status
,
121 static int init_pci_slot(struct zpci_dev
*zdev
)
123 struct hotplug_slot
*hotplug_slot
;
124 struct hotplug_slot_info
*info
;
125 char name
[SLOT_NAME_SIZE
];
132 slot
= kzalloc(sizeof(*slot
), GFP_KERNEL
);
136 hotplug_slot
= kzalloc(sizeof(*hotplug_slot
), GFP_KERNEL
);
139 hotplug_slot
->private = slot
;
141 slot
->hotplug_slot
= hotplug_slot
;
144 info
= kzalloc(sizeof(*info
), GFP_KERNEL
);
147 hotplug_slot
->info
= info
;
149 hotplug_slot
->ops
= &s390_hotplug_slot_ops
;
150 hotplug_slot
->release
= &release_slot
;
152 get_power_status(hotplug_slot
, &info
->power_status
);
153 get_adapter_status(hotplug_slot
, &info
->adapter_status
);
155 snprintf(name
, SLOT_NAME_SIZE
, "%08x", zdev
->fid
);
156 rc
= pci_hp_register(slot
->hotplug_slot
, zdev
->bus
,
159 pr_err("pci_hp_register failed with error %d\n", rc
);
162 list_add(&slot
->slot_list
, &s390_hotplug_slot_list
);
175 static void exit_pci_slot(struct zpci_dev
*zdev
)
177 struct list_head
*tmp
, *n
;
180 list_for_each_safe(tmp
, n
, &s390_hotplug_slot_list
) {
181 slot
= list_entry(tmp
, struct slot
, slot_list
);
182 if (slot
->zdev
!= zdev
)
184 list_del(&slot
->slot_list
);
185 pci_hp_deregister(slot
->hotplug_slot
);
189 static struct pci_hp_callback_ops hp_ops
= {
190 .create_slot
= init_pci_slot
,
191 .remove_slot
= exit_pci_slot
,
194 static void __init
init_pci_slots(void)
196 struct zpci_dev
*zdev
;
199 * Create a structure for each slot, and register that slot
200 * with the pci_hotplug subsystem.
202 mutex_lock(&zpci_list_lock
);
203 list_for_each_entry(zdev
, &zpci_list
, entry
) {
206 mutex_unlock(&zpci_list_lock
);
209 static void __exit
exit_pci_slots(void)
211 struct list_head
*tmp
, *n
;
215 * Unregister all of our slots with the pci_hotplug subsystem.
216 * Memory will be freed in release_slot() callback after slot's
217 * lifespan is finished.
219 list_for_each_safe(tmp
, n
, &s390_hotplug_slot_list
) {
220 slot
= list_entry(tmp
, struct slot
, slot_list
);
221 list_del(&slot
->slot_list
);
222 pci_hp_deregister(slot
->hotplug_slot
);
226 static int __init
pci_hotplug_s390_init(void)
231 zpci_register_hp_ops(&hp_ops
);
237 static void __exit
pci_hotplug_s390_exit(void)
240 zpci_deregister_hp_ops();
243 module_init(pci_hotplug_s390_init
);
244 module_exit(pci_hotplug_s390_exit
);