#!/bin/bash

# Generates a 2.6.34.*, 2.6.35.* or 2.6.36* kernel tree with the SRP_CRED_REQ
# and several other patches applied to the ib_srp initiator.

# Adjust this variable such that it points to the directory with
# linux-x.y.z.tar.bz2 and patch-x.y.z.p.bz2 files on your system
TARBALLDIR=/home/bart/software/downloads

# Local functions

usage() {
  echo "$0 <kernel-version>"
}

# Source: http://git.kernel.org/?p=linux/kernel/git/roland/infiniband.git;a=patch;h=$commit
get_2_6_36_patch() {
case "$1" in
  7a7008110b94dfaa90db4b0cc5b0c3f964c80506)
    cat <<EOF
index ed3f9eb..4675def 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -879,21 +879,10 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
 	opcode = *(u8 *) iu->buf;
 
 	if (0) {
-		int i;
-
 		shost_printk(KERN_ERR, target->scsi_host,
 			     PFX "recv completion, opcode 0x%02x\n", opcode);
-
-		for (i = 0; i < wc->byte_len; ++i) {
-			if (i % 8 == 0)
-				printk(KERN_ERR "  [%02x] ", i);
-			printk(" %02x", ((u8 *) iu->buf)[i]);
-			if ((i + 1) % 8 == 0)
-				printk("\n");
-		}
-
-		if (wc->byte_len % 8)
-			printk("\n");
+		print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 8, 1,
+			       iu->buf, wc->byte_len, true);
 	}
 
 	switch (opcode) {
-- 
1.7.3

EOF
    ;;
  c996bb47bb419b7c2f75499e11750142775e5da9)
    cat <<EOF
index 4675def..ffdd2d1 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -811,6 +811,38 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
 	return len;
 }
 
+static int srp_post_recv(struct srp_target_port *target)
+{
+	unsigned long flags;
+	struct srp_iu *iu;
+	struct ib_sge list;
+	struct ib_recv_wr wr, *bad_wr;
+	unsigned int next;
+	int ret;
+
+	spin_lock_irqsave(target->scsi_host->host_lock, flags);
+
+	next	 = target->rx_head & (SRP_RQ_SIZE - 1);
+	wr.wr_id = next;
+	iu	 = target->rx_ring[next];
+
+	list.addr   = iu->dma;
+	list.length = iu->size;
+	list.lkey   = target->srp_host->srp_dev->mr->lkey;
+
+	wr.next     = NULL;
+	wr.sg_list  = &list;
+	wr.num_sge  = 1;
+
+	ret = ib_post_recv(target->qp, &wr, &bad_wr);
+	if (!ret)
+		++target->rx_head;
+
+	spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
+
+	return ret;
+}
+
 static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
 {
 	struct srp_request *req;
@@ -868,6 +900,7 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
 {
 	struct ib_device *dev;
 	struct srp_iu *iu;
+	int res;
 	u8 opcode;
 
 	iu = target->rx_ring[wc->wr_id];
@@ -904,6 +937,11 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
 
 	ib_dma_sync_single_for_device(dev, iu->dma, target->max_ti_iu_len,
 				      DMA_FROM_DEVICE);
+
+	res = srp_post_recv(target);
+	if (res != 0)
+		shost_printk(KERN_ERR, target->scsi_host,
+			     PFX "Recv failed with error code %d\n", res);
 }
 
 static void srp_recv_completion(struct ib_cq *cq, void *target_ptr)
@@ -943,45 +981,6 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr)
 	}
 }
 
