aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2013-01-31 13:55:17 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-02-14 09:55:17 -0500
commit53923354d69e4748506bfee932b7c6b309a15c21 (patch)
tree3d6e2d0fac4f26f53cbff549ad31b0032006c99d
parentadd09d61fee72d7a346051332b6d99f18989504c (diff)
s390/pci: fix hotplug module init
Loading the pci hotplug module when no devices are present will fail but unfortunately some hotplug callbacks stay registered to the pci bus level. Fix this by not letting module loading fail when no pci devices are present and provide proper {de}registration functions for these callbacks. Reviewed-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/include/asm/pci.h4
-rw-r--r--arch/s390/pci/pci.c27
-rw-r--r--drivers/pci/hotplug/s390_pci_hpc.c58
3 files changed, 49 insertions, 40 deletions
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 6383c44c6629..05333b7f0469 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -185,9 +185,11 @@ void zpci_dma_exit(void);
185/* Hotplug */ 185/* Hotplug */
186extern struct mutex zpci_list_lock; 186extern struct mutex zpci_list_lock;
187extern struct list_head zpci_list; 187extern struct list_head zpci_list;
188extern struct pci_hp_callback_ops hotplug_ops;
189extern unsigned int s390_pci_probe; 188extern unsigned int s390_pci_probe;
190 189
190void zpci_register_hp_ops(struct pci_hp_callback_ops *);
191void zpci_deregister_hp_ops(void);
192
191/* FMB */ 193/* FMB */
192int zpci_fmb_enable_device(struct zpci_dev *); 194int zpci_fmb_enable_device(struct zpci_dev *);
193int zpci_fmb_disable_device(struct zpci_dev *); 195int zpci_fmb_disable_device(struct zpci_dev *);
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index aa74409db656..27b4c17855b9 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -51,8 +51,7 @@ EXPORT_SYMBOL_GPL(zpci_list);
51DEFINE_MUTEX(zpci_list_lock); 51DEFINE_MUTEX(zpci_list_lock);
52EXPORT_SYMBOL_GPL(zpci_list_lock); 52EXPORT_SYMBOL_GPL(zpci_list_lock);
53 53
54struct pci_hp_callback_ops hotplug_ops; 54static struct pci_hp_callback_ops *hotplug_ops;
55EXPORT_SYMBOL_GPL(hotplug_ops);
56 55
57static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES); 56static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES);
58static DEFINE_SPINLOCK(zpci_domain_lock); 57static DEFINE_SPINLOCK(zpci_domain_lock);
@@ -974,8 +973,8 @@ int zpci_create_device(struct zpci_dev *zdev)
974 973
975 mutex_lock(&zpci_list_lock); 974 mutex_lock(&zpci_list_lock);
976 list_add_tail(&zdev->entry, &zpci_list); 975 list_add_tail(&zdev->entry, &zpci_list);
977 if (hotplug_ops.create_slot) 976 if (hotplug_ops)
978 hotplug_ops.create_slot(zdev); 977 hotplug_ops->create_slot(zdev);
979 mutex_unlock(&zpci_list_lock); 978 mutex_unlock(&zpci_list_lock);
980 979
981 if (zdev->state == ZPCI_FN_STATE_STANDBY) 980 if (zdev->state == ZPCI_FN_STATE_STANDBY)
@@ -989,8 +988,8 @@ int zpci_create_device(struct zpci_dev *zdev)
989out_start: 988out_start:
990 mutex_lock(&zpci_list_lock); 989 mutex_lock(&zpci_list_lock);
991 list_del(&zdev->entry); 990 list_del(&zdev->entry);
992 if (hotplug_ops.remove_slot) 991 if (hotplug_ops)
993 hotplug_ops.remove_slot(zdev); 992 hotplug_ops->remove_slot(zdev);
994 mutex_unlock(&zpci_list_lock); 993 mutex_unlock(&zpci_list_lock);
995out_bus: 994out_bus:
996 zpci_free_domain(zdev); 995 zpci_free_domain(zdev);
@@ -1072,6 +1071,22 @@ static void zpci_mem_exit(void)
1072 kmem_cache_destroy(zdev_fmb_cache); 1071 kmem_cache_destroy(zdev_fmb_cache);
1073} 1072}
1074 1073
1074void zpci_register_hp_ops(struct pci_hp_callback_ops *ops)
1075{
1076 mutex_lock(&zpci_list_lock);
1077 hotplug_ops = ops;
1078 mutex_unlock(&zpci_list_lock);
1079}
1080EXPORT_SYMBOL_GPL(zpci_register_hp_ops);
1081
1082void zpci_deregister_hp_ops(void)
1083{
1084 mutex_lock(&zpci_list_lock);
1085 hotplug_ops = NULL;
1086 mutex_unlock(&zpci_list_lock);
1087}
1088EXPORT_SYMBOL_GPL(zpci_deregister_hp_ops);
1089
1075unsigned int s390_pci_probe = 1; 1090unsigned int s390_pci_probe = 1;
1076EXPORT_SYMBOL_GPL(s390_pci_probe); 1091EXPORT_SYMBOL_GPL(s390_pci_probe);
1077 1092
diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c
index 8fe2a8aa89a1..7db249a25016 100644
--- a/drivers/pci/hotplug/s390_pci_hpc.c
+++ b/drivers/pci/hotplug/s390_pci_hpc.c
@@ -172,25 +172,6 @@ error:
172 return -ENOMEM; 172 return -ENOMEM;
173} 173}
174 174
175static int __init init_pci_slots(void)
176{
177 struct zpci_dev *zdev;
178 int device = 0;
179
180 /*
181 * Create a structure for each slot, and register that slot
182 * with the pci_hotplug subsystem.
183 */
184 mutex_lock(&zpci_list_lock);
185 list_for_each_entry(zdev, &zpci_list, entry) {
186 init_pci_slot(zdev);
187 device++;
188 }
189
190 mutex_unlock(&zpci_list_lock);
191 return (device) ? 0 : -ENODEV;
192}
193
194static void exit_pci_slot(struct zpci_dev *zdev) 175static void exit_pci_slot(struct zpci_dev *zdev)
195{ 176{
196 struct list_head *tmp, *n; 177 struct list_head *tmp, *n;
@@ -205,6 +186,26 @@ static void exit_pci_slot(struct zpci_dev *zdev)
205 } 186 }
206} 187}
207 188
189static struct pci_hp_callback_ops hp_ops = {
190 .create_slot = init_pci_slot,
191 .remove_slot = exit_pci_slot,
192};
193
194static void __init init_pci_slots(void)
195{
196 struct zpci_dev *zdev;
197
198 /*
199 * Create a structure for each slot, and register that slot
200 * with the pci_hotplug subsystem.
201 */
202 mutex_lock(&zpci_list_lock);
203 list_for_each_entry(zdev, &zpci_list, entry) {
204 init_pci_slot(zdev);
205 }
206 mutex_unlock(&zpci_list_lock);
207}
208
208static void __exit exit_pci_slots(void) 209static void __exit exit_pci_slots(void)
209{ 210{
210 struct list_head *tmp, *n; 211 struct list_head *tmp, *n;
@@ -224,28 +225,19 @@ static void __exit exit_pci_slots(void)
224 225
225static int __init pci_hotplug_s390_init(void) 226static int __init pci_hotplug_s390_init(void)
226{ 227{
227 /*
228 * Do specific initialization stuff for your driver here
229 * like initializing your controller hardware (if any) and
230 * determining the number of slots you have in the system
231 * right now.
232 */
233
234 if (!s390_pci_probe) 228 if (!s390_pci_probe)
235 return -EOPNOTSUPP; 229 return -EOPNOTSUPP;
236 230
237 /* register callbacks for slot handling from arch code */ 231 zpci_register_hp_ops(&hp_ops);
238 mutex_lock(&zpci_list_lock); 232 init_pci_slots();
239 hotplug_ops.create_slot = init_pci_slot; 233
240 hotplug_ops.remove_slot = exit_pci_slot; 234 return 0;
241 mutex_unlock(&zpci_list_lock);
242 pr_info("registered hotplug slot callbacks\n");
243 return init_pci_slots();
244} 235}
245 236
246static void __exit pci_hotplug_s390_exit(void) 237static void __exit pci_hotplug_s390_exit(void)
247{ 238{
248 exit_pci_slots(); 239 exit_pci_slots();
240 zpci_deregister_hp_ops();
249} 241}
250 242
251module_init(pci_hotplug_s390_init); 243module_init(pci_hotplug_s390_init);