aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bnx2fc/bnx2fc_io.c
diff options
context:
space:
mode:
authorBhanu Prakash Gollapudi <bprakash@broadcom.com>2011-07-27 14:32:05 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-07-28 03:42:57 -0400
commit6c5a7ce4f176b641fd11e59be4df31ee3e6202dd (patch)
tree676e052ad6c2ac3868e934a9f22e2f5528d6a8f3 /drivers/scsi/bnx2fc/bnx2fc_io.c
parentd6857595394f1fa5c5752eae9bb6045c067fa41e (diff)
[SCSI] bnx2fc: Support 'sequence cleanup' task
For the devices that support sequence level error recovery, based on the REC response, the firmware has to be informed about the offset from which the retransmission should happen. Driver initiates sequence cleanup task to firmware so that the firmware can program the task. Upon the sequence cleanup completion, SRR is issued to retransmit the sequence. Signed-off-by: Bhanu Prakash Gollapudi <bprakash@broadcom.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/bnx2fc/bnx2fc_io.c')
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index 72940b8625bd..9820d3060cd8 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -930,6 +930,76 @@ abts_err:
930 return rc; 930 return rc;
931} 931}
932 932
933int bnx2fc_initiate_seq_cleanup(struct bnx2fc_cmd *orig_io_req, u32 offset,
934 enum fc_rctl r_ctl)
935{
936 struct fc_lport *lport;
937 struct bnx2fc_rport *tgt = orig_io_req->tgt;
938 struct bnx2fc_interface *interface;
939 struct fcoe_port *port;
940 struct bnx2fc_cmd *seq_clnp_req;
941 struct fcoe_task_ctx_entry *task;
942 struct fcoe_task_ctx_entry *task_page;
943 struct bnx2fc_els_cb_arg *cb_arg = NULL;
944 int task_idx, index;
945 u16 xid;
946 int rc = 0;
947
948 BNX2FC_IO_DBG(orig_io_req, "bnx2fc_initiate_seq_cleanup xid = 0x%x\n",
949 orig_io_req->xid);
950 kref_get(&orig_io_req->refcount);
951
952 port = orig_io_req->port;
953 interface = port->priv;
954 lport = port->lport;
955
956 cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
957 if (!cb_arg) {
958 printk(KERN_ERR PFX "Unable to alloc cb_arg for seq clnup\n");
959 rc = -ENOMEM;
960 goto cleanup_err;
961 }
962
963 seq_clnp_req = bnx2fc_elstm_alloc(tgt, BNX2FC_SEQ_CLEANUP);
964 if (!seq_clnp_req) {
965 printk(KERN_ERR PFX "cleanup: couldnt allocate cmd\n");
966 rc = -ENOMEM;
967 kfree(cb_arg);
968 goto cleanup_err;
969 }
970 /* Initialize rest of io_req fields */
971 seq_clnp_req->sc_cmd = NULL;
972 seq_clnp_req->port = port;
973 seq_clnp_req->tgt = tgt;
974 seq_clnp_req->data_xfer_len = 0; /* No data transfer for cleanup */
975
976 xid = seq_clnp_req->xid;
977
978 task_idx = xid/BNX2FC_TASKS_PER_PAGE;
979 index = xid % BNX2FC_TASKS_PER_PAGE;
980
981 /* Initialize task context for this IO request */
982 task_page = (struct fcoe_task_ctx_entry *)
983 interface->hba->task_ctx[task_idx];
984 task = &(task_page[index]);
985 cb_arg->aborted_io_req = orig_io_req;
986 cb_arg->io_req = seq_clnp_req;
987 cb_arg->r_ctl = r_ctl;
988 cb_arg->offset = offset;
989 seq_clnp_req->cb_arg = cb_arg;
990
991 printk(KERN_ERR PFX "call init_seq_cleanup_task\n");
992 bnx2fc_init_seq_cleanup_task(seq_clnp_req, task, orig_io_req, offset);
993
994 /* Obtain free SQ entry */
995 bnx2fc_add_2_sq(tgt, xid);
996
997 /* Ring doorbell */
998 bnx2fc_ring_doorbell(tgt);
999cleanup_err:
1000 return rc;
1001}
1002
933int bnx2fc_initiate_cleanup(struct bnx2fc_cmd *io_req) 1003int bnx2fc_initiate_cleanup(struct bnx2fc_cmd *io_req)
934{ 1004{
935 struct fc_lport *lport; 1005 struct fc_lport *lport;
@@ -1156,6 +1226,42 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
1156 return rc; 1226 return rc;
1157} 1227}
1158 1228
1229void bnx2fc_process_seq_cleanup_compl(struct bnx2fc_cmd *seq_clnp_req,
1230 struct fcoe_task_ctx_entry *task,
1231 u8 rx_state)
1232{
1233 struct bnx2fc_els_cb_arg *cb_arg = seq_clnp_req->cb_arg;
1234 struct bnx2fc_cmd *orig_io_req = cb_arg->aborted_io_req;
1235 u32 offset = cb_arg->offset;
1236 enum fc_rctl r_ctl = cb_arg->r_ctl;
1237 int rc = 0;
1238 struct bnx2fc_rport *tgt = orig_io_req->tgt;
1239
1240 BNX2FC_IO_DBG(orig_io_req, "Entered process_cleanup_compl xid = 0x%x"
1241 "cmd_type = %d\n",
1242 seq_clnp_req->xid, seq_clnp_req->cmd_type);
1243
1244 if (rx_state == FCOE_TASK_RX_STATE_IGNORED_SEQUENCE_CLEANUP) {
1245 printk(KERN_ERR PFX "seq cleanup ignored - xid = 0x%x\n",
1246 seq_clnp_req->xid);
1247 goto free_cb_arg;
1248 }
1249 kref_get(&orig_io_req->refcount);
1250
1251 spin_unlock_bh(&tgt->tgt_lock);
1252 rc = bnx2fc_send_srr(orig_io_req, offset, r_ctl);
1253 spin_lock_bh(&tgt->tgt_lock);
1254
1255 if (rc)
1256 printk(KERN_ERR PFX "clnup_compl: Unable to send SRR"
1257 " IO will abort\n");
1258 seq_clnp_req->cb_arg = NULL;
1259 kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
1260free_cb_arg:
1261 kfree(cb_arg);
1262 return;
1263}
1264
1159void bnx2fc_process_cleanup_compl(struct bnx2fc_cmd *io_req, 1265void bnx2fc_process_cleanup_compl(struct bnx2fc_cmd *io_req,
1160 struct fcoe_task_ctx_entry *task, 1266 struct fcoe_task_ctx_entry *task,
1161 u8 num_rq) 1267 u8 num_rq)