blob: 1f1a7c0e88e72a1dfe8fb30c3622b7d90561a2c8 [file] [log] [blame]
8482e1182005-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
8482e1182005-04-17 15:04:54 -05004 *
Andrew Vasquezfa90c542005-10-27 11:10:08 -07005 * See LICENSE.qla2xxx for copyright and licensing details.
8482e1182005-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>
FUJITA Tomonori00eabe72008-07-28 11:59:20 +090011#include <linux/delay.h>
8482e1182005-04-17 15:04:54 -050012
Adrian Bunka824ebb2008-01-17 09:02:15 -080013static int qla24xx_vport_disable(struct fc_vport *, bool);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -070014
8482e1182005-04-17 15:04:54 -050015/* SYSFS attributes --------------------------------------------------------- */
16
17static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +080018qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
19 struct bin_attribute *bin_attr,
20 char *buf, loff_t off, size_t count)
8482e1182005-04-17 15:04:54 -050021{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080022 struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
8482e1182005-04-17 15:04:54 -050023 struct device, kobj)));
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080024 struct qla_hw_data *ha = vha->hw;
8482e1182005-04-17 15:04:54 -050025
26 if (ha->fw_dump_reading == 0)
27 return 0;
8482e1182005-04-17 15:04:54 -050028
Akinobu Mitab3dc9082008-07-24 08:31:47 -070029 return memory_read_from_buffer(buf, count, &off, ha->fw_dump,
30 ha->fw_dump_len);
8482e1182005-04-17 15:04:54 -050031}
32
33static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +080034qla2x00_sysfs_write_fw_dump(struct kobject *kobj,
35 struct bin_attribute *bin_attr,
36 char *buf, loff_t off, size_t count)
8482e1182005-04-17 15:04:54 -050037{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080038 struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
8482e1182005-04-17 15:04:54 -050039 struct device, kobj)));
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080040 struct qla_hw_data *ha = vha->hw;
8482e1182005-04-17 15:04:54 -050041 int reading;
8482e1182005-04-17 15:04:54 -050042
43 if (off != 0)
44 return (0);
45
46 reading = simple_strtol(buf, NULL, 10);
47 switch (reading) {
48 case 0:
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070049 if (!ha->fw_dump_reading)
50 break;
8482e1182005-04-17 15:04:54 -050051
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070052 qla_printk(KERN_INFO, ha,
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080053 "Firmware dump cleared on (%ld).\n", vha->host_no);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070054
55 ha->fw_dump_reading = 0;
56 ha->fw_dumped = 0;
8482e1182005-04-17 15:04:54 -050057 break;
58 case 1:
Andrew Vasquezd4e3e042006-05-17 15:09:50 -070059 if (ha->fw_dumped && !ha->fw_dump_reading) {
8482e1182005-04-17 15:04:54 -050060 ha->fw_dump_reading = 1;
61
8482e1182005-04-17 15:04:54 -050062 qla_printk(KERN_INFO, ha,
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070063 "Raw firmware dump ready for read on (%ld).\n",
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080064 vha->host_no);
8482e1182005-04-17 15:04:54 -050065 }
66 break;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070067 case 2:
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080068 qla2x00_alloc_fw_dump(vha);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070069 break;
Andrew Vasquez68af0812008-05-12 22:21:13 -070070 case 3:
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080071 qla2x00_system_error(vha);
Andrew Vasquez68af0812008-05-12 22:21:13 -070072 break;
8482e1182005-04-17 15:04:54 -050073 }
74 return (count);
75}
76
77static struct bin_attribute sysfs_fw_dump_attr = {
78 .attr = {
79 .name = "fw_dump",
80 .mode = S_IRUSR | S_IWUSR,
8482e1182005-04-17 15:04:54 -050081 },
82 .size = 0,
83 .read = qla2x00_sysfs_read_fw_dump,
84 .write = qla2x00_sysfs_write_fw_dump,
85};
86
87static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +080088qla2x00_sysfs_read_nvram(struct kobject *kobj,
89 struct bin_attribute *bin_attr,
90 char *buf, loff_t off, size_t count)
8482e1182005-04-17 15:04:54 -050091{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080092 struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
8482e1182005-04-17 15:04:54 -050093 struct device, kobj)));
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080094 struct qla_hw_data *ha = vha->hw;
8482e1182005-04-17 15:04:54 -050095
Akinobu Mitab3dc9082008-07-24 08:31:47 -070096 if (!capable(CAP_SYS_ADMIN))
8482e1182005-04-17 15:04:54 -050097 return 0;
98
Seokmann Ju281afe12007-07-26 13:43:34 -070099 /* Read NVRAM data from cache. */
Akinobu Mitab3dc9082008-07-24 08:31:47 -0700100 return memory_read_from_buffer(buf, count, &off, ha->nvram,
101 ha->nvram_size);
8482e1182005-04-17 15:04:54 -0500102}
103
104static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +0800105qla2x00_sysfs_write_nvram(struct kobject *kobj,
106 struct bin_attribute *bin_attr,
107 char *buf, loff_t off, size_t count)
8482e1182005-04-17 15:04:54 -0500108{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800109 struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
8482e1182005-04-17 15:04:54 -0500110 struct device, kobj)));
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800111 struct qla_hw_data *ha = vha->hw;
8482e1182005-04-17 15:04:54 -0500112 uint16_t cnt;
8482e1182005-04-17 15:04:54 -0500113
Andrew Vasquez459c5372005-07-06 10:31:07 -0700114 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
8482e1182005-04-17 15:04:54 -0500115 return 0;
116
117 /* Checksum NVRAM. */
Andrew Vasqueze4289242007-07-19 15:05:56 -0700118 if (IS_FWI2_CAPABLE(ha)) {
Andrew Vasquez459c5372005-07-06 10:31:07 -0700119 uint32_t *iter;
120 uint32_t chksum;
121
122 iter = (uint32_t *)buf;
123 chksum = 0;
124 for (cnt = 0; cnt < ((count >> 2) - 1); cnt++)
125 chksum += le32_to_cpu(*iter++);
126 chksum = ~chksum + 1;
127 *iter = cpu_to_le32(chksum);
128 } else {
129 uint8_t *iter;
130 uint8_t chksum;
131
132 iter = (uint8_t *)buf;
133 chksum = 0;
134 for (cnt = 0; cnt < count - 1; cnt++)
135 chksum += *iter++;
136 chksum = ~chksum + 1;
137 *iter = chksum;
138 }
8482e1182005-04-17 15:04:54 -0500139
Lalit Chandivade2533cf62009-03-24 09:08:07 -0700140 if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
141 qla_printk(KERN_WARNING, ha,
142 "HBA not online, failing NVRAM update.\n");
143 return -EAGAIN;
144 }
145
8482e1182005-04-17 15:04:54 -0500146 /* Write NVRAM. */
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800147 ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->nvram_base, count);
148 ha->isp_ops->read_nvram(vha, (uint8_t *)ha->nvram, ha->nvram_base,
Seokmann Ju281afe12007-07-26 13:43:34 -0700149 count);
8482e1182005-04-17 15:04:54 -0500150
Lalit Chandivade2533cf62009-03-24 09:08:07 -0700151 /* NVRAM settings take effect immediately. */
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800152 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Lalit Chandivade2533cf62009-03-24 09:08:07 -0700153 qla2xxx_wake_dpc(vha);
154 qla2x00_wait_for_chip_reset(vha);
Andrew Vasquez26b8d3482007-01-29 10:22:28 -0800155
8482e1182005-04-17 15:04:54 -0500156 return (count);
157}
158
159static struct bin_attribute sysfs_nvram_attr = {
160 .attr = {
161 .name = "nvram",
162 .mode = S_IRUSR | S_IWUSR,
8482e1182005-04-17 15:04:54 -0500163 },
andrew.vasquez@qlogic.com1b3f6362006-01-31 16:05:12 -0800164 .size = 512,
8482e1182005-04-17 15:04:54 -0500165 .read = qla2x00_sysfs_read_nvram,
166 .write = qla2x00_sysfs_write_nvram,
167};
168
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800169static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +0800170qla2x00_sysfs_read_optrom(struct kobject *kobj,
171 struct bin_attribute *bin_attr,
172 char *buf, loff_t off, size_t count)
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800173{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800174 struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800175 struct device, kobj)));
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800176 struct qla_hw_data *ha = vha->hw;
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800177
178 if (ha->optrom_state != QLA_SREADING)
179 return 0;
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800180
Akinobu Mitab3dc9082008-07-24 08:31:47 -0700181 return memory_read_from_buffer(buf, count, &off, ha->optrom_buffer,
182 ha->optrom_region_size);
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800183}
184
185static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +0800186qla2x00_sysfs_write_optrom(struct kobject *kobj,
187 struct bin_attribute *bin_attr,
188 char *buf, loff_t off, size_t count)
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800189{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800190 struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800191 struct device, kobj)));
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800192 struct qla_hw_data *ha = vha->hw;
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800193
194 if (ha->optrom_state != QLA_SWRITING)
195 return -EINVAL;
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700196 if (off > ha->optrom_region_size)
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800197 return -ERANGE;
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700198 if (off + count > ha->optrom_region_size)
199 count = ha->optrom_region_size - off;
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800200
201 memcpy(&ha->optrom_buffer[off], buf, count);
202
203 return count;
204}
205
206static struct bin_attribute sysfs_optrom_attr = {
207 .attr = {
208 .name = "optrom",
209 .mode = S_IRUSR | S_IWUSR,
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800210 },
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700211 .size = 0,
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800212 .read = qla2x00_sysfs_read_optrom,
213 .write = qla2x00_sysfs_write_optrom,
214};
215
216static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +0800217qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
218 struct bin_attribute *bin_attr,
219 char *buf, loff_t off, size_t count)
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800220{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800221 struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800222 struct device, kobj)));
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800223 struct qla_hw_data *ha = vha->hw;
224
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 ha->optrom_region_start = start;
257 ha->optrom_region_size = start + size > ha->optrom_size ?
258 ha->optrom_size - start : size;
259
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800260 ha->optrom_state = QLA_SREADING;
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700261 ha->optrom_buffer = vmalloc(ha->optrom_region_size);
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800262 if (ha->optrom_buffer == NULL) {
263 qla_printk(KERN_WARNING, ha,
264 "Unable to allocate memory for optrom retrieval "
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700265 "(%x).\n", ha->optrom_region_size);
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800266
267 ha->optrom_state = QLA_SWAITING;
268 return count;
269 }
270
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700271 DEBUG2(qla_printk(KERN_INFO, ha,
272 "Reading flash region -- 0x%x/0x%x.\n",
273 ha->optrom_region_start, ha->optrom_region_size));
274
275 memset(ha->optrom_buffer, 0, ha->optrom_region_size);
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800276 ha->isp_ops->read_optrom(vha, ha->optrom_buffer,
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700277 ha->optrom_region_start, ha->optrom_region_size);
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800278 break;
279 case 2:
280 if (ha->optrom_state != QLA_SWAITING)
281 break;
282
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700283 /*
284 * We need to be more restrictive on which FLASH regions are
285 * allowed to be updated via user-space. Regions accessible
286 * via this method include:
287 *
288 * ISP21xx/ISP22xx/ISP23xx type boards:
289 *
290 * 0x000000 -> 0x020000 -- Boot code.
291 *
292 * ISP2322/ISP24xx type boards:
293 *
294 * 0x000000 -> 0x07ffff -- Boot code.
295 * 0x080000 -> 0x0fffff -- Firmware.
296 *
297 * ISP25xx type boards:
298 *
299 * 0x000000 -> 0x07ffff -- Boot code.
300 * 0x080000 -> 0x0fffff -- Firmware.
301 * 0x120000 -> 0x12ffff -- VPD and HBA parameters.
302 */
303 valid = 0;
304 if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
305 valid = 1;
Andrew Vasquezc00d8992008-09-11 21:22:49 -0700306 else if (start == (ha->flt_region_boot * 4) ||
307 start == (ha->flt_region_fw * 4))
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700308 valid = 1;
Andrew Vasquez6431c5d2009-03-05 11:07:00 -0800309 else if (IS_QLA25XX(ha) || IS_QLA81XX(ha))
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700310 valid = 1;
311 if (!valid) {
312 qla_printk(KERN_WARNING, ha,
313 "Invalid start region 0x%x/0x%x.\n", start, size);
314 return -EINVAL;
315 }
316
317 ha->optrom_region_start = start;
318 ha->optrom_region_size = start + size > ha->optrom_size ?
319 ha->optrom_size - start : size;
320
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800321 ha->optrom_state = QLA_SWRITING;
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700322 ha->optrom_buffer = vmalloc(ha->optrom_region_size);
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800323 if (ha->optrom_buffer == NULL) {
324 qla_printk(KERN_WARNING, ha,
325 "Unable to allocate memory for optrom update "
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700326 "(%x).\n", ha->optrom_region_size);
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800327
328 ha->optrom_state = QLA_SWAITING;
329 return count;
330 }
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700331
332 DEBUG2(qla_printk(KERN_INFO, ha,
333 "Staging flash region write -- 0x%x/0x%x.\n",
334 ha->optrom_region_start, ha->optrom_region_size));
335
336 memset(ha->optrom_buffer, 0, ha->optrom_region_size);
andrew.vasquez@qlogic.com854165f2006-01-31 16:05:17 -0800337 break;
338 case 3:
339 if (ha->optrom_state != QLA_SWRITING)
340 break;
341
Lalit Chandivade2533cf62009-03-24 09:08:07 -0700342 if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
343 qla_printk(KERN_WARNING, ha,
344 "HBA not online, failing flash update.\n");
345 return -EAGAIN;
346 }
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
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800352 ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
Joe Carnucciob7cc1762007-09-20 14:07:35 -0700353 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{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800375 struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800376 struct device, kobj)));
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800377 struct qla_hw_data *ha = vha->hw;
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800378
Akinobu Mitab3dc9082008-07-24 08:31:47 -0700379 if (!capable(CAP_SYS_ADMIN))
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800380 return 0;
381
Seokmann Ju281afe12007-07-26 13:43:34 -0700382 /* Read NVRAM data from cache. */
Akinobu Mitab3dc9082008-07-24 08:31:47 -0700383 return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size);
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800384}
385
386static ssize_t
Zhang Rui91a69022007-06-09 13:57:22 +0800387qla2x00_sysfs_write_vpd(struct kobject *kobj,
388 struct bin_attribute *bin_attr,
389 char *buf, loff_t off, size_t count)
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800390{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800391 struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800392 struct device, kobj)));
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800393 struct qla_hw_data *ha = vha->hw;
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800394
395 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size)
396 return 0;
397
Lalit Chandivade2533cf62009-03-24 09:08:07 -0700398 if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
399 qla_printk(KERN_WARNING, ha,
400 "HBA not online, failing VPD update.\n");
401 return -EAGAIN;
402 }
403
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -0800404 /* Write NVRAM. */
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800405 ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->vpd_base, count);
406 ha->isp_ops->read_nvram(vha, (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{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800426 struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
Andrew Vasquez88729e52006-06-23 16:10:50 -0700427 struct device, kobj)));
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800428 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez88729e52006-06-23 16:10:50 -0700429 uint16_t iter, addr, offset;
430 int rval;
431
432 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != SFP_DEV_SIZE * 2)
433 return 0;
434
Andrew Vasqueze8711082008-01-31 12:33:48 -0800435 if (ha->sfp_data)
436 goto do_read;
437
438 ha->sfp_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
439 &ha->sfp_data_dma);
440 if (!ha->sfp_data) {
441 qla_printk(KERN_WARNING, ha,
442 "Unable to allocate memory for SFP read-data.\n");
443 return 0;
444 }
445
446do_read:
447 memset(ha->sfp_data, 0, SFP_BLOCK_SIZE);
Andrew Vasquez88729e52006-06-23 16:10:50 -0700448 addr = 0xa0;
449 for (iter = 0, offset = 0; iter < (SFP_DEV_SIZE * 2) / SFP_BLOCK_SIZE;
450 iter++, offset += SFP_BLOCK_SIZE) {
451 if (iter == 4) {
452 /* Skip to next device address. */
453 addr = 0xa2;
454 offset = 0;
455 }
456
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800457 rval = qla2x00_read_sfp(vha, ha->sfp_data_dma, addr, offset,
Andrew Vasquez88729e52006-06-23 16:10:50 -0700458 SFP_BLOCK_SIZE);
459 if (rval != QLA_SUCCESS) {
460 qla_printk(KERN_WARNING, ha,
461 "Unable to read SFP data (%x/%x/%x).\n", rval,
462 addr, offset);
463 count = 0;
464 break;
465 }
466 memcpy(buf, ha->sfp_data, SFP_BLOCK_SIZE);
467 buf += SFP_BLOCK_SIZE;
468 }
469
470 return count;
471}
472
473static struct bin_attribute sysfs_sfp_attr = {
474 .attr = {
475 .name = "sfp",
476 .mode = S_IRUSR | S_IWUSR,
Andrew Vasquez88729e52006-06-23 16:10:50 -0700477 },
478 .size = SFP_DEV_SIZE * 2,
479 .read = qla2x00_sysfs_read_sfp,
480};
481
Lalit Chandivade6e181be2009-03-26 08:49:17 -0700482static ssize_t
483qla2x00_sysfs_write_reset(struct kobject *kobj,
484 struct bin_attribute *bin_attr,
485 char *buf, loff_t off, size_t count)
486{
487 struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
488 struct device, kobj)));
489 struct qla_hw_data *ha = vha->hw;
490 int type;
491
492 if (off != 0)
493 return 0;
494
495 type = simple_strtol(buf, NULL, 10);
496 switch (type) {
497 case 0x2025c:
498 qla_printk(KERN_INFO, ha,
499 "Issuing ISP reset on (%ld).\n", vha->host_no);
500
501 scsi_block_requests(vha->host);
502 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
503 qla2xxx_wake_dpc(vha);
504 qla2x00_wait_for_chip_reset(vha);
505 scsi_unblock_requests(vha->host);
506 break;
507 case 0x2025d:
508 if (!IS_QLA81XX(ha))
509 break;
510
511 qla_printk(KERN_INFO, ha,
512 "Issuing MPI reset on (%ld).\n", vha->host_no);
513
514 /* Make sure FC side is not in reset */
515 qla2x00_wait_for_hba_online(vha);
516
517 /* Issue MPI reset */
518 scsi_block_requests(vha->host);
519 if (qla81xx_restart_mpi_firmware(vha) != QLA_SUCCESS)
520 qla_printk(KERN_WARNING, ha,
521 "MPI reset failed on (%ld).\n", vha->host_no);
522 scsi_unblock_requests(vha->host);
523 break;
524 }
525 return count;
526}
527
528static struct bin_attribute sysfs_reset_attr = {
529 .attr = {
530 .name = "reset",
531 .mode = S_IWUSR,
532 },
533 .size = 0,
534 .write = qla2x00_sysfs_write_reset,
535};
536
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700537static struct sysfs_entry {
538 char *name;
539 struct bin_attribute *attr;
540 int is4GBp_only;
541} bin_file_entries[] = {
542 { "fw_dump", &sysfs_fw_dump_attr, },
543 { "nvram", &sysfs_nvram_attr, },
544 { "optrom", &sysfs_optrom_attr, },
545 { "optrom_ctl", &sysfs_optrom_ctl_attr, },
546 { "vpd", &sysfs_vpd_attr, 1 },
547 { "sfp", &sysfs_sfp_attr, 1 },
Lalit Chandivade6e181be2009-03-26 08:49:17 -0700548 { "reset", &sysfs_reset_attr, },
Randy Dunlap46ddab72006-11-27 09:35:42 -0800549 { NULL },
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700550};
551
8482e1182005-04-17 15:04:54 -0500552void
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800553qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha)
8482e1182005-04-17 15:04:54 -0500554{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800555 struct Scsi_Host *host = vha->host;
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700556 struct sysfs_entry *iter;
557 int ret;
8482e1182005-04-17 15:04:54 -0500558
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700559 for (iter = bin_file_entries; iter->name; iter++) {
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800560 if (iter->is4GBp_only && !IS_FWI2_CAPABLE(vha->hw))
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700561 continue;
562
563 ret = sysfs_create_bin_file(&host->shost_gendev.kobj,
564 iter->attr);
565 if (ret)
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800566 qla_printk(KERN_INFO, vha->hw,
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700567 "Unable to create sysfs %s binary attribute "
568 "(%d).\n", iter->name, ret);
Andrew Vasquez7914d002006-06-23 16:10:55 -0700569 }
8482e1182005-04-17 15:04:54 -0500570}
571
572void
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800573qla2x00_free_sysfs_attr(scsi_qla_host_t *vha)
8482e1182005-04-17 15:04:54 -0500574{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800575 struct Scsi_Host *host = vha->host;
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700576 struct sysfs_entry *iter;
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800577 struct qla_hw_data *ha = vha->hw;
8482e1182005-04-17 15:04:54 -0500578
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700579 for (iter = bin_file_entries; iter->name; iter++) {
Andrew Vasqueze4289242007-07-19 15:05:56 -0700580 if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha))
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700581 continue;
582
Andrew Vasquez7914d002006-06-23 16:10:55 -0700583 sysfs_remove_bin_file(&host->shost_gendev.kobj,
Andrew Vasquezf1663ad2006-10-13 09:33:37 -0700584 iter->attr);
Andrew Vasquez7914d002006-06-23 16:10:55 -0700585 }
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800586
587 if (ha->beacon_blink_led == 1)
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800588 ha->isp_ops->beacon_off(vha);
8482e1182005-04-17 15:04:54 -0500589}
590
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700591/* Scsi_Host attributes. */
592
593static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100594qla2x00_drvr_version_show(struct device *dev,
595 struct device_attribute *attr, char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700596{
597 return snprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str);
598}
599
600static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100601qla2x00_fw_version_show(struct device *dev,
602 struct device_attribute *attr, char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700603{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800604 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
605 struct qla_hw_data *ha = vha->hw;
606 char fw_str[128];
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700607
608 return snprintf(buf, PAGE_SIZE, "%s\n",
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800609 ha->isp_ops->fw_version_str(vha, fw_str));
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700610}
611
612static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100613qla2x00_serial_num_show(struct device *dev, struct device_attribute *attr,
614 char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700615{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800616 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
617 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700618 uint32_t sn;
619
Joe Carnuccio1ee27142008-07-10 16:55:53 -0700620 if (IS_FWI2_CAPABLE(ha)) {
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800621 qla2xxx_get_vpd_field(vha, "SN", buf, PAGE_SIZE);
Joe Carnuccio1ee27142008-07-10 16:55:53 -0700622 return snprintf(buf, PAGE_SIZE, "%s\n", buf);
623 }
Andrew Vasquez8b7afc22007-10-19 15:59:19 -0700624
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700625 sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
626 return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000,
627 sn % 100000);
628}
629
630static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100631qla2x00_isp_name_show(struct device *dev, struct device_attribute *attr,
632 char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700633{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800634 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
635 return snprintf(buf, PAGE_SIZE, "ISP%04X\n", vha->hw->pdev->device);
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700636}
637
638static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100639qla2x00_isp_id_show(struct device *dev, struct device_attribute *attr,
640 char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700641{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800642 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
643 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700644 return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n",
645 ha->product_id[0], ha->product_id[1], ha->product_id[2],
646 ha->product_id[3]);
647}
648
649static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100650qla2x00_model_name_show(struct device *dev, struct device_attribute *attr,
651 char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700652{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800653 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
654 return snprintf(buf, PAGE_SIZE, "%s\n", vha->hw->model_number);
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700655}
656
657static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100658qla2x00_model_desc_show(struct device *dev, struct device_attribute *attr,
659 char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700660{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800661 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700662 return snprintf(buf, PAGE_SIZE, "%s\n",
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800663 vha->hw->model_desc ? vha->hw->model_desc : "");
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700664}
665
666static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100667qla2x00_pci_info_show(struct device *dev, struct device_attribute *attr,
668 char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700669{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800670 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700671 char pci_info[30];
672
673 return snprintf(buf, PAGE_SIZE, "%s\n",
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800674 vha->hw->isp_ops->pci_info_str(vha, pci_info));
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700675}
676
677static ssize_t
Hannes Reineckebbd1ae42008-03-18 14:32:28 +0100678qla2x00_link_state_show(struct device *dev, struct device_attribute *attr,
679 char *buf)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700680{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800681 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
682 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700683 int len = 0;
684
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800685 if (atomic_read(&vha->loop_state) == LOOP_DOWN ||
686 atomic_read(&vha->loop_state) == LOOP_DEAD)
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700687 len = snprintf(buf, PAGE_SIZE, "Link Down\n");
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800688 else if (atomic_read(&vha->loop_state) != LOOP_READY ||
689 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
690 test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700691 len = snprintf(buf, PAGE_SIZE, "Unknown Link State\n");
692 else {
693 len = snprintf(buf, PAGE_SIZE, "Link Up - ");
694
695 switch (ha->current_topology) {
696 case ISP_CFG_NL:
697 len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n");
698 break;
699 case ISP_CFG_FL:
700 len += snprintf(buf + len, PAGE_SIZE-len, "FL_Port\n");
701 break;
702 case ISP_CFG_N:
703 len += snprintf(buf + len, PAGE_SIZE-len,
704 "N_Port to N_Port\n");
705 break;
706 case ISP_CFG_F:
707 len += snprintf(buf + len, PAGE_SIZE-len, "F_Port\n");
708 break;
709 default:
710 len += snprintf(buf + len, PAGE_SIZE-len, "Loop\n");
711 break;
712 }
713 }
714 return len;
715}
716
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700717static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100718qla2x00_zio_show(struct device *dev, struct device_attribute *attr,
719 char *buf)
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700720{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800721 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700722 int len = 0;
723
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800724 switch (vha->hw->zio_mode) {
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700725 case QLA_ZIO_MODE_6:
726 len += snprintf(buf + len, PAGE_SIZE-len, "Mode 6\n");
727 break;
728 case QLA_ZIO_DISABLED:
729 len += snprintf(buf + len, PAGE_SIZE-len, "Disabled\n");
730 break;
731 }
732 return len;
733}
734
735static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100736qla2x00_zio_store(struct device *dev, struct device_attribute *attr,
737 const char *buf, size_t count)
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700738{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800739 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
740 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700741 int val = 0;
742 uint16_t zio_mode;
743
andrew.vasquez@qlogic.com4a59f712006-03-09 14:27:39 -0800744 if (!IS_ZIO_SUPPORTED(ha))
745 return -ENOTSUPP;
746
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700747 if (sscanf(buf, "%d", &val) != 1)
748 return -EINVAL;
749
andrew.vasquez@qlogic.com4a59f712006-03-09 14:27:39 -0800750 if (val)
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700751 zio_mode = QLA_ZIO_MODE_6;
andrew.vasquez@qlogic.com4a59f712006-03-09 14:27:39 -0800752 else
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700753 zio_mode = QLA_ZIO_DISABLED;
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700754
755 /* Update per-hba values and queue a reset. */
756 if (zio_mode != QLA_ZIO_DISABLED || ha->zio_mode != QLA_ZIO_DISABLED) {
757 ha->zio_mode = zio_mode;
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800758 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700759 }
760 return strlen(buf);
761}
762
763static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100764qla2x00_zio_timer_show(struct device *dev, struct device_attribute *attr,
765 char *buf)
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700766{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800767 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700768
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800769 return snprintf(buf, PAGE_SIZE, "%d us\n", vha->hw->zio_timer * 100);
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700770}
771
772static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100773qla2x00_zio_timer_store(struct device *dev, struct device_attribute *attr,
774 const char *buf, size_t count)
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700775{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800776 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700777 int val = 0;
778 uint16_t zio_timer;
779
780 if (sscanf(buf, "%d", &val) != 1)
781 return -EINVAL;
782 if (val > 25500 || val < 100)
783 return -ERANGE;
784
785 zio_timer = (uint16_t)(val / 100);
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800786 vha->hw->zio_timer = zio_timer;
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -0700787
788 return strlen(buf);
789}
790
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800791static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100792qla2x00_beacon_show(struct device *dev, struct device_attribute *attr,
793 char *buf)
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800794{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800795 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800796 int len = 0;
797
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800798 if (vha->hw->beacon_blink_led)
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800799 len += snprintf(buf + len, PAGE_SIZE-len, "Enabled\n");
800 else
801 len += snprintf(buf + len, PAGE_SIZE-len, "Disabled\n");
802 return len;
803}
804
805static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100806qla2x00_beacon_store(struct device *dev, struct device_attribute *attr,
807 const char *buf, size_t count)
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800808{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800809 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
810 struct qla_hw_data *ha = vha->hw;
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800811 int val = 0;
812 int rval;
813
814 if (IS_QLA2100(ha) || IS_QLA2200(ha))
815 return -EPERM;
816
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800817 if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) {
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800818 qla_printk(KERN_WARNING, ha,
819 "Abort ISP active -- ignoring beacon request.\n");
820 return -EBUSY;
821 }
822
823 if (sscanf(buf, "%d", &val) != 1)
824 return -EINVAL;
825
826 if (val)
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800827 rval = ha->isp_ops->beacon_on(vha);
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800828 else
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800829 rval = ha->isp_ops->beacon_off(vha);
andrew.vasquez@qlogic.comf6df1442006-01-31 16:05:07 -0800830
831 if (rval != QLA_SUCCESS)
832 count = 0;
833
834 return count;
835}
836
Andrew Vasquez30c47662007-01-29 10:22:21 -0800837static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100838qla2x00_optrom_bios_version_show(struct device *dev,
839 struct device_attribute *attr, char *buf)
Andrew Vasquez30c47662007-01-29 10:22:21 -0800840{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800841 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
842 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez30c47662007-01-29 10:22:21 -0800843 return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1],
844 ha->bios_revision[0]);
845}
846
847static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100848qla2x00_optrom_efi_version_show(struct device *dev,
849 struct device_attribute *attr, char *buf)
Andrew Vasquez30c47662007-01-29 10:22:21 -0800850{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800851 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
852 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez30c47662007-01-29 10:22:21 -0800853 return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1],
854 ha->efi_revision[0]);
855}
856
857static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100858qla2x00_optrom_fcode_version_show(struct device *dev,
859 struct device_attribute *attr, char *buf)
Andrew Vasquez30c47662007-01-29 10:22:21 -0800860{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800861 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
862 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez30c47662007-01-29 10:22:21 -0800863 return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1],
864 ha->fcode_revision[0]);
865}
866
867static ssize_t
Tony Jonesee959b02008-02-22 00:13:36 +0100868qla2x00_optrom_fw_version_show(struct device *dev,
869 struct device_attribute *attr, char *buf)
Andrew Vasquez30c47662007-01-29 10:22:21 -0800870{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800871 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
872 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez30c47662007-01-29 10:22:21 -0800873 return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n",
874 ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2],
875 ha->fw_revision[3]);
876}
877
Harish Zunjarraoe5f5f6f2008-07-10 16:55:49 -0700878static ssize_t
879qla2x00_total_isp_aborts_show(struct device *dev,
880 struct device_attribute *attr, char *buf)
881{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800882 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
883 struct qla_hw_data *ha = vha->hw;
Harish Zunjarraoe5f5f6f2008-07-10 16:55:49 -0700884 return snprintf(buf, PAGE_SIZE, "%d\n",
885 ha->qla_stats.total_isp_aborts);
886}
887
Andrew Vasquez3a03eb72009-01-05 11:18:11 -0800888static ssize_t
889qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr,
890 char *buf)
891{
892 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
893 struct qla_hw_data *ha = vha->hw;
894
895 if (!IS_QLA81XX(ha))
896 return snprintf(buf, PAGE_SIZE, "\n");
897
Andrew Vasquez55a96152009-03-24 09:08:03 -0700898 return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n",
Andrew Vasquez3a03eb72009-01-05 11:18:11 -0800899 ha->mpi_version[0], ha->mpi_version[1], ha->mpi_version[2],
Andrew Vasquez55a96152009-03-24 09:08:03 -0700900 ha->mpi_capabilities);
901}
902
903static ssize_t
904qla2x00_phy_version_show(struct device *dev, struct device_attribute *attr,
905 char *buf)
906{
907 scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
908 struct qla_hw_data *ha = vha->hw;
909
910 if (!IS_QLA81XX(ha))
911 return snprintf(buf, PAGE_SIZE, "\n");
912
913 return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n",
914 ha->phy_version[0], ha->phy_version[1], ha->phy_version[2]);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -0800915}
916
Tony Jonesee959b02008-02-22 00:13:36 +0100917static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
918static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
919static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
920static DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL);
921static DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL);
922static DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL);
923static DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL);
924static DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL);
Hannes Reineckebbd1ae42008-03-18 14:32:28 +0100925static DEVICE_ATTR(link_state, S_IRUGO, qla2x00_link_state_show, NULL);
Tony Jonesee959b02008-02-22 00:13:36 +0100926static DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show, qla2x00_zio_store);
927static DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
928 qla2x00_zio_timer_store);
929static DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show,
930 qla2x00_beacon_store);
931static DEVICE_ATTR(optrom_bios_version, S_IRUGO,
932 qla2x00_optrom_bios_version_show, NULL);
933static DEVICE_ATTR(optrom_efi_version, S_IRUGO,
934 qla2x00_optrom_efi_version_show, NULL);
935static DEVICE_ATTR(optrom_fcode_version, S_IRUGO,
936 qla2x00_optrom_fcode_version_show, NULL);
937static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show,
938 NULL);
Harish Zunjarraoe5f5f6f2008-07-10 16:55:49 -0700939static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show,
940 NULL);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -0800941static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL);
Andrew Vasquez55a96152009-03-24 09:08:03 -0700942static DEVICE_ATTR(phy_version, S_IRUGO, qla2x00_phy_version_show, NULL);
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700943
Tony Jonesee959b02008-02-22 00:13:36 +0100944struct device_attribute *qla2x00_host_attrs[] = {
945 &dev_attr_driver_version,
946 &dev_attr_fw_version,
947 &dev_attr_serial_num,
948 &dev_attr_isp_name,
949 &dev_attr_isp_id,
950 &dev_attr_model_name,
951 &dev_attr_model_desc,
952 &dev_attr_pci_info,
Hannes Reineckebbd1ae42008-03-18 14:32:28 +0100953 &dev_attr_link_state,
Tony Jonesee959b02008-02-22 00:13:36 +0100954 &dev_attr_zio,
955 &dev_attr_zio_timer,
956 &dev_attr_beacon,
957 &dev_attr_optrom_bios_version,
958 &dev_attr_optrom_efi_version,
959 &dev_attr_optrom_fcode_version,
960 &dev_attr_optrom_fw_version,
Harish Zunjarraoe5f5f6f2008-07-10 16:55:49 -0700961 &dev_attr_total_isp_aborts,
Andrew Vasquez3a03eb72009-01-05 11:18:11 -0800962 &dev_attr_mpi_version,
Andrew Vasquez55a96152009-03-24 09:08:03 -0700963 &dev_attr_phy_version,
Andrew Vasquezafb046e2005-08-26 19:09:40 -0700964 NULL,
965};
966
8482e1182005-04-17 15:04:54 -0500967/* Host attributes. */
968
969static void
970qla2x00_get_host_port_id(struct Scsi_Host *shost)
971{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800972 scsi_qla_host_t *vha = shost_priv(shost);
8482e1182005-04-17 15:04:54 -0500973
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800974 fc_host_port_id(shost) = vha->d_id.b.domain << 16 |
975 vha->d_id.b.area << 8 | vha->d_id.b.al_pa;
8482e1182005-04-17 15:04:54 -0500976}
977
978static void
andrew.vasquez@qlogic.com04414012006-01-31 16:04:51 -0800979qla2x00_get_host_speed(struct Scsi_Host *shost)
980{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800981 struct qla_hw_data *ha = ((struct scsi_qla_host *)
982 (shost_priv(shost)))->hw;
Andrew Vasquez2ae2b372008-04-03 13:13:14 -0700983 u32 speed = FC_PORTSPEED_UNKNOWN;
andrew.vasquez@qlogic.com04414012006-01-31 16:04:51 -0800984
985 switch (ha->link_data_rate) {
Andrew Vasquezd8b45212006-10-02 12:00:43 -0700986 case PORT_SPEED_1GB:
Andrew Vasquez2ae2b372008-04-03 13:13:14 -0700987 speed = FC_PORTSPEED_1GBIT;
andrew.vasquez@qlogic.com04414012006-01-31 16:04:51 -0800988 break;
Andrew Vasquezd8b45212006-10-02 12:00:43 -0700989 case PORT_SPEED_2GB:
Andrew Vasquez2ae2b372008-04-03 13:13:14 -0700990 speed = FC_PORTSPEED_2GBIT;
andrew.vasquez@qlogic.com04414012006-01-31 16:04:51 -0800991 break;
Andrew Vasquezd8b45212006-10-02 12:00:43 -0700992 case PORT_SPEED_4GB:
Andrew Vasquez2ae2b372008-04-03 13:13:14 -0700993 speed = FC_PORTSPEED_4GBIT;
andrew.vasquez@qlogic.com04414012006-01-31 16:04:51 -0800994 break;
Seokmann Juda4541b2008-01-31 12:33:52 -0800995 case PORT_SPEED_8GB:
Andrew Vasquez2ae2b372008-04-03 13:13:14 -0700996 speed = FC_PORTSPEED_8GBIT;
Seokmann Juda4541b2008-01-31 12:33:52 -0800997 break;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -0800998 case PORT_SPEED_10GB:
999 speed = FC_PORTSPEED_10GBIT;
1000 break;
andrew.vasquez@qlogic.com04414012006-01-31 16:04:51 -08001001 }
1002 fc_host_speed(shost) = speed;
1003}
1004
1005static void
andrew.vasquez@qlogic.com8d067622006-01-31 16:04:56 -08001006qla2x00_get_host_port_type(struct Scsi_Host *shost)
1007{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001008 scsi_qla_host_t *vha = shost_priv(shost);
andrew.vasquez@qlogic.com8d067622006-01-31 16:04:56 -08001009 uint32_t port_type = FC_PORTTYPE_UNKNOWN;
1010
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001011 if (vha->vp_idx) {
Shyam Sundar2f2fa132008-05-12 22:21:07 -07001012 fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
1013 return;
1014 }
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001015 switch (vha->hw->current_topology) {
andrew.vasquez@qlogic.com8d067622006-01-31 16:04:56 -08001016 case ISP_CFG_NL:
1017 port_type = FC_PORTTYPE_LPORT;
1018 break;
1019 case ISP_CFG_FL:
1020 port_type = FC_PORTTYPE_NLPORT;
1021 break;
1022 case ISP_CFG_N:
1023 port_type = FC_PORTTYPE_PTP;
1024 break;
1025 case ISP_CFG_F:
1026 port_type = FC_PORTTYPE_NPORT;
1027 break;
1028 }
1029 fc_host_port_type(shost) = port_type;
1030}
1031
1032static void
8482e1182005-04-17 15:04:54 -05001033qla2x00_get_starget_node_name(struct scsi_target *starget)
1034{
1035 struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001036 scsi_qla_host_t *vha = shost_priv(host);
bdf79622005-04-17 15:06:53 -05001037 fc_port_t *fcport;
Andrew Vasquezf8b02a82005-08-31 15:21:20 -07001038 u64 node_name = 0;
8482e1182005-04-17 15:04:54 -05001039
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001040 list_for_each_entry(fcport, &vha->vp_fcports, list) {
Andrew Vasquez5ab5a4d2008-04-03 13:13:16 -07001041 if (fcport->rport &&
1042 starget->id == fcport->rport->scsi_target_id) {
Andrew Vasquezf8b02a82005-08-31 15:21:20 -07001043 node_name = wwn_to_u64(fcport->node_name);
bdf79622005-04-17 15:06:53 -05001044 break;
1045 }
1046 }
1047
Andrew Vasquezf8b02a82005-08-31 15:21:20 -07001048 fc_starget_node_name(starget) = node_name;
8482e1182005-04-17 15:04:54 -05001049}
1050
1051static void
1052qla2x00_get_starget_port_name(struct scsi_target *starget)
1053{
1054 struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001055 scsi_qla_host_t *vha = shost_priv(host);
bdf79622005-04-17 15:06:53 -05001056 fc_port_t *fcport;
Andrew Vasquezf8b02a82005-08-31 15:21:20 -07001057 u64 port_name = 0;
8482e1182005-04-17 15:04:54 -05001058
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001059 list_for_each_entry(fcport, &vha->vp_fcports, list) {
Andrew Vasquez5ab5a4d2008-04-03 13:13:16 -07001060 if (fcport->rport &&
1061 starget->id == fcport->rport->scsi_target_id) {
Andrew Vasquezf8b02a82005-08-31 15:21:20 -07001062 port_name = wwn_to_u64(fcport->port_name);
bdf79622005-04-17 15:06:53 -05001063 break;
1064 }
1065 }
1066
Andrew Vasquezf8b02a82005-08-31 15:21:20 -07001067 fc_starget_port_name(starget) = port_name;
8482e1182005-04-17 15:04:54 -05001068}
1069
1070static void
1071qla2x00_get_starget_port_id(struct scsi_target *starget)
1072{
1073 struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001074 scsi_qla_host_t *vha = shost_priv(host);
bdf79622005-04-17 15:06:53 -05001075 fc_port_t *fcport;
1076 uint32_t port_id = ~0U;
8482e1182005-04-17 15:04:54 -05001077
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001078 list_for_each_entry(fcport, &vha->vp_fcports, list) {
Andrew Vasquez5ab5a4d2008-04-03 13:13:16 -07001079 if (fcport->rport &&
1080 starget->id == fcport->rport->scsi_target_id) {
bdf79622005-04-17 15:06:53 -05001081 port_id = fcport->d_id.b.domain << 16 |
1082 fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
1083 break;
1084 }
1085 }
1086
8482e1182005-04-17 15:04:54 -05001087 fc_starget_port_id(starget) = port_id;
1088}
1089
1090static void
8482e1182005-04-17 15:04:54 -05001091qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
1092{
8482e1182005-04-17 15:04:54 -05001093 if (timeout)
Andrew Vasquez85821c92008-07-10 16:55:48 -07001094 rport->dev_loss_tmo = timeout;
8482e1182005-04-17 15:04:54 -05001095 else
Andrew Vasquez85821c92008-07-10 16:55:48 -07001096 rport->dev_loss_tmo = 1;
8482e1182005-04-17 15:04:54 -05001097}
1098
Seokmann Ju5f3a9a22008-07-10 16:55:47 -07001099static void
1100qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
1101{
1102 struct Scsi_Host *host = rport_to_shost(rport);
1103 fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
1104
Seokmann Ju3c01b4f2009-01-22 09:45:38 -08001105 if (!fcport)
1106 return;
1107
Seokmann Ju5f3a9a22008-07-10 16:55:47 -07001108 qla2x00_abort_fcport_cmds(fcport);
1109
1110 /*
1111 * Transport has effectively 'deleted' the rport, clear
1112 * all local references.
1113 */
1114 spin_lock_irq(host->host_lock);
1115 fcport->rport = NULL;
1116 *((fc_port_t **)rport->dd_data) = NULL;
1117 spin_unlock_irq(host->host_lock);
1118}
1119
1120static void
1121qla2x00_terminate_rport_io(struct fc_rport *rport)
1122{
1123 fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
1124
Seokmann Ju3c01b4f2009-01-22 09:45:38 -08001125 if (!fcport)
1126 return;
1127
Andrew Vasquez6390d1f2008-08-13 21:36:56 -07001128 /*
1129 * At this point all fcport's software-states are cleared. Perform any
1130 * final cleanup of firmware resources (PCBs and XCBs).
1131 */
Andrew Vasquezbe67e652009-03-24 09:08:02 -07001132 if (fcport->loop_id != FC_NO_LOOP_ID)
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001133 fcport->vha->hw->isp_ops->fabric_logout(fcport->vha,
1134 fcport->loop_id, fcport->d_id.b.domain,
1135 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Andrew Vasquez6390d1f2008-08-13 21:36:56 -07001136
Seokmann Ju5f3a9a22008-07-10 16:55:47 -07001137 qla2x00_abort_fcport_cmds(fcport);
Seokmann Ju5f3a9a22008-07-10 16:55:47 -07001138}
1139
Andrew Vasquez91ca7b02005-10-27 16:03:37 -07001140static int
1141qla2x00_issue_lip(struct Scsi_Host *shost)
1142{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001143 scsi_qla_host_t *vha = shost_priv(shost);
Andrew Vasquez91ca7b02005-10-27 16:03:37 -07001144
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001145 qla2x00_loop_reset(vha);
Andrew Vasquez91ca7b02005-10-27 16:03:37 -07001146 return 0;
1147}
1148
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08001149static struct fc_host_statistics *
1150qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
1151{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001152 scsi_qla_host_t *vha = shost_priv(shost);
1153 struct qla_hw_data *ha = vha->hw;
1154 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08001155 int rval;
Andrew Vasquez43ef0582008-01-17 09:02:08 -08001156 struct link_statistics *stats;
1157 dma_addr_t stats_dma;
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08001158 struct fc_host_statistics *pfc_host_stat;
1159
1160 pfc_host_stat = &ha->fc_host_stat;
1161 memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics));
1162
Andrew Vasquez43ef0582008-01-17 09:02:08 -08001163 stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma);
1164 if (stats == NULL) {
1165 DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n",
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001166 __func__, base_vha->host_no));
Andrew Vasquez43ef0582008-01-17 09:02:08 -08001167 goto done;
1168 }
1169 memset(stats, 0, DMA_POOL_SIZE);
1170
1171 rval = QLA_FUNCTION_FAILED;
Andrew Vasqueze4289242007-07-19 15:05:56 -07001172 if (IS_FWI2_CAPABLE(ha)) {
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001173 rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma);
1174 } else if (atomic_read(&base_vha->loop_state) == LOOP_READY &&
1175 !test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) &&
1176 !test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags) &&
Andrew Vasquez178779a2007-01-29 10:22:25 -08001177 !ha->dpc_active) {
1178 /* Must be in a 'READY' state for statistics retrieval. */
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001179 rval = qla2x00_get_link_status(base_vha, base_vha->loop_id,
1180 stats, stats_dma);
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08001181 }
Andrew Vasquez178779a2007-01-29 10:22:25 -08001182
1183 if (rval != QLA_SUCCESS)
Andrew Vasquez43ef0582008-01-17 09:02:08 -08001184 goto done_free;
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08001185
Andrew Vasquez43ef0582008-01-17 09:02:08 -08001186 pfc_host_stat->link_failure_count = stats->link_fail_cnt;
1187 pfc_host_stat->loss_of_sync_count = stats->loss_sync_cnt;
1188 pfc_host_stat->loss_of_signal_count = stats->loss_sig_cnt;
1189 pfc_host_stat->prim_seq_protocol_err_count = stats->prim_seq_err_cnt;
1190 pfc_host_stat->invalid_tx_word_count = stats->inval_xmit_word_cnt;
1191 pfc_host_stat->invalid_crc_count = stats->inval_crc_cnt;
1192 if (IS_FWI2_CAPABLE(ha)) {
Harish Zunjarrao032d8dd2008-07-10 16:55:50 -07001193 pfc_host_stat->lip_count = stats->lip_cnt;
Andrew Vasquez43ef0582008-01-17 09:02:08 -08001194 pfc_host_stat->tx_frames = stats->tx_frames;
1195 pfc_host_stat->rx_frames = stats->rx_frames;
1196 pfc_host_stat->dumped_frames = stats->dumped_frames;
1197 pfc_host_stat->nos_count = stats->nos_rcvd;
1198 }
Harish Zunjarrao49fd4622008-09-11 21:22:47 -07001199 pfc_host_stat->fcp_input_megabytes = ha->qla_stats.input_bytes >> 20;
1200 pfc_host_stat->fcp_output_megabytes = ha->qla_stats.output_bytes >> 20;
Andrew Vasquez43ef0582008-01-17 09:02:08 -08001201
1202done_free:
1203 dma_pool_free(ha->s_dma_pool, stats, stats_dma);
Andrew Vasquez178779a2007-01-29 10:22:25 -08001204done:
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08001205 return pfc_host_stat;
1206}
1207
Andrew Vasquez1620f7c2006-10-02 12:00:44 -07001208static void
1209qla2x00_get_host_symbolic_name(struct Scsi_Host *shost)
1210{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001211 scsi_qla_host_t *vha = shost_priv(shost);
Andrew Vasquez1620f7c2006-10-02 12:00:44 -07001212
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001213 qla2x00_get_sym_node_name(vha, fc_host_symbolic_name(shost));
Andrew Vasquez1620f7c2006-10-02 12:00:44 -07001214}
1215
Andrew Vasqueza740a3f2006-10-02 12:00:45 -07001216static void
1217qla2x00_set_host_system_hostname(struct Scsi_Host *shost)
1218{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001219 scsi_qla_host_t *vha = shost_priv(shost);
Andrew Vasqueza740a3f2006-10-02 12:00:45 -07001220
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001221 set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
Andrew Vasqueza740a3f2006-10-02 12:00:45 -07001222}
1223
Andrew Vasquez90991c82006-10-02 12:00:46 -07001224static void
1225qla2x00_get_host_fabric_name(struct Scsi_Host *shost)
1226{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001227 scsi_qla_host_t *vha = shost_priv(shost);
Andrew Vasquez90991c82006-10-02 12:00:46 -07001228 u64 node_name;
1229
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001230 if (vha->device_flags & SWITCH_FOUND)
1231 node_name = wwn_to_u64(vha->fabric_node_name);
Andrew Vasquez90991c82006-10-02 12:00:46 -07001232 else
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001233 node_name = wwn_to_u64(vha->node_name);
Andrew Vasquez90991c82006-10-02 12:00:46 -07001234
1235 fc_host_fabric_name(shost) = node_name;
1236}
1237
Andrew Vasquez7047fcd2006-10-02 12:00:47 -07001238static void
1239qla2x00_get_host_port_state(struct Scsi_Host *shost)
1240{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001241 scsi_qla_host_t *vha = shost_priv(shost);
1242 struct scsi_qla_host *base_vha = pci_get_drvdata(vha->hw->pdev);
Andrew Vasquez7047fcd2006-10-02 12:00:47 -07001243
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001244 if (!base_vha->flags.online)
Andrew Vasquez7047fcd2006-10-02 12:00:47 -07001245 fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001246 else if (atomic_read(&base_vha->loop_state) == LOOP_TIMEOUT)
Andrew Vasquez7047fcd2006-10-02 12:00:47 -07001247 fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
1248 else
1249 fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
1250}
1251
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001252static int
1253qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
1254{
1255 int ret = 0;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001256 int cnt = 0;
1257 uint8_t qos = QLA_DEFAULT_QUE_QOS;
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001258 scsi_qla_host_t *base_vha = shost_priv(fc_vport->shost);
1259 scsi_qla_host_t *vha = NULL;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001260 struct qla_hw_data *ha = base_vha->hw;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001261
1262 ret = qla24xx_vport_create_req_sanity_check(fc_vport);
1263 if (ret) {
1264 DEBUG15(printk("qla24xx_vport_create_req_sanity_check failed, "
1265 "status %x\n", ret));
1266 return (ret);
1267 }
1268
1269 vha = qla24xx_create_vhost(fc_vport);
1270 if (vha == NULL) {
1271 DEBUG15(printk ("qla24xx_create_vhost failed, vha = %p\n",
1272 vha));
1273 return FC_VPORT_FAILED;
1274 }
1275 if (disable) {
1276 atomic_set(&vha->vp_state, VP_OFFLINE);
1277 fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
1278 } else
1279 atomic_set(&vha->vp_state, VP_FAILED);
1280
1281 /* ready to create vport */
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001282 qla_printk(KERN_INFO, vha->hw, "VP entry id %d assigned.\n",
1283 vha->vp_idx);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001284
1285 /* initialized vport states */
1286 atomic_set(&vha->loop_state, LOOP_DOWN);
1287 vha->vp_err_state= VP_ERR_PORTDWN;
1288 vha->vp_prev_err_state= VP_ERR_UNKWN;
1289 /* Check if physical ha port is Up */
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001290 if (atomic_read(&base_vha->loop_state) == LOOP_DOWN ||
1291 atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001292 /* Don't retry or attempt login of this virtual port */
1293 DEBUG15(printk ("scsi(%ld): pport loop_state is not UP.\n",
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001294 base_vha->host_no));
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001295 atomic_set(&vha->loop_state, LOOP_DEAD);
1296 if (!disable)
1297 fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
1298 }
1299
1300 if (scsi_add_host(vha->host, &fc_vport->dev)) {
1301 DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
1302 vha->host_no, vha->vp_idx));
1303 goto vport_create_failed_2;
1304 }
1305
1306 /* initialize attributes */
1307 fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
1308 fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
1309 fc_host_supported_classes(vha->host) =
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001310 fc_host_supported_classes(base_vha->host);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001311 fc_host_supported_speeds(vha->host) =
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001312 fc_host_supported_speeds(base_vha->host);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001313
1314 qla24xx_vport_disable(fc_vport, disable);
1315
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001316 /* Create a queue pair for the vport */
1317 if (ha->mqenable) {
1318 if (ha->npiv_info) {
1319 for (; cnt < ha->nvram_npiv_size; cnt++) {
1320 if (ha->npiv_info[cnt].port_name ==
1321 vha->port_name &&
1322 ha->npiv_info[cnt].node_name ==
1323 vha->node_name) {
1324 qos = ha->npiv_info[cnt].q_qos;
1325 break;
1326 }
1327 }
1328 }
1329 qla25xx_create_queues(vha, qos);
1330 }
1331
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001332 return 0;
1333vport_create_failed_2:
1334 qla24xx_disable_vp(vha);
1335 qla24xx_deallocate_vp_id(vha);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001336 scsi_host_put(vha->host);
1337 return FC_VPORT_FAILED;
1338}
1339
Adrian Bunka824ebb2008-01-17 09:02:15 -08001340static int
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001341qla24xx_vport_delete(struct fc_vport *fc_vport)
1342{
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001343 scsi_qla_host_t *vha = fc_vport->dd_data;
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001344 fc_port_t *fcport, *tfcport;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001345 struct qla_hw_data *ha = vha->hw;
1346 uint16_t id = vha->vp_idx;
Andrew Vasquezc9c5ced2008-07-24 08:31:49 -07001347
1348 while (test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags) ||
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001349 test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags))
Andrew Vasquezc9c5ced2008-07-24 08:31:49 -07001350 msleep(1000);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001351
1352 qla24xx_disable_vp(vha);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001353
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001354 fc_remove_host(vha->host);
1355
1356 scsi_remove_host(vha->host);
1357
1358 list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) {
1359 list_del(&fcport->list);
1360 kfree(fcport);
1361 fcport = NULL;
1362 }
1363
1364 qla24xx_deallocate_vp_id(vha);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001365
1366 if (vha->timer_active) {
1367 qla2x00_vp_stop_timer(vha);
1368 DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p "
1369 "has stopped\n",
1370 vha->host_no, vha->vp_idx, vha));
1371 }
1372
Anirban Chakrabortycf5a1632009-02-08 20:50:13 -08001373 if (ha->mqenable) {
1374 if (qla25xx_delete_queues(vha, 0) != QLA_SUCCESS)
1375 qla_printk(KERN_WARNING, ha,
1376 "Queue delete failed.\n");
1377 }
1378
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001379 scsi_host_put(vha->host);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001380 qla_printk(KERN_INFO, ha, "vport %d deleted\n", id);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001381 return 0;
1382}
1383
Adrian Bunka824ebb2008-01-17 09:02:15 -08001384static int
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001385qla24xx_vport_disable(struct fc_vport *fc_vport, bool disable)
1386{
1387 scsi_qla_host_t *vha = fc_vport->dd_data;
1388
1389 if (disable)
1390 qla24xx_disable_vp(vha);
1391 else
1392 qla24xx_enable_vp(vha);
1393
1394 return 0;
1395}
1396
Andrew Vasquez1c97a122005-04-21 16:13:36 -04001397struct fc_function_template qla2xxx_transport_functions = {
8482e1182005-04-17 15:04:54 -05001398
1399 .show_host_node_name = 1,
1400 .show_host_port_name = 1,
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07001401 .show_host_supported_classes = 1,
Andrew Vasquez2ae2b372008-04-03 13:13:14 -07001402 .show_host_supported_speeds = 1,
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07001403
8482e1182005-04-17 15:04:54 -05001404 .get_host_port_id = qla2x00_get_host_port_id,
1405 .show_host_port_id = 1,
andrew.vasquez@qlogic.com04414012006-01-31 16:04:51 -08001406 .get_host_speed = qla2x00_get_host_speed,
1407 .show_host_speed = 1,
andrew.vasquez@qlogic.com8d067622006-01-31 16:04:56 -08001408 .get_host_port_type = qla2x00_get_host_port_type,
1409 .show_host_port_type = 1,
Andrew Vasquez1620f7c2006-10-02 12:00:44 -07001410 .get_host_symbolic_name = qla2x00_get_host_symbolic_name,
1411 .show_host_symbolic_name = 1,
Andrew Vasqueza740a3f2006-10-02 12:00:45 -07001412 .set_host_system_hostname = qla2x00_set_host_system_hostname,
1413 .show_host_system_hostname = 1,
Andrew Vasquez90991c82006-10-02 12:00:46 -07001414 .get_host_fabric_name = qla2x00_get_host_fabric_name,
1415 .show_host_fabric_name = 1,
Andrew Vasquez7047fcd2006-10-02 12:00:47 -07001416 .get_host_port_state = qla2x00_get_host_port_state,
1417 .show_host_port_state = 1,
8482e1182005-04-17 15:04:54 -05001418
bdf79622005-04-17 15:06:53 -05001419 .dd_fcrport_size = sizeof(struct fc_port *),
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07001420 .show_rport_supported_classes = 1,
8482e1182005-04-17 15:04:54 -05001421
1422 .get_starget_node_name = qla2x00_get_starget_node_name,
1423 .show_starget_node_name = 1,
1424 .get_starget_port_name = qla2x00_get_starget_port_name,
1425 .show_starget_port_name = 1,
1426 .get_starget_port_id = qla2x00_get_starget_port_id,
1427 .show_starget_port_id = 1,
1428
8482e1182005-04-17 15:04:54 -05001429 .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
1430 .show_rport_dev_loss_tmo = 1,
1431
Andrew Vasquez91ca7b02005-10-27 16:03:37 -07001432 .issue_fc_host_lip = qla2x00_issue_lip,
Seokmann Ju5f3a9a22008-07-10 16:55:47 -07001433 .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
1434 .terminate_rport_io = qla2x00_terminate_rport_io,
andrew.vasquez@qlogic.com392e2f62006-01-31 16:05:02 -08001435 .get_fc_host_stats = qla2x00_get_fc_host_stats,
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001436
1437 .vport_create = qla24xx_vport_create,
1438 .vport_disable = qla24xx_vport_disable,
1439 .vport_delete = qla24xx_vport_delete,
1440};
1441
1442struct fc_function_template qla2xxx_transport_vport_functions = {
1443
1444 .show_host_node_name = 1,
1445 .show_host_port_name = 1,
1446 .show_host_supported_classes = 1,
1447
1448 .get_host_port_id = qla2x00_get_host_port_id,
1449 .show_host_port_id = 1,
1450 .get_host_speed = qla2x00_get_host_speed,
1451 .show_host_speed = 1,
1452 .get_host_port_type = qla2x00_get_host_port_type,
1453 .show_host_port_type = 1,
1454 .get_host_symbolic_name = qla2x00_get_host_symbolic_name,
1455 .show_host_symbolic_name = 1,
1456 .set_host_system_hostname = qla2x00_set_host_system_hostname,
1457 .show_host_system_hostname = 1,
1458 .get_host_fabric_name = qla2x00_get_host_fabric_name,
1459 .show_host_fabric_name = 1,
1460 .get_host_port_state = qla2x00_get_host_port_state,
1461 .show_host_port_state = 1,
1462
1463 .dd_fcrport_size = sizeof(struct fc_port *),
1464 .show_rport_supported_classes = 1,
1465
1466 .get_starget_node_name = qla2x00_get_starget_node_name,
1467 .show_starget_node_name = 1,
1468 .get_starget_port_name = qla2x00_get_starget_port_name,
1469 .show_starget_port_name = 1,
1470 .get_starget_port_id = qla2x00_get_starget_port_id,
1471 .show_starget_port_id = 1,
1472
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001473 .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
1474 .show_rport_dev_loss_tmo = 1,
1475
1476 .issue_fc_host_lip = qla2x00_issue_lip,
Seokmann Ju5f3a9a22008-07-10 16:55:47 -07001477 .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
1478 .terminate_rport_io = qla2x00_terminate_rport_io,
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001479 .get_fc_host_stats = qla2x00_get_fc_host_stats,
8482e1182005-04-17 15:04:54 -05001480};
1481
8482e1182005-04-17 15:04:54 -05001482void
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001483qla2x00_init_host_attr(scsi_qla_host_t *vha)
8482e1182005-04-17 15:04:54 -05001484{
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001485 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez2ae2b372008-04-03 13:13:14 -07001486 u32 speed = FC_PORTSPEED_UNKNOWN;
1487
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001488 fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
1489 fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
1490 fc_host_supported_classes(vha->host) = FC_COS_CLASS3;
1491 fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports;
1492 fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count;
Andrew Vasquez2ae2b372008-04-03 13:13:14 -07001493
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001494 if (IS_QLA81XX(ha))
1495 speed = FC_PORTSPEED_10GBIT;
1496 else if (IS_QLA25XX(ha))
Andrew Vasquez2ae2b372008-04-03 13:13:14 -07001497 speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT |
1498 FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07001499 else if (IS_QLA24XX_TYPE(ha))
Andrew Vasquez2ae2b372008-04-03 13:13:14 -07001500 speed = FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
1501 FC_PORTSPEED_1GBIT;
1502 else if (IS_QLA23XX(ha))
1503 speed = FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
1504 else
1505 speed = FC_PORTSPEED_1GBIT;
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001506 fc_host_supported_speeds(vha->host) = speed;
8482e1182005-04-17 15:04:54 -05001507}