Merge branch 'ipoib' into for-next
Roland Dreier [Tue, 2 Mar 2010 07:51:56 +0000 (23:51 -0800)]
22 files changed:
drivers/infiniband/core/ucm.c
drivers/infiniband/core/user_mad.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/cxgb3/cxio_hal.c
drivers/infiniband/hw/cxgb3/cxio_hal.h
drivers/infiniband/hw/cxgb3/cxio_wr.h
drivers/infiniband/hw/cxgb3/iwch.c
drivers/infiniband/hw/cxgb3/iwch.h
drivers/infiniband/hw/cxgb3/iwch_provider.c
drivers/infiniband/hw/cxgb3/iwch_qp.c
drivers/infiniband/hw/ehca/ehca_irq.c
drivers/infiniband/hw/ehca/ehca_qp.c
drivers/infiniband/hw/ehca/ehca_sqp.c
drivers/net/cxgb3/adapter.h
drivers/net/cxgb3/cxgb3_main.c
drivers/net/cxgb3/cxgb3_offload.h
drivers/net/cxgb3/regs.h
drivers/net/cxgb3/sge.c
drivers/net/cxgb3/t3_hw.c
include/rdma/ib_verbs.h
include/rdma/rdma_cm.h

index f504c9b..1b09b73 100644 (file)
@@ -1215,15 +1215,18 @@ static void ib_ucm_release_dev(struct device *dev)
 
        ucm_dev = container_of(dev, struct ib_ucm_device, dev);
        cdev_del(&ucm_dev->cdev);
-       clear_bit(ucm_dev->devnum, dev_map);
+       if (ucm_dev->devnum < IB_UCM_MAX_DEVICES)
+               clear_bit(ucm_dev->devnum, dev_map);
+       else
+               clear_bit(ucm_dev->devnum - IB_UCM_MAX_DEVICES, dev_map);
        kfree(ucm_dev);
 }
 
 static const struct file_operations ucm_fops = {
-       .owner   = THIS_MODULE,
-       .open    = ib_ucm_open,
+       .owner   = THIS_MODULE,
+       .open    = ib_ucm_open,
        .release = ib_ucm_close,
-       .write   = ib_ucm_write,
+       .write   = ib_ucm_write,
        .poll    = ib_ucm_poll,
 };
 
@@ -1237,8 +1240,32 @@ static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
 
+static dev_t overflow_maj;
+static DECLARE_BITMAP(overflow_map, IB_UCM_MAX_DEVICES);
+static int find_overflow_devnum(void)
+{
+       int ret;
+
+       if (!overflow_maj) {
+               ret = alloc_chrdev_region(&overflow_maj, 0, IB_UCM_MAX_DEVICES,
+                                         "infiniband_cm");
+               if (ret) {
+                       printk(KERN_ERR "ucm: couldn't register dynamic device number\n");
+                       return ret;
+               }
+       }
+
+       ret = find_first_zero_bit(overflow_map, IB_UCM_MAX_DEVICES);
+       if (ret >= IB_UCM_MAX_DEVICES)
+               return -1;
+
+       return ret;
+}
+
 static void ib_ucm_add_one(struct ib_device *device)
 {
+       int devnum;
+       dev_t base;
        struct ib_ucm_device *ucm_dev;
 
        if (!device->alloc_ucontext ||
@@ -1251,16 +1278,25 @@ static void ib_ucm_add_one(struct ib_device *device)
 
        ucm_dev->ib_dev = device;
 
-       ucm_dev->devnum = find_first_zero_bit(dev_map, IB_UCM_MAX_DEVICES);
-       if (ucm_dev->devnum >= IB_UCM_MAX_DEVICES)
-               goto err;
-
-       set_bit(ucm_dev->devnum, dev_map);
+       devnum = find_first_zero_bit(dev_map, IB_UCM_MAX_DEVICES);
+       if (devnum >= IB_UCM_MAX_DEVICES) {
+               devnum = find_overflow_devnum();
+               if (devnum < 0)
+                       goto err;
+
+               ucm_dev->devnum = devnum + IB_UCM_MAX_DEVICES;
+               base = devnum + overflow_maj;
+               set_bit(devnum, overflow_map);
+       } else {
+               ucm_dev->devnum = devnum;
+               base = devnum + IB_UCM_BASE_DEV;
+               set_bit(devnum, dev_map);
+       }
 
        cdev_init(&ucm_dev->cdev, &ucm_fops);
        ucm_dev->cdev.owner = THIS_MODULE;
        kobject_set_name(&ucm_dev->cdev.kobj, "ucm%d", ucm_dev->devnum);
-       if (cdev_add(&ucm_dev->cdev, IB_UCM_BASE_DEV + ucm_dev->devnum, 1))
+       if (cdev_add(&ucm_dev->cdev, base, 1))
                goto err;
 
        ucm_dev->dev.class = &cm_class;
@@ -1281,7 +1317,10 @@ err_dev:
        device_unregister(&ucm_dev->dev);
 err_cdev:
        cdev_del(&ucm_dev->cdev);
-       clear_bit(ucm_dev->devnum, dev_map);
+       if (ucm_dev->devnum < IB_UCM_MAX_DEVICES)
+               clear_bit(devnum, dev_map);
+       else
+               clear_bit(devnum, overflow_map);
 err:
        kfree(ucm_dev);
        return;
@@ -1340,6 +1379,8 @@ static void __exit ib_ucm_cleanup(void)
        ib_unregister_client(&ucm_client);
        class_remove_file(&cm_class, &class_attr_abi_version);
        unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
+       if (overflow_maj)
+               unregister_chrdev_region(overflow_maj, IB_UCM_MAX_DEVICES);
        idr_destroy(&ctx_id_table);
 }
 
index 7de0296..02d360c 100644 (file)
@@ -65,12 +65,9 @@ enum {
 };
 
 /*
- * Our lifetime rules for these structs are the following: each time a
- * device special file is opened, we look up the corresponding struct
- * ib_umad_port by minor in the umad_port[] table while holding the
- * port_lock.  If this lookup succeeds, we take a reference on the
- * ib_umad_port's struct ib_umad_device while still holding the
- * port_lock; if the lookup fails, we fail the open().  We drop these
+ * Our lifetime rules for these structs are the following:
+ * device special file is opened, we take a reference on the
+ * ib_umad_port's struct ib_umad_device. We drop these
  * references in the corresponding close().
  *
  * In addition to references coming from open character devices, there
@@ -78,19 +75,14 @@ enum {
  * module's reference taken when allocating the ib_umad_device in
  * ib_umad_add_one().
  *
- * When destroying an ib_umad_device, we clear all of its
- * ib_umad_ports from umad_port[] while holding port_lock before
- * dropping the module's reference to the ib_umad_device.  This is
- * always safe because any open() calls will either succeed and obtain
- * a reference before we clear the umad_port[] entries, or fail after
- * we clear the umad_port[] entries.
+ * When destroying an ib_umad_device, we drop the module's reference.
  */
 
 struct ib_umad_port {
-       struct cdev           *cdev;
+       struct cdev           cdev;
        struct device         *dev;
 
-       struct cdev           *sm_cdev;
+       struct cdev           sm_cdev;
        struct device         *sm_dev;
        struct semaphore       sm_sem;
 
@@ -136,7 +128,6 @@ static struct class *umad_class;
 static const dev_t base_dev = MKDEV(IB_UMAD_MAJOR, IB_UMAD_MINOR_BASE);
 
 static DEFINE_SPINLOCK(port_lock);
-static struct ib_umad_port *umad_port[IB_UMAD_MAX_PORTS];
 static DECLARE_BITMAP(dev_map, IB_UMAD_MAX_PORTS);
 
 static void ib_umad_add_one(struct ib_device *device);
@@ -496,8 +487,8 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
                ah_attr.ah_flags = IB_AH_GRH;
                memcpy(ah_attr.grh.dgid.raw, packet->mad.hdr.gid, 16);
                ah_attr.grh.sgid_index     = packet->mad.hdr.gid_index;
-               ah_attr.grh.flow_label     = be32_to_cpu(packet->mad.hdr.flow_label);
-               ah_attr.grh.hop_limit      = packet->mad.hdr.hop_limit;
+               ah_attr.grh.flow_label     = be32_to_cpu(packet->mad.hdr.flow_label);
+               ah_attr.grh.hop_limit      = packet->mad.hdr.hop_limit;
                ah_attr.grh.traffic_class  = packet->mad.hdr.traffic_class;
        }
 
@@ -528,9 +519,9 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
                goto err_ah;
        }
 
