Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 1721

kernel-2.6.18-128.1.10.el5.src.rpm

From: Doug Ledford <dledford@redhat.com>
Date: Mon, 24 Mar 2008 14:24:23 -0400
Subject: [openib] remove xrc support
Message-id: 1206383072-7299-3-git-send-email-dledford@redhat.com
O-Subject: [Patch RHEL5 02/10] Infiniband: Remove xrc support
Bugzilla: 253023

I accidentally let a feature that we don't think is ready for prime
time into the OFED 1.3-rc1 patch set.  This backs that feature out.
Upstream still isn't certain that this feature's ABI won't change
in the future, so it would be best to avoid shipping it yet.

Signed-off-by: Doug Ledford <dledford@redhat.com>

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 137c9e9..858b6ea 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -296,8 +296,6 @@ int ib_register_device(struct ib_device *device)
 	INIT_LIST_HEAD(&device->client_data_list);
 	spin_lock_init(&device->event_handler_lock);
 	spin_lock_init(&device->client_data_lock);
-	device->ib_uverbs_xrcd_table = RB_ROOT;
-	mutex_init(&device->xrcd_table_mutex);
 
 	ret = read_port_table_lengths(device);
 	if (ret) {
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 237cc2d..c75eb6c 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -143,7 +143,6 @@ extern struct idr ib_uverbs_ah_idr;
 extern struct idr ib_uverbs_cq_idr;
 extern struct idr ib_uverbs_qp_idr;
 extern struct idr ib_uverbs_srq_idr;
-extern struct idr ib_uverbs_xrc_domain_idr;
 
 void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
 
@@ -163,8 +162,6 @@ void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
 void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
 void ib_uverbs_event_handler(struct ib_event_handler *handler,
 			     struct ib_event *event);
-void ib_uverbs_dealloc_xrcd(struct ib_device *ib_dev,
-			    struct ib_xrcd *xrcd);
 
 #define IB_UVERBS_DECLARE_CMD(name)					\
 	ssize_t ib_uverbs_##name(struct ib_uverbs_file *file,		\
@@ -199,9 +196,5 @@ IB_UVERBS_DECLARE_CMD(create_srq);
 IB_UVERBS_DECLARE_CMD(modify_srq);
 IB_UVERBS_DECLARE_CMD(query_srq);
 IB_UVERBS_DECLARE_CMD(destroy_srq);
-IB_UVERBS_DECLARE_CMD(create_xrc_srq);
-IB_UVERBS_DECLARE_CMD(open_xrc_domain);
-IB_UVERBS_DECLARE_CMD(close_xrc_domain);
-
 
 #endif /* UVERBS_H */
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index a99839b..9e98cec 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -39,7 +39,6 @@
 #include <linux/fs.h>
 
 #include <asm/uaccess.h>
-#include <asm/fcntl.h>
 
 #include "uverbs.h"
 
@@ -257,20 +256,6 @@ static void put_srq_read(struct ib_srq *srq)
 	put_uobj_read(srq->uobject);
 }
 
-static struct ib_xrcd *idr_read_xrcd(int xrcd_handle,
-				     struct ib_ucontext *context,
-				     struct ib_uobject **uobj)
-{
-	*uobj = idr_read_uobj(&ib_uverbs_xrc_domain_idr, xrcd_handle,
-			      context, 0);
-	return *uobj ? (*uobj)->object : NULL;
-}
-
-static void put_xrcd_read(struct ib_uobject *uobj)
-{
-	put_uobj_read(uobj);
-}
-
 ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
 			      const char __user *buf,
 			      int in_len, int out_len)
@@ -314,7 +299,6 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
 	INIT_LIST_HEAD(&ucontext->qp_list);
 	INIT_LIST_HEAD(&ucontext->srq_list);
 	INIT_LIST_HEAD(&ucontext->ah_list);
-	INIT_LIST_HEAD(&ucontext->xrc_domain_list);
 	ucontext->closing = 0;
 
 	resp.num_comp_vectors = file->device->num_comp_vectors;
@@ -1044,8 +1028,6 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
 	struct ib_srq                  *srq;
 	struct ib_qp                   *qp;
 	struct ib_qp_init_attr          attr;
-	struct ib_xrcd	 	       *xrcd;
-	struct ib_uobject		*xrcd_uobj;
 	int ret;
 
 	if (out_len < sizeof resp)
@@ -1065,17 +1047,13 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
 	init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
 	down_write(&obj->uevent.uobject.mutex);
 
-	srq = (cmd.is_srq && cmd.qp_type != IB_QPT_XRC) ?
-		idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
-	xrcd = cmd.qp_type == IB_QPT_XRC ?
-		idr_read_xrcd(cmd.srq_handle, file->ucontext, &xrcd_uobj) : NULL;
+	srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
 	pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
 	scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
 	rcq = cmd.recv_cq_handle == cmd.send_cq_handle ?
 		scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
 
-	if (!pd || !scq || !rcq || cmd.is_srq && !srq ||
-	    cmd.qp_type == IB_QPT_XRC && !xrcd) {
+	if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
 		ret = -EINVAL;
 		goto err_put;
 	}
@@ -1087,7 +1065,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
 	attr.srq           = srq;
 	attr.sq_sig_type   = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
 	attr.qp_type       = cmd.qp_type;
-	attr.xrc_domain	   = xrcd;
+	attr.create_flags  = 0;
 
 	attr.cap.max_send_wr     = cmd.max_send_wr;
 	attr.cap.max_recv_wr     = cmd.max_recv_wr;
@@ -1114,14 +1092,11 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
 	qp->event_handler = attr.event_handler;
 	qp->qp_context    = attr.qp_context;
 	qp->qp_type	  = attr.qp_type;
-	qp->xrcd	  = attr.xrc_domain;
 	atomic_inc(&pd->usecnt);
 	atomic_inc(&attr.send_cq->usecnt);
 	atomic_inc(&attr.recv_cq->usecnt);
 	if (attr.srq)
 		atomic_inc(&attr.srq->usecnt);
-	else if (attr.xrc_domain)
-		atomic_inc(&attr.xrc_domain->usecnt);
 
 	obj->uevent.uobject.object = qp;
 	ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
@@ -1149,8 +1124,6 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
 		put_cq_read(rcq);
 	if (srq)
 		put_srq_read(srq);
-	if (xrcd)
-		put_xrcd_read(xrcd_uobj);
 
 	mutex_lock(&file->mutex);
 	list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list);
@@ -1177,8 +1150,6 @@ err_put:
 		put_cq_read(rcq);
 	if (srq)
 		put_srq_read(srq);
-	if (xrcd)
-		put_xrcd_read(xrcd_uobj);
 
 	put_uobj_write(&obj->uevent.uobject);
 	return ret;
@@ -2022,8 +1993,6 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
 	srq->uobject       = &obj->uobject;
 	srq->event_handler = attr.event_handler;
 	srq->srq_context   = attr.srq_context;
-	srq->xrc_cq = NULL;
-	srq->xrcd = NULL;
 	atomic_inc(&pd->usecnt);
 	atomic_set(&srq->usecnt, 0);
 
@@ -2069,136 +2038,6 @@ err:
 	return ret;
 }
 
-ssize_t ib_uverbs_create_xrc_srq(struct ib_uverbs_file *file,
-			     const char __user *buf, int in_len,
-			     int out_len)
-{
-	struct ib_uverbs_create_xrc_srq  cmd;
-	struct ib_uverbs_create_srq_resp resp;
-	struct ib_udata                  udata;
-	struct ib_uevent_object         *obj;
-	struct ib_pd                    *pd;
-	struct ib_srq                   *srq;
-	struct ib_cq			*xrc_cq;
-	struct ib_xrcd			*xrcd;
-	struct ib_srq_init_attr          attr;
-	struct ib_uobject		*xrcd_uobj;
-	int ret;
-
-	if (out_len < sizeof resp)
-		return -ENOSPC;
-
-	if (copy_from_user(&cmd, buf, sizeof cmd))
-		return -EFAULT;
-
-	INIT_UDATA(&udata, buf + sizeof cmd,
-		   (unsigned long) cmd.response + sizeof resp,
-		   in_len - sizeof cmd, out_len - sizeof resp);
-
-	obj = kmalloc(sizeof *obj, GFP_KERNEL);
-	if (!obj)
-		return -ENOMEM;
-
-	init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &srq_lock_key);
-	down_write(&obj->uobject.mutex);
-
-	pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
-	if (!pd) {
-		ret = -EINVAL;
-		goto err;
-	}
-
-	xrc_cq  = idr_read_cq(cmd.xrc_cq, file->ucontext, 0);
-	if (!xrc_cq) {
-		ret = -EINVAL;
-		goto err_put_pd;
-	}
-
-	xrcd  = idr_read_xrcd(cmd.xrcd_handle, file->ucontext, &xrcd_uobj);
-	if (!xrcd) {
-		ret = -EINVAL;
-		goto err_put_cq;
-	}
-
-
-	attr.event_handler  = ib_uverbs_srq_event_handler;
-	attr.srq_context    = file;
-	attr.attr.max_wr    = cmd.max_wr;
-	attr.attr.max_sge   = cmd.max_sge;
-	attr.attr.srq_limit = cmd.srq_limit;
-
-	obj->events_reported     = 0;
-	INIT_LIST_HEAD(&obj->event_list);
-
-	srq = pd->device->create_xrc_srq(pd, xrc_cq, xrcd, &attr, &udata);
-	if (IS_ERR(srq)) {
-		ret = PTR_ERR(srq);
-		goto err_put;
-	}
-
-	srq->device    	   = pd->device;
-	srq->pd        	   = pd;
-	srq->uobject       = &obj->uobject;
-	srq->event_handler = attr.event_handler;
-	srq->srq_context   = attr.srq_context;
-	srq->xrc_cq	   = xrc_cq;
-	srq->xrcd	   = xrcd;
-	atomic_inc(&pd->usecnt);
-	atomic_inc(&xrc_cq->usecnt);
-	atomic_inc(&xrcd->usecnt);
-
-	atomic_set(&srq->usecnt, 0);
-
-	obj->uobject.object = srq;
-	ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uobject);
-	if (ret)
-		goto err_destroy;
-
-	memset(&resp, 0, sizeof resp);
-	resp.srq_handle = obj->uobject.id;
-	resp.max_wr     = attr.attr.max_wr;
-	resp.max_sge    = attr.attr.max_sge;
-
-	if (copy_to_user((void __user *) (unsigned long) cmd.response,
-			 &resp, sizeof resp)) {
-		ret = -EFAULT;
-		goto err_copy;
-	}
-
-	put_xrcd_read(xrcd_uobj);
-	put_cq_read(xrc_cq);
-	put_pd_read(pd);
-
-	mutex_lock(&file->mutex);
-	list_add_tail(&obj->uobject.list, &file->ucontext->srq_list);
-	mutex_unlock(&file->mutex);
-
-	obj->uobject.live = 1;
-
-	up_write(&obj->uobject.mutex);
-
-	return in_len;
-
-err_copy:
-	idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uobject);
-
-err_destroy:
-	ib_destroy_srq(srq);
-
-err_put:
-	put_xrcd_read(xrcd_uobj);
-
-err_put_cq:
-	put_cq_read(xrc_cq);
-
-err_put_pd:
-	put_pd_read(pd);
-
-err:
-	put_uobj_write(&obj->uobject);
-	return ret;
-}
-
 ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
 			     const char __user *buf, int in_len,
 			     int out_len)
@@ -2317,311 +2156,3 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
 
 	return ret ? ret : in_len;
 }
-
-static struct inode * xrc_fd2inode(unsigned int fd)
-{
-	struct file * f = fget(fd);
-
-	if (!f)
-		return NULL;
-
-	return f->f_dentry->d_inode;
-}
-
-struct xrcd_table_entry {
-	struct rb_node node;
-	struct inode * inode;
-	struct ib_xrcd *xrcd;
-};
-
-static int xrcd_table_insert(struct ib_device *dev,
-			     struct inode *i_n,
-			     struct ib_xrcd *xrcd)
-{
-	struct xrcd_table_entry *entry, *scan;
-	struct rb_node **p = &dev->ib_uverbs_xrcd_table.rb_node;
-	struct rb_node *parent = NULL;
-
-	entry = kmalloc(sizeof(struct xrcd_table_entry), GFP_KERNEL);
-	if (!entry)
-		return -ENOMEM;
-
-	entry->inode = i_n;
-	entry->xrcd = xrcd;
-
-	while (*p)
-	{
-		parent = *p;
-		scan = rb_entry(parent, struct xrcd_table_entry, node);
-
-		if (i_n < scan->inode)
-			p = &(*p)->rb_left;
-		else if (i_n > scan->inode)
-			p = &(*p)->rb_right;
-		else {
-			kfree(entry);
-			return -EEXIST;
-		}
-	}
-
-	rb_link_node(&entry->node, parent, p);
-	rb_insert_color(&entry->node, &dev->ib_uverbs_xrcd_table);
-	return 0;
-}
-
-static int insert_xrcd(struct ib_device *dev, struct inode *i_n,
-		       struct ib_xrcd *xrcd)
-{
-	int ret;
-
-	ret = xrcd_table_insert(dev, i_n, xrcd);
-	if (!ret)
-		igrab(i_n);
-
-	return ret;
-}
-
-static struct xrcd_table_entry * xrcd_table_search(struct ib_device *dev,
-						   struct inode *i_n)
-{
-	struct xrcd_table_entry *scan;
-	struct rb_node **p = &dev->ib_uverbs_xrcd_table.rb_node;
-	struct rb_node *parent = NULL;
-
-	while (*p)
-	{
-		parent = *p;
-		scan = rb_entry(parent, struct xrcd_table_entry, node);
-
-		if (i_n < scan->inode)
-			p = &(*p)->rb_left;
-		else if (i_n > scan->inode)
-			p = &(*p)->rb_right;
-		else
-			return scan;
-	}
-	return NULL;
-}
-
-static int find_xrcd(struct ib_device *dev, struct inode *i_n,
-		     struct ib_xrcd **xrcd)
-{
-	struct xrcd_table_entry *entry;
-
-	entry = xrcd_table_search(dev, i_n);
-	if (!entry)
-		return -EINVAL;
-
-	*xrcd = entry->xrcd;
-	return 0;
-}
-
-
-static void xrcd_table_delete(struct ib_device *dev,
-			      struct inode *i_n)
-{
-	struct xrcd_table_entry *entry = xrcd_table_search(dev, i_n);
-
-	if (entry) {
-		iput(i_n);
-		rb_erase(&entry->node, &dev->ib_uverbs_xrcd_table);
-		kfree(entry);
-	}
-}
-
-ssize_t ib_uverbs_open_xrc_domain(struct ib_uverbs_file *file,
-				  const char __user *buf, int in_len,
-				  int out_len)
-{
-	struct ib_uverbs_open_xrc_domain cmd;
-	struct ib_uverbs_open_xrc_domain_resp resp;
-	struct ib_udata			 udata;
-	struct ib_uobject             	*uobj;
-	struct ib_xrcd			*xrcd = NULL;
-	struct inode			*inode = NULL;
-	int				 ret = 0;
-	int				 new_xrcd = 0;
-
-	if (out_len < sizeof resp)
-		return -ENOSPC;
-
-	if (copy_from_user(&cmd, buf, sizeof cmd))
-		return -EFAULT;
-
-	INIT_UDATA(&udata, buf + sizeof cmd,
-		   (unsigned long) cmd.response + sizeof resp,
-		   in_len - sizeof cmd, out_len - sizeof resp);
-
-	mutex_lock(&file->device->ib_dev->xrcd_table_mutex);
-	if (cmd.fd != (u32) (-1)) {
-		/* search for file descriptor */
-		inode = xrc_fd2inode(cmd.fd);
-		if (!inode) {
-			ret = -EBADF;
-			goto err_table_mutex_unlock;
-		}
-
-		ret = find_xrcd(file->device->ib_dev, inode, &xrcd);
-		if (ret && !(cmd.oflags & O_CREAT)) {
-			/* no file descriptor. Need CREATE flag */
-			ret = -EAGAIN;
-			goto err_table_mutex_unlock;
-        	}
-
-        	if (xrcd && cmd.oflags & O_EXCL){
-			ret = -EINVAL;
-			goto err_table_mutex_unlock;
-		}
-	}
-
-	uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
-	if (!uobj) {
-		ret = -ENOMEM;
-		goto err_table_mutex_unlock;
-	}
-
-	init_uobj(uobj, 0, file->ucontext, &pd_lock_key);
-	down_write(&uobj->mutex);
-
-	if (!xrcd) {
-		xrcd = file->device->ib_dev->alloc_xrcd(file->device->ib_dev,
-							file->ucontext, &udata);
-		if (IS_ERR(xrcd)) {
-			ret = PTR_ERR(xrcd);
-			goto err;
-		}
-		xrcd->uobject = (cmd.fd == -1) ? uobj : NULL;
-		xrcd->inode = inode;
-		xrcd->device  = file->device->ib_dev;
-		atomic_set(&xrcd->usecnt, 0);
-		new_xrcd = 1;
-	}
-
-	uobj->object = xrcd;
-	ret = idr_add_uobj(&ib_uverbs_xrc_domain_idr, uobj);
-	if (ret)
-		goto err_idr;
-
-	memset(&resp, 0, sizeof resp);
-	resp.xrcd_handle = uobj->id;
-
-	if (inode) {
-		if (new_xrcd) {
-		/* create new inode/xrcd table entry */
-			ret = insert_xrcd(file->device->ib_dev, inode, xrcd);
-			if (ret)
-				goto err_insert_xrcd;
-		}
-		atomic_inc(&xrcd->usecnt);
-	}
-
-	if (copy_to_user((void __user *) (unsigned long) cmd.response,
-			 &resp, sizeof resp)) {
-		ret = -EFAULT;
-		goto err_copy;
-	}
-
-	mutex_lock(&file->mutex);
-	list_add_tail(&uobj->list, &file->ucontext->xrc_domain_list);
-	mutex_unlock(&file->mutex);
-
-	uobj->live = 1;
-
-	up_write(&uobj->mutex);
-
-	mutex_unlock(&file->device->ib_dev->xrcd_table_mutex);
-	return in_len;
-
-err_copy:
-
-	if (inode) {
-		if (new_xrcd)
-			xrcd_table_delete(file->device->ib_dev, inode);
-		atomic_dec(&xrcd->usecnt);
-	}
-
-err_insert_xrcd:
-	idr_remove_uobj(&ib_uverbs_xrc_domain_idr, uobj);
-
-err_idr:
-	ib_dealloc_xrcd(xrcd);
-
-err:
-	put_uobj_write(uobj);
-
-err_table_mutex_unlock:
-
-	mutex_unlock(&file->device->ib_dev->xrcd_table_mutex);
-	return ret;
-}
-
-ssize_t ib_uverbs_close_xrc_domain(struct ib_uverbs_file *file,
-				   const char __user *buf, int in_len,
-				   int out_len)
-{
-	struct ib_uverbs_close_xrc_domain cmd;
-	struct ib_uobject          *uobj;
-	struct ib_xrcd             *xrcd = NULL;
-	struct inode		   *inode = NULL;
-	int                         ret = 0;
-
-	if (copy_from_user(&cmd, buf, sizeof cmd))
-		return -EFAULT;
-
-	mutex_lock(&file->device->ib_dev->xrcd_table_mutex);
-	uobj = idr_write_uobj(&ib_uverbs_xrc_domain_idr, cmd.xrcd_handle, file->ucontext);
-	if (!uobj) {
-		ret = -EINVAL;
-		goto err_unlock_mutex;
-	}
-
-	xrcd = (struct ib_xrcd *) (uobj->object);
-	inode = xrcd->inode;
-
-	if (inode)
-		atomic_dec(&xrcd->usecnt);
-
-	ret = ib_dealloc_xrcd(uobj->object);
-	if (!ret)
-		uobj->live = 0;
-
-	put_uobj_write(uobj);
-
-	if (ret && !inode)
-		goto err_unlock_mutex;
-
-	if (!ret && inode)
-		xrcd_table_delete(file->device->ib_dev, inode);
-
-	idr_remove_uobj(&ib_uverbs_xrc_domain_idr, uobj);
-
-	mutex_lock(&file->mutex);
-	list_del(&uobj->list);
-	mutex_unlock(&file->mutex);
-
-	put_uobj(uobj);
-
-	mutex_unlock(&file->device->ib_dev->xrcd_table_mutex);
-	return in_len;
-
-err_unlock_mutex:
-	mutex_unlock(&file->device->ib_dev->xrcd_table_mutex);
-	return ret;
-}
-
-void ib_uverbs_dealloc_xrcd(struct ib_device *ib_dev,
-				   struct ib_xrcd *xrcd)
-{
-	struct inode		   *inode = NULL;
-	int                         ret = 0;
-
-	inode = xrcd->inode;
-	if (inode)
-		atomic_dec(&xrcd->usecnt);
-
-	ret = ib_dealloc_xrcd(xrcd);
-	if (!ret && inode)
-		xrcd_table_delete(ib_dev, inode);
-}
-
-
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index d9b0818..cfa567b 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -74,7 +74,6 @@ DEFINE_IDR(ib_uverbs_ah_idr);
 DEFINE_IDR(ib_uverbs_cq_idr);
 DEFINE_IDR(ib_uverbs_qp_idr);
 DEFINE_IDR(ib_uverbs_srq_idr);