-static int __srp_post_recv(struct srp_target_port *target)
-{
-	struct srp_iu *iu;
-	struct ib_sge list;
-	struct ib_recv_wr wr, *bad_wr;
-	unsigned int next;
-	int ret;
-
-	next 	 = target->rx_head & (SRP_RQ_SIZE - 1);
-	wr.wr_id = next;
-	iu 	 = target->rx_ring[next];
-
-	list.addr   = iu->dma;
-	list.length = iu->size;
-	list.lkey   = target->srp_host->srp_dev->mr->lkey;
-
-	wr.next     = NULL;
-	wr.sg_list  = &list;
-	wr.num_sge  = 1;
-
-	ret = ib_post_recv(target->qp, &wr, &bad_wr);
-	if (!ret)
-		++target->rx_head;
-
-	return ret;
-}
-
-static int srp_post_recv(struct srp_target_port *target)
-{
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(target->scsi_host->host_lock, flags);
-	ret = __srp_post_recv(target);
-	spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
-
-	return ret;
-}
-
 /*
  * Must be called with target->scsi_host->host_lock held to protect
  * req_lim and tx_head.  Lock cannot be dropped between call here and
@@ -1091,11 +1090,6 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 		goto err;
 	}
 
-	if (__srp_post_recv(target)) {
-		shost_printk(KERN_ERR, target->scsi_host, PFX "Recv failed\n");
-		goto err_unmap;
-	}
-
 	ib_dma_sync_single_for_device(dev, iu->dma, srp_max_iu_len,
 				      DMA_TO_DEVICE);
 
@@ -1238,6 +1232,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
 	int attr_mask = 0;
 	int comp = 0;
 	int opcode = 0;
+	int i;
 
 	switch (event->event) {
 	case IB_CM_REQ_ERROR:
@@ -1287,7 +1282,11 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
 		if (target->status)
 			break;
 
-		target->status = srp_post_recv(target);
+		for (i = 0; i < SRP_RQ_SIZE; i++) {
+			target->status = srp_post_recv(target);
+			if (target->status)
+				break;
+		}
 		if (target->status)
 			break;
 
-- 
1.7.3

EOF
    ;;
  89de74866b846cc48780fda3de7fd223296aaca9)
    cat <<EOF
index ffdd2d1..7f8f16b 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1552,6 +1552,18 @@ static ssize_t show_orig_dgid(struct device *dev,
 	return sprintf(buf, "%pI6\n", target->orig_dgid);
 }
 
+static ssize_t show_req_lim(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	struct srp_target_port *target = host_to_target(class_to_shost(dev));
+
+	if (target->state == SRP_TARGET_DEAD ||
+	    target->state == SRP_TARGET_REMOVED)
+		return -ENODEV;
+
+	return sprintf(buf, "%d\n", target->req_lim);
+}
+
 static ssize_t show_zero_req_lim(struct device *dev,
 				 struct device_attribute *attr, char *buf)
 {
@@ -1586,6 +1598,7 @@ static DEVICE_ATTR(service_id,	    S_IRUGO, show_service_id,	   NULL);
 static DEVICE_ATTR(pkey,	    S_IRUGO, show_pkey,		   NULL);
 static DEVICE_ATTR(dgid,	    S_IRUGO, show_dgid,		   NULL);
 static DEVICE_ATTR(orig_dgid,	    S_IRUGO, show_orig_dgid,	   NULL);
+static DEVICE_ATTR(req_lim,         S_IRUGO, show_req_lim,         NULL);
 static DEVICE_ATTR(zero_req_lim,    S_IRUGO, show_zero_req_lim,	   NULL);
 static DEVICE_ATTR(local_ib_port,   S_IRUGO, show_local_ib_port,   NULL);
 static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
@@ -1597,6 +1610,7 @@ static struct device_attribute *srp_host_attrs[] = {
 	&dev_attr_pkey,
 	&dev_attr_dgid,
 	&dev_attr_orig_dgid,
+	&dev_attr_req_lim,
 	&dev_attr_zero_req_lim,
 	&dev_attr_local_ib_port,
 	&dev_attr_local_ib_device,
-- 
1.7.3

EOF
    ;;
  *)
    echo ERROR
    ;;
  esac
}

# Source: https://patchwork.kernel.org/patch/$p/raw/
get_2_6_37_patch() {
case "$1" in
  143381)
    cat <<EOF
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 7f8f16b..07e10fa 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -291,7 +291,7 @@ static void srp_free_target_ib(struct srp_target_port *target)
 
 	for (i = 0; i < SRP_RQ_SIZE; ++i)
 		srp_free_iu(target->srp_host, target->rx_ring[i]);
-	for (i = 0; i < SRP_SQ_SIZE + 1; ++i)
+	for (i = 0; i < SRP_SQ_SIZE; ++i)
 		srp_free_iu(target->srp_host, target->tx_ring[i]);
 }
 
@@ -822,7 +822,7 @@ static int srp_post_recv(struct srp_target_port *target)
 
 	spin_lock_irqsave(target->scsi_host->host_lock, flags);
 
-	next	 = target->rx_head & (SRP_RQ_SIZE - 1);
+	next	 = target->rx_head & SRP_RQ_MASK;
 	wr.wr_id = next;
 	iu	 = target->rx_ring[next];
 
@@ -989,19 +989,19 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr)
 static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
 					enum srp_request_type req_type)
 {
-	s32 min = (req_type == SRP_REQ_TASK_MGMT) ? 1 : 2;
+	s32 rsv = (req_type == SRP_REQ_TASK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
 
 	srp_send_completion(target->send_cq, target);
 
 	if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
 		return NULL;
 
-	if (target->req_lim < min) {
+	if (target->req_lim <= rsv) {
 		++target->zero_req_lim;
 		return NULL;
 	}
 
-	return target->tx_ring[target->tx_head & SRP_SQ_SIZE];
+	return target->tx_ring[target->tx_head & SRP_SQ_MASK];
 }
 
 /*
@@ -1020,7 +1020,7 @@ static int __srp_post_send(struct srp_target_port *target,
 	list.lkey   = target->srp_host->srp_dev->mr->lkey;
 
 	wr.next       = NULL;
-	wr.wr_id      = target->tx_head & SRP_SQ_SIZE;
+	wr.wr_id      = target->tx_head & SRP_SQ_MASK;
 	wr.sg_list    = &list;
 	wr.num_sge    = 1;
 	wr.opcode     = IB_WR_SEND;
@@ -1121,7 +1121,7 @@ static int srp_alloc_iu_bufs(struct srp_target_port *target)
 			goto err;
 	}
 
-	for (i = 0; i < SRP_SQ_SIZE + 1; ++i) {
+	for (i = 0; i < SRP_SQ_SIZE; ++i) {
 		target->tx_ring[i] = srp_alloc_iu(target->srp_host,
 						  srp_max_iu_len,
 						  GFP_KERNEL, DMA_TO_DEVICE);
@@ -1137,7 +1137,7 @@ err:
 		target->rx_ring[i] = NULL;
 	}
 
-	for (i = 0; i < SRP_SQ_SIZE + 1; ++i) {
+	for (i = 0; i < SRP_SQ_SIZE; ++i) {
 		srp_free_iu(target->srp_host, target->tx_ring[i]);
 		target->tx_ring[i] = NULL;
 	}
@@ -1626,9 +1626,9 @@ static struct scsi_host_template srp_template = {
 	.eh_abort_handler		= srp_abort,
 	.eh_device_reset_handler	= srp_reset_device,
 	.eh_host_reset_handler		= srp_reset_host,
-	.can_queue			= SRP_SQ_SIZE,
+	.can_queue			= SRP_CMD_SQ_SIZE,
 	.this_id			= -1,
-	.cmd_per_lun			= SRP_SQ_SIZE,
+	.cmd_per_lun			= SRP_CMD_SQ_SIZE,
 	.use_clustering			= ENABLE_CLUSTERING,
 	.shost_attrs			= srp_host_attrs
 };
@@ -1813,7 +1813,8 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
 				printk(KERN_WARNING PFX "bad max cmd_per_lun parameter '%s'\n", p);
 				goto out;
 			}
-			target->scsi_host->cmd_per_lun = min(token, SRP_SQ_SIZE);
+			target->scsi_host->cmd_per_lun
+				= min(token, SRP_CMD_SQ_SIZE);
 			break;
 
 		case SRP_OPT_IO_CLASS:
@@ -1891,7 +1892,7 @@ static ssize_t srp_create_target(struct device *dev,
 
 	INIT_LIST_HEAD(&target->free_reqs);
 	INIT_LIST_HEAD(&target->req_queue);
-	for (i = 0; i < SRP_SQ_SIZE; ++i) {
+	for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
 		target->req_ring[i].index = i;
 		list_add_tail(&target->req_ring[i].list, &target->free_reqs);
 	}
@@ -2159,6 +2160,9 @@ static int __init srp_init_module(void)
 {
 	int ret;
 
+	BUILD_BUG_ON_NOT_POWER_OF_2(SRP_SQ_SIZE);
+	BUILD_BUG_ON_NOT_POWER_OF_2(SRP_RQ_SIZE);
+
 	if (srp_sg_tablesize > 255) {
 		printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n");
 		srp_sg_tablesize = 255;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index 5a80eac..7a959d5 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -59,7 +59,14 @@ enum {
 
 	SRP_RQ_SHIFT    	= 6,
 	SRP_RQ_SIZE		= 1 << SRP_RQ_SHIFT,
-	SRP_SQ_SIZE		= SRP_RQ_SIZE - 1,
+	SRP_RQ_MASK		= SRP_RQ_SIZE - 1,
+
+	SRP_SQ_SIZE		= SRP_RQ_SIZE,
+	SRP_SQ_MASK		= SRP_SQ_SIZE - 1,
+	SRP_RSP_SQ_SIZE		= 1,
+	SRP_REQ_SQ_SIZE		= SRP_SQ_SIZE - SRP_RSP_SQ_SIZE,
+	SRP_TSK_MGMT_SQ_SIZE	= 1,
+	SRP_CMD_SQ_SIZE		= SRP_REQ_SQ_SIZE - SRP_TSK_MGMT_SQ_SIZE,
 
 	SRP_TAG_TSK_MGMT	= 1 << (SRP_RQ_SHIFT + 1),
 
@@ -144,11 +151,11 @@ struct srp_target_port {
 
 	unsigned		tx_head;
 	unsigned		tx_tail;
-	struct srp_iu	       *tx_ring[SRP_SQ_SIZE + 1];
+	struct srp_iu	       *tx_ring[SRP_SQ_SIZE];
 
 	struct list_head	free_reqs;
 	struct list_head	req_queue;
-	struct srp_request	req_ring[SRP_SQ_SIZE];
+	struct srp_request	req_ring[SRP_CMD_SQ_SIZE];
 
 	struct work_struct	work;
 
EOF
    ;;
  143391)
    cat <<EOF
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 07e10fa..e8be7b5 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -83,6 +83,11 @@ static void srp_remove_one(struct ib_device *device);
 static void srp_recv_completion(struct ib_cq *cq, void *target_ptr);
 static void srp_send_completion(struct ib_cq *cq, void *target_ptr);
 static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event);
+static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
+				      enum srp_tx_iu_type iu_type);
+static int __srp_post_send(struct srp_target_port *target,
+			   struct srp_iu *iu, int len,
+			   enum srp_send_iu_type iu_type);
 
 static struct scsi_transport_template *ib_srp_transport_template;
 
@@ -896,6 +901,80 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
 	spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
 }
 
+/*
+ * Must be called with target->scsi_host->host_lock locked to protect
+ * target->req_lim.
+ */
+static void __srp_handle_cred_req(struct srp_target_port *target,
+				  void *req_ptr, void *rsp_ptr)
+{
+	struct srp_cred_req *req = req_ptr;
+	struct srp_cred_rsp *rsp = rsp_ptr;
+
+	target->req_lim += be32_to_cpu(req->req_lim_delta);
+
+	memset(rsp, 0, sizeof *rsp);
+	rsp->opcode = SRP_CRED_RSP;
+	rsp->tag    = req->tag;
+}
+
+/*
+ * Must be called with target->scsi_host->host_lock locked to protect
+ * target->req_lim.
+ */
+static void __srp_handle_aer_req(struct srp_target_port *target,
+				 void *req_ptr, void *rsp_ptr)
+{
+	struct srp_aer_req *req = req_ptr;
+	struct srp_aer_rsp *rsp = rsp_ptr;
+
+	target->req_lim += be32_to_cpu(req->req_lim_delta);
+
+	shost_printk(KERN_ERR, target->scsi_host,
+		     PFX "ignoring AER for LUN %llu\n", be64_to_cpu(req->lun));
+
+	memset(rsp, 0, sizeof *rsp);
+	rsp->opcode = SRP_AER_RSP;
+	rsp->tag    = req->tag;
+}
+
+static void srp_handle_req(struct srp_target_port *target,
+			   struct srp_iu *req_iu,
+			   void (*req_fn)(struct srp_target_port *,
+					  void *, void *))
+{
+	struct ib_device *dev;
+	u8 *req_buf;
+	unsigned long flags;
+	struct srp_iu *rsp_iu;
+	u8 *rsp_buf;
+	int res;
+
+	dev = target->srp_host->srp_dev->dev;
+	req_buf = req_iu->buf;
+
+	spin_lock_irqsave(target->scsi_host->host_lock, flags);
+
+	rsp_iu = __srp_get_tx_iu(target, SRP_IU_RSP);
+	if (!rsp_iu)
+		goto out_unlock;
+
+	rsp_buf = rsp_iu->buf;
+
+	(*req_fn)(target, req_buf, rsp_buf);
+
+	ib_dma_sync_single_for_device(dev, rsp_iu->dma, srp_max_iu_len,
+				      DMA_TO_DEVICE);
+
+	res = __srp_post_send(target, rsp_iu, sizeof *rsp_iu, SRP_SEND_RSP);
+	if (res)
+		shost_printk(KERN_ERR, target->scsi_host,
+			     PFX "Sending response failed -- res = %d\n", res);
+
+out_unlock:
+	spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
+}
+
 static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
 {
 	struct ib_device *dev;
@@ -929,6 +1008,14 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
 			     PFX "Got target logout request\n");
 		break;
 
+	case SRP_CRED_REQ:
+		srp_handle_req(target, iu, __srp_handle_cred_req);
+		break;
+
+	case SRP_AER_REQ:
+		srp_handle_req(target, iu, __srp_handle_aer_req);
+		break;
+
 	default:
 		shost_printk(KERN_WARNING, target->scsi_host,
 			     PFX "Unhandled SRP opcode 0x%02x\n", opcode);
@@ -985,18 +1072,27 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr)
  * Must be called with target->scsi_host->host_lock held to protect
  * req_lim and tx_head.  Lock cannot be dropped between call here and
  * call to __srp_post_send().
+ *
+ * Note:
+ * An upper limit for the number of allocated information units for each
+ * request type is:
+ * - SRP_IU_CMD: SRP_CMD_SQ_SIZE, since the SCSI mid-layer never queues
+ *   more than Scsi_Host.can_queue requests.
+ * - SRP_IU_TSK_MGMT: SRP_TSK_MGMT_SQ_SIZE.
+ * - SRP_IU_RSP: 1, since a conforming SRP target never sends more than
+ *   one unanswered SRP request to an initiator.
  */
 static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
