0001
0002
0003
0004
0005
0006
0007 #include "efct_driver.h"
0008 #include "efct_unsol.h"
0009
0010 static struct dentry *efct_debugfs_root;
0011 static atomic_t efct_debugfs_count;
0012
0013 static struct scsi_host_template efct_template = {
0014 .module = THIS_MODULE,
0015 .name = EFCT_DRIVER_NAME,
0016 .supported_mode = MODE_TARGET,
0017 };
0018
0019
0020 static struct fc_function_template efct_xport_functions;
0021 static struct fc_function_template efct_vport_functions;
0022
0023 static struct scsi_transport_template *efct_xport_fc_tt;
0024 static struct scsi_transport_template *efct_vport_fc_tt;
0025
0026 struct efct_xport *
0027 efct_xport_alloc(struct efct *efct)
0028 {
0029 struct efct_xport *xport;
0030
0031 xport = kzalloc(sizeof(*xport), GFP_KERNEL);
0032 if (!xport)
0033 return xport;
0034
0035 xport->efct = efct;
0036 return xport;
0037 }
0038
0039 static int
0040 efct_xport_init_debugfs(struct efct *efct)
0041 {
0042
0043 if (!efct_debugfs_root) {
0044 efct_debugfs_root = debugfs_create_dir("efct", NULL);
0045 atomic_set(&efct_debugfs_count, 0);
0046 }
0047
0048
0049 if (!efct->sess_debugfs_dir) {
0050 efct->sess_debugfs_dir = debugfs_create_dir("sessions",
0051 efct_debugfs_root);
0052 if (IS_ERR(efct->sess_debugfs_dir)) {
0053 efc_log_err(efct,
0054 "failed to create debugfs entry for sessions\n");
0055 goto debugfs_fail;
0056 }
0057 atomic_inc(&efct_debugfs_count);
0058 }
0059
0060 return 0;
0061
0062 debugfs_fail:
0063 return -EIO;
0064 }
0065
0066 static void efct_xport_delete_debugfs(struct efct *efct)
0067 {
0068
0069 debugfs_remove(efct->sess_debugfs_dir);
0070 efct->sess_debugfs_dir = NULL;
0071 atomic_dec(&efct_debugfs_count);
0072
0073 if (atomic_read(&efct_debugfs_count) == 0) {
0074
0075 debugfs_remove(efct_debugfs_root);
0076 efct_debugfs_root = NULL;
0077 }
0078 }
0079
0080 int
0081 efct_xport_attach(struct efct_xport *xport)
0082 {
0083 struct efct *efct = xport->efct;
0084 int rc;
0085
0086 rc = efct_hw_setup(&efct->hw, efct, efct->pci);
0087 if (rc) {
0088 efc_log_err(efct, "%s: Can't setup hardware\n", efct->desc);
0089 return rc;
0090 }
0091
0092 efct_hw_parse_filter(&efct->hw, (void *)efct->filter_def);
0093
0094 xport->io_pool = efct_io_pool_create(efct, efct->hw.config.n_sgl);
0095 if (!xport->io_pool) {
0096 efc_log_err(efct, "Can't allocate IO pool\n");
0097 return -ENOMEM;
0098 }
0099
0100 return 0;
0101 }
0102
0103 static void
0104 efct_xport_link_stats_cb(int status, u32 num_counters,
0105 struct efct_hw_link_stat_counts *counters, void *arg)
0106 {
0107 union efct_xport_stats_u *result = arg;
0108
0109 result->stats.link_stats.link_failure_error_count =
0110 counters[EFCT_HW_LINK_STAT_LINK_FAILURE_COUNT].counter;
0111 result->stats.link_stats.loss_of_sync_error_count =
0112 counters[EFCT_HW_LINK_STAT_LOSS_OF_SYNC_COUNT].counter;
0113 result->stats.link_stats.primitive_sequence_error_count =
0114 counters[EFCT_HW_LINK_STAT_PRIMITIVE_SEQ_COUNT].counter;
0115 result->stats.link_stats.invalid_transmission_word_error_count =
0116 counters[EFCT_HW_LINK_STAT_INVALID_XMIT_WORD_COUNT].counter;
0117 result->stats.link_stats.crc_error_count =
0118 counters[EFCT_HW_LINK_STAT_CRC_COUNT].counter;
0119
0120 complete(&result->stats.done);
0121 }
0122
0123 static void
0124 efct_xport_host_stats_cb(int status, u32 num_counters,
0125 struct efct_hw_host_stat_counts *counters, void *arg)
0126 {
0127 union efct_xport_stats_u *result = arg;
0128
0129 result->stats.host_stats.transmit_kbyte_count =
0130 counters[EFCT_HW_HOST_STAT_TX_KBYTE_COUNT].counter;
0131 result->stats.host_stats.receive_kbyte_count =
0132 counters[EFCT_HW_HOST_STAT_RX_KBYTE_COUNT].counter;
0133 result->stats.host_stats.transmit_frame_count =
0134 counters[EFCT_HW_HOST_STAT_TX_FRAME_COUNT].counter;
0135 result->stats.host_stats.receive_frame_count =
0136 counters[EFCT_HW_HOST_STAT_RX_FRAME_COUNT].counter;
0137
0138 complete(&result->stats.done);
0139 }
0140
0141 static void
0142 efct_xport_async_link_stats_cb(int status, u32 num_counters,
0143 struct efct_hw_link_stat_counts *counters,
0144 void *arg)
0145 {
0146 union efct_xport_stats_u *result = arg;
0147
0148 result->stats.link_stats.link_failure_error_count =
0149 counters[EFCT_HW_LINK_STAT_LINK_FAILURE_COUNT].counter;
0150 result->stats.link_stats.loss_of_sync_error_count =
0151 counters[EFCT_HW_LINK_STAT_LOSS_OF_SYNC_COUNT].counter;
0152 result->stats.link_stats.primitive_sequence_error_count =
0153 counters[EFCT_HW_LINK_STAT_PRIMITIVE_SEQ_COUNT].counter;
0154 result->stats.link_stats.invalid_transmission_word_error_count =
0155 counters[EFCT_HW_LINK_STAT_INVALID_XMIT_WORD_COUNT].counter;
0156 result->stats.link_stats.crc_error_count =
0157 counters[EFCT_HW_LINK_STAT_CRC_COUNT].counter;
0158 }
0159
0160 static void
0161 efct_xport_async_host_stats_cb(int status, u32 num_counters,
0162 struct efct_hw_host_stat_counts *counters,
0163 void *arg)
0164 {
0165 union efct_xport_stats_u *result = arg;
0166
0167 result->stats.host_stats.transmit_kbyte_count =
0168 counters[EFCT_HW_HOST_STAT_TX_KBYTE_COUNT].counter;
0169 result->stats.host_stats.receive_kbyte_count =
0170 counters[EFCT_HW_HOST_STAT_RX_KBYTE_COUNT].counter;
0171 result->stats.host_stats.transmit_frame_count =
0172 counters[EFCT_HW_HOST_STAT_TX_FRAME_COUNT].counter;
0173 result->stats.host_stats.receive_frame_count =
0174 counters[EFCT_HW_HOST_STAT_RX_FRAME_COUNT].counter;
0175 }
0176
0177 static void
0178 efct_xport_config_stats_timer(struct efct *efct);
0179
0180 static void
0181 efct_xport_stats_timer_cb(struct timer_list *t)
0182 {
0183 struct efct_xport *xport = from_timer(xport, t, stats_timer);
0184 struct efct *efct = xport->efct;
0185
0186 efct_xport_config_stats_timer(efct);
0187 }
0188
0189 static void
0190 efct_xport_config_stats_timer(struct efct *efct)
0191 {
0192 u32 timeout = 3 * 1000;
0193 struct efct_xport *xport = NULL;
0194
0195 if (!efct) {
0196 pr_err("%s: failed to locate EFCT device\n", __func__);
0197 return;
0198 }
0199
0200 xport = efct->xport;
0201 efct_hw_get_link_stats(&efct->hw, 0, 0, 0,
0202 efct_xport_async_link_stats_cb,
0203 &xport->fc_xport_stats);
0204 efct_hw_get_host_stats(&efct->hw, 0, efct_xport_async_host_stats_cb,
0205 &xport->fc_xport_stats);
0206
0207 timer_setup(&xport->stats_timer,
0208 &efct_xport_stats_timer_cb, 0);
0209 mod_timer(&xport->stats_timer,
0210 jiffies + msecs_to_jiffies(timeout));
0211 }
0212
0213 int
0214 efct_xport_initialize(struct efct_xport *xport)
0215 {
0216 struct efct *efct = xport->efct;
0217 int rc = 0;
0218
0219
0220 spin_lock_init(&xport->io_pending_lock);
0221 INIT_LIST_HEAD(&xport->io_pending_list);
0222 atomic_set(&xport->io_active_count, 0);
0223 atomic_set(&xport->io_pending_count, 0);
0224 atomic_set(&xport->io_total_free, 0);
0225 atomic_set(&xport->io_total_pending, 0);
0226 atomic_set(&xport->io_alloc_failed_count, 0);
0227 atomic_set(&xport->io_pending_recursing, 0);
0228
0229 rc = efct_hw_init(&efct->hw);
0230 if (rc) {
0231 efc_log_err(efct, "efct_hw_init failure\n");
0232 goto out;
0233 }
0234
0235 rc = efct_scsi_tgt_new_device(efct);
0236 if (rc) {
0237 efc_log_err(efct, "failed to initialize target\n");
0238 goto hw_init_out;
0239 }
0240
0241 rc = efct_scsi_new_device(efct);
0242 if (rc) {
0243 efc_log_err(efct, "failed to initialize initiator\n");
0244 goto tgt_dev_out;
0245 }
0246
0247
0248 efct_xport_config_stats_timer(efct);
0249
0250 efct_xport_init_debugfs(efct);
0251
0252 return rc;
0253
0254 tgt_dev_out:
0255 efct_scsi_tgt_del_device(efct);
0256
0257 hw_init_out:
0258 efct_hw_teardown(&efct->hw);
0259 out:
0260 return rc;
0261 }
0262
0263 int
0264 efct_xport_status(struct efct_xport *xport, enum efct_xport_status cmd,
0265 union efct_xport_stats_u *result)
0266 {
0267 int rc = 0;
0268 struct efct *efct = NULL;
0269 union efct_xport_stats_u value;
0270
0271 efct = xport->efct;
0272
0273 switch (cmd) {
0274 case EFCT_XPORT_CONFIG_PORT_STATUS:
0275 if (xport->configured_link_state == 0) {
0276
0277
0278
0279
0280 xport->configured_link_state = EFCT_XPORT_PORT_OFFLINE;
0281 }
0282 result->value = xport->configured_link_state;
0283 break;
0284
0285 case EFCT_XPORT_PORT_STATUS:
0286
0287 value.value = efct_hw_get_link_speed(&efct->hw);
0288 if (value.value == 0)
0289 result->value = EFCT_XPORT_PORT_OFFLINE;
0290 else
0291 result->value = EFCT_XPORT_PORT_ONLINE;
0292 break;
0293
0294 case EFCT_XPORT_LINK_SPEED:
0295 result->value = efct_hw_get_link_speed(&efct->hw);
0296 break;
0297
0298 case EFCT_XPORT_LINK_STATISTICS:
0299 memcpy((void *)result, &efct->xport->fc_xport_stats,
0300 sizeof(union efct_xport_stats_u));
0301 break;
0302 case EFCT_XPORT_LINK_STAT_RESET: {
0303
0304 init_completion(&result->stats.done);
0305
0306
0307 rc = efct_hw_get_link_stats(&efct->hw, 0, 1, 1,
0308 efct_xport_link_stats_cb, result);
0309 if (rc)
0310 break;
0311
0312
0313 if (wait_for_completion_interruptible(&result->stats.done)) {
0314
0315 efc_log_debug(efct, "sem wait failed\n");
0316 rc = -EIO;
0317 break;
0318 }
0319
0320
0321 rc = efct_hw_get_host_stats(&efct->hw, 1,
0322 efct_xport_host_stats_cb, result);
0323
0324 if (rc)
0325 break;
0326
0327
0328 if (wait_for_completion_interruptible(&result->stats.done)) {
0329
0330 efc_log_debug(efct, "sem wait failed\n");
0331 rc = -EIO;
0332 break;
0333 }
0334 break;
0335 }
0336 default:
0337 rc = -EIO;
0338 break;
0339 }
0340
0341 return rc;
0342 }
0343
0344 static int
0345 efct_get_link_supported_speeds(struct efct *efct)
0346 {
0347 u32 supported_speeds = 0;
0348 u32 link_module_type, i;
0349 struct {
0350 u32 lmt_speed;
0351 u32 speed;
0352 } supported_speed_list[] = {
0353 {SLI4_LINK_MODULE_TYPE_1GB, FC_PORTSPEED_1GBIT},
0354 {SLI4_LINK_MODULE_TYPE_2GB, FC_PORTSPEED_2GBIT},
0355 {SLI4_LINK_MODULE_TYPE_4GB, FC_PORTSPEED_4GBIT},
0356 {SLI4_LINK_MODULE_TYPE_8GB, FC_PORTSPEED_8GBIT},
0357 {SLI4_LINK_MODULE_TYPE_16GB, FC_PORTSPEED_16GBIT},
0358 {SLI4_LINK_MODULE_TYPE_32GB, FC_PORTSPEED_32GBIT},
0359 {SLI4_LINK_MODULE_TYPE_64GB, FC_PORTSPEED_64GBIT},
0360 {SLI4_LINK_MODULE_TYPE_128GB, FC_PORTSPEED_128GBIT},
0361 };
0362
0363 link_module_type = sli_get_lmt(&efct->hw.sli);
0364
0365
0366 for (i = 0; i < ARRAY_SIZE(supported_speed_list); i++) {
0367 if (link_module_type & supported_speed_list[i].lmt_speed)
0368 supported_speeds |= supported_speed_list[i].speed;
0369 }
0370
0371 return supported_speeds;
0372 }
0373
0374 int
0375 efct_scsi_new_device(struct efct *efct)
0376 {
0377 struct Scsi_Host *shost = NULL;
0378 int error = 0;
0379 struct efct_vport *vport = NULL;
0380
0381 shost = scsi_host_alloc(&efct_template, sizeof(*vport));
0382 if (!shost) {
0383 efc_log_err(efct, "failed to allocate Scsi_Host struct\n");
0384 return -ENOMEM;
0385 }
0386
0387
0388 efct->shost = shost;
0389
0390
0391 vport = (struct efct_vport *)shost->hostdata;
0392 vport->efct = efct;
0393
0394
0395
0396
0397
0398
0399 shost->can_queue = efct->hw.config.n_io;
0400 shost->max_cmd_len = 16;
0401 shost->max_id = 0xffff;
0402 shost->max_lun = 0xffffffff;
0403
0404
0405
0406
0407
0408 shost->sg_tablesize = sli_get_max_sgl(&efct->hw.sli);
0409
0410
0411 shost->transportt = efct_xport_fc_tt;
0412 efc_log_debug(efct, "transport template=%p\n", efct_xport_fc_tt);
0413
0414
0415 error = scsi_add_host_with_dma(shost, &efct->pci->dev,
0416 &efct->pci->dev);
0417 if (error) {
0418 efc_log_debug(efct, "failed scsi_add_host_with_dma\n");
0419 return -EIO;
0420 }
0421
0422
0423 snprintf(fc_host_symbolic_name(shost),
0424 sizeof(fc_host_symbolic_name(shost)),
0425 "Emulex %s FV%s DV%s", efct->model,
0426 efct->hw.sli.fw_name[0], EFCT_DRIVER_VERSION);
0427
0428
0429 fc_host_supported_classes(shost) = FC_COS_CLASS3;
0430
0431 fc_host_supported_speeds(shost) = efct_get_link_supported_speeds(efct);
0432
0433 fc_host_node_name(shost) = efct_get_wwnn(&efct->hw);
0434 fc_host_port_name(shost) = efct_get_wwpn(&efct->hw);
0435 fc_host_max_npiv_vports(shost) = 128;
0436
0437 return 0;
0438 }
0439
0440 struct scsi_transport_template *
0441 efct_attach_fc_transport(void)
0442 {
0443 struct scsi_transport_template *efct_fc_template = NULL;
0444
0445 efct_fc_template = fc_attach_transport(&efct_xport_functions);
0446
0447 if (!efct_fc_template)
0448 pr_err("failed to attach EFCT with fc transport\n");
0449
0450 return efct_fc_template;
0451 }
0452
0453 struct scsi_transport_template *
0454 efct_attach_vport_fc_transport(void)
0455 {
0456 struct scsi_transport_template *efct_fc_template = NULL;
0457
0458 efct_fc_template = fc_attach_transport(&efct_vport_functions);
0459
0460 if (!efct_fc_template)
0461 pr_err("failed to attach EFCT with fc transport\n");
0462
0463 return efct_fc_template;
0464 }
0465
0466 int
0467 efct_scsi_reg_fc_transport(void)
0468 {
0469
0470 efct_xport_fc_tt = efct_attach_fc_transport();
0471 if (!efct_xport_fc_tt) {
0472 pr_err("%s: failed to attach to scsi_transport_*", __func__);
0473 return -EIO;
0474 }
0475
0476 efct_vport_fc_tt = efct_attach_vport_fc_transport();
0477 if (!efct_vport_fc_tt) {
0478 pr_err("%s: failed to attach to scsi_transport_*", __func__);
0479 efct_release_fc_transport(efct_xport_fc_tt);
0480 efct_xport_fc_tt = NULL;
0481 return -EIO;
0482 }
0483
0484 return 0;
0485 }
0486
0487 void
0488 efct_scsi_release_fc_transport(void)
0489 {
0490
0491 efct_release_fc_transport(efct_xport_fc_tt);
0492 efct_xport_fc_tt = NULL;
0493 if (efct_vport_fc_tt)
0494 efct_release_fc_transport(efct_vport_fc_tt);
0495
0496 efct_vport_fc_tt = NULL;
0497 }
0498
0499 void
0500 efct_xport_detach(struct efct_xport *xport)
0501 {
0502 struct efct *efct = xport->efct;
0503
0504
0505 efct_scsi_tgt_del_device(efct);
0506
0507 efct_scsi_del_device(efct);
0508
0509
0510 if (timer_pending(&xport->stats_timer))
0511 del_timer(&xport->stats_timer);
0512
0513 efct_hw_teardown(&efct->hw);
0514
0515 efct_xport_delete_debugfs(efct);
0516 }
0517
0518 static void
0519 efct_xport_domain_free_cb(struct efc *efc, void *arg)
0520 {
0521 struct completion *done = arg;
0522
0523 complete(done);
0524 }
0525
0526 int
0527 efct_xport_control(struct efct_xport *xport, enum efct_xport_ctrl cmd, ...)
0528 {
0529 u32 rc = 0;
0530 struct efct *efct = NULL;
0531 va_list argp;
0532
0533 efct = xport->efct;
0534
0535 switch (cmd) {
0536 case EFCT_XPORT_PORT_ONLINE: {
0537
0538 rc = efct_hw_port_control(&efct->hw, EFCT_HW_PORT_INIT, 0,
0539 NULL, NULL);
0540 if (rc)
0541 efc_log_err(efct,
0542 "%s: Can't init port\n", efct->desc);
0543 else
0544 xport->configured_link_state = cmd;
0545 break;
0546 }
0547 case EFCT_XPORT_PORT_OFFLINE: {
0548 if (efct_hw_port_control(&efct->hw, EFCT_HW_PORT_SHUTDOWN, 0,
0549 NULL, NULL))
0550 efc_log_err(efct, "port shutdown failed\n");
0551 else
0552 xport->configured_link_state = cmd;
0553 break;
0554 }
0555
0556 case EFCT_XPORT_SHUTDOWN: {
0557 struct completion done;
0558 unsigned long timeout;
0559
0560
0561
0562
0563
0564 if (sli_reset_required(&efct->hw.sli)) {
0565 struct efc_domain *domain = efct->efcport->domain;
0566
0567 if (domain)
0568 efc_domain_cb(efct->efcport, EFC_HW_DOMAIN_LOST,
0569 domain);
0570 } else {
0571 efct_hw_port_control(&efct->hw, EFCT_HW_PORT_SHUTDOWN,
0572 0, NULL, NULL);
0573 }
0574
0575 init_completion(&done);
0576
0577 efc_register_domain_free_cb(efct->efcport,
0578 efct_xport_domain_free_cb, &done);
0579
0580 efc_log_debug(efct, "Waiting %d seconds for domain shutdown\n",
0581 (EFC_SHUTDOWN_TIMEOUT_USEC / 1000000));
0582
0583 timeout = usecs_to_jiffies(EFC_SHUTDOWN_TIMEOUT_USEC);
0584 if (!wait_for_completion_timeout(&done, timeout)) {
0585 efc_log_err(efct, "Domain shutdown timed out!!\n");
0586 WARN_ON(1);
0587 }
0588
0589 efc_register_domain_free_cb(efct->efcport, NULL, NULL);
0590
0591
0592 efc_vport_del_all(efct->efcport);
0593 break;
0594 }
0595
0596
0597
0598
0599
0600 case EFCT_XPORT_WWNN_SET: {
0601 u64 wwnn;
0602
0603
0604 va_start(argp, cmd);
0605 wwnn = va_arg(argp, uint64_t);
0606 va_end(argp);
0607
0608 efc_log_debug(efct, " WWNN %016llx\n", wwnn);
0609 xport->req_wwnn = wwnn;
0610
0611 break;
0612 }
0613
0614
0615
0616
0617 case EFCT_XPORT_WWPN_SET: {
0618 u64 wwpn;
0619
0620
0621 va_start(argp, cmd);
0622 wwpn = va_arg(argp, uint64_t);
0623 va_end(argp);
0624
0625 efc_log_debug(efct, " WWPN %016llx\n", wwpn);
0626 xport->req_wwpn = wwpn;
0627
0628 break;
0629 }
0630
0631 default:
0632 break;
0633 }
0634 return rc;
0635 }
0636
0637 void
0638 efct_xport_free(struct efct_xport *xport)
0639 {
0640 if (xport) {
0641 efct_io_pool_free(xport->io_pool);
0642
0643 kfree(xport);
0644 }
0645 }
0646
0647 void
0648 efct_release_fc_transport(struct scsi_transport_template *transport_template)
0649 {
0650 if (transport_template)
0651 pr_err("releasing transport layer\n");
0652
0653
0654 fc_release_transport(transport_template);
0655 }
0656
0657 static void
0658 efct_xport_remove_host(struct Scsi_Host *shost)
0659 {
0660 fc_remove_host(shost);
0661 }
0662
0663 void
0664 efct_scsi_del_device(struct efct *efct)
0665 {
0666 if (!efct->shost)
0667 return;
0668
0669 efc_log_debug(efct, "Unregistering with Transport Layer\n");
0670 efct_xport_remove_host(efct->shost);
0671 efc_log_debug(efct, "Unregistering with SCSI Midlayer\n");
0672 scsi_remove_host(efct->shost);
0673 scsi_host_put(efct->shost);
0674 efct->shost = NULL;
0675 }
0676
0677 static void
0678 efct_get_host_port_id(struct Scsi_Host *shost)
0679 {
0680 struct efct_vport *vport = (struct efct_vport *)shost->hostdata;
0681 struct efct *efct = vport->efct;
0682 struct efc *efc = efct->efcport;
0683 struct efc_nport *nport;
0684
0685 if (efc->domain && efc->domain->nport) {
0686 nport = efc->domain->nport;
0687 fc_host_port_id(shost) = nport->fc_id;
0688 }
0689 }
0690
0691 static void
0692 efct_get_host_port_type(struct Scsi_Host *shost)
0693 {
0694 struct efct_vport *vport = (struct efct_vport *)shost->hostdata;
0695 struct efct *efct = vport->efct;
0696 struct efc *efc = efct->efcport;
0697 int type = FC_PORTTYPE_UNKNOWN;
0698
0699 if (efc->domain && efc->domain->nport) {
0700 if (efc->domain->is_loop) {
0701 type = FC_PORTTYPE_LPORT;
0702 } else {
0703 struct efc_nport *nport = efc->domain->nport;
0704
0705 if (nport->is_vport)
0706 type = FC_PORTTYPE_NPIV;
0707 else if (nport->topology == EFC_NPORT_TOPO_P2P)
0708 type = FC_PORTTYPE_PTP;
0709 else if (nport->topology == EFC_NPORT_TOPO_UNKNOWN)
0710 type = FC_PORTTYPE_UNKNOWN;
0711 else
0712 type = FC_PORTTYPE_NPORT;
0713 }
0714 }
0715 fc_host_port_type(shost) = type;
0716 }
0717
0718 static void
0719 efct_get_host_vport_type(struct Scsi_Host *shost)
0720 {
0721 fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
0722 }
0723
0724 static void
0725 efct_get_host_port_state(struct Scsi_Host *shost)
0726 {
0727 struct efct_vport *vport = (struct efct_vport *)shost->hostdata;
0728 struct efct *efct = vport->efct;
0729 union efct_xport_stats_u status;
0730 int rc;
0731
0732 rc = efct_xport_status(efct->xport, EFCT_XPORT_PORT_STATUS, &status);
0733 if ((!rc) && (status.value == EFCT_XPORT_PORT_ONLINE))
0734 fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
0735 else
0736 fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
0737 }
0738
0739 static void
0740 efct_get_host_speed(struct Scsi_Host *shost)
0741 {
0742 struct efct_vport *vport = (struct efct_vport *)shost->hostdata;
0743 struct efct *efct = vport->efct;
0744 struct efc *efc = efct->efcport;
0745 union efct_xport_stats_u speed;
0746 u32 fc_speed = FC_PORTSPEED_UNKNOWN;
0747 int rc;
0748
0749 if (!efc->domain || !efc->domain->nport) {
0750 fc_host_speed(shost) = fc_speed;
0751 return;
0752 }
0753
0754 rc = efct_xport_status(efct->xport, EFCT_XPORT_LINK_SPEED, &speed);
0755 if (!rc) {
0756 switch (speed.value) {
0757 case 1000:
0758 fc_speed = FC_PORTSPEED_1GBIT;
0759 break;
0760 case 2000:
0761 fc_speed = FC_PORTSPEED_2GBIT;
0762 break;
0763 case 4000:
0764 fc_speed = FC_PORTSPEED_4GBIT;
0765 break;
0766 case 8000:
0767 fc_speed = FC_PORTSPEED_8GBIT;
0768 break;
0769 case 10000:
0770 fc_speed = FC_PORTSPEED_10GBIT;
0771 break;
0772 case 16000:
0773 fc_speed = FC_PORTSPEED_16GBIT;
0774 break;
0775 case 32000:
0776 fc_speed = FC_PORTSPEED_32GBIT;
0777 break;
0778 case 64000:
0779 fc_speed = FC_PORTSPEED_64GBIT;
0780 break;
0781 case 128000:
0782 fc_speed = FC_PORTSPEED_128GBIT;
0783 break;
0784 }
0785 }
0786
0787 fc_host_speed(shost) = fc_speed;
0788 }
0789
0790 static void
0791 efct_get_host_fabric_name(struct Scsi_Host *shost)
0792 {
0793 struct efct_vport *vport = (struct efct_vport *)shost->hostdata;
0794 struct efct *efct = vport->efct;
0795 struct efc *efc = efct->efcport;
0796
0797 if (efc->domain) {
0798 struct fc_els_flogi *sp =
0799 (struct fc_els_flogi *)
0800 efc->domain->flogi_service_params;
0801
0802 fc_host_fabric_name(shost) = be64_to_cpu(sp->fl_wwnn);
0803 }
0804 }
0805
0806 static struct fc_host_statistics *
0807 efct_get_stats(struct Scsi_Host *shost)
0808 {
0809 struct efct_vport *vport = (struct efct_vport *)shost->hostdata;
0810 struct efct *efct = vport->efct;
0811 union efct_xport_stats_u stats;
0812 struct efct_xport *xport = efct->xport;
0813 int rc = 0;
0814
0815 rc = efct_xport_status(xport, EFCT_XPORT_LINK_STATISTICS, &stats);
0816 if (rc) {
0817 pr_err("efct_xport_status returned non 0 - %d\n", rc);
0818 return NULL;
0819 }
0820
0821 vport->fc_host_stats.loss_of_sync_count =
0822 stats.stats.link_stats.loss_of_sync_error_count;
0823 vport->fc_host_stats.link_failure_count =
0824 stats.stats.link_stats.link_failure_error_count;
0825 vport->fc_host_stats.prim_seq_protocol_err_count =
0826 stats.stats.link_stats.primitive_sequence_error_count;
0827 vport->fc_host_stats.invalid_tx_word_count =
0828 stats.stats.link_stats.invalid_transmission_word_error_count;
0829 vport->fc_host_stats.invalid_crc_count =
0830 stats.stats.link_stats.crc_error_count;
0831
0832 vport->fc_host_stats.tx_words =
0833 stats.stats.host_stats.transmit_kbyte_count * 256;
0834
0835 vport->fc_host_stats.rx_words =
0836 stats.stats.host_stats.receive_kbyte_count * 256;
0837 vport->fc_host_stats.tx_frames =
0838 stats.stats.host_stats.transmit_frame_count;
0839 vport->fc_host_stats.rx_frames =
0840 stats.stats.host_stats.receive_frame_count;
0841
0842 vport->fc_host_stats.fcp_input_requests =
0843 xport->fcp_stats.input_requests;
0844 vport->fc_host_stats.fcp_output_requests =
0845 xport->fcp_stats.output_requests;
0846 vport->fc_host_stats.fcp_output_megabytes =
0847 xport->fcp_stats.output_bytes >> 20;
0848 vport->fc_host_stats.fcp_input_megabytes =
0849 xport->fcp_stats.input_bytes >> 20;
0850 vport->fc_host_stats.fcp_control_requests =
0851 xport->fcp_stats.control_requests;
0852
0853 return &vport->fc_host_stats;
0854 }
0855
0856 static void
0857 efct_reset_stats(struct Scsi_Host *shost)
0858 {
0859 struct efct_vport *vport = (struct efct_vport *)shost->hostdata;
0860 struct efct *efct = vport->efct;
0861
0862 union efct_xport_stats_u dummy;
0863 int rc;
0864
0865 rc = efct_xport_status(efct->xport, EFCT_XPORT_LINK_STAT_RESET, &dummy);
0866 if (rc)
0867 pr_err("efct_xport_status returned non 0 - %d\n", rc);
0868 }
0869
0870 static int
0871 efct_issue_lip(struct Scsi_Host *shost)
0872 {
0873 struct efct_vport *vport =
0874 shost ? (struct efct_vport *)shost->hostdata : NULL;
0875 struct efct *efct = vport ? vport->efct : NULL;
0876
0877 if (!shost || !vport || !efct) {
0878 pr_err("%s: shost=%p vport=%p efct=%p\n", __func__,
0879 shost, vport, efct);
0880 return -EPERM;
0881 }
0882
0883
0884
0885
0886
0887
0888
0889 if (efct_xport_control(efct->xport, EFCT_XPORT_PORT_OFFLINE))
0890 efc_log_debug(efct, "EFCT_XPORT_PORT_OFFLINE failed\n");
0891
0892 if (efct_xport_control(efct->xport, EFCT_XPORT_PORT_ONLINE))
0893 efc_log_debug(efct, "EFCT_XPORT_PORT_ONLINE failed\n");
0894
0895 return 0;
0896 }
0897
0898 struct efct_vport *
0899 efct_scsi_new_vport(struct efct *efct, struct device *dev)
0900 {
0901 struct Scsi_Host *shost = NULL;
0902 int error = 0;
0903 struct efct_vport *vport = NULL;
0904
0905 shost = scsi_host_alloc(&efct_template, sizeof(*vport));
0906 if (!shost) {
0907 efc_log_err(efct, "failed to allocate Scsi_Host struct\n");
0908 return NULL;
0909 }
0910
0911
0912 vport = (struct efct_vport *)shost->hostdata;
0913 vport->efct = efct;
0914 vport->is_vport = true;
0915
0916 shost->can_queue = efct->hw.config.n_io;
0917 shost->max_cmd_len = 16;
0918 shost->max_id = 0xffff;
0919 shost->max_lun = 0xffffffff;
0920
0921
0922 shost->sg_tablesize = sli_get_max_sgl(&efct->hw.sli);
0923
0924
0925 shost->transportt = efct_vport_fc_tt;
0926 efc_log_debug(efct, "vport transport template=%p\n",
0927 efct_vport_fc_tt);
0928
0929
0930 error = scsi_add_host_with_dma(shost, dev, &efct->pci->dev);
0931 if (error) {
0932 efc_log_debug(efct, "failed scsi_add_host_with_dma\n");
0933 return NULL;
0934 }
0935
0936
0937 snprintf(fc_host_symbolic_name(shost),
0938 sizeof(fc_host_symbolic_name(shost)),
0939 "Emulex %s FV%s DV%s", efct->model, efct->hw.sli.fw_name[0],
0940 EFCT_DRIVER_VERSION);
0941
0942
0943 fc_host_supported_classes(shost) = FC_COS_CLASS3;
0944
0945 fc_host_supported_speeds(shost) = efct_get_link_supported_speeds(efct);
0946 vport->shost = shost;
0947
0948 return vport;
0949 }
0950
0951 int efct_scsi_del_vport(struct efct *efct, struct Scsi_Host *shost)
0952 {
0953 if (shost) {
0954 efc_log_debug(efct,
0955 "Unregistering vport with Transport Layer\n");
0956 efct_xport_remove_host(shost);
0957 efc_log_debug(efct, "Unregistering vport with SCSI Midlayer\n");
0958 scsi_remove_host(shost);
0959 scsi_host_put(shost);
0960 return 0;
0961 }
0962 return -EIO;
0963 }
0964
0965 static int
0966 efct_vport_create(struct fc_vport *fc_vport, bool disable)
0967 {
0968 struct Scsi_Host *shost = fc_vport ? fc_vport->shost : NULL;
0969 struct efct_vport *pport = shost ?
0970 (struct efct_vport *)shost->hostdata :
0971 NULL;
0972 struct efct *efct = pport ? pport->efct : NULL;
0973 struct efct_vport *vport = NULL;
0974
0975 if (!fc_vport || !shost || !efct)
0976 goto fail;
0977
0978 vport = efct_scsi_new_vport(efct, &fc_vport->dev);
0979 if (!vport) {
0980 efc_log_err(efct, "failed to create vport\n");
0981 goto fail;
0982 }
0983
0984 vport->fc_vport = fc_vport;
0985 vport->npiv_wwpn = fc_vport->port_name;
0986 vport->npiv_wwnn = fc_vport->node_name;
0987 fc_host_node_name(vport->shost) = vport->npiv_wwnn;
0988 fc_host_port_name(vport->shost) = vport->npiv_wwpn;
0989 *(struct efct_vport **)fc_vport->dd_data = vport;
0990
0991 return 0;
0992
0993 fail:
0994 return -EIO;
0995 }
0996
0997 static int
0998 efct_vport_delete(struct fc_vport *fc_vport)
0999 {
1000 struct efct_vport *vport = *(struct efct_vport **)fc_vport->dd_data;
1001 struct Scsi_Host *shost = vport ? vport->shost : NULL;
1002 struct efct *efct = vport ? vport->efct : NULL;
1003 int rc;
1004
1005 rc = efct_scsi_del_vport(efct, shost);
1006
1007 if (rc)
1008 pr_err("%s: vport delete failed\n", __func__);
1009
1010 return rc;
1011 }
1012
1013 static int
1014 efct_vport_disable(struct fc_vport *fc_vport, bool disable)
1015 {
1016 return 0;
1017 }
1018
1019 static struct fc_function_template efct_xport_functions = {
1020 .get_host_port_id = efct_get_host_port_id,
1021 .get_host_port_type = efct_get_host_port_type,
1022 .get_host_port_state = efct_get_host_port_state,
1023 .get_host_speed = efct_get_host_speed,
1024 .get_host_fabric_name = efct_get_host_fabric_name,
1025
1026 .get_fc_host_stats = efct_get_stats,
1027 .reset_fc_host_stats = efct_reset_stats,
1028
1029 .issue_fc_host_lip = efct_issue_lip,
1030
1031 .vport_disable = efct_vport_disable,
1032
1033
1034 .dd_fcrport_size = sizeof(struct efct_rport_data),
1035 .dd_fcvport_size = 128,
1036
1037
1038 .show_rport_maxframe_size = 1,
1039 .show_rport_supported_classes = 1,
1040 .show_rport_dev_loss_tmo = 1,
1041
1042
1043 .show_starget_node_name = 1,
1044 .show_starget_port_name = 1,
1045 .show_starget_port_id = 1,
1046
1047
1048 .show_host_node_name = 1,
1049 .show_host_port_name = 1,
1050 .show_host_supported_classes = 1,
1051 .show_host_supported_fc4s = 1,
1052 .show_host_supported_speeds = 1,
1053 .show_host_maxframe_size = 1,
1054
1055
1056 .show_host_port_id = 1,
1057 .show_host_port_type = 1,
1058 .show_host_port_state = 1,
1059
1060 .show_host_active_fc4s = 1,
1061 .show_host_speed = 1,
1062 .show_host_fabric_name = 1,
1063 .show_host_symbolic_name = 1,
1064 .vport_create = efct_vport_create,
1065 .vport_delete = efct_vport_delete,
1066 };
1067
1068 static struct fc_function_template efct_vport_functions = {
1069 .get_host_port_id = efct_get_host_port_id,
1070 .get_host_port_type = efct_get_host_vport_type,
1071 .get_host_port_state = efct_get_host_port_state,
1072 .get_host_speed = efct_get_host_speed,
1073 .get_host_fabric_name = efct_get_host_fabric_name,
1074
1075 .get_fc_host_stats = efct_get_stats,
1076 .reset_fc_host_stats = efct_reset_stats,
1077
1078 .issue_fc_host_lip = efct_issue_lip,
1079
1080
1081 .dd_fcrport_size = sizeof(struct efct_rport_data),
1082 .dd_fcvport_size = 128,
1083
1084
1085 .show_rport_maxframe_size = 1,
1086 .show_rport_supported_classes = 1,
1087 .show_rport_dev_loss_tmo = 1,
1088
1089
1090 .show_starget_node_name = 1,
1091 .show_starget_port_name = 1,
1092 .show_starget_port_id = 1,
1093
1094
1095 .show_host_node_name = 1,
1096 .show_host_port_name = 1,
1097 .show_host_supported_classes = 1,
1098 .show_host_supported_fc4s = 1,
1099 .show_host_supported_speeds = 1,
1100 .show_host_maxframe_size = 1,
1101
1102
1103 .show_host_port_id = 1,
1104 .show_host_port_type = 1,
1105 .show_host_port_state = 1,
1106
1107 .show_host_active_fc4s = 1,
1108 .show_host_speed = 1,
1109 .show_host_fabric_name = 1,
1110 .show_host_symbolic_name = 1,
1111 };