17ad633c0SHarish Zunjarrao /* 27ad633c0SHarish Zunjarrao * QLogic iSCSI HBA Driver 37ad633c0SHarish Zunjarrao * Copyright (c) 2003-2011 QLogic Corporation 47ad633c0SHarish Zunjarrao * 57ad633c0SHarish Zunjarrao * See LICENSE.qla4xxx for copyright and licensing details. 67ad633c0SHarish Zunjarrao */ 77ad633c0SHarish Zunjarrao 87ad633c0SHarish Zunjarrao #include "ql4_def.h" 97ad633c0SHarish Zunjarrao #include "ql4_glbl.h" 107ad633c0SHarish Zunjarrao #include "ql4_dbg.h" 117ad633c0SHarish Zunjarrao 12068237c8STej Parkash static ssize_t 13068237c8STej Parkash qla4_8xxx_sysfs_read_fw_dump(struct file *filep, struct kobject *kobj, 14068237c8STej Parkash struct bin_attribute *ba, char *buf, loff_t off, 15068237c8STej Parkash size_t count) 16068237c8STej Parkash { 17068237c8STej Parkash struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 18068237c8STej Parkash struct device, kobj))); 19068237c8STej Parkash 20*ee996a69SVikas Chaudhary if (is_qla40XX(ha)) 21068237c8STej Parkash return -EINVAL; 22068237c8STej Parkash 23068237c8STej Parkash if (!test_bit(AF_82XX_DUMP_READING, &ha->flags)) 24068237c8STej Parkash return 0; 25068237c8STej Parkash 26068237c8STej Parkash return memory_read_from_buffer(buf, count, &off, ha->fw_dump, 27068237c8STej Parkash ha->fw_dump_size); 28068237c8STej Parkash } 29068237c8STej Parkash 30068237c8STej Parkash static ssize_t 31068237c8STej Parkash qla4_8xxx_sysfs_write_fw_dump(struct file *filep, struct kobject *kobj, 32068237c8STej Parkash struct bin_attribute *ba, char *buf, loff_t off, 33068237c8STej Parkash size_t count) 34068237c8STej Parkash { 35068237c8STej Parkash struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 36068237c8STej Parkash struct device, kobj))); 37068237c8STej Parkash uint32_t dev_state; 38068237c8STej Parkash long reading; 39068237c8STej Parkash int ret = 0; 40068237c8STej Parkash 41*ee996a69SVikas Chaudhary if (is_qla40XX(ha)) 42068237c8STej Parkash return -EINVAL; 43068237c8STej Parkash 44068237c8STej Parkash if (off != 0) 45068237c8STej Parkash return ret; 46068237c8STej Parkash 47068237c8STej Parkash buf[1] = 0; 48068237c8STej Parkash ret = kstrtol(buf, 10, &reading); 49068237c8STej Parkash if (ret) { 50068237c8STej Parkash ql4_printk(KERN_ERR, ha, "%s: Invalid input. Return err %d\n", 51068237c8STej Parkash __func__, ret); 52068237c8STej Parkash return ret; 53068237c8STej Parkash } 54068237c8STej Parkash 55068237c8STej Parkash switch (reading) { 56068237c8STej Parkash case 0: 57068237c8STej Parkash /* clear dump collection flags */ 58068237c8STej Parkash if (test_and_clear_bit(AF_82XX_DUMP_READING, &ha->flags)) { 59068237c8STej Parkash clear_bit(AF_82XX_FW_DUMPED, &ha->flags); 60068237c8STej Parkash /* Reload minidump template */ 61068237c8STej Parkash qla4xxx_alloc_fw_dump(ha); 62068237c8STej Parkash DEBUG2(ql4_printk(KERN_INFO, ha, 63068237c8STej Parkash "Firmware template reloaded\n")); 64068237c8STej Parkash } 65068237c8STej Parkash break; 66068237c8STej Parkash case 1: 67068237c8STej Parkash /* Set flag to read dump */ 68068237c8STej Parkash if (test_bit(AF_82XX_FW_DUMPED, &ha->flags) && 69068237c8STej Parkash !test_bit(AF_82XX_DUMP_READING, &ha->flags)) { 70068237c8STej Parkash set_bit(AF_82XX_DUMP_READING, &ha->flags); 71068237c8STej Parkash DEBUG2(ql4_printk(KERN_INFO, ha, 72068237c8STej Parkash "Raw firmware dump ready for read on (%ld).\n", 73068237c8STej Parkash ha->host_no)); 74068237c8STej Parkash } 75068237c8STej Parkash break; 76068237c8STej Parkash case 2: 77068237c8STej Parkash /* Reset HBA */ 7833693c7aSVikas Chaudhary ha->isp_ops->idc_lock(ha); 7933693c7aSVikas Chaudhary dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE); 80de8c72daSVikas Chaudhary if (dev_state == QLA8XXX_DEV_READY) { 81068237c8STej Parkash ql4_printk(KERN_INFO, ha, 82068237c8STej Parkash "%s: Setting Need reset, reset_owner is 0x%x.\n", 83068237c8STej Parkash __func__, ha->func_num); 8433693c7aSVikas Chaudhary qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, 85de8c72daSVikas Chaudhary QLA8XXX_DEV_NEED_RESET); 86de8c72daSVikas Chaudhary set_bit(AF_8XXX_RST_OWNER, &ha->flags); 87068237c8STej Parkash } else 88068237c8STej Parkash ql4_printk(KERN_INFO, ha, 89068237c8STej Parkash "%s: Reset not performed as device state is 0x%x\n", 90068237c8STej Parkash __func__, dev_state); 91068237c8STej Parkash 9233693c7aSVikas Chaudhary ha->isp_ops->idc_unlock(ha); 93068237c8STej Parkash break; 94068237c8STej Parkash default: 95068237c8STej Parkash /* do nothing */ 96068237c8STej Parkash break; 97068237c8STej Parkash } 98068237c8STej Parkash 99068237c8STej Parkash return count; 100068237c8STej Parkash } 101068237c8STej Parkash 102068237c8STej Parkash static struct bin_attribute sysfs_fw_dump_attr = { 103068237c8STej Parkash .attr = { 104068237c8STej Parkash .name = "fw_dump", 105068237c8STej Parkash .mode = S_IRUSR | S_IWUSR, 106068237c8STej Parkash }, 107068237c8STej Parkash .size = 0, 108068237c8STej Parkash .read = qla4_8xxx_sysfs_read_fw_dump, 109068237c8STej Parkash .write = qla4_8xxx_sysfs_write_fw_dump, 110068237c8STej Parkash }; 111068237c8STej Parkash 112068237c8STej Parkash static struct sysfs_entry { 113068237c8STej Parkash char *name; 114068237c8STej Parkash struct bin_attribute *attr; 115068237c8STej Parkash } bin_file_entries[] = { 116068237c8STej Parkash { "fw_dump", &sysfs_fw_dump_attr }, 117068237c8STej Parkash { NULL }, 118068237c8STej Parkash }; 119068237c8STej Parkash 120068237c8STej Parkash void qla4_8xxx_alloc_sysfs_attr(struct scsi_qla_host *ha) 121068237c8STej Parkash { 122068237c8STej Parkash struct Scsi_Host *host = ha->host; 123068237c8STej Parkash struct sysfs_entry *iter; 124068237c8STej Parkash int ret; 125068237c8STej Parkash 126068237c8STej Parkash for (iter = bin_file_entries; iter->name; iter++) { 127068237c8STej Parkash ret = sysfs_create_bin_file(&host->shost_gendev.kobj, 128068237c8STej Parkash iter->attr); 129068237c8STej Parkash if (ret) 130068237c8STej Parkash ql4_printk(KERN_ERR, ha, 131068237c8STej Parkash "Unable to create sysfs %s binary attribute (%d).\n", 132068237c8STej Parkash iter->name, ret); 133068237c8STej Parkash } 134068237c8STej Parkash } 135068237c8STej Parkash 136068237c8STej Parkash void qla4_8xxx_free_sysfs_attr(struct scsi_qla_host *ha) 137068237c8STej Parkash { 138068237c8STej Parkash struct Scsi_Host *host = ha->host; 139068237c8STej Parkash struct sysfs_entry *iter; 140068237c8STej Parkash 141068237c8STej Parkash for (iter = bin_file_entries; iter->name; iter++) 142068237c8STej Parkash sysfs_remove_bin_file(&host->shost_gendev.kobj, 143068237c8STej Parkash iter->attr); 144068237c8STej Parkash } 145068237c8STej Parkash 1467ad633c0SHarish Zunjarrao /* Scsi_Host attributes. */ 1477ad633c0SHarish Zunjarrao static ssize_t 1487ad633c0SHarish Zunjarrao qla4xxx_fw_version_show(struct device *dev, 1497ad633c0SHarish Zunjarrao struct device_attribute *attr, char *buf) 1507ad633c0SHarish Zunjarrao { 1517ad633c0SHarish Zunjarrao struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 1527ad633c0SHarish Zunjarrao 1537ad633c0SHarish Zunjarrao if (is_qla8022(ha)) 1547ad633c0SHarish Zunjarrao return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n", 1557ad633c0SHarish Zunjarrao ha->firmware_version[0], 1567ad633c0SHarish Zunjarrao ha->firmware_version[1], 1577ad633c0SHarish Zunjarrao ha->patch_number, ha->build_number); 1587ad633c0SHarish Zunjarrao else 1597ad633c0SHarish Zunjarrao return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d.%02d\n", 1607ad633c0SHarish Zunjarrao ha->firmware_version[0], 1617ad633c0SHarish Zunjarrao ha->firmware_version[1], 1627ad633c0SHarish Zunjarrao ha->patch_number, ha->build_number); 1637ad633c0SHarish Zunjarrao } 1647ad633c0SHarish Zunjarrao 1657ad633c0SHarish Zunjarrao static ssize_t 1667ad633c0SHarish Zunjarrao qla4xxx_serial_num_show(struct device *dev, struct device_attribute *attr, 1677ad633c0SHarish Zunjarrao char *buf) 1687ad633c0SHarish Zunjarrao { 1697ad633c0SHarish Zunjarrao struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 1707ad633c0SHarish Zunjarrao return snprintf(buf, PAGE_SIZE, "%s\n", ha->serial_number); 1717ad633c0SHarish Zunjarrao } 1727ad633c0SHarish Zunjarrao 1737ad633c0SHarish Zunjarrao static ssize_t 1747ad633c0SHarish Zunjarrao qla4xxx_iscsi_version_show(struct device *dev, struct device_attribute *attr, 1757ad633c0SHarish Zunjarrao char *buf) 1767ad633c0SHarish Zunjarrao { 1777ad633c0SHarish Zunjarrao struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 1787ad633c0SHarish Zunjarrao return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->iscsi_major, 1797ad633c0SHarish Zunjarrao ha->iscsi_minor); 1807ad633c0SHarish Zunjarrao } 1817ad633c0SHarish Zunjarrao 1827ad633c0SHarish Zunjarrao static ssize_t 1837ad633c0SHarish Zunjarrao qla4xxx_optrom_version_show(struct device *dev, struct device_attribute *attr, 1847ad633c0SHarish Zunjarrao char *buf) 1857ad633c0SHarish Zunjarrao { 1867ad633c0SHarish Zunjarrao struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 1877ad633c0SHarish Zunjarrao return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d.%02d\n", 1887ad633c0SHarish Zunjarrao ha->bootload_major, ha->bootload_minor, 1897ad633c0SHarish Zunjarrao ha->bootload_patch, ha->bootload_build); 1907ad633c0SHarish Zunjarrao } 1917ad633c0SHarish Zunjarrao 19291ec7cecSVikas Chaudhary static ssize_t 19391ec7cecSVikas Chaudhary qla4xxx_board_id_show(struct device *dev, struct device_attribute *attr, 19491ec7cecSVikas Chaudhary char *buf) 19591ec7cecSVikas Chaudhary { 19691ec7cecSVikas Chaudhary struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 19791ec7cecSVikas Chaudhary return snprintf(buf, PAGE_SIZE, "0x%08X\n", ha->board_id); 19891ec7cecSVikas Chaudhary } 19991ec7cecSVikas Chaudhary 20091ec7cecSVikas Chaudhary static ssize_t 20191ec7cecSVikas Chaudhary qla4xxx_fw_state_show(struct device *dev, struct device_attribute *attr, 20291ec7cecSVikas Chaudhary char *buf) 20391ec7cecSVikas Chaudhary { 20491ec7cecSVikas Chaudhary struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 20591ec7cecSVikas Chaudhary 20691ec7cecSVikas Chaudhary qla4xxx_get_firmware_state(ha); 20791ec7cecSVikas Chaudhary return snprintf(buf, PAGE_SIZE, "0x%08X%8X\n", ha->firmware_state, 20891ec7cecSVikas Chaudhary ha->addl_fw_state); 20991ec7cecSVikas Chaudhary } 21091ec7cecSVikas Chaudhary 21191ec7cecSVikas Chaudhary static ssize_t 21291ec7cecSVikas Chaudhary qla4xxx_phy_port_cnt_show(struct device *dev, struct device_attribute *attr, 21391ec7cecSVikas Chaudhary char *buf) 21491ec7cecSVikas Chaudhary { 21591ec7cecSVikas Chaudhary struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 21691ec7cecSVikas Chaudhary 217*ee996a69SVikas Chaudhary if (is_qla40XX(ha)) 21891ec7cecSVikas Chaudhary return -ENOSYS; 21991ec7cecSVikas Chaudhary 22091ec7cecSVikas Chaudhary return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->phy_port_cnt); 22191ec7cecSVikas Chaudhary } 22291ec7cecSVikas Chaudhary 22391ec7cecSVikas Chaudhary static ssize_t 22491ec7cecSVikas Chaudhary qla4xxx_phy_port_num_show(struct device *dev, struct device_attribute *attr, 22591ec7cecSVikas Chaudhary char *buf) 22691ec7cecSVikas Chaudhary { 22791ec7cecSVikas Chaudhary struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 22891ec7cecSVikas Chaudhary 229*ee996a69SVikas Chaudhary if (is_qla40XX(ha)) 23091ec7cecSVikas Chaudhary return -ENOSYS; 23191ec7cecSVikas Chaudhary 23291ec7cecSVikas Chaudhary return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->phy_port_num); 23391ec7cecSVikas Chaudhary } 23491ec7cecSVikas Chaudhary 23591ec7cecSVikas Chaudhary static ssize_t 23691ec7cecSVikas Chaudhary qla4xxx_iscsi_func_cnt_show(struct device *dev, struct device_attribute *attr, 23791ec7cecSVikas Chaudhary char *buf) 23891ec7cecSVikas Chaudhary { 23991ec7cecSVikas Chaudhary struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 24091ec7cecSVikas Chaudhary 241*ee996a69SVikas Chaudhary if (is_qla40XX(ha)) 24291ec7cecSVikas Chaudhary return -ENOSYS; 24391ec7cecSVikas Chaudhary 24491ec7cecSVikas Chaudhary return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->iscsi_pci_func_cnt); 24591ec7cecSVikas Chaudhary } 24691ec7cecSVikas Chaudhary 24791ec7cecSVikas Chaudhary static ssize_t 24891ec7cecSVikas Chaudhary qla4xxx_hba_model_show(struct device *dev, struct device_attribute *attr, 24991ec7cecSVikas Chaudhary char *buf) 25091ec7cecSVikas Chaudhary { 25191ec7cecSVikas Chaudhary struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); 25291ec7cecSVikas Chaudhary 25391ec7cecSVikas Chaudhary return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_name); 25491ec7cecSVikas Chaudhary } 25591ec7cecSVikas Chaudhary 2567ad633c0SHarish Zunjarrao static DEVICE_ATTR(fw_version, S_IRUGO, qla4xxx_fw_version_show, NULL); 2577ad633c0SHarish Zunjarrao static DEVICE_ATTR(serial_num, S_IRUGO, qla4xxx_serial_num_show, NULL); 2587ad633c0SHarish Zunjarrao static DEVICE_ATTR(iscsi_version, S_IRUGO, qla4xxx_iscsi_version_show, NULL); 2597ad633c0SHarish Zunjarrao static DEVICE_ATTR(optrom_version, S_IRUGO, qla4xxx_optrom_version_show, NULL); 26091ec7cecSVikas Chaudhary static DEVICE_ATTR(board_id, S_IRUGO, qla4xxx_board_id_show, NULL); 26191ec7cecSVikas Chaudhary static DEVICE_ATTR(fw_state, S_IRUGO, qla4xxx_fw_state_show, NULL); 26291ec7cecSVikas Chaudhary static DEVICE_ATTR(phy_port_cnt, S_IRUGO, qla4xxx_phy_port_cnt_show, NULL); 26391ec7cecSVikas Chaudhary static DEVICE_ATTR(phy_port_num, S_IRUGO, qla4xxx_phy_port_num_show, NULL); 26491ec7cecSVikas Chaudhary static DEVICE_ATTR(iscsi_func_cnt, S_IRUGO, qla4xxx_iscsi_func_cnt_show, NULL); 26591ec7cecSVikas Chaudhary static DEVICE_ATTR(hba_model, S_IRUGO, qla4xxx_hba_model_show, NULL); 2667ad633c0SHarish Zunjarrao 2677ad633c0SHarish Zunjarrao struct device_attribute *qla4xxx_host_attrs[] = { 2687ad633c0SHarish Zunjarrao &dev_attr_fw_version, 2697ad633c0SHarish Zunjarrao &dev_attr_serial_num, 2707ad633c0SHarish Zunjarrao &dev_attr_iscsi_version, 2717ad633c0SHarish Zunjarrao &dev_attr_optrom_version, 27291ec7cecSVikas Chaudhary &dev_attr_board_id, 27391ec7cecSVikas Chaudhary &dev_attr_fw_state, 27491ec7cecSVikas Chaudhary &dev_attr_phy_port_cnt, 27591ec7cecSVikas Chaudhary &dev_attr_phy_port_num, 27691ec7cecSVikas Chaudhary &dev_attr_iscsi_func_cnt, 27791ec7cecSVikas Chaudhary &dev_attr_hba_model, 2787ad633c0SHarish Zunjarrao NULL, 2797ad633c0SHarish Zunjarrao }; 280