qla_attr.c
来自「linux 内核源代码」· C语言 代码 · 共 1,253 行 · 第 1/3 页
C
1,253 行
/* * QLogic Fibre Channel HBA Driver * Copyright (c) 2003-2005 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */#include "qla_def.h"#include <linux/kthread.h>#include <linux/vmalloc.h>int qla24xx_vport_disable(struct fc_vport *, bool);/* SYSFS attributes --------------------------------------------------------- */static ssize_tqla2x00_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 = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); char *rbuf = (char *)ha->fw_dump; if (ha->fw_dump_reading == 0) return 0; if (off > ha->fw_dump_len) return 0; if (off + count > ha->fw_dump_len) count = ha->fw_dump_len - off; memcpy(buf, &rbuf[off], count); return (count);}static ssize_tqla2x00_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 = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); int reading; if (off != 0) return (0); reading = simple_strtol(buf, NULL, 10); switch (reading) { case 0: if (!ha->fw_dump_reading) break; qla_printk(KERN_INFO, ha, "Firmware dump cleared on (%ld).\n", ha->host_no); ha->fw_dump_reading = 0; ha->fw_dumped = 0; break; case 1: if (ha->fw_dumped && !ha->fw_dump_reading) { ha->fw_dump_reading = 1; qla_printk(KERN_INFO, ha, "Raw firmware dump ready for read on (%ld).\n", ha->host_no); } break; case 2: qla2x00_alloc_fw_dump(ha); break; } return (count);}static struct bin_attribute sysfs_fw_dump_attr = { .attr = { .name = "fw_dump", .mode = S_IRUSR | S_IWUSR, }, .size = 0, .read = qla2x00_sysfs_read_fw_dump, .write = qla2x00_sysfs_write_fw_dump,};static ssize_tqla2x00_sysfs_read_nvram(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count){ struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); int size = ha->nvram_size; char *nvram_cache = ha->nvram; if (!capable(CAP_SYS_ADMIN) || off > size || count == 0) return 0; if (off + count > size) { size -= off; count = size; } /* Read NVRAM data from cache. */ memcpy(buf, &nvram_cache[off], count); return count;}static ssize_tqla2x00_sysfs_write_nvram(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count){ struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); uint16_t cnt; if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size) return 0; /* Checksum NVRAM. */ if (IS_FWI2_CAPABLE(ha)) { uint32_t *iter; uint32_t chksum; iter = (uint32_t *)buf; chksum = 0; for (cnt = 0; cnt < ((count >> 2) - 1); cnt++) chksum += le32_to_cpu(*iter++); chksum = ~chksum + 1; *iter = cpu_to_le32(chksum); } else { uint8_t *iter; uint8_t chksum; iter = (uint8_t *)buf; chksum = 0; for (cnt = 0; cnt < count - 1; cnt++) chksum += *iter++; chksum = ~chksum + 1; *iter = chksum; } /* Write NVRAM. */ ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); ha->isp_ops->read_nvram(ha, (uint8_t *)ha->nvram, ha->nvram_base, count); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); return (count);}static struct bin_attribute sysfs_nvram_attr = { .attr = { .name = "nvram", .mode = S_IRUSR | S_IWUSR, }, .size = 512, .read = qla2x00_sysfs_read_nvram, .write = qla2x00_sysfs_write_nvram,};static ssize_tqla2x00_sysfs_read_optrom(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count){ struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); if (ha->optrom_state != QLA_SREADING) return 0; if (off > ha->optrom_region_size) return 0; if (off + count > ha->optrom_region_size) count = ha->optrom_region_size - off; memcpy(buf, &ha->optrom_buffer[off], count); return count;}static ssize_tqla2x00_sysfs_write_optrom(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count){ struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); if (ha->optrom_state != QLA_SWRITING) return -EINVAL; if (off > ha->optrom_region_size) return -ERANGE; if (off + count > ha->optrom_region_size) count = ha->optrom_region_size - off; memcpy(&ha->optrom_buffer[off], buf, count); return count;}static struct bin_attribute sysfs_optrom_attr = { .attr = { .name = "optrom", .mode = S_IRUSR | S_IWUSR, }, .size = 0, .read = qla2x00_sysfs_read_optrom, .write = qla2x00_sysfs_write_optrom,};static ssize_tqla2x00_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 = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); uint32_t start = 0; uint32_t size = ha->optrom_size; int val, valid; if (off) return 0; if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1) return -EINVAL; if (start > ha->optrom_size) return -EINVAL; switch (val) { case 0: if (ha->optrom_state != QLA_SREADING && ha->optrom_state != QLA_SWRITING) break; ha->optrom_state = QLA_SWAITING; DEBUG2(qla_printk(KERN_INFO, ha, "Freeing flash region allocation -- 0x%x bytes.\n", ha->optrom_region_size)); vfree(ha->optrom_buffer); ha->optrom_buffer = NULL; break; case 1: if (ha->optrom_state != QLA_SWAITING) break; if (start & 0xfff) { qla_printk(KERN_WARNING, ha, "Invalid start region 0x%x/0x%x.\n", start, size); return -EINVAL; } ha->optrom_region_start = start; ha->optrom_region_size = start + size > ha->optrom_size ? ha->optrom_size - start : size; ha->optrom_state = QLA_SREADING; ha->optrom_buffer = vmalloc(ha->optrom_region_size); if (ha->optrom_buffer == NULL) { qla_printk(KERN_WARNING, ha, "Unable to allocate memory for optrom retrieval " "(%x).\n", ha->optrom_region_size); ha->optrom_state = QLA_SWAITING; return count; } DEBUG2(qla_printk(KERN_INFO, ha, "Reading flash region -- 0x%x/0x%x.\n", ha->optrom_region_start, ha->optrom_region_size)); memset(ha->optrom_buffer, 0, ha->optrom_region_size); ha->isp_ops->read_optrom(ha, ha->optrom_buffer, ha->optrom_region_start, ha->optrom_region_size); break; case 2: if (ha->optrom_state != QLA_SWAITING) break; /* * We need to be more restrictive on which FLASH regions are * allowed to be updated via user-space. Regions accessible * via this method include: * * ISP21xx/ISP22xx/ISP23xx type boards: * * 0x000000 -> 0x020000 -- Boot code. * * ISP2322/ISP24xx type boards: * * 0x000000 -> 0x07ffff -- Boot code. * 0x080000 -> 0x0fffff -- Firmware. * * ISP25xx type boards: * * 0x000000 -> 0x07ffff -- Boot code. * 0x080000 -> 0x0fffff -- Firmware. * 0x120000 -> 0x12ffff -- VPD and HBA parameters. */ valid = 0; if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) valid = 1; else if (start == (FA_BOOT_CODE_ADDR*4) || start == (FA_RISC_CODE_ADDR*4)) valid = 1; else if (IS_QLA25XX(ha) && start == (FA_VPD_NVRAM_ADDR*4)) valid = 1; if (!valid) { qla_printk(KERN_WARNING, ha, "Invalid start region 0x%x/0x%x.\n", start, size); return -EINVAL; } ha->optrom_region_start = start; ha->optrom_region_size = start + size > ha->optrom_size ? ha->optrom_size - start : size; ha->optrom_state = QLA_SWRITING; ha->optrom_buffer = vmalloc(ha->optrom_region_size); if (ha->optrom_buffer == NULL) { qla_printk(KERN_WARNING, ha, "Unable to allocate memory for optrom update " "(%x).\n", ha->optrom_region_size); ha->optrom_state = QLA_SWAITING; return count; } DEBUG2(qla_printk(KERN_INFO, ha, "Staging flash region write -- 0x%x/0x%x.\n", ha->optrom_region_start, ha->optrom_region_size)); memset(ha->optrom_buffer, 0, ha->optrom_region_size); break; case 3: if (ha->optrom_state != QLA_SWRITING) break; DEBUG2(qla_printk(KERN_INFO, ha, "Writing flash region -- 0x%x/0x%x.\n", ha->optrom_region_start, ha->optrom_region_size)); ha->isp_ops->write_optrom(ha, ha->optrom_buffer, ha->optrom_region_start, ha->optrom_region_size); break; default: count = -EINVAL; } return count;}static struct bin_attribute sysfs_optrom_ctl_attr = { .attr = { .name = "optrom_ctl", .mode = S_IWUSR, }, .size = 0, .write = qla2x00_sysfs_write_optrom_ctl,};static ssize_tqla2x00_sysfs_read_vpd(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count){ struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); int size = ha->vpd_size; char *vpd_cache = ha->vpd; if (!capable(CAP_SYS_ADMIN) || off > size || count == 0) return 0; if (off + count > size) { size -= off; count = size; } /* Read NVRAM data from cache. */ memcpy(buf, &vpd_cache[off], count); return count;}static ssize_tqla2x00_sysfs_write_vpd(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count){ struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size) return 0; /* Write NVRAM. */ ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, ha->vpd_base, count); return count;}static struct bin_attribute sysfs_vpd_attr = { .attr = { .name = "vpd", .mode = S_IRUSR | S_IWUSR, }, .size = 0, .read = qla2x00_sysfs_read_vpd, .write = qla2x00_sysfs_write_vpd,};static ssize_t
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?