/* * csio_reg_rnode - Register a remote port with FC transport. * @rn: Rnode representing remote port. * * Call fc_remote_port_add() to register this remote port with FC transport. * If remote port is Initiator OR Target OR both, change the role appropriately. * */ void csio_reg_rnode(struct csio_rnode *rn) { struct csio_lnode *ln = csio_rnode_to_lnode(rn); struct Scsi_Host *shost = csio_ln_to_shost(ln); struct fc_rport_identifiers ids; struct fc_rport *rport; struct csio_service_parms *sp; ids.node_name = wwn_to_u64(csio_rn_wwnn(rn)); ids.port_name = wwn_to_u64(csio_rn_wwpn(rn)); ids.port_id = rn->nport_id; ids.roles = FC_RPORT_ROLE_UNKNOWN; if (rn->role & CSIO_RNFR_INITIATOR || rn->role & CSIO_RNFR_TARGET) { rport = rn->rport; CSIO_ASSERT(rport != NULL); goto update_role; } rn->rport = fc_remote_port_add(shost, 0, &ids); if (!rn->rport) { csio_ln_err(ln, "Failed to register rport = 0x%x.\n", rn->nport_id); return; } ln->num_reg_rnodes++; rport = rn->rport; spin_lock_irq(shost->host_lock); *((struct csio_rnode **)rport->dd_data) = rn; spin_unlock_irq(shost->host_lock); sp = &rn->rn_sparm; rport->maxframe_size = ntohs(sp->csp.sp_bb_data); if (ntohs(sp->clsp[2].cp_class) & FC_CPC_VALID) rport->supported_classes = FC_COS_CLASS3; else rport->supported_classes = FC_COS_UNSPECIFIED; update_role: if (rn->role & CSIO_RNFR_INITIATOR) ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; if (rn->role & CSIO_RNFR_TARGET) ids.roles |= FC_RPORT_ROLE_FCP_TARGET; if (ids.roles != FC_RPORT_ROLE_UNKNOWN) fc_remote_port_rolechg(rport, ids.roles); rn->scsi_id = rport->scsi_target_id; csio_ln_dbg(ln, "Remote port x%x role 0x%x registered\n", rn->nport_id, ids.roles); }
static int bfad_im_vport_disable(struct fc_vport *fc_vport, bool disable) { struct bfad_vport_s *vport; struct bfad_s *bfad; struct bfa_fcs_vport_s *fcs_vport; struct Scsi_Host *vshost; wwn_t pwwn; unsigned long flags; vport = (struct bfad_vport_s *)fc_vport->dd_data; bfad = vport->drv_port.bfad; vshost = vport->drv_port.im_port->shost; pwwn = wwn_to_u64((u8 *) &fc_vport->port_name); spin_lock_irqsave(&bfad->bfad_lock, flags); fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn); spin_unlock_irqrestore(&bfad->bfad_lock, flags); if (fcs_vport == NULL) return VPCERR_BAD_WWN; if (disable) { bfa_fcs_vport_stop(fcs_vport); fc_vport_set_state(fc_vport, FC_VPORT_DISABLED); } else { bfa_fcs_vport_start(fcs_vport); fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE); } return 0; }
/* * csio_fchost_attr_init - Initialize FC transport attributes * @ln: Lnode. * */ void csio_fchost_attr_init(struct csio_lnode *ln) { struct Scsi_Host *shost = csio_ln_to_shost(ln); fc_host_node_name(shost) = wwn_to_u64(csio_ln_wwnn(ln)); fc_host_port_name(shost) = wwn_to_u64(csio_ln_wwpn(ln)); fc_host_supported_classes(shost) = FC_COS_CLASS3; fc_host_max_npiv_vports(shost) = (csio_lnode_to_hw(ln))->fres_info.max_vnps; fc_host_supported_speeds(shost) = FC_PORTSPEED_10GBIT | FC_PORTSPEED_1GBIT; fc_host_maxframe_size(shost) = ntohs(ln->ln_sparm.csp.sp_bb_data); memset(fc_host_supported_fc4s(shost), 0, sizeof(fc_host_supported_fc4s(shost))); fc_host_supported_fc4s(shost)[7] = 1; memset(fc_host_active_fc4s(shost), 0, sizeof(fc_host_active_fc4s(shost))); fc_host_active_fc4s(shost)[7] = 1; }
/* * csio_get_host_fabric_name - Return fabric name * @shost: scsi host. * */ static void csio_get_host_fabric_name(struct Scsi_Host *shost) { struct csio_lnode *ln = shost_priv(shost); struct csio_rnode *rn = NULL; struct csio_hw *hw = csio_lnode_to_hw(ln); spin_lock_irq(&hw->lock); rn = csio_rnode_lookup_portid(ln, FC_FID_FLOGI); if (rn) fc_host_fabric_name(shost) = wwn_to_u64(csio_rn_wwnn(rn)); else fc_host_fabric_name(shost) = 0; spin_unlock_irq(&hw->lock); }
static int bfad_im_vport_delete(struct fc_vport *fc_vport) { struct bfad_vport_s *vport = (struct bfad_vport_s *)fc_vport->dd_data; struct bfad_im_port_s *im_port = (struct bfad_im_port_s *) vport->drv_port.im_port; struct bfad_s *bfad = im_port->bfad; struct bfad_port_s *port; struct bfa_fcs_vport_s *fcs_vport; struct Scsi_Host *vshost; wwn_t pwwn; int rc; unsigned long flags; struct completion fcomp; if (im_port->flags & BFAD_PORT_DELETE) goto free_scsi_host; port = im_port->port; vshost = vport->drv_port.im_port->shost; pwwn = wwn_to_u64((u8 *) &fc_host_port_name(vshost)); spin_lock_irqsave(&bfad->bfad_lock, flags); fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn); spin_unlock_irqrestore(&bfad->bfad_lock, flags); if (fcs_vport == NULL) return VPCERR_BAD_WWN; vport->drv_port.flags |= BFAD_PORT_DELETE; vport->comp_del = &fcomp; init_completion(vport->comp_del); spin_lock_irqsave(&bfad->bfad_lock, flags); rc = bfa_fcs_vport_delete(&vport->fcs_vport); spin_unlock_irqrestore(&bfad->bfad_lock, flags); wait_for_completion(vport->comp_del); free_scsi_host: bfad_os_scsi_host_free(bfad, im_port); kfree(vport); return 0; }
static int csio_vport_create(struct fc_vport *fc_vport, bool disable) { struct Scsi_Host *shost = fc_vport->shost; struct csio_lnode *pln = shost_priv(shost); struct csio_lnode *ln = NULL; struct csio_hw *hw = csio_lnode_to_hw(pln); uint8_t wwn[8]; int ret = -1; ln = csio_shost_init(hw, &fc_vport->dev, false, pln); if (!ln) goto error; if (fc_vport->node_name != 0) { u64_to_wwn(fc_vport->node_name, wwn); if (!CSIO_VALID_WWN(wwn)) { csio_ln_err(ln, "vport create failed. Invalid wwnn\n"); goto error; } memcpy(csio_ln_wwnn(ln), wwn, 8); } if (fc_vport->port_name != 0) { u64_to_wwn(fc_vport->port_name, wwn); if (!CSIO_VALID_WWN(wwn)) { csio_ln_err(ln, "vport create failed. Invalid wwpn\n"); goto error; } if (csio_lnode_lookup_by_wwpn(hw, wwn)) { csio_ln_err(ln, "vport create failed. wwpn already exists\n"); goto error; } memcpy(csio_ln_wwpn(ln), wwn, 8); } fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING); if (csio_fcoe_alloc_vnp(hw, ln)) goto error; *(struct csio_lnode **)fc_vport->dd_data = ln; ln->fc_vport = fc_vport; if (!fc_vport->node_name) fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln)); if (!fc_vport->port_name) fc_vport->port_name = wwn_to_u64(csio_ln_wwpn(ln)); csio_fchost_attr_init(ln); return 0; error: if (ln) csio_shost_exit(ln); return ret; }
static int bfad_im_vport_create(struct fc_vport *fc_vport, bool disable) { char *vname = fc_vport->symbolic_name; struct Scsi_Host *shost = fc_vport->shost; struct bfad_im_port_s *im_port = (struct bfad_im_port_s *) shost->hostdata[0]; struct bfad_s *bfad = im_port->bfad; struct bfa_port_cfg_s port_cfg; int status = 0, rc; unsigned long flags; memset(&port_cfg, 0, sizeof(port_cfg)); port_cfg.pwwn = wwn_to_u64((u8 *) &fc_vport->port_name); port_cfg.nwwn = wwn_to_u64((u8 *) &fc_vport->node_name); if (strlen(vname) > 0) strcpy((char *)&port_cfg.sym_name, vname); port_cfg.roles = BFA_PORT_ROLE_FCP_IM; rc = bfad_vport_create(bfad, 0, &port_cfg, &fc_vport->dev); if (rc == BFA_STATUS_OK) { struct bfad_vport_s *vport; struct bfa_fcs_vport_s *fcs_vport; struct Scsi_Host *vshost; spin_lock_irqsave(&bfad->bfad_lock, flags); fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, port_cfg.pwwn); if (fcs_vport == NULL) { spin_unlock_irqrestore(&bfad->bfad_lock, flags); return VPCERR_BAD_WWN; } fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE); if (disable) { bfa_fcs_vport_stop(fcs_vport); fc_vport_set_state(fc_vport, FC_VPORT_DISABLED); } spin_unlock_irqrestore(&bfad->bfad_lock, flags); vport = fcs_vport->vport_drv; vshost = vport->drv_port.im_port->shost; fc_host_node_name(vshost) = wwn_to_u64((u8 *) &port_cfg.nwwn); fc_host_port_name(vshost) = wwn_to_u64((u8 *) &port_cfg.pwwn); fc_vport->dd_data = vport; vport->drv_port.im_port->fc_vport = fc_vport; } else if (rc == BFA_STATUS_INVALID_WWN) return VPCERR_BAD_WWN; else if (rc == BFA_STATUS_VPORT_EXISTS) return VPCERR_BAD_WWN; else if (rc == BFA_STATUS_VPORT_MAX) return VPCERR_NO_FABRIC_SUPP; else if (rc == BFA_STATUS_VPORT_WWN_BP) return VPCERR_BAD_WWN; else return FC_VPORT_FAILED; return status; }