-DEFINE_IDR(ib_uverbs_xrc_domain_idr);
 
 static spinlock_t map_lock;
 static struct ib_uverbs_device *dev_table[IB_UVERBS_MAX_DEVICES];
@@ -111,9 +110,6 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
 	[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_XRC_SRQ]	= ib_uverbs_create_xrc_srq,
-	[IB_USER_VERBS_CMD_OPEN_XRC_DOMAIN]	= ib_uverbs_open_xrc_domain,
-	[IB_USER_VERBS_CMD_CLOSE_XRC_DOMAIN]	= ib_uverbs_close_xrc_domain,
 };
 
 static struct vfsmount *uverbs_event_mnt;
@@ -217,18 +213,6 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
 		kfree(uqp);
 	}
 
-
-	list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
-		struct ib_srq *srq = uobj->object;
-		struct ib_uevent_object *uevent =
-			container_of(uobj, struct ib_uevent_object, uobject);
-
-		idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
-		ib_destroy_srq(srq);
-		ib_uverbs_release_uevent(file, uevent);
-		kfree(uevent);
-	}
-
 	list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
 		struct ib_cq *cq = uobj->object;
 		struct ib_uverbs_event_file *ev_file = cq->cq_context;
@@ -241,6 +225,17 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
 		kfree(ucq);
 	}
 
+	list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
+		struct ib_srq *srq = uobj->object;
+		struct ib_uevent_object *uevent =
+			container_of(uobj, struct ib_uevent_object, uobject);
+
+		idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
+		ib_destroy_srq(srq);
+		ib_uverbs_release_uevent(file, uevent);
+		kfree(uevent);
+	}
+
 	/* XXX Free MWs */
 
 	list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
@@ -251,16 +246,6 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
 		kfree(uobj);
 	}
 
-	mutex_lock(&file->device->ib_dev->xrcd_table_mutex);
-	list_for_each_entry_safe(uobj, tmp, &context->xrc_domain_list, list) {
-		struct ib_xrcd *xrcd = uobj->object;
-
-		idr_remove_uobj(&ib_uverbs_xrc_domain_idr, uobj);
-		ib_uverbs_dealloc_xrcd(file->device->ib_dev, xrcd);
-		kfree(uobj);
-	}
-	mutex_unlock(&file->device->ib_dev->xrcd_table_mutex);
-
 	list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
 		struct ib_pd *pd = uobj->object;
 
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 5e2eb58..84709ed 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -236,8 +236,6 @@ struct ib_srq *ib_create_srq(struct ib_pd *pd,
 		srq->uobject       = NULL;
 		srq->event_handler = srq_init_attr->event_handler;
 		srq->srq_context   = srq_init_attr->srq_context;
-		srq->xrc_cq = NULL;
-		srq->xrcd = NULL;
 		atomic_inc(&pd->usecnt);
 		atomic_set(&srq->usecnt, 0);
 	}
@@ -246,36 +244,6 @@ struct ib_srq *ib_create_srq(struct ib_pd *pd,
 }
 EXPORT_SYMBOL(ib_create_srq);
 
-struct ib_srq *ib_create_xrc_srq(struct ib_pd *pd,
-				 struct ib_cq *xrc_cq,
-				 struct ib_xrcd *xrcd,
-				 struct ib_srq_init_attr *srq_init_attr)
-{
-	struct ib_srq *srq;
-
-	if (!pd->device->create_xrc_srq)
-		return ERR_PTR(-ENOSYS);
-
-	srq = pd->device->create_xrc_srq(pd, xrc_cq, xrcd, srq_init_attr, NULL);
-
-	if (!IS_ERR(srq)) {
-		srq->device	   = pd->device;
-		srq->pd		   = pd;
-		srq->uobject	   = NULL;
-		srq->event_handler = srq_init_attr->event_handler;
-		srq->srq_context   = srq_init_attr->srq_context;
-		srq->xrc_cq	   = xrc_cq;
-		srq->xrcd	   = xrcd;
-		atomic_inc(&pd->usecnt);
-		atomic_inc(&xrcd->usecnt);
-		atomic_inc(&xrc_cq->usecnt);
-		atomic_set(&srq->usecnt, 0);
-	}
-
-	return srq;
-}
-EXPORT_SYMBOL(ib_create_xrc_srq);
-
 int ib_modify_srq(struct ib_srq *srq,
 		  struct ib_srq_attr *srq_attr,
 		  enum ib_srq_attr_mask srq_attr_mask)
@@ -295,25 +263,16 @@ EXPORT_SYMBOL(ib_query_srq);
 int ib_destroy_srq(struct ib_srq *srq)
 {
 	struct ib_pd *pd;
-	struct ib_cq *xrc_cq;
-	struct ib_xrcd *xrcd;
 	int ret;
 
 	if (atomic_read(&srq->usecnt))
 		return -EBUSY;
 
 	pd = srq->pd;
-	xrc_cq = srq->xrc_cq;
-	xrcd = srq->xrcd;
 
 	ret = srq->device->destroy_srq(srq);
-	if (!ret) {
+	if (!ret)
 		atomic_dec(&pd->usecnt);
-		if (xrc_cq)
-			atomic_dec(&xrc_cq->usecnt);
-		if (xrcd)
-			atomic_dec(&xrcd->usecnt);
-	}
 
 	return ret;
 }
@@ -338,15 +297,11 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
 		qp->event_handler = qp_init_attr->event_handler;
 		qp->qp_context    = qp_init_attr->qp_context;
 		qp->qp_type	  = qp_init_attr->qp_type;
-		qp->xrcd	  = qp->qp_type == IB_QPT_XRC ?
-			qp_init_attr->xrc_domain : NULL;
 		atomic_inc(&pd->usecnt);
 		atomic_inc(&qp_init_attr->send_cq->usecnt);
 		atomic_inc(&qp_init_attr->recv_cq->usecnt);
 		if (qp_init_attr->srq)
 			atomic_inc(&qp_init_attr->srq->usecnt);
-		if (qp->qp_type == IB_QPT_XRC)
-			atomic_inc(&qp->xrcd->usecnt);
 	}
 
 	return qp;