-					enum srp_request_type req_type)
+				      enum srp_tx_iu_type iu_type)
 {
-	s32 rsv = (req_type == SRP_REQ_TASK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
+	s32 rsv = (iu_type == SRP_IU_TSK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
 
 	srp_send_completion(target->send_cq, target);
 
 	if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
 		return NULL;
 
-	if (target->req_lim <= rsv) {
+	if (iu_type != SRP_IU_RSP && target->req_lim <= rsv) {
 		++target->zero_req_lim;
 		return NULL;
 	}
@@ -1009,7 +1105,8 @@ static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
  * req_lim and tx_head.
  */
 static int __srp_post_send(struct srp_target_port *target,
-			   struct srp_iu *iu, int len)
+			   struct srp_iu *iu, int len,
+			   enum srp_send_iu_type iu_type)
 {
 	struct ib_sge list;
 	struct ib_send_wr wr, *bad_wr;
@@ -1030,7 +1127,8 @@ static int __srp_post_send(struct srp_target_port *target,
 
 	if (!ret) {
 		++target->tx_head;
-		--target->req_lim;
+		if (iu_type == SRP_SEND_REQ)
+			--target->req_lim;
 	}
 
 	return ret;
@@ -1056,7 +1154,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 		return 0;
 	}
 
-	iu = __srp_get_tx_iu(target, SRP_REQ_NORMAL);
+	iu = __srp_get_tx_iu(target, SRP_IU_CMD);
 	if (!iu)
 		goto err;
 
@@ -1093,7 +1191,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 	ib_dma_sync_single_for_device(dev, iu->dma, srp_max_iu_len,
 				      DMA_TO_DEVICE);
 
-	if (__srp_post_send(target, iu, len)) {
+	if (__srp_post_send(target, iu, len, SRP_SEND_REQ)) {
 		shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n");
 		goto err_unmap;
 	}
@@ -1363,7 +1461,7 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
 
 	init_completion(&req->done);
 
-	iu = __srp_get_tx_iu(target, SRP_REQ_TASK_MGMT);
+	iu = __srp_get_tx_iu(target, SRP_IU_TSK_MGMT);
 	if (!iu)
 		goto out;
 
@@ -1376,7 +1474,7 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
 	tsk_mgmt->tsk_mgmt_func = func;
 	tsk_mgmt->task_tag 	= req->index;
 
-	if (__srp_post_send(target, iu, sizeof *tsk_mgmt))
+	if (__srp_post_send(target, iu, sizeof *tsk_mgmt, SRP_SEND_REQ))
 		goto out;
 
 	req->tsk_mgmt = iu;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index 7a959d5..854ec81 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -82,9 +82,15 @@ enum srp_target_state {
 	SRP_TARGET_REMOVED
 };
 
-enum srp_request_type {
-	SRP_REQ_NORMAL,
-	SRP_REQ_TASK_MGMT,
+enum srp_tx_iu_type {
+	SRP_IU_CMD,
+	SRP_IU_TSK_MGMT,
+	SRP_IU_RSP,
+};
+
+enum srp_send_iu_type {
+	SRP_SEND_REQ,
+	SRP_SEND_RSP,
 };
 
 struct srp_device {
diff --git a/include/scsi/srp.h b/include/scsi/srp.h
index ad178fa..1ae84db 100644
--- a/include/scsi/srp.h
+++ b/include/scsi/srp.h
@@ -239,4 +239,42 @@ struct srp_rsp {
 	u8	data[0];
 } __packed;
 
+struct srp_cred_req {
+	u8	opcode;
+	u8	sol_not;
+	u8	reserved[2];
+	__be32	req_lim_delta;
+	u64	tag;
+};
+
+struct srp_cred_rsp {
+	u8	opcode;
+	u8	reserved[7];
+	u64	tag;
+};
+
+/*
+ * The SRP spec defines the fixed portion of the AER_REQ structure to be
+ * 36 bytes, so it needs to be packed to avoid having it padded to 40 bytes
+ * on 64-bit architectures.
+ */
+struct srp_aer_req {
+	u8	opcode;
+	u8	sol_not;
+	u8	reserved[2];
+	__be32	req_lim_delta;
+	u64	tag;
+	u32	reserved2;
+	__be64	lun;
+	__be32	sense_data_len;
+	u32	reserved3;
+	u8	sense_data[0];
+} __packed;
+
+struct srp_aer_rsp {
+	u8	opcode;
+	u8	reserved[7];
+	u64	tag;
+};
+
 #endif /* SCSI_SRP_H */
EOF
    ;;
  143401)
    cat <<EOF
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index e8be7b5..17e948d 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -83,11 +83,6 @@ static void srp_remove_one(struct ib_device *device);
 static void srp_recv_completion(struct ib_cq *cq, void *target_ptr);
 static void srp_send_completion(struct ib_cq *cq, void *target_ptr);
 static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event);
-static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
-				      enum srp_tx_iu_type iu_type);
-static int __srp_post_send(struct srp_target_port *target,
-			   struct srp_iu *iu, int len,
-			   enum srp_send_iu_type iu_type);
 
 static struct scsi_transport_template *ib_srp_transport_template;
 
@@ -902,6 +897,72 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
 }
 
 /*
+ * Must be called with target->scsi_host->host_lock held to protect
+ * req_lim and tx_head.  Lock cannot be dropped between call here and
+ * call to __srp_post_send().
+ *
+ * Note:
+ * An upper limit for the number of allocated information units for each
+ * request type is:
+ * - SRP_IU_CMD: SRP_CMD_SQ_SIZE, since the SCSI mid-layer never queues
+ *   more than Scsi_Host.can_queue requests.
+ * - SRP_IU_TSK_MGMT: SRP_TSK_MGMT_SQ_SIZE.
+ * - SRP_IU_RSP: 1, since a conforming SRP target never sends more than
+ *   one unanswered SRP request to an initiator.
+ */
+static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
+				      enum srp_tx_iu_type iu_type)
+{
+	s32 rsv = (iu_type == SRP_IU_TSK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
+
+	srp_send_completion(target->send_cq, target);
+
+	if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
+		return NULL;
+
+	if (iu_type != SRP_IU_RSP && target->req_lim <= rsv) {
+		++target->zero_req_lim;
+		return NULL;
+	}
+
+	return target->tx_ring[target->tx_head & SRP_SQ_MASK];
+}
+
+/*
+ * Must be called with target->scsi_host->host_lock held to protect
+ * req_lim and tx_head.
+ */
+static int __srp_post_send(struct srp_target_port *target,
+			   struct srp_iu *iu, int len,
+			   enum srp_send_iu_type iu_type)
+{
+	struct ib_sge list;
+	struct ib_send_wr wr, *bad_wr;
+	int ret = 0;
+
+	list.addr   = iu->dma;
+	list.length = len;
+	list.lkey   = target->srp_host->srp_dev->mr->lkey;
+
+	wr.next       = NULL;
+	wr.wr_id      = target->tx_head & SRP_SQ_MASK;
+	wr.sg_list    = &list;
+	wr.num_sge    = 1;
+	wr.opcode     = IB_WR_SEND;
+	wr.send_flags = IB_SEND_SIGNALED;
+
+	ret = ib_post_send(target->qp, &wr, &bad_wr);
+
+	if (!ret) {
+		++target->tx_head;
+		if (iu_type == SRP_SEND_REQ)
+			--target->req_lim;
+	}
+
+	return ret;
+}
+
+/*
  * Must be called with target->scsi_host->host_lock locked to protect
  * target->req_lim.
  */
@@ -1068,72 +1129,6 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr)
 	}
 }
 
-/*
- * Must be called with target->scsi_host->host_lock held to protect
- * req_lim and tx_head.  Lock cannot be dropped between call here and
- * call to __srp_post_send().
- *
- * Note:
- * An upper limit for the number of allocated information units for each
- * request type is:
- * - SRP_IU_CMD: SRP_CMD_SQ_SIZE, since the SCSI mid-layer never queues
- *   more than Scsi_Host.can_queue requests.
- * - SRP_IU_TSK_MGMT: SRP_TSK_MGMT_SQ_SIZE.
- * - SRP_IU_RSP: 1, since a conforming SRP target never sends more than
- *   one unanswered SRP request to an initiator.
- */
-static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
-				      enum srp_tx_iu_type iu_type)
-{
-	s32 rsv = (iu_type == SRP_IU_TSK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
-
-	srp_send_completion(target->send_cq, target);
-
-	if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
-		return NULL;
-
-	if (iu_type != SRP_IU_RSP && target->req_lim <= rsv) {
-		++target->zero_req_lim;
-		return NULL;
-	}
-
-	return target->tx_ring[target->tx_head & SRP_SQ_MASK];
-}
-
-/*
- * Must be called with target->scsi_host->host_lock held to protect
- * req_lim and tx_head.
- */
-static int __srp_post_send(struct srp_target_port *target,
-			   struct srp_iu *iu, int len,
-			   enum srp_send_iu_type iu_type)
-{
-	struct ib_sge list;
-	struct ib_send_wr wr, *bad_wr;
-	int ret = 0;
-
-	list.addr   = iu->dma;
-	list.length = len;
-	list.lkey   = target->srp_host->srp_dev->mr->lkey;
-
-	wr.next       = NULL;
-	wr.wr_id      = target->tx_head & SRP_SQ_MASK;
-	wr.sg_list    = &list;
-	wr.num_sge    = 1;
-	wr.opcode     = IB_WR_SEND;
-	wr.send_flags = IB_SEND_SIGNALED;
-
-	ret = ib_post_send(target->qp, &wr, &bad_wr);
-
-	if (!ret) {
-		++target->tx_head;
-		if (iu_type == SRP_SEND_REQ)
-			--target->req_lim;
-	}
-
-	return ret;
-}
-
 static int srp_queuecommand(struct scsi_cmnd *scmnd,
 			    void (*done)(struct scsi_cmnd *))
 {
EOF
    ;;
  143411)
    cat <<EOF
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 17e948d..2de894e 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1345,8 +1345,13 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
 			target->max_ti_iu_len = be32_to_cpu(rsp->max_ti_iu_len);
 			target->req_lim       = be32_to_cpu(rsp->req_lim_delta);
 
-			target->scsi_host->can_queue = min(target->req_lim,
-							   target->scsi_host->can_queue);
+			/*
+			 * Set can_queue such that we don't needlessly
+			 * bounce requests back to the SCSI mid-layer.
+			 */
+			target->scsi_host->can_queue
+				= min(target->req_lim - SRP_TSK_MGMT_SQ_SIZE,
+				      target->scsi_host->can_queue);
 		} else {
 			shost_printk(KERN_WARNING, target->scsi_host,
 				    PFX "Unhandled RSP opcode %#x\n", opcode);
EOF
    ;;
  143421)
    cat <<EOF
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 2de894e..a2935e3 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1157,7 +1157,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 	ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len,
 				   DMA_TO_DEVICE);
 
-	req = list_entry(target->free_reqs.next, struct srp_request, list);
+	req = list_first_entry(&target->free_reqs, struct srp_request, list);
 
 	scmnd->scsi_done     = done;
 	scmnd->result        = 0;
EOF
    ;;
  *)
    echo ERROR
    ;;
  esac
}

get_locking_per_lun_patch() {
cat <<EOF
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index a2935e3..f2cc342 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -81,6 +81,7 @@ MODULE_PARM_DESC(mellanox_workarounds,
 static void srp_add_one(struct ib_device *device);
 static void srp_remove_one(struct ib_device *device);
 static void srp_recv_completion(struct ib_cq *cq, void *target_ptr);
+static void __srp_send_completion(struct ib_cq *cq, void *target_ptr);
 static void srp_send_completion(struct ib_cq *cq, void *target_ptr);
 static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event);
 
@@ -441,18 +442,30 @@ static void srp_disconnect_target(struct srp_target_port *target)
 	wait_for_completion(&target->done);
 }
 
