0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #include <linux/kernel.h>
0036 #include <linux/string.h>
0037 #include <linux/delay.h>
0038 #include <linux/module.h>
0039 #include <linux/init.h>
0040 #include <linux/pci.h>
0041 #include <linux/mm.h>
0042 #include <linux/jiffies.h>
0043 #include <scsi/fc/fc_fs.h>
0044
0045 #include "csio_init.h"
0046
0047 static void
0048 csio_vport_set_state(struct csio_lnode *ln);
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 void
0059 csio_reg_rnode(struct csio_rnode *rn)
0060 {
0061 struct csio_lnode *ln = csio_rnode_to_lnode(rn);
0062 struct Scsi_Host *shost = csio_ln_to_shost(ln);
0063 struct fc_rport_identifiers ids;
0064 struct fc_rport *rport;
0065 struct csio_service_parms *sp;
0066
0067 ids.node_name = wwn_to_u64(csio_rn_wwnn(rn));
0068 ids.port_name = wwn_to_u64(csio_rn_wwpn(rn));
0069 ids.port_id = rn->nport_id;
0070 ids.roles = FC_RPORT_ROLE_UNKNOWN;
0071
0072 if (rn->role & CSIO_RNFR_INITIATOR || rn->role & CSIO_RNFR_TARGET) {
0073 rport = rn->rport;
0074 CSIO_ASSERT(rport != NULL);
0075 goto update_role;
0076 }
0077
0078 rn->rport = fc_remote_port_add(shost, 0, &ids);
0079 if (!rn->rport) {
0080 csio_ln_err(ln, "Failed to register rport = 0x%x.\n",
0081 rn->nport_id);
0082 return;
0083 }
0084
0085 ln->num_reg_rnodes++;
0086 rport = rn->rport;
0087 spin_lock_irq(shost->host_lock);
0088 *((struct csio_rnode **)rport->dd_data) = rn;
0089 spin_unlock_irq(shost->host_lock);
0090
0091 sp = &rn->rn_sparm;
0092 rport->maxframe_size = ntohs(sp->csp.sp_bb_data);
0093 if (ntohs(sp->clsp[2].cp_class) & FC_CPC_VALID)
0094 rport->supported_classes = FC_COS_CLASS3;
0095 else
0096 rport->supported_classes = FC_COS_UNSPECIFIED;
0097 update_role:
0098 if (rn->role & CSIO_RNFR_INITIATOR)
0099 ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
0100 if (rn->role & CSIO_RNFR_TARGET)
0101 ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
0102
0103 if (ids.roles != FC_RPORT_ROLE_UNKNOWN)
0104 fc_remote_port_rolechg(rport, ids.roles);
0105
0106 rn->scsi_id = rport->scsi_target_id;
0107
0108 csio_ln_dbg(ln, "Remote port x%x role 0x%x registered\n",
0109 rn->nport_id, ids.roles);
0110 }
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 void
0121 csio_unreg_rnode(struct csio_rnode *rn)
0122 {
0123 struct csio_lnode *ln = csio_rnode_to_lnode(rn);
0124 struct fc_rport *rport = rn->rport;
0125
0126 rn->role &= ~(CSIO_RNFR_INITIATOR | CSIO_RNFR_TARGET);
0127 fc_remote_port_delete(rport);
0128 ln->num_reg_rnodes--;
0129
0130 csio_ln_dbg(ln, "Remote port x%x un-registered\n", rn->nport_id);
0131 }
0132
0133
0134
0135
0136
0137
0138
0139
0140 void
0141 csio_lnode_async_event(struct csio_lnode *ln, enum csio_ln_fc_evt fc_evt)
0142 {
0143 switch (fc_evt) {
0144 case CSIO_LN_FC_RSCN:
0145
0146
0147
0148
0149
0150
0151
0152
0153 break;
0154 case CSIO_LN_FC_LINKUP:
0155
0156
0157 if (csio_is_npiv_ln(ln))
0158 csio_vport_set_state(ln);
0159
0160 break;
0161 case CSIO_LN_FC_LINKDOWN:
0162
0163
0164 if (csio_is_npiv_ln(ln))
0165 csio_vport_set_state(ln);
0166
0167 break;
0168 case CSIO_LN_FC_ATTRIB_UPDATE:
0169 csio_fchost_attr_init(ln);
0170 break;
0171 default:
0172 break;
0173 }
0174 }
0175
0176
0177
0178
0179
0180
0181 void
0182 csio_fchost_attr_init(struct csio_lnode *ln)
0183 {
0184 struct Scsi_Host *shost = csio_ln_to_shost(ln);
0185
0186 fc_host_node_name(shost) = wwn_to_u64(csio_ln_wwnn(ln));
0187 fc_host_port_name(shost) = wwn_to_u64(csio_ln_wwpn(ln));
0188
0189 fc_host_supported_classes(shost) = FC_COS_CLASS3;
0190 fc_host_max_npiv_vports(shost) =
0191 (csio_lnode_to_hw(ln))->fres_info.max_vnps;
0192 fc_host_supported_speeds(shost) = FC_PORTSPEED_10GBIT |
0193 FC_PORTSPEED_1GBIT;
0194
0195 fc_host_maxframe_size(shost) = ntohs(ln->ln_sparm.csp.sp_bb_data);
0196 memset(fc_host_supported_fc4s(shost), 0,
0197 sizeof(fc_host_supported_fc4s(shost)));
0198 fc_host_supported_fc4s(shost)[7] = 1;
0199
0200 memset(fc_host_active_fc4s(shost), 0,
0201 sizeof(fc_host_active_fc4s(shost)));
0202 fc_host_active_fc4s(shost)[7] = 1;
0203 }
0204
0205
0206
0207
0208
0209 static void
0210 csio_get_host_port_id(struct Scsi_Host *shost)
0211 {
0212 struct csio_lnode *ln = shost_priv(shost);
0213 struct csio_hw *hw = csio_lnode_to_hw(ln);
0214
0215 spin_lock_irq(&hw->lock);
0216 fc_host_port_id(shost) = ln->nport_id;
0217 spin_unlock_irq(&hw->lock);
0218 }
0219
0220
0221
0222
0223
0224
0225 static void
0226 csio_get_host_port_type(struct Scsi_Host *shost)
0227 {
0228 struct csio_lnode *ln = shost_priv(shost);
0229 struct csio_hw *hw = csio_lnode_to_hw(ln);
0230
0231 spin_lock_irq(&hw->lock);
0232 if (csio_is_npiv_ln(ln))
0233 fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
0234 else
0235 fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
0236 spin_unlock_irq(&hw->lock);
0237 }
0238
0239
0240
0241
0242
0243
0244 static void
0245 csio_get_host_port_state(struct Scsi_Host *shost)
0246 {
0247 struct csio_lnode *ln = shost_priv(shost);
0248 struct csio_hw *hw = csio_lnode_to_hw(ln);
0249 char state[16];
0250
0251 spin_lock_irq(&hw->lock);
0252
0253 csio_lnode_state_to_str(ln, state);
0254 if (!strcmp(state, "READY"))
0255 fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
0256 else if (!strcmp(state, "OFFLINE"))
0257 fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
0258 else
0259 fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
0260
0261 spin_unlock_irq(&hw->lock);
0262 }
0263
0264
0265
0266
0267
0268
0269 static void
0270 csio_get_host_speed(struct Scsi_Host *shost)
0271 {
0272 struct csio_lnode *ln = shost_priv(shost);
0273 struct csio_hw *hw = csio_lnode_to_hw(ln);
0274
0275 spin_lock_irq(&hw->lock);
0276 switch (hw->pport[ln->portid].link_speed) {
0277 case FW_PORT_CAP32_SPEED_1G:
0278 fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
0279 break;
0280 case FW_PORT_CAP32_SPEED_10G:
0281 fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
0282 break;
0283 case FW_PORT_CAP32_SPEED_25G:
0284 fc_host_speed(shost) = FC_PORTSPEED_25GBIT;
0285 break;
0286 case FW_PORT_CAP32_SPEED_40G:
0287 fc_host_speed(shost) = FC_PORTSPEED_40GBIT;
0288 break;
0289 case FW_PORT_CAP32_SPEED_50G:
0290 fc_host_speed(shost) = FC_PORTSPEED_50GBIT;
0291 break;
0292 case FW_PORT_CAP32_SPEED_100G:
0293 fc_host_speed(shost) = FC_PORTSPEED_100GBIT;
0294 break;
0295 default:
0296 fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
0297 break;
0298 }
0299 spin_unlock_irq(&hw->lock);
0300 }
0301
0302
0303
0304
0305
0306
0307 static void
0308 csio_get_host_fabric_name(struct Scsi_Host *shost)
0309 {
0310 struct csio_lnode *ln = shost_priv(shost);
0311 struct csio_rnode *rn = NULL;
0312 struct csio_hw *hw = csio_lnode_to_hw(ln);
0313
0314 spin_lock_irq(&hw->lock);
0315 rn = csio_rnode_lookup_portid(ln, FC_FID_FLOGI);
0316 if (rn)
0317 fc_host_fabric_name(shost) = wwn_to_u64(csio_rn_wwnn(rn));
0318 else
0319 fc_host_fabric_name(shost) = 0;
0320 spin_unlock_irq(&hw->lock);
0321 }
0322
0323
0324
0325
0326
0327
0328 static struct fc_host_statistics *
0329 csio_get_stats(struct Scsi_Host *shost)
0330 {
0331 struct csio_lnode *ln = shost_priv(shost);
0332 struct csio_hw *hw = csio_lnode_to_hw(ln);
0333 struct fc_host_statistics *fhs = &ln->fch_stats;
0334 struct fw_fcoe_port_stats fcoe_port_stats;
0335 uint64_t seconds;
0336
0337 memset(&fcoe_port_stats, 0, sizeof(struct fw_fcoe_port_stats));
0338 csio_get_phy_port_stats(hw, ln->portid, &fcoe_port_stats);
0339
0340 fhs->tx_frames += (be64_to_cpu(fcoe_port_stats.tx_bcast_frames) +
0341 be64_to_cpu(fcoe_port_stats.tx_mcast_frames) +
0342 be64_to_cpu(fcoe_port_stats.tx_ucast_frames) +
0343 be64_to_cpu(fcoe_port_stats.tx_offload_frames));
0344 fhs->tx_words += (be64_to_cpu(fcoe_port_stats.tx_bcast_bytes) +
0345 be64_to_cpu(fcoe_port_stats.tx_mcast_bytes) +
0346 be64_to_cpu(fcoe_port_stats.tx_ucast_bytes) +
0347 be64_to_cpu(fcoe_port_stats.tx_offload_bytes)) /
0348 CSIO_WORD_TO_BYTE;
0349 fhs->rx_frames += (be64_to_cpu(fcoe_port_stats.rx_bcast_frames) +
0350 be64_to_cpu(fcoe_port_stats.rx_mcast_frames) +
0351 be64_to_cpu(fcoe_port_stats.rx_ucast_frames));
0352 fhs->rx_words += (be64_to_cpu(fcoe_port_stats.rx_bcast_bytes) +
0353 be64_to_cpu(fcoe_port_stats.rx_mcast_bytes) +
0354 be64_to_cpu(fcoe_port_stats.rx_ucast_bytes)) /
0355 CSIO_WORD_TO_BYTE;
0356 fhs->error_frames += be64_to_cpu(fcoe_port_stats.rx_err_frames);
0357 fhs->fcp_input_requests += ln->stats.n_input_requests;
0358 fhs->fcp_output_requests += ln->stats.n_output_requests;
0359 fhs->fcp_control_requests += ln->stats.n_control_requests;
0360 fhs->fcp_input_megabytes += ln->stats.n_input_bytes >> 20;
0361 fhs->fcp_output_megabytes += ln->stats.n_output_bytes >> 20;
0362 fhs->link_failure_count = ln->stats.n_link_down;
0363
0364 seconds = jiffies_to_msecs(jiffies) - hw->stats.n_reset_start;
0365 do_div(seconds, 1000);
0366 fhs->seconds_since_last_reset = seconds;
0367
0368 return fhs;
0369 }
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379 static void
0380 csio_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
0381 {
0382 if (timeout)
0383 rport->dev_loss_tmo = timeout;
0384 else
0385 rport->dev_loss_tmo = 1;
0386 }
0387
0388 static void
0389 csio_vport_set_state(struct csio_lnode *ln)
0390 {
0391 struct fc_vport *fc_vport = ln->fc_vport;
0392 struct csio_lnode *pln = ln->pln;
0393 char state[16];
0394
0395
0396 csio_lnode_state_to_str(pln, state);
0397 if (strcmp(state, "READY")) {
0398 fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
0399 return;
0400 }
0401
0402 if (!(pln->flags & CSIO_LNF_NPIVSUPP)) {
0403 fc_vport_set_state(fc_vport, FC_VPORT_NO_FABRIC_SUPP);
0404 return;
0405 }
0406
0407
0408 csio_lnode_state_to_str(ln, state);
0409 if (strcmp(state, "READY")) {
0410 fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
0411 return;
0412 }
0413 fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
0414 }
0415
0416 static int
0417 csio_fcoe_alloc_vnp(struct csio_hw *hw, struct csio_lnode *ln)
0418 {
0419 struct csio_lnode *pln;
0420 struct csio_mb *mbp;
0421 struct fw_fcoe_vnp_cmd *rsp;
0422 int ret = 0;
0423 int retry = 0;
0424
0425
0426
0427 spin_lock_irq(&hw->lock);
0428 mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
0429 if (!mbp) {
0430 CSIO_INC_STATS(hw, n_err_nomem);
0431 ret = -ENOMEM;
0432 goto out;
0433 }
0434
0435 pln = ln->pln;
0436 ln->fcf_flowid = pln->fcf_flowid;
0437 ln->portid = pln->portid;
0438
0439 csio_fcoe_vnp_alloc_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
0440 pln->fcf_flowid, pln->vnp_flowid, 0,
0441 csio_ln_wwnn(ln), csio_ln_wwpn(ln), NULL);
0442
0443 for (retry = 0; retry < 3; retry++) {
0444
0445
0446
0447
0448
0449 ret = csio_mb_issue(hw, mbp);
0450 if (ret != -EBUSY)
0451 break;
0452
0453
0454 spin_unlock_irq(&hw->lock);
0455 msleep(2000);
0456 spin_lock_irq(&hw->lock);
0457 }
0458
0459 if (ret) {
0460 csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");
0461 goto out_free;
0462 }
0463
0464
0465 rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
0466 if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {
0467 csio_ln_err(ln, "FCOE VNP ALLOC cmd returned 0x%x!\n",
0468 FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)));
0469 ret = -EINVAL;
0470 goto out_free;
0471 }
0472
0473 ln->vnp_flowid = FW_FCOE_VNP_CMD_VNPI_GET(
0474 ntohl(rsp->gen_wwn_to_vnpi));
0475 memcpy(csio_ln_wwnn(ln), rsp->vnport_wwnn, 8);
0476 memcpy(csio_ln_wwpn(ln), rsp->vnport_wwpn, 8);
0477
0478 csio_ln_dbg(ln, "FCOE VNPI: 0x%x\n", ln->vnp_flowid);
0479 csio_ln_dbg(ln, "\tWWNN: %x%x%x%x%x%x%x%x\n",
0480 ln->ln_sparm.wwnn[0], ln->ln_sparm.wwnn[1],
0481 ln->ln_sparm.wwnn[2], ln->ln_sparm.wwnn[3],
0482 ln->ln_sparm.wwnn[4], ln->ln_sparm.wwnn[5],
0483 ln->ln_sparm.wwnn[6], ln->ln_sparm.wwnn[7]);
0484 csio_ln_dbg(ln, "\tWWPN: %x%x%x%x%x%x%x%x\n",
0485 ln->ln_sparm.wwpn[0], ln->ln_sparm.wwpn[1],
0486 ln->ln_sparm.wwpn[2], ln->ln_sparm.wwpn[3],
0487 ln->ln_sparm.wwpn[4], ln->ln_sparm.wwpn[5],
0488 ln->ln_sparm.wwpn[6], ln->ln_sparm.wwpn[7]);
0489
0490 out_free:
0491 mempool_free(mbp, hw->mb_mempool);
0492 out:
0493 spin_unlock_irq(&hw->lock);
0494 return ret;
0495 }
0496
0497 static int
0498 csio_fcoe_free_vnp(struct csio_hw *hw, struct csio_lnode *ln)
0499 {
0500 struct csio_mb *mbp;
0501 struct fw_fcoe_vnp_cmd *rsp;
0502 int ret = 0;
0503 int retry = 0;
0504
0505
0506
0507
0508 spin_lock_irq(&hw->lock);
0509 mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
0510 if (!mbp) {
0511 CSIO_INC_STATS(hw, n_err_nomem);
0512 ret = -ENOMEM;
0513 goto out;
0514 }
0515
0516 csio_fcoe_vnp_free_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
0517 ln->fcf_flowid, ln->vnp_flowid,
0518 NULL);
0519
0520 for (retry = 0; retry < 3; retry++) {
0521 ret = csio_mb_issue(hw, mbp);
0522 if (ret != -EBUSY)
0523 break;
0524
0525
0526 spin_unlock_irq(&hw->lock);
0527 msleep(2000);
0528 spin_lock_irq(&hw->lock);
0529 }
0530
0531 if (ret) {
0532 csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");
0533 goto out_free;
0534 }
0535
0536
0537 rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
0538 if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {
0539 csio_ln_err(ln, "FCOE VNP FREE cmd returned 0x%x!\n",
0540 FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)));
0541 ret = -EINVAL;
0542 }
0543
0544 out_free:
0545 mempool_free(mbp, hw->mb_mempool);
0546 out:
0547 spin_unlock_irq(&hw->lock);
0548 return ret;
0549 }
0550
0551 static int
0552 csio_vport_create(struct fc_vport *fc_vport, bool disable)
0553 {
0554 struct Scsi_Host *shost = fc_vport->shost;
0555 struct csio_lnode *pln = shost_priv(shost);
0556 struct csio_lnode *ln = NULL;
0557 struct csio_hw *hw = csio_lnode_to_hw(pln);
0558 uint8_t wwn[8];
0559 int ret = -1;
0560
0561 ln = csio_shost_init(hw, &fc_vport->dev, false, pln);
0562 if (!ln)
0563 goto error;
0564
0565 if (fc_vport->node_name != 0) {
0566 u64_to_wwn(fc_vport->node_name, wwn);
0567
0568 if (!CSIO_VALID_WWN(wwn)) {
0569 csio_ln_err(ln,
0570 "vport create failed. Invalid wwnn\n");
0571 goto error;
0572 }
0573 memcpy(csio_ln_wwnn(ln), wwn, 8);
0574 }
0575
0576 if (fc_vport->port_name != 0) {
0577 u64_to_wwn(fc_vport->port_name, wwn);
0578
0579 if (!CSIO_VALID_WWN(wwn)) {
0580 csio_ln_err(ln,
0581 "vport create failed. Invalid wwpn\n");
0582 goto error;
0583 }
0584
0585 if (csio_lnode_lookup_by_wwpn(hw, wwn)) {
0586 csio_ln_err(ln,
0587 "vport create failed. wwpn already exists\n");
0588 goto error;
0589 }
0590 memcpy(csio_ln_wwpn(ln), wwn, 8);
0591 }
0592
0593 fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
0594 ln->fc_vport = fc_vport;
0595
0596 if (csio_fcoe_alloc_vnp(hw, ln))
0597 goto error;
0598
0599 *(struct csio_lnode **)fc_vport->dd_data = ln;
0600 if (!fc_vport->node_name)
0601 fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln));
0602 if (!fc_vport->port_name)
0603 fc_vport->port_name = wwn_to_u64(csio_ln_wwpn(ln));
0604 csio_fchost_attr_init(ln);
0605 return 0;
0606 error:
0607 if (ln)
0608 csio_shost_exit(ln);
0609
0610 return ret;
0611 }
0612
0613 static int
0614 csio_vport_delete(struct fc_vport *fc_vport)
0615 {
0616 struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;
0617 struct Scsi_Host *shost = csio_ln_to_shost(ln);
0618 struct csio_hw *hw = csio_lnode_to_hw(ln);
0619 int rmv;
0620
0621 spin_lock_irq(&hw->lock);
0622 rmv = csio_is_hw_removing(hw);
0623 spin_unlock_irq(&hw->lock);
0624
0625 if (rmv) {
0626 csio_shost_exit(ln);
0627 return 0;
0628 }
0629
0630
0631 scsi_block_requests(shost);
0632 spin_lock_irq(&hw->lock);
0633 csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);
0634 csio_lnode_close(ln);
0635 spin_unlock_irq(&hw->lock);
0636 scsi_unblock_requests(shost);
0637
0638
0639 if (fc_vport->vport_state != FC_VPORT_DISABLED)
0640 csio_fcoe_free_vnp(hw, ln);
0641
0642 csio_shost_exit(ln);
0643 return 0;
0644 }
0645
0646 static int
0647 csio_vport_disable(struct fc_vport *fc_vport, bool disable)
0648 {
0649 struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;
0650 struct Scsi_Host *shost = csio_ln_to_shost(ln);
0651 struct csio_hw *hw = csio_lnode_to_hw(ln);
0652
0653
0654 if (disable) {
0655
0656 scsi_block_requests(shost);
0657 spin_lock_irq(&hw->lock);
0658 csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);
0659 csio_lnode_stop(ln);
0660 spin_unlock_irq(&hw->lock);
0661 scsi_unblock_requests(shost);
0662
0663
0664 csio_fcoe_free_vnp(hw, ln);
0665 fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
0666 csio_ln_err(ln, "vport disabled\n");
0667 return 0;
0668 } else {
0669
0670 fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
0671 if (csio_fcoe_alloc_vnp(hw, ln)) {
0672 csio_ln_err(ln, "vport enabled failed.\n");
0673 return -1;
0674 }
0675 csio_ln_err(ln, "vport enabled\n");
0676 return 0;
0677 }
0678 }
0679
0680 static void
0681 csio_dev_loss_tmo_callbk(struct fc_rport *rport)
0682 {
0683 struct csio_rnode *rn;
0684 struct csio_hw *hw;
0685 struct csio_lnode *ln;
0686
0687 rn = *((struct csio_rnode **)rport->dd_data);
0688 ln = csio_rnode_to_lnode(rn);
0689 hw = csio_lnode_to_hw(ln);
0690
0691 spin_lock_irq(&hw->lock);
0692
0693
0694 if (csio_is_hw_removing(hw) || csio_is_rnode_ready(rn))
0695 goto out;
0696
0697 csio_ln_dbg(ln, "devloss timeout on rnode:%p portid:x%x flowid:x%x\n",
0698 rn, rn->nport_id, csio_rn_flowid(rn));
0699
0700 CSIO_INC_STATS(ln, n_dev_loss_tmo);
0701
0702
0703
0704
0705
0706 if (csio_enqueue_evt(hw, CSIO_EVT_DEV_LOSS, &rn, sizeof(rn))) {
0707 CSIO_INC_STATS(hw, n_evt_drop);
0708 goto out;
0709 }
0710
0711 if (!(hw->flags & CSIO_HWF_FWEVT_PENDING)) {
0712 hw->flags |= CSIO_HWF_FWEVT_PENDING;
0713 spin_unlock_irq(&hw->lock);
0714 schedule_work(&hw->evtq_work);
0715 return;
0716 }
0717
0718 out:
0719 spin_unlock_irq(&hw->lock);
0720 }
0721
0722
0723 struct fc_function_template csio_fc_transport_funcs = {
0724 .show_host_node_name = 1,
0725 .show_host_port_name = 1,
0726 .show_host_supported_classes = 1,
0727 .show_host_supported_fc4s = 1,
0728 .show_host_maxframe_size = 1,
0729
0730 .get_host_port_id = csio_get_host_port_id,
0731 .show_host_port_id = 1,
0732
0733 .get_host_port_type = csio_get_host_port_type,
0734 .show_host_port_type = 1,
0735
0736 .get_host_port_state = csio_get_host_port_state,
0737 .show_host_port_state = 1,
0738
0739 .show_host_active_fc4s = 1,
0740 .get_host_speed = csio_get_host_speed,
0741 .show_host_speed = 1,
0742 .get_host_fabric_name = csio_get_host_fabric_name,
0743 .show_host_fabric_name = 1,
0744
0745 .get_fc_host_stats = csio_get_stats,
0746
0747 .dd_fcrport_size = sizeof(struct csio_rnode *),
0748 .show_rport_maxframe_size = 1,
0749 .show_rport_supported_classes = 1,
0750
0751 .set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,
0752 .show_rport_dev_loss_tmo = 1,
0753
0754 .show_starget_port_id = 1,
0755 .show_starget_node_name = 1,
0756 .show_starget_port_name = 1,
0757
0758 .dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,
0759 .dd_fcvport_size = sizeof(struct csio_lnode *),
0760
0761 .vport_create = csio_vport_create,
0762 .vport_disable = csio_vport_disable,
0763 .vport_delete = csio_vport_delete,
0764 };
0765
0766
0767 struct fc_function_template csio_fc_transport_vport_funcs = {
0768 .show_host_node_name = 1,
0769 .show_host_port_name = 1,
0770 .show_host_supported_classes = 1,
0771 .show_host_supported_fc4s = 1,
0772 .show_host_maxframe_size = 1,
0773
0774 .get_host_port_id = csio_get_host_port_id,
0775 .show_host_port_id = 1,
0776
0777 .get_host_port_type = csio_get_host_port_type,
0778 .show_host_port_type = 1,
0779
0780 .get_host_port_state = csio_get_host_port_state,
0781 .show_host_port_state = 1,
0782 .show_host_active_fc4s = 1,
0783
0784 .get_host_speed = csio_get_host_speed,
0785 .show_host_speed = 1,
0786
0787 .get_host_fabric_name = csio_get_host_fabric_name,
0788 .show_host_fabric_name = 1,
0789
0790 .get_fc_host_stats = csio_get_stats,
0791
0792 .dd_fcrport_size = sizeof(struct csio_rnode *),
0793 .show_rport_maxframe_size = 1,
0794 .show_rport_supported_classes = 1,
0795
0796 .set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,
0797 .show_rport_dev_loss_tmo = 1,
0798
0799 .show_starget_port_id = 1,
0800 .show_starget_node_name = 1,
0801 .show_starget_port_name = 1,
0802
0803 .dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,
0804
0805 };