ql4_attr.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. * QLogic iSCSI HBA Driver
  3. * Copyright (c) 2003-2011 QLogic Corporation
  4. *
  5. * See LICENSE.qla4xxx for copyright and licensing details.
  6. */
  7. #include "ql4_def.h"
  8. #include "ql4_glbl.h"
  9. #include "ql4_dbg.h"
  10. static ssize_t
  11. qla4_8xxx_sysfs_read_fw_dump(struct file *filep, struct kobject *kobj,
  12. struct bin_attribute *ba, char *buf, loff_t off,
  13. size_t count)
  14. {
  15. struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
  16. struct device, kobj)));
  17. if (is_qla40XX(ha))
  18. return -EINVAL;
  19. if (!test_bit(AF_82XX_DUMP_READING, &ha->flags))
  20. return 0;
  21. return memory_read_from_buffer(buf, count, &off, ha->fw_dump,
  22. ha->fw_dump_size);
  23. }
  24. static ssize_t
  25. qla4_8xxx_sysfs_write_fw_dump(struct file *filep, struct kobject *kobj,
  26. struct bin_attribute *ba, char *buf, loff_t off,
  27. size_t count)
  28. {
  29. struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
  30. struct device, kobj)));
  31. uint32_t dev_state;
  32. long reading;
  33. int ret = 0;
  34. if (is_qla40XX(ha))
  35. return -EINVAL;
  36. if (off != 0)
  37. return ret;
  38. buf[1] = 0;
  39. ret = kstrtol(buf, 10, &reading);
  40. if (ret) {
  41. ql4_printk(KERN_ERR, ha, "%s: Invalid input. Return err %d\n",
  42. __func__, ret);
  43. return ret;
  44. }
  45. switch (reading) {
  46. case 0:
  47. /* clear dump collection flags */
  48. if (test_and_clear_bit(AF_82XX_DUMP_READING, &ha->flags)) {
  49. clear_bit(AF_82XX_FW_DUMPED, &ha->flags);
  50. /* Reload minidump template */
  51. qla4xxx_alloc_fw_dump(ha);
  52. DEBUG2(ql4_printk(KERN_INFO, ha,
  53. "Firmware template reloaded\n"));
  54. }
  55. break;
  56. case 1:
  57. /* Set flag to read dump */
  58. if (test_bit(AF_82XX_FW_DUMPED, &ha->flags) &&
  59. !test_bit(AF_82XX_DUMP_READING, &ha->flags)) {
  60. set_bit(AF_82XX_DUMP_READING, &ha->flags);
  61. DEBUG2(ql4_printk(KERN_INFO, ha,
  62. "Raw firmware dump ready for read on (%ld).\n",
  63. ha->host_no));
  64. }
  65. break;
  66. case 2:
  67. /* Reset HBA */
  68. ha->isp_ops->idc_lock(ha);
  69. dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE);
  70. if (dev_state == QLA8XXX_DEV_READY) {
  71. ql4_printk(KERN_INFO, ha,
  72. "%s: Setting Need reset, reset_owner is 0x%x.\n",
  73. __func__, ha->func_num);
  74. qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,
  75. QLA8XXX_DEV_NEED_RESET);
  76. set_bit(AF_8XXX_RST_OWNER, &ha->flags);
  77. } else
  78. ql4_printk(KERN_INFO, ha,
  79. "%s: Reset not performed as device state is 0x%x\n",
  80. __func__, dev_state);
  81. ha->isp_ops->idc_unlock(ha);
  82. break;
  83. default:
  84. /* do nothing */
  85. break;
  86. }
  87. return count;
  88. }
  89. static struct bin_attribute sysfs_fw_dump_attr = {
  90. .attr = {
  91. .name = "fw_dump",
  92. .mode = S_IRUSR | S_IWUSR,
  93. },
  94. .size = 0,
  95. .read = qla4_8xxx_sysfs_read_fw_dump,
  96. .write = qla4_8xxx_sysfs_write_fw_dump,
  97. };
  98. static struct sysfs_entry {
  99. char *name;
  100. struct bin_attribute *attr;
  101. } bin_file_entries[] = {
  102. { "fw_dump", &sysfs_fw_dump_attr },
  103. { NULL },
  104. };
  105. void qla4_8xxx_alloc_sysfs_attr(struct scsi_qla_host *ha)
  106. {
  107. struct Scsi_Host *host = ha->host;
  108. struct sysfs_entry *iter;
  109. int ret;
  110. for (iter = bin_file_entries; iter->name; iter++) {
  111. ret = sysfs_create_bin_file(&host->shost_gendev.kobj,
  112. iter->attr);
  113. if (ret)
  114. ql4_printk(KERN_ERR, ha,
  115. "Unable to create sysfs %s binary attribute (%d).\n",
  116. iter->name, ret);
  117. }
  118. }
  119. void qla4_8xxx_free_sysfs_attr(struct scsi_qla_host *ha)
  120. {
  121. struct Scsi_Host *host = ha->host;
  122. struct sysfs_entry *iter;
  123. for (iter = bin_file_entries; iter->name; iter++)
  124. sysfs_remove_bin_file(&host->shost_gendev.kobj,
  125. iter->attr);
  126. }
  127. /* Scsi_Host attributes. */
  128. static ssize_t
  129. qla4xxx_fw_version_show(struct device *dev,
  130. struct device_attribute *attr, char *buf)
  131. {
  132. struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
  133. if (is_qla80XX(ha))
  134. return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n",
  135. ha->firmware_version[0],
  136. ha->firmware_version[1],
  137. ha->patch_number, ha->build_number);
  138. else
  139. return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d.%02d\n",
  140. ha->firmware_version[0],
  141. ha->firmware_version[1],
  142. ha->patch_number, ha->build_number);
  143. }
  144. static ssize_t
  145. qla4xxx_serial_num_show(struct device *dev, struct device_attribute *attr,
  146. char *buf)
  147. {
  148. struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
  149. return snprintf(buf, PAGE_SIZE, "%s\n", ha->serial_number);
  150. }
  151. static ssize_t
  152. qla4xxx_iscsi_version_show(struct device *dev, struct device_attribute *attr,
  153. char *buf)
  154. {
  155. struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
  156. return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->iscsi_major,
  157. ha->iscsi_minor);
  158. }
  159. static ssize_t
  160. qla4xxx_optrom_version_show(struct device *dev, struct device_attribute *attr,
  161. char *buf)
  162. {
  163. struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
  164. return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d.%02d\n",
  165. ha->bootload_major, ha->bootload_minor,
  166. ha->bootload_patch, ha->bootload_build);
  167. }
  168. static ssize_t
  169. qla4xxx_board_id_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, "0x%08X\n", ha->board_id);
  174. }
  175. static ssize_t
  176. qla4xxx_fw_state_show(struct device *dev, struct device_attribute *attr,
  177. char *buf)
  178. {
  179. struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
  180. qla4xxx_get_firmware_state(ha);
  181. return snprintf(buf, PAGE_SIZE, "0x%08X%8X\n", ha->firmware_state,
  182. ha->addl_fw_state);
  183. }
  184. static ssize_t
  185. qla4xxx_phy_port_cnt_show(struct device *dev, struct device_attribute *attr,
  186. char *buf)
  187. {
  188. struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
  189. if (is_qla40XX(ha))
  190. return -ENOSYS;
  191. return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->phy_port_cnt);
  192. }
  193. static ssize_t
  194. qla4xxx_phy_port_num_show(struct device *dev, struct device_attribute *attr,
  195. char *buf)
  196. {
  197. struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
  198. if (is_qla40XX(ha))
  199. return -ENOSYS;
  200. return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->phy_port_num);
  201. }
  202. static ssize_t
  203. qla4xxx_iscsi_func_cnt_show(struct device *dev, struct device_attribute *attr,
  204. char *buf)
  205. {
  206. struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
  207. if (is_qla40XX(ha))
  208. return -ENOSYS;
  209. return snprintf(buf, PAGE_SIZE, "0x%04X\n", ha->iscsi_pci_func_cnt);
  210. }
  211. static ssize_t
  212. qla4xxx_hba_model_show(struct device *dev, struct device_attribute *attr,
  213. char *buf)
  214. {
  215. struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
  216. return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_name);
  217. }
  218. static DEVICE_ATTR(fw_version, S_IRUGO, qla4xxx_fw_version_show, NULL);
  219. static DEVICE_ATTR(serial_num, S_IRUGO, qla4xxx_serial_num_show, NULL);
  220. static DEVICE_ATTR(iscsi_version, S_IRUGO, qla4xxx_iscsi_version_show, NULL);
  221. static DEVICE_ATTR(optrom_version, S_IRUGO, qla4xxx_optrom_version_show, NULL);
  222. static DEVICE_ATTR(board_id, S_IRUGO, qla4xxx_board_id_show, NULL);
  223. static DEVICE_ATTR(fw_state, S_IRUGO, qla4xxx_fw_state_show, NULL);
  224. static DEVICE_ATTR(phy_port_cnt, S_IRUGO, qla4xxx_phy_port_cnt_show, NULL);
  225. static DEVICE_ATTR(phy_port_num, S_IRUGO, qla4xxx_phy_port_num_show, NULL);
  226. static DEVICE_ATTR(iscsi_func_cnt, S_IRUGO, qla4xxx_iscsi_func_cnt_show, NULL);
  227. static DEVICE_ATTR(hba_model, S_IRUGO, qla4xxx_hba_model_show, NULL);
  228. struct device_attribute *qla4xxx_host_attrs[] = {
  229. &dev_attr_fw_version,
  230. &dev_attr_serial_num,
  231. &dev_attr_iscsi_version,
  232. &dev_attr_optrom_version,
  233. &dev_attr_board_id,
  234. &dev_attr_fw_state,
  235. &dev_attr_phy_port_cnt,
  236. &dev_attr_phy_port_num,
  237. &dev_attr_iscsi_func_cnt,
  238. &dev_attr_hba_model,
  239. NULL,
  240. };