1 From: David Wagner <david.wagner@qlogic.com>
2 Subject: qla2xxx: additional fixes/updates for SLES11
5 Here's some additional updates/corrections to qla2xxx for SLES11.
6 Should apply cleanly to the beta6 driver sources.
8 [PATCH 1/5] qla2xxx: Add ISP84xx firmware-update support.
9 [PATCH 2/5] qla2xxx: Add CT/ELS passthru support.
10 [PATCH 3/5] qla2xxx: Use correct value for max vport in LOOP topology.
11 [PATCH 4/5] qla2xxx: Correction of struct qla_flt_location.
12 [PATCH 5/5] qla2xxx: Update version number to 8.02.01.02.11.0-k9.
14 Corresponding upstream patches are queued in our local tree for
15 for the next merge window (post 2.6.28).
17 Signed-off-by: David Vasquez <david.vasquez@qlogic.com>
18 Signed-off-by: Hannes Reinecke <hare@suse.de>
20 diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
21 index c51fd1f..01ed81c 100644
22 --- a/drivers/scsi/qla2xxx/Makefile
23 +++ b/drivers/scsi/qla2xxx/Makefile
25 qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
26 - qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o
27 + qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o \
30 obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
31 diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
32 index ed73196..6d5210e 100644
33 --- a/drivers/scsi/qla2xxx/qla_attr.c
34 +++ b/drivers/scsi/qla2xxx/qla_attr.c
35 @@ -454,6 +454,287 @@ static struct bin_attribute sysfs_sfp_attr = {
36 .read = qla2x00_sysfs_read_sfp,
40 +qla2x00_find_port(struct scsi_qla_host *ha, uint8_t *pn)
44 + list_for_each_entry(fcport, &ha->fcports, list)
45 + if (!memcmp(pn, fcport->port_name, sizeof(fcport->port_name)))
52 +qla2x00_wait_for_passthru_completion(struct scsi_qla_host *ha)
54 + if (!wait_for_completion_timeout(&ha->pass_thru_intr_comp, 10 * HZ)) {
55 + DEBUG2(qla_printk(KERN_WARNING, ha,
56 + "Passthru request timed out.\n"));
57 + ha->isp_ops->fw_dump(ha, 0);
62 +qla2x00_sysfs_read_els(struct kobject *kobj, struct bin_attribute *bin_attr,
63 + char *buf, loff_t off, size_t count)
65 + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
66 + struct device, kobj)));
68 + if (!IS_FWI2_CAPABLE(ha))
71 + if (!ha->pass_thru_cmd_in_process || !ha->pass_thru_cmd_result) {
72 + DEBUG2(qla_printk(KERN_WARNING, ha,
73 + "Passthru ELS response is not available.\n"));
77 + memcpy(buf, ha->pass_thru, count);
79 + ha->pass_thru_cmd_result = 0;
80 + ha->pass_thru_cmd_in_process = 0;
86 +qla2x00_sysfs_write_els(struct kobject *kobj, struct bin_attribute *bin_attr,
87 + char *buf, loff_t off, size_t count)
89 + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
90 + struct device, kobj)));
91 + struct els_request *request = (struct els_request *) buf;
92 + struct els_entry_24xx *els_iocb;
93 + unsigned long flags;
94 + uint16_t nextlid = 0;
97 + count -= sizeof(request->header);
99 + if (!IS_FWI2_CAPABLE(ha) ||
100 + atomic_read(&ha->loop_state) != LOOP_READY)
103 + if (count < sizeof(request->ct_iu)) {
104 + DEBUG2(qla_printk(KERN_WARNING, ha,
105 + "Passthru ELS buffer insufficient size %ld...\n", count));
109 + if (ha->pass_thru_cmd_in_process || ha->pass_thru_cmd_result) {
110 + DEBUG2(qla_printk(KERN_WARNING, ha,
111 + "Passthru ELS request is already progress\n"));
115 + fcport = qla2x00_find_port(ha, request->header.WWPN);
117 + DEBUG2(qla_printk(KERN_WARNING, ha,
118 + "Passthru ELS request failed find port\n"));
122 + if (qla2x00_fabric_login(ha, fcport, &nextlid)) {
123 + DEBUG2(qla_printk(KERN_WARNING, ha,
124 + "Passthru ELS request failed to login port %06X\n",
125 + fcport->d_id.b24));
129 + ha->pass_thru_cmd_in_process = 1;
130 + spin_lock_irqsave(&ha->hardware_lock, flags);
132 + els_iocb = (void *)qla2x00_req_pkt(ha);
133 + if (els_iocb == NULL) {
134 + DEBUG2(qla_printk(KERN_WARNING, ha,
135 + "Passthru ELS request failed to get request packet\n"));
139 + if (count > PAGE_SIZE) {
140 + DEBUG2(qla_printk(KERN_INFO, ha,
141 + "Passthru ELS request excessive size %ld...\n", count));
145 + memset(ha->pass_thru, 0, PAGE_SIZE);
146 + memcpy(ha->pass_thru, &request->ct_iu, count);
148 + els_iocb->entry_type = ELS_IOCB_TYPE;
149 + els_iocb->entry_count = 1;
150 + els_iocb->sys_define = 0;
151 + els_iocb->entry_status = 0;
152 + els_iocb->nport_handle = cpu_to_le16(fcport->loop_id);
153 + els_iocb->tx_dsd_count = __constant_cpu_to_le16(1);
154 + els_iocb->vp_index = ha->vp_idx;
155 + els_iocb->sof_type = EST_SOFI3;
156 + els_iocb->rx_dsd_count = __constant_cpu_to_le16(1);
157 + els_iocb->opcode = 0;
158 + els_iocb->port_id[0] = fcport->d_id.b.al_pa;
159 + els_iocb->port_id[1] = fcport->d_id.b.area;
160 + els_iocb->port_id[2] = fcport->d_id.b.domain;
161 + els_iocb->control_flags = __constant_cpu_to_le16(0);
162 + els_iocb->rx_byte_count = cpu_to_le32(PAGE_SIZE);
163 + els_iocb->tx_byte_count = cpu_to_le32(count);
164 + els_iocb->tx_address[0] = cpu_to_le32(LSD(ha->pass_thru_dma));
165 + els_iocb->tx_address[1] = cpu_to_le32(MSD(ha->pass_thru_dma));
166 + els_iocb->tx_len = els_iocb->tx_byte_count;
167 + els_iocb->rx_address[0] = cpu_to_le32(LSD(ha->pass_thru_dma));
168 + els_iocb->rx_address[1] = cpu_to_le32(MSD(ha->pass_thru_dma));
169 + els_iocb->rx_len = els_iocb->rx_byte_count;
172 + qla2x00_isp_cmd(ha);
174 + spin_unlock_irqrestore(&ha->hardware_lock, flags);
175 + qla2x00_wait_for_passthru_completion(ha);
180 + ha->pass_thru_cmd_in_process = 0;
181 + spin_unlock_irqrestore(&ha->hardware_lock, flags);
183 + DEBUG2(qla_printk(KERN_WARNING, ha,
184 + "Passthru ELS failed on scsi(%ld)\n", ha->host_no));
188 +static struct bin_attribute sysfs_els_attr = {
191 + .mode = S_IRUSR | S_IWUSR,
192 + .owner = THIS_MODULE,
195 + .read = qla2x00_sysfs_read_els,
196 + .write = qla2x00_sysfs_write_els,
200 +qla2x00_sysfs_read_ct(struct kobject *kobj, struct bin_attribute *bin_attr,
201 + char *buf, loff_t off, size_t count)
203 + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
204 + struct device, kobj)));
206 + if (!IS_FWI2_CAPABLE(ha))
209 + if (!ha->pass_thru_cmd_in_process || !ha->pass_thru_cmd_result) {
210 + DEBUG2(qla_printk(KERN_WARNING, ha,
211 + "Passthru CT response is not available.\n"));
215 + memcpy(buf, ha->pass_thru, count);
217 + ha->pass_thru_cmd_result = 0;
218 + ha->pass_thru_cmd_in_process = 0;
224 +qla2x00_sysfs_write_ct(struct kobject *kobj, struct bin_attribute *bin_attr,
225 + char *buf, loff_t off, size_t count)
227 + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
228 + struct device, kobj)));
229 + struct fc_ct_request *request = (struct fc_ct_request *) buf;
230 + struct ct_entry_24xx *ct_iocb;
231 + unsigned long flags;
233 + if (!IS_FWI2_CAPABLE(ha) ||
234 + atomic_read(&ha->loop_state) != LOOP_READY)
237 + if (count < sizeof(request->ct_iu)) {
238 + DEBUG2(qla_printk(KERN_WARNING, ha,
239 + "Passthru CT buffer insufficient size %ld...\n", count));
243 + if (ha->pass_thru_cmd_in_process || ha->pass_thru_cmd_result) {
244 + DEBUG2(qla_printk(KERN_WARNING, ha,
245 + "Passthru CT request is already progress\n"));
249 + if (qla2x00_mgmt_svr_login(ha)) {
250 + DEBUG2(qla_printk(KERN_WARNING, ha,
251 + "Passthru CT request failed to login management server\n"));
255 + ha->pass_thru_cmd_in_process = 1;
256 + spin_lock_irqsave(&ha->hardware_lock, flags);
258 + ct_iocb = (void *)qla2x00_req_pkt(ha);
259 + if (ct_iocb == NULL) {
260 + DEBUG2(qla_printk(KERN_WARNING, ha,
261 + "Passthru CT request failed to get request packet\n"));
265 + if (count > PAGE_SIZE) {
266 + DEBUG2(qla_printk(KERN_INFO, ha,
267 + "Passthru CT request excessive size %ld...\n", count));
271 + memset(ha->pass_thru, 0, PAGE_SIZE);
272 + memcpy(ha->pass_thru, &request->ct_iu, count);
274 + ct_iocb->entry_type = CT_IOCB_TYPE;
275 + ct_iocb->entry_count = 1;
276 + ct_iocb->entry_status = 0;
277 + ct_iocb->comp_status = __constant_cpu_to_le16(0);
278 + ct_iocb->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id);
279 + ct_iocb->cmd_dsd_count = __constant_cpu_to_le16(1);
280 + ct_iocb->vp_index = ha->vp_idx;
281 + ct_iocb->timeout = __constant_cpu_to_le16(25);
282 + ct_iocb->rsp_dsd_count = __constant_cpu_to_le16(1);
283 + ct_iocb->rsp_byte_count = cpu_to_le32(PAGE_SIZE);
284 + ct_iocb->cmd_byte_count = cpu_to_le32(count);
285 + ct_iocb->dseg_0_address[0] = cpu_to_le32(LSD(ha->pass_thru_dma));
286 + ct_iocb->dseg_0_address[1] = cpu_to_le32(MSD(ha->pass_thru_dma));
287 + ct_iocb->dseg_0_len = ct_iocb->cmd_byte_count;
288 + ct_iocb->dseg_1_address[0] = cpu_to_le32(LSD(ha->pass_thru_dma));
289 + ct_iocb->dseg_1_address[1] = cpu_to_le32(MSD(ha->pass_thru_dma));
290 + ct_iocb->dseg_1_len = ct_iocb->rsp_byte_count;
293 + qla2x00_isp_cmd(ha);
295 + spin_unlock_irqrestore(&ha->hardware_lock, flags);
296 + qla2x00_wait_for_passthru_completion(ha);
301 + ha->pass_thru_cmd_in_process = 0;
302 + spin_unlock_irqrestore(&ha->hardware_lock, flags);
304 + DEBUG2(qla_printk(KERN_WARNING, ha,
305 + "Passthru CT failed on scsi(%ld)\n", ha->host_no));
309 +static struct bin_attribute sysfs_ct_attr = {
312 + .mode = S_IRUSR | S_IWUSR,
313 + .owner = THIS_MODULE,
316 + .read = qla2x00_sysfs_read_ct,
317 + .write = qla2x00_sysfs_write_ct,
320 static struct sysfs_entry {
322 struct bin_attribute *attr;
323 @@ -465,6 +746,8 @@ static struct sysfs_entry {
324 { "optrom_ctl", &sysfs_optrom_ctl_attr, },
325 { "vpd", &sysfs_vpd_attr, 1 },
326 { "sfp", &sysfs_sfp_attr, 1 },
327 + { "els", &sysfs_els_attr, 1 },
328 + { "ct", &sysfs_ct_attr, 1 },
332 @@ -797,6 +1080,27 @@ qla2x00_total_isp_aborts_show(struct device *dev,
333 ha->qla_stats.total_isp_aborts);
337 +qla24xx_84xx_fw_version_show(struct device *dev,
338 + struct device_attribute *attr, char *buf)
340 + int rval = QLA_SUCCESS;
341 + uint16_t status[2] = {0, 0};
342 + scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
344 + if (IS_QLA84XX(ha) && ha->cs84xx) {
345 + if (ha->cs84xx->op_fw_version == 0) {
346 + rval = qla84xx_verify_chip(ha, status);
349 + if ((rval == QLA_SUCCESS) && (status[0] == 0))
350 + return snprintf(buf, PAGE_SIZE, "%u\n",
351 + (uint32_t)ha->cs84xx->op_fw_version);
354 + return snprintf(buf, PAGE_SIZE, "\n");
357 static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
358 static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
359 static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
360 @@ -821,6 +1125,8 @@ static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show,
362 static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show,
364 +static DEVICE_ATTR(84xx_fw_version, S_IRUGO, qla24xx_84xx_fw_version_show,
367 struct device_attribute *qla2x00_host_attrs[] = {
368 &dev_attr_driver_version,
369 @@ -840,6 +1146,7 @@ struct device_attribute *qla2x00_host_attrs[] = {
370 &dev_attr_optrom_fcode_version,
371 &dev_attr_optrom_fw_version,
372 &dev_attr_total_isp_aborts,
373 + &dev_attr_84xx_fw_version,
377 diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
378 index a45e333..851dc96 100644
379 --- a/drivers/scsi/qla2xxx/qla_def.h
380 +++ b/drivers/scsi/qla2xxx/qla_def.h
382 #define LSD(x) ((uint32_t)((uint64_t)(x)))
383 #define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16))
385 +/* ELS PT request buffer = 32 bytes */
386 +#define EXT_ELS_PT_REQ_WWPN_VALID 0x1
387 +#define EXT_ELS_PT_REQ_WWNN_VALID 0x2
388 +#define EXT_ELS_PT_REQ_PID_VALID 0x4
390 +struct ext_els_pt_req {
394 + uint16_t ValidMask;
406 + uint8_t gs_subtype;
410 + uint16_t max_rsp_size;
411 + uint8_t fragment_id;
412 + uint8_t reserved1[3];
415 +/* CT request format */
416 +struct fc_ct_request {
417 + struct ct_iu ct_iu;
421 + uint8_t port_id[3];
433 + uint8_t port_id[3];
434 + uint8_t fc4_types[32];
439 + uint8_t port_id[3];
440 + uint16_t reserved2;
441 + uint8_t fc4_feature;
447 + uint8_t port_id[3];
448 + uint8_t node_name[8];
452 + uint8_t node_name[8];
454 + uint8_t sym_node_name[255];
458 + uint8_t hba_indentifier[8];
463 +/* ELS request format */
464 +struct els_request {
465 + struct ext_els_pt_req header;
466 + struct ct_iu ct_iu;
471 @@ -2161,6 +2244,14 @@ struct qla_statistics {
472 uint64_t output_bytes;
475 +#include "qla_nlnk.h"
476 +/* place holder for fw buffer parameters for netlink */
484 * Linux Host Adapter structure
486 @@ -2426,6 +2517,8 @@ typedef struct scsi_qla_host {
487 /* SNS command interfaces for 2200. */
488 struct sns_cmd_pkt *sns_cmd;
489 dma_addr_t sns_cmd_dma;
491 + dma_addr_t pass_thru_dma;
493 #define SFP_DEV_SIZE 256
494 #define SFP_BLOCK_SIZE 64
495 @@ -2467,6 +2560,7 @@ typedef struct scsi_qla_host {
496 struct mutex vport_lock; /* Virtual port synchronization */
497 struct completion mbx_cmd_comp; /* Serialize mbx access */
498 struct completion mbx_intr_comp; /* Used for completion notification */
499 + struct completion pass_thru_intr_comp; /* For pass thru notification */
502 #define MBX_IN_PROGRESS BIT_0
503 @@ -2608,8 +2702,13 @@ typedef struct scsi_qla_host {
504 uint16_t max_npiv_vports; /* 63 or 125 per topoloty */
507 + /* pass throuth support */
508 + int pass_thru_cmd_result;
509 + int pass_thru_cmd_in_process;
511 struct qla_chip_state_84xx *cs84xx;
512 struct qla_statistics qla_stats;
513 + struct qlfc_fw fw_buf;
517 diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
518 index d1d1420..0ccf534 100644
519 --- a/drivers/scsi/qla2xxx/qla_fw.h
520 +++ b/drivers/scsi/qla2xxx/qla_fw.h
521 @@ -1212,9 +1212,10 @@ struct qla_fdt_layout {
523 struct qla_flt_location {
535 diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
536 index 753dbe6..de1efc6 100644
537 --- a/drivers/scsi/qla2xxx/qla_gbl.h
538 +++ b/drivers/scsi/qla2xxx/qla_gbl.h
539 @@ -121,6 +121,8 @@ extern int qla2x00_start_scsi(srb_t *sp);
540 extern int qla24xx_start_scsi(srb_t *sp);
541 int qla2x00_marker(scsi_qla_host_t *, uint16_t, uint16_t, uint8_t);
542 int __qla2x00_marker(scsi_qla_host_t *, uint16_t, uint16_t, uint8_t);
543 +extern request_t *qla2x00_req_pkt(scsi_qla_host_t *);
544 +extern void qla2x00_isp_cmd(scsi_qla_host_t *ha);
547 * Global Function Prototypes in qla_mbx.c source file.
548 @@ -154,6 +156,10 @@ extern int
549 qla2x00_issue_iocb(scsi_qla_host_t *, void *, dma_addr_t, size_t);
552 +qla2x00_issue_iocb_timeout(scsi_qla_host_t *, void *, dma_addr_t, size_t,
556 qla2x00_abort_command(scsi_qla_host_t *, srb_t *);
559 @@ -258,6 +264,8 @@ qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *);
561 extern int qla84xx_verify_chip(struct scsi_qla_host *, uint16_t *);
563 +extern int qla84xx_reset(struct scsi_qla_host *, uint32_t);
566 * Global Function Prototypes in qla_isr.c source file.
568 @@ -327,6 +335,8 @@ extern void qla24xx_fw_dump(scsi_qla_host_t *, int);
569 extern void qla25xx_fw_dump(scsi_qla_host_t *, int);
570 extern void qla2x00_dump_regs(scsi_qla_host_t *);
571 extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
572 +extern void qla2x00_print_byte_buf(void *, size_t, size_t);
573 +extern void qla2x00_print_word_buf(void *, size_t, size_t);
576 * Global Function Prototypes in qla_gs.c source file.
577 @@ -347,6 +357,7 @@ extern int qla2x00_fdmi_register(scsi_qla_host_t *);
578 extern int qla2x00_gfpn_id(scsi_qla_host_t *, sw_info_t *);
579 extern int qla2x00_gpsc(scsi_qla_host_t *, sw_info_t *);
580 extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *);
581 +extern int qla2x00_mgmt_svr_login(scsi_qla_host_t *);
584 * Global Function Prototypes in qla_attr.c source file.
585 @@ -363,6 +374,13 @@ extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
586 extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
589 + * Global functions in qla_nlk.c
591 +extern int ql_nl_register(void);
592 +extern void ql_nl_unregister(void);
593 +extern void qla_free_nlnk_dmabuf(scsi_qla_host_t *);
596 * Global Function Prototypes in qla_dfs.c source file.
598 extern int qla2x00_dfs_setup(scsi_qla_host_t *);
599 diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
600 index c2a4bfb..ceef231 100644
601 --- a/drivers/scsi/qla2xxx/qla_gs.c
602 +++ b/drivers/scsi/qla2xxx/qla_gs.c
603 @@ -1093,7 +1093,7 @@ qla2x00_sns_rnn_id(scsi_qla_host_t *ha)
605 * Returns 0 on success.
609 qla2x00_mgmt_svr_login(scsi_qla_host_t *ha)
612 diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
613 index ad2dd8c..407e87a 100644
614 --- a/drivers/scsi/qla2xxx/qla_init.c
615 +++ b/drivers/scsi/qla2xxx/qla_init.c
616 @@ -1241,8 +1241,11 @@ qla2x00_init_rings(scsi_qla_host_t *ha)
618 DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no));
620 - if (ha->flags.npiv_supported)
621 + if (ha->flags.npiv_supported) {
622 + if (ha->operating_mode == LOOP)
623 + ha->max_npiv_vports = MIN_MULTI_ID_FABRIC - 1;
624 mid_init_cb->count = cpu_to_le16(ha->max_npiv_vports);
627 mid_init_cb->options = __constant_cpu_to_le16(BIT_1);
629 diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
630 index 85bc0a4..352517d 100644
631 --- a/drivers/scsi/qla2xxx/qla_iocb.c
632 +++ b/drivers/scsi/qla2xxx/qla_iocb.c
635 #include <scsi/scsi_tcq.h>
637 -static request_t *qla2x00_req_pkt(scsi_qla_host_t *ha);
638 -static void qla2x00_isp_cmd(scsi_qla_host_t *ha);
641 * qla2x00_get_cmd_direction() - Determine control_flag data direction.
642 @@ -476,7 +474,7 @@ qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun,
644 * Returns NULL if function failed, else, a pointer to the request packet.
648 qla2x00_req_pkt(scsi_qla_host_t *ha)
650 device_reg_t __iomem *reg = ha->iobase;
651 @@ -546,7 +544,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha)
653 * Note: The caller must hold the hardware lock before calling this routine.
657 qla2x00_isp_cmd(scsi_qla_host_t *ha)
659 device_reg_t __iomem *reg = ha->iobase;
660 diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
661 index a76efd9..758d0ee 100644
662 --- a/drivers/scsi/qla2xxx/qla_isr.c
663 +++ b/drivers/scsi/qla2xxx/qla_isr.c
664 @@ -1443,6 +1443,27 @@ qla24xx_process_response_queue(struct scsi_qla_host *ha)
665 case STATUS_CONT_TYPE:
666 qla2x00_status_cont_entry(ha, (sts_cont_entry_t *)pkt);
669 + if (ha->pass_thru_cmd_result)
670 + DEBUG2(qla_printk(KERN_INFO, ha,
671 + "Passthru cmd result on.\n"));
672 + if (!ha->pass_thru_cmd_in_process)
673 + DEBUG2(qla_printk(KERN_INFO, ha,
674 + "Passthru in process off.\n"));
676 + ha->pass_thru_cmd_result = 1;
677 + complete(&ha->pass_thru_intr_comp);
679 + case ELS_IOCB_TYPE:
680 + if (ha->pass_thru_cmd_result)
681 + DEBUG2(qla_printk(KERN_INFO, ha,
682 + "Passthru cmd result on.\n"));
683 + if (!ha->pass_thru_cmd_in_process)
684 + DEBUG2(qla_printk(KERN_INFO, ha,
685 + "Passthru in process off.\n"));
687 + ha->pass_thru_cmd_result = 1;
688 + complete(&ha->pass_thru_intr_comp);
689 case VP_RPT_ID_IOCB_TYPE:
690 qla24xx_report_id_acquisition(ha,
691 (struct vp_rpt_id_entry_24xx *)pkt);
692 diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
693 index 3402746..9d78629 100644
694 --- a/drivers/scsi/qla2xxx/qla_mbx.c
695 +++ b/drivers/scsi/qla2xxx/qla_mbx.c
696 @@ -681,7 +681,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
702 qla2x00_issue_iocb_timeout(scsi_qla_host_t *ha, void *buffer,
703 dma_addr_t phys_addr, size_t size, uint32_t tov)
705 @@ -2946,6 +2946,33 @@ qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr,
707 /* 84XX Support **************************************************************/
711 + * Resets the QLA8432
714 +qla84xx_reset(struct scsi_qla_host *ha, uint32_t diag_fw)
718 + mbx_cmd_t *mcp = &mc;
720 + mcp->mb[0] = MBC_ISP84XX_RESET;
721 + mcp->mb[1] = diag_fw;
722 + mcp->out_mb = MBX_1 | MBX_0;
723 + mcp->in_mb = MBX_1 | MBX_0;
724 + mcp->tov = MBX_TOV_SECONDS;
727 + rval = qla2x00_mailbox_command(ha, mcp);
729 + if (rval != QLA_SUCCESS)
730 + DEBUG2_16(printk("%s(%ld): failed mb[0]=0x%x mb[1]=0x%x\n",
731 + __func__, ha->host_no, mcp->mb[0], mcp->mb[1]));
736 struct cs84xx_mgmt_cmd {
738 struct verify_chip_entry_84xx req;
739 diff --git a/drivers/scsi/qla2xxx/qla_nlnk.c b/drivers/scsi/qla2xxx/qla_nlnk.c
741 index 0000000..2ab339d
743 +++ b/drivers/scsi/qla2xxx/qla_nlnk.c
746 + * QLogic Fibre Channel HBA Driver
747 + * Copyright (c) 2003-2005 QLogic Corporation
749 + * See LICENSE.qla2xxx for copyright and licensing details.
752 +#include "qla_def.h"
753 +#include <net/sock.h>
754 +#include <net/netlink.h>
755 +#include "qla_nlnk.h"
757 +static struct sock *ql_fc_nl_sock = NULL;
758 +static int ql_fc_nl_event(struct notifier_block *this,
759 + unsigned long event, void *ptr);
761 +static struct notifier_block ql_fc_nl_notifier = {
762 + .notifier_call = ql_fc_nl_event,
768 +static int ql_fc_proc_nl_rcv_msg(struct sk_buff *skb,
769 + struct nlmsghdr *nlh, int rcvlen);
770 +static int ql_fc_nl_rsp(uint32_t pid, uint32_t seq, uint32_t type,
771 + void *hdr, int hdr_len, void *payload, int size);
773 +static int qla84xx_update_fw(struct scsi_qla_host *ha, int rlen,
774 + struct msg_update_fw *upd_fw)
776 + struct qlfc_fw *qlfw;
777 + struct verify_chip_entry_84xx *mn;
783 + if (rlen < (sizeof(struct msg_update_fw) + upd_fw->len +
784 + offsetof(struct qla_fc_msg, u))){
785 + DEBUG2_16(printk(KERN_ERR "%s(%lu): invalid len\n",
786 + __func__, ha->host_no));
790 + qlfw = &ha->fw_buf;
791 + if (!upd_fw->offset) {
792 + if (qlfw->fw_buf || !upd_fw->fw_len ||
793 + upd_fw->len > upd_fw->fw_len) {
794 + DEBUG2_16(printk(KERN_ERR "%s(%lu): invalid offset or "
795 + "fw_len\n", __func__, ha->host_no));
798 + qlfw->fw_buf = dma_alloc_coherent(&ha->pdev->dev,
799 + upd_fw->fw_len, &qlfw->fw_dma,
801 + if (qlfw->fw_buf == NULL) {
802 + DEBUG2_16(printk(KERN_ERR "%s: dma alloc "
803 + "failed%lu\n", __func__, ha->host_no));
806 + qlfw->len = upd_fw->fw_len;
808 + fw_ver = le32_to_cpu(*((uint32_t *)
809 + ((uint32_t *)upd_fw->fw_bytes + 2)));
811 + DEBUG2_16(printk(KERN_ERR "%s(%lu): invalid fw "
812 + "revision 0x%x\n", __func__, ha->host_no, fw_ver));
816 + /* make sure we have a buffer allocated */
817 + if (!qlfw->fw_buf || upd_fw->fw_len != qlfw->len ||
818 + ((upd_fw->offset + upd_fw->len) > upd_fw->fw_len)){
819 + DEBUG2_16(printk(KERN_ERR "%s(%lu): invalid size of "
820 + "offset=0 expected\n", __func__, ha->host_no));
824 + /* Copy the firmware into DMA Buffer */
825 + memcpy(((uint8_t *)qlfw->fw_buf + upd_fw->offset),
826 + upd_fw->fw_bytes, upd_fw->len);
828 + if ((upd_fw->offset+upd_fw->len) != qlfw->len)
831 + mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
833 + DEBUG2_16(printk(KERN_ERR "%s: dma alloc for fw buffer "
834 + "failed%lu\n", __func__, ha->host_no));
838 + fw_ver = le32_to_cpu(*((uint32_t *)((uint32_t *)qlfw->fw_buf + 2)));
840 + /* Create iocb and issue it */
841 + memset(mn, 0, sizeof(*mn));
843 + mn->entry_type = VERIFY_CHIP_IOCB_TYPE;
844 + mn->entry_count = 1;
846 + options = VCO_FORCE_UPDATE | VCO_END_OF_DATA;
847 + if (upd_fw->diag_fw)
848 + options |= VCO_DIAG_FW;
849 + mn->options = cpu_to_le16(options);
851 + mn->fw_ver = cpu_to_le32(fw_ver);
852 + mn->fw_size = cpu_to_le32(qlfw->len);
853 + mn->fw_seq_size = cpu_to_le32(qlfw->len);
855 + mn->dseg_address[0] = cpu_to_le32(LSD(qlfw->fw_dma));
856 + mn->dseg_address[1] = cpu_to_le32(MSD(qlfw->fw_dma));
857 + mn->dseg_length = cpu_to_le32(qlfw->len);
858 + mn->data_seg_cnt = cpu_to_le16(1);
860 + ret = qla2x00_issue_iocb_timeout(ha, mn, mn_dma, 0, 120);
862 + if (ret != QLA_SUCCESS) {
863 + DEBUG2_16(printk(KERN_ERR "%s(%lu): failed\n", __func__,
867 + qla_free_nlnk_dmabuf(ha);
872 +qla84xx_mgmt_cmd(scsi_qla_host_t *ha, struct qla_fc_msg *cmd, int rlen,
873 + uint32_t pid, uint32_t seq, uint32_t type)
875 + struct access_chip_84xx *mn;
876 + dma_addr_t mn_dma, mgmt_dma;
877 + void *mgmt_b = NULL;
879 + int rsp_hdr_len, len = 0;
880 + struct qla84_msg_mgmt *ql84_mgmt;
882 + ql84_mgmt = &cmd->u.utok.mgmt;
883 + rsp_hdr_len = offsetof(struct qla_fc_msg, u) +
884 + offsetof(struct qla84_msg_mgmt, payload);
886 + mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
888 + DEBUG2_16(printk(KERN_ERR "%s: dma alloc for fw buffer "
889 + "failed%lu\n", __FUNCTION__, ha->host_no));
893 + memset(mn, 0, sizeof (struct access_chip_84xx));
895 + mn->entry_type = ACCESS_CHIP_IOCB_TYPE;
896 + mn->entry_count = 1;
898 + switch (ql84_mgmt->cmd) {
899 + case QLA84_MGMT_READ_MEM:
900 + mn->options = cpu_to_le16(ACO_DUMP_MEMORY);
901 + mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.mem.start_addr);
903 + case QLA84_MGMT_WRITE_MEM:
904 + if (rlen < (sizeof(struct qla84_msg_mgmt) + ql84_mgmt->len +
905 + offsetof(struct qla_fc_msg, u))){
909 + mn->options = cpu_to_le16(ACO_LOAD_MEMORY);
910 + mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.mem.start_addr);
912 + case QLA84_MGMT_CHNG_CONFIG:
913 + mn->options = cpu_to_le16(ACO_CHANGE_CONFIG_PARAM);
914 + mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.id);
915 + mn->parameter2 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.param0);
916 + mn->parameter3 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.param1);
918 + case QLA84_MGMT_GET_INFO:
919 + mn->options = cpu_to_le16(ACO_REQUEST_INFO);
920 + mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.info.type);
921 + mn->parameter2 = cpu_to_le32(ql84_mgmt->mgmtp.u.info.context);
928 + if ((len = ql84_mgmt->len) && ql84_mgmt->cmd != QLA84_MGMT_CHNG_CONFIG) {
929 + mgmt_b = dma_alloc_coherent(&ha->pdev->dev, len,
930 + &mgmt_dma, GFP_KERNEL);
931 + if (mgmt_b == NULL) {
932 + DEBUG2_16(printk(KERN_ERR "%s: dma alloc mgmt_b "
933 + "failed%lu\n", __func__, ha->host_no));
937 + mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->len);
938 + mn->dseg_count = cpu_to_le16(1);
939 + mn->dseg_address[0] = cpu_to_le32(LSD(mgmt_dma));
940 + mn->dseg_address[1] = cpu_to_le32(MSD(mgmt_dma));
941 + mn->dseg_length = cpu_to_le32(len);
943 + if (ql84_mgmt->cmd == QLA84_MGMT_WRITE_MEM) {
944 + memcpy(mgmt_b, ql84_mgmt->payload, len);
948 + ret = qla2x00_issue_iocb(ha, mn, mn_dma, 0);
951 + if ((ret != QLA_SUCCESS) ||
952 + (ql84_mgmt->cmd == QLA84_MGMT_WRITE_MEM) ||
953 + (ql84_mgmt->cmd == QLA84_MGMT_CHNG_CONFIG)) {
954 + if (ret != QLA_SUCCESS)
955 + DEBUG2_16(printk(KERN_ERR "%s(%lu): failed\n",
956 + __func__, ha->host_no));
957 + ret = ql_fc_nl_rsp(pid, seq, type, cmd, rsp_hdr_len, NULL, 0);
958 + } else if ((ql84_mgmt->cmd == QLA84_MGMT_READ_MEM)||
959 + (ql84_mgmt->cmd == QLA84_MGMT_GET_INFO)) {
960 + ret = ql_fc_nl_rsp(pid, seq, type, cmd, rsp_hdr_len, mgmt_b, len);
964 + dma_free_coherent(&ha->pdev->dev, len, mgmt_b, mgmt_dma);
967 + dma_pool_free(ha->s_dma_pool, mn, mn_dma);
972 + * Netlink Interface Related Functions
976 +ql_fc_nl_rcv_msg(struct sk_buff *skb)
978 + struct nlmsghdr *nlh;
979 + struct scsi_nl_hdr *snlh;
983 + while (skb->len >= NLMSG_SPACE(0)) {
986 + nlh = (struct nlmsghdr *) skb->data;
988 + if ((nlh->nlmsg_len < (sizeof(*nlh) + sizeof(*snlh))) ||
989 + (skb->len < nlh->nlmsg_len)) {
990 + DEBUG2_16(printk(KERN_WARNING "%s: discarding partial "
991 + "skb\n", __FUNCTION__));
995 + rlen = NLMSG_ALIGN(nlh->nlmsg_len);
996 + if (rlen > skb->len) {
997 + DEBUG2_16(printk(KERN_WARNING "%s: rlen > skb->len\n",
1002 + if (nlh->nlmsg_type != FC_TRANSPORT_MSG) {
1003 + DEBUG2_16(printk(KERN_WARNING "%s: Not "
1004 + "FC_TRANSPORT_MSG\n", __FUNCTION__));
1009 + snlh = NLMSG_DATA(nlh);
1010 + if ((snlh->version != SCSI_NL_VERSION) ||
1011 + (snlh->magic != SCSI_NL_MAGIC)) {
1012 + DEBUG2_16(printk(KERN_WARNING "%s: Bad Version or "
1013 + "Magic number\n", __FUNCTION__));
1014 + err = -EPROTOTYPE;
1017 + err = ql_fc_proc_nl_rcv_msg(skb, nlh, rlen);
1020 + netlink_ack(skb, nlh, err);
1021 + skb_pull(skb, rlen);
1026 +ql_fc_proc_nl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int rcvlen)
1028 + struct scsi_nl_hdr *snlh;
1029 + struct qla_fc_msg *ql_cmd;
1030 + struct Scsi_Host *shost;
1031 + struct scsi_qla_host *ha;
1035 + snlh = NLMSG_DATA(nlh);
1037 + /* Only vendor specific commands are supported */
1038 + if (!(snlh->msgtype & FC_NL_VNDR_SPECIFIC))
1041 + ql_cmd = (struct qla_fc_msg *)((char *)snlh + sizeof (struct scsi_nl_hdr));
1043 + if (ql_cmd->magic != QL_FC_NL_MAGIC)
1046 + shost = scsi_host_lookup(ql_cmd->host_no);
1047 + if (IS_ERR(shost)) {
1048 + DEBUG2_16(printk(KERN_ERR "%s: could not find host no %u\n",
1049 + __FUNCTION__, ql_cmd->host_no));
1051 + goto exit_proc_nl_rcv_msg;
1054 + ha = (struct scsi_qla_host *)shost->hostdata;
1056 + if (!ha || (!IS_QLA84XX(ha) && (ql_cmd->cmd != QLFC_GET_AEN))) {
1057 + DEBUG2_16(printk(KERN_ERR "%s: invalid host ha = %p dtype = "
1058 + "0x%x\n", __FUNCTION__, ha, (ha ? DT_MASK(ha): ~0)));
1060 + goto exit_proc_nl_rcv_msg;
1063 + switch (ql_cmd->cmd) {
1067 + rsp_hdr_len = offsetof(struct qla_fc_msg, u);
1068 + err = qla84xx_reset(ha, ql_cmd->u.utok.qla84_reset.diag_fw);
1069 + ql_cmd->error = err;
1071 + err = ql_fc_nl_rsp(NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
1072 + (uint32_t)nlh->nlmsg_type, ql_cmd, rsp_hdr_len, NULL, 0);
1075 + case QLA84_UPDATE_FW:
1076 + rsp_hdr_len = offsetof(struct qla_fc_msg, u);
1077 + err = qla84xx_update_fw(ha, (rcvlen - sizeof(struct scsi_nl_hdr)),
1078 + &ql_cmd->u.utok.qla84_update_fw);
1079 + ql_cmd->error = err;
1081 + err = ql_fc_nl_rsp(NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
1082 + (uint32_t)nlh->nlmsg_type, ql_cmd, rsp_hdr_len, NULL, 0);
1085 + case QLA84_MGMT_CMD:
1086 + err = qla84xx_mgmt_cmd(ha, ql_cmd,
1087 + (rcvlen - sizeof(struct scsi_nl_hdr)),
1088 + NETLINK_CREDS(skb)->pid,
1089 + nlh->nlmsg_seq, (uint32_t)nlh->nlmsg_type);
1095 +exit_proc_nl_rcv_msg:
1100 +ql_fc_nl_event(struct notifier_block *this, unsigned long event, void *ptr)
1102 + DEBUG16(printk(KERN_WARNING "%s: event 0x%lx ptr = %p\n", __func__,
1104 + return NOTIFY_DONE;
1108 +ql_fc_nl_rsp(uint32_t pid, uint32_t seq, uint32_t type, void *hdr, int hdr_len,
1109 + void *payload, int size)
1111 + struct sk_buff *skb;
1112 + struct nlmsghdr *nlh;
1114 + int len = NLMSG_SPACE(size + hdr_len);
1116 + skb = alloc_skb(len, GFP_ATOMIC);
1118 + DEBUG2_16(printk(KERN_ERR "%s: Could not alloc skb\n",
1122 + nlh = __nlmsg_put(skb, pid, seq, type, (len - sizeof(*nlh)), 0);
1123 + nlh->nlmsg_flags = 0;
1124 + memcpy(NLMSG_DATA(nlh), hdr, hdr_len);
1127 + memcpy((void *)((char *)(NLMSG_DATA(nlh)) + hdr_len), payload, size);
1129 + rc = netlink_unicast(ql_fc_nl_sock, skb, pid, MSG_DONTWAIT);
1131 + DEBUG2_16(printk(KERN_ERR "%s: netlink_unicast failed\n",
1138 +void qla_free_nlnk_dmabuf(scsi_qla_host_t *ha)
1140 + struct qlfc_fw *qlfw;
1142 + qlfw = &ha->fw_buf;
1144 + if (qlfw->fw_buf) {
1145 + dma_free_coherent(&ha->pdev->dev, qlfw->len, qlfw->fw_buf,
1147 + memset(qlfw, 0, sizeof(struct qlfc_fw));
1152 +ql_nl_register(void)
1156 + error = netlink_register_notifier(&ql_fc_nl_notifier);
1159 + ql_fc_nl_sock = netlink_kernel_create(&init_net,
1160 + NETLINK_FCTRANSPORT, QL_FC_NL_GROUP_CNT, ql_fc_nl_rcv_msg,
1161 + NULL, THIS_MODULE);
1163 + if (!ql_fc_nl_sock) {
1164 + netlink_unregister_notifier(&ql_fc_nl_notifier);
1174 + if (ql_fc_nl_sock) {
1175 + sock_release(ql_fc_nl_sock->sk_socket);
1176 + netlink_unregister_notifier(&ql_fc_nl_notifier);
1179 diff --git a/drivers/scsi/qla2xxx/qla_nlnk.h b/drivers/scsi/qla2xxx/qla_nlnk.h
1180 new file mode 100644
1181 index 0000000..d1488a6
1183 +++ b/drivers/scsi/qla2xxx/qla_nlnk.h
1186 + * QLogic Fibre Channel HBA Driver
1187 + * Copyright (c) 2003-2005 QLogic Corporation
1189 + * See LICENSE.qla2xxx for copyright and licensing details.
1191 +#ifndef _QLA_NLNK_H_
1192 +#define _QLA_NLNK_H_
1194 +#ifndef NETLINK_FCTRANSPORT
1195 +#define NETLINK_FCTRANSPORT 20
1197 +#define QL_FC_NL_GROUP_CNT 0
1199 +#define FC_TRANSPORT_MSG NLMSG_MIN_TYPE + 1
1202 + * Transport Message Types
1204 +#define FC_NL_VNDR_SPECIFIC 0x8000
1210 +struct qla84_mgmt_param {
1213 + uint32_t start_addr;
1214 + } mem; /* for QLA84_MGMT_READ/WRITE_MEM */
1217 +#define QLA84_MGMT_CONFIG_ID_UIF 1
1218 +#define QLA84_MGMT_CONFIG_ID_FCOE_COS 2
1219 +#define QLA84_MGMT_CONFIG_ID_PAUSE 3
1220 +#define QLA84_MGMT_CONFIG_ID_TIMEOUTS 4
1224 + } config; /* for QLA84_MGMT_CHNG_CONFIG */
1228 +#define QLA84_MGMT_INFO_CONFIG_LOG_DATA 1 /* Get Config Log Data */
1229 +#define QLA84_MGMT_INFO_LOG_DATA 2 /* Get Log Data */
1230 +#define QLA84_MGMT_INFO_PORT_STAT 3 /* Get Port Statistics */
1231 +#define QLA84_MGMT_INFO_LIF_STAT 4 /* Get LIF Statistics */
1232 +#define QLA84_MGMT_INFO_ASIC_STAT 5 /* Get ASIC Statistics */
1233 +#define QLA84_MGMT_INFO_CONFIG_PARAMS 6 /* Get Config Parameters */
1234 +#define QLA84_MGMT_INFO_PANIC_LOG 7 /* Get Panic Log */
1238 + * context definitions for QLA84_MGMT_INFO_CONFIG_LOG_DATA
1240 +#define IC_LOG_DATA_LOG_ID_DEBUG_LOG 0
1241 +#define IC_LOG_DATA_LOG_ID_LEARN_LOG 1
1242 +#define IC_LOG_DATA_LOG_ID_FC_ACL_INGRESS_LOG 2
1243 +#define IC_LOG_DATA_LOG_ID_FC_ACL_EGRESS_LOG 3
1244 +#define IC_LOG_DATA_LOG_ID_ETHERNET_ACL_INGRESS_LOG 4
1245 +#define IC_LOG_DATA_LOG_ID_ETHERNET_ACL_EGRESS_LOG 5
1246 +#define IC_LOG_DATA_LOG_ID_MESSAGE_TRANSMIT_LOG 6
1247 +#define IC_LOG_DATA_LOG_ID_MESSAGE_RECEIVE_LOG 7
1248 +#define IC_LOG_DATA_LOG_ID_LINK_EVENT_LOG 8
1249 +#define IC_LOG_DATA_LOG_ID_DCX_LOG 9
1252 + * context definitions for QLA84_MGMT_INFO_PORT_STAT
1254 +#define IC_PORT_STATISTICS_PORT_NUMBER_ETHERNET_PORT0 0
1255 +#define IC_PORT_STATISTICS_PORT_NUMBER_ETHERNET_PORT1 1
1256 +#define IC_PORT_STATISTICS_PORT_NUMBER_NSL_PORT0 2
1257 +#define IC_PORT_STATISTICS_PORT_NUMBER_NSL_PORT1 3
1258 +#define IC_PORT_STATISTICS_PORT_NUMBER_FC_PORT0 4
1259 +#define IC_PORT_STATISTICS_PORT_NUMBER_FC_PORT1 5
1263 + * context definitions for QLA84_MGMT_INFO_LIF_STAT
1265 +#define IC_LIF_STATISTICS_LIF_NUMBER_ETHERNET_PORT0 0
1266 +#define IC_LIF_STATISTICS_LIF_NUMBER_ETHERNET_PORT1 1
1267 +#define IC_LIF_STATISTICS_LIF_NUMBER_FC_PORT0 2
1268 +#define IC_LIF_STATISTICS_LIF_NUMBER_FC_PORT1 3
1269 +#define IC_LIF_STATISTICS_LIF_NUMBER_CPU 6
1271 + } info; /* for QLA84_MGMT_GET_INFO */
1275 +#define QLFC_MAX_AEN 256
1276 +struct qlfc_aen_entry {
1277 + uint16_t event_code;
1278 + uint16_t payload[3];
1281 +struct qlfc_aen_log {
1282 + uint32_t num_events;
1283 + struct qlfc_aen_entry aen[QLFC_MAX_AEN];
1286 +struct qla84_msg_mgmt {
1288 +#define QLA84_MGMT_READ_MEM 0x00
1289 +#define QLA84_MGMT_WRITE_MEM 0x01
1290 +#define QLA84_MGMT_CHNG_CONFIG 0x02
1291 +#define QLA84_MGMT_GET_INFO 0x03
1293 + struct qla84_mgmt_param mgmtp;/* parameters for cmd */
1294 + uint32_t len; /* bytes in payload following this struct */
1295 + uint8_t payload[0]; /* payload for cmd */
1298 +struct msg_update_fw {
1300 + * diag_fw = 0 operational fw
1301 + * otherwise diagnostic fw
1302 + * offset, len, fw_len are present to overcome the current limitation
1303 + * of 128Kb xfer size. The fw is sent in smaller chunks. Each chunk
1304 + * specifies the byte "offset" where it fits in the fw buffer. The
1305 + * number of bytes in each chunk is specified in "len". "fw_len"
1306 + * is the total size of fw. The first chunk should start at offset = 0.
1307 + * When offset+len == fw_len, the fw is written to the HBA.
1310 + uint32_t offset;/* start offset */
1311 + uint32_t len; /* num bytes in cur xfer */
1312 + uint32_t fw_len; /* size of fw in bytes */
1313 + uint8_t fw_bytes[0];
1316 +struct qla_fc_msg {
1319 +#define QL_FC_NL_MAGIC 0x107784DDFCAB1FC1
1321 + uint16_t vmsg_datalen;
1324 +#define QLA84_RESET 0x01
1325 +#define QLA84_UPDATE_FW 0x02
1326 +#define QLA84_MGMT_CMD 0x03
1327 +#define QLFC_GET_AEN 0x04
1329 + uint32_t error; /* interface or resource error holder*/
1333 + struct msg_reset {
1335 + * diag_fw = 0 for operational fw
1336 + * otherwise diagnostic fw
1341 + struct msg_update_fw qla84_update_fw;
1342 + struct qla84_msg_mgmt mgmt;
1346 + struct qla84_msg_mgmt mgmt;
1347 + struct qlfc_aen_log aen_log;
1350 +} __attribute__ ((aligned (sizeof(uint64_t))));
1352 +#endif /* _QLA_NLNK_H_ */
1353 diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
1354 index 4774acb..70d03a8 100644
1355 --- a/drivers/scsi/qla2xxx/qla_os.c
1356 +++ b/drivers/scsi/qla2xxx/qla_os.c
1357 @@ -1670,6 +1670,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
1358 init_completion(&ha->mbx_cmd_comp);
1359 complete(&ha->mbx_cmd_comp);
1360 init_completion(&ha->mbx_intr_comp);
1361 + init_completion(&ha->pass_thru_intr_comp);
1363 INIT_LIST_HEAD(&ha->list);
1364 INIT_LIST_HEAD(&ha->fcports);
1365 @@ -1790,6 +1791,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
1367 qla2x00_free_sysfs_attr(ha);
1369 + qla_free_nlnk_dmabuf(ha);
1371 fc_remove_host(ha->host);
1373 scsi_remove_host(ha->host);
1374 @@ -2020,10 +2023,19 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
1375 sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, GFP_KERNEL);
1377 goto fail_free_ms_iocb;
1378 + /*Get consistent memory allocated for pass-thru commands */
1379 + ha->pass_thru = dma_alloc_coherent(&ha->pdev->dev,
1380 + PAGE_SIZE, &ha->pass_thru_dma, GFP_KERNEL);
1381 + if (!ha->pass_thru)
1382 + goto fail_free_ct_sns;
1388 + dma_pool_free(ha->s_dma_pool, ha->ct_sns, ha->ct_sns_dma);
1389 + ha->ct_sns = NULL;
1390 + ha->ct_sns_dma = 0;
1392 dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
1394 @@ -2092,6 +2104,10 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
1395 dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),
1396 ha->sns_cmd, ha->sns_cmd_dma);
1398 + if (ha->pass_thru)
1399 + dma_free_coherent(&ha->pdev->dev, PAGE_SIZE,
1400 + ha->pass_thru, ha->pass_thru_dma);
1403 dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt),
1404 ha->ct_sns, ha->ct_sns_dma);
1405 @@ -2130,6 +2146,8 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
1406 ha->sns_cmd_dma = 0;
1409 + ha->pass_thru = NULL;
1410 + ha->pass_thru_dma = 0;
1412 ha->ms_iocb_dma = 0;
1414 @@ -2903,10 +2921,18 @@ qla2x00_module_init(void)
1418 + if (ql_nl_register()) {
1419 + kmem_cache_destroy(srb_cachep);
1420 + fc_release_transport(qla2xxx_transport_template);
1421 + fc_release_transport(qla2xxx_transport_vport_template);
1425 printk(KERN_INFO "QLogic Fibre Channel HBA Driver: %s\n",
1426 qla2x00_version_str);
1427 ret = pci_register_driver(&qla2xxx_pci_driver);
1429 + ql_nl_unregister();
1430 kmem_cache_destroy(srb_cachep);
1431 fc_release_transport(qla2xxx_transport_template);
1432 fc_release_transport(qla2xxx_transport_vport_template);
1433 @@ -2922,6 +2948,7 @@ qla2x00_module_exit(void)
1435 pci_unregister_driver(&qla2xxx_pci_driver);
1436 qla2x00_release_firmware();
1437 + ql_nl_unregister();
1438 kmem_cache_destroy(srb_cachep);
1439 fc_release_transport(qla2xxx_transport_template);
1440 fc_release_transport(qla2xxx_transport_vport_template);
1441 diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
1442 index eea6720..d88bb2c 100644
1443 --- a/drivers/scsi/qla2xxx/qla_version.h
1444 +++ b/drivers/scsi/qla2xxx/qla_version.h
1449 -#define QLA2XXX_VERSION "8.02.01-k9"
1450 +#define QLA2XXX_VERSION "8.02.01.02.11.0-k9"
1452 #define QLA_DRIVER_MAJOR_VER 8
1453 #define QLA_DRIVER_MINOR_VER 2