@@ -373,9 +328,6 @@ static const struct {
 				[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
 						IB_QP_PORT			|
 						IB_QP_ACCESS_FLAGS),
-				[IB_QPT_XRC] = (IB_QP_PKEY_INDEX		|
-						IB_QP_PORT			|
-						IB_QP_ACCESS_FLAGS),
 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -398,9 +350,6 @@ static const struct {
 				[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
 						IB_QP_PORT			|
 						IB_QP_ACCESS_FLAGS),
-				[IB_QPT_XRC] = (IB_QP_PKEY_INDEX		|
-						IB_QP_PORT			|
-						IB_QP_ACCESS_FLAGS),
 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -420,12 +369,6 @@ static const struct {
 						IB_QP_RQ_PSN			|
 						IB_QP_MAX_DEST_RD_ATOMIC	|
 						IB_QP_MIN_RNR_TIMER),
-				[IB_QPT_XRC] = (IB_QP_AV			|
-						IB_QP_PATH_MTU			|
-						IB_QP_DEST_QPN			|
-						IB_QP_RQ_PSN			|
-						IB_QP_MAX_DEST_RD_ATOMIC	|
-						IB_QP_MIN_RNR_TIMER),
 			},
 			.opt_param = {
 				 [IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
@@ -436,9 +379,6 @@ static const struct {
 				 [IB_QPT_RC]  = (IB_QP_ALT_PATH			|
 						 IB_QP_ACCESS_FLAGS		|
 						 IB_QP_PKEY_INDEX),
-				 [IB_QPT_XRC] = (IB_QP_ALT_PATH			|
-						IB_QP_ACCESS_FLAGS		|
-						IB_QP_PKEY_INDEX),
 				 [IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						 IB_QP_QKEY),
 				 [IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -459,11 +399,6 @@ static const struct {
 						IB_QP_RNR_RETRY			|
 						IB_QP_SQ_PSN			|
 						IB_QP_MAX_QP_RD_ATOMIC),
-				[IB_QPT_XRC] = (IB_QP_TIMEOUT			|
-						IB_QP_RETRY_CNT			|
-						IB_QP_RNR_RETRY			|
-						IB_QP_SQ_PSN			|
-						IB_QP_MAX_QP_RD_ATOMIC),
 				[IB_QPT_SMI] = IB_QP_SQ_PSN,
 				[IB_QPT_GSI] = IB_QP_SQ_PSN,
 			},
@@ -479,11 +414,6 @@ static const struct {
 						 IB_QP_ACCESS_FLAGS		|
 						 IB_QP_MIN_RNR_TIMER		|
 						 IB_QP_PATH_MIG_STATE),
-				 [IB_QPT_XRC] = (IB_QP_CUR_STATE		|
-						IB_QP_ALT_PATH			|
-						IB_QP_ACCESS_FLAGS		|
-						IB_QP_MIN_RNR_TIMER		|
-						IB_QP_PATH_MIG_STATE),
 				 [IB_QPT_SMI] = (IB_QP_CUR_STATE		|
 						 IB_QP_QKEY),
 				 [IB_QPT_GSI] = (IB_QP_CUR_STATE		|
@@ -508,11 +438,6 @@ static const struct {
 						IB_QP_ALT_PATH			|
 						IB_QP_PATH_MIG_STATE		|
 						IB_QP_MIN_RNR_TIMER),
-				[IB_QPT_XRC] = (IB_QP_CUR_STATE			|
-						IB_QP_ACCESS_FLAGS		|
-						IB_QP_ALT_PATH			|
-						IB_QP_PATH_MIG_STATE		|
-						IB_QP_MIN_RNR_TIMER),
 				[IB_QPT_SMI] = (IB_QP_CUR_STATE			|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
@@ -525,7 +450,6 @@ static const struct {
 				[IB_QPT_UD]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
 				[IB_QPT_UC]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
 				[IB_QPT_RC]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
-				[IB_QPT_XRC] = IB_QP_EN_SQD_ASYNC_NOTIFY,
 				[IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
 				[IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY
 			}
@@ -548,11 +472,6 @@ static const struct {
 						IB_QP_ACCESS_FLAGS		|
 						IB_QP_MIN_RNR_TIMER		|
 						IB_QP_PATH_MIG_STATE),
-				[IB_QPT_XRC] = (IB_QP_CUR_STATE			|
-						IB_QP_ALT_PATH			|
-						IB_QP_ACCESS_FLAGS		|
-						IB_QP_MIN_RNR_TIMER		|
-						IB_QP_PATH_MIG_STATE),
 				[IB_QPT_SMI] = (IB_QP_CUR_STATE			|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
@@ -581,18 +500,6 @@ static const struct {
 						IB_QP_PKEY_INDEX		|
 						IB_QP_MIN_RNR_TIMER		|
 						IB_QP_PATH_MIG_STATE),
-				[IB_QPT_XRC] = (IB_QP_PORT			|
-						IB_QP_AV			|
-						IB_QP_TIMEOUT			|
-						IB_QP_RETRY_CNT			|
-						IB_QP_RNR_RETRY			|
-						IB_QP_MAX_QP_RD_ATOMIC		|
-						IB_QP_MAX_DEST_RD_ATOMIC	|
-						IB_QP_ALT_PATH			|
-						IB_QP_ACCESS_FLAGS		|
-						IB_QP_PKEY_INDEX		|
-						IB_QP_MIN_RNR_TIMER		|
-						IB_QP_PATH_MIG_STATE),
 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -677,15 +584,12 @@ int ib_destroy_qp(struct ib_qp *qp)
 	struct ib_pd *pd;
 	struct ib_cq *scq, *rcq;
 	struct ib_srq *srq;
-	struct ib_xrcd *xrcd;
-	enum ib_qp_type	qp_type = qp->qp_type;
 	int ret;
 
 	pd  = qp->pd;
 	scq = qp->send_cq;
 	rcq = qp->recv_cq;
 	srq = qp->srq;
-	xrcd = qp->xrcd;
 
 	ret = qp->device->destroy_qp(qp);
 	if (!ret) {
@@ -694,8 +598,6 @@ int ib_destroy_qp(struct ib_qp *qp)
 		atomic_dec(&rcq->usecnt);
 		if (srq)
 			atomic_dec(&srq->usecnt);
-		if (qp_type == IB_QPT_XRC)
-			atomic_dec(&xrcd->usecnt);
 	}
 
 	return ret;
@@ -954,32 +856,3 @@ int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
 	return qp->device->detach_mcast(qp, gid, lid);
 }
 EXPORT_SYMBOL(ib_detach_mcast);
-
-int ib_dealloc_xrcd(struct ib_xrcd *xrcd)
-{
-	if (atomic_read(&xrcd->usecnt))
-		return -EBUSY;
-
-	return xrcd->device->dealloc_xrcd(xrcd);
-}
-EXPORT_SYMBOL(ib_dealloc_xrcd);
-
-struct ib_xrcd * ib_alloc_xrcd(struct ib_device *device)
-{
-	struct ib_xrcd *xrcd;
-
-	if (!device->alloc_xrcd)
-		return ERR_PTR(-ENOSYS);
-
-	xrcd = device->alloc_xrcd(device, NULL, NULL);
-	if (!IS_ERR(xrcd)) {
-		xrcd->device = device;
-		xrcd->inode = NULL;
-		xrcd->uobject = NULL;
-		atomic_set(&xrcd->usecnt, 0);
-	}
-	return xrcd;
-}
-EXPORT_SYMBOL(ib_alloc_xrcd);
-
-
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index 300f14d..b730afa 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -32,7 +32,6 @@
 
 #include <linux/mlx4/cq.h>
 #include <linux/mlx4/qp.h>
-#include <linux/mlx4/srq.h>
 
 #include "mlx4_ib.h"
 #include "user.h"
@@ -121,8 +120,10 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
 	int buf_size;
 	int err;
 
-	if (entries < 1 || entries > dev->dev->caps.max_cqes)
+	if (entries < 1 || entries > dev->dev->caps.max_cqes) {
+		mlx4_ib_dbg("invalid num of entries: %d", entries);
 		return ERR_PTR(-EINVAL);
+	}
 
 	cq = kmalloc(sizeof *cq, GFP_KERNEL);
 	if (!cq)
@@ -331,11 +332,15 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
 	struct mlx4_qp *mqp;
 	struct mlx4_ib_wq *wq;
 	struct mlx4_ib_srq *srq;
-	struct mlx4_srq *msrq;
 	int is_send;
 	int is_error;
-	int is_xrc_recv = 0;
 	u16 wqe_ctr;
+	u32 g_mlpath_rqpn;
+	__be32 status;
+
+#define CSUM_MASK_BITS cpu_to_be32(0x13c00000)
+#define CSUM_VAL_BITS  cpu_to_be32(0x10400000)
+#define CSUM_MASK2_BITS cpu_to_be32(0x0c000000)
 
 	cqe = next_cqe_sw(cq);
 	if (!cqe)
@@ -359,23 +364,7 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
 		return -EINVAL;
 	}
 
-	if ((be32_to_cpu(cqe->my_qpn) & (1 << 23)) && !is_send) {
-		 /*
-		  * We do not have to take the XRC SRQ table lock here,
-		  * because CQs will be locked while XRC SRQs are removed
-		  * from the table.
-		  */
-		 msrq = __mlx4_srq_lookup(to_mdev(cq->ibcq.device)->dev,
-					 be32_to_cpu(cqe->g_mlpath_rqpn) &
-					 0xffffff);
-		 if (unlikely(!msrq)) {
-			 printk(KERN_WARNING "CQ %06x with entry for unknown XRC SRQ %06x\n",
-				cq->mcq.cqn, be32_to_cpu(cqe->g_mlpath_rqpn) & 0xffffff);
-			 return -EINVAL;
-		 }
-		 is_xrc_recv = 1;
-		 srq = to_mibsrq(msrq);
-	} else if (!*cur_qp ||
+	if (!*cur_qp ||
 	    (be32_to_cpu(cqe->my_qpn) & 0xffffff) != (*cur_qp)->mqp.qpn) {
 		/*
 		 * We do not have to take the QP table lock here,
@@ -393,7 +382,7 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
 		*cur_qp = to_mibqp(mqp);
 	}
 
-	wc->qp = is_xrc_recv ? NULL: &(*cur_qp)->ibqp;
+	wc->qp = &(*cur_qp)->ibqp;
 
 	if (is_send) {
 		wq = &(*cur_qp)->sq;
@@ -403,10 +392,6 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
 		}
 		wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];
 		++wq->tail;
-	} else if (is_xrc_recv) {
-		wqe_ctr = be16_to_cpu(cqe->wqe_index);
-		wc->wr_id = srq->wrid[wqe_ctr];
-		mlx4_ib_free_srq_wqe(srq, wqe_ctr);
 	} else if ((*cur_qp)->ibqp.srq) {
 		srq = to_msrq((*cur_qp)->ibqp.srq);
 		wqe_ctr = be16_to_cpu(cqe->wqe_index);
@@ -479,13 +464,16 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
 
 		wc->slid	   = be16_to_cpu(cqe->rlid);
 		wc->sl		   = cqe->sl >> 4;
-		wc->src_qp	   = be32_to_cpu(cqe->g_mlpath_rqpn) & 0xffffff;
-		wc->dlid_path_bits = (be32_to_cpu(cqe->g_mlpath_rqpn) >> 24) & 0x7f;
-		wc->wc_flags      |= be32_to_cpu(cqe->g_mlpath_rqpn) & 0x80000000 ?
+		g_mlpath_rqpn	   = be32_to_cpu(cqe->g_mlpath_rqpn);
+		wc->src_qp	   = g_mlpath_rqpn & 0xffffff;
+		wc->dlid_path_bits = (g_mlpath_rqpn >> 24) & 0x7f;
+		wc->wc_flags      |= g_mlpath_rqpn & 0x80000000 ?
 			IB_WC_GRH : 0;
-		wc->pkey_index     = (u16) be32_to_cpu(cqe->immed_rss_invalid);
-		wc->csum_ok   = be32_to_cpu(cqe->ipoib_status) & 0x10000000 &&
-				be16_to_cpu(cqe->checksum) == 0xffff;
+		wc->pkey_index     = be32_to_cpu(cqe->immed_rss_invalid) & 0x7f;
+ 		status = cqe->ipoib_status;
+ 		wc->csum_ok = (status & CSUM_MASK_BITS) == CSUM_VAL_BITS &&
+ 			      (status & CSUM_MASK2_BITS) &&
+ 			      cqe->checksum == 0xffff;
 	}
 
 	return 0;
@@ -535,10 +523,6 @@ void __mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq)
 	int nfreed = 0;
 	struct mlx4_cqe *cqe, *dest;
 	u8 owner_bit;
-	int is_xrc_srq = 0;
-
-	if (srq && srq->ibsrq.xrc_cq)
-		is_xrc_srq = 1;
 
 	/*
 	 * First we need to find the current producer index, so we
@@ -557,9 +541,7 @@ void __mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq)
 	 */
 	while ((int) --prod_index - (int) cq->mcq.cons_index >= 0) {
 		cqe = get_cqe(cq, prod_index & cq->ibcq.cqe);
-		if (((be32_to_cpu(cqe->my_qpn) & 0xffffff) == qpn) ||
-		    (is_xrc_srq &&
-		     (be32_to_cpu(cqe->g_mlpath_rqpn) & 0xffffff) == srq->msrq.srqn)) {
+		if ((be32_to_cpu(cqe->my_qpn) & 0xffffff) == qpn) {
 			if (srq && !(cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK))
 				mlx4_ib_free_srq_wqe(srq, be16_to_cpu(cqe->wqe_index));
 			++nfreed;
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index f03025c..2d9c39a 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -44,15 +44,23 @@
 #include "user.h"
 #include "wc.h"
 
-#define DRV_NAME	"mlx4_ib"
-#define DRV_VERSION	"0.01"
-#define DRV_RELDATE	"May 1, 2006"
+#define DRV_NAME	MLX4_IB_DRV_NAME
+#define DRV_VERSION	"1.0"
+#define DRV_RELDATE	"February 28, 2008"
 
 MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 
+#ifdef CONFIG_MLX4_DEBUG
+
+int mlx4_ib_debug_level = 0;
+module_param_named(debug_level, mlx4_ib_debug_level, int, 0644);
+MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
+
+#endif /* CONFIG_MLX4_DEBUG */
+
 static const char mlx4_ib_version[] __devinitdata =
 	DRV_NAME ": Mellanox ConnectX InfiniBand driver v"
 	DRV_VERSION " (" DRV_RELDATE ")\n";
@@ -104,8 +112,6 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
 		props->device_cap_flags |= IB_DEVICE_IP_CSUM;
 	if (dev->dev->caps.max_gso_sz)
 		props->device_cap_flags |= IB_DEVICE_TCP_TSO;
-	if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)
-		props->device_cap_flags |= IB_DEVICE_XRC;
 
 	props->vendor_id	   = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
 		0xffffff;
@@ -449,46 +455,6 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 				     &to_mqp(ibqp)->mqp, gid->raw);
 }
 
-static struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev,
-					  struct ib_ucontext *context,
-					  struct ib_udata *udata)
-{
-	struct mlx4_ib_xrcd *xrcd;
-	struct mlx4_ib_dev *mdev = to_mdev(ibdev);
-	int err;
-
-	if (!(mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
-		return ERR_PTR(-ENOSYS);
-
-	xrcd = kmalloc(sizeof *xrcd, GFP_KERNEL);
-	if (!xrcd)
-		return ERR_PTR(-ENOMEM);
-
-	err = mlx4_xrcd_alloc(mdev->dev, &xrcd->xrcdn);
-	if (err) {
-		kfree(xrcd);
-		return ERR_PTR(err);
-	}
-
-	if (context)
-		if (ib_copy_to_udata(udata, &xrcd->xrcdn, sizeof (__u32))) {
-			mlx4_xrcd_free(mdev->dev, xrcd->xrcdn);
-			kfree(xrcd);
-			return ERR_PTR(-EFAULT);
-		}
-
-	return &xrcd->ibxrcd;
-}
-
-static int mlx4_ib_dealloc_xrcd(struct ib_xrcd *xrcd)
-{
-	mlx4_xrcd_free(to_mdev(xrcd->device)->dev, to_mxrcd(xrcd)->xrcdn);
-	kfree(xrcd);
-
-	return 0;
-}
-
-
 static int init_node_data(struct mlx4_ib_dev *dev)
 {
 	struct ib_smp *in_mad  = NULL;
@@ -515,6 +481,7 @@ static int init_node_data(struct mlx4_ib_dev *dev)
 	if (err)
 		goto out;
 
+	dev->dev->rev_id = be32_to_cpup((__be32 *) (out_mad->data + 32));
 	memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
 
 out:
@@ -561,6 +528,155 @@ static struct class_device_attribute *mlx4_class_attributes[] = {
 	&class_device_attr_board_id
 };
 
+/*
+ * create 2 functions (show, store) and a class_device_attribute struct
+ * pointing to the functions for _name
+ */
+#define CLASS_DEVICE_DIAG_CLR_RPRT_ATTR(_name, _offset, _in_mod)		\
+static ssize_t store_rprt_##_name(struct class_device *cdev, 			\
+				  const char *buf, size_t length) {		\
+	return store_diag_rprt(cdev, buf, length, _offset, _in_mod);		\
+}										\
+static ssize_t show_rprt_##_name(struct class_device *cdev, char *buf) {	\
+	return show_diag_rprt(cdev, buf, _offset, _in_mod);			\
+}										\
+static CLASS_DEVICE_ATTR(_name, S_IRUGO | S_IWUGO, 				\
+	show_rprt_##_name, store_rprt_##_name);
+
+/*
+ * create show function and a class_device_attribute struct pointing to
+ * the function for _name
+ */
+#define CLASS_DEVICE_DIAG_RPRT_ATTR(_name, _offset, _in_mod)			\
+static ssize_t show_rprt_##_name(struct class_device *cdev, char *buf){		\
+	return show_diag_rprt(cdev, buf, _offset, _in_mod);			\
+}										\
+static CLASS_DEVICE_ATTR(_name, S_IRUGO, show_rprt_##_name, NULL);
+
+static ssize_t show_diag_rprt(struct class_device *cdev, char *buf,
+                              int offset, int in_mod)
+{
+	size_t ret = -1;
+	u32 counter_offset = offset;
+	u32 diag_counter = 0;
+	struct mlx4_ib_dev *dev = container_of(cdev, struct mlx4_ib_dev,
+					       ib_dev.class_dev);
+	/* clear counters file, can't read it */
+	if(offset < 0)
+		return sprintf(buf,"This file is write only\n");
+
+	ret = mlx4_query_diag_counters(dev->dev, 1, in_mod, &counter_offset,
+			 	       &diag_counter);
+	if (ret < 0)
+	{
+		sprintf(buf,"Operation failed\n");
+		return ret;
+	}
+
+	return sprintf(buf,"%d\n", diag_counter);
+}
+
+/* the store function is used for counter clear */
+static ssize_t store_diag_rprt(struct class_device *cdev,
+			       const char *buf, size_t length,
+			       int offset, int in_mod)
+{
+	size_t ret = -1;
+	u32 counter_offset = 0;
+	u32 diag_counter;
+	struct mlx4_ib_dev *dev = container_of(cdev, struct mlx4_ib_dev,
+					       ib_dev.class_dev);
+
+	ret = mlx4_query_diag_counters(dev->dev, 1, in_mod, &counter_offset,
+				       &diag_counter);
+	if (ret)
+		return ret;
+
+	return length;
+}
+
+CLASS_DEVICE_DIAG_RPRT_ATTR(rq_num_lle		  , 0x00, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_lle		  , 0x04, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(rq_num_lqpoe	  , 0x08, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_lqpoe 	  , 0x0C, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(rq_num_leeoe	  , 0x10, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_leeoe	  , 0x14, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(rq_num_lpe		  , 0x18, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_lpe		  , 0x1C, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(rq_num_wrfe		  , 0x20, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_wrfe		  , 0x24, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_mwbe		  , 0x2C, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_bre		  , 0x34, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(rq_num_lae		  , 0x38, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_rire		  , 0x44, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(rq_num_rire		  , 0x48, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_rae		  , 0x4C, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(rq_num_rae		  , 0x50, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_roe		  , 0x54, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_tree		  , 0x5C, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_rree		  , 0x64, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(rq_num_rnr		  , 0x68, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_rnr		  , 0x6C, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_rabrte	  , 0x7C, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_ieecne	  , 0x84, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_ieecse	  , 0x8C, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(rq_num_oos		  , 0x100, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_oos		  , 0x104, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(rq_num_mce		  , 0x108, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(rq_num_rsync	  , 0x110, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(sq_num_rsync	  , 0x114, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(rq_num_udsdprd	  , 0x118, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(rq_num_ucsdprd	  , 0x120, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(num_cqovf	  	  , 0x1A0, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(num_eqovf		  , 0x1A4, 2);
+CLASS_DEVICE_DIAG_RPRT_ATTR(num_baddb		  , 0x1A8, 2);
+CLASS_DEVICE_DIAG_CLR_RPRT_ATTR(clear_diag	  , -1   , 3);
+
+static struct attribute *diag_rprt_attrs[] = {
+	&class_device_attr_rq_num_lle.attr,
+	&class_device_attr_sq_num_lle.attr,
+	&class_device_attr_rq_num_lqpoe.attr,
+	&class_device_attr_sq_num_lqpoe.attr,
+	&class_device_attr_rq_num_leeoe.attr,
+	&class_device_attr_sq_num_leeoe.attr,
+	&class_device_attr_rq_num_lpe.attr,
+	&class_device_attr_sq_num_lpe.attr,
+	&class_device_attr_rq_num_wrfe.attr,
+	&class_device_attr_sq_num_wrfe.attr,
+	&class_device_attr_sq_num_mwbe.attr,
+	&class_device_attr_sq_num_bre.attr,
+	&class_device_attr_rq_num_lae.attr,
+	&class_device_attr_sq_num_rire.attr,
+	&class_device_attr_rq_num_rire.attr,
+	&class_device_attr_sq_num_rae.attr,
+	&class_device_attr_rq_num_rae.attr,
+	&class_device_attr_sq_num_roe.attr,
+	&class_device_attr_sq_num_tree.attr,
+	&class_device_attr_sq_num_rree.attr,
+	&class_device_attr_rq_num_rnr.attr,
+	&class_device_attr_sq_num_rnr.attr,
+	&class_device_attr_sq_num_rabrte.attr,
+	&class_device_attr_sq_num_ieecne.attr,
+	&class_device_attr_sq_num_ieecse.attr,
+	&class_device_attr_rq_num_oos.attr,
+	&class_device_attr_sq_num_oos.attr,
+	&class_device_attr_rq_num_mce.attr,
+	&class_device_attr_rq_num_rsync.attr,
+	&class_device_attr_sq_num_rsync.attr,
+	&class_device_attr_rq_num_udsdprd.attr,
+	&class_device_attr_rq_num_ucsdprd.attr,
+	&class_device_attr_num_cqovf.attr,
+	&class_device_attr_num_eqovf.attr,
+	&class_device_attr_num_baddb.attr,
+	&class_device_attr_clear_diag.attr,
+	NULL
+};
+
+static struct attribute_group diag_counters_group = {
+	.name  = "diag_counters",
+	.attrs  = diag_rprt_attrs
+};
+
 static void *mlx4_ib_add(struct mlx4_dev *dev)
 {
 	struct mlx4_ib_dev *ibdev;
@@ -659,16 +775,6 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
 	ibdev->ib_dev.map_phys_fmr	= mlx4_ib_map_phys_fmr;
 	ibdev->ib_dev.unmap_fmr		= mlx4_ib_unmap_fmr;
 	ibdev->ib_dev.dealloc_fmr	= mlx4_ib_fmr_dealloc;
-	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) {
-		ibdev->ib_dev.create_xrc_srq = mlx4_ib_create_xrc_srq;
-		ibdev->ib_dev.alloc_xrcd = mlx4_ib_alloc_xrcd;
-		ibdev->ib_dev.dealloc_xrcd = mlx4_ib_dealloc_xrcd;
-		ibdev->ib_dev.uverbs_cmd_mask |=
-			(1ull << IB_USER_VERBS_CMD_CREATE_XRC_SRQ)	|
-			(1ull << IB_USER_VERBS_CMD_OPEN_XRC_DOMAIN)	|
-			(1ull << IB_USER_VERBS_CMD_CLOSE_XRC_DOMAIN);
-	}
-
 
 	if (ibdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM)
 		ibdev->ib_dev.flags |= IB_DEVICE_IP_CSUM;
@@ -693,8 +799,14 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
 			goto err_reg;
 	}
 
+	if(sysfs_create_group(&ibdev->ib_dev.class_dev.kobj, &diag_counters_group))
+		goto err_diag;
+
 	return ibdev;
 
+err_diag:
+	ib_unregister_device(&ibdev->ib_dev);
+
 err_reg:
 	ib_unregister_device(&ibdev->ib_dev);
 
@@ -718,6 +830,8 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
 	struct mlx4_ib_dev *ibdev = ibdev_ptr;
 	int p;
 
+	sysfs_remove_group(&ibdev->ib_dev.class_dev.kobj, &diag_counters_group);
+
 	for (p = 1; p <= dev->caps.num_ports; ++p)
 		mlx4_CLOSE_PORT(dev, p);
 
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 53a377d..f86a19d 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -43,6 +43,25 @@
 #include <linux/mlx4/device.h>
 #include <linux/mlx4/doorbell.h>
 
+
+#define MLX4_IB_DRV_NAME	"mlx4_ib"
+
+#ifdef CONFIG_MLX4_DEBUG
+extern int mlx4_ib_debug_level;
+
+#define mlx4_ib_dbg(format, arg...) 		\
+	do {					\
+		if (mlx4_ib_debug_level) 	\
+			printk(KERN_DEBUG "<" MLX4_IB_DRV_NAME "> %s: " format "\n",\
+			__func__, ## arg);	\
+	} while (0)
+
+#else /* CONFIG_MLX4_DEBUG */
+
+#define mlx4_ib_dbg(format, arg...) do {} while (0)
+
+#endif /* CONFIG_MLX4_DEBUG */
+
 enum {
 	MLX4_IB_DB_PER_PAGE	= PAGE_SIZE / 4
 };
@@ -80,11 +99,6 @@ struct mlx4_ib_pd {
 	u32			pdn;
 };
 
-struct mlx4_ib_xrcd {
-	struct ib_xrcd	ibxrcd;
-	u32		xrcdn;
-};
-
 struct mlx4_ib_cq_buf {
 	struct mlx4_buf		buf;
 	struct mlx4_mtt		mtt;
@@ -122,6 +136,10 @@ struct mlx4_ib_wq {
 	unsigned		tail;
 };
 
+enum qp_flags {
+	MLX4_QP_LSO = 1 << 0
+};
+
 struct mlx4_ib_qp {
 	struct ib_qp		ibqp;
 	struct mlx4_qp		mqp;
@@ -141,13 +159,13 @@ struct mlx4_ib_qp {
 	struct mlx4_mtt		mtt;
 	int			buf_size;
 	struct mutex		mutex;
-	u16			xrcdn;
 	u8			port;
 	u8			alt_port;
 	u8			atomic_rd_en;
 	u8			resp_depth;
 	u8			sq_no_prefetch;
 	u8			state;
+	int			flags;
 };
 
 struct mlx4_ib_srq {
@@ -204,11 +222,6 @@ static inline struct mlx4_ib_pd *to_mpd(struct ib_pd *ibpd)
 	return container_of(ibpd, struct mlx4_ib_pd, ibpd);
 }
 
-static inline struct mlx4_ib_xrcd *to_mxrcd(struct ib_xrcd *ibxrcd)
-{
-	return container_of(ibxrcd, struct mlx4_ib_xrcd, ibxrcd);
-}
-
 static inline struct mlx4_ib_cq *to_mcq(struct ib_cq *ibcq)
 {
 	return container_of(ibcq, struct mlx4_ib_cq, ibcq);
@@ -284,11 +297,6 @@ int mlx4_ib_destroy_ah(struct ib_ah *ah);
 struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
 				  struct ib_srq_init_attr *init_attr,
 				  struct ib_udata *udata);
-struct ib_srq *mlx4_ib_create_xrc_srq(struct ib_pd *pd,
-				      struct ib_cq *xrc_cq,
-				      struct ib_xrcd *xrcd,
-				      struct ib_srq_init_attr *init_attr,
-				      struct ib_udata *udata);
 int mlx4_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
 		       enum ib_srq_attr_mask attr_mask, struct ib_udata *udata);
 int mlx4_ib_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c
index 7dc91a3..fe2c2e9 100644
--- a/drivers/infiniband/hw/mlx4/mr.c
+++ b/drivers/infiniband/hw/mlx4/mr.c
@@ -199,7 +199,7 @@ struct ib_fmr *mlx4_ib_fmr_alloc(struct ib_pd *pd, int acc,
 	if (err)
 		goto err_free;
 
-	err = mlx4_mr_enable(to_mdev(pd->device)->dev, &fmr->mfmr.mr);
+	err = mlx4_fmr_enable(to_mdev(pd->device)->dev, &fmr->mfmr);
 	if (err)
 		goto err_mr;
 
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index ec66e7d..21580ab 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -132,9 +132,10 @@ static void stamp_send_wqe(struct mlx4_ib_qp *qp, int n, int size)
 	int ind;
 	void *buf;
 	__be32 stamp;
+	struct mlx4_wqe_ctrl_seg *ctrl;
 
-	s = roundup(size, 1 << qp->sq.wqe_shift);
 	if (qp->sq_max_wqes_per_wr > 1) {
+		s = roundup(size, 1 << qp->sq.wqe_shift);
 		for (i = 0; i < s; i += 64) {
 			ind = (i >> qp->sq.wqe_shift) + n;
 			stamp = ind & qp->sq.wqe_cnt ?  cpu_to_be32(0x7fffffff) :
@@ -144,7 +145,8 @@ static void stamp_send_wqe(struct mlx4_ib_qp *qp, int n, int size)
 			*wqe = stamp;
 		}
 	} else {
-		buf = get_send_wqe(qp, n & (qp->sq.wqe_cnt - 1));
+		ctrl = buf = get_send_wqe(qp, n & (qp->sq.wqe_cnt - 1));
+		s = (ctrl->fence_size & 0x3f) << 4;
 		for (i = 64; i < s; i += 64) {
 			wqe = buf + i;
 			*wqe = 0xffffffff;
@@ -262,7 +264,6 @@ static int send_wqe_overhead(enum ib_qp_type type)
 	case IB_QPT_UC:
 		return sizeof (struct mlx4_wqe_ctrl_seg) +
 			sizeof (struct mlx4_wqe_raddr_seg);
-	case IB_QPT_XRC:
 	case IB_QPT_RC:
 		return sizeof (struct mlx4_wqe_ctrl_seg) +
 			sizeof (struct mlx4_wqe_atomic_seg) +
@@ -284,24 +285,32 @@ static int send_wqe_overhead(enum ib_qp_type type)
 }
 
 static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
-		       int is_user, int has_srq_or_is_xrc, struct mlx4_ib_qp *qp)
+		       int is_user, int has_srq, struct mlx4_ib_qp *qp)
 {
 	/* Sanity check RQ size before proceeding */
 	if (cap->max_recv_wr > dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE ||
 	    cap->max_recv_sge >
-		min(dev->dev->caps.max_sq_sg, dev->dev->caps.max_rq_sg))
+		min(dev->dev->caps.max_sq_sg, dev->dev->caps.max_rq_sg)) {
+		mlx4_ib_dbg("Requested RQ size (sge or wr) too large");
 		return -EINVAL;
+	}
 
-	if (has_srq_or_is_xrc) {
+	if (has_srq) {
 		/* QPs attached to an SRQ should have no RQ */
-		if (cap->max_recv_wr)
+		if (cap->max_recv_wr) {
+			mlx4_ib_dbg("non-zero RQ size for QP using SRQ");
 			return -EINVAL;
+		}
 
 		qp->rq.wqe_cnt = qp->rq.max_gs = 0;
 	} else {
 		/* HW requires >= 1 RQ entry with >= 1 gather entry */
-		if (is_user && (!cap->max_recv_wr || !cap->max_recv_sge))
+		if (is_user && (!cap->max_recv_wr || !cap->max_recv_sge)) {
+			mlx4_ib_dbg("user QP RQ has 0 wr's or 0 sge's "
+				    "(wr: 0x%x, sge: 0x%x)", cap->max_recv_wr,
+				    cap->max_recv_sge);
 			return -EINVAL;
+		}
 
 		qp->rq.wqe_cnt	 = roundup_pow_of_two(max(1U, cap->max_recv_wr));
 		qp->rq.max_gs	 = roundup_pow_of_two(max(1U, cap->max_recv_sge));
@@ -325,28 +334,39 @@ static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
 	return 0;
 }
 
-static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
-			      enum ib_qp_type type, struct mlx4_ib_qp *qp)
+static int set_kernel_sq_size(struct mlx4_ib_dev *dev,
+			      struct ib_qp_init_attr *init_attr,
+			      struct mlx4_ib_qp *qp)
 {
+	struct ib_qp_cap *cap = &init_attr->cap;
+	enum ib_qp_type type = init_attr->qp_type;
 	int s;
+	int reserve = 0;
 
 	/* Sanity check SQ size before proceeding */
 	if (cap->max_send_wr	 > (dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE) ||
 	    cap->max_send_sge	 >
 		min(dev->dev->caps.max_sq_sg, dev->dev->caps.max_rq_sg) ||
 	    cap->max_inline_data + send_wqe_overhead(type) +
-	    sizeof (struct mlx4_wqe_inline_seg) > dev->dev->caps.max_sq_desc_sz)
+	    sizeof (struct mlx4_wqe_inline_seg) > dev->dev->caps.max_sq_desc_sz) {
+		mlx4_ib_dbg("Requested SQ resources exceed device maxima");
 		return -EINVAL;
+	}
 
 	/*
 	 * For MLX transport we need 2 extra S/G entries:
 	 * one for the header and one for the checksum at the end
 	 */
 	if ((type == IB_QPT_SMI || type == IB_QPT_GSI) &&
-	    cap->max_send_sge + 2 > dev->dev->caps.max_sq_sg)
+	    cap->max_send_sge + 2 > dev->dev->caps.max_sq_sg) {
+		mlx4_ib_dbg("No space for SQP hdr/csum sge's");
 		return -EINVAL;
+	}
 
-	s = max(cap->max_send_sge * sizeof (struct mlx4_wqe_data_seg),
+	if (qp->flags & MLX4_QP_LSO)
+		reserve = 64;
+
+	s = max(cap->max_send_sge * sizeof (struct mlx4_wqe_data_seg) + reserve,
 		cap->max_inline_data + sizeof (struct mlx4_wqe_inline_seg)) +
 		send_wqe_overhead(type);
 
@@ -407,7 +427,7 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
 		++qp->sq.wqe_shift;
 	}
 
-	qp->sq.max_gs = ((qp->sq_max_wqes_per_wr << qp->sq.wqe_shift) -
+	qp->sq.max_gs = ((qp->sq_max_wqes_per_wr << qp->sq.wqe_shift) - reserve -
 			 send_wqe_overhead(type)) / sizeof (struct mlx4_wqe_data_seg);
 
 	qp->buf_size = (qp->rq.wqe_cnt << qp->rq.wqe_shift) +
@@ -439,8 +459,10 @@ static int set_user_sq_size(struct mlx4_ib_dev *dev,
 	if ((1 << ucmd->log_sq_bb_count) > dev->dev->caps.max_wqes	 ||
 	    ucmd->log_sq_stride >
 		ilog2(roundup_pow_of_two(dev->dev->caps.max_sq_desc_sz)) ||
-	    ucmd->log_sq_stride < MLX4_IB_MIN_SQ_STRIDE)
+	    ucmd->log_sq_stride < MLX4_IB_MIN_SQ_STRIDE) {
+		mlx4_ib_dbg("Requested max wqes or wqe stride exceeds max");
 		return -EINVAL;
+	}
 
 	qp->sq.wqe_cnt   = 1 << ucmd->log_sq_bb_count;
 	qp->sq.wqe_shift = ucmd->log_sq_stride;
@@ -476,8 +498,10 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 	else
 		qp->sq_signal_bits = 0;
 
-	err = set_rq_size(dev, &init_attr->cap, !!pd->uobject,
-			  !!init_attr->srq || !!init_attr->xrc_domain , qp);
+	if (init_attr->create_flags & QP_CREATE_LSO)
+		qp->flags |= MLX4_QP_LSO;
+
+	err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, !!init_attr->srq, qp);
 	if (err)
 		goto err;
 
@@ -499,32 +523,39 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 				       qp->buf_size, 0);
 		if (IS_ERR(qp->umem)) {
 			err = PTR_ERR(qp->umem);
+			mlx4_ib_dbg("ib_umem_get error (%d)", err);
 			goto err;
 		}
 
 		err = mlx4_mtt_init(dev->dev, ib_umem_page_count(qp->umem),
 				    ilog2(qp->umem->page_size), &qp->mtt);
-		if (err)
+		if (err) {
+			mlx4_ib_dbg("mlx4_mtt_init error (%d)", err);
 			goto err_buf;
+		}
 
 		err = mlx4_ib_umem_write_mtt(dev, &qp->mtt, qp->umem);
-		if (err)
+		if (err) {
+			mlx4_ib_dbg("mlx4_ib_umem_write_mtt error (%d)", err);
 			goto err_mtt;
+		}
 
-		if (!init_attr->srq && init_attr->qp_type != IB_QPT_XRC) {
+		if (!init_attr->srq) {
 			err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context),
 						  ucmd.db_addr, &qp->db);
-			if (err)
+			if (err) {
+				mlx4_ib_dbg("mlx4_ib_db_map_user error (%d)", err);
 				goto err_mtt;
+			}
 		}
 	} else {
 		qp->sq_no_prefetch = 0;
 
-		err = set_kernel_sq_size(dev, &init_attr->cap, init_attr->qp_type, qp);
+		err = set_kernel_sq_size(dev, init_attr, qp);
 		if (err)
 			goto err;
 
-		if (!init_attr->srq && init_attr->qp_type != IB_QPT_XRC) {
+		if (!init_attr->srq) {
 			err = mlx4_ib_db_alloc(dev, &qp->db, 0);
 			if (err)
 				goto err;
@@ -539,12 +570,16 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 
 		err = mlx4_mtt_init(dev->dev, qp->buf.npages, qp->buf.page_shift,
 				    &qp->mtt);
-		if (err)
+		if (err) {
+			mlx4_ib_dbg("kernel qp mlx4_mtt_init error (%d)", err);
 			goto err_buf;
+		}
 
 		err = mlx4_buf_write_mtt(dev->dev, &qp->mtt, &qp->buf);
-		if (err)
+		if (err) {
+			mlx4_ib_dbg("mlx4_buf_write_mtt error (%d)", err);
 			goto err_mtt;
+		}
 
 		qp->sq.wrid  = kmalloc(qp->sq.wqe_cnt * sizeof (u64), GFP_KERNEL);
 		qp->rq.wrid  = kmalloc(qp->rq.wqe_cnt * sizeof (u64), GFP_KERNEL);
@@ -559,9 +594,6 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 	if (err)
 		goto err_wrid;
 
-	if (init_attr->qp_type == IB_QPT_XRC)
-		qp->mqp.qpn |= (1 << 23);
-
 	/*
 	 * Hardware wants QPN written in big-endian order (after
 	 * shifting) for send doorbell.  Precompute this value to save
@@ -575,7 +607,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 
 err_wrid:
 	if (pd->uobject) {
-		if (!init_attr->srq && init_attr->qp_type != IB_QPT_XRC)
+		if (!init_attr->srq)
 			mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context),
 					      &qp->db);
 	} else {
@@ -593,7 +625,7 @@ err_buf:
 		mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
 
 err_db:
-	if (!pd->uobject && !init_attr->srq && init_attr->qp_type != IB_QPT_XRC)
+	if (!pd->uobject && !init_attr->srq)
 		mlx4_ib_db_free(dev, &qp->db);
 
 err:
@@ -671,7 +703,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
 	mlx4_mtt_cleanup(dev->dev, &qp->mtt);
 
 	if (is_user) {
-		if (!qp->ibqp.srq && qp->ibqp.qp_type != IB_QPT_XRC)
+		if (!qp->ibqp.srq)
 			mlx4_ib_db_unmap_user(to_mucontext(qp->ibqp.uobject->context),
 					      &qp->db);
 		ib_umem_release(qp->umem);
@@ -679,7 +711,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
 		kfree(qp->sq.wrid);
 		kfree(qp->rq.wrid);
 		mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
-		if (!qp->ibqp.srq && qp->ibqp.qp_type != IB_QPT_XRC)
+		if (!qp->ibqp.srq)
 			mlx4_ib_db_free(dev, &qp->db);
 	}
 }
@@ -694,9 +726,6 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 	int err;
 
 	switch (init_attr->qp_type) {
-	case IB_QPT_XRC:
-		if (!(dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
-			return ERR_PTR(-ENOSYS);
 	case IB_QPT_RC:
 	case IB_QPT_UC:
 	case IB_QPT_UD:
@@ -711,11 +740,6 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 			return ERR_PTR(err);
 		}
 
-		if (init_attr->qp_type == IB_QPT_XRC)
-			qp->xrcdn = to_mxrcd(init_attr->xrc_domain)->xrcdn;
-		else
-			qp->xrcdn = 0;
-
 		qp->ibqp.qp_num = qp->mqp.qpn;
 
 		break;
@@ -724,8 +748,10 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 	case IB_QPT_GSI:
 	{
 		/* Userspace is not allowed to create special QPs: */
-		if (pd->uobject)
+		if (pd->uobject) {
+			mlx4_ib_dbg("Userspace is not allowed to create special QPs");
 			return ERR_PTR(-EINVAL);
+		}
 
 		sqp = kmalloc(sizeof *sqp, GFP_KERNEL);
 		if (!sqp)
@@ -750,6 +776,8 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 	}
 	default:
 		/* Don't support raw QPs */
+		mlx4_ib_dbg("Invalid QP type requested for create_qp (%d)",
+			    init_attr->qp_type);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -780,7 +808,6 @@ static int to_mlx4_st(enum ib_qp_type type)
 	case IB_QPT_RC:		return MLX4_QP_ST_RC;
 	case IB_QPT_UC:		return MLX4_QP_ST_UC;
 	case IB_QPT_UD:		return MLX4_QP_ST_UD;
-	case IB_QPT_XRC:	return MLX4_QP_ST_XRC;
 	case IB_QPT_SMI:
 	case IB_QPT_GSI:	return MLX4_QP_ST_MLX;
 	default:		return -1;
@@ -928,11 +955,8 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 		context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3;
 	context->sq_size_stride |= qp->sq.wqe_shift - 4;
 
-	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
+	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
 		context->sq_size_stride |= !!qp->sq_no_prefetch << 7;
-		if (ibqp->qp_type == IB_QPT_XRC)
-			context->xrcd = cpu_to_be32((u32) qp->xrcdn);
-	}
 
 	if (qp->ibqp.uobject)
 		context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index);
@@ -957,8 +981,11 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 
 	if (attr_mask & IB_QP_AV) {
 		if (mlx4_set_path(dev, &attr->ah_attr, &context->pri_path,
-				  attr_mask & IB_QP_PORT ? attr->port_num : qp->port))
+				  attr_mask & IB_QP_PORT ? attr->port_num : qp->port)) {
+			mlx4_ib_dbg("qpn 0x%x: could not set pri path params",
+				    ibqp->qp_num);
 			goto out;
+		}
 
 		optpar |= (MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH |
 			   MLX4_QP_OPTPAR_SCHED_QUEUE);
@@ -971,16 +998,25 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 
 	if (attr_mask & IB_QP_ALT_PATH) {
 		if (attr->alt_port_num == 0 ||
-		    attr->alt_port_num > dev->dev->caps.num_ports)
+		    attr->alt_port_num > dev->dev->caps.num_ports) {
+			mlx4_ib_dbg("qpn 0x%x: invalid alternate port num (%d)",
+				    ibqp->qp_num, attr->alt_port_num);
 			goto out;
+		}
 
 		if (attr->alt_pkey_index >=
-		    dev->dev->caps.pkey_table_len[attr->alt_port_num])
+		    dev->dev->caps.pkey_table_len[attr->alt_port_num]) {
+			mlx4_ib_dbg("qpn 0x%x: invalid alt pkey index (0x%x)",
+				    ibqp->qp_num, attr->alt_pkey_index);
 			goto out;
+		}
 
 		if (mlx4_set_path(dev, &attr->alt_ah_attr, &context->alt_path,
-				  attr->alt_port_num))
+				  attr->alt_port_num)) {
+			mlx4_ib_dbg("qpn 0x%x: could not set alt path params",
+				    ibqp->qp_num);
 			goto out;
+		}
 
 		context->alt_path.pkey_index = attr->alt_pkey_index;
 		context->alt_path.ackto = attr->alt_timeout << 3;
@@ -1044,8 +1080,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 	if (ibqp->srq)
 		context->srqn = cpu_to_be32(1 << 24 | to_msrq(ibqp->srq)->msrq.srqn);
 
-	if (!ibqp->srq && ibqp->qp_type != IB_QPT_XRC &&
-	    cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+	if (!ibqp->srq && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
 		context->db_rec_addr = cpu_to_be64(qp->db.dma);
 
 	if (cur_state == IB_QPS_INIT &&
@@ -1078,6 +1113,8 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 		for (i = 0; i < qp->sq.wqe_cnt; ++i) {
 			ctrl = get_send_wqe(qp, i);
 			ctrl->owner_opcode = cpu_to_be32(1 << 31);
+			if (!(qp->sq_max_wqes_per_wr > 1))
+				ctrl->fence_size = 1 << (qp->sq.wqe_shift - 4);
 
 			stamp_send_wqe(qp, i, 1 << qp->sq.wqe_shift);
 		}
@@ -1133,7 +1170,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 		qp->sq.head = 0;
 		qp->sq.tail = 0;
 		qp->sq_next_wqe = 0;
-		if (!ibqp->srq && ibqp->qp_type != IB_QPT_XRC)
+		if (!ibqp->srq)
 			*qp->db.db  = 0;
 	}
 
@@ -1143,7 +1180,7 @@ out:
 }
 
 static const struct ib_qp_attr mlx4_ib_qp_attr = { .port_num = 1 };
-static const int mlx4_ib_qp_attr_mask_table[IB_QPT_XRC + 1] = {
+static const int mlx4_ib_qp_attr_mask_table[IB_QPT_UD + 1] = {
 		[IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
 				IB_QP_PORT			|
 				IB_QP_QKEY),
@@ -1153,9 +1190,6 @@ static const int mlx4_ib_qp_attr_mask_table[IB_QPT_XRC + 1] = {
 		[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
 				IB_QP_PORT			|
 				IB_QP_ACCESS_FLAGS),
-		[IB_QPT_XRC] = (IB_QP_PKEY_INDEX		|
-				IB_QP_PORT			|
-				IB_QP_ACCESS_FLAGS),
 		[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 				IB_QP_QKEY),
 		[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -1175,27 +1209,49 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 	cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state;
 	new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
 
-	if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask))
+	if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask)) {
+		mlx4_ib_dbg("qpn 0x%x: invalid attribute mask specified "
+			    "for transition %d to %d. qp_type %d, attr_mask 0x%x",
+			    ibqp->qp_num, cur_state, new_state,
+			    ibqp->qp_type, attr_mask);
 		goto out;
+	}
 
 	if ((attr_mask & IB_QP_PORT) &&
 	    (attr->port_num == 0 || attr->port_num > dev->dev->caps.num_ports)) {
+		mlx4_ib_dbg("qpn 0x%x: invalid port number (%d) specified "
+			    "for transition %d to %d. qp_type %d",
+			    ibqp->qp_num, attr->port_num, cur_state,
+			    new_state, ibqp->qp_type);
 		goto out;
 	}
 
 	if (attr_mask & IB_QP_PKEY_INDEX) {
 		int p = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
-		if (attr->pkey_index >= dev->dev->caps.pkey_table_len[p])
+		if (attr->pkey_index >= dev->dev->caps.pkey_table_len[p]) {
+			mlx4_ib_dbg("qpn 0x%x: invalid pkey index (%d) specified "
+				    "for transition %d to %d. qp_type %d",
+				    ibqp->qp_num, attr->pkey_index, cur_state,
+				    new_state, ibqp->qp_type);
 			goto out;
+		}
 	}
 
 	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
 	    attr->max_rd_atomic > dev->dev->caps.max_qp_init_rdma) {
+		mlx4_ib_dbg("qpn 0x%x: max_rd_atomic (%d) too large. "
+			    "Transition %d to %d. qp_type %d",
+			    ibqp->qp_num, attr->max_rd_atomic, cur_state,
+			    new_state, ibqp->qp_type);
 		goto out;
 	}
 
 	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
 	    attr->max_dest_rd_atomic > dev->dev->caps.max_qp_dest_rdma) {
+		mlx4_ib_dbg("qpn 0x%x: max_dest_rd_atomic (%d) too large. "
+			    "Transition %d to %d. qp_type %d",
+			    ibqp->qp_num, attr->max_dest_rd_atomic, cur_state,
+			    new_state, ibqp->qp_type);
 		goto out;
 	}
 
@@ -1273,6 +1329,8 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
 		sqp->ud_header.immediate_data    = wr->imm_data;
 		break;
 	default:
+		mlx4_ib_dbg("special QP type %d: invalid wr opcode 0x%x",
+			    sqp->qp.ibqp.qp_type, wr->opcode);
 		return -EINVAL;
 	}
 
@@ -1440,6 +1498,10 @@ static int build_lso_seg(struct mlx4_lso_seg *wqe, struct ib_send_wr *wr,
 {
 	int halign;
 
+	halign = ALIGN(wr->wr.ud.hlen, 16);
+	if (unlikely(!(qp->flags & MLX4_QP_LSO) && wr->num_sge > qp->sq.max_gs - (halign >> 4)))
+                return -EINVAL;
+
 	memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen);
 
 	/* make sure LSO header is written before
@@ -1449,11 +1511,6 @@ static int build_lso_seg(struct mlx4_lso_seg *wqe, struct ib_send_wr *wr,
 	wqe->mss_hdr_size = cpu_to_be32(((wr->wr.ud.mss - wr->wr.ud.hlen)
 					 << 16) | wr->wr.ud.hlen);
 
-	halign = ALIGN(wr->wr.ud.hlen, 16);
-
-	if (unlikely(wr->num_sge > qp->sq.max_gs - (halign >> 4)))
-		return -EINVAL;
-
 	*lso_seg_len = halign;
 	return 0;
 }
@@ -1479,12 +1536,15 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 
 	for (nreq = 0; wr; ++nreq, wr = wr->next) {
 		if (mlx4_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)) {
+			mlx4_ib_dbg("QP 0x%x: WQE overflow", ibqp->qp_num);
 			err = -ENOMEM;
 			*bad_wr = wr;
 			goto out;
 		}
 
 		if (unlikely(wr->num_sge > qp->sq.max_gs)) {
+			mlx4_ib_dbg("QP 0x%x: too many sg entries (%d)",
+				    ibqp->qp_num, wr->num_sge);
 			err = -EINVAL;
 			*bad_wr = wr;
 			goto out;
@@ -1499,9 +1559,8 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 			(wr->send_flags & IB_SEND_SOLICITED ?
 			 cpu_to_be32(MLX4_WQE_CTRL_SOLICITED) : 0) |
 			((wr->send_flags & IB_SEND_IP_CSUM) ?
-			 cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM) : 0)   |
-			((wr->send_flags & IB_SEND_UDP_TCP_CSUM) ?
-			 cpu_to_be32(MLX4_WQE_CTRL_TCP_UDP_CSUM) : 0)   |
+			 cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM |
+				     MLX4_WQE_CTRL_TCP_UDP_CSUM) : 0) |
 			qp->sq_signal_bits;
 
 		if (wr->opcode == IB_WR_SEND_WITH_IMM ||
@@ -1514,10 +1573,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 		size = sizeof *ctrl / 16;
 
 		switch (ibqp->qp_type) {
-		case IB_QPT_XRC:
-			ctrl->srcrb_flags |=
-				cpu_to_be32(wr->xrc_remote_srq_num << 8);
-			/* fall thru */
 		case IB_QPT_RC:
 		case IB_QPT_UC:
 			switch (wr->opcode) {
@@ -1691,12 +1746,15 @@ int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 
 	for (nreq = 0; wr; ++nreq, wr = wr->next) {
 		if (mlx4_wq_overflow(&qp->rq, nreq, qp->ibqp.send_cq)) {
+			mlx4_ib_dbg("QP 0x%x: WQE overflow", ibqp->qp_num);
 			err = -ENOMEM;
 			*bad_wr = wr;
 			goto out;
 		}
 
 		if (unlikely(wr->num_sge > qp->rq.max_gs)) {
+			mlx4_ib_dbg("QP 0x%x: too many sg entries (%d)",
+				    ibqp->qp_num, wr->num_sge);
 			err = -EINVAL;
 			*bad_wr = wr;
 			goto out;
@@ -1832,8 +1890,7 @@ int mlx4_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr
 	qp_attr->qp_access_flags     =
 		to_ib_qp_access_flags(be32_to_cpu(context.params2));
 
-	if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC ||
-	    qp->ibqp.qp_type == IB_QPT_XRC) {
+	if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) {
 		to_ib_ah_attr(dev->dev, &qp_attr->ah_attr, &context.pri_path);
 		to_ib_ah_attr(dev->dev, &qp_attr->alt_ah_attr, &context.alt_path);
 		qp_attr->alt_pkey_index = context.alt_path.pkey_index & 0x7f;
diff --git a/drivers/infiniband/hw/mlx4/srq.c b/drivers/infiniband/hw/mlx4/srq.c
index e708357..a1ad4cc 100644
--- a/drivers/infiniband/hw/mlx4/srq.c
+++ b/drivers/infiniband/hw/mlx4/srq.c
@@ -72,17 +72,13 @@ static void mlx4_ib_srq_event(struct mlx4_srq *srq, enum mlx4_event type)
 	}
 }
 
-struct ib_srq *mlx4_ib_create_xrc_srq(struct ib_pd *pd,
-				      struct ib_cq *xrc_cq,
-				      struct ib_xrcd *xrcd,
-				      struct ib_srq_init_attr *init_attr,
-				      struct ib_udata *udata)
+struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
+				  struct ib_srq_init_attr *init_attr,
+				  struct ib_udata *udata)
 {
 	struct mlx4_ib_dev *dev = to_mdev(pd->device);
 	struct mlx4_ib_srq *srq;
 	struct mlx4_wqe_srq_next_seg *next;
-	u32	cqn;
-	u16	xrcdn;
 	int desc_size;
 	int buf_size;
 	int err;
@@ -90,8 +86,12 @@ struct ib_srq *mlx4_ib_create_xrc_srq(struct ib_pd *pd,
 
 	/* Sanity check SRQ size before proceeding */
 	if (init_attr->attr.max_wr  >= dev->dev->caps.max_srq_wqes ||
-	    init_attr->attr.max_sge >  dev->dev->caps.max_srq_sge)
+	    init_attr->attr.max_sge >  dev->dev->caps.max_srq_sge) {
+		mlx4_ib_dbg("a size param is out of range. "
+			    "max_wr = 0x%x, max_sge = 0x%x",
+			    init_attr->attr.max_wr, init_attr->attr.max_sge);
 		return ERR_PTR(-EINVAL);
+	}
 
 	srq = kmalloc(sizeof *srq, GFP_KERNEL);
 	if (!srq)
@@ -176,24 +176,18 @@ struct ib_srq *mlx4_ib_create_xrc_srq(struct ib_pd *pd,
 		}
 	}
 
-	cqn = xrc_cq ? (u32) (to_mcq(xrc_cq)->mcq.cqn) : 0;
-	xrcdn = xrcd ? (u16) (to_mxrcd(xrcd)->xrcdn) :
-		(u16) dev->dev->caps.reserved_xrcds;
-
-	err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, cqn, xrcdn, &srq->mtt,
+	err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, &srq->mtt,
 			     srq->db.dma, &srq->msrq);
 	if (err)
 		goto err_wrid;
 
 	srq->msrq.event = mlx4_ib_srq_event;
 
-	if (pd->uobject) {
+	if (pd->uobject)
 		if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof (__u32))) {
 			err = -EFAULT;
 			goto err_wrid;
 		}
-	} else
-		srq->ibsrq.xrc_srq_num = srq->msrq.srqn;
 
 	init_attr->attr.max_wr = srq->msrq.max - 1;
 
@@ -232,12 +226,16 @@ int mlx4_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
 	int ret;
 
 	/* We don't support resizing SRQs (yet?) */
-	if (attr_mask & IB_SRQ_MAX_WR)
+	if (attr_mask & IB_SRQ_MAX_WR) {
+		mlx4_ib_dbg("resize not yet supported");
 		return -EINVAL;
+	}
 
 	if (attr_mask & IB_SRQ_LIMIT) {
-		if (attr->srq_limit >= srq->msrq.max)
+		if (attr->srq_limit >= srq->msrq.max){
+			mlx4_ib_dbg("limit (0x%x) too high", attr->srq_limit);
 			return -EINVAL;
+		}
 
 		mutex_lock(&srq->mutex);
 		ret = mlx4_srq_arm(dev->dev, &srq->msrq, attr->srq_limit);
@@ -250,13 +248,6 @@ int mlx4_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
 	return 0;
 }
 
-struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
-				  struct ib_srq_init_attr *init_attr,
-				  struct ib_udata *udata)
-{
-	return mlx4_ib_create_xrc_srq(pd, NULL, NULL, init_attr, udata);
-}
-
 int mlx4_ib_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
 {
 	struct mlx4_ib_dev *dev = to_mdev(ibsrq->device);
@@ -279,18 +270,6 @@ int mlx4_ib_destroy_srq(struct ib_srq *srq)
 {
 	struct mlx4_ib_dev *dev = to_mdev(srq->device);
 	struct mlx4_ib_srq *msrq = to_msrq(srq);
-	struct mlx4_ib_cq *cq;
-
-	mlx4_srq_invalidate(dev->dev, &msrq->msrq);
-
-	if (srq->xrc_cq && !srq->uobject) {
-		cq = to_mcq(srq->xrc_cq);
-		spin_lock_irq(&cq->lock);
-		__mlx4_ib_cq_clean(cq, -1, msrq);
-		mlx4_srq_remove(dev->dev, &msrq->msrq);
-		spin_unlock_irq(&cq->lock);
-	} else
-		mlx4_srq_remove(dev->dev, &msrq->msrq);
 
 	mlx4_srq_free(dev->dev, &msrq->msrq);
 	mlx4_mtt_cleanup(dev->dev, &msrq->mtt);
@@ -339,12 +318,16 @@ int mlx4_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
 
 	for (nreq = 0; wr; ++nreq, wr = wr->next) {
 		if (unlikely(wr->num_sge > srq->msrq.max_gs)) {
+			mlx4_ib_dbg("srq num 0x%x: num s/g entries too large (%d)",
+				    srq->msrq.srqn, wr->num_sge);
 			err = -EINVAL;
 			*bad_wr = wr;
 			break;
 		}
 
 		if (unlikely(srq->head == srq->tail)) {
+			mlx4_ib_dbg("srq num 0x%x: No entries available to post.",
+				    srq->msrq.srqn);
 			err = -ENOMEM;
 			*bad_wr = wr;
 			break;
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 2a38926..6d59a22 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -1254,10 +1254,14 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
 
 	if (err)
 		goto out;
-
-	MTHCA_GET(adapter->vendor_id, outbox,   QUERY_ADAPTER_VENDOR_ID_OFFSET);
-	MTHCA_GET(adapter->device_id, outbox,   QUERY_ADAPTER_DEVICE_ID_OFFSET);
-	MTHCA_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET);
+	if (!mthca_is_memfree(dev)) {
+		MTHCA_GET(adapter->vendor_id, outbox,
+			  QUERY_ADAPTER_VENDOR_ID_OFFSET);
+		MTHCA_GET(adapter->device_id, outbox,
+			  QUERY_ADAPTER_DEVICE_ID_OFFSET);
+		MTHCA_GET(adapter->revision_id, outbox,
+			  QUERY_ADAPTER_REVISION_ID_OFFSET);
+	}
 	MTHCA_GET(adapter->inta_pin, outbox,    QUERY_ADAPTER_INTA_PIN_OFFSET);
 
 	get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4,
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index 15aa32e..1b7e253 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -54,8 +54,8 @@
 
 #define DRV_NAME	"ib_mthca"
 #define PFX		DRV_NAME ": "
-#define DRV_VERSION	"0.08"
-#define DRV_RELDATE	"February 14, 2006"
+#define DRV_VERSION	"1.0"
+#define DRV_RELDATE	"February 28, 2008"
 
 enum {
 	MTHCA_FLAG_DDR_HIDDEN = 1 << 1,
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 1a766ef..c7b819b 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -761,7 +761,8 @@ static int mthca_init_hca(struct mthca_dev *mdev)
 	}
 
 	mdev->eq_table.inta_pin = adapter.inta_pin;
-	mdev->rev_id            = adapter.revision_id;
+	if (!mthca_is_memfree(mdev))
+		mdev->rev_id = adapter.revision_id;
 	memcpy(mdev->board_id, adapter.board_id, sizeof mdev->board_id);
 
 	return 0;
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 1f4d27d..252db08 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -542,6 +542,7 @@ struct mthca_user_db_table *mthca_init_user_db_tab(struct mthca_dev *dev)
 	for (i = 0; i < npages; ++i) {
 		db_tab->page[i].refcount = 0;
 		db_tab->page[i].uvirt    = 0;
+		sg_init_table(&db_tab->page[i].mem, 1);
 	}
 
 	return db_tab;
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index aa6c70a..3538da1 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -613,8 +613,10 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
 			sizeof *(mr->mem.tavor.mpt) * idx;
 
 	mr->mtt = __mthca_alloc_mtt(dev, list_len, dev->mr_table.fmr_mtt_buddy);
-	if (IS_ERR(mr->mtt))
+	if (IS_ERR(mr->mtt)) {
+		err = PTR_ERR(mr->mtt);
 		goto err_out_table;
+	}
 
 	mtt_seg = mr->mtt->first_seg * MTHCA_MTT_SEG_SIZE;
 
@@ -627,8 +629,10 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
 		mr->mem.tavor.mtts = dev->mr_table.tavor_fmr.mtt_base + mtt_seg;
 
 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
-	if (IS_ERR(mailbox))
+	if (IS_ERR(mailbox)) {
+		err = PTR_ERR(mailbox);
 		goto err_out_free_mtt;
+	}
 
 	mpt_entry = mailbox->buf;
 
@@ -682,7 +686,7 @@ err_out_table:
 	mthca_table_put(dev, dev->mr_table.mpt_table, key);
 
 err_out_mpt_free:
-	mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey);
+	mthca_free(&dev->mr_table.mpt_alloc, key);
 	return err;
 }
 
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 6bcde1c..9e491df 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -923,17 +923,13 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd       *pd,
 	struct mthca_mr *mr;
 	u64 *page_list;
 	u64 total_size;
-	u64 mask;
+	unsigned long mask;
 	int shift;
 	int npages;
 	int err;
 	int i, j, n;
 
-	/* First check that we have enough alignment */
-	if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK))
-		return ERR_PTR(-EINVAL);
-
-	mask = 0;
+	mask = buffer_list[0].addr ^ *iova_start;
 	total_size = 0;
 	for (i = 0; i < num_phys_buf; ++i) {
 		if (i != 0)
@@ -947,17 +943,7 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd       *pd,
 	if (mask & ~PAGE_MASK)
 		return ERR_PTR(-EINVAL);
 
-	/* Find largest page shift we can use to cover buffers */
-	for (shift = PAGE_SHIFT; shift < 31; ++shift)
-		if (num_phys_buf > 1) {
-			if ((1ULL << shift) & mask)
-				break;
-		} else {
-			if (1ULL << shift >=
-			    buffer_list[0].size +
-			    (buffer_list[0].addr & ((1ULL << shift) - 1)))
-				break;
-		}
+	shift = __ffs(mask | 1 << 31);
 
 	buffer_list[0].size += buffer_list[0].addr & ((1ULL << shift) - 1);
 	buffer_list[0].addr &= ~0ull << shift;
@@ -1270,6 +1256,8 @@ static int mthca_init_node_data(struct mthca_dev *dev)
 		goto out;
 	}
 
+	if (mthca_is_memfree(dev))
+		dev->rev_id = be32_to_cpup((__be32 *) (out_mad->data + 32));
 	memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
 
 out:
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 68aa73d..067fbd7 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -249,7 +249,8 @@ void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
 	spin_unlock(&dev->qp_table.lock);
 
 	if (!qp) {
-		mthca_warn(dev, "Async event for bogus QP %08x\n", qpn);
+		mthca_dbg(dev, "Async event %d for bogus QP %08x\n",
+			  (int) event_type, qpn);
 		return;
 	}
 
@@ -1175,6 +1176,7 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
 {
 	int ret;
 	int i;
+	struct mthca_next_seg *next;
 
 	qp->refcount = 1;
 	init_waitqueue_head(&qp->wait);
@@ -1217,7 +1219,6 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
 	}
 
 	if (mthca_is_memfree(dev)) {
-		struct mthca_next_seg *next;
 		struct mthca_data_seg *scatter;
 		int size = (sizeof (struct mthca_next_seg) +
 			    qp->rq.max_gs * sizeof (struct mthca_data_seg)) / 16;
@@ -1240,6 +1241,13 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
 						    qp->sq.wqe_shift) +
 						   qp->send_wqe_offset);
 		}
+	} else {
+		for (i = 0; i < qp->rq.max; ++i) {
+			next = get_recv_wqe(qp, i);
+			next->nda_op = htonl((((i + 1) % qp->rq.max) <<
+					      qp->rq.wqe_shift) | 1);
+		}
+
 	}
 
 	qp->sq.last = get_send_wqe(qp, qp->sq.max - 1);
@@ -1863,7 +1871,6 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 		prev_wqe = qp->rq.last;
 		qp->rq.last = wqe;
 
-		((struct mthca_next_seg *) wqe)->nda_op = 0;
 		((struct mthca_next_seg *) wqe)->ee_nds =
 			cpu_to_be32(MTHCA_NEXT_DBD);
 		((struct mthca_next_seg *) wqe)->flags = 0;
@@ -1885,9 +1892,6 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 
 		qp->wrid[ind + qp->sq.max] = wr->wr_id;
 
-		((struct mthca_next_seg *) prev_wqe)->nda_op =
-			cpu_to_be32((ind << qp->rq.wqe_shift) | 1);
-		wmb();
 		((struct mthca_next_seg *) prev_wqe)->ee_nds =
 			cpu_to_be32(MTHCA_NEXT_DBD | size);
 
@@ -2013,9 +2017,7 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 			((wr->send_flags & IB_SEND_SOLICITED) ?
 			 cpu_to_be32(MTHCA_NEXT_SOLICIT) : 0)   |
 			((wr->send_flags & IB_SEND_IP_CSUM) ?
-			 cpu_to_be32(MTHCA_NEXT_IP_CSUM) : 0)   |
-			((wr->send_flags & IB_SEND_UDP_TCP_CSUM) ?
-			 cpu_to_be32(MTHCA_NEXT_TCP_UDP_CSUM) : 0)   |
+			 cpu_to_be32(MTHCA_NEXT_IP_CSUM | MTHCA_NEXT_TCP_UDP_CSUM) : 0) |
 			cpu_to_be32(1);
 		if (wr->opcode == IB_WR_SEND_WITH_IMM ||
 		    wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 553d681..af8483c 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -175,9 +175,17 @@ static int mthca_alloc_srq_buf(struct mthca_dev *dev, struct mthca_pd *pd,
 	 * scatter list L_Keys to the sentry value of 0x100.
 	 */
 	for (i = 0; i < srq->max; ++i) {
-		wqe = get_wqe(srq, i);
+		struct mthca_next_seg *next;
 
-		*wqe_to_link(wqe) = i < srq->max - 1 ? i + 1 : -1;
+		next = wqe = get_wqe(srq, i);
+
+		if (i < srq->max - 1) {
+			*wqe_to_link(wqe) = i + 1;
+			next->nda_op = htonl(((i + 1) << srq->wqe_shift) | 1);
+		} else {
+			*wqe_to_link(wqe) = -1;
+			next->nda_op = 0;
+		}
 
 		for (scatter = wqe + sizeof (struct mthca_next_seg);
 		     (void *) scatter < wqe + (1 << srq->wqe_shift);
@@ -470,16 +478,15 @@ out:
 void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr)
 {
 	int ind;
+	struct mthca_next_seg *last_free;
 
 	ind = wqe_addr >> srq->wqe_shift;
 
 	spin_lock(&srq->lock);
 
-	if (likely(srq->first_free >= 0))
-		*wqe_to_link(get_wqe(srq, srq->last_free)) = ind;
-	else
-		srq->first_free = ind;
-
+	last_free = get_wqe(srq, srq->last_free);
+	*wqe_to_link(last_free) = ind;
+	last_free->nda_op = htonl((ind << srq->wqe_shift) | 1);
 	*wqe_to_link(get_wqe(srq, ind)) = -1;
 	srq->last_free = ind;
 
@@ -528,7 +535,6 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
 		prev_wqe  = srq->last;
 		srq->last = wqe;
 
-		((struct mthca_next_seg *) wqe)->nda_op = 0;
 		((struct mthca_next_seg *) wqe)->ee_nds = 0;
 		/* flags field will always remain 0 */
 
@@ -549,9 +555,6 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
 		if (i < srq->max_gs)
 			mthca_set_data_seg_inval(wqe);
 
-		((struct mthca_next_seg *) prev_wqe)->nda_op =
-			cpu_to_be32((ind << srq->wqe_shift) | 1);
-		wmb();
 		((struct mthca_next_seg *) prev_wqe)->ee_nds =
 			cpu_to_be32(MTHCA_NEXT_DBD);
 
@@ -633,8 +636,6 @@ int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
 			break;
 		}
 
-		((struct mthca_next_seg *) wqe)->nda_op =
-			cpu_to_be32((next_ind << srq->wqe_shift) | 1);
 		((struct mthca_next_seg *) wqe)->ee_nds = 0;
 		/* flags field will always remain 0 */
 
diff --git a/drivers/net/mlx4/Makefile b/drivers/net/mlx4/Makefile
index 161e01b..3af97af 100644
--- a/drivers/net/mlx4/Makefile
+++ b/drivers/net/mlx4/Makefile
@@ -6,4 +6,4 @@ export CPPFLAGS := $(INFINIBANDINCLUDE) $(CPPFLAGS)
 obj-$(CONFIG_MLX4_CORE)		+= mlx4_core.o
 
 mlx4_core-y :=	alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \
-		mr.o pd.o profile.o qp.o reset.o srq.o xrcd.o
+		mr.o pd.o profile.o qp.o reset.o srq.o
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index f154e6f..cb8de45 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -46,6 +46,10 @@ enum {
 extern void __buggy_use_of_MLX4_GET(void);
 extern void __buggy_use_of_MLX4_PUT(void);
 
+static int mlx4_core_enable_qos = 1;
+module_param_named(enable_qos, mlx4_core_enable_qos, int, 0444);
+MODULE_PARM_DESC(enable_qos, "Enable Quality of Service support in the HCA if > 0, (default 1)");
+
 #define MLX4_GET(dest, source, offset)				      \
 	do {							      \
 		void *__p = (char *) (source) + (offset);	      \
@@ -160,8 +164,6 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 #define QUERY_DEV_CAP_MAX_MCG_OFFSET		0x63
 #define QUERY_DEV_CAP_RSVD_PD_OFFSET		0x64
 #define QUERY_DEV_CAP_MAX_PD_OFFSET		0x65
-#define QUERY_DEV_CAP_RSVD_XRC_OFFSET		0x66
-#define QUERY_DEV_CAP_MAX_XRC_OFFSET		0x67
 #define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET	0x80
 #define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET	0x82
 #define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET	0x84
@@ -272,11 +274,6 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET);
 	dev_cap->max_pds = 1 << (field & 0x3f);
 
-	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_XRC_OFFSET);
-	dev_cap->reserved_xrcds = field >> 4;
-	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_XRC_OFFSET);
-	dev_cap->max_xrcds = 1 << (field & 0x1f);
-
 	MLX4_GET(size, outbox, QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET);
 	dev_cap->rdmarc_entry_sz = size;
 	MLX4_GET(size, outbox, QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET);
@@ -633,9 +630,6 @@ int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter)
 	int err;
 
 #define QUERY_ADAPTER_OUT_SIZE             0x100
-#define QUERY_ADAPTER_VENDOR_ID_OFFSET     0x00
-#define QUERY_ADAPTER_DEVICE_ID_OFFSET     0x04
-#define QUERY_ADAPTER_REVISION_ID_OFFSET   0x08
 #define QUERY_ADAPTER_INTA_PIN_OFFSET      0x10
 #define QUERY_ADAPTER_VSD_OFFSET           0x20
 
@@ -649,9 +643,6 @@ int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter)
 	if (err)
 		goto out;
 
-	MLX4_GET(adapter->vendor_id, outbox,   QUERY_ADAPTER_VENDOR_ID_OFFSET);
-	MLX4_GET(adapter->device_id, outbox,   QUERY_ADAPTER_DEVICE_ID_OFFSET);
-	MLX4_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET);
 	MLX4_GET(adapter->inta_pin, outbox,    QUERY_ADAPTER_INTA_PIN_OFFSET);
 
 	get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4,
@@ -723,6 +714,10 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
 	/* Check port for UD address vector: */
 	*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1);
 
+	/* Enable QoS support if module parameter set */
+	if (mlx4_core_enable_qos)
+		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 2);
+
 	/* QPC/EEC/CQC/EQC/RDMARC attributes */
 
 	MLX4_PUT(inbox, param->qpc_base,      INIT_HCA_QPC_BASE_OFFSET);
@@ -857,3 +852,40 @@ int mlx4_NOP(struct mlx4_dev *dev)
 	/* Input modifier of 0x1f means "finish as soon as possible." */
 	return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100);
 }
+
+int mlx4_query_diag_counters(struct mlx4_dev *dev, int array_length,
+			     int in_modifier, unsigned int in_offset[],
+			     u32 counter_out[])
+{
+	struct mlx4_cmd_mailbox *mailbox;
+	u32 *outbox;
+	u32 op_modifer = (u32)in_modifier;
+	int ret;
+	int i;
+
+	mailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(mailbox))
+		return PTR_ERR(mailbox);
+	outbox = mailbox->buf;
+
+	ret = mlx4_cmd_box(dev, 0, mailbox->dma, 0, op_modifer,
+			   MLX4_CMD_DIAG_RPRT, MLX4_CMD_TIME_CLASS_A);
+	if (ret)
+		goto out;
+
+	for(i=0; i<array_length; i++) {
+		if (in_offset[i] > MLX4_MAILBOX_SIZE) {
+			ret = -1;
+			goto out;
+		}
+
+		MLX4_GET(counter_out[i], outbox,   in_offset[i]);
+	}
+	ret = 0;
+
+out:
+	mlx4_free_cmd_mailbox(dev, mailbox);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mlx4_query_diag_counters);
+
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index e271e36..306cb9b 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -82,8 +82,6 @@ struct mlx4_dev_cap {
 	int max_mcgs;
 	int reserved_pds;
 	int max_pds;
-	int reserved_xrcds;
-	int max_xrcds;
 	int qpc_entry_sz;
 	int rdmarc_entry_sz;
 	int altc_entry_sz;
@@ -102,9 +100,6 @@ struct mlx4_dev_cap {
 };
 
 struct mlx4_adapter {
-	u32  vendor_id;
-	u32  device_id;
-	u32  revision_id;
 	char board_id[MLX4_BOARD_ID_LEN];
 	u8   inta_pin;
 };
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index e2d7755..ea1ebdc 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -59,6 +59,10 @@ MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
 
 #endif /* CONFIG_MLX4_DEBUG */
 
+int mlx4_blck_lb=1;
+module_param_named(block_loopback, mlx4_blck_lb, int, 0644);
+MODULE_PARM_DESC(block_loopback, "Block multicast loopback packets if > 0");
+
 #ifdef CONFIG_PCI_MSI
 
 static int msi_x = 1;
@@ -210,10 +214,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 	dev->caps.flags		     = dev_cap->flags;
 	dev->caps.stat_rate_support  = dev_cap->stat_rate_support;
 	dev->caps.max_gso_sz	     = dev_cap->max_gso_sz;
-	dev->caps.reserved_xrcds     = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ?
-		dev_cap->reserved_xrcds : 0;
-	dev->caps.max_xrcds	     = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ?
-		dev_cap->max_xrcds : 0;
 
 	return 0;
 }
@@ -590,7 +590,6 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
 	}
 
 	priv->eq_table.inta_pin = adapter.inta_pin;
-	dev->rev_id		= adapter.revision_id;
 	memcpy(dev->board_id, adapter.board_id, sizeof dev->board_id);
 
 	return 0;
@@ -642,18 +641,11 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
 		goto err_kar_unmap;
 	}
 
-	err = mlx4_init_xrcd_table(dev);
-	if (err) {
-		mlx4_err(dev, "Failed to initialize "
-			 "extended reliably connected domain table, aborting.\n");
-		goto err_pd_table_free;
-	}
-
 	err = mlx4_init_mr_table(dev);
 	if (err) {
 		mlx4_err(dev, "Failed to initialize "
 			 "memory region table, aborting.\n");
-		goto err_xrcd_table_free;
+		goto err_pd_table_free;
 	}
 
 	err = mlx4_init_eq_table(dev);
@@ -737,9 +729,6 @@ err_eq_table_free:
 err_mr_table_free:
 	mlx4_cleanup_mr_table(dev);
 
-err_xrcd_table_free:
-	mlx4_cleanup_xrcd_table(dev);
-
 err_pd_table_free:
 	mlx4_cleanup_pd_table(dev);
 
@@ -913,7 +902,6 @@ err_cleanup:
 	mlx4_cmd_use_polling(dev);
 	mlx4_cleanup_eq_table(dev);
 	mlx4_cleanup_mr_table(dev);
-	mlx4_cleanup_xrcd_table(dev);
 	mlx4_cleanup_pd_table(dev);
 	mlx4_cleanup_uar_table(dev);
 
@@ -973,7 +961,6 @@ static void mlx4_remove_one(struct pci_dev *pdev)
 		mlx4_cmd_use_polling(dev);
 		mlx4_cleanup_eq_table(dev);
 		mlx4_cleanup_mr_table(dev);
-		mlx4_cleanup_xrcd_table(dev);
 		mlx4_cleanup_pd_table(dev);
 
 		iounmap(priv->kar);
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
index a99e772..6da6a43 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/mlx4/mcg.c
@@ -206,13 +206,14 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
 	}
 
 	for (i = 0; i < members_count; ++i)
