Fix common misspellings
[linux-flexiantxendom0-3.2.10.git] / drivers / scsi / bnx2fc / bnx2fc_els.c
1 /*
2  * bnx2fc_els.c: Broadcom NetXtreme II Linux FCoE offload driver.
3  * This file contains helper routines that handle ELS requests
4  * and responses.
5  *
6  * Copyright (c) 2008 - 2010 Broadcom Corporation
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation.
11  *
12  * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
13  */
14
15 #include "bnx2fc.h"
16
17 static void bnx2fc_logo_resp(struct fc_seq *seq, struct fc_frame *fp,
18                              void *arg);
19 static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
20                               void *arg);
21 static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
22                         void *data, u32 data_len,
23                         void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg),
24                         struct bnx2fc_els_cb_arg *cb_arg, u32 timer_msec);
25
26 static void bnx2fc_rrq_compl(struct bnx2fc_els_cb_arg *cb_arg)
27 {
28         struct bnx2fc_cmd *orig_io_req;
29         struct bnx2fc_cmd *rrq_req;
30         int rc = 0;
31
32         BUG_ON(!cb_arg);
33         rrq_req = cb_arg->io_req;
34         orig_io_req = cb_arg->aborted_io_req;
35         BUG_ON(!orig_io_req);
36         BNX2FC_ELS_DBG("rrq_compl: orig xid = 0x%x, rrq_xid = 0x%x\n",
37                    orig_io_req->xid, rrq_req->xid);
38
39         kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
40
41         if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &rrq_req->req_flags)) {
42                 /*
43                  * els req is timed out. cleanup the IO with FW and
44                  * drop the completion. Remove from active_cmd_queue.
45                  */
46                 BNX2FC_ELS_DBG("rrq xid - 0x%x timed out, clean it up\n",
47                            rrq_req->xid);
48
49                 if (rrq_req->on_active_queue) {
50                         list_del_init(&rrq_req->link);
51                         rrq_req->on_active_queue = 0;
52                         rc = bnx2fc_initiate_cleanup(rrq_req);
53                         BUG_ON(rc);
54                 }
55         }
56         kfree(cb_arg);
57 }
58 int bnx2fc_send_rrq(struct bnx2fc_cmd *aborted_io_req)
59 {
60
61         struct fc_els_rrq rrq;
62         struct bnx2fc_rport *tgt = aborted_io_req->tgt;
63         struct fc_lport *lport = tgt->rdata->local_port;
64         struct bnx2fc_els_cb_arg *cb_arg = NULL;
65         u32 sid = tgt->sid;
66         u32 r_a_tov = lport->r_a_tov;
67         unsigned long start = jiffies;
68         int rc;
69
70         BNX2FC_ELS_DBG("Sending RRQ orig_xid = 0x%x\n",
71                    aborted_io_req->xid);
72         memset(&rrq, 0, sizeof(rrq));
73
74         cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_NOIO);
75         if (!cb_arg) {
76                 printk(KERN_ERR PFX "Unable to allocate cb_arg for RRQ\n");
77                 rc = -ENOMEM;
78                 goto rrq_err;
79         }
80
81         cb_arg->aborted_io_req = aborted_io_req;
82
83         rrq.rrq_cmd = ELS_RRQ;
84         hton24(rrq.rrq_s_id, sid);
85         rrq.rrq_ox_id = htons(aborted_io_req->xid);
86         rrq.rrq_rx_id = htons(aborted_io_req->task->rx_wr_tx_rd.rx_id);
87
88 retry_rrq:
89         rc = bnx2fc_initiate_els(tgt, ELS_RRQ, &rrq, sizeof(rrq),
90                                  bnx2fc_rrq_compl, cb_arg,
91                                  r_a_tov);
92         if (rc == -ENOMEM) {
93                 if (time_after(jiffies, start + (10 * HZ))) {
94                         BNX2FC_ELS_DBG("rrq Failed\n");
95                         rc = FAILED;
96                         goto rrq_err;
97                 }
98                 msleep(20);
99                 goto retry_rrq;
100         }
101 rrq_err:
102         if (rc) {
103                 BNX2FC_ELS_DBG("RRQ failed - release orig io req 0x%x\n",
104                         aborted_io_req->xid);
105                 kfree(cb_arg);
106                 spin_lock_bh(&tgt->tgt_lock);
107                 kref_put(&aborted_io_req->refcount, bnx2fc_cmd_release);
108                 spin_unlock_bh(&tgt->tgt_lock);
109         }
110         return rc;
111 }
112
113 static void bnx2fc_l2_els_compl(struct bnx2fc_els_cb_arg *cb_arg)
114 {
115         struct bnx2fc_cmd *els_req;
116         struct bnx2fc_rport *tgt;
117         struct bnx2fc_mp_req *mp_req;
118         struct fc_frame_header *fc_hdr;
119         unsigned char *buf;
120         void *resp_buf;
121         u32 resp_len, hdr_len;
122         u16 l2_oxid;
123         int frame_len;
124         int rc = 0;
125
126         l2_oxid = cb_arg->l2_oxid;
127         BNX2FC_ELS_DBG("ELS COMPL - l2_oxid = 0x%x\n", l2_oxid);
128
129         els_req = cb_arg->io_req;
130         if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &els_req->req_flags)) {
131                 /*
132                  * els req is timed out. cleanup the IO with FW and
133                  * drop the completion. libfc will handle the els timeout
134                  */
135                 if (els_req->on_active_queue) {
136                         list_del_init(&els_req->link);
137                         els_req->on_active_queue = 0;
138                         rc = bnx2fc_initiate_cleanup(els_req);
139                         BUG_ON(rc);
140                 }
141                 goto free_arg;
142         }
143
144         tgt = els_req->tgt;
145         mp_req = &(els_req->mp_req);
146         fc_hdr = &(mp_req->resp_fc_hdr);
147         resp_len = mp_req->resp_len;
148         resp_buf = mp_req->resp_buf;
149
150         buf = kzalloc(PAGE_SIZE, GFP_ATOMIC);
151         if (!buf) {
152                 printk(KERN_ERR PFX "Unable to alloc mp buf\n");
153                 goto free_arg;
154         }
155         hdr_len = sizeof(*fc_hdr);
156         if (hdr_len + resp_len > PAGE_SIZE) {
157                 printk(KERN_ERR PFX "l2_els_compl: resp len is "
158                                     "beyond page size\n");
159                 goto free_buf;
160         }
161         memcpy(buf, fc_hdr, hdr_len);
162         memcpy(buf + hdr_len, resp_buf, resp_len);
163         frame_len = hdr_len + resp_len;
164
165         bnx2fc_process_l2_frame_compl(tgt, buf, frame_len, l2_oxid);
166
167 free_buf:
168         kfree(buf);
169 free_arg:
170         kfree(cb_arg);
171 }
172
173 int bnx2fc_send_adisc(struct bnx2fc_rport *tgt, struct fc_frame *fp)
174 {
175         struct fc_els_adisc *adisc;
176         struct fc_frame_header *fh;
177         struct bnx2fc_els_cb_arg *cb_arg;
178         struct fc_lport *lport = tgt->rdata->local_port;
179         u32 r_a_tov = lport->r_a_tov;
180         int rc;
181
182         fh = fc_frame_header_get(fp);
183         cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
184         if (!cb_arg) {
185                 printk(KERN_ERR PFX "Unable to allocate cb_arg for ADISC\n");
186                 return -ENOMEM;
187         }
188
189         cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
190
191         BNX2FC_ELS_DBG("send ADISC: l2_oxid = 0x%x\n", cb_arg->l2_oxid);
192         adisc = fc_frame_payload_get(fp, sizeof(*adisc));
193         /* adisc is initialized by libfc */
194         rc = bnx2fc_initiate_els(tgt, ELS_ADISC, adisc, sizeof(*adisc),
195                                  bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
196         if (rc)
197                 kfree(cb_arg);
198         return rc;
199 }
200
201 int bnx2fc_send_logo(struct bnx2fc_rport *tgt, struct fc_frame *fp)
202 {
203         struct fc_els_logo *logo;
204         struct fc_frame_header *fh;
205         struct bnx2fc_els_cb_arg *cb_arg;
206         struct fc_lport *lport = tgt->rdata->local_port;
207         u32 r_a_tov = lport->r_a_tov;
208         int rc;
209
210         fh = fc_frame_header_get(fp);
211         cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
212         if (!cb_arg) {
213                 printk(KERN_ERR PFX "Unable to allocate cb_arg for LOGO\n");
214                 return -ENOMEM;
215         }
216
217         cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
218
219         BNX2FC_ELS_DBG("Send LOGO: l2_oxid = 0x%x\n", cb_arg->l2_oxid);
220         logo = fc_frame_payload_get(fp, sizeof(*logo));
221         /* logo is initialized by libfc */
222         rc = bnx2fc_initiate_els(tgt, ELS_LOGO, logo, sizeof(*logo),
223                                  bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
224         if (rc)
225                 kfree(cb_arg);
226         return rc;
227 }
228
229 int bnx2fc_send_rls(struct bnx2fc_rport *tgt, struct fc_frame *fp)
230 {
231         struct fc_els_rls *rls;
232         struct fc_frame_header *fh;
233         struct bnx2fc_els_cb_arg *cb_arg;
234         struct fc_lport *lport = tgt->rdata->local_port;
235         u32 r_a_tov = lport->r_a_tov;
236         int rc;
237
238         fh = fc_frame_header_get(fp);
239         cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
240         if (!cb_arg) {
241                 printk(KERN_ERR PFX "Unable to allocate cb_arg for LOGO\n");
242                 return -ENOMEM;
243         }
244
245         cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
246
247         rls = fc_frame_payload_get(fp, sizeof(*rls));
248         /* rls is initialized by libfc */
249         rc = bnx2fc_initiate_els(tgt, ELS_RLS, rls, sizeof(*rls),
250                                   bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
251         if (rc)
252                 kfree(cb_arg);
253         return rc;
254 }
255
256 static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
257                         void *data, u32 data_len,
258                         void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg),
259                         struct bnx2fc_els_cb_arg *cb_arg, u32 timer_msec)
260 {
261         struct fcoe_port *port = tgt->port;
262         struct bnx2fc_hba *hba = port->priv;
263         struct fc_rport *rport = tgt->rport;
264         struct fc_lport *lport = port->lport;
265         struct bnx2fc_cmd *els_req;
266         struct bnx2fc_mp_req *mp_req;
267         struct fc_frame_header *fc_hdr;
268         struct fcoe_task_ctx_entry *task;
269         struct fcoe_task_ctx_entry *task_page;
270         int rc = 0;
271         int task_idx, index;
272         u32 did, sid;
273         u16 xid;
274
275         rc = fc_remote_port_chkready(rport);
276         if (rc) {
277                 printk(KERN_ALERT PFX "els 0x%x: rport not ready\n", op);
278                 rc = -EINVAL;
279                 goto els_err;
280         }
281         if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
282                 printk(KERN_ALERT PFX "els 0x%x: link is not ready\n", op);
283                 rc = -EINVAL;
284                 goto els_err;
285         }
286         if (!(test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) ||
287              (test_bit(BNX2FC_FLAG_EXPL_LOGO, &tgt->flags))) {
288                 printk(KERN_ERR PFX "els 0x%x: tgt not ready\n", op);
289                 rc = -EINVAL;
290                 goto els_err;
291         }
292         els_req = bnx2fc_elstm_alloc(tgt, BNX2FC_ELS);
293         if (!els_req) {
294                 rc = -ENOMEM;
295                 goto els_err;
296         }
297
298         els_req->sc_cmd = NULL;
299         els_req->port = port;
300         els_req->tgt = tgt;
301         els_req->cb_func = cb_func;
302         cb_arg->io_req = els_req;
303         els_req->cb_arg = cb_arg;
304
305         mp_req = (struct bnx2fc_mp_req *)&(els_req->mp_req);
306         rc = bnx2fc_init_mp_req(els_req);
307         if (rc == FAILED) {
308                 printk(KERN_ALERT PFX "ELS MP request init failed\n");
309                 spin_lock_bh(&tgt->tgt_lock);
310                 kref_put(&els_req->refcount, bnx2fc_cmd_release);
311                 spin_unlock_bh(&tgt->tgt_lock);
312                 rc = -ENOMEM;
313                 goto els_err;
314         } else {
315                 /* rc SUCCESS */
316                 rc = 0;
317         }
318
319         /* Set the data_xfer_len to the size of ELS payload */
320         mp_req->req_len = data_len;
321         els_req->data_xfer_len = mp_req->req_len;
322
323         /* Fill ELS Payload */
324         if ((op >= ELS_LS_RJT) && (op <= ELS_AUTH_ELS)) {
325                 memcpy(mp_req->req_buf, data, data_len);
326         } else {
327                 printk(KERN_ALERT PFX "Invalid ELS op 0x%x\n", op);
328                 els_req->cb_func = NULL;
329                 els_req->cb_arg = NULL;
330                 spin_lock_bh(&tgt->tgt_lock);
331                 kref_put(&els_req->refcount, bnx2fc_cmd_release);
332                 spin_unlock_bh(&tgt->tgt_lock);
333                 rc = -EINVAL;
334         }
335
336         if (rc)
337                 goto els_err;
338
339         /* Fill FC header */
340         fc_hdr = &(mp_req->req_fc_hdr);
341
342         did = tgt->rport->port_id;
343         sid = tgt->sid;
344
345         __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid,
346                            FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
347                            FC_FC_SEQ_INIT, 0);
348
349         /* Obtain exchange id */
350         xid = els_req->xid;
351         task_idx = xid/BNX2FC_TASKS_PER_PAGE;
352         index = xid % BNX2FC_TASKS_PER_PAGE;
353
354         /* Initialize task context for this IO request */
355         task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
356         task = &(task_page[index]);
357         bnx2fc_init_mp_task(els_req, task);
358
359         spin_lock_bh(&tgt->tgt_lock);
360
361         if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
362                 printk(KERN_ERR PFX "initiate_els.. session not ready\n");
363                 els_req->cb_func = NULL;
364                 els_req->cb_arg = NULL;
365                 kref_put(&els_req->refcount, bnx2fc_cmd_release);
366                 spin_unlock_bh(&tgt->tgt_lock);
367                 return -EINVAL;
368         }
369
370         if (timer_msec)
371                 bnx2fc_cmd_timer_set(els_req, timer_msec);
372         bnx2fc_add_2_sq(tgt, xid);
373
374         els_req->on_active_queue = 1;
375         list_add_tail(&els_req->link, &tgt->els_queue);
376
377         /* Ring doorbell */
378         bnx2fc_ring_doorbell(tgt);
379         spin_unlock_bh(&tgt->tgt_lock);
380
381 els_err:
382         return rc;
383 }
384
385 void bnx2fc_process_els_compl(struct bnx2fc_cmd *els_req,
386                               struct fcoe_task_ctx_entry *task, u8 num_rq)
387 {
388         struct bnx2fc_mp_req *mp_req;
389         struct fc_frame_header *fc_hdr;
390         u64 *hdr;
391         u64 *temp_hdr;
392
393         BNX2FC_ELS_DBG("Entered process_els_compl xid = 0x%x"
394                         "cmd_type = %d\n", els_req->xid, els_req->cmd_type);
395
396         if (test_and_set_bit(BNX2FC_FLAG_ELS_DONE,
397                              &els_req->req_flags)) {
398                 BNX2FC_ELS_DBG("Timer context finished processing this "
399                            "els - 0x%x\n", els_req->xid);
400                 /* This IO doesn't receive cleanup completion */
401                 kref_put(&els_req->refcount, bnx2fc_cmd_release);
402                 return;
403         }
404
405         /* Cancel the timeout_work, as we received the response */
406         if (cancel_delayed_work(&els_req->timeout_work))
407                 kref_put(&els_req->refcount,
408                          bnx2fc_cmd_release); /* drop timer hold */
409
410         if (els_req->on_active_queue) {
411                 list_del_init(&els_req->link);
412                 els_req->on_active_queue = 0;
413         }
414
415         mp_req = &(els_req->mp_req);
416         fc_hdr = &(mp_req->resp_fc_hdr);
417
418         hdr = (u64 *)fc_hdr;
419         temp_hdr = (u64 *)
420                 &task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
421         hdr[0] = cpu_to_be64(temp_hdr[0]);
422         hdr[1] = cpu_to_be64(temp_hdr[1]);
423         hdr[2] = cpu_to_be64(temp_hdr[2]);
424
425         mp_req->resp_len = task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_off;
426
427         /* Parse ELS response */
428         if ((els_req->cb_func) && (els_req->cb_arg)) {
429                 els_req->cb_func(els_req->cb_arg);
430                 els_req->cb_arg = NULL;
431         }
432
433         kref_put(&els_req->refcount, bnx2fc_cmd_release);
434 }
435
436 static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
437                               void *arg)
438 {
439         struct fcoe_ctlr *fip = arg;
440         struct fc_exch *exch = fc_seq_exch(seq);
441         struct fc_lport *lport = exch->lp;
442         u8 *mac;
443         struct fc_frame_header *fh;
444         u8 op;
445
446         if (IS_ERR(fp))
447                 goto done;
448
449         mac = fr_cb(fp)->granted_mac;
450         if (is_zero_ether_addr(mac)) {
451                 fh = fc_frame_header_get(fp);
452                 if (fh->fh_type != FC_TYPE_ELS) {
453                         printk(KERN_ERR PFX "bnx2fc_flogi_resp:"
454                                 "fh_type != FC_TYPE_ELS\n");
455                         fc_frame_free(fp);
456                         return;
457                 }
458                 op = fc_frame_payload_op(fp);
459                 if (lport->vport) {
460                         if (op == ELS_LS_RJT) {
461                                 printk(KERN_ERR PFX "bnx2fc_flogi_resp is LS_RJT\n");
462                                 fc_vport_terminate(lport->vport);
463                                 fc_frame_free(fp);
464                                 return;
465                         }
466                 }
467                 if (fcoe_ctlr_recv_flogi(fip, lport, fp)) {
468                         fc_frame_free(fp);
469                         return;
470                 }
471         }
472         fip->update_mac(lport, mac);
473 done:
474         fc_lport_flogi_resp(seq, fp, lport);
475 }
476
477 static void bnx2fc_logo_resp(struct fc_seq *seq, struct fc_frame *fp,
478                              void *arg)
479 {
480         struct fcoe_ctlr *fip = arg;
481         struct fc_exch *exch = fc_seq_exch(seq);
482         struct fc_lport *lport = exch->lp;
483         static u8 zero_mac[ETH_ALEN] = { 0 };
484
485         if (!IS_ERR(fp))
486                 fip->update_mac(lport, zero_mac);
487         fc_lport_logo_resp(seq, fp, lport);
488 }
489
490 struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did,
491                                       struct fc_frame *fp, unsigned int op,
492                                       void (*resp)(struct fc_seq *,
493                                                    struct fc_frame *,
494                                                    void *),
495                                       void *arg, u32 timeout)
496 {
497         struct fcoe_port *port = lport_priv(lport);
498         struct bnx2fc_hba *hba = port->priv;
499         struct fcoe_ctlr *fip = &hba->ctlr;
500         struct fc_frame_header *fh = fc_frame_header_get(fp);
501
502         switch (op) {
503         case ELS_FLOGI:
504         case ELS_FDISC:
505                 return fc_elsct_send(lport, did, fp, op, bnx2fc_flogi_resp,
506                                      fip, timeout);
507         case ELS_LOGO:
508                 /* only hook onto fabric logouts, not port logouts */
509                 if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI)
510                         break;
511                 return fc_elsct_send(lport, did, fp, op, bnx2fc_logo_resp,
512                                      fip, timeout);
513         }
514         return fc_elsct_send(lport, did, fp, op, resp, arg, timeout);
515 }