diff options
Diffstat (limited to 'drivers/scsi/bfa/bfad_attr.c')
-rw-r--r-- | drivers/scsi/bfa/bfad_attr.c | 278 |
1 files changed, 236 insertions, 42 deletions
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index 9129ae3040ff..e477bfbfa7d8 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -19,6 +19,7 @@ * bfa_attr.c Linux driver configuration interface module. */ +#include <linux/slab.h> #include "bfad_drv.h" #include "bfad_im.h" #include "bfad_trcmod.h" @@ -141,7 +142,7 @@ bfad_im_get_host_port_type(struct Scsi_Host *shost) struct bfad_s *bfad = im_port->bfad; struct bfa_pport_attr_s attr; - bfa_pport_get_attr(&bfad->bfa, &attr); + bfa_fcport_get_attr(&bfad->bfa, &attr); switch (attr.port_type) { case BFA_PPORT_TYPE_NPORT: @@ -173,7 +174,7 @@ bfad_im_get_host_port_state(struct Scsi_Host *shost) struct bfad_s *bfad = im_port->bfad; struct bfa_pport_attr_s attr; - bfa_pport_get_attr(&bfad->bfa, &attr); + bfa_fcport_get_attr(&bfad->bfa, &attr); switch (attr.port_state) { case BFA_PPORT_ST_LINKDOWN: @@ -229,8 +230,10 @@ bfad_im_get_host_speed(struct Scsi_Host *shost) (struct bfad_im_port_s *) shost->hostdata[0]; struct bfad_s *bfad = im_port->bfad; struct bfa_pport_attr_s attr; + unsigned long flags; - bfa_pport_get_attr(&bfad->bfa, &attr); + spin_lock_irqsave(shost->host_lock, flags); + bfa_fcport_get_attr(&bfad->bfa, &attr); switch (attr.speed) { case BFA_PPORT_SPEED_8GBPS: fc_host_speed(shost) = FC_PORTSPEED_8GBIT; @@ -248,6 +251,7 @@ bfad_im_get_host_speed(struct Scsi_Host *shost) fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; break; } + spin_unlock_irqrestore(shost->host_lock, flags); } /** @@ -285,7 +289,7 @@ bfad_im_get_stats(struct Scsi_Host *shost) init_completion(&fcomp.comp); spin_lock_irqsave(&bfad->bfad_lock, flags); memset(hstats, 0, sizeof(struct fc_host_statistics)); - rc = bfa_pport_get_stats(&bfad->bfa, + rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa), (union bfa_pport_stats_u *) hstats, bfad_hcb_comp, &fcomp); spin_unlock_irqrestore(&bfad->bfad_lock, flags); @@ -312,7 +316,8 @@ bfad_im_reset_stats(struct Scsi_Host *shost) init_completion(&fcomp.comp); spin_lock_irqsave(&bfad->bfad_lock, flags); - rc = bfa_pport_clear_stats(&bfad->bfa, bfad_hcb_comp, &fcomp); + rc = bfa_port_clear_stats(BFA_FCPORT(&bfad->bfa), bfad_hcb_comp, + &fcomp); spin_unlock_irqrestore(&bfad->bfad_lock, flags); if (rc != BFA_STATUS_OK) @@ -359,6 +364,152 @@ bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) } +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; +} + +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 +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; +} + struct fc_function_template bfad_im_fc_function_template = { /* Target dynamic attributes */ @@ -408,6 +559,61 @@ struct fc_function_template bfad_im_fc_function_template = { .show_rport_dev_loss_tmo = 1, .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo, .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo, + + .vport_create = bfad_im_vport_create, + .vport_delete = bfad_im_vport_delete, + .vport_disable = bfad_im_vport_disable, +}; + +struct fc_function_template bfad_im_vport_fc_function_template = { + + /* Target dynamic attributes */ + .get_starget_port_id = bfad_im_get_starget_port_id, + .show_starget_port_id = 1, + .get_starget_node_name = bfad_im_get_starget_node_name, + .show_starget_node_name = 1, + .get_starget_port_name = bfad_im_get_starget_port_name, + .show_starget_port_name = 1, + + /* Host dynamic attribute */ + .get_host_port_id = bfad_im_get_host_port_id, + .show_host_port_id = 1, + + /* Host fixed attributes */ + .show_host_node_name = 1, + .show_host_port_name = 1, + .show_host_supported_classes = 1, + .show_host_supported_fc4s = 1, + .show_host_supported_speeds = 1, + .show_host_maxframe_size = 1, + + /* More host dynamic attributes */ + .show_host_port_type = 1, + .get_host_port_type = bfad_im_get_host_port_type, + .show_host_port_state = 1, + .get_host_port_state = bfad_im_get_host_port_state, + .show_host_active_fc4s = 1, + .get_host_active_fc4s = bfad_im_get_host_active_fc4s, + .show_host_speed = 1, + .get_host_speed = bfad_im_get_host_speed, + .show_host_fabric_name = 1, + .get_host_fabric_name = bfad_im_get_host_fabric_name, + + .show_host_symbolic_name = 1, + + /* Statistics */ + .get_fc_host_stats = bfad_im_get_stats, + .reset_fc_host_stats = bfad_im_reset_stats, + + /* Allocation length for host specific data */ + .dd_fcrport_size = sizeof(struct bfad_itnim_data_s *), + + /* Remote port fixed attributes */ + .show_rport_maxframe_size = 1, + .show_rport_supported_classes = 1, + .show_rport_dev_loss_tmo = 1, + .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo, + .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo, }; /** @@ -421,12 +627,10 @@ bfad_im_serial_num_show(struct device *dev, struct device_attribute *attr, struct bfad_im_port_s *im_port = (struct bfad_im_port_s *) shost->hostdata[0]; struct bfad_s *bfad = im_port->bfad; - struct bfa_ioc_attr_s ioc_attr; + char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN]; - memset(&ioc_attr, 0, sizeof(ioc_attr)); - bfa_get_attr(&bfad->bfa, &ioc_attr); - return snprintf(buf, PAGE_SIZE, "%s\n", - ioc_attr.adapter_attr.serial_num); + bfa_get_adapter_serial_num(&bfad->bfa, serial_num); + return snprintf(buf, PAGE_SIZE, "%s\n", serial_num); } static ssize_t @@ -437,11 +641,10 @@ bfad_im_model_show(struct device *dev, struct device_attribute *attr, struct bfad_im_port_s *im_port = (struct bfad_im_port_s *) shost->hostdata[0]; struct bfad_s *bfad = im_port->bfad; - struct bfa_ioc_attr_s ioc_attr; + char model[BFA_ADAPTER_MODEL_NAME_LEN]; - memset(&ioc_attr, 0, sizeof(ioc_attr)); - bfa_get_attr(&bfad->bfa, &ioc_attr); - return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.model); + bfa_get_adapter_model(&bfad->bfa, model); + return snprintf(buf, PAGE_SIZE, "%s\n", model); } static ssize_t @@ -452,12 +655,10 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr, struct bfad_im_port_s *im_port = (struct bfad_im_port_s *) shost->hostdata[0]; struct bfad_s *bfad = im_port->bfad; - struct bfa_ioc_attr_s ioc_attr; + char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN]; - memset(&ioc_attr, 0, sizeof(ioc_attr)); - bfa_get_attr(&bfad->bfa, &ioc_attr); - return snprintf(buf, PAGE_SIZE, "%s\n", - ioc_attr.adapter_attr.model_descr); + bfa_get_adapter_model(&bfad->bfa, model_descr); + return snprintf(buf, PAGE_SIZE, "%s\n", model_descr); } static ssize_t @@ -482,14 +683,13 @@ bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr, struct bfad_im_port_s *im_port = (struct bfad_im_port_s *) shost->hostdata[0]; struct bfad_s *bfad = im_port->bfad; - struct bfa_ioc_attr_s ioc_attr; - - memset(&ioc_attr, 0, sizeof(ioc_attr)); - bfa_get_attr(&bfad->bfa, &ioc_attr); + char model[BFA_ADAPTER_MODEL_NAME_LEN]; + char fw_ver[BFA_VERSION_LEN]; + bfa_get_adapter_model(&bfad->bfa, model); + bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver); return snprintf(buf, PAGE_SIZE, "Brocade %s FV%s DV%s\n", - ioc_attr.adapter_attr.model, - ioc_attr.adapter_attr.fw_ver, BFAD_DRIVER_VERSION); + model, fw_ver, BFAD_DRIVER_VERSION); } static ssize_t @@ -500,11 +700,10 @@ bfad_im_hw_version_show(struct device *dev, struct device_attribute *attr, struct bfad_im_port_s *im_port = (struct bfad_im_port_s *) shost->hostdata[0]; struct bfad_s *bfad = im_port->bfad; - struct bfa_ioc_attr_s ioc_attr; + char hw_ver[BFA_VERSION_LEN]; - memset(&ioc_attr, 0, sizeof(ioc_attr)); - bfa_get_attr(&bfad->bfa, &ioc_attr); - return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.hw_ver); + bfa_get_pci_chip_rev(&bfad->bfa, hw_ver); + return snprintf(buf, PAGE_SIZE, "%s\n", hw_ver); } static ssize_t @@ -522,12 +721,10 @@ bfad_im_optionrom_version_show(struct device *dev, struct bfad_im_port_s *im_port = (struct bfad_im_port_s *) shost->hostdata[0]; struct bfad_s *bfad = im_port->bfad; - struct bfa_ioc_attr_s ioc_attr; + char optrom_ver[BFA_VERSION_LEN]; - memset(&ioc_attr, 0, sizeof(ioc_attr)); - bfa_get_attr(&bfad->bfa, &ioc_attr); - return snprintf(buf, PAGE_SIZE, "%s\n", - ioc_attr.adapter_attr.optrom_ver); + bfa_get_adapter_optrom_ver(&bfad->bfa, optrom_ver); + return snprintf(buf, PAGE_SIZE, "%s\n", optrom_ver); } static ssize_t @@ -538,11 +735,10 @@ bfad_im_fw_version_show(struct device *dev, struct device_attribute *attr, struct bfad_im_port_s *im_port = (struct bfad_im_port_s *) shost->hostdata[0]; struct bfad_s *bfad = im_port->bfad; - struct bfa_ioc_attr_s ioc_attr; + char fw_ver[BFA_VERSION_LEN]; - memset(&ioc_attr, 0, sizeof(ioc_attr)); - bfa_get_attr(&bfad->bfa, &ioc_attr); - return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.fw_ver); + bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver); + return snprintf(buf, PAGE_SIZE, "%s\n", fw_ver); } static ssize_t @@ -553,11 +749,9 @@ bfad_im_num_of_ports_show(struct device *dev, struct device_attribute *attr, struct bfad_im_port_s *im_port = (struct bfad_im_port_s *) shost->hostdata[0]; struct bfad_s *bfad = im_port->bfad; - struct bfa_ioc_attr_s ioc_attr; - memset(&ioc_attr, 0, sizeof(ioc_attr)); - bfa_get_attr(&bfad->bfa, &ioc_attr); - return snprintf(buf, PAGE_SIZE, "%d\n", ioc_attr.adapter_attr.nports); + return snprintf(buf, PAGE_SIZE, "%d\n", + bfa_get_nports(&bfad->bfa)); } static ssize_t |