-		if (mgm->qp[i] == cpu_to_be32(qp->qpn)) {
+		if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) {
 			mlx4_dbg(dev, "QP %06x already a member of MGM\n", qp->qpn);
 			err = 0;
 			goto out;
 		}
 
-	mgm->qp[members_count++] = cpu_to_be32(qp->qpn);
+	mgm->qp[members_count++] = cpu_to_be32((qp->qpn & MGM_QPN_MASK) |
+					       (!!mlx4_blck_lb << MGM_BLCK_LB_BIT));
 	mgm->members_count       = cpu_to_be32(members_count);
 
 	err = mlx4_WRITE_MCG(dev, index, mailbox);
@@ -287,7 +288,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
 
 	members_count = be32_to_cpu(mgm->members_count);
 	for (loc = -1, i = 0; i < members_count; ++i)
-		if (mgm->qp[i] == cpu_to_be32(qp->qpn))
+		if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn)
 			loc = i;
 
 	if (loc == -1) {
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index d1ac68f..8fc297e 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -46,8 +46,8 @@
 
 #define DRV_NAME	"mlx4_core"
 #define PFX		DRV_NAME ": "
-#define DRV_VERSION	"0.01"
-#define DRV_RELDATE	"May 1, 2007"
+#define DRV_VERSION	"1.0"
+#define DRV_RELDATE	"February 28, 2008"
 
 enum {
 	MLX4_HCR_BASE		= 0x80680,
@@ -106,6 +106,10 @@ extern int mlx4_debug_level;
 #define mlx4_warn(mdev, format, arg...) \
 	dev_warn(&mdev->pdev->dev, format, ## arg)
 
+#define MGM_QPN_MASK       0x00FFFFFF
+#define MGM_BLCK_LB_BIT    30
+extern int mlx4_blck_lb;
+
 struct mlx4_bitmap {
 	u32			last;
 	u32			top;
@@ -220,6 +224,7 @@ struct mlx4_eq_table {
 struct mlx4_srq_table {
 	struct mlx4_bitmap	bitmap;
 	spinlock_t		lock;
+	struct radix_tree_root	tree;
 	struct mlx4_icm_table	table;
 	struct mlx4_icm_table	cmpt_table;
 };
@@ -259,7 +264,6 @@ struct mlx4_priv {
 	struct mlx4_cmd		cmd;
 
 	struct mlx4_bitmap	pd_bitmap;
-	struct mlx4_bitmap	xrcd_bitmap;
 	struct mlx4_uar_table	uar_table;
 	struct mlx4_mr_table	mr_table;
 	struct mlx4_cq_table	cq_table;
@@ -289,7 +293,6 @@ void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap);
 int mlx4_reset(struct mlx4_dev *dev);
 
 int mlx4_init_pd_table(struct mlx4_dev *dev);
-int mlx4_init_xrcd_table(struct mlx4_dev *dev);
 int mlx4_init_uar_table(struct mlx4_dev *dev);
 int mlx4_init_mr_table(struct mlx4_dev *dev);
 int mlx4_init_eq_table(struct mlx4_dev *dev);
@@ -306,7 +309,6 @@ void mlx4_cleanup_cq_table(struct mlx4_dev *dev);
 void mlx4_cleanup_qp_table(struct mlx4_dev *dev);
 void mlx4_cleanup_srq_table(struct mlx4_dev *dev);
 void mlx4_cleanup_mcg_table(struct mlx4_dev *dev);
-void mlx4_cleanup_xrcd_table(struct mlx4_dev *dev);
 
 void mlx4_start_catas_poll(struct mlx4_dev *dev);
 void mlx4_stop_catas_poll(struct mlx4_dev *dev);
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c
index 0c05a10..730b3dc 100644
--- a/drivers/net/mlx4/mr.c
+++ b/drivers/net/mlx4/mr.c
@@ -578,13 +578,6 @@ int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages,
 		goto err_free;
 	}
 
-	fmr->mpt = mlx4_table_find(&priv->mr_table.dmpt_table,
-				    key_to_hw_index(fmr->mr.key), NULL);
-	if (!fmr->mpt) {
-		err = -ENOMEM;
-		goto err_free;
-	}
-
 	return 0;
 
 err_free:
@@ -595,7 +588,19 @@ EXPORT_SYMBOL_GPL(mlx4_fmr_alloc);
 
 int mlx4_fmr_enable(struct mlx4_dev *dev, struct mlx4_fmr *fmr)
 {
-	return mlx4_mr_enable(dev, &fmr->mr);
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	int err;
+
+	err = mlx4_mr_enable(dev, &fmr->mr);
+	if (err)
+		return err;
+
+	fmr->mpt = mlx4_table_find(&priv->mr_table.dmpt_table,
+				    key_to_hw_index(fmr->mr.key), NULL);
+	if (!fmr->mpt)
+		return -ENOMEM;
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(mlx4_fmr_enable);
 
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
index 04def82..1692a4b 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/mlx4/qp.c
@@ -55,7 +55,8 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type)
 	spin_unlock(&qp_table->lock);
 
 	if (!qp) {
-		mlx4_warn(dev, "Async event for bogus QP %08x\n", qpn);
+		mlx4_dbg(dev, "Async event %d for bogus QP %08x\n",
+			 event_type, qpn);
 		return;
 	}
 
@@ -263,12 +264,10 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)
 	 * We reserve 2 extra QPs per port for the special QPs.  The
 	 * block of special QPs must be aligned to a multiple of 8, so
 	 * round up.
-	 * We also reserve the MSB of the 24-bit QP number to indicate
-	 * an XRC qp.
 	 */
 	dev->caps.sqp_start = ALIGN(dev->caps.reserved_qps, 8);
 	err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps,
-			       (1 << 23) - 1, dev->caps.sqp_start + 8);
+			       (1 << 24) - 1, dev->caps.sqp_start + 8);
 	if (err)
 		return err;
 
diff --git a/drivers/net/mlx4/srq.c b/drivers/net/mlx4/srq.c
index 84c070a..d23f46d 100644
--- a/drivers/net/mlx4/srq.c
+++ b/drivers/net/mlx4/srq.c
@@ -40,20 +40,20 @@
 struct mlx4_srq_context {
 	__be32			state_logsize_srqn;
 	u8			logstride;
-	u8			reserved1;
-	__be16			xrc_domain;
-	__be32			pg_offset_cqn;
-	u32			reserved2;
+	u8			reserved1[3];
+	u8			pg_offset;
+	u8			reserved2[3];
+	u32			reserved3;
 	u8			log_page_size;
-	u8			reserved3[2];
+	u8			reserved4[2];
 	u8			mtt_base_addr_h;
 	__be32			mtt_base_addr_l;
 	__be32			pd;
 	__be16			limit_watermark;
 	__be16			wqe_cnt;
-	u16			reserved4;
+	u16			reserved5;
 	__be16			wqe_counter;
-	u32			reserved5;
+	u32			reserved6;
 	__be64			db_rec_addr;
 };
 
@@ -64,7 +64,7 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type)
 
 	spin_lock(&srq_table->lock);
 
