1098585aaSKaran Tilak Kumar // SPDX-License-Identifier: GPL-2.0-only
2098585aaSKaran Tilak Kumar /*
3098585aaSKaran Tilak Kumar * Copyright 2008 Cisco Systems, Inc. All rights reserved.
4098585aaSKaran Tilak Kumar * Copyright 2007 Nuova Systems, Inc. All rights reserved.
5098585aaSKaran Tilak Kumar */
6098585aaSKaran Tilak Kumar #include "fnic.h"
7098585aaSKaran Tilak Kumar #include "fip.h"
8098585aaSKaran Tilak Kumar #include <linux/etherdevice.h>
9098585aaSKaran Tilak Kumar
10098585aaSKaran Tilak Kumar #define FIP_FNIC_RESET_WAIT_COUNT 15
11098585aaSKaran Tilak Kumar
12098585aaSKaran Tilak Kumar /**
13098585aaSKaran Tilak Kumar * fnic_fcoe_reset_vlans - Free up the list of discovered vlans
14098585aaSKaran Tilak Kumar * @fnic: Handle to fnic driver instance
15098585aaSKaran Tilak Kumar */
fnic_fcoe_reset_vlans(struct fnic * fnic)16098585aaSKaran Tilak Kumar void fnic_fcoe_reset_vlans(struct fnic *fnic)
17098585aaSKaran Tilak Kumar {
18098585aaSKaran Tilak Kumar unsigned long flags;
19098585aaSKaran Tilak Kumar struct fcoe_vlan *vlan, *next;
20098585aaSKaran Tilak Kumar
21098585aaSKaran Tilak Kumar spin_lock_irqsave(&fnic->vlans_lock, flags);
22098585aaSKaran Tilak Kumar if (!list_empty(&fnic->vlan_list)) {
23098585aaSKaran Tilak Kumar list_for_each_entry_safe(vlan, next, &fnic->vlan_list, list) {
24098585aaSKaran Tilak Kumar list_del(&vlan->list);
25098585aaSKaran Tilak Kumar kfree(vlan);
26098585aaSKaran Tilak Kumar }
27098585aaSKaran Tilak Kumar }
28098585aaSKaran Tilak Kumar
29098585aaSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->vlans_lock, flags);
307e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
31098585aaSKaran Tilak Kumar "Reset vlan complete\n");
32098585aaSKaran Tilak Kumar }
33098585aaSKaran Tilak Kumar
34098585aaSKaran Tilak Kumar /**
35098585aaSKaran Tilak Kumar * fnic_fcoe_send_vlan_req - Send FIP vlan request to all FCFs MAC
36098585aaSKaran Tilak Kumar * @fnic: Handle to fnic driver instance
37098585aaSKaran Tilak Kumar */
fnic_fcoe_send_vlan_req(struct fnic * fnic)38098585aaSKaran Tilak Kumar void fnic_fcoe_send_vlan_req(struct fnic *fnic)
39098585aaSKaran Tilak Kumar {
40098585aaSKaran Tilak Kumar uint8_t *frame;
41098585aaSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport;
42098585aaSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats;
43098585aaSKaran Tilak Kumar u64 vlan_tov;
44098585aaSKaran Tilak Kumar struct fip_vlan_req *pvlan_req;
45098585aaSKaran Tilak Kumar uint16_t frame_size = sizeof(struct fip_vlan_req);
46098585aaSKaran Tilak Kumar
47098585aaSKaran Tilak Kumar frame = fdls_alloc_frame(iport);
48098585aaSKaran Tilak Kumar if (frame == NULL) {
497e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
50098585aaSKaran Tilak Kumar "Failed to allocate frame to send VLAN req");
51098585aaSKaran Tilak Kumar return;
52098585aaSKaran Tilak Kumar }
53098585aaSKaran Tilak Kumar
54098585aaSKaran Tilak Kumar fnic_fcoe_reset_vlans(fnic);
55098585aaSKaran Tilak Kumar
56098585aaSKaran Tilak Kumar fnic->set_vlan(fnic, 0);
577e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
58098585aaSKaran Tilak Kumar "set vlan done\n");
59098585aaSKaran Tilak Kumar
607e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
61098585aaSKaran Tilak Kumar "got MAC 0x%x:%x:%x:%x:%x:%x\n", iport->hwmac[0],
62098585aaSKaran Tilak Kumar iport->hwmac[1], iport->hwmac[2], iport->hwmac[3],
63098585aaSKaran Tilak Kumar iport->hwmac[4], iport->hwmac[5]);
64098585aaSKaran Tilak Kumar
65098585aaSKaran Tilak Kumar pvlan_req = (struct fip_vlan_req *) frame;
66098585aaSKaran Tilak Kumar *pvlan_req = (struct fip_vlan_req) {
67098585aaSKaran Tilak Kumar .eth = {.h_dest = FCOE_ALL_FCFS_MAC,
68098585aaSKaran Tilak Kumar .h_proto = cpu_to_be16(ETH_P_FIP)},
69098585aaSKaran Tilak Kumar .fip = {.fip_ver = FIP_VER_ENCAPS(FIP_VER),
70098585aaSKaran Tilak Kumar .fip_op = cpu_to_be16(FIP_OP_VLAN),
71098585aaSKaran Tilak Kumar .fip_subcode = FIP_SC_REQ,
72098585aaSKaran Tilak Kumar .fip_dl_len = cpu_to_be16(FIP_VLAN_REQ_LEN)},
73098585aaSKaran Tilak Kumar .mac_desc = {.fd_desc = {.fip_dtype = FIP_DT_MAC,
74098585aaSKaran Tilak Kumar .fip_dlen = 2}}
75098585aaSKaran Tilak Kumar };
76098585aaSKaran Tilak Kumar
77098585aaSKaran Tilak Kumar memcpy(pvlan_req->eth.h_source, iport->hwmac, ETH_ALEN);
78098585aaSKaran Tilak Kumar memcpy(pvlan_req->mac_desc.fd_mac, iport->hwmac, ETH_ALEN);
79098585aaSKaran Tilak Kumar
80098585aaSKaran Tilak Kumar atomic64_inc(&fnic_stats->vlan_stats.vlan_disc_reqs);
81098585aaSKaran Tilak Kumar
82098585aaSKaran Tilak Kumar iport->fip.state = FDLS_FIP_VLAN_DISCOVERY_STARTED;
83098585aaSKaran Tilak Kumar
847e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
85098585aaSKaran Tilak Kumar "Send VLAN req\n");
86098585aaSKaran Tilak Kumar fnic_send_fip_frame(iport, frame, frame_size);
87098585aaSKaran Tilak Kumar
88098585aaSKaran Tilak Kumar vlan_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_FIPVLAN_TOV);
89098585aaSKaran Tilak Kumar mod_timer(&fnic->retry_fip_timer, round_jiffies(vlan_tov));
907e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
91098585aaSKaran Tilak Kumar "fip timer set\n");
92098585aaSKaran Tilak Kumar }
93098585aaSKaran Tilak Kumar
94098585aaSKaran Tilak Kumar /**
95098585aaSKaran Tilak Kumar * fnic_fcoe_process_vlan_resp - Processes the vlan response from one FCF and
96098585aaSKaran Tilak Kumar * populates VLAN list.
97098585aaSKaran Tilak Kumar * @fnic: Handle to fnic driver instance
98098585aaSKaran Tilak Kumar * @fiph: Received FIP frame
99098585aaSKaran Tilak Kumar *
100098585aaSKaran Tilak Kumar * Will wait for responses from multiple FCFs until timeout.
101098585aaSKaran Tilak Kumar */
fnic_fcoe_process_vlan_resp(struct fnic * fnic,struct fip_header * fiph)102098585aaSKaran Tilak Kumar void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct fip_header *fiph)
103098585aaSKaran Tilak Kumar {
104098585aaSKaran Tilak Kumar struct fip_vlan_notif *vlan_notif = (struct fip_vlan_notif *)fiph;
105098585aaSKaran Tilak Kumar
106098585aaSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats;
107098585aaSKaran Tilak Kumar u16 vid;
108098585aaSKaran Tilak Kumar int num_vlan = 0;
109098585aaSKaran Tilak Kumar int cur_desc, desc_len;
110098585aaSKaran Tilak Kumar struct fcoe_vlan *vlan;
111098585aaSKaran Tilak Kumar struct fip_vlan_desc *vlan_desc;
112098585aaSKaran Tilak Kumar unsigned long flags;
113098585aaSKaran Tilak Kumar
1147e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
115098585aaSKaran Tilak Kumar "fnic 0x%p got vlan resp\n", fnic);
116098585aaSKaran Tilak Kumar
117098585aaSKaran Tilak Kumar desc_len = be16_to_cpu(vlan_notif->fip.fip_dl_len);
1187e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
119098585aaSKaran Tilak Kumar "desc_len %d\n", desc_len);
120098585aaSKaran Tilak Kumar
121098585aaSKaran Tilak Kumar spin_lock_irqsave(&fnic->vlans_lock, flags);
122098585aaSKaran Tilak Kumar
123098585aaSKaran Tilak Kumar cur_desc = 0;
124098585aaSKaran Tilak Kumar while (desc_len > 0) {
125098585aaSKaran Tilak Kumar vlan_desc =
126098585aaSKaran Tilak Kumar (struct fip_vlan_desc *)(((char *)vlan_notif->vlans_desc)
127098585aaSKaran Tilak Kumar + cur_desc * 4);
128098585aaSKaran Tilak Kumar
129098585aaSKaran Tilak Kumar if (vlan_desc->fd_desc.fip_dtype == FIP_DT_VLAN) {
130098585aaSKaran Tilak Kumar if (vlan_desc->fd_desc.fip_dlen != 1) {
1317e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host,
132098585aaSKaran Tilak Kumar fnic->fnic_num,
133098585aaSKaran Tilak Kumar "Invalid descriptor length(%x) in VLan response\n",
134098585aaSKaran Tilak Kumar vlan_desc->fd_desc.fip_dlen);
135098585aaSKaran Tilak Kumar
136098585aaSKaran Tilak Kumar }
137098585aaSKaran Tilak Kumar num_vlan++;
138098585aaSKaran Tilak Kumar vid = be16_to_cpu(vlan_desc->fd_vlan);
1397e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host,
140098585aaSKaran Tilak Kumar fnic->fnic_num,
141098585aaSKaran Tilak Kumar "process_vlan_resp: FIP VLAN %d\n", vid);
142098585aaSKaran Tilak Kumar vlan = kzalloc(sizeof(*vlan), GFP_KERNEL);
143098585aaSKaran Tilak Kumar
144098585aaSKaran Tilak Kumar if (!vlan) {
145098585aaSKaran Tilak Kumar /* retry from timer */
1467e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host,
147098585aaSKaran Tilak Kumar fnic->fnic_num,
148098585aaSKaran Tilak Kumar "Mem Alloc failure\n");
149098585aaSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->vlans_lock,
150098585aaSKaran Tilak Kumar flags);
151098585aaSKaran Tilak Kumar goto out;
152098585aaSKaran Tilak Kumar }
153098585aaSKaran Tilak Kumar vlan->vid = vid & 0x0fff;
154098585aaSKaran Tilak Kumar vlan->state = FIP_VLAN_AVAIL;
155098585aaSKaran Tilak Kumar list_add_tail(&vlan->list, &fnic->vlan_list);
156098585aaSKaran Tilak Kumar break;
157*bab8551eSKaran Tilak Kumar }
1587e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host,
159098585aaSKaran Tilak Kumar fnic->fnic_num,
160098585aaSKaran Tilak Kumar "Invalid descriptor type(%x) in VLan response\n",
161098585aaSKaran Tilak Kumar vlan_desc->fd_desc.fip_dtype);
162098585aaSKaran Tilak Kumar /*
163098585aaSKaran Tilak Kumar * Note : received a type=2 descriptor here i.e. FIP
164098585aaSKaran Tilak Kumar * MAC Address Descriptor
165098585aaSKaran Tilak Kumar */
166098585aaSKaran Tilak Kumar cur_desc += vlan_desc->fd_desc.fip_dlen;
167098585aaSKaran Tilak Kumar desc_len -= vlan_desc->fd_desc.fip_dlen;
168098585aaSKaran Tilak Kumar }
169098585aaSKaran Tilak Kumar
170098585aaSKaran Tilak Kumar /* any VLAN descriptors present ? */
171098585aaSKaran Tilak Kumar if (num_vlan == 0) {
172098585aaSKaran Tilak Kumar atomic64_inc(&fnic_stats->vlan_stats.resp_withno_vlanID);
1737e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
174098585aaSKaran Tilak Kumar "fnic 0x%p No VLAN descriptors in FIP VLAN response\n",
175098585aaSKaran Tilak Kumar fnic);
176098585aaSKaran Tilak Kumar }
177098585aaSKaran Tilak Kumar
178098585aaSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->vlans_lock, flags);
179098585aaSKaran Tilak Kumar
180098585aaSKaran Tilak Kumar out:
181098585aaSKaran Tilak Kumar return;
182098585aaSKaran Tilak Kumar }
183098585aaSKaran Tilak Kumar
184098585aaSKaran Tilak Kumar /**
185098585aaSKaran Tilak Kumar * fnic_fcoe_start_fcf_discovery - Start FIP FCF discovery in a selected vlan
186098585aaSKaran Tilak Kumar * @fnic: Handle to fnic driver instance
187098585aaSKaran Tilak Kumar */
fnic_fcoe_start_fcf_discovery(struct fnic * fnic)188098585aaSKaran Tilak Kumar void fnic_fcoe_start_fcf_discovery(struct fnic *fnic)
189098585aaSKaran Tilak Kumar {
190098585aaSKaran Tilak Kumar uint8_t *frame;
191098585aaSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport;
192098585aaSKaran Tilak Kumar u64 fcs_tov;
193098585aaSKaran Tilak Kumar struct fip_discovery *pdisc_sol;
194098585aaSKaran Tilak Kumar uint16_t frame_size = sizeof(struct fip_discovery);
195098585aaSKaran Tilak Kumar
196098585aaSKaran Tilak Kumar frame = fdls_alloc_frame(iport);
197098585aaSKaran Tilak Kumar if (frame == NULL) {
1987e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
199098585aaSKaran Tilak Kumar "Failed to allocate frame to start FCF discovery");
200098585aaSKaran Tilak Kumar return;
201098585aaSKaran Tilak Kumar }
202098585aaSKaran Tilak Kumar
203098585aaSKaran Tilak Kumar memset(iport->selected_fcf.fcf_mac, 0, ETH_ALEN);
204098585aaSKaran Tilak Kumar
205098585aaSKaran Tilak Kumar pdisc_sol = (struct fip_discovery *) frame;
206098585aaSKaran Tilak Kumar *pdisc_sol = (struct fip_discovery) {
207098585aaSKaran Tilak Kumar .eth = {.h_dest = FCOE_ALL_FCFS_MAC,
208098585aaSKaran Tilak Kumar .h_proto = cpu_to_be16(ETH_P_FIP)},
209098585aaSKaran Tilak Kumar .fip = {
210098585aaSKaran Tilak Kumar .fip_ver = FIP_VER_ENCAPS(FIP_VER), .fip_op = cpu_to_be16(FIP_OP_DISC),
211098585aaSKaran Tilak Kumar .fip_subcode = FIP_SC_REQ, .fip_dl_len = cpu_to_be16(FIP_DISC_SOL_LEN),
212098585aaSKaran Tilak Kumar .fip_flags = cpu_to_be16(FIP_FL_FPMA)},
213098585aaSKaran Tilak Kumar .mac_desc = {.fd_desc = {.fip_dtype = FIP_DT_MAC, .fip_dlen = 2}},
214098585aaSKaran Tilak Kumar .name_desc = {.fd_desc = {.fip_dtype = FIP_DT_NAME, .fip_dlen = 3}},
215098585aaSKaran Tilak Kumar .fcoe_desc = {.fd_desc = {.fip_dtype = FIP_DT_FCOE_SIZE, .fip_dlen = 1},
216098585aaSKaran Tilak Kumar .fd_size = cpu_to_be16(FCOE_MAX_SIZE)}
217098585aaSKaran Tilak Kumar };
218098585aaSKaran Tilak Kumar
219098585aaSKaran Tilak Kumar memcpy(pdisc_sol->eth.h_source, iport->hwmac, ETH_ALEN);
220098585aaSKaran Tilak Kumar memcpy(pdisc_sol->mac_desc.fd_mac, iport->hwmac, ETH_ALEN);
221098585aaSKaran Tilak Kumar iport->selected_fcf.fcf_priority = 0xFF;
222098585aaSKaran Tilak Kumar
223098585aaSKaran Tilak Kumar FNIC_STD_SET_NODE_NAME(&pdisc_sol->name_desc.fd_wwn, iport->wwnn);
224098585aaSKaran Tilak Kumar
2257e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
226098585aaSKaran Tilak Kumar "Start FCF discovery\n");
227098585aaSKaran Tilak Kumar fnic_send_fip_frame(iport, frame, frame_size);
228098585aaSKaran Tilak Kumar
229098585aaSKaran Tilak Kumar iport->fip.state = FDLS_FIP_FCF_DISCOVERY_STARTED;
230098585aaSKaran Tilak Kumar
231098585aaSKaran Tilak Kumar fcs_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_FCS_TOV);
232098585aaSKaran Tilak Kumar mod_timer(&fnic->retry_fip_timer, round_jiffies(fcs_tov));
233098585aaSKaran Tilak Kumar }
234098585aaSKaran Tilak Kumar
235098585aaSKaran Tilak Kumar /**
236098585aaSKaran Tilak Kumar * fnic_fcoe_fip_discovery_resp - Processes FCF advertisements.
237098585aaSKaran Tilak Kumar * @fnic: Handle to fnic driver instance
238098585aaSKaran Tilak Kumar * @fiph: Received frame
239098585aaSKaran Tilak Kumar *
240098585aaSKaran Tilak Kumar * FCF advertisements can be:
241098585aaSKaran Tilak Kumar * solicited - Sent in response of a discover FCF FIP request
242098585aaSKaran Tilak Kumar * Store the information of the FCF with highest priority.
243098585aaSKaran Tilak Kumar * Wait until timeout in case of multiple FCFs.
244098585aaSKaran Tilak Kumar *
245098585aaSKaran Tilak Kumar * unsolicited - Sent periodically by the FCF for keep alive.
246098585aaSKaran Tilak Kumar * If FLOGI is in progress or completed and the advertisement is
247098585aaSKaran Tilak Kumar * received by our selected FCF, refresh the keep alive timer.
248098585aaSKaran Tilak Kumar */
fnic_fcoe_fip_discovery_resp(struct fnic * fnic,struct fip_header * fiph)249098585aaSKaran Tilak Kumar void fnic_fcoe_fip_discovery_resp(struct fnic *fnic, struct fip_header *fiph)
250098585aaSKaran Tilak Kumar {
251098585aaSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport;
252098585aaSKaran Tilak Kumar struct fip_disc_adv *disc_adv = (struct fip_disc_adv *)fiph;
253098585aaSKaran Tilak Kumar u64 fcs_ka_tov;
254098585aaSKaran Tilak Kumar u64 tov;
255098585aaSKaran Tilak Kumar int fka_has_changed;
256098585aaSKaran Tilak Kumar
257098585aaSKaran Tilak Kumar switch (iport->fip.state) {
258098585aaSKaran Tilak Kumar case FDLS_FIP_FCF_DISCOVERY_STARTED:
259098585aaSKaran Tilak Kumar if (be16_to_cpu(disc_adv->fip.fip_flags) & FIP_FL_SOL) {
2607e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host,
261098585aaSKaran Tilak Kumar fnic->fnic_num,
262098585aaSKaran Tilak Kumar "fnic 0x%p Solicited adv\n", fnic);
263098585aaSKaran Tilak Kumar
264098585aaSKaran Tilak Kumar if ((disc_adv->prio_desc.fd_pri <
265098585aaSKaran Tilak Kumar iport->selected_fcf.fcf_priority)
266098585aaSKaran Tilak Kumar && (be16_to_cpu(disc_adv->fip.fip_flags) & FIP_FL_AVAIL)) {
267098585aaSKaran Tilak Kumar
2687e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host,
269098585aaSKaran Tilak Kumar fnic->fnic_num,
270098585aaSKaran Tilak Kumar "fnic 0x%p FCF Available\n", fnic);
271098585aaSKaran Tilak Kumar memcpy(iport->selected_fcf.fcf_mac,
272098585aaSKaran Tilak Kumar disc_adv->mac_desc.fd_mac, ETH_ALEN);
273098585aaSKaran Tilak Kumar iport->selected_fcf.fcf_priority =
274098585aaSKaran Tilak Kumar disc_adv->prio_desc.fd_pri;
275098585aaSKaran Tilak Kumar iport->selected_fcf.fka_adv_period =
276098585aaSKaran Tilak Kumar be32_to_cpu(disc_adv->fka_adv_desc.fd_fka_period);
2777e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host,
278098585aaSKaran Tilak Kumar fnic->fnic_num, "adv time %d",
279098585aaSKaran Tilak Kumar iport->selected_fcf.fka_adv_period);
280098585aaSKaran Tilak Kumar iport->selected_fcf.ka_disabled =
281098585aaSKaran Tilak Kumar (disc_adv->fka_adv_desc.fd_flags & 1);
282098585aaSKaran Tilak Kumar }
283098585aaSKaran Tilak Kumar }
284098585aaSKaran Tilak Kumar break;
285098585aaSKaran Tilak Kumar case FDLS_FIP_FLOGI_STARTED:
286098585aaSKaran Tilak Kumar case FDLS_FIP_FLOGI_COMPLETE:
287098585aaSKaran Tilak Kumar if (!(be16_to_cpu(disc_adv->fip.fip_flags) & FIP_FL_SOL)) {
288098585aaSKaran Tilak Kumar /* same fcf */
289098585aaSKaran Tilak Kumar if (memcmp
290098585aaSKaran Tilak Kumar (iport->selected_fcf.fcf_mac,
291098585aaSKaran Tilak Kumar disc_adv->mac_desc.fd_mac, ETH_ALEN) == 0) {
292098585aaSKaran Tilak Kumar if (iport->selected_fcf.fka_adv_period !=
293098585aaSKaran Tilak Kumar be32_to_cpu(disc_adv->fka_adv_desc.fd_fka_period)) {
294098585aaSKaran Tilak Kumar iport->selected_fcf.fka_adv_period =
295098585aaSKaran Tilak Kumar be32_to_cpu(disc_adv->fka_adv_desc.fd_fka_period);
296098585aaSKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO,
2977e6886b7SKaran Tilak Kumar fnic->host,
298098585aaSKaran Tilak Kumar fnic->fnic_num,
299098585aaSKaran Tilak Kumar "change fka to %d",
300098585aaSKaran Tilak Kumar iport->selected_fcf.fka_adv_period);
301098585aaSKaran Tilak Kumar }
302098585aaSKaran Tilak Kumar
303098585aaSKaran Tilak Kumar fka_has_changed =
304098585aaSKaran Tilak Kumar (iport->selected_fcf.ka_disabled == 1)
305098585aaSKaran Tilak Kumar && ((disc_adv->fka_adv_desc.fd_flags & 1) ==
306098585aaSKaran Tilak Kumar 0);
307098585aaSKaran Tilak Kumar
308098585aaSKaran Tilak Kumar iport->selected_fcf.ka_disabled =
309098585aaSKaran Tilak Kumar (disc_adv->fka_adv_desc.fd_flags & 1);
310098585aaSKaran Tilak Kumar if (!((iport->selected_fcf.ka_disabled)
311098585aaSKaran Tilak Kumar || (iport->selected_fcf.fka_adv_period ==
312098585aaSKaran Tilak Kumar 0))) {
313098585aaSKaran Tilak Kumar
314098585aaSKaran Tilak Kumar fcs_ka_tov = jiffies
315098585aaSKaran Tilak Kumar + 3
316098585aaSKaran Tilak Kumar *
317098585aaSKaran Tilak Kumar msecs_to_jiffies(iport->selected_fcf.fka_adv_period);
318098585aaSKaran Tilak Kumar mod_timer(&fnic->fcs_ka_timer,
319098585aaSKaran Tilak Kumar round_jiffies(fcs_ka_tov));
320098585aaSKaran Tilak Kumar } else {
321098585aaSKaran Tilak Kumar if (timer_pending(&fnic->fcs_ka_timer))
322098585aaSKaran Tilak Kumar del_timer_sync(&fnic->fcs_ka_timer);
323098585aaSKaran Tilak Kumar }
324098585aaSKaran Tilak Kumar
325098585aaSKaran Tilak Kumar if (fka_has_changed) {
326098585aaSKaran Tilak Kumar if (iport->selected_fcf.fka_adv_period != 0) {
327098585aaSKaran Tilak Kumar tov =
328098585aaSKaran Tilak Kumar jiffies +
329098585aaSKaran Tilak Kumar msecs_to_jiffies(
330098585aaSKaran Tilak Kumar iport->selected_fcf.fka_adv_period);
331098585aaSKaran Tilak Kumar mod_timer(&fnic->enode_ka_timer,
332098585aaSKaran Tilak Kumar round_jiffies(tov));
333098585aaSKaran Tilak Kumar
334098585aaSKaran Tilak Kumar tov =
335098585aaSKaran Tilak Kumar jiffies +
336098585aaSKaran Tilak Kumar msecs_to_jiffies
337098585aaSKaran Tilak Kumar (FIP_VN_KA_PERIOD);
338098585aaSKaran Tilak Kumar mod_timer(&fnic->vn_ka_timer,
339098585aaSKaran Tilak Kumar round_jiffies(tov));
340098585aaSKaran Tilak Kumar }
341098585aaSKaran Tilak Kumar }
342098585aaSKaran Tilak Kumar }
343098585aaSKaran Tilak Kumar }
344098585aaSKaran Tilak Kumar break;
345098585aaSKaran Tilak Kumar default:
346098585aaSKaran Tilak Kumar break;
347098585aaSKaran Tilak Kumar } /* end switch */
348098585aaSKaran Tilak Kumar }
349098585aaSKaran Tilak Kumar
350098585aaSKaran Tilak Kumar /**
351098585aaSKaran Tilak Kumar * fnic_fcoe_start_flogi - Send FIP FLOGI to the selected FCF
352098585aaSKaran Tilak Kumar * @fnic: Handle to fnic driver instance
353098585aaSKaran Tilak Kumar */
fnic_fcoe_start_flogi(struct fnic * fnic)354098585aaSKaran Tilak Kumar void fnic_fcoe_start_flogi(struct fnic *fnic)
355098585aaSKaran Tilak Kumar {
356098585aaSKaran Tilak Kumar uint8_t *frame;
357098585aaSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport;
358098585aaSKaran Tilak Kumar struct fip_flogi *pflogi_req;
359098585aaSKaran Tilak Kumar u64 flogi_tov;
360098585aaSKaran Tilak Kumar uint16_t oxid;
361098585aaSKaran Tilak Kumar uint16_t frame_size = sizeof(struct fip_flogi);
362098585aaSKaran Tilak Kumar
363098585aaSKaran Tilak Kumar frame = fdls_alloc_frame(iport);
364098585aaSKaran Tilak Kumar if (frame == NULL) {
3657e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
366098585aaSKaran Tilak Kumar "Failed to allocate frame to start FIP FLOGI");
367098585aaSKaran Tilak Kumar return;
368098585aaSKaran Tilak Kumar }
369098585aaSKaran Tilak Kumar
370098585aaSKaran Tilak Kumar pflogi_req = (struct fip_flogi *) frame;
371098585aaSKaran Tilak Kumar *pflogi_req = (struct fip_flogi) {
372098585aaSKaran Tilak Kumar .eth = {
373098585aaSKaran Tilak Kumar .h_proto = cpu_to_be16(ETH_P_FIP)},
374098585aaSKaran Tilak Kumar .fip = {
375098585aaSKaran Tilak Kumar .fip_ver = FIP_VER_ENCAPS(FIP_VER),
376098585aaSKaran Tilak Kumar .fip_op = cpu_to_be16(FIP_OP_LS),
377098585aaSKaran Tilak Kumar .fip_subcode = FIP_SC_REQ,
378098585aaSKaran Tilak Kumar .fip_dl_len = cpu_to_be16(FIP_FLOGI_LEN),
379098585aaSKaran Tilak Kumar .fip_flags = cpu_to_be16(FIP_FL_FPMA)},
380098585aaSKaran Tilak Kumar .flogi_desc = {
381098585aaSKaran Tilak Kumar .fd_desc = {.fip_dtype = FIP_DT_FLOGI, .fip_dlen = 36},
382098585aaSKaran Tilak Kumar .flogi = {
383098585aaSKaran Tilak Kumar .fchdr = {
384098585aaSKaran Tilak Kumar .fh_r_ctl = FC_RCTL_ELS_REQ,
385098585aaSKaran Tilak Kumar .fh_d_id = {0xFF, 0xFF, 0xFE},
386098585aaSKaran Tilak Kumar .fh_type = FC_TYPE_ELS,
387098585aaSKaran Tilak Kumar .fh_f_ctl = {FNIC_ELS_REQ_FCTL, 0, 0},
388098585aaSKaran Tilak Kumar .fh_rx_id = cpu_to_be16(FNIC_UNASSIGNED_RXID)},
389098585aaSKaran Tilak Kumar .els = {
390098585aaSKaran Tilak Kumar .fl_cmd = ELS_FLOGI,
391098585aaSKaran Tilak Kumar .fl_csp = {
392098585aaSKaran Tilak Kumar .sp_hi_ver =
393098585aaSKaran Tilak Kumar FNIC_FC_PH_VER_HI,
394098585aaSKaran Tilak Kumar .sp_lo_ver =
395098585aaSKaran Tilak Kumar FNIC_FC_PH_VER_LO,
396098585aaSKaran Tilak Kumar .sp_bb_cred =
397098585aaSKaran Tilak Kumar cpu_to_be16
398098585aaSKaran Tilak Kumar (FNIC_FC_B2B_CREDIT),
399098585aaSKaran Tilak Kumar .sp_bb_data =
400098585aaSKaran Tilak Kumar cpu_to_be16
401098585aaSKaran Tilak Kumar (FNIC_FC_B2B_RDF_SZ)},
402098585aaSKaran Tilak Kumar .fl_cssp[2].cp_class =
403098585aaSKaran Tilak Kumar cpu_to_be16(FC_CPC_VALID | FC_CPC_SEQ)
404098585aaSKaran Tilak Kumar },
405098585aaSKaran Tilak Kumar }
406098585aaSKaran Tilak Kumar },
407098585aaSKaran Tilak Kumar .mac_desc = {.fd_desc = {.fip_dtype = FIP_DT_MAC, .fip_dlen = 2}}
408098585aaSKaran Tilak Kumar };
409098585aaSKaran Tilak Kumar
410098585aaSKaran Tilak Kumar memcpy(pflogi_req->eth.h_source, iport->hwmac, ETH_ALEN);
411098585aaSKaran Tilak Kumar if (iport->usefip)
412098585aaSKaran Tilak Kumar memcpy(pflogi_req->eth.h_dest, iport->selected_fcf.fcf_mac,
413098585aaSKaran Tilak Kumar ETH_ALEN);
414098585aaSKaran Tilak Kumar
415098585aaSKaran Tilak Kumar oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_FABRIC_FLOGI,
416098585aaSKaran Tilak Kumar &iport->active_oxid_fabric_req);
417098585aaSKaran Tilak Kumar if (oxid == FNIC_UNASSIGNED_OXID) {
4187e6886b7SKaran Tilak Kumar FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
419098585aaSKaran Tilak Kumar "Failed to allocate OXID to send FIP FLOGI");
420098585aaSKaran Tilak Kumar mempool_free(frame, fnic->frame_pool);
421098585aaSKaran Tilak Kumar return;
422098585aaSKaran Tilak Kumar }
423098585aaSKaran Tilak Kumar FNIC_STD_SET_OX_ID(pflogi_req->flogi_desc.flogi.fchdr, oxid);
424098585aaSKaran Tilak Kumar
425098585aaSKaran Tilak Kumar FNIC_STD_SET_NPORT_NAME(&pflogi_req->flogi_desc.flogi.els.fl_wwpn,
426098585aaSKaran Tilak Kumar iport->wwpn);
427098585aaSKaran Tilak Kumar FNIC_STD_SET_NODE_NAME(&pflogi_req->flogi_desc.flogi.els.fl_wwnn,
428098585aaSKaran Tilak Kumar iport->wwnn);
429098585aaSKaran Tilak Kumar
4307e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
431098585aaSKaran Tilak Kumar "FIP start FLOGI\n");
432098585aaSKaran Tilak Kumar fnic_send_fip_frame(iport, frame, frame_size);
433098585aaSKaran Tilak Kumar iport->fip.flogi_retry++;
434098585aaSKaran Tilak Kumar
435098585aaSKaran Tilak Kumar iport->fip.state = FDLS_FIP_FLOGI_STARTED;
436098585aaSKaran Tilak Kumar flogi_tov = jiffies + msecs_to_jiffies(fnic->config.flogi_timeout);
437098585aaSKaran Tilak Kumar mod_timer(&fnic->retry_fip_timer, round_jiffies(flogi_tov));
438098585aaSKaran Tilak Kumar }
439098585aaSKaran Tilak Kumar
440098585aaSKaran Tilak Kumar /**
441098585aaSKaran Tilak Kumar * fnic_fcoe_process_flogi_resp - Processes FLOGI response from FCF.
442098585aaSKaran Tilak Kumar * @fnic: Handle to fnic driver instance
443098585aaSKaran Tilak Kumar * @fiph: Received frame
444098585aaSKaran Tilak Kumar *
445098585aaSKaran Tilak Kumar * If successful save assigned fc_id and MAC, program firmware
446098585aaSKaran Tilak Kumar * and start fdls discovery, else restart vlan discovery.
447098585aaSKaran Tilak Kumar */
fnic_fcoe_process_flogi_resp(struct fnic * fnic,struct fip_header * fiph)448098585aaSKaran Tilak Kumar void fnic_fcoe_process_flogi_resp(struct fnic *fnic, struct fip_header *fiph)
449098585aaSKaran Tilak Kumar {
450098585aaSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport;
451098585aaSKaran Tilak Kumar struct fip_flogi_rsp *flogi_rsp = (struct fip_flogi_rsp *)fiph;
452098585aaSKaran Tilak Kumar int desc_len;
453098585aaSKaran Tilak Kumar uint32_t s_id;
454098585aaSKaran Tilak Kumar int frame_type;
455098585aaSKaran Tilak Kumar uint16_t oxid;
456098585aaSKaran Tilak Kumar
457098585aaSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats;
458098585aaSKaran Tilak Kumar struct fc_frame_header *fchdr = &flogi_rsp->rsp_desc.flogi.fchdr;
459098585aaSKaran Tilak Kumar
4607e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
461098585aaSKaran Tilak Kumar "fnic 0x%p FIP FLOGI rsp\n", fnic);
462098585aaSKaran Tilak Kumar desc_len = be16_to_cpu(flogi_rsp->fip.fip_dl_len);
463098585aaSKaran Tilak Kumar if (desc_len != 38) {
4647e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
465098585aaSKaran Tilak Kumar "Invalid Descriptor List len (%x). Dropping frame\n",
466098585aaSKaran Tilak Kumar desc_len);
467098585aaSKaran Tilak Kumar return;
468098585aaSKaran Tilak Kumar }
469098585aaSKaran Tilak Kumar
470098585aaSKaran Tilak Kumar if (!((flogi_rsp->rsp_desc.fd_desc.fip_dtype == 7)
471098585aaSKaran Tilak Kumar && (flogi_rsp->rsp_desc.fd_desc.fip_dlen == 36))
472098585aaSKaran Tilak Kumar || !((flogi_rsp->mac_desc.fd_desc.fip_dtype == 2)
473098585aaSKaran Tilak Kumar && (flogi_rsp->mac_desc.fd_desc.fip_dlen == 2))) {
4747e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
475098585aaSKaran Tilak Kumar "Dropping frame invalid type and len mix\n");
476098585aaSKaran Tilak Kumar return;
477098585aaSKaran Tilak Kumar }
478098585aaSKaran Tilak Kumar
479098585aaSKaran Tilak Kumar frame_type = fnic_fdls_validate_and_get_frame_type(iport, fchdr);
480098585aaSKaran Tilak Kumar
481098585aaSKaran Tilak Kumar s_id = ntoh24(fchdr->fh_s_id);
482098585aaSKaran Tilak Kumar if ((fchdr->fh_f_ctl[0] != 0x98)
483098585aaSKaran Tilak Kumar || (fchdr->fh_r_ctl != 0x23)
484098585aaSKaran Tilak Kumar || (s_id != FC_FID_FLOGI)
485098585aaSKaran Tilak Kumar || (frame_type != FNIC_FABRIC_FLOGI_RSP)
486098585aaSKaran Tilak Kumar || (fchdr->fh_type != 0x01)) {
4877e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
488098585aaSKaran Tilak Kumar "Dropping invalid frame: s_id %x F %x R %x t %x OX_ID %x\n",
489098585aaSKaran Tilak Kumar s_id, fchdr->fh_f_ctl[0], fchdr->fh_r_ctl,
490098585aaSKaran Tilak Kumar fchdr->fh_type, FNIC_STD_GET_OX_ID(fchdr));
491098585aaSKaran Tilak Kumar return;
492098585aaSKaran Tilak Kumar }
493098585aaSKaran Tilak Kumar
494098585aaSKaran Tilak Kumar if (iport->fip.state == FDLS_FIP_FLOGI_STARTED) {
4957e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
496098585aaSKaran Tilak Kumar "fnic 0x%p rsp for pending FLOGI\n", fnic);
497098585aaSKaran Tilak Kumar
498098585aaSKaran Tilak Kumar oxid = FNIC_STD_GET_OX_ID(fchdr);
499098585aaSKaran Tilak Kumar fdls_free_oxid(iport, oxid, &iport->active_oxid_fabric_req);
500098585aaSKaran Tilak Kumar del_timer_sync(&fnic->retry_fip_timer);
501098585aaSKaran Tilak Kumar
502098585aaSKaran Tilak Kumar if ((be16_to_cpu(flogi_rsp->fip.fip_dl_len) == FIP_FLOGI_LEN)
503098585aaSKaran Tilak Kumar && (flogi_rsp->rsp_desc.flogi.els.fl_cmd == ELS_LS_ACC)) {
504098585aaSKaran Tilak Kumar
5057e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host,
506098585aaSKaran Tilak Kumar fnic->fnic_num,
507098585aaSKaran Tilak Kumar "fnic 0x%p FLOGI success\n", fnic);
508098585aaSKaran Tilak Kumar memcpy(iport->fpma, flogi_rsp->mac_desc.fd_mac, ETH_ALEN);
509098585aaSKaran Tilak Kumar iport->fcid =
510098585aaSKaran Tilak Kumar ntoh24(flogi_rsp->rsp_desc.flogi.fchdr.fh_d_id);
511098585aaSKaran Tilak Kumar
512098585aaSKaran Tilak Kumar iport->r_a_tov =
513098585aaSKaran Tilak Kumar be32_to_cpu(flogi_rsp->rsp_desc.flogi.els.fl_csp.sp_r_a_tov);
514098585aaSKaran Tilak Kumar iport->e_d_tov =
515098585aaSKaran Tilak Kumar be32_to_cpu(flogi_rsp->rsp_desc.flogi.els.fl_csp.sp_e_d_tov);
516098585aaSKaran Tilak Kumar memcpy(fnic->iport.fcfmac, iport->selected_fcf.fcf_mac,
517098585aaSKaran Tilak Kumar ETH_ALEN);
518098585aaSKaran Tilak Kumar vnic_dev_add_addr(fnic->vdev, flogi_rsp->mac_desc.fd_mac);
519098585aaSKaran Tilak Kumar
520098585aaSKaran Tilak Kumar if (fnic_fdls_register_portid(iport, iport->fcid, NULL)
521098585aaSKaran Tilak Kumar != 0) {
5227e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host,
523098585aaSKaran Tilak Kumar fnic->fnic_num,
524098585aaSKaran Tilak Kumar "fnic 0x%p flogi registration failed\n",
525098585aaSKaran Tilak Kumar fnic);
526098585aaSKaran Tilak Kumar return;
527098585aaSKaran Tilak Kumar }
528098585aaSKaran Tilak Kumar
529098585aaSKaran Tilak Kumar iport->fip.state = FDLS_FIP_FLOGI_COMPLETE;
530098585aaSKaran Tilak Kumar iport->state = FNIC_IPORT_STATE_FABRIC_DISC;
5317e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host,
532098585aaSKaran Tilak Kumar fnic->fnic_num, "iport->state:%d\n",
533098585aaSKaran Tilak Kumar iport->state);
5349cf9fe2fSKaran Tilak Kumar fnic_fdls_disc_start(iport);
535098585aaSKaran Tilak Kumar if (!((iport->selected_fcf.ka_disabled)
536098585aaSKaran Tilak Kumar || (iport->selected_fcf.fka_adv_period == 0))) {
537098585aaSKaran Tilak Kumar u64 tov;
538098585aaSKaran Tilak Kumar
539098585aaSKaran Tilak Kumar tov = jiffies
540098585aaSKaran Tilak Kumar +
541098585aaSKaran Tilak Kumar msecs_to_jiffies(iport->selected_fcf.fka_adv_period);
542098585aaSKaran Tilak Kumar mod_timer(&fnic->enode_ka_timer,
543098585aaSKaran Tilak Kumar round_jiffies(tov));
544098585aaSKaran Tilak Kumar
545098585aaSKaran Tilak Kumar tov =
546098585aaSKaran Tilak Kumar jiffies +
547098585aaSKaran Tilak Kumar msecs_to_jiffies(FIP_VN_KA_PERIOD);
548098585aaSKaran Tilak Kumar mod_timer(&fnic->vn_ka_timer,
549098585aaSKaran Tilak Kumar round_jiffies(tov));
550098585aaSKaran Tilak Kumar
551098585aaSKaran Tilak Kumar }
552098585aaSKaran Tilak Kumar } else {
553098585aaSKaran Tilak Kumar /*
554098585aaSKaran Tilak Kumar * If there's FLOGI rejects - clear all
555098585aaSKaran Tilak Kumar * fcf's & restart from scratch
556098585aaSKaran Tilak Kumar */
557098585aaSKaran Tilak Kumar atomic64_inc(&fnic_stats->vlan_stats.flogi_rejects);
558098585aaSKaran Tilak Kumar /* start FCoE VLAN discovery */
559098585aaSKaran Tilak Kumar fnic_fcoe_send_vlan_req(fnic);
560098585aaSKaran Tilak Kumar
561098585aaSKaran Tilak Kumar iport->fip.state = FDLS_FIP_VLAN_DISCOVERY_STARTED;
562098585aaSKaran Tilak Kumar }
563098585aaSKaran Tilak Kumar }
564098585aaSKaran Tilak Kumar }
565098585aaSKaran Tilak Kumar
566098585aaSKaran Tilak Kumar /**
567098585aaSKaran Tilak Kumar * fnic_common_fip_cleanup - Clean up FCF info and timers in case of
568098585aaSKaran Tilak Kumar * link down/CVL
569098585aaSKaran Tilak Kumar * @fnic: Handle to fnic driver instance
570098585aaSKaran Tilak Kumar */
fnic_common_fip_cleanup(struct fnic * fnic)571098585aaSKaran Tilak Kumar void fnic_common_fip_cleanup(struct fnic *fnic)
572098585aaSKaran Tilak Kumar {
573098585aaSKaran Tilak Kumar
574098585aaSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport;
575098585aaSKaran Tilak Kumar
576098585aaSKaran Tilak Kumar if (!iport->usefip)
577098585aaSKaran Tilak Kumar return;
5787e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
579098585aaSKaran Tilak Kumar "fnic 0x%p fip cleanup\n", fnic);
580098585aaSKaran Tilak Kumar
581098585aaSKaran Tilak Kumar iport->fip.state = FDLS_FIP_INIT;
582098585aaSKaran Tilak Kumar
583098585aaSKaran Tilak Kumar del_timer_sync(&fnic->retry_fip_timer);
584098585aaSKaran Tilak Kumar del_timer_sync(&fnic->fcs_ka_timer);
585098585aaSKaran Tilak Kumar del_timer_sync(&fnic->enode_ka_timer);
586098585aaSKaran Tilak Kumar del_timer_sync(&fnic->vn_ka_timer);
587098585aaSKaran Tilak Kumar
588098585aaSKaran Tilak Kumar if (!is_zero_ether_addr(iport->fpma))
589098585aaSKaran Tilak Kumar vnic_dev_del_addr(fnic->vdev, iport->fpma);
590098585aaSKaran Tilak Kumar
591098585aaSKaran Tilak Kumar memset(iport->fpma, 0, ETH_ALEN);
592098585aaSKaran Tilak Kumar iport->fcid = 0;
593098585aaSKaran Tilak Kumar iport->r_a_tov = 0;
594098585aaSKaran Tilak Kumar iport->e_d_tov = 0;
595098585aaSKaran Tilak Kumar memset(fnic->iport.fcfmac, 0, ETH_ALEN);
596098585aaSKaran Tilak Kumar memset(iport->selected_fcf.fcf_mac, 0, ETH_ALEN);
597098585aaSKaran Tilak Kumar iport->selected_fcf.fcf_priority = 0;
598098585aaSKaran Tilak Kumar iport->selected_fcf.fka_adv_period = 0;
599098585aaSKaran Tilak Kumar iport->selected_fcf.ka_disabled = 0;
600098585aaSKaran Tilak Kumar
601098585aaSKaran Tilak Kumar fnic_fcoe_reset_vlans(fnic);
602098585aaSKaran Tilak Kumar }
603098585aaSKaran Tilak Kumar
604098585aaSKaran Tilak Kumar /**
605098585aaSKaran Tilak Kumar * fnic_fcoe_process_cvl - Processes Clear Virtual Link from FCF.
606098585aaSKaran Tilak Kumar * @fnic: Handle to fnic driver instance
607098585aaSKaran Tilak Kumar * @fiph: Received frame
608098585aaSKaran Tilak Kumar *
609098585aaSKaran Tilak Kumar * Verify that cvl is received from our current FCF for our assigned MAC
610098585aaSKaran Tilak Kumar * and clean up and restart the vlan discovery.
611098585aaSKaran Tilak Kumar */
fnic_fcoe_process_cvl(struct fnic * fnic,struct fip_header * fiph)612098585aaSKaran Tilak Kumar void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header *fiph)
613098585aaSKaran Tilak Kumar {
614098585aaSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport;
615098585aaSKaran Tilak Kumar struct fip_cvl *cvl_msg = (struct fip_cvl *)fiph;
616098585aaSKaran Tilak Kumar int i;
617098585aaSKaran Tilak Kumar int found = false;
6189cf9fe2fSKaran Tilak Kumar int max_count = 0;
619098585aaSKaran Tilak Kumar
6207e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
621098585aaSKaran Tilak Kumar "fnic 0x%p clear virtual link handler\n", fnic);
622098585aaSKaran Tilak Kumar
623098585aaSKaran Tilak Kumar if (!((cvl_msg->fcf_mac_desc.fd_desc.fip_dtype == 2)
624098585aaSKaran Tilak Kumar && (cvl_msg->fcf_mac_desc.fd_desc.fip_dlen == 2))
625098585aaSKaran Tilak Kumar || !((cvl_msg->name_desc.fd_desc.fip_dtype == 4)
626098585aaSKaran Tilak Kumar && (cvl_msg->name_desc.fd_desc.fip_dlen == 3))) {
627098585aaSKaran Tilak Kumar
6287e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
629098585aaSKaran Tilak Kumar "invalid mix: ft %x fl %x ndt %x ndl %x",
630098585aaSKaran Tilak Kumar cvl_msg->fcf_mac_desc.fd_desc.fip_dtype,
631098585aaSKaran Tilak Kumar cvl_msg->fcf_mac_desc.fd_desc.fip_dlen,
632098585aaSKaran Tilak Kumar cvl_msg->name_desc.fd_desc.fip_dtype,
633098585aaSKaran Tilak Kumar cvl_msg->name_desc.fd_desc.fip_dlen);
634098585aaSKaran Tilak Kumar }
635098585aaSKaran Tilak Kumar
636098585aaSKaran Tilak Kumar if (memcmp
637098585aaSKaran Tilak Kumar (iport->selected_fcf.fcf_mac, cvl_msg->fcf_mac_desc.fd_mac, ETH_ALEN)
638098585aaSKaran Tilak Kumar == 0) {
639098585aaSKaran Tilak Kumar for (i = 0; i < ((be16_to_cpu(fiph->fip_dl_len) / 5) - 1); i++) {
640098585aaSKaran Tilak Kumar if (!((cvl_msg->vn_ports_desc[i].fd_desc.fip_dtype == 11)
641098585aaSKaran Tilak Kumar && (cvl_msg->vn_ports_desc[i].fd_desc.fip_dlen == 5))) {
642098585aaSKaran Tilak Kumar
6437e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host,
644098585aaSKaran Tilak Kumar fnic->fnic_num,
645098585aaSKaran Tilak Kumar "Invalid type and len mix type: %d len: %d\n",
646098585aaSKaran Tilak Kumar cvl_msg->vn_ports_desc[i].fd_desc.fip_dtype,
647098585aaSKaran Tilak Kumar cvl_msg->vn_ports_desc[i].fd_desc.fip_dlen);
648098585aaSKaran Tilak Kumar }
649098585aaSKaran Tilak Kumar if (memcmp
650098585aaSKaran Tilak Kumar (iport->fpma, cvl_msg->vn_ports_desc[i].fd_mac,
651098585aaSKaran Tilak Kumar ETH_ALEN) == 0) {
652098585aaSKaran Tilak Kumar found = true;
653098585aaSKaran Tilak Kumar break;
654098585aaSKaran Tilak Kumar }
655098585aaSKaran Tilak Kumar }
656098585aaSKaran Tilak Kumar if (!found)
657098585aaSKaran Tilak Kumar return;
658098585aaSKaran Tilak Kumar fnic_common_fip_cleanup(fnic);
659098585aaSKaran Tilak Kumar
6609cf9fe2fSKaran Tilak Kumar while (fnic->reset_in_progress == IN_PROGRESS) {
6619cf9fe2fSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
6629cf9fe2fSKaran Tilak Kumar wait_for_completion_timeout(&fnic->reset_completion_wait,
6639cf9fe2fSKaran Tilak Kumar msecs_to_jiffies(5000));
6649cf9fe2fSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
6659cf9fe2fSKaran Tilak Kumar max_count++;
6669cf9fe2fSKaran Tilak Kumar if (max_count >= FIP_FNIC_RESET_WAIT_COUNT) {
6677e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
6689cf9fe2fSKaran Tilak Kumar "Rthr waited too long. Skipping handle link event %p\n",
6699cf9fe2fSKaran Tilak Kumar fnic);
6709cf9fe2fSKaran Tilak Kumar return;
6719cf9fe2fSKaran Tilak Kumar }
6727e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
6739cf9fe2fSKaran Tilak Kumar "fnic reset in progress. Link event needs to wait %p",
6749cf9fe2fSKaran Tilak Kumar fnic);
6759cf9fe2fSKaran Tilak Kumar }
6769cf9fe2fSKaran Tilak Kumar fnic->reset_in_progress = IN_PROGRESS;
6779cf9fe2fSKaran Tilak Kumar fnic_fdls_link_down(iport);
6789cf9fe2fSKaran Tilak Kumar fnic->reset_in_progress = NOT_IN_PROGRESS;
6799cf9fe2fSKaran Tilak Kumar complete(&fnic->reset_completion_wait);
680098585aaSKaran Tilak Kumar fnic_fcoe_send_vlan_req(fnic);
681098585aaSKaran Tilak Kumar }
682098585aaSKaran Tilak Kumar }
683098585aaSKaran Tilak Kumar
684098585aaSKaran Tilak Kumar /**
685098585aaSKaran Tilak Kumar * fdls_fip_recv_frame - Demultiplexer for FIP frames
686098585aaSKaran Tilak Kumar * @fnic: Handle to fnic driver instance
687098585aaSKaran Tilak Kumar * @frame: Received ethernet frame
688098585aaSKaran Tilak Kumar */
fdls_fip_recv_frame(struct fnic * fnic,void * frame)689098585aaSKaran Tilak Kumar int fdls_fip_recv_frame(struct fnic *fnic, void *frame)
690098585aaSKaran Tilak Kumar {
691098585aaSKaran Tilak Kumar struct ethhdr *eth = (struct ethhdr *)frame;
692098585aaSKaran Tilak Kumar struct fip_header *fiph;
693098585aaSKaran Tilak Kumar u16 op;
694098585aaSKaran Tilak Kumar u8 sub;
695098585aaSKaran Tilak Kumar int len = 2048;
696098585aaSKaran Tilak Kumar
697098585aaSKaran Tilak Kumar if (be16_to_cpu(eth->h_proto) == ETH_P_FIP) {
698098585aaSKaran Tilak Kumar fiph = (struct fip_header *)(eth + 1);
699098585aaSKaran Tilak Kumar op = be16_to_cpu(fiph->fip_op);
700098585aaSKaran Tilak Kumar sub = fiph->fip_subcode;
701098585aaSKaran Tilak Kumar
702098585aaSKaran Tilak Kumar fnic_debug_dump_fip_frame(fnic, eth, len, "Incoming");
703098585aaSKaran Tilak Kumar
704098585aaSKaran Tilak Kumar if (op == FIP_OP_DISC && sub == FIP_SC_REP)
705098585aaSKaran Tilak Kumar fnic_fcoe_fip_discovery_resp(fnic, fiph);
706098585aaSKaran Tilak Kumar else if (op == FIP_OP_VLAN && sub == FIP_SC_REP)
707098585aaSKaran Tilak Kumar fnic_fcoe_process_vlan_resp(fnic, fiph);
708098585aaSKaran Tilak Kumar else if (op == FIP_OP_CTRL && sub == FIP_SC_REP)
709098585aaSKaran Tilak Kumar fnic_fcoe_process_cvl(fnic, fiph);
710098585aaSKaran Tilak Kumar else if (op == FIP_OP_LS && sub == FIP_SC_REP)
711098585aaSKaran Tilak Kumar fnic_fcoe_process_flogi_resp(fnic, fiph);
712098585aaSKaran Tilak Kumar
713098585aaSKaran Tilak Kumar /* Return true if the frame was a FIP frame */
714098585aaSKaran Tilak Kumar return true;
715098585aaSKaran Tilak Kumar }
716098585aaSKaran Tilak Kumar
7177e6886b7SKaran Tilak Kumar FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
718098585aaSKaran Tilak Kumar "Not a FIP Frame");
719098585aaSKaran Tilak Kumar return false;
720098585aaSKaran Tilak Kumar }
721098585aaSKaran Tilak Kumar
fnic_work_on_fip_timer(struct work_struct * work)722098585aaSKaran Tilak Kumar void fnic_work_on_fip_timer(struct work_struct *work)
723098585aaSKaran Tilak Kumar {
724098585aaSKaran Tilak Kumar struct fnic *fnic = container_of(work, struct fnic, fip_timer_work);
725098585aaSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport;
726098585aaSKaran Tilak Kumar
7277e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
728098585aaSKaran Tilak Kumar "FIP timeout\n");
729098585aaSKaran Tilak Kumar
730098585aaSKaran Tilak Kumar if (iport->fip.state == FDLS_FIP_VLAN_DISCOVERY_STARTED) {
731098585aaSKaran Tilak Kumar fnic_vlan_discovery_timeout(fnic);
732098585aaSKaran Tilak Kumar } else if (iport->fip.state == FDLS_FIP_FCF_DISCOVERY_STARTED) {
733098585aaSKaran Tilak Kumar u8 zmac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
734098585aaSKaran Tilak Kumar
7357e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
736098585aaSKaran Tilak Kumar "FCF Discovery timeout\n");
737098585aaSKaran Tilak Kumar if (memcmp(iport->selected_fcf.fcf_mac, zmac, ETH_ALEN) != 0) {
738098585aaSKaran Tilak Kumar
7399cf9fe2fSKaran Tilak Kumar if (iport->flags & FNIC_FIRST_LINK_UP) {
7409cf9fe2fSKaran Tilak Kumar fnic_scsi_fcpio_reset(iport->fnic);
741098585aaSKaran Tilak Kumar iport->flags &= ~FNIC_FIRST_LINK_UP;
7429cf9fe2fSKaran Tilak Kumar }
743098585aaSKaran Tilak Kumar
744098585aaSKaran Tilak Kumar fnic_fcoe_start_flogi(fnic);
745098585aaSKaran Tilak Kumar if (!((iport->selected_fcf.ka_disabled)
746098585aaSKaran Tilak Kumar || (iport->selected_fcf.fka_adv_period == 0))) {
747098585aaSKaran Tilak Kumar u64 fcf_tov;
748098585aaSKaran Tilak Kumar
749098585aaSKaran Tilak Kumar fcf_tov = jiffies
750098585aaSKaran Tilak Kumar + 3
751098585aaSKaran Tilak Kumar *
752098585aaSKaran Tilak Kumar msecs_to_jiffies(iport->selected_fcf.fka_adv_period);
753098585aaSKaran Tilak Kumar mod_timer(&fnic->fcs_ka_timer,
754098585aaSKaran Tilak Kumar round_jiffies(fcf_tov));
755098585aaSKaran Tilak Kumar }
756098585aaSKaran Tilak Kumar } else {
7577e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host,
758098585aaSKaran Tilak Kumar fnic->fnic_num, "FCF Discovery timeout\n");
759098585aaSKaran Tilak Kumar fnic_vlan_discovery_timeout(fnic);
760098585aaSKaran Tilak Kumar }
761098585aaSKaran Tilak Kumar } else if (iport->fip.state == FDLS_FIP_FLOGI_STARTED) {
762098585aaSKaran Tilak Kumar fdls_schedule_oxid_free(iport, &iport->active_oxid_fabric_req);
7637e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
764098585aaSKaran Tilak Kumar "FLOGI timeout\n");
765098585aaSKaran Tilak Kumar if (iport->fip.flogi_retry < fnic->config.flogi_retries)
766098585aaSKaran Tilak Kumar fnic_fcoe_start_flogi(fnic);
767098585aaSKaran Tilak Kumar else
768098585aaSKaran Tilak Kumar fnic_vlan_discovery_timeout(fnic);
769098585aaSKaran Tilak Kumar }
770098585aaSKaran Tilak Kumar }
771098585aaSKaran Tilak Kumar
772098585aaSKaran Tilak Kumar /**
773098585aaSKaran Tilak Kumar * fnic_handle_fip_timer - Timeout handler for FIP discover phase.
774098585aaSKaran Tilak Kumar * @t: Handle to the timer list
775098585aaSKaran Tilak Kumar *
776098585aaSKaran Tilak Kumar * Based on the current state, start next phase or restart discovery.
777098585aaSKaran Tilak Kumar */
fnic_handle_fip_timer(struct timer_list * t)778098585aaSKaran Tilak Kumar void fnic_handle_fip_timer(struct timer_list *t)
779098585aaSKaran Tilak Kumar {
780098585aaSKaran Tilak Kumar struct fnic *fnic = from_timer(fnic, t, retry_fip_timer);
781098585aaSKaran Tilak Kumar
782098585aaSKaran Tilak Kumar INIT_WORK(&fnic->fip_timer_work, fnic_work_on_fip_timer);
783098585aaSKaran Tilak Kumar queue_work(fnic_fip_queue, &fnic->fip_timer_work);
784098585aaSKaran Tilak Kumar }
785098585aaSKaran Tilak Kumar
786098585aaSKaran Tilak Kumar /**
787098585aaSKaran Tilak Kumar * fnic_handle_enode_ka_timer - FIP node keep alive.
788098585aaSKaran Tilak Kumar * @t: Handle to the timer list
789098585aaSKaran Tilak Kumar */
fnic_handle_enode_ka_timer(struct timer_list * t)790098585aaSKaran Tilak Kumar void fnic_handle_enode_ka_timer(struct timer_list *t)
791098585aaSKaran Tilak Kumar {
792098585aaSKaran Tilak Kumar uint8_t *frame;
793098585aaSKaran Tilak Kumar struct fnic *fnic = from_timer(fnic, t, enode_ka_timer);
794098585aaSKaran Tilak Kumar
795098585aaSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport;
796098585aaSKaran Tilak Kumar struct fip_enode_ka *penode_ka;
797098585aaSKaran Tilak Kumar u64 enode_ka_tov;
798098585aaSKaran Tilak Kumar uint16_t frame_size = sizeof(struct fip_enode_ka);
799098585aaSKaran Tilak Kumar
800098585aaSKaran Tilak Kumar if (iport->fip.state != FDLS_FIP_FLOGI_COMPLETE)
801098585aaSKaran Tilak Kumar return;
802098585aaSKaran Tilak Kumar
803098585aaSKaran Tilak Kumar if ((iport->selected_fcf.ka_disabled)
804098585aaSKaran Tilak Kumar || (iport->selected_fcf.fka_adv_period == 0)) {
805098585aaSKaran Tilak Kumar return;
806098585aaSKaran Tilak Kumar }
807098585aaSKaran Tilak Kumar
808098585aaSKaran Tilak Kumar frame = fdls_alloc_frame(iport);
809098585aaSKaran Tilak Kumar if (frame == NULL) {
8107e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
811098585aaSKaran Tilak Kumar "Failed to allocate frame to send enode ka");
812098585aaSKaran Tilak Kumar return;
813098585aaSKaran Tilak Kumar }
814098585aaSKaran Tilak Kumar
815098585aaSKaran Tilak Kumar penode_ka = (struct fip_enode_ka *) frame;
816098585aaSKaran Tilak Kumar *penode_ka = (struct fip_enode_ka) {
817098585aaSKaran Tilak Kumar .eth = {
818098585aaSKaran Tilak Kumar .h_proto = cpu_to_be16(ETH_P_FIP)},
819098585aaSKaran Tilak Kumar .fip = {
820098585aaSKaran Tilak Kumar .fip_ver = FIP_VER_ENCAPS(FIP_VER),
821098585aaSKaran Tilak Kumar .fip_op = cpu_to_be16(FIP_OP_CTRL),
822098585aaSKaran Tilak Kumar .fip_subcode = FIP_SC_REQ,
823098585aaSKaran Tilak Kumar .fip_dl_len = cpu_to_be16(FIP_ENODE_KA_LEN)},
824098585aaSKaran Tilak Kumar .mac_desc = {.fd_desc = {.fip_dtype = FIP_DT_MAC, .fip_dlen = 2}}
825098585aaSKaran Tilak Kumar };
826098585aaSKaran Tilak Kumar
827098585aaSKaran Tilak Kumar memcpy(penode_ka->eth.h_source, iport->hwmac, ETH_ALEN);
828098585aaSKaran Tilak Kumar memcpy(penode_ka->eth.h_dest, iport->selected_fcf.fcf_mac, ETH_ALEN);
829098585aaSKaran Tilak Kumar memcpy(penode_ka->mac_desc.fd_mac, iport->hwmac, ETH_ALEN);
830098585aaSKaran Tilak Kumar
8317e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
832098585aaSKaran Tilak Kumar "Handle enode KA timer\n");
833098585aaSKaran Tilak Kumar fnic_send_fip_frame(iport, frame, frame_size);
834098585aaSKaran Tilak Kumar enode_ka_tov = jiffies
835098585aaSKaran Tilak Kumar + msecs_to_jiffies(iport->selected_fcf.fka_adv_period);
836098585aaSKaran Tilak Kumar mod_timer(&fnic->enode_ka_timer, round_jiffies(enode_ka_tov));
837098585aaSKaran Tilak Kumar }
838098585aaSKaran Tilak Kumar
839098585aaSKaran Tilak Kumar /**
840098585aaSKaran Tilak Kumar * fnic_handle_vn_ka_timer - FIP virtual port keep alive.
841098585aaSKaran Tilak Kumar * @t: Handle to the timer list
842098585aaSKaran Tilak Kumar */
fnic_handle_vn_ka_timer(struct timer_list * t)843098585aaSKaran Tilak Kumar void fnic_handle_vn_ka_timer(struct timer_list *t)
844098585aaSKaran Tilak Kumar {
845098585aaSKaran Tilak Kumar uint8_t *frame;
846098585aaSKaran Tilak Kumar struct fnic *fnic = from_timer(fnic, t, vn_ka_timer);
847098585aaSKaran Tilak Kumar
848098585aaSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport;
849098585aaSKaran Tilak Kumar struct fip_vn_port_ka *pvn_port_ka;
850098585aaSKaran Tilak Kumar u64 vn_ka_tov;
851098585aaSKaran Tilak Kumar uint8_t fcid[3];
852098585aaSKaran Tilak Kumar uint16_t frame_size = sizeof(struct fip_vn_port_ka);
853098585aaSKaran Tilak Kumar
854098585aaSKaran Tilak Kumar if (iport->fip.state != FDLS_FIP_FLOGI_COMPLETE)
855098585aaSKaran Tilak Kumar return;
856098585aaSKaran Tilak Kumar
857098585aaSKaran Tilak Kumar if ((iport->selected_fcf.ka_disabled)
858098585aaSKaran Tilak Kumar || (iport->selected_fcf.fka_adv_period == 0)) {
859098585aaSKaran Tilak Kumar return;
860098585aaSKaran Tilak Kumar }
861098585aaSKaran Tilak Kumar
862098585aaSKaran Tilak Kumar frame = fdls_alloc_frame(iport);
863098585aaSKaran Tilak Kumar if (frame == NULL) {
8647e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
865098585aaSKaran Tilak Kumar "Failed to allocate frame to send vn ka");
866098585aaSKaran Tilak Kumar return;
867098585aaSKaran Tilak Kumar }
868098585aaSKaran Tilak Kumar
869098585aaSKaran Tilak Kumar pvn_port_ka = (struct fip_vn_port_ka *) frame;
870098585aaSKaran Tilak Kumar *pvn_port_ka = (struct fip_vn_port_ka) {
871098585aaSKaran Tilak Kumar .eth = {
872098585aaSKaran Tilak Kumar .h_proto = cpu_to_be16(ETH_P_FIP)},
873098585aaSKaran Tilak Kumar .fip = {
874098585aaSKaran Tilak Kumar .fip_ver = FIP_VER_ENCAPS(FIP_VER),
875098585aaSKaran Tilak Kumar .fip_op = cpu_to_be16(FIP_OP_CTRL),
876098585aaSKaran Tilak Kumar .fip_subcode = FIP_SC_REQ,
877098585aaSKaran Tilak Kumar .fip_dl_len = cpu_to_be16(FIP_VN_KA_LEN)},
878098585aaSKaran Tilak Kumar .mac_desc = {.fd_desc = {.fip_dtype = FIP_DT_MAC, .fip_dlen = 2}},
879098585aaSKaran Tilak Kumar .vn_port_desc = {.fd_desc = {.fip_dtype = FIP_DT_VN_ID, .fip_dlen = 5}}
880098585aaSKaran Tilak Kumar };
881098585aaSKaran Tilak Kumar
882098585aaSKaran Tilak Kumar memcpy(pvn_port_ka->eth.h_source, iport->fpma, ETH_ALEN);
883098585aaSKaran Tilak Kumar memcpy(pvn_port_ka->eth.h_dest, iport->selected_fcf.fcf_mac, ETH_ALEN);
884098585aaSKaran Tilak Kumar memcpy(pvn_port_ka->mac_desc.fd_mac, iport->hwmac, ETH_ALEN);
885098585aaSKaran Tilak Kumar memcpy(pvn_port_ka->vn_port_desc.fd_mac, iport->fpma, ETH_ALEN);
886098585aaSKaran Tilak Kumar hton24(fcid, iport->fcid);
887098585aaSKaran Tilak Kumar memcpy(pvn_port_ka->vn_port_desc.fd_fc_id, fcid, 3);
888098585aaSKaran Tilak Kumar FNIC_STD_SET_NPORT_NAME(&pvn_port_ka->vn_port_desc.fd_wwpn, iport->wwpn);
889098585aaSKaran Tilak Kumar
8907e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
891098585aaSKaran Tilak Kumar "Handle vnport KA timer\n");
892098585aaSKaran Tilak Kumar fnic_send_fip_frame(iport, frame, frame_size);
893098585aaSKaran Tilak Kumar vn_ka_tov = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);
894098585aaSKaran Tilak Kumar mod_timer(&fnic->vn_ka_timer, round_jiffies(vn_ka_tov));
895098585aaSKaran Tilak Kumar }
896098585aaSKaran Tilak Kumar
897098585aaSKaran Tilak Kumar /**
898098585aaSKaran Tilak Kumar * fnic_vlan_discovery_timeout - Handle vlan discovery timeout
899098585aaSKaran Tilak Kumar * @fnic: Handle to fnic driver instance
900098585aaSKaran Tilak Kumar *
901098585aaSKaran Tilak Kumar * End of VLAN discovery or FCF discovery time window.
902098585aaSKaran Tilak Kumar * Start the FCF discovery if VLAN was never used.
903098585aaSKaran Tilak Kumar */
fnic_vlan_discovery_timeout(struct fnic * fnic)904098585aaSKaran Tilak Kumar void fnic_vlan_discovery_timeout(struct fnic *fnic)
905098585aaSKaran Tilak Kumar {
906098585aaSKaran Tilak Kumar struct fcoe_vlan *vlan;
907098585aaSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport;
908098585aaSKaran Tilak Kumar struct fnic_stats *fnic_stats = &fnic->fnic_stats;
909098585aaSKaran Tilak Kumar unsigned long flags;
910098585aaSKaran Tilak Kumar
911098585aaSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, flags);
912098585aaSKaran Tilak Kumar if (fnic->stop_rx_link_events) {
913098585aaSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags);
914098585aaSKaran Tilak Kumar return;
915098585aaSKaran Tilak Kumar }
916098585aaSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, flags);
917098585aaSKaran Tilak Kumar
918098585aaSKaran Tilak Kumar if (!iport->usefip)
919098585aaSKaran Tilak Kumar return;
920098585aaSKaran Tilak Kumar
921098585aaSKaran Tilak Kumar spin_lock_irqsave(&fnic->vlans_lock, flags);
922098585aaSKaran Tilak Kumar if (list_empty(&fnic->vlan_list)) {
923098585aaSKaran Tilak Kumar /* no vlans available, try again */
924098585aaSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->vlans_lock, flags);
925098585aaSKaran Tilak Kumar fnic_fcoe_send_vlan_req(fnic);
926098585aaSKaran Tilak Kumar return;
927098585aaSKaran Tilak Kumar }
928098585aaSKaran Tilak Kumar
929098585aaSKaran Tilak Kumar vlan = list_first_entry(&fnic->vlan_list, struct fcoe_vlan, list);
930098585aaSKaran Tilak Kumar
931098585aaSKaran Tilak Kumar if (vlan->state == FIP_VLAN_SENT) {
932098585aaSKaran Tilak Kumar if (vlan->sol_count >= FCOE_CTLR_MAX_SOL) {
933098585aaSKaran Tilak Kumar /*
934098585aaSKaran Tilak Kumar * no response on this vlan, remove from the list.
935098585aaSKaran Tilak Kumar * Try the next vlan
936098585aaSKaran Tilak Kumar */
937098585aaSKaran Tilak Kumar list_del(&vlan->list);
938098585aaSKaran Tilak Kumar kfree(vlan);
939098585aaSKaran Tilak Kumar vlan = NULL;
940098585aaSKaran Tilak Kumar if (list_empty(&fnic->vlan_list)) {
941098585aaSKaran Tilak Kumar /* we exhausted all vlans, restart vlan disc */
942098585aaSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->vlans_lock,
943098585aaSKaran Tilak Kumar flags);
944098585aaSKaran Tilak Kumar fnic_fcoe_send_vlan_req(fnic);
945098585aaSKaran Tilak Kumar return;
946098585aaSKaran Tilak Kumar }
947098585aaSKaran Tilak Kumar /* check the next vlan */
948098585aaSKaran Tilak Kumar vlan =
949098585aaSKaran Tilak Kumar list_first_entry(&fnic->vlan_list, struct fcoe_vlan,
950098585aaSKaran Tilak Kumar list);
951098585aaSKaran Tilak Kumar
952098585aaSKaran Tilak Kumar fnic->set_vlan(fnic, vlan->vid);
953098585aaSKaran Tilak Kumar vlan->state = FIP_VLAN_SENT; /* sent now */
954098585aaSKaran Tilak Kumar
955098585aaSKaran Tilak Kumar }
956098585aaSKaran Tilak Kumar atomic64_inc(&fnic_stats->vlan_stats.sol_expiry_count);
957098585aaSKaran Tilak Kumar
958098585aaSKaran Tilak Kumar } else {
959098585aaSKaran Tilak Kumar fnic->set_vlan(fnic, vlan->vid);
960098585aaSKaran Tilak Kumar vlan->state = FIP_VLAN_SENT; /* sent now */
961098585aaSKaran Tilak Kumar }
962098585aaSKaran Tilak Kumar vlan->sol_count++;
963098585aaSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->vlans_lock, flags);
964098585aaSKaran Tilak Kumar fnic_fcoe_start_fcf_discovery(fnic);
965098585aaSKaran Tilak Kumar }
966098585aaSKaran Tilak Kumar
967098585aaSKaran Tilak Kumar /**
968098585aaSKaran Tilak Kumar * fnic_work_on_fcs_ka_timer - Handle work on FCS keep alive timer.
969098585aaSKaran Tilak Kumar * @work: the work queue to be serviced
970098585aaSKaran Tilak Kumar *
971098585aaSKaran Tilak Kumar * Finish handling fcs_ka_timer in process context.
972098585aaSKaran Tilak Kumar * Clean up, bring the link down, and restart all FIP discovery.
973098585aaSKaran Tilak Kumar */
fnic_work_on_fcs_ka_timer(struct work_struct * work)974098585aaSKaran Tilak Kumar void fnic_work_on_fcs_ka_timer(struct work_struct *work)
975098585aaSKaran Tilak Kumar {
976098585aaSKaran Tilak Kumar struct fnic
977098585aaSKaran Tilak Kumar *fnic = container_of(work, struct fnic, fip_timer_work);
978098585aaSKaran Tilak Kumar struct fnic_iport_s *iport = &fnic->iport;
979098585aaSKaran Tilak Kumar
9807e6886b7SKaran Tilak Kumar FNIC_FIP_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
981098585aaSKaran Tilak Kumar "fnic 0x%p fcs ka timeout\n", fnic);
982098585aaSKaran Tilak Kumar
983098585aaSKaran Tilak Kumar fnic_common_fip_cleanup(fnic);
984098585aaSKaran Tilak Kumar spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
9859cf9fe2fSKaran Tilak Kumar fnic_fdls_link_down(iport);
986098585aaSKaran Tilak Kumar iport->state = FNIC_IPORT_STATE_FIP;
987098585aaSKaran Tilak Kumar spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
988098585aaSKaran Tilak Kumar
989098585aaSKaran Tilak Kumar fnic_fcoe_send_vlan_req(fnic);
990098585aaSKaran Tilak Kumar }
991098585aaSKaran Tilak Kumar
992098585aaSKaran Tilak Kumar /**
993098585aaSKaran Tilak Kumar * fnic_handle_fcs_ka_timer - Handle FCS keep alive timer.
994098585aaSKaran Tilak Kumar * @t: Handle to the timer list
995098585aaSKaran Tilak Kumar *
996098585aaSKaran Tilak Kumar * No keep alives received from FCF. Clean up, bring the link down
997098585aaSKaran Tilak Kumar * and restart all the FIP discovery.
998098585aaSKaran Tilak Kumar */
fnic_handle_fcs_ka_timer(struct timer_list * t)999098585aaSKaran Tilak Kumar void fnic_handle_fcs_ka_timer(struct timer_list *t)
1000098585aaSKaran Tilak Kumar {
1001098585aaSKaran Tilak Kumar struct fnic *fnic = from_timer(fnic, t, fcs_ka_timer);
1002098585aaSKaran Tilak Kumar
1003098585aaSKaran Tilak Kumar INIT_WORK(&fnic->fip_timer_work, fnic_work_on_fcs_ka_timer);
1004098585aaSKaran Tilak Kumar queue_work(fnic_fip_queue, &fnic->fip_timer_work);
1005098585aaSKaran Tilak Kumar }
1006