Merge branch 'linux-2.6' into for-2.6.22
[safe/jmp/linux-2.6] / drivers / infiniband / hw / ehca / ehca_main.c
index 2380994..4700085 100644 (file)
@@ -40,6 +40,9 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifdef CONFIG_PPC_64K_PAGES
+#include <linux/slab.h>
+#endif
 #include "ehca_classes.h"
 #include "ehca_iverbs.h"
 #include "ehca_mrmw.h"
@@ -49,7 +52,7 @@
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
 MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
-MODULE_VERSION("SVNEHCA_0016");
+MODULE_VERSION("SVNEHCA_0022");
 
 int ehca_open_aqp1     = 0;
 int ehca_debug_level   = 0;
@@ -59,6 +62,7 @@ int ehca_use_hp_mr     = 0;
 int ehca_port_act_time = 30;
 int ehca_poll_all_eqs  = 1;
 int ehca_static_rate   = -1;
+int ehca_scaling_code  = 1;
 
 module_param_named(open_aqp1,     ehca_open_aqp1,     int, 0);
 module_param_named(debug_level,   ehca_debug_level,   int, 0);
@@ -68,6 +72,7 @@ module_param_named(use_hp_mr,     ehca_use_hp_mr,     int, 0);
 module_param_named(port_act_time, ehca_port_act_time, int, 0);
 module_param_named(poll_all_eqs,  ehca_poll_all_eqs,  int, 0);
 module_param_named(static_rate,   ehca_static_rate,   int, 0);
+module_param_named(scaling_code,   ehca_scaling_code,   int, 0);
 
 MODULE_PARM_DESC(open_aqp1,
                 "AQP1 on startup (0: no (default), 1: yes)");
@@ -88,17 +93,39 @@ MODULE_PARM_DESC(poll_all_eqs,
                 " (0: no, 1: yes (default))");
 MODULE_PARM_DESC(static_rate,
                 "set permanent static rate (default: disabled)");
+MODULE_PARM_DESC(scaling_code,
+                "set scaling code (0: disabled, 1: enabled/default)");
 
 spinlock_t ehca_qp_idr_lock;
 spinlock_t ehca_cq_idr_lock;
 DEFINE_IDR(ehca_qp_idr);
 DEFINE_IDR(ehca_cq_idr);
 
+
 static struct list_head shca_list; /* list of all registered ehcas */
 static spinlock_t shca_list_lock;
 
 static struct timer_list poll_eqs_timer;
 
+#ifdef CONFIG_PPC_64K_PAGES
+static struct kmem_cache *ctblk_cache = NULL;
+
+void *ehca_alloc_fw_ctrlblock(gfp_t flags)
+{
+       void *ret = kmem_cache_zalloc(ctblk_cache, flags);
+       if (!ret)
+               ehca_gen_err("Out of memory for ctblk");
+       return ret;
+}
+
+void ehca_free_fw_ctrlblock(void *ptr)
+{
+       if (ptr)
+               kmem_cache_free(ctblk_cache, ptr);
+
+}
+#endif
+
 static int ehca_create_slab_caches(void)
 {
        int ret;
@@ -133,6 +160,17 @@ static int ehca_create_slab_caches(void)
                goto create_slab_caches5;
        }
 
+#ifdef CONFIG_PPC_64K_PAGES
+       ctblk_cache = kmem_cache_create("ehca_cache_ctblk",
+                                       EHCA_PAGESIZE, H_CB_ALIGNMENT,
+                                       SLAB_HWCACHE_ALIGN,
+                                       NULL, NULL);
+       if (!ctblk_cache) {
+               ehca_gen_err("Cannot create ctblk SLAB cache.");
+               ehca_cleanup_mrmw_cache();
+               goto create_slab_caches5;
+       }
+#endif
        return 0;
 
 create_slab_caches5:
@@ -157,6 +195,10 @@ static void ehca_destroy_slab_caches(void)
        ehca_cleanup_qp_cache();
        ehca_cleanup_cq_cache();
        ehca_cleanup_pd_cache();
+#ifdef CONFIG_PPC_64K_PAGES
+       if (ctblk_cache)
+               kmem_cache_destroy(ctblk_cache);
+#endif
 }
 
 #define EHCA_HCAAVER  EHCA_BMASK_IBM(32,39)