-	srq = radix_tree_lookup(&dev->srq_table_tree, srqn & (dev->caps.num_srqs - 1));
+	srq = radix_tree_lookup(&srq_table->tree, srqn & (dev->caps.num_srqs - 1));
 	if (srq)
 		atomic_inc(&srq->refcount);
 
@@ -109,8 +109,8 @@ static int mlx4_QUERY_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox
 			    MLX4_CMD_TIME_CLASS_A);
 }
 
-int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd,
-		   struct mlx4_mtt *mtt, u64 db_rec, struct mlx4_srq *srq)
+int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
+		   u64 db_rec, struct mlx4_srq *srq)
 {
 	struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
 	struct mlx4_cmd_mailbox *mailbox;
@@ -131,7 +131,7 @@ int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd,
 		goto err_put;
 
 	spin_lock_irq(&srq_table->lock);
-	err = radix_tree_insert(&dev->srq_table_tree, srq->srqn, srq);
+	err = radix_tree_insert(&srq_table->tree, srq->srqn, srq);
 	spin_unlock_irq(&srq_table->lock);
 	if (err)
 		goto err_cmpt_put;
@@ -148,8 +148,6 @@ int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd,
 	srq_context->state_logsize_srqn = cpu_to_be32((ilog2(srq->max) << 24) |
 						      srq->srqn);
 	srq_context->logstride          = srq->wqe_shift - 4;
-	srq_context->xrc_domain		= cpu_to_be16(xrcd);
-	srq_context->pg_offset_cqn	= cpu_to_be32(cqn & 0xffffff);
 	srq_context->log_page_size      = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
 
 	mtt_addr = mlx4_mtt_addr(dev, mtt);
@@ -170,7 +168,7 @@ int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd,
 
 err_radix:
 	spin_lock_irq(&srq_table->lock);
-	radix_tree_delete(&dev->srq_table_tree, srq->srqn);
+	radix_tree_delete(&srq_table->tree, srq->srqn);
 	spin_unlock_irq(&srq_table->lock);
 
 err_cmpt_put:
@@ -186,29 +184,18 @@ err_out:
 }
 EXPORT_SYMBOL_GPL(mlx4_srq_alloc);
 