+static bool srp_port_change_state(struct srp_target_port *target,
+				  enum srp_target_state old,
+				  enum srp_target_state new)
+{
+	unsigned long flags;
+	bool ret;
+
+	spin_lock_irqsave(&target->lock, flags);
+	if (target->state == old) {
+		target->state = new;
+		ret = true;
+	} else
+		ret = false;
+	spin_unlock_irqrestore(&target->lock, flags);
+	return ret;
+}
+
 static void srp_remove_work(struct work_struct *work)
 {
 	struct srp_target_port *target =
 		container_of(work, struct srp_target_port, work);
 
-	spin_lock_irq(target->scsi_host->host_lock);
-	if (target->state != SRP_TARGET_DEAD) {
-		spin_unlock_irq(target->scsi_host->host_lock);
+	if (!srp_port_change_state(target, SRP_TARGET_DEAD, SRP_TARGET_REMOVED))
 		return;
-	}
-	target->state = SRP_TARGET_REMOVED;
-	spin_unlock_irq(target->scsi_host->host_lock);
 
 	spin_lock(&target->srp_host->target_lock);
 	list_del(&target->list);
@@ -541,8 +554,13 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
 
 static void srp_remove_req(struct srp_target_port *target, struct srp_request *req)
 {
+	unsigned long flags;
+
 	srp_unmap_data(req->scmnd, target, req);
-	list_move_tail(&req->list, &target->free_reqs);
+	req->scmnd = NULL;
+	spin_lock_irqsave(&target->lock, flags);
+	list_add_tail(&req->list, &target->free_reqs);
+	spin_unlock_irqrestore(&target->lock, flags);
 }
 
 static void srp_reset_req(struct srp_target_port *target, struct srp_request *req)
@@ -555,17 +573,14 @@ static void srp_reset_req(struct srp_target_port *target, struct srp_request *re
 static int srp_reconnect_target(struct srp_target_port *target)
 {
 	struct ib_qp_attr qp_attr;
-	struct srp_request *req, *tmp;
 	struct ib_wc wc;
 	int ret;
+	int i;
 
-	spin_lock_irq(target->scsi_host->host_lock);
-	if (target->state != SRP_TARGET_LIVE) {
-		spin_unlock_irq(target->scsi_host->host_lock);
+	if (!srp_port_change_state(target, SRP_TARGET_LIVE,
+				   SRP_TARGET_CONNECTING)) {
 		return -EAGAIN;
 	}
-	target->state = SRP_TARGET_CONNECTING;
-	spin_unlock_irq(target->scsi_host->host_lock);
 
 	srp_disconnect_target(target);
 	/*
@@ -590,27 +605,20 @@ static int srp_reconnect_target(struct srp_target_port *target)
 	while (ib_poll_cq(target->send_cq, 1, &wc) > 0)
 		; /* nothing */
 
-	spin_lock_irq(target->scsi_host->host_lock);
-	list_for_each_entry_safe(req, tmp, &target->req_queue, list)
-		srp_reset_req(target, req);
-	spin_unlock_irq(target->scsi_host->host_lock);
-
-	target->rx_head	 = 0;
-	target->tx_head	 = 0;
-	target->tx_tail  = 0;
+	for (i = 0; i < ARRAY_SIZE(target->req_ring); ++i)
+		if (target->req_ring[i].scmnd)
+			srp_reset_req(target, &target->req_ring[i]);
 
 	target->qp_in_error = 0;
 	ret = srp_connect_target(target);
 	if (ret)
 		goto err;
 
-	spin_lock_irq(target->scsi_host->host_lock);
-	if (target->state == SRP_TARGET_CONNECTING) {
+	if (srp_port_change_state(target, SRP_TARGET_CONNECTING,
+				  SRP_TARGET_LIVE))
 		ret = 0;
-		target->state = SRP_TARGET_LIVE;
-	} else
+	else
 		ret = -EAGAIN;
-	spin_unlock_irq(target->scsi_host->host_lock);
 
 	return ret;
 
@@ -624,13 +632,11 @@ err:
 	 * be in the context of the SCSI error handler now, which
 	 * would deadlock if we call scsi_remove_host().
 	 */
-	spin_lock_irq(target->scsi_host->host_lock);
-	if (target->state == SRP_TARGET_CONNECTING) {
-		target->state = SRP_TARGET_DEAD;
+	if (srp_port_change_state(target, SRP_TARGET_CONNECTING,
+				  SRP_TARGET_DEAD)) {
 		INIT_WORK(&target->work, srp_remove_work);
 		schedule_work(&target->work);
 	}
-	spin_unlock_irq(target->scsi_host->host_lock);
 
 	return ret;
 }
@@ -811,20 +817,12 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
 	return len;
 }
 
-static int srp_post_recv(struct srp_target_port *target)
+static int srp_post_recv(struct srp_target_port *target, struct srp_iu *iu)
 {
-	unsigned long flags;
-	struct srp_iu *iu;
 	struct ib_sge list;
 	struct ib_recv_wr wr, *bad_wr;
-	unsigned int next;
-	int ret;
-
-	spin_lock_irqsave(target->scsi_host->host_lock, flags);
 
-	next	 = target->rx_head & SRP_RQ_MASK;
-	wr.wr_id = next;
-	iu	 = target->rx_ring[next];
+	wr.wr_id    = iu->index;
 
 	list.addr   = iu->dma;
 	list.length = iu->size;
@@ -834,13 +832,7 @@ static int srp_post_recv(struct srp_target_port *target)
 	wr.sg_list  = &list;
 	wr.num_sge  = 1;
 
-	ret = ib_post_recv(target->qp, &wr, &bad_wr);
-	if (!ret)
-		++target->rx_head;
-
-	spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
-
-	return ret;
+	return ib_post_recv(target->qp, &wr, &bad_wr);
 }
 
 static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
@@ -852,9 +844,9 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
 
 	delta = (s32) be32_to_cpu(rsp->req_lim_delta);
 
-	spin_lock_irqsave(target->scsi_host->host_lock, flags);
-
+	spin_lock_irqsave(&target->lock, flags);
 	target->req_lim += delta;
+	spin_unlock_irqrestore(&target->lock, flags);
 
 	req = &target->req_ring[rsp->tag & ~SRP_TAG_TSK_MGMT];
 
@@ -892,14 +884,12 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
 		} else
 			req->cmd_done = 1;
 	}
-
-	spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
 }
 
 /*
- * Must be called with target->scsi_host->host_lock held to protect
- * req_lim and tx_head.  Lock cannot be dropped between call here and
- * call to __srp_post_send().
+ * It is the responsability of the caller to put back the returned information
+ * unit in the target->tx_free list and to increment target->req_lim if an
+ * error occurs before __srp_post_send() is called.
  *
  * Note:
  * An upper limit for the number of allocated information units for each
@@ -914,24 +904,29 @@ static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
 				      enum srp_tx_iu_type iu_type)
 {
 	s32 rsv = (iu_type == SRP_IU_TSK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
+	struct srp_iu *res = NULL;
+	unsigned long flags;
 
-	srp_send_completion(target->send_cq, target);
+	spin_lock_irqsave(&target->lock, flags);
 
-	if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
-		return NULL;
+	__srp_send_completion(target->send_cq, target);
+
+	if (list_empty(&target->tx_free))
+		goto out;
 
 	if (iu_type != SRP_IU_RSP && target->req_lim <= rsv) {
 		++target->zero_req_lim;
-		return NULL;
+		goto out;
 	}
 
-	return target->tx_ring[target->tx_head & SRP_SQ_MASK];
+	--target->req_lim;
+	res = list_first_entry(&target->tx_free, struct srp_iu, list);
+	list_del(&res->list);
+out:
+	spin_unlock_irqrestore(&target->lock, flags);
+	return res;
 }
 
-/*
- * Must be called with target->scsi_host->host_lock held to protect
- * req_lim and tx_head.
- */
 static int __srp_post_send(struct srp_target_port *target,
 			   struct srp_iu *iu, int len,
 			   enum srp_send_iu_type iu_type)
@@ -945,7 +940,7 @@ static int __srp_post_send(struct srp_target_port *target,
 	list.lkey   = target->srp_host->srp_dev->mr->lkey;
 
 	wr.next       = NULL;
-	wr.wr_id      = target->tx_head & SRP_SQ_MASK;
+	wr.wr_id      = iu->index;
 	wr.sg_list    = &list;
 	wr.num_sge    = 1;
 	wr.opcode     = IB_WR_SEND;
@@ -953,43 +948,45 @@ static int __srp_post_send(struct srp_target_port *target,
 
 	ret = ib_post_send(target->qp, &wr, &bad_wr);
 
-	if (!ret) {
-		++target->tx_head;
+	if (ret) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&target->lock, flags);
 		if (iu_type == SRP_SEND_REQ)
-			--target->req_lim;
+			target->req_lim++;
+		list_add(&iu->list, &target->tx_free);
+		spin_unlock_irqrestore(&target->lock, flags);
 	}
 
 	return ret;
 }
 
-/*
- * Must be called with target->scsi_host->host_lock locked to protect
- * target->req_lim.
- */
-static void __srp_handle_cred_req(struct srp_target_port *target,
-				  void *req_ptr, void *rsp_ptr)
+static void srp_handle_cred_req(struct srp_target_port *target,
+				void *req_ptr, void *rsp_ptr)
 {
+	unsigned long flags;
 	struct srp_cred_req *req = req_ptr;
 	struct srp_cred_rsp *rsp = rsp_ptr;
 
+	spin_lock_irqsave(&target->lock, flags);
 	target->req_lim += be32_to_cpu(req->req_lim_delta);
+	spin_unlock_irqrestore(&target->lock, flags);
 
 	memset(rsp, 0, sizeof *rsp);
 	rsp->opcode = SRP_CRED_RSP;
 	rsp->tag    = req->tag;
 }
 