@@ -168,7 +210,7 @@ int ehca_sense_attributes(struct ehca_shca *shca)
        u64 h_ret;
        struct hipz_query_hca *rblock;
 
-       rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL);
+       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
        if (!rblock) {
                ehca_gen_err("Cannot allocate rblock memory.");
                return -ENOMEM;
@@ -211,7 +253,7 @@ int ehca_sense_attributes(struct ehca_shca *shca)
        shca->sport[1].rate = IB_RATE_30_GBPS;
 
 num_ports1:
-       kfree(rblock);
+       ehca_free_fw_ctrlblock(rblock);
        return ret;
 }
 
@@ -220,7 +262,7 @@ static int init_node_guid(struct ehca_shca *shca)
        int ret = 0;
        struct hipz_query_hca *rblock;
 
-       rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL);
+       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
        if (!rblock) {
                ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
                return -ENOMEM;
@@ -235,11 +277,11 @@ static int init_node_guid(struct ehca_shca *shca)
        memcpy(&shca->ib_device.node_guid, &rblock->node_guid, sizeof(u64));
 
 init_node_guid1:
-       kfree(rblock);
+       ehca_free_fw_ctrlblock(rblock);
        return ret;
 }
 
-int ehca_register_device(struct ehca_shca *shca)
+int ehca_init_device(struct ehca_shca *shca)
 {
        int ret;
 
@@ -250,7 +292,7 @@ int ehca_register_device(struct ehca_shca *shca)
        strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX);
        shca->ib_device.owner               = THIS_MODULE;
 
-       shca->ib_device.uverbs_abi_ver      = 5;
+       shca->ib_device.uverbs_abi_ver      = 6;
        shca->ib_device.uverbs_cmd_mask     =
                (1ull << IB_USER_VERBS_CMD_GET_CONTEXT)         |
                (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)        |
@@ -317,11 +359,6 @@ int ehca_register_device(struct ehca_shca *shca)
        /* shca->ib_device.process_mad      = ehca_process_mad;     */
        shca->ib_device.mmap                = ehca_mmap;
 
-       ret = ib_register_device(&shca->ib_device);
-       if (ret)
-               ehca_err(&shca->ib_device,
-                        "ib_register_device() failed ret=%x", ret);
-
        return ret;
 }
 
@@ -399,8 +436,8 @@ static int ehca_destroy_aqp1(struct ehca_sport *sport)
 
 static ssize_t ehca_show_debug_level(struct device_driver *ddp, char *buf)
 {
-       return  snprintf(buf, PAGE_SIZE, "%d\n",
-                        ehca_debug_level);
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       ehca_debug_level);
 }
 
 static ssize_t ehca_store_debug_level(struct device_driver *ddp,
@@ -436,7 +473,7 @@ static ssize_t  ehca_show_##name(struct device *dev,                       \
                                                                           \
        shca = dev->driver_data;                                           \
                                                                           \
-       rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL);                      \
+       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);                      \
        if (!rblock) {                                                     \
                dev_err(dev, "Can't allocate rblock memory.");             \
                return 0;                                                  \
@@ -444,12 +481,12 @@ static ssize_t  ehca_show_##name(struct device *dev,                       \
                                                                           \
        if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { \
                dev_err(dev, "Can't query device properties");             \
-               kfree(rblock);                                             \
+               ehca_free_fw_ctrlblock(rblock);                            \
                return 0;                                                  \
        }                                                                  \
                                                                           \
        data = rblock->name;                                               \
-       kfree(rblock);                                                     \
+       ehca_free_fw_ctrlblock(rblock);                                    \
                                                                           \
        if ((strcmp(#name, "num_ports") == 0) && (ehca_nr_ports == 1))     \
                return snprintf(buf, 256, "1\n");                          \
@@ -528,11 +565,11 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
                                const struct of_device_id *id)
 {
        struct ehca_shca *shca;
-       u64 *handle;
+       const u64 *handle;
        struct ib_pd *ibpd;
        int ret;
 
-       handle = (u64 *)get_property(dev->ofdev.node, "ibm,hca-handle", NULL);
+       handle = get_property(dev->ofdev.node, "ibm,hca-handle", NULL);
        if (!handle) {
                ehca_gen_err("Cannot get eHCA handle for adapter: %s.",
                             dev->ofdev.node->full_name);
@@ -550,6 +587,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
                ehca_gen_err("Cannot allocate shca memory.");
                return -ENOMEM;
        }
+       mutex_init(&shca->modify_mutex);
 
        shca->ibmebus_dev = dev;
        shca->ipz_hca_handle.handle = *handle;
@@ -561,9 +599,9 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
                goto probe1;
        }
 
-       ret = ehca_register_device(shca);
+       ret = ehca_init_device(shca);
        if (ret) {
-               ehca_gen_err("Cannot register Infiniband device");
+               ehca_gen_err("Cannot init ehca  device struct");
                goto probe1;
        }
 
@@ -571,7 +609,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
        ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, 2048);
        if (ret) {
                ehca_err(&shca->ib_device, "Cannot create EQ.");
-               goto probe2;
+               goto probe1;
        }
 
        ret = ehca_create_eq(shca, &shca->neq, EHCA_NEQ, 513);
@@ -600,6 +638,13 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
                goto probe5;
        }
 
+       ret = ib_register_device(&shca->ib_device);
+       if (ret) {
+               ehca_err(&shca->ib_device,
+                        "ib_register_device() failed ret=%x", ret);
+               goto probe6;
+       }
+
        /* create AQP1 for port 1 */
        if (ehca_open_aqp1 == 1) {
                shca->sport[0].port_state = IB_PORT_DOWN;
@@ -607,7 +652,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
                if (ret) {
                        ehca_err(&shca->ib_device,
                                 "Cannot create AQP1 for port 1.");
-                       goto probe6;
+                       goto probe7;
                }
        }
 
@@ -618,7 +663,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
                if (ret) {
                        ehca_err(&shca->ib_device,
                                 "Cannot create AQP1 for port 2.");
-                       goto probe7;
+                       goto probe8;
                }
        }
 