-void mlx4_srq_invalidate(struct mlx4_dev *dev, struct mlx4_srq *srq)
+void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq)
 {
+	struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
 	int err;
 
 	err = mlx4_HW2SW_SRQ(dev, NULL, srq->srqn);
 	if (err)
 		mlx4_warn(dev, "HW2SW_SRQ failed (%d) for SRQN %06x\n", err, srq->srqn);
-}
-EXPORT_SYMBOL_GPL(mlx4_srq_invalidate);
-
-void mlx4_srq_remove(struct mlx4_dev *dev, struct mlx4_srq *srq)
-{
-	struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
 
 	spin_lock_irq(&srq_table->lock);
-	radix_tree_delete(&dev->srq_table_tree, srq->srqn);
+	radix_tree_delete(&srq_table->tree, srq->srqn);
 	spin_unlock_irq(&srq_table->lock);
-}
-EXPORT_SYMBOL_GPL(mlx4_srq_remove);
-
-void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq)
-{
-	struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
 
 	if (atomic_dec_and_test(&srq->refcount))
 		complete(&srq->free);
@@ -254,7 +241,7 @@ int mlx4_init_srq_table(struct mlx4_dev *dev)
 	int err;
 
 	spin_lock_init(&srq_table->lock);
-	INIT_RADIX_TREE(&dev->srq_table_tree, GFP_ATOMIC);
+	INIT_RADIX_TREE(&srq_table->tree, GFP_ATOMIC);
 
 	err = mlx4_bitmap_init(&srq_table->bitmap, dev->caps.num_srqs,
 			       dev->caps.num_srqs - 1, dev->caps.reserved_srqs);
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index e1253b3..645dedc 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -56,7 +56,6 @@ enum {
 	MLX4_DEV_CAP_FLAG_RC		= 1 <<  0,
 	MLX4_DEV_CAP_FLAG_UC		= 1 <<  1,
 	MLX4_DEV_CAP_FLAG_UD		= 1 <<  2,
-	MLX4_DEV_CAP_FLAG_XRC		= 1 <<  3,
 	MLX4_DEV_CAP_FLAG_SRQ		= 1 <<  6,
 	MLX4_DEV_CAP_FLAG_IPOIB_CSUM	= 1 <<  7,
 	MLX4_DEV_CAP_FLAG_BAD_PKEY_CNTR	= 1 <<  8,
@@ -182,8 +181,6 @@ struct mlx4_caps {
 	int			num_pds;
 	int			reserved_pds;
 	int			mtt_entry_sz;
-	int			reserved_xrcds;
-	int			max_xrcds;
 	u32			max_msg_sz;
 	u32			page_size_cap;
 	u32			flags;
@@ -296,7 +293,6 @@ struct mlx4_dev {
 	unsigned long		flags;
 	struct mlx4_caps	caps;
 	struct radix_tree_root	qp_table_tree;
-	struct radix_tree_root	srq_table_tree;
 	u32			rev_id;
 	char			board_id[MLX4_BOARD_ID_LEN];
 };
@@ -322,9 +318,6 @@ void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf);
 int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn);
 void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn);
 
