]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/ehea/ehea_main.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[linux-2.6-omap-h63xx.git] / drivers / net / ehea / ehea_main.c
index f460b623c0771356acca11780e06b62efac2e0c4..d1b6d4e7495d1dee77247c74e1aa061b23e89026 100644 (file)
@@ -35,7 +35,9 @@
 #include <linux/if_ether.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
+#include <linux/memory.h>
 #include <asm/kexec.h>
+#include <linux/mutex.h>
 
 #include <net/ip.h>
 
@@ -99,7 +101,7 @@ static int port_name_cnt;
 static LIST_HEAD(adapter_list);
 u64 ehea_driver_flags;
 struct work_struct ehea_rereg_mr_task;
-struct semaphore dlpar_mem_lock;
+static DEFINE_MUTEX(dlpar_mem_lock);
 struct ehea_fw_handle_array ehea_fw_handles;
 struct ehea_bcmc_reg_array ehea_bcmc_regs;
 
@@ -1761,7 +1763,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
 
        memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len);
 
-       down(&ehea_bcmc_regs.lock);
+       mutex_lock(&ehea_bcmc_regs.lock);
 
        /* Deregister old MAC in pHYP */
        ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
@@ -1779,7 +1781,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
 
 out_upregs:
        ehea_update_bcmc_registrations();
-       up(&ehea_bcmc_regs.lock);
+       mutex_unlock(&ehea_bcmc_regs.lock);
 out_free:
        kfree(cb0);
 out:
@@ -1941,7 +1943,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
        }
        ehea_promiscuous(dev, 0);
 
-       down(&ehea_bcmc_regs.lock);
+       mutex_lock(&ehea_bcmc_regs.lock);
 
        if (dev->flags & IFF_ALLMULTI) {
                ehea_allmulti(dev, 1);
@@ -1972,7 +1974,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
        }
 out:
        ehea_update_bcmc_registrations();
-       up(&ehea_bcmc_regs.lock);
+       mutex_unlock(&ehea_bcmc_regs.lock);
        return;
 }
 
@@ -2455,7 +2457,7 @@ static int ehea_up(struct net_device *dev)
        if (port->state == EHEA_PORT_UP)
                return 0;
 
-       down(&ehea_fw_handles.lock);
+       mutex_lock(&ehea_fw_handles.lock);
 
        ret = ehea_port_res_setup(port, port->num_def_qps,
                                  port->num_add_tx_qps);
@@ -2493,7 +2495,7 @@ static int ehea_up(struct net_device *dev)
                }
        }
 
-       down(&ehea_bcmc_regs.lock);
+       mutex_lock(&ehea_bcmc_regs.lock);
 
        ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
        if (ret) {
@@ -2516,10 +2518,10 @@ out:
                ehea_info("Failed starting %s. ret=%i", dev->name, ret);
 
        ehea_update_bcmc_registrations();
-       up(&ehea_bcmc_regs.lock);
+       mutex_unlock(&ehea_bcmc_regs.lock);
 
        ehea_update_firmware_handles();
-       up(&ehea_fw_handles.lock);
+       mutex_unlock(&ehea_fw_handles.lock);
 
        return ret;
 }
@@ -2545,7 +2547,7 @@ static int ehea_open(struct net_device *dev)
        int ret;
        struct ehea_port *port = netdev_priv(dev);
 
-       down(&port->port_lock);
+       mutex_lock(&port->port_lock);
 
        if (netif_msg_ifup(port))
                ehea_info("enabling port %s", dev->name);
@@ -2556,7 +2558,7 @@ static int ehea_open(struct net_device *dev)
                netif_start_queue(dev);
        }
 
-       up(&port->port_lock);
+       mutex_unlock(&port->port_lock);
 
        return ret;
 }
@@ -2569,18 +2571,18 @@ static int ehea_down(struct net_device *dev)
        if (port->state == EHEA_PORT_DOWN)
                return 0;
 
-       down(&ehea_bcmc_regs.lock);
+       mutex_lock(&ehea_fw_handles.lock);
+
+       mutex_lock(&ehea_bcmc_regs.lock);
        ehea_drop_multicast_list(dev);
        ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
 
        ehea_free_interrupts(dev);
 
-       down(&ehea_fw_handles.lock);
-
        port->state = EHEA_PORT_DOWN;
 
        ehea_update_bcmc_registrations();