-       packet->msg->ah         = ah;
+       packet->msg->ah         = ah;
        packet->msg->timeout_ms = packet->mad.hdr.timeout_ms;
-       packet->msg->retries    = packet->mad.hdr.retries;
+       packet->msg->retries    = packet->mad.hdr.retries;
        packet->msg->context[0] = packet;
 
        /* Copy MAD header.  Any RMPP header is already in place. */
@@ -779,15 +770,11 @@ static long ib_umad_compat_ioctl(struct file *filp, unsigned int cmd,
 /*
  * ib_umad_open() does not need the BKL:
  *
- *  - umad_port[] accesses are protected by port_lock, the
- *    ib_umad_port structures are properly reference counted, and
+ *  - the ib_umad_port structures are properly reference counted, and
  *    everything else is purely local to the file being created, so
  *    races against other open calls are not a problem;
  *  - the ioctl method does not affect any global state outside of the
  *    file structure being operated on;
- *  - the port is added to umad_port[] as the last part of module
- *    initialization so the open method will either immediately run
- *    -ENXIO, or all required initialization will be done.
  */
 static int ib_umad_open(struct inode *inode, struct file *filp)
 {
@@ -795,13 +782,10 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
        struct ib_umad_file *file;
        int ret = 0;
 
-       spin_lock(&port_lock);
-       port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE];
+       port = container_of(inode->i_cdev, struct ib_umad_port, cdev);
        if (port)
                kref_get(&port->umad_dev->ref);
-       spin_unlock(&port_lock);
-
-       if (!port)
+       else
                return -ENXIO;
 
        mutex_lock(&port->file_mutex);
@@ -872,16 +856,16 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
 }
 
 static const struct file_operations umad_fops = {
-       .owner          = THIS_MODULE,
-       .read           = ib_umad_read,
-       .write          = ib_umad_write,
-       .poll           = ib_umad_poll,
+       .owner          = THIS_MODULE,
+       .read           = ib_umad_read,
+       .write          = ib_umad_write,
+       .poll           = ib_umad_poll,
        .unlocked_ioctl = ib_umad_ioctl,
 #ifdef CONFIG_COMPAT
-       .compat_ioctl   = ib_umad_compat_ioctl,
+       .compat_ioctl   = ib_umad_compat_ioctl,
 #endif
-       .open           = ib_umad_open,
-       .release        = ib_umad_close
+       .open           = ib_umad_open,
+       .release        = ib_umad_close
 };
 
 static int ib_umad_sm_open(struct inode *inode, struct file *filp)
@@ -892,13 +876,10 @@ static int ib_umad_sm_open(struct inode *inode, struct file *filp)
        };
        int ret;
 
-       spin_lock(&port_lock);
-       port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE - IB_UMAD_MAX_PORTS];
+       port = container_of(inode->i_cdev, struct ib_umad_port, sm_cdev);
        if (port)
                kref_get(&port->umad_dev->ref);
-       spin_unlock(&port_lock);
-
-       if (!port)
+       else
                return -ENXIO;
 
        if (filp->f_flags & O_NONBLOCK) {
@@ -949,8 +930,8 @@ static int ib_umad_sm_close(struct inode *inode, struct file *filp)
 }
 
 static const struct file_operations umad_sm_fops = {
-       .owner   = THIS_MODULE,
-       .open    = ib_umad_sm_open,
+       .owner   = THIS_MODULE,
+       .open    = ib_umad_sm_open,
        .release = ib_umad_sm_close
 };
 
@@ -990,16 +971,51 @@ static ssize_t show_abi_version(struct class *class, char *buf)
 }
 static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
 
+static dev_t overflow_maj;
+static DECLARE_BITMAP(overflow_map, IB_UMAD_MAX_PORTS);
+static int find_overflow_devnum(void)
+{
+       int ret;
+
+       if (!overflow_maj) {
+               ret = alloc_chrdev_region(&overflow_maj, 0, IB_UMAD_MAX_PORTS * 2,
+                                         "infiniband_mad");
+               if (ret) {
+                       printk(KERN_ERR "user_mad: couldn't register dynamic device number\n");
+                       return ret;
+               }
+       }
+
+       ret = find_first_zero_bit(overflow_map, IB_UMAD_MAX_PORTS);
+       if (ret >= IB_UMAD_MAX_PORTS)
+               return -1;
+
+       return ret;
+}
+
 static int ib_umad_init_port(struct ib_device *device, int port_num,
                             struct ib_umad_port *port)
 {
+       int devnum;
+       dev_t base;
+
        spin_lock(&port_lock);
-       port->dev_num = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);
-       if (port->dev_num >= IB_UMAD_MAX_PORTS) {
+       devnum = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);
+       if (devnum >= IB_UMAD_MAX_PORTS) {
                spin_unlock(&port_lock);
-               return -1;
+               devnum = find_overflow_devnum();
+               if (devnum < 0)
+                       return -1;
+
+               spin_lock(&port_lock);
+               port->dev_num = devnum + IB_UMAD_MAX_PORTS;
+               base = devnum + overflow_maj;
+               set_bit(devnum, overflow_map);
+       } else {
+               port->dev_num = devnum;
+               base = devnum + base_dev;
+               set_bit(devnum, dev_map);
        }
-       set_bit(port->dev_num, dev_map);
        spin_unlock(&port_lock);
 
        port->ib_dev   = device;
@@ -1008,17 +1024,14 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
        mutex_init(&port->file_mutex);
        INIT_LIST_HEAD(&port->file_list);
 
