aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
author <andrew.vasquez@qlogic.com>2005-04-17 16:04:54 -0400
committerJames Bottomley <jejb@titanic>2005-04-18 14:47:19 -0400
commit8482e118afa0cb4321ab3d30b1100d27d63130c0 (patch)
tree971714d297194e1c20e1b80b1d2e031d4517f5ad /drivers/scsi
parentf4f051ebb40e74ad0ba02d2cb3a6c16b0393472b (diff)
[PATCH] qla2xxx: add remote port codes...
Add initial support for FC remote port infrastructure. o Use fc_remote_port...() registration and block/unlock functions. o Consolidate 'attribute' (fc-remote/sysfs) helpers into new qla_attr.c file. Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/qla2xxx/Makefile2
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c323
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h3
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h12
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c31
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c302
6 files changed, 403 insertions, 270 deletions
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index f7a247defba6..48fdd406c075 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -1,7 +1,7 @@
1EXTRA_CFLAGS += -DUNIQUE_FW_NAME 1EXTRA_CFLAGS += -DUNIQUE_FW_NAME
2 2
3qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ 3qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
4 qla_dbg.o qla_sup.o qla_rscn.o 4 qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o
5 5
6qla2100-y := ql2100.o ql2100_fw.o 6qla2100-y := ql2100.o ql2100_fw.o
7qla2200-y := ql2200.o ql2200_fw.o 7qla2200-y := ql2200.o ql2200_fw.o
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
new file mode 100644
index 000000000000..0105b609ff3a
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -0,0 +1,323 @@
1/*
2 * QLOGIC LINUX SOFTWARE
3 *
4 * QLogic ISP2x00 device driver for Linux 2.6.x
5 * Copyright (C) 2003-2005 QLogic Corporation
6 * (www.qlogic.com)
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 */
19#include "qla_def.h"
20
21#include <linux/version.h>
22#include <scsi/scsi_transport_fc.h>
23
24/* SYSFS attributes --------------------------------------------------------- */
25
26static ssize_t
27qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off,
28 size_t count)
29{
30 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
31 struct device, kobj)));
32
33 if (ha->fw_dump_reading == 0)
34 return 0;
35 if (off > ha->fw_dump_buffer_len)
36 return 0;
37 if (off + count > ha->fw_dump_buffer_len)
38 count = ha->fw_dump_buffer_len - off;
39
40 memcpy(buf, &ha->fw_dump_buffer[off], count);
41
42 return (count);
43}
44
45static ssize_t
46qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
47 size_t count)
48{
49 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
50 struct device, kobj)));
51 int reading;
52 uint32_t dump_size;
53
54 if (off != 0)
55 return (0);
56
57 reading = simple_strtol(buf, NULL, 10);
58 switch (reading) {
59 case 0:
60 if (ha->fw_dump_reading == 1) {
61 qla_printk(KERN_INFO, ha,
62 "Firmware dump cleared on (%ld).\n",
63 ha->host_no);
64
65 vfree(ha->fw_dump_buffer);
66 free_pages((unsigned long)ha->fw_dump,
67 ha->fw_dump_order);
68
69 ha->fw_dump_reading = 0;
70 ha->fw_dump_buffer = NULL;
71 ha->fw_dump = NULL;
72 }
73 break;
74 case 1:
75 if (ha->fw_dump != NULL && !ha->fw_dump_reading) {
76 ha->fw_dump_reading = 1;
77
78 dump_size = FW_DUMP_SIZE_1M;
79 if (ha->fw_memory_size < 0x20000)
80 dump_size = FW_DUMP_SIZE_128K;
81 else if (ha->fw_memory_size < 0x80000)
82 dump_size = FW_DUMP_SIZE_512K;
83 ha->fw_dump_buffer = (char *)vmalloc(dump_size);
84 if (ha->fw_dump_buffer == NULL) {
85 qla_printk(KERN_WARNING, ha,
86 "Unable to allocate memory for firmware "
87 "dump buffer (%d).\n", dump_size);
88
89 ha->fw_dump_reading = 0;
90 return (count);
91 }
92 qla_printk(KERN_INFO, ha,
93 "Firmware dump ready for read on (%ld).\n",
94 ha->host_no);
95 memset(ha->fw_dump_buffer, 0, dump_size);
96 if (IS_QLA2100(ha) || IS_QLA2200(ha))
97 qla2100_ascii_fw_dump(ha);
98 else
99 qla2300_ascii_fw_dump(ha);
100 ha->fw_dump_buffer_len = strlen(ha->fw_dump_buffer);
101 }
102 break;
103 }
104 return (count);
105}
106
107static struct bin_attribute sysfs_fw_dump_attr = {
108 .attr = {
109 .name = "fw_dump",
110 .mode = S_IRUSR | S_IWUSR,
111 .owner = THIS_MODULE,
112 },
113 .size = 0,
114 .read = qla2x00_sysfs_read_fw_dump,
115 .write = qla2x00_sysfs_write_fw_dump,
116};
117
118static ssize_t
119qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
120 size_t count)
121{
122 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
123 struct device, kobj)));
124 uint16_t *witer;
125 unsigned long flags;
126 uint16_t cnt;
127
128 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != sizeof(nvram_t))
129 return 0;
130
131 /* Read NVRAM. */
132 spin_lock_irqsave(&ha->hardware_lock, flags);
133 qla2x00_lock_nvram_access(ha);
134 witer = (uint16_t *)buf;
135 for (cnt = 0; cnt < count / 2; cnt++) {
136 *witer = cpu_to_le16(qla2x00_get_nvram_word(ha,
137 cnt+ha->nvram_base));
138 witer++;
139 }
140 qla2x00_unlock_nvram_access(ha);
141 spin_unlock_irqrestore(&ha->hardware_lock, flags);
142
143 return (count);
144}
145
146static ssize_t
147qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off,
148 size_t count)
149{
150 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
151 struct device, kobj)));
152 uint8_t *iter;
153 uint16_t *witer;
154 unsigned long flags;
155 uint16_t cnt;
156 uint8_t chksum;
157
158 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != sizeof(nvram_t))
159 return 0;
160
161 /* Checksum NVRAM. */
162 iter = (uint8_t *)buf;
163 chksum = 0;
164 for (cnt = 0; cnt < count - 1; cnt++)
165 chksum += *iter++;
166 chksum = ~chksum + 1;
167 *iter = chksum;
168
169 /* Write NVRAM. */
170 spin_lock_irqsave(&ha->hardware_lock, flags);
171 qla2x00_lock_nvram_access(ha);
172 qla2x00_release_nvram_protection(ha);
173 witer = (uint16_t *)buf;
174 for (cnt = 0; cnt < count / 2; cnt++) {
175 qla2x00_write_nvram_word(ha, cnt+ha->nvram_base,
176 cpu_to_le16(*witer));
177 witer++;
178 }
179 qla2x00_unlock_nvram_access(ha);
180 spin_unlock_irqrestore(&ha->hardware_lock, flags);
181
182 return (count);
183}
184
185static struct bin_attribute sysfs_nvram_attr = {
186 .attr = {
187 .name = "nvram",
188 .mode = S_IRUSR | S_IWUSR,
189 .owner = THIS_MODULE,
190 },
191 .size = sizeof(nvram_t),
192 .read = qla2x00_sysfs_read_nvram,
193 .write = qla2x00_sysfs_write_nvram,
194};
195
196void
197qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
198{
199 struct Scsi_Host *host = ha->host;
200
201 sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr);
202 sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
203}
204
205void
206qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
207{
208 struct Scsi_Host *host = ha->host;
209
210 sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr);
211 sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
212}
213
214/* Host attributes. */
215
216static void
217qla2x00_get_host_port_id(struct Scsi_Host *shost)
218{
219 scsi_qla_host_t *ha = to_qla_host(shost);
220
221 fc_host_port_id(shost) = ha->d_id.b.domain << 16 |
222 ha->d_id.b.area << 8 | ha->d_id.b.al_pa;
223}
224
225static void
226qla2x00_get_starget_node_name(struct scsi_target *starget)
227{
228 struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
229 scsi_qla_host_t *ha = to_qla_host(host);
230 os_tgt_t *tq = (os_tgt_t *) TGT_Q(ha, starget->id);
231 uint64_t node_name = 0;
232
233 if (tq->fcport)
234 node_name = be64_to_cpu(*(uint64_t *)tq->fcport->node_name);
235 fc_starget_node_name(starget) = node_name;
236}
237
238static void
239qla2x00_get_starget_port_name(struct scsi_target *starget)
240{
241 struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
242 scsi_qla_host_t *ha = to_qla_host(host);
243 os_tgt_t *tq = (os_tgt_t *) TGT_Q(ha, starget->id);
244 uint64_t port_name = 0;
245
246 if (tq->fcport)
247 port_name = be64_to_cpu(*(uint64_t *)tq->fcport->port_name);
248 fc_starget_port_name(starget) = port_name;
249}
250
251static void
252qla2x00_get_starget_port_id(struct scsi_target *starget)
253{
254 struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
255 scsi_qla_host_t *ha = to_qla_host(host);
256 os_tgt_t *tq = (os_tgt_t *) TGT_Q(ha, starget->id);
257 uint32_t port_id = 0;
258
259 if (tq->fcport)
260 port_id = tq->fcport->d_id.b.domain << 16 |
261 tq->fcport->d_id.b.area << 8 | tq->fcport->d_id.b.al_pa;
262 fc_starget_port_id(starget) = port_id;
263}
264
265static void
266qla2x00_get_rport_loss_tmo(struct fc_rport *rport)
267{
268 os_tgt_t *tq = rport->dd_data;
269 scsi_qla_host_t *ha = tq->ha;
270
271 rport->dev_loss_tmo = ha->port_down_retry_count + 5;
272}
273
274static void
275qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
276{
277 os_tgt_t *tq = rport->dd_data;
278 scsi_qla_host_t *ha = tq->ha;
279
280 if (timeout)
281 ha->port_down_retry_count = timeout;
282 else
283 ha->port_down_retry_count = 1;
284
285 rport->dev_loss_tmo = ha->port_down_retry_count + 5;
286}
287
288static struct fc_function_template qla2xxx_transport_functions = {
289
290 .show_host_node_name = 1,
291 .show_host_port_name = 1,
292 .get_host_port_id = qla2x00_get_host_port_id,
293 .show_host_port_id = 1,
294
295 .dd_fcrport_size = sizeof(os_tgt_t *),
296
297 .get_starget_node_name = qla2x00_get_starget_node_name,
298 .show_starget_node_name = 1,
299 .get_starget_port_name = qla2x00_get_starget_port_name,
300 .show_starget_port_name = 1,
301 .get_starget_port_id = qla2x00_get_starget_port_id,
302 .show_starget_port_id = 1,
303
304 .get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo,
305 .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
306 .show_rport_dev_loss_tmo = 1,
307
308};
309
310struct scsi_transport_template *
311qla2x00_alloc_transport_tmpl(void)
312{
313 return (fc_attach_transport(&qla2xxx_transport_functions));
314}
315
316void
317qla2x00_init_host_attr(scsi_qla_host_t *ha)
318{
319 fc_host_node_name(ha->host) =
320 be64_to_cpu(*(uint64_t *)ha->init_cb->node_name);
321 fc_host_port_name(ha->host) =
322 be64_to_cpu(*(uint64_t *)ha->init_cb->port_name);
323}
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 9e3144f42f57..b153d64bb966 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -219,7 +219,7 @@
219/* 219/*
220 * Timeout timer counts in seconds 220 * Timeout timer counts in seconds
221 */ 221 */
222#define PORT_RETRY_TIME 2 222#define PORT_RETRY_TIME 1
223#define LOOP_DOWN_TIMEOUT 60 223#define LOOP_DOWN_TIMEOUT 60
224#define LOOP_DOWN_TIME 255 /* 240 */ 224#define LOOP_DOWN_TIME 255 /* 240 */
225#define LOOP_DOWN_RESET (LOOP_DOWN_TIME - 30) 225#define LOOP_DOWN_RESET (LOOP_DOWN_TIME - 30)
@@ -1718,6 +1718,7 @@ typedef struct fc_port {
1718 uint8_t cur_path; /* current path id */ 1718 uint8_t cur_path; /* current path id */
1719 1719
1720 lun_bit_mask_t lun_mask; 1720 lun_bit_mask_t lun_mask;
1721 struct fc_rport *rport;
1721} fc_port_t; 1722} fc_port_t;
1722 1723
1723/* 1724/*
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 47efa46bff27..bc1ef103495a 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -24,6 +24,7 @@
24#define __QLA_GBL_H 24#define __QLA_GBL_H
25 25
26#include <linux/interrupt.h> 26#include <linux/interrupt.h>
27#include <scsi/scsi_transport.h>
27 28
28extern void qla2x00_remove_one(struct pci_dev *); 29extern void qla2x00_remove_one(struct pci_dev *);
29extern int qla2x00_probe_one(struct pci_dev *, struct qla_board_info *); 30extern int qla2x00_probe_one(struct pci_dev *, struct qla_board_info *);
@@ -48,6 +49,8 @@ extern void qla2x00_tgt_free(scsi_qla_host_t *ha, uint16_t t);
48 49
49extern int qla2x00_abort_isp(scsi_qla_host_t *); 50extern int qla2x00_abort_isp(scsi_qla_host_t *);
50 51
52extern void qla2x00_reg_remote_port(scsi_qla_host_t *, fc_port_t *);
53
51/* 54/*
52 * Global Data in qla_os.c source file. 55 * Global Data in qla_os.c source file.
53 */ 56 */
@@ -250,4 +253,13 @@ extern void qla2x00_cancel_io_descriptors(scsi_qla_host_t *);
250#define qla2x00_alloc_ioctl_mem(ha) (0) 253#define qla2x00_alloc_ioctl_mem(ha) (0)
251#define qla2x00_free_ioctl_mem(ha) do { } while (0) 254#define qla2x00_free_ioctl_mem(ha) do { } while (0)
252 255
256/*
257 * Global Function Prototypes in qla_attr.c source file.
258 */
259extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
260extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
261extern struct scsi_transport_template *qla2x00_alloc_transport_tmpl(void);
262extern void qla2x00_init_host_attr(scsi_qla_host_t *);
263extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
264extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
253#endif /* _QLA_GBL_H */ 265#endif /* _QLA_GBL_H */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 00bfbd42bdb6..29b301ecd2ff 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -19,6 +19,7 @@
19#include "qla_def.h" 19#include "qla_def.h"
20 20
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <scsi/scsi_transport_fc.h>
22 23
23#include "qla_devtbl.h" 24#include "qla_devtbl.h"
24 25
@@ -1927,8 +1928,35 @@ qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
1927 qla2x00_lun_discovery(ha, fcport); 1928 qla2x00_lun_discovery(ha, fcport);
1928 } 1929 }
1929 atomic_set(&fcport->state, FCS_ONLINE); 1930 atomic_set(&fcport->state, FCS_ONLINE);
1931 if (ha->flags.init_done)
1932 qla2x00_reg_remote_port(ha, fcport);
1930} 1933}
1931 1934
1935void
1936qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
1937{
1938 struct fc_rport_identifiers rport_ids;
1939
1940 if (fcport->rport) {
1941 fc_remote_port_unblock(fcport->rport);
1942 return;
1943 }
1944
1945 rport_ids.node_name = be64_to_cpu(*(uint64_t *)fcport->node_name);
1946 rport_ids.port_name = be64_to_cpu(*(uint64_t *)fcport->port_name);
1947 rport_ids.port_id = fcport->d_id.b.domain << 16 |
1948 fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
1949 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
1950 if (fcport->port_type == FCT_INITIATOR)
1951 rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
1952 if (fcport->port_type == FCT_TARGET)
1953 rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
1954
1955 fcport->rport = fc_remote_port_add(ha->host, 0, &rport_ids);
1956 if (!fcport->rport)
1957 qla_printk(KERN_WARNING, ha,
1958 "Unable to allocate fc remote port!\n");
1959}
1932/* 1960/*
1933 * qla2x00_lun_discovery 1961 * qla2x00_lun_discovery
1934 * Issue SCSI inquiry command for LUN discovery. 1962 * Issue SCSI inquiry command for LUN discovery.
@@ -2895,8 +2923,7 @@ qla2x00_device_resync(scsi_qla_host_t *ha)
2895 if (atomic_read(&fcport->state) == FCS_ONLINE) { 2923 if (atomic_read(&fcport->state) == FCS_ONLINE) {
2896 if (format != 3 || 2924 if (format != 3 ||
2897 fcport->port_type != FCT_INITIATOR) { 2925 fcport->port_type != FCT_INITIATOR) {
2898 atomic_set(&fcport->state, 2926 qla2x00_mark_device_lost(ha, fcport, 0);
2899 FCS_DEVICE_LOST);
2900 } 2927 }
2901 } 2928 }
2902 fcport->flags &= ~FCF_FARP_DONE; 2929 fcport->flags &= ~FCF_FARP_DONE;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 0e7e51db470c..d0aa18831544 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -63,7 +63,7 @@ module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
63MODULE_PARM_DESC(ql2xlogintimeout, 63MODULE_PARM_DESC(ql2xlogintimeout,
64 "Login timeout value in seconds."); 64 "Login timeout value in seconds.");
65 65
66int qlport_down_retry; 66int qlport_down_retry = 30;
67module_param(qlport_down_retry, int, S_IRUGO|S_IRUSR); 67module_param(qlport_down_retry, int, S_IRUGO|S_IRUSR);
68MODULE_PARM_DESC(qlport_down_retry, 68MODULE_PARM_DESC(qlport_down_retry,
69 "Maximum number of command retries to a port that returns" 69 "Maximum number of command retries to a port that returns"
@@ -246,184 +246,8 @@ static srb_t *qla2x00_get_new_sp(scsi_qla_host_t *);
246static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *); 246static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *);
247void qla2x00_sp_compl(scsi_qla_host_t *ha, srb_t *); 247void qla2x00_sp_compl(scsi_qla_host_t *ha, srb_t *);
248 248
249static ssize_t qla2x00_sysfs_read_fw_dump(struct kobject *, char *, loff_t,
250 size_t);
251static ssize_t qla2x00_sysfs_write_fw_dump(struct kobject *, char *, loff_t,
252 size_t);
253static struct bin_attribute sysfs_fw_dump_attr = {
254 .attr = {
255 .name = "fw_dump",
256 .mode = S_IRUSR | S_IWUSR,
257 .owner = THIS_MODULE,
258 },
259 .size = 0,
260 .read = qla2x00_sysfs_read_fw_dump,
261 .write = qla2x00_sysfs_write_fw_dump,
262};
263static ssize_t qla2x00_sysfs_read_nvram(struct kobject *, char *, loff_t,
264 size_t);
265static ssize_t qla2x00_sysfs_write_nvram(struct kobject *, char *, loff_t,
266 size_t);
267static struct bin_attribute sysfs_nvram_attr = {
268 .attr = {
269 .name = "nvram",
270 .mode = S_IRUSR | S_IWUSR,
271 .owner = THIS_MODULE,
272 },
273 .size = sizeof(nvram_t),
274 .read = qla2x00_sysfs_read_nvram,
275 .write = qla2x00_sysfs_write_nvram,
276};
277
278/* -------------------------------------------------------------------------- */ 249/* -------------------------------------------------------------------------- */
279 250
280
281/* SysFS attributes. */
282static ssize_t qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf,
283 loff_t off, size_t count)
284{
285 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
286 struct device, kobj)));
287
288 if (ha->fw_dump_reading == 0)
289 return 0;
290 if (off > ha->fw_dump_buffer_len)
291 return 0;
292 if (off + count > ha->fw_dump_buffer_len)
293 count = ha->fw_dump_buffer_len - off;
294
295 memcpy(buf, &ha->fw_dump_buffer[off], count);
296
297 return (count);
298}
299
300static ssize_t qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf,
301 loff_t off, size_t count)
302{
303 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
304 struct device, kobj)));
305 int reading;
306 uint32_t dump_size;
307
308 if (off != 0)
309 return (0);
310
311 reading = simple_strtol(buf, NULL, 10);
312 switch (reading) {
313 case 0:
314 if (ha->fw_dump_reading == 1) {
315 qla_printk(KERN_INFO, ha,
316 "Firmware dump cleared on (%ld).\n",
317 ha->host_no);
318
319 vfree(ha->fw_dump_buffer);
320 free_pages((unsigned long)ha->fw_dump,
321 ha->fw_dump_order);
322
323 ha->fw_dump_reading = 0;
324 ha->fw_dump_buffer = NULL;
325 ha->fw_dump = NULL;
326 }
327 break;
328 case 1:
329 if (ha->fw_dump != NULL && !ha->fw_dump_reading) {
330 ha->fw_dump_reading = 1;
331
332 dump_size = FW_DUMP_SIZE_1M;
333 if (ha->fw_memory_size < 0x20000)
334 dump_size = FW_DUMP_SIZE_128K;
335 else if (ha->fw_memory_size < 0x80000)
336 dump_size = FW_DUMP_SIZE_512K;
337 ha->fw_dump_buffer = (char *)vmalloc(dump_size);
338 if (ha->fw_dump_buffer == NULL) {
339 qla_printk(KERN_WARNING, ha,
340 "Unable to allocate memory for firmware "
341 "dump buffer (%d).\n", dump_size);
342
343 ha->fw_dump_reading = 0;
344 return (count);
345 }
346 qla_printk(KERN_INFO, ha,
347 "Firmware dump ready for read on (%ld).\n",
348 ha->host_no);
349 memset(ha->fw_dump_buffer, 0, dump_size);
350 if (IS_QLA2100(ha) || IS_QLA2200(ha))
351 qla2100_ascii_fw_dump(ha);
352 else
353 qla2300_ascii_fw_dump(ha);
354 ha->fw_dump_buffer_len = strlen(ha->fw_dump_buffer);
355 }
356 break;
357 }
358 return (count);
359}
360
361static ssize_t qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf,
362 loff_t off, size_t count)
363{
364 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
365 struct device, kobj)));
366 uint16_t *witer;
367 unsigned long flags;
368 uint16_t cnt;
369
370 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != sizeof(nvram_t))
371 return 0;
372
373 /* Read NVRAM. */
374 spin_lock_irqsave(&ha->hardware_lock, flags);
375 qla2x00_lock_nvram_access(ha);
376 witer = (uint16_t *)buf;
377 for (cnt = 0; cnt < count / 2; cnt++) {
378 *witer = cpu_to_le16(qla2x00_get_nvram_word(ha,
379 cnt+ha->nvram_base));
380 witer++;
381 }
382 qla2x00_unlock_nvram_access(ha);
383 spin_unlock_irqrestore(&ha->hardware_lock, flags);
384
385 return (count);
386}
387
388static ssize_t qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf,
389 loff_t off, size_t count)
390{
391 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
392 struct device, kobj)));
393 uint8_t *iter;
394 uint16_t *witer;
395 unsigned long flags;
396 uint16_t cnt;
397 uint8_t chksum;
398
399 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != sizeof(nvram_t))
400 return 0;
401
402 /* Checksum NVRAM. */
403 iter = (uint8_t *)buf;
404 chksum = 0;
405 for (cnt = 0; cnt < count - 1; cnt++)
406 chksum += *iter++;
407 chksum = ~chksum + 1;
408 *iter = chksum;
409
410 /* Write NVRAM. */
411 spin_lock_irqsave(&ha->hardware_lock, flags);
412 qla2x00_lock_nvram_access(ha);
413 qla2x00_release_nvram_protection(ha);
414 witer = (uint16_t *)buf;
415 for (cnt = 0; cnt < count / 2; cnt++) {
416 qla2x00_write_nvram_word(ha, cnt+ha->nvram_base,
417 cpu_to_le16(*witer));
418 witer++;
419 }
420 qla2x00_unlock_nvram_access(ha);
421 spin_unlock_irqrestore(&ha->hardware_lock, flags);
422
423 return (count);
424}
425
426/* -------------------------------------------------------------------------- */
427static char * 251static char *
428qla2x00_get_pci_info_str(struct scsi_qla_host *ha, char *str) 252qla2x00_get_pci_info_str(struct scsi_qla_host *ha, char *str)
429{ 253{
@@ -1233,11 +1057,16 @@ qla2xxx_slave_alloc(struct scsi_device *sdev)
1233static int 1057static int
1234qla2xxx_slave_configure(struct scsi_device *sdev) 1058qla2xxx_slave_configure(struct scsi_device *sdev)
1235{ 1059{
1060 scsi_qla_host_t *ha = to_qla_host(sdev->host);
1061 struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
1062
1236 if (sdev->tagged_supported) 1063 if (sdev->tagged_supported)
1237 scsi_activate_tcq(sdev, 32); 1064 scsi_activate_tcq(sdev, 32);
1238 else 1065 else
1239 scsi_deactivate_tcq(sdev, 32); 1066 scsi_deactivate_tcq(sdev, 32);
1240 1067
1068 rport->dev_loss_tmo = ha->port_down_retry_count + 5;
1069
1241 return 0; 1070 return 0;
1242} 1071}
1243 1072
@@ -1370,6 +1199,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
1370 unsigned long wait_switch = 0; 1199 unsigned long wait_switch = 0;
1371 char pci_info[20]; 1200 char pci_info[20];
1372 char fw_str[30]; 1201 char fw_str[30];
1202 fc_port_t *fcport;
1373 1203
1374 if (pci_enable_device(pdev)) 1204 if (pci_enable_device(pdev))
1375 return -1; 1205 return -1;
@@ -1395,7 +1225,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
1395 /* Configure PCI I/O space */ 1225 /* Configure PCI I/O space */
1396 ret = qla2x00_iospace_config(ha); 1226 ret = qla2x00_iospace_config(ha);
1397 if (ret != 0) { 1227 if (ret != 0) {
1398 goto probe_failed; 1228 goto probe_alloc_failed;
1399 } 1229 }
1400 1230
1401 /* Sanitize the information from PCI BIOS. */ 1231 /* Sanitize the information from PCI BIOS. */
@@ -1469,9 +1299,23 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
1469 qla_printk(KERN_WARNING, ha, 1299 qla_printk(KERN_WARNING, ha,
1470 "[ERROR] Failed to allocate memory for adapter\n"); 1300 "[ERROR] Failed to allocate memory for adapter\n");
1471 1301
1472 goto probe_failed; 1302 goto probe_alloc_failed;
1473 } 1303 }
1474 1304
1305 pci_set_drvdata(pdev, ha);
1306 host->this_id = 255;
1307 host->cmd_per_lun = 3;
1308 host->unique_id = ha->instance;
1309 host->max_cmd_len = MAX_CMDSZ;
1310 host->max_channel = ha->ports - 1;
1311 host->max_id = ha->max_targets;
1312 host->max_lun = ha->max_luns;
1313 host->transportt = qla2xxx_transport_template;
1314 if (scsi_add_host(host, &pdev->dev))
1315 goto probe_alloc_failed;
1316
1317 qla2x00_alloc_sysfs_attr(ha);
1318
1475 if (qla2x00_initialize_adapter(ha) && 1319 if (qla2x00_initialize_adapter(ha) &&
1476 !(ha->device_flags & DFLG_NO_CABLE)) { 1320 !(ha->device_flags & DFLG_NO_CABLE)) {
1477 1321
@@ -1485,6 +1329,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
1485 goto probe_failed; 1329 goto probe_failed;
1486 } 1330 }
1487 1331
1332 qla2x00_init_host_attr(ha);
1488 /* 1333 /*
1489 * Startup the kernel thread for this host adapter 1334 * Startup the kernel thread for this host adapter
1490 */ 1335 */
@@ -1498,16 +1343,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
1498 } 1343 }
1499 wait_for_completion(&ha->dpc_inited); 1344 wait_for_completion(&ha->dpc_inited);
1500 1345
1501 host->this_id = 255;
1502 host->cmd_per_lun = 3;
1503 host->max_cmd_len = MAX_CMDSZ;
1504 host->max_channel = ha->ports - 1;
1505 host->max_lun = ha->max_luns;
1506 BUG_ON(qla2xxx_transport_template == NULL);
1507 host->transportt = qla2xxx_transport_template;
1508 host->unique_id = ha->instance;
1509 host->max_id = ha->max_targets;
1510
1511 if (IS_QLA2100(ha) || IS_QLA2200(ha)) 1346 if (IS_QLA2100(ha) || IS_QLA2200(ha))
1512 ret = request_irq(host->irq, qla2100_intr_handler, 1347 ret = request_irq(host->irq, qla2100_intr_handler,
1513 SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha); 1348 SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha);
@@ -1568,7 +1403,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
1568 msleep(10); 1403 msleep(10);
1569 } 1404 }
1570 1405
1571 pci_set_drvdata(pdev, ha);
1572 ha->flags.init_done = 1; 1406 ha->flags.init_done = 1;
1573 num_hosts++; 1407 num_hosts++;
1574 1408
@@ -1577,12 +1411,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
1577 qla2x00_display_fc_names(ha); 1411 qla2x00_display_fc_names(ha);
1578 } 1412 }
1579 1413
1580 if (scsi_add_host(host, &pdev->dev))
1581 goto probe_failed;
1582
1583 sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr);
1584 sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
1585
1586 qla_printk(KERN_INFO, ha, "\n" 1414 qla_printk(KERN_INFO, ha, "\n"
1587 " QLogic Fibre Channel HBA Driver: %s\n" 1415 " QLogic Fibre Channel HBA Driver: %s\n"
1588 " QLogic %s - %s\n" 1416 " QLogic %s - %s\n"
@@ -1592,12 +1420,16 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
1592 pci_name(ha->pdev), ha->flags.enable_64bit_addressing ? '+': '-', 1420 pci_name(ha->pdev), ha->flags.enable_64bit_addressing ? '+': '-',
1593 ha->host_no, qla2x00_get_fw_version_str(ha, fw_str)); 1421 ha->host_no, qla2x00_get_fw_version_str(ha, fw_str));
1594 1422
1595 if (ql2xdoinitscan) 1423 /* Go with fc_rport registration. */
1596 scsi_scan_host(host); 1424 list_for_each_entry(fcport, &ha->fcports, list)
1425 qla2x00_reg_remote_port(ha, fcport);
1597 1426
1598 return 0; 1427 return 0;
1599 1428
1600probe_failed: 1429probe_failed:
1430 scsi_remove_host(host);
1431
1432probe_alloc_failed:
1601 qla2x00_free_device(ha); 1433 qla2x00_free_device(ha);
1602 1434
1603 scsi_host_put(host); 1435 scsi_host_put(host);
@@ -1615,9 +1447,7 @@ void qla2x00_remove_one(struct pci_dev *pdev)
1615 1447
1616 ha = pci_get_drvdata(pdev); 1448 ha = pci_get_drvdata(pdev);
1617 1449
1618 sysfs_remove_bin_file(&ha->host->shost_gendev.kobj, 1450 qla2x00_free_sysfs_attr(ha);
1619 &sysfs_fw_dump_attr);
1620 sysfs_remove_bin_file(&ha->host->shost_gendev.kobj, &sysfs_nvram_attr);
1621 1451
1622 scsi_remove_host(ha->host); 1452 scsi_remove_host(ha->host);
1623 1453
@@ -2090,6 +1920,8 @@ qla2x00_display_fc_names(scsi_qla_host_t *ha)
2090void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport, 1920void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport,
2091 int do_login) 1921 int do_login)
2092{ 1922{
1923 if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport)
1924 fc_remote_port_block(fcport->rport);
2093 /* 1925 /*
2094 * We may need to retry the login, so don't change the state of the 1926 * We may need to retry the login, so don't change the state of the
2095 * port but do the retries. 1927 * port but do the retries.
@@ -2149,7 +1981,8 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha)
2149 */ 1981 */
2150 if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) 1982 if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
2151 continue; 1983 continue;
2152 1984 if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport)
1985 fc_remote_port_block(fcport->rport);
2153 atomic_set(&fcport->state, FCS_DEVICE_LOST); 1986 atomic_set(&fcport->state, FCS_DEVICE_LOST);
2154 } 1987 }
2155} 1988}
@@ -2815,7 +2648,6 @@ qla2x00_sp_compl(scsi_qla_host_t *ha, srb_t *sp)
2815 2648
2816 cmd->scsi_done(cmd); 2649 cmd->scsi_done(cmd);
2817} 2650}
2818
2819/************************************************************************** 2651/**************************************************************************
2820* qla2x00_timer 2652* qla2x00_timer
2821* 2653*
@@ -2953,67 +2785,6 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout)
2953 return -ETIMEDOUT; 2785 return -ETIMEDOUT;
2954} 2786}
2955 2787
2956static void
2957qla2xxx_get_port_id(struct scsi_target *starget)
2958{
2959 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2960 scsi_qla_host_t *ha = to_qla_host(shost);
2961 struct fc_port *fc;
2962
2963 list_for_each_entry(fc, &ha->fcports, list) {
2964 if (fc->os_target_id == starget->id) {
2965 fc_starget_port_id(starget) = fc->d_id.b.domain << 16 |
2966 fc->d_id.b.area << 8 |
2967 fc->d_id.b.al_pa;
2968 return;
2969 }
2970 }
2971 fc_starget_port_id(starget) = -1;
2972}
2973
2974static void
2975qla2xxx_get_port_name(struct scsi_target *starget)
2976{
2977 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2978 scsi_qla_host_t *ha = to_qla_host(shost);
2979 struct fc_port *fc;
2980
2981 list_for_each_entry(fc, &ha->fcports, list) {
2982 if (fc->os_target_id == starget->id) {
2983 fc_starget_port_name(starget) =
2984 __be64_to_cpu(*(uint64_t *)fc->port_name);
2985 return;
2986 }
2987 }
2988 fc_starget_port_name(starget) = -1;
2989}
2990
2991static void
2992qla2xxx_get_node_name(struct scsi_target *starget)
2993{
2994 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2995 scsi_qla_host_t *ha = to_qla_host(shost);
2996 struct fc_port *fc;
2997
2998 list_for_each_entry(fc, &ha->fcports, list) {
2999 if (fc->os_target_id == starget->id) {
3000 fc_starget_node_name(starget) =
3001 __be64_to_cpu(*(uint64_t *)fc->node_name);
3002 return;
3003 }
3004 }
3005 fc_starget_node_name(starget) = -1;
3006}
3007
3008static struct fc_function_template qla2xxx_transport_functions = {
3009 .get_starget_port_id = qla2xxx_get_port_id,
3010 .show_starget_port_id = 1,
3011 .get_starget_port_name = qla2xxx_get_port_name,
3012 .show_starget_port_name = 1,
3013 .get_starget_node_name = qla2xxx_get_node_name,
3014 .show_starget_node_name = 1,
3015};
3016
3017/** 2788/**
3018 * qla2x00_module_init - Module initialization. 2789 * qla2x00_module_init - Module initialization.
3019 **/ 2790 **/
@@ -3035,8 +2806,7 @@ qla2x00_module_init(void)
3035#if DEBUG_QLA2100 2806#if DEBUG_QLA2100
3036 strcat(qla2x00_version_str, "-debug"); 2807 strcat(qla2x00_version_str, "-debug");
3037#endif 2808#endif
3038 2809 qla2xxx_transport_template = qla2x00_alloc_transport_tmpl();
3039 qla2xxx_transport_template = fc_attach_transport(&qla2xxx_transport_functions);
3040 if (!qla2xxx_transport_template) 2810 if (!qla2xxx_transport_template)
3041 return -ENODEV; 2811 return -ENODEV;
3042 2812