-/*
- * Must be called with target->scsi_host->host_lock locked to protect
- * target->req_lim.
- */
-static void __srp_handle_aer_req(struct srp_target_port *target,
-				 void *req_ptr, void *rsp_ptr)
+static void srp_handle_aer_req(struct srp_target_port *target,
+			       void *req_ptr, void *rsp_ptr)
 {
+	unsigned long flags;
 	struct srp_aer_req *req = req_ptr;
 	struct srp_aer_rsp *rsp = rsp_ptr;
 
+	spin_lock_irqsave(&target->lock, flags);
 	target->req_lim += be32_to_cpu(req->req_lim_delta);
+	spin_unlock_irqrestore(&target->lock, flags);
 
 	shost_printk(KERN_ERR, target->scsi_host,
 		     PFX "ignoring AER for LUN %llu\n", be64_to_cpu(req->lun));
@@ -1006,7 +1003,6 @@ static void srp_handle_req(struct srp_target_port *target,
 {
 	struct ib_device *dev;
 	u8 *req_buf;
-	unsigned long flags;
 	struct srp_iu *rsp_iu;
 	u8 *rsp_buf;
 	int res;
@@ -1014,11 +1010,9 @@ static void srp_handle_req(struct srp_target_port *target,
 	dev = target->srp_host->srp_dev->dev;
 	req_buf = req_iu->buf;
 
-	spin_lock_irqsave(target->scsi_host->host_lock, flags);
-
 	rsp_iu = __srp_get_tx_iu(target, SRP_IU_RSP);
 	if (!rsp_iu)
-		goto out_unlock;
+		return;
 
 	rsp_buf = rsp_iu->buf;
 
@@ -1031,9 +1025,6 @@ static void srp_handle_req(struct srp_target_port *target,
 	if (res)
 		shost_printk(KERN_ERR, target->scsi_host,
 			     PFX "Sending response failed -- res = %d\n", res);
-
-out_unlock:
-	spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
 }
 
 static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
@@ -1070,11 +1061,11 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
 		break;
 
 	case SRP_CRED_REQ:
-		srp_handle_req(target, iu, __srp_handle_cred_req);
+		srp_handle_req(target, iu, srp_handle_cred_req);
 		break;
 
 	case SRP_AER_REQ:
-		srp_handle_req(target, iu, __srp_handle_aer_req);
+		srp_handle_req(target, iu, srp_handle_aer_req);
 		break;
 
 	default:
@@ -1086,7 +1077,7 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
 	ib_dma_sync_single_for_device(dev, iu->dma, target->max_ti_iu_len,
 				      DMA_FROM_DEVICE);
 
-	res = srp_post_recv(target);
+	res = srp_post_recv(target, iu);
 	if (res != 0)
 		shost_printk(KERN_ERR, target->scsi_host,
 			     PFX "Recv failed with error code %d\n", res);
@@ -1095,38 +1086,59 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
 static void srp_recv_completion(struct ib_cq *cq, void *target_ptr)
 {
 	struct srp_target_port *target = target_ptr;
-	struct ib_wc wc;
+	struct ib_wc *const wc = target->recv_wc;
+	int i, n;
 
 	ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
-	while (ib_poll_cq(cq, 1, &wc) > 0) {
-		if (wc.status) {
-			shost_printk(KERN_ERR, target->scsi_host,
-				     PFX "failed receive status %d\n",
-				     wc.status);
-			target->qp_in_error = 1;
-			break;
-		}
+	while ((n = ib_poll_cq(cq, ARRAY_SIZE(target->recv_wc), wc)) > 0) {
+		for (i = 0; i < n; ++i) {
+			if (wc[i].status) {
+				shost_printk(KERN_ERR, target->scsi_host,
+					     PFX "failed receive status %d\n",
+					     wc[i].status);
+				target->qp_in_error = 1;
+				goto out;
+			}
 
-		srp_handle_recv(target, &wc);
+			srp_handle_recv(target, &wc[i]);
+		}
 	}
+out:
+	return;
 }
 
-static void srp_send_completion(struct ib_cq *cq, void *target_ptr)
+static void __srp_send_completion(struct ib_cq *cq, void *target_ptr)
 {
 	struct srp_target_port *target = target_ptr;
-	struct ib_wc wc;
+	struct ib_wc *const wc = target->send_wc;
+	int i, n;
+
+	while ((n = ib_poll_cq(cq, ARRAY_SIZE(target->send_wc), wc)) > 0) {
+		for (i = 0; i < n; ++i) {
+			if (wc[i].status) {
+				shost_printk(KERN_ERR, target->scsi_host,
+					     PFX "failed send status %d\n",
+					     wc[i].status);
+				target->qp_in_error = 1;
+				goto out;
+			}
 
-	while (ib_poll_cq(cq, 1, &wc) > 0) {
-		if (wc.status) {
-			shost_printk(KERN_ERR, target->scsi_host,
-				     PFX "failed send status %d\n",
-				     wc.status);
-			target->qp_in_error = 1;
-			break;
+			list_add_tail(&target->tx_ring[wc[i].wr_id]->list,
+				      &target->tx_free);
 		}
-
-		++target->tx_tail;
 	}
+out:
+	return;
+}
+
+static void srp_send_completion(struct ib_cq *cq, void *target_ptr)
+{
+	struct srp_target_port *target = target_ptr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&target->lock, flags);
+	__srp_send_completion(cq, target_ptr);
+	spin_unlock_irqrestore(&target->lock, flags);
 }
 
 static int srp_queuecommand(struct scsi_cmnd *scmnd,
@@ -1138,6 +1150,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 	struct srp_cmd *cmd;
 	struct ib_device *dev;
 	int len;
+	unsigned long flags;
 
 	if (target->state == SRP_TARGET_CONNECTING)
 		goto err;
@@ -1157,7 +1170,10 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 	ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len,
 				   DMA_TO_DEVICE);
 
+	spin_lock_irqsave(&target->lock, flags);
 	req = list_first_entry(&target->free_reqs, struct srp_request, list);
+	list_del(&req->list);
+	spin_unlock_irqrestore(&target->lock, flags);
 
 	scmnd->scsi_done     = done;
 	scmnd->result        = 0;
@@ -1180,7 +1196,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 	if (len < 0) {
 		shost_printk(KERN_ERR, target->scsi_host,
 			     PFX "Failed to map data\n");
-		goto err;
+		goto err_putback;
 	}
 
 	ib_dma_sync_single_for_device(dev, iu->dma, srp_max_iu_len,
@@ -1188,16 +1204,22 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
 
 	if (__srp_post_send(target, iu, len, SRP_SEND_REQ)) {
 		shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n");
+		spin_lock_irqsave(&target->lock, flags);
+		list_del(&req->list);
+		spin_unlock_irqrestore(&target->lock, flags);
 		goto err_unmap;
 	}
 
-	list_move_tail(&req->list, &target->req_queue);
-
 	return 0;
 
 err_unmap:
 	srp_unmap_data(scmnd, target, req);
 
+err_putback:
+	spin_lock_irqsave(&target->lock, flags);
+	list_add(&req->list, &target->free_reqs);
+	spin_unlock_irqrestore(&target->lock, flags);
+
 err:
 	return SCSI_MLQUEUE_HOST_BUSY;
 }
@@ -1212,14 +1234,19 @@ static int srp_alloc_iu_bufs(struct srp_target_port *target)
 						  GFP_KERNEL, DMA_FROM_DEVICE);
 		if (!target->rx_ring[i])
 			goto err;
+		target->rx_ring[i]->index = i;
 	}
 
+	INIT_LIST_HEAD(&target->tx_free);
+
 	for (i = 0; i < SRP_SQ_SIZE; ++i) {
 		target->tx_ring[i] = srp_alloc_iu(target->srp_host,
 						  srp_max_iu_len,
 						  GFP_KERNEL, DMA_TO_DEVICE);
 		if (!target->tx_ring[i])
 			goto err;
+		target->tx_ring[i]->index = i;
+		list_add_tail(&target->tx_ring[i]->list, &target->tx_free);
 	}
 
 	return 0;
@@ -1381,7 +1408,8 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
 			break;
 
 		for (i = 0; i < SRP_RQ_SIZE; i++) {
-			target->status = srp_post_recv(target);
+			target->status = srp_post_recv(target,
+						       target->rx_ring[i]);
 			if (target->status)
 				break;
 		}
@@ -1451,8 +1479,6 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
 	struct srp_iu *iu;
 	struct srp_tsk_mgmt *tsk_mgmt;
 
-	spin_lock_irq(target->scsi_host->host_lock);
-
 	if (target->state == SRP_TARGET_DEAD ||
 	    target->state == SRP_TARGET_REMOVED) {
 		req->scmnd->result = DID_BAD_TARGET << 16;
@@ -1479,8 +1505,6 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
 
 	req->tsk_mgmt = iu;
 
-	spin_unlock_irq(target->scsi_host->host_lock);
-
 	if (!wait_for_completion_timeout(&req->done,
 					 msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS)))
 		return -1;
@@ -1488,7 +1512,6 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
 	return 0;
 
 out:
-	spin_unlock_irq(target->scsi_host->host_lock);
 	return -1;
 }
 
@@ -1519,8 +1542,6 @@ static int srp_abort(struct scsi_cmnd *scmnd)
 	if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK))
 		return FAILED;
 
-	spin_lock_irq(target->scsi_host->host_lock);
-
 	if (req->cmd_done) {
 		srp_remove_req(target, req);
 		scmnd->scsi_done(scmnd);
@@ -1530,15 +1551,14 @@ static int srp_abort(struct scsi_cmnd *scmnd)
 	} else
 		ret = FAILED;
 
-	spin_unlock_irq(target->scsi_host->host_lock);
-
 	return ret;
 }
 
 static int srp_reset_device(struct scsi_cmnd *scmnd)
 {
 	struct srp_target_port *target = host_to_target(scmnd->device->host);
-	struct srp_request *req, *tmp;
+	struct srp_request *req;
+	int i;
 
 	shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
 
@@ -1551,14 +1571,10 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
 	if (req->tsk_status)
 		return FAILED;
 
-	spin_lock_irq(target->scsi_host->host_lock);
-
-	list_for_each_entry_safe(req, tmp, &target->req_queue, list)
-		if (req->scmnd->device == scmnd->device)
+	for (i = 0; i < ARRAY_SIZE(target->req_ring); ++i)
+		if (req->scmnd && req->scmnd->device == scmnd->device)
 			srp_reset_req(target, req);
 
-	spin_unlock_irq(target->scsi_host->host_lock);
-
 	return SUCCESS;
 }
 
@@ -1575,6 +1591,26 @@ static int srp_reset_host(struct scsi_cmnd *scmnd)
 	return ret;
 }
 
