[go: nahoru, domu]

1853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi/*
217d87c45b9042fa2f830c5a47cdfd3370bb60729Saurav Kashyap * bnx2fc_els.c: QLogic NetXtreme II Linux FCoE offload driver.
3853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi * This file contains helper routines that handle ELS requests
4853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi * and responses.
5853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi *
6cf1221912fcdc2542509ef41543117ee86254d04Bhanu Prakash Gollapudi * Copyright (c) 2008 - 2013 Broadcom Corporation
717d87c45b9042fa2f830c5a47cdfd3370bb60729Saurav Kashyap * Copyright (c) 2014, QLogic Corporation
8853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi *
9853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi * This program is free software; you can redistribute it and/or modify
10853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi * it under the terms of the GNU General Public License as published by
11853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi * the Free Software Foundation.
12853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi *
13853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
14853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi */
15853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
16853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi#include "bnx2fc.h"
17853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
18853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudistatic void bnx2fc_logo_resp(struct fc_seq *seq, struct fc_frame *fp,
19853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			     void *arg);
20853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudistatic void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
21853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			      void *arg);
22853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudistatic int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
23853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			void *data, u32 data_len,
24853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg),
25853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			struct bnx2fc_els_cb_arg *cb_arg, u32 timer_msec);
26853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
27853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudistatic void bnx2fc_rrq_compl(struct bnx2fc_els_cb_arg *cb_arg)
28853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi{
29853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct bnx2fc_cmd *orig_io_req;
30853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct bnx2fc_cmd *rrq_req;
31853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	int rc = 0;
32853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
33853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	BUG_ON(!cb_arg);
34853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	rrq_req = cb_arg->io_req;
35853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	orig_io_req = cb_arg->aborted_io_req;
36853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	BUG_ON(!orig_io_req);
37853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	BNX2FC_ELS_DBG("rrq_compl: orig xid = 0x%x, rrq_xid = 0x%x\n",
38853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		   orig_io_req->xid, rrq_req->xid);
39853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
40853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
41853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
42853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &rrq_req->req_flags)) {
43853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		/*
44853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		 * els req is timed out. cleanup the IO with FW and
45853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		 * drop the completion. Remove from active_cmd_queue.
46853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		 */
47853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		BNX2FC_ELS_DBG("rrq xid - 0x%x timed out, clean it up\n",
48853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			   rrq_req->xid);
49853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
50853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		if (rrq_req->on_active_queue) {
51853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			list_del_init(&rrq_req->link);
52853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			rrq_req->on_active_queue = 0;
53853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			rc = bnx2fc_initiate_cleanup(rrq_req);
54853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			BUG_ON(rc);
55853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		}
56853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
57853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	kfree(cb_arg);
58853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi}
59853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudiint bnx2fc_send_rrq(struct bnx2fc_cmd *aborted_io_req)
60853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi{
61853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
62853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_els_rrq rrq;
63853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct bnx2fc_rport *tgt = aborted_io_req->tgt;
64853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_lport *lport = tgt->rdata->local_port;
65853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct bnx2fc_els_cb_arg *cb_arg = NULL;
66853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	u32 sid = tgt->sid;
67853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	u32 r_a_tov = lport->r_a_tov;
68853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	unsigned long start = jiffies;
69853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	int rc;
70853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
71853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	BNX2FC_ELS_DBG("Sending RRQ orig_xid = 0x%x\n",
72853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		   aborted_io_req->xid);
73853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	memset(&rrq, 0, sizeof(rrq));
74853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
75853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_NOIO);
76853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (!cb_arg) {
77853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		printk(KERN_ERR PFX "Unable to allocate cb_arg for RRQ\n");
78853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		rc = -ENOMEM;
79853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		goto rrq_err;
80853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
81853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
82853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	cb_arg->aborted_io_req = aborted_io_req;
83853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
84853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	rrq.rrq_cmd = ELS_RRQ;
85853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	hton24(rrq.rrq_s_id, sid);
86853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	rrq.rrq_ox_id = htons(aborted_io_req->xid);
87619c5cb6885b936c44ae1422ef805b69c6291485Vlad Zolotarov	rrq.rrq_rx_id = htons(aborted_io_req->task->rxwr_txrd.var_ctx.rx_id);
88853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
89853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudiretry_rrq:
90853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	rc = bnx2fc_initiate_els(tgt, ELS_RRQ, &rrq, sizeof(rrq),
91853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				 bnx2fc_rrq_compl, cb_arg,
92853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				 r_a_tov);
93853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (rc == -ENOMEM) {
94853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		if (time_after(jiffies, start + (10 * HZ))) {
95853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			BNX2FC_ELS_DBG("rrq Failed\n");
96853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			rc = FAILED;
97853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			goto rrq_err;
98853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		}
99853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		msleep(20);
100853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		goto retry_rrq;
101853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
102853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudirrq_err:
103853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (rc) {
104853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		BNX2FC_ELS_DBG("RRQ failed - release orig io req 0x%x\n",
105853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			aborted_io_req->xid);
106853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		kfree(cb_arg);
107853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		spin_lock_bh(&tgt->tgt_lock);
108853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		kref_put(&aborted_io_req->refcount, bnx2fc_cmd_release);
109853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		spin_unlock_bh(&tgt->tgt_lock);
110853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
111853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	return rc;
112853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi}
113853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
114853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudistatic void bnx2fc_l2_els_compl(struct bnx2fc_els_cb_arg *cb_arg)
115853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi{
116853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct bnx2fc_cmd *els_req;
117853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct bnx2fc_rport *tgt;
118853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct bnx2fc_mp_req *mp_req;
119853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_frame_header *fc_hdr;
120853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	unsigned char *buf;
121853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	void *resp_buf;
122853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	u32 resp_len, hdr_len;
123853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	u16 l2_oxid;
124853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	int frame_len;
125853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	int rc = 0;
126853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
127853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	l2_oxid = cb_arg->l2_oxid;
128853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	BNX2FC_ELS_DBG("ELS COMPL - l2_oxid = 0x%x\n", l2_oxid);
129853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
130853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	els_req = cb_arg->io_req;
131853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &els_req->req_flags)) {
132853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		/*
133853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		 * els req is timed out. cleanup the IO with FW and
134853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		 * drop the completion. libfc will handle the els timeout
135853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		 */
136853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		if (els_req->on_active_queue) {
137853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			list_del_init(&els_req->link);
138853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			els_req->on_active_queue = 0;
139853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			rc = bnx2fc_initiate_cleanup(els_req);
140853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			BUG_ON(rc);
141853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		}
142853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		goto free_arg;
143853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
144853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
145853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	tgt = els_req->tgt;
146853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	mp_req = &(els_req->mp_req);
147853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	fc_hdr = &(mp_req->resp_fc_hdr);
148853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	resp_len = mp_req->resp_len;
149853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	resp_buf = mp_req->resp_buf;
150853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
151853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	buf = kzalloc(PAGE_SIZE, GFP_ATOMIC);
152853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (!buf) {
153853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		printk(KERN_ERR PFX "Unable to alloc mp buf\n");
154853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		goto free_arg;
155853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
156853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	hdr_len = sizeof(*fc_hdr);
157853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (hdr_len + resp_len > PAGE_SIZE) {
158853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		printk(KERN_ERR PFX "l2_els_compl: resp len is "
159853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				    "beyond page size\n");
160853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		goto free_buf;
161853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
162853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	memcpy(buf, fc_hdr, hdr_len);
163853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	memcpy(buf + hdr_len, resp_buf, resp_len);
164853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	frame_len = hdr_len + resp_len;
165853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
166853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	bnx2fc_process_l2_frame_compl(tgt, buf, frame_len, l2_oxid);
167853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
168853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudifree_buf:
169853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	kfree(buf);
170853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudifree_arg:
171853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	kfree(cb_arg);
172853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi}
173853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
174853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudiint bnx2fc_send_adisc(struct bnx2fc_rport *tgt, struct fc_frame *fp)
175853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi{
176853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_els_adisc *adisc;
177853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_frame_header *fh;
178853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct bnx2fc_els_cb_arg *cb_arg;
179853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_lport *lport = tgt->rdata->local_port;
180853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	u32 r_a_tov = lport->r_a_tov;
181853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	int rc;
182853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
183853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	fh = fc_frame_header_get(fp);
184853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
185853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (!cb_arg) {
186853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		printk(KERN_ERR PFX "Unable to allocate cb_arg for ADISC\n");
187853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		return -ENOMEM;
188853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
189853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
190853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
191853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
192853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	BNX2FC_ELS_DBG("send ADISC: l2_oxid = 0x%x\n", cb_arg->l2_oxid);
193853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	adisc = fc_frame_payload_get(fp, sizeof(*adisc));
194853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	/* adisc is initialized by libfc */
195853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	rc = bnx2fc_initiate_els(tgt, ELS_ADISC, adisc, sizeof(*adisc),
196853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				 bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
197853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (rc)
198853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		kfree(cb_arg);
199853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	return rc;
200853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi}
201853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
202853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudiint bnx2fc_send_logo(struct bnx2fc_rport *tgt, struct fc_frame *fp)
203853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi{
204853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_els_logo *logo;
205853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_frame_header *fh;
206853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct bnx2fc_els_cb_arg *cb_arg;
207853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_lport *lport = tgt->rdata->local_port;
208853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	u32 r_a_tov = lport->r_a_tov;
209853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	int rc;
210853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
211853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	fh = fc_frame_header_get(fp);
212853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
213853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (!cb_arg) {
214853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		printk(KERN_ERR PFX "Unable to allocate cb_arg for LOGO\n");
215853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		return -ENOMEM;
216853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
217853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
218853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
219853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
220853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	BNX2FC_ELS_DBG("Send LOGO: l2_oxid = 0x%x\n", cb_arg->l2_oxid);
221853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	logo = fc_frame_payload_get(fp, sizeof(*logo));
222853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	/* logo is initialized by libfc */
223853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	rc = bnx2fc_initiate_els(tgt, ELS_LOGO, logo, sizeof(*logo),
224853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				 bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
225853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (rc)
226853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		kfree(cb_arg);
227853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	return rc;
228853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi}
229853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
230853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudiint bnx2fc_send_rls(struct bnx2fc_rport *tgt, struct fc_frame *fp)
231853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi{
232853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_els_rls *rls;
233853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_frame_header *fh;
234853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct bnx2fc_els_cb_arg *cb_arg;
235853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_lport *lport = tgt->rdata->local_port;
236853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	u32 r_a_tov = lport->r_a_tov;
237853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	int rc;
238853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
239853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	fh = fc_frame_header_get(fp);
240853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
241853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (!cb_arg) {
242853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		printk(KERN_ERR PFX "Unable to allocate cb_arg for LOGO\n");
243853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		return -ENOMEM;
244853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
245853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
246853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
247853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
248853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	rls = fc_frame_payload_get(fp, sizeof(*rls));
249853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	/* rls is initialized by libfc */
250853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	rc = bnx2fc_initiate_els(tgt, ELS_RLS, rls, sizeof(*rls),
251853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				  bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
252853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (rc)
253853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		kfree(cb_arg);
254853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	return rc;
255853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi}
256853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
257744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudivoid bnx2fc_srr_compl(struct bnx2fc_els_cb_arg *cb_arg)
258744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi{
259744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct bnx2fc_mp_req *mp_req;
260744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct fc_frame_header *fc_hdr, *fh;
261744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct bnx2fc_cmd *srr_req;
262744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct bnx2fc_cmd *orig_io_req;
263744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct fc_frame *fp;
264744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	unsigned char *buf;
265744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	void *resp_buf;
266744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	u32 resp_len, hdr_len;
267744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	u8 opcode;
268744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	int rc = 0;
269744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
270744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	orig_io_req = cb_arg->aborted_io_req;
271744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	srr_req = cb_arg->io_req;
272744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &srr_req->req_flags)) {
273744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		/* SRR timedout */
274744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		BNX2FC_IO_DBG(srr_req, "srr timed out, abort "
275744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		       "orig_io - 0x%x\n",
276744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			orig_io_req->xid);
277744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		rc = bnx2fc_initiate_abts(srr_req);
278744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		if (rc != SUCCESS) {
279744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts "
280744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				"failed. issue cleanup\n");
281744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			bnx2fc_initiate_cleanup(srr_req);
282744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		}
28332c30454507b4f5f00661ac12ddbcc150983b9ffBhanu Prakash Gollapudi		if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags) ||
28432c30454507b4f5f00661ac12ddbcc150983b9ffBhanu Prakash Gollapudi		    test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
28532c30454507b4f5f00661ac12ddbcc150983b9ffBhanu Prakash Gollapudi			BNX2FC_IO_DBG(srr_req, "srr_compl:xid 0x%x flags = %lx",
28632c30454507b4f5f00661ac12ddbcc150983b9ffBhanu Prakash Gollapudi				      orig_io_req->xid, orig_io_req->req_flags);
28732c30454507b4f5f00661ac12ddbcc150983b9ffBhanu Prakash Gollapudi			goto srr_compl_done;
28832c30454507b4f5f00661ac12ddbcc150983b9ffBhanu Prakash Gollapudi		}
289744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		orig_io_req->srr_retry++;
290744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		if (orig_io_req->srr_retry <= SRR_RETRY_COUNT) {
291744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			struct bnx2fc_rport *tgt = orig_io_req->tgt;
292744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			spin_unlock_bh(&tgt->tgt_lock);
293744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			rc = bnx2fc_send_srr(orig_io_req,
294744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi					     orig_io_req->srr_offset,
295744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi					     orig_io_req->srr_rctl);
296744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			spin_lock_bh(&tgt->tgt_lock);
297744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			if (!rc)
298744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				goto srr_compl_done;
299744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		}
300744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
301744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		rc = bnx2fc_initiate_abts(orig_io_req);
302744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		if (rc != SUCCESS) {
303744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts "
304744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				"failed xid = 0x%x. issue cleanup\n",
305744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				orig_io_req->xid);
306744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			bnx2fc_initiate_cleanup(orig_io_req);
307744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		}
308744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		goto srr_compl_done;
309744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	}
31032c30454507b4f5f00661ac12ddbcc150983b9ffBhanu Prakash Gollapudi	if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags) ||
31132c30454507b4f5f00661ac12ddbcc150983b9ffBhanu Prakash Gollapudi	    test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
31232c30454507b4f5f00661ac12ddbcc150983b9ffBhanu Prakash Gollapudi		BNX2FC_IO_DBG(srr_req, "srr_compl:xid - 0x%x flags = %lx",
31332c30454507b4f5f00661ac12ddbcc150983b9ffBhanu Prakash Gollapudi			      orig_io_req->xid, orig_io_req->req_flags);
31432c30454507b4f5f00661ac12ddbcc150983b9ffBhanu Prakash Gollapudi		goto srr_compl_done;
31532c30454507b4f5f00661ac12ddbcc150983b9ffBhanu Prakash Gollapudi	}
316744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	mp_req = &(srr_req->mp_req);
317744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	fc_hdr = &(mp_req->resp_fc_hdr);
318744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	resp_len = mp_req->resp_len;
319744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	resp_buf = mp_req->resp_buf;
320744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
321744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	hdr_len = sizeof(*fc_hdr);
322744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	buf = kzalloc(PAGE_SIZE, GFP_ATOMIC);
323744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	if (!buf) {
324744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		printk(KERN_ERR PFX "srr buf: mem alloc failure\n");
325744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		goto srr_compl_done;
326744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	}
327744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	memcpy(buf, fc_hdr, hdr_len);
328744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	memcpy(buf + hdr_len, resp_buf, resp_len);
329744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
330744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	fp = fc_frame_alloc(NULL, resp_len);
331744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	if (!fp) {
332744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		printk(KERN_ERR PFX "fc_frame_alloc failure\n");
333744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		goto free_buf;
334744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	}
335744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
336744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	fh = (struct fc_frame_header *) fc_frame_header_get(fp);
337744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	/* Copy FC Frame header and payload into the frame */
338744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	memcpy(fh, buf, hdr_len + resp_len);
339744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
340744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	opcode = fc_frame_payload_op(fp);
341744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	switch (opcode) {
342744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	case ELS_LS_ACC:
343744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		BNX2FC_IO_DBG(srr_req, "SRR success\n");
344744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		break;
345744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	case ELS_LS_RJT:
346744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		BNX2FC_IO_DBG(srr_req, "SRR rejected\n");
347744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		rc = bnx2fc_initiate_abts(orig_io_req);
348744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		if (rc != SUCCESS) {
349744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			BNX2FC_IO_DBG(srr_req, "srr_compl: initiate_abts "
350744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				"failed xid = 0x%x. issue cleanup\n",
351744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				orig_io_req->xid);
352744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			bnx2fc_initiate_cleanup(orig_io_req);
353744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		}
354744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		break;
355744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	default:
356744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		BNX2FC_IO_DBG(srr_req, "srr compl - invalid opcode = %d\n",
357744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			opcode);
358744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		break;
359744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	}
360744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	fc_frame_free(fp);
361744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudifree_buf:
362744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	kfree(buf);
363744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudisrr_compl_done:
364744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
365744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi}
366744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
367744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudivoid bnx2fc_rec_compl(struct bnx2fc_els_cb_arg *cb_arg)
368744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi{
369744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct bnx2fc_cmd *orig_io_req, *new_io_req;
370744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct bnx2fc_cmd *rec_req;
371744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct bnx2fc_mp_req *mp_req;
372744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct fc_frame_header *fc_hdr, *fh;
373744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct fc_els_ls_rjt *rjt;
374744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct fc_els_rec_acc *acc;
375744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct bnx2fc_rport *tgt;
376744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct fcoe_err_report_entry *err_entry;
377744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct scsi_cmnd *sc_cmd;
378744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	enum fc_rctl r_ctl;
379744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	unsigned char *buf;
380744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	void *resp_buf;
381744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct fc_frame *fp;
382744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	u8 opcode;
383744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	u32 offset;
384744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	u32 e_stat;
385744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	u32 resp_len, hdr_len;
386744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	int rc = 0;
387744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	bool send_seq_clnp = false;
388744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	bool abort_io = false;
389744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
390744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	BNX2FC_MISC_DBG("Entered rec_compl callback\n");
391744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	rec_req = cb_arg->io_req;
392744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	orig_io_req = cb_arg->aborted_io_req;
393744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	BNX2FC_IO_DBG(rec_req, "rec_compl: orig xid = 0x%x", orig_io_req->xid);
394744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	tgt = orig_io_req->tgt;
395744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
396744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	/* Handle REC timeout case */
397744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &rec_req->req_flags)) {
398744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		BNX2FC_IO_DBG(rec_req, "timed out, abort "
399744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		       "orig_io - 0x%x\n",
400744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			orig_io_req->xid);
401744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		/* els req is timed out. send abts for els */
402744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		rc = bnx2fc_initiate_abts(rec_req);
403744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		if (rc != SUCCESS) {
404744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts "
405744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				"failed. issue cleanup\n");
406744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			bnx2fc_initiate_cleanup(rec_req);
407744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		}
408744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		orig_io_req->rec_retry++;
409744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		/* REC timedout. send ABTS to the orig IO req */
410744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		if (orig_io_req->rec_retry <= REC_RETRY_COUNT) {
411744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			spin_unlock_bh(&tgt->tgt_lock);
412744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			rc = bnx2fc_send_rec(orig_io_req);
413744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			spin_lock_bh(&tgt->tgt_lock);
414744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			if (!rc)
415744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				goto rec_compl_done;
416744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		}
417744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		rc = bnx2fc_initiate_abts(orig_io_req);
418744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		if (rc != SUCCESS) {
419744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts "
420744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				"failed xid = 0x%x. issue cleanup\n",
421744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				orig_io_req->xid);
422744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			bnx2fc_initiate_cleanup(orig_io_req);
423744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		}
424744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		goto rec_compl_done;
425744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	}
426c1c16bd51a29eea8843f20161ddd32cddc524142Bhanu Prakash Gollapudi
427c1c16bd51a29eea8843f20161ddd32cddc524142Bhanu Prakash Gollapudi	if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags)) {
428c1c16bd51a29eea8843f20161ddd32cddc524142Bhanu Prakash Gollapudi		BNX2FC_IO_DBG(rec_req, "completed"
429c1c16bd51a29eea8843f20161ddd32cddc524142Bhanu Prakash Gollapudi		       "orig_io - 0x%x\n",
430c1c16bd51a29eea8843f20161ddd32cddc524142Bhanu Prakash Gollapudi			orig_io_req->xid);
431c1c16bd51a29eea8843f20161ddd32cddc524142Bhanu Prakash Gollapudi		goto rec_compl_done;
432c1c16bd51a29eea8843f20161ddd32cddc524142Bhanu Prakash Gollapudi	}
433c1c16bd51a29eea8843f20161ddd32cddc524142Bhanu Prakash Gollapudi	if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
434c1c16bd51a29eea8843f20161ddd32cddc524142Bhanu Prakash Gollapudi		BNX2FC_IO_DBG(rec_req, "abts in prog "
435c1c16bd51a29eea8843f20161ddd32cddc524142Bhanu Prakash Gollapudi		       "orig_io - 0x%x\n",
436c1c16bd51a29eea8843f20161ddd32cddc524142Bhanu Prakash Gollapudi			orig_io_req->xid);
437c1c16bd51a29eea8843f20161ddd32cddc524142Bhanu Prakash Gollapudi		goto rec_compl_done;
438c1c16bd51a29eea8843f20161ddd32cddc524142Bhanu Prakash Gollapudi	}
439c1c16bd51a29eea8843f20161ddd32cddc524142Bhanu Prakash Gollapudi
440744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	mp_req = &(rec_req->mp_req);
441744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	fc_hdr = &(mp_req->resp_fc_hdr);
442744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	resp_len = mp_req->resp_len;
443744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	acc = resp_buf = mp_req->resp_buf;
444744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
445744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	hdr_len = sizeof(*fc_hdr);
446744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
447744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	buf = kzalloc(PAGE_SIZE, GFP_ATOMIC);
448744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	if (!buf) {
449744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		printk(KERN_ERR PFX "rec buf: mem alloc failure\n");
450744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		goto rec_compl_done;
451744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	}
452744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	memcpy(buf, fc_hdr, hdr_len);
453744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	memcpy(buf + hdr_len, resp_buf, resp_len);
454744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
455744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	fp = fc_frame_alloc(NULL, resp_len);
456744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	if (!fp) {
457744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		printk(KERN_ERR PFX "fc_frame_alloc failure\n");
458744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		goto free_buf;
459744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	}
460744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
461744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	fh = (struct fc_frame_header *) fc_frame_header_get(fp);
462744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	/* Copy FC Frame header and payload into the frame */
463744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	memcpy(fh, buf, hdr_len + resp_len);
464744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
465744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	opcode = fc_frame_payload_op(fp);
466744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	if (opcode == ELS_LS_RJT) {
467744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		BNX2FC_IO_DBG(rec_req, "opcode is RJT\n");
468744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		rjt = fc_frame_payload_get(fp, sizeof(*rjt));
469744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		if ((rjt->er_reason == ELS_RJT_LOGIC ||
470744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		    rjt->er_reason == ELS_RJT_UNAB) &&
471744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		    rjt->er_explan == ELS_EXPL_OXID_RXID) {
472744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			BNX2FC_IO_DBG(rec_req, "handle CMD LOST case\n");
473744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			new_io_req = bnx2fc_cmd_alloc(tgt);
474744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			if (!new_io_req)
475744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				goto abort_io;
476744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			new_io_req->sc_cmd = orig_io_req->sc_cmd;
477744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			/* cleanup orig_io_req that is with the FW */
478744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			set_bit(BNX2FC_FLAG_CMD_LOST,
479744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				&orig_io_req->req_flags);
480744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			bnx2fc_initiate_cleanup(orig_io_req);
481744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			/* Post a new IO req with the same sc_cmd */
482744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			BNX2FC_IO_DBG(rec_req, "Post IO request again\n");
483744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			rc = bnx2fc_post_io_req(tgt, new_io_req);
484744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			if (!rc)
485744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				goto free_frame;
486744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			BNX2FC_IO_DBG(rec_req, "REC: io post err\n");
487744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		}
488744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudiabort_io:
489744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		rc = bnx2fc_initiate_abts(orig_io_req);
490744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		if (rc != SUCCESS) {
491744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			BNX2FC_IO_DBG(rec_req, "rec_compl: initiate_abts "
492744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				"failed. issue cleanup\n");
493744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			bnx2fc_initiate_cleanup(orig_io_req);
494744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		}
495744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	} else if (opcode == ELS_LS_ACC) {
496744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		/* REVISIT: Check if the exchange is already aborted */
497744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		offset = ntohl(acc->reca_fc4value);
498744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		e_stat = ntohl(acc->reca_e_stat);
499744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		if (e_stat & ESB_ST_SEQ_INIT)  {
500744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			BNX2FC_IO_DBG(rec_req, "target has the seq init\n");
501744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			goto free_frame;
502744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		}
503744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		BNX2FC_IO_DBG(rec_req, "e_stat = 0x%x, offset = 0x%x\n",
504744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			e_stat, offset);
505744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		/* Seq initiative is with us */
506744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		err_entry = (struct fcoe_err_report_entry *)
507744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			     &orig_io_req->err_entry;
508744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		sc_cmd = orig_io_req->sc_cmd;
509744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		if (sc_cmd->sc_data_direction == DMA_TO_DEVICE) {
510744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			/* SCSI WRITE command */
511744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			if (offset == orig_io_req->data_xfer_len) {
512744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				BNX2FC_IO_DBG(rec_req, "WRITE - resp lost\n");
513744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				/* FCP_RSP lost */
514744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				r_ctl = FC_RCTL_DD_CMD_STATUS;
515744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				offset = 0;
516744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			} else  {
517744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				/* start transmitting from offset */
518744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				BNX2FC_IO_DBG(rec_req, "XFER_RDY/DATA lost\n");
519744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				send_seq_clnp = true;
520744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				r_ctl = FC_RCTL_DD_DATA_DESC;
521744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				if (bnx2fc_initiate_seq_cleanup(orig_io_req,
522744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi								offset, r_ctl))
523744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi					abort_io = true;
524744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				/* XFER_RDY */
525744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			}
526744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		} else {
527744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			/* SCSI READ command */
528744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			if (err_entry->data.rx_buf_off ==
529744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi					orig_io_req->data_xfer_len) {
530744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				/* FCP_RSP lost */
531744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				BNX2FC_IO_DBG(rec_req, "READ - resp lost\n");
532744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				r_ctl = FC_RCTL_DD_CMD_STATUS;
533744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				offset = 0;
534744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			} else  {
535744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				/* request retransmission from this offset */
536744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				send_seq_clnp = true;
537744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				offset = err_entry->data.rx_buf_off;
538744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				BNX2FC_IO_DBG(rec_req, "RD DATA lost\n");
539744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				/* FCP_DATA lost */
540744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				r_ctl = FC_RCTL_DD_SOL_DATA;
541744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				if (bnx2fc_initiate_seq_cleanup(orig_io_req,
542744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi								offset, r_ctl))
543744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi					abort_io = true;
544744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			}
545744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		}
546744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		if (abort_io) {
547744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			rc = bnx2fc_initiate_abts(orig_io_req);
548744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			if (rc != SUCCESS) {
549744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				BNX2FC_IO_DBG(rec_req, "rec_compl:initiate_abts"
550744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi					      " failed. issue cleanup\n");
551744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				bnx2fc_initiate_cleanup(orig_io_req);
552744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			}
553744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		} else if (!send_seq_clnp) {
554744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			BNX2FC_IO_DBG(rec_req, "Send SRR - FCP_RSP\n");
555744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			spin_unlock_bh(&tgt->tgt_lock);
556744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			rc = bnx2fc_send_srr(orig_io_req, offset, r_ctl);
557744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			spin_lock_bh(&tgt->tgt_lock);
558744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
559744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			if (rc) {
560744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				BNX2FC_IO_DBG(rec_req, "Unable to send SRR"
561744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi					" IO will abort\n");
562744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi			}
563744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		}
564744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	}
565744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudifree_frame:
566744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	fc_frame_free(fp);
567744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudifree_buf:
568744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	kfree(buf);
569744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudirec_compl_done:
570744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
571744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	kfree(cb_arg);
572744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi}
573744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
5746c5a7ce4f176b641fd11e59be4df31ee3e6202ddBhanu Prakash Gollapudiint bnx2fc_send_rec(struct bnx2fc_cmd *orig_io_req)
5756c5a7ce4f176b641fd11e59be4df31ee3e6202ddBhanu Prakash Gollapudi{
576744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct fc_els_rec rec;
577744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct bnx2fc_rport *tgt = orig_io_req->tgt;
578744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct fc_lport *lport = tgt->rdata->local_port;
579744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct bnx2fc_els_cb_arg *cb_arg = NULL;
580744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	u32 sid = tgt->sid;
581744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	u32 r_a_tov = lport->r_a_tov;
582744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	int rc;
583744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
584744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	BNX2FC_IO_DBG(orig_io_req, "Sending REC\n");
585744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	memset(&rec, 0, sizeof(rec));
586744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
587744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
588744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	if (!cb_arg) {
589744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		printk(KERN_ERR PFX "Unable to allocate cb_arg for REC\n");
590744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		rc = -ENOMEM;
591744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		goto rec_err;
592744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	}
593744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	kref_get(&orig_io_req->refcount);
594744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
595744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	cb_arg->aborted_io_req = orig_io_req;
596744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
597744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	rec.rec_cmd = ELS_REC;
598744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	hton24(rec.rec_s_id, sid);
599744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	rec.rec_ox_id = htons(orig_io_req->xid);
600744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	rec.rec_rx_id = htons(orig_io_req->task->rxwr_txrd.var_ctx.rx_id);
601744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
602744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	rc = bnx2fc_initiate_els(tgt, ELS_REC, &rec, sizeof(rec),
603744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				 bnx2fc_rec_compl, cb_arg,
604744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				 r_a_tov);
605744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudirec_err:
606744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	if (rc) {
607744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		BNX2FC_IO_DBG(orig_io_req, "REC failed - release\n");
608744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		spin_lock_bh(&tgt->tgt_lock);
609744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
610744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		spin_unlock_bh(&tgt->tgt_lock);
611744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		kfree(cb_arg);
612744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	}
613744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	return rc;
6146c5a7ce4f176b641fd11e59be4df31ee3e6202ddBhanu Prakash Gollapudi}
6156c5a7ce4f176b641fd11e59be4df31ee3e6202ddBhanu Prakash Gollapudi
6166c5a7ce4f176b641fd11e59be4df31ee3e6202ddBhanu Prakash Gollapudiint bnx2fc_send_srr(struct bnx2fc_cmd *orig_io_req, u32 offset, u8 r_ctl)
6176c5a7ce4f176b641fd11e59be4df31ee3e6202ddBhanu Prakash Gollapudi{
618744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct fcp_srr srr;
619744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct bnx2fc_rport *tgt = orig_io_req->tgt;
620744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct fc_lport *lport = tgt->rdata->local_port;
621744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	struct bnx2fc_els_cb_arg *cb_arg = NULL;
622744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	u32 r_a_tov = lport->r_a_tov;
623744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	int rc;
6246c5a7ce4f176b641fd11e59be4df31ee3e6202ddBhanu Prakash Gollapudi
625744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	BNX2FC_IO_DBG(orig_io_req, "Sending SRR\n");
626744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	memset(&srr, 0, sizeof(srr));
6276c5a7ce4f176b641fd11e59be4df31ee3e6202ddBhanu Prakash Gollapudi
628744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
629744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	if (!cb_arg) {
630744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		printk(KERN_ERR PFX "Unable to allocate cb_arg for SRR\n");
631744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		rc = -ENOMEM;
632744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		goto srr_err;
633744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	}
634744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	kref_get(&orig_io_req->refcount);
635744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
636744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	cb_arg->aborted_io_req = orig_io_req;
637744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
638744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	srr.srr_op = ELS_SRR;
639744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	srr.srr_ox_id = htons(orig_io_req->xid);
640744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	srr.srr_rx_id = htons(orig_io_req->task->rxwr_txrd.var_ctx.rx_id);
641744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	srr.srr_rel_off = htonl(offset);
642744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	srr.srr_r_ctl = r_ctl;
643744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	orig_io_req->srr_offset = offset;
644744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	orig_io_req->srr_rctl = r_ctl;
645744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
646744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	rc = bnx2fc_initiate_els(tgt, ELS_SRR, &srr, sizeof(srr),
647744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				 bnx2fc_srr_compl, cb_arg,
648744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				 r_a_tov);
649744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudisrr_err:
650744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	if (rc) {
651744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		BNX2FC_IO_DBG(orig_io_req, "SRR failed - release\n");
652744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		spin_lock_bh(&tgt->tgt_lock);
653744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
654744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		spin_unlock_bh(&tgt->tgt_lock);
655744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		kfree(cb_arg);
656744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	} else
657744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		set_bit(BNX2FC_FLAG_SRR_SENT, &orig_io_req->req_flags);
658744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi
659744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	return rc;
660744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi}
6616c5a7ce4f176b641fd11e59be4df31ee3e6202ddBhanu Prakash Gollapudi
662853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudistatic int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
663853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			void *data, u32 data_len,
664853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg),
665853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			struct bnx2fc_els_cb_arg *cb_arg, u32 timer_msec)
666853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi{
667853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fcoe_port *port = tgt->port;
668aea71a024914e8b5b8bed31256dae42195a0a207Bhanu Prakash Gollapudi	struct bnx2fc_interface *interface = port->priv;
669853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_rport *rport = tgt->rport;
670853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_lport *lport = port->lport;
671853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct bnx2fc_cmd *els_req;
672853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct bnx2fc_mp_req *mp_req;
673853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_frame_header *fc_hdr;
674853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fcoe_task_ctx_entry *task;
675853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fcoe_task_ctx_entry *task_page;
676853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	int rc = 0;
677853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	int task_idx, index;
678853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	u32 did, sid;
679853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	u16 xid;
680853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
681853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	rc = fc_remote_port_chkready(rport);
682853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (rc) {
683b2a554ff9ad5cdd8d00dac168f2bb3db7ccedb61Bhanu Prakash Gollapudi		printk(KERN_ERR PFX "els 0x%x: rport not ready\n", op);
684853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		rc = -EINVAL;
685853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		goto els_err;
686853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
687853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
688b2a554ff9ad5cdd8d00dac168f2bb3db7ccedb61Bhanu Prakash Gollapudi		printk(KERN_ERR PFX "els 0x%x: link is not ready\n", op);
689853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		rc = -EINVAL;
690853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		goto els_err;
691853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
692853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (!(test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) ||
693853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	     (test_bit(BNX2FC_FLAG_EXPL_LOGO, &tgt->flags))) {
694853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		printk(KERN_ERR PFX "els 0x%x: tgt not ready\n", op);
695853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		rc = -EINVAL;
696853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		goto els_err;
697853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
698853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	els_req = bnx2fc_elstm_alloc(tgt, BNX2FC_ELS);
699853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (!els_req) {
700853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		rc = -ENOMEM;
701853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		goto els_err;
702853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
703853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
704853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	els_req->sc_cmd = NULL;
705853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	els_req->port = port;
706853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	els_req->tgt = tgt;
707853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	els_req->cb_func = cb_func;
708853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	cb_arg->io_req = els_req;
709853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	els_req->cb_arg = cb_arg;
710853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
711853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	mp_req = (struct bnx2fc_mp_req *)&(els_req->mp_req);
712853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	rc = bnx2fc_init_mp_req(els_req);
713853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (rc == FAILED) {
714b2a554ff9ad5cdd8d00dac168f2bb3db7ccedb61Bhanu Prakash Gollapudi		printk(KERN_ERR PFX "ELS MP request init failed\n");
715853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		spin_lock_bh(&tgt->tgt_lock);
716853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		kref_put(&els_req->refcount, bnx2fc_cmd_release);
717853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		spin_unlock_bh(&tgt->tgt_lock);
718853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		rc = -ENOMEM;
719853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		goto els_err;
720853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	} else {
721853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		/* rc SUCCESS */
722853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		rc = 0;
723853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
724853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
725853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	/* Set the data_xfer_len to the size of ELS payload */
726853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	mp_req->req_len = data_len;
727853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	els_req->data_xfer_len = mp_req->req_len;
728853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
729853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	/* Fill ELS Payload */
730853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if ((op >= ELS_LS_RJT) && (op <= ELS_AUTH_ELS)) {
731853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		memcpy(mp_req->req_buf, data, data_len);
732853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	} else {
733b2a554ff9ad5cdd8d00dac168f2bb3db7ccedb61Bhanu Prakash Gollapudi		printk(KERN_ERR PFX "Invalid ELS op 0x%x\n", op);
734853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		els_req->cb_func = NULL;
735853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		els_req->cb_arg = NULL;
736853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		spin_lock_bh(&tgt->tgt_lock);
737853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		kref_put(&els_req->refcount, bnx2fc_cmd_release);
738853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		spin_unlock_bh(&tgt->tgt_lock);
739853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		rc = -EINVAL;
740853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
741853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
742853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (rc)
743853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		goto els_err;
744853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
745853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	/* Fill FC header */
746853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	fc_hdr = &(mp_req->req_fc_hdr);
747853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
748853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	did = tgt->rport->port_id;
749853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	sid = tgt->sid;
750853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
751744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	if (op == ELS_SRR)
752744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		__fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS4_REQ, did, sid,
753744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				   FC_TYPE_FCP, FC_FC_FIRST_SEQ |
754744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				   FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
755744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi	else
756744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi		__fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid,
757744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				   FC_TYPE_ELS, FC_FC_FIRST_SEQ |
758744469542951d32979a8dcb1dbed560bfed1745eBhanu Prakash Gollapudi				   FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
759853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
760853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	/* Obtain exchange id */
761853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	xid = els_req->xid;
762853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	task_idx = xid/BNX2FC_TASKS_PER_PAGE;
763853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	index = xid % BNX2FC_TASKS_PER_PAGE;
764853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
765853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	/* Initialize task context for this IO request */
766aea71a024914e8b5b8bed31256dae42195a0a207Bhanu Prakash Gollapudi	task_page = (struct fcoe_task_ctx_entry *)
767aea71a024914e8b5b8bed31256dae42195a0a207Bhanu Prakash Gollapudi			interface->hba->task_ctx[task_idx];
768853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	task = &(task_page[index]);
769853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	bnx2fc_init_mp_task(els_req, task);
770853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
771853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	spin_lock_bh(&tgt->tgt_lock);
772853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
773853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
774853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		printk(KERN_ERR PFX "initiate_els.. session not ready\n");
775853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		els_req->cb_func = NULL;
776853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		els_req->cb_arg = NULL;
777853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		kref_put(&els_req->refcount, bnx2fc_cmd_release);
778853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		spin_unlock_bh(&tgt->tgt_lock);
779853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		return -EINVAL;
780853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
781853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
782853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (timer_msec)
783853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		bnx2fc_cmd_timer_set(els_req, timer_msec);
784853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	bnx2fc_add_2_sq(tgt, xid);
785853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
786853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	els_req->on_active_queue = 1;
787853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	list_add_tail(&els_req->link, &tgt->els_queue);
788853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
789853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	/* Ring doorbell */
790853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	bnx2fc_ring_doorbell(tgt);
791853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	spin_unlock_bh(&tgt->tgt_lock);
792853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
793853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudiels_err:
794853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	return rc;
795853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi}
796853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
797853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudivoid bnx2fc_process_els_compl(struct bnx2fc_cmd *els_req,
798853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			      struct fcoe_task_ctx_entry *task, u8 num_rq)
799853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi{
800853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct bnx2fc_mp_req *mp_req;
801853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_frame_header *fc_hdr;
802853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	u64 *hdr;
803853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	u64 *temp_hdr;
804853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
805853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	BNX2FC_ELS_DBG("Entered process_els_compl xid = 0x%x"
806853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			"cmd_type = %d\n", els_req->xid, els_req->cmd_type);
807853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
808853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (test_and_set_bit(BNX2FC_FLAG_ELS_DONE,
809853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			     &els_req->req_flags)) {
810853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		BNX2FC_ELS_DBG("Timer context finished processing this "
811853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			   "els - 0x%x\n", els_req->xid);
81225985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		/* This IO doesn't receive cleanup completion */
813853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		kref_put(&els_req->refcount, bnx2fc_cmd_release);
814853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		return;
815853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
816853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
817853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	/* Cancel the timeout_work, as we received the response */
818853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (cancel_delayed_work(&els_req->timeout_work))
819853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		kref_put(&els_req->refcount,
820853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			 bnx2fc_cmd_release); /* drop timer hold */
821853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
822853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (els_req->on_active_queue) {
823853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		list_del_init(&els_req->link);
824853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		els_req->on_active_queue = 0;
825853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
826853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
827853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	mp_req = &(els_req->mp_req);
828853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	fc_hdr = &(mp_req->resp_fc_hdr);
829853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
830853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	hdr = (u64 *)fc_hdr;
831853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	temp_hdr = (u64 *)
832619c5cb6885b936c44ae1422ef805b69c6291485Vlad Zolotarov		&task->rxwr_only.union_ctx.comp_info.mp_rsp.fc_hdr;
833853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	hdr[0] = cpu_to_be64(temp_hdr[0]);
834853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	hdr[1] = cpu_to_be64(temp_hdr[1]);
835853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	hdr[2] = cpu_to_be64(temp_hdr[2]);
836853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
837619c5cb6885b936c44ae1422ef805b69c6291485Vlad Zolotarov	mp_req->resp_len =
838619c5cb6885b936c44ae1422ef805b69c6291485Vlad Zolotarov		task->rxwr_only.union_ctx.comp_info.mp_rsp.mp_payload_len;
839853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
840853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	/* Parse ELS response */
841853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if ((els_req->cb_func) && (els_req->cb_arg)) {
842853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		els_req->cb_func(els_req->cb_arg);
843853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		els_req->cb_arg = NULL;
844853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
845853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
846853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	kref_put(&els_req->refcount, bnx2fc_cmd_release);
847853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi}
848853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
849853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudistatic void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
850853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			      void *arg)
851853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi{
852853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fcoe_ctlr *fip = arg;
853853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_exch *exch = fc_seq_exch(seq);
854853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_lport *lport = exch->lp;
855853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	u8 *mac;
856853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	u8 op;
857853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
858853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (IS_ERR(fp))
859853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		goto done;
860853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
861853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	mac = fr_cb(fp)->granted_mac;
862853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (is_zero_ether_addr(mac)) {
863853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		op = fc_frame_payload_op(fp);
864853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		if (lport->vport) {
865853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			if (op == ELS_LS_RJT) {
866853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				printk(KERN_ERR PFX "bnx2fc_flogi_resp is LS_RJT\n");
867853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				fc_vport_terminate(lport->vport);
868853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				fc_frame_free(fp);
869853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				return;
870853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			}
871853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		}
872de9c05fafc296aa95b58352bad7f23f6199aa90dBhanu Prakash Gollapudi		fcoe_ctlr_recv_flogi(fip, lport, fp);
873853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
874de9c05fafc296aa95b58352bad7f23f6199aa90dBhanu Prakash Gollapudi	if (!is_zero_ether_addr(mac))
875de9c05fafc296aa95b58352bad7f23f6199aa90dBhanu Prakash Gollapudi		fip->update_mac(lport, mac);
876853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudidone:
877853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	fc_lport_flogi_resp(seq, fp, lport);
878853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi}
879853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
880853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudistatic void bnx2fc_logo_resp(struct fc_seq *seq, struct fc_frame *fp,
881853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			     void *arg)
882853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi{
883853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fcoe_ctlr *fip = arg;
884853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_exch *exch = fc_seq_exch(seq);
885853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_lport *lport = exch->lp;
886853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	static u8 zero_mac[ETH_ALEN] = { 0 };
887853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
888853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	if (!IS_ERR(fp))
889853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		fip->update_mac(lport, zero_mac);
890853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	fc_lport_logo_resp(seq, fp, lport);
891853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi}
892853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
893853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudistruct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did,
894853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				      struct fc_frame *fp, unsigned int op,
895853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				      void (*resp)(struct fc_seq *,
896853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi						   struct fc_frame *,
897853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi						   void *),
898853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				      void *arg, u32 timeout)
899853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi{
900853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fcoe_port *port = lport_priv(lport);
901aea71a024914e8b5b8bed31256dae42195a0a207Bhanu Prakash Gollapudi	struct bnx2fc_interface *interface = port->priv;
902fd8f89027d816cb023edf6bfd4c744f194150a05Robert Love	struct fcoe_ctlr *fip = bnx2fc_to_ctlr(interface);
903853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	struct fc_frame_header *fh = fc_frame_header_get(fp);
904853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi
905853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	switch (op) {
906853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	case ELS_FLOGI:
907853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	case ELS_FDISC:
908853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		return fc_elsct_send(lport, did, fp, op, bnx2fc_flogi_resp,
909853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				     fip, timeout);
910853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	case ELS_LOGO:
911853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		/* only hook onto fabric logouts, not port logouts */
912853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI)
913853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi			break;
914853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi		return fc_elsct_send(lport, did, fp, op, bnx2fc_logo_resp,
915853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi				     fip, timeout);
916853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	}
917853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi	return fc_elsct_send(lport, did, fp, op, resp, arg, timeout);
918853e2bd2103aaa91d1ba1c0b57ba17628d836f03Bhanu Gollapudi}
919