Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[linux-2.6-microblaze.git] / drivers / pci / hotplug / pcihp_skeleton.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * PCI Hot Plug Controller Skeleton Driver - 0.3
4  *
5  * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
6  * Copyright (C) 2001,2003 IBM Corp.
7  *
8  * All rights reserved.
9  *
10  * This driver is to be used as a skeleton driver to show how to interface
11  * with the pci hotplug core easily.
12  *
13  * Send feedback to <greg@kroah.com>
14  *
15  */
16
17 #include <linux/module.h>
18 #include <linux/moduleparam.h>
19 #include <linux/kernel.h>
20 #include <linux/slab.h>
21 #include <linux/pci.h>
22 #include <linux/pci_hotplug.h>
23 #include <linux/init.h>
24
25 #define SLOT_NAME_SIZE  10
26 struct slot {
27         u8 number;
28         struct hotplug_slot *hotplug_slot;
29         struct list_head slot_list;
30         char name[SLOT_NAME_SIZE];
31 };
32
33 static LIST_HEAD(slot_list);
34
35 #define MY_NAME "pcihp_skeleton"
36
37 #define dbg(format, arg...)                                     \
38         do {                                                    \
39                 if (debug)                                      \
40                         printk(KERN_DEBUG "%s: " format "\n",   \
41                                 MY_NAME, ## arg);               \
42         } while (0)
43 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME, ## arg)
44 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME, ## arg)
45 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME, ## arg)
46
47 /* local variables */
48 static bool debug;
49 static int num_slots;
50
51 #define DRIVER_VERSION  "0.3"
52 #define DRIVER_AUTHOR   "Greg Kroah-Hartman <greg@kroah.com>"
53 #define DRIVER_DESC     "Hot Plug PCI Controller Skeleton Driver"
54
55 MODULE_AUTHOR(DRIVER_AUTHOR);
56 MODULE_DESCRIPTION(DRIVER_DESC);
57 MODULE_LICENSE("GPL");
58 module_param(debug, bool, 0644);
59 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
60
61 static int enable_slot(struct hotplug_slot *slot);
62 static int disable_slot(struct hotplug_slot *slot);
63 static int set_attention_status(struct hotplug_slot *slot, u8 value);
64 static int hardware_test(struct hotplug_slot *slot, u32 value);
65 static int get_power_status(struct hotplug_slot *slot, u8 *value);
66 static int get_attention_status(struct hotplug_slot *slot, u8 *value);
67 static int get_latch_status(struct hotplug_slot *slot, u8 *value);
68 static int get_adapter_status(struct hotplug_slot *slot, u8 *value);
69
70 static struct hotplug_slot_ops skel_hotplug_slot_ops = {
71         .enable_slot =          enable_slot,
72         .disable_slot =         disable_slot,
73         .set_attention_status = set_attention_status,
74         .hardware_test =        hardware_test,
75         .get_power_status =     get_power_status,
76         .get_attention_status = get_attention_status,
77         .get_latch_status =     get_latch_status,
78         .get_adapter_status =   get_adapter_status,
79 };
80
81 static int enable_slot(struct hotplug_slot *hotplug_slot)
82 {
83         struct slot *slot = hotplug_slot->private;
84         int retval = 0;
85
86         dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
87
88         /*
89          * Fill in code here to enable the specified slot
90          */
91
92         return retval;
93 }
94
95 static int disable_slot(struct hotplug_slot *hotplug_slot)
96 {
97         struct slot *slot = hotplug_slot->private;
98         int retval = 0;
99
100         dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
101
102         /*
103          * Fill in code here to disable the specified slot
104          */
105
106         return retval;
107 }
108
109 static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
110 {
111         struct slot *slot = hotplug_slot->private;
112         int retval = 0;
113
114         dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
115
116         switch (status) {
117         case 0:
118                 /*
119                  * Fill in code here to turn light off
120                  */
121                 break;
122
123         case 1:
124         default:
125                 /*
126                  * Fill in code here to turn light on
127                  */
128                 break;
129         }
130
131         return retval;
132 }
133
134 static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value)
135 {
136         struct slot *slot = hotplug_slot->private;
137         int retval = 0;
138
139         dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
140
141         switch (value) {
142         case 0:
143                 /* Specify a test here */
144                 break;
145         case 1:
146                 /* Specify another test here */
147                 break;
148         }
149
150         return retval;
151 }
152
153 static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
154 {
155         struct slot *slot = hotplug_slot->private;
156         int retval = 0;
157
158         dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
159
160         /*
161          * Fill in logic to get the current power status of the specific
162          * slot and store it in the *value location.
163          */
164
165         return retval;
166 }
167
168 static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
169 {
170         struct slot *slot = hotplug_slot->private;
171         int retval = 0;
172
173         dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
174
175         /*
176          * Fill in logic to get the current attention status of the specific
177          * slot and store it in the *value location.
178          */
179
180         return retval;
181 }
182
183 static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
184 {
185         struct slot *slot = hotplug_slot->private;
186         int retval = 0;
187
188         dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
189
190         /*
191          * Fill in logic to get the current latch status of the specific
192          * slot and store it in the *value location.
193          */
194
195         return retval;
196 }
197
198 static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
199 {
200         struct slot *slot = hotplug_slot->private;
201         int retval = 0;
202
203         dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
204
205         /*
206          * Fill in logic to get the current adapter status of the specific
207          * slot and store it in the *value location.
208          */
209
210         return retval;
211 }
212
213 static void release_slot(struct hotplug_slot *hotplug_slot)
214 {
215         struct slot *slot = hotplug_slot->private;
216
217         dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
218         kfree(slot->hotplug_slot->info);
219         kfree(slot->hotplug_slot);
220         kfree(slot);
221 }
222
223 static void make_slot_name(struct slot *slot)
224 {
225         /*
226          * Stupid way to make a filename out of the slot name.
227          * replace this if your hardware provides a better way to name slots.
228          */
229         snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", slot->number);
230 }
231
232 /**
233  * init_slots - initialize 'struct slot' structures for each slot
234  *
235  */
236 static int __init init_slots(void)
237 {
238         struct slot *slot;
239         struct hotplug_slot *hotplug_slot;
240         struct hotplug_slot_info *info;
241         int retval;
242         int i;
243
244         /*
245          * Create a structure for each slot, and register that slot
246          * with the pci_hotplug subsystem.
247          */
248         for (i = 0; i < num_slots; ++i) {
249                 slot = kzalloc(sizeof(*slot), GFP_KERNEL);
250                 if (!slot) {
251                         retval = -ENOMEM;
252                         goto error;
253                 }
254
255                 hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
256                 if (!hotplug_slot) {
257                         retval = -ENOMEM;
258                         goto error_slot;
259                 }
260                 slot->hotplug_slot = hotplug_slot;
261
262                 info = kzalloc(sizeof(*info), GFP_KERNEL);
263                 if (!info) {
264                         retval = -ENOMEM;
265                         goto error_hpslot;
266                 }
267                 hotplug_slot->info = info;
268
269                 slot->number = i;
270
271                 hotplug_slot->name = slot->name;
272                 hotplug_slot->private = slot;
273                 hotplug_slot->release = &release_slot;
274                 make_slot_name(slot);
275                 hotplug_slot->ops = &skel_hotplug_slot_ops;
276
277                 /*
278                  * Initialize the slot info structure with some known
279                  * good values.
280                  */
281                 get_power_status(hotplug_slot, &info->power_status);
282                 get_attention_status(hotplug_slot, &info->attention_status);
283                 get_latch_status(hotplug_slot, &info->latch_status);
284                 get_adapter_status(hotplug_slot, &info->adapter_status);
285
286                 dbg("registering slot %d\n", i);
287                 retval = pci_hp_register(slot->hotplug_slot);
288                 if (retval) {
289                         err("pci_hp_register failed with error %d\n", retval);
290                         goto error_info;
291                 }
292
293                 /* add slot to our internal list */
294                 list_add(&slot->slot_list, &slot_list);
295         }
296
297         return 0;
298 error_info:
299         kfree(info);
300 error_hpslot:
301         kfree(hotplug_slot);
302 error_slot:
303         kfree(slot);
304 error:
305         return retval;
306 }
307
308 static void __exit cleanup_slots(void)
309 {
310         struct slot *slot, *next;
311
312         /*
313          * Unregister all of our slots with the pci_hotplug subsystem.
314          * Memory will be freed in release_slot() callback after slot's
315          * lifespan is finished.
316          */
317         list_for_each_entry_safe(slot, next, &slot_list, slot_list) {
318                 list_del(&slot->slot_list);
319                 pci_hp_deregister(slot->hotplug_slot);
320         }
321 }
322
323 static int __init pcihp_skel_init(void)
324 {
325         int retval;
326
327         info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
328         /*
329          * Do specific initialization stuff for your driver here
330          * like initializing your controller hardware (if any) and
331          * determining the number of slots you have in the system
332          * right now.
333          */
334         num_slots = 5;
335
336         return init_slots();
337 }
338
339 static void __exit pcihp_skel_exit(void)
340 {
341         /*
342          * Clean everything up.
343          */
344         cleanup_slots();
345 }
346
347 module_init(pcihp_skel_init);
348 module_exit(pcihp_skel_exit);