+static ssize_t show_max_host_blocked(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct Scsi_Host *host = class_to_shost(dev);
+
+	return sprintf(buf, "%d\n", max(1U, host->max_host_blocked));
+}
+
+
+static ssize_t set_max_host_blocked(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	struct Scsi_Host *host = class_to_shost(dev);
+
+	host->max_host_blocked = max(1UL, simple_strtoul(buf, NULL, 0));
+	return count;
+}
+
 static ssize_t show_id_ext(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 {
@@ -1690,6 +1726,8 @@ static ssize_t show_local_ib_device(struct device *dev,
 	return sprintf(buf, "%s\n", target->srp_host->srp_dev->dev->name);
 }
 
+static DEVICE_ATTR(max_host_blocked, S_IWUSR | S_IRUGO,
+		   show_max_host_blocked, set_max_host_blocked);
 static DEVICE_ATTR(id_ext,	    S_IRUGO, show_id_ext,	   NULL);
 static DEVICE_ATTR(ioc_guid,	    S_IRUGO, show_ioc_guid,	   NULL);
 static DEVICE_ATTR(service_id,	    S_IRUGO, show_service_id,	   NULL);
@@ -1702,6 +1740,7 @@ static DEVICE_ATTR(local_ib_port,   S_IRUGO, show_local_ib_port,   NULL);
 static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
 
 static struct device_attribute *srp_host_attrs[] = {
+	&dev_attr_max_host_blocked,
 	&dev_attr_id_ext,
 	&dev_attr_ioc_guid,
 	&dev_attr_service_id,
@@ -1981,6 +2020,7 @@ static ssize_t srp_create_target(struct device *dev,
 	target_host->transportt = ib_srp_transport_template;
 	target_host->max_lun     = SRP_MAX_LUN;
 	target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
+	target_host->unlocked_qcmds = true;
 
 	target = host_to_target(target_host);
 
@@ -1988,8 +2028,9 @@ static ssize_t srp_create_target(struct device *dev,
 	target->scsi_host  = target_host;
 	target->srp_host   = host;
 
+	spin_lock_init(&target->lock);
+
 	INIT_LIST_HEAD(&target->free_reqs);
-	INIT_LIST_HEAD(&target->req_queue);
 	for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
 		target->req_ring[i].index = i;
 		list_add_tail(&target->req_ring[i].list, &target->free_reqs);
@@ -2200,6 +2241,7 @@ static void srp_remove_one(struct ib_device *device)
 	struct srp_host *host, *tmp_host;
 	LIST_HEAD(target_list);
 	struct srp_target_port *target, *tmp_target;
+	unsigned long flags;
 
 	srp_dev = ib_get_client_data(device, &srp_client);
 
@@ -2217,9 +2259,9 @@ static void srp_remove_one(struct ib_device *device)
 		 */
 		spin_lock(&host->target_lock);
 		list_for_each_entry(target, &host->target_list, list) {
-			spin_lock_irq(target->scsi_host->host_lock);
+			spin_lock_irqsave(&target->lock, flags);
 			target->state = SRP_TARGET_REMOVED;
-			spin_unlock_irq(target->scsi_host->host_lock);
+			spin_unlock_irqrestore(&target->lock, flags);
 		}
 		spin_unlock(&host->target_lock);
 
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index 854ec81..1d5ab5d 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -146,21 +146,23 @@ struct srp_target_port {
 	struct ib_cq	       *recv_cq;
 	struct ib_cq	       *send_cq;
 	struct ib_qp	       *qp;
+	struct ib_wc		send_wc[16];
+	struct ib_wc		recv_wc[16];
 
 	int			max_ti_iu_len;
+
+	spinlock_t		lock;
+
 	s32			req_lim;
 
 	int			zero_req_lim;
 
-	unsigned		rx_head;
 	struct srp_iu	       *rx_ring[SRP_RQ_SIZE];
 
-	unsigned		tx_head;
-	unsigned		tx_tail;
+	struct list_head	tx_free;
 	struct srp_iu	       *tx_ring[SRP_SQ_SIZE];
 
 	struct list_head	free_reqs;
-	struct list_head	req_queue;
 	struct srp_request	req_ring[SRP_CMD_SQ_SIZE];
 
 	struct work_struct	work;
@@ -173,9 +175,11 @@ struct srp_target_port {
 };
 
 struct srp_iu {
+	struct list_head	list;
 	u64			dma;
 	void		       *buf;
 	size_t			size;
+	short			index;
 	enum dma_data_direction	direction;
 };
 
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index ad0ed21..2f9110c 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -737,23 +737,31 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 		goto out;
 	}
 
-	spin_lock_irqsave(host->host_lock, flags);
-	/*
-	 * AK: unlikely race here: for some reason the timer could
-	 * expire before the serial number is set up below.
-	 *
-	 * TODO: kill serial or move to blk layer
-	 */
-	scsi_cmd_get_serial(host, cmd); 
+	if (!host->unlocked_qcmds) {
+		spin_lock_irqsave(host->host_lock, flags);
+		/*
+		 * AK: unlikely race here: for some reason the timer could
+		 * expire before the serial number is set up below.
+		 *
+		 * TODO: kill serial or move to blk layer
+		 */
+		scsi_cmd_get_serial(host, cmd); 
+	} else
+		cmd->serial_number = 1;
 
 	if (unlikely(host->shost_state == SHOST_DEL)) {
+		if (host->unlocked_qcmds)
+			spin_lock_irqsave(host->host_lock, flags);
 		cmd->result = (DID_NO_CONNECT << 16);
 		scsi_done(cmd);
+		spin_unlock_irqrestore(host->host_lock, flags);
 	} else {
 		trace_scsi_dispatch_cmd_start(cmd);
 		rtn = host->hostt->queuecommand(cmd, scsi_done);
+		if (!host->unlocked_qcmds)
+			spin_unlock_irqrestore(host->host_lock, flags);
 	}
-	spin_unlock_irqrestore(host->host_lock, flags);
+
 	if (rtn) {
 		trace_scsi_dispatch_cmd_error(cmd, rtn);
 		if (rtn != SCSI_MLQUEUE_DEVICE_BUSY &&
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index b7bdecb..1814c51 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -636,6 +636,9 @@ struct Scsi_Host {
 	/* Asynchronous scan in progress */
 	unsigned async_scan:1;
 
+	/* call queuecommand without Scsi_Host lock held */
+	unsigned unlocked_qcmds:1;
+
 	/*
 	 * Optional work queue to be utilized by the transport
 	 */

EOF
}

# Source: http://git.kernel.dk/?p=linux-2.6-block.git;a=patch;h=$commit
get_block_layer_patch() {
case "$1" in
  5a00f237eb167a5e98d5f3bb56e11e4da406a5bc)
    cat <<EOF
index 32a1c12..1a9403e 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -672,40 +672,6 @@ blk_alloc_request(struct request_queue *q, int flags, int priv, gfp_t gfp_mask)
 	return rq;
 }
 
-/*
- * ioc_batching returns true if the ioc is a valid batching request and
- * should be given priority access to a request.
- */
-static inline int ioc_batching(struct request_queue *q, struct io_context *ioc)
-{
-	if (!ioc)
-		return 0;
-
-	/*
-	 * Make sure the process is able to allocate at least 1 request
-	 * even if the batch times out, otherwise we could theoretically
-	 * lose wakeups.
-	 */
-	return ioc->nr_batch_requests == q->nr_batching ||
-		(ioc->nr_batch_requests > 0
-		&& time_before(jiffies, ioc->last_waited + BLK_BATCH_TIME));
-}
-
-/*
- * ioc_set_batching sets ioc to be a new "batcher" if it is not one. This
- * will cause the process to be a "batcher" on all queues in the system. This
- * is the behaviour we want though - once it gets a wakeup it should be given
- * a nice run.
- */
-static void ioc_set_batching(struct request_queue *q, struct io_context *ioc)
-{
-	if (!ioc || ioc_batching(q, ioc))
-		return;
-
-	ioc->nr_batch_requests = q->nr_batching;
-	ioc->last_waited = jiffies;
-}
-
 static void __freed_request(struct request_queue *q, int sync)
 {
 	struct request_list *rl = &q->rq;
@@ -749,7 +715,6 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
 {
 	struct request *rq = NULL;
 	struct request_list *rl = &q->rq;
-	struct io_context *ioc = NULL;
 	const bool is_sync = rw_is_sync(rw_flags) != 0;
 	int may_queue, priv;
 
@@ -757,41 +722,6 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
 	if (may_queue == ELV_MQUEUE_NO)
 		goto rq_starved;
 
-	if (rl->count[is_sync]+1 >= queue_congestion_on_threshold(q)) {
-		if (rl->count[is_sync]+1 >= q->nr_requests) {
-			ioc = current_io_context(GFP_ATOMIC, q->node);
-			/*
-			 * The queue will fill after this allocation, so set
-			 * it as full, and mark this process as "batching".
-			 * This process will be allowed to complete a batch of
-			 * requests, others will be blocked.
-			 */
-			if (!blk_queue_full(q, is_sync)) {
-				ioc_set_batching(q, ioc);
-				blk_set_queue_full(q, is_sync);
-			} else {
-				if (may_queue != ELV_MQUEUE_MUST
-						&& !ioc_batching(q, ioc)) {
-					/*
-					 * The queue is full and the allocating
-					 * process is not a "batcher", and not
-					 * exempted by the IO scheduler
-					 */
-					goto out;
-				}
-			}
-		}
-		blk_set_queue_congested(q, is_sync);
-	}
-
-	/*
-	 * Only allow batching queuers to allocate up to 50% over the defined
-	 * limit of requests, otherwise we could have thousands of requests
-	 * allocated with any setting of ->nr_requests
-	 */
-	if (rl->count[is_sync] >= (3 * q->nr_requests / 2))
-		goto out;
-
 	rl->count[is_sync]++;
 	rl->starved[is_sync] = 0;
 
@@ -829,15 +759,6 @@ rq_starved:
 		goto out;
 	}
 
-	/*
-	 * ioc may be NULL here, and ioc_batching will be false. That's
-	 * OK, if the queue is under the request limit then requests need
-	 * not count toward the nr_batch_requests limit. There will always
-	 * be some limit enforced by BLK_BATCH_TIME.
-	 */
-	if (ioc_batching(q, ioc))
-		ioc->nr_batch_requests--;
-
 	trace_block_getrq(q, bio, rw_flags & 1);
 out:
 	return rq;
@@ -858,7 +779,6 @@ static struct request *get_request_wait(struct request_queue *q, int rw_flags,
 	rq = get_request(q, rw_flags, bio, GFP_NOIO);
 	while (!rq) {
 		DEFINE_WAIT(wait);
-		struct io_context *ioc;
 		struct request_list *rl = &q->rq;
 
 		prepare_to_wait_exclusive(&rl->wait[is_sync], &wait,
@@ -870,15 +790,6 @@ static struct request *get_request_wait(struct request_queue *q, int rw_flags,
 		spin_unlock_irq(q->queue_lock);
 		io_schedule();
 
-		/*
-		 * After sleeping, we become a "batching" process and
-		 * will be able to allocate at least one request, and
-		 * up to a big batch of them for a small period time.
-		 * See ioc_batching, ioc_set_batching
-		 */
-		ioc = current_io_context(GFP_NOIO, q->node);
-		ioc_set_batching(q, ioc);
-
 		spin_lock_irq(q->queue_lock);
 		finish_wait(&rl->wait[is_sync], &wait);
 
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index d22c4c5..49beb97 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -92,8 +92,6 @@ struct io_context *alloc_io_context(gfp_t gfp_flags, int node)
 		spin_lock_init(&ret->lock);
 		ret->ioprio_changed = 0;
 		ret->ioprio = 0;
-		ret->last_waited = 0; /* doesn't matter... */
-		ret->nr_batch_requests = 0; /* because this is 0 */
 		INIT_RADIX_TREE(&ret->radix_root, GFP_ATOMIC | __GFP_HIGH);
 		INIT_HLIST_HEAD(&ret->cic_list);
 		ret->ioc_data = NULL;
diff --git a/block/blk-settings.c b/block/blk-settings.c
index a234f4b..4ce5d80 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -161,7 +161,6 @@ void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn)
 	q->make_request_fn = mfn;
 	blk_queue_dma_alignment(q, 511);
 	blk_queue_congestion_threshold(q);
-	q->nr_batching = BLK_BATCH_REQ;
 
 	q->unplug_thresh = 4;		/* hmm */
 	q->unplug_delay = msecs_to_jiffies(3);	/* 3 milliseconds */
diff --git a/block/blk.h b/block/blk.h
index d6b911a..709e351 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -1,12 +1,6 @@
 #ifndef BLK_INTERNAL_H
 #define BLK_INTERNAL_H
 
-/* Amount of time in which a process may batch requests */
-#define BLK_BATCH_TIME	(HZ/50UL)
-
-/* Number of requests a "batching" process may submit */
-#define BLK_BATCH_REQ	32
-
 extern struct kmem_cache *blk_requestq_cachep;
 extern struct kobj_type blk_queue_ktype;
 
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index dd318ff..2ad9087 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -164,7 +164,6 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
 	unsigned long num_sync_run;
 	unsigned long batch_run = 0;
 	unsigned long limit;
-	unsigned long last_waited = 0;
 	int force_reg = 0;
 
 	bdi = blk_get_backing_dev_info(device->bdev);
@@ -279,39 +278,6 @@ loop_lock:
 		 */
 		if (pending && bdi_write_congested(bdi) && batch_run > 8 &&
 		    fs_info->fs_devices->open_devices > 1) {
-			struct io_context *ioc;
-
-			ioc = current->io_context;
-
-			/*
-			 * the main goal here is that we don't want to
-			 * block if we're going to be able to submit
-			 * more requests without blocking.
-			 *
-			 * This code does two great things, it pokes into
-			 * the elevator code from a filesystem _and_
-			 * it makes assumptions about how batching works.
-			 */
-			if (ioc && ioc->nr_batch_requests > 0 &&
-			    time_before(jiffies, ioc->last_waited + HZ/50UL) &&
-			    (last_waited == 0 ||
-			     ioc->last_waited == last_waited)) {
-				/*
-				 * we want to go through our batch of
-				 * requests and stop.  So, we copy out
-				 * the ioc->last_waited time and test
-				 * against it before looping
-				 */
-				last_waited = ioc->last_waited;
-				if (need_resched()) {
-					if (num_sync_run) {
-						blk_run_backing_dev(bdi, NULL);
-						num_sync_run = 0;
-					}
-					cond_resched();
-				}
-				continue;
-			}
 			spin_lock(&device->io_lock);
 			requeue_list(pending_bios, pending, tail);
 			device->running_pending = 1;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 2c54906..2fc7917 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -326,7 +326,6 @@ struct request_queue
 	unsigned long		nr_requests;	/* Max # of requests */
 	unsigned int		nr_congestion_on;
 	unsigned int		nr_congestion_off;
-	unsigned int		nr_batching;
 
 	void			*dma_drain_buffer;
 	unsigned int		dma_drain_size;
diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h
index 64d5291..e8c9165 100644
--- a/include/linux/iocontext.h
+++ b/include/linux/iocontext.h
@@ -45,12 +45,6 @@ struct io_context {
 	unsigned short cgroup_changed;
 #endif
 
-	/*
-	 * For request batching
-	 */
-	int nr_batch_requests;     /* Number of requests left in the batch */
-	unsigned long last_waited; /* Time last woken after wait for request */
-
 	struct radix_tree_root radix_root;
 	struct hlist_head cic_list;
 	void *ioc_data;
-- 
1.7.1.426.gb436

EOF
    ;;
  76241c12f6a730241b9fa6a795dff55f826ce391)
    cat <<EOF
index 1a9403e..a520cea 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -467,7 +467,7 @@ static int blk_init_free_list(struct request_queue *q)
 {
 	struct request_list *rl = &q->rq;
 
-	if (unlikely(rl->rq_pool))
+	if (unlikely(rl->rq_pool[0]))
 		return 0;
 
 	rl->count[BLK_RW_SYNC] = rl->count[BLK_RW_ASYNC] = 0;
@@ -476,11 +476,17 @@ static int blk_init_free_list(struct request_queue *q)
 	init_waitqueue_head(&rl->wait[BLK_RW_SYNC]);
 	init_waitqueue_head(&rl->wait[BLK_RW_ASYNC]);
 
-	rl->rq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
+	rl->rq_pool[0] = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
 				mempool_free_slab, request_cachep, q->node);
+	if (!rl->rq_pool[0])
+		return -ENOMEM;
 
-	if (!rl->rq_pool)
+	rl->rq_pool[1] = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
+				mempool_free_slab, request_cachep, q->node);
+	if (!rl->rq_pool[1]) {
+		mempool_destroy(rl->rq_pool[0]);
 		return -ENOMEM;
+	}
 
 	return 0;
 }
@@ -644,16 +650,21 @@ int blk_get_queue(struct request_queue *q)
 
 static inline void blk_free_request(struct request_queue *q, struct request *rq)
 {
+	const bool is_sync = rq_is_sync(rq) != 0;
+
 	if (rq->cmd_flags & REQ_ELVPRIV)
 		elv_put_request(q, rq);
-	mempool_free(rq, q->rq.rq_pool);
+
+	mempool_free(rq, q->rq.rq_pool[is_sync]);
 }
 
 static struct request *
 blk_alloc_request(struct request_queue *q, int flags, int priv, gfp_t gfp_mask)
 {
-	struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
+	const bool is_sync = rw_is_sync(flags) != 0;
+	struct request *rq;
 
+	rq = mempool_alloc(q->rq.rq_pool[is_sync], gfp_mask);
 	if (!rq)
 		return NULL;
 
@@ -663,7 +674,7 @@ blk_alloc_request(struct request_queue *q, int flags, int priv, gfp_t gfp_mask)
 
 	if (priv) {
 		if (unlikely(elv_set_request(q, rq, gfp_mask))) {
-			mempool_free(rq, q->rq.rq_pool);
+			mempool_free(rq, q->rq.rq_pool[is_sync]);
 			return NULL;
 		}
 		rq->cmd_flags |= REQ_ELVPRIV;
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 0749b89..ee44ce5 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -460,8 +460,10 @@ static void blk_release_queue(struct kobject *kobj)
 
 	blk_sync_queue(q);
 
-	if (rl->rq_pool)
-		mempool_destroy(rl->rq_pool);
+	if (rl->rq_pool[0])
+		mempool_destroy(rl->rq_pool[0]);
+	if (rl->rq_pool[1])
+		mempool_destroy(rl->rq_pool[1]);
 
 	if (q->queue_tags)
 		__blk_queue_free_tags(q);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 2fc7917..858235d 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -45,7 +45,7 @@ struct request_list {
 	int count[2];
 	int starved[2];
 	int elvpriv;
-	mempool_t *rq_pool;
+	mempool_t *rq_pool[2];
 	wait_queue_head_t wait[2];
 };
 
-- 
1.7.1.426.gb436

EOF
    ;;
  35f2046ac858ca165a8aba477c9236e53a8dbffa)
    cat <<EOF
index a520cea..91bc13d 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -471,7 +471,6 @@ static int blk_init_free_list(struct request_queue *q)
 		return 0;
 
 	rl->count[BLK_RW_SYNC] = rl->count[BLK_RW_ASYNC] = 0;
-	rl->starved[BLK_RW_SYNC] = rl->starved[BLK_RW_ASYNC] = 0;
 	rl->elvpriv = 0;
 	init_waitqueue_head(&rl->wait[BLK_RW_SYNC]);
 	init_waitqueue_head(&rl->wait[BLK_RW_ASYNC]);
@@ -711,9 +710,6 @@ static void freed_request(struct request_queue *q, int sync, int priv)
 		rl->elvpriv--;
 
 	__freed_request(q, sync);
-
-	if (unlikely(rl->starved[sync ^ 1]))
-		__freed_request(q, sync ^ 1);
 }
 
 /*
@@ -731,10 +727,9 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
 
 	may_queue = elv_may_queue(q, rw_flags);
 	if (may_queue == ELV_MQUEUE_NO)
-		goto rq_starved;
+		goto out;
 
 	rl->count[is_sync]++;
-	rl->starved[is_sync] = 0;
 
 	priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
 	if (priv)
@@ -755,18 +750,6 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
 		 */
 		spin_lock_irq(q->queue_lock);
 		freed_request(q, is_sync, priv);
-
-		/*
-		 * in the very unlikely event that allocation failed and no
-		 * requests for this direction was pending, mark us starved
-		 * so that freeing of a request in the other direction will
-		 * notice us. another possible fix would be to split the
-		 * rq mempool into READ and WRITE
-		 */
-rq_starved:
-		if (unlikely(rl->count[is_sync] == 0))
-			rl->starved[is_sync] = 1;
-
 		goto out;
 	}
 
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 858235d..089b8a2 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -39,11 +39,10 @@ typedef void (rq_end_io_fn)(struct request *, int);
 
 struct request_list {
 	/*
-	 * count[], starved[], and wait[] are indexed by
+	 * count[], and wait[] are indexed by
 	 * BLK_RW_SYNC/BLK_RW_ASYNC
 	 */
 	int count[2];
-	int starved[2];
 	int elvpriv;
 	mempool_t *rq_pool[2];
 	wait_queue_head_t wait[2];
-- 
1.7.1.426.gb436

EOF
    ;;
  38bb177765247024dad4b70a2abe0044d0574998)
    cat <<EOF
index 91bc13d..aa94ba3 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -714,8 +714,6 @@ static void freed_request(struct request_queue *q, int sync, int priv)
 
 /*
  * Get a free request, queue_lock must be held.
- * Returns NULL on failure, with queue_lock held.
- * Returns !NULL on success, with queue_lock *not held*.
  */
 static struct request *get_request(struct request_queue *q, int rw_flags,
 				   struct bio *bio, gfp_t gfp_mask)
@@ -723,6 +721,7 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
 	struct request *rq = NULL;
 	struct request_list *rl = &q->rq;
 	const bool is_sync = rw_is_sync(rw_flags) != 0;
+	const bool drop_lock = (gfp_mask & __GFP_WAIT) != 0;
 	int may_queue, priv;
 
 	may_queue = elv_may_queue(q, rw_flags);
@@ -737,7 +736,9 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
 
 	if (blk_queue_io_stat(q))
 		rw_flags |= REQ_IO_STAT;
-	spin_unlock_irq(q->queue_lock);
+
+	if (drop_lock)
+		spin_unlock_irq(q->queue_lock);
 
 	rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
 	if (unlikely(!rq)) {
@@ -748,12 +749,17 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
 		 * Allocating task should really be put onto the front of the
 		 * wait queue, but this is pretty rare.
 		 */
-		spin_lock_irq(q->queue_lock);
+		if (drop_lock)
+			spin_lock_irq(q->queue_lock);
+
 		freed_request(q, is_sync, priv);
 		goto out;
 	}
 
 	trace_block_getrq(q, bio, rw_flags & 1);
+
+	if (drop_lock)
+		spin_lock_irq(q->queue_lock);
 out:
 	return rq;
 }
@@ -762,7 +768,7 @@ out:
  * No available requests for this queue, unplug the device and wait for some
  * requests to become available.
  *
- * Called with q->queue_lock held, and returns with it unlocked.
+ * Called with q->queue_lock held.
  */
 static struct request *get_request_wait(struct request_queue *q, int rw_flags,
 					struct bio *bio)
@@ -770,7 +776,7 @@ static struct request *get_request_wait(struct request_queue *q, int rw_flags,
 	const bool is_sync = rw_is_sync(rw_flags) != 0;
 	struct request *rq;
 
-	rq = get_request(q, rw_flags, bio, GFP_NOIO);
+	rq = get_request(q, rw_flags, bio, GFP_ATOMIC);
 	while (!rq) {
 		DEFINE_WAIT(wait);
 		struct request_list *rl = &q->rq;
@@ -800,15 +806,13 @@ struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask)
 	BUG_ON(rw != READ && rw != WRITE);
 
 	spin_lock_irq(q->queue_lock);
-	if (gfp_mask & __GFP_WAIT) {
+
+	if (gfp_mask & __GFP_WAIT)
 		rq = get_request_wait(q, rw, NULL);
-	} else {
+	else
 		rq = get_request(q, rw, NULL, gfp_mask);
-		if (!rq)
-			spin_unlock_irq(q->queue_lock);
-	}
-	/* q->queue_lock is unlocked at this point */
 
+	spin_unlock_irq(q->queue_lock);
 	return rq;
 }
 EXPORT_SYMBOL(blk_get_request);
@@ -1200,8 +1204,7 @@ get_rq:
 		rw_flags |= REQ_SYNC;
 
 	/*
-	 * Grab a free request. This is might sleep but can not fail.
-	 * Returns with the queue unlocked.
+	 * Grab a free request.
 	 */
 	req = get_request_wait(q, rw_flags, bio);
 
@@ -1213,7 +1216,6 @@ get_rq:
 	 */
 	init_request_from_bio(req, bio);
 
-	spin_lock_irq(q->queue_lock);
 	if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) ||
 	    bio_flagged(bio, BIO_CPU_AFFINE))
 		req->cpu = blk_cpu_to_group(smp_processor_id());
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index f65c6f0..3d8635d 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -2543,12 +2543,12 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
 		cfq_put_cfqg(orig_cfqg);
 }
 
+typedef void (cic_call_fn)(struct io_context *, struct cfq_io_context *);
+
 /*
  * Must always be called with the rcu_read_lock() held
  */
-static void
-__call_for_each_cic(struct io_context *ioc,
-		    void (*func)(struct io_context *, struct cfq_io_context *))
+static void __call_for_each_cic(struct io_context *ioc, cic_call_fn *func)
 {
 	struct cfq_io_context *cic;
 	struct hlist_node *n;
@@ -2560,9 +2560,7 @@ __call_for_each_cic(struct io_context *ioc,
 /*
  * Call func for each cic attached to this ioc.
  */
-static void
-call_for_each_cic(struct io_context *ioc,
-		  void (*func)(struct io_context *, struct cfq_io_context *))
+static void call_for_each_cic(struct io_context *ioc, cic_call_fn *func)
 {
 	rcu_read_lock();
 	__call_for_each_cic(ioc, func);
@@ -2787,13 +2785,10 @@ static void changed_ioprio(struct io_context *ioc, struct cfq_io_context *cic)
 {
 	struct cfq_data *cfqd = cic_to_cfqd(cic);
 	struct cfq_queue *cfqq;
-	unsigned long flags;
 
 	if (unlikely(!cfqd))
 		return;
 
-	spin_lock_irqsave(cfqd->queue->queue_lock, flags);
-
 	cfqq = cic->cfqq[BLK_RW_ASYNC];
 	if (cfqq) {
 		struct cfq_queue *new_cfqq;
@@ -2808,8 +2803,6 @@ static void changed_ioprio(struct io_context *ioc, struct cfq_io_context *cic)
 	cfqq = cic->cfqq[BLK_RW_SYNC];
 	if (cfqq)
 		cfq_mark_cfqq_prio_changed(cfqq);
-
-	spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
 }
 
 static void cfq_ioc_set_ioprio(struct io_context *ioc)
@@ -3057,11 +3050,8 @@ static int cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
 
 		radix_tree_preload_end();
 
-		if (!ret) {
-			spin_lock_irqsave(cfqd->queue->queue_lock, flags);
+		if (!ret)
 			list_add(&cic->queue_list, &cfqd->cic_list);
-			spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
-		}
 	}
 
 	if (ret)
@@ -3081,8 +3071,6 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
 	struct io_context *ioc = NULL;
 	struct cfq_io_context *cic;
 
-	might_sleep_if(gfp_mask & __GFP_WAIT);
-
 	ioc = get_io_context(gfp_mask, cfqd->queue->node);
 	if (!ioc)
 		return NULL;
@@ -3633,14 +3621,10 @@ cfq_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
 	const int rw = rq_data_dir(rq);
 	const bool is_sync = rq_is_sync(rq);
 	struct cfq_queue *cfqq;
-	unsigned long flags;
 
 	might_sleep_if(gfp_mask & __GFP_WAIT);
 
 	cic = cfq_get_io_context(cfqd, gfp_mask);
-
-	spin_lock_irqsave(q->queue_lock, flags);
-
 	if (!cic)
 		goto queue_fail;
 
@@ -3673,8 +3657,6 @@ new_queue:
 	cfqq->allocated[rw]++;
 	atomic_inc(&cfqq->ref);
 
-	spin_unlock_irqrestore(q->queue_lock, flags);
-
 	rq->elevator_private = cic;
 	rq->elevator_private2 = cfqq;
 	rq->elevator_private3 = cfq_ref_get_cfqg(cfqq->cfqg);
@@ -3685,7 +3667,6 @@ queue_fail:
 		put_io_context(cic->ioc);
 
 	cfq_schedule_dispatch(cfqd);
-	spin_unlock_irqrestore(q->queue_lock, flags);
 	cfq_log(cfqd, "set_request fail");
 	return 1;
 }
-- 
1.7.1.426.gb436

EOF
    ;;
  *)
    echo ERROR
    ;;
  esac
}


# Argument processing

if [ $# != 1 ]; then
  usage
  exit 1
fi

if [ "${1#[0-9]*.[0-9]*.[0-9]*.[0-9]*}" != "$1" ]; then
  kernel_version="${1%.[0-9]*}"
  patch_level="${1#${kernel_version}.}"
else
  kernel_version="$1"
fi

# Actual kernel source generation

if [ -e linux-${kernel_version} -o -e linux-$1 ]; then
  echo "Error: directoy not clean."
  exit 1
fi

echo "Extracting kernel sources ..."
tar xaf $TARBALLDIR/linux-${kernel_version}.tar.bz2 || exit $?
if [ "${patch_level}" != "" ]; then
  mv -i linux-${kernel_version} linux-$1 || exit $?
fi
cd linux-$1 || exit $?

if [ "${patch_level}" != "" ]; then
  patchfile="patch-${kernel_version}.${patch_level}"
  echo "Applying ${patchfile} ..."
  bzip2 -cd <${TARBALLDIR}/${patchfile}.bz2 | \
    patch -p1 -s
fi
if [ "${kernel_version}" "<" "2.6.36" ]; then
  # IB/srp: Use print_hex_dump()
  # IB/srp: Make receive buffer handling more robust
  # IB/srp: Export req_lim via sysfs
  for commit in \
    7a7008110b94dfaa90db4b0cc5b0c3f964c80506 \
    c996bb47bb419b7c2f75499e11750142775e5da9 \
    89de74866b846cc48780fda3de7fd223296aaca9
  do
    echo "Applying patch $commit ..."
    get_2_6_36_patch $commit | patch -p1 -s
  done
fi
# IB/srp: Preparation for transmit ring response allocation
# IB/srp: Implement SRP_CRED_REQ and SRP_AER_REQ
# IB/srp: Eliminate two forward declarations
# IB/srp: Reduce number of BUSY conditions
# IB/srp: Introduce list_first_entry()
for p in \
  143381 \
  143391 \
  143401 \
  143411 \
  143421
do
  echo "Applying patch $p ..."
  get_2_6_37_patch $p | patch -p1 -s
done

echo "Applying locking-per-lun patch ..."
get_locking_per_lun_patch | patch -p1 -s

echo "Applying Jens' block layer optimization patches ..."
if [ "${kernel_version}" "<" "2.6.38" ]; then
  # block: kill request batching
  # block: add separate sync/async rq allocation mempools
  # block: get rid of request_list->starved[]
  # block: optimize rq allocation path for less queue locking
  for commit in \
    5a00f237eb167a5e98d5f3bb56e11e4da406a5bc \
    76241c12f6a730241b9fa6a795dff55f826ce391 \
    35f2046ac858ca165a8aba477c9236e53a8dbffa \
    38bb177765247024dad4b70a2abe0044d0574998
  do
    echo "Applying patch $commit ..."
    get_block_layer_patch $commit | patch -p1 -s
  done
fi
