diff --git a/drivers/infiniband/ulp/srp/ib_srp.c
b/drivers/infiniband/ulp/srp/ib_srp.c
index 54c8fe2..2006a0a 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1,5 +1,6 @@
Â /*
Â * Copyright (c) 2005 Cisco Systems. Â All rights reserved.
+ * Copyright (c) 2009 Bart Van Assche <bart.vanassche@gmail.com>.
Â *
Â * This software is available to you under a choice of one of two
Â * licenses. Â You may choose to be licensed under the terms of the GNU
@@ -53,6 +54,8 @@
Â #define PFX Â  Â  Â  Â  Â  Â DRV_NAME ": "
Â #define DRV_VERSION Â  Â "0.2"
Â #define DRV_RELDATE Â  Â "November 1, 2005"
+/* Similar to is_power_of_2(), but can be evaluated at compile time. */
+#define IS_POWER_OF_2(n) ((n) != 0 && (((n) & ((n) - 1)) == 0))

Â MODULE_AUTHOR("Roland Dreier");
Â MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator "
@@ -82,6 +85,11 @@ static void srp_add_one(struct ib_device *device);
Â static void srp_remove_one(struct ib_device *device);
Â static void srp_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 void srp_process_cred_req(struct srp_target_port *target,
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â struct srp_cred_req *req);
+static void srp_process_aer_req(struct srp_target_port *target,
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  struct srp_cred_req *req);
+static int srp_post_recv(struct srp_target_port *target);

Â static struct scsi_transport_template *ib_srp_transport_template;

@@ -237,7 +245,7 @@ static int srp_create_target_ib(struct
srp_target_port *target)
Â  Â  Â  Â ib_req_notify_cq(target->cq, IB_CQ_NEXT_COMP);

Â  Â  Â  Â init_attr->event_handler Â  Â  Â  = srp_qp_event;
- Â  Â  Â  init_attr->cap.max_send_wr Â  Â  = SRP_SQ_SIZE;
+ Â  Â  Â  init_attr->cap.max_send_wr Â  Â  = SRP_SQ_SIZE + SRP_TXP_SIZE;
Â  Â  Â  Â init_attr->cap.max_recv_wr Â  Â  = SRP_RQ_SIZE;
Â  Â  Â  Â init_attr->cap.max_recv_sge Â  Â = 1;
Â  Â  Â  Â init_attr->cap.max_send_sge Â  Â = 1;
@@ -272,10 +280,12 @@ static void srp_free_target_ib(struct
srp_target_port *target)
Â  Â  Â  Â ib_destroy_qp(target->qp);
Â  Â  Â  Â ib_destroy_cq(target->cq);

- Â  Â  Â  for (i = 0; i < SRP_RQ_SIZE; ++i)
+ Â  Â  Â  for (i = 0; i < ARRAY_SIZE(target->rx_ring); ++i)
Â  Â  Â  Â  Â  Â  Â  Â srp_free_iu(target->srp_host, target->rx_ring[i]);
- Â  Â  Â  for (i = 0; i < SRP_SQ_SIZE + 1; ++i)
+ Â  Â  Â  for (i = 0; i < ARRAY_SIZE(target->tx_ring); ++i)
Â  Â  Â  Â  Â  Â  Â  Â srp_free_iu(target->srp_host, target->tx_ring[i]);
+ Â  Â  Â  for (i = 0; i < ARRAY_SIZE(target->txp_ring); ++i)
+ Â  Â  Â  Â  Â  Â  Â  srp_free_iu(target->srp_host, target->txp_ring[i]);
Â }

Â static void srp_path_rec_completion(int status,
@@ -888,6 +898,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_process_cred_req(target, iu->buf);
+ Â  Â  Â  Â  Â  Â  Â  break;
+
+ Â  Â  Â  case SRP_AER_REQ:
+ Â  Â  Â  Â  Â  Â  Â  srp_process_aer_req(target, iu->buf);
+ Â  Â  Â  Â  Â  Â  Â  break;
+
Â  Â  Â  Â default:
Â  Â  Â  Â  Â  Â  Â  Â shost_printk(KERN_WARNING, target->scsi_host,
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  PFX "Unhandled SRP opcode 0x%02x\n", opcode);
@@ -908,7 +926,11 @@ static void srp_completion(struct ib_cq *cq, void
*target_ptr)
Â  Â  Â  Â  Â  Â  Â  Â if (wc.status) {
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â shost_printk(KERN_ERR, target->scsi_host,
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  PFX "failed %s status %d\n",
- Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â wc.wr_id & SRP_OP_RECV ?
"receive" : "send",
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â wc.wr_id & SRP_OP_RECV
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â ? "receiving"
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â : wc.wr_id & SRP_OP_TXP
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â ? "sending response"
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â : "sending request",
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  wc.status);
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â target->qp_in_error = 1;
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â break;
@@ -916,6 +938,8 @@ static void srp_completion(struct ib_cq *cq, void
*target_ptr)

Â  Â  Â  Â  Â  Â  Â  Â if (wc.wr_id & SRP_OP_RECV)
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â srp_handle_recv(target, &wc);
+ Â  Â  Â  Â  Â  Â  Â  else if (wc.wr_id & SRP_OP_TXP)
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  ++target->txp_tail;
Â  Â  Â  Â  Â  Â  Â  Â else
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â ++target->tx_tail;
Â  Â  Â  Â }
@@ -961,15 +985,19 @@ static int srp_post_recv(struct srp_target_port *target)
Â }