-int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn);
-void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn);
-
 int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar);
 void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar);
 
@@ -349,8 +342,8 @@ void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq);
 int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp);
 void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp);
 
-int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd,
-		   struct mlx4_mtt *mtt, u64 db_rec, struct mlx4_srq *srq);
+int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
+		   u64 db_rec, struct mlx4_srq *srq);
 void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq);
 int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark);
 int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark);
@@ -370,5 +363,8 @@ void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr,
 		    u32 *lkey, u32 *rkey);
 int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr);
 int mlx4_SYNC_TPT(struct mlx4_dev *dev);
+int mlx4_query_diag_counters(struct mlx4_dev *melx4_dev, int array_length,
+			     int in_modifier, unsigned int in_offset[],
+			     u32 counter_out[]);
 
 #endif /* MLX4_DEVICE_H */
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
index dbd95d4..ac33c5c 100644
--- a/include/linux/mlx4/qp.h
+++ b/include/linux/mlx4/qp.h
@@ -74,7 +74,6 @@ enum {
 	MLX4_QP_ST_UC				= 0x1,
 	MLX4_QP_ST_RD				= 0x2,
 	MLX4_QP_ST_UD				= 0x3,
-	MLX4_QP_ST_XRC				= 0x6,
 	MLX4_QP_ST_MLX				= 0x7
 };
 