-       port->cdev = cdev_alloc();
-       if (!port->cdev)
-               return -1;
-       port->cdev->owner = THIS_MODULE;
-       port->cdev->ops   = &umad_fops;
-       kobject_set_name(&port->cdev->kobj, "umad%d", port->dev_num);
-       if (cdev_add(port->cdev, base_dev + port->dev_num, 1))
+       cdev_init(&port->cdev, &umad_fops);
+       port->cdev.owner = THIS_MODULE;
+       kobject_set_name(&port->cdev.kobj, "umad%d", port->dev_num);
+       if (cdev_add(&port->cdev, base, 1))
                goto err_cdev;
 
        port->dev = device_create(umad_class, device->dma_device,
-                                 port->cdev->dev, port,
+                                 port->cdev.dev, port,
                                  "umad%d", port->dev_num);
        if (IS_ERR(port->dev))
                goto err_cdev;
@@ -1028,17 +1041,15 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
        if (device_create_file(port->dev, &dev_attr_port))
                goto err_dev;
 
-       port->sm_cdev = cdev_alloc();
-       if (!port->sm_cdev)
-               goto err_dev;
-       port->sm_cdev->owner = THIS_MODULE;
-       port->sm_cdev->ops   = &umad_sm_fops;
-       kobject_set_name(&port->sm_cdev->kobj, "issm%d", port->dev_num);
-       if (cdev_add(port->sm_cdev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
+       base += IB_UMAD_MAX_PORTS;
+       cdev_init(&port->sm_cdev, &umad_sm_fops);
+       port->sm_cdev.owner = THIS_MODULE;
+       kobject_set_name(&port->sm_cdev.kobj, "issm%d", port->dev_num);
+       if (cdev_add(&port->sm_cdev, base, 1))
                goto err_sm_cdev;
 
        port->sm_dev = device_create(umad_class, device->dma_device,
-                                    port->sm_cdev->dev, port,
+                                    port->sm_cdev.dev, port,
                                     "issm%d", port->dev_num);
        if (IS_ERR(port->sm_dev))
                goto err_sm_cdev;
@@ -1048,24 +1059,23 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
        if (device_create_file(port->sm_dev, &dev_attr_port))
                goto err_sm_dev;
 
-       spin_lock(&port_lock);
-       umad_port[port->dev_num] = port;
-       spin_unlock(&port_lock);
-
        return 0;
 
 err_sm_dev:
-       device_destroy(umad_class, port->sm_cdev->dev);
+       device_destroy(umad_class, port->sm_cdev.dev);
 
 err_sm_cdev:
-       cdev_del(port->sm_cdev);
+       cdev_del(&port->sm_cdev);
 
 err_dev:
-       device_destroy(umad_class, port->cdev->dev);
+       device_destroy(umad_class, port->cdev.dev);
 
 err_cdev:
-       cdev_del(port->cdev);
-       clear_bit(port->dev_num, dev_map);
+       cdev_del(&port->cdev);
+       if (port->dev_num < IB_UMAD_MAX_PORTS)
+               clear_bit(devnum, dev_map);
+       else
+               clear_bit(devnum, overflow_map);
 
        return -1;
 }
@@ -1079,15 +1089,11 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
        dev_set_drvdata(port->dev,    NULL);
        dev_set_drvdata(port->sm_dev, NULL);
 
-       device_destroy(umad_class, port->cdev->dev);
-       device_destroy(umad_class, port->sm_cdev->dev);
+       device_destroy(umad_class, port->cdev.dev);
+       device_destroy(umad_class, port->sm_cdev.dev);
 
-       cdev_del(port->cdev);
-       cdev_del(port->sm_cdev);
-
-       spin_lock(&port_lock);
-       umad_port[port->dev_num] = NULL;
-       spin_unlock(&port_lock);
+       cdev_del(&port->cdev);
+       cdev_del(&port->sm_cdev);
 
        mutex_lock(&port->file_mutex);
 
@@ -1106,7 +1112,10 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
 
        mutex_unlock(&port->file_mutex);
 
-       clear_bit(port->dev_num, dev_map);
+       if (port->dev_num < IB_UMAD_MAX_PORTS)
+               clear_bit(port->dev_num, dev_map);
+       else
+               clear_bit(port->dev_num - IB_UMAD_MAX_PORTS, overflow_map);
 }
 
 static void ib_umad_add_one(struct ib_device *device)
@@ -1214,6 +1223,8 @@ static void __exit ib_umad_cleanup(void)
        ib_unregister_client(&umad_client);
        class_destroy(umad_class);
        unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2);
+       if (overflow_maj)
+               unregister_chrdev_region(overflow_maj, IB_UMAD_MAX_PORTS * 2);
 }
 
 module_init(ib_umad_init);
index b3ea958..e54d9ac 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/idr.h>
 #include <linux/mutex.h>
 #include <linux/completion.h>
