From patchwork Mon Jan 4 01:43:36 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Dillow X-Patchwork-Id: 70532 X-Patchwork-Delegate: dave@thedillows.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.2) with ESMTP id o0423waZ029002 for ; Mon, 4 Jan 2010 02:03:58 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751294Ab0ADCD5 (ORCPT ); Sun, 3 Jan 2010 21:03:57 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751556Ab0ADCD5 (ORCPT ); Sun, 3 Jan 2010 21:03:57 -0500 Received: from smtp.knology.net ([24.214.63.101]:40957 "EHLO smtp.knology.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751294Ab0ADCD4 (ORCPT ); Sun, 3 Jan 2010 21:03:56 -0500 Received: (qmail 14991 invoked by uid 0); 4 Jan 2010 01:43:55 -0000 Received: from unknown (HELO shed.thedillows.org) (207.98.218.89) by smtp7.knology.net with SMTP; 4 Jan 2010 01:43:55 -0000 Received: from obelisk.thedillows.org (obelisk.thedillows.org [192.168.0.10]) by shed.thedillows.org (8.14.3/8.14.3) with ESMTP id o041hr4i023256; Sun, 3 Jan 2010 20:43:53 -0500 Received: from obelisk.thedillows.org (localhost [127.0.0.1]) by obelisk.thedillows.org (8.14.3/8.14.3) with ESMTP id o041hrNJ020390; Sun, 3 Jan 2010 20:43:53 -0500 Received: (from dad@localhost) by obelisk.thedillows.org (8.14.3/8.14.3/Submit) id o041hrHF020389; Sun, 3 Jan 2010 20:43:53 -0500 X-Authentication-Warning: obelisk.thedillows.org: dad set sender to dave@thedillows.org using -f From: David Dillow To: Bart Van Assche Cc: linux-rdma@vger.kernel.org, Roland Dreier , Chris Worley , David Dillow Subject: [RFC PATCH 2/3] IB/srp: minimal support for SRP_CRED_REQ and SRP_AER_REQ Date: Sun, 3 Jan 2010 20:43:36 -0500 Message-Id: <1262569417-20341-2-git-send-email-dave@thedillows.org> X-Mailer: git-send-email 1.6.5.2 In-Reply-To: <1262568846.13289.4.camel@obelisk.thedillows.org> References: <1262568846.13289.4.camel@obelisk.thedillows.org> In-Reply-To: <1262568846.13289.4.camel@obelisk.thedillows.org> References: <1262568846.13289.4.camel@obelisk.thedillows.org> Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 82e7f9d..c0a5ccb 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -82,6 +82,8 @@ 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 int srp_response_common(struct srp_target_port *target, s32 req_delta, + void *rsp, int len); static struct scsi_transport_template *ib_srp_transport_template; @@ -845,6 +847,37 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) spin_unlock_irqrestore(target->scsi_host->host_lock, flags); } +static void srp_process_cred_req(struct srp_target_port *target, + struct srp_cred_req *req) +{ + struct srp_cred_rsp rsp = { + .opcode = SRP_CRED_RSP, + .tag = req->tag, + }; + s32 delta = be32_to_cpu(req->req_lim_delta); + + if (srp_response_common(target, delta, &rsp, sizeof rsp)) + shost_printk(KERN_ERR, target->scsi_host, PFX + "problems processing SRP_CRED_REQ\n"); +} + +static void srp_process_aer_req(struct srp_target_port *target, + struct srp_aer_req *req) +{ + struct srp_aer_rsp rsp = { + .opcode = SRP_AER_RSP, + .tag = req->tag, + }; + s32 delta = 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)); + + if (srp_response_common(target, delta, &rsp, sizeof rsp)) + shost_printk(KERN_ERR, target->scsi_host, PFX + "problems processing SRP_AER_REQ\n"); +} + static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) { struct ib_device *dev; @@ -888,6 +921,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); @@ -973,7 +1014,8 @@ static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target, if (target->tx_head - target->tx_tail >= SRP_SQ_FULL) return NULL; - if (target->req_lim < min) { + /* SRP responses do not consume credits */ + if (req_type != SRP_REQ_RESPONSE && target->req_lim < min) { ++target->zero_req_lim; return NULL; } @@ -986,7 +1028,7 @@ 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, int credits) { struct ib_sge list; struct ib_send_wr wr, *bad_wr; @@ -1007,7 +1049,7 @@ static int __srp_post_send(struct srp_target_port *target, if (!ret) { ++target->tx_head; - --target->req_lim; + target->req_lim -= credits; } return ret; @@ -1075,7 +1117,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, 1)) { shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n"); goto err_unmap; } @@ -1091,6 +1133,40 @@ err: return SCSI_MLQUEUE_HOST_BUSY; } +static int srp_response_common(struct srp_target_port *target, s32 req_delta, + void *rsp, int len) +{ + struct ib_device *dev; + unsigned long flags; + struct srp_iu *iu; + int err = 1; + + dev = target->srp_host->srp_dev->dev; + + spin_lock_irqsave(target->scsi_host->host_lock, flags); + target->req_lim += req_delta; + + iu = __srp_get_tx_iu(target, SRP_REQ_RESPONSE); + if (!iu) { + shost_printk(KERN_ERR, target->scsi_host, PFX + "no IU available to send response\n"); + goto out; + } + + ib_dma_sync_single_for_cpu(dev, iu->dma, len, DMA_TO_DEVICE); + memcpy(iu->buf, rsp, len); + ib_dma_sync_single_for_device(dev, iu->dma, len, DMA_TO_DEVICE); + + err = __srp_post_send(target, iu, len, 0); + if (err) + shost_printk(KERN_ERR, target->scsi_host, PFX + "unable to post response: %d\n", err); + +out: + spin_unlock_irqrestore(target->scsi_host->host_lock, flags); + return err; +} + static int srp_alloc_iu_bufs(struct srp_target_port *target) { int i; @@ -1214,6 +1290,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: @@ -1263,9 +1340,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); - if (target->status) - break; + for (i = 0; i < SRP_RESP_RESV; ++i) { + target->status = srp_post_recv(target); + if (target->status) + break; + } qp_attr->qp_state = IB_QPS_RTS; target->status = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask); @@ -1353,7 +1432,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, 1)) 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 2742969..2ae3a8f 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h @@ -57,14 +57,19 @@ enum { SRP_MAX_LUN = 512, SRP_DEF_SG_TABLESIZE = 12, + /* SRP_RQ_SHIFT sets the physical size of the TX/RX queues */ SRP_RQ_SHIFT = 6, SRP_RQ_SIZE = 1 << SRP_RQ_SHIFT, SRP_SQ_SIZE = SRP_RQ_SIZE, SRP_CQ_SIZE = SRP_SQ_SIZE + SRP_RQ_SIZE, + /* SRP_RESP_RESV sets the number of queue entries reserved for + * unsolicited messages from the target and the responses to them. + */ + SRP_RESP_RESV = 2, SRP_SQ_FULL = SRP_SQ_SIZE - 1, SRP_SQ_MASK = SRP_SQ_SIZE - 1, - SRP_MAX_CREDIT = SRP_SQ_SIZE - 1, + SRP_MAX_CREDIT = SRP_SQ_SIZE - SRP_RESP_RESV - 1, SRP_TAG_TSK_MGMT = 1 << (SRP_RQ_SHIFT + 1), @@ -85,6 +90,7 @@ enum srp_target_state { enum srp_request_type { SRP_REQ_NORMAL, SRP_REQ_TASK_MGMT, + SRP_REQ_RESPONSE, }; struct srp_device { diff --git a/include/scsi/srp.h b/include/scsi/srp.h index ad178fa..ae7dcfd 100644 --- a/include/scsi/srp.h +++ b/include/scsi/srp.h @@ -239,4 +239,53 @@ 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)); + +/* + * SRP_AER_REQ information unit, as defined in section 6.12 of the + * T10 SRP r16a document. + */ +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]; +} __attribute__((packed)); + +/* + * SRP_AER_RSP information unit, as defined in section 6.13 of the + * T10 SRP r16a document. + */ +struct srp_aer_rsp { + u8 opcode; + u8 reserved[7]; + u64 tag; +} __attribute__((packed)); + #endif /* SCSI_SRP_H */