X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fscsi%2Fqla2xxx%2Fqla_attr.c;h=2efca52dff50c45629b82c6a9d3c3a2ea137d497;hb=db9edfd7e339ca4113153d887e782dd05be5a9eb;hp=659a5d63467dc335a570f62e20f4d874bbbabe23;hpb=33ac02aa4cef417871e128ab4a6565e751e5f3b2;p=linux-2.6-omap-h63xx.git diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 659a5d63467..2efca52dff5 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1,20 +1,8 @@ /* - * QLOGIC LINUX SOFTWARE - * - * QLogic ISP2x00 device driver for Linux 2.6.x - * Copyright (C) 2003-2005 QLogic Corporation - * (www.qlogic.com) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * QLogic Fibre Channel HBA Driver + * Copyright (c) 2003-2005 QLogic Corporation * + * See LICENSE.qla2xxx for copyright and licensing details. */ #include "qla_def.h" @@ -211,6 +199,221 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); } +/* Scsi_Host attributes. */ + +static ssize_t +qla2x00_drvr_version_show(struct class_device *cdev, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str); +} + +static ssize_t +qla2x00_fw_version_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + char fw_str[30]; + + return snprintf(buf, PAGE_SIZE, "%s\n", + ha->isp_ops.fw_version_str(ha, fw_str)); +} + +static ssize_t +qla2x00_serial_num_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + uint32_t sn; + + sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1; + return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000, + sn % 100000); +} + +static ssize_t +qla2x00_isp_name_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + return snprintf(buf, PAGE_SIZE, "ISP%04X\n", ha->pdev->device); +} + +static ssize_t +qla2x00_isp_id_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n", + ha->product_id[0], ha->product_id[1], ha->product_id[2], + ha->product_id[3]); +} + +static ssize_t +qla2x00_model_name_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_number); +} + +static ssize_t +qla2x00_model_desc_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + return snprintf(buf, PAGE_SIZE, "%s\n", + ha->model_desc ? ha->model_desc: ""); +} + +static ssize_t +qla2x00_pci_info_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + char pci_info[30]; + + return snprintf(buf, PAGE_SIZE, "%s\n", + ha->isp_ops.pci_info_str(ha, pci_info)); +} + +static ssize_t +qla2x00_state_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + int len = 0; + + if (atomic_read(&ha->loop_state) == LOOP_DOWN || + atomic_read(&ha->loop_state) == LOOP_DEAD) + len = snprintf(buf, PAGE_SIZE, "Link Down\n"); + else if (atomic_read(&ha->loop_state) != LOOP_READY || + test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) || + test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) + len = snprintf(buf, PAGE_SIZE, "Unknown Link State\n"); + else { + len = snprintf(buf, PAGE_SIZE, "Link Up - "); + + switch (ha->current_topology) { + case ISP_CFG_NL: + len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n"); + break; + case ISP_CFG_FL: + len += snprintf(buf + len, PAGE_SIZE-len, "FL_Port\n"); + break; + case ISP_CFG_N: + len += snprintf(buf + len, PAGE_SIZE-len, + "N_Port to N_Port\n"); + break; + case ISP_CFG_F: + len += snprintf(buf + len, PAGE_SIZE-len, "F_Port\n"); + break; + default: + len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n"); + break; + } + } + return len; +} + +static ssize_t +qla2x00_zio_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + int len = 0; + + switch (ha->zio_mode) { + case QLA_ZIO_MODE_5: + len += snprintf(buf + len, PAGE_SIZE-len, "Mode 5\n"); + break; + case QLA_ZIO_MODE_6: + len += snprintf(buf + len, PAGE_SIZE-len, "Mode 6\n"); + break; + case QLA_ZIO_DISABLED: + len += snprintf(buf + len, PAGE_SIZE-len, "Disabled\n"); + break; + } + return len; +} + +static ssize_t +qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + int val = 0; + uint16_t zio_mode; + + if (sscanf(buf, "%d", &val) != 1) + return -EINVAL; + + switch (val) { + case 1: + zio_mode = QLA_ZIO_MODE_5; + break; + case 2: + zio_mode = QLA_ZIO_MODE_6; + break; + default: + zio_mode = QLA_ZIO_DISABLED; + break; + } + + /* Update per-hba values and queue a reset. */ + if (zio_mode != QLA_ZIO_DISABLED || ha->zio_mode != QLA_ZIO_DISABLED) { + ha->zio_mode = zio_mode; + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + } + return strlen(buf); +} + +static ssize_t +qla2x00_zio_timer_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + + return snprintf(buf, PAGE_SIZE, "%d us\n", ha->zio_timer * 100); +} + +static ssize_t +qla2x00_zio_timer_store(struct class_device *cdev, const char *buf, + size_t count) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + int val = 0; + uint16_t zio_timer; + + if (sscanf(buf, "%d", &val) != 1) + return -EINVAL; + if (val > 25500 || val < 100) + return -ERANGE; + + zio_timer = (uint16_t)(val / 100); + ha->zio_timer = zio_timer; + + return strlen(buf); +} + +static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, + NULL); +static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); +static CLASS_DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); +static CLASS_DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL); +static CLASS_DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL); +static CLASS_DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL); +static CLASS_DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL); +static CLASS_DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL); +static CLASS_DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL); +static CLASS_DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show, + qla2x00_zio_store); +static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show, + qla2x00_zio_timer_store); + +struct class_device_attribute *qla2x00_host_attrs[] = { + &class_device_attr_driver_version, + &class_device_attr_fw_version, + &class_device_attr_serial_num, + &class_device_attr_isp_name, + &class_device_attr_isp_id, + &class_device_attr_model_name, + &class_device_attr_model_desc, + &class_device_attr_pci_info, + &class_device_attr_state, + &class_device_attr_zio, + &class_device_attr_zio_timer, + NULL, +}; + /* Host attributes. */ static void @@ -228,16 +431,16 @@ qla2x00_get_starget_node_name(struct scsi_target *starget) struct Scsi_Host *host = dev_to_shost(starget->dev.parent); scsi_qla_host_t *ha = to_qla_host(host); fc_port_t *fcport; - uint64_t node_name = 0; + u64 node_name = 0; list_for_each_entry(fcport, &ha->fcports, list) { if (starget->id == fcport->os_target_id) { - node_name = *(uint64_t *)fcport->node_name; + node_name = wwn_to_u64(fcport->node_name); break; } } - fc_starget_node_name(starget) = be64_to_cpu(node_name); + fc_starget_node_name(starget) = node_name; } static void @@ -246,16 +449,16 @@ qla2x00_get_starget_port_name(struct scsi_target *starget) struct Scsi_Host *host = dev_to_shost(starget->dev.parent); scsi_qla_host_t *ha = to_qla_host(host); fc_port_t *fcport; - uint64_t port_name = 0; + u64 port_name = 0; list_for_each_entry(fcport, &ha->fcports, list) { if (starget->id == fcport->os_target_id) { - port_name = *(uint64_t *)fcport->port_name; + port_name = wwn_to_u64(fcport->port_name); break; } } - fc_starget_port_name(starget) = be64_to_cpu(port_name); + fc_starget_port_name(starget) = port_name; } static void @@ -300,14 +503,26 @@ qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) rport->dev_loss_tmo = ha->port_down_retry_count + 5; } +static int +qla2x00_issue_lip(struct Scsi_Host *shost) +{ + scsi_qla_host_t *ha = to_qla_host(shost); + + set_bit(LOOP_RESET_NEEDED, &ha->dpc_flags); + return 0; +} + struct fc_function_template qla2xxx_transport_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, .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, @@ -320,13 +535,13 @@ struct fc_function_template qla2xxx_transport_functions = { .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo, .show_rport_dev_loss_tmo = 1, + .issue_fc_host_lip = qla2x00_issue_lip, }; void qla2x00_init_host_attr(scsi_qla_host_t *ha) { - fc_host_node_name(ha->host) = - be64_to_cpu(*(uint64_t *)ha->init_cb->node_name); - fc_host_port_name(ha->host) = - be64_to_cpu(*(uint64_t *)ha->init_cb->port_name); + fc_host_node_name(ha->host) = wwn_to_u64(ha->init_cb->node_name); + fc_host_port_name(ha->host) = wwn_to_u64(ha->init_cb->port_name); + fc_host_supported_classes(ha->host) = FC_COS_CLASS3; }