Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / scsi / csiostor / csio_attr.c
1 /*
2  * This file is part of the Chelsio FCoE driver for Linux.
3  *
4  * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
5  *
6  * This software is available to you under a choice of one of two
7  * licenses.  You may choose to be licensed under the terms of the GNU
8  * General Public License (GPL) Version 2, available from the file
9  * COPYING in the main directory of this source tree, or the
10  * OpenIB.org BSD license below:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      - Redistributions of source code must retain the above
17  *        copyright notice, this list of conditions and the following
18  *        disclaimer.
19  *
20  *      - Redistributions in binary form must reproduce the above
21  *        copyright notice, this list of conditions and the following
22  *        disclaimer in the documentation and/or other materials
23  *        provided with the distribution.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32  * SOFTWARE.
33  */
34
35 #include <linux/kernel.h>
36 #include <linux/string.h>
37 #include <linux/delay.h>
38 #include <linux/module.h>
39 #include <linux/init.h>
40 #include <linux/pci.h>
41 #include <linux/mm.h>
42 #include <linux/jiffies.h>
43 #include <scsi/fc/fc_fs.h>
44
45 #include "csio_init.h"
46
47 static void
48 csio_vport_set_state(struct csio_lnode *ln);
49
50 /*
51  * csio_reg_rnode - Register a remote port with FC transport.
52  * @rn: Rnode representing remote port.
53  *
54  * Call fc_remote_port_add() to register this remote port with FC transport.
55  * If remote port is Initiator OR Target OR both, change the role appropriately.
56  *
57  */
58 void
59 csio_reg_rnode(struct csio_rnode *rn)
60 {
61         struct csio_lnode *ln           = csio_rnode_to_lnode(rn);
62         struct Scsi_Host *shost         = csio_ln_to_shost(ln);
63         struct fc_rport_identifiers ids;
64         struct fc_rport  *rport;
65         struct csio_service_parms *sp;
66
67         ids.node_name   = wwn_to_u64(csio_rn_wwnn(rn));
68         ids.port_name   = wwn_to_u64(csio_rn_wwpn(rn));
69         ids.port_id     = rn->nport_id;
70         ids.roles       = FC_RPORT_ROLE_UNKNOWN;
71
72         if (rn->role & CSIO_RNFR_INITIATOR || rn->role & CSIO_RNFR_TARGET) {
73                 rport = rn->rport;
74                 CSIO_ASSERT(rport != NULL);
75                 goto update_role;
76         }
77
78         rn->rport = fc_remote_port_add(shost, 0, &ids);
79         if (!rn->rport) {
80                 csio_ln_err(ln, "Failed to register rport = 0x%x.\n",
81                                         rn->nport_id);
82                 return;
83         }
84
85         ln->num_reg_rnodes++;
86         rport = rn->rport;
87         spin_lock_irq(shost->host_lock);
88         *((struct csio_rnode **)rport->dd_data) = rn;
89         spin_unlock_irq(shost->host_lock);
90
91         sp = &rn->rn_sparm;
92         rport->maxframe_size = ntohs(sp->csp.sp_bb_data);
93         if (ntohs(sp->clsp[2].cp_class) & FC_CPC_VALID)
94                 rport->supported_classes = FC_COS_CLASS3;
95         else
96                 rport->supported_classes = FC_COS_UNSPECIFIED;
97 update_role:
98         if (rn->role & CSIO_RNFR_INITIATOR)
99                 ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
100         if (rn->role & CSIO_RNFR_TARGET)
101                 ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
102
103         if (ids.roles != FC_RPORT_ROLE_UNKNOWN)
104                 fc_remote_port_rolechg(rport, ids.roles);
105
106         rn->scsi_id = rport->scsi_target_id;
107
108         csio_ln_dbg(ln, "Remote port x%x role 0x%x registered\n",
109                 rn->nport_id, ids.roles);
110 }
111
112 /*
113  * csio_unreg_rnode - Unregister a remote port with FC transport.
114  * @rn: Rnode representing remote port.
115  *
116  * Call fc_remote_port_delete() to unregister this remote port with FC
117  * transport.
118  *
119  */
120 void
121 csio_unreg_rnode(struct csio_rnode *rn)
122 {
123         struct csio_lnode *ln = csio_rnode_to_lnode(rn);
124         struct fc_rport *rport = rn->rport;
125
126         rn->role &= ~(CSIO_RNFR_INITIATOR | CSIO_RNFR_TARGET);
127         fc_remote_port_delete(rport);
128         ln->num_reg_rnodes--;
129
130         csio_ln_dbg(ln, "Remote port x%x un-registered\n", rn->nport_id);
131 }
132
133 /*
134  * csio_lnode_async_event - Async events from local port.
135  * @ln: lnode representing local port.
136  *
137  * Async events from local node that FC transport/SCSI ML
138  * should be made aware of (Eg: RSCN).
139  */
140 void
141 csio_lnode_async_event(struct csio_lnode *ln, enum csio_ln_fc_evt fc_evt)
142 {
143         switch (fc_evt) {
144         case CSIO_LN_FC_RSCN:
145                 /* Get payload of rscn from ln */
146                 /* For each RSCN entry */
147                         /*
148                          * fc_host_post_event(shost,
149                          *                    fc_get_event_number(),
150                          *                    FCH_EVT_RSCN,
151                          *                    rscn_entry);
152                          */
153                 break;
154         case CSIO_LN_FC_LINKUP:
155                 /* send fc_host_post_event */
156                 /* set vport state */
157                 if (csio_is_npiv_ln(ln))
158                         csio_vport_set_state(ln);
159
160                 break;
161         case CSIO_LN_FC_LINKDOWN:
162                 /* send fc_host_post_event */
163                 /* set vport state */
164                 if (csio_is_npiv_ln(ln))
165                         csio_vport_set_state(ln);
166
167                 break;
168         case CSIO_LN_FC_ATTRIB_UPDATE:
169                 csio_fchost_attr_init(ln);
170                 break;
171         default:
172                 break;
173         }
174 }
175
176 /*
177  * csio_fchost_attr_init - Initialize FC transport attributes
178  * @ln: Lnode.
179  *
180  */
181 void
182 csio_fchost_attr_init(struct csio_lnode *ln)
183 {
184         struct Scsi_Host  *shost = csio_ln_to_shost(ln);
185
186         fc_host_node_name(shost) = wwn_to_u64(csio_ln_wwnn(ln));
187         fc_host_port_name(shost) = wwn_to_u64(csio_ln_wwpn(ln));
188
189         fc_host_supported_classes(shost) = FC_COS_CLASS3;
190         fc_host_max_npiv_vports(shost) =
191                         (csio_lnode_to_hw(ln))->fres_info.max_vnps;
192         fc_host_supported_speeds(shost) = FC_PORTSPEED_10GBIT |
193                 FC_PORTSPEED_1GBIT;
194
195         fc_host_maxframe_size(shost) = ntohs(ln->ln_sparm.csp.sp_bb_data);
196         memset(fc_host_supported_fc4s(shost), 0,
197                 sizeof(fc_host_supported_fc4s(shost)));
198         fc_host_supported_fc4s(shost)[7] = 1;
199
200         memset(fc_host_active_fc4s(shost), 0,
201                 sizeof(fc_host_active_fc4s(shost)));
202         fc_host_active_fc4s(shost)[7] = 1;
203 }
204
205 /*
206  * csio_get_host_port_id - sysfs entries for nport_id is
207  * populated/cached from this function
208  */
209 static void
210 csio_get_host_port_id(struct Scsi_Host *shost)
211 {
212         struct csio_lnode *ln   = shost_priv(shost);
213         struct csio_hw *hw = csio_lnode_to_hw(ln);
214
215         spin_lock_irq(&hw->lock);
216         fc_host_port_id(shost) = ln->nport_id;
217         spin_unlock_irq(&hw->lock);
218 }
219
220 /*
221  * csio_get_port_type - Return FC local port type.
222  * @shost: scsi host.
223  *
224  */
225 static void
226 csio_get_host_port_type(struct Scsi_Host *shost)
227 {
228         struct csio_lnode *ln = shost_priv(shost);
229         struct csio_hw *hw = csio_lnode_to_hw(ln);
230
231         spin_lock_irq(&hw->lock);
232         if (csio_is_npiv_ln(ln))
233                 fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
234         else
235                 fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
236         spin_unlock_irq(&hw->lock);
237 }
238
239 /*
240  * csio_get_port_state - Return FC local port state.
241  * @shost: scsi host.
242  *
243  */
244 static void
245 csio_get_host_port_state(struct Scsi_Host *shost)
246 {
247         struct csio_lnode *ln = shost_priv(shost);
248         struct csio_hw *hw = csio_lnode_to_hw(ln);
249         char state[16];
250
251         spin_lock_irq(&hw->lock);
252
253         csio_lnode_state_to_str(ln, state);
254         if (!strcmp(state, "READY"))
255                 fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
256         else if (!strcmp(state, "OFFLINE"))
257                 fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
258         else
259                 fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
260
261         spin_unlock_irq(&hw->lock);
262 }
263
264 /*
265  * csio_get_host_speed - Return link speed to FC transport.
266  * @shost: scsi host.
267  *
268  */
269 static void
270 csio_get_host_speed(struct Scsi_Host *shost)
271 {
272         struct csio_lnode *ln = shost_priv(shost);
273         struct csio_hw *hw = csio_lnode_to_hw(ln);
274
275         spin_lock_irq(&hw->lock);
276         switch (hw->pport[ln->portid].link_speed) {
277         case FW_PORT_CAP_SPEED_1G:
278                 fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
279                 break;
280         case FW_PORT_CAP_SPEED_10G:
281                 fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
282                 break;
283         default:
284                 fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
285                 break;
286         }
287         spin_unlock_irq(&hw->lock);
288 }
289
290 /*
291  * csio_get_host_fabric_name - Return fabric name
292  * @shost: scsi host.
293  *
294  */
295 static void
296 csio_get_host_fabric_name(struct Scsi_Host *shost)
297 {
298         struct csio_lnode *ln = shost_priv(shost);
299         struct csio_rnode *rn = NULL;
300         struct csio_hw *hw = csio_lnode_to_hw(ln);
301
302         spin_lock_irq(&hw->lock);
303         rn = csio_rnode_lookup_portid(ln, FC_FID_FLOGI);
304         if (rn)
305                 fc_host_fabric_name(shost) = wwn_to_u64(csio_rn_wwnn(rn));
306         else
307                 fc_host_fabric_name(shost) = 0;
308         spin_unlock_irq(&hw->lock);
309 }
310
311 /*
312  * csio_get_host_speed - Return FC transport statistics.
313  * @ln: Lnode.
314  *
315  */
316 static struct fc_host_statistics *
317 csio_get_stats(struct Scsi_Host *shost)
318 {
319         struct csio_lnode *ln = shost_priv(shost);
320         struct csio_hw *hw = csio_lnode_to_hw(ln);
321         struct fc_host_statistics *fhs = &ln->fch_stats;
322         struct fw_fcoe_port_stats fcoe_port_stats;
323         uint64_t seconds;
324
325         memset(&fcoe_port_stats, 0, sizeof(struct fw_fcoe_port_stats));
326         csio_get_phy_port_stats(hw, ln->portid, &fcoe_port_stats);
327
328         fhs->tx_frames  += (be64_to_cpu(fcoe_port_stats.tx_bcast_frames) +
329                             be64_to_cpu(fcoe_port_stats.tx_mcast_frames) +
330                             be64_to_cpu(fcoe_port_stats.tx_ucast_frames) +
331                             be64_to_cpu(fcoe_port_stats.tx_offload_frames));
332         fhs->tx_words  += (be64_to_cpu(fcoe_port_stats.tx_bcast_bytes) +
333                            be64_to_cpu(fcoe_port_stats.tx_mcast_bytes) +
334                            be64_to_cpu(fcoe_port_stats.tx_ucast_bytes) +
335                            be64_to_cpu(fcoe_port_stats.tx_offload_bytes)) /
336                                                         CSIO_WORD_TO_BYTE;
337         fhs->rx_frames += (be64_to_cpu(fcoe_port_stats.rx_bcast_frames) +
338                            be64_to_cpu(fcoe_port_stats.rx_mcast_frames) +
339                            be64_to_cpu(fcoe_port_stats.rx_ucast_frames));
340         fhs->rx_words += (be64_to_cpu(fcoe_port_stats.rx_bcast_bytes) +
341                           be64_to_cpu(fcoe_port_stats.rx_mcast_bytes) +
342                           be64_to_cpu(fcoe_port_stats.rx_ucast_bytes)) /
343                                                         CSIO_WORD_TO_BYTE;
344         fhs->error_frames += be64_to_cpu(fcoe_port_stats.rx_err_frames);
345         fhs->fcp_input_requests +=  ln->stats.n_input_requests;
346         fhs->fcp_output_requests +=  ln->stats.n_output_requests;
347         fhs->fcp_control_requests +=  ln->stats.n_control_requests;
348         fhs->fcp_input_megabytes +=  ln->stats.n_input_bytes >> 20;
349         fhs->fcp_output_megabytes +=  ln->stats.n_output_bytes >> 20;
350         fhs->link_failure_count = ln->stats.n_link_down;
351         /* Reset stats for the device */
352         seconds = jiffies_to_msecs(jiffies) - hw->stats.n_reset_start;
353         do_div(seconds, 1000);
354         fhs->seconds_since_last_reset = seconds;
355
356         return fhs;
357 }
358
359 /*
360  * csio_set_rport_loss_tmo - Set the rport dev loss timeout
361  * @rport: fc rport.
362  * @timeout: new value for dev loss tmo.
363  *
364  * If timeout is non zero set the dev_loss_tmo to timeout, else set
365  * dev_loss_tmo to one.
366  */
367 static void
368 csio_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
369 {
370         if (timeout)
371                 rport->dev_loss_tmo = timeout;
372         else
373                 rport->dev_loss_tmo = 1;
374 }
375
376 static void
377 csio_vport_set_state(struct csio_lnode *ln)
378 {
379         struct fc_vport *fc_vport = ln->fc_vport;
380         struct csio_lnode  *pln = ln->pln;
381         char state[16];
382
383         /* Set fc vport state based on phyiscal lnode */
384         csio_lnode_state_to_str(pln, state);
385         if (strcmp(state, "READY")) {
386                 fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
387                 return;
388         }
389
390         if (!(pln->flags & CSIO_LNF_NPIVSUPP)) {
391                 fc_vport_set_state(fc_vport, FC_VPORT_NO_FABRIC_SUPP);
392                 return;
393         }
394
395         /* Set fc vport state based on virtual lnode */
396         csio_lnode_state_to_str(ln, state);
397         if (strcmp(state, "READY")) {
398                 fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
399                 return;
400         }
401         fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
402 }
403
404 static int
405 csio_fcoe_alloc_vnp(struct csio_hw *hw, struct csio_lnode *ln)
406 {
407         struct csio_lnode *pln;
408         struct csio_mb  *mbp;
409         struct fw_fcoe_vnp_cmd *rsp;
410         int ret = 0;
411         int retry = 0;
412
413         /* Issue VNP cmd to alloc vport */
414         /* Allocate Mbox request */
415         spin_lock_irq(&hw->lock);
416         mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
417         if (!mbp) {
418                 CSIO_INC_STATS(hw, n_err_nomem);
419                 ret = -ENOMEM;
420                 goto out;
421         }
422
423         pln = ln->pln;
424         ln->fcf_flowid = pln->fcf_flowid;
425         ln->portid = pln->portid;
426
427         csio_fcoe_vnp_alloc_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
428                                     pln->fcf_flowid, pln->vnp_flowid, 0,
429                                     csio_ln_wwnn(ln), csio_ln_wwpn(ln), NULL);
430
431         for (retry = 0; retry < 3; retry++) {
432                 /* FW is expected to complete vnp cmd in immediate mode
433                  * without much delay.
434                  * Otherwise, there will be increase in IO latency since HW
435                  * lock is held till completion of vnp mbox cmd.
436                  */
437                 ret = csio_mb_issue(hw, mbp);
438                 if (ret != -EBUSY)
439                         break;
440
441                 /* Retry if mbox returns busy */
442                 spin_unlock_irq(&hw->lock);
443                 msleep(2000);
444                 spin_lock_irq(&hw->lock);
445         }
446
447         if (ret) {
448                 csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");
449                 goto out_free;
450         }
451
452         /* Process Mbox response of VNP command */
453         rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
454         if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {
455                 csio_ln_err(ln, "FCOE VNP ALLOC cmd returned 0x%x!\n",
456                             FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)));
457                 ret = -EINVAL;
458                 goto out_free;
459         }
460
461         ln->vnp_flowid = FW_FCOE_VNP_CMD_VNPI_GET(
462                                 ntohl(rsp->gen_wwn_to_vnpi));
463         memcpy(csio_ln_wwnn(ln), rsp->vnport_wwnn, 8);
464         memcpy(csio_ln_wwpn(ln), rsp->vnport_wwpn, 8);
465
466         csio_ln_dbg(ln, "FCOE VNPI: 0x%x\n", ln->vnp_flowid);
467         csio_ln_dbg(ln, "\tWWNN: %x%x%x%x%x%x%x%x\n",
468                     ln->ln_sparm.wwnn[0], ln->ln_sparm.wwnn[1],
469                     ln->ln_sparm.wwnn[2], ln->ln_sparm.wwnn[3],
470                     ln->ln_sparm.wwnn[4], ln->ln_sparm.wwnn[5],
471                     ln->ln_sparm.wwnn[6], ln->ln_sparm.wwnn[7]);
472         csio_ln_dbg(ln, "\tWWPN: %x%x%x%x%x%x%x%x\n",
473                     ln->ln_sparm.wwpn[0], ln->ln_sparm.wwpn[1],
474                     ln->ln_sparm.wwpn[2], ln->ln_sparm.wwpn[3],
475                     ln->ln_sparm.wwpn[4], ln->ln_sparm.wwpn[5],
476                     ln->ln_sparm.wwpn[6], ln->ln_sparm.wwpn[7]);
477
478 out_free:
479         mempool_free(mbp, hw->mb_mempool);
480 out:
481         spin_unlock_irq(&hw->lock);
482         return ret;
483 }
484
485 static int
486 csio_fcoe_free_vnp(struct csio_hw *hw, struct csio_lnode *ln)
487 {
488         struct csio_lnode *pln;
489         struct csio_mb  *mbp;
490         struct fw_fcoe_vnp_cmd *rsp;
491         int ret = 0;
492         int retry = 0;
493
494         /* Issue VNP cmd to free vport */
495         /* Allocate Mbox request */
496
497         spin_lock_irq(&hw->lock);
498         mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
499         if (!mbp) {
500                 CSIO_INC_STATS(hw, n_err_nomem);
501                 ret = -ENOMEM;
502                 goto out;
503         }
504
505         pln = ln->pln;
506
507         csio_fcoe_vnp_free_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
508                                    ln->fcf_flowid, ln->vnp_flowid,
509                                    NULL);
510
511         for (retry = 0; retry < 3; retry++) {
512                 ret = csio_mb_issue(hw, mbp);
513                 if (ret != -EBUSY)
514                         break;
515
516                 /* Retry if mbox returns busy */
517                 spin_unlock_irq(&hw->lock);
518                 msleep(2000);
519                 spin_lock_irq(&hw->lock);
520         }
521
522         if (ret) {
523                 csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");
524                 goto out_free;
525         }
526
527         /* Process Mbox response of VNP command */
528         rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
529         if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {
530                 csio_ln_err(ln, "FCOE VNP FREE cmd returned 0x%x!\n",
531                             FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)));
532                 ret = -EINVAL;
533         }
534
535 out_free:
536         mempool_free(mbp, hw->mb_mempool);
537 out:
538         spin_unlock_irq(&hw->lock);
539         return ret;
540 }
541
542 static int
543 csio_vport_create(struct fc_vport *fc_vport, bool disable)
544 {
545         struct Scsi_Host *shost = fc_vport->shost;
546         struct csio_lnode *pln = shost_priv(shost);
547         struct csio_lnode *ln = NULL;
548         struct csio_hw *hw = csio_lnode_to_hw(pln);
549         uint8_t wwn[8];
550         int ret = -1;
551
552         ln = csio_shost_init(hw, &fc_vport->dev, false, pln);
553         if (!ln)
554                 goto error;
555
556         if (fc_vport->node_name != 0) {
557                 u64_to_wwn(fc_vport->node_name, wwn);
558
559                 if (!CSIO_VALID_WWN(wwn)) {
560                         csio_ln_err(ln,
561                                     "vport create failed. Invalid wwnn\n");
562                         goto error;
563                 }
564                 memcpy(csio_ln_wwnn(ln), wwn, 8);
565         }
566
567         if (fc_vport->port_name != 0) {
568                 u64_to_wwn(fc_vport->port_name, wwn);
569
570                 if (!CSIO_VALID_WWN(wwn)) {
571                         csio_ln_err(ln,
572                                     "vport create failed. Invalid wwpn\n");
573                         goto error;
574                 }
575
576                 if (csio_lnode_lookup_by_wwpn(hw, wwn)) {
577                         csio_ln_err(ln,
578                             "vport create failed. wwpn already exists\n");
579                         goto error;
580                 }
581                 memcpy(csio_ln_wwpn(ln), wwn, 8);
582         }
583
584         fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
585
586         if (csio_fcoe_alloc_vnp(hw, ln))
587                 goto error;
588
589         *(struct csio_lnode **)fc_vport->dd_data = ln;
590         ln->fc_vport = fc_vport;
591         if (!fc_vport->node_name)
592                 fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln));
593         if (!fc_vport->port_name)
594                 fc_vport->port_name = wwn_to_u64(csio_ln_wwpn(ln));
595         csio_fchost_attr_init(ln);
596         return 0;
597 error:
598         if (ln)
599                 csio_shost_exit(ln);
600
601         return ret;
602 }
603
604 static int
605 csio_vport_delete(struct fc_vport *fc_vport)
606 {
607         struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;
608         struct Scsi_Host *shost = csio_ln_to_shost(ln);
609         struct csio_hw *hw = csio_lnode_to_hw(ln);
610         int rmv;
611
612         spin_lock_irq(&hw->lock);
613         rmv = csio_is_hw_removing(hw);
614         spin_unlock_irq(&hw->lock);
615
616         if (rmv) {
617                 csio_shost_exit(ln);
618                 return 0;
619         }
620
621         /* Quiesce ios and send remove event to lnode */
622         scsi_block_requests(shost);
623         spin_lock_irq(&hw->lock);
624         csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);
625         csio_lnode_close(ln);
626         spin_unlock_irq(&hw->lock);
627         scsi_unblock_requests(shost);
628
629         /* Free vnp */
630         if (fc_vport->vport_state !=  FC_VPORT_DISABLED)
631                 csio_fcoe_free_vnp(hw, ln);
632
633         csio_shost_exit(ln);
634         return 0;
635 }
636
637 static int
638 csio_vport_disable(struct fc_vport *fc_vport, bool disable)
639 {
640         struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;
641         struct Scsi_Host *shost = csio_ln_to_shost(ln);
642         struct csio_hw *hw = csio_lnode_to_hw(ln);
643
644         /* disable vport */
645         if (disable) {
646                 /* Quiesce ios and send stop event to lnode */
647                 scsi_block_requests(shost);
648                 spin_lock_irq(&hw->lock);
649                 csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);
650                 csio_lnode_stop(ln);
651                 spin_unlock_irq(&hw->lock);
652                 scsi_unblock_requests(shost);
653
654                 /* Free vnp */
655                 csio_fcoe_free_vnp(hw, ln);
656                 fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
657                 csio_ln_err(ln, "vport disabled\n");
658                 return 0;
659         } else {
660                 /* enable vport */
661                 fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
662                 if (csio_fcoe_alloc_vnp(hw, ln)) {
663                         csio_ln_err(ln, "vport enabled failed.\n");
664                         return -1;
665                 }
666                 csio_ln_err(ln, "vport enabled\n");
667                 return 0;
668         }
669 }
670
671 static void
672 csio_dev_loss_tmo_callbk(struct fc_rport *rport)
673 {
674         struct csio_rnode *rn;
675         struct csio_hw *hw;
676         struct csio_lnode *ln;
677
678         rn = *((struct csio_rnode **)rport->dd_data);
679         ln = csio_rnode_to_lnode(rn);
680         hw = csio_lnode_to_hw(ln);
681
682         spin_lock_irq(&hw->lock);
683
684         /* return if driver is being removed or same rnode comes back online */
685         if (csio_is_hw_removing(hw) || csio_is_rnode_ready(rn))
686                 goto out;
687
688         csio_ln_dbg(ln, "devloss timeout on rnode:%p portid:x%x flowid:x%x\n",
689                     rn, rn->nport_id, csio_rn_flowid(rn));
690
691         CSIO_INC_STATS(ln, n_dev_loss_tmo);
692
693         /*
694          * enqueue devloss event to event worker thread to serialize all
695          * rnode events.
696          */
697         if (csio_enqueue_evt(hw, CSIO_EVT_DEV_LOSS, &rn, sizeof(rn))) {
698                 CSIO_INC_STATS(hw, n_evt_drop);
699                 goto out;
700         }
701
702         if (!(hw->flags & CSIO_HWF_FWEVT_PENDING)) {
703                 hw->flags |= CSIO_HWF_FWEVT_PENDING;
704                 spin_unlock_irq(&hw->lock);
705                 schedule_work(&hw->evtq_work);
706                 return;
707         }
708
709 out:
710         spin_unlock_irq(&hw->lock);
711 }
712
713 /* FC transport functions template - Physical port */
714 struct fc_function_template csio_fc_transport_funcs = {
715         .show_host_node_name = 1,
716         .show_host_port_name = 1,
717         .show_host_supported_classes = 1,
718         .show_host_supported_fc4s = 1,
719         .show_host_maxframe_size = 1,
720
721         .get_host_port_id = csio_get_host_port_id,
722         .show_host_port_id = 1,
723
724         .get_host_port_type = csio_get_host_port_type,
725         .show_host_port_type = 1,
726
727         .get_host_port_state = csio_get_host_port_state,
728         .show_host_port_state = 1,
729
730         .show_host_active_fc4s = 1,
731         .get_host_speed = csio_get_host_speed,
732         .show_host_speed = 1,
733         .get_host_fabric_name = csio_get_host_fabric_name,
734         .show_host_fabric_name = 1,
735
736         .get_fc_host_stats = csio_get_stats,
737
738         .dd_fcrport_size = sizeof(struct csio_rnode *),
739         .show_rport_maxframe_size = 1,
740         .show_rport_supported_classes = 1,
741
742         .set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,
743         .show_rport_dev_loss_tmo = 1,
744
745         .show_starget_port_id = 1,
746         .show_starget_node_name = 1,
747         .show_starget_port_name = 1,
748
749         .dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,
750         .dd_fcvport_size = sizeof(struct csio_lnode *),
751
752         .vport_create = csio_vport_create,
753         .vport_disable = csio_vport_disable,
754         .vport_delete = csio_vport_delete,
755 };
756
757 /* FC transport functions template - Virtual  port */
758 struct fc_function_template csio_fc_transport_vport_funcs = {
759         .show_host_node_name = 1,
760         .show_host_port_name = 1,
761         .show_host_supported_classes = 1,
762         .show_host_supported_fc4s = 1,
763         .show_host_maxframe_size = 1,
764
765         .get_host_port_id = csio_get_host_port_id,
766         .show_host_port_id = 1,
767
768         .get_host_port_type = csio_get_host_port_type,
769         .show_host_port_type = 1,
770
771         .get_host_port_state = csio_get_host_port_state,
772         .show_host_port_state = 1,
773         .show_host_active_fc4s = 1,
774
775         .get_host_speed = csio_get_host_speed,
776         .show_host_speed = 1,
777
778         .get_host_fabric_name = csio_get_host_fabric_name,
779         .show_host_fabric_name = 1,
780
781         .get_fc_host_stats = csio_get_stats,
782
783         .dd_fcrport_size = sizeof(struct csio_rnode *),
784         .show_rport_maxframe_size = 1,
785         .show_rport_supported_classes = 1,
786
787         .set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,
788         .show_rport_dev_loss_tmo = 1,
789
790         .show_starget_port_id = 1,
791         .show_starget_node_name = 1,
792         .show_starget_port_name = 1,
793
794         .dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,
795
796 };