ql4_attr.c (10093B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * QLogic iSCSI HBA Driver 4 * Copyright (c) 2003-2013 QLogic Corporation 5 */ 6 7#include "ql4_def.h" 8#include "ql4_glbl.h" 9#include "ql4_dbg.h" 10 11static ssize_t 12qla4_8xxx_sysfs_read_fw_dump(struct file *filep, struct kobject *kobj, 13 struct bin_attribute *ba, char *buf, loff_t off, 14 size_t count) 15{ 16 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 17 struct device, kobj))); 18 19 if (is_qla40XX(ha)) 20 return -EINVAL; 21 22 if (!test_bit(AF_82XX_DUMP_READING, &ha->flags)) 23 return 0; 24 25 return memory_read_from_buffer(buf, count, &off, ha->fw_dump, 26 ha->fw_dump_size); 27} 28 29static ssize_t 30qla4_8xxx_sysfs_write_fw_dump(struct file *filep, struct kobject *kobj, 31 struct bin_attribute *ba, char *buf, loff_t off, 32 size_t count) 33{ 34 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 35 struct device, kobj))); 36 uint32_t dev_state; 37 long reading; 38 int ret = 0; 39 40 if (is_qla40XX(ha)) 41 return -EINVAL; 42 43 if (off != 0) 44 return ret; 45 46 buf[1] = 0; 47 ret = kstrtol(buf, 10, &reading); 48 if (ret) { 49 ql4_printk(KERN_ERR, ha, "%s: Invalid input. Return err %d\n", 50 __func__, ret); 51 return ret; 52 } 53 54 switch (reading) { 55 case 0: 56 /* clear dump collection flags */ 57 if (test_and_clear_bit(AF_82XX_DUMP_READING, &ha->flags)) { 58 clear_bit(AF_82XX_FW_DUMPED, &ha->flags); 59 /* Reload minidump template */ 60 qla4xxx_alloc_fw_dump(ha); 61 DEBUG2(ql4_printk(KERN_INFO, ha, 62 "Firmware template reloaded\n")); 63 } 64 break; 65 case 1: 66 /* Set flag to read dump */ 67 if (test_bit(AF_82XX_FW_DUMPED, &ha->flags) && 68 !test_bit(AF_82XX_DUMP_READING, &ha->flags)) { 69 set_bit(AF_82XX_DUMP_READING, &ha->flags); 70 DEBUG2(ql4_printk(KERN_INFO, ha, 71 "Raw firmware dump ready for read on (%ld).\n", 72 ha->host_no)); 73 } 74 break; 75 case 2: 76 /* Reset HBA and collect FW dump */ 77 ha->isp_ops->idc_lock(ha); 78 dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE); 79 if (dev_state == QLA8XXX_DEV_READY) { 80 ql4_printk(KERN_INFO, ha, "%s: Setting Need reset\n", 81 __func__); 82 qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, 83 QLA8XXX_DEV_NEED_RESET); 84 if (is_qla8022(ha) || 85 ((is_qla8032(ha) || is_qla8042(ha)) && 86 qla4_83xx_can_perform_reset(ha))) { 87 set_bit(AF_8XXX_RST_OWNER, &ha->flags); 88 set_bit(AF_FW_RECOVERY, &ha->flags); 89 ql4_printk(KERN_INFO, ha, "%s: Reset owner is 0x%x\n", 90 __func__, ha->func_num); 91 } 92 } else 93 ql4_printk(KERN_INFO, ha, 94 "%s: Reset not performed as device state is 0x%x\n", 95 __func__, dev_state); 96 97 ha->isp_ops->idc_unlock(ha); 98 break; 99 default: 100 /* do nothing */ 101 break; 102 } 103 104 return count; 105} 106 107static struct bin_attribute sysfs_fw_dump_attr = { 108 .attr = { 109 .name = "fw_dump", 110 .mode = S_IRUSR | S_IWUSR, 111 }, 112 .size = 0, 113 .read = qla4_8xxx_sysfs_read_fw_dump, 114 .write = qla4_8xxx_sysfs_write_fw_dump, 115}; 116 117static struct sysfs_entry { 118 char *name; 119 struct bin_attribute *attr; 120} bin_file_entries[] = { 121 { "fw_dump", &sysfs_fw_dump_attr }, 122 { NULL }, 123}; 124 125void qla4_8xxx_alloc_sysfs_attr(struct scsi_qla_host *ha) 126{ 127 struct Scsi_Host *host = ha->host; 128 struct sysfs_entry *iter; 129 int ret; 130 131 for (iter = bin_file_entries; iter->name; iter++) { 132 ret = sysfs_create_bin_file(&host->shost_gendev.kobj, 133 iter->attr); 134 if (ret) 135 ql4_printk(KERN_ERR, ha, 136 "Unable to create sysfs %s binary attribute (%d).\n", 137 iter->name, ret); 138 } 139} 140 141void qla4_8xxx_free_sysfs_attr(struct scsi_qla_host *ha) 142{ 143 struct Scsi_Host *host = ha->host; 144 struct sysfs_entry *iter; 145 146 for (iter = bin_file_entries; iter->name; iter++) 147 sysfs_remove_bin_file(&host->shost_gendev.kobj, 148 iter->attr); 149} 150 151/* Scsi_Host attributes. */ 152static ssize_t 153qla4xxx_fw_version_show(struct device *dev, 154 struct device_attribute *attr, char *buf) 155{ 156 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 157 158 if (is_qla80XX(ha)) 159 return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n", 160 ha->fw_info.fw_major, ha->fw_info.fw_minor, 161 ha->fw_info.fw_patch, ha->fw_info.fw_build); 162 else 163 return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d.%02d\n", 164 ha->fw_info.fw_major, ha->fw_info.fw_minor, 165 ha->fw_info.fw_patch, ha->fw_info.fw_build); 166} 167 168static ssize_t 169qla4xxx_serial_num_show(struct device *dev, struct device_attribute *attr, 170 char *buf) 171{ 172 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 173 return snprintf(buf, PAGE_SIZE, "%s\n", ha->serial_number); 174} 175 176static ssize_t 177qla4xxx_iscsi_version_show(struct device *dev, struct device_attribute *attr, 178 char *buf) 179{ 180 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 181 return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fw_info.iscsi_major, 182 ha->fw_info.iscsi_minor); 183} 184 185static ssize_t 186qla4xxx_optrom_version_show(struct device *dev, struct device_attribute *attr, 187 char *buf) 188{ 189 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 190 return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d.%02d\n", 191 ha->fw_info.bootload_major, ha->fw_info.bootload_minor, 192 ha->fw_info.bootload_patch, ha->fw_info.bootload_build); 193} 194 195static ssize_t 196qla4xxx_board_id_show(struct device *dev, struct device_attribute *attr, 197 char *buf) 198{ 199 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 200 return snprintf(buf, PAGE_SIZE, "0x%08X\n", ha->board_id); 201} 202 203static ssize_t 204qla4xxx_fw_state_show(struct device *dev, struct device_attribute *attr, 205 char *buf) 206{ 207 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 208 209 qla4xxx_get_firmware_state(ha); 210 return snprintf(buf, PAGE_SIZE, "0x%08X%8X\n", ha->firmware_state, 211 ha->addl_fw_state); 212} 213 214static ssize_t 215qla4xxx_phy_port_cnt_show(struct device *dev, struct device_attribute *attr, 216 char *buf) 217{ 218 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 219 220 if (is_qla40XX(ha)) 221 return -ENOSYS; 222 223 return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->phy_port_cnt); 224} 225 226static ssize_t 227qla4xxx_phy_port_num_show(struct device *dev, struct device_attribute *attr, 228 char *buf) 229{ 230 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 231 232 if (is_qla40XX(ha)) 233 return -ENOSYS; 234 235 return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->phy_port_num); 236} 237 238static ssize_t 239qla4xxx_iscsi_func_cnt_show(struct device *dev, struct device_attribute *attr, 240 char *buf) 241{ 242 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 243 244 if (is_qla40XX(ha)) 245 return -ENOSYS; 246 247 return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->iscsi_pci_func_cnt); 248} 249 250static ssize_t 251qla4xxx_hba_model_show(struct device *dev, struct device_attribute *attr, 252 char *buf) 253{ 254 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 255 256 return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_name); 257} 258 259static ssize_t 260qla4xxx_fw_timestamp_show(struct device *dev, struct device_attribute *attr, 261 char *buf) 262{ 263 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 264 return snprintf(buf, PAGE_SIZE, "%s %s\n", ha->fw_info.fw_build_date, 265 ha->fw_info.fw_build_time); 266} 267 268static ssize_t 269qla4xxx_fw_build_user_show(struct device *dev, struct device_attribute *attr, 270 char *buf) 271{ 272 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 273 return snprintf(buf, PAGE_SIZE, "%s\n", ha->fw_info.fw_build_user); 274} 275 276static ssize_t 277qla4xxx_fw_ext_timestamp_show(struct device *dev, struct device_attribute *attr, 278 char *buf) 279{ 280 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 281 return snprintf(buf, PAGE_SIZE, "%s\n", ha->fw_info.extended_timestamp); 282} 283 284static ssize_t 285qla4xxx_fw_load_src_show(struct device *dev, struct device_attribute *attr, 286 char *buf) 287{ 288 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 289 char *load_src = NULL; 290 291 switch (ha->fw_info.fw_load_source) { 292 case 1: 293 load_src = "Flash Primary"; 294 break; 295 case 2: 296 load_src = "Flash Secondary"; 297 break; 298 case 3: 299 load_src = "Host Download"; 300 break; 301 } 302 303 return snprintf(buf, PAGE_SIZE, "%s\n", load_src); 304} 305 306static ssize_t 307qla4xxx_fw_uptime_show(struct device *dev, struct device_attribute *attr, 308 char *buf) 309{ 310 struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 311 qla4xxx_about_firmware(ha); 312 return snprintf(buf, PAGE_SIZE, "%u.%u secs\n", ha->fw_uptime_secs, 313 ha->fw_uptime_msecs); 314} 315 316static DEVICE_ATTR(fw_version, S_IRUGO, qla4xxx_fw_version_show, NULL); 317static DEVICE_ATTR(serial_num, S_IRUGO, qla4xxx_serial_num_show, NULL); 318static DEVICE_ATTR(iscsi_version, S_IRUGO, qla4xxx_iscsi_version_show, NULL); 319static DEVICE_ATTR(optrom_version, S_IRUGO, qla4xxx_optrom_version_show, NULL); 320static DEVICE_ATTR(board_id, S_IRUGO, qla4xxx_board_id_show, NULL); 321static DEVICE_ATTR(fw_state, S_IRUGO, qla4xxx_fw_state_show, NULL); 322static DEVICE_ATTR(phy_port_cnt, S_IRUGO, qla4xxx_phy_port_cnt_show, NULL); 323static DEVICE_ATTR(phy_port_num, S_IRUGO, qla4xxx_phy_port_num_show, NULL); 324static DEVICE_ATTR(iscsi_func_cnt, S_IRUGO, qla4xxx_iscsi_func_cnt_show, NULL); 325static DEVICE_ATTR(hba_model, S_IRUGO, qla4xxx_hba_model_show, NULL); 326static DEVICE_ATTR(fw_timestamp, S_IRUGO, qla4xxx_fw_timestamp_show, NULL); 327static DEVICE_ATTR(fw_build_user, S_IRUGO, qla4xxx_fw_build_user_show, NULL); 328static DEVICE_ATTR(fw_ext_timestamp, S_IRUGO, qla4xxx_fw_ext_timestamp_show, 329 NULL); 330static DEVICE_ATTR(fw_load_src, S_IRUGO, qla4xxx_fw_load_src_show, NULL); 331static DEVICE_ATTR(fw_uptime, S_IRUGO, qla4xxx_fw_uptime_show, NULL); 332 333static struct attribute *qla4xxx_host_attrs[] = { 334 &dev_attr_fw_version.attr, 335 &dev_attr_serial_num.attr, 336 &dev_attr_iscsi_version.attr, 337 &dev_attr_optrom_version.attr, 338 &dev_attr_board_id.attr, 339 &dev_attr_fw_state.attr, 340 &dev_attr_phy_port_cnt.attr, 341 &dev_attr_phy_port_num.attr, 342 &dev_attr_iscsi_func_cnt.attr, 343 &dev_attr_hba_model.attr, 344 &dev_attr_fw_timestamp.attr, 345 &dev_attr_fw_build_user.attr, 346 &dev_attr_fw_ext_timestamp.attr, 347 &dev_attr_fw_load_src.attr, 348 &dev_attr_fw_uptime.attr, 349 NULL, 350}; 351 352static const struct attribute_group qla4xxx_host_attr_group = { 353 .attrs = qla4xxx_host_attrs 354}; 355 356const struct attribute_group *qla4xxx_host_groups[] = { 357 &qla4xxx_host_attr_group, 358 NULL 359};