aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ehea
diff options
context:
space:
mode:
authorThomas Klein <osstklei@de.ibm.com>2008-02-13 10:18:33 -0500
committerJeff Garzik <jeff@garzik.org>2008-02-23 23:54:59 -0500
commit21eee2dd1b5702f15924f18f923b2a281f0e72e8 (patch)
tree451ef826604048c9b3fd0d2362bbc9659170da6a /drivers/net/ehea
parent8d3c202be23c5a915f7053ebd4e96f44700c6a62 (diff)
ehea: add kdump support
This patch adds kdump support to the ehea driver. As the firmware doesn't free resource handles automatically, the driver has to run an as simple as possible free resource function in case of a crash shutdown. The function iterates over two arrays freeing all resource handles which are stored there. The arrays are kept up-to-date during normal runtime. The crash handler fn is triggered by the recently introduced PPC crash shutdown reg/unreg functions. Signed-off-by: Thomas Klein <tklein@de.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/ehea')
-rw-r--r--drivers/net/ehea/ehea.h34
-rw-r--r--drivers/net/ehea/ehea_main.c281
2 files changed, 290 insertions, 25 deletions
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 88fb53eba715..7c4ead35cfa2 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,7 +40,7 @@
40#include <asm/io.h> 40#include <asm/io.h>
41 41
42#define DRV_NAME "ehea" 42#define DRV_NAME "ehea"
43#define DRV_VERSION "EHEA_0083" 43#define DRV_VERSION "EHEA_0087"
44 44
45/* eHEA capability flags */ 45/* eHEA capability flags */
46#define DLPAR_PORT_ADD_REM 1 46#define DLPAR_PORT_ADD_REM 1
@@ -386,6 +386,13 @@ struct ehea_port_res {
386 386
387 387
388#define EHEA_MAX_PORTS 16 388#define EHEA_MAX_PORTS 16
389
390#define EHEA_NUM_PORTRES_FW_HANDLES 6 /* QP handle, SendCQ handle,
391 RecvCQ handle, EQ handle,
392 SendMR handle, RecvMR handle */
393#define EHEA_NUM_PORT_FW_HANDLES 1 /* EQ handle */
394#define EHEA_NUM_ADAPTER_FW_HANDLES 2 /* MR handle, NEQ handle */
395
389struct ehea_adapter { 396struct ehea_adapter {
390 u64 handle; 397 u64 handle;
391 struct of_device *ofdev; 398 struct of_device *ofdev;
@@ -405,6 +412,31 @@ struct ehea_mc_list {
405 u64 macaddr; 412 u64 macaddr;
406}; 413};
407 414
415/* kdump support */
416struct ehea_fw_handle_entry {
417 u64 adh; /* Adapter Handle */
418 u64 fwh; /* Firmware Handle */
419};
420
421struct ehea_fw_handle_array {
422 struct ehea_fw_handle_entry *arr;
423 int num_entries;
424 struct semaphore lock;
425};
426
427struct ehea_bcmc_reg_entry {
428 u64 adh; /* Adapter Handle */
429 u32 port_id; /* Logical Port Id */
430 u8 reg_type; /* Registration Type */
431 u64 macaddr;
432};
433
434struct ehea_bcmc_reg_array {
435 struct ehea_bcmc_reg_entry *arr;
436 int num_entries;
437 struct semaphore lock;
438};
439
408#define EHEA_PORT_UP 1 440#define EHEA_PORT_UP 1
409#define EHEA_PORT_DOWN 0 441#define EHEA_PORT_DOWN 0
410#define EHEA_PHY_LINK_UP 1 442#define EHEA_PHY_LINK_UP 1
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index c051c7e09b9a..21af674b764e 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -35,6 +35,7 @@
35#include <linux/if_ether.h> 35#include <linux/if_ether.h>
36#include <linux/notifier.h> 36#include <linux/notifier.h>
37#include <linux/reboot.h> 37#include <linux/reboot.h>
38#include <asm/kexec.h>
38 39
39#include <net/ip.h> 40#include <net/ip.h>
40 41
@@ -98,8 +99,10 @@ static int port_name_cnt;
98static LIST_HEAD(adapter_list); 99static LIST_HEAD(adapter_list);
99u64 ehea_driver_flags; 100u64 ehea_driver_flags;
100struct work_struct ehea_rereg_mr_task; 101struct work_struct ehea_rereg_mr_task;
101
102struct semaphore dlpar_mem_lock; 102struct semaphore dlpar_mem_lock;
103struct ehea_fw_handle_array ehea_fw_handles;
104struct ehea_bcmc_reg_array ehea_bcmc_regs;
105
103 106
104static int __devinit ehea_probe_adapter(struct of_device *dev, 107static int __devinit ehea_probe_adapter(struct of_device *dev,
105 const struct of_device_id *id); 108 const struct of_device_id *id);
@@ -132,6 +135,160 @@ void ehea_dump(void *adr, int len, char *msg)
132 } 135 }
133} 136}
134 137
138static void ehea_update_firmware_handles(void)
139{
140 struct ehea_fw_handle_entry *arr = NULL;
141 struct ehea_adapter *adapter;
142 int num_adapters = 0;
143 int num_ports = 0;
144 int num_portres = 0;
145 int i = 0;
146 int num_fw_handles, k, l;
147
148 /* Determine number of handles */
149 list_for_each_entry(adapter, &adapter_list, list) {
150 num_adapters++;
151
152 for (k = 0; k < EHEA_MAX_PORTS; k++) {
153 struct ehea_port *port = adapter->port[k];
154
155 if (!port || (port->state != EHEA_PORT_UP))
156 continue;
157
158 num_ports++;
159 num_portres += port->num_def_qps + port->num_add_tx_qps;
160 }
161 }
162
163 num_fw_handles = num_adapters * EHEA_NUM_ADAPTER_FW_HANDLES +
164 num_ports * EHEA_NUM_PORT_FW_HANDLES +
165 num_portres * EHEA_NUM_PORTRES_FW_HANDLES;
166
167 if (num_fw_handles) {
168 arr = kzalloc(num_fw_handles * sizeof(*arr), GFP_KERNEL);
169 if (!arr)
170 return; /* Keep the existing array */
171 } else
172 goto out_update;
173
174 list_for_each_entry(adapter, &adapter_list, list) {
175 for (k = 0; k < EHEA_MAX_PORTS; k++) {
176 struct ehea_port *port = adapter->port[k];
177
178 if (!port || (port->state != EHEA_PORT_UP))
179 continue;
180
181 for (l = 0;
182 l < port->num_def_qps + port->num_add_tx_qps;
183 l++) {
184 struct ehea_port_res *pr = &port->port_res[l];
185
186 arr[i].adh = adapter->handle;
187 arr[i++].fwh = pr->qp->fw_handle;
188 arr[i].adh = adapter->handle;
189 arr[i++].fwh = pr->send_cq->fw_handle;
190 arr[i].adh = adapter->handle;
191 arr[i++].fwh = pr->recv_cq->fw_handle;
192 arr[i].adh = adapter->handle;
193 arr[i++].fwh = pr->eq->fw_handle;
194 arr[i].adh = adapter->handle;
195 arr[i++].fwh = pr->send_mr.handle;
196 arr[i].adh = adapter->handle;
197 arr[i++].fwh = pr->recv_mr.handle;
198 }
199 arr[i].adh = adapter->handle;
200 arr[i++].fwh = port->qp_eq->fw_handle;
201 }
202
203 arr[i].adh = adapter->handle;
204 arr[i++].fwh = adapter->neq->fw_handle;
205
206 if (adapter->mr.handle) {
207 arr[i].adh = adapter->handle;
208 arr[i++].fwh = adapter->mr.handle;
209 }
210 }
211
212out_update:
213 kfree(ehea_fw_handles.arr);
214 ehea_fw_handles.arr = arr;
215 ehea_fw_handles.num_entries = i;
216}
217
218static void ehea_update_bcmc_registrations(void)
219{
220 struct ehea_bcmc_reg_entry *arr = NULL;
221 struct ehea_adapter *adapter;
222 struct ehea_mc_list *mc_entry;
223 int num_registrations = 0;
224 int i = 0;
225 int k;
226
227 /* Determine number of registrations */
228 list_for_each_entry(adapter, &adapter_list, list)
229 for (k = 0; k < EHEA_MAX_PORTS; k++) {
230 struct ehea_port *port = adapter->port[k];
231
232 if (!port || (port->state != EHEA_PORT_UP))
233 continue;
234
235 num_registrations += 2; /* Broadcast registrations */
236
237 list_for_each_entry(mc_entry, &port->mc_list->list,list)
238 num_registrations += 2;
239 }
240
241 if (num_registrations) {
242 arr = kzalloc(num_registrations * sizeof(*arr), GFP_KERNEL);
243 if (!arr)
244 return; /* Keep the existing array */
245 } else
246 goto out_update;
247
248 list_for_each_entry(adapter, &adapter_list, list) {
249 for (k = 0; k < EHEA_MAX_PORTS; k++) {
250 struct ehea_port *port = adapter->port[k];
251
252 if (!port || (port->state != EHEA_PORT_UP))
253 continue;
254
255 arr[i].adh = adapter->handle;
256 arr[i].port_id = port->logical_port_id;
257 arr[i].reg_type = EHEA_BCMC_BROADCAST |
258 EHEA_BCMC_UNTAGGED;
259 arr[i++].macaddr = port->mac_addr;
260
261 arr[i].adh = adapter->handle;
262 arr[i].port_id = port->logical_port_id;
263 arr[i].reg_type = EHEA_BCMC_BROADCAST |
264 EHEA_BCMC_VLANID_ALL;
265 arr[i++].macaddr = port->mac_addr;
266
267 list_for_each_entry(mc_entry,
268 &port->mc_list->list, list) {
269 arr[i].adh = adapter->handle;
270 arr[i].port_id = port->logical_port_id;
271 arr[i].reg_type = EHEA_BCMC_SCOPE_ALL |
272 EHEA_BCMC_MULTICAST |
273 EHEA_BCMC_UNTAGGED;
274 arr[i++].macaddr = mc_entry->macaddr;
275
276 arr[i].adh = adapter->handle;
277 arr[i].port_id = port->logical_port_id;
278 arr[i].reg_type = EHEA_BCMC_SCOPE_ALL |
279 EHEA_BCMC_MULTICAST |
280 EHEA_BCMC_VLANID_ALL;
281 arr[i++].macaddr = mc_entry->macaddr;
282 }
283 }
284 }
285
286out_update:
287 kfree(ehea_bcmc_regs.arr);
288 ehea_bcmc_regs.arr = arr;
289 ehea_bcmc_regs.num_entries = i;
290}
291
135static struct net_device_stats *ehea_get_stats(struct net_device *dev) 292static struct net_device_stats *ehea_get_stats(struct net_device *dev)
136{ 293{
137 struct ehea_port *port = netdev_priv(dev); 294 struct ehea_port *port = netdev_priv(dev);
@@ -1601,19 +1758,25 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
1601 1758
1602 memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len); 1759 memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len);
1603 1760
1761 down(&ehea_bcmc_regs.lock);
1762
1604 /* Deregister old MAC in pHYP */ 1763 /* Deregister old MAC in pHYP */
1605 ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC); 1764 ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
1606 if (ret) 1765 if (ret)
1607 goto out_free; 1766 goto out_upregs;
1608 1767
1609 port->mac_addr = cb0->port_mac_addr << 16; 1768 port->mac_addr = cb0->port_mac_addr << 16;
1610 1769
1611 /* Register new MAC in pHYP */ 1770 /* Register new MAC in pHYP */
1612 ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); 1771 ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
1613 if (ret) 1772 if (ret)
1614 goto out_free; 1773 goto out_upregs;
1615 1774
1616 ret = 0; 1775 ret = 0;
1776
1777out_upregs:
1778 ehea_update_bcmc_registrations();
1779 up(&ehea_bcmc_regs.lock);
1617out_free: 1780out_free:
1618 kfree(cb0); 1781 kfree(cb0);
1619out: 1782out:
@@ -1775,9 +1938,11 @@ static void ehea_set_multicast_list(struct net_device *dev)
1775 } 1938 }
1776 ehea_promiscuous(dev, 0); 1939 ehea_promiscuous(dev, 0);
1777 1940
1941 down(&ehea_bcmc_regs.lock);
1942
1778 if (dev->flags & IFF_ALLMULTI) { 1943 if (dev->flags & IFF_ALLMULTI) {
1779 ehea_allmulti(dev, 1); 1944 ehea_allmulti(dev, 1);
1780 return; 1945 goto out;
1781 } 1946 }
1782 ehea_allmulti(dev, 0); 1947 ehea_allmulti(dev, 0);
1783 1948
@@ -1803,6 +1968,8 @@ static void ehea_set_multicast_list(struct net_device *dev)
1803 1968
1804 } 1969 }
1805out: 1970out:
1971 ehea_update_bcmc_registrations();
1972 up(&ehea_bcmc_regs.lock);
1806 return; 1973 return;
1807} 1974}
1808 1975
@@ -2285,6 +2452,8 @@ static int ehea_up(struct net_device *dev)
2285 if (port->state == EHEA_PORT_UP) 2452 if (port->state == EHEA_PORT_UP)
2286 return 0; 2453 return 0;
2287 2454
2455 down(&ehea_fw_handles.lock);
2456
2288 ret = ehea_port_res_setup(port, port->num_def_qps, 2457 ret = ehea_port_res_setup(port, port->num_def_qps,
2289 port->num_add_tx_qps); 2458 port->num_add_tx_qps);
2290 if (ret) { 2459 if (ret) {
@@ -2321,8 +2490,17 @@ static int ehea_up(struct net_device *dev)
2321 } 2490 }
2322 } 2491 }
2323 2492
2324 ret = 0; 2493 down(&ehea_bcmc_regs.lock);
2494
2495 ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
2496 if (ret) {
2497 ret = -EIO;
2498 goto out_free_irqs;
2499 }
2500
2325 port->state = EHEA_PORT_UP; 2501 port->state = EHEA_PORT_UP;
2502
2503 ret = 0;
2326 goto out; 2504 goto out;
2327 2505
2328out_free_irqs: 2506out_free_irqs:
@@ -2334,6 +2512,12 @@ out:
2334 if (ret) 2512 if (ret)
2335 ehea_info("Failed starting %s. ret=%i", dev->name, ret); 2513 ehea_info("Failed starting %s. ret=%i", dev->name, ret);
2336 2514
2515 ehea_update_bcmc_registrations();
2516 up(&ehea_bcmc_regs.lock);
2517
2518 ehea_update_firmware_handles();
2519 up(&ehea_fw_handles.lock);
2520
2337 return ret; 2521 return ret;
2338} 2522}
2339 2523
@@ -2382,16 +2566,27 @@ static int ehea_down(struct net_device *dev)
2382 if (port->state == EHEA_PORT_DOWN) 2566 if (port->state == EHEA_PORT_DOWN)
2383 return 0; 2567 return 0;
2384 2568
2569 down(&ehea_bcmc_regs.lock);
2385 ehea_drop_multicast_list(dev); 2570 ehea_drop_multicast_list(dev);
2571 ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
2572
2386 ehea_free_interrupts(dev); 2573 ehea_free_interrupts(dev);
2387 2574
2575 down(&ehea_fw_handles.lock);
2576
2388 port->state = EHEA_PORT_DOWN; 2577 port->state = EHEA_PORT_DOWN;
2389 2578
2579 ehea_update_bcmc_registrations();
2580 up(&ehea_bcmc_regs.lock);
2581
2390 ret = ehea_clean_all_portres(port); 2582 ret = ehea_clean_all_portres(port);
2391 if (ret) 2583 if (ret)
2392 ehea_info("Failed freeing resources for %s. ret=%i", 2584 ehea_info("Failed freeing resources for %s. ret=%i",
2393 dev->name, ret); 2585 dev->name, ret);
2394 2586
2587 ehea_update_firmware_handles();
2588 up(&ehea_fw_handles.lock);
2589
2395 return ret; 2590 return ret;
2396} 2591}
2397 2592
@@ -2920,19 +3115,12 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
2920 dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT; 3115 dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
2921 3116
2922 INIT_WORK(&port->reset_task, ehea_reset_port); 3117 INIT_WORK(&port->reset_task, ehea_reset_port);
2923
2924 ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
2925 if (ret) {
2926 ret = -EIO;
2927 goto out_unreg_port;
2928 }
2929
2930 ehea_set_ethtool_ops(dev); 3118 ehea_set_ethtool_ops(dev);
2931 3119
2932 ret = register_netdev(dev); 3120 ret = register_netdev(dev);
2933 if (ret) { 3121 if (ret) {
2934 ehea_error("register_netdev failed. ret=%d", ret); 3122 ehea_error("register_netdev failed. ret=%d", ret);
2935 goto out_dereg_bc; 3123 goto out_unreg_port;
2936 } 3124 }
2937 3125
2938 port->lro_max_aggr = lro_max_aggr; 3126 port->lro_max_aggr = lro_max_aggr;
@@ -2949,9 +3137,6 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
2949 3137
2950 return port; 3138 return port;
2951 3139
2952out_dereg_bc:
2953 ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
2954
2955out_unreg_port: 3140out_unreg_port:
2956 ehea_unregister_port(port); 3141 ehea_unregister_port(port);
2957 3142
@@ -2971,7 +3156,6 @@ static void ehea_shutdown_single_port(struct ehea_port *port)
2971{ 3156{
2972 unregister_netdev(port->netdev); 3157 unregister_netdev(port->netdev);
2973 ehea_unregister_port(port); 3158 ehea_unregister_port(port);
2974 ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
2975 kfree(port->mc_list); 3159 kfree(port->mc_list);
2976 free_netdev(port->netdev); 3160 free_netdev(port->netdev);
2977 port->adapter->active_ports--; 3161 port->adapter->active_ports--;
@@ -3014,7 +3198,6 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)
3014 3198
3015 i++; 3199 i++;
3016 }; 3200 };
3017
3018 return 0; 3201 return 0;
3019} 3202}
3020 3203
@@ -3159,6 +3342,7 @@ static int __devinit ehea_probe_adapter(struct of_device *dev,
3159 ehea_error("Invalid ibmebus device probed"); 3342 ehea_error("Invalid ibmebus device probed");
3160 return -EINVAL; 3343 return -EINVAL;
3161 } 3344 }
3345 down(&ehea_fw_handles.lock);
3162 3346
3163 adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); 3347 adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
3164 if (!adapter) { 3348 if (!adapter) {
@@ -3239,7 +3423,10 @@ out_kill_eq:
3239 3423
3240out_free_ad: 3424out_free_ad:
3241 kfree(adapter); 3425 kfree(adapter);
3426
3242out: 3427out:
3428 ehea_update_firmware_handles();
3429 up(&ehea_fw_handles.lock);
3243 return ret; 3430 return ret;
3244} 3431}
3245 3432
@@ -3258,18 +3445,41 @@ static int __devexit ehea_remove(struct of_device *dev)
3258 3445
3259 flush_scheduled_work(); 3446 flush_scheduled_work();
3260 3447
3448 down(&ehea_fw_handles.lock);
3449
3261 ibmebus_free_irq(adapter->neq->attr.ist1, adapter); 3450 ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
3262 tasklet_kill(&adapter->neq_tasklet); 3451 tasklet_kill(&adapter->neq_tasklet);
3263 3452
3264 ehea_destroy_eq(adapter->neq); 3453 ehea_destroy_eq(adapter->neq);
3265 ehea_remove_adapter_mr(adapter); 3454 ehea_remove_adapter_mr(adapter);
3266 list_del(&adapter->list); 3455 list_del(&adapter->list);
3267
3268 kfree(adapter); 3456 kfree(adapter);
3269 3457
3458 ehea_update_firmware_handles();
3459 up(&ehea_fw_handles.lock);
3460
3270 return 0; 3461 return 0;
3271} 3462}
3272 3463
3464void ehea_crash_handler(void)
3465{
3466 int i;
3467
3468 if (ehea_fw_handles.arr)
3469 for (i = 0; i < ehea_fw_handles.num_entries; i++)
3470 ehea_h_free_resource(ehea_fw_handles.arr[i].adh,
3471 ehea_fw_handles.arr[i].fwh,
3472 FORCE_FREE);
3473
3474 if (ehea_bcmc_regs.arr)
3475 for (i = 0; i < ehea_bcmc_regs.num_entries; i++)
3476 ehea_h_reg_dereg_bcmc(ehea_bcmc_regs.arr[i].adh,
3477 ehea_bcmc_regs.arr[i].port_id,
3478 ehea_bcmc_regs.arr[i].reg_type,
3479 ehea_bcmc_regs.arr[i].macaddr,
3480 0, H_DEREG_BCMC);
3481}
3482
3273static int ehea_reboot_notifier(struct notifier_block *nb, 3483static int ehea_reboot_notifier(struct notifier_block *nb,
3274 unsigned long action, void *unused) 3484 unsigned long action, void *unused)
3275{ 3485{
@@ -3330,7 +3540,12 @@ int __init ehea_module_init(void)
3330 3540
3331 3541
3332 INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs); 3542 INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs);
3543 memset(&ehea_fw_handles, 0, sizeof(ehea_fw_handles));
3544 memset(&ehea_bcmc_regs, 0, sizeof(ehea_bcmc_regs));
3545
3333 sema_init(&dlpar_mem_lock, 1); 3546 sema_init(&dlpar_mem_lock, 1);
3547 sema_init(&ehea_fw_handles.lock, 1);
3548 sema_init(&ehea_bcmc_regs.lock, 1);
3334 3549
3335 ret = check_module_parm(); 3550 ret = check_module_parm();
3336 if (ret) 3551 if (ret)
@@ -3340,12 +3555,18 @@ int __init ehea_module_init(void)
3340 if (ret) 3555 if (ret)
3341 goto out; 3556 goto out;
3342 3557
3343 register_reboot_notifier(&ehea_reboot_nb); 3558 ret = register_reboot_notifier(&ehea_reboot_nb);
3559 if (ret)
3560 ehea_info("failed registering reboot notifier");
3561
3562 ret = crash_shutdown_register(&ehea_crash_handler);
3563 if (ret)
3564 ehea_info("failed registering crash handler");
3344 3565
3345 ret = ibmebus_register_driver(&ehea_driver); 3566 ret = ibmebus_register_driver(&ehea_driver);
3346 if (ret) { 3567 if (ret) {
3347 ehea_error("failed registering eHEA device driver on ebus"); 3568 ehea_error("failed registering eHEA device driver on ebus");
3348 goto out; 3569 goto out2;
3349 } 3570 }
3350 3571
3351 ret = driver_create_file(&ehea_driver.driver, 3572 ret = driver_create_file(&ehea_driver.driver,
@@ -3353,21 +3574,33 @@ int __init ehea_module_init(void)
3353 if (ret) { 3574 if (ret) {
3354 ehea_error("failed to register capabilities attribute, ret=%d", 3575 ehea_error("failed to register capabilities attribute, ret=%d",
3355 ret); 3576 ret);
3356 unregister_reboot_notifier(&ehea_reboot_nb); 3577 goto out3;
3357 ibmebus_unregister_driver(&ehea_driver);
3358 goto out;
3359 } 3578 }
3360 3579
3580 return ret;
3581
3582out3:
3583 ibmebus_unregister_driver(&ehea_driver);
3584out2:
3585 unregister_reboot_notifier(&ehea_reboot_nb);
3586 crash_shutdown_unregister(&ehea_crash_handler);
3361out: 3587out:
3362 return ret; 3588 return ret;
3363} 3589}
3364 3590
3365static void __exit ehea_module_exit(void) 3591static void __exit ehea_module_exit(void)
3366{ 3592{
3593 int ret;
3594
3367 flush_scheduled_work(); 3595 flush_scheduled_work();
3368 driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities); 3596 driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
3369 ibmebus_unregister_driver(&ehea_driver); 3597 ibmebus_unregister_driver(&ehea_driver);
3370 unregister_reboot_notifier(&ehea_reboot_nb); 3598 unregister_reboot_notifier(&ehea_reboot_nb);
3599 ret = crash_shutdown_unregister(&ehea_crash_handler);
3600 if (ret)
3601 ehea_info("failed unregistering crash handler");
3602 kfree(ehea_fw_handles.arr);
3603 kfree(ehea_bcmc_regs.arr);
3371 ehea_destroy_busmap(); 3604 ehea_destroy_busmap();
3372} 3605}
3373 3606