@@ -137,7 +136,7 @@ struct mlx4_qp_context {
 	__be32			ssn;
 	__be32			params2;
 	__be32			rnr_nextrecvpsn;
-	__be32			xrcd;
+	__be32			srcd;
 	__be32			cqn_recv;
 	__be64			db_rec_addr;
 	__be32			qkey;
diff --git a/include/linux/mlx4/srq.h b/include/linux/mlx4/srq.h
index 5371415..799a069 100644
--- a/include/linux/mlx4/srq.h
+++ b/include/linux/mlx4/srq.h
@@ -33,21 +33,10 @@
 #ifndef MLX4_SRQ_H
 #define MLX4_SRQ_H
 
-#include <linux/types.h>
-#include <linux/mlx4/device.h>
-
 struct mlx4_wqe_srq_next_seg {
 	u16			reserved1;
 	__be16			next_wqe_index;
 	u32			reserved2[3];
 };
 
-void mlx4_srq_invalidate(struct mlx4_dev *dev, struct mlx4_srq *srq);
-void mlx4_srq_remove(struct mlx4_dev *dev, struct mlx4_srq *srq);
-
-static inline struct mlx4_srq *__mlx4_srq_lookup(struct mlx4_dev *dev, u32 srqn)
-{
-	return radix_tree_lookup(&dev->srq_table_tree, srqn & (dev->caps.num_srqs - 1));
-}
-
 #endif /* MLX4_SRQ_H */
diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h
index 27f5e76..64a721f 100644
--- a/include/rdma/ib_user_verbs.h
+++ b/include/rdma/ib_user_verbs.h
@@ -83,10 +83,7 @@ enum {
 	IB_USER_VERBS_CMD_MODIFY_SRQ,
 	IB_USER_VERBS_CMD_QUERY_SRQ,
 	IB_USER_VERBS_CMD_DESTROY_SRQ,
-	IB_USER_VERBS_CMD_POST_SRQ_RECV,
-	IB_USER_VERBS_CMD_CREATE_XRC_SRQ,
-	IB_USER_VERBS_CMD_OPEN_XRC_DOMAIN,
-	IB_USER_VERBS_CMD_CLOSE_XRC_DOMAIN
+	IB_USER_VERBS_CMD_POST_SRQ_RECV
 };
 
 /*
@@ -646,18 +643,6 @@ struct ib_uverbs_create_srq {
 	__u64 driver_data[0];
 };
 
-struct ib_uverbs_create_xrc_srq {
-	__u64 response;
-	__u64 user_handle;
-	__u32 pd_handle;
-	__u32 max_wr;
-	__u32 max_sge;
-	__u32 srq_limit;
-	__u32 xrcd_handle;
-	__u32 xrc_cq;
-	__u64 driver_data[0];
-};
-
 struct ib_uverbs_create_srq_resp {
 	__u32 srq_handle;
 	__u32 max_wr;
@@ -697,23 +682,4 @@ struct ib_uverbs_destroy_srq_resp {
 	__u32 events_reported;
 };
 
-struct ib_uverbs_open_xrc_domain {
-	__u64 response;
-	__u32 fd;
-	__u32 oflags;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_open_xrc_domain_resp {
-	__u32 xrcd_handle;
-};
-
-struct ib_uverbs_close_xrc_domain {
-	__u64 response;
-	__u32 xrcd_handle;
-	__u64 driver_data[0];
-};
-
-
-
 #endif /* IB_USER_VERBS_H */
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 14a51b8..81dacbb 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -52,8 +52,6 @@
 
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
-#include <linux/rbtree.h>
-#include <linux/mutex.h>
 
 union ib_gid {
 	u8	raw[16];
@@ -98,11 +96,14 @@ enum ib_device_cap_flags {
 	IB_DEVICE_ZERO_STAG		= (1<<15),
 	IB_DEVICE_SEND_W_INV		= (1<<16),
 	IB_DEVICE_MEM_WINDOW		= (1<<17),
-	/* devices which publish this capability must support insertion of
-	   IP, UDP and TCP checksum on outgoing packets */
+	/*
+	 * devices which publish this capability must support insertion of UDP
+	 * and TCP checksum on outgoing packets and can verify the validity of
+	 * checksum for incoming packets. Setting this flag implies the driver
+	 * may set NETIF_F_IP_CSUM.
+	 */
 	IB_DEVICE_IP_CSUM		= (1<<18),
 	IB_DEVICE_TCP_TSO               = (1<<19),
-	IB_DEVICE_XRC                   = (1<<20),
 };
 
 enum ib_atomic_cap {
@@ -491,11 +492,14 @@ enum ib_qp_type {
 	IB_QPT_RC,
 	IB_QPT_UC,
 	IB_QPT_UD,
-	IB_QPT_XRC,
 	IB_QPT_RAW_IPV6,
 	IB_QPT_RAW_ETY
 };
 
+enum qp_create_flags {
+	QP_CREATE_LSO = 1 << 0,
+};
+
 struct ib_qp_init_attr {
 	void                  (*event_handler)(struct ib_event *, void *);
 	void		       *qp_context;
@@ -505,8 +509,8 @@ struct ib_qp_init_attr {
 	struct ib_qp_cap	cap;
 	enum ib_sig_type	sq_sig_type;
 	enum ib_qp_type		qp_type;
-	struct ib_xrcd	       *xrc_domain; /* XRC qp's only */
 	u8			port_num; /* special QP types only */
+	enum qp_create_flags    create_flags;
 };
 
 enum ib_rnr_timeout {
@@ -616,11 +620,11 @@ enum ib_wr_opcode {
 	IB_WR_RDMA_WRITE,
 	IB_WR_RDMA_WRITE_WITH_IMM,
 	IB_WR_SEND,
-	IB_WR_LSO,
 	IB_WR_SEND_WITH_IMM,
 	IB_WR_RDMA_READ,
 	IB_WR_ATOMIC_CMP_AND_SWP,
-	IB_WR_ATOMIC_FETCH_AND_ADD
+	IB_WR_ATOMIC_FETCH_AND_ADD,
+	IB_WR_LSO
 };
 
 enum ib_send_flags {
@@ -629,8 +633,7 @@ enum ib_send_flags {
 	IB_SEND_SOLICITED	= (1<<2),
 	IB_SEND_INLINE		= (1<<3),
 	IB_SEND_IP_CSUM         = (1<<4),
-	IB_SEND_UDP_TCP_CSUM    = (1<<5),
-	IB_SEND_UDP_LSO		= (1<<6)
+	IB_SEND_UDP_LSO		= (1<<5)
 };
 
 struct ib_sge {
@@ -669,7 +672,6 @@ struct ib_send_wr {
 			u8	port_num;   /* valid for DR SMPs on switch only */
 		} ud;
 	} wr;
-	u32			xrc_remote_srq_num; /* valid for XRC sends only */
 };
 
 struct ib_recv_wr {
@@ -731,7 +733,6 @@ struct ib_ucontext {
 	struct list_head	qp_list;
 	struct list_head	srq_list;
 	struct list_head	ah_list;
-	struct list_head	xrc_domain_list;
 	int			closing;
 };
 
@@ -759,15 +760,6 @@ struct ib_pd {
 	atomic_t          	usecnt; /* count all resources */
 };
 
-struct ib_xrcd {
-	struct ib_device       *device;
-	struct ib_uobject      *uobject;
-	struct inode	       *inode;
-	struct rb_node	        node;
-	atomic_t          	usecnt; /* count all resources */
-};
-
-
 struct ib_ah {
 	struct ib_device	*device;
 	struct ib_pd		*pd;
@@ -789,13 +781,10 @@ struct ib_cq {
 struct ib_srq {
 	struct ib_device       *device;
 	struct ib_pd	       *pd;
-	struct ib_cq	       *xrc_cq;
-	struct ib_xrcd	       *xrcd;
 	struct ib_uobject      *uobject;
 	void		      (*event_handler)(struct ib_event *, void *);
 	void		       *srq_context;
 	atomic_t		usecnt;
-	u32			xrc_srq_num;
 };
 
 struct ib_qp {
@@ -809,7 +798,6 @@ struct ib_qp {
 	void		       *qp_context;
 	u32			qp_num;
 	enum ib_qp_type		qp_type;
-	struct ib_xrcd	       *xrcd;  /* XRC QPs only */
 };
 
 struct ib_mr {
@@ -1056,15 +1044,6 @@ struct ib_device {
 						  struct ib_grh *in_grh,
 						  struct ib_mad *in_mad,
 						  struct ib_mad *out_mad);
-	struct ib_srq *            (*create_xrc_srq)(struct ib_pd *pd,
-						     struct ib_cq *xrc_cq,
-						     struct ib_xrcd *xrcd,
-						     struct ib_srq_init_attr *srq_init_attr,
-						     struct ib_udata *udata);
-	struct ib_xrcd *	   (*alloc_xrcd)(struct ib_device *device,
-						 struct ib_ucontext *context,
-						 struct ib_udata *udata);
-	int                        (*dealloc_xrcd)(struct ib_xrcd *xrcd);
 
 	struct ib_dma_mapping_ops   *dma_ops;
 
@@ -1086,8 +1065,6 @@ struct ib_device {
 	__be64			     node_guid;
 	u8                           node_type;
 	u8                           phys_port_cnt;
-	struct rb_root		     ib_uverbs_xrcd_table;
-	struct mutex		     xrcd_table_mutex;
 };
 
 struct ib_client {
@@ -1248,28 +1225,8 @@ int ib_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr);
 int ib_destroy_ah(struct ib_ah *ah);
 
 /**
- * ib_create_xrc_srq - Creates an XRC SRQ associated with the specified
- *   protection domain, cq, and xrc domain.
- * @pd: The protection domain associated with the SRQ.
- * @xrc_cq: The cq to be associated with the XRC SRQ.
- * @xrcd: The XRC domain to be associated with the XRC SRQ.
- * @srq_init_attr: A list of initial attributes required to create the
- *   XRC SRQ.  If XRC SRQ creation succeeds, then the attributes are updated
- *   to the actual capabilities of the created XRC SRQ.
- *
- * srq_attr->max_wr and srq_attr->max_sge are read the determine the
- * requested size of the XRC SRQ, and set to the actual values allocated
- * on return.  If ib_create_xrc_srq() succeeds, then max_wr and max_sge
- * will always be at least as large as the requested values.
- */
-struct ib_srq *ib_create_xrc_srq(struct ib_pd *pd,
-				 struct ib_cq *xrc_cq,
-				 struct ib_xrcd *xrcd,
-				 struct ib_srq_init_attr *srq_init_attr);
-
-/**
- * ib_create_srq - Creates an SRQ associated with the specified
- *   protection domain.
+ * ib_create_srq - Creates a SRQ associated with the specified protection
+ *   domain.
  * @pd: The protection domain associated with the SRQ.
  * @srq_init_attr: A list of initial attributes required to create the
  *   SRQ.  If SRQ creation succeeds, then the attributes are updated to
@@ -1907,17 +1864,4 @@ int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid);
  */
 int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid);
 
-
-/**
- * ib_dealloc_xrcd - Deallocates an extended reliably connected domain.
- * @xrcd: The xrc domain to deallocate.
- */
-int ib_dealloc_xrcd(struct ib_xrcd *xrcd);
-
-/**
- * ib_alloc_xrcd - Allocates an extended reliably connected domain.
- * @device: The device on which to allocate the xrcd.
- */
-struct ib_xrcd * ib_alloc_xrcd(struct ib_device *device);
-
 #endif /* IB_VERBS_H */