Â /*
+ * Obtain an information unit for sending a request to the target.
+ *
Â * 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().
+ * call to __srp_post_send_req().
Â */
Â 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;

+ Â  Â  Â  BUILD_BUG_ON(!IS_POWER_OF_2(ARRAY_SIZE(target->tx_ring)));
+
Â  Â  Â  Â if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
Â  Â  Â  Â  Â  Â  Â  Â return NULL;

@@ -978,26 +1006,31 @@ static struct srp_iu *__srp_get_tx_iu(struct
srp_target_port *target,
Â  Â  Â  Â  Â  Â  Â  Â return NULL;
Â  Â  Â  Â }

- Â  Â  Â  return target->tx_ring[target->tx_head & SRP_SQ_SIZE];
+ Â  Â  Â  return target->tx_ring[target->tx_head
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â & (ARRAY_SIZE(target->tx_ring) - 1)];
Â }

Â /*
+ * Send a request to the target.
+ *
Â * 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)
+static int __srp_post_send_req(struct srp_target_port *target,
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â struct srp_iu *iu, int len)
Â {
Â  Â  Â  Â struct ib_sge list;
Â  Â  Â  Â struct ib_send_wr wr, *bad_wr;
Â  Â  Â  Â int ret = 0;

+ Â  Â  Â  BUILD_BUG_ON(!IS_POWER_OF_2(ARRAY_SIZE(target->tx_ring)));
+
Â  Â  Â  Â 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_SIZE;
+ Â  Â  Â  wr.wr_id Â  Â  Â = target->tx_head & (ARRAY_SIZE(target->tx_ring) - 1);
Â  Â  Â  Â wr.sg_list Â  Â = &list;
Â  Â  Â  Â wr.num_sge Â  Â = 1;
Â  Â  Â  Â wr.opcode Â  Â  = IB_WR_SEND;
@@ -1013,6 +1046,117 @@ static int __srp_post_send(struct
srp_target_port *target,
Â  Â  Â  Â return ret;
Â }

+/*
+ * Obtain an information unit for sending a response to the target.
+ *
+ * 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_rsp().
+ */
+static struct srp_iu *__srp_get_txp_iu(struct srp_target_port *target)
+{
+ Â  Â  Â  BUILD_BUG_ON(!IS_POWER_OF_2(SRP_TXP_SIZE));
+
+ Â  Â  Â  if (WARN_ON(target->txp_head - target->txp_tail >= SRP_TXP_SIZE))
+ Â  Â  Â  Â  Â  Â  Â  return NULL;
+
+ Â  Â  Â  return target->txp_ring[target->txp_head & (SRP_TXP_SIZE - 1)];
+}
+
+/*
+ * Send a response to a request received from the target.
+ *
+ * Must be called with target->scsi_host->host_lock held to protect txp_head.
+ */
+static int __srp_post_send_rsp(struct srp_target_port *target,
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â struct srp_iu *iu, int len)
+{
+ Â  Â  Â  struct ib_sge list;
+ Â  Â  Â  struct ib_send_wr wr, *bad_wr;
+ Â  Â  Â  int ret = 0;
+
+ Â  Â  Â  BUILD_BUG_ON(!IS_POWER_OF_2(SRP_TXP_SIZE));
+
+ Â  Â  Â  list.addr Â  = iu->dma;
+ Â  Â  Â  list.length = len;
+ Â  Â  Â  list.lkey Â  = target->srp_host->srp_dev->mr->lkey;
+
+ Â  Â  Â  wr.next Â  Â  Â  = NULL;
+ Â  Â  Â  wr.wr_id Â  Â  Â = (target->txp_head & (SRP_TXP_SIZE - 1)) | SRP_OP_TXP;
+ Â  Â  Â  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->txp_head;
+
+ Â  Â  Â  return ret;
+}
+
+static void srp_process_cred_req(struct srp_target_port *target,
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â struct srp_cred_req *req)
+{
+ Â  Â  Â  struct ib_device *dev;
+ Â  Â  Â  struct srp_iu *iu;
+ Â  Â  Â  struct srp_cred_rsp *rsp;
+ Â  Â  Â  unsigned long flags;
+ Â  Â  Â  int res;
+ Â  Â  Â  s32 delta;
+ Â  Â  Â  u64 tag;
+
+ Â  Â  Â  dev = target->srp_host->srp_dev->dev;
+ Â  Â  Â  delta = (s32) be32_to_cpu(req->req_lim_delta);
+ Â  Â  Â  tag = req->tag;
+
+ Â  Â  Â  spin_lock_irqsave(target->scsi_host->host_lock, flags);
+
+ Â  Â  Â  target->req_lim += delta;
+
+ Â  Â  Â  iu = __srp_get_txp_iu(target);
+ Â  Â  Â  if (!iu)
+ Â  Â  Â  Â  Â  Â  Â  goto out;
+
+ Â  Â  Â  rsp = iu->buf;
+
+ Â  Â  Â  ib_dma_sync_single_for_cpu(dev, iu->dma, sizeof(*rsp),
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â DMA_TO_DEVICE);
+
+ Â  Â  Â  memset(rsp, 0, sizeof *rsp);
+ Â  Â  Â  rsp->opcode = SRP_CRED_RSP;
+ Â  Â  Â  rsp->tag Â  Â = tag;
+
+ Â  Â  Â  ib_dma_sync_single_for_device(dev, iu->dma, srp_max_iu_len,
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  DMA_TO_DEVICE);
+
+ Â  Â  Â  if (__srp_post_send_rsp(target, iu, sizeof(*rsp)))
+ Â  Â  Â  Â  Â  Â  Â  shost_printk(KERN_ERR, target->scsi_host,
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â PFX "Sending response failed\n");
+
+ Â  Â  Â  res = __srp_post_recv(target);
+ Â  Â  Â  if (res)
+ Â  Â  Â  Â  Â  Â  Â  shost_printk(KERN_ERR, target->scsi_host,
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â PFX "ib_post_recv() failed -- res = %d\n", res);
+
+out:
+ Â  Â  Â  spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
+}
+
+static void srp_process_aer_req(struct srp_target_port *target,
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â struct srp_cred_req *req)
+{
+ Â  Â  Â  int res;
+
+ Â  Â  Â  shost_printk(KERN_ERR, target->scsi_host,
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â PFX "received and ignored SRP_AER_REQ\n");
+ Â  Â  Â  res = srp_post_recv(target);
+ Â  Â  Â  if (res)
+ Â  Â  Â  Â  Â  Â  Â  shost_printk(KERN_ERR, target->scsi_host,
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â PFX "ib_post_recv() failed -- res = %d\n", res);
+}
+
Â static int srp_queuecommand(struct scsi_cmnd *scmnd,
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â void (*done)(struct scsi_cmnd *))
Â {
@@ -1075,8 +1219,9 @@ 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)) {
- Â  Â  Â  Â  Â  Â  Â  shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n");
+ Â  Â  Â  if (__srp_post_send_req(target, iu, len)) {
+ Â  Â  Â  Â  Â  Â  Â  shost_printk(KERN_ERR, target->scsi_host,
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â PFX "Sending request failed\n");
Â  Â  Â  Â  Â  Â  Â  Â goto err_unmap;
Â  Â  Â  Â }

@@ -1095,7 +1240,7 @@ static int srp_alloc_iu_bufs(struct
srp_target_port *target)
Â {
Â  Â  Â  Â int i;

- Â  Â  Â  for (i = 0; i < SRP_RQ_SIZE; ++i) {
+ Â  Â  Â  for (i = 0; i < ARRAY_SIZE(target->rx_ring); ++i) {
Â  Â  Â  Â  Â  Â  Â  Â target->rx_ring[i] = srp_alloc_iu(target->srp_host,
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â target->max_ti_iu_len,
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â GFP_KERNEL, DMA_FROM_DEVICE);
@@ -1103,7 +1248,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 < ARRAY_SIZE(target->tx_ring); ++i) {
Â  Â  Â  Â  Â  Â  Â  Â target->tx_ring[i] = srp_alloc_iu(target->srp_host,
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â srp_max_iu_len,
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â GFP_KERNEL, DMA_TO_DEVICE);
@@ -1111,19 +1256,32 @@ static int srp_alloc_iu_bufs(struct
srp_target_port *target)
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â goto err;
Â  Â  Â  Â }

+ Â  Â  Â  for (i = 0; i < ARRAY_SIZE(target->txp_ring); ++i) {
+ Â  Â  Â  Â  Â  Â  Â  target->txp_ring[i] = srp_alloc_iu(target->srp_host,
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  srp_max_iu_len,
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  GFP_KERNEL, DMA_TO_DEVICE);
+ Â  Â  Â  Â  Â  Â  Â  if (!target->txp_ring[i])
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  goto err;
+ Â  Â  Â  }
+
Â  Â  Â  Â return 0;

Â err:
- Â  Â  Â  for (i = 0; i < SRP_RQ_SIZE; ++i) {
+ Â  Â  Â  for (i = 0; i < ARRAY_SIZE(target->rx_ring); ++i) {
Â  Â  Â  Â  Â  Â  Â  Â srp_free_iu(target->srp_host, target->rx_ring[i]);
Â  Â  Â  Â  Â  Â  Â  Â target->rx_ring[i] = NULL;
Â  Â  Â  Â }

- Â  Â  Â  for (i = 0; i < SRP_SQ_SIZE + 1; ++i) {
+ Â  Â  Â  for (i = 0; i < ARRAY_SIZE(target->tx_ring); ++i) {
Â  Â  Â  Â  Â  Â  Â  Â srp_free_iu(target->srp_host, target->tx_ring[i]);
Â  Â  Â  Â  Â  Â  Â  Â target->tx_ring[i] = NULL;
Â  Â  Â  Â }

+ Â  Â  Â  for (i = 0; i < ARRAY_SIZE(target->txp_ring); ++i) {
+ Â  Â  Â  Â  Â  Â  Â  srp_free_iu(target->srp_host, target->txp_ring[i]);
+ Â  Â  Â  Â  Â  Â  Â  target->tx_ring[i] = NULL;
+ Â  Â  Â  }
+
Â  Â  Â  Â return -ENOMEM;
Â }

@@ -1211,6 +1369,7 @@ static int srp_cm_handler(struct ib_cm_id
*cm_id, struct ib_cm_event *event)
Â {
Â  Â  Â  Â struct srp_target_port *target = cm_id->context;
Â  Â  Â  Â struct ib_qp_attr *qp_attr = NULL;
+ Â  Â  Â  int i;
Â  Â  Â  Â int attr_mask = 0;
Â  Â  Â  Â int comp = 0;
Â  Â  Â  Â int opcode = 0;
@@ -1263,7 +1422,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_RXR_SIZE; ++i) {
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  target->status = srp_post_recv(target);
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  if (target->status)
+ Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  break;
+ Â  Â  Â  Â  Â  Â  Â  }
Â  Â  Â  Â  Â  Â  Â  Â if (target->status)
Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â break;

@@ -1353,7 +1516,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_req(target, iu, sizeof *tsk_mgmt))
Â  Â  Â  Â  Â  Â  Â  Â goto out;

Â  Â  Â  Â req->tsk_mgmt = iu;
@@ -1529,6 +1692,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)
Â {
@@ -1563,6 +1738,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);
@@ -1574,6 +1750,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,
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h
b/drivers/infiniband/ulp/srp/ib_srp.h
index e185b90..c553a03 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -57,10 +57,20 @@ enum {
Â  Â  Â  Â SRP_MAX_LUN Â  Â  Â  Â  Â  Â  = 512,
Â  Â  Â  Â SRP_DEF_SG_TABLESIZE Â  Â = 12,

+ Â  Â  Â  /*
+ Â  Â  Â  Â * Receive queue: queue for receiving responses and requests from the
+ Â  Â  Â  Â * target.
+ Â  Â  Â  Â */
Â  Â  Â  Â SRP_RQ_SHIFT Â  Â  Â  Â  Â  Â = 6,
Â  Â  Â  Â SRP_RQ_SIZE Â  Â  Â  Â  Â  Â  = 1 << SRP_RQ_SHIFT,
- Â  Â  Â  SRP_SQ_SIZE Â  Â  Â  Â  Â  Â  = SRP_RQ_SIZE - 1,
- Â  Â  Â  SRP_CQ_SIZE Â  Â  Â  Â  Â  Â  = SRP_SQ_SIZE + SRP_RQ_SIZE,
+ Â  Â  Â  /* Number of receive slots reserved for receiving requests. */
+ Â  Â  Â  SRP_RXR_SIZE Â  Â  Â  Â  Â  Â = 2,
+ Â  Â  Â  /* Send queue: queue for sending requests to the target. */
+ Â  Â  Â  SRP_SQ_SIZE Â  Â  Â  Â  Â  Â  = SRP_RQ_SIZE - SRP_RXR_SIZE - 1,
+ Â  Â  Â  /* Size of the queue for sending responses to the target. */
+ Â  Â  Â  SRP_TXP_SIZE Â  Â  Â  Â  Â  Â = 2,
+ Â  Â  Â  /* Completion queue. */
+ Â  Â  Â  SRP_CQ_SIZE Â  Â  Â  Â  Â  Â  = SRP_SQ_SIZE + SRP_TXP_SIZE + SRP_RQ_SIZE,

Â  Â  Â  Â SRP_TAG_TSK_MGMT Â  Â  Â  Â = 1 << (SRP_RQ_SHIFT + 1),

@@ -69,6 +79,9 @@ enum {
Â  Â  Â  Â SRP_FMR_DIRTY_SIZE Â  Â  Â = SRP_FMR_POOL_SIZE / 4
Â };

+/* wr_id / wc_id flag for marking responses sent to the target. */
+#define SRP_OP_TXP Â  Â  Â  Â  Â  Â  (1 << 30)
+/* wr_id / wc_id flag for marking receive operations. */
Â #define SRP_OP_RECV Â  Â  Â  Â  Â  Â (1 << 31)

Â enum srp_target_state {
@@ -141,12 +154,20 @@ struct srp_target_port {

Â  Â  Â  Â int Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  zero_req_lim;

+
+ Â  Â  Â  /* Receive ring for responses and requests received by the initiator. */
Â  Â  Â  Â unsigned Â  Â  Â  Â  Â  Â  Â  Â rx_head;
Â  Â  Â  Â struct srp_iu Â  Â  Â  Â  Â *rx_ring[SRP_RQ_SIZE];

+ Â  Â  Â  /* Transmit ring for requests sent to the target. */
Â  Â  Â  Â unsigned Â  Â  Â  Â  Â  Â  Â  Â tx_head;
Â  Â  Â  Â unsigned Â  Â  Â  Â  Â  Â  Â  Â tx_tail;
- Â  Â  Â  struct srp_iu Â  Â  Â  Â  Â *tx_ring[SRP_SQ_SIZE + 1];
+ Â  Â  Â  struct srp_iu Â  Â  Â  Â  Â *tx_ring[SRP_SQ_SIZE + SRP_RXR_SIZE + 1];
+
+ Â  Â  Â  /* Transmit ring for responses sent to the target. */
+ Â  Â  Â  unsigned Â  Â  Â  Â  Â  Â  Â  Â txp_head;
+ Â  Â  Â  unsigned Â  Â  Â  Â  Â  Â  Â  Â txp_tail;
+ Â  Â  Â  struct srp_iu Â  Â  Â  Â  Â *txp_ring[SRP_TXP_SIZE];

Â  Â  Â  Â struct list_head Â  Â  Â  Â free_reqs;
Â  Â  Â  Â struct list_head Â  Â  Â  Â req_queue;
diff --git a/include/scsi/srp.h b/include/scsi/srp.h
index ad178fa..55c16c7 100644
--- a/include/scsi/srp.h
+++ b/include/scsi/srp.h
@@ -239,4 +239,26 @@ struct srp_rsp {
Â  Â  Â  Â u8 Â  Â  Â data[0];
Â } __attribute__((packed));

+/*
+ * SRP_CRED_REQ information unit, as defined in section 6.10 of the
+ * T10 SRP r16a document.
+ */
+struct srp_cred_req {
+ Â  Â  Â  u8 Â  Â  Â opcode;
+ Â  Â  Â  u8 Â  Â  Â sol_not;
+ Â  Â  Â  u8 Â  Â  Â reserved[2];
+ Â  Â  Â  __be32 Â req_lim_delta;
+ Â  Â  Â  u64 Â  Â  tag;
+} __attribute__((packed));
+
+/*
+ * SRP_CRED_RSP information unit, as defined in section 6.11 of the
+ * T10 SRP r16a document.
+ */
+struct srp_cred_rsp {
+ Â  Â  Â  u8 Â  Â  Â opcode;
+ Â  Â  Â  u8 Â  Â  Â reserved[7];
+ Â  Â  Â  u64 Â  Â  tag;
+} __attribute__((packed));
+
Â #endif /* SCSI_SRP_H */
