1a3667aaeSNaresh Kumar Inna /*
2a3667aaeSNaresh Kumar Inna * This file is part of the Chelsio FCoE driver for Linux.
3a3667aaeSNaresh Kumar Inna *
4a3667aaeSNaresh Kumar Inna * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
5a3667aaeSNaresh Kumar Inna *
6a3667aaeSNaresh Kumar Inna * This software is available to you under a choice of one of two
7a3667aaeSNaresh Kumar Inna * licenses. You may choose to be licensed under the terms of the GNU
8a3667aaeSNaresh Kumar Inna * General Public License (GPL) Version 2, available from the file
9a3667aaeSNaresh Kumar Inna * COPYING in the main directory of this source tree, or the
10a3667aaeSNaresh Kumar Inna * OpenIB.org BSD license below:
11a3667aaeSNaresh Kumar Inna *
12a3667aaeSNaresh Kumar Inna * Redistribution and use in source and binary forms, with or
13a3667aaeSNaresh Kumar Inna * without modification, are permitted provided that the following
14a3667aaeSNaresh Kumar Inna * conditions are met:
15a3667aaeSNaresh Kumar Inna *
16a3667aaeSNaresh Kumar Inna * - Redistributions of source code must retain the above
17a3667aaeSNaresh Kumar Inna * copyright notice, this list of conditions and the following
18a3667aaeSNaresh Kumar Inna * disclaimer.
19a3667aaeSNaresh Kumar Inna *
20a3667aaeSNaresh Kumar Inna * - Redistributions in binary form must reproduce the above
21a3667aaeSNaresh Kumar Inna * copyright notice, this list of conditions and the following
22a3667aaeSNaresh Kumar Inna * disclaimer in the documentation and/or other materials
23a3667aaeSNaresh Kumar Inna * provided with the distribution.
24a3667aaeSNaresh Kumar Inna *
25a3667aaeSNaresh Kumar Inna * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26a3667aaeSNaresh Kumar Inna * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27a3667aaeSNaresh Kumar Inna * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28a3667aaeSNaresh Kumar Inna * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29a3667aaeSNaresh Kumar Inna * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30a3667aaeSNaresh Kumar Inna * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31a3667aaeSNaresh Kumar Inna * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32a3667aaeSNaresh Kumar Inna * SOFTWARE.
33a3667aaeSNaresh Kumar Inna */
34a3667aaeSNaresh Kumar Inna
35a3667aaeSNaresh Kumar Inna #include <linux/kernel.h>
36a3667aaeSNaresh Kumar Inna #include <linux/delay.h>
37a3667aaeSNaresh Kumar Inna #include <linux/slab.h>
38a3667aaeSNaresh Kumar Inna #include <linux/utsname.h>
39a3667aaeSNaresh Kumar Inna #include <scsi/scsi_device.h>
40a3667aaeSNaresh Kumar Inna #include <scsi/scsi_transport_fc.h>
41a3667aaeSNaresh Kumar Inna #include <asm/unaligned.h>
42a3667aaeSNaresh Kumar Inna #include <scsi/fc/fc_els.h>
43a3667aaeSNaresh Kumar Inna #include <scsi/fc/fc_fs.h>
44a3667aaeSNaresh Kumar Inna #include <scsi/fc/fc_gs.h>
45a3667aaeSNaresh Kumar Inna #include <scsi/fc/fc_ms.h>
46a3667aaeSNaresh Kumar Inna
47a3667aaeSNaresh Kumar Inna #include "csio_hw.h"
48a3667aaeSNaresh Kumar Inna #include "csio_mb.h"
49a3667aaeSNaresh Kumar Inna #include "csio_lnode.h"
50a3667aaeSNaresh Kumar Inna #include "csio_rnode.h"
51a3667aaeSNaresh Kumar Inna
52a3667aaeSNaresh Kumar Inna int csio_fcoe_rnodes = 1024;
53a3667aaeSNaresh Kumar Inna int csio_fdmi_enable = 1;
54a3667aaeSNaresh Kumar Inna
55a3667aaeSNaresh Kumar Inna #define PORT_ID_PTR(_x) ((uint8_t *)(&_x) + 1)
56a3667aaeSNaresh Kumar Inna
57a3667aaeSNaresh Kumar Inna /* Lnode SM declarations */
58a3667aaeSNaresh Kumar Inna static void csio_lns_uninit(struct csio_lnode *, enum csio_ln_ev);
59a3667aaeSNaresh Kumar Inna static void csio_lns_online(struct csio_lnode *, enum csio_ln_ev);
60a3667aaeSNaresh Kumar Inna static void csio_lns_ready(struct csio_lnode *, enum csio_ln_ev);
61a3667aaeSNaresh Kumar Inna static void csio_lns_offline(struct csio_lnode *, enum csio_ln_ev);
62a3667aaeSNaresh Kumar Inna
63a3667aaeSNaresh Kumar Inna static int csio_ln_mgmt_submit_req(struct csio_ioreq *,
64a3667aaeSNaresh Kumar Inna void (*io_cbfn) (struct csio_hw *, struct csio_ioreq *),
65a3667aaeSNaresh Kumar Inna enum fcoe_cmn_type, struct csio_dma_buf *, uint32_t);
66a3667aaeSNaresh Kumar Inna
67a3667aaeSNaresh Kumar Inna /* LN event mapping */
68a3667aaeSNaresh Kumar Inna static enum csio_ln_ev fwevt_to_lnevt[] = {
69a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* None */
70a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* PLOGI_ACC_RCVD */
71a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* PLOGI_RJT_RCVD */
72a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* PLOGI_RCVD */
73a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* PLOGO_RCVD */
74a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* PRLI_ACC_RCVD */
75a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* PRLI_RJT_RCVD */
76a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* PRLI_RCVD */
77a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* PRLO_RCVD */
78a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* NPORT_ID_CHGD */
79a3667aaeSNaresh Kumar Inna CSIO_LNE_LOGO, /* FLOGO_RCVD */
80a3667aaeSNaresh Kumar Inna CSIO_LNE_LOGO, /* CLR_VIRT_LNK_RCVD */
81a3667aaeSNaresh Kumar Inna CSIO_LNE_FAB_INIT_DONE,/* FLOGI_ACC_RCVD */
82a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* FLOGI_RJT_RCVD */
83a3667aaeSNaresh Kumar Inna CSIO_LNE_FAB_INIT_DONE,/* FDISC_ACC_RCVD */
84a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* FDISC_RJT_RCVD */
85a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* FLOGI_TMO_MAX_RETRY */
86a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* IMPL_LOGO_ADISC_ACC */
87a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* IMPL_LOGO_ADISC_RJT */
88a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* IMPL_LOGO_ADISC_CNFLT */
89a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* PRLI_TMO */
90a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* ADISC_TMO */
91a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* RSCN_DEV_LOST */
92a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* SCR_ACC_RCVD */
93a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* ADISC_RJT_RCVD */
94a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* LOGO_SNT */
95a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE, /* PROTO_ERR_IMPL_LOGO */
96a3667aaeSNaresh Kumar Inna };
97a3667aaeSNaresh Kumar Inna
98a3667aaeSNaresh Kumar Inna #define CSIO_FWE_TO_LNE(_evt) ((_evt > PROTO_ERR_IMPL_LOGO) ? \
99a3667aaeSNaresh Kumar Inna CSIO_LNE_NONE : \
100a3667aaeSNaresh Kumar Inna fwevt_to_lnevt[_evt])
101a3667aaeSNaresh Kumar Inna
102a3667aaeSNaresh Kumar Inna #define csio_ct_rsp(cp) (((struct fc_ct_hdr *)cp)->ct_cmd)
103a3667aaeSNaresh Kumar Inna #define csio_ct_reason(cp) (((struct fc_ct_hdr *)cp)->ct_reason)
104a3667aaeSNaresh Kumar Inna #define csio_ct_expl(cp) (((struct fc_ct_hdr *)cp)->ct_explan)
105a3667aaeSNaresh Kumar Inna #define csio_ct_get_pld(cp) ((void *)(((uint8_t *)cp) + FC_CT_HDR_LEN))
106a3667aaeSNaresh Kumar Inna
107a3667aaeSNaresh Kumar Inna /*
108a3667aaeSNaresh Kumar Inna * csio_ln_match_by_portid - lookup lnode using given portid.
109a3667aaeSNaresh Kumar Inna * @hw: HW module
110a3667aaeSNaresh Kumar Inna * @portid: port-id.
111a3667aaeSNaresh Kumar Inna *
112a3667aaeSNaresh Kumar Inna * If found, returns lnode matching given portid otherwise returns NULL.
113a3667aaeSNaresh Kumar Inna */
114a3667aaeSNaresh Kumar Inna static struct csio_lnode *
csio_ln_lookup_by_portid(struct csio_hw * hw,uint8_t portid)115a3667aaeSNaresh Kumar Inna csio_ln_lookup_by_portid(struct csio_hw *hw, uint8_t portid)
116a3667aaeSNaresh Kumar Inna {
11752797a1dSColin Ian King struct csio_lnode *ln;
118a3667aaeSNaresh Kumar Inna struct list_head *tmp;
119a3667aaeSNaresh Kumar Inna
120a3667aaeSNaresh Kumar Inna /* Match siblings lnode with portid */
121a3667aaeSNaresh Kumar Inna list_for_each(tmp, &hw->sln_head) {
122a3667aaeSNaresh Kumar Inna ln = (struct csio_lnode *) tmp;
123a3667aaeSNaresh Kumar Inna if (ln->portid == portid)
124a3667aaeSNaresh Kumar Inna return ln;
125a3667aaeSNaresh Kumar Inna }
126a3667aaeSNaresh Kumar Inna
127a3667aaeSNaresh Kumar Inna return NULL;
128a3667aaeSNaresh Kumar Inna }
129a3667aaeSNaresh Kumar Inna
130a3667aaeSNaresh Kumar Inna /*
131a3667aaeSNaresh Kumar Inna * csio_ln_lookup_by_vnpi - Lookup lnode using given vnp id.
132a3667aaeSNaresh Kumar Inna * @hw - HW module
133a3667aaeSNaresh Kumar Inna * @vnpi - vnp index.
134a3667aaeSNaresh Kumar Inna * Returns - If found, returns lnode matching given vnp id
135a3667aaeSNaresh Kumar Inna * otherwise returns NULL.
136a3667aaeSNaresh Kumar Inna */
137a3667aaeSNaresh Kumar Inna static struct csio_lnode *
csio_ln_lookup_by_vnpi(struct csio_hw * hw,uint32_t vnp_id)138a3667aaeSNaresh Kumar Inna csio_ln_lookup_by_vnpi(struct csio_hw *hw, uint32_t vnp_id)
139a3667aaeSNaresh Kumar Inna {
140a3667aaeSNaresh Kumar Inna struct list_head *tmp1, *tmp2;
141a3667aaeSNaresh Kumar Inna struct csio_lnode *sln = NULL, *cln = NULL;
142a3667aaeSNaresh Kumar Inna
143a3667aaeSNaresh Kumar Inna if (list_empty(&hw->sln_head)) {
144a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_lnlkup_miss);
145a3667aaeSNaresh Kumar Inna return NULL;
146a3667aaeSNaresh Kumar Inna }
147a3667aaeSNaresh Kumar Inna /* Traverse sibling lnodes */
148a3667aaeSNaresh Kumar Inna list_for_each(tmp1, &hw->sln_head) {
149a3667aaeSNaresh Kumar Inna sln = (struct csio_lnode *) tmp1;
150a3667aaeSNaresh Kumar Inna
151a3667aaeSNaresh Kumar Inna /* Match sibling lnode */
152a3667aaeSNaresh Kumar Inna if (sln->vnp_flowid == vnp_id)
153a3667aaeSNaresh Kumar Inna return sln;
154a3667aaeSNaresh Kumar Inna
155a3667aaeSNaresh Kumar Inna if (list_empty(&sln->cln_head))
156a3667aaeSNaresh Kumar Inna continue;
157a3667aaeSNaresh Kumar Inna
158a3667aaeSNaresh Kumar Inna /* Traverse children lnodes */
159a3667aaeSNaresh Kumar Inna list_for_each(tmp2, &sln->cln_head) {
160a3667aaeSNaresh Kumar Inna cln = (struct csio_lnode *) tmp2;
161a3667aaeSNaresh Kumar Inna
162a3667aaeSNaresh Kumar Inna if (cln->vnp_flowid == vnp_id)
163a3667aaeSNaresh Kumar Inna return cln;
164a3667aaeSNaresh Kumar Inna }
165a3667aaeSNaresh Kumar Inna }
166a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_lnlkup_miss);
167a3667aaeSNaresh Kumar Inna return NULL;
168a3667aaeSNaresh Kumar Inna }
169a3667aaeSNaresh Kumar Inna
170a3667aaeSNaresh Kumar Inna /**
171a3667aaeSNaresh Kumar Inna * csio_lnode_lookup_by_wwpn - Lookup lnode using given wwpn.
172a3667aaeSNaresh Kumar Inna * @hw: HW module.
173a3667aaeSNaresh Kumar Inna * @wwpn: WWPN.
174a3667aaeSNaresh Kumar Inna *
175a3667aaeSNaresh Kumar Inna * If found, returns lnode matching given wwpn, returns NULL otherwise.
176a3667aaeSNaresh Kumar Inna */
177a3667aaeSNaresh Kumar Inna struct csio_lnode *
csio_lnode_lookup_by_wwpn(struct csio_hw * hw,uint8_t * wwpn)178a3667aaeSNaresh Kumar Inna csio_lnode_lookup_by_wwpn(struct csio_hw *hw, uint8_t *wwpn)
179a3667aaeSNaresh Kumar Inna {
180a3667aaeSNaresh Kumar Inna struct list_head *tmp1, *tmp2;
181a3667aaeSNaresh Kumar Inna struct csio_lnode *sln = NULL, *cln = NULL;
182a3667aaeSNaresh Kumar Inna
183a3667aaeSNaresh Kumar Inna if (list_empty(&hw->sln_head)) {
184a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_lnlkup_miss);
185a3667aaeSNaresh Kumar Inna return NULL;
186a3667aaeSNaresh Kumar Inna }
187a3667aaeSNaresh Kumar Inna /* Traverse sibling lnodes */
188a3667aaeSNaresh Kumar Inna list_for_each(tmp1, &hw->sln_head) {
189a3667aaeSNaresh Kumar Inna sln = (struct csio_lnode *) tmp1;
190a3667aaeSNaresh Kumar Inna
191a3667aaeSNaresh Kumar Inna /* Match sibling lnode */
192a3667aaeSNaresh Kumar Inna if (!memcmp(csio_ln_wwpn(sln), wwpn, 8))
193a3667aaeSNaresh Kumar Inna return sln;
194a3667aaeSNaresh Kumar Inna
195a3667aaeSNaresh Kumar Inna if (list_empty(&sln->cln_head))
196a3667aaeSNaresh Kumar Inna continue;
197a3667aaeSNaresh Kumar Inna
198a3667aaeSNaresh Kumar Inna /* Traverse children lnodes */
199a3667aaeSNaresh Kumar Inna list_for_each(tmp2, &sln->cln_head) {
200a3667aaeSNaresh Kumar Inna cln = (struct csio_lnode *) tmp2;
201a3667aaeSNaresh Kumar Inna
202a3667aaeSNaresh Kumar Inna if (!memcmp(csio_ln_wwpn(cln), wwpn, 8))
203a3667aaeSNaresh Kumar Inna return cln;
204a3667aaeSNaresh Kumar Inna }
205a3667aaeSNaresh Kumar Inna }
206a3667aaeSNaresh Kumar Inna return NULL;
207a3667aaeSNaresh Kumar Inna }
208a3667aaeSNaresh Kumar Inna
209a3667aaeSNaresh Kumar Inna /* FDMI */
210a3667aaeSNaresh Kumar Inna static void
csio_fill_ct_iu(void * buf,uint8_t type,uint8_t sub_type,uint16_t op)211a3667aaeSNaresh Kumar Inna csio_fill_ct_iu(void *buf, uint8_t type, uint8_t sub_type, uint16_t op)
212a3667aaeSNaresh Kumar Inna {
213a3667aaeSNaresh Kumar Inna struct fc_ct_hdr *cmd = (struct fc_ct_hdr *)buf;
214a3667aaeSNaresh Kumar Inna cmd->ct_rev = FC_CT_REV;
215a3667aaeSNaresh Kumar Inna cmd->ct_fs_type = type;
216a3667aaeSNaresh Kumar Inna cmd->ct_fs_subtype = sub_type;
2175036f0a0SNaresh Kumar Inna cmd->ct_cmd = htons(op);
218a3667aaeSNaresh Kumar Inna }
219a3667aaeSNaresh Kumar Inna
220a3667aaeSNaresh Kumar Inna static int
csio_hostname(uint8_t * buf,size_t buf_len)221a3667aaeSNaresh Kumar Inna csio_hostname(uint8_t *buf, size_t buf_len)
222a3667aaeSNaresh Kumar Inna {
223a3667aaeSNaresh Kumar Inna if (snprintf(buf, buf_len, "%s", init_utsname()->nodename) > 0)
224a3667aaeSNaresh Kumar Inna return 0;
225a3667aaeSNaresh Kumar Inna return -1;
226a3667aaeSNaresh Kumar Inna }
227a3667aaeSNaresh Kumar Inna
228a3667aaeSNaresh Kumar Inna static int
csio_osname(uint8_t * buf,size_t buf_len)229a3667aaeSNaresh Kumar Inna csio_osname(uint8_t *buf, size_t buf_len)
230a3667aaeSNaresh Kumar Inna {
231a3667aaeSNaresh Kumar Inna if (snprintf(buf, buf_len, "%s %s %s",
232a3667aaeSNaresh Kumar Inna init_utsname()->sysname,
233a3667aaeSNaresh Kumar Inna init_utsname()->release,
234a3667aaeSNaresh Kumar Inna init_utsname()->version) > 0)
235a3667aaeSNaresh Kumar Inna return 0;
236a3667aaeSNaresh Kumar Inna
237a3667aaeSNaresh Kumar Inna return -1;
238a3667aaeSNaresh Kumar Inna }
239a3667aaeSNaresh Kumar Inna
240a3667aaeSNaresh Kumar Inna static inline void
csio_append_attrib(uint8_t ** ptr,uint16_t type,void * val,size_t val_len)24142c335f7SKees Cook csio_append_attrib(uint8_t **ptr, uint16_t type, void *val, size_t val_len)
242a3667aaeSNaresh Kumar Inna {
24342c335f7SKees Cook uint16_t len;
244a3667aaeSNaresh Kumar Inna struct fc_fdmi_attr_entry *ae = (struct fc_fdmi_attr_entry *)*ptr;
24542c335f7SKees Cook
24642c335f7SKees Cook if (WARN_ON(val_len > U16_MAX))
24742c335f7SKees Cook return;
24842c335f7SKees Cook
24942c335f7SKees Cook len = val_len;
25042c335f7SKees Cook
251a3667aaeSNaresh Kumar Inna ae->type = htons(type);
252a3667aaeSNaresh Kumar Inna len += 4; /* includes attribute type and length */
253a3667aaeSNaresh Kumar Inna len = (len + 3) & ~3; /* should be multiple of 4 bytes */
254a3667aaeSNaresh Kumar Inna ae->len = htons(len);
25542c335f7SKees Cook memcpy(ae->value, val, val_len);
25642c335f7SKees Cook if (len > val_len)
25742c335f7SKees Cook memset(ae->value + val_len, 0, len - val_len);
258a3667aaeSNaresh Kumar Inna *ptr += len;
259a3667aaeSNaresh Kumar Inna }
260a3667aaeSNaresh Kumar Inna
261a3667aaeSNaresh Kumar Inna /*
262a3667aaeSNaresh Kumar Inna * csio_ln_fdmi_done - FDMI registeration completion
263a3667aaeSNaresh Kumar Inna * @hw: HW context
264a3667aaeSNaresh Kumar Inna * @fdmi_req: fdmi request
265a3667aaeSNaresh Kumar Inna */
266a3667aaeSNaresh Kumar Inna static void
csio_ln_fdmi_done(struct csio_hw * hw,struct csio_ioreq * fdmi_req)267a3667aaeSNaresh Kumar Inna csio_ln_fdmi_done(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
268a3667aaeSNaresh Kumar Inna {
269a3667aaeSNaresh Kumar Inna void *cmd;
270a3667aaeSNaresh Kumar Inna struct csio_lnode *ln = fdmi_req->lnode;
271a3667aaeSNaresh Kumar Inna
272a3667aaeSNaresh Kumar Inna if (fdmi_req->wr_status != FW_SUCCESS) {
273a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln, "WR error:%x in processing fdmi rpa cmd\n",
274a3667aaeSNaresh Kumar Inna fdmi_req->wr_status);
275a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_fdmi_err);
276a3667aaeSNaresh Kumar Inna }
277a3667aaeSNaresh Kumar Inna
278a3667aaeSNaresh Kumar Inna cmd = fdmi_req->dma_buf.vaddr;
279a3667aaeSNaresh Kumar Inna if (ntohs(csio_ct_rsp(cmd)) != FC_FS_ACC) {
280a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln, "fdmi rpa cmd rejected reason %x expl %x\n",
281a3667aaeSNaresh Kumar Inna csio_ct_reason(cmd), csio_ct_expl(cmd));
282a3667aaeSNaresh Kumar Inna }
283a3667aaeSNaresh Kumar Inna }
284a3667aaeSNaresh Kumar Inna
285a3667aaeSNaresh Kumar Inna /*
286a3667aaeSNaresh Kumar Inna * csio_ln_fdmi_rhba_cbfn - RHBA completion
287a3667aaeSNaresh Kumar Inna * @hw: HW context
288a3667aaeSNaresh Kumar Inna * @fdmi_req: fdmi request
289a3667aaeSNaresh Kumar Inna */
290a3667aaeSNaresh Kumar Inna static void
csio_ln_fdmi_rhba_cbfn(struct csio_hw * hw,struct csio_ioreq * fdmi_req)291a3667aaeSNaresh Kumar Inna csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
292a3667aaeSNaresh Kumar Inna {
293a3667aaeSNaresh Kumar Inna void *cmd;
294a3667aaeSNaresh Kumar Inna uint8_t *pld;
295a3667aaeSNaresh Kumar Inna uint32_t len = 0;
2965036f0a0SNaresh Kumar Inna __be32 val;
2975036f0a0SNaresh Kumar Inna __be16 mfs;
2985036f0a0SNaresh Kumar Inna uint32_t numattrs = 0;
299a3667aaeSNaresh Kumar Inna struct csio_lnode *ln = fdmi_req->lnode;
300a3667aaeSNaresh Kumar Inna struct fs_fdmi_attrs *attrib_blk;
301a3667aaeSNaresh Kumar Inna struct fc_fdmi_port_name *port_name;
302a3667aaeSNaresh Kumar Inna uint8_t buf[64];
303a3667aaeSNaresh Kumar Inna uint8_t *fc4_type;
304d6c9b31aSDan Carpenter unsigned long flags;
305a3667aaeSNaresh Kumar Inna
306a3667aaeSNaresh Kumar Inna if (fdmi_req->wr_status != FW_SUCCESS) {
307a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln, "WR error:%x in processing fdmi rhba cmd\n",
308a3667aaeSNaresh Kumar Inna fdmi_req->wr_status);
309a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_fdmi_err);
310a3667aaeSNaresh Kumar Inna }
311a3667aaeSNaresh Kumar Inna
312a3667aaeSNaresh Kumar Inna cmd = fdmi_req->dma_buf.vaddr;
313a3667aaeSNaresh Kumar Inna if (ntohs(csio_ct_rsp(cmd)) != FC_FS_ACC) {
314a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln, "fdmi rhba cmd rejected reason %x expl %x\n",
315a3667aaeSNaresh Kumar Inna csio_ct_reason(cmd), csio_ct_expl(cmd));
316a3667aaeSNaresh Kumar Inna }
317a3667aaeSNaresh Kumar Inna
318a3667aaeSNaresh Kumar Inna if (!csio_is_rnode_ready(fdmi_req->rnode)) {
319a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_fdmi_err);
320a3667aaeSNaresh Kumar Inna return;
321a3667aaeSNaresh Kumar Inna }
322a3667aaeSNaresh Kumar Inna
323a3667aaeSNaresh Kumar Inna /* Prepare CT hdr for RPA cmd */
324a3667aaeSNaresh Kumar Inna memset(cmd, 0, FC_CT_HDR_LEN);
3255036f0a0SNaresh Kumar Inna csio_fill_ct_iu(cmd, FC_FST_MGMT, FC_FDMI_SUBTYPE, FC_FDMI_RPA);
326a3667aaeSNaresh Kumar Inna
327a3667aaeSNaresh Kumar Inna /* Prepare RPA payload */
328a3667aaeSNaresh Kumar Inna pld = (uint8_t *)csio_ct_get_pld(cmd);
329a3667aaeSNaresh Kumar Inna port_name = (struct fc_fdmi_port_name *)pld;
330a3667aaeSNaresh Kumar Inna memcpy(&port_name->portname, csio_ln_wwpn(ln), 8);
331a3667aaeSNaresh Kumar Inna pld += sizeof(*port_name);
332a3667aaeSNaresh Kumar Inna
333a3667aaeSNaresh Kumar Inna /* Start appending Port attributes */
334a3667aaeSNaresh Kumar Inna attrib_blk = (struct fs_fdmi_attrs *)pld;
335a3667aaeSNaresh Kumar Inna attrib_blk->numattrs = 0;
336a3667aaeSNaresh Kumar Inna len += sizeof(attrib_blk->numattrs);
337a3667aaeSNaresh Kumar Inna pld += sizeof(attrib_blk->numattrs);
338a3667aaeSNaresh Kumar Inna
339a3667aaeSNaresh Kumar Inna fc4_type = &buf[0];
340a3667aaeSNaresh Kumar Inna memset(fc4_type, 0, FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
341a3667aaeSNaresh Kumar Inna fc4_type[2] = 1;
342a3667aaeSNaresh Kumar Inna fc4_type[7] = 1;
343a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_FC4TYPES,
344a3667aaeSNaresh Kumar Inna fc4_type, FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
3455036f0a0SNaresh Kumar Inna numattrs++;
346a3667aaeSNaresh Kumar Inna val = htonl(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
347a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_SUPPORTEDSPEED,
34842c335f7SKees Cook &val,
349a3667aaeSNaresh Kumar Inna FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN);
3505036f0a0SNaresh Kumar Inna numattrs++;
351a3667aaeSNaresh Kumar Inna
352a3667aaeSNaresh Kumar Inna if (hw->pport[ln->portid].link_speed == FW_PORT_CAP_SPEED_1G)
353a3667aaeSNaresh Kumar Inna val = htonl(FC_PORTSPEED_1GBIT);
354a3667aaeSNaresh Kumar Inna else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP_SPEED_10G)
355a3667aaeSNaresh Kumar Inna val = htonl(FC_PORTSPEED_10GBIT);
356e1735d9aSVarun Prakash else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_25G)
357e1735d9aSVarun Prakash val = htonl(FC_PORTSPEED_25GBIT);
358e1735d9aSVarun Prakash else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_40G)
359e1735d9aSVarun Prakash val = htonl(FC_PORTSPEED_40GBIT);
360e1735d9aSVarun Prakash else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_50G)
361e1735d9aSVarun Prakash val = htonl(FC_PORTSPEED_50GBIT);
362e1735d9aSVarun Prakash else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_100G)
363e1735d9aSVarun Prakash val = htonl(FC_PORTSPEED_100GBIT);
364a3667aaeSNaresh Kumar Inna else
365a3667aaeSNaresh Kumar Inna val = htonl(CSIO_HBA_PORTSPEED_UNKNOWN);
366a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
36742c335f7SKees Cook &val, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN);
3685036f0a0SNaresh Kumar Inna numattrs++;
369a3667aaeSNaresh Kumar Inna
3705036f0a0SNaresh Kumar Inna mfs = ln->ln_sparm.csp.sp_bb_data;
371a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_MAXFRAMESIZE,
37242c335f7SKees Cook &mfs, sizeof(mfs));
3735036f0a0SNaresh Kumar Inna numattrs++;
374a3667aaeSNaresh Kumar Inna
375a3667aaeSNaresh Kumar Inna strcpy(buf, "csiostor");
376a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_OSDEVICENAME, buf,
37742c335f7SKees Cook strlen(buf));
3785036f0a0SNaresh Kumar Inna numattrs++;
379a3667aaeSNaresh Kumar Inna
380a3667aaeSNaresh Kumar Inna if (!csio_hostname(buf, sizeof(buf))) {
381a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_HOSTNAME,
38242c335f7SKees Cook buf, strlen(buf));
3835036f0a0SNaresh Kumar Inna numattrs++;
384a3667aaeSNaresh Kumar Inna }
3855036f0a0SNaresh Kumar Inna attrib_blk->numattrs = htonl(numattrs);
386a3667aaeSNaresh Kumar Inna len = (uint32_t)(pld - (uint8_t *)cmd);
387a3667aaeSNaresh Kumar Inna
388a3667aaeSNaresh Kumar Inna /* Submit FDMI RPA request */
389d6c9b31aSDan Carpenter spin_lock_irqsave(&hw->lock, flags);
390a3667aaeSNaresh Kumar Inna if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_done,
391a3667aaeSNaresh Kumar Inna FCOE_CT, &fdmi_req->dma_buf, len)) {
392a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_fdmi_err);
393a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln, "Failed to issue fdmi rpa req\n");
394a3667aaeSNaresh Kumar Inna }
395d6c9b31aSDan Carpenter spin_unlock_irqrestore(&hw->lock, flags);
396a3667aaeSNaresh Kumar Inna }
397a3667aaeSNaresh Kumar Inna
398a3667aaeSNaresh Kumar Inna /*
399a3667aaeSNaresh Kumar Inna * csio_ln_fdmi_dprt_cbfn - DPRT completion
400a3667aaeSNaresh Kumar Inna * @hw: HW context
401a3667aaeSNaresh Kumar Inna * @fdmi_req: fdmi request
402a3667aaeSNaresh Kumar Inna */
403a3667aaeSNaresh Kumar Inna static void
csio_ln_fdmi_dprt_cbfn(struct csio_hw * hw,struct csio_ioreq * fdmi_req)404a3667aaeSNaresh Kumar Inna csio_ln_fdmi_dprt_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
405a3667aaeSNaresh Kumar Inna {
406a3667aaeSNaresh Kumar Inna void *cmd;
407a3667aaeSNaresh Kumar Inna uint8_t *pld;
408a3667aaeSNaresh Kumar Inna uint32_t len = 0;
4095036f0a0SNaresh Kumar Inna uint32_t numattrs = 0;
4105036f0a0SNaresh Kumar Inna __be32 maxpayload = htonl(65536);
411a3667aaeSNaresh Kumar Inna struct fc_fdmi_hba_identifier *hbaid;
412a3667aaeSNaresh Kumar Inna struct csio_lnode *ln = fdmi_req->lnode;
413a3667aaeSNaresh Kumar Inna struct fc_fdmi_rpl *reg_pl;
414a3667aaeSNaresh Kumar Inna struct fs_fdmi_attrs *attrib_blk;
415a3667aaeSNaresh Kumar Inna uint8_t buf[64];
416d6c9b31aSDan Carpenter unsigned long flags;
417a3667aaeSNaresh Kumar Inna
418a3667aaeSNaresh Kumar Inna if (fdmi_req->wr_status != FW_SUCCESS) {
419a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln, "WR error:%x in processing fdmi dprt cmd\n",
420a3667aaeSNaresh Kumar Inna fdmi_req->wr_status);
421a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_fdmi_err);
422a3667aaeSNaresh Kumar Inna }
423a3667aaeSNaresh Kumar Inna
424a3667aaeSNaresh Kumar Inna if (!csio_is_rnode_ready(fdmi_req->rnode)) {
425a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_fdmi_err);
426a3667aaeSNaresh Kumar Inna return;
427a3667aaeSNaresh Kumar Inna }
428a3667aaeSNaresh Kumar Inna cmd = fdmi_req->dma_buf.vaddr;
429a3667aaeSNaresh Kumar Inna if (ntohs(csio_ct_rsp(cmd)) != FC_FS_ACC) {
430a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln, "fdmi dprt cmd rejected reason %x expl %x\n",
431a3667aaeSNaresh Kumar Inna csio_ct_reason(cmd), csio_ct_expl(cmd));
432a3667aaeSNaresh Kumar Inna }
433a3667aaeSNaresh Kumar Inna
434a3667aaeSNaresh Kumar Inna /* Prepare CT hdr for RHBA cmd */
435a3667aaeSNaresh Kumar Inna memset(cmd, 0, FC_CT_HDR_LEN);
4365036f0a0SNaresh Kumar Inna csio_fill_ct_iu(cmd, FC_FST_MGMT, FC_FDMI_SUBTYPE, FC_FDMI_RHBA);
437a3667aaeSNaresh Kumar Inna len = FC_CT_HDR_LEN;
438a3667aaeSNaresh Kumar Inna
439a3667aaeSNaresh Kumar Inna /* Prepare RHBA payload */
440a3667aaeSNaresh Kumar Inna pld = (uint8_t *)csio_ct_get_pld(cmd);
441a3667aaeSNaresh Kumar Inna hbaid = (struct fc_fdmi_hba_identifier *)pld;
442a3667aaeSNaresh Kumar Inna memcpy(&hbaid->id, csio_ln_wwpn(ln), 8); /* HBA identifer */
443a3667aaeSNaresh Kumar Inna pld += sizeof(*hbaid);
444a3667aaeSNaresh Kumar Inna
445a3667aaeSNaresh Kumar Inna /* Register one port per hba */
446a3667aaeSNaresh Kumar Inna reg_pl = (struct fc_fdmi_rpl *)pld;
4475036f0a0SNaresh Kumar Inna reg_pl->numport = htonl(1);
448a3667aaeSNaresh Kumar Inna memcpy(®_pl->port[0].portname, csio_ln_wwpn(ln), 8);
449a3667aaeSNaresh Kumar Inna pld += sizeof(*reg_pl);
450a3667aaeSNaresh Kumar Inna
451a3667aaeSNaresh Kumar Inna /* Start appending HBA attributes hba */
452a3667aaeSNaresh Kumar Inna attrib_blk = (struct fs_fdmi_attrs *)pld;
453a3667aaeSNaresh Kumar Inna attrib_blk->numattrs = 0;
454a3667aaeSNaresh Kumar Inna len += sizeof(attrib_blk->numattrs);
455a3667aaeSNaresh Kumar Inna pld += sizeof(attrib_blk->numattrs);
456a3667aaeSNaresh Kumar Inna
457a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_NODENAME, csio_ln_wwnn(ln),
458a3667aaeSNaresh Kumar Inna FC_FDMI_HBA_ATTR_NODENAME_LEN);
4595036f0a0SNaresh Kumar Inna numattrs++;
460a3667aaeSNaresh Kumar Inna
461a3667aaeSNaresh Kumar Inna memset(buf, 0, sizeof(buf));
462a3667aaeSNaresh Kumar Inna
463a3667aaeSNaresh Kumar Inna strcpy(buf, "Chelsio Communications");
464a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MANUFACTURER, buf,
46542c335f7SKees Cook strlen(buf));
4665036f0a0SNaresh Kumar Inna numattrs++;
467a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_SERIALNUMBER,
46842c335f7SKees Cook hw->vpd.sn, sizeof(hw->vpd.sn));
4695036f0a0SNaresh Kumar Inna numattrs++;
470a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MODEL, hw->vpd.id,
47142c335f7SKees Cook sizeof(hw->vpd.id));
4725036f0a0SNaresh Kumar Inna numattrs++;
473a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MODELDESCRIPTION,
47442c335f7SKees Cook hw->model_desc, strlen(hw->model_desc));
4755036f0a0SNaresh Kumar Inna numattrs++;
476a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_HARDWAREVERSION,
47742c335f7SKees Cook hw->hw_ver, sizeof(hw->hw_ver));
4785036f0a0SNaresh Kumar Inna numattrs++;
479a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_FIRMWAREVERSION,
48042c335f7SKees Cook hw->fwrev_str, strlen(hw->fwrev_str));
4815036f0a0SNaresh Kumar Inna numattrs++;
482a3667aaeSNaresh Kumar Inna
483a3667aaeSNaresh Kumar Inna if (!csio_osname(buf, sizeof(buf))) {
484a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_OSNAMEVERSION,
48542c335f7SKees Cook buf, strlen(buf));
4865036f0a0SNaresh Kumar Inna numattrs++;
487a3667aaeSNaresh Kumar Inna }
488a3667aaeSNaresh Kumar Inna
489a3667aaeSNaresh Kumar Inna csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MAXCTPAYLOAD,
49042c335f7SKees Cook &maxpayload, FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN);
491a3667aaeSNaresh Kumar Inna len = (uint32_t)(pld - (uint8_t *)cmd);
4925036f0a0SNaresh Kumar Inna numattrs++;
4935036f0a0SNaresh Kumar Inna attrib_blk->numattrs = htonl(numattrs);
494a3667aaeSNaresh Kumar Inna
495a3667aaeSNaresh Kumar Inna /* Submit FDMI RHBA request */
496d6c9b31aSDan Carpenter spin_lock_irqsave(&hw->lock, flags);
497a3667aaeSNaresh Kumar Inna if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_rhba_cbfn,
498a3667aaeSNaresh Kumar Inna FCOE_CT, &fdmi_req->dma_buf, len)) {
499a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_fdmi_err);
500a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln, "Failed to issue fdmi rhba req\n");
501a3667aaeSNaresh Kumar Inna }
502d6c9b31aSDan Carpenter spin_unlock_irqrestore(&hw->lock, flags);
503a3667aaeSNaresh Kumar Inna }
504a3667aaeSNaresh Kumar Inna
505a3667aaeSNaresh Kumar Inna /*
506a3667aaeSNaresh Kumar Inna * csio_ln_fdmi_dhba_cbfn - DHBA completion
507a3667aaeSNaresh Kumar Inna * @hw: HW context
508a3667aaeSNaresh Kumar Inna * @fdmi_req: fdmi request
509a3667aaeSNaresh Kumar Inna */
510a3667aaeSNaresh Kumar Inna static void
csio_ln_fdmi_dhba_cbfn(struct csio_hw * hw,struct csio_ioreq * fdmi_req)511a3667aaeSNaresh Kumar Inna csio_ln_fdmi_dhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
512a3667aaeSNaresh Kumar Inna {
513a3667aaeSNaresh Kumar Inna struct csio_lnode *ln = fdmi_req->lnode;
514a3667aaeSNaresh Kumar Inna void *cmd;
515a3667aaeSNaresh Kumar Inna struct fc_fdmi_port_name *port_name;
516a3667aaeSNaresh Kumar Inna uint32_t len;
517d6c9b31aSDan Carpenter unsigned long flags;
518a3667aaeSNaresh Kumar Inna
519a3667aaeSNaresh Kumar Inna if (fdmi_req->wr_status != FW_SUCCESS) {
520a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln, "WR error:%x in processing fdmi dhba cmd\n",
521a3667aaeSNaresh Kumar Inna fdmi_req->wr_status);
522a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_fdmi_err);
523a3667aaeSNaresh Kumar Inna }
524a3667aaeSNaresh Kumar Inna
525a3667aaeSNaresh Kumar Inna if (!csio_is_rnode_ready(fdmi_req->rnode)) {
526a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_fdmi_err);
527a3667aaeSNaresh Kumar Inna return;
528a3667aaeSNaresh Kumar Inna }
529a3667aaeSNaresh Kumar Inna cmd = fdmi_req->dma_buf.vaddr;
530a3667aaeSNaresh Kumar Inna if (ntohs(csio_ct_rsp(cmd)) != FC_FS_ACC) {
531a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln, "fdmi dhba cmd rejected reason %x expl %x\n",
532a3667aaeSNaresh Kumar Inna csio_ct_reason(cmd), csio_ct_expl(cmd));
533a3667aaeSNaresh Kumar Inna }
534a3667aaeSNaresh Kumar Inna
535a3667aaeSNaresh Kumar Inna /* Send FDMI cmd to de-register any Port attributes if registered
536a3667aaeSNaresh Kumar Inna * before
537a3667aaeSNaresh Kumar Inna */
538a3667aaeSNaresh Kumar Inna
539a3667aaeSNaresh Kumar Inna /* Prepare FDMI DPRT cmd */
540a3667aaeSNaresh Kumar Inna memset(cmd, 0, FC_CT_HDR_LEN);
5415036f0a0SNaresh Kumar Inna csio_fill_ct_iu(cmd, FC_FST_MGMT, FC_FDMI_SUBTYPE, FC_FDMI_DPRT);
542a3667aaeSNaresh Kumar Inna len = FC_CT_HDR_LEN;
543a3667aaeSNaresh Kumar Inna port_name = (struct fc_fdmi_port_name *)csio_ct_get_pld(cmd);
544a3667aaeSNaresh Kumar Inna memcpy(&port_name->portname, csio_ln_wwpn(ln), 8);
545a3667aaeSNaresh Kumar Inna len += sizeof(*port_name);
546a3667aaeSNaresh Kumar Inna
547a3667aaeSNaresh Kumar Inna /* Submit FDMI request */
548d6c9b31aSDan Carpenter spin_lock_irqsave(&hw->lock, flags);
549a3667aaeSNaresh Kumar Inna if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_dprt_cbfn,
550a3667aaeSNaresh Kumar Inna FCOE_CT, &fdmi_req->dma_buf, len)) {
551a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_fdmi_err);
552a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln, "Failed to issue fdmi dprt req\n");
553a3667aaeSNaresh Kumar Inna }
554d6c9b31aSDan Carpenter spin_unlock_irqrestore(&hw->lock, flags);
555a3667aaeSNaresh Kumar Inna }
556a3667aaeSNaresh Kumar Inna
557a3667aaeSNaresh Kumar Inna /**
558a3667aaeSNaresh Kumar Inna * csio_ln_fdmi_start - Start an FDMI request.
559a3667aaeSNaresh Kumar Inna * @ln: lnode
560a3667aaeSNaresh Kumar Inna * @context: session context
561a3667aaeSNaresh Kumar Inna *
562a3667aaeSNaresh Kumar Inna * Issued with lock held.
563a3667aaeSNaresh Kumar Inna */
564a3667aaeSNaresh Kumar Inna int
csio_ln_fdmi_start(struct csio_lnode * ln,void * context)565a3667aaeSNaresh Kumar Inna csio_ln_fdmi_start(struct csio_lnode *ln, void *context)
566a3667aaeSNaresh Kumar Inna {
567a3667aaeSNaresh Kumar Inna struct csio_ioreq *fdmi_req;
568a3667aaeSNaresh Kumar Inna struct csio_rnode *fdmi_rn = (struct csio_rnode *)context;
569a3667aaeSNaresh Kumar Inna void *cmd;
570a3667aaeSNaresh Kumar Inna struct fc_fdmi_hba_identifier *hbaid;
571a3667aaeSNaresh Kumar Inna uint32_t len;
572a3667aaeSNaresh Kumar Inna
573a3667aaeSNaresh Kumar Inna if (!(ln->flags & CSIO_LNF_FDMI_ENABLE))
574a3667aaeSNaresh Kumar Inna return -EPROTONOSUPPORT;
575a3667aaeSNaresh Kumar Inna
576a3667aaeSNaresh Kumar Inna if (!csio_is_rnode_ready(fdmi_rn))
577a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_fdmi_err);
578a3667aaeSNaresh Kumar Inna
579a3667aaeSNaresh Kumar Inna /* Send FDMI cmd to de-register any HBA attributes if registered
580a3667aaeSNaresh Kumar Inna * before
581a3667aaeSNaresh Kumar Inna */
582a3667aaeSNaresh Kumar Inna
583a3667aaeSNaresh Kumar Inna fdmi_req = ln->mgmt_req;
584a3667aaeSNaresh Kumar Inna fdmi_req->lnode = ln;
585a3667aaeSNaresh Kumar Inna fdmi_req->rnode = fdmi_rn;
586a3667aaeSNaresh Kumar Inna
587a3667aaeSNaresh Kumar Inna /* Prepare FDMI DHBA cmd */
588a3667aaeSNaresh Kumar Inna cmd = fdmi_req->dma_buf.vaddr;
589a3667aaeSNaresh Kumar Inna memset(cmd, 0, FC_CT_HDR_LEN);
5905036f0a0SNaresh Kumar Inna csio_fill_ct_iu(cmd, FC_FST_MGMT, FC_FDMI_SUBTYPE, FC_FDMI_DHBA);
591a3667aaeSNaresh Kumar Inna len = FC_CT_HDR_LEN;
592a3667aaeSNaresh Kumar Inna
593a3667aaeSNaresh Kumar Inna hbaid = (struct fc_fdmi_hba_identifier *)csio_ct_get_pld(cmd);
594a3667aaeSNaresh Kumar Inna memcpy(&hbaid->id, csio_ln_wwpn(ln), 8);
595a3667aaeSNaresh Kumar Inna len += sizeof(*hbaid);
596a3667aaeSNaresh Kumar Inna
597a3667aaeSNaresh Kumar Inna /* Submit FDMI request */
598a3667aaeSNaresh Kumar Inna if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_dhba_cbfn,
599a3667aaeSNaresh Kumar Inna FCOE_CT, &fdmi_req->dma_buf, len)) {
600a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_fdmi_err);
601a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln, "Failed to issue fdmi dhba req\n");
602a3667aaeSNaresh Kumar Inna }
603a3667aaeSNaresh Kumar Inna
604a3667aaeSNaresh Kumar Inna return 0;
605a3667aaeSNaresh Kumar Inna }
606a3667aaeSNaresh Kumar Inna
607a3667aaeSNaresh Kumar Inna /*
608a3667aaeSNaresh Kumar Inna * csio_ln_vnp_read_cbfn - vnp read completion handler.
609a3667aaeSNaresh Kumar Inna * @hw: HW lnode
610a3667aaeSNaresh Kumar Inna * @cbfn: Completion handler.
611a3667aaeSNaresh Kumar Inna *
612a3667aaeSNaresh Kumar Inna * Reads vnp response and updates ln parameters.
613a3667aaeSNaresh Kumar Inna */
614a3667aaeSNaresh Kumar Inna static void
csio_ln_vnp_read_cbfn(struct csio_hw * hw,struct csio_mb * mbp)615a3667aaeSNaresh Kumar Inna csio_ln_vnp_read_cbfn(struct csio_hw *hw, struct csio_mb *mbp)
616a3667aaeSNaresh Kumar Inna {
617a3667aaeSNaresh Kumar Inna struct csio_lnode *ln = ((struct csio_lnode *)mbp->priv);
618a3667aaeSNaresh Kumar Inna struct fw_fcoe_vnp_cmd *rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
619a3667aaeSNaresh Kumar Inna struct fc_els_csp *csp;
620a3667aaeSNaresh Kumar Inna struct fc_els_cssp *clsp;
621a3667aaeSNaresh Kumar Inna enum fw_retval retval;
622f4875d50SDan Carpenter __be32 nport_id = 0;
623a3667aaeSNaresh Kumar Inna
624e2ac9628SHariprasad Shenai retval = FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16));
625a3667aaeSNaresh Kumar Inna if (retval != FW_SUCCESS) {
626a3667aaeSNaresh Kumar Inna csio_err(hw, "FCOE VNP read cmd returned error:0x%x\n", retval);
627a3667aaeSNaresh Kumar Inna mempool_free(mbp, hw->mb_mempool);
628a3667aaeSNaresh Kumar Inna return;
629a3667aaeSNaresh Kumar Inna }
630a3667aaeSNaresh Kumar Inna
631a3667aaeSNaresh Kumar Inna spin_lock_irq(&hw->lock);
632a3667aaeSNaresh Kumar Inna
633a3667aaeSNaresh Kumar Inna memcpy(ln->mac, rsp->vnport_mac, sizeof(ln->mac));
6345036f0a0SNaresh Kumar Inna memcpy(&nport_id, &rsp->vnport_mac[3], sizeof(uint8_t)*3);
6355036f0a0SNaresh Kumar Inna ln->nport_id = ntohl(nport_id);
636a3667aaeSNaresh Kumar Inna ln->nport_id = ln->nport_id >> 8;
637a3667aaeSNaresh Kumar Inna
638a3667aaeSNaresh Kumar Inna /* Update WWNs */
639a3667aaeSNaresh Kumar Inna /*
640a3667aaeSNaresh Kumar Inna * This may look like a duplication of what csio_fcoe_enable_link()
641a3667aaeSNaresh Kumar Inna * does, but is absolutely necessary if the vnpi changes between
642a3667aaeSNaresh Kumar Inna * a FCOE LINK UP and FCOE LINK DOWN.
643a3667aaeSNaresh Kumar Inna */
644a3667aaeSNaresh Kumar Inna memcpy(csio_ln_wwnn(ln), rsp->vnport_wwnn, 8);
645a3667aaeSNaresh Kumar Inna memcpy(csio_ln_wwpn(ln), rsp->vnport_wwpn, 8);
646a3667aaeSNaresh Kumar Inna
647a3667aaeSNaresh Kumar Inna /* Copy common sparam */
648a3667aaeSNaresh Kumar Inna csp = (struct fc_els_csp *)rsp->cmn_srv_parms;
649a3667aaeSNaresh Kumar Inna ln->ln_sparm.csp.sp_hi_ver = csp->sp_hi_ver;
650a3667aaeSNaresh Kumar Inna ln->ln_sparm.csp.sp_lo_ver = csp->sp_lo_ver;
6515036f0a0SNaresh Kumar Inna ln->ln_sparm.csp.sp_bb_cred = csp->sp_bb_cred;
6525036f0a0SNaresh Kumar Inna ln->ln_sparm.csp.sp_features = csp->sp_features;
6535036f0a0SNaresh Kumar Inna ln->ln_sparm.csp.sp_bb_data = csp->sp_bb_data;
6545036f0a0SNaresh Kumar Inna ln->ln_sparm.csp.sp_r_a_tov = csp->sp_r_a_tov;
6555036f0a0SNaresh Kumar Inna ln->ln_sparm.csp.sp_e_d_tov = csp->sp_e_d_tov;
656a3667aaeSNaresh Kumar Inna
657a3667aaeSNaresh Kumar Inna /* Copy word 0 & word 1 of class sparam */
658a3667aaeSNaresh Kumar Inna clsp = (struct fc_els_cssp *)rsp->clsp_word_0_1;
6595036f0a0SNaresh Kumar Inna ln->ln_sparm.clsp[2].cp_class = clsp->cp_class;
6605036f0a0SNaresh Kumar Inna ln->ln_sparm.clsp[2].cp_init = clsp->cp_init;
6615036f0a0SNaresh Kumar Inna ln->ln_sparm.clsp[2].cp_recip = clsp->cp_recip;
6625036f0a0SNaresh Kumar Inna ln->ln_sparm.clsp[2].cp_rdfs = clsp->cp_rdfs;
663a3667aaeSNaresh Kumar Inna
664a3667aaeSNaresh Kumar Inna spin_unlock_irq(&hw->lock);
665a3667aaeSNaresh Kumar Inna
666a3667aaeSNaresh Kumar Inna mempool_free(mbp, hw->mb_mempool);
667a3667aaeSNaresh Kumar Inna
668a3667aaeSNaresh Kumar Inna /* Send an event to update local attribs */
669a3667aaeSNaresh Kumar Inna csio_lnode_async_event(ln, CSIO_LN_FC_ATTRIB_UPDATE);
670a3667aaeSNaresh Kumar Inna }
671a3667aaeSNaresh Kumar Inna
672a3667aaeSNaresh Kumar Inna /*
673a3667aaeSNaresh Kumar Inna * csio_ln_vnp_read - Read vnp params.
674a3667aaeSNaresh Kumar Inna * @ln: lnode
675a3667aaeSNaresh Kumar Inna * @cbfn: Completion handler.
676a3667aaeSNaresh Kumar Inna *
677a3667aaeSNaresh Kumar Inna * Issued with lock held.
678a3667aaeSNaresh Kumar Inna */
679a3667aaeSNaresh Kumar Inna static int
csio_ln_vnp_read(struct csio_lnode * ln,void (* cbfn)(struct csio_hw *,struct csio_mb *))680a3667aaeSNaresh Kumar Inna csio_ln_vnp_read(struct csio_lnode *ln,
681a3667aaeSNaresh Kumar Inna void (*cbfn) (struct csio_hw *, struct csio_mb *))
682a3667aaeSNaresh Kumar Inna {
683a3667aaeSNaresh Kumar Inna struct csio_hw *hw = ln->hwp;
684a3667aaeSNaresh Kumar Inna struct csio_mb *mbp;
685a3667aaeSNaresh Kumar Inna
686a3667aaeSNaresh Kumar Inna /* Allocate Mbox request */
687a3667aaeSNaresh Kumar Inna mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
688a3667aaeSNaresh Kumar Inna if (!mbp) {
689a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_err_nomem);
690a3667aaeSNaresh Kumar Inna return -ENOMEM;
691a3667aaeSNaresh Kumar Inna }
692a3667aaeSNaresh Kumar Inna
693a3667aaeSNaresh Kumar Inna /* Prepare VNP Command */
694a3667aaeSNaresh Kumar Inna csio_fcoe_vnp_read_init_mb(ln, mbp,
695a3667aaeSNaresh Kumar Inna CSIO_MB_DEFAULT_TMO,
696a3667aaeSNaresh Kumar Inna ln->fcf_flowid,
697a3667aaeSNaresh Kumar Inna ln->vnp_flowid,
698a3667aaeSNaresh Kumar Inna cbfn);
699a3667aaeSNaresh Kumar Inna
700a3667aaeSNaresh Kumar Inna /* Issue MBOX cmd */
701a3667aaeSNaresh Kumar Inna if (csio_mb_issue(hw, mbp)) {
702a3667aaeSNaresh Kumar Inna csio_err(hw, "Failed to issue mbox FCoE VNP command\n");
703a3667aaeSNaresh Kumar Inna mempool_free(mbp, hw->mb_mempool);
704a3667aaeSNaresh Kumar Inna return -EINVAL;
705a3667aaeSNaresh Kumar Inna }
706a3667aaeSNaresh Kumar Inna
707a3667aaeSNaresh Kumar Inna return 0;
708a3667aaeSNaresh Kumar Inna }
709a3667aaeSNaresh Kumar Inna
710a3667aaeSNaresh Kumar Inna /*
711a3667aaeSNaresh Kumar Inna * csio_fcoe_enable_link - Enable fcoe link.
712a3667aaeSNaresh Kumar Inna * @ln: lnode
713a3667aaeSNaresh Kumar Inna * @enable: enable/disable
714a3667aaeSNaresh Kumar Inna * Issued with lock held.
715a3667aaeSNaresh Kumar Inna * Issues mbox cmd to bring up FCOE link on port associated with given ln.
716a3667aaeSNaresh Kumar Inna */
717a3667aaeSNaresh Kumar Inna static int
csio_fcoe_enable_link(struct csio_lnode * ln,bool enable)718a3667aaeSNaresh Kumar Inna csio_fcoe_enable_link(struct csio_lnode *ln, bool enable)
719a3667aaeSNaresh Kumar Inna {
720a3667aaeSNaresh Kumar Inna struct csio_hw *hw = ln->hwp;
721a3667aaeSNaresh Kumar Inna struct csio_mb *mbp;
722a3667aaeSNaresh Kumar Inna enum fw_retval retval;
723a3667aaeSNaresh Kumar Inna uint8_t portid;
724a3667aaeSNaresh Kumar Inna uint8_t sub_op;
725a3667aaeSNaresh Kumar Inna struct fw_fcoe_link_cmd *lcmd;
726a3667aaeSNaresh Kumar Inna int i;
727a3667aaeSNaresh Kumar Inna
728a3667aaeSNaresh Kumar Inna mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
729a3667aaeSNaresh Kumar Inna if (!mbp) {
730a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_err_nomem);
731a3667aaeSNaresh Kumar Inna return -ENOMEM;
732a3667aaeSNaresh Kumar Inna }
733a3667aaeSNaresh Kumar Inna
734a3667aaeSNaresh Kumar Inna portid = ln->portid;
735a3667aaeSNaresh Kumar Inna sub_op = enable ? FCOE_LINK_UP : FCOE_LINK_DOWN;
736a3667aaeSNaresh Kumar Inna
737a3667aaeSNaresh Kumar Inna csio_dbg(hw, "bringing FCOE LINK %s on Port:%d\n",
738a3667aaeSNaresh Kumar Inna sub_op ? "UP" : "DOWN", portid);
739a3667aaeSNaresh Kumar Inna
740a3667aaeSNaresh Kumar Inna csio_write_fcoe_link_cond_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
741a3667aaeSNaresh Kumar Inna portid, sub_op, 0, 0, 0, NULL);
742a3667aaeSNaresh Kumar Inna
743a3667aaeSNaresh Kumar Inna if (csio_mb_issue(hw, mbp)) {
744a3667aaeSNaresh Kumar Inna csio_err(hw, "failed to issue FCOE LINK cmd on port[%d]\n",
745a3667aaeSNaresh Kumar Inna portid);
746a3667aaeSNaresh Kumar Inna mempool_free(mbp, hw->mb_mempool);
747a3667aaeSNaresh Kumar Inna return -EINVAL;
748a3667aaeSNaresh Kumar Inna }
749a3667aaeSNaresh Kumar Inna
750a3667aaeSNaresh Kumar Inna retval = csio_mb_fw_retval(mbp);
751a3667aaeSNaresh Kumar Inna if (retval != FW_SUCCESS) {
752a3667aaeSNaresh Kumar Inna csio_err(hw,
753a3667aaeSNaresh Kumar Inna "FCOE LINK %s cmd on port[%d] failed with "
754a3667aaeSNaresh Kumar Inna "ret:x%x\n", sub_op ? "UP" : "DOWN", portid, retval);
755a3667aaeSNaresh Kumar Inna mempool_free(mbp, hw->mb_mempool);
756a3667aaeSNaresh Kumar Inna return -EINVAL;
757a3667aaeSNaresh Kumar Inna }
758a3667aaeSNaresh Kumar Inna
759a3667aaeSNaresh Kumar Inna if (!enable)
760a3667aaeSNaresh Kumar Inna goto out;
761a3667aaeSNaresh Kumar Inna
762a3667aaeSNaresh Kumar Inna lcmd = (struct fw_fcoe_link_cmd *)mbp->mb;
763a3667aaeSNaresh Kumar Inna
764a3667aaeSNaresh Kumar Inna memcpy(csio_ln_wwnn(ln), lcmd->vnport_wwnn, 8);
765a3667aaeSNaresh Kumar Inna memcpy(csio_ln_wwpn(ln), lcmd->vnport_wwpn, 8);
766a3667aaeSNaresh Kumar Inna
767a3667aaeSNaresh Kumar Inna for (i = 0; i < CSIO_MAX_PPORTS; i++)
768a3667aaeSNaresh Kumar Inna if (hw->pport[i].portid == portid)
769a3667aaeSNaresh Kumar Inna memcpy(hw->pport[i].mac, lcmd->phy_mac, 6);
770a3667aaeSNaresh Kumar Inna
771a3667aaeSNaresh Kumar Inna out:
772a3667aaeSNaresh Kumar Inna mempool_free(mbp, hw->mb_mempool);
773a3667aaeSNaresh Kumar Inna return 0;
774a3667aaeSNaresh Kumar Inna }
775a3667aaeSNaresh Kumar Inna
776a3667aaeSNaresh Kumar Inna /*
777a3667aaeSNaresh Kumar Inna * csio_ln_read_fcf_cbfn - Read fcf parameters
778a3667aaeSNaresh Kumar Inna * @ln: lnode
779a3667aaeSNaresh Kumar Inna *
780a3667aaeSNaresh Kumar Inna * read fcf response and Update ln fcf information.
781a3667aaeSNaresh Kumar Inna */
782a3667aaeSNaresh Kumar Inna static void
csio_ln_read_fcf_cbfn(struct csio_hw * hw,struct csio_mb * mbp)783a3667aaeSNaresh Kumar Inna csio_ln_read_fcf_cbfn(struct csio_hw *hw, struct csio_mb *mbp)
784a3667aaeSNaresh Kumar Inna {
785a3667aaeSNaresh Kumar Inna struct csio_lnode *ln = (struct csio_lnode *)mbp->priv;
786a3667aaeSNaresh Kumar Inna struct csio_fcf_info *fcf_info;
787a3667aaeSNaresh Kumar Inna struct fw_fcoe_fcf_cmd *rsp =
788a3667aaeSNaresh Kumar Inna (struct fw_fcoe_fcf_cmd *)(mbp->mb);
789a3667aaeSNaresh Kumar Inna enum fw_retval retval;
790a3667aaeSNaresh Kumar Inna
791e2ac9628SHariprasad Shenai retval = FW_CMD_RETVAL_G(ntohl(rsp->retval_len16));
792a3667aaeSNaresh Kumar Inna if (retval != FW_SUCCESS) {
793a3667aaeSNaresh Kumar Inna csio_ln_err(ln, "FCOE FCF cmd failed with ret x%x\n",
794a3667aaeSNaresh Kumar Inna retval);
795a3667aaeSNaresh Kumar Inna mempool_free(mbp, hw->mb_mempool);
796a3667aaeSNaresh Kumar Inna return;
797a3667aaeSNaresh Kumar Inna }
798a3667aaeSNaresh Kumar Inna
799a3667aaeSNaresh Kumar Inna spin_lock_irq(&hw->lock);
800a3667aaeSNaresh Kumar Inna fcf_info = ln->fcfinfo;
801a3667aaeSNaresh Kumar Inna fcf_info->priority = FW_FCOE_FCF_CMD_PRIORITY_GET(
802a3667aaeSNaresh Kumar Inna ntohs(rsp->priority_pkd));
803a3667aaeSNaresh Kumar Inna fcf_info->vf_id = ntohs(rsp->vf_id);
804a3667aaeSNaresh Kumar Inna fcf_info->vlan_id = rsp->vlan_id;
805a3667aaeSNaresh Kumar Inna fcf_info->max_fcoe_size = ntohs(rsp->max_fcoe_size);
806a3667aaeSNaresh Kumar Inna fcf_info->fka_adv = be32_to_cpu(rsp->fka_adv);
807a3667aaeSNaresh Kumar Inna fcf_info->fcfi = FW_FCOE_FCF_CMD_FCFI_GET(ntohl(rsp->op_to_fcfi));
808a3667aaeSNaresh Kumar Inna fcf_info->fpma = FW_FCOE_FCF_CMD_FPMA_GET(rsp->fpma_to_portid);
809a3667aaeSNaresh Kumar Inna fcf_info->spma = FW_FCOE_FCF_CMD_SPMA_GET(rsp->fpma_to_portid);
810a3667aaeSNaresh Kumar Inna fcf_info->login = FW_FCOE_FCF_CMD_LOGIN_GET(rsp->fpma_to_portid);
811a3667aaeSNaresh Kumar Inna fcf_info->portid = FW_FCOE_FCF_CMD_PORTID_GET(rsp->fpma_to_portid);
812a3667aaeSNaresh Kumar Inna memcpy(fcf_info->fc_map, rsp->fc_map, sizeof(fcf_info->fc_map));
813a3667aaeSNaresh Kumar Inna memcpy(fcf_info->mac, rsp->mac, sizeof(fcf_info->mac));
814a3667aaeSNaresh Kumar Inna memcpy(fcf_info->name_id, rsp->name_id, sizeof(fcf_info->name_id));
815a3667aaeSNaresh Kumar Inna memcpy(fcf_info->fabric, rsp->fabric, sizeof(fcf_info->fabric));
816a3667aaeSNaresh Kumar Inna memcpy(fcf_info->spma_mac, rsp->spma_mac, sizeof(fcf_info->spma_mac));
817a3667aaeSNaresh Kumar Inna
818a3667aaeSNaresh Kumar Inna spin_unlock_irq(&hw->lock);
819a3667aaeSNaresh Kumar Inna
820a3667aaeSNaresh Kumar Inna mempool_free(mbp, hw->mb_mempool);
821a3667aaeSNaresh Kumar Inna }
822a3667aaeSNaresh Kumar Inna
823a3667aaeSNaresh Kumar Inna /*
824a3667aaeSNaresh Kumar Inna * csio_ln_read_fcf_entry - Read fcf entry.
825a3667aaeSNaresh Kumar Inna * @ln: lnode
826a3667aaeSNaresh Kumar Inna * @cbfn: Completion handler.
827a3667aaeSNaresh Kumar Inna *
828a3667aaeSNaresh Kumar Inna * Issued with lock held.
829a3667aaeSNaresh Kumar Inna */
830a3667aaeSNaresh Kumar Inna static int
csio_ln_read_fcf_entry(struct csio_lnode * ln,void (* cbfn)(struct csio_hw *,struct csio_mb *))831a3667aaeSNaresh Kumar Inna csio_ln_read_fcf_entry(struct csio_lnode *ln,
832a3667aaeSNaresh Kumar Inna void (*cbfn) (struct csio_hw *, struct csio_mb *))
833a3667aaeSNaresh Kumar Inna {
834a3667aaeSNaresh Kumar Inna struct csio_hw *hw = ln->hwp;
835a3667aaeSNaresh Kumar Inna struct csio_mb *mbp;
836a3667aaeSNaresh Kumar Inna
837a3667aaeSNaresh Kumar Inna mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
838a3667aaeSNaresh Kumar Inna if (!mbp) {
839a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_err_nomem);
840a3667aaeSNaresh Kumar Inna return -ENOMEM;
841a3667aaeSNaresh Kumar Inna }
842a3667aaeSNaresh Kumar Inna
843a3667aaeSNaresh Kumar Inna /* Get FCoE FCF information */
844a3667aaeSNaresh Kumar Inna csio_fcoe_read_fcf_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
845a3667aaeSNaresh Kumar Inna ln->portid, ln->fcf_flowid, cbfn);
846a3667aaeSNaresh Kumar Inna
847a3667aaeSNaresh Kumar Inna if (csio_mb_issue(hw, mbp)) {
848a3667aaeSNaresh Kumar Inna csio_err(hw, "failed to issue FCOE FCF cmd\n");
849a3667aaeSNaresh Kumar Inna mempool_free(mbp, hw->mb_mempool);
850a3667aaeSNaresh Kumar Inna return -EINVAL;
851a3667aaeSNaresh Kumar Inna }
852a3667aaeSNaresh Kumar Inna
853a3667aaeSNaresh Kumar Inna return 0;
854a3667aaeSNaresh Kumar Inna }
855a3667aaeSNaresh Kumar Inna
856a3667aaeSNaresh Kumar Inna /*
857a3667aaeSNaresh Kumar Inna * csio_handle_link_up - Logical Linkup event.
858a3667aaeSNaresh Kumar Inna * @hw - HW module.
859a3667aaeSNaresh Kumar Inna * @portid - Physical port number
860a3667aaeSNaresh Kumar Inna * @fcfi - FCF index.
861a3667aaeSNaresh Kumar Inna * @vnpi - VNP index.
862a3667aaeSNaresh Kumar Inna * Returns - none.
863a3667aaeSNaresh Kumar Inna *
864a3667aaeSNaresh Kumar Inna * This event is received from FW, when virtual link is established between
865a3667aaeSNaresh Kumar Inna * Physical port[ENode] and FCF. If its new vnpi, then local node object is
866a3667aaeSNaresh Kumar Inna * created on this FCF and set to [ONLINE] state.
867a3667aaeSNaresh Kumar Inna * Lnode waits for FW_RDEV_CMD event to be received indicating that
868a3667aaeSNaresh Kumar Inna * Fabric login is completed and lnode moves to [READY] state.
869a3667aaeSNaresh Kumar Inna *
870a3667aaeSNaresh Kumar Inna * This called with hw lock held
871a3667aaeSNaresh Kumar Inna */
872a3667aaeSNaresh Kumar Inna static void
csio_handle_link_up(struct csio_hw * hw,uint8_t portid,uint32_t fcfi,uint32_t vnpi)873a3667aaeSNaresh Kumar Inna csio_handle_link_up(struct csio_hw *hw, uint8_t portid, uint32_t fcfi,
874a3667aaeSNaresh Kumar Inna uint32_t vnpi)
875a3667aaeSNaresh Kumar Inna {
876a3667aaeSNaresh Kumar Inna struct csio_lnode *ln = NULL;
877a3667aaeSNaresh Kumar Inna
878a3667aaeSNaresh Kumar Inna /* Lookup lnode based on vnpi */
879a3667aaeSNaresh Kumar Inna ln = csio_ln_lookup_by_vnpi(hw, vnpi);
880a3667aaeSNaresh Kumar Inna if (!ln) {
881a3667aaeSNaresh Kumar Inna /* Pick lnode based on portid */
882a3667aaeSNaresh Kumar Inna ln = csio_ln_lookup_by_portid(hw, portid);
883a3667aaeSNaresh Kumar Inna if (!ln) {
884a3667aaeSNaresh Kumar Inna csio_err(hw, "failed to lookup fcoe lnode on port:%d\n",
885a3667aaeSNaresh Kumar Inna portid);
886a3667aaeSNaresh Kumar Inna CSIO_DB_ASSERT(0);
887a3667aaeSNaresh Kumar Inna return;
888a3667aaeSNaresh Kumar Inna }
889a3667aaeSNaresh Kumar Inna
890a3667aaeSNaresh Kumar Inna /* Check if lnode has valid vnp flowid */
891a3667aaeSNaresh Kumar Inna if (ln->vnp_flowid != CSIO_INVALID_IDX) {
892a3667aaeSNaresh Kumar Inna /* New VN-Port */
893a3667aaeSNaresh Kumar Inna spin_unlock_irq(&hw->lock);
894a3667aaeSNaresh Kumar Inna csio_lnode_alloc(hw);
895a3667aaeSNaresh Kumar Inna spin_lock_irq(&hw->lock);
896a3667aaeSNaresh Kumar Inna if (!ln) {
897a3667aaeSNaresh Kumar Inna csio_err(hw,
898a3667aaeSNaresh Kumar Inna "failed to allocate fcoe lnode"
899a3667aaeSNaresh Kumar Inna "for port:%d vnpi:x%x\n",
900a3667aaeSNaresh Kumar Inna portid, vnpi);
901a3667aaeSNaresh Kumar Inna CSIO_DB_ASSERT(0);
902a3667aaeSNaresh Kumar Inna return;
903a3667aaeSNaresh Kumar Inna }
904a3667aaeSNaresh Kumar Inna ln->portid = portid;
905a3667aaeSNaresh Kumar Inna }
906a3667aaeSNaresh Kumar Inna ln->vnp_flowid = vnpi;
907a3667aaeSNaresh Kumar Inna ln->dev_num &= ~0xFFFF;
908a3667aaeSNaresh Kumar Inna ln->dev_num |= vnpi;
909a3667aaeSNaresh Kumar Inna }
910a3667aaeSNaresh Kumar Inna
911a3667aaeSNaresh Kumar Inna /*Initialize fcfi */
912a3667aaeSNaresh Kumar Inna ln->fcf_flowid = fcfi;
913a3667aaeSNaresh Kumar Inna
914a3667aaeSNaresh Kumar Inna csio_info(hw, "Port:%d - FCOE LINK UP\n", portid);
915a3667aaeSNaresh Kumar Inna
916a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_link_up);
917a3667aaeSNaresh Kumar Inna
918a3667aaeSNaresh Kumar Inna /* Send LINKUP event to SM */
919a3667aaeSNaresh Kumar Inna csio_post_event(&ln->sm, CSIO_LNE_LINKUP);
920a3667aaeSNaresh Kumar Inna }
921a3667aaeSNaresh Kumar Inna
922a3667aaeSNaresh Kumar Inna /*
923a3667aaeSNaresh Kumar Inna * csio_post_event_rns
924a3667aaeSNaresh Kumar Inna * @ln - FCOE lnode
925a3667aaeSNaresh Kumar Inna * @evt - Given rnode event
926a3667aaeSNaresh Kumar Inna * Returns - none
927a3667aaeSNaresh Kumar Inna *
928a3667aaeSNaresh Kumar Inna * Posts given rnode event to all FCOE rnodes connected with given Lnode.
929a3667aaeSNaresh Kumar Inna * This routine is invoked when lnode receives LINK_DOWN/DOWN_LINK/CLOSE
930a3667aaeSNaresh Kumar Inna * event.
931a3667aaeSNaresh Kumar Inna *
932a3667aaeSNaresh Kumar Inna * This called with hw lock held
933a3667aaeSNaresh Kumar Inna */
934a3667aaeSNaresh Kumar Inna static void
csio_post_event_rns(struct csio_lnode * ln,enum csio_rn_ev evt)935a3667aaeSNaresh Kumar Inna csio_post_event_rns(struct csio_lnode *ln, enum csio_rn_ev evt)
936a3667aaeSNaresh Kumar Inna {
937a3667aaeSNaresh Kumar Inna struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
938a3667aaeSNaresh Kumar Inna struct list_head *tmp, *next;
939a3667aaeSNaresh Kumar Inna struct csio_rnode *rn;
940a3667aaeSNaresh Kumar Inna
941a3667aaeSNaresh Kumar Inna list_for_each_safe(tmp, next, &rnhead->sm.sm_list) {
942a3667aaeSNaresh Kumar Inna rn = (struct csio_rnode *) tmp;
943a3667aaeSNaresh Kumar Inna csio_post_event(&rn->sm, evt);
944a3667aaeSNaresh Kumar Inna }
945a3667aaeSNaresh Kumar Inna }
946a3667aaeSNaresh Kumar Inna
947a3667aaeSNaresh Kumar Inna /*
948a3667aaeSNaresh Kumar Inna * csio_cleanup_rns
949a3667aaeSNaresh Kumar Inna * @ln - FCOE lnode
950a3667aaeSNaresh Kumar Inna * Returns - none
951a3667aaeSNaresh Kumar Inna *
952a3667aaeSNaresh Kumar Inna * Frees all FCOE rnodes connected with given Lnode.
953a3667aaeSNaresh Kumar Inna *
954a3667aaeSNaresh Kumar Inna * This called with hw lock held
955a3667aaeSNaresh Kumar Inna */
956a3667aaeSNaresh Kumar Inna static void
csio_cleanup_rns(struct csio_lnode * ln)957a3667aaeSNaresh Kumar Inna csio_cleanup_rns(struct csio_lnode *ln)
958a3667aaeSNaresh Kumar Inna {
959a3667aaeSNaresh Kumar Inna struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
960a3667aaeSNaresh Kumar Inna struct list_head *tmp, *next_rn;
961a3667aaeSNaresh Kumar Inna struct csio_rnode *rn;
962a3667aaeSNaresh Kumar Inna
963a3667aaeSNaresh Kumar Inna list_for_each_safe(tmp, next_rn, &rnhead->sm.sm_list) {
964a3667aaeSNaresh Kumar Inna rn = (struct csio_rnode *) tmp;
965a3667aaeSNaresh Kumar Inna csio_put_rnode(ln, rn);
966a3667aaeSNaresh Kumar Inna }
967a3667aaeSNaresh Kumar Inna
968a3667aaeSNaresh Kumar Inna }
969a3667aaeSNaresh Kumar Inna
970a3667aaeSNaresh Kumar Inna /*
971a3667aaeSNaresh Kumar Inna * csio_post_event_lns
972a3667aaeSNaresh Kumar Inna * @ln - FCOE lnode
973a3667aaeSNaresh Kumar Inna * @evt - Given lnode event
974a3667aaeSNaresh Kumar Inna * Returns - none
975a3667aaeSNaresh Kumar Inna *
976a3667aaeSNaresh Kumar Inna * Posts given lnode event to all FCOE lnodes connected with given Lnode.
977a3667aaeSNaresh Kumar Inna * This routine is invoked when lnode receives LINK_DOWN/DOWN_LINK/CLOSE
978a3667aaeSNaresh Kumar Inna * event.
979a3667aaeSNaresh Kumar Inna *
980a3667aaeSNaresh Kumar Inna * This called with hw lock held
981a3667aaeSNaresh Kumar Inna */
982a3667aaeSNaresh Kumar Inna static void
csio_post_event_lns(struct csio_lnode * ln,enum csio_ln_ev evt)983a3667aaeSNaresh Kumar Inna csio_post_event_lns(struct csio_lnode *ln, enum csio_ln_ev evt)
984a3667aaeSNaresh Kumar Inna {
985a3667aaeSNaresh Kumar Inna struct list_head *tmp;
986a3667aaeSNaresh Kumar Inna struct csio_lnode *cln, *sln;
987a3667aaeSNaresh Kumar Inna
988a3667aaeSNaresh Kumar Inna /* If NPIV lnode, send evt only to that and return */
989a3667aaeSNaresh Kumar Inna if (csio_is_npiv_ln(ln)) {
990a3667aaeSNaresh Kumar Inna csio_post_event(&ln->sm, evt);
991a3667aaeSNaresh Kumar Inna return;
992a3667aaeSNaresh Kumar Inna }
993a3667aaeSNaresh Kumar Inna
994a3667aaeSNaresh Kumar Inna sln = ln;
995a3667aaeSNaresh Kumar Inna /* Traverse children lnodes list and send evt */
996a3667aaeSNaresh Kumar Inna list_for_each(tmp, &sln->cln_head) {
997a3667aaeSNaresh Kumar Inna cln = (struct csio_lnode *) tmp;
998a3667aaeSNaresh Kumar Inna csio_post_event(&cln->sm, evt);
999a3667aaeSNaresh Kumar Inna }
1000a3667aaeSNaresh Kumar Inna
1001a3667aaeSNaresh Kumar Inna /* Send evt to parent lnode */
1002a3667aaeSNaresh Kumar Inna csio_post_event(&ln->sm, evt);
1003a3667aaeSNaresh Kumar Inna }
1004a3667aaeSNaresh Kumar Inna
1005a3667aaeSNaresh Kumar Inna /*
1006a3667aaeSNaresh Kumar Inna * csio_ln_down - Lcoal nport is down
1007a3667aaeSNaresh Kumar Inna * @ln - FCOE Lnode
1008a3667aaeSNaresh Kumar Inna * Returns - none
1009a3667aaeSNaresh Kumar Inna *
1010a3667aaeSNaresh Kumar Inna * Sends LINK_DOWN events to Lnode and its associated NPIVs lnodes.
1011a3667aaeSNaresh Kumar Inna *
1012a3667aaeSNaresh Kumar Inna * This called with hw lock held
1013a3667aaeSNaresh Kumar Inna */
1014a3667aaeSNaresh Kumar Inna static void
csio_ln_down(struct csio_lnode * ln)1015a3667aaeSNaresh Kumar Inna csio_ln_down(struct csio_lnode *ln)
1016a3667aaeSNaresh Kumar Inna {
1017a3667aaeSNaresh Kumar Inna csio_post_event_lns(ln, CSIO_LNE_LINK_DOWN);
1018a3667aaeSNaresh Kumar Inna }
1019a3667aaeSNaresh Kumar Inna
1020a3667aaeSNaresh Kumar Inna /*
1021a3667aaeSNaresh Kumar Inna * csio_handle_link_down - Logical Linkdown event.
1022a3667aaeSNaresh Kumar Inna * @hw - HW module.
1023a3667aaeSNaresh Kumar Inna * @portid - Physical port number
1024a3667aaeSNaresh Kumar Inna * @fcfi - FCF index.
1025a3667aaeSNaresh Kumar Inna * @vnpi - VNP index.
1026a3667aaeSNaresh Kumar Inna * Returns - none
1027a3667aaeSNaresh Kumar Inna *
1028a3667aaeSNaresh Kumar Inna * This event is received from FW, when virtual link goes down between
1029a3667aaeSNaresh Kumar Inna * Physical port[ENode] and FCF. Lnode and its associated NPIVs lnode hosted on
1030a3667aaeSNaresh Kumar Inna * this vnpi[VN-Port] will be de-instantiated.
1031a3667aaeSNaresh Kumar Inna *
1032a3667aaeSNaresh Kumar Inna * This called with hw lock held
1033a3667aaeSNaresh Kumar Inna */
1034a3667aaeSNaresh Kumar Inna static void
csio_handle_link_down(struct csio_hw * hw,uint8_t portid,uint32_t fcfi,uint32_t vnpi)1035a3667aaeSNaresh Kumar Inna csio_handle_link_down(struct csio_hw *hw, uint8_t portid, uint32_t fcfi,
1036a3667aaeSNaresh Kumar Inna uint32_t vnpi)
1037a3667aaeSNaresh Kumar Inna {
1038a3667aaeSNaresh Kumar Inna struct csio_fcf_info *fp;
1039a3667aaeSNaresh Kumar Inna struct csio_lnode *ln;
1040a3667aaeSNaresh Kumar Inna
1041a3667aaeSNaresh Kumar Inna /* Lookup lnode based on vnpi */
1042a3667aaeSNaresh Kumar Inna ln = csio_ln_lookup_by_vnpi(hw, vnpi);
1043a3667aaeSNaresh Kumar Inna if (ln) {
1044a3667aaeSNaresh Kumar Inna fp = ln->fcfinfo;
1045a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_link_down);
1046a3667aaeSNaresh Kumar Inna
1047a3667aaeSNaresh Kumar Inna /*Warn if linkdown received if lnode is not in ready state */
1048a3667aaeSNaresh Kumar Inna if (!csio_is_lnode_ready(ln)) {
1049a3667aaeSNaresh Kumar Inna csio_ln_warn(ln,
1050a3667aaeSNaresh Kumar Inna "warn: FCOE link is already in offline "
1051a3667aaeSNaresh Kumar Inna "Ignoring Fcoe linkdown event on portid %d\n",
1052a3667aaeSNaresh Kumar Inna portid);
1053a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_drop);
1054a3667aaeSNaresh Kumar Inna return;
1055a3667aaeSNaresh Kumar Inna }
1056a3667aaeSNaresh Kumar Inna
1057a3667aaeSNaresh Kumar Inna /* Verify portid */
1058a3667aaeSNaresh Kumar Inna if (fp->portid != portid) {
1059a3667aaeSNaresh Kumar Inna csio_ln_warn(ln,
1060a3667aaeSNaresh Kumar Inna "warn: FCOE linkdown recv with "
1061a3667aaeSNaresh Kumar Inna "invalid port %d\n", portid);
1062a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_drop);
1063a3667aaeSNaresh Kumar Inna return;
1064a3667aaeSNaresh Kumar Inna }
1065a3667aaeSNaresh Kumar Inna
1066a3667aaeSNaresh Kumar Inna /* verify fcfi */
1067a3667aaeSNaresh Kumar Inna if (ln->fcf_flowid != fcfi) {
1068a3667aaeSNaresh Kumar Inna csio_ln_warn(ln,
1069a3667aaeSNaresh Kumar Inna "warn: FCOE linkdown recv with "
1070a3667aaeSNaresh Kumar Inna "invalid fcfi x%x\n", fcfi);
1071a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_drop);
1072a3667aaeSNaresh Kumar Inna return;
1073a3667aaeSNaresh Kumar Inna }
1074a3667aaeSNaresh Kumar Inna
1075a3667aaeSNaresh Kumar Inna csio_info(hw, "Port:%d - FCOE LINK DOWN\n", portid);
1076a3667aaeSNaresh Kumar Inna
1077a3667aaeSNaresh Kumar Inna /* Send LINK_DOWN event to lnode s/m */
1078a3667aaeSNaresh Kumar Inna csio_ln_down(ln);
1079a3667aaeSNaresh Kumar Inna
1080a3667aaeSNaresh Kumar Inna return;
1081a3667aaeSNaresh Kumar Inna } else {
1082a3667aaeSNaresh Kumar Inna csio_warn(hw,
1083a3667aaeSNaresh Kumar Inna "warn: FCOE linkdown recv with invalid vnpi x%x\n",
1084a3667aaeSNaresh Kumar Inna vnpi);
1085a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_evt_drop);
1086a3667aaeSNaresh Kumar Inna }
1087a3667aaeSNaresh Kumar Inna }
1088a3667aaeSNaresh Kumar Inna
1089a3667aaeSNaresh Kumar Inna /*
1090a3667aaeSNaresh Kumar Inna * csio_is_lnode_ready - Checks FCOE lnode is in ready state.
1091a3667aaeSNaresh Kumar Inna * @ln: Lnode module
1092a3667aaeSNaresh Kumar Inna *
1093a3667aaeSNaresh Kumar Inna * Returns True if FCOE lnode is in ready state.
1094a3667aaeSNaresh Kumar Inna */
1095a3667aaeSNaresh Kumar Inna int
csio_is_lnode_ready(struct csio_lnode * ln)1096a3667aaeSNaresh Kumar Inna csio_is_lnode_ready(struct csio_lnode *ln)
1097a3667aaeSNaresh Kumar Inna {
1098*ccb6998cSArnd Bergmann return (csio_get_state(ln) == csio_lns_ready);
1099a3667aaeSNaresh Kumar Inna }
1100a3667aaeSNaresh Kumar Inna
1101a3667aaeSNaresh Kumar Inna /*****************************************************************************/
1102a3667aaeSNaresh Kumar Inna /* START: Lnode SM */
1103a3667aaeSNaresh Kumar Inna /*****************************************************************************/
1104a3667aaeSNaresh Kumar Inna /*
1105a3667aaeSNaresh Kumar Inna * csio_lns_uninit - The request in uninit state.
1106a3667aaeSNaresh Kumar Inna * @ln - FCOE lnode.
1107a3667aaeSNaresh Kumar Inna * @evt - Event to be processed.
1108a3667aaeSNaresh Kumar Inna *
1109a3667aaeSNaresh Kumar Inna * Process the given lnode event which is currently in "uninit" state.
1110a3667aaeSNaresh Kumar Inna * Invoked with HW lock held.
1111a3667aaeSNaresh Kumar Inna * Return - none.
1112a3667aaeSNaresh Kumar Inna */
1113a3667aaeSNaresh Kumar Inna static void
csio_lns_uninit(struct csio_lnode * ln,enum csio_ln_ev evt)1114a3667aaeSNaresh Kumar Inna csio_lns_uninit(struct csio_lnode *ln, enum csio_ln_ev evt)
1115a3667aaeSNaresh Kumar Inna {
1116a3667aaeSNaresh Kumar Inna struct csio_hw *hw = csio_lnode_to_hw(ln);
1117a3667aaeSNaresh Kumar Inna struct csio_lnode *rln = hw->rln;
1118a3667aaeSNaresh Kumar Inna int rv;
1119a3667aaeSNaresh Kumar Inna
1120a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_sm[evt]);
1121a3667aaeSNaresh Kumar Inna switch (evt) {
1122a3667aaeSNaresh Kumar Inna case CSIO_LNE_LINKUP:
1123a3667aaeSNaresh Kumar Inna csio_set_state(&ln->sm, csio_lns_online);
1124a3667aaeSNaresh Kumar Inna /* Read FCF only for physical lnode */
1125a3667aaeSNaresh Kumar Inna if (csio_is_phys_ln(ln)) {
1126a3667aaeSNaresh Kumar Inna rv = csio_ln_read_fcf_entry(ln,
1127a3667aaeSNaresh Kumar Inna csio_ln_read_fcf_cbfn);
1128a3667aaeSNaresh Kumar Inna if (rv != 0) {
1129a3667aaeSNaresh Kumar Inna /* TODO: Send HW RESET event */
1130a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_err);
1131a3667aaeSNaresh Kumar Inna break;
1132a3667aaeSNaresh Kumar Inna }
1133a3667aaeSNaresh Kumar Inna
1134a3667aaeSNaresh Kumar Inna /* Add FCF record */
1135a3667aaeSNaresh Kumar Inna list_add_tail(&ln->fcfinfo->list, &rln->fcf_lsthead);
1136a3667aaeSNaresh Kumar Inna }
1137a3667aaeSNaresh Kumar Inna
1138a3667aaeSNaresh Kumar Inna rv = csio_ln_vnp_read(ln, csio_ln_vnp_read_cbfn);
1139a3667aaeSNaresh Kumar Inna if (rv != 0) {
1140a3667aaeSNaresh Kumar Inna /* TODO: Send HW RESET event */
1141a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_err);
1142a3667aaeSNaresh Kumar Inna }
1143a3667aaeSNaresh Kumar Inna break;
1144a3667aaeSNaresh Kumar Inna
1145a3667aaeSNaresh Kumar Inna case CSIO_LNE_DOWN_LINK:
1146a3667aaeSNaresh Kumar Inna break;
1147a3667aaeSNaresh Kumar Inna
1148a3667aaeSNaresh Kumar Inna default:
1149a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln,
1150a3667aaeSNaresh Kumar Inna "unexp ln event %d recv from did:x%x in "
1151a3667aaeSNaresh Kumar Inna "ln state[uninit].\n", evt, ln->nport_id);
1152a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_unexp);
1153a3667aaeSNaresh Kumar Inna break;
1154a3667aaeSNaresh Kumar Inna } /* switch event */
1155a3667aaeSNaresh Kumar Inna }
1156a3667aaeSNaresh Kumar Inna
1157a3667aaeSNaresh Kumar Inna /*
1158a3667aaeSNaresh Kumar Inna * csio_lns_online - The request in online state.
1159a3667aaeSNaresh Kumar Inna * @ln - FCOE lnode.
1160a3667aaeSNaresh Kumar Inna * @evt - Event to be processed.
1161a3667aaeSNaresh Kumar Inna *
1162a3667aaeSNaresh Kumar Inna * Process the given lnode event which is currently in "online" state.
1163a3667aaeSNaresh Kumar Inna * Invoked with HW lock held.
1164a3667aaeSNaresh Kumar Inna * Return - none.
1165a3667aaeSNaresh Kumar Inna */
1166a3667aaeSNaresh Kumar Inna static void
csio_lns_online(struct csio_lnode * ln,enum csio_ln_ev evt)1167a3667aaeSNaresh Kumar Inna csio_lns_online(struct csio_lnode *ln, enum csio_ln_ev evt)
1168a3667aaeSNaresh Kumar Inna {
1169a3667aaeSNaresh Kumar Inna struct csio_hw *hw = csio_lnode_to_hw(ln);
1170a3667aaeSNaresh Kumar Inna
1171a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_sm[evt]);
1172a3667aaeSNaresh Kumar Inna switch (evt) {
1173a3667aaeSNaresh Kumar Inna case CSIO_LNE_LINKUP:
1174a3667aaeSNaresh Kumar Inna csio_ln_warn(ln,
1175a3667aaeSNaresh Kumar Inna "warn: FCOE link is up already "
1176a3667aaeSNaresh Kumar Inna "Ignoring linkup on port:%d\n", ln->portid);
1177a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_drop);
1178a3667aaeSNaresh Kumar Inna break;
1179a3667aaeSNaresh Kumar Inna
1180a3667aaeSNaresh Kumar Inna case CSIO_LNE_FAB_INIT_DONE:
1181a3667aaeSNaresh Kumar Inna csio_set_state(&ln->sm, csio_lns_ready);
1182a3667aaeSNaresh Kumar Inna
1183a3667aaeSNaresh Kumar Inna spin_unlock_irq(&hw->lock);
1184a3667aaeSNaresh Kumar Inna csio_lnode_async_event(ln, CSIO_LN_FC_LINKUP);
1185a3667aaeSNaresh Kumar Inna spin_lock_irq(&hw->lock);
1186a3667aaeSNaresh Kumar Inna
1187a3667aaeSNaresh Kumar Inna break;
1188a3667aaeSNaresh Kumar Inna
1189a3667aaeSNaresh Kumar Inna case CSIO_LNE_LINK_DOWN:
1190a3667aaeSNaresh Kumar Inna case CSIO_LNE_DOWN_LINK:
1191a3667aaeSNaresh Kumar Inna csio_set_state(&ln->sm, csio_lns_uninit);
1192a3667aaeSNaresh Kumar Inna if (csio_is_phys_ln(ln)) {
1193a3667aaeSNaresh Kumar Inna /* Remove FCF entry */
1194a3667aaeSNaresh Kumar Inna list_del_init(&ln->fcfinfo->list);
1195a3667aaeSNaresh Kumar Inna }
1196a3667aaeSNaresh Kumar Inna break;
1197a3667aaeSNaresh Kumar Inna
1198a3667aaeSNaresh Kumar Inna default:
1199a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln,
1200a3667aaeSNaresh Kumar Inna "unexp ln event %d recv from did:x%x in "
1201a3667aaeSNaresh Kumar Inna "ln state[uninit].\n", evt, ln->nport_id);
1202a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_unexp);
1203a3667aaeSNaresh Kumar Inna
1204a3667aaeSNaresh Kumar Inna break;
1205a3667aaeSNaresh Kumar Inna } /* switch event */
1206a3667aaeSNaresh Kumar Inna }
1207a3667aaeSNaresh Kumar Inna
1208a3667aaeSNaresh Kumar Inna /*
1209a3667aaeSNaresh Kumar Inna * csio_lns_ready - The request in ready state.
1210a3667aaeSNaresh Kumar Inna * @ln - FCOE lnode.
1211a3667aaeSNaresh Kumar Inna * @evt - Event to be processed.
1212a3667aaeSNaresh Kumar Inna *
1213a3667aaeSNaresh Kumar Inna * Process the given lnode event which is currently in "ready" state.
1214a3667aaeSNaresh Kumar Inna * Invoked with HW lock held.
1215a3667aaeSNaresh Kumar Inna * Return - none.
1216a3667aaeSNaresh Kumar Inna */
1217a3667aaeSNaresh Kumar Inna static void
csio_lns_ready(struct csio_lnode * ln,enum csio_ln_ev evt)1218a3667aaeSNaresh Kumar Inna csio_lns_ready(struct csio_lnode *ln, enum csio_ln_ev evt)
1219a3667aaeSNaresh Kumar Inna {
1220a3667aaeSNaresh Kumar Inna struct csio_hw *hw = csio_lnode_to_hw(ln);
1221a3667aaeSNaresh Kumar Inna
1222a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_sm[evt]);
1223a3667aaeSNaresh Kumar Inna switch (evt) {
1224a3667aaeSNaresh Kumar Inna case CSIO_LNE_FAB_INIT_DONE:
1225a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln,
1226a3667aaeSNaresh Kumar Inna "ignoring event %d recv from did x%x"
1227a3667aaeSNaresh Kumar Inna "in ln state[ready].\n", evt, ln->nport_id);
1228a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_drop);
1229a3667aaeSNaresh Kumar Inna break;
1230a3667aaeSNaresh Kumar Inna
1231a3667aaeSNaresh Kumar Inna case CSIO_LNE_LINK_DOWN:
1232a3667aaeSNaresh Kumar Inna csio_set_state(&ln->sm, csio_lns_offline);
1233a3667aaeSNaresh Kumar Inna csio_post_event_rns(ln, CSIO_RNFE_DOWN);
1234a3667aaeSNaresh Kumar Inna
1235a3667aaeSNaresh Kumar Inna spin_unlock_irq(&hw->lock);
1236a3667aaeSNaresh Kumar Inna csio_lnode_async_event(ln, CSIO_LN_FC_LINKDOWN);
1237a3667aaeSNaresh Kumar Inna spin_lock_irq(&hw->lock);
1238a3667aaeSNaresh Kumar Inna
1239a3667aaeSNaresh Kumar Inna if (csio_is_phys_ln(ln)) {
1240a3667aaeSNaresh Kumar Inna /* Remove FCF entry */
1241a3667aaeSNaresh Kumar Inna list_del_init(&ln->fcfinfo->list);
1242a3667aaeSNaresh Kumar Inna }
1243a3667aaeSNaresh Kumar Inna break;
1244a3667aaeSNaresh Kumar Inna
1245a3667aaeSNaresh Kumar Inna case CSIO_LNE_DOWN_LINK:
1246a3667aaeSNaresh Kumar Inna csio_set_state(&ln->sm, csio_lns_offline);
1247a3667aaeSNaresh Kumar Inna csio_post_event_rns(ln, CSIO_RNFE_DOWN);
1248a3667aaeSNaresh Kumar Inna
1249a3667aaeSNaresh Kumar Inna /* Host need to issue aborts in case if FW has not returned
1250a3667aaeSNaresh Kumar Inna * WRs with status "ABORTED"
1251a3667aaeSNaresh Kumar Inna */
1252a3667aaeSNaresh Kumar Inna spin_unlock_irq(&hw->lock);
1253a3667aaeSNaresh Kumar Inna csio_lnode_async_event(ln, CSIO_LN_FC_LINKDOWN);
1254a3667aaeSNaresh Kumar Inna spin_lock_irq(&hw->lock);
1255a3667aaeSNaresh Kumar Inna
1256a3667aaeSNaresh Kumar Inna if (csio_is_phys_ln(ln)) {
1257a3667aaeSNaresh Kumar Inna /* Remove FCF entry */
1258a3667aaeSNaresh Kumar Inna list_del_init(&ln->fcfinfo->list);
1259a3667aaeSNaresh Kumar Inna }
1260a3667aaeSNaresh Kumar Inna break;
1261a3667aaeSNaresh Kumar Inna
1262a3667aaeSNaresh Kumar Inna case CSIO_LNE_CLOSE:
1263a3667aaeSNaresh Kumar Inna csio_set_state(&ln->sm, csio_lns_uninit);
1264a3667aaeSNaresh Kumar Inna csio_post_event_rns(ln, CSIO_RNFE_CLOSE);
1265a3667aaeSNaresh Kumar Inna break;
1266a3667aaeSNaresh Kumar Inna
1267a3667aaeSNaresh Kumar Inna case CSIO_LNE_LOGO:
1268a3667aaeSNaresh Kumar Inna csio_set_state(&ln->sm, csio_lns_offline);
1269a3667aaeSNaresh Kumar Inna csio_post_event_rns(ln, CSIO_RNFE_DOWN);
1270a3667aaeSNaresh Kumar Inna break;
1271a3667aaeSNaresh Kumar Inna
1272a3667aaeSNaresh Kumar Inna default:
1273a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln,
1274a3667aaeSNaresh Kumar Inna "unexp ln event %d recv from did:x%x in "
1275a3667aaeSNaresh Kumar Inna "ln state[uninit].\n", evt, ln->nport_id);
1276a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_unexp);
1277a3667aaeSNaresh Kumar Inna CSIO_DB_ASSERT(0);
1278a3667aaeSNaresh Kumar Inna break;
1279a3667aaeSNaresh Kumar Inna } /* switch event */
1280a3667aaeSNaresh Kumar Inna }
1281a3667aaeSNaresh Kumar Inna
1282a3667aaeSNaresh Kumar Inna /*
1283a3667aaeSNaresh Kumar Inna * csio_lns_offline - The request in offline state.
1284a3667aaeSNaresh Kumar Inna * @ln - FCOE lnode.
1285a3667aaeSNaresh Kumar Inna * @evt - Event to be processed.
1286a3667aaeSNaresh Kumar Inna *
1287a3667aaeSNaresh Kumar Inna * Process the given lnode event which is currently in "offline" state.
1288a3667aaeSNaresh Kumar Inna * Invoked with HW lock held.
1289a3667aaeSNaresh Kumar Inna * Return - none.
1290a3667aaeSNaresh Kumar Inna */
1291a3667aaeSNaresh Kumar Inna static void
csio_lns_offline(struct csio_lnode * ln,enum csio_ln_ev evt)1292a3667aaeSNaresh Kumar Inna csio_lns_offline(struct csio_lnode *ln, enum csio_ln_ev evt)
1293a3667aaeSNaresh Kumar Inna {
1294a3667aaeSNaresh Kumar Inna struct csio_hw *hw = csio_lnode_to_hw(ln);
1295a3667aaeSNaresh Kumar Inna struct csio_lnode *rln = hw->rln;
1296a3667aaeSNaresh Kumar Inna int rv;
1297a3667aaeSNaresh Kumar Inna
1298a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_sm[evt]);
1299a3667aaeSNaresh Kumar Inna switch (evt) {
1300a3667aaeSNaresh Kumar Inna case CSIO_LNE_LINKUP:
1301a3667aaeSNaresh Kumar Inna csio_set_state(&ln->sm, csio_lns_online);
1302a3667aaeSNaresh Kumar Inna /* Read FCF only for physical lnode */
1303a3667aaeSNaresh Kumar Inna if (csio_is_phys_ln(ln)) {
1304a3667aaeSNaresh Kumar Inna rv = csio_ln_read_fcf_entry(ln,
1305a3667aaeSNaresh Kumar Inna csio_ln_read_fcf_cbfn);
1306a3667aaeSNaresh Kumar Inna if (rv != 0) {
1307a3667aaeSNaresh Kumar Inna /* TODO: Send HW RESET event */
1308a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_err);
1309a3667aaeSNaresh Kumar Inna break;
1310a3667aaeSNaresh Kumar Inna }
1311a3667aaeSNaresh Kumar Inna
1312a3667aaeSNaresh Kumar Inna /* Add FCF record */
1313a3667aaeSNaresh Kumar Inna list_add_tail(&ln->fcfinfo->list, &rln->fcf_lsthead);
1314a3667aaeSNaresh Kumar Inna }
1315a3667aaeSNaresh Kumar Inna
1316a3667aaeSNaresh Kumar Inna rv = csio_ln_vnp_read(ln, csio_ln_vnp_read_cbfn);
1317a3667aaeSNaresh Kumar Inna if (rv != 0) {
1318a3667aaeSNaresh Kumar Inna /* TODO: Send HW RESET event */
1319a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_err);
1320a3667aaeSNaresh Kumar Inna }
1321a3667aaeSNaresh Kumar Inna break;
1322a3667aaeSNaresh Kumar Inna
1323a3667aaeSNaresh Kumar Inna case CSIO_LNE_LINK_DOWN:
1324a3667aaeSNaresh Kumar Inna case CSIO_LNE_DOWN_LINK:
1325a3667aaeSNaresh Kumar Inna case CSIO_LNE_LOGO:
1326a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln,
1327a3667aaeSNaresh Kumar Inna "ignoring event %d recv from did x%x"
1328a3667aaeSNaresh Kumar Inna "in ln state[offline].\n", evt, ln->nport_id);
1329a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_drop);
1330a3667aaeSNaresh Kumar Inna break;
1331a3667aaeSNaresh Kumar Inna
1332a3667aaeSNaresh Kumar Inna case CSIO_LNE_CLOSE:
1333a3667aaeSNaresh Kumar Inna csio_set_state(&ln->sm, csio_lns_uninit);
1334a3667aaeSNaresh Kumar Inna csio_post_event_rns(ln, CSIO_RNFE_CLOSE);
1335a3667aaeSNaresh Kumar Inna break;
1336a3667aaeSNaresh Kumar Inna
1337a3667aaeSNaresh Kumar Inna default:
1338a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln,
1339a3667aaeSNaresh Kumar Inna "unexp ln event %d recv from did:x%x in "
1340a3667aaeSNaresh Kumar Inna "ln state[offline]\n", evt, ln->nport_id);
1341a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_unexp);
1342a3667aaeSNaresh Kumar Inna CSIO_DB_ASSERT(0);
1343a3667aaeSNaresh Kumar Inna break;
1344a3667aaeSNaresh Kumar Inna } /* switch event */
1345a3667aaeSNaresh Kumar Inna }
1346a3667aaeSNaresh Kumar Inna
1347a3667aaeSNaresh Kumar Inna /*****************************************************************************/
1348a3667aaeSNaresh Kumar Inna /* END: Lnode SM */
1349a3667aaeSNaresh Kumar Inna /*****************************************************************************/
1350a3667aaeSNaresh Kumar Inna
1351a3667aaeSNaresh Kumar Inna static void
csio_free_fcfinfo(struct kref * kref)1352a3667aaeSNaresh Kumar Inna csio_free_fcfinfo(struct kref *kref)
1353a3667aaeSNaresh Kumar Inna {
1354a3667aaeSNaresh Kumar Inna struct csio_fcf_info *fcfinfo = container_of(kref,
1355a3667aaeSNaresh Kumar Inna struct csio_fcf_info, kref);
1356a3667aaeSNaresh Kumar Inna kfree(fcfinfo);
1357a3667aaeSNaresh Kumar Inna }
1358a3667aaeSNaresh Kumar Inna
1359a3667aaeSNaresh Kumar Inna /* Helper routines for attributes */
1360a3667aaeSNaresh Kumar Inna /*
1361a3667aaeSNaresh Kumar Inna * csio_lnode_state_to_str - Get current state of FCOE lnode.
1362a3667aaeSNaresh Kumar Inna * @ln - lnode
1363a3667aaeSNaresh Kumar Inna * @str - state of lnode.
1364a3667aaeSNaresh Kumar Inna *
1365a3667aaeSNaresh Kumar Inna */
1366a3667aaeSNaresh Kumar Inna void
csio_lnode_state_to_str(struct csio_lnode * ln,int8_t * str)1367a3667aaeSNaresh Kumar Inna csio_lnode_state_to_str(struct csio_lnode *ln, int8_t *str)
1368a3667aaeSNaresh Kumar Inna {
1369*ccb6998cSArnd Bergmann if (csio_get_state(ln) == csio_lns_uninit) {
1370a3667aaeSNaresh Kumar Inna strcpy(str, "UNINIT");
1371a3667aaeSNaresh Kumar Inna return;
1372a3667aaeSNaresh Kumar Inna }
1373*ccb6998cSArnd Bergmann if (csio_get_state(ln) == csio_lns_ready) {
1374a3667aaeSNaresh Kumar Inna strcpy(str, "READY");
1375a3667aaeSNaresh Kumar Inna return;
1376a3667aaeSNaresh Kumar Inna }
1377*ccb6998cSArnd Bergmann if (csio_get_state(ln) == csio_lns_offline) {
1378a3667aaeSNaresh Kumar Inna strcpy(str, "OFFLINE");
1379a3667aaeSNaresh Kumar Inna return;
1380a3667aaeSNaresh Kumar Inna }
1381a3667aaeSNaresh Kumar Inna strcpy(str, "UNKNOWN");
1382a3667aaeSNaresh Kumar Inna } /* csio_lnode_state_to_str */
1383a3667aaeSNaresh Kumar Inna
1384a3667aaeSNaresh Kumar Inna
1385a3667aaeSNaresh Kumar Inna int
csio_get_phy_port_stats(struct csio_hw * hw,uint8_t portid,struct fw_fcoe_port_stats * port_stats)1386a3667aaeSNaresh Kumar Inna csio_get_phy_port_stats(struct csio_hw *hw, uint8_t portid,
1387a3667aaeSNaresh Kumar Inna struct fw_fcoe_port_stats *port_stats)
1388a3667aaeSNaresh Kumar Inna {
1389a3667aaeSNaresh Kumar Inna struct csio_mb *mbp;
1390a3667aaeSNaresh Kumar Inna struct fw_fcoe_port_cmd_params portparams;
1391a3667aaeSNaresh Kumar Inna enum fw_retval retval;
1392a3667aaeSNaresh Kumar Inna int idx;
1393a3667aaeSNaresh Kumar Inna
1394a3667aaeSNaresh Kumar Inna mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
1395a3667aaeSNaresh Kumar Inna if (!mbp) {
1396a3667aaeSNaresh Kumar Inna csio_err(hw, "FCoE FCF PARAMS command out of memory!\n");
1397a3667aaeSNaresh Kumar Inna return -EINVAL;
1398a3667aaeSNaresh Kumar Inna }
1399a3667aaeSNaresh Kumar Inna portparams.portid = portid;
1400a3667aaeSNaresh Kumar Inna
1401a3667aaeSNaresh Kumar Inna for (idx = 1; idx <= 3; idx++) {
1402a3667aaeSNaresh Kumar Inna portparams.idx = (idx-1)*6 + 1;
1403a3667aaeSNaresh Kumar Inna portparams.nstats = 6;
1404a3667aaeSNaresh Kumar Inna if (idx == 3)
1405a3667aaeSNaresh Kumar Inna portparams.nstats = 4;
1406a3667aaeSNaresh Kumar Inna csio_fcoe_read_portparams_init_mb(hw, mbp, CSIO_MB_DEFAULT_TMO,
1407a3667aaeSNaresh Kumar Inna &portparams, NULL);
1408a3667aaeSNaresh Kumar Inna if (csio_mb_issue(hw, mbp)) {
1409a3667aaeSNaresh Kumar Inna csio_err(hw, "Issue of FCoE port params failed!\n");
1410a3667aaeSNaresh Kumar Inna mempool_free(mbp, hw->mb_mempool);
1411a3667aaeSNaresh Kumar Inna return -EINVAL;
1412a3667aaeSNaresh Kumar Inna }
1413a3667aaeSNaresh Kumar Inna csio_mb_process_portparams_rsp(hw, mbp, &retval,
1414a3667aaeSNaresh Kumar Inna &portparams, port_stats);
1415a3667aaeSNaresh Kumar Inna }
1416a3667aaeSNaresh Kumar Inna
1417a3667aaeSNaresh Kumar Inna mempool_free(mbp, hw->mb_mempool);
1418a3667aaeSNaresh Kumar Inna return 0;
1419a3667aaeSNaresh Kumar Inna }
1420a3667aaeSNaresh Kumar Inna
1421a3667aaeSNaresh Kumar Inna /*
1422a3667aaeSNaresh Kumar Inna * csio_ln_mgmt_wr_handler -Mgmt Work Request handler.
1423a3667aaeSNaresh Kumar Inna * @wr - WR.
1424a3667aaeSNaresh Kumar Inna * @len - WR len.
1425a3667aaeSNaresh Kumar Inna * This handler is invoked when an outstanding mgmt WR is completed.
1426a3667aaeSNaresh Kumar Inna * Its invoked in the context of FW event worker thread for every
1427a3667aaeSNaresh Kumar Inna * mgmt event received.
1428a3667aaeSNaresh Kumar Inna * Return - none.
1429a3667aaeSNaresh Kumar Inna */
1430a3667aaeSNaresh Kumar Inna
1431a3667aaeSNaresh Kumar Inna static void
csio_ln_mgmt_wr_handler(struct csio_hw * hw,void * wr,uint32_t len)1432a3667aaeSNaresh Kumar Inna csio_ln_mgmt_wr_handler(struct csio_hw *hw, void *wr, uint32_t len)
1433a3667aaeSNaresh Kumar Inna {
1434a3667aaeSNaresh Kumar Inna struct csio_mgmtm *mgmtm = csio_hw_to_mgmtm(hw);
1435a3667aaeSNaresh Kumar Inna struct csio_ioreq *io_req = NULL;
1436a3667aaeSNaresh Kumar Inna struct fw_fcoe_els_ct_wr *wr_cmd;
1437a3667aaeSNaresh Kumar Inna
1438a3667aaeSNaresh Kumar Inna
1439a3667aaeSNaresh Kumar Inna wr_cmd = (struct fw_fcoe_els_ct_wr *) wr;
1440a3667aaeSNaresh Kumar Inna
1441a3667aaeSNaresh Kumar Inna if (len < sizeof(struct fw_fcoe_els_ct_wr)) {
1442a3667aaeSNaresh Kumar Inna csio_err(mgmtm->hw,
1443a3667aaeSNaresh Kumar Inna "Invalid ELS CT WR length recvd, len:%x\n", len);
1444a3667aaeSNaresh Kumar Inna mgmtm->stats.n_err++;
1445a3667aaeSNaresh Kumar Inna return;
1446a3667aaeSNaresh Kumar Inna }
1447a3667aaeSNaresh Kumar Inna
1448a3667aaeSNaresh Kumar Inna io_req = (struct csio_ioreq *) ((uintptr_t) wr_cmd->cookie);
1449a3667aaeSNaresh Kumar Inna io_req->wr_status = csio_wr_status(wr_cmd);
1450a3667aaeSNaresh Kumar Inna
1451a3667aaeSNaresh Kumar Inna /* lookup ioreq exists in our active Q */
1452a3667aaeSNaresh Kumar Inna spin_lock_irq(&hw->lock);
1453a3667aaeSNaresh Kumar Inna if (csio_mgmt_req_lookup(mgmtm, io_req) != 0) {
1454a3667aaeSNaresh Kumar Inna csio_err(mgmtm->hw,
1455a3667aaeSNaresh Kumar Inna "Error- Invalid IO handle recv in WR. handle: %p\n",
1456a3667aaeSNaresh Kumar Inna io_req);
1457a3667aaeSNaresh Kumar Inna mgmtm->stats.n_err++;
1458a3667aaeSNaresh Kumar Inna spin_unlock_irq(&hw->lock);
1459a3667aaeSNaresh Kumar Inna return;
1460a3667aaeSNaresh Kumar Inna }
1461a3667aaeSNaresh Kumar Inna
1462a3667aaeSNaresh Kumar Inna mgmtm = csio_hw_to_mgmtm(hw);
1463a3667aaeSNaresh Kumar Inna
1464a3667aaeSNaresh Kumar Inna /* Dequeue from active queue */
1465a3667aaeSNaresh Kumar Inna list_del_init(&io_req->sm.sm_list);
1466a3667aaeSNaresh Kumar Inna mgmtm->stats.n_active--;
1467a3667aaeSNaresh Kumar Inna spin_unlock_irq(&hw->lock);
1468a3667aaeSNaresh Kumar Inna
1469a3667aaeSNaresh Kumar Inna /* io_req will be freed by completion handler */
1470a3667aaeSNaresh Kumar Inna if (io_req->io_cbfn)
1471a3667aaeSNaresh Kumar Inna io_req->io_cbfn(hw, io_req);
1472a3667aaeSNaresh Kumar Inna }
1473a3667aaeSNaresh Kumar Inna
1474a3667aaeSNaresh Kumar Inna /**
1475a3667aaeSNaresh Kumar Inna * csio_fcoe_fwevt_handler - Event handler for Firmware FCoE events.
1476a3667aaeSNaresh Kumar Inna * @hw: HW module
1477a3667aaeSNaresh Kumar Inna * @cpl_op: CPL opcode
1478a3667aaeSNaresh Kumar Inna * @cmd: FW cmd/WR.
1479a3667aaeSNaresh Kumar Inna *
1480a3667aaeSNaresh Kumar Inna * Process received FCoE cmd/WR event from FW.
1481a3667aaeSNaresh Kumar Inna */
1482a3667aaeSNaresh Kumar Inna void
csio_fcoe_fwevt_handler(struct csio_hw * hw,__u8 cpl_op,__be64 * cmd)1483a3667aaeSNaresh Kumar Inna csio_fcoe_fwevt_handler(struct csio_hw *hw, __u8 cpl_op, __be64 *cmd)
1484a3667aaeSNaresh Kumar Inna {
1485a3667aaeSNaresh Kumar Inna struct csio_lnode *ln;
1486a3667aaeSNaresh Kumar Inna struct csio_rnode *rn;
1487a3667aaeSNaresh Kumar Inna uint8_t portid, opcode = *(uint8_t *)cmd;
1488a3667aaeSNaresh Kumar Inna struct fw_fcoe_link_cmd *lcmd;
1489a3667aaeSNaresh Kumar Inna struct fw_wr_hdr *wr;
1490a3667aaeSNaresh Kumar Inna struct fw_rdev_wr *rdev_wr;
1491a3667aaeSNaresh Kumar Inna enum fw_fcoe_link_status lstatus;
1492a3667aaeSNaresh Kumar Inna uint32_t fcfi, rdev_flowid, vnpi;
1493a3667aaeSNaresh Kumar Inna enum csio_ln_ev evt;
1494a3667aaeSNaresh Kumar Inna
1495a3667aaeSNaresh Kumar Inna if (cpl_op == CPL_FW6_MSG && opcode == FW_FCOE_LINK_CMD) {
1496a3667aaeSNaresh Kumar Inna
1497a3667aaeSNaresh Kumar Inna lcmd = (struct fw_fcoe_link_cmd *)cmd;
1498a3667aaeSNaresh Kumar Inna lstatus = lcmd->lstatus;
1499a3667aaeSNaresh Kumar Inna portid = FW_FCOE_LINK_CMD_PORTID_GET(
1500a3667aaeSNaresh Kumar Inna ntohl(lcmd->op_to_portid));
1501a3667aaeSNaresh Kumar Inna fcfi = FW_FCOE_LINK_CMD_FCFI_GET(ntohl(lcmd->sub_opcode_fcfi));
1502a3667aaeSNaresh Kumar Inna vnpi = FW_FCOE_LINK_CMD_VNPI_GET(ntohl(lcmd->vnpi_pkd));
1503a3667aaeSNaresh Kumar Inna
1504a3667aaeSNaresh Kumar Inna if (lstatus == FCOE_LINKUP) {
1505a3667aaeSNaresh Kumar Inna
1506a3667aaeSNaresh Kumar Inna /* HW lock here */
1507a3667aaeSNaresh Kumar Inna spin_lock_irq(&hw->lock);
1508a3667aaeSNaresh Kumar Inna csio_handle_link_up(hw, portid, fcfi, vnpi);
1509a3667aaeSNaresh Kumar Inna spin_unlock_irq(&hw->lock);
1510a3667aaeSNaresh Kumar Inna /* HW un lock here */
1511a3667aaeSNaresh Kumar Inna
1512a3667aaeSNaresh Kumar Inna } else if (lstatus == FCOE_LINKDOWN) {
1513a3667aaeSNaresh Kumar Inna
1514a3667aaeSNaresh Kumar Inna /* HW lock here */
1515a3667aaeSNaresh Kumar Inna spin_lock_irq(&hw->lock);
1516a3667aaeSNaresh Kumar Inna csio_handle_link_down(hw, portid, fcfi, vnpi);
1517a3667aaeSNaresh Kumar Inna spin_unlock_irq(&hw->lock);
1518a3667aaeSNaresh Kumar Inna /* HW un lock here */
1519a3667aaeSNaresh Kumar Inna } else {
1520a3667aaeSNaresh Kumar Inna csio_warn(hw, "Unexpected FCOE LINK status:0x%x\n",
15215036f0a0SNaresh Kumar Inna lcmd->lstatus);
1522a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_cpl_unexp);
1523a3667aaeSNaresh Kumar Inna }
1524a3667aaeSNaresh Kumar Inna } else if (cpl_op == CPL_FW6_PLD) {
1525a3667aaeSNaresh Kumar Inna wr = (struct fw_wr_hdr *) (cmd + 4);
1526e2ac9628SHariprasad Shenai if (FW_WR_OP_G(be32_to_cpu(wr->hi))
1527a3667aaeSNaresh Kumar Inna == FW_RDEV_WR) {
1528a3667aaeSNaresh Kumar Inna
1529a3667aaeSNaresh Kumar Inna rdev_wr = (struct fw_rdev_wr *) (cmd + 4);
1530a3667aaeSNaresh Kumar Inna
1531a3667aaeSNaresh Kumar Inna rdev_flowid = FW_RDEV_WR_FLOWID_GET(
1532a3667aaeSNaresh Kumar Inna ntohl(rdev_wr->alloc_to_len16));
1533a3667aaeSNaresh Kumar Inna vnpi = FW_RDEV_WR_ASSOC_FLOWID_GET(
1534a3667aaeSNaresh Kumar Inna ntohl(rdev_wr->flags_to_assoc_flowid));
1535a3667aaeSNaresh Kumar Inna
1536a3667aaeSNaresh Kumar Inna csio_dbg(hw,
1537a3667aaeSNaresh Kumar Inna "FW_RDEV_WR: flowid:x%x ev_cause:x%x "
1538a3667aaeSNaresh Kumar Inna "vnpi:0x%x\n", rdev_flowid,
1539a3667aaeSNaresh Kumar Inna rdev_wr->event_cause, vnpi);
1540a3667aaeSNaresh Kumar Inna
1541a3667aaeSNaresh Kumar Inna if (rdev_wr->protocol != PROT_FCOE) {
1542a3667aaeSNaresh Kumar Inna csio_err(hw,
1543a3667aaeSNaresh Kumar Inna "FW_RDEV_WR: invalid proto:x%x "
1544a3667aaeSNaresh Kumar Inna "received with flowid:x%x\n",
1545a3667aaeSNaresh Kumar Inna rdev_wr->protocol,
1546a3667aaeSNaresh Kumar Inna rdev_flowid);
1547a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_evt_drop);
1548a3667aaeSNaresh Kumar Inna return;
1549a3667aaeSNaresh Kumar Inna }
1550a3667aaeSNaresh Kumar Inna
1551a3667aaeSNaresh Kumar Inna /* HW lock here */
1552a3667aaeSNaresh Kumar Inna spin_lock_irq(&hw->lock);
1553a3667aaeSNaresh Kumar Inna ln = csio_ln_lookup_by_vnpi(hw, vnpi);
1554a3667aaeSNaresh Kumar Inna if (!ln) {
1555a3667aaeSNaresh Kumar Inna csio_err(hw,
1556a3667aaeSNaresh Kumar Inna "FW_DEV_WR: invalid vnpi:x%x received "
1557a3667aaeSNaresh Kumar Inna "with flowid:x%x\n", vnpi, rdev_flowid);
1558a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_evt_drop);
1559a3667aaeSNaresh Kumar Inna goto out_pld;
1560a3667aaeSNaresh Kumar Inna }
1561a3667aaeSNaresh Kumar Inna
1562a3667aaeSNaresh Kumar Inna rn = csio_confirm_rnode(ln, rdev_flowid,
1563a3667aaeSNaresh Kumar Inna &rdev_wr->u.fcoe_rdev);
1564a3667aaeSNaresh Kumar Inna if (!rn) {
1565a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln,
1566a3667aaeSNaresh Kumar Inna "Failed to confirm rnode "
1567a3667aaeSNaresh Kumar Inna "for flowid:x%x\n", rdev_flowid);
1568a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_evt_drop);
1569a3667aaeSNaresh Kumar Inna goto out_pld;
1570a3667aaeSNaresh Kumar Inna }
1571a3667aaeSNaresh Kumar Inna
1572a3667aaeSNaresh Kumar Inna /* save previous event for debugging */
1573a3667aaeSNaresh Kumar Inna ln->prev_evt = ln->cur_evt;
1574a3667aaeSNaresh Kumar Inna ln->cur_evt = rdev_wr->event_cause;
1575a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(ln, n_evt_fw[rdev_wr->event_cause]);
1576a3667aaeSNaresh Kumar Inna
1577a3667aaeSNaresh Kumar Inna /* Translate all the fabric events to lnode SM events */
1578a3667aaeSNaresh Kumar Inna evt = CSIO_FWE_TO_LNE(rdev_wr->event_cause);
1579a3667aaeSNaresh Kumar Inna if (evt) {
1580a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln,
1581a3667aaeSNaresh Kumar Inna "Posting event to lnode event:%d "
1582a3667aaeSNaresh Kumar Inna "cause:%d flowid:x%x\n", evt,
1583a3667aaeSNaresh Kumar Inna rdev_wr->event_cause, rdev_flowid);
1584a3667aaeSNaresh Kumar Inna csio_post_event(&ln->sm, evt);
1585a3667aaeSNaresh Kumar Inna }
1586a3667aaeSNaresh Kumar Inna
1587a3667aaeSNaresh Kumar Inna /* Handover event to rn SM here. */
1588a3667aaeSNaresh Kumar Inna csio_rnode_fwevt_handler(rn, rdev_wr->event_cause);
1589a3667aaeSNaresh Kumar Inna out_pld:
1590a3667aaeSNaresh Kumar Inna spin_unlock_irq(&hw->lock);
1591a3667aaeSNaresh Kumar Inna return;
1592a3667aaeSNaresh Kumar Inna } else {
1593a3667aaeSNaresh Kumar Inna csio_warn(hw, "unexpected WR op(0x%x) recv\n",
1594e2ac9628SHariprasad Shenai FW_WR_OP_G(be32_to_cpu((wr->hi))));
1595a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_cpl_unexp);
1596a3667aaeSNaresh Kumar Inna }
1597a3667aaeSNaresh Kumar Inna } else if (cpl_op == CPL_FW6_MSG) {
1598a3667aaeSNaresh Kumar Inna wr = (struct fw_wr_hdr *) (cmd);
1599e2ac9628SHariprasad Shenai if (FW_WR_OP_G(be32_to_cpu(wr->hi)) == FW_FCOE_ELS_CT_WR) {
1600a3667aaeSNaresh Kumar Inna csio_ln_mgmt_wr_handler(hw, wr,
1601a3667aaeSNaresh Kumar Inna sizeof(struct fw_fcoe_els_ct_wr));
1602a3667aaeSNaresh Kumar Inna } else {
1603a3667aaeSNaresh Kumar Inna csio_warn(hw, "unexpected WR op(0x%x) recv\n",
1604e2ac9628SHariprasad Shenai FW_WR_OP_G(be32_to_cpu((wr->hi))));
1605a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_cpl_unexp);
1606a3667aaeSNaresh Kumar Inna }
1607a3667aaeSNaresh Kumar Inna } else {
1608a3667aaeSNaresh Kumar Inna csio_warn(hw, "unexpected CPL op(0x%x) recv\n", opcode);
1609a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_cpl_unexp);
1610a3667aaeSNaresh Kumar Inna }
1611a3667aaeSNaresh Kumar Inna }
1612a3667aaeSNaresh Kumar Inna
1613a3667aaeSNaresh Kumar Inna /**
1614a3667aaeSNaresh Kumar Inna * csio_lnode_start - Kickstart lnode discovery.
1615a3667aaeSNaresh Kumar Inna * @ln: lnode
1616a3667aaeSNaresh Kumar Inna *
1617a3667aaeSNaresh Kumar Inna * This routine kickstarts the discovery by issuing an FCOE_LINK (up) command.
1618a3667aaeSNaresh Kumar Inna */
1619a3667aaeSNaresh Kumar Inna int
csio_lnode_start(struct csio_lnode * ln)1620a3667aaeSNaresh Kumar Inna csio_lnode_start(struct csio_lnode *ln)
1621a3667aaeSNaresh Kumar Inna {
1622a3667aaeSNaresh Kumar Inna int rv = 0;
1623a3667aaeSNaresh Kumar Inna if (csio_is_phys_ln(ln) && !(ln->flags & CSIO_LNF_LINK_ENABLE)) {
1624a3667aaeSNaresh Kumar Inna rv = csio_fcoe_enable_link(ln, 1);
1625a3667aaeSNaresh Kumar Inna ln->flags |= CSIO_LNF_LINK_ENABLE;
1626a3667aaeSNaresh Kumar Inna }
1627a3667aaeSNaresh Kumar Inna
1628a3667aaeSNaresh Kumar Inna return rv;
1629a3667aaeSNaresh Kumar Inna }
1630a3667aaeSNaresh Kumar Inna
1631a3667aaeSNaresh Kumar Inna /**
1632a3667aaeSNaresh Kumar Inna * csio_lnode_stop - Stop the lnode.
1633a3667aaeSNaresh Kumar Inna * @ln: lnode
1634a3667aaeSNaresh Kumar Inna *
1635a3667aaeSNaresh Kumar Inna * This routine is invoked by HW module to stop lnode and its associated NPIV
1636a3667aaeSNaresh Kumar Inna * lnodes.
1637a3667aaeSNaresh Kumar Inna */
1638a3667aaeSNaresh Kumar Inna void
csio_lnode_stop(struct csio_lnode * ln)1639a3667aaeSNaresh Kumar Inna csio_lnode_stop(struct csio_lnode *ln)
1640a3667aaeSNaresh Kumar Inna {
1641a3667aaeSNaresh Kumar Inna csio_post_event_lns(ln, CSIO_LNE_DOWN_LINK);
1642a3667aaeSNaresh Kumar Inna if (csio_is_phys_ln(ln) && (ln->flags & CSIO_LNF_LINK_ENABLE)) {
1643a3667aaeSNaresh Kumar Inna csio_fcoe_enable_link(ln, 0);
1644a3667aaeSNaresh Kumar Inna ln->flags &= ~CSIO_LNF_LINK_ENABLE;
1645a3667aaeSNaresh Kumar Inna }
1646a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln, "stopping ln :%p\n", ln);
1647a3667aaeSNaresh Kumar Inna }
1648a3667aaeSNaresh Kumar Inna
1649a3667aaeSNaresh Kumar Inna /**
1650a3667aaeSNaresh Kumar Inna * csio_lnode_close - Close an lnode.
1651a3667aaeSNaresh Kumar Inna * @ln: lnode
1652a3667aaeSNaresh Kumar Inna *
1653a3667aaeSNaresh Kumar Inna * This routine is invoked by HW module to close an lnode and its
1654a3667aaeSNaresh Kumar Inna * associated NPIV lnodes. Lnode and its associated NPIV lnodes are
1655a3667aaeSNaresh Kumar Inna * set to uninitialized state.
1656a3667aaeSNaresh Kumar Inna */
1657a3667aaeSNaresh Kumar Inna void
csio_lnode_close(struct csio_lnode * ln)1658a3667aaeSNaresh Kumar Inna csio_lnode_close(struct csio_lnode *ln)
1659a3667aaeSNaresh Kumar Inna {
1660a3667aaeSNaresh Kumar Inna csio_post_event_lns(ln, CSIO_LNE_CLOSE);
1661a3667aaeSNaresh Kumar Inna if (csio_is_phys_ln(ln))
1662a3667aaeSNaresh Kumar Inna ln->vnp_flowid = CSIO_INVALID_IDX;
1663a3667aaeSNaresh Kumar Inna
1664a3667aaeSNaresh Kumar Inna csio_ln_dbg(ln, "closed ln :%p\n", ln);
1665a3667aaeSNaresh Kumar Inna }
1666a3667aaeSNaresh Kumar Inna
1667a3667aaeSNaresh Kumar Inna /*
1668a3667aaeSNaresh Kumar Inna * csio_ln_prep_ecwr - Prepare ELS/CT WR.
1669a3667aaeSNaresh Kumar Inna * @io_req - IO request.
1670a3667aaeSNaresh Kumar Inna * @wr_len - WR len
1671a3667aaeSNaresh Kumar Inna * @immd_len - WR immediate data
1672a3667aaeSNaresh Kumar Inna * @sub_op - Sub opcode
1673a3667aaeSNaresh Kumar Inna * @sid - source portid.
1674a3667aaeSNaresh Kumar Inna * @did - destination portid
1675a3667aaeSNaresh Kumar Inna * @flow_id - flowid
1676a3667aaeSNaresh Kumar Inna * @fw_wr - ELS/CT WR to be prepared.
1677a3667aaeSNaresh Kumar Inna * Returns: 0 - on success
1678a3667aaeSNaresh Kumar Inna */
1679a3667aaeSNaresh Kumar Inna static int
csio_ln_prep_ecwr(struct csio_ioreq * io_req,uint32_t wr_len,uint32_t immd_len,uint8_t sub_op,uint32_t sid,uint32_t did,uint32_t flow_id,uint8_t * fw_wr)1680a3667aaeSNaresh Kumar Inna csio_ln_prep_ecwr(struct csio_ioreq *io_req, uint32_t wr_len,
1681a3667aaeSNaresh Kumar Inna uint32_t immd_len, uint8_t sub_op, uint32_t sid,
1682a3667aaeSNaresh Kumar Inna uint32_t did, uint32_t flow_id, uint8_t *fw_wr)
1683a3667aaeSNaresh Kumar Inna {
1684a3667aaeSNaresh Kumar Inna struct fw_fcoe_els_ct_wr *wr;
16855036f0a0SNaresh Kumar Inna __be32 port_id;
1686a3667aaeSNaresh Kumar Inna
1687a3667aaeSNaresh Kumar Inna wr = (struct fw_fcoe_els_ct_wr *)fw_wr;
1688e2ac9628SHariprasad Shenai wr->op_immdlen = cpu_to_be32(FW_WR_OP_V(FW_FCOE_ELS_CT_WR) |
1689a3667aaeSNaresh Kumar Inna FW_FCOE_ELS_CT_WR_IMMDLEN(immd_len));
1690a3667aaeSNaresh Kumar Inna
1691a3667aaeSNaresh Kumar Inna wr_len = DIV_ROUND_UP(wr_len, 16);
1692e2ac9628SHariprasad Shenai wr->flowid_len16 = cpu_to_be32(FW_WR_FLOWID_V(flow_id) |
1693e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wr_len));
1694a3667aaeSNaresh Kumar Inna wr->els_ct_type = sub_op;
1695a3667aaeSNaresh Kumar Inna wr->ctl_pri = 0;
1696a3667aaeSNaresh Kumar Inna wr->cp_en_class = 0;
1697a3667aaeSNaresh Kumar Inna wr->cookie = io_req->fw_handle;
16985036f0a0SNaresh Kumar Inna wr->iqid = cpu_to_be16(csio_q_physiqid(
1699a3667aaeSNaresh Kumar Inna io_req->lnode->hwp, io_req->iq_idx));
1700a3667aaeSNaresh Kumar Inna wr->fl_to_sp = FW_FCOE_ELS_CT_WR_SP(1);
1701a3667aaeSNaresh Kumar Inna wr->tmo_val = (uint8_t) io_req->tmo;
1702a3667aaeSNaresh Kumar Inna port_id = htonl(sid);
1703a3667aaeSNaresh Kumar Inna memcpy(wr->l_id, PORT_ID_PTR(port_id), 3);
1704a3667aaeSNaresh Kumar Inna port_id = htonl(did);
1705a3667aaeSNaresh Kumar Inna memcpy(wr->r_id, PORT_ID_PTR(port_id), 3);
1706a3667aaeSNaresh Kumar Inna
1707a3667aaeSNaresh Kumar Inna /* Prepare RSP SGL */
1708a3667aaeSNaresh Kumar Inna wr->rsp_dmalen = cpu_to_be32(io_req->dma_buf.len);
1709a3667aaeSNaresh Kumar Inna wr->rsp_dmaaddr = cpu_to_be64(io_req->dma_buf.paddr);
1710a3667aaeSNaresh Kumar Inna return 0;
1711a3667aaeSNaresh Kumar Inna }
1712a3667aaeSNaresh Kumar Inna
1713a3667aaeSNaresh Kumar Inna /*
1714a3667aaeSNaresh Kumar Inna * csio_ln_mgmt_submit_wr - Post elsct work request.
1715a3667aaeSNaresh Kumar Inna * @mgmtm - mgmtm
1716a3667aaeSNaresh Kumar Inna * @io_req - io request.
1717a3667aaeSNaresh Kumar Inna * @sub_op - ELS or CT request type
1718a3667aaeSNaresh Kumar Inna * @pld - Dma Payload buffer
1719a3667aaeSNaresh Kumar Inna * @pld_len - Payload len
1720a3667aaeSNaresh Kumar Inna * Prepares ELSCT Work request and sents it to FW.
1721a3667aaeSNaresh Kumar Inna * Returns: 0 - on success
1722a3667aaeSNaresh Kumar Inna */
1723a3667aaeSNaresh Kumar Inna static int
csio_ln_mgmt_submit_wr(struct csio_mgmtm * mgmtm,struct csio_ioreq * io_req,uint8_t sub_op,struct csio_dma_buf * pld,uint32_t pld_len)1724a3667aaeSNaresh Kumar Inna csio_ln_mgmt_submit_wr(struct csio_mgmtm *mgmtm, struct csio_ioreq *io_req,
1725a3667aaeSNaresh Kumar Inna uint8_t sub_op, struct csio_dma_buf *pld,
1726a3667aaeSNaresh Kumar Inna uint32_t pld_len)
1727a3667aaeSNaresh Kumar Inna {
1728a3667aaeSNaresh Kumar Inna struct csio_wr_pair wrp;
1729a3667aaeSNaresh Kumar Inna struct csio_lnode *ln = io_req->lnode;
1730a3667aaeSNaresh Kumar Inna struct csio_rnode *rn = io_req->rnode;
1731a3667aaeSNaresh Kumar Inna struct csio_hw *hw = mgmtm->hw;
1732a3667aaeSNaresh Kumar Inna uint8_t fw_wr[64];
1733a3667aaeSNaresh Kumar Inna struct ulptx_sgl dsgl;
1734a3667aaeSNaresh Kumar Inna uint32_t wr_size = 0;
1735a3667aaeSNaresh Kumar Inna uint8_t im_len = 0;
1736a3667aaeSNaresh Kumar Inna uint32_t wr_off = 0;
1737a3667aaeSNaresh Kumar Inna
1738a3667aaeSNaresh Kumar Inna int ret = 0;
1739a3667aaeSNaresh Kumar Inna
1740a3667aaeSNaresh Kumar Inna /* Calculate WR Size for this ELS REQ */
1741a3667aaeSNaresh Kumar Inna wr_size = sizeof(struct fw_fcoe_els_ct_wr);
1742a3667aaeSNaresh Kumar Inna
1743a3667aaeSNaresh Kumar Inna /* Send as immediate data if pld < 256 */
1744a3667aaeSNaresh Kumar Inna if (pld_len < 256) {
1745a3667aaeSNaresh Kumar Inna wr_size += ALIGN(pld_len, 8);
1746a3667aaeSNaresh Kumar Inna im_len = (uint8_t)pld_len;
1747a3667aaeSNaresh Kumar Inna } else
1748a3667aaeSNaresh Kumar Inna wr_size += sizeof(struct ulptx_sgl);
1749a3667aaeSNaresh Kumar Inna
1750a3667aaeSNaresh Kumar Inna /* Roundup WR size in units of 16 bytes */
1751a3667aaeSNaresh Kumar Inna wr_size = ALIGN(wr_size, 16);
1752a3667aaeSNaresh Kumar Inna
1753a3667aaeSNaresh Kumar Inna /* Get WR to send ELS REQ */
1754a3667aaeSNaresh Kumar Inna ret = csio_wr_get(hw, mgmtm->eq_idx, wr_size, &wrp);
1755a3667aaeSNaresh Kumar Inna if (ret != 0) {
1756a3667aaeSNaresh Kumar Inna csio_err(hw, "Failed to get WR for ec_req %p ret:%d\n",
1757a3667aaeSNaresh Kumar Inna io_req, ret);
1758a3667aaeSNaresh Kumar Inna return ret;
1759a3667aaeSNaresh Kumar Inna }
1760a3667aaeSNaresh Kumar Inna
1761a3667aaeSNaresh Kumar Inna /* Prepare Generic WR used by all ELS/CT cmd */
1762a3667aaeSNaresh Kumar Inna csio_ln_prep_ecwr(io_req, wr_size, im_len, sub_op,
1763a3667aaeSNaresh Kumar Inna ln->nport_id, rn->nport_id,
1764a3667aaeSNaresh Kumar Inna csio_rn_flowid(rn),
1765a3667aaeSNaresh Kumar Inna &fw_wr[0]);
1766a3667aaeSNaresh Kumar Inna
1767a3667aaeSNaresh Kumar Inna /* Copy ELS/CT WR CMD */
1768a3667aaeSNaresh Kumar Inna csio_wr_copy_to_wrp(&fw_wr[0], &wrp, wr_off,
1769a3667aaeSNaresh Kumar Inna sizeof(struct fw_fcoe_els_ct_wr));
1770a3667aaeSNaresh Kumar Inna wr_off += sizeof(struct fw_fcoe_els_ct_wr);
1771a3667aaeSNaresh Kumar Inna
1772a3667aaeSNaresh Kumar Inna /* Copy payload to Immediate section of WR */
1773a3667aaeSNaresh Kumar Inna if (im_len)
1774a3667aaeSNaresh Kumar Inna csio_wr_copy_to_wrp(pld->vaddr, &wrp, wr_off, im_len);
1775a3667aaeSNaresh Kumar Inna else {
1776a3667aaeSNaresh Kumar Inna /* Program DSGL to dma payload */
1777d7990b0cSAnish Bhatt dsgl.cmd_nsge = htonl(ULPTX_CMD_V(ULP_TX_SC_DSGL) |
1778bdc590b9SHariprasad Shenai ULPTX_MORE_F | ULPTX_NSGE_V(1));
1779a3667aaeSNaresh Kumar Inna dsgl.len0 = cpu_to_be32(pld_len);
1780a3667aaeSNaresh Kumar Inna dsgl.addr0 = cpu_to_be64(pld->paddr);
1781a3667aaeSNaresh Kumar Inna csio_wr_copy_to_wrp(&dsgl, &wrp, ALIGN(wr_off, 8),
1782a3667aaeSNaresh Kumar Inna sizeof(struct ulptx_sgl));
1783a3667aaeSNaresh Kumar Inna }
1784a3667aaeSNaresh Kumar Inna
1785a3667aaeSNaresh Kumar Inna /* Issue work request to xmit ELS/CT req to FW */
1786a3667aaeSNaresh Kumar Inna csio_wr_issue(mgmtm->hw, mgmtm->eq_idx, false);
1787a3667aaeSNaresh Kumar Inna return ret;
1788a3667aaeSNaresh Kumar Inna }
1789a3667aaeSNaresh Kumar Inna
1790a3667aaeSNaresh Kumar Inna /*
1791a3667aaeSNaresh Kumar Inna * csio_ln_mgmt_submit_req - Submit FCOE Mgmt request.
1792a3667aaeSNaresh Kumar Inna * @io_req - IO Request
1793a3667aaeSNaresh Kumar Inna * @io_cbfn - Completion handler.
1794a3667aaeSNaresh Kumar Inna * @req_type - ELS or CT request type
1795a3667aaeSNaresh Kumar Inna * @pld - Dma Payload buffer
1796a3667aaeSNaresh Kumar Inna * @pld_len - Payload len
1797a3667aaeSNaresh Kumar Inna *
1798a3667aaeSNaresh Kumar Inna *
1799a3667aaeSNaresh Kumar Inna * This API used submit managment ELS/CT request.
1800a3667aaeSNaresh Kumar Inna * This called with hw lock held
1801a3667aaeSNaresh Kumar Inna * Returns: 0 - on success
1802a3667aaeSNaresh Kumar Inna * -ENOMEM - on error.
1803a3667aaeSNaresh Kumar Inna */
1804a3667aaeSNaresh Kumar Inna static int
csio_ln_mgmt_submit_req(struct csio_ioreq * io_req,void (* io_cbfn)(struct csio_hw *,struct csio_ioreq *),enum fcoe_cmn_type req_type,struct csio_dma_buf * pld,uint32_t pld_len)1805a3667aaeSNaresh Kumar Inna csio_ln_mgmt_submit_req(struct csio_ioreq *io_req,
1806a3667aaeSNaresh Kumar Inna void (*io_cbfn) (struct csio_hw *, struct csio_ioreq *),
1807a3667aaeSNaresh Kumar Inna enum fcoe_cmn_type req_type, struct csio_dma_buf *pld,
1808a3667aaeSNaresh Kumar Inna uint32_t pld_len)
1809a3667aaeSNaresh Kumar Inna {
1810a3667aaeSNaresh Kumar Inna struct csio_hw *hw = csio_lnode_to_hw(io_req->lnode);
1811a3667aaeSNaresh Kumar Inna struct csio_mgmtm *mgmtm = csio_hw_to_mgmtm(hw);
1812a3667aaeSNaresh Kumar Inna int rv;
1813a3667aaeSNaresh Kumar Inna
181442c335f7SKees Cook BUG_ON(pld_len > pld->len);
181542c335f7SKees Cook
1816a3667aaeSNaresh Kumar Inna io_req->io_cbfn = io_cbfn; /* Upper layer callback handler */
1817a3667aaeSNaresh Kumar Inna io_req->fw_handle = (uintptr_t) (io_req);
1818a3667aaeSNaresh Kumar Inna io_req->eq_idx = mgmtm->eq_idx;
1819a3667aaeSNaresh Kumar Inna io_req->iq_idx = mgmtm->iq_idx;
1820a3667aaeSNaresh Kumar Inna
1821a3667aaeSNaresh Kumar Inna rv = csio_ln_mgmt_submit_wr(mgmtm, io_req, req_type, pld, pld_len);
1822a3667aaeSNaresh Kumar Inna if (rv == 0) {
1823a3667aaeSNaresh Kumar Inna list_add_tail(&io_req->sm.sm_list, &mgmtm->active_q);
1824a3667aaeSNaresh Kumar Inna mgmtm->stats.n_active++;
1825a3667aaeSNaresh Kumar Inna }
1826a3667aaeSNaresh Kumar Inna return rv;
1827a3667aaeSNaresh Kumar Inna }
1828a3667aaeSNaresh Kumar Inna
1829a3667aaeSNaresh Kumar Inna /*
1830a3667aaeSNaresh Kumar Inna * csio_ln_fdmi_init - FDMI Init entry point.
1831a3667aaeSNaresh Kumar Inna * @ln: lnode
1832a3667aaeSNaresh Kumar Inna */
1833a3667aaeSNaresh Kumar Inna static int
csio_ln_fdmi_init(struct csio_lnode * ln)1834a3667aaeSNaresh Kumar Inna csio_ln_fdmi_init(struct csio_lnode *ln)
1835a3667aaeSNaresh Kumar Inna {
1836a3667aaeSNaresh Kumar Inna struct csio_hw *hw = csio_lnode_to_hw(ln);
1837a3667aaeSNaresh Kumar Inna struct csio_dma_buf *dma_buf;
1838a3667aaeSNaresh Kumar Inna
1839a3667aaeSNaresh Kumar Inna /* Allocate MGMT request required for FDMI */
1840a3667aaeSNaresh Kumar Inna ln->mgmt_req = kzalloc(sizeof(struct csio_ioreq), GFP_KERNEL);
1841a3667aaeSNaresh Kumar Inna if (!ln->mgmt_req) {
1842a3667aaeSNaresh Kumar Inna csio_ln_err(ln, "Failed to alloc ioreq for FDMI\n");
1843a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_err_nomem);
1844a3667aaeSNaresh Kumar Inna return -ENOMEM;
1845a3667aaeSNaresh Kumar Inna }
1846a3667aaeSNaresh Kumar Inna
1847a3667aaeSNaresh Kumar Inna /* Allocate Dma buffers for FDMI response Payload */
1848a3667aaeSNaresh Kumar Inna dma_buf = &ln->mgmt_req->dma_buf;
1849a3667aaeSNaresh Kumar Inna dma_buf->len = 2048;
1850c22b332dSChristoph Hellwig dma_buf->vaddr = dma_alloc_coherent(&hw->pdev->dev, dma_buf->len,
1851c22b332dSChristoph Hellwig &dma_buf->paddr, GFP_KERNEL);
1852a3667aaeSNaresh Kumar Inna if (!dma_buf->vaddr) {
1853a3667aaeSNaresh Kumar Inna csio_err(hw, "Failed to alloc DMA buffer for FDMI!\n");
1854a3667aaeSNaresh Kumar Inna kfree(ln->mgmt_req);
1855a3667aaeSNaresh Kumar Inna ln->mgmt_req = NULL;
1856a3667aaeSNaresh Kumar Inna return -ENOMEM;
1857a3667aaeSNaresh Kumar Inna }
1858a3667aaeSNaresh Kumar Inna
1859a3667aaeSNaresh Kumar Inna ln->flags |= CSIO_LNF_FDMI_ENABLE;
1860a3667aaeSNaresh Kumar Inna return 0;
1861a3667aaeSNaresh Kumar Inna }
1862a3667aaeSNaresh Kumar Inna
1863a3667aaeSNaresh Kumar Inna /*
1864a3667aaeSNaresh Kumar Inna * csio_ln_fdmi_exit - FDMI exit entry point.
1865a3667aaeSNaresh Kumar Inna * @ln: lnode
1866a3667aaeSNaresh Kumar Inna */
1867a3667aaeSNaresh Kumar Inna static int
csio_ln_fdmi_exit(struct csio_lnode * ln)1868a3667aaeSNaresh Kumar Inna csio_ln_fdmi_exit(struct csio_lnode *ln)
1869a3667aaeSNaresh Kumar Inna {
1870a3667aaeSNaresh Kumar Inna struct csio_dma_buf *dma_buf;
1871a3667aaeSNaresh Kumar Inna struct csio_hw *hw = csio_lnode_to_hw(ln);
1872a3667aaeSNaresh Kumar Inna
1873a3667aaeSNaresh Kumar Inna if (!ln->mgmt_req)
1874a3667aaeSNaresh Kumar Inna return 0;
1875a3667aaeSNaresh Kumar Inna
1876a3667aaeSNaresh Kumar Inna dma_buf = &ln->mgmt_req->dma_buf;
1877a3667aaeSNaresh Kumar Inna if (dma_buf->vaddr)
1878c22b332dSChristoph Hellwig dma_free_coherent(&hw->pdev->dev, dma_buf->len, dma_buf->vaddr,
1879a3667aaeSNaresh Kumar Inna dma_buf->paddr);
1880a3667aaeSNaresh Kumar Inna
1881a3667aaeSNaresh Kumar Inna kfree(ln->mgmt_req);
1882a3667aaeSNaresh Kumar Inna return 0;
1883a3667aaeSNaresh Kumar Inna }
1884a3667aaeSNaresh Kumar Inna
1885a3667aaeSNaresh Kumar Inna int
csio_scan_done(struct csio_lnode * ln,unsigned long ticks,unsigned long time,unsigned long max_scan_ticks,unsigned long delta_scan_ticks)1886a3667aaeSNaresh Kumar Inna csio_scan_done(struct csio_lnode *ln, unsigned long ticks,
1887a3667aaeSNaresh Kumar Inna unsigned long time, unsigned long max_scan_ticks,
1888a3667aaeSNaresh Kumar Inna unsigned long delta_scan_ticks)
1889a3667aaeSNaresh Kumar Inna {
1890a3667aaeSNaresh Kumar Inna int rv = 0;
1891a3667aaeSNaresh Kumar Inna
1892a3667aaeSNaresh Kumar Inna if (time >= max_scan_ticks)
1893a3667aaeSNaresh Kumar Inna return 1;
1894a3667aaeSNaresh Kumar Inna
1895a3667aaeSNaresh Kumar Inna if (!ln->tgt_scan_tick)
1896a3667aaeSNaresh Kumar Inna ln->tgt_scan_tick = ticks;
1897a3667aaeSNaresh Kumar Inna
1898a3667aaeSNaresh Kumar Inna if (((ticks - ln->tgt_scan_tick) >= delta_scan_ticks)) {
1899a3667aaeSNaresh Kumar Inna if (!ln->last_scan_ntgts)
1900a3667aaeSNaresh Kumar Inna ln->last_scan_ntgts = ln->n_scsi_tgts;
1901a3667aaeSNaresh Kumar Inna else {
1902a3667aaeSNaresh Kumar Inna if (ln->last_scan_ntgts == ln->n_scsi_tgts)
1903a3667aaeSNaresh Kumar Inna return 1;
1904a3667aaeSNaresh Kumar Inna
1905a3667aaeSNaresh Kumar Inna ln->last_scan_ntgts = ln->n_scsi_tgts;
1906a3667aaeSNaresh Kumar Inna }
1907a3667aaeSNaresh Kumar Inna ln->tgt_scan_tick = ticks;
1908a3667aaeSNaresh Kumar Inna }
1909a3667aaeSNaresh Kumar Inna return rv;
1910a3667aaeSNaresh Kumar Inna }
1911a3667aaeSNaresh Kumar Inna
1912a3667aaeSNaresh Kumar Inna /*
1913a3667aaeSNaresh Kumar Inna * csio_notify_lnodes:
1914a3667aaeSNaresh Kumar Inna * @hw: HW module
1915a3667aaeSNaresh Kumar Inna * @note: Notification
1916a3667aaeSNaresh Kumar Inna *
1917a3667aaeSNaresh Kumar Inna * Called from the HW SM to fan out notifications to the
1918a3667aaeSNaresh Kumar Inna * Lnode SM. Since the HW SM is entered with lock held,
1919a3667aaeSNaresh Kumar Inna * there is no need to hold locks here.
1920a3667aaeSNaresh Kumar Inna *
1921a3667aaeSNaresh Kumar Inna */
1922a3667aaeSNaresh Kumar Inna void
csio_notify_lnodes(struct csio_hw * hw,enum csio_ln_notify note)1923a3667aaeSNaresh Kumar Inna csio_notify_lnodes(struct csio_hw *hw, enum csio_ln_notify note)
1924a3667aaeSNaresh Kumar Inna {
1925a3667aaeSNaresh Kumar Inna struct list_head *tmp;
1926a3667aaeSNaresh Kumar Inna struct csio_lnode *ln;
1927a3667aaeSNaresh Kumar Inna
1928a3667aaeSNaresh Kumar Inna csio_dbg(hw, "Notifying all nodes of event %d\n", note);
1929a3667aaeSNaresh Kumar Inna
1930a3667aaeSNaresh Kumar Inna /* Traverse children lnodes list and send evt */
1931a3667aaeSNaresh Kumar Inna list_for_each(tmp, &hw->sln_head) {
1932a3667aaeSNaresh Kumar Inna ln = (struct csio_lnode *) tmp;
1933a3667aaeSNaresh Kumar Inna
1934a3667aaeSNaresh Kumar Inna switch (note) {
1935a3667aaeSNaresh Kumar Inna case CSIO_LN_NOTIFY_HWREADY:
1936a3667aaeSNaresh Kumar Inna csio_lnode_start(ln);
1937a3667aaeSNaresh Kumar Inna break;
1938a3667aaeSNaresh Kumar Inna
1939a3667aaeSNaresh Kumar Inna case CSIO_LN_NOTIFY_HWRESET:
1940a3667aaeSNaresh Kumar Inna case CSIO_LN_NOTIFY_HWREMOVE:
1941a3667aaeSNaresh Kumar Inna csio_lnode_close(ln);
1942a3667aaeSNaresh Kumar Inna break;
1943a3667aaeSNaresh Kumar Inna
1944a3667aaeSNaresh Kumar Inna case CSIO_LN_NOTIFY_HWSTOP:
1945a3667aaeSNaresh Kumar Inna csio_lnode_stop(ln);
1946a3667aaeSNaresh Kumar Inna break;
1947a3667aaeSNaresh Kumar Inna
1948a3667aaeSNaresh Kumar Inna default:
1949a3667aaeSNaresh Kumar Inna break;
1950a3667aaeSNaresh Kumar Inna
1951a3667aaeSNaresh Kumar Inna }
1952a3667aaeSNaresh Kumar Inna }
1953a3667aaeSNaresh Kumar Inna }
1954a3667aaeSNaresh Kumar Inna
1955a3667aaeSNaresh Kumar Inna /*
1956a3667aaeSNaresh Kumar Inna * csio_disable_lnodes:
1957a3667aaeSNaresh Kumar Inna * @hw: HW module
1958a3667aaeSNaresh Kumar Inna * @portid:port id
1959a3667aaeSNaresh Kumar Inna * @disable: disable/enable flag.
1960a3667aaeSNaresh Kumar Inna * If disable=1, disables all lnode hosted on given physical port.
1961a3667aaeSNaresh Kumar Inna * otherwise enables all the lnodes on given phsysical port.
1962a3667aaeSNaresh Kumar Inna * This routine need to called with hw lock held.
1963a3667aaeSNaresh Kumar Inna */
1964a3667aaeSNaresh Kumar Inna void
csio_disable_lnodes(struct csio_hw * hw,uint8_t portid,bool disable)1965a3667aaeSNaresh Kumar Inna csio_disable_lnodes(struct csio_hw *hw, uint8_t portid, bool disable)
1966a3667aaeSNaresh Kumar Inna {
1967a3667aaeSNaresh Kumar Inna struct list_head *tmp;
1968a3667aaeSNaresh Kumar Inna struct csio_lnode *ln;
1969a3667aaeSNaresh Kumar Inna
1970a3667aaeSNaresh Kumar Inna csio_dbg(hw, "Notifying event to all nodes of port:%d\n", portid);
1971a3667aaeSNaresh Kumar Inna
1972a3667aaeSNaresh Kumar Inna /* Traverse sibling lnodes list and send evt */
1973a3667aaeSNaresh Kumar Inna list_for_each(tmp, &hw->sln_head) {
1974a3667aaeSNaresh Kumar Inna ln = (struct csio_lnode *) tmp;
1975a3667aaeSNaresh Kumar Inna if (ln->portid != portid)
1976a3667aaeSNaresh Kumar Inna continue;
1977a3667aaeSNaresh Kumar Inna
1978a3667aaeSNaresh Kumar Inna if (disable)
1979a3667aaeSNaresh Kumar Inna csio_lnode_stop(ln);
1980a3667aaeSNaresh Kumar Inna else
1981a3667aaeSNaresh Kumar Inna csio_lnode_start(ln);
1982a3667aaeSNaresh Kumar Inna }
1983a3667aaeSNaresh Kumar Inna }
1984a3667aaeSNaresh Kumar Inna
1985a3667aaeSNaresh Kumar Inna /*
1986a3667aaeSNaresh Kumar Inna * csio_ln_init - Initialize an lnode.
1987a3667aaeSNaresh Kumar Inna * @ln: lnode
1988a3667aaeSNaresh Kumar Inna *
1989a3667aaeSNaresh Kumar Inna */
1990a3667aaeSNaresh Kumar Inna static int
csio_ln_init(struct csio_lnode * ln)1991a3667aaeSNaresh Kumar Inna csio_ln_init(struct csio_lnode *ln)
1992a3667aaeSNaresh Kumar Inna {
1993a3667aaeSNaresh Kumar Inna int rv = -EINVAL;
199463f565aaSYueHaibing struct csio_lnode *pln;
1995a3667aaeSNaresh Kumar Inna struct csio_hw *hw = csio_lnode_to_hw(ln);
1996a3667aaeSNaresh Kumar Inna
1997a3667aaeSNaresh Kumar Inna csio_init_state(&ln->sm, csio_lns_uninit);
1998a3667aaeSNaresh Kumar Inna ln->vnp_flowid = CSIO_INVALID_IDX;
1999a3667aaeSNaresh Kumar Inna ln->fcf_flowid = CSIO_INVALID_IDX;
2000a3667aaeSNaresh Kumar Inna
2001a3667aaeSNaresh Kumar Inna if (csio_is_root_ln(ln)) {
2002a3667aaeSNaresh Kumar Inna
2003a3667aaeSNaresh Kumar Inna /* This is the lnode used during initialization */
2004a3667aaeSNaresh Kumar Inna
2005a3667aaeSNaresh Kumar Inna ln->fcfinfo = kzalloc(sizeof(struct csio_fcf_info), GFP_KERNEL);
2006a3667aaeSNaresh Kumar Inna if (!ln->fcfinfo) {
2007a3667aaeSNaresh Kumar Inna csio_ln_err(ln, "Failed to alloc FCF record\n");
2008a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_err_nomem);
2009a3667aaeSNaresh Kumar Inna goto err;
2010a3667aaeSNaresh Kumar Inna }
2011a3667aaeSNaresh Kumar Inna
2012a3667aaeSNaresh Kumar Inna INIT_LIST_HEAD(&ln->fcf_lsthead);
2013a3667aaeSNaresh Kumar Inna kref_init(&ln->fcfinfo->kref);
2014a3667aaeSNaresh Kumar Inna
2015a3667aaeSNaresh Kumar Inna if (csio_fdmi_enable && csio_ln_fdmi_init(ln))
2016a3667aaeSNaresh Kumar Inna goto err;
2017a3667aaeSNaresh Kumar Inna
2018a3667aaeSNaresh Kumar Inna } else { /* Either a non-root physical or a virtual lnode */
2019a3667aaeSNaresh Kumar Inna
2020a3667aaeSNaresh Kumar Inna /*
2021a3667aaeSNaresh Kumar Inna * THe rest is common for non-root physical and NPIV lnodes.
2022a3667aaeSNaresh Kumar Inna * Just get references to all other modules
2023a3667aaeSNaresh Kumar Inna */
2024a3667aaeSNaresh Kumar Inna
2025a3667aaeSNaresh Kumar Inna if (csio_is_npiv_ln(ln)) {
2026a3667aaeSNaresh Kumar Inna /* NPIV */
2027a3667aaeSNaresh Kumar Inna pln = csio_parent_lnode(ln);
2028a3667aaeSNaresh Kumar Inna kref_get(&pln->fcfinfo->kref);
2029a3667aaeSNaresh Kumar Inna ln->fcfinfo = pln->fcfinfo;
2030a3667aaeSNaresh Kumar Inna } else {
2031a3667aaeSNaresh Kumar Inna /* Another non-root physical lnode (FCF) */
2032a3667aaeSNaresh Kumar Inna ln->fcfinfo = kzalloc(sizeof(struct csio_fcf_info),
2033a3667aaeSNaresh Kumar Inna GFP_KERNEL);
2034a3667aaeSNaresh Kumar Inna if (!ln->fcfinfo) {
2035a3667aaeSNaresh Kumar Inna csio_ln_err(ln, "Failed to alloc FCF info\n");
2036a3667aaeSNaresh Kumar Inna CSIO_INC_STATS(hw, n_err_nomem);
2037a3667aaeSNaresh Kumar Inna goto err;
2038a3667aaeSNaresh Kumar Inna }
2039a3667aaeSNaresh Kumar Inna
2040a3667aaeSNaresh Kumar Inna kref_init(&ln->fcfinfo->kref);
2041a3667aaeSNaresh Kumar Inna
2042a3667aaeSNaresh Kumar Inna if (csio_fdmi_enable && csio_ln_fdmi_init(ln))
2043a3667aaeSNaresh Kumar Inna goto err;
2044a3667aaeSNaresh Kumar Inna }
2045a3667aaeSNaresh Kumar Inna
2046a3667aaeSNaresh Kumar Inna } /* if (!csio_is_root_ln(ln)) */
2047a3667aaeSNaresh Kumar Inna
2048a3667aaeSNaresh Kumar Inna return 0;
2049a3667aaeSNaresh Kumar Inna err:
2050a3667aaeSNaresh Kumar Inna return rv;
2051a3667aaeSNaresh Kumar Inna }
2052a3667aaeSNaresh Kumar Inna
2053a3667aaeSNaresh Kumar Inna static void
csio_ln_exit(struct csio_lnode * ln)2054a3667aaeSNaresh Kumar Inna csio_ln_exit(struct csio_lnode *ln)
2055a3667aaeSNaresh Kumar Inna {
2056a3667aaeSNaresh Kumar Inna struct csio_lnode *pln;
2057a3667aaeSNaresh Kumar Inna
2058a3667aaeSNaresh Kumar Inna csio_cleanup_rns(ln);
2059a3667aaeSNaresh Kumar Inna if (csio_is_npiv_ln(ln)) {
2060a3667aaeSNaresh Kumar Inna pln = csio_parent_lnode(ln);
2061a3667aaeSNaresh Kumar Inna kref_put(&pln->fcfinfo->kref, csio_free_fcfinfo);
2062a3667aaeSNaresh Kumar Inna } else {
2063a3667aaeSNaresh Kumar Inna kref_put(&ln->fcfinfo->kref, csio_free_fcfinfo);
2064a3667aaeSNaresh Kumar Inna if (csio_fdmi_enable)
2065a3667aaeSNaresh Kumar Inna csio_ln_fdmi_exit(ln);
2066a3667aaeSNaresh Kumar Inna }
2067a3667aaeSNaresh Kumar Inna ln->fcfinfo = NULL;
2068a3667aaeSNaresh Kumar Inna }
2069a3667aaeSNaresh Kumar Inna
2070fd4cdf64SLee Jones /*
2071a3667aaeSNaresh Kumar Inna * csio_lnode_init - Initialize the members of an lnode.
2072a3667aaeSNaresh Kumar Inna * @ln: lnode
2073a3667aaeSNaresh Kumar Inna */
2074a3667aaeSNaresh Kumar Inna int
csio_lnode_init(struct csio_lnode * ln,struct csio_hw * hw,struct csio_lnode * pln)2075a3667aaeSNaresh Kumar Inna csio_lnode_init(struct csio_lnode *ln, struct csio_hw *hw,
2076a3667aaeSNaresh Kumar Inna struct csio_lnode *pln)
2077a3667aaeSNaresh Kumar Inna {
2078a3667aaeSNaresh Kumar Inna int rv = -EINVAL;
2079a3667aaeSNaresh Kumar Inna
2080a3667aaeSNaresh Kumar Inna /* Link this lnode to hw */
2081a3667aaeSNaresh Kumar Inna csio_lnode_to_hw(ln) = hw;
2082a3667aaeSNaresh Kumar Inna
2083a3667aaeSNaresh Kumar Inna /* Link child to parent if child lnode */
2084a3667aaeSNaresh Kumar Inna if (pln)
2085a3667aaeSNaresh Kumar Inna ln->pln = pln;
2086a3667aaeSNaresh Kumar Inna else
2087a3667aaeSNaresh Kumar Inna ln->pln = NULL;
2088a3667aaeSNaresh Kumar Inna
2089a3667aaeSNaresh Kumar Inna /* Initialize scsi_tgt and timers to zero */
2090a3667aaeSNaresh Kumar Inna ln->n_scsi_tgts = 0;
2091a3667aaeSNaresh Kumar Inna ln->last_scan_ntgts = 0;
2092a3667aaeSNaresh Kumar Inna ln->tgt_scan_tick = 0;
2093a3667aaeSNaresh Kumar Inna
2094a3667aaeSNaresh Kumar Inna /* Initialize rnode list */
2095a3667aaeSNaresh Kumar Inna INIT_LIST_HEAD(&ln->rnhead);
2096a3667aaeSNaresh Kumar Inna INIT_LIST_HEAD(&ln->cln_head);
2097a3667aaeSNaresh Kumar Inna
2098a3667aaeSNaresh Kumar Inna /* Initialize log level for debug */
2099a3667aaeSNaresh Kumar Inna ln->params.log_level = hw->params.log_level;
2100a3667aaeSNaresh Kumar Inna
2101a3667aaeSNaresh Kumar Inna if (csio_ln_init(ln))
2102a3667aaeSNaresh Kumar Inna goto err;
2103a3667aaeSNaresh Kumar Inna
2104a3667aaeSNaresh Kumar Inna /* Add lnode to list of sibling or children lnodes */
2105a3667aaeSNaresh Kumar Inna spin_lock_irq(&hw->lock);
2106a3667aaeSNaresh Kumar Inna list_add_tail(&ln->sm.sm_list, pln ? &pln->cln_head : &hw->sln_head);
2107a3667aaeSNaresh Kumar Inna if (pln)
2108a3667aaeSNaresh Kumar Inna pln->num_vports++;
2109a3667aaeSNaresh Kumar Inna spin_unlock_irq(&hw->lock);
2110a3667aaeSNaresh Kumar Inna
2111a3667aaeSNaresh Kumar Inna hw->num_lns++;
2112a3667aaeSNaresh Kumar Inna
2113a3667aaeSNaresh Kumar Inna return 0;
2114a3667aaeSNaresh Kumar Inna err:
2115a3667aaeSNaresh Kumar Inna csio_lnode_to_hw(ln) = NULL;
2116a3667aaeSNaresh Kumar Inna return rv;
2117a3667aaeSNaresh Kumar Inna }
2118a3667aaeSNaresh Kumar Inna
2119a3667aaeSNaresh Kumar Inna /**
2120a3667aaeSNaresh Kumar Inna * csio_lnode_exit - De-instantiate an lnode.
2121a3667aaeSNaresh Kumar Inna * @ln: lnode
2122a3667aaeSNaresh Kumar Inna *
2123a3667aaeSNaresh Kumar Inna */
2124a3667aaeSNaresh Kumar Inna void
csio_lnode_exit(struct csio_lnode * ln)2125a3667aaeSNaresh Kumar Inna csio_lnode_exit(struct csio_lnode *ln)
2126a3667aaeSNaresh Kumar Inna {
2127a3667aaeSNaresh Kumar Inna struct csio_hw *hw = csio_lnode_to_hw(ln);
2128a3667aaeSNaresh Kumar Inna
2129a3667aaeSNaresh Kumar Inna csio_ln_exit(ln);
2130a3667aaeSNaresh Kumar Inna
2131a3667aaeSNaresh Kumar Inna /* Remove this lnode from hw->sln_head */
2132a3667aaeSNaresh Kumar Inna spin_lock_irq(&hw->lock);
2133a3667aaeSNaresh Kumar Inna
2134a3667aaeSNaresh Kumar Inna list_del_init(&ln->sm.sm_list);
2135a3667aaeSNaresh Kumar Inna
2136a3667aaeSNaresh Kumar Inna /* If it is children lnode, decrement the
2137a3667aaeSNaresh Kumar Inna * counter in its parent lnode
2138a3667aaeSNaresh Kumar Inna */
2139a3667aaeSNaresh Kumar Inna if (ln->pln)
2140a3667aaeSNaresh Kumar Inna ln->pln->num_vports--;
2141a3667aaeSNaresh Kumar Inna
2142a3667aaeSNaresh Kumar Inna /* Update root lnode pointer */
2143a3667aaeSNaresh Kumar Inna if (list_empty(&hw->sln_head))
2144a3667aaeSNaresh Kumar Inna hw->rln = NULL;
2145a3667aaeSNaresh Kumar Inna else
2146a3667aaeSNaresh Kumar Inna hw->rln = (struct csio_lnode *)csio_list_next(&hw->sln_head);
2147a3667aaeSNaresh Kumar Inna
2148a3667aaeSNaresh Kumar Inna spin_unlock_irq(&hw->lock);
2149a3667aaeSNaresh Kumar Inna
2150a3667aaeSNaresh Kumar Inna csio_lnode_to_hw(ln) = NULL;
2151a3667aaeSNaresh Kumar Inna hw->num_lns--;
2152a3667aaeSNaresh Kumar Inna }
2153