diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_attr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 253 |
1 files changed, 211 insertions, 42 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 8081b637d97e..1612f9200a52 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -6,13 +6,17 @@ */ #include "qla_def.h" +#include <linux/kthread.h> #include <linux/vmalloc.h> +int qla24xx_vport_disable(struct fc_vport *, bool); + /* SYSFS attributes --------------------------------------------------------- */ static ssize_t -qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_read_fw_dump(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -31,8 +35,9 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off, } static ssize_t -qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_write_fw_dump(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -73,7 +78,6 @@ static struct bin_attribute sysfs_fw_dump_attr = { .attr = { .name = "fw_dump", .mode = S_IRUSR | S_IWUSR, - .owner = THIS_MODULE, }, .size = 0, .read = qla2x00_sysfs_read_fw_dump, @@ -81,8 +85,9 @@ static struct bin_attribute sysfs_fw_dump_attr = { }; static ssize_t -qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_read_nvram(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -93,7 +98,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off, /* Read NVRAM. */ spin_lock_irqsave(&ha->hardware_lock, flags); - ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->nvram_base, + ha->isp_ops->read_nvram(ha, (uint8_t *)buf, ha->nvram_base, ha->nvram_size); spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -101,8 +106,9 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off, } static ssize_t -qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_write_nvram(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -113,7 +119,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off, return 0; /* Checksum NVRAM. */ - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { uint32_t *iter; uint32_t chksum; @@ -137,7 +143,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off, /* Write NVRAM. */ spin_lock_irqsave(&ha->hardware_lock, flags); - ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); + ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); spin_unlock_irqrestore(&ha->hardware_lock, flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); @@ -149,7 +155,6 @@ static struct bin_attribute sysfs_nvram_attr = { .attr = { .name = "nvram", .mode = S_IRUSR | S_IWUSR, - .owner = THIS_MODULE, }, .size = 512, .read = qla2x00_sysfs_read_nvram, @@ -157,8 +162,9 @@ static struct bin_attribute sysfs_nvram_attr = { }; static ssize_t -qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_read_optrom(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -176,8 +182,9 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off, } static ssize_t -qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_write_optrom(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -198,16 +205,16 @@ static struct bin_attribute sysfs_optrom_attr = { .attr = { .name = "optrom", .mode = S_IRUSR | S_IWUSR, - .owner = THIS_MODULE, }, - .size = OPTROM_SIZE_24XX, + .size = 0, .read = qla2x00_sysfs_read_optrom, .write = qla2x00_sysfs_write_optrom, }; static ssize_t -qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -245,7 +252,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off, } memset(ha->optrom_buffer, 0, ha->optrom_size); - ha->isp_ops.read_optrom(ha, ha->optrom_buffer, 0, + ha->isp_ops->read_optrom(ha, ha->optrom_buffer, 0, ha->optrom_size); break; case 2: @@ -268,7 +275,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off, if (ha->optrom_state != QLA_SWRITING) break; - ha->isp_ops.write_optrom(ha, ha->optrom_buffer, 0, + ha->isp_ops->write_optrom(ha, ha->optrom_buffer, 0, ha->optrom_size); break; } @@ -279,15 +286,15 @@ static struct bin_attribute sysfs_optrom_ctl_attr = { .attr = { .name = "optrom_ctl", .mode = S_IWUSR, - .owner = THIS_MODULE, }, .size = 0, .write = qla2x00_sysfs_write_optrom_ctl, }; static ssize_t -qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_read_vpd(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -298,15 +305,17 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off, /* Read NVRAM. */ spin_lock_irqsave(&ha->hardware_lock, flags); - ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->vpd_base, ha->vpd_size); + ha->isp_ops->read_nvram(ha, (uint8_t *)buf, ha->vpd_base, + ha->vpd_size); spin_unlock_irqrestore(&ha->hardware_lock, flags); return ha->vpd_size; } static ssize_t -qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_write_vpd(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -317,7 +326,7 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off, /* Write NVRAM. */ spin_lock_irqsave(&ha->hardware_lock, flags); - ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); + ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); spin_unlock_irqrestore(&ha->hardware_lock, flags); return count; @@ -327,7 +336,6 @@ static struct bin_attribute sysfs_vpd_attr = { .attr = { .name = "vpd", .mode = S_IRUSR | S_IWUSR, - .owner = THIS_MODULE, }, .size = 0, .read = qla2x00_sysfs_read_vpd, @@ -335,8 +343,9 @@ static struct bin_attribute sysfs_vpd_attr = { }; static ssize_t -qla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off, - size_t count) +qla2x00_sysfs_read_sfp(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); @@ -375,7 +384,6 @@ static struct bin_attribute sysfs_sfp_attr = { .attr = { .name = "sfp", .mode = S_IRUSR | S_IWUSR, - .owner = THIS_MODULE, }, .size = SFP_DEV_SIZE * 2, .read = qla2x00_sysfs_read_sfp, @@ -403,7 +411,7 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) int ret; for (iter = bin_file_entries; iter->name; iter++) { - if (iter->is4GBp_only && (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))) + if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha)) continue; ret = sysfs_create_bin_file(&host->shost_gendev.kobj, @@ -422,7 +430,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) struct sysfs_entry *iter; for (iter = bin_file_entries; iter->name; iter++) { - if (iter->is4GBp_only && (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))) + if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha)) continue; sysfs_remove_bin_file(&host->shost_gendev.kobj, @@ -430,7 +438,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) } if (ha->beacon_blink_led == 1) - ha->isp_ops.beacon_off(ha); + ha->isp_ops->beacon_off(ha); } /* Scsi_Host attributes. */ @@ -448,7 +456,7 @@ qla2x00_fw_version_show(struct class_device *cdev, char *buf) char fw_str[30]; return snprintf(buf, PAGE_SIZE, "%s\n", - ha->isp_ops.fw_version_str(ha, fw_str)); + ha->isp_ops->fw_version_str(ha, fw_str)); } static ssize_t @@ -500,7 +508,7 @@ qla2x00_pci_info_show(struct class_device *cdev, char *buf) char pci_info[30]; return snprintf(buf, PAGE_SIZE, "%s\n", - ha->isp_ops.pci_info_str(ha, pci_info)); + ha->isp_ops->pci_info_str(ha, pci_info)); } static ssize_t @@ -645,9 +653,9 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf, return -EINVAL; if (val) - rval = ha->isp_ops.beacon_on(ha); + rval = ha->isp_ops->beacon_on(ha); else - rval = ha->isp_ops.beacon_off(ha); + rval = ha->isp_ops->beacon_off(ha); if (rval != QLA_SUCCESS) count = 0; @@ -891,7 +899,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) pfc_host_stat = &ha->fc_host_stat; memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, sizeof(stat_buf) / 4, mb_stat); } else if (atomic_read(&ha->loop_state) == LOOP_READY && @@ -959,6 +967,122 @@ qla2x00_get_host_port_state(struct Scsi_Host *shost) fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; } +static int +qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) +{ + int ret = 0; + scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; + scsi_qla_host_t *vha; + + ret = qla24xx_vport_create_req_sanity_check(fc_vport); + if (ret) { + DEBUG15(printk("qla24xx_vport_create_req_sanity_check failed, " + "status %x\n", ret)); + return (ret); + } + + vha = qla24xx_create_vhost(fc_vport); + if (vha == NULL) { + DEBUG15(printk ("qla24xx_create_vhost failed, vha = %p\n", + vha)); + return FC_VPORT_FAILED; + } + if (disable) { + atomic_set(&vha->vp_state, VP_OFFLINE); + fc_vport_set_state(fc_vport, FC_VPORT_DISABLED); + } else + atomic_set(&vha->vp_state, VP_FAILED); + + /* ready to create vport */ + qla_printk(KERN_INFO, vha, "VP entry id %d assigned.\n", vha->vp_idx); + + /* initialized vport states */ + atomic_set(&vha->loop_state, LOOP_DOWN); + vha->vp_err_state= VP_ERR_PORTDWN; + vha->vp_prev_err_state= VP_ERR_UNKWN; + /* Check if physical ha port is Up */ + if (atomic_read(&ha->loop_state) == LOOP_DOWN || + atomic_read(&ha->loop_state) == LOOP_DEAD) { + /* Don't retry or attempt login of this virtual port */ + DEBUG15(printk ("scsi(%ld): pport loop_state is not UP.\n", + vha->host_no)); + atomic_set(&vha->loop_state, LOOP_DEAD); + if (!disable) + fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); + } + + if (scsi_add_host(vha->host, &fc_vport->dev)) { + DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n", + vha->host_no, vha->vp_idx)); + goto vport_create_failed_2; + } + + /* initialize attributes */ + fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name); + fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name); + fc_host_supported_classes(vha->host) = + fc_host_supported_classes(ha->host); + fc_host_supported_speeds(vha->host) = + fc_host_supported_speeds(ha->host); + + qla24xx_vport_disable(fc_vport, disable); + + return 0; +vport_create_failed_2: + qla24xx_disable_vp(vha); + qla24xx_deallocate_vp_id(vha); + kfree(vha->port_name); + kfree(vha->node_name); + scsi_host_put(vha->host); + return FC_VPORT_FAILED; +} + +int +qla24xx_vport_delete(struct fc_vport *fc_vport) +{ + scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; + scsi_qla_host_t *vha = fc_vport->dd_data; + + qla24xx_disable_vp(vha); + qla24xx_deallocate_vp_id(vha); + + down(&ha->vport_sem); + ha->cur_vport_count--; + clear_bit(vha->vp_idx, (unsigned long *)ha->vp_idx_map); + up(&ha->vport_sem); + + kfree(vha->node_name); + kfree(vha->port_name); + + if (vha->timer_active) { + qla2x00_vp_stop_timer(vha); + DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p " + "has stopped\n", + vha->host_no, vha->vp_idx, vha)); + } + + fc_remove_host(vha->host); + + scsi_remove_host(vha->host); + + scsi_host_put(vha->host); + + return 0; +} + +int +qla24xx_vport_disable(struct fc_vport *fc_vport, bool disable) +{ + scsi_qla_host_t *vha = fc_vport->dd_data; + + if (disable) + qla24xx_disable_vp(vha); + else + qla24xx_enable_vp(vha); + + return 0; +} + struct fc_function_template qla2xxx_transport_functions = { .show_host_node_name = 1, @@ -996,6 +1120,49 @@ struct fc_function_template qla2xxx_transport_functions = { .issue_fc_host_lip = qla2x00_issue_lip, .get_fc_host_stats = qla2x00_get_fc_host_stats, + + .vport_create = qla24xx_vport_create, + .vport_disable = qla24xx_vport_disable, + .vport_delete = qla24xx_vport_delete, +}; + +struct fc_function_template qla2xxx_transport_vport_functions = { + + .show_host_node_name = 1, + .show_host_port_name = 1, + .show_host_supported_classes = 1, + + .get_host_port_id = qla2x00_get_host_port_id, + .show_host_port_id = 1, + .get_host_speed = qla2x00_get_host_speed, + .show_host_speed = 1, + .get_host_port_type = qla2x00_get_host_port_type, + .show_host_port_type = 1, + .get_host_symbolic_name = qla2x00_get_host_symbolic_name, + .show_host_symbolic_name = 1, + .set_host_system_hostname = qla2x00_set_host_system_hostname, + .show_host_system_hostname = 1, + .get_host_fabric_name = qla2x00_get_host_fabric_name, + .show_host_fabric_name = 1, + .get_host_port_state = qla2x00_get_host_port_state, + .show_host_port_state = 1, + + .dd_fcrport_size = sizeof(struct fc_port *), + .show_rport_supported_classes = 1, + + .get_starget_node_name = qla2x00_get_starget_node_name, + .show_starget_node_name = 1, + .get_starget_port_name = qla2x00_get_starget_port_name, + .show_starget_port_name = 1, + .get_starget_port_id = qla2x00_get_starget_port_id, + .show_starget_port_id = 1, + + .get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo, + .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo, + .show_rport_dev_loss_tmo = 1, + + .issue_fc_host_lip = qla2x00_issue_lip, + .get_fc_host_stats = qla2x00_get_fc_host_stats, }; void @@ -1004,4 +1171,6 @@ qla2x00_init_host_attr(scsi_qla_host_t *ha) fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name); fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name); fc_host_supported_classes(ha->host) = FC_COS_CLASS3; + fc_host_max_npiv_vports(ha->host) = MAX_NUM_VPORT_FABRIC; + fc_host_npiv_vports_inuse(ha->host) = ha->cur_vport_count; } |