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; }
/** * Use this function to instantiate a new FCS vport object. This * function will not trigger any HW initialization process (which will be * done in vport_start() call) * * param[in] vport - pointer to bfa_fcs_vport_t. This space * needs to be allocated by the driver. * param[in] fcs - FCS instance * param[in] vport_cfg - vport configuration * param[in] vf_id - VF_ID if vport is created within a VF. * FC_VF_ID_NULL to specify base fabric. * param[in] vport_drv - Opaque handle back to the driver's vport * structure * * retval BFA_STATUS_OK - on success. * retval BFA_STATUS_FAILED - on failure. */ bfa_status_t bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, u16 vf_id, struct bfa_port_cfg_s *vport_cfg, struct bfad_vport_s *vport_drv) { if (vport_cfg->pwwn == 0) return BFA_STATUS_INVALID_WWN; if (bfa_fcs_port_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn) return BFA_STATUS_VPORT_WWN_BP; if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL) return BFA_STATUS_VPORT_EXISTS; if (bfa_fcs_fabric_vport_count(&fcs->fabric) == bfa_fcs_vport_get_max(fcs)) return BFA_STATUS_VPORT_MAX; vport->lps = bfa_lps_alloc(fcs->bfa); if (!vport->lps) return BFA_STATUS_VPORT_MAX; vport->vport_drv = vport_drv; bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); bfa_fcs_lport_init(&vport->lport, fcs, vf_id, vport_cfg, vport); bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE); return BFA_STATUS_OK; }
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 ssize_t bfad_im_vport_delete(struct class_device *cdev, const char *buf, size_t count) { struct Scsi_Host *shost = class_to_shost(cdev); struct bfad_im_port_s *im_port = (struct bfad_im_port_s *) shost->hostdata[0]; struct bfad_s *bfad = im_port->bfad; u8 wwn[8]; int status; unsigned long flags; struct bfa_fcs_vport_s *fcs_vport; struct bfad_vport_s *bfad_vport; struct completion fcomp; status = bfad_im_parse_wwn(&buf[0], wwn); if (status) return status; spin_lock_irqsave(&bfad->bfad_lock, flags); fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, *(wwn_t *)wwn); if (fcs_vport == NULL) { spin_unlock_irqrestore(&bfad->bfad_lock, flags); return -EINVAL; } bfad_vport = fcs_vport->vport_drv; bfad_vport->drv_port.flags |= BFAD_PORT_DELETE; bfad_vport->comp_del = &fcomp; init_completion(bfad_vport->comp_del); status = bfa_fcs_vport_delete(fcs_vport); spin_unlock_irqrestore(&bfad->bfad_lock, flags); wait_for_completion(bfad_vport->comp_del); if (status != BFA_STATUS_OK) return -EIO; bfad_os_scsi_host_free(bfad, bfad_vport->drv_port.im_port); kfree(bfad_vport); return count; }
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; }