qla_attr.c revision 30c4766213aeb684ee477ac7f36703f9134ac7ad
1d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek/* 2d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek * QLogic Fibre Channel HBA Driver 3d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek * Copyright (c) 2003-2005 QLogic Corporation 4d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek * 5d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek * See LICENSE.qla2xxx for copyright and licensing details. 6d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek */ 7d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek#include "qla_def.h" 8d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 9d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek#include <linux/vmalloc.h> 10d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 11d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek/* SYSFS attributes --------------------------------------------------------- */ 12d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 13d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 14d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off, 15d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek size_t count) 16d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 17d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 18d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct device, kobj))); 19d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek char *rbuf = (char *)ha->fw_dump; 20d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 21d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (ha->fw_dump_reading == 0) 22d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return 0; 23d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (off > ha->fw_dump_len) 24d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return 0; 25d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (off + count > ha->fw_dump_len) 26d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek count = ha->fw_dump_len - off; 27d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 28d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek memcpy(buf, &rbuf[off], count); 29d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 30d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return (count); 31d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 32d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 33d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 34d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off, 35d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek size_t count) 36d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 37d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 38d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct device, kobj))); 39d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek int reading; 40d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 41d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (off != 0) 42d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return (0); 43d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 44d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek reading = simple_strtol(buf, NULL, 10); 45d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek switch (reading) { 46d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek case 0: 47d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (!ha->fw_dump_reading) 48d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 49d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 50d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla_printk(KERN_INFO, ha, 51d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek "Firmware dump cleared on (%ld).\n", ha->host_no); 52d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 53d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->fw_dump_reading = 0; 54d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->fw_dumped = 0; 55d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 56d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek case 1: 57d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (ha->fw_dumped && !ha->fw_dump_reading) { 58d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->fw_dump_reading = 1; 59d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 60d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla_printk(KERN_INFO, ha, 61d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek "Raw firmware dump ready for read on (%ld).\n", 62d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->host_no); 63d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 64d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 65d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek case 2: 66d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla2x00_alloc_fw_dump(ha); 67d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 68d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 69d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return (count); 70d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 71d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 72a8d380f30a7d8cc507fd5cc84b2dc5ee2b2144d7Dima Zavinstatic struct bin_attribute sysfs_fw_dump_attr = { 73d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .attr = { 74d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .name = "fw_dump", 75d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .mode = S_IRUSR | S_IWUSR, 76d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .owner = THIS_MODULE, 77d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek }, 78d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .size = 0, 79d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .read = qla2x00_sysfs_read_fw_dump, 80d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .write = qla2x00_sysfs_write_fw_dump, 81d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek}; 82d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 83d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 84d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off, 85d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek size_t count) 86d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 87d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 88d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct device, kobj))); 89d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek unsigned long flags; 90d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 91d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (!capable(CAP_SYS_ADMIN) || off != 0) 92d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return 0; 93d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 94d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek /* Read NVRAM. */ 95d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek spin_lock_irqsave(&ha->hardware_lock, flags); 96d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->nvram_base, 97d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->nvram_size); 98d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek spin_unlock_irqrestore(&ha->hardware_lock, flags); 99d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 100d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return ha->nvram_size; 101d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 102d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 103d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 104d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off, 105d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek size_t count) 106d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 107d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 108d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct device, kobj))); 109d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek unsigned long flags; 110d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek uint16_t cnt; 111d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 112d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size) 113d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return 0; 114d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 115d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek /* Checksum NVRAM. */ 116d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { 117d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek uint32_t *iter; 118d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek uint32_t chksum; 119d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 120d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek iter = (uint32_t *)buf; 121d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek chksum = 0; 122d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek for (cnt = 0; cnt < ((count >> 2) - 1); cnt++) 123d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek chksum += le32_to_cpu(*iter++); 124d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek chksum = ~chksum + 1; 125d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek *iter = cpu_to_le32(chksum); 126d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } else { 127d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek uint8_t *iter; 128d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek uint8_t chksum; 129d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 130d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek iter = (uint8_t *)buf; 131d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek chksum = 0; 132d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek for (cnt = 0; cnt < count - 1; cnt++) 133d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek chksum += *iter++; 134d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek chksum = ~chksum + 1; 135d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek *iter = chksum; 136d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 137d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 138d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek /* Write NVRAM. */ 139d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek spin_lock_irqsave(&ha->hardware_lock, flags); 140d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); 141d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek spin_unlock_irqrestore(&ha->hardware_lock, flags); 142d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 143d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return (count); 144d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 145d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 146d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic struct bin_attribute sysfs_nvram_attr = { 147d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .attr = { 148d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .name = "nvram", 149d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .mode = S_IRUSR | S_IWUSR, 150d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .owner = THIS_MODULE, 151d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek }, 152d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .size = 512, 153d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .read = qla2x00_sysfs_read_nvram, 154d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .write = qla2x00_sysfs_write_nvram, 155d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek}; 156d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 157d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 158d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off, 159d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek size_t count) 160d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 161d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 162d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct device, kobj))); 163d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 164d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (ha->optrom_state != QLA_SREADING) 165d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return 0; 166d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (off > ha->optrom_size) 167d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return 0; 168d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (off + count > ha->optrom_size) 169d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek count = ha->optrom_size - off; 170d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 171d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek memcpy(buf, &ha->optrom_buffer[off], count); 172d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 173d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return count; 174d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 175d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 176d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 177d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off, 178d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek size_t count) 179d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 180d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 181d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct device, kobj))); 182d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 183d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (ha->optrom_state != QLA_SWRITING) 184d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return -EINVAL; 185d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (off > ha->optrom_size) 186d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return -ERANGE; 187d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (off + count > ha->optrom_size) 188d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek count = ha->optrom_size - off; 189d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 190d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek memcpy(&ha->optrom_buffer[off], buf, count); 191d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 192d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return count; 193d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 194d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 195d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic struct bin_attribute sysfs_optrom_attr = { 196d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .attr = { 197d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .name = "optrom", 198d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .mode = S_IRUSR | S_IWUSR, 199d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .owner = THIS_MODULE, 200d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek }, 201d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .size = OPTROM_SIZE_24XX, 202d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .read = qla2x00_sysfs_read_optrom, 203d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .write = qla2x00_sysfs_write_optrom, 204d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek}; 205d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 206d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 207d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off, 208d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek size_t count) 209d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 210d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 211d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct device, kobj))); 212d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek int val; 213d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 214d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (off) 215d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return 0; 216d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 217d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (sscanf(buf, "%d", &val) != 1) 218d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return -EINVAL; 219d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 220d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek switch (val) { 221d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek case 0: 222d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (ha->optrom_state != QLA_SREADING && 223d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->optrom_state != QLA_SWRITING) 224d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 225d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 226d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->optrom_state = QLA_SWAITING; 227d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek vfree(ha->optrom_buffer); 228d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->optrom_buffer = NULL; 229d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 230d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek case 1: 231d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (ha->optrom_state != QLA_SWAITING) 232d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 233d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 234d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->optrom_state = QLA_SREADING; 235d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size); 236d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (ha->optrom_buffer == NULL) { 237d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla_printk(KERN_WARNING, ha, 238d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek "Unable to allocate memory for optrom retrieval " 239d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek "(%x).\n", ha->optrom_size); 240d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 241d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->optrom_state = QLA_SWAITING; 242d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return count; 243d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 244d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 245d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek memset(ha->optrom_buffer, 0, ha->optrom_size); 246d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->isp_ops.read_optrom(ha, ha->optrom_buffer, 0, 247d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->optrom_size); 248d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 249d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek case 2: 250d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (ha->optrom_state != QLA_SWAITING) 251d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 252d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 253d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->optrom_state = QLA_SWRITING; 254d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size); 255d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (ha->optrom_buffer == NULL) { 256d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla_printk(KERN_WARNING, ha, 257d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek "Unable to allocate memory for optrom update " 258d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek "(%x).\n", ha->optrom_size); 259d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 260d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->optrom_state = QLA_SWAITING; 261d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return count; 262d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 263d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek memset(ha->optrom_buffer, 0, ha->optrom_size); 264d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 265d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek case 3: 266d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (ha->optrom_state != QLA_SWRITING) 267d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 268d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 269d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->isp_ops.write_optrom(ha, ha->optrom_buffer, 0, 270d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->optrom_size); 271d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 272d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 273d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return count; 274d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 275d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 276d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic struct bin_attribute sysfs_optrom_ctl_attr = { 277d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .attr = { 278d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .name = "optrom_ctl", 279d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .mode = S_IWUSR, 280d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .owner = THIS_MODULE, 281d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek }, 282d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .size = 0, 283d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .write = qla2x00_sysfs_write_optrom_ctl, 284d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek}; 285d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 286d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 287d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off, 288d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek size_t count) 289d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 290d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 291d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct device, kobj))); 292d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek unsigned long flags; 293d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 294d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (!capable(CAP_SYS_ADMIN) || off != 0) 295d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return 0; 296d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 297d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek /* Read NVRAM. */ 298d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek spin_lock_irqsave(&ha->hardware_lock, flags); 299d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->vpd_base, ha->vpd_size); 300d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek spin_unlock_irqrestore(&ha->hardware_lock, flags); 301d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 302d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return ha->vpd_size; 303d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 304d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 305d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 306d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off, 307d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek size_t count) 308d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 309d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 310d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct device, kobj))); 311d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek unsigned long flags; 312d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 313d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size) 314d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return 0; 315d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 316d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek /* Write NVRAM. */ 317d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek spin_lock_irqsave(&ha->hardware_lock, flags); 318d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); 319d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek spin_unlock_irqrestore(&ha->hardware_lock, flags); 320d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 321d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return count; 322d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 323d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 324d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic struct bin_attribute sysfs_vpd_attr = { 325d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .attr = { 326d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .name = "vpd", 327d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .mode = S_IRUSR | S_IWUSR, 328d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .owner = THIS_MODULE, 329d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek }, 330d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .size = 0, 331d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .read = qla2x00_sysfs_read_vpd, 332d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .write = qla2x00_sysfs_write_vpd, 333d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek}; 334d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 335d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 336d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off, 337d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek size_t count) 338d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 339d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 340d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct device, kobj))); 341d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek uint16_t iter, addr, offset; 342d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek int rval; 343d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 344d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (!capable(CAP_SYS_ADMIN) || off != 0 || count != SFP_DEV_SIZE * 2) 345d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return 0; 346d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 347d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek addr = 0xa0; 348d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek for (iter = 0, offset = 0; iter < (SFP_DEV_SIZE * 2) / SFP_BLOCK_SIZE; 349d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek iter++, offset += SFP_BLOCK_SIZE) { 350d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (iter == 4) { 351d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek /* Skip to next device address. */ 352d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek addr = 0xa2; 353d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek offset = 0; 354d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 355d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 356d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek rval = qla2x00_read_sfp(ha, ha->sfp_data_dma, addr, offset, 357d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek SFP_BLOCK_SIZE); 358d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (rval != QLA_SUCCESS) { 359d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla_printk(KERN_WARNING, ha, 360d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek "Unable to read SFP data (%x/%x/%x).\n", rval, 361d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek addr, offset); 362d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek count = 0; 363d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 364d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 365d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek memcpy(buf, ha->sfp_data, SFP_BLOCK_SIZE); 366d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek buf += SFP_BLOCK_SIZE; 367d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 368d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 369d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return count; 370d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 371d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 372d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic struct bin_attribute sysfs_sfp_attr = { 373d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .attr = { 374d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .name = "sfp", 375d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .mode = S_IRUSR | S_IWUSR, 376d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .owner = THIS_MODULE, 377d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek }, 378d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .size = SFP_DEV_SIZE * 2, 379d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek .read = qla2x00_sysfs_read_sfp, 380d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek}; 381d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 382d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic struct sysfs_entry { 383d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek char *name; 384d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct bin_attribute *attr; 385d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek int is4GBp_only; 386d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} bin_file_entries[] = { 387d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek { "fw_dump", &sysfs_fw_dump_attr, }, 388d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek { "nvram", &sysfs_nvram_attr, }, 389d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek { "optrom", &sysfs_optrom_attr, }, 390d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek { "optrom_ctl", &sysfs_optrom_ctl_attr, }, 391d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek { "vpd", &sysfs_vpd_attr, 1 }, 392d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek { "sfp", &sysfs_sfp_attr, 1 }, 393d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek { NULL }, 394d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek}; 395d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 396d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekvoid 397d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) 398d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 399d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct Scsi_Host *host = ha->host; 400d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct sysfs_entry *iter; 401d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek int ret; 402d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 403d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek for (iter = bin_file_entries; iter->name; iter++) { 404d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (iter->is4GBp_only && (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))) 405d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek continue; 406d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 407d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ret = sysfs_create_bin_file(&host->shost_gendev.kobj, 408d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek iter->attr); 409d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (ret) 410d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla_printk(KERN_INFO, ha, 411d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek "Unable to create sysfs %s binary attribute " 412d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek "(%d).\n", iter->name, ret); 413d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 414d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 415d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 416d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekvoid 417d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_free_sysfs_attr(scsi_qla_host_t *ha) 418d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 419d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct Scsi_Host *host = ha->host; 420d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek struct sysfs_entry *iter; 421d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 422d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek for (iter = bin_file_entries; iter->name; iter++) { 423d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (iter->is4GBp_only && (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))) 424d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek continue; 425d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 426d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek sysfs_remove_bin_file(&host->shost_gendev.kobj, 427d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek iter->attr); 428d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 429d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 430d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (ha->beacon_blink_led == 1) 431d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->isp_ops.beacon_off(ha); 432d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 433d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 434d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek/* Scsi_Host attributes. */ 435d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 436d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 437d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_drvr_version_show(struct class_device *cdev, char *buf) 438d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 439d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return snprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str); 440d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 441d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 442d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 443d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_fw_version_show(struct class_device *cdev, char *buf) 444d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 445d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 446d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek char fw_str[30]; 447d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 448d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return snprintf(buf, PAGE_SIZE, "%s\n", 449d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->isp_ops.fw_version_str(ha, fw_str)); 450d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 451d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 452d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 453d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_serial_num_show(struct class_device *cdev, char *buf) 454d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 455d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 456d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek uint32_t sn; 457d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 458d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1; 459d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000, 460d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek sn % 100000); 461d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 462d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 463d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 464d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_isp_name_show(struct class_device *cdev, char *buf) 465d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 466d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 467d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return snprintf(buf, PAGE_SIZE, "ISP%04X\n", ha->pdev->device); 468d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 469d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 470d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 471d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_isp_id_show(struct class_device *cdev, char *buf) 472d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 473d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 474d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n", 475d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->product_id[0], ha->product_id[1], ha->product_id[2], 476d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->product_id[3]); 477d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 478d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 479d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 480d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_model_name_show(struct class_device *cdev, char *buf) 481d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 482d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 483d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_number); 484d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 485d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 486d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 487d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_model_desc_show(struct class_device *cdev, char *buf) 488d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 489d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 490d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return snprintf(buf, PAGE_SIZE, "%s\n", 491d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->model_desc ? ha->model_desc: ""); 492d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 493d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 494d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 495d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_pci_info_show(struct class_device *cdev, char *buf) 496d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 497d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 498d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek char pci_info[30]; 499d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 500d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return snprintf(buf, PAGE_SIZE, "%s\n", 501d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->isp_ops.pci_info_str(ha, pci_info)); 502d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 503d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 504d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 505d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_state_show(struct class_device *cdev, char *buf) 506d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 507d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 508d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek int len = 0; 509d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 510d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (atomic_read(&ha->loop_state) == LOOP_DOWN || 511d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek atomic_read(&ha->loop_state) == LOOP_DEAD) 512d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek len = snprintf(buf, PAGE_SIZE, "Link Down\n"); 513d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek else if (atomic_read(&ha->loop_state) != LOOP_READY || 514d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) || 515d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) 516d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek len = snprintf(buf, PAGE_SIZE, "Unknown Link State\n"); 517d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek else { 518d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek len = snprintf(buf, PAGE_SIZE, "Link Up - "); 519d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 520d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek switch (ha->current_topology) { 521d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek case ISP_CFG_NL: 522d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n"); 523d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 524d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek case ISP_CFG_FL: 525d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek len += snprintf(buf + len, PAGE_SIZE-len, "FL_Port\n"); 526d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 527d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek case ISP_CFG_N: 528d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek len += snprintf(buf + len, PAGE_SIZE-len, 529d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek "N_Port to N_Port\n"); 530d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 531d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek case ISP_CFG_F: 532d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek len += snprintf(buf + len, PAGE_SIZE-len, "F_Port\n"); 533d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 534d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek default: 535d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n"); 536d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 537d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 538d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 539d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return len; 540d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 541d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 542d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 543d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_zio_show(struct class_device *cdev, char *buf) 544d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 545d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 546d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek int len = 0; 547d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 548d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek switch (ha->zio_mode) { 549d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek case QLA_ZIO_MODE_6: 550d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek len += snprintf(buf + len, PAGE_SIZE-len, "Mode 6\n"); 551d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 552d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek case QLA_ZIO_DISABLED: 553d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek len += snprintf(buf + len, PAGE_SIZE-len, "Disabled\n"); 554d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek break; 555d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 556d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return len; 557d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 558d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 559d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 560d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count) 561d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 562d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 563d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek int val = 0; 564d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek uint16_t zio_mode; 565d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 566d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (!IS_ZIO_SUPPORTED(ha)) 567d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return -ENOTSUPP; 568d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 569d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (sscanf(buf, "%d", &val) != 1) 570d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return -EINVAL; 571d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 572d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (val) 573d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek zio_mode = QLA_ZIO_MODE_6; 574d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek else 575d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek zio_mode = QLA_ZIO_DISABLED; 576d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 577d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek /* Update per-hba values and queue a reset. */ 578d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (zio_mode != QLA_ZIO_DISABLED || ha->zio_mode != QLA_ZIO_DISABLED) { 579d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->zio_mode = zio_mode; 580d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); 581d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 582d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return strlen(buf); 583d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 584d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 585d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 586d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_zio_timer_show(struct class_device *cdev, char *buf) 587d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 588d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 589d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 590d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return snprintf(buf, PAGE_SIZE, "%d us\n", ha->zio_timer * 100); 591d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 592d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 593d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 594d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_zio_timer_store(struct class_device *cdev, const char *buf, 595d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek size_t count) 596d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 597d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 598d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek int val = 0; 599d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek uint16_t zio_timer; 600d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 601d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (sscanf(buf, "%d", &val) != 1) 602d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return -EINVAL; 603d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (val > 25500 || val < 100) 604d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return -ERANGE; 605d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 606d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek zio_timer = (uint16_t)(val / 100); 607d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->zio_timer = zio_timer; 608d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 609d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return strlen(buf); 610d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 611d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 612d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 613d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_beacon_show(struct class_device *cdev, char *buf) 614d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 615d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 616d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek int len = 0; 617d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 618d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (ha->beacon_blink_led) 619d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek len += snprintf(buf + len, PAGE_SIZE-len, "Enabled\n"); 620d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek else 621d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek len += snprintf(buf + len, PAGE_SIZE-len, "Disabled\n"); 622d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return len; 623d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 624d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 625d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 626d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_beacon_store(struct class_device *cdev, const char *buf, 627d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek size_t count) 628d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 629d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 630d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek int val = 0; 631d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek int rval; 632d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 633d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (IS_QLA2100(ha) || IS_QLA2200(ha)) 634d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return -EPERM; 635d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 636d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) { 637d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla_printk(KERN_WARNING, ha, 638d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek "Abort ISP active -- ignoring beacon request.\n"); 639d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return -EBUSY; 640d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek } 641d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 642d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (sscanf(buf, "%d", &val) != 1) 643d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return -EINVAL; 644d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 645d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (val) 646d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek rval = ha->isp_ops.beacon_on(ha); 647d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek else 648d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek rval = ha->isp_ops.beacon_off(ha); 649d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 650d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek if (rval != QLA_SUCCESS) 651d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek count = 0; 652d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 653d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return count; 654d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 655d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 656d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 657d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_optrom_bios_version_show(struct class_device *cdev, char *buf) 658d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 659d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 660d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 661d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1], 662d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->bios_revision[0]); 663d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 664d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 665d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 666d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_optrom_efi_version_show(struct class_device *cdev, char *buf) 667d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 668d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 669d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 670d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1], 671d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->efi_revision[0]); 672d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 673d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 674d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 675d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_optrom_fcode_version_show(struct class_device *cdev, char *buf) 676d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 677d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 678d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 679d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1], 680d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->fcode_revision[0]); 681d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 682d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 683d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic ssize_t 684d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekqla2x00_optrom_fw_version_show(struct class_device *cdev, char *buf) 685d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek{ 686d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); 687d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 688d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n", 689d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2], 690d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek ha->fw_revision[3]); 691d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek} 692d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 693d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, 694d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek NULL); 695d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); 696d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); 697d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL); 698d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL); 699d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL); 700d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL); 701d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL); 702d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL); 703d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show, 704d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla2x00_zio_store); 705d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show, 706d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla2x00_zio_timer_store); 707d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show, 708d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla2x00_beacon_store); 709d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(optrom_bios_version, S_IRUGO, 710d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla2x00_optrom_bios_version_show, NULL); 711d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(optrom_efi_version, S_IRUGO, 712d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla2x00_optrom_efi_version_show, NULL); 713d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(optrom_fcode_version, S_IRUGO, 714d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla2x00_optrom_fcode_version_show, NULL); 715d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstatic CLASS_DEVICE_ATTR(optrom_fw_version, S_IRUGO, 716d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek qla2x00_optrom_fw_version_show, NULL); 717d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek 718d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machekstruct class_device_attribute *qla2x00_host_attrs[] = { 719d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek &class_device_attr_driver_version, 720d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek &class_device_attr_fw_version, 721d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek &class_device_attr_serial_num, 722d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek &class_device_attr_isp_name, 723d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek &class_device_attr_isp_id, 724d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek &class_device_attr_model_name, 725d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek &class_device_attr_model_desc, 726d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek &class_device_attr_pci_info, 727d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek &class_device_attr_state, 728d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek &class_device_attr_zio, 729d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek &class_device_attr_zio_timer, 730d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek &class_device_attr_beacon, 731d480ace08d5b59133575e672a0bd1c97b0f8400fPavel Machek &class_device_attr_optrom_bios_version, 732 &class_device_attr_optrom_efi_version, 733 &class_device_attr_optrom_fcode_version, 734 &class_device_attr_optrom_fw_version, 735 NULL, 736}; 737 738/* Host attributes. */ 739 740static void 741qla2x00_get_host_port_id(struct Scsi_Host *shost) 742{ 743 scsi_qla_host_t *ha = to_qla_host(shost); 744 745 fc_host_port_id(shost) = ha->d_id.b.domain << 16 | 746 ha->d_id.b.area << 8 | ha->d_id.b.al_pa; 747} 748 749static void 750qla2x00_get_host_speed(struct Scsi_Host *shost) 751{ 752 scsi_qla_host_t *ha = to_qla_host(shost); 753 uint32_t speed = 0; 754 755 switch (ha->link_data_rate) { 756 case PORT_SPEED_1GB: 757 speed = 1; 758 break; 759 case PORT_SPEED_2GB: 760 speed = 2; 761 break; 762 case PORT_SPEED_4GB: 763 speed = 4; 764 break; 765 } 766 fc_host_speed(shost) = speed; 767} 768 769static void 770qla2x00_get_host_port_type(struct Scsi_Host *shost) 771{ 772 scsi_qla_host_t *ha = to_qla_host(shost); 773 uint32_t port_type = FC_PORTTYPE_UNKNOWN; 774 775 switch (ha->current_topology) { 776 case ISP_CFG_NL: 777 port_type = FC_PORTTYPE_LPORT; 778 break; 779 case ISP_CFG_FL: 780 port_type = FC_PORTTYPE_NLPORT; 781 break; 782 case ISP_CFG_N: 783 port_type = FC_PORTTYPE_PTP; 784 break; 785 case ISP_CFG_F: 786 port_type = FC_PORTTYPE_NPORT; 787 break; 788 } 789 fc_host_port_type(shost) = port_type; 790} 791 792static void 793qla2x00_get_starget_node_name(struct scsi_target *starget) 794{ 795 struct Scsi_Host *host = dev_to_shost(starget->dev.parent); 796 scsi_qla_host_t *ha = to_qla_host(host); 797 fc_port_t *fcport; 798 u64 node_name = 0; 799 800 list_for_each_entry(fcport, &ha->fcports, list) { 801 if (starget->id == fcport->os_target_id) { 802 node_name = wwn_to_u64(fcport->node_name); 803 break; 804 } 805 } 806 807 fc_starget_node_name(starget) = node_name; 808} 809 810static void 811qla2x00_get_starget_port_name(struct scsi_target *starget) 812{ 813 struct Scsi_Host *host = dev_to_shost(starget->dev.parent); 814 scsi_qla_host_t *ha = to_qla_host(host); 815 fc_port_t *fcport; 816 u64 port_name = 0; 817 818 list_for_each_entry(fcport, &ha->fcports, list) { 819 if (starget->id == fcport->os_target_id) { 820 port_name = wwn_to_u64(fcport->port_name); 821 break; 822 } 823 } 824 825 fc_starget_port_name(starget) = port_name; 826} 827 828static void 829qla2x00_get_starget_port_id(struct scsi_target *starget) 830{ 831 struct Scsi_Host *host = dev_to_shost(starget->dev.parent); 832 scsi_qla_host_t *ha = to_qla_host(host); 833 fc_port_t *fcport; 834 uint32_t port_id = ~0U; 835 836 list_for_each_entry(fcport, &ha->fcports, list) { 837 if (starget->id == fcport->os_target_id) { 838 port_id = fcport->d_id.b.domain << 16 | 839 fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; 840 break; 841 } 842 } 843 844 fc_starget_port_id(starget) = port_id; 845} 846 847static void 848qla2x00_get_rport_loss_tmo(struct fc_rport *rport) 849{ 850 struct Scsi_Host *host = rport_to_shost(rport); 851 scsi_qla_host_t *ha = to_qla_host(host); 852 853 rport->dev_loss_tmo = ha->port_down_retry_count + 5; 854} 855 856static void 857qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) 858{ 859 struct Scsi_Host *host = rport_to_shost(rport); 860 scsi_qla_host_t *ha = to_qla_host(host); 861 862 if (timeout) 863 ha->port_down_retry_count = timeout; 864 else 865 ha->port_down_retry_count = 1; 866 867 rport->dev_loss_tmo = ha->port_down_retry_count + 5; 868} 869 870static int 871qla2x00_issue_lip(struct Scsi_Host *shost) 872{ 873 scsi_qla_host_t *ha = to_qla_host(shost); 874 875 set_bit(LOOP_RESET_NEEDED, &ha->dpc_flags); 876 return 0; 877} 878 879static struct fc_host_statistics * 880qla2x00_get_fc_host_stats(struct Scsi_Host *shost) 881{ 882 scsi_qla_host_t *ha = to_qla_host(shost); 883 int rval; 884 uint16_t mb_stat[1]; 885 link_stat_t stat_buf; 886 struct fc_host_statistics *pfc_host_stat; 887 888 pfc_host_stat = &ha->fc_host_stat; 889 memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); 890 891 if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { 892 rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, 893 sizeof(stat_buf) / 4, mb_stat); 894 } else { 895 rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf, 896 mb_stat); 897 } 898 if (rval != 0) { 899 qla_printk(KERN_WARNING, ha, 900 "Unable to retrieve host statistics (%d).\n", mb_stat[0]); 901 return pfc_host_stat; 902 } 903 904 pfc_host_stat->link_failure_count = stat_buf.link_fail_cnt; 905 pfc_host_stat->loss_of_sync_count = stat_buf.loss_sync_cnt; 906 pfc_host_stat->loss_of_signal_count = stat_buf.loss_sig_cnt; 907 pfc_host_stat->prim_seq_protocol_err_count = stat_buf.prim_seq_err_cnt; 908 pfc_host_stat->invalid_tx_word_count = stat_buf.inval_xmit_word_cnt; 909 pfc_host_stat->invalid_crc_count = stat_buf.inval_crc_cnt; 910 911 return pfc_host_stat; 912} 913 914static void 915qla2x00_get_host_symbolic_name(struct Scsi_Host *shost) 916{ 917 scsi_qla_host_t *ha = to_qla_host(shost); 918 919 qla2x00_get_sym_node_name(ha, fc_host_symbolic_name(shost)); 920} 921 922static void 923qla2x00_set_host_system_hostname(struct Scsi_Host *shost) 924{ 925 scsi_qla_host_t *ha = to_qla_host(shost); 926 927 set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); 928} 929 930static void 931qla2x00_get_host_fabric_name(struct Scsi_Host *shost) 932{ 933 scsi_qla_host_t *ha = to_qla_host(shost); 934 u64 node_name; 935 936 if (ha->device_flags & SWITCH_FOUND) 937 node_name = wwn_to_u64(ha->fabric_node_name); 938 else 939 node_name = wwn_to_u64(ha->node_name); 940 941 fc_host_fabric_name(shost) = node_name; 942} 943 944static void 945qla2x00_get_host_port_state(struct Scsi_Host *shost) 946{ 947 scsi_qla_host_t *ha = to_qla_host(shost); 948 949 if (!ha->flags.online) 950 fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; 951 else if (atomic_read(&ha->loop_state) == LOOP_TIMEOUT) 952 fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN; 953 else 954 fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; 955} 956 957struct fc_function_template qla2xxx_transport_functions = { 958 959 .show_host_node_name = 1, 960 .show_host_port_name = 1, 961 .show_host_supported_classes = 1, 962 963 .get_host_port_id = qla2x00_get_host_port_id, 964 .show_host_port_id = 1, 965 .get_host_speed = qla2x00_get_host_speed, 966 .show_host_speed = 1, 967 .get_host_port_type = qla2x00_get_host_port_type, 968 .show_host_port_type = 1, 969 .get_host_symbolic_name = qla2x00_get_host_symbolic_name, 970 .show_host_symbolic_name = 1, 971 .set_host_system_hostname = qla2x00_set_host_system_hostname, 972 .show_host_system_hostname = 1, 973 .get_host_fabric_name = qla2x00_get_host_fabric_name, 974 .show_host_fabric_name = 1, 975 .get_host_port_state = qla2x00_get_host_port_state, 976 .show_host_port_state = 1, 977 978 .dd_fcrport_size = sizeof(struct fc_port *), 979 .show_rport_supported_classes = 1, 980 981 .get_starget_node_name = qla2x00_get_starget_node_name, 982 .show_starget_node_name = 1, 983 .get_starget_port_name = qla2x00_get_starget_port_name, 984 .show_starget_port_name = 1, 985 .get_starget_port_id = qla2x00_get_starget_port_id, 986 .show_starget_port_id = 1, 987 988 .get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo, 989 .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo, 990 .show_rport_dev_loss_tmo = 1, 991 992 .issue_fc_host_lip = qla2x00_issue_lip, 993 .get_fc_host_stats = qla2x00_get_fc_host_stats, 994}; 995 996void 997qla2x00_init_host_attr(scsi_qla_host_t *ha) 998{ 999 fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name); 1000 fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name); 1001 fc_host_supported_classes(ha->host) = FC_COS_CLASS3; 1002} 1003