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