+#include <linux/cdev.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_umem.h>
 
 struct ib_uverbs_device {
        struct kref                             ref;
+       int                                     num_comp_vectors;
        struct completion                       comp;
-       int                                     devnum;
-       struct cdev                            *cdev;
        struct device                          *dev;
        struct ib_device                       *ib_dev;
-       int                                     num_comp_vectors;
+       int                                     devnum;
+       struct cdev                             cdev;
 };
 
 struct ib_uverbs_event_file {
        struct kref                             ref;
+       int                                     is_async;
        struct ib_uverbs_file                  *uverbs_file;
        spinlock_t                              lock;
+       int                                     is_closed;
        wait_queue_head_t                       poll_wait;
        struct fasync_struct                   *async_queue;
        struct list_head                        event_list;
-       int                                     is_async;
-       int                                     is_closed;
 };
 
 struct ib_uverbs_file {
index 5f284ff..dbf0451 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/sched.h>
 #include <linux/file.h>
 #include <linux/mount.h>
-#include <linux/cdev.h>
 
 #include <asm/uaccess.h>
 
@@ -75,40 +74,39 @@ DEFINE_IDR(ib_uverbs_qp_idr);
 DEFINE_IDR(ib_uverbs_srq_idr);
 
 static DEFINE_SPINLOCK(map_lock);
-static struct ib_uverbs_device *dev_table[IB_UVERBS_MAX_DEVICES];
 static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
 
 static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
                                     const char __user *buf, int in_len,
                                     int out_len) = {
-       [IB_USER_VERBS_CMD_GET_CONTEXT]         = ib_uverbs_get_context,
-       [IB_USER_VERBS_CMD_QUERY_DEVICE]        = ib_uverbs_query_device,
-       [IB_USER_VERBS_CMD_QUERY_PORT]          = ib_uverbs_query_port,
-       [IB_USER_VERBS_CMD_ALLOC_PD]            = ib_uverbs_alloc_pd,
-       [IB_USER_VERBS_CMD_DEALLOC_PD]          = ib_uverbs_dealloc_pd,
-       [IB_USER_VERBS_CMD_REG_MR]              = ib_uverbs_reg_mr,
-       [IB_USER_VERBS_CMD_DEREG_MR]            = ib_uverbs_dereg_mr,
+       [IB_USER_VERBS_CMD_GET_CONTEXT]         = ib_uverbs_get_context,
+       [IB_USER_VERBS_CMD_QUERY_DEVICE]        = ib_uverbs_query_device,
+       [IB_USER_VERBS_CMD_QUERY_PORT]          = ib_uverbs_query_port,
+       [IB_USER_VERBS_CMD_ALLOC_PD]            = ib_uverbs_alloc_pd,
+       [IB_USER_VERBS_CMD_DEALLOC_PD]          = ib_uverbs_dealloc_pd,
+       [IB_USER_VERBS_CMD_REG_MR]              = ib_uverbs_reg_mr,
+       [IB_USER_VERBS_CMD_DEREG_MR]            = ib_uverbs_dereg_mr,
        [IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel,
-       [IB_USER_VERBS_CMD_CREATE_CQ]           = ib_uverbs_create_cq,
-       [IB_USER_VERBS_CMD_RESIZE_CQ]           = ib_uverbs_resize_cq,
-       [IB_USER_VERBS_CMD_POLL_CQ]             = ib_uverbs_poll_cq,
-       [IB_USER_VERBS_CMD_REQ_NOTIFY_CQ]       = ib_uverbs_req_notify_cq,
-       [IB_USER_VERBS_CMD_DESTROY_CQ]          = ib_uverbs_destroy_cq,
-       [IB_USER_VERBS_CMD_CREATE_QP]           = ib_uverbs_create_qp,
-       [IB_USER_VERBS_CMD_QUERY_QP]            = ib_uverbs_query_qp,
-       [IB_USER_VERBS_CMD_MODIFY_QP]           = ib_uverbs_modify_qp,
-       [IB_USER_VERBS_CMD_DESTROY_QP]          = ib_uverbs_destroy_qp,
-       [IB_USER_VERBS_CMD_POST_SEND]           = ib_uverbs_post_send,
-       [IB_USER_VERBS_CMD_POST_RECV]           = ib_uverbs_post_recv,
-       [IB_USER_VERBS_CMD_POST_SRQ_RECV]       = ib_uverbs_post_srq_recv,
-       [IB_USER_VERBS_CMD_CREATE_AH]           = ib_uverbs_create_ah,
-       [IB_USER_VERBS_CMD_DESTROY_AH]          = ib_uverbs_destroy_ah,
-       [IB_USER_VERBS_CMD_ATTACH_MCAST]        = ib_uverbs_attach_mcast,
-       [IB_USER_VERBS_CMD_DETACH_MCAST]        = ib_uverbs_detach_mcast,
-       [IB_USER_VERBS_CMD_CREATE_SRQ]          = ib_uverbs_create_srq,
-       [IB_USER_VERBS_CMD_MODIFY_SRQ]          = ib_uverbs_modify_srq,
-       [IB_USER_VERBS_CMD_QUERY_SRQ]           = ib_uverbs_query_srq,
-       [IB_USER_VERBS_CMD_DESTROY_SRQ]         = ib_uverbs_destroy_srq,
+       [IB_USER_VERBS_CMD_CREATE_CQ]           = ib_uverbs_create_cq,
+       [IB_USER_VERBS_CMD_RESIZE_CQ]           = ib_uverbs_resize_cq,
+       [IB_USER_VERBS_CMD_POLL_CQ]             = ib_uverbs_poll_cq,
+       [IB_USER_VERBS_CMD_REQ_NOTIFY_CQ]       = ib_uverbs_req_notify_cq,
+       [IB_USER_VERBS_CMD_DESTROY_CQ]          = ib_uverbs_destroy_cq,
+       [IB_USER_VERBS_CMD_CREATE_QP]           = ib_uverbs_create_qp,
+       [IB_USER_VERBS_CMD_QUERY_QP]            = ib_uverbs_query_qp,
+       [IB_USER_VERBS_CMD_MODIFY_QP]           = ib_uverbs_modify_qp,
+       [IB_USER_VERBS_CMD_DESTROY_QP]          = ib_uverbs_destroy_qp,
+       [IB_USER_VERBS_CMD_POST_SEND]           = ib_uverbs_post_send,
+       [IB_USER_VERBS_CMD_POST_RECV]           = ib_uverbs_post_recv,
+       [IB_USER_VERBS_CMD_POST_SRQ_RECV]       = ib_uverbs_post_srq_recv,
+       [IB_USER_VERBS_CMD_CREATE_AH]           = ib_uverbs_create_ah,
+       [IB_USER_VERBS_CMD_DESTROY_AH]          = ib_uverbs_destroy_ah,
+       [IB_USER_VERBS_CMD_ATTACH_MCAST]        = ib_uverbs_attach_mcast,
+       [IB_USER_VERBS_CMD_DETACH_MCAST]        = ib_uverbs_detach_mcast,
+       [IB_USER_VERBS_CMD_CREATE_SRQ]          = ib_uverbs_create_srq,
+       [IB_USER_VERBS_CMD_MODIFY_SRQ]          = ib_uverbs_modify_srq,
+       [IB_USER_VERBS_CMD_QUERY_SRQ]           = ib_uverbs_query_srq,
+       [IB_USER_VERBS_CMD_DESTROY_SRQ]         = ib_uverbs_destroy_srq,
 };
 
 static struct vfsmount *uverbs_event_mnt;
@@ -370,7 +368,7 @@ static int ib_uverbs_event_close(struct inode *inode, struct file *filp)
 
 static const struct file_operations uverbs_event_fops = {
        .owner   = THIS_MODULE,
-       .read    = ib_uverbs_event_read,
+       .read    = ib_uverbs_event_read,
        .poll    = ib_uverbs_event_poll,
        .release = ib_uverbs_event_close,
        .fasync  = ib_uverbs_event_fasync
@@ -617,14 +615,12 @@ static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
 /*
  * ib_uverbs_open() does not need the BKL:
  *
- *  - dev_table[] accesses are protected by map_lock, the
- *    ib_uverbs_device structures are properly reference counted, and
+ *  - the ib_uverbs_device structures are properly reference counted and
  *    everything else is purely local to the file being created, so
  *    races against other open calls are not a problem;
  *  - there is no ioctl method to race against;
- *  - the device is added to dev_table[] as the last part of module
- *    initialization, the open method will either immediately run
- *    -ENXIO, or all required initialization will be done.
+ *  - the open method will either immediately run -ENXIO, or all
+ *    required initialization will be done.
  */
 static int ib_uverbs_open(struct inode *inode, struct file *filp)
 {
@@ -632,13 +628,10 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
        struct ib_uverbs_file *file;
        int ret;
 
-       spin_lock(&map_lock);
-       dev = dev_table[iminor(inode) - IB_UVERBS_BASE_MINOR];
+       dev = container_of(inode->i_cdev, struct ib_uverbs_device, cdev);
        if (dev)
                kref_get(&dev->ref);
-       spin_unlock(&map_lock);
-
-       if (!dev)
+       else
                return -ENXIO;
 
        if (!try_module_get(dev->ib_dev->owner)) {
@@ -685,17 +678,17 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp)
 }
 
 static const struct file_operations uverbs_fops = {
-       .owner   = THIS_MODULE,
-       .write   = ib_uverbs_write,
-       .open    = ib_uverbs_open,
+       .owner   = THIS_MODULE,
+       .write   = ib_uverbs_write,
+       .open    = ib_uverbs_open,
        .release = ib_uverbs_close
 };
 
 static const struct file_operations uverbs_mmap_fops = {
-       .owner   = THIS_MODULE,
-       .write   = ib_uverbs_write,
+       .owner   = THIS_MODULE,
+       .write   = ib_uverbs_write,
        .mmap    = ib_uverbs_mmap,
-       .open    = ib_uverbs_open,
+       .open    = ib_uverbs_open,
        .release = ib_uverbs_close
 };
 
@@ -735,8 +728,38 @@ static ssize_t show_abi_version(struct class *class, char *buf)
 }
 static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
 
+static dev_t overflow_maj;
+static DECLARE_BITMAP(overflow_map, IB_UVERBS_MAX_DEVICES);
+
+/*
+ * If we have more than IB_UVERBS_MAX_DEVICES, dynamically overflow by
+ * requesting a new major number and doubling the number of max devices we
+ * support. It's stupid, but simple.
+ */
+static int find_overflow_devnum(void)
+{
+       int ret;
+
+       if (!overflow_maj) {
+               ret = alloc_chrdev_region(&overflow_maj, 0, IB_UVERBS_MAX_DEVICES,
+                                         "infiniband_verbs");
+               if (ret) {
+                       printk(KERN_ERR "user_verbs: couldn't register dynamic device number\n");
+                       return ret;
+               }
+       }
+
+       ret = find_first_zero_bit(overflow_map, IB_UVERBS_MAX_DEVICES);
+       if (ret >= IB_UVERBS_MAX_DEVICES)
+               return -1;
+
+       return ret;
+}
+
 static void ib_uverbs_add_one(struct ib_device *device)
 {
+       int devnum;
+       dev_t base;
        struct ib_uverbs_device *uverbs_dev;
 
        if (!device->alloc_ucontext)
@@ -750,28 +773,36 @@ static void ib_uverbs_add_one(struct ib_device *device)
        init_completion(&uverbs_dev->comp);
 
        spin_lock(&map_lock);
-       uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
-       if (uverbs_dev->devnum >= IB_UVERBS_MAX_DEVICES) {
+       devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
+       if (devnum >= IB_UVERBS_MAX_DEVICES) {
                spin_unlock(&map_lock);
-               goto err;
+               devnum = find_overflow_devnum();
+               if (devnum < 0)
+                       goto err;
+
+               spin_lock(&map_lock);
+               uverbs_dev->devnum = devnum + IB_UVERBS_MAX_DEVICES;
+               base = devnum + overflow_maj;
+               set_bit(devnum, overflow_map);
+       } else {
+               uverbs_dev->devnum = devnum;
+               base = devnum + IB_UVERBS_BASE_DEV;
+               set_bit(devnum, dev_map);
        }
-       set_bit(uverbs_dev->devnum, dev_map);
        spin_unlock(&map_lock);
 
        uverbs_dev->ib_dev           = device;
        uverbs_dev->num_comp_vectors = device->num_comp_vectors;
 
-       uverbs_dev->cdev = cdev_alloc();
-       if (!uverbs_dev->cdev)
-               goto err;
-       uverbs_dev->cdev->owner = THIS_MODULE;
-       uverbs_dev->cdev->ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
-       kobject_set_name(&uverbs_dev->cdev->kobj, "uverbs%d", uverbs_dev->devnum);
-       if (cdev_add(uverbs_dev->cdev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
+       cdev_init(&uverbs_dev->cdev, NULL);
+       uverbs_dev->cdev.owner = THIS_MODULE;
+       uverbs_dev->cdev.ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
+       kobject_set_name(&uverbs_dev->cdev.kobj, "uverbs%d", uverbs_dev->devnum);
+       if (cdev_add(&uverbs_dev->cdev, base, 1))
                goto err_cdev;
 
        uverbs_dev->dev = device_create(uverbs_class, device->dma_device,
-                                       uverbs_dev->cdev->dev, uverbs_dev,
+                                       uverbs_dev->cdev.dev, uverbs_dev,
                                        "uverbs%d", uverbs_dev->devnum);
        if (IS_ERR(uverbs_dev->dev))
                goto err_cdev;
@@ -781,20 +812,19 @@ static void ib_uverbs_add_one(struct ib_device *device)
        if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version))
                goto err_class;
 
-       spin_lock(&map_lock);
-       dev_table[uverbs_dev->devnum] = uverbs_dev;
-       spin_unlock(&map_lock);
-
        ib_set_client_data(device, &uverbs_client, uverbs_dev);
 
        return;
 
 err_class:
-       device_destroy(uverbs_class, uverbs_dev->cdev->dev);
+       device_destroy(uverbs_class, uverbs_dev->cdev.dev);
 
 err_cdev:
-       cdev_del(uverbs_dev->cdev);
-       clear_bit(uverbs_dev->devnum, dev_map);
+       cdev_del(&uverbs_dev->cdev);
+       if (uverbs_dev->devnum < IB_UVERBS_MAX_DEVICES)
+               clear_bit(devnum, dev_map);
+       else
+               clear_bit(devnum, overflow_map);
 
 err:
        kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
@@ -811,14 +841,13 @@ static void ib_uverbs_remove_one(struct ib_device *device)
                return;
 
        dev_set_drvdata(uverbs_dev->dev, NULL);
-       device_destroy(uverbs_class, uverbs_dev->cdev->dev);
-       cdev_del(uverbs_dev->cdev);
+       device_destroy(uverbs_class, uverbs_dev->cdev.dev);
+       cdev_del(&uverbs_dev->cdev);
 
-       spin_lock(&map_lock);
-       dev_table[uverbs_dev->devnum] = NULL;
-       spin_unlock(&map_lock);
-
-       clear_bit(uverbs_dev->devnum, dev_map);
+       if (uverbs_dev->devnum < IB_UVERBS_MAX_DEVICES)
+               clear_bit(uverbs_dev->devnum, dev_map);
+       else
+               clear_bit(uverbs_dev->devnum - IB_UVERBS_MAX_DEVICES, overflow_map);
 
        kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
        wait_for_completion(&uverbs_dev->comp);
@@ -908,6 +937,8 @@ static void __exit ib_uverbs_cleanup(void)
        unregister_filesystem(&uverbs_event_fs);
        class_destroy(uverbs_class);
        unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
+       if (overflow_maj)
+               unregister_chrdev_region(overflow_maj, IB_UVERBS_MAX_DEVICES);
        idr_destroy(&ib_uverbs_pd_idr);
        idr_destroy(&ib_uverbs_mr_idr);
        idr_destroy(&ib_uverbs_mw_idr);
index 0677fc7..a28e862 100644 (file)
@@ -109,7 +109,6 @@ int cxio_hal_cq_op(struct cxio_rdev *rdev_p, struct t3_cq *cq,
                while (!CQ_VLD_ENTRY(rptr, cq->size_log2, cqe)) {
                        udelay(1);
                        if (i++ > 1000000) {
-                               BUG_ON(1);
                                printk(KERN_ERR "%s: stalled rnic\n",
                                       rdev_p->dev_name);
                                return -EIO;
@@ -155,7 +154,7 @@ static int cxio_hal_clear_qp_ctx(struct cxio_rdev *rdev_p, u32 qpid)
        return iwch_cxgb3_ofld_send(rdev_p->t3cdev_p, skb);
 }
 
-int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)
+int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq, int kernel)
 {
        struct rdma_cq_setup setup;
        int size = (1UL << (cq->size_log2)) * sizeof(struct t3_cqe);
@@ -163,12 +162,12 @@ int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)
        cq->cqid = cxio_hal_get_cqid(rdev_p->rscp);
        if (!cq->cqid)
                return -ENOMEM;
-       cq->sw_queue = kzalloc(size, GFP_KERNEL);
-       if (!cq->sw_queue)
-               return -ENOMEM;
-       cq->queue = dma_alloc_coherent(&(rdev_p->rnic_info.pdev->dev),
-                                            (1UL << (cq->size_log2)) *
-                                            sizeof(struct t3_cqe),
+       if (kernel) {
+               cq->sw_queue = kzalloc(size, GFP_KERNEL);
+               if (!cq->sw_queue)
+                       return -ENOMEM;
+       }
+       cq->queue = dma_alloc_coherent(&(rdev_p->rnic_info.pdev->dev), size,
                                             &(cq->dma_addr), GFP_KERNEL);
        if (!cq->queue) {
                kfree(cq->sw_queue);
index f3d440c..073373c 100644 (file)
@@ -53,7 +53,7 @@
 #define T3_MAX_PBL_SIZE 256
 #define T3_MAX_RQ_SIZE 1024
 #define T3_MAX_QP_DEPTH (T3_MAX_RQ_SIZE-1)
-#define T3_MAX_CQ_DEPTH 8192
+#define T3_MAX_CQ_DEPTH 262144
 #define T3_MAX_NUM_STAG (1<<15)
 #define T3_MAX_MR_SIZE 0x100000000ULL
 #define T3_PAGESIZE_MASK 0xffff000  /* 4KB-128MB */
@@ -157,7 +157,7 @@ int cxio_rdev_open(struct cxio_rdev *rdev);
 void cxio_rdev_close(struct cxio_rdev *rdev);
 int cxio_hal_cq_op(struct cxio_rdev *rdev, struct t3_cq *cq,
                   enum t3_cq_opcode op, u32 credit);
-int cxio_create_cq(struct cxio_rdev *rdev, struct t3_cq *cq);
+int cxio_create_cq(struct cxio_rdev *rdev, struct t3_cq *cq, int kernel);
 int cxio_destroy_cq(struct cxio_rdev *rdev, struct t3_cq *cq);
 int cxio_resize_cq(struct cxio_rdev *rdev, struct t3_cq *cq);
 void cxio_release_ucontext(struct cxio_rdev *rdev, struct cxio_ucontext *uctx);
index a197a5b..15073b2 100644 (file)
@@ -730,7 +730,22 @@ struct t3_cq {
 
 static inline void cxio_set_wq_in_error(struct t3_wq *wq)
 {
-       wq->queue->wq_in_err.err = 1;
+       wq->queue->wq_in_err.err |= 1;
+}
+
+static inline void cxio_disable_wq_db(struct t3_wq *wq)
+{
+       wq->queue->wq_in_err.err |= 2;
+}
+
+static inline void cxio_enable_wq_db(struct t3_wq *wq)
+{
+       wq->queue->wq_in_err.err &= ~2;
+}
+
+static inline int cxio_wq_db_enabled(struct t3_wq *wq)
+{
+       return !(wq->queue->wq_in_err.err & 2);
 }
 
 static inline struct t3_cqe *cxio_next_hw_cqe(struct t3_cq *cq)
index b0ea010..ee1d8b4 100644 (file)
@@ -65,6 +65,46 @@ struct cxgb3_client t3c_client = {
 static LIST_HEAD(dev_list);
 static DEFINE_MUTEX(dev_mutex);
 
+static int disable_qp_db(int id, void *p, void *data)
+{
+       struct iwch_qp *qhp = p;
+
+       cxio_disable_wq_db(&qhp->wq);
+       return 0;
+}
+
+static int enable_qp_db(int id, void *p, void *data)
+{
+       struct iwch_qp *qhp = p;
+
+       if (data)
+               ring_doorbell(qhp->rhp->rdev.ctrl_qp.doorbell, qhp->wq.qpid);
+       cxio_enable_wq_db(&qhp->wq);
+       return 0;
+}
+
+static void disable_dbs(struct iwch_dev *rnicp)
+{
+       spin_lock_irq(&rnicp->lock);
+       idr_for_each(&rnicp->qpidr, disable_qp_db, NULL);
+       spin_unlock_irq(&rnicp->lock);
+}
+
+static void enable_dbs(struct iwch_dev *rnicp, int ring_db)
+{
+       spin_lock_irq(&rnicp->lock);
+       idr_for_each(&rnicp->qpidr, enable_qp_db,
+                    (void *)(unsigned long)ring_db);
+       spin_unlock_irq(&rnicp->lock);
+}
+
+static void iwch_db_drop_task(struct work_struct *work)
+{
+       struct iwch_dev *rnicp = container_of(work, struct iwch_dev,
+                                             db_drop_task.work);
+       enable_dbs(rnicp, 1);
+}
+
 static void rnic_init(struct iwch_dev *rnicp)
 {
        PDBG("%s iwch_dev %p\n", __func__,  rnicp);
@@ -72,6 +112,7 @@ static void rnic_init(struct iwch_dev *rnicp)
        idr_init(&rnicp->qpidr);
        idr_init(&rnicp->mmidr);
        spin_lock_init(&rnicp->lock);
+       INIT_DELAYED_WORK(&rnicp->db_drop_task, iwch_db_drop_task);
 
        rnicp->attr.max_qps = T3_MAX_NUM_QP - 32;
        rnicp->attr.max_wrs = T3_MAX_QP_DEPTH;
@@ -147,6 +188,8 @@ static void close_rnic_dev(struct t3cdev *tdev)
        mutex_lock(&dev_mutex);
        list_for_each_entry_safe(dev, tmp, &dev_list, entry) {
                if (dev->rdev.t3cdev_p == tdev) {
+                       dev->rdev.flags = CXIO_ERROR_FATAL;
+                       cancel_delayed_work_sync(&dev->db_drop_task);
                        list_del(&dev->entry);
                        iwch_unregister_device(dev);
                        cxio_rdev_close(&dev->rdev);
@@ -165,7 +208,8 @@ static void iwch_event_handler(struct t3cdev *tdev, u32 evt, u32 port_id)
        struct cxio_rdev *rdev = tdev->ulp;
        struct iwch_dev *rnicp;
        struct ib_event event;
-       u32    portnum = port_id + 1;
+       u32 portnum = port_id + 1;
+       int dispatch = 0;
 
        if (!rdev)
                return;
@@ -174,21 +218,49 @@ static void iwch_event_handler(struct t3cdev *tdev, u32 evt, u32 port_id)
        case OFFLOAD_STATUS_DOWN: {
                rdev->flags = CXIO_ERROR_FATAL;
                event.event  = IB_EVENT_DEVICE_FATAL;
+               dispatch = 1;
                break;
                }
        case OFFLOAD_PORT_DOWN: {
                event.event  = IB_EVENT_PORT_ERR;
+               dispatch = 1;
                break;
                }
        case OFFLOAD_PORT_UP: {
                event.event  = IB_EVENT_PORT_ACTIVE;
+               dispatch = 1;
+               break;
+               }
+       case OFFLOAD_DB_FULL: {
+               disable_dbs(rnicp);
+               break;
+               }
+       case OFFLOAD_DB_EMPTY: {
+               enable_dbs(rnicp, 1);
+               break;
+               }
+       case OFFLOAD_DB_DROP: {
+               unsigned long delay = 1000;
+               unsigned short r;
+
+               disable_dbs(rnicp);
+               get_random_bytes(&r, 2);
+               delay += r & 1023;
+
+               /*
+                * delay is between 1000-2023 usecs.
+                */
+               schedule_delayed_work(&rnicp->db_drop_task,
+                       usecs_to_jiffies(delay));
                break;
                }
        }
 
-       event.device = &rnicp->ibdev;
-       event.element.port_num = portnum;
-       ib_dispatch_event(&event);
+       if (dispatch) {
+               event.device = &rnicp->ibdev;
+               event.element.port_num = portnum;
+               ib_dispatch_event(&event);
+       }
 
        return;
 }
index 8473550..a1c4457 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/idr.h>
+#include <linux/workqueue.h>
 
 #include <rdma/ib_verbs.h>
 
@@ -110,6 +111,7 @@ struct iwch_dev {
        struct idr mmidr;
        spinlock_t lock;
        struct list_head entry;
+       struct delayed_work db_drop_task;
 };
 
 static inline struct iwch_dev *to_iwch_dev(struct ib_device *ibdev)
index ed71755..47b35c6 100644 (file)
@@ -187,7 +187,7 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
        entries = roundup_pow_of_two(entries);
        chp->cq.size_log2 = ilog2(entries);
 
-       if (cxio_create_cq(&rhp->rdev, &chp->cq)) {
+       if (cxio_create_cq(&rhp->rdev, &chp->cq, !ucontext)) {
                kfree(chp);
                return ERR_PTR(-ENOMEM);
        }
index 3eb8cec..b4d893d 100644 (file)
@@ -452,7 +452,8 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                ++(qhp->wq.sq_wptr);
        }
        spin_unlock_irqrestore(&qhp->lock, flag);
-       ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
+       if (cxio_wq_db_enabled(&qhp->wq))
+               ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
 
 out:
        if (err)
@@ -514,7 +515,8 @@ int iwch_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
                num_wrs--;
        }
        spin_unlock_irqrestore(&qhp->lock, flag);
-       ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
+       if (cxio_wq_db_enabled(&qhp->wq))
+               ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
 
 out:
        if (err)
@@ -597,7 +599,8 @@ int iwch_bind_mw(struct ib_qp *qp,
        ++(qhp->wq.sq_wptr);
        spin_unlock_irqrestore(&qhp->lock, flag);
 
-       ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
+       if (cxio_wq_db_enabled(&qhp->wq))
+               ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
 
        return err;
 }
index 42be0b1..b2b6fea 100644 (file)
@@ -548,11 +548,10 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
        struct ehca_eq *eq = &shca->eq;
        struct ehca_eqe_cache_entry *eqe_cache = eq->eqe_cache;
        u64 eqe_value, ret;
-       unsigned long flags;
        int eqe_cnt, i;
        int eq_empty = 0;
 
-       spin_lock_irqsave(&eq->irq_spinlock, flags);
+       spin_lock(&eq->irq_spinlock);
        if (is_irq) {
                const int max_query_cnt = 100;
                int query_cnt = 0;
@@ -643,7 +642,7 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
        } while (1);
 
 unlock_irq_spinlock:
-       spin_unlock_irqrestore(&eq->irq_spinlock, flags);
+       spin_unlock(&eq->irq_spinlock);
 }
 
 void ehca_tasklet_eq(unsigned long data)
index 0338f1f..b105f66 100644 (file)
@@ -55,9 +55,7 @@ static struct kmem_cache *qp_cache;
 /*
  * attributes not supported by query qp
  */
-#define QP_ATTR_QUERY_NOT_SUPPORTED (IB_QP_MAX_DEST_RD_ATOMIC | \
-                                    IB_QP_MAX_QP_RD_ATOMIC   | \
-                                    IB_QP_ACCESS_FLAGS       | \
+#define QP_ATTR_QUERY_NOT_SUPPORTED (IB_QP_ACCESS_FLAGS       | \
                                     IB_QP_EN_SQD_ASYNC_NOTIFY)
 
 /*
index 8c1213f..dba8f9f 100644 (file)
@@ -222,7 +222,7 @@ int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
 {
        int ret;
 
-       if (!port_num || port_num > ibdev->phys_port_cnt)
+       if (!port_num || port_num > ibdev->phys_port_cnt || !in_wc)
                return IB_MAD_RESULT_FAILURE;
 
        /* accept only pma request */
index 3e8618b..4cd7f42 100644 (file)
@@ -264,6 +264,10 @@ struct adapter {
        struct work_struct fatal_error_handler_task;
        struct work_struct link_fault_handler_task;
 
+       struct work_struct db_full_task;
+       struct work_struct db_empty_task;
+       struct work_struct db_drop_task;
+
        struct dentry *debugfs_root;
 
        struct mutex mdio_lock;
@@ -335,6 +339,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
 int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx,
                unsigned char *data);
 irqreturn_t t3_sge_intr_msix(int irq, void *cookie);
+extern struct workqueue_struct *cxgb3_wq;
 
 int t3_get_edc_fw(struct cphy *phy, int edc_idx, int size);
 
index 89bec9c..37945fc 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/firmware.h>
 #include <linux/log2.h>
 #include <linux/stringify.h>
+#include <linux/sched.h>
 #include <asm/uaccess.h>
 
 #include "common.h"
@@ -140,7 +141,7 @@ MODULE_PARM_DESC(ofld_disable, "whether to enable offload at init time or not");
  * will block keventd as it needs the rtnl lock, and we'll deadlock waiting
  * for our work to complete.  Get our own work queue to solve this.
  */
-static struct workqueue_struct *cxgb3_wq;
+struct workqueue_struct *cxgb3_wq;
 
 /**
  *     link_report - show link status and link speed/duplex
@@ -590,6 +591,19 @@ static void setup_rss(struct adapter *adap)
                      V_RRCPLCPUSIZE(6) | F_HASHTOEPLITZ, cpus, rspq_map);
 }
 
+static void ring_dbs(struct adapter *adap)
+{
+       int i, j;
+
+       for (i = 0; i < SGE_QSETS; i++) {
+               struct sge_qset *qs = &adap->sge.qs[i];
+
+               if (qs->adap)
+                       for (j = 0; j < SGE_TXQ_PER_SET; j++)
+                               t3_write_reg(adap, A_SG_KDOORBELL, F_SELEGRCNTX | V_EGRCNTX(qs->txq[j].cntxt_id));
+       }
+}
+
 static void init_napi(struct adapter *adap)
 {
        int i;
@@ -2754,6 +2768,42 @@ static void t3_adap_check_task(struct work_struct *work)
        spin_unlock_irq(&adapter->work_lock);
 }
 
+static void db_full_task(struct work_struct *work)
+{
+       struct adapter *adapter = container_of(work, struct adapter,
+                                              db_full_task);
+
+       cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_FULL, 0);
+}
+
+static void db_empty_task(struct work_struct *work)
+{
+       struct adapter *adapter = container_of(work, struct adapter,
+                                              db_empty_task);
+
+       cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_EMPTY, 0);
+}
+
+static void db_drop_task(struct work_struct *work)
+{
+       struct adapter *adapter = container_of(work, struct adapter,
+                                              db_drop_task);
+       unsigned long delay = 1000;
+       unsigned short r;
+
+       cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_DROP, 0);
+
+       /*
+        * Sleep a while before ringing the driver qset dbs.
+        * The delay is between 1000-2023 usecs.
+        */
+       get_random_bytes(&r, 2);
+       delay += r & 1023;
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule_timeout(usecs_to_jiffies(delay));
+       ring_dbs(adapter);
+}
+
 /*
  * Processes external (PHY) interrupts in process context.
  */
@@ -3222,6 +3272,11 @@ static int __devinit init_one(struct pci_dev *pdev,
        INIT_LIST_HEAD(&adapter->adapter_list);
        INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task);
        INIT_WORK(&adapter->fatal_error_handler_task, fatal_error_task);
+
+       INIT_WORK(&adapter->db_full_task, db_full_task);
+       INIT_WORK(&adapter->db_empty_task, db_empty_task);
+       INIT_WORK(&adapter->db_drop_task, db_drop_task);
+
        INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task);
 
        for (i = 0; i < ai->nports0 + ai->nports1; ++i) {
index 670aa62..929c298 100644 (file)
@@ -73,7 +73,10 @@ enum {
        OFFLOAD_STATUS_UP,
        OFFLOAD_STATUS_DOWN,
        OFFLOAD_PORT_DOWN,
-       OFFLOAD_PORT_UP
+       OFFLOAD_PORT_UP,
+       OFFLOAD_DB_FULL,
+       OFFLOAD_DB_EMPTY,
+       OFFLOAD_DB_DROP
 };
 
 struct cxgb3_client {
index 1b5327b..cb42353 100644 (file)
 #define V_LOPIODRBDROPERR(x) ((x) << S_LOPIODRBDROPERR)
 #define F_LOPIODRBDROPERR    V_LOPIODRBDROPERR(1U)
 
+#define S_HIPRIORITYDBFULL    7
+#define V_HIPRIORITYDBFULL(x) ((x) << S_HIPRIORITYDBFULL)
+#define F_HIPRIORITYDBFULL    V_HIPRIORITYDBFULL(1U)
+
+#define S_HIPRIORITYDBEMPTY   6
+#define V_HIPRIORITYDBEMPTY(x) ((x) << S_HIPRIORITYDBEMPTY)
+#define F_HIPRIORITYDBEMPTY    V_HIPRIORITYDBEMPTY(1U)
+
+#define S_LOPRIORITYDBFULL    5
+#define V_LOPRIORITYDBFULL(x) ((x) << S_LOPRIORITYDBFULL)
+#define F_LOPRIORITYDBFULL    V_LOPRIORITYDBFULL(1U)
+
+#define S_LOPRIORITYDBEMPTY   4
+#define V_LOPRIORITYDBEMPTY(x) ((x) << S_LOPRIORITYDBEMPTY)
+#define F_LOPRIORITYDBEMPTY    V_LOPRIORITYDBEMPTY(1U)
+
 #define S_RSPQDISABLED    3
 #define V_RSPQDISABLED(x) ((x) << S_RSPQDISABLED)
 #define F_RSPQDISABLED    V_RSPQDISABLED(1U)
index 318a018..9b43446 100644 (file)
@@ -42,6 +42,7 @@
 #include "sge_defs.h"
 #include "t3_cpl.h"
 #include "firmware_exports.h"
+#include "cxgb3_offload.h"
 
 #define USE_GTS 0
 
@@ -2833,8 +2834,13 @@ void t3_sge_err_intr_handler(struct adapter *adapter)
        }
 
        if (status & (F_HIPIODRBDROPERR | F_LOPIODRBDROPERR))
-               CH_ALERT(adapter, "SGE dropped %s priority doorbell\n",
-                        status & F_HIPIODRBDROPERR ? "high" : "lo");
+               queue_work(cxgb3_wq, &adapter->db_drop_task);
+
+       if (status & (F_HIPRIORITYDBFULL | F_LOPRIORITYDBFULL))
+               queue_work(cxgb3_wq, &adapter->db_full_task);
+
+       if (status & (F_HIPRIORITYDBEMPTY | F_LOPRIORITYDBEMPTY))
+               queue_work(cxgb3_wq, &adapter->db_empty_task);
 
        t3_write_reg(adapter, A_SG_INT_CAUSE, status);
        if (status &  SGE_FATALERR)
index 032cfe0..c38fc71 100644 (file)
@@ -1432,7 +1432,10 @@ static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg,
                       F_IRPARITYERROR | V_ITPARITYERROR(M_ITPARITYERROR) | \
                       V_FLPARITYERROR(M_FLPARITYERROR) | F_LODRBPARITYERROR | \
                       F_HIDRBPARITYERROR | F_LORCQPARITYERROR | \
-                      F_HIRCQPARITYERROR)
+                      F_HIRCQPARITYERROR | F_LOPRIORITYDBFULL | \
+                      F_HIPRIORITYDBFULL | F_LOPRIORITYDBEMPTY | \
+                      F_HIPRIORITYDBEMPTY | F_HIPIODRBDROPERR | \
+                      F_LOPIODRBDROPERR)
 #define MC5_INTR_MASK (F_PARITYERR | F_ACTRGNFULL | F_UNKNOWNCMD | \
                       F_REQQPARERR | F_DISPQPARERR | F_DELACTEMPTY | \
                       F_NFASRCHFAIL)
index 09509ed..a585e0f 100644 (file)
@@ -984,9 +984,9 @@ struct ib_device {
        struct list_head              event_handler_list;
        spinlock_t                    event_handler_lock;
 
+       spinlock_t                    client_data_lock;
        struct list_head              core_list;
        struct list_head              client_data_list;
-       spinlock_t                    client_data_lock;
 
        struct ib_cache               cache;
        int                          *pkey_tbl_len;
@@ -1144,8 +1144,8 @@ struct ib_device {
                IB_DEV_UNREGISTERED
        }                            reg_state;
 
-       u64                          uverbs_cmd_mask;
        int                          uverbs_abi_ver;
+       u64                          uverbs_cmd_mask;
 
        char                         node_desc[64];
        __be64                       node_guid;
index c6b2962..4fae903 100644 (file)
@@ -67,7 +67,6 @@ enum rdma_port_space {
        RDMA_PS_IPOIB = 0x0002,
        RDMA_PS_TCP   = 0x0106,
        RDMA_PS_UDP   = 0x0111,
-       RDMA_PS_SCTP  = 0x0183
 };
 
 struct rdma_addr {