qla_attr.c 25 KB

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