-       up(&ehea_bcmc_regs.lock);
+       mutex_unlock(&ehea_bcmc_regs.lock);
 
        ret = ehea_clean_all_portres(port);
        if (ret)
@@ -2588,7 +2590,7 @@ static int ehea_down(struct net_device *dev)
                          dev->name, ret);
 
        ehea_update_firmware_handles();
-       up(&ehea_fw_handles.lock);
+       mutex_unlock(&ehea_fw_handles.lock);
 
        return ret;
 }
@@ -2602,15 +2604,15 @@ static int ehea_stop(struct net_device *dev)
                ehea_info("disabling port %s", dev->name);
 
        flush_scheduled_work();
-       down(&port->port_lock);
+       mutex_lock(&port->port_lock);
        netif_stop_queue(dev);
        port_napi_disable(port);
        ret = ehea_down(dev);
-       up(&port->port_lock);
+       mutex_unlock(&port->port_lock);
        return ret;
 }
 
-void ehea_purge_sq(struct ehea_qp *orig_qp)
+static void ehea_purge_sq(struct ehea_qp *orig_qp)
 {
        struct ehea_qp qp = *orig_qp;
        struct ehea_qp_init_attr *init_attr = &qp.init_attr;
@@ -2624,7 +2626,7 @@ void ehea_purge_sq(struct ehea_qp *orig_qp)
        }
 }
 
-void ehea_flush_sq(struct ehea_port *port)
+static void ehea_flush_sq(struct ehea_port *port)
 {
        int i;
 
@@ -2820,7 +2822,7 @@ static void ehea_reset_port(struct work_struct *work)
        struct net_device *dev = port->netdev;
 
        port->resets++;
-       down(&port->port_lock);
+       mutex_lock(&port->port_lock);
        netif_stop_queue(dev);
 
        port_napi_disable(port);
@@ -2840,7 +2842,7 @@ static void ehea_reset_port(struct work_struct *work)
 
        netif_wake_queue(dev);
 out:
-       up(&port->port_lock);
+       mutex_unlock(&port->port_lock);
        return;
 }
 
@@ -2849,7 +2851,7 @@ static void ehea_rereg_mrs(struct work_struct *work)
        int ret, i;
        struct ehea_adapter *adapter;
 
-       down(&dlpar_mem_lock);
+       mutex_lock(&dlpar_mem_lock);
        ehea_info("LPAR memory enlarged - re-initializing driver");
 
        list_for_each_entry(adapter, &adapter_list, list)
@@ -2857,22 +2859,24 @@ static void ehea_rereg_mrs(struct work_struct *work)
                        /* Shutdown all ports */
                        for (i = 0; i < EHEA_MAX_PORTS; i++) {
                                struct ehea_port *port = adapter->port[i];
+                               struct net_device *dev;
 
-                               if (port) {
-                                       struct net_device *dev = port->netdev;
+                               if (!port)
+                                       continue;
 
-                                       if (dev->flags & IFF_UP) {
-                                               down(&port->port_lock);
-                                               netif_stop_queue(dev);
-                                               ehea_flush_sq(port);
-                                               ret = ehea_stop_qps(dev);
-                                               if (ret) {
-                                                       up(&port->port_lock);
-                                                       goto out;
-                                               }
-                                               port_napi_disable(port);
-                                               up(&port->port_lock);
+                               dev = port->netdev;
+
+                               if (dev->flags & IFF_UP) {
+                                       mutex_lock(&port->port_lock);
+                                       netif_stop_queue(dev);
+                                       ehea_flush_sq(port);
+                                       ret = ehea_stop_qps(dev);
+                                       if (ret) {
+                                               mutex_unlock(&port->port_lock);
+                                               goto out;
                                        }
+                                       port_napi_disable(port);
+                                       mutex_unlock(&port->port_lock);
                                }
                        }
 
@@ -2912,17 +2916,17 @@ static void ehea_rereg_mrs(struct work_struct *work)
                                        struct net_device *dev = port->netdev;
 
                                        if (dev->flags & IFF_UP) {
-                                               down(&port->port_lock);
+                                               mutex_lock(&port->port_lock);
                                                port_napi_enable(port);
                                                ret = ehea_restart_qps(dev);
                                                if (!ret)
                                                        netif_wake_queue(dev);
-                                               up(&port->port_lock);
+                                               mutex_unlock(&port->port_lock);
                                        }
                                }
                        }
                }
