aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ehea
diff options
context:
space:
mode:
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