@@ -630,12 +675,15 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
 
        return 0;
 
-probe7:
+probe8:
        ret = ehca_destroy_aqp1(&shca->sport[0]);
        if (ret)
                ehca_err(&shca->ib_device,
                         "Cannot destroy AQP1 for port 1. ret=%x", ret);
 
+probe7:
+       ib_unregister_device(&shca->ib_device);
+
 probe6:
        ret = ehca_dereg_internal_maxmr(shca);
        if (ret)
@@ -660,9 +708,6 @@ probe3:
                ehca_err(&shca->ib_device,
                         "Cannot destroy EQ. ret=%x", ret);
 
-probe2:
-       ib_unregister_device(&shca->ib_device);
-
 probe1:
        ib_dealloc_device(&shca->ib_device);
 
@@ -738,8 +783,24 @@ void ehca_poll_eqs(unsigned long data)
 
        spin_lock(&shca_list_lock);
        list_for_each_entry(shca, &shca_list, shca_list) {
-               if (shca->eq.is_initialized)
-                       ehca_tasklet_eq((unsigned long)(void*)shca);
+               if (shca->eq.is_initialized) {
+                       /* call deadman proc only if eq ptr does not change */
+                       struct ehca_eq *eq = &shca->eq;
+                       int max = 3;
+                       volatile u64 q_ofs, q_ofs2;
+                       u64 flags;
+                       spin_lock_irqsave(&eq->spinlock, flags);
+                       q_ofs = eq->ipz_queue.current_q_offset;
+                       spin_unlock_irqrestore(&eq->spinlock, flags);
+                       do {
+                               spin_lock_irqsave(&eq->spinlock, flags);
+                               q_ofs2 = eq->ipz_queue.current_q_offset;
+                               spin_unlock_irqrestore(&eq->spinlock, flags);
+                               max--;
+                       } while (q_ofs == q_ofs2 && max > 0);
+                       if (q_ofs == q_ofs2)
+                               ehca_process_eq(shca, 0);
+               }
        }
        mod_timer(&poll_eqs_timer, jiffies + HZ);
        spin_unlock(&shca_list_lock);
@@ -750,7 +811,7 @@ int __init ehca_module_init(void)
        int ret;
 
        printk(KERN_INFO "eHCA Infiniband Device Driver "
-                        "(Rel.: SVNEHCA_0016)\n");
+              "(Rel.: SVNEHCA_0022)\n");
        idr_init(&ehca_qp_idr);
        idr_init(&ehca_cq_idr);
        spin_lock_init(&ehca_qp_idr_lock);