-       up(&dlpar_mem_lock);
+       mutex_unlock(&dlpar_mem_lock);
        ehea_info("re-initializing driver complete");
 out:
        return;
@@ -3083,7 +3087,7 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
 
        port = netdev_priv(dev);
 
-       sema_init(&port->port_lock, 1);
+       mutex_init(&port->port_lock);
        port->state = EHEA_PORT_DOWN;
        port->sig_comp_iv = sq_entries / 10;
 
@@ -3362,7 +3366,7 @@ static int __devinit ehea_probe_adapter(struct of_device *dev,
                ehea_error("Invalid ibmebus device probed");
                return -EINVAL;
        }
-       down(&ehea_fw_handles.lock);
+       mutex_lock(&ehea_fw_handles.lock);
 
        adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
        if (!adapter) {
@@ -3446,7 +3450,7 @@ out_free_ad:
 
 out:
        ehea_update_firmware_handles();
-       up(&ehea_fw_handles.lock);
+       mutex_unlock(&ehea_fw_handles.lock);
        return ret;
 }
 
@@ -3465,7 +3469,7 @@ static int __devexit ehea_remove(struct of_device *dev)
 
        flush_scheduled_work();
 
-       down(&ehea_fw_handles.lock);
+       mutex_lock(&ehea_fw_handles.lock);
 
        ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
        tasklet_kill(&adapter->neq_tasklet);
@@ -3476,7 +3480,7 @@ static int __devexit ehea_remove(struct of_device *dev)
        kfree(adapter);
 
        ehea_update_firmware_handles();
-       up(&ehea_fw_handles.lock);
+       mutex_unlock(&ehea_fw_handles.lock);
 
        return 0;
 }
@@ -3500,6 +3504,24 @@ void ehea_crash_handler(void)
                                              0, H_DEREG_BCMC);
 }
 
+static int ehea_mem_notifier(struct notifier_block *nb,
+                             unsigned long action, void *data)
+{
+       switch (action) {
+       case MEM_OFFLINE:
+               ehea_info("memory has been removed");
+               ehea_rereg_mrs(NULL);
+               break;
+       default:
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block ehea_mem_nb = {
+       .notifier_call = ehea_mem_notifier,
+};
+
 static int ehea_reboot_notifier(struct notifier_block *nb,
                                unsigned long action, void *unused)
 {
@@ -3563,9 +3585,8 @@ int __init ehea_module_init(void)
        memset(&ehea_fw_handles, 0, sizeof(ehea_fw_handles));
        memset(&ehea_bcmc_regs, 0, sizeof(ehea_bcmc_regs));
 
-       sema_init(&dlpar_mem_lock, 1);
-       sema_init(&ehea_fw_handles.lock, 1);
-       sema_init(&ehea_bcmc_regs.lock, 1);
+       mutex_init(&ehea_fw_handles.lock);
+       mutex_init(&ehea_bcmc_regs.lock);
 
        ret = check_module_parm();
        if (ret)
@@ -3579,6 +3600,10 @@ int __init ehea_module_init(void)
        if (ret)
                ehea_info("failed registering reboot notifier");
 
+       ret = register_memory_notifier(&ehea_mem_nb);
+       if (ret)
+               ehea_info("failed registering memory remove notifier");
+
        ret = crash_shutdown_register(&ehea_crash_handler);
        if (ret)
                ehea_info("failed registering crash handler");
@@ -3602,6 +3627,7 @@ int __init ehea_module_init(void)
 out3:
        ibmebus_unregister_driver(&ehea_driver);
 out2:
+       unregister_memory_notifier(&ehea_mem_nb);
        unregister_reboot_notifier(&ehea_reboot_nb);
        crash_shutdown_unregister(&ehea_crash_handler);
 out:
@@ -3619,6 +3645,7 @@ static void __exit ehea_module_exit(void)
        ret = crash_shutdown_unregister(&ehea_crash_handler);
        if (ret)
                ehea_info("failed unregistering crash handler");
+       unregister_memory_notifier(&ehea_mem_nb);
        kfree(ehea_fw_handles.arr);
        kfree(ehea_bcmc_regs.arr);
        ehea_destroy_busmap();