blob: 612e3d0c7bd109be53a267cabc4274478c6ad34e [file] [log] [blame]
8482e112005-04-17 15:04:54 -05001/*
Andrew Vasquezfa90c542005-10-27 11:10:08 -07002 * QLogic Fibre Channel HBA Driver
Andrew Vasquez01e58d82008-04-03 13:13:13 -07003 * Copyright (c) 2003-2008 QLogic Corporation
8482e112005-04-17 15:04:54 -05004 *
Andrew Vasquezfa90c542005-10-27 11:10:08 -07005 * See LICENSE.qla2xxx for copyright and licensing details.
8482e112005-04-17 15:04:54 -05006 */
7#include "qla_def.h"
8
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07009#include <linux/kthread.h>
7aaef272005-04-17 16:32:42 -050010#include <linux/vmalloc.h>
8482e112005-04-17 15:04:54 -050011
Adrian Bunka824ebb2008-01-17 09:02:15 -080012static int qla24xx_vport_disable(struct fc_vport *, bool);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -070013
8482e112005-04-17 15:04:54 -050014/* SYSFS attributes --------------------------------------------------------- */
15
16static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +080017qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
18 struct bin_attribute *bin_attr,
19 char *buf, loff_t off, size_t count)
8482e112005-04-17 15:04:54 -050020{
Andrew Vasquezf363b942007-09-20 14:07:45 -070021 struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
8482e112005-04-17 15:04:54 -050022 struct device, kobj)));
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070023 char *rbuf = (char *)ha->fw_dump;
8482e112005-04-17 15:04:54 -050024
25 if (ha->fw_dump_reading == 0)
26 return 0;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070027 if (off > ha->fw_dump_len)
28 return 0;
29 if (off + count > ha->fw_dump_len)
30 count = ha->fw_dump_len - off;
8482e112005-04-17 15:04:54 -050031
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070032 memcpy(buf, &rbuf[off], count);
8482e112005-04-17 15:04:54 -050033
34 return (count);
35}
36
37static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +080038qla2x00_sysfs_write_fw_dump(struct kobject *kobj,
39 struct bin_attribute *bin_attr,
40 char *buf, loff_t off, size_t count)
8482e112005-04-17 15:04:54 -050041{
Andrew Vasquezf363b942007-09-20 14:07:45 -070042 struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
8482e112005-04-17 15:04:54 -050043 struct device, kobj)));
44 int reading;
8482e112005-04-17 15:04:54 -050045
46 if (off != 0)
47 return (0);
48
49 reading = simple_strtol(buf, NULL, 10);
50 switch (reading) {
51 case 0:
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070052 if (!ha->fw_dump_reading)
53 break;
8482e112005-04-17 15:04:54 -050054
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070055 qla_printk(KERN_INFO, ha,
56 "Firmware dump cleared on (%ld).\n", ha->host_no);
57
58 ha->fw_dump_reading = 0;
59 ha->fw_dumped = 0;
8482e112005-04-17 15:04:54 -050060 break;
61 case 1:
Andrew Vasquezd4e3e042006-05-17 15:09:50 -070062 if (ha->fw_dumped && !ha->fw_dump_reading) {
8482e112005-04-17 15:04:54 -050063 ha->fw_dump_reading = 1;
64
8482e112005-04-17 15:04:54 -050065 qla_printk(KERN_INFO, ha,
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070066 "Raw firmware dump ready for read on (%ld).\n",
8482e112005-04-17 15:04:54 -050067 ha->host_no);
8482e112005-04-17 15:04:54 -050068 }
69 break;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070070 case 2:
71 qla2x00_alloc_fw_dump(ha);
72 break;
Andrew Vasquez68af0812008-05-12 22:21:13 -070073 case 3:
74 qla2x00_system_error(ha);
75 break;
8482e112005-04-17 15:04:54 -050076 }
77 return (count);
78}
79
80static struct bin_attribute sysfs_fw_dump_attr = {
81 .attr = {
82 .name = "fw_dump",
83 .mode = S_IRUSR | S_IWUSR,
8482e112005-04-17 15:04:54 -050084 },
85 .size = 0,
86 .read = qla2x00_sysfs_read_fw_dump,
87 .write = qla2x00_sysfs_write_fw_dump,
88};
89
90static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +080091qla2x00_sysfs_read_nvram(struct kobject *kobj,
92 struct bin_attribute *bin_attr,
93 char *buf, loff_t off, size_t count)
8482e112005-04-17 15:04:54 -050094{
Andrew Vasquezf363b942007-09-20 14:07:45 -070095 struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
8482e112005-04-17 15:04:54 -050096 struct device, kobj)));
Seokmann Ju281afe12007-07-26 13:43:34 -070097 int size = ha->nvram_size;
98 char *nvram_cache = ha->nvram;
8482e112005-04-17 15:04:54 -050099
Seokmann Ju281afe12007-07-26 13:43:34 -0700100 if (!capable(CAP_SYS_ADMIN) || off > size || count == 0)
8482e112005-04-17 15:04:54 -0500101 return 0;
Seokmann Ju281afe12007-07-26 13:43:34 -0700102 if (off + count > size) {
103 size -= off;
104 count = size;
105 }
8482e112005-04-17 15:04:54 -0500106
Seokmann Ju281afe12007-07-26 13:43:34 -0700107 /* Read NVRAM data from cache. */
108 memcpy(buf, &nvram_cache[off], count);
8482e112005-04-17 15:04:54 -0500109
Seokmann Ju281afe12007-07-26 13:43:34 -0700110 return count;
8482e112005-04-17 15:04:54 -0500111}
112
113static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +0800114qla2x00_sysfs_write_nvram(struct kobject *kobj,
115 struct bin_attribute *bin_attr,
116 char *buf, loff_t off, size_t count)
8482e112005-04-17 15:04:54 -0500117{
Andrew Vasquezf363b942007-09-20 14:07:45 -0700118 struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
8482e112005-04-17 15:04:54 -0500119 struct device, kobj)));
8482e112005-04-17 15:04:54 -0500120 uint16_t cnt;
8482e112005-04-17 15:04:54 -0500121
Andrew Vasquez459c5372005-07-06 10:31:07 -0700122 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
8482e112005-04-17 15:04:54 -0500123 return 0;
124
125 /* Checksum NVRAM. */
Andrew Vasqueze4289242007-07-19 15:05:56 -0700126 if (IS_FWI2_CAPABLE(ha)) {
Andrew Vasquez459c5372005-07-06 10:31:07 -0700127 uint32_t *iter;
128 uint32_t chksum;
129
130 iter = (uint32_t *)buf;
131 chksum = 0;
132 for (cnt = 0; cnt < ((count >> 2) - 1); cnt++)
133 chksum += le32_to_cpu(*iter++);
134 chksum = ~chksum + 1;
135 *iter = cpu_to_le32(chksum);
136 } else {
137 uint8_t *iter;
138 uint8_t chksum;
139
140 iter = (uint8_t *)buf;
141 chksum = 0;
142 for (cnt = 0; cnt < count - 1; cnt++)
143 chksum += *iter++;
144 chksum = ~chksum + 1;
145 *iter = chksum;
146 }
8482e112005-04-17 15:04:54 -0500147
148 /* Write NVRAM. */
Andrew Vasquezfd34f552007-07-19 15:06:00 -0700149 ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count);
Andrew Vasquezc45bcc82007-09-20 14:07:42 -0700150 ha->isp_ops->read_nvram(ha, (uint8_t *)ha->nvram, ha->nvram_base,
Seokmann Ju281afe12007-07-26 13:43:34 -0700151 count);
8482e112005-04-17 15:04:54 -0500152
Andrew Vasquez26b8d3482007-01-29 10:22:28 -0800153 set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
154
8482e112005-04-17 15:04:54 -0500155 return (count);
156}
157
158static struct bin_attribute sysfs_nvram_attr = {
159 .attr = {
160 .name = "nvram",
161 .mode = S_IRUSR | S_IWUSR,
8482e112005-04-17 15:04:54 -0500162 },
andrew.vasquez@qlogic.com1b3f6362006-01-31 16:05:12 -0800163 .size = 512,
8482e112005-04-17 15:04:54 -0500164 .read = qla2x00_sysfs_read_nvram,
165 .write = qla2x00_sysfs_write_nvram,
166};
167
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800168static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +0800169qla2x00_sysfs_read_optrom(struct kobject *kobj,
170 struct bin_attribute *bin_attr,
171 char *buf, loff_t off, size_t count)
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800172{
Andrew Vasquezf363b942007-09-20 14:07:45 -0700173 struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800174 struct device, kobj)));
175
176 if (ha->optrom_state != QLA_SREADING)
177 return 0;
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700178 if (off > ha->optrom_region_size)
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800179 return 0;
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700180 if (off + count > ha->optrom_region_size)
181 count = ha->optrom_region_size - off;
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800182
183 memcpy(buf, &ha->optrom_buffer[off], count);
184
185 return count;
186}
187
188static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +0800189qla2x00_sysfs_write_optrom(struct kobject *kobj,
190 struct bin_attribute *bin_attr,
191 char *buf, loff_t off, size_t count)
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800192{
Andrew Vasquezf363b942007-09-20 14:07:45 -0700193 struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800194 struct device, kobj)));
195
196 if (ha->optrom_state != QLA_SWRITING)
197 return -EINVAL;
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700198 if (off > ha->optrom_region_size)
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800199 return -ERANGE;
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700200 if (off + count > ha->optrom_region_size)
201 count = ha->optrom_region_size - off;
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800202
203 memcpy(&ha->optrom_buffer[off], buf, count);
204
205 return count;
206}
207
208static struct bin_attribute sysfs_optrom_attr = {
209 .attr = {
210 .name = "optrom",
211 .mode = S_IRUSR | S_IWUSR,
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800212 },
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700213 .size = 0,
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800214 .read = qla2x00_sysfs_read_optrom,
215 .write = qla2x00_sysfs_write_optrom,
216};
217
218static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +0800219qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
220 struct bin_attribute *bin_attr,
221 char *buf, loff_t off, size_t count)
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800222{
Andrew Vasquezf363b942007-09-20 14:07:45 -0700223 struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800224 struct device, kobj)));
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700225 uint32_t start = 0;
226 uint32_t size = ha->optrom_size;
227 int val, valid;
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800228
229 if (off)
230 return 0;
231
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700232 if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1)
233 return -EINVAL;
234 if (start > ha->optrom_size)
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800235 return -EINVAL;
236
237 switch (val) {
238 case 0:
239 if (ha->optrom_state != QLA_SREADING &&
240 ha->optrom_state != QLA_SWRITING)
241 break;
242
243 ha->optrom_state = QLA_SWAITING;
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700244
245 DEBUG2(qla_printk(KERN_INFO, ha,
246 "Freeing flash region allocation -- 0x%x bytes.\n",
247 ha->optrom_region_size));
248
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800249 vfree(ha->optrom_buffer);
250 ha->optrom_buffer = NULL;
251 break;
252 case 1:
253 if (ha->optrom_state != QLA_SWAITING)
254 break;
255
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700256 if (start & 0xfff) {
257 qla_printk(KERN_WARNING, ha,
258 "Invalid start region 0x%x/0x%x.\n", start, size);
259 return -EINVAL;
260 }
261
262 ha->optrom_region_start = start;
263 ha->optrom_region_size = start + size > ha->optrom_size ?
264 ha->optrom_size - start : size;
265
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800266 ha->optrom_state = QLA_SREADING;
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700267 ha->optrom_buffer = vmalloc(ha->optrom_region_size);
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800268 if (ha->optrom_buffer == NULL) {
269 qla_printk(KERN_WARNING, ha,
270 "Unable to allocate memory for optrom retrieval "
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700271 "(%x).\n", ha->optrom_region_size);
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800272
273 ha->optrom_state = QLA_SWAITING;
274 return count;
275 }
276
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700277 DEBUG2(qla_printk(KERN_INFO, ha,
278 "Reading flash region -- 0x%x/0x%x.\n",
279 ha->optrom_region_start, ha->optrom_region_size));
280
281 memset(ha->optrom_buffer, 0, ha->optrom_region_size);
282 ha->isp_ops->read_optrom(ha, ha->optrom_buffer,
283 ha->optrom_region_start, ha->optrom_region_size);
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800284 break;
285 case 2:
286 if (ha->optrom_state != QLA_SWAITING)
287 break;
288
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700289 /*
290 * We need to be more restrictive on which FLASH regions are
291 * allowed to be updated via user-space. Regions accessible
292 * via this method include:
293 *
294 * ISP21xx/ISP22xx/ISP23xx type boards:
295 *
296 * 0x000000 -> 0x020000 -- Boot code.
297 *
298 * ISP2322/ISP24xx type boards:
299 *
300 * 0x000000 -> 0x07ffff -- Boot code.
301 * 0x080000 -> 0x0fffff -- Firmware.
302 *
303 * ISP25xx type boards:
304 *
305 * 0x000000 -> 0x07ffff -- Boot code.
306 * 0x080000 -> 0x0fffff -- Firmware.
307 * 0x120000 -> 0x12ffff -- VPD and HBA parameters.
308 */
309 valid = 0;
310 if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
311 valid = 1;
312 else if (start == (FA_BOOT_CODE_ADDR*4) ||
313 start == (FA_RISC_CODE_ADDR*4))
314 valid = 1;
315 else if (IS_QLA25XX(ha) && start == (FA_VPD_NVRAM_ADDR*4))
316 valid = 1;
317 if (!valid) {
318 qla_printk(KERN_WARNING, ha,
319 "Invalid start region 0x%x/0x%x.\n", start, size);
320 return -EINVAL;
321 }
322
323 ha->optrom_region_start = start;
324 ha->optrom_region_size = start + size > ha->optrom_size ?
325 ha->optrom_size - start : size;
326
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800327 ha->optrom_state = QLA_SWRITING;
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700328 ha->optrom_buffer = vmalloc(ha->optrom_region_size);
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800329 if (ha->optrom_buffer == NULL) {
330 qla_printk(KERN_WARNING, ha,
331 "Unable to allocate memory for optrom update "
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700332 "(%x).\n", ha->optrom_region_size);
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800333
334 ha->optrom_state = QLA_SWAITING;
335 return count;
336 }
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700337
338 DEBUG2(qla_printk(KERN_INFO, ha,
339 "Staging flash region write -- 0x%x/0x%x.\n",
340 ha->optrom_region_start, ha->optrom_region_size));
341
342 memset(ha->optrom_buffer, 0, ha->optrom_region_size);
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800343 break;
344 case 3:
345 if (ha->optrom_state != QLA_SWRITING)
346 break;
347
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700348 DEBUG2(qla_printk(KERN_INFO, ha,
349 "Writing flash region -- 0x%x/0x%x.\n",
350 ha->optrom_region_start, ha->optrom_region_size));
351
352 ha->isp_ops->write_optrom(ha, ha->optrom_buffer,
353 ha->optrom_region_start, ha->optrom_region_size);
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800354 break;
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700355 default:
356 count = -EINVAL;
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800357 }
358 return count;
359}
360
361static struct bin_attribute sysfs_optrom_ctl_attr = {
362 .attr = {
363 .name = "optrom_ctl",
364 .mode = S_IWUSR,
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800365 },
366 .size = 0,
367 .write = qla2x00_sysfs_write_optrom_ctl,
368};
369
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800370static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +0800371qla2x00_sysfs_read_vpd(struct kobject *kobj,
372 struct bin_attribute *bin_attr,
373 char *buf, loff_t off, size_t count)
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800374{
Andrew Vasquezf363b942007-09-20 14:07:45 -0700375 struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800376 struct device, kobj)));
Seokmann Ju281afe12007-07-26 13:43:34 -0700377 int size = ha->vpd_size;
378 char *vpd_cache = ha->vpd;
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800379
Seokmann Ju281afe12007-07-26 13:43:34 -0700380 if (!capable(CAP_SYS_ADMIN) || off > size || count == 0)
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800381 return 0;
Seokmann Ju281afe12007-07-26 13:43:34 -0700382 if (off + count > size) {
383 size -= off;
384 count = size;
385 }
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800386
Seokmann Ju281afe12007-07-26 13:43:34 -0700387 /* Read NVRAM data from cache. */
388 memcpy(buf, &vpd_cache[off], count);
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800389
Seokmann Ju281afe12007-07-26 13:43:34 -0700390 return count;
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800391}
392
393static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +0800394qla2x00_sysfs_write_vpd(struct kobject *kobj,
395 struct bin_attribute *bin_attr,
396 char *buf, loff_t off, size_t count)
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800397{
Andrew Vasquezf363b942007-09-20 14:07:45 -0700398 struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800399 struct device, kobj)));
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800400
401 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size)
402 return 0;
403
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800404 /* Write NVRAM. */
Andrew Vasquezfd34f552007-07-19 15:06:00 -0700405 ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count);
Seokmann Ju281afe12007-07-26 13:43:34 -0700406 ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, ha->vpd_base, count);
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800407
408 return count;
409}
410
411static struct bin_attribute sysfs_vpd_attr = {
412 .attr = {
413 .name = "vpd",
414 .mode = S_IRUSR | S_IWUSR,
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800415 },
416 .size = 0,
417 .read = qla2x00_sysfs_read_vpd,
418 .write = qla2x00_sysfs_write_vpd,
419};
420
Andrew Vasquez88729e52006-06-23 16:10:50 -0700421static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +0800422qla2x00_sysfs_read_sfp(struct kobject *kobj,
423 struct bin_attribute *bin_attr,
424 char *buf, loff_t off, size_t count)
Andrew Vasquez88729e52006-06-23 16:10:50 -0700425{
Andrew Vasquezf363b942007-09-20 14:07:45 -0700426 struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
Andrew Vasquez88729e52006-06-23 16:10:50 -0700427 struct device, kobj)));
428 uint16_t iter, addr, offset;
429 int rval;
430
431 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != SFP_DEV_SIZE * 2)
432 return 0;
433
Andrew Vasqueze8711082008-01-31 12:33:48 -0800434 if (ha->sfp_data)
435 goto do_read;
436
437 ha->sfp_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
438 &ha->sfp_data_dma);
439 if (!ha->sfp_data) {
440 qla_printk(KERN_WARNING, ha,
441 "Unable to allocate memory for SFP read-data.\n");
442 return 0;
443 }
444
445do_read:
446 memset(ha->sfp_data, 0, SFP_BLOCK_SIZE);
Andrew Vasquez88729e52006-06-23 16:10:50 -0700447 addr = 0xa0;
448 for (iter = 0, offset = 0; iter < (SFP_DEV_SIZE * 2) / SFP_BLOCK_SIZE;
449 iter++, offset += SFP_BLOCK_SIZE) {
450 if (iter == 4) {
451 /* Skip to next device address. */
452 addr = 0xa2;
453 offset = 0;
454 }
455
456 rval = qla2x00_read_sfp(ha, ha->sfp_data_dma, addr, offset,
457 SFP_BLOCK_SIZE);
458 if (rval != QLA_SUCCESS) {
459 qla_printk(KERN_WARNING, ha,
460 "Unable to read SFP data (%x/%x/%x).\n", rval,
461 addr, offset);
462 count = 0;
463 break;
464 }
465 memcpy(buf, ha->sfp_data, SFP_BLOCK_SIZE);
466 buf += SFP_BLOCK_SIZE;
467 }
468
469 return count;
470}
471
472static struct bin_attribute sysfs_sfp_attr = {
473 .attr = {
474 .name = "sfp",
475 .mode = S_IRUSR | S_IWUSR,
Andrew Vasquez88729e52006-06-23 16:10:50 -0700476 },
477 .size = SFP_DEV_SIZE * 2,
478 .read = qla2x00_sysfs_read_sfp,
479};
480
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700481static struct sysfs_entry {
482 char *name;
483 struct bin_attribute *attr;
484 int is4GBp_only;
485} bin_file_entries[] = {
486 { "fw_dump", &sysfs_fw_dump_attr, },
487 { "nvram", &sysfs_nvram_attr, },
488 { "optrom", &sysfs_optrom_attr, },
489 { "optrom_ctl", &sysfs_optrom_ctl_attr, },
490 { "vpd", &sysfs_vpd_attr, 1 },
491 { "sfp", &sysfs_sfp_attr, 1 },
Randy Dunlap46ddab72006-11-27 09:35:42 -0800492 { NULL },
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700493};
494
8482e112005-04-17 15:04:54 -0500495void
496qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
497{
498 struct Scsi_Host *host = ha->host;
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700499 struct sysfs_entry *iter;
500 int ret;
8482e112005-04-17 15:04:54 -0500501
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700502 for (iter = bin_file_entries; iter->name; iter++) {
Andrew Vasqueze4289242007-07-19 15:05:56 -0700503 if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha))
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700504 continue;
505
506 ret = sysfs_create_bin_file(&host->shost_gendev.kobj,
507 iter->attr);
508 if (ret)
509 qla_printk(KERN_INFO, ha,
510 "Unable to create sysfs %s binary attribute "
511 "(%d).\n", iter->name, ret);
Andrew Vasquez7914d002006-06-23 16:10:55 -0700512 }
8482e112005-04-17 15:04:54 -0500513}
514
515void
516qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
517{
518 struct Scsi_Host *host = ha->host;
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700519 struct sysfs_entry *iter;
8482e112005-04-17 15:04:54 -0500520
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700521 for (iter = bin_file_entries; iter->name; iter++) {
Andrew Vasqueze4289242007-07-19 15:05:56 -0700522 if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha))
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700523 continue;
524
Andrew Vasquez7914d002006-06-23 16:10:55 -0700525 sysfs_remove_bin_file(&host->shost_gendev.kobj,
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700526 iter->attr);
Andrew Vasquez7914d002006-06-23 16:10:55 -0700527 }
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800528
529 if (ha->beacon_blink_led == 1)
Andrew Vasquezfd34f552007-07-19 15:06:00 -0700530 ha->isp_ops->beacon_off(ha);
8482e112005-04-17 15:04:54 -0500531}
532
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700533/* Scsi_Host attributes. */
534
535static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100536qla2x00_drvr_version_show(struct device *dev,
537 struct device_attribute *attr, char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700538{
539 return snprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str);
540}
541
542static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100543qla2x00_fw_version_show(struct device *dev,
544 struct device_attribute *attr, char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700545{
Tony Jonesee959b02008-02-22 00:13:36 +0100546 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700547 char fw_str[30];
548
549 return snprintf(buf, PAGE_SIZE, "%s\n",
Andrew Vasquezfd34f552007-07-19 15:06:00 -0700550 ha->isp_ops->fw_version_str(ha, fw_str));
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700551}
552
553static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100554qla2x00_serial_num_show(struct device *dev, struct device_attribute *attr,
555 char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700556{
Tony Jonesee959b02008-02-22 00:13:36 +0100557 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700558 uint32_t sn;
559
Joe Carnuccio1ee27142008-07-10 16:55:53 -0700560 if (IS_FWI2_CAPABLE(ha)) {
561 qla2xxx_get_vpd_field(ha, "SN", buf, PAGE_SIZE);
562 return snprintf(buf, PAGE_SIZE, "%s\n", buf);
563 }
Andrew Vasquez8b7afc22007-10-19 15:59:19 -0700564
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700565 sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
566 return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000,
567 sn % 100000);
568}
569
570static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100571qla2x00_isp_name_show(struct device *dev, struct device_attribute *attr,
572 char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700573{
Tony Jonesee959b02008-02-22 00:13:36 +0100574 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquez54333832005-11-09 15:49:04 -0800575 return snprintf(buf, PAGE_SIZE, "ISP%04X\n", ha->pdev->device);
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700576}
577
578static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100579qla2x00_isp_id_show(struct device *dev, struct device_attribute *attr,
580 char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700581{
Tony Jonesee959b02008-02-22 00:13:36 +0100582 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700583 return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n",
584 ha->product_id[0], ha->product_id[1], ha->product_id[2],
585 ha->product_id[3]);
586}
587
588static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100589qla2x00_model_name_show(struct device *dev, struct device_attribute *attr,
590 char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700591{
Tony Jonesee959b02008-02-22 00:13:36 +0100592 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700593 return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_number);
594}
595
596static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100597qla2x00_model_desc_show(struct device *dev, struct device_attribute *attr,
598 char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700599{
Tony Jonesee959b02008-02-22 00:13:36 +0100600 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700601 return snprintf(buf, PAGE_SIZE, "%s\n",
602 ha->model_desc ? ha->model_desc: "");
603}
604
605static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100606qla2x00_pci_info_show(struct device *dev, struct device_attribute *attr,
607 char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700608{
Tony Jonesee959b02008-02-22 00:13:36 +0100609 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700610 char pci_info[30];
611
612 return snprintf(buf, PAGE_SIZE, "%s\n",
Andrew Vasquezfd34f552007-07-19 15:06:00 -0700613 ha->isp_ops->pci_info_str(ha, pci_info));
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700614}
615
616static ssize_t
Hannes Reineckebbd1ae42008-03-18 14:32:28 +0100617qla2x00_link_state_show(struct device *dev, struct device_attribute *attr,
618 char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700619{
Tony Jonesee959b02008-02-22 00:13:36 +0100620 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700621 int len = 0;
622
623 if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
624 atomic_read(&ha->loop_state) == LOOP_DEAD)
625 len = snprintf(buf, PAGE_SIZE, "Link Down\n");
626 else if (atomic_read(&ha->loop_state) != LOOP_READY ||
627 test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) ||
628 test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags))
629 len = snprintf(buf, PAGE_SIZE, "Unknown Link State\n");
630 else {
631 len = snprintf(buf, PAGE_SIZE, "Link Up - ");
632
633 switch (ha->current_topology) {
634 case ISP_CFG_NL:
635 len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n");
636 break;
637 case ISP_CFG_FL:
638 len += snprintf(buf + len, PAGE_SIZE-len, "FL_Port\n");
639 break;
640 case ISP_CFG_N:
641 len += snprintf(buf + len, PAGE_SIZE-len,
642 "N_Port to N_Port\n");
643 break;
644 case ISP_CFG_F:
645 len += snprintf(buf + len, PAGE_SIZE-len, "F_Port\n");
646 break;
647 default:
648 len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n");
649 break;
650 }
651 }
652 return len;
653}
654
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700655static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100656qla2x00_zio_show(struct device *dev, struct device_attribute *attr,
657 char *buf)
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700658{
Tony Jonesee959b02008-02-22 00:13:36 +0100659 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700660 int len = 0;
661
662 switch (ha->zio_mode) {
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700663 case QLA_ZIO_MODE_6:
664 len += snprintf(buf + len, PAGE_SIZE-len, "Mode 6\n");
665 break;
666 case QLA_ZIO_DISABLED:
667 len += snprintf(buf + len, PAGE_SIZE-len, "Disabled\n");
668 break;
669 }
670 return len;
671}
672
673static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100674qla2x00_zio_store(struct device *dev, struct device_attribute *attr,
675 const char *buf, size_t count)
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700676{
Tony Jonesee959b02008-02-22 00:13:36 +0100677 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700678 int val = 0;
679 uint16_t zio_mode;
680
andrew.vasquez@qlogic.com4a59f712006-03-09 14:27:39 -0800681 if (!IS_ZIO_SUPPORTED(ha))
682 return -ENOTSUPP;
683
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700684 if (sscanf(buf, "%d", &val) != 1)
685 return -EINVAL;
686
andrew.vasquez@qlogic.com4a59f712006-03-09 14:27:39 -0800687 if (val)
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700688 zio_mode = QLA_ZIO_MODE_6;
andrew.vasquez@qlogic.com4a59f712006-03-09 14:27:39 -0800689 else
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700690 zio_mode = QLA_ZIO_DISABLED;
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700691
692 /* Update per-hba values and queue a reset. */
693 if (zio_mode != QLA_ZIO_DISABLED || ha->zio_mode != QLA_ZIO_DISABLED) {
694 ha->zio_mode = zio_mode;
695 set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
696 }
697 return strlen(buf);
698}
699
700static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100701qla2x00_zio_timer_show(struct device *dev, struct device_attribute *attr,
702 char *buf)
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700703{
Tony Jonesee959b02008-02-22 00:13:36 +0100704 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700705
706 return snprintf(buf, PAGE_SIZE, "%d us\n", ha->zio_timer * 100);
707}
708
709static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100710qla2x00_zio_timer_store(struct device *dev, struct device_attribute *attr,
711 const char *buf, size_t count)
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700712{
Tony Jonesee959b02008-02-22 00:13:36 +0100713 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700714 int val = 0;
715 uint16_t zio_timer;
716
717 if (sscanf(buf, "%d", &val) != 1)
718 return -EINVAL;
719 if (val > 25500 || val < 100)
720 return -ERANGE;
721
722 zio_timer = (uint16_t)(val / 100);
723 ha->zio_timer = zio_timer;
724
725 return strlen(buf);
726}
727
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800728static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100729qla2x00_beacon_show(struct device *dev, struct device_attribute *attr,
730 char *buf)
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800731{
Tony Jonesee959b02008-02-22 00:13:36 +0100732 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800733 int len = 0;
734
735 if (ha->beacon_blink_led)
736 len += snprintf(buf + len, PAGE_SIZE-len, "Enabled\n");
737 else
738 len += snprintf(buf + len, PAGE_SIZE-len, "Disabled\n");
739 return len;
740}
741
742static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100743qla2x00_beacon_store(struct device *dev, struct device_attribute *attr,
744 const char *buf, size_t count)
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800745{
Tony Jonesee959b02008-02-22 00:13:36 +0100746 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800747 int val = 0;
748 int rval;
749
750 if (IS_QLA2100(ha) || IS_QLA2200(ha))
751 return -EPERM;
752
753 if (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) {
754 qla_printk(KERN_WARNING, ha,
755 "Abort ISP active -- ignoring beacon request.\n");
756 return -EBUSY;
757 }
758
759 if (sscanf(buf, "%d", &val) != 1)
760 return -EINVAL;
761
762 if (val)
Andrew Vasquezfd34f552007-07-19 15:06:00 -0700763 rval = ha->isp_ops->beacon_on(ha);
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800764 else
Andrew Vasquezfd34f552007-07-19 15:06:00 -0700765 rval = ha->isp_ops->beacon_off(ha);
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800766
767 if (rval != QLA_SUCCESS)
768 count = 0;
769
770 return count;
771}
772
Andrew Vasquez30c47662007-01-29 10:22:21 -0800773static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100774qla2x00_optrom_bios_version_show(struct device *dev,
775 struct device_attribute *attr, char *buf)
Andrew Vasquez30c47662007-01-29 10:22:21 -0800776{
Tony Jonesee959b02008-02-22 00:13:36 +0100777 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquez30c47662007-01-29 10:22:21 -0800778
779 return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1],
780 ha->bios_revision[0]);
781}
782
783static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100784qla2x00_optrom_efi_version_show(struct device *dev,
785 struct device_attribute *attr, char *buf)
Andrew Vasquez30c47662007-01-29 10:22:21 -0800786{
Tony Jonesee959b02008-02-22 00:13:36 +0100787 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquez30c47662007-01-29 10:22:21 -0800788
789 return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1],
790 ha->efi_revision[0]);
791}
792
793static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100794qla2x00_optrom_fcode_version_show(struct device *dev,
795 struct device_attribute *attr, char *buf)
Andrew Vasquez30c47662007-01-29 10:22:21 -0800796{
Tony Jonesee959b02008-02-22 00:13:36 +0100797 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquez30c47662007-01-29 10:22:21 -0800798
799 return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1],
800 ha->fcode_revision[0]);
801}
802
803static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100804qla2x00_optrom_fw_version_show(struct device *dev,
805 struct device_attribute *attr, char *buf)
Andrew Vasquez30c47662007-01-29 10:22:21 -0800806{
Tony Jonesee959b02008-02-22 00:13:36 +0100807 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
Andrew Vasquez30c47662007-01-29 10:22:21 -0800808
809 return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n",
810 ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2],
811 ha->fw_revision[3]);
812}
813
Harish Zunjarraoe5f5f6f2008-07-10 16:55:49 -0700814static ssize_t
815qla2x00_total_isp_aborts_show(struct device *dev,
816 struct device_attribute *attr, char *buf)
817{
818 scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
819
820 return snprintf(buf, PAGE_SIZE, "%d\n",
821 ha->qla_stats.total_isp_aborts);
822}
823
Tony Jonesee959b02008-02-22 00:13:36 +0100824static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
825static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
826static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
827static DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL);
828static DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL);
829static DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL);
830static DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL);
831static DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL);
Hannes Reineckebbd1ae42008-03-18 14:32:28 +0100832static DEVICE_ATTR(link_state, S_IRUGO, qla2x00_link_state_show, NULL);
Tony Jonesee959b02008-02-22 00:13:36 +0100833static DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show, qla2x00_zio_store);
834static DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
835 qla2x00_zio_timer_store);
836static DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show,
837 qla2x00_beacon_store);
838static DEVICE_ATTR(optrom_bios_version, S_IRUGO,
839 qla2x00_optrom_bios_version_show, NULL);
840static DEVICE_ATTR(optrom_efi_version, S_IRUGO,
841 qla2x00_optrom_efi_version_show, NULL);
842static DEVICE_ATTR(optrom_fcode_version, S_IRUGO,
843 qla2x00_optrom_fcode_version_show, NULL);
844static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show,
845 NULL);
Harish Zunjarraoe5f5f6f2008-07-10 16:55:49 -0700846static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show,
847 NULL);
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700848
Tony Jonesee959b02008-02-22 00:13:36 +0100849struct device_attribute *qla2x00_host_attrs[] = {
850 &dev_attr_driver_version,
851 &dev_attr_fw_version,
852 &dev_attr_serial_num,
853 &dev_attr_isp_name,
854 &dev_attr_isp_id,
855 &dev_attr_model_name,
856 &dev_attr_model_desc,
857 &dev_attr_pci_info,
Hannes Reineckebbd1ae42008-03-18 14:32:28 +0100858 &dev_attr_link_state,
Tony Jonesee959b02008-02-22 00:13:36 +0100859 &dev_attr_zio,
860 &dev_attr_zio_timer,
861 &dev_attr_beacon,
862 &dev_attr_optrom_bios_version,
863 &dev_attr_optrom_efi_version,
864 &dev_attr_optrom_fcode_version,
865 &dev_attr_optrom_fw_version,
Harish Zunjarraoe5f5f6f2008-07-10 16:55:49 -0700866 &dev_attr_total_isp_aborts,
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700867 NULL,
868};
869
8482e112005-04-17 15:04:54 -0500870/* Host attributes. */
871
872static void
873qla2x00_get_host_port_id(struct Scsi_Host *shost)
874{
Andrew Vasquezf363b942007-09-20 14:07:45 -0700875 scsi_qla_host_t *ha = shost_priv(shost);
8482e112005-04-17 15:04:54 -0500876
877 fc_host_port_id(shost) = ha->d_id.b.domain << 16 |
878 ha->d_id.b.area << 8 | ha->d_id.b.al_pa;
879}
880
881static void
andrew.vasquez@qlogic.com04414012006-01-31 16:04:51 -0800882qla2x00_get_host_speed(struct Scsi_Host *shost)
883{
Seokmann Juda4541b2008-01-31 12:33:52 -0800884 scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost));
Andrew Vasquez2ae2b372008-04-03 13:13:14 -0700885 u32 speed = FC_PORTSPEED_UNKNOWN;
andrew.vasquez@qlogic.com04414012006-01-31 16:04:51 -0800886
887 switch (ha->link_data_rate) {
Andrew Vasquezd8b45212006-10-02 12:00:43 -0700888 case PORT_SPEED_1GB:
Andrew Vasquez2ae2b372008-04-03 13:13:14 -0700889 speed = FC_PORTSPEED_1GBIT;
andrew.vasquez@qlogic.com04414012006-01-31 16:04:51 -0800890 break;
Andrew Vasquezd8b45212006-10-02 12:00:43 -0700891 case PORT_SPEED_2GB:
Andrew Vasquez2ae2b372008-04-03 13:13:14 -0700892 speed = FC_PORTSPEED_2GBIT;
andrew.vasquez@qlogic.com04414012006-01-31 16:04:51 -0800893 break;
Andrew Vasquezd8b45212006-10-02 12:00:43 -0700894 case PORT_SPEED_4GB:
Andrew Vasquez2ae2b372008-04-03 13:13:14 -0700895 speed = FC_PORTSPEED_4GBIT;
andrew.vasquez@qlogic.com04414012006-01-31 16:04:51 -0800896 break;
Seokmann Juda4541b2008-01-31 12:33:52 -0800897 case PORT_SPEED_8GB:
Andrew Vasquez2ae2b372008-04-03 13:13:14 -0700898 speed = FC_PORTSPEED_8GBIT;
Seokmann Juda4541b2008-01-31 12:33:52 -0800899 break;
andrew.vasquez@qlogic.com04414012006-01-31 16:04:51 -0800900 }
901 fc_host_speed(shost) = speed;
902}
903
904static void
andrew.vasquez@qlogic.com8d067622006-01-31 16:04:56 -0800905qla2x00_get_host_port_type(struct Scsi_Host *shost)
906{
Shyam Sundar2f2fa132008-05-12 22:21:07 -0700907 scsi_qla_host_t *ha = shost_priv(shost);
andrew.vasquez@qlogic.com8d067622006-01-31 16:04:56 -0800908 uint32_t port_type = FC_PORTTYPE_UNKNOWN;
909
Shyam Sundar2f2fa132008-05-12 22:21:07 -0700910 if (ha->parent) {
911 fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
912 return;
913 }
andrew.vasquez@qlogic.com8d067622006-01-31 16:04:56 -0800914 switch (ha->current_topology) {
915 case ISP_CFG_NL:
916 port_type = FC_PORTTYPE_LPORT;
917 break;
918 case ISP_CFG_FL:
919 port_type = FC_PORTTYPE_NLPORT;
920 break;
921 case ISP_CFG_N:
922 port_type = FC_PORTTYPE_PTP;
923 break;
924 case ISP_CFG_F:
925 port_type = FC_PORTTYPE_NPORT;
926 break;
927 }
928 fc_host_port_type(shost) = port_type;
929}
930
931static void
8482e112005-04-17 15:04:54 -0500932qla2x00_get_starget_node_name(struct scsi_target *starget)
933{
934 struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
Andrew Vasquezf363b942007-09-20 14:07:45 -0700935 scsi_qla_host_t *ha = shost_priv(host);
bdf79622005-04-17 15:06:53 -0500936 fc_port_t *fcport;
Andrew Vasquezf8b02a82005-08-31 15:21:20 -0700937 u64 node_name = 0;
8482e112005-04-17 15:04:54 -0500938
bdf79622005-04-17 15:06:53 -0500939 list_for_each_entry(fcport, &ha->fcports, list) {
Andrew Vasquez5ab5a4d2008-04-03 13:13:16 -0700940 if (fcport->rport &&
941 starget->id == fcport->rport->scsi_target_id) {
Andrew Vasquezf8b02a82005-08-31 15:21:20 -0700942 node_name = wwn_to_u64(fcport->node_name);
bdf79622005-04-17 15:06:53 -0500943 break;
944 }
945 }
946
Andrew Vasquezf8b02a82005-08-31 15:21:20 -0700947 fc_starget_node_name(starget) = node_name;
8482e112005-04-17 15:04:54 -0500948}
949
950static void
951qla2x00_get_starget_port_name(struct scsi_target *starget)
952{
953 struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
Andrew Vasquezf363b942007-09-20 14:07:45 -0700954 scsi_qla_host_t *ha = shost_priv(host);
bdf79622005-04-17 15:06:53 -0500955 fc_port_t *fcport;
Andrew Vasquezf8b02a82005-08-31 15:21:20 -0700956 u64 port_name = 0;
8482e112005-04-17 15:04:54 -0500957
bdf79622005-04-17 15:06:53 -0500958 list_for_each_entry(fcport, &ha->fcports, list) {
Andrew Vasquez5ab5a4d2008-04-03 13:13:16 -0700959 if (fcport->rport &&
960 starget->id == fcport->rport->scsi_target_id) {
Andrew Vasquezf8b02a82005-08-31 15:21:20 -0700961 port_name = wwn_to_u64(fcport->port_name);
bdf79622005-04-17 15:06:53 -0500962 break;
963 }
964 }
965
Andrew Vasquezf8b02a82005-08-31 15:21:20 -0700966 fc_starget_port_name(starget) = port_name;
8482e112005-04-17 15:04:54 -0500967}
968
969static void
970qla2x00_get_starget_port_id(struct scsi_target *starget)
971{
972 struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
Andrew Vasquezf363b942007-09-20 14:07:45 -0700973 scsi_qla_host_t *ha = shost_priv(host);
bdf79622005-04-17 15:06:53 -0500974 fc_port_t *fcport;
975 uint32_t port_id = ~0U;
8482e112005-04-17 15:04:54 -0500976
bdf79622005-04-17 15:06:53 -0500977 list_for_each_entry(fcport, &ha->fcports, list) {
Andrew Vasquez5ab5a4d2008-04-03 13:13:16 -0700978 if (fcport->rport &&
979 starget->id == fcport->rport->scsi_target_id) {
bdf79622005-04-17 15:06:53 -0500980 port_id = fcport->d_id.b.domain << 16 |
981 fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
982 break;
983 }
984 }
985
8482e112005-04-17 15:04:54 -0500986 fc_starget_port_id(starget) = port_id;
987}
988
989static void
8482e112005-04-17 15:04:54 -0500990qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
991{
8482e112005-04-17 15:04:54 -0500992 if (timeout)
Andrew Vasquez85821c92008-07-10 16:55:48 -0700993 rport->dev_loss_tmo = timeout;
8482e112005-04-17 15:04:54 -0500994 else
Andrew Vasquez85821c92008-07-10 16:55:48 -0700995 rport->dev_loss_tmo = 1;
8482e112005-04-17 15:04:54 -0500996}
997
Seokmann Ju5f3a9a22008-07-10 16:55:47 -0700998static void
999qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
1000{
1001 struct Scsi_Host *host = rport_to_shost(rport);
1002 fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
1003
1004 qla2x00_abort_fcport_cmds(fcport);
1005
1006 /*
1007 * Transport has effectively 'deleted' the rport, clear
1008 * all local references.
1009 */
1010 spin_lock_irq(host->host_lock);
1011 fcport->rport = NULL;
1012 *((fc_port_t **)rport->dd_data) = NULL;
1013 spin_unlock_irq(host->host_lock);
1014}
1015
1016static void
1017qla2x00_terminate_rport_io(struct fc_rport *rport)
1018{
1019 fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
1020
1021 qla2x00_abort_fcport_cmds(fcport);
1022 scsi_target_unblock(&rport->dev);
1023}
1024
Andrew Vasquez91ca7b02005-10-27 16:03:37 -07001025static int
1026qla2x00_issue_lip(struct Scsi_Host *shost)
1027{
Andrew Vasquezf363b942007-09-20 14:07:45 -07001028 scsi_qla_host_t *ha = shost_priv(shost);
Andrew Vasquez91ca7b02005-10-27 16:03:37 -07001029
Andrew Vasqueza4722cf2008-01-17 09:02:12 -08001030 qla2x00_loop_reset(ha);
Andrew Vasquez91ca7b02005-10-27 16:03:37 -07001031 return 0;
1032}
1033
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08001034static struct fc_host_statistics *
1035qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
1036{
Seokmann Juda4541b2008-01-31 12:33:52 -08001037 scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost));
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08001038 int rval;
Andrew Vasquez43ef0582008-01-17 09:02:08 -08001039 struct link_statistics *stats;
1040 dma_addr_t stats_dma;
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08001041 struct fc_host_statistics *pfc_host_stat;
1042
1043 pfc_host_stat = &ha->fc_host_stat;
1044 memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics));
1045
Andrew Vasquez43ef0582008-01-17 09:02:08 -08001046 stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma);
1047 if (stats == NULL) {
1048 DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n",
1049 __func__, ha->host_no));
1050 goto done;
1051 }
1052 memset(stats, 0, DMA_POOL_SIZE);
1053
1054 rval = QLA_FUNCTION_FAILED;
Andrew Vasqueze4289242007-07-19 15:05:56 -07001055 if (IS_FWI2_CAPABLE(ha)) {
Andrew Vasquez43ef0582008-01-17 09:02:08 -08001056 rval = qla24xx_get_isp_stats(ha, stats, stats_dma);
Andrew Vasquez178779a2007-01-29 10:22:25 -08001057 } else if (atomic_read(&ha->loop_state) == LOOP_READY &&
1058 !test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) &&
1059 !test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) &&
1060 !ha->dpc_active) {
1061 /* Must be in a 'READY' state for statistics retrieval. */
Andrew Vasquez43ef0582008-01-17 09:02:08 -08001062 rval = qla2x00_get_link_status(ha, ha->loop_id, stats,
1063 stats_dma);
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08001064 }
Andrew Vasquez178779a2007-01-29 10:22:25 -08001065
1066 if (rval != QLA_SUCCESS)
Andrew Vasquez43ef0582008-01-17 09:02:08 -08001067 goto done_free;
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08001068
Andrew Vasquez43ef0582008-01-17 09:02:08 -08001069 pfc_host_stat->link_failure_count = stats->link_fail_cnt;
1070 pfc_host_stat->loss_of_sync_count = stats->loss_sync_cnt;
1071 pfc_host_stat->loss_of_signal_count = stats->loss_sig_cnt;
1072 pfc_host_stat->prim_seq_protocol_err_count = stats->prim_seq_err_cnt;
1073 pfc_host_stat->invalid_tx_word_count = stats->inval_xmit_word_cnt;
1074 pfc_host_stat->invalid_crc_count = stats->inval_crc_cnt;
1075 if (IS_FWI2_CAPABLE(ha)) {
Harish Zunjarrao032d8dd2008-07-10 16:55:50 -07001076 pfc_host_stat->lip_count = stats->lip_cnt;
Andrew Vasquez43ef0582008-01-17 09:02:08 -08001077 pfc_host_stat->tx_frames = stats->tx_frames;
1078 pfc_host_stat->rx_frames = stats->rx_frames;
1079 pfc_host_stat->dumped_frames = stats->dumped_frames;
1080 pfc_host_stat->nos_count = stats->nos_rcvd;
1081 }
1082
1083done_free:
1084 dma_pool_free(ha->s_dma_pool, stats, stats_dma);
Andrew Vasquez178779a2007-01-29 10:22:25 -08001085done:
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08001086 return pfc_host_stat;
1087}
1088
Andrew Vasquez1620f7c2006-10-02 12:00:44 -07001089static void
1090qla2x00_get_host_symbolic_name(struct Scsi_Host *shost)
1091{
Andrew Vasquezf363b942007-09-20 14:07:45 -07001092 scsi_qla_host_t *ha = shost_priv(shost);
Andrew Vasquez1620f7c2006-10-02 12:00:44 -07001093
1094 qla2x00_get_sym_node_name(ha, fc_host_symbolic_name(shost));
1095}
1096
Andrew Vasqueza740a3f2006-10-02 12:00:45 -07001097static void
1098qla2x00_set_host_system_hostname(struct Scsi_Host *shost)
1099{
Andrew Vasquezf363b942007-09-20 14:07:45 -07001100 scsi_qla_host_t *ha = shost_priv(shost);
Andrew Vasqueza740a3f2006-10-02 12:00:45 -07001101
1102 set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
1103}
1104
Andrew Vasquez90991c82006-10-02 12:00:46 -07001105static void
1106qla2x00_get_host_fabric_name(struct Scsi_Host *shost)
1107{
Andrew Vasquezf363b942007-09-20 14:07:45 -07001108 scsi_qla_host_t *ha = shost_priv(shost);
Andrew Vasquez90991c82006-10-02 12:00:46 -07001109 u64 node_name;
1110
1111 if (ha->device_flags & SWITCH_FOUND)
1112 node_name = wwn_to_u64(ha->fabric_node_name);
1113 else
1114 node_name = wwn_to_u64(ha->node_name);
1115
1116 fc_host_fabric_name(shost) = node_name;
1117}
1118
Andrew Vasquez7047fcd2006-10-02 12:00:47 -07001119static void
1120qla2x00_get_host_port_state(struct Scsi_Host *shost)
1121{
Seokmann Juda4541b2008-01-31 12:33:52 -08001122 scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost));
Andrew Vasquez7047fcd2006-10-02 12:00:47 -07001123
1124 if (!ha->flags.online)
1125 fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
1126 else if (atomic_read(&ha->loop_state) == LOOP_TIMEOUT)
1127 fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
1128 else
1129 fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
1130}
1131
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001132static int
1133qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
1134{
1135 int ret = 0;
Andrew Vasquezf363b942007-09-20 14:07:45 -07001136 scsi_qla_host_t *ha = shost_priv(fc_vport->shost);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001137 scsi_qla_host_t *vha;
1138
1139 ret = qla24xx_vport_create_req_sanity_check(fc_vport);
1140 if (ret) {
1141 DEBUG15(printk("qla24xx_vport_create_req_sanity_check failed, "
1142 "status %x\n", ret));
1143 return (ret);
1144 }
1145
1146 vha = qla24xx_create_vhost(fc_vport);
1147 if (vha == NULL) {
1148 DEBUG15(printk ("qla24xx_create_vhost failed, vha = %p\n",
1149 vha));
1150 return FC_VPORT_FAILED;
1151 }
1152 if (disable) {
1153 atomic_set(&vha->vp_state, VP_OFFLINE);
1154 fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
1155 } else
1156 atomic_set(&vha->vp_state, VP_FAILED);
1157
1158 /* ready to create vport */
1159 qla_printk(KERN_INFO, vha, "VP entry id %d assigned.\n", vha->vp_idx);
1160
1161 /* initialized vport states */
1162 atomic_set(&vha->loop_state, LOOP_DOWN);
1163 vha->vp_err_state= VP_ERR_PORTDWN;
1164 vha->vp_prev_err_state= VP_ERR_UNKWN;
1165 /* Check if physical ha port is Up */
1166 if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
1167 atomic_read(&ha->loop_state) == LOOP_DEAD) {
1168 /* Don't retry or attempt login of this virtual port */
1169 DEBUG15(printk ("scsi(%ld): pport loop_state is not UP.\n",
1170 vha->host_no));
1171 atomic_set(&vha->loop_state, LOOP_DEAD);
1172 if (!disable)
1173 fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
1174 }
1175
1176 if (scsi_add_host(vha->host, &fc_vport->dev)) {
1177 DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
1178 vha->host_no, vha->vp_idx));
1179 goto vport_create_failed_2;
1180 }
1181
1182 /* initialize attributes */
1183 fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
1184 fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
1185 fc_host_supported_classes(vha->host) =
1186 fc_host_supported_classes(ha->host);
1187 fc_host_supported_speeds(vha->host) =
1188 fc_host_supported_speeds(ha->host);
1189
1190 qla24xx_vport_disable(fc_vport, disable);
1191
1192 return 0;
1193vport_create_failed_2:
1194 qla24xx_disable_vp(vha);
1195 qla24xx_deallocate_vp_id(vha);
1196 kfree(vha->port_name);
1197 kfree(vha->node_name);
1198 scsi_host_put(vha->host);
1199 return FC_VPORT_FAILED;
1200}
1201
Adrian Bunka824ebb2008-01-17 09:02:15 -08001202static int
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001203qla24xx_vport_delete(struct fc_vport *fc_vport)
1204{
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001205 scsi_qla_host_t *vha = fc_vport->dd_data;
1206
1207 qla24xx_disable_vp(vha);
1208 qla24xx_deallocate_vp_id(vha);
1209
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001210 kfree(vha->node_name);
1211 kfree(vha->port_name);
1212
1213 if (vha->timer_active) {
1214 qla2x00_vp_stop_timer(vha);
1215 DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p "
1216 "has stopped\n",
1217 vha->host_no, vha->vp_idx, vha));
1218 }
1219
1220 fc_remove_host(vha->host);
1221
1222 scsi_remove_host(vha->host);
1223
1224 scsi_host_put(vha->host);
1225
1226 return 0;
1227}
1228
Adrian Bunka824ebb2008-01-17 09:02:15 -08001229static int
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001230qla24xx_vport_disable(struct fc_vport *fc_vport, bool disable)
1231{
1232 scsi_qla_host_t *vha = fc_vport->dd_data;
1233
1234 if (disable)
1235 qla24xx_disable_vp(vha);
1236 else
1237 qla24xx_enable_vp(vha);
1238
1239 return 0;
1240}
1241
Andrew Vasquez1c97a122005-04-21 16:13:36 -04001242struct fc_function_template qla2xxx_transport_functions = {
8482e112005-04-17 15:04:54 -05001243
1244 .show_host_node_name = 1,
1245 .show_host_port_name = 1,
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07001246 .show_host_supported_classes = 1,
Andrew Vasquez2ae2b372008-04-03 13:13:14 -07001247 .show_host_supported_speeds = 1,
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07001248
8482e112005-04-17 15:04:54 -05001249 .get_host_port_id = qla2x00_get_host_port_id,
1250 .show_host_port_id = 1,
andrew.vasquez@qlogic.com04414012006-01-31 16:04:51 -08001251 .get_host_speed = qla2x00_get_host_speed,
1252 .show_host_speed = 1,
andrew.vasquez@qlogic.com8d067622006-01-31 16:04:56 -08001253 .get_host_port_type = qla2x00_get_host_port_type,
1254 .show_host_port_type = 1,
Andrew Vasquez1620f7c2006-10-02 12:00:44 -07001255 .get_host_symbolic_name = qla2x00_get_host_symbolic_name,
1256 .show_host_symbolic_name = 1,
Andrew Vasqueza740a3f2006-10-02 12:00:45 -07001257 .set_host_system_hostname = qla2x00_set_host_system_hostname,
1258 .show_host_system_hostname = 1,
Andrew Vasquez90991c82006-10-02 12:00:46 -07001259 .get_host_fabric_name = qla2x00_get_host_fabric_name,
1260 .show_host_fabric_name = 1,
Andrew Vasquez7047fcd2006-10-02 12:00:47 -07001261 .get_host_port_state = qla2x00_get_host_port_state,
1262 .show_host_port_state = 1,
8482e112005-04-17 15:04:54 -05001263
bdf79622005-04-17 15:06:53 -05001264 .dd_fcrport_size = sizeof(struct fc_port *),
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07001265 .show_rport_supported_classes = 1,
8482e112005-04-17 15:04:54 -05001266
1267 .get_starget_node_name = qla2x00_get_starget_node_name,
1268 .show_starget_node_name = 1,
1269 .get_starget_port_name = qla2x00_get_starget_port_name,
1270 .show_starget_port_name = 1,
1271 .get_starget_port_id = qla2x00_get_starget_port_id,
1272 .show_starget_port_id = 1,
1273
8482e112005-04-17 15:04:54 -05001274 .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
1275 .show_rport_dev_loss_tmo = 1,
1276
Andrew Vasquez91ca7b02005-10-27 16:03:37 -07001277 .issue_fc_host_lip = qla2x00_issue_lip,
Seokmann Ju5f3a9a22008-07-10 16:55:47 -07001278 .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
1279 .terminate_rport_io = qla2x00_terminate_rport_io,
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08001280 .get_fc_host_stats = qla2x00_get_fc_host_stats,
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001281
1282 .vport_create = qla24xx_vport_create,
1283 .vport_disable = qla24xx_vport_disable,
1284 .vport_delete = qla24xx_vport_delete,
1285};
1286
1287struct fc_function_template qla2xxx_transport_vport_functions = {
1288
1289 .show_host_node_name = 1,
1290 .show_host_port_name = 1,
1291 .show_host_supported_classes = 1,
1292
1293 .get_host_port_id = qla2x00_get_host_port_id,
1294 .show_host_port_id = 1,
1295 .get_host_speed = qla2x00_get_host_speed,
1296 .show_host_speed = 1,
1297 .get_host_port_type = qla2x00_get_host_port_type,
1298 .show_host_port_type = 1,
1299 .get_host_symbolic_name = qla2x00_get_host_symbolic_name,
1300 .show_host_symbolic_name = 1,
1301 .set_host_system_hostname = qla2x00_set_host_system_hostname,
1302 .show_host_system_hostname = 1,
1303 .get_host_fabric_name = qla2x00_get_host_fabric_name,
1304 .show_host_fabric_name = 1,
1305 .get_host_port_state = qla2x00_get_host_port_state,
1306 .show_host_port_state = 1,
1307
1308 .dd_fcrport_size = sizeof(struct fc_port *),
1309 .show_rport_supported_classes = 1,
1310
1311 .get_starget_node_name = qla2x00_get_starget_node_name,
1312 .show_starget_node_name = 1,
1313 .get_starget_port_name = qla2x00_get_starget_port_name,
1314 .show_starget_port_name = 1,
1315 .get_starget_port_id = qla2x00_get_starget_port_id,
1316 .show_starget_port_id = 1,
1317
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001318 .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
1319 .show_rport_dev_loss_tmo = 1,
1320
1321 .issue_fc_host_lip = qla2x00_issue_lip,
Seokmann Ju5f3a9a22008-07-10 16:55:47 -07001322 .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
1323 .terminate_rport_io = qla2x00_terminate_rport_io,
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001324 .get_fc_host_stats = qla2x00_get_fc_host_stats,
8482e112005-04-17 15:04:54 -05001325};
1326
8482e112005-04-17 15:04:54 -05001327void
1328qla2x00_init_host_attr(scsi_qla_host_t *ha)
1329{
Andrew Vasquez2ae2b372008-04-03 13:13:14 -07001330 u32 speed = FC_PORTSPEED_UNKNOWN;
1331
andrew.vasquez@qlogic.comdad9c8c2006-01-13 17:04:49 -08001332 fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name);
1333 fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name);
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07001334 fc_host_supported_classes(ha->host) = FC_COS_CLASS3;
Seokmann Ju4d0ea242007-09-20 14:07:43 -07001335 fc_host_max_npiv_vports(ha->host) = ha->max_npiv_vports;;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001336 fc_host_npiv_vports_inuse(ha->host) = ha->cur_vport_count;
Andrew Vasquez2ae2b372008-04-03 13:13:14 -07001337
1338 if (IS_QLA25XX(ha))
1339 speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT |
1340 FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07001341 else if (IS_QLA24XX_TYPE(ha))
Andrew Vasquez2ae2b372008-04-03 13:13:14 -07001342 speed = FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
1343 FC_PORTSPEED_1GBIT;
1344 else if (IS_QLA23XX(ha))
1345 speed = FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
1346 else
1347 speed = FC_PORTSPEED_1GBIT;
1348 fc_host_supported_speeds(ha->host) = speed;
8482e112005-04-17 15:04:54 -05001349}