blob: c3aa1eb8c1bac2d7321d74fe3115e3fcd3843a92 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Andrew Vasquezfa90c542005-10-27 11:10:08 -07002 * QLogic Fibre Channel HBA Driver
Armen Baloyanbd21eaf2014-04-11 16:54:24 -04003 * Copyright (c) 2003-2014 QLogic Corporation
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
Andrew Vasquezfa90c542005-10-27 11:10:08 -07005 * See LICENSE.qla2xxx for copyright and licensing details.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 */
7#include "qla_def.h"
Anirban Chakraborty73208df2008-12-09 16:45:39 -08008#include "qla_gbl.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -07009
10#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090011#include <linux/slab.h>
Andrew Vasquez0107109e2005-07-06 10:31:37 -070012#include <linux/vmalloc.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013
14#include "qla_devtbl.h"
15
David Miller4e08df32007-04-16 12:37:43 -070016#ifdef CONFIG_SPARC
17#include <asm/prom.h>
David Miller4e08df32007-04-16 12:37:43 -070018#endif
19
Nicholas Bellinger2d70c102012-05-15 14:34:28 -040020#include <target/target_core_base.h>
21#include "qla_target.h"
22
Linus Torvalds1da177e2005-04-16 15:20:36 -070023/*
24* QLogic ISP2x00 Hardware Support Function Prototypes.
25*/
Linus Torvalds1da177e2005-04-16 15:20:36 -070026static int qla2x00_isp_firmware(scsi_qla_host_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070027static int qla2x00_setup_chip(scsi_qla_host_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070028static int qla2x00_fw_ready(scsi_qla_host_t *);
29static int qla2x00_configure_hba(scsi_qla_host_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070030static int qla2x00_configure_loop(scsi_qla_host_t *);
31static int qla2x00_configure_local_loop(scsi_qla_host_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070032static int qla2x00_configure_fabric(scsi_qla_host_t *);
33static int qla2x00_find_all_fabric_devs(scsi_qla_host_t *, struct list_head *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070034static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
35 uint16_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070036
37static int qla2x00_restart_isp(scsi_qla_host_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
Harihara Kadayam4d4df192008-04-03 13:13:26 -070039static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
40static int qla84xx_init_chip(scsi_qla_host_t *);
Anirban Chakraborty73208df2008-12-09 16:45:39 -080041static int qla25xx_init_queues(struct qla_hw_data *);
Harihara Kadayam4d4df192008-04-03 13:13:26 -070042
Andrew Vasquezac280b62009-08-20 11:06:05 -070043/* SRB Extensions ---------------------------------------------------------- */
44
Giridhar Malavali9ba56b92012-02-09 11:15:36 -080045void
46qla2x00_sp_timeout(unsigned long __data)
Andrew Vasquezac280b62009-08-20 11:06:05 -070047{
48 srb_t *sp = (srb_t *)__data;
Madhuranath Iyengar49163922010-05-04 15:01:28 -070049 struct srb_iocb *iocb;
Andrew Vasquezac280b62009-08-20 11:06:05 -070050 fc_port_t *fcport = sp->fcport;
51 struct qla_hw_data *ha = fcport->vha->hw;
52 struct req_que *req;
53 unsigned long flags;
54
55 spin_lock_irqsave(&ha->hardware_lock, flags);
56 req = ha->req_q_map[0];
57 req->outstanding_cmds[sp->handle] = NULL;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -080058 iocb = &sp->u.iocb_cmd;
Madhuranath Iyengar49163922010-05-04 15:01:28 -070059 iocb->timeout(sp);
Giridhar Malavali9ba56b92012-02-09 11:15:36 -080060 sp->free(fcport->vha, sp);
Andrew Vasquez6ac52602010-05-28 15:08:19 -070061 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Andrew Vasquezac280b62009-08-20 11:06:05 -070062}
63
Giridhar Malavali9ba56b92012-02-09 11:15:36 -080064void
65qla2x00_sp_free(void *data, void *ptr)
Andrew Vasquezac280b62009-08-20 11:06:05 -070066{
Giridhar Malavali9ba56b92012-02-09 11:15:36 -080067 srb_t *sp = (srb_t *)ptr;
68 struct srb_iocb *iocb = &sp->u.iocb_cmd;
69 struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
Andrew Vasquezac280b62009-08-20 11:06:05 -070070
Chad Dupuis4d97cc52010-10-15 11:27:41 -070071 del_timer(&iocb->timer);
Chad Dupuisb00ee7d2013-02-08 01:57:50 -050072 qla2x00_rel_sp(vha, sp);
Andrew Vasquezac280b62009-08-20 11:06:05 -070073}
74
Andrew Vasquezac280b62009-08-20 11:06:05 -070075/* Asynchronous Login/Logout Routines -------------------------------------- */
76
Saurav Kashyapa9b6f722012-08-22 14:21:01 -040077unsigned long
Andrew Vasquez5b914902010-05-28 15:08:30 -070078qla2x00_get_async_timeout(struct scsi_qla_host *vha)
79{
80 unsigned long tmo;
81 struct qla_hw_data *ha = vha->hw;
82
83 /* Firmware should use switch negotiated r_a_tov for timeout. */
84 tmo = ha->r_a_tov / 10 * 2;
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -040085 if (IS_QLAFX00(ha)) {
86 tmo = FX00_DEF_RATOV * 2;
87 } else if (!IS_FWI2_CAPABLE(ha)) {
Andrew Vasquez5b914902010-05-28 15:08:30 -070088 /*
89 * Except for earlier ISPs where the timeout is seeded from the
90 * initialization control block.
91 */
92 tmo = ha->login_timeout;
93 }
94 return tmo;
95}
Andrew Vasquezac280b62009-08-20 11:06:05 -070096
97static void
Giridhar Malavali9ba56b92012-02-09 11:15:36 -080098qla2x00_async_iocb_timeout(void *data)
Andrew Vasquezac280b62009-08-20 11:06:05 -070099{
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800100 srb_t *sp = (srb_t *)data;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700101 fc_port_t *fcport = sp->fcport;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700102
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700103 ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
Chad Dupuiscfb09192011-11-18 09:03:07 -0800104 "Async-%s timeout - hdl=%x portid=%02x%02x%02x.\n",
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800105 sp->name, sp->handle, fcport->d_id.b.domain, fcport->d_id.b.area,
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700106 fcport->d_id.b.al_pa);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700107
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700108 fcport->flags &= ~FCF_ASYNC_SENT;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800109 if (sp->type == SRB_LOGIN_CMD) {
110 struct srb_iocb *lio = &sp->u.iocb_cmd;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700111 qla2x00_post_async_logout_work(fcport->vha, fcport, NULL);
Andrew Vasquez6ac52602010-05-28 15:08:19 -0700112 /* Retry as needed. */
113 lio->u.logio.data[0] = MBS_COMMAND_ERROR;
114 lio->u.logio.data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
115 QLA_LOGIO_LOGIN_RETRIED : 0;
116 qla2x00_post_async_login_done_work(fcport->vha, fcport,
117 lio->u.logio.data);
Alexei Potashnika6ca8872015-07-14 16:00:44 -0400118 } else if (sp->type == SRB_LOGOUT_CMD) {
119 qlt_logo_completion_handler(fcport, QLA_FUNCTION_TIMEOUT);
Andrew Vasquez6ac52602010-05-28 15:08:19 -0700120 }
Andrew Vasquezac280b62009-08-20 11:06:05 -0700121}
122
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700123static void
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800124qla2x00_async_login_sp_done(void *data, void *ptr, int res)
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700125{
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800126 srb_t *sp = (srb_t *)ptr;
127 struct srb_iocb *lio = &sp->u.iocb_cmd;
128 struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700129
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800130 if (!test_bit(UNLOADING, &vha->dpc_flags))
131 qla2x00_post_async_login_done_work(sp->fcport->vha, sp->fcport,
132 lio->u.logio.data);
133 sp->free(sp->fcport->vha, sp);
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700134}
135
Andrew Vasquezac280b62009-08-20 11:06:05 -0700136int
137qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
138 uint16_t *data)
139{
Andrew Vasquezac280b62009-08-20 11:06:05 -0700140 srb_t *sp;
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700141 struct srb_iocb *lio;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700142 int rval;
143
144 rval = QLA_FUNCTION_FAILED;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800145 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700146 if (!sp)
147 goto done;
148
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800149 sp->type = SRB_LOGIN_CMD;
150 sp->name = "login";
151 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
152
153 lio = &sp->u.iocb_cmd;
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700154 lio->timeout = qla2x00_async_iocb_timeout;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800155 sp->done = qla2x00_async_login_sp_done;
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700156 lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700157 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700158 lio->u.logio.flags |= SRB_LOGIN_RETRIED;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700159 rval = qla2x00_start_sp(sp);
160 if (rval != QLA_SUCCESS)
161 goto done_free_sp;
162
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700163 ql_dbg(ql_dbg_disc, vha, 0x2072,
Chad Dupuiscfb09192011-11-18 09:03:07 -0800164 "Async-login - hdl=%x, loopid=%x portid=%02x%02x%02x "
165 "retries=%d.\n", sp->handle, fcport->loop_id,
166 fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
167 fcport->login_retry);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700168 return rval;
169
170done_free_sp:
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800171 sp->free(fcport->vha, sp);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700172done:
173 return rval;
174}
175
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700176static void
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800177qla2x00_async_logout_sp_done(void *data, void *ptr, int res)
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700178{
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800179 srb_t *sp = (srb_t *)ptr;
180 struct srb_iocb *lio = &sp->u.iocb_cmd;
181 struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700182
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800183 if (!test_bit(UNLOADING, &vha->dpc_flags))
184 qla2x00_post_async_logout_done_work(sp->fcport->vha, sp->fcport,
185 lio->u.logio.data);
186 sp->free(sp->fcport->vha, sp);
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700187}
188
Andrew Vasquezac280b62009-08-20 11:06:05 -0700189int
190qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
191{
Andrew Vasquezac280b62009-08-20 11:06:05 -0700192 srb_t *sp;
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700193 struct srb_iocb *lio;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700194 int rval;
195
196 rval = QLA_FUNCTION_FAILED;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800197 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700198 if (!sp)
199 goto done;
200
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800201 sp->type = SRB_LOGOUT_CMD;
202 sp->name = "logout";
203 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
204
205 lio = &sp->u.iocb_cmd;
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700206 lio->timeout = qla2x00_async_iocb_timeout;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800207 sp->done = qla2x00_async_logout_sp_done;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700208 rval = qla2x00_start_sp(sp);
209 if (rval != QLA_SUCCESS)
210 goto done_free_sp;
211
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700212 ql_dbg(ql_dbg_disc, vha, 0x2070,
Chad Dupuiscfb09192011-11-18 09:03:07 -0800213 "Async-logout - hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
214 sp->handle, fcport->loop_id, fcport->d_id.b.domain,
215 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700216 return rval;
217
218done_free_sp:
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800219 sp->free(fcport->vha, sp);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700220done:
221 return rval;
222}
223
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700224static void
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800225qla2x00_async_adisc_sp_done(void *data, void *ptr, int res)
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700226{
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800227 srb_t *sp = (srb_t *)ptr;
228 struct srb_iocb *lio = &sp->u.iocb_cmd;
229 struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700230
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800231 if (!test_bit(UNLOADING, &vha->dpc_flags))
232 qla2x00_post_async_adisc_done_work(sp->fcport->vha, sp->fcport,
233 lio->u.logio.data);
234 sp->free(sp->fcport->vha, sp);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700235}
236
237int
238qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
239 uint16_t *data)
240{
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700241 srb_t *sp;
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700242 struct srb_iocb *lio;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700243 int rval;
244
245 rval = QLA_FUNCTION_FAILED;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800246 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700247 if (!sp)
248 goto done;
249
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800250 sp->type = SRB_ADISC_CMD;
251 sp->name = "adisc";
252 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
253
254 lio = &sp->u.iocb_cmd;
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700255 lio->timeout = qla2x00_async_iocb_timeout;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800256 sp->done = qla2x00_async_adisc_sp_done;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700257 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700258 lio->u.logio.flags |= SRB_LOGIN_RETRIED;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700259 rval = qla2x00_start_sp(sp);
260 if (rval != QLA_SUCCESS)
261 goto done_free_sp;
262
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700263 ql_dbg(ql_dbg_disc, vha, 0x206f,
Chad Dupuiscfb09192011-11-18 09:03:07 -0800264 "Async-adisc - hdl=%x loopid=%x portid=%02x%02x%02x.\n",
265 sp->handle, fcport->loop_id, fcport->d_id.b.domain,
266 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700267 return rval;
268
269done_free_sp:
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800270 sp->free(fcport->vha, sp);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700271done:
272 return rval;
273}
274
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700275static void
Armen Baloyanfaef62d2014-02-26 04:15:17 -0500276qla2x00_tmf_iocb_timeout(void *data)
277{
278 srb_t *sp = (srb_t *)data;
279 struct srb_iocb *tmf = &sp->u.iocb_cmd;
280
281 tmf->u.tmf.comp_status = CS_TIMEOUT;
282 complete(&tmf->u.tmf.comp);
283}
284
285static void
286qla2x00_tmf_sp_done(void *data, void *ptr, int res)
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700287{
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800288 srb_t *sp = (srb_t *)ptr;
Armen Baloyanfaef62d2014-02-26 04:15:17 -0500289 struct srb_iocb *tmf = &sp->u.iocb_cmd;
290 complete(&tmf->u.tmf.comp);
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700291}
292
293int
Armen Baloyanfaef62d2014-02-26 04:15:17 -0500294qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700295 uint32_t tag)
296{
297 struct scsi_qla_host *vha = fcport->vha;
Armen Baloyanfaef62d2014-02-26 04:15:17 -0500298 struct srb_iocb *tm_iocb;
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700299 srb_t *sp;
Armen Baloyanfaef62d2014-02-26 04:15:17 -0500300 int rval = QLA_FUNCTION_FAILED;
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700301
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800302 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700303 if (!sp)
304 goto done;
305
Armen Baloyanfaef62d2014-02-26 04:15:17 -0500306 tm_iocb = &sp->u.iocb_cmd;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800307 sp->type = SRB_TM_CMD;
308 sp->name = "tmf";
Armen Baloyanfaef62d2014-02-26 04:15:17 -0500309 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
310 tm_iocb->u.tmf.flags = flags;
311 tm_iocb->u.tmf.lun = lun;
312 tm_iocb->u.tmf.data = tag;
313 sp->done = qla2x00_tmf_sp_done;
314 tm_iocb->timeout = qla2x00_tmf_iocb_timeout;
315 init_completion(&tm_iocb->u.tmf.comp);
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700316
317 rval = qla2x00_start_sp(sp);
318 if (rval != QLA_SUCCESS)
319 goto done_free_sp;
320
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700321 ql_dbg(ql_dbg_taskm, vha, 0x802f,
Chad Dupuiscfb09192011-11-18 09:03:07 -0800322 "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
323 sp->handle, fcport->loop_id, fcport->d_id.b.domain,
324 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Armen Baloyanfaef62d2014-02-26 04:15:17 -0500325
326 wait_for_completion(&tm_iocb->u.tmf.comp);
327
328 rval = tm_iocb->u.tmf.comp_status == CS_COMPLETE ?
329 QLA_SUCCESS : QLA_FUNCTION_FAILED;
330
331 if ((rval != QLA_SUCCESS) || tm_iocb->u.tmf.data) {
332 ql_dbg(ql_dbg_taskm, vha, 0x8030,
333 "TM IOCB failed (%x).\n", rval);
334 }
335
336 if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) {
337 flags = tm_iocb->u.tmf.flags;
338 lun = (uint16_t)tm_iocb->u.tmf.lun;
339
340 /* Issue Marker IOCB */
341 qla2x00_marker(vha, vha->hw->req_q_map[0],
342 vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun,
343 flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
344 }
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700345
346done_free_sp:
Armen Baloyanfaef62d2014-02-26 04:15:17 -0500347 sp->free(vha, sp);
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700348done:
349 return rval;
350}
351
Armen Baloyan4440e462014-02-26 04:15:18 -0500352static void
353qla24xx_abort_iocb_timeout(void *data)
354{
355 srb_t *sp = (srb_t *)data;
356 struct srb_iocb *abt = &sp->u.iocb_cmd;
357
358 abt->u.abt.comp_status = CS_TIMEOUT;
359 complete(&abt->u.abt.comp);
360}
361
362static void
363qla24xx_abort_sp_done(void *data, void *ptr, int res)
364{
365 srb_t *sp = (srb_t *)ptr;
366 struct srb_iocb *abt = &sp->u.iocb_cmd;
367
368 complete(&abt->u.abt.comp);
369}
370
371static int
372qla24xx_async_abort_cmd(srb_t *cmd_sp)
373{
374 scsi_qla_host_t *vha = cmd_sp->fcport->vha;
375 fc_port_t *fcport = cmd_sp->fcport;
376 struct srb_iocb *abt_iocb;
377 srb_t *sp;
378 int rval = QLA_FUNCTION_FAILED;
379
380 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
381 if (!sp)
382 goto done;
383
384 abt_iocb = &sp->u.iocb_cmd;
385 sp->type = SRB_ABT_CMD;
386 sp->name = "abort";
387 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
388 abt_iocb->u.abt.cmd_hndl = cmd_sp->handle;
389 sp->done = qla24xx_abort_sp_done;
390 abt_iocb->timeout = qla24xx_abort_iocb_timeout;
391 init_completion(&abt_iocb->u.abt.comp);
392
393 rval = qla2x00_start_sp(sp);
394 if (rval != QLA_SUCCESS)
395 goto done_free_sp;
396
397 ql_dbg(ql_dbg_async, vha, 0x507c,
398 "Abort command issued - hdl=%x, target_id=%x\n",
399 cmd_sp->handle, fcport->tgt_id);
400
401 wait_for_completion(&abt_iocb->u.abt.comp);
402
403 rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
404 QLA_SUCCESS : QLA_FUNCTION_FAILED;
405
406done_free_sp:
407 sp->free(vha, sp);
408done:
409 return rval;
410}
411
412int
413qla24xx_async_abort_command(srb_t *sp)
414{
415 unsigned long flags = 0;
416
417 uint32_t handle;
418 fc_port_t *fcport = sp->fcport;
419 struct scsi_qla_host *vha = fcport->vha;
420 struct qla_hw_data *ha = vha->hw;
421 struct req_que *req = vha->req;
422
423 spin_lock_irqsave(&ha->hardware_lock, flags);
424 for (handle = 1; handle < req->num_outstanding_cmds; handle++) {
425 if (req->outstanding_cmds[handle] == sp)
426 break;
427 }
428 spin_unlock_irqrestore(&ha->hardware_lock, flags);
429 if (handle == req->num_outstanding_cmds) {
430 /* Command not found. */
431 return QLA_FUNCTION_FAILED;
432 }
433 if (sp->type == SRB_FXIOCB_DCMD)
434 return qlafx00_fx_disc(vha, &vha->hw->mr.fcport,
435 FXDISC_ABORT_IOCTL);
436
437 return qla24xx_async_abort_cmd(sp);
438}
439
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700440void
Andrew Vasquezac280b62009-08-20 11:06:05 -0700441qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
442 uint16_t *data)
443{
444 int rval;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700445
446 switch (data[0]) {
447 case MBS_COMMAND_COMPLETE:
Andrew Vasqueza4f92a32011-03-30 11:46:31 -0700448 /*
449 * Driver must validate login state - If PRLI not complete,
450 * force a relogin attempt via implicit LOGO, PLOGI, and PRLI
451 * requests.
452 */
453 rval = qla2x00_get_port_database(vha, fcport, 0);
Arun Easi0eba25d2012-02-09 11:15:58 -0800454 if (rval == QLA_NOT_LOGGED_IN) {
455 fcport->flags &= ~FCF_ASYNC_SENT;
456 fcport->flags |= FCF_LOGIN_NEEDED;
457 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
458 break;
459 }
460
Andrew Vasqueza4f92a32011-03-30 11:46:31 -0700461 if (rval != QLA_SUCCESS) {
462 qla2x00_post_async_logout_work(vha, fcport, NULL);
463 qla2x00_post_async_login_work(vha, fcport, NULL);
464 break;
465 }
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700466 if (fcport->flags & FCF_FCP2_DEVICE) {
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700467 qla2x00_post_async_adisc_work(vha, fcport, data);
468 break;
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700469 }
470 qla2x00_update_fcport(vha, fcport);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700471 break;
472 case MBS_COMMAND_ERROR:
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700473 fcport->flags &= ~FCF_ASYNC_SENT;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700474 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
475 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
476 else
Andrew Vasquez80d79442011-03-30 11:46:17 -0700477 qla2x00_mark_device_lost(vha, fcport, 1, 0);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700478 break;
479 case MBS_PORT_ID_USED:
480 fcport->loop_id = data[1];
Andrew Vasquez6ac52602010-05-28 15:08:19 -0700481 qla2x00_post_async_logout_work(vha, fcport, NULL);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700482 qla2x00_post_async_login_work(vha, fcport, NULL);
483 break;
484 case MBS_LOOP_ID_USED:
485 fcport->loop_id++;
486 rval = qla2x00_find_new_loop_id(vha, fcport);
487 if (rval != QLA_SUCCESS) {
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700488 fcport->flags &= ~FCF_ASYNC_SENT;
Andrew Vasquez80d79442011-03-30 11:46:17 -0700489 qla2x00_mark_device_lost(vha, fcport, 1, 0);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700490 break;
491 }
492 qla2x00_post_async_login_work(vha, fcport, NULL);
493 break;
494 }
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700495 return;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700496}
497
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700498void
Andrew Vasquezac280b62009-08-20 11:06:05 -0700499qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
500 uint16_t *data)
501{
Alexei Potashnika6ca8872015-07-14 16:00:44 -0400502 /* Don't re-login in target mode */
503 if (!fcport->tgt_session)
504 qla2x00_mark_device_lost(vha, fcport, 1, 0);
505 qlt_logo_completion_handler(fcport, data[0]);
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700506 return;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700507}
508
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700509void
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700510qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
511 uint16_t *data)
512{
513 if (data[0] == MBS_COMMAND_COMPLETE) {
514 qla2x00_update_fcport(vha, fcport);
515
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700516 return;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700517 }
518
519 /* Retry login. */
520 fcport->flags &= ~FCF_ASYNC_SENT;
521 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
522 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
523 else
Andrew Vasquez80d79442011-03-30 11:46:17 -0700524 qla2x00_mark_device_lost(vha, fcport, 1, 0);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700525
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700526 return;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700527}
528
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529/****************************************************************************/
530/* QLogic ISP2x00 Hardware Support Functions. */
531/****************************************************************************/
532
Saurav Kashyapfa492632012-11-21 02:40:29 -0500533static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -0400534qla83xx_nic_core_fw_load(scsi_qla_host_t *vha)
535{
536 int rval = QLA_SUCCESS;
537 struct qla_hw_data *ha = vha->hw;
538 uint32_t idc_major_ver, idc_minor_ver;
Saurav Kashyap711aa7f2012-08-22 14:21:15 -0400539 uint16_t config[4];
Santosh Vernekar7d613ac2012-08-22 14:21:03 -0400540
541 qla83xx_idc_lock(vha, 0);
542
543 /* SV: TODO: Assign initialization timeout from
544 * flash-info / other param
545 */
546 ha->fcoe_dev_init_timeout = QLA83XX_IDC_INITIALIZATION_TIMEOUT;
547 ha->fcoe_reset_timeout = QLA83XX_IDC_RESET_ACK_TIMEOUT;
548
549 /* Set our fcoe function presence */
550 if (__qla83xx_set_drv_presence(vha) != QLA_SUCCESS) {
551 ql_dbg(ql_dbg_p3p, vha, 0xb077,
552 "Error while setting DRV-Presence.\n");
553 rval = QLA_FUNCTION_FAILED;
554 goto exit;
555 }
556
557 /* Decide the reset ownership */
558 qla83xx_reset_ownership(vha);
559
560 /*
561 * On first protocol driver load:
562 * Init-Owner: Set IDC-Major-Version and Clear IDC-Lock-Recovery
563 * register.
564 * Others: Check compatibility with current IDC Major version.
565 */
566 qla83xx_rd_reg(vha, QLA83XX_IDC_MAJOR_VERSION, &idc_major_ver);
567 if (ha->flags.nic_core_reset_owner) {
568 /* Set IDC Major version */
569 idc_major_ver = QLA83XX_SUPP_IDC_MAJOR_VERSION;
570 qla83xx_wr_reg(vha, QLA83XX_IDC_MAJOR_VERSION, idc_major_ver);
571
572 /* Clearing IDC-Lock-Recovery register */
573 qla83xx_wr_reg(vha, QLA83XX_IDC_LOCK_RECOVERY, 0);
574 } else if (idc_major_ver != QLA83XX_SUPP_IDC_MAJOR_VERSION) {
575 /*
576 * Clear further IDC participation if we are not compatible with
577 * the current IDC Major Version.
578 */
579 ql_log(ql_log_warn, vha, 0xb07d,
580 "Failing load, idc_major_ver=%d, expected_major_ver=%d.\n",
581 idc_major_ver, QLA83XX_SUPP_IDC_MAJOR_VERSION);
582 __qla83xx_clear_drv_presence(vha);
583 rval = QLA_FUNCTION_FAILED;
584 goto exit;
585 }
586 /* Each function sets its supported Minor version. */
587 qla83xx_rd_reg(vha, QLA83XX_IDC_MINOR_VERSION, &idc_minor_ver);
588 idc_minor_ver |= (QLA83XX_SUPP_IDC_MINOR_VERSION << (ha->portnum * 2));
589 qla83xx_wr_reg(vha, QLA83XX_IDC_MINOR_VERSION, idc_minor_ver);
590
Saurav Kashyap711aa7f2012-08-22 14:21:15 -0400591 if (ha->flags.nic_core_reset_owner) {
592 memset(config, 0, sizeof(config));
593 if (!qla81xx_get_port_config(vha, config))
594 qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE,
595 QLA8XXX_DEV_READY);
596 }
597
Santosh Vernekar7d613ac2012-08-22 14:21:03 -0400598 rval = qla83xx_idc_state_handler(vha);
599
600exit:
601 qla83xx_idc_unlock(vha, 0);
602
603 return rval;
604}
605
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606/*
607* qla2x00_initialize_adapter
608* Initialize board.
609*
610* Input:
611* ha = adapter block pointer.
612*
613* Returns:
614* 0 = success
615*/
616int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800617qla2x00_initialize_adapter(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618{
619 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800620 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800621 struct req_que *req = ha->req_q_map[0];
Lalit Chandivade2533cf62009-03-24 09:08:07 -0700622
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 /* Clear adapter flags. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800624 vha->flags.online = 0;
Lalit Chandivade2533cf62009-03-24 09:08:07 -0700625 ha->flags.chip_reset_done = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800626 vha->flags.reset_active = 0;
Andrew Vasquez85880802009-12-15 21:29:46 -0800627 ha->flags.pci_channel_io_perm_failure = 0;
628 ha->flags.eeh_busy = 0;
Joe Carnucciofabbb8d2013-08-27 01:37:40 -0400629 vha->qla_stats.jiffies_at_last_reset = get_jiffies_64();
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800630 atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
631 atomic_set(&vha->loop_state, LOOP_DOWN);
632 vha->device_flags = DFLG_NO_CABLE;
633 vha->dpc_flags = 0;
634 vha->flags.management_server_logged_in = 0;
635 vha->marker_needed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 ha->isp_abort_cnt = 0;
637 ha->beacon_blink_led = 0;
638
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800639 set_bit(0, ha->req_qid_map);
640 set_bit(0, ha->rsp_qid_map);
641
Chad Dupuiscfb09192011-11-18 09:03:07 -0800642 ql_dbg(ql_dbg_init, vha, 0x0040,
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700643 "Configuring PCI space...\n");
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800644 rval = ha->isp_ops->pci_config(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700646 ql_log(ql_log_warn, vha, 0x0044,
647 "Unable to configure PCI space.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 return (rval);
649 }
650
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800651 ha->isp_ops->reset_chip(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800653 rval = qla2xxx_get_flash_info(vha);
Andrew Vasquezc00d8992008-09-11 21:22:49 -0700654 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700655 ql_log(ql_log_fatal, vha, 0x004f,
656 "Unable to validate FLASH data.\n");
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -0400657 return rval;
658 }
659
660 if (IS_QLA8044(ha)) {
661 qla8044_read_reset_template(vha);
662
663 /* NOTE: If ql2xdontresethba==1, set IDC_CTRL DONTRESET_BIT0.
664 * If DONRESET_BIT0 is set, drivers should not set dev_state
665 * to NEED_RESET. But if NEED_RESET is set, drivers should
666 * should honor the reset. */
667 if (ql2xdontresethba == 1)
668 qla8044_set_idc_dontreset(vha);
Andrew Vasquezc00d8992008-09-11 21:22:49 -0700669 }
670
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800671 ha->isp_ops->get_flash_version(vha, req->ring);
Chad Dupuiscfb09192011-11-18 09:03:07 -0800672 ql_dbg(ql_dbg_init, vha, 0x0061,
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700673 "Configure NVRAM parameters...\n");
Andrew Vasquez0107109e2005-07-06 10:31:37 -0700674
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800675 ha->isp_ops->nvram_config(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676
Andrew Vasquezd4c760c2006-06-23 16:10:39 -0700677 if (ha->flags.disable_serdes) {
678 /* Mask HBA via NVRAM settings? */
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700679 ql_log(ql_log_info, vha, 0x0077,
Oleksandr Khoshaba7b8335582013-08-27 01:37:27 -0400680 "Masking HBA WWPN %8phN (via NVRAM).\n", vha->port_name);
Andrew Vasquezd4c760c2006-06-23 16:10:39 -0700681 return QLA_FUNCTION_FAILED;
682 }
683
Chad Dupuiscfb09192011-11-18 09:03:07 -0800684 ql_dbg(ql_dbg_init, vha, 0x0078,
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700685 "Verifying loaded RISC code...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800687 if (qla2x00_isp_firmware(vha) != QLA_SUCCESS) {
688 rval = ha->isp_ops->chip_diag(vha);
Andrew Vasquezd19044c2006-11-22 08:22:19 -0800689 if (rval)
690 return (rval);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800691 rval = qla2x00_setup_chip(vha);
Andrew Vasquezd19044c2006-11-22 08:22:19 -0800692 if (rval)
693 return (rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 }
Giridhar Malavalia9083012010-04-12 17:59:55 -0700695
Harihara Kadayam4d4df192008-04-03 13:13:26 -0700696 if (IS_QLA84XX(ha)) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800697 ha->cs84xx = qla84xx_get_chip(vha);
Harihara Kadayam4d4df192008-04-03 13:13:26 -0700698 if (!ha->cs84xx) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700699 ql_log(ql_log_warn, vha, 0x00d0,
Harihara Kadayam4d4df192008-04-03 13:13:26 -0700700 "Unable to configure ISP84XX.\n");
701 return QLA_FUNCTION_FAILED;
702 }
703 }
Nicholas Bellinger2d70c102012-05-15 14:34:28 -0400704
705 if (qla_ini_mode_enabled(vha))
706 rval = qla2x00_init_rings(vha);
707
Lalit Chandivade2533cf62009-03-24 09:08:07 -0700708 ha->flags.chip_reset_done = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
Giridhar Malavali9a069e12010-01-12 13:02:47 -0800710 if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) {
Andrew Vasquez6c452a42010-03-19 17:04:02 -0700711 /* Issue verify 84xx FW IOCB to complete 84xx initialization */
Giridhar Malavali9a069e12010-01-12 13:02:47 -0800712 rval = qla84xx_init_chip(vha);
713 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700714 ql_log(ql_log_warn, vha, 0x00d4,
715 "Unable to initialize ISP84XX.\n");
Bart Van Assche8d2b21d2015-06-04 15:58:09 -0700716 qla84xx_put_chip(vha);
Giridhar Malavali9a069e12010-01-12 13:02:47 -0800717 }
718 }
719
Santosh Vernekar7d613ac2012-08-22 14:21:03 -0400720 /* Load the NIC Core f/w if we are the first protocol driver. */
721 if (IS_QLA8031(ha)) {
722 rval = qla83xx_nic_core_fw_load(vha);
723 if (rval)
724 ql_log(ql_log_warn, vha, 0x0124,
725 "Error in initializing NIC Core f/w.\n");
726 }
727
Madhuranath Iyengar2f0f3f42010-07-23 15:28:24 +0500728 if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))
729 qla24xx_read_fcp_prio_cfg(vha);
Sarang Radke09ff7012010-03-19 17:03:59 -0700730
Joe Carnuccioc46e65c2013-08-27 01:37:35 -0400731 if (IS_P3P_TYPE(ha))
732 qla82xx_set_driver_version(vha, QLA2XXX_VERSION);
733 else
734 qla25xx_set_driver_version(vha, QLA2XXX_VERSION);
735
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 return (rval);
737}
738
739/**
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700740 * qla2100_pci_config() - Setup ISP21xx PCI configuration registers.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 * @ha: HA context
742 *
743 * Returns 0 on success.
744 */
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700745int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800746qla2100_pci_config(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747{
Andrew Vasqueza157b102007-05-07 07:43:01 -0700748 uint16_t w;
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700749 unsigned long flags;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800750 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -0700751 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 pci_set_master(ha->pdev);
Andrew Vasquezaf6177d2007-07-19 15:06:02 -0700754 pci_try_set_mwi(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
Andrew Vasqueza157b102007-05-07 07:43:01 -0700757 w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 pci_write_config_word(ha->pdev, PCI_COMMAND, w);
759
Andrew Vasquez737faec2008-10-24 15:13:45 -0700760 pci_disable_rom(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700762 /* Get PCI bus information. */
763 spin_lock_irqsave(&ha->hardware_lock, flags);
Andrew Vasquez3d716442005-07-06 10:30:26 -0700764 ha->pci_attr = RD_REG_WORD(&reg->ctrl_status);
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700765 spin_unlock_irqrestore(&ha->hardware_lock, flags);
766
767 return QLA_SUCCESS;
768}
769
770/**
771 * qla2300_pci_config() - Setup ISP23xx PCI configuration registers.
772 * @ha: HA context
773 *
774 * Returns 0 on success.
775 */
776int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800777qla2300_pci_config(scsi_qla_host_t *vha)
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700778{
Andrew Vasqueza157b102007-05-07 07:43:01 -0700779 uint16_t w;
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700780 unsigned long flags = 0;
781 uint32_t cnt;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800782 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -0700783 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700784
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700785 pci_set_master(ha->pdev);
Andrew Vasquezaf6177d2007-07-19 15:06:02 -0700786 pci_try_set_mwi(ha->pdev);
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700787
788 pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
Andrew Vasqueza157b102007-05-07 07:43:01 -0700789 w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700790
791 if (IS_QLA2322(ha) || IS_QLA6322(ha))
792 w &= ~PCI_COMMAND_INTX_DISABLE;
Andrew Vasqueza157b102007-05-07 07:43:01 -0700793 pci_write_config_word(ha->pdev, PCI_COMMAND, w);
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700794
795 /*
796 * If this is a 2300 card and not 2312, reset the
797 * COMMAND_INVALIDATE due to a bug in the 2300. Unfortunately,
798 * the 2310 also reports itself as a 2300 so we need to get the
799 * fb revision level -- a 6 indicates it really is a 2300 and
800 * not a 2310.
801 */
802 if (IS_QLA2300(ha)) {
803 spin_lock_irqsave(&ha->hardware_lock, flags);
804
805 /* Pause RISC. */
Andrew Vasquez3d716442005-07-06 10:30:26 -0700806 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700807 for (cnt = 0; cnt < 30000; cnt++) {
Andrew Vasquez3d716442005-07-06 10:30:26 -0700808 if ((RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) != 0)
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700809 break;
810
811 udelay(10);
812 }
813
814 /* Select FPM registers. */
Andrew Vasquez3d716442005-07-06 10:30:26 -0700815 WRT_REG_WORD(&reg->ctrl_status, 0x20);
816 RD_REG_WORD(&reg->ctrl_status);
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700817
818 /* Get the fb rev level */
Andrew Vasquez3d716442005-07-06 10:30:26 -0700819 ha->fb_rev = RD_FB_CMD_REG(ha, reg);
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700820
821 if (ha->fb_rev == FPM_2300)
Andrew Vasqueza157b102007-05-07 07:43:01 -0700822 pci_clear_mwi(ha->pdev);
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700823
824 /* Deselect FPM registers. */
Andrew Vasquez3d716442005-07-06 10:30:26 -0700825 WRT_REG_WORD(&reg->ctrl_status, 0x0);
826 RD_REG_WORD(&reg->ctrl_status);
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700827
828 /* Release RISC module. */
Andrew Vasquez3d716442005-07-06 10:30:26 -0700829 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700830 for (cnt = 0; cnt < 30000; cnt++) {
Andrew Vasquez3d716442005-07-06 10:30:26 -0700831 if ((RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0)
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700832 break;
833
834 udelay(10);
835 }
836
837 spin_unlock_irqrestore(&ha->hardware_lock, flags);
838 }
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700839
840 pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
841
Andrew Vasquez737faec2008-10-24 15:13:45 -0700842 pci_disable_rom(ha->pdev);
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700843
844 /* Get PCI bus information. */
845 spin_lock_irqsave(&ha->hardware_lock, flags);
Andrew Vasquez3d716442005-07-06 10:30:26 -0700846 ha->pci_attr = RD_REG_WORD(&reg->ctrl_status);
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700847 spin_unlock_irqrestore(&ha->hardware_lock, flags);
848
849 return QLA_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850}
851
852/**
Andrew Vasquez0107109e2005-07-06 10:31:37 -0700853 * qla24xx_pci_config() - Setup ISP24xx PCI configuration registers.
854 * @ha: HA context
855 *
856 * Returns 0 on success.
857 */
858int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800859qla24xx_pci_config(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -0700860{
Andrew Vasqueza157b102007-05-07 07:43:01 -0700861 uint16_t w;
Andrew Vasquez0107109e2005-07-06 10:31:37 -0700862 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800863 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -0700864 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
Andrew Vasquez0107109e2005-07-06 10:31:37 -0700865
866 pci_set_master(ha->pdev);
Andrew Vasquezaf6177d2007-07-19 15:06:02 -0700867 pci_try_set_mwi(ha->pdev);
Andrew Vasquez0107109e2005-07-06 10:31:37 -0700868
869 pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
Andrew Vasqueza157b102007-05-07 07:43:01 -0700870 w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
Andrew Vasquez0107109e2005-07-06 10:31:37 -0700871 w &= ~PCI_COMMAND_INTX_DISABLE;
872 pci_write_config_word(ha->pdev, PCI_COMMAND, w);
873
874 pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
875
876 /* PCI-X -- adjust Maximum Memory Read Byte Count (2048). */
Andrew Vasquezf85ec182007-07-19 15:06:01 -0700877 if (pci_find_capability(ha->pdev, PCI_CAP_ID_PCIX))
878 pcix_set_mmrbc(ha->pdev, 2048);
Andrew Vasquez0107109e2005-07-06 10:31:37 -0700879
880 /* PCIe -- adjust Maximum Read Request Size (2048). */
Jon Masone67f1322012-07-10 14:57:56 -0700881 if (pci_is_pcie(ha->pdev))
Chad Dupuis5ffd3a52012-08-22 14:21:26 -0400882 pcie_set_readrq(ha->pdev, 4096);
Andrew Vasquez0107109e2005-07-06 10:31:37 -0700883
Andrew Vasquez737faec2008-10-24 15:13:45 -0700884 pci_disable_rom(ha->pdev);
Andrew Vasquez0107109e2005-07-06 10:31:37 -0700885
Auke Kok44c10132007-06-08 15:46:36 -0700886 ha->chip_revision = ha->pdev->revision;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -0800887
Andrew Vasquez0107109e2005-07-06 10:31:37 -0700888 /* Get PCI bus information. */
889 spin_lock_irqsave(&ha->hardware_lock, flags);
890 ha->pci_attr = RD_REG_DWORD(&reg->ctrl_status);
891 spin_unlock_irqrestore(&ha->hardware_lock, flags);
892
893 return QLA_SUCCESS;
894}
895
896/**
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700897 * qla25xx_pci_config() - Setup ISP25xx PCI configuration registers.
898 * @ha: HA context
899 *
900 * Returns 0 on success.
901 */
902int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800903qla25xx_pci_config(scsi_qla_host_t *vha)
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700904{
905 uint16_t w;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800906 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700907
908 pci_set_master(ha->pdev);
909 pci_try_set_mwi(ha->pdev);
910
911 pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
912 w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
913 w &= ~PCI_COMMAND_INTX_DISABLE;
914 pci_write_config_word(ha->pdev, PCI_COMMAND, w);
915
916 /* PCIe -- adjust Maximum Read Request Size (2048). */
Jon Masone67f1322012-07-10 14:57:56 -0700917 if (pci_is_pcie(ha->pdev))
Chad Dupuis5ffd3a52012-08-22 14:21:26 -0400918 pcie_set_readrq(ha->pdev, 4096);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700919
Andrew Vasquez737faec2008-10-24 15:13:45 -0700920 pci_disable_rom(ha->pdev);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700921
922 ha->chip_revision = ha->pdev->revision;
923
924 return QLA_SUCCESS;
925}
926
927/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 * qla2x00_isp_firmware() - Choose firmware image.
929 * @ha: HA context
930 *
931 * Returns 0 on success.
932 */
933static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800934qla2x00_isp_firmware(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935{
936 int rval;
Andrew Vasquez42e421b2008-07-10 16:56:01 -0700937 uint16_t loop_id, topo, sw_cap;
938 uint8_t domain, area, al_pa;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800939 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940
941 /* Assume loading risc code */
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700942 rval = QLA_FUNCTION_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
944 if (ha->flags.disable_risc_code_load) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700945 ql_log(ql_log_info, vha, 0x0079, "RISC CODE NOT loaded.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946
947 /* Verify checksum of loaded RISC code. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800948 rval = qla2x00_verify_checksum(vha, ha->fw_srisc_address);
Andrew Vasquez42e421b2008-07-10 16:56:01 -0700949 if (rval == QLA_SUCCESS) {
950 /* And, verify we are not in ROM code. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800951 rval = qla2x00_get_adapter_id(vha, &loop_id, &al_pa,
Andrew Vasquez42e421b2008-07-10 16:56:01 -0700952 &area, &domain, &topo, &sw_cap);
953 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 }
955
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700956 if (rval)
957 ql_dbg(ql_dbg_init, vha, 0x007a,
958 "**** Load RISC code ****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959
960 return (rval);
961}
962
963/**
964 * qla2x00_reset_chip() - Reset ISP chip.
965 * @ha: HA context
966 *
967 * Returns 0 on success.
968 */
Andrew Vasquezabbd8872005-07-06 10:30:05 -0700969void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800970qla2x00_reset_chip(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971{
972 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800973 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -0700974 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 uint32_t cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 uint16_t cmd;
977
Andrew Vasquez85880802009-12-15 21:29:46 -0800978 if (unlikely(pci_channel_offline(ha->pdev)))
979 return;
980
Andrew Vasquezfd34f552007-07-19 15:06:00 -0700981 ha->isp_ops->disable_intrs(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
983 spin_lock_irqsave(&ha->hardware_lock, flags);
984
985 /* Turn off master enable */
986 cmd = 0;
987 pci_read_config_word(ha->pdev, PCI_COMMAND, &cmd);
988 cmd &= ~PCI_COMMAND_MASTER;
989 pci_write_config_word(ha->pdev, PCI_COMMAND, cmd);
990
991 if (!IS_QLA2100(ha)) {
992 /* Pause RISC. */
993 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
994 if (IS_QLA2200(ha) || IS_QLA2300(ha)) {
995 for (cnt = 0; cnt < 30000; cnt++) {
996 if ((RD_REG_WORD(&reg->hccr) &
997 HCCR_RISC_PAUSE) != 0)
998 break;
999 udelay(100);
1000 }
1001 } else {
1002 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
1003 udelay(10);
1004 }
1005
1006 /* Select FPM registers. */
1007 WRT_REG_WORD(&reg->ctrl_status, 0x20);
1008 RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
1009
1010 /* FPM Soft Reset. */
1011 WRT_REG_WORD(&reg->fpm_diag_config, 0x100);
1012 RD_REG_WORD(&reg->fpm_diag_config); /* PCI Posting. */
1013
1014 /* Toggle Fpm Reset. */
1015 if (!IS_QLA2200(ha)) {
1016 WRT_REG_WORD(&reg->fpm_diag_config, 0x0);
1017 RD_REG_WORD(&reg->fpm_diag_config); /* PCI Posting. */
1018 }
1019
1020 /* Select frame buffer registers. */
1021 WRT_REG_WORD(&reg->ctrl_status, 0x10);
1022 RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
1023
1024 /* Reset frame buffer FIFOs. */
1025 if (IS_QLA2200(ha)) {
1026 WRT_FB_CMD_REG(ha, reg, 0xa000);
1027 RD_FB_CMD_REG(ha, reg); /* PCI Posting. */
1028 } else {
1029 WRT_FB_CMD_REG(ha, reg, 0x00fc);
1030
1031 /* Read back fb_cmd until zero or 3 seconds max */
1032 for (cnt = 0; cnt < 3000; cnt++) {
1033 if ((RD_FB_CMD_REG(ha, reg) & 0xff) == 0)
1034 break;
1035 udelay(100);
1036 }
1037 }
1038
1039 /* Select RISC module registers. */
1040 WRT_REG_WORD(&reg->ctrl_status, 0);
1041 RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
1042
1043 /* Reset RISC processor. */
1044 WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
1045 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
1046
1047 /* Release RISC processor. */
1048 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
1049 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
1050 }
1051
1052 WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
1053 WRT_REG_WORD(&reg->hccr, HCCR_CLR_HOST_INT);
1054
1055 /* Reset ISP chip. */
1056 WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
1057
1058 /* Wait for RISC to recover from reset. */
1059 if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
1060 /*
1061 * It is necessary to for a delay here since the card doesn't
1062 * respond to PCI reads during a reset. On some architectures
1063 * this will result in an MCA.
1064 */
1065 udelay(20);
1066 for (cnt = 30000; cnt; cnt--) {
1067 if ((RD_REG_WORD(&reg->ctrl_status) &
1068 CSR_ISP_SOFT_RESET) == 0)
1069 break;
1070 udelay(100);
1071 }
1072 } else
1073 udelay(10);
1074
1075 /* Reset RISC processor. */
1076 WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
1077
1078 WRT_REG_WORD(&reg->semaphore, 0);
1079
1080 /* Release RISC processor. */
1081 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
1082 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
1083
1084 if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
1085 for (cnt = 0; cnt < 30000; cnt++) {
Andrew Vasquezffb39f02006-05-17 15:09:06 -07001086 if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088
1089 udelay(100);
1090 }
1091 } else
1092 udelay(100);
1093
1094 /* Turn on master enable */
1095 cmd |= PCI_COMMAND_MASTER;
1096 pci_write_config_word(ha->pdev, PCI_COMMAND, cmd);
1097
1098 /* Disable RISC pause on FPM parity error. */
1099 if (!IS_QLA2100(ha)) {
1100 WRT_REG_WORD(&reg->hccr, HCCR_DISABLE_PARITY_PAUSE);
1101 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
1102 }
1103
1104 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1105}
1106
1107/**
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07001108 * qla81xx_reset_mpi() - Reset's MPI FW via Write MPI Register MBC.
1109 *
1110 * Returns 0 on success.
1111 */
Saurav Kashyapfa492632012-11-21 02:40:29 -05001112static int
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07001113qla81xx_reset_mpi(scsi_qla_host_t *vha)
1114{
1115 uint16_t mb[4] = {0x1010, 0, 1, 0};
1116
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08001117 if (!IS_QLA81XX(vha->hw))
1118 return QLA_SUCCESS;
1119
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07001120 return qla81xx_write_mpi_register(vha, mb);
1121}
1122
1123/**
Andrew Vasquez88c26662005-07-08 17:59:26 -07001124 * qla24xx_reset_risc() - Perform full reset of ISP24xx RISC.
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001125 * @ha: HA context
1126 *
1127 * Returns 0 on success.
1128 */
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001129static inline int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001130qla24xx_reset_risc(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001131{
1132 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001133 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001134 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
Bart Van Assche52c82822015-07-09 07:23:26 -07001135 uint32_t cnt;
Andrew Vasquez335a1cc2005-11-08 14:37:48 -08001136 uint16_t wd;
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07001137 static int abts_cnt; /* ISP abort retry counts */
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001138 int rval = QLA_SUCCESS;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001139
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001140 spin_lock_irqsave(&ha->hardware_lock, flags);
1141
1142 /* Reset RISC. */
1143 WRT_REG_DWORD(&reg->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
1144 for (cnt = 0; cnt < 30000; cnt++) {
1145 if ((RD_REG_DWORD(&reg->ctrl_status) & CSRX_DMA_ACTIVE) == 0)
1146 break;
1147
1148 udelay(10);
1149 }
1150
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001151 if (!(RD_REG_DWORD(&reg->ctrl_status) & CSRX_DMA_ACTIVE))
1152 set_bit(DMA_SHUTDOWN_CMPL, &ha->fw_dump_cap_flags);
1153
1154 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x017e,
1155 "HCCR: 0x%x, Control Status %x, DMA active status:0x%x\n",
1156 RD_REG_DWORD(&reg->hccr),
1157 RD_REG_DWORD(&reg->ctrl_status),
1158 (RD_REG_DWORD(&reg->ctrl_status) & CSRX_DMA_ACTIVE));
1159
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001160 WRT_REG_DWORD(&reg->ctrl_status,
1161 CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
Andrew Vasquez335a1cc2005-11-08 14:37:48 -08001162 pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
Andrew Vasquez88c26662005-07-08 17:59:26 -07001163
Andrew Vasquez335a1cc2005-11-08 14:37:48 -08001164 udelay(100);
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001165
Andrew Vasquez88c26662005-07-08 17:59:26 -07001166 /* Wait for firmware to complete NVRAM accesses. */
Bart Van Assche52c82822015-07-09 07:23:26 -07001167 RD_REG_WORD(&reg->mailbox0);
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001168 for (cnt = 10000; RD_REG_WORD(&reg->mailbox0) != 0 &&
1169 rval == QLA_SUCCESS; cnt--) {
Andrew Vasquez88c26662005-07-08 17:59:26 -07001170 barrier();
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001171 if (cnt)
1172 udelay(5);
1173 else
1174 rval = QLA_FUNCTION_TIMEOUT;
Andrew Vasquez88c26662005-07-08 17:59:26 -07001175 }
1176
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001177 if (rval == QLA_SUCCESS)
1178 set_bit(ISP_MBX_RDY, &ha->fw_dump_cap_flags);
1179
1180 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x017f,
1181 "HCCR: 0x%x, MailBox0 Status 0x%x\n",
1182 RD_REG_DWORD(&reg->hccr),
1183 RD_REG_DWORD(&reg->mailbox0));
1184
Andrew Vasquez335a1cc2005-11-08 14:37:48 -08001185 /* Wait for soft-reset to complete. */
Bart Van Assche52c82822015-07-09 07:23:26 -07001186 RD_REG_DWORD(&reg->ctrl_status);
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001187 for (cnt = 0; cnt < 6000000; cnt++) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001188 barrier();
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001189 if ((RD_REG_DWORD(&reg->ctrl_status) &
1190 CSRX_ISP_SOFT_RESET) == 0)
1191 break;
1192
1193 udelay(5);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001194 }
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001195 if (!(RD_REG_DWORD(&reg->ctrl_status) & CSRX_ISP_SOFT_RESET))
1196 set_bit(ISP_SOFT_RESET_CMPL, &ha->fw_dump_cap_flags);
1197
1198 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x015d,
1199 "HCCR: 0x%x, Soft Reset status: 0x%x\n",
1200 RD_REG_DWORD(&reg->hccr),
1201 RD_REG_DWORD(&reg->ctrl_status));
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001202
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07001203 /* If required, do an MPI FW reset now */
1204 if (test_and_clear_bit(MPI_RESET_NEEDED, &vha->dpc_flags)) {
1205 if (qla81xx_reset_mpi(vha) != QLA_SUCCESS) {
1206 if (++abts_cnt < 5) {
1207 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
1208 set_bit(MPI_RESET_NEEDED, &vha->dpc_flags);
1209 } else {
1210 /*
1211 * We exhausted the ISP abort retries. We have to
1212 * set the board offline.
1213 */
1214 abts_cnt = 0;
1215 vha->flags.online = 0;
1216 }
1217 }
1218 }
1219
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001220 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
1221 RD_REG_DWORD(&reg->hccr);
1222
1223 WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
1224 RD_REG_DWORD(&reg->hccr);
1225
1226 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_RESET);
1227 RD_REG_DWORD(&reg->hccr);
1228
Bart Van Assche52c82822015-07-09 07:23:26 -07001229 RD_REG_WORD(&reg->mailbox0);
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001230 for (cnt = 6000000; RD_REG_WORD(&reg->mailbox0) != 0 &&
1231 rval == QLA_SUCCESS; cnt--) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001232 barrier();
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001233 if (cnt)
1234 udelay(5);
1235 else
1236 rval = QLA_FUNCTION_TIMEOUT;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001237 }
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001238 if (rval == QLA_SUCCESS)
1239 set_bit(RISC_RDY_AFT_RESET, &ha->fw_dump_cap_flags);
1240
1241 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x015e,
1242 "Host Risc 0x%x, mailbox0 0x%x\n",
1243 RD_REG_DWORD(&reg->hccr),
1244 RD_REG_WORD(&reg->mailbox0));
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001245
1246 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Andrew Vasquez124f85e2009-01-05 11:18:06 -08001247
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001248 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x015f,
1249 "Driver in %s mode\n",
1250 IS_NOPOLLING_TYPE(ha) ? "Interrupt" : "Polling");
1251
Andrew Vasquez124f85e2009-01-05 11:18:06 -08001252 if (IS_NOPOLLING_TYPE(ha))
1253 ha->isp_ops->enable_intrs(ha);
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04001254
1255 return rval;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001256}
1257
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05001258static void
1259qla25xx_read_risc_sema_reg(scsi_qla_host_t *vha, uint32_t *data)
1260{
1261 struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;
1262
1263 WRT_REG_DWORD(&reg->iobase_addr, RISC_REGISTER_BASE_OFFSET);
1264 *data = RD_REG_DWORD(&reg->iobase_window + RISC_REGISTER_WINDOW_OFFET);
1265
1266}
1267
1268static void
1269qla25xx_write_risc_sema_reg(scsi_qla_host_t *vha, uint32_t data)
1270{
1271 struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;
1272
1273 WRT_REG_DWORD(&reg->iobase_addr, RISC_REGISTER_BASE_OFFSET);
1274 WRT_REG_DWORD(&reg->iobase_window + RISC_REGISTER_WINDOW_OFFET, data);
1275}
1276
1277static void
1278qla25xx_manipulate_risc_semaphore(scsi_qla_host_t *vha)
1279{
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05001280 uint32_t wd32 = 0;
1281 uint delta_msec = 100;
1282 uint elapsed_msec = 0;
1283 uint timeout_msec;
1284 ulong n;
1285
Joe Carnucciocc790762015-08-04 13:37:53 -04001286 if (vha->hw->pdev->subsystem_device != 0x0175 &&
1287 vha->hw->pdev->subsystem_device != 0x0240)
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05001288 return;
1289
Joe Carnuccio8dd7e3a2015-08-04 13:37:54 -04001290 WRT_REG_DWORD(&vha->hw->iobase->isp24.hccr, HCCRX_SET_RISC_PAUSE);
1291 udelay(100);
1292
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05001293attempt:
1294 timeout_msec = TIMEOUT_SEMAPHORE;
1295 n = timeout_msec / delta_msec;
1296 while (n--) {
1297 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_SET);
1298 qla25xx_read_risc_sema_reg(vha, &wd32);
1299 if (wd32 & RISC_SEMAPHORE)
1300 break;
1301 msleep(delta_msec);
1302 elapsed_msec += delta_msec;
1303 if (elapsed_msec > TIMEOUT_TOTAL_ELAPSED)
1304 goto force;
1305 }
1306
1307 if (!(wd32 & RISC_SEMAPHORE))
1308 goto force;
1309
1310 if (!(wd32 & RISC_SEMAPHORE_FORCE))
1311 goto acquired;
1312
1313 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_CLR);
1314 timeout_msec = TIMEOUT_SEMAPHORE_FORCE;
1315 n = timeout_msec / delta_msec;
1316 while (n--) {
1317 qla25xx_read_risc_sema_reg(vha, &wd32);
1318 if (!(wd32 & RISC_SEMAPHORE_FORCE))
1319 break;
1320 msleep(delta_msec);
1321 elapsed_msec += delta_msec;
1322 if (elapsed_msec > TIMEOUT_TOTAL_ELAPSED)
1323 goto force;
1324 }
1325
1326 if (wd32 & RISC_SEMAPHORE_FORCE)
1327 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_FORCE_CLR);
1328
1329 goto attempt;
1330
1331force:
1332 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_FORCE_SET);
1333
1334acquired:
1335 return;
1336}
1337
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001338/**
Andrew Vasquez88c26662005-07-08 17:59:26 -07001339 * qla24xx_reset_chip() - Reset ISP24xx chip.
1340 * @ha: HA context
1341 *
1342 * Returns 0 on success.
1343 */
1344void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001345qla24xx_reset_chip(scsi_qla_host_t *vha)
Andrew Vasquez88c26662005-07-08 17:59:26 -07001346{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001347 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez85880802009-12-15 21:29:46 -08001348
1349 if (pci_channel_offline(ha->pdev) &&
1350 ha->flags.pci_channel_io_perm_failure) {
1351 return;
1352 }
1353
Andrew Vasquezfd34f552007-07-19 15:06:00 -07001354 ha->isp_ops->disable_intrs(ha);
Andrew Vasquez88c26662005-07-08 17:59:26 -07001355
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05001356 qla25xx_manipulate_risc_semaphore(vha);
1357
Andrew Vasquez88c26662005-07-08 17:59:26 -07001358 /* Perform RISC reset. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001359 qla24xx_reset_risc(vha);
Andrew Vasquez88c26662005-07-08 17:59:26 -07001360}
1361
1362/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 * qla2x00_chip_diag() - Test chip for proper operation.
1364 * @ha: HA context
1365 *
1366 * Returns 0 on success.
1367 */
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001368int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001369qla2x00_chip_diag(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370{
1371 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001372 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07001373 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 unsigned long flags = 0;
1375 uint16_t data;
1376 uint32_t cnt;
1377 uint16_t mb[5];
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001378 struct req_que *req = ha->req_q_map[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379
1380 /* Assume a failed state */
1381 rval = QLA_FUNCTION_FAILED;
1382
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001383 ql_dbg(ql_dbg_init, vha, 0x007b,
1384 "Testing device at %lx.\n", (u_long)&reg->flash_address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
1386 spin_lock_irqsave(&ha->hardware_lock, flags);
1387
1388 /* Reset ISP chip. */
1389 WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
1390
1391 /*
1392 * We need to have a delay here since the card will not respond while
1393 * in reset causing an MCA on some architectures.
1394 */
1395 udelay(20);
1396 data = qla2x00_debounce_register(&reg->ctrl_status);
1397 for (cnt = 6000000 ; cnt && (data & CSR_ISP_SOFT_RESET); cnt--) {
1398 udelay(5);
1399 data = RD_REG_WORD(&reg->ctrl_status);
1400 barrier();
1401 }
1402
1403 if (!cnt)
1404 goto chip_diag_failed;
1405
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001406 ql_dbg(ql_dbg_init, vha, 0x007c,
1407 "Reset register cleared by chip reset.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408
1409 /* Reset RISC processor. */
1410 WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
1411 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
1412
1413 /* Workaround for QLA2312 PCI parity error */
1414 if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
1415 data = qla2x00_debounce_register(MAILBOX_REG(ha, reg, 0));
1416 for (cnt = 6000000; cnt && (data == MBS_BUSY); cnt--) {
1417 udelay(5);
1418 data = RD_MAILBOX_REG(ha, reg, 0);
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07001419 barrier();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 }
1421 } else
1422 udelay(10);
1423
1424 if (!cnt)
1425 goto chip_diag_failed;
1426
1427 /* Check product ID of chip */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001428 ql_dbg(ql_dbg_init, vha, 0x007d, "Checking product Id of chip.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429
1430 mb[1] = RD_MAILBOX_REG(ha, reg, 1);
1431 mb[2] = RD_MAILBOX_REG(ha, reg, 2);
1432 mb[3] = RD_MAILBOX_REG(ha, reg, 3);
1433 mb[4] = qla2x00_debounce_register(MAILBOX_REG(ha, reg, 4));
1434 if (mb[1] != PROD_ID_1 || (mb[2] != PROD_ID_2 && mb[2] != PROD_ID_2a) ||
1435 mb[3] != PROD_ID_3) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001436 ql_log(ql_log_warn, vha, 0x0062,
1437 "Wrong product ID = 0x%x,0x%x,0x%x.\n",
1438 mb[1], mb[2], mb[3]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
1440 goto chip_diag_failed;
1441 }
1442 ha->product_id[0] = mb[1];
1443 ha->product_id[1] = mb[2];
1444 ha->product_id[2] = mb[3];
1445 ha->product_id[3] = mb[4];
1446
1447 /* Adjust fw RISC transfer size */
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001448 if (req->length > 1024)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 ha->fw_transfer_size = REQUEST_ENTRY_SIZE * 1024;
1450 else
1451 ha->fw_transfer_size = REQUEST_ENTRY_SIZE *
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001452 req->length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
1454 if (IS_QLA2200(ha) &&
1455 RD_MAILBOX_REG(ha, reg, 7) == QLA2200A_RISC_ROM_VER) {
1456 /* Limit firmware transfer size with a 2200A */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001457 ql_dbg(ql_dbg_init, vha, 0x007e, "Found QLA2200A Chip.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
andrew.vasquez@qlogic.comea5b6382006-03-09 14:27:08 -08001459 ha->device_type |= DT_ISP2200A;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 ha->fw_transfer_size = 128;
1461 }
1462
1463 /* Wrap Incoming Mailboxes Test. */
1464 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1465
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001466 ql_dbg(ql_dbg_init, vha, 0x007f, "Checking mailboxes.\n");
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001467 rval = qla2x00_mbx_reg_test(vha);
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001468 if (rval)
1469 ql_log(ql_log_warn, vha, 0x0080,
1470 "Failed mailbox send register test.\n");
1471 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 /* Flag a successful rval */
1473 rval = QLA_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 spin_lock_irqsave(&ha->hardware_lock, flags);
1475
1476chip_diag_failed:
1477 if (rval)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001478 ql_log(ql_log_info, vha, 0x0081,
1479 "Chip diagnostics **** FAILED ****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480
1481 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1482
1483 return (rval);
1484}
1485
1486/**
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001487 * qla24xx_chip_diag() - Test ISP24xx for proper operation.
1488 * @ha: HA context
1489 *
1490 * Returns 0 on success.
1491 */
1492int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001493qla24xx_chip_diag(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001494{
1495 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001496 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001497 struct req_que *req = ha->req_q_map[0];
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001498
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04001499 if (IS_P3P_TYPE(ha))
Giridhar Malavalia9083012010-04-12 17:59:55 -07001500 return QLA_SUCCESS;
1501
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001502 ha->fw_transfer_size = REQUEST_ENTRY_SIZE * req->length;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001503
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001504 rval = qla2x00_mbx_reg_test(vha);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001505 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001506 ql_log(ql_log_warn, vha, 0x0082,
1507 "Failed mailbox send register test.\n");
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001508 } else {
1509 /* Flag a successful rval */
1510 rval = QLA_SUCCESS;
1511 }
1512
1513 return rval;
1514}
1515
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001516void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001517qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001518{
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001519 int rval;
1520 uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size,
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001521 eft_size, fce_size, mq_size;
Andrew Vasquezdf613b92008-01-17 09:02:17 -08001522 dma_addr_t tc_dma;
1523 void *tc;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001524 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001525 struct req_que *req = ha->req_q_map[0];
1526 struct rsp_que *rsp = ha->rsp_q_map[0];
Andrew Vasquezd4e3e042006-05-17 15:09:50 -07001527
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001528 if (ha->fw_dump) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001529 ql_dbg(ql_dbg_init, vha, 0x00bd,
1530 "Firmware dump already allocated.\n");
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001531 return;
Andrew Vasquezd4e3e042006-05-17 15:09:50 -07001532 }
1533
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001534 ha->fw_dumped = 0;
Hiral Patel61f098d2014-04-11 16:54:21 -04001535 ha->fw_dump_cap_flags = 0;
Chad Dupuisf73cb692014-02-26 04:15:06 -05001536 dump_size = fixed_size = mem_size = eft_size = fce_size = mq_size = 0;
1537 req_q_size = rsp_q_size = 0;
1538
1539 if (IS_QLA27XX(ha))
1540 goto try_fce;
1541
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001542 if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
1543 fixed_size = sizeof(struct qla2100_fw_dump);
1544 } else if (IS_QLA23XX(ha)) {
1545 fixed_size = offsetof(struct qla2300_fw_dump, data_ram);
1546 mem_size = (ha->fw_memory_size - 0x11000 + 1) *
1547 sizeof(uint16_t);
Andrew Vasqueze4289242007-07-19 15:05:56 -07001548 } else if (IS_FWI2_CAPABLE(ha)) {
Himanshu Madhanib20f02e2015-06-10 11:05:18 -04001549 if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08001550 fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem);
1551 else if (IS_QLA81XX(ha))
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001552 fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem);
1553 else if (IS_QLA25XX(ha))
1554 fixed_size = offsetof(struct qla25xx_fw_dump, ext_mem);
1555 else
1556 fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem);
Chad Dupuisf73cb692014-02-26 04:15:06 -05001557
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001558 mem_size = (ha->fw_memory_size - 0x100000 + 1) *
1559 sizeof(uint32_t);
Giridhar Malavali050c9bb2012-02-09 11:15:33 -08001560 if (ha->mqenable) {
Himanshu Madhanib20f02e2015-06-10 11:05:18 -04001561 if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08001562 mq_size = sizeof(struct qla2xxx_mq_chain);
Giridhar Malavali050c9bb2012-02-09 11:15:33 -08001563 /*
1564 * Allocate maximum buffer size for all queues.
1565 * Resizing must be done at end-of-dump processing.
1566 */
1567 mq_size += ha->max_req_queues *
1568 (req->length * sizeof(request_t));
1569 mq_size += ha->max_rsp_queues *
1570 (rsp->length * sizeof(response_t));
1571 }
Arun Easi00876ae2013-03-25 02:21:37 -04001572 if (ha->tgt.atio_ring)
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04001573 mq_size += ha->tgt.atio_q_length * sizeof(request_t);
Andrew Vasquez436a7b12008-07-10 16:55:54 -07001574 /* Allocate memory for Fibre Channel Event Buffer. */
Chad Dupuisf73cb692014-02-26 04:15:06 -05001575 if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
1576 !IS_QLA27XX(ha))
Andrew Vasquez436a7b12008-07-10 16:55:54 -07001577 goto try_eft;
1578
Chad Dupuisf73cb692014-02-26 04:15:06 -05001579try_fce:
1580 if (ha->fce)
1581 dma_free_coherent(&ha->pdev->dev,
1582 FCE_SIZE, ha->fce, ha->fce_dma);
1583
1584 /* Allocate memory for Fibre Channel Event Buffer. */
Joe Perches0ea85b52014-06-15 13:37:51 -07001585 tc = dma_zalloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
1586 GFP_KERNEL);
Andrew Vasquez436a7b12008-07-10 16:55:54 -07001587 if (!tc) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001588 ql_log(ql_log_warn, vha, 0x00be,
1589 "Unable to allocate (%d KB) for FCE.\n",
1590 FCE_SIZE / 1024);
Anirban Chakraborty17d98632008-12-18 10:06:15 -08001591 goto try_eft;
Andrew Vasquez436a7b12008-07-10 16:55:54 -07001592 }
1593
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001594 rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS,
Andrew Vasquez436a7b12008-07-10 16:55:54 -07001595 ha->fce_mb, &ha->fce_bufs);
1596 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001597 ql_log(ql_log_warn, vha, 0x00bf,
1598 "Unable to initialize FCE (%d).\n", rval);
Andrew Vasquez436a7b12008-07-10 16:55:54 -07001599 dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc,
1600 tc_dma);
1601 ha->flags.fce_enabled = 0;
Anirban Chakraborty17d98632008-12-18 10:06:15 -08001602 goto try_eft;
Andrew Vasquez436a7b12008-07-10 16:55:54 -07001603 }
Chad Dupuiscfb09192011-11-18 09:03:07 -08001604 ql_dbg(ql_dbg_init, vha, 0x00c0,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001605 "Allocate (%d KB) for FCE...\n", FCE_SIZE / 1024);
Andrew Vasquez436a7b12008-07-10 16:55:54 -07001606
Giridhar Malavali7d9dade2009-03-24 09:07:58 -07001607 fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
Andrew Vasquez436a7b12008-07-10 16:55:54 -07001608 ha->flags.fce_enabled = 1;
1609 ha->fce_dma = tc_dma;
1610 ha->fce = tc;
Chad Dupuisf73cb692014-02-26 04:15:06 -05001611
Andrew Vasquez436a7b12008-07-10 16:55:54 -07001612try_eft:
Chad Dupuisf73cb692014-02-26 04:15:06 -05001613 if (ha->eft)
1614 dma_free_coherent(&ha->pdev->dev,
1615 EFT_SIZE, ha->eft, ha->eft_dma);
1616
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001617 /* Allocate memory for Extended Trace Buffer. */
Joe Perches0ea85b52014-06-15 13:37:51 -07001618 tc = dma_zalloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
1619 GFP_KERNEL);
Andrew Vasquezdf613b92008-01-17 09:02:17 -08001620 if (!tc) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001621 ql_log(ql_log_warn, vha, 0x00c1,
1622 "Unable to allocate (%d KB) for EFT.\n",
1623 EFT_SIZE / 1024);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001624 goto cont_alloc;
1625 }
1626
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001627 rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001628 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001629 ql_log(ql_log_warn, vha, 0x00c2,
1630 "Unable to initialize EFT (%d).\n", rval);
Andrew Vasquezdf613b92008-01-17 09:02:17 -08001631 dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc,
1632 tc_dma);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001633 goto cont_alloc;
1634 }
Chad Dupuiscfb09192011-11-18 09:03:07 -08001635 ql_dbg(ql_dbg_init, vha, 0x00c3,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001636 "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001637
1638 eft_size = EFT_SIZE;
Andrew Vasquezdf613b92008-01-17 09:02:17 -08001639 ha->eft_dma = tc_dma;
1640 ha->eft = tc;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001641 }
Chad Dupuisf73cb692014-02-26 04:15:06 -05001642
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001643cont_alloc:
Chad Dupuisf73cb692014-02-26 04:15:06 -05001644 if (IS_QLA27XX(ha)) {
1645 if (!ha->fw_dump_template) {
1646 ql_log(ql_log_warn, vha, 0x00ba,
1647 "Failed missing fwdump template\n");
1648 return;
1649 }
1650 dump_size = qla27xx_fwdt_calculate_dump_size(vha);
1651 ql_dbg(ql_dbg_init, vha, 0x00fa,
1652 "-> allocating fwdump (%x bytes)...\n", dump_size);
1653 goto allocate;
1654 }
1655
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001656 req_q_size = req->length * sizeof(request_t);
1657 rsp_q_size = rsp->length * sizeof(response_t);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001658 dump_size = offsetof(struct qla2xxx_fw_dump, isp);
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07001659 dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + eft_size;
Andrew Vasquezbb99de62009-01-05 11:18:08 -08001660 ha->chain_offset = dump_size;
1661 dump_size += mq_size + fce_size;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001662
Chad Dupuisf73cb692014-02-26 04:15:06 -05001663allocate:
Andrew Vasquezd4e3e042006-05-17 15:09:50 -07001664 ha->fw_dump = vmalloc(dump_size);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001665 if (!ha->fw_dump) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001666 ql_log(ql_log_warn, vha, 0x00c4,
1667 "Unable to allocate (%d KB) for firmware dump.\n",
1668 dump_size / 1024);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001669
Madhuranath Iyengare30d1752010-10-15 11:27:46 -07001670 if (ha->fce) {
1671 dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
1672 ha->fce_dma);
1673 ha->fce = NULL;
1674 ha->fce_dma = 0;
1675 }
1676
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001677 if (ha->eft) {
1678 dma_free_coherent(&ha->pdev->dev, eft_size, ha->eft,
1679 ha->eft_dma);
1680 ha->eft = NULL;
1681 ha->eft_dma = 0;
1682 }
1683 return;
1684 }
Chad Dupuisf73cb692014-02-26 04:15:06 -05001685 ha->fw_dump_len = dump_size;
Chad Dupuiscfb09192011-11-18 09:03:07 -08001686 ql_dbg(ql_dbg_init, vha, 0x00c5,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001687 "Allocated (%d KB) for firmware dump.\n", dump_size / 1024);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001688
Chad Dupuisf73cb692014-02-26 04:15:06 -05001689 if (IS_QLA27XX(ha))
1690 return;
1691
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001692 ha->fw_dump->signature[0] = 'Q';
1693 ha->fw_dump->signature[1] = 'L';
1694 ha->fw_dump->signature[2] = 'G';
1695 ha->fw_dump->signature[3] = 'C';
Bart Van Asschead950362015-07-09 07:24:08 -07001696 ha->fw_dump->version = htonl(1);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07001697
1698 ha->fw_dump->fixed_size = htonl(fixed_size);
1699 ha->fw_dump->mem_size = htonl(mem_size);
1700 ha->fw_dump->req_q_size = htonl(req_q_size);
1701 ha->fw_dump->rsp_q_size = htonl(rsp_q_size);
1702
1703 ha->fw_dump->eft_size = htonl(eft_size);
1704 ha->fw_dump->eft_addr_l = htonl(LSD(ha->eft_dma));
1705 ha->fw_dump->eft_addr_h = htonl(MSD(ha->eft_dma));
1706
1707 ha->fw_dump->header_size =
1708 htonl(offsetof(struct qla2xxx_fw_dump, isp));
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001709}
1710
Andrew Vasquez18e75552009-06-03 09:55:30 -07001711static int
1712qla81xx_mpi_sync(scsi_qla_host_t *vha)
1713{
1714#define MPS_MASK 0xe0
1715 int rval;
1716 uint16_t dc;
1717 uint32_t dw;
Andrew Vasquez18e75552009-06-03 09:55:30 -07001718
1719 if (!IS_QLA81XX(vha->hw))
1720 return QLA_SUCCESS;
1721
1722 rval = qla2x00_write_ram_word(vha, 0x7c00, 1);
1723 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001724 ql_log(ql_log_warn, vha, 0x0105,
1725 "Unable to acquire semaphore.\n");
Andrew Vasquez18e75552009-06-03 09:55:30 -07001726 goto done;
1727 }
1728
1729 pci_read_config_word(vha->hw->pdev, 0x54, &dc);
1730 rval = qla2x00_read_ram_word(vha, 0x7a15, &dw);
1731 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001732 ql_log(ql_log_warn, vha, 0x0067, "Unable to read sync.\n");
Andrew Vasquez18e75552009-06-03 09:55:30 -07001733 goto done_release;
1734 }
1735
1736 dc &= MPS_MASK;
1737 if (dc == (dw & MPS_MASK))
1738 goto done_release;
1739
1740 dw &= ~MPS_MASK;
1741 dw |= dc;
1742 rval = qla2x00_write_ram_word(vha, 0x7a15, dw);
1743 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001744 ql_log(ql_log_warn, vha, 0x0114, "Unable to gain sync.\n");
Andrew Vasquez18e75552009-06-03 09:55:30 -07001745 }
1746
1747done_release:
1748 rval = qla2x00_write_ram_word(vha, 0x7c00, 0);
1749 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001750 ql_log(ql_log_warn, vha, 0x006d,
1751 "Unable to release semaphore.\n");
Andrew Vasquez18e75552009-06-03 09:55:30 -07001752 }
1753
1754done:
1755 return rval;
1756}
1757
Chad Dupuis8d93f552013-01-30 03:34:37 -05001758int
1759qla2x00_alloc_outstanding_cmds(struct qla_hw_data *ha, struct req_que *req)
1760{
1761 /* Don't try to reallocate the array */
1762 if (req->outstanding_cmds)
1763 return QLA_SUCCESS;
1764
1765 if (!IS_FWI2_CAPABLE(ha) || (ha->mqiobase &&
1766 (ql2xmultique_tag || ql2xmaxqueues > 1)))
1767 req->num_outstanding_cmds = DEFAULT_OUTSTANDING_COMMANDS;
1768 else {
Quinn Tran03e8c682015-12-17 14:56:59 -05001769 if (ha->cur_fw_xcb_count <= ha->cur_fw_iocb_count)
1770 req->num_outstanding_cmds = ha->cur_fw_xcb_count;
Chad Dupuis8d93f552013-01-30 03:34:37 -05001771 else
Quinn Tran03e8c682015-12-17 14:56:59 -05001772 req->num_outstanding_cmds = ha->cur_fw_iocb_count;
Chad Dupuis8d93f552013-01-30 03:34:37 -05001773 }
1774
1775 req->outstanding_cmds = kzalloc(sizeof(srb_t *) *
1776 req->num_outstanding_cmds, GFP_KERNEL);
1777
1778 if (!req->outstanding_cmds) {
1779 /*
1780 * Try to allocate a minimal size just so we can get through
1781 * initialization.
1782 */
1783 req->num_outstanding_cmds = MIN_OUTSTANDING_COMMANDS;
1784 req->outstanding_cmds = kzalloc(sizeof(srb_t *) *
1785 req->num_outstanding_cmds, GFP_KERNEL);
1786
1787 if (!req->outstanding_cmds) {
1788 ql_log(ql_log_fatal, NULL, 0x0126,
1789 "Failed to allocate memory for "
1790 "outstanding_cmds for req_que %p.\n", req);
1791 req->num_outstanding_cmds = 0;
1792 return QLA_FUNCTION_FAILED;
1793 }
1794 }
1795
1796 return QLA_SUCCESS;
1797}
1798
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001799/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 * qla2x00_setup_chip() - Load and start RISC firmware.
1801 * @ha: HA context
1802 *
1803 * Returns 0 on success.
1804 */
1805static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001806qla2x00_setup_chip(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807{
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001808 int rval;
1809 uint32_t srisc_address = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001810 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3db06522008-01-31 12:33:49 -08001811 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
1812 unsigned long flags;
Andrew Vasquezdda772e2009-03-24 09:08:00 -07001813 uint16_t fw_major_version;
Andrew Vasquez3db06522008-01-31 12:33:49 -08001814
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04001815 if (IS_P3P_TYPE(ha)) {
Giridhar Malavalia9083012010-04-12 17:59:55 -07001816 rval = ha->isp_ops->load_risc(vha, &srisc_address);
Andrew Vasquez14e303d2010-07-23 15:28:29 +05001817 if (rval == QLA_SUCCESS) {
1818 qla2x00_stop_firmware(vha);
Giridhar Malavalia9083012010-04-12 17:59:55 -07001819 goto enable_82xx_npiv;
Andrew Vasquez14e303d2010-07-23 15:28:29 +05001820 } else
Giridhar Malavalib9637522010-05-28 15:08:15 -07001821 goto failed;
Giridhar Malavalia9083012010-04-12 17:59:55 -07001822 }
1823
Andrew Vasquez3db06522008-01-31 12:33:49 -08001824 if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) {
1825 /* Disable SRAM, Instruction RAM and GP RAM parity. */
1826 spin_lock_irqsave(&ha->hardware_lock, flags);
1827 WRT_REG_WORD(&reg->hccr, (HCCR_ENABLE_PARITY + 0x0));
1828 RD_REG_WORD(&reg->hccr);
1829 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1830 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831
Andrew Vasquez18e75552009-06-03 09:55:30 -07001832 qla81xx_mpi_sync(vha);
1833
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 /* Load firmware sequences */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001835 rval = ha->isp_ops->load_risc(vha, &srisc_address);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001836 if (rval == QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001837 ql_dbg(ql_dbg_init, vha, 0x00c9,
1838 "Verifying Checksum of loaded RISC code.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001840 rval = qla2x00_verify_checksum(vha, srisc_address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 if (rval == QLA_SUCCESS) {
1842 /* Start firmware execution. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001843 ql_dbg(ql_dbg_init, vha, 0x00ca,
1844 "Starting firmware.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845
Himanshu Madhanib0d6cab2015-12-17 14:56:56 -05001846 if (ql2xexlogins)
1847 ha->flags.exlogins_enabled = 1;
1848
Himanshu Madhani2f56a7f2015-12-17 14:56:57 -05001849 if (ql2xexchoffld)
1850 ha->flags.exchoffld_enabled = 1;
1851
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001852 rval = qla2x00_execute_fw(vha, srisc_address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 /* Retrieve firmware information. */
Andrew Vasquezdda772e2009-03-24 09:08:00 -07001854 if (rval == QLA_SUCCESS) {
Himanshu Madhanib0d6cab2015-12-17 14:56:56 -05001855 rval = qla2x00_set_exlogins_buffer(vha);
1856 if (rval != QLA_SUCCESS)
1857 goto failed;
1858
Himanshu Madhani2f56a7f2015-12-17 14:56:57 -05001859 rval = qla2x00_set_exchoffld_buffer(vha);
1860 if (rval != QLA_SUCCESS)
1861 goto failed;
1862
Giridhar Malavalia9083012010-04-12 17:59:55 -07001863enable_82xx_npiv:
Andrew Vasquezdda772e2009-03-24 09:08:00 -07001864 fw_major_version = ha->fw_major_version;
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04001865 if (IS_P3P_TYPE(ha))
Giridhar Malavali31731672011-08-16 11:31:54 -07001866 qla82xx_check_md_needed(vha);
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08001867 else
1868 rval = qla2x00_get_fw_version(vha);
Andrew Vasquezca9e9c32009-06-03 09:55:20 -07001869 if (rval != QLA_SUCCESS)
1870 goto failed;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001871 ha->flags.npiv_supported = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001872 if (IS_QLA2XXX_MIDTYPE(ha) &&
Mike Hernandez946fb892008-08-13 21:36:59 -07001873 (ha->fw_attributes & BIT_2)) {
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001874 ha->flags.npiv_supported = 1;
Seokmann Ju4d0ea242007-09-20 14:07:43 -07001875 if ((!ha->max_npiv_vports) ||
1876 ((ha->max_npiv_vports + 1) %
Andrew Vasquezeb66dc62007-11-12 10:30:58 -08001877 MIN_MULTI_ID_FABRIC))
Seokmann Ju4d0ea242007-09-20 14:07:43 -07001878 ha->max_npiv_vports =
Andrew Vasquezeb66dc62007-11-12 10:30:58 -08001879 MIN_MULTI_ID_FABRIC - 1;
Seokmann Ju4d0ea242007-09-20 14:07:43 -07001880 }
Quinn Tran03e8c682015-12-17 14:56:59 -05001881 qla2x00_get_resource_cnts(vha);
Andrew Vasquezd743de62009-03-24 09:08:15 -07001882
Chad Dupuis8d93f552013-01-30 03:34:37 -05001883 /*
1884 * Allocate the array of outstanding commands
1885 * now that we know the firmware resources.
1886 */
1887 rval = qla2x00_alloc_outstanding_cmds(ha,
1888 vha->req);
1889 if (rval != QLA_SUCCESS)
1890 goto failed;
1891
Saurav Kashyapbe5ea3c2011-11-18 09:02:11 -08001892 if (!fw_major_version && ql2xallocfwdump
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04001893 && !(IS_P3P_TYPE(ha)))
Giridhar Malavali08de2842011-08-16 11:31:44 -07001894 qla2x00_alloc_fw_dump(vha);
Chad Dupuis3b6e5b92013-10-30 03:38:09 -04001895 } else {
1896 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 }
1898 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001899 ql_log(ql_log_fatal, vha, 0x00cd,
1900 "ISP Firmware failed checksum.\n");
1901 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 }
Andrew Vasquezc74d88a2012-08-22 14:21:19 -04001903 } else
1904 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905
Andrew Vasquez3db06522008-01-31 12:33:49 -08001906 if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) {
1907 /* Enable proper parity. */
1908 spin_lock_irqsave(&ha->hardware_lock, flags);
1909 if (IS_QLA2300(ha))
1910 /* SRAM parity */
1911 WRT_REG_WORD(&reg->hccr, HCCR_ENABLE_PARITY + 0x1);
1912 else
1913 /* SRAM, Instruction RAM and GP RAM parity */
1914 WRT_REG_WORD(&reg->hccr, HCCR_ENABLE_PARITY + 0x7);
1915 RD_REG_WORD(&reg->hccr);
1916 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1917 }
1918
Chad Dupuisf3982d82014-09-25 05:16:57 -04001919 if (IS_QLA27XX(ha))
1920 ha->flags.fac_supported = 1;
1921 else if (rval == QLA_SUCCESS && IS_FAC_REQUIRED(ha)) {
Joe Carnuccio1d2874d2009-03-24 09:08:06 -07001922 uint32_t size;
1923
1924 rval = qla81xx_fac_get_sector_size(vha, &size);
1925 if (rval == QLA_SUCCESS) {
1926 ha->flags.fac_supported = 1;
1927 ha->fdt_block_size = size << 2;
1928 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001929 ql_log(ql_log_warn, vha, 0x00ce,
Joe Carnuccio1d2874d2009-03-24 09:08:06 -07001930 "Unsupported FAC firmware (%d.%02d.%02d).\n",
1931 ha->fw_major_version, ha->fw_minor_version,
1932 ha->fw_subminor_version);
Joe Carnuccio1ca60e32014-02-26 04:15:02 -05001933
Chad Dupuisf73cb692014-02-26 04:15:06 -05001934 if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08001935 ha->flags.fac_supported = 0;
1936 rval = QLA_SUCCESS;
1937 }
Joe Carnuccio1d2874d2009-03-24 09:08:06 -07001938 }
1939 }
Andrew Vasquezca9e9c32009-06-03 09:55:20 -07001940failed:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001942 ql_log(ql_log_fatal, vha, 0x00cf,
1943 "Setup chip ****FAILED****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 }
1945
1946 return (rval);
1947}
1948
1949/**
1950 * qla2x00_init_response_q_entries() - Initializes response queue entries.
1951 * @ha: HA context
1952 *
1953 * Beginning of request ring has initialization control block already built
1954 * by nvram config routine.
1955 *
1956 * Returns 0 on success.
1957 */
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001958void
1959qla2x00_init_response_q_entries(struct rsp_que *rsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960{
1961 uint16_t cnt;
1962 response_t *pkt;
1963
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07001964 rsp->ring_ptr = rsp->ring;
1965 rsp->ring_index = 0;
1966 rsp->status_srb = NULL;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001967 pkt = rsp->ring_ptr;
1968 for (cnt = 0; cnt < rsp->length; cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 pkt->signature = RESPONSE_PROCESSED;
1970 pkt++;
1971 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972}
1973
1974/**
1975 * qla2x00_update_fw_options() - Read and process firmware options.
1976 * @ha: HA context
1977 *
1978 * Returns 0 on success.
1979 */
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001980void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001981qla2x00_update_fw_options(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982{
1983 uint16_t swing, emphasis, tx_sens, rx_sens;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001984 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985
1986 memset(ha->fw_options, 0, sizeof(ha->fw_options));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001987 qla2x00_get_fw_options(vha, ha->fw_options);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988
1989 if (IS_QLA2100(ha) || IS_QLA2200(ha))
1990 return;
1991
1992 /* Serial Link options. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001993 ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0115,
1994 "Serial link options.\n");
1995 ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0109,
1996 (uint8_t *)&ha->fw_seriallink_options,
1997 sizeof(ha->fw_seriallink_options));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998
1999 ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
2000 if (ha->fw_seriallink_options[3] & BIT_2) {
2001 ha->fw_options[1] |= FO1_SET_EMPHASIS_SWING;
2002
2003 /* 1G settings */
2004 swing = ha->fw_seriallink_options[2] & (BIT_2 | BIT_1 | BIT_0);
2005 emphasis = (ha->fw_seriallink_options[2] &
2006 (BIT_4 | BIT_3)) >> 3;
2007 tx_sens = ha->fw_seriallink_options[0] &
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07002008 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 rx_sens = (ha->fw_seriallink_options[0] &
2010 (BIT_7 | BIT_6 | BIT_5 | BIT_4)) >> 4;
2011 ha->fw_options[10] = (emphasis << 14) | (swing << 8);
2012 if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {
2013 if (rx_sens == 0x0)
2014 rx_sens = 0x3;
2015 ha->fw_options[10] |= (tx_sens << 4) | rx_sens;
2016 } else if (IS_QLA2322(ha) || IS_QLA6322(ha))
2017 ha->fw_options[10] |= BIT_5 |
2018 ((rx_sens & (BIT_1 | BIT_0)) << 2) |
2019 (tx_sens & (BIT_1 | BIT_0));
2020
2021 /* 2G settings */
2022 swing = (ha->fw_seriallink_options[2] &
2023 (BIT_7 | BIT_6 | BIT_5)) >> 5;
2024 emphasis = ha->fw_seriallink_options[3] & (BIT_1 | BIT_0);
2025 tx_sens = ha->fw_seriallink_options[1] &
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07002026 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 rx_sens = (ha->fw_seriallink_options[1] &
2028 (BIT_7 | BIT_6 | BIT_5 | BIT_4)) >> 4;
2029 ha->fw_options[11] = (emphasis << 14) | (swing << 8);
2030 if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {
2031 if (rx_sens == 0x0)
2032 rx_sens = 0x3;
2033 ha->fw_options[11] |= (tx_sens << 4) | rx_sens;
2034 } else if (IS_QLA2322(ha) || IS_QLA6322(ha))
2035 ha->fw_options[11] |= BIT_5 |
2036 ((rx_sens & (BIT_1 | BIT_0)) << 2) |
2037 (tx_sens & (BIT_1 | BIT_0));
2038 }
2039
2040 /* FCP2 options. */
2041 /* Return command IOCBs without waiting for an ABTS to complete. */
2042 ha->fw_options[3] |= BIT_13;
2043
2044 /* LED scheme. */
2045 if (ha->flags.enable_led_scheme)
2046 ha->fw_options[2] |= BIT_12;
2047
andrew.vasquez@qlogic.com48c02fd2006-03-09 14:27:18 -08002048 /* Detect ISP6312. */
2049 if (IS_QLA6312(ha))
2050 ha->fw_options[2] |= BIT_13;
2051
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 /* Update firmware options. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002053 qla2x00_set_fw_options(vha, ha->fw_options);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054}
2055
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002056void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002057qla24xx_update_fw_options(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002058{
2059 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002060 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002061
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04002062 if (IS_P3P_TYPE(ha))
Giridhar Malavalia9083012010-04-12 17:59:55 -07002063 return;
2064
Himanshu Madhanif198caf2016-01-27 12:03:30 -05002065 /* Hold status IOCBs until ABTS response received. */
2066 if (ql2xfwholdabts)
2067 ha->fw_options[3] |= BIT_12;
2068
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002069 /* Update Serial Link options. */
andrew.vasquez@qlogic.comf94097e2006-01-13 17:05:32 -08002070 if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002071 return;
2072
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002073 rval = qla2x00_set_serdes_params(vha,
andrew.vasquez@qlogic.comf94097e2006-01-13 17:05:32 -08002074 le16_to_cpu(ha->fw_seriallink_options24[1]),
2075 le16_to_cpu(ha->fw_seriallink_options24[2]),
2076 le16_to_cpu(ha->fw_seriallink_options24[3]));
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002077 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002078 ql_log(ql_log_warn, vha, 0x0104,
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002079 "Unable to update Serial Link options (%x).\n", rval);
2080 }
2081}
2082
2083void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002084qla2x00_config_rings(struct scsi_qla_host *vha)
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002085{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002086 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07002087 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002088 struct req_que *req = ha->req_q_map[0];
2089 struct rsp_que *rsp = ha->rsp_q_map[0];
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002090
2091 /* Setup ring parameters in initialization control block. */
Bart Van Asschead950362015-07-09 07:24:08 -07002092 ha->init_cb->request_q_outpointer = cpu_to_le16(0);
2093 ha->init_cb->response_q_inpointer = cpu_to_le16(0);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002094 ha->init_cb->request_q_length = cpu_to_le16(req->length);
2095 ha->init_cb->response_q_length = cpu_to_le16(rsp->length);
2096 ha->init_cb->request_q_address[0] = cpu_to_le32(LSD(req->dma));
2097 ha->init_cb->request_q_address[1] = cpu_to_le32(MSD(req->dma));
2098 ha->init_cb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma));
2099 ha->init_cb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma));
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002100
2101 WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), 0);
2102 WRT_REG_WORD(ISP_REQ_Q_OUT(ha, reg), 0);
2103 WRT_REG_WORD(ISP_RSP_Q_IN(ha, reg), 0);
2104 WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), 0);
2105 RD_REG_WORD(ISP_RSP_Q_OUT(ha, reg)); /* PCI Posting. */
2106}
2107
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002108void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002109qla24xx_config_rings(struct scsi_qla_host *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002110{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002111 struct qla_hw_data *ha = vha->hw;
Bart Van Assche118e2ef2015-07-09 07:24:27 -07002112 device_reg_t *reg = ISP_QUE_REG(ha, 0);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002113 struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp;
2114 struct qla_msix_entry *msix;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002115 struct init_cb_24xx *icb;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002116 uint16_t rid = 0;
2117 struct req_que *req = ha->req_q_map[0];
2118 struct rsp_que *rsp = ha->rsp_q_map[0];
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002119
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08002120 /* Setup ring parameters in initialization control block. */
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002121 icb = (struct init_cb_24xx *)ha->init_cb;
Bart Van Asschead950362015-07-09 07:24:08 -07002122 icb->request_q_outpointer = cpu_to_le16(0);
2123 icb->response_q_inpointer = cpu_to_le16(0);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002124 icb->request_q_length = cpu_to_le16(req->length);
2125 icb->response_q_length = cpu_to_le16(rsp->length);
2126 icb->request_q_address[0] = cpu_to_le32(LSD(req->dma));
2127 icb->request_q_address[1] = cpu_to_le32(MSD(req->dma));
2128 icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma));
2129 icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma));
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002130
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002131 /* Setup ATIO queue dma pointers for target mode */
Bart Van Asschead950362015-07-09 07:24:08 -07002132 icb->atio_q_inpointer = cpu_to_le16(0);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002133 icb->atio_q_length = cpu_to_le16(ha->tgt.atio_q_length);
2134 icb->atio_q_address[0] = cpu_to_le32(LSD(ha->tgt.atio_dma));
2135 icb->atio_q_address[1] = cpu_to_le32(MSD(ha->tgt.atio_dma));
2136
Joe Carnuccio7c6300e2014-04-11 16:54:37 -04002137 if (IS_SHADOW_REG_CAPABLE(ha))
Bart Van Asschead950362015-07-09 07:24:08 -07002138 icb->firmware_options_2 |= cpu_to_le32(BIT_30|BIT_29);
Joe Carnuccio7c6300e2014-04-11 16:54:37 -04002139
Chad Dupuisf73cb692014-02-26 04:15:06 -05002140 if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
Bart Van Asschead950362015-07-09 07:24:08 -07002141 icb->qos = cpu_to_le16(QLA_DEFAULT_QUE_QOS);
2142 icb->rid = cpu_to_le16(rid);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002143 if (ha->flags.msix_enabled) {
2144 msix = &ha->msix_entries[1];
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002145 ql_dbg(ql_dbg_init, vha, 0x00fd,
2146 "Registering vector 0x%x for base que.\n",
2147 msix->entry);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002148 icb->msix = cpu_to_le16(msix->entry);
2149 }
2150 /* Use alternate PCI bus number */
2151 if (MSB(rid))
Bart Van Asschead950362015-07-09 07:24:08 -07002152 icb->firmware_options_2 |= cpu_to_le32(BIT_19);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002153 /* Use alternate PCI devfn */
2154 if (LSB(rid))
Bart Van Asschead950362015-07-09 07:24:08 -07002155 icb->firmware_options_2 |= cpu_to_le32(BIT_18);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002156
Anirban Chakraborty31557542009-12-02 10:36:55 -08002157 /* Use Disable MSIX Handshake mode for capable adapters */
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08002158 if ((ha->fw_attributes & BIT_6) && (IS_MSIX_NACK_CAPABLE(ha)) &&
2159 (ha->flags.msix_enabled)) {
Bart Van Asschead950362015-07-09 07:24:08 -07002160 icb->firmware_options_2 &= cpu_to_le32(~BIT_22);
Anirban Chakraborty31557542009-12-02 10:36:55 -08002161 ha->flags.disable_msix_handshake = 1;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002162 ql_dbg(ql_dbg_init, vha, 0x00fe,
2163 "MSIX Handshake Disable Mode turned on.\n");
Anirban Chakraborty31557542009-12-02 10:36:55 -08002164 } else {
Bart Van Asschead950362015-07-09 07:24:08 -07002165 icb->firmware_options_2 |= cpu_to_le32(BIT_22);
Anirban Chakraborty31557542009-12-02 10:36:55 -08002166 }
Bart Van Asschead950362015-07-09 07:24:08 -07002167 icb->firmware_options_2 |= cpu_to_le32(BIT_23);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002168
2169 WRT_REG_DWORD(&reg->isp25mq.req_q_in, 0);
2170 WRT_REG_DWORD(&reg->isp25mq.req_q_out, 0);
2171 WRT_REG_DWORD(&reg->isp25mq.rsp_q_in, 0);
2172 WRT_REG_DWORD(&reg->isp25mq.rsp_q_out, 0);
2173 } else {
2174 WRT_REG_DWORD(&reg->isp24.req_q_in, 0);
2175 WRT_REG_DWORD(&reg->isp24.req_q_out, 0);
2176 WRT_REG_DWORD(&reg->isp24.rsp_q_in, 0);
2177 WRT_REG_DWORD(&reg->isp24.rsp_q_out, 0);
2178 }
Arun Easiaa230bc2013-01-30 03:34:39 -05002179 qlt_24xx_config_rings(vha);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002180
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002181 /* PCI posting */
2182 RD_REG_DWORD(&ioreg->hccr);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002183}
2184
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185/**
2186 * qla2x00_init_rings() - Initializes firmware.
2187 * @ha: HA context
2188 *
2189 * Beginning of request ring has initialization control block already built
2190 * by nvram config routine.
2191 *
2192 * Returns 0 on success.
2193 */
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04002194int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002195qla2x00_init_rings(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196{
2197 int rval;
2198 unsigned long flags = 0;
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08002199 int cnt, que;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002200 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08002201 struct req_que *req;
2202 struct rsp_que *rsp;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07002203 struct mid_init_cb_24xx *mid_init_cb =
2204 (struct mid_init_cb_24xx *) ha->init_cb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205
2206 spin_lock_irqsave(&ha->hardware_lock, flags);
2207
2208 /* Clear outstanding commands array. */
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002209 for (que = 0; que < ha->max_req_queues; que++) {
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08002210 req = ha->req_q_map[que];
Quinn Trancb432852016-02-04 11:45:16 -05002211 if (!req || !test_bit(que, ha->req_qid_map))
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08002212 continue;
Joe Carnuccio7c6300e2014-04-11 16:54:37 -04002213 req->out_ptr = (void *)(req->ring + req->length);
2214 *req->out_ptr = 0;
Chad Dupuis8d93f552013-01-30 03:34:37 -05002215 for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++)
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08002216 req->outstanding_cmds[cnt] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002218 req->current_outstanding_cmd = 1;
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08002219
2220 /* Initialize firmware. */
2221 req->ring_ptr = req->ring;
2222 req->ring_index = 0;
2223 req->cnt = req->length;
2224 }
2225
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002226 for (que = 0; que < ha->max_rsp_queues; que++) {
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08002227 rsp = ha->rsp_q_map[que];
Quinn Trancb432852016-02-04 11:45:16 -05002228 if (!rsp || !test_bit(que, ha->rsp_qid_map))
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08002229 continue;
Joe Carnuccio7c6300e2014-04-11 16:54:37 -04002230 rsp->in_ptr = (void *)(rsp->ring + rsp->length);
2231 *rsp->in_ptr = 0;
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08002232 /* Initialize response queue entries */
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04002233 if (IS_QLAFX00(ha))
2234 qlafx00_init_response_q_entries(rsp);
2235 else
2236 qla2x00_init_response_q_entries(rsp);
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08002237 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002239 ha->tgt.atio_ring_ptr = ha->tgt.atio_ring;
2240 ha->tgt.atio_ring_index = 0;
2241 /* Initialize ATIO queue entries */
2242 qlt_init_atio_q_entries(vha);
2243
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002244 ha->isp_ops->config_rings(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245
2246 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2247
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04002248 ql_dbg(ql_dbg_init, vha, 0x00d1, "Issue init firmware.\n");
2249
2250 if (IS_QLAFX00(ha)) {
2251 rval = qlafx00_init_firmware(vha, ha->init_cb_size);
2252 goto next_check;
2253 }
2254
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 /* Update any ISP specific firmware options before initialization. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002256 ha->isp_ops->update_fw_options(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
Lalit Chandivade605aa2b2009-03-05 11:07:01 -08002258 if (ha->flags.npiv_supported) {
Saurav Kashyap45980cc2012-08-22 14:21:21 -04002259 if (ha->operating_mode == LOOP && !IS_CNA_CAPABLE(ha))
Lalit Chandivade605aa2b2009-03-05 11:07:01 -08002260 ha->max_npiv_vports = MIN_MULTI_ID_FABRIC - 1;
Seokmann Juc48339d2008-01-17 09:02:19 -08002261 mid_init_cb->count = cpu_to_le16(ha->max_npiv_vports);
Lalit Chandivade605aa2b2009-03-05 11:07:01 -08002262 }
2263
Andrew Vasquez24a08132009-03-24 09:08:16 -07002264 if (IS_FWI2_CAPABLE(ha)) {
Bart Van Asschead950362015-07-09 07:24:08 -07002265 mid_init_cb->options = cpu_to_le16(BIT_1);
Andrew Vasquez24a08132009-03-24 09:08:16 -07002266 mid_init_cb->init_cb.execution_throttle =
Quinn Tran03e8c682015-12-17 14:56:59 -05002267 cpu_to_le16(ha->cur_fw_xcb_count);
Himanshu Madhani25232cc2014-09-25 05:16:54 -04002268 /* D-Port Status */
2269 if (IS_DPORT_CAPABLE(ha))
2270 mid_init_cb->init_cb.firmware_options_1 |=
2271 cpu_to_le16(BIT_7);
Himanshu Madhani2486c622014-09-25 05:17:00 -04002272 /* Enable FA-WWPN */
2273 ha->flags.fawwpn_enabled =
2274 (mid_init_cb->init_cb.firmware_options_1 & BIT_6) ? 1 : 0;
2275 ql_dbg(ql_dbg_init, vha, 0x0141, "FA-WWPN Support: %s.\n",
2276 (ha->flags.fawwpn_enabled) ? "enabled" : "disabled");
Andrew Vasquez24a08132009-03-24 09:08:16 -07002277 }
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07002278
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002279 rval = qla2x00_init_firmware(vha, ha->init_cb_size);
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04002280next_check:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002282 ql_log(ql_log_fatal, vha, 0x00d2,
2283 "Init Firmware **** FAILED ****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002285 ql_dbg(ql_dbg_init, vha, 0x00d3,
2286 "Init Firmware -- success.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 }
2288
2289 return (rval);
2290}
2291
2292/**
2293 * qla2x00_fw_ready() - Waits for firmware ready.
2294 * @ha: HA context
2295 *
2296 * Returns 0 on success.
2297 */
2298static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002299qla2x00_fw_ready(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300{
2301 int rval;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07002302 unsigned long wtime, mtime, cs84xx_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 uint16_t min_wait; /* Minimum wait time if loop is down */
2304 uint16_t wait_time; /* Wait time if loop is coming ready */
Joe Carnucciob5a340d2014-09-25 05:16:48 -04002305 uint16_t state[6];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002306 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04002308 if (IS_QLAFX00(vha->hw))
2309 return qlafx00_fw_ready(vha);
2310
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 rval = QLA_SUCCESS;
2312
Chad Dupuis334614912015-04-09 14:59:57 -04002313 /* Time to wait for loop down */
2314 if (IS_P3P_TYPE(ha))
2315 min_wait = 30;
2316 else
2317 min_wait = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318
2319 /*
2320 * Firmware should take at most one RATOV to login, plus 5 seconds for
2321 * our own processing.
2322 */
2323 if ((wait_time = (ha->retry_count*ha->login_timeout) + 5) < min_wait) {
2324 wait_time = min_wait;
2325 }
2326
2327 /* Min wait time if loop down */
2328 mtime = jiffies + (min_wait * HZ);
2329
2330 /* wait time before firmware ready */
2331 wtime = jiffies + (wait_time * HZ);
2332
2333 /* Wait for ISP to finish LIP */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002334 if (!vha->flags.init_done)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002335 ql_log(ql_log_info, vha, 0x801e,
2336 "Waiting for LIP to complete.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337
2338 do {
Andrew Vasquez5b939032012-11-21 02:40:26 -05002339 memset(state, -1, sizeof(state));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002340 rval = qla2x00_get_firmware_state(vha, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 if (rval == QLA_SUCCESS) {
Harihara Kadayam4d4df192008-04-03 13:13:26 -07002342 if (state[0] < FSTATE_LOSS_OF_SYNC) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002343 vha->device_flags &= ~DFLG_NO_CABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 }
Harihara Kadayam4d4df192008-04-03 13:13:26 -07002345 if (IS_QLA84XX(ha) && state[0] != FSTATE_READY) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002346 ql_dbg(ql_dbg_taskm, vha, 0x801f,
2347 "fw_state=%x 84xx=%x.\n", state[0],
2348 state[2]);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07002349 if ((state[2] & FSTATE_LOGGED_IN) &&
2350 (state[2] & FSTATE_WAITING_FOR_VERIFY)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002351 ql_dbg(ql_dbg_taskm, vha, 0x8028,
2352 "Sending verify iocb.\n");
Harihara Kadayam4d4df192008-04-03 13:13:26 -07002353
2354 cs84xx_time = jiffies;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002355 rval = qla84xx_init_chip(vha);
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002356 if (rval != QLA_SUCCESS) {
2357 ql_log(ql_log_warn,
Chad Dupuiscfb09192011-11-18 09:03:07 -08002358 vha, 0x8007,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002359 "Init chip failed.\n");
Harihara Kadayam4d4df192008-04-03 13:13:26 -07002360 break;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002361 }
Harihara Kadayam4d4df192008-04-03 13:13:26 -07002362
2363 /* Add time taken to initialize. */
2364 cs84xx_time = jiffies - cs84xx_time;
2365 wtime += cs84xx_time;
2366 mtime += cs84xx_time;
Chad Dupuiscfb09192011-11-18 09:03:07 -08002367 ql_dbg(ql_dbg_taskm, vha, 0x8008,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002368 "Increasing wait time by %ld. "
2369 "New time %ld.\n", cs84xx_time,
2370 wtime);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07002371 }
2372 } else if (state[0] == FSTATE_READY) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002373 ql_dbg(ql_dbg_taskm, vha, 0x8037,
2374 "F/W Ready - OK.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002376 qla2x00_get_retry_cnt(vha, &ha->retry_count,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 &ha->login_timeout, &ha->r_a_tov);
2378
2379 rval = QLA_SUCCESS;
2380 break;
2381 }
2382
2383 rval = QLA_FUNCTION_FAILED;
2384
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002385 if (atomic_read(&vha->loop_down_timer) &&
Harihara Kadayam4d4df192008-04-03 13:13:26 -07002386 state[0] != FSTATE_READY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 /* Loop down. Timeout on min_wait for states
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07002388 * other than Wait for Login.
2389 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 if (time_after_eq(jiffies, mtime)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002391 ql_log(ql_log_info, vha, 0x8038,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392 "Cable is unplugged...\n");
2393
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002394 vha->device_flags |= DFLG_NO_CABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 break;
2396 }
2397 }
2398 } else {
2399 /* Mailbox cmd failed. Timeout on min_wait. */
Santosh Vernekarcdbb0a4f2010-05-28 15:08:25 -07002400 if (time_after_eq(jiffies, mtime) ||
Giridhar Malavali71905752011-02-23 15:27:10 -08002401 ha->flags.isp82xx_fw_hung)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 break;
2403 }
2404
2405 if (time_after_eq(jiffies, wtime))
2406 break;
2407
2408 /* Delay for a while */
2409 msleep(500);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 } while (1);
2411
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002412 ql_dbg(ql_dbg_taskm, vha, 0x803a,
Joe Carnucciob5a340d2014-09-25 05:16:48 -04002413 "fw_state=%x (%x, %x, %x, %x %x) curr time=%lx.\n", state[0],
2414 state[1], state[2], state[3], state[4], state[5], jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415
Chad Dupuiscfb09192011-11-18 09:03:07 -08002416 if (rval && !(vha->device_flags & DFLG_NO_CABLE)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002417 ql_log(ql_log_warn, vha, 0x803b,
2418 "Firmware ready **** FAILED ****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 }
2420
2421 return (rval);
2422}
2423
2424/*
2425* qla2x00_configure_hba
2426* Setup adapter context.
2427*
2428* Input:
2429* ha = adapter state pointer.
2430*
2431* Returns:
2432* 0 = success
2433*
2434* Context:
2435* Kernel context.
2436*/
2437static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002438qla2x00_configure_hba(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439{
2440 int rval;
2441 uint16_t loop_id;
2442 uint16_t topo;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07002443 uint16_t sw_cap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 uint8_t al_pa;
2445 uint8_t area;
2446 uint8_t domain;
2447 char connect_type[22];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002448 struct qla_hw_data *ha = vha->hw;
Jiri Kosinaf24b5cb2012-10-08 09:23:54 +02002449 unsigned long flags;
Joe Carnuccio61e1b262013-02-08 01:57:48 -05002450 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451
2452 /* Get host addresses. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002453 rval = qla2x00_get_adapter_id(vha,
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07002454 &loop_id, &al_pa, &area, &domain, &topo, &sw_cap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 if (rval != QLA_SUCCESS) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002456 if (LOOP_TRANSITION(vha) || atomic_read(&ha->loop_down_timer) ||
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08002457 IS_CNA_CAPABLE(ha) ||
Ravi Anand33135aa2005-11-08 14:37:20 -08002458 (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002459 ql_dbg(ql_dbg_disc, vha, 0x2008,
2460 "Loop is in a transition state.\n");
Ravi Anand33135aa2005-11-08 14:37:20 -08002461 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002462 ql_log(ql_log_warn, vha, 0x2009,
2463 "Unable to get host loop ID.\n");
Joe Carnuccio61e1b262013-02-08 01:57:48 -05002464 if (IS_FWI2_CAPABLE(ha) && (vha == base_vha) &&
2465 (rval == QLA_COMMAND_ERROR && loop_id == 0x1b)) {
2466 ql_log(ql_log_warn, vha, 0x1151,
2467 "Doing link init.\n");
2468 if (qla24xx_link_initialize(vha) == QLA_SUCCESS)
2469 return rval;
2470 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002471 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Ravi Anand33135aa2005-11-08 14:37:20 -08002472 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 return (rval);
2474 }
2475
2476 if (topo == 4) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002477 ql_log(ql_log_info, vha, 0x200a,
2478 "Cannot get topology - retrying.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 return (QLA_FUNCTION_FAILED);
2480 }
2481
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002482 vha->loop_id = loop_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483
2484 /* initialize */
2485 ha->min_external_loopid = SNS_FIRST_LOOP_ID;
2486 ha->operating_mode = LOOP;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07002487 ha->switch_cap = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488
2489 switch (topo) {
2490 case 0:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002491 ql_dbg(ql_dbg_disc, vha, 0x200b, "HBA in NL topology.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492 ha->current_topology = ISP_CFG_NL;
2493 strcpy(connect_type, "(Loop)");
2494 break;
2495
2496 case 1:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002497 ql_dbg(ql_dbg_disc, vha, 0x200c, "HBA in FL topology.\n");
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07002498 ha->switch_cap = sw_cap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 ha->current_topology = ISP_CFG_FL;
2500 strcpy(connect_type, "(FL_Port)");
2501 break;
2502
2503 case 2:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002504 ql_dbg(ql_dbg_disc, vha, 0x200d, "HBA in N P2P topology.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 ha->operating_mode = P2P;
2506 ha->current_topology = ISP_CFG_N;
2507 strcpy(connect_type, "(N_Port-to-N_Port)");
2508 break;
2509
2510 case 3:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002511 ql_dbg(ql_dbg_disc, vha, 0x200e, "HBA in F P2P topology.\n");
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07002512 ha->switch_cap = sw_cap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513 ha->operating_mode = P2P;
2514 ha->current_topology = ISP_CFG_F;
2515 strcpy(connect_type, "(F_Port)");
2516 break;
2517
2518 default:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002519 ql_dbg(ql_dbg_disc, vha, 0x200f,
2520 "HBA in unknown topology %x, using NL.\n", topo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 ha->current_topology = ISP_CFG_NL;
2522 strcpy(connect_type, "(Loop)");
2523 break;
2524 }
2525
2526 /* Save Host port and loop ID. */
2527 /* byte order - Big Endian */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002528 vha->d_id.b.domain = domain;
2529 vha->d_id.b.area = area;
2530 vha->d_id.b.al_pa = al_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531
Jiri Kosinaf24b5cb2012-10-08 09:23:54 +02002532 spin_lock_irqsave(&ha->vport_slock, flags);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002533 qlt_update_vp_map(vha, SET_AL_PA);
Jiri Kosinaf24b5cb2012-10-08 09:23:54 +02002534 spin_unlock_irqrestore(&ha->vport_slock, flags);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002535
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002536 if (!vha->flags.init_done)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002537 ql_log(ql_log_info, vha, 0x2010,
2538 "Topology - %s, Host Loop address 0x%x.\n",
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002539 connect_type, vha->loop_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 return(rval);
2542}
2543
Giridhar Malavalia9083012010-04-12 17:59:55 -07002544inline void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002545qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
2546 char *def)
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08002547{
2548 char *st, *en;
2549 uint16_t index;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002550 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezab671142009-08-25 11:36:17 -07002551 int use_tbl = !IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) &&
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08002552 !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha);
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08002553
2554 if (memcmp(model, BINZERO, len) != 0) {
2555 strncpy(ha->model_number, model, len);
2556 st = en = ha->model_number;
2557 en += len - 1;
2558 while (en > st) {
2559 if (*en != 0x20 && *en != 0x00)
2560 break;
2561 *en-- = '\0';
2562 }
2563
2564 index = (ha->pdev->subsystem_device & 0xff);
Andrew Vasquez7d0dba12009-04-06 22:33:45 -07002565 if (use_tbl &&
2566 ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08002567 index < QLA_MODEL_NAMES)
Joe Carnuccio1ee27142008-07-10 16:55:53 -07002568 strncpy(ha->model_desc,
2569 qla2x00_model_name[index * 2 + 1],
2570 sizeof(ha->model_desc) - 1);
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08002571 } else {
2572 index = (ha->pdev->subsystem_device & 0xff);
Andrew Vasquez7d0dba12009-04-06 22:33:45 -07002573 if (use_tbl &&
2574 ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08002575 index < QLA_MODEL_NAMES) {
2576 strcpy(ha->model_number,
2577 qla2x00_model_name[index * 2]);
Joe Carnuccio1ee27142008-07-10 16:55:53 -07002578 strncpy(ha->model_desc,
2579 qla2x00_model_name[index * 2 + 1],
2580 sizeof(ha->model_desc) - 1);
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08002581 } else {
2582 strcpy(ha->model_number, def);
2583 }
2584 }
Joe Carnuccio1ee27142008-07-10 16:55:53 -07002585 if (IS_FWI2_CAPABLE(ha))
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002586 qla2xxx_get_vpd_field(vha, "\x82", ha->model_desc,
Joe Carnuccio1ee27142008-07-10 16:55:53 -07002587 sizeof(ha->model_desc));
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08002588}
2589
David Miller4e08df32007-04-16 12:37:43 -07002590/* On sparc systems, obtain port and node WWN from firmware
2591 * properties.
2592 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002593static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
David Miller4e08df32007-04-16 12:37:43 -07002594{
2595#ifdef CONFIG_SPARC
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002596 struct qla_hw_data *ha = vha->hw;
David Miller4e08df32007-04-16 12:37:43 -07002597 struct pci_dev *pdev = ha->pdev;
David S. Miller15576bc2007-05-08 00:36:49 -07002598 struct device_node *dp = pci_device_to_OF_node(pdev);
2599 const u8 *val;
David Miller4e08df32007-04-16 12:37:43 -07002600 int len;
2601
2602 val = of_get_property(dp, "port-wwn", &len);
2603 if (val && len >= WWN_SIZE)
2604 memcpy(nv->port_name, val, WWN_SIZE);
2605
2606 val = of_get_property(dp, "node-wwn", &len);
2607 if (val && len >= WWN_SIZE)
2608 memcpy(nv->node_name, val, WWN_SIZE);
2609#endif
2610}
2611
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612/*
2613* NVRAM configuration for ISP 2xxx
2614*
2615* Input:
2616* ha = adapter block pointer.
2617*
2618* Output:
2619* initialization control block in response_ring
2620* host adapters parameters in host adapter block
2621*
2622* Returns:
2623* 0 = success.
2624*/
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002625int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002626qla2x00_nvram_config(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627{
David Miller4e08df32007-04-16 12:37:43 -07002628 int rval;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002629 uint8_t chksum = 0;
2630 uint16_t cnt;
2631 uint8_t *dptr1, *dptr2;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002632 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002633 init_cb_t *icb = ha->init_cb;
Seokmann Ju281afe12007-07-26 13:43:34 -07002634 nvram_t *nv = ha->nvram;
2635 uint8_t *ptr = ha->nvram;
Andrew Vasquez3d716442005-07-06 10:30:26 -07002636 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637
David Miller4e08df32007-04-16 12:37:43 -07002638 rval = QLA_SUCCESS;
2639
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 /* Determine NVRAM starting address. */
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002641 ha->nvram_size = sizeof(nvram_t);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 ha->nvram_base = 0;
2643 if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha))
2644 if ((RD_REG_WORD(&reg->ctrl_status) >> 14) == 1)
2645 ha->nvram_base = 0x80;
2646
2647 /* Get NVRAM data and calculate checksum. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002648 ha->isp_ops->read_nvram(vha, ptr, ha->nvram_base, ha->nvram_size);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002649 for (cnt = 0, chksum = 0; cnt < ha->nvram_size; cnt++)
2650 chksum += *ptr++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002652 ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x010f,
2653 "Contents of NVRAM.\n");
2654 ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0110,
2655 (uint8_t *)nv, ha->nvram_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656
2657 /* Bad NVRAM data, set defaults parameters. */
2658 if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
2659 nv->id[2] != 'P' || nv->id[3] != ' ' || nv->nvram_version < 1) {
2660 /* Reset NVRAM data. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002661 ql_log(ql_log_warn, vha, 0x0064,
Raul Porcel9e336522012-05-15 14:34:08 -04002662 "Inconsistent NVRAM "
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002663 "detected: checksum=0x%x id=%c version=0x%x.\n",
2664 chksum, nv->id[0], nv->nvram_version);
2665 ql_log(ql_log_warn, vha, 0x0065,
2666 "Falling back to "
2667 "functioning (yet invalid -- WWPN) defaults.\n");
David Miller4e08df32007-04-16 12:37:43 -07002668
2669 /*
2670 * Set default initialization control block.
2671 */
2672 memset(nv, 0, ha->nvram_size);
2673 nv->parameter_block_version = ICB_VERSION;
2674
2675 if (IS_QLA23XX(ha)) {
2676 nv->firmware_options[0] = BIT_2 | BIT_1;
2677 nv->firmware_options[1] = BIT_7 | BIT_5;
2678 nv->add_firmware_options[0] = BIT_5;
2679 nv->add_firmware_options[1] = BIT_5 | BIT_4;
Joe Carnuccio98aee702014-09-25 05:16:38 -04002680 nv->frame_payload_size = 2048;
David Miller4e08df32007-04-16 12:37:43 -07002681 nv->special_options[1] = BIT_7;
2682 } else if (IS_QLA2200(ha)) {
2683 nv->firmware_options[0] = BIT_2 | BIT_1;
2684 nv->firmware_options[1] = BIT_7 | BIT_5;
2685 nv->add_firmware_options[0] = BIT_5;
2686 nv->add_firmware_options[1] = BIT_5 | BIT_4;
Joe Carnuccio98aee702014-09-25 05:16:38 -04002687 nv->frame_payload_size = 1024;
David Miller4e08df32007-04-16 12:37:43 -07002688 } else if (IS_QLA2100(ha)) {
2689 nv->firmware_options[0] = BIT_3 | BIT_1;
2690 nv->firmware_options[1] = BIT_5;
Joe Carnuccio98aee702014-09-25 05:16:38 -04002691 nv->frame_payload_size = 1024;
David Miller4e08df32007-04-16 12:37:43 -07002692 }
2693
Bart Van Asschead950362015-07-09 07:24:08 -07002694 nv->max_iocb_allocation = cpu_to_le16(256);
2695 nv->execution_throttle = cpu_to_le16(16);
David Miller4e08df32007-04-16 12:37:43 -07002696 nv->retry_count = 8;
2697 nv->retry_delay = 1;
2698
2699 nv->port_name[0] = 33;
2700 nv->port_name[3] = 224;
2701 nv->port_name[4] = 139;
2702
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002703 qla2xxx_nvram_wwn_from_ofw(vha, nv);
David Miller4e08df32007-04-16 12:37:43 -07002704
2705 nv->login_timeout = 4;
2706
2707 /*
2708 * Set default host adapter parameters
2709 */
2710 nv->host_p[1] = BIT_2;
2711 nv->reset_delay = 5;
2712 nv->port_down_retry_count = 8;
Bart Van Asschead950362015-07-09 07:24:08 -07002713 nv->max_luns_per_target = cpu_to_le16(8);
David Miller4e08df32007-04-16 12:37:43 -07002714 nv->link_down_timeout = 60;
2715
2716 rval = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 }
2718
2719#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
2720 /*
2721 * The SN2 does not provide BIOS emulation which means you can't change
2722 * potentially bogus BIOS settings. Force the use of default settings
2723 * for link rate and frame size. Hope that the rest of the settings
2724 * are valid.
2725 */
2726 if (ia64_platform_is("sn2")) {
Joe Carnuccio98aee702014-09-25 05:16:38 -04002727 nv->frame_payload_size = 2048;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 if (IS_QLA23XX(ha))
2729 nv->special_options[1] = BIT_7;
2730 }
2731#endif
2732
2733 /* Reset Initialization control block */
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002734 memset(icb, 0, ha->init_cb_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735
2736 /*
2737 * Setup driver NVRAM options.
2738 */
2739 nv->firmware_options[0] |= (BIT_6 | BIT_1);
2740 nv->firmware_options[0] &= ~(BIT_5 | BIT_4);
2741 nv->firmware_options[1] |= (BIT_5 | BIT_0);
2742 nv->firmware_options[1] &= ~BIT_4;
2743
2744 if (IS_QLA23XX(ha)) {
2745 nv->firmware_options[0] |= BIT_2;
2746 nv->firmware_options[0] &= ~BIT_3;
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002747 nv->special_options[0] &= ~BIT_6;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002748 nv->add_firmware_options[1] |= BIT_5 | BIT_4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749
2750 if (IS_QLA2300(ha)) {
2751 if (ha->fb_rev == FPM_2310) {
2752 strcpy(ha->model_number, "QLA2310");
2753 } else {
2754 strcpy(ha->model_number, "QLA2300");
2755 }
2756 } else {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002757 qla2x00_set_model_info(vha, nv->model_number,
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08002758 sizeof(nv->model_number), "QLA23xx");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 }
2760 } else if (IS_QLA2200(ha)) {
2761 nv->firmware_options[0] |= BIT_2;
2762 /*
2763 * 'Point-to-point preferred, else loop' is not a safe
2764 * connection mode setting.
2765 */
2766 if ((nv->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) ==
2767 (BIT_5 | BIT_4)) {
2768 /* Force 'loop preferred, else point-to-point'. */
2769 nv->add_firmware_options[0] &= ~(BIT_6 | BIT_5 | BIT_4);
2770 nv->add_firmware_options[0] |= BIT_5;
2771 }
2772 strcpy(ha->model_number, "QLA22xx");
2773 } else /*if (IS_QLA2100(ha))*/ {
2774 strcpy(ha->model_number, "QLA2100");
2775 }
2776
2777 /*
2778 * Copy over NVRAM RISC parameter block to initialization control block.
2779 */
2780 dptr1 = (uint8_t *)icb;
2781 dptr2 = (uint8_t *)&nv->parameter_block_version;
2782 cnt = (uint8_t *)&icb->request_q_outpointer - (uint8_t *)&icb->version;
2783 while (cnt--)
2784 *dptr1++ = *dptr2++;
2785
2786 /* Copy 2nd half. */
2787 dptr1 = (uint8_t *)icb->add_firmware_options;
2788 cnt = (uint8_t *)icb->reserved_3 - (uint8_t *)icb->add_firmware_options;
2789 while (cnt--)
2790 *dptr1++ = *dptr2++;
2791
Andrew Vasquez5341e862006-05-17 15:09:16 -07002792 /* Use alternate WWN? */
2793 if (nv->host_p[1] & BIT_7) {
2794 memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
2795 memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
2796 }
2797
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 /* Prepare nodename */
2799 if ((icb->firmware_options[1] & BIT_6) == 0) {
2800 /*
2801 * Firmware will apply the following mask if the nodename was
2802 * not provided.
2803 */
2804 memcpy(icb->node_name, icb->port_name, WWN_SIZE);
2805 icb->node_name[0] &= 0xF0;
2806 }
2807
2808 /*
2809 * Set host adapter parameters.
2810 */
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002811
2812 /*
2813 * BIT_7 in the host-parameters section allows for modification to
2814 * internal driver logging.
2815 */
Andrew Vasquez01819442006-06-23 16:11:10 -07002816 if (nv->host_p[0] & BIT_7)
Chad Dupuiscfb09192011-11-18 09:03:07 -08002817 ql2xextended_error_logging = QL_DBG_DEFAULT1_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818 ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0);
2819 /* Always load RISC code on non ISP2[12]00 chips. */
2820 if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
2821 ha->flags.disable_risc_code_load = 0;
2822 ha->flags.enable_lip_reset = ((nv->host_p[1] & BIT_1) ? 1 : 0);
2823 ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0);
2824 ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0);
Andrew Vasquez06c22bd2005-08-26 19:09:00 -07002825 ha->flags.enable_led_scheme = (nv->special_options[1] & BIT_4) ? 1 : 0;
Andrew Vasquezd4c760c2006-06-23 16:10:39 -07002826 ha->flags.disable_serdes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827
2828 ha->operating_mode =
2829 (icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4;
2830
2831 memcpy(ha->fw_seriallink_options, nv->seriallink_options,
2832 sizeof(ha->fw_seriallink_options));
2833
2834 /* save HBA serial number */
2835 ha->serial0 = icb->port_name[5];
2836 ha->serial1 = icb->port_name[6];
2837 ha->serial2 = icb->port_name[7];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002838 memcpy(vha->node_name, icb->node_name, WWN_SIZE);
2839 memcpy(vha->port_name, icb->port_name, WWN_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840
Bart Van Asschead950362015-07-09 07:24:08 -07002841 icb->execution_throttle = cpu_to_le16(0xFFFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842
2843 ha->retry_count = nv->retry_count;
2844
2845 /* Set minimum login_timeout to 4 seconds. */
Andrew Vasquez5b914902010-05-28 15:08:30 -07002846 if (nv->login_timeout != ql2xlogintimeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847 nv->login_timeout = ql2xlogintimeout;
2848 if (nv->login_timeout < 4)
2849 nv->login_timeout = 4;
2850 ha->login_timeout = nv->login_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851
Andrew Vasquez00a537b2008-02-28 14:06:11 -08002852 /* Set minimum RATOV to 100 tenths of a second. */
2853 ha->r_a_tov = 100;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855 ha->loop_reset_delay = nv->reset_delay;
2856
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857 /* Link Down Timeout = 0:
2858 *
2859 * When Port Down timer expires we will start returning
2860 * I/O's to OS with "DID_NO_CONNECT".
2861 *
2862 * Link Down Timeout != 0:
2863 *
2864 * The driver waits for the link to come up after link down
2865 * before returning I/Os to OS with "DID_NO_CONNECT".
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07002866 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867 if (nv->link_down_timeout == 0) {
2868 ha->loop_down_abort_time =
Andrew Vasquez 354d6b22005-04-23 02:47:27 -04002869 (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870 } else {
2871 ha->link_down_timeout = nv->link_down_timeout;
2872 ha->loop_down_abort_time =
2873 (LOOP_DOWN_TIME - ha->link_down_timeout);
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07002874 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876 /*
2877 * Need enough time to try and get the port back.
2878 */
2879 ha->port_down_retry_count = nv->port_down_retry_count;
2880 if (qlport_down_retry)
2881 ha->port_down_retry_count = qlport_down_retry;
2882 /* Set login_retry_count */
2883 ha->login_retry_count = nv->retry_count;
2884 if (ha->port_down_retry_count == nv->port_down_retry_count &&
2885 ha->port_down_retry_count > 3)
2886 ha->login_retry_count = ha->port_down_retry_count;
2887 else if (ha->port_down_retry_count > (int)ha->login_retry_count)
2888 ha->login_retry_count = ha->port_down_retry_count;
2889 if (ql2xloginretrycount)
2890 ha->login_retry_count = ql2xloginretrycount;
2891
Bart Van Asschead950362015-07-09 07:24:08 -07002892 icb->lun_enables = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893 icb->command_resource_count = 0;
2894 icb->immediate_notify_resource_count = 0;
Bart Van Asschead950362015-07-09 07:24:08 -07002895 icb->timeout = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896
2897 if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
2898 /* Enable RIO */
2899 icb->firmware_options[0] &= ~BIT_3;
2900 icb->add_firmware_options[0] &=
2901 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0);
2902 icb->add_firmware_options[0] |= BIT_2;
2903 icb->response_accumulation_timer = 3;
2904 icb->interrupt_delay_timer = 5;
2905
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002906 vha->flags.process_response_queue = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907 } else {
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07002908 /* Enable ZIO. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002909 if (!vha->flags.init_done) {
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07002910 ha->zio_mode = icb->add_firmware_options[0] &
2911 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
2912 ha->zio_timer = icb->interrupt_delay_timer ?
2913 icb->interrupt_delay_timer: 2;
2914 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915 icb->add_firmware_options[0] &=
2916 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002917 vha->flags.process_response_queue = 0;
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07002918 if (ha->zio_mode != QLA_ZIO_DISABLED) {
andrew.vasquez@qlogic.com4a59f712006-03-09 14:27:39 -08002919 ha->zio_mode = QLA_ZIO_MODE_6;
2920
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002921 ql_log(ql_log_info, vha, 0x0068,
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07002922 "ZIO mode %d enabled; timer delay (%d us).\n",
2923 ha->zio_mode, ha->zio_timer * 100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07002925 icb->add_firmware_options[0] |= (uint8_t)ha->zio_mode;
2926 icb->interrupt_delay_timer = (uint8_t)ha->zio_timer;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002927 vha->flags.process_response_queue = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928 }
2929 }
2930
David Miller4e08df32007-04-16 12:37:43 -07002931 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002932 ql_log(ql_log_warn, vha, 0x0069,
2933 "NVRAM configuration failed.\n");
David Miller4e08df32007-04-16 12:37:43 -07002934 }
2935 return (rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936}
2937
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04002938static void
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04002939qla2x00_rport_del(void *data)
2940{
2941 fc_port_t *fcport = data;
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08002942 struct fc_rport *rport;
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08002943 unsigned long flags;
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04002944
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08002945 spin_lock_irqsave(fcport->vha->host->host_lock, flags);
Andrew Vasquezac280b62009-08-20 11:06:05 -07002946 rport = fcport->drport ? fcport->drport: fcport->rport;
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08002947 fcport->drport = NULL;
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08002948 spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
Alexei Potashnikdf673272015-07-14 16:00:46 -04002949 if (rport)
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08002950 fc_remote_port_delete(rport);
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04002951}
2952
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953/**
2954 * qla2x00_alloc_fcport() - Allocate a generic fcport.
2955 * @ha: HA context
2956 * @flags: allocation flags
2957 *
2958 * Returns a pointer to the allocated fcport, or NULL, if none available.
2959 */
Giridhar Malavali9a069e12010-01-12 13:02:47 -08002960fc_port_t *
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002961qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962{
2963 fc_port_t *fcport;
2964
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02002965 fcport = kzalloc(sizeof(fc_port_t), flags);
2966 if (!fcport)
2967 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968
2969 /* Setup fcport template structure. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002970 fcport->vha = vha;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971 fcport->port_type = FCT_UNKNOWN;
2972 fcport->loop_id = FC_NO_LOOP_ID;
Chad Dupuisec426e12011-03-30 11:46:32 -07002973 qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED);
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07002974 fcport->supported_classes = FC_COS_UNSPECIFIED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02002976 return fcport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977}
2978
2979/*
2980 * qla2x00_configure_loop
2981 * Updates Fibre Channel Device Database with what is actually on loop.
2982 *
2983 * Input:
2984 * ha = adapter block pointer.
2985 *
2986 * Returns:
2987 * 0 = success.
2988 * 1 = error.
2989 * 2 = database was full and device was not configured.
2990 */
2991static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002992qla2x00_configure_loop(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993{
2994 int rval;
2995 unsigned long flags, save_flags;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002996 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997 rval = QLA_SUCCESS;
2998
2999 /* Get Initiator ID */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003000 if (test_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags)) {
3001 rval = qla2x00_configure_hba(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003003 ql_dbg(ql_dbg_disc, vha, 0x2013,
3004 "Unable to configure HBA.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 return (rval);
3006 }
3007 }
3008
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003009 save_flags = flags = vha->dpc_flags;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003010 ql_dbg(ql_dbg_disc, vha, 0x2014,
3011 "Configure loop -- dpc flags = 0x%lx.\n", flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012
3013 /*
3014 * If we have both an RSCN and PORT UPDATE pending then handle them
3015 * both at the same time.
3016 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003017 clear_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
3018 clear_bit(RSCN_UPDATE, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019
Michael Hernandez3064ff32009-12-15 21:29:44 -08003020 qla2x00_get_data_rate(vha);
3021
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 /* Determine what we need to do */
3023 if (ha->current_topology == ISP_CFG_FL &&
3024 (test_bit(LOCAL_LOOP_UPDATE, &flags))) {
3025
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 set_bit(RSCN_UPDATE, &flags);
3027
3028 } else if (ha->current_topology == ISP_CFG_F &&
3029 (test_bit(LOCAL_LOOP_UPDATE, &flags))) {
3030
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 set_bit(RSCN_UPDATE, &flags);
3032 clear_bit(LOCAL_LOOP_UPDATE, &flags);
3033
Andrew Vasquez21333b42006-05-17 15:09:56 -07003034 } else if (ha->current_topology == ISP_CFG_N) {
3035 clear_bit(RSCN_UPDATE, &flags);
3036
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003037 } else if (!vha->flags.online ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038 (test_bit(ABORT_ISP_ACTIVE, &flags))) {
3039
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040 set_bit(RSCN_UPDATE, &flags);
3041 set_bit(LOCAL_LOOP_UPDATE, &flags);
3042 }
3043
3044 if (test_bit(LOCAL_LOOP_UPDATE, &flags)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003045 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
3046 ql_dbg(ql_dbg_disc, vha, 0x2015,
3047 "Loop resync needed, failing.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048 rval = QLA_FUNCTION_FAILED;
Chad Dupuis642ef982012-02-09 11:15:57 -08003049 } else
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003050 rval = qla2x00_configure_local_loop(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051 }
3052
3053 if (rval == QLA_SUCCESS && test_bit(RSCN_UPDATE, &flags)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003054 if (LOOP_TRANSITION(vha)) {
3055 ql_dbg(ql_dbg_disc, vha, 0x201e,
3056 "Needs RSCN update and loop transition.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057 rval = QLA_FUNCTION_FAILED;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003058 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003059 else
3060 rval = qla2x00_configure_fabric(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061 }
3062
3063 if (rval == QLA_SUCCESS) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003064 if (atomic_read(&vha->loop_down_timer) ||
3065 test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 rval = QLA_FUNCTION_FAILED;
3067 } else {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003068 atomic_set(&vha->loop_state, LOOP_READY);
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003069 ql_dbg(ql_dbg_disc, vha, 0x2069,
3070 "LOOP READY.\n");
Dilip Kumar Uppugandla3bb67df2015-12-17 14:57:11 -05003071
3072 /*
3073 * Process any ATIO queue entries that came in
3074 * while we weren't online.
3075 */
3076 if (qla_tgt_mode_enabled(vha)) {
3077 if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) {
3078 spin_lock_irqsave(&ha->tgt.atio_lock,
3079 flags);
3080 qlt_24xx_process_atio_queue(vha, 0);
3081 spin_unlock_irqrestore(
3082 &ha->tgt.atio_lock, flags);
3083 } else {
3084 spin_lock_irqsave(&ha->hardware_lock,
3085 flags);
3086 qlt_24xx_process_atio_queue(vha, 1);
3087 spin_unlock_irqrestore(
3088 &ha->hardware_lock, flags);
3089 }
3090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091 }
3092 }
3093
3094 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003095 ql_dbg(ql_dbg_disc, vha, 0x206a,
3096 "%s *** FAILED ***.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003098 ql_dbg(ql_dbg_disc, vha, 0x206b,
3099 "%s: exiting normally.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100 }
3101
Bjorn Helgaascc3ef7b2008-09-11 21:22:51 -07003102 /* Restore state if a resync event occurred during processing */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003103 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104 if (test_bit(LOCAL_LOOP_UPDATE, &save_flags))
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003105 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
Andrew Vasquezf4658b62009-06-03 09:55:21 -07003106 if (test_bit(RSCN_UPDATE, &save_flags)) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003107 set_bit(RSCN_UPDATE, &vha->dpc_flags);
Andrew Vasquezf4658b62009-06-03 09:55:21 -07003108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 }
3110
3111 return (rval);
3112}
3113
3114
3115
3116/*
3117 * qla2x00_configure_local_loop
3118 * Updates Fibre Channel Device Database with local loop devices.
3119 *
3120 * Input:
3121 * ha = adapter block pointer.
3122 *
3123 * Returns:
3124 * 0 = success.
3125 */
3126static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003127qla2x00_configure_local_loop(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128{
3129 int rval, rval2;
3130 int found_devs;
3131 int found;
3132 fc_port_t *fcport, *new_fcport;
3133
3134 uint16_t index;
3135 uint16_t entries;
3136 char *id_iter;
3137 uint16_t loop_id;
3138 uint8_t domain, area, al_pa;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003139 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140
3141 found_devs = 0;
3142 new_fcport = NULL;
Chad Dupuis642ef982012-02-09 11:15:57 -08003143 entries = MAX_FIBRE_DEVICES_LOOP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145 /* Get list of logged in devices. */
Chad Dupuis642ef982012-02-09 11:15:57 -08003146 memset(ha->gid_list, 0, qla2x00_gid_list_size(ha));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003147 rval = qla2x00_get_id_list(vha, ha->gid_list, ha->gid_list_dma,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 &entries);
3149 if (rval != QLA_SUCCESS)
3150 goto cleanup_allocation;
3151
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003152 ql_dbg(ql_dbg_disc, vha, 0x2017,
3153 "Entries in ID list (%d).\n", entries);
3154 ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2075,
3155 (uint8_t *)ha->gid_list,
3156 entries * sizeof(struct gid_list_info));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157
3158 /* Allocate temporary fcport for any new fcports discovered. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003159 new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 if (new_fcport == NULL) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003161 ql_log(ql_log_warn, vha, 0x2018,
3162 "Memory allocation failed for fcport.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163 rval = QLA_MEMORY_ALLOC_FAILED;
3164 goto cleanup_allocation;
3165 }
3166 new_fcport->flags &= ~FCF_FABRIC_DEVICE;
3167
3168 /*
3169 * Mark local devices that were present with FCF_DEVICE_LOST for now.
3170 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003171 list_for_each_entry(fcport, &vha->vp_fcports, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 if (atomic_read(&fcport->state) == FCS_ONLINE &&
3173 fcport->port_type != FCT_BROADCAST &&
3174 (fcport->flags & FCF_FABRIC_DEVICE) == 0) {
3175
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003176 ql_dbg(ql_dbg_disc, vha, 0x2019,
3177 "Marking port lost loop_id=0x%04x.\n",
3178 fcport->loop_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179
Chad Dupuisec426e12011-03-30 11:46:32 -07003180 qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181 }
3182 }
3183
3184 /* Add devices to port list. */
3185 id_iter = (char *)ha->gid_list;
3186 for (index = 0; index < entries; index++) {
3187 domain = ((struct gid_list_info *)id_iter)->domain;
3188 area = ((struct gid_list_info *)id_iter)->area;
3189 al_pa = ((struct gid_list_info *)id_iter)->al_pa;
Andrew Vasquezabbd8872005-07-06 10:30:05 -07003190 if (IS_QLA2100(ha) || IS_QLA2200(ha))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191 loop_id = (uint16_t)
3192 ((struct gid_list_info *)id_iter)->loop_id_2100;
Andrew Vasquezabbd8872005-07-06 10:30:05 -07003193 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194 loop_id = le16_to_cpu(
3195 ((struct gid_list_info *)id_iter)->loop_id);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07003196 id_iter += ha->gid_list_info_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197
3198 /* Bypass reserved domain fields. */
3199 if ((domain & 0xf0) == 0xf0)
3200 continue;
3201
3202 /* Bypass if not same domain and area of adapter. */
Andrew Vasquezf7d289f2005-08-26 19:08:40 -07003203 if (area && domain &&
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003204 (area != vha->d_id.b.area || domain != vha->d_id.b.domain))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205 continue;
3206
3207 /* Bypass invalid local loop ID. */
3208 if (loop_id > LAST_LOCAL_LOOP_ID)
3209 continue;
3210
Arun Easi370d5502012-08-22 14:21:10 -04003211 memset(new_fcport, 0, sizeof(fc_port_t));
3212
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213 /* Fill in member data. */
3214 new_fcport->d_id.b.domain = domain;
3215 new_fcport->d_id.b.area = area;
3216 new_fcport->d_id.b.al_pa = al_pa;
3217 new_fcport->loop_id = loop_id;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003218 rval2 = qla2x00_get_port_database(vha, new_fcport, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219 if (rval2 != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003220 ql_dbg(ql_dbg_disc, vha, 0x201a,
3221 "Failed to retrieve fcport information "
3222 "-- get_port_database=%x, loop_id=0x%04x.\n",
3223 rval2, new_fcport->loop_id);
3224 ql_dbg(ql_dbg_disc, vha, 0x201b,
3225 "Scheduling resync.\n");
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003226 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227 continue;
3228 }
3229
3230 /* Check for matching device in port list. */
3231 found = 0;
3232 fcport = NULL;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003233 list_for_each_entry(fcport, &vha->vp_fcports, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234 if (memcmp(new_fcport->port_name, fcport->port_name,
3235 WWN_SIZE))
3236 continue;
3237
Shyam Sundarddb9b122009-03-24 09:08:10 -07003238 fcport->flags &= ~FCF_FABRIC_DEVICE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239 fcport->loop_id = new_fcport->loop_id;
3240 fcport->port_type = new_fcport->port_type;
3241 fcport->d_id.b24 = new_fcport->d_id.b24;
3242 memcpy(fcport->node_name, new_fcport->node_name,
3243 WWN_SIZE);
3244
3245 found++;
3246 break;
3247 }
3248
3249 if (!found) {
3250 /* New device, add to fcports list. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003251 list_add_tail(&new_fcport->list, &vha->vp_fcports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252
3253 /* Allocate a new replacement fcport. */
3254 fcport = new_fcport;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003255 new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256 if (new_fcport == NULL) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003257 ql_log(ql_log_warn, vha, 0x201c,
3258 "Failed to allocate memory for fcport.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259 rval = QLA_MEMORY_ALLOC_FAILED;
3260 goto cleanup_allocation;
3261 }
3262 new_fcport->flags &= ~FCF_FABRIC_DEVICE;
3263 }
3264
Andrew Vasquezd8b45212006-10-02 12:00:43 -07003265 /* Base iIDMA settings on HBA port speed. */
Andrew Vasqueza3cbdfa2007-08-13 10:13:18 -07003266 fcport->fp_speed = ha->link_data_rate;
Andrew Vasquezd8b45212006-10-02 12:00:43 -07003267
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003268 qla2x00_update_fcport(vha, fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269
3270 found_devs++;
3271 }
3272
3273cleanup_allocation:
Jesper Juhlc9475cb2005-11-07 01:01:26 -08003274 kfree(new_fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275
3276 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003277 ql_dbg(ql_dbg_disc, vha, 0x201d,
3278 "Configure local loop error exit: rval=%x.\n", rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279 }
3280
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281 return (rval);
3282}
3283
3284static void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003285qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
Andrew Vasquezd8b45212006-10-02 12:00:43 -07003286{
Andrew Vasquezd8b45212006-10-02 12:00:43 -07003287 int rval;
Quinn Tran93f2bd62014-09-25 05:16:53 -04003288 uint16_t mb[MAILBOX_REGISTER_COUNT];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003289 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezd8b45212006-10-02 12:00:43 -07003290
Andrew Vasquezc76f2c02007-07-19 15:05:57 -07003291 if (!IS_IIDMA_CAPABLE(ha))
Andrew Vasquezd8b45212006-10-02 12:00:43 -07003292 return;
3293
Giridhar Malavalic9afb9a2010-09-03 15:20:48 -07003294 if (atomic_read(&fcport->state) != FCS_ONLINE)
3295 return;
3296
Andrew Vasquez39bd9622007-09-20 14:07:34 -07003297 if (fcport->fp_speed == PORT_SPEED_UNKNOWN ||
3298 fcport->fp_speed > ha->link_data_rate)
Andrew Vasquezd8b45212006-10-02 12:00:43 -07003299 return;
3300
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003301 rval = qla2x00_set_idma_speed(vha, fcport->loop_id, fcport->fp_speed,
Andrew Vasqueza3cbdfa2007-08-13 10:13:18 -07003302 mb);
Andrew Vasquezd8b45212006-10-02 12:00:43 -07003303 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003304 ql_dbg(ql_dbg_disc, vha, 0x2004,
Oleksandr Khoshaba7b8335582013-08-27 01:37:27 -04003305 "Unable to adjust iIDMA %8phN -- %04x %x %04x %04x.\n",
3306 fcport->port_name, rval, fcport->fp_speed, mb[0], mb[1]);
Andrew Vasquezd8b45212006-10-02 12:00:43 -07003307 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003308 ql_dbg(ql_dbg_disc, vha, 0x2005,
Oleksandr Khoshaba7b8335582013-08-27 01:37:27 -04003309 "iIDMA adjusted to %s GB/s on %8phN.\n",
Joe Carnucciod0297c92012-11-21 02:40:40 -05003310 qla2x00_get_link_speed_str(ha, fcport->fp_speed),
Oleksandr Khoshaba7b8335582013-08-27 01:37:27 -04003311 fcport->port_name);
Andrew Vasquezd8b45212006-10-02 12:00:43 -07003312 }
3313}
3314
Adrian Bunk23be3312006-11-24 02:46:01 +01003315static void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003316qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
8482e1182005-04-17 15:04:54 -05003317{
3318 struct fc_rport_identifiers rport_ids;
bdf79622005-04-17 15:06:53 -05003319 struct fc_rport *rport;
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08003320 unsigned long flags;
8482e1182005-04-17 15:04:54 -05003321
Andrew Vasquezf8b02a82005-08-31 15:21:20 -07003322 rport_ids.node_name = wwn_to_u64(fcport->node_name);
3323 rport_ids.port_name = wwn_to_u64(fcport->port_name);
8482e1182005-04-17 15:04:54 -05003324 rport_ids.port_id = fcport->d_id.b.domain << 16 |
3325 fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
3326 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003327 fcport->rport = rport = fc_remote_port_add(vha->host, 0, &rport_ids);
Andrew Vasquez77d74142005-07-08 18:00:36 -07003328 if (!rport) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003329 ql_log(ql_log_warn, vha, 0x2006,
3330 "Unable to allocate fc remote port.\n");
Andrew Vasquez77d74142005-07-08 18:00:36 -07003331 return;
3332 }
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003333 /*
3334 * Create target mode FC NEXUS in qla_target.c if target mode is
3335 * enabled..
3336 */
Saurav Kashyapba9f6f62015-06-10 11:05:17 -04003337
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003338 qlt_fc_port_added(vha, fcport);
3339
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08003340 spin_lock_irqsave(fcport->vha->host->host_lock, flags);
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04003341 *((fc_port_t **)rport->dd_data) = fcport;
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08003342 spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08003343
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07003344 rport->supported_classes = fcport->supported_classes;
Andrew Vasquez77d74142005-07-08 18:00:36 -07003345
3346 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
8482e1182005-04-17 15:04:54 -05003347 if (fcport->port_type == FCT_INITIATOR)
3348 rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
3349 if (fcport->port_type == FCT_TARGET)
3350 rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
Andrew Vasquez77d74142005-07-08 18:00:36 -07003351 fc_remote_port_rolechg(rport, rport_ids.roles);
8482e1182005-04-17 15:04:54 -05003352}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353
3354/*
Adrian Bunk23be3312006-11-24 02:46:01 +01003355 * qla2x00_update_fcport
3356 * Updates device on list.
3357 *
3358 * Input:
3359 * ha = adapter block pointer.
3360 * fcport = port structure pointer.
3361 *
3362 * Return:
3363 * 0 - Success
3364 * BIT_0 - error
3365 *
3366 * Context:
3367 * Kernel context.
3368 */
3369void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003370qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
Adrian Bunk23be3312006-11-24 02:46:01 +01003371{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003372 fcport->vha = vha;
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04003373
3374 if (IS_QLAFX00(vha->hw)) {
3375 qla2x00_set_fcport_state(fcport, FCS_ONLINE);
Alexei Potashnikd20ed912015-07-14 16:00:47 -04003376 goto reg_port;
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04003377 }
Adrian Bunk23be3312006-11-24 02:46:01 +01003378 fcport->login_retry = 0;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07003379 fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
Adrian Bunk23be3312006-11-24 02:46:01 +01003380
Joe Carnuccio1f93da522012-11-21 02:40:38 -05003381 qla2x00_set_fcport_state(fcport, FCS_ONLINE);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003382 qla2x00_iidma_fcport(vha, fcport);
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08003383 qla24xx_update_fcport_fcp_prio(vha, fcport);
Alexei Potashnikd20ed912015-07-14 16:00:47 -04003384
3385reg_port:
3386 if (qla_ini_mode_enabled(vha))
3387 qla2x00_reg_remote_port(vha, fcport);
3388 else {
3389 /*
3390 * Create target mode FC NEXUS in qla_target.c
3391 */
3392 qlt_fc_port_added(vha, fcport);
3393 }
Adrian Bunk23be3312006-11-24 02:46:01 +01003394}
3395
3396/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397 * qla2x00_configure_fabric
3398 * Setup SNS devices with loop ID's.
3399 *
3400 * Input:
3401 * ha = adapter block pointer.
3402 *
3403 * Returns:
3404 * 0 = success.
3405 * BIT_0 = error
3406 */
3407static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003408qla2x00_configure_fabric(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409{
Arun Easib3b02e62012-02-09 11:15:39 -08003410 int rval;
Joe Carnuccioe452ceb2013-02-08 01:57:56 -05003411 fc_port_t *fcport, *fcptemp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412 uint16_t next_loopid;
3413 uint16_t mb[MAILBOX_REGISTER_COUNT];
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003414 uint16_t loop_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415 LIST_HEAD(new_fcports);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003416 struct qla_hw_data *ha = vha->hw;
3417 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Alexei Potashnikdf673272015-07-14 16:00:46 -04003418 int discovery_gen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419
3420 /* If FL port exists, then SNS is present */
Andrew Vasqueze4289242007-07-19 15:05:56 -07003421 if (IS_FWI2_CAPABLE(ha))
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003422 loop_id = NPH_F_PORT;
3423 else
3424 loop_id = SNS_FL_PORT;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003425 rval = qla2x00_get_port_name(vha, loop_id, vha->fabric_node_name, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003427 ql_dbg(ql_dbg_disc, vha, 0x201f,
3428 "MBX_GET_PORT_NAME failed, No FL Port.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003430 vha->device_flags &= ~SWITCH_FOUND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431 return (QLA_SUCCESS);
3432 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003433 vha->device_flags |= SWITCH_FOUND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435 do {
Andrew Vasquezcca53352005-08-26 19:08:30 -07003436 /* FDMI support. */
3437 if (ql2xfdmienable &&
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003438 test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags))
3439 qla2x00_fdmi_register(vha);
Andrew Vasquezcca53352005-08-26 19:08:30 -07003440
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441 /* Ensure we are logged into the SNS. */
Andrew Vasqueze4289242007-07-19 15:05:56 -07003442 if (IS_FWI2_CAPABLE(ha))
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003443 loop_id = NPH_SNS;
3444 else
3445 loop_id = SIMPLE_NAME_SERVER;
Chad Dupuis0b91d112012-02-09 11:15:42 -08003446 rval = ha->isp_ops->fabric_login(vha, loop_id, 0xff, 0xff,
3447 0xfc, mb, BIT_1|BIT_0);
3448 if (rval != QLA_SUCCESS) {
3449 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
Joe Carnuccioe452ceb2013-02-08 01:57:56 -05003450 return rval;
Chad Dupuis0b91d112012-02-09 11:15:42 -08003451 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452 if (mb[0] != MBS_COMMAND_COMPLETE) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003453 ql_dbg(ql_dbg_disc, vha, 0x2042,
3454 "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x "
3455 "mb[6]=%x mb[7]=%x.\n", loop_id, mb[0], mb[1],
3456 mb[2], mb[6], mb[7]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 return (QLA_SUCCESS);
3458 }
3459
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003460 if (test_and_clear_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags)) {
3461 if (qla2x00_rft_id(vha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462 /* EMPTY */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003463 ql_dbg(ql_dbg_disc, vha, 0x2045,
3464 "Register FC-4 TYPE failed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003466 if (qla2x00_rff_id(vha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467 /* EMPTY */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003468 ql_dbg(ql_dbg_disc, vha, 0x2049,
3469 "Register FC-4 Features failed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003471 if (qla2x00_rnn_id(vha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472 /* EMPTY */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003473 ql_dbg(ql_dbg_disc, vha, 0x204f,
3474 "Register Node Name failed.\n");
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003475 } else if (qla2x00_rsnn_nn(vha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476 /* EMPTY */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003477 ql_dbg(ql_dbg_disc, vha, 0x2053,
3478 "Register Symobilic Node Name failed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479 }
3480 }
3481
Joe Carnuccio827210b2013-02-08 01:57:57 -05003482#define QLA_FCPORT_SCAN 1
3483#define QLA_FCPORT_FOUND 2
3484
3485 list_for_each_entry(fcport, &vha->vp_fcports, list) {
3486 fcport->scan_state = QLA_FCPORT_SCAN;
3487 }
3488
Alexei Potashnikdf673272015-07-14 16:00:46 -04003489 /* Mark the time right before querying FW for connected ports.
3490 * This process is long, asynchronous and by the time it's done,
3491 * collected information might not be accurate anymore. E.g.
3492 * disconnected port might have re-connected and a brand new
3493 * session has been created. In this case session's generation
3494 * will be newer than discovery_gen. */
3495 qlt_do_generation_tick(vha, &discovery_gen);
3496
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003497 rval = qla2x00_find_all_fabric_devs(vha, &new_fcports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498 if (rval != QLA_SUCCESS)
3499 break;
3500
Joe Carnuccioe452ceb2013-02-08 01:57:56 -05003501 /*
3502 * Logout all previous fabric devices marked lost, except
3503 * FCP2 devices.
3504 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003505 list_for_each_entry(fcport, &vha->vp_fcports, list) {
3506 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507 break;
3508
3509 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
3510 continue;
3511
Roland Dreierb2032fd2015-07-14 16:00:42 -04003512 if (fcport->scan_state == QLA_FCPORT_SCAN) {
3513 if (qla_ini_mode_enabled(base_vha) &&
3514 atomic_read(&fcport->state) == FCS_ONLINE) {
3515 qla2x00_mark_device_lost(vha, fcport,
3516 ql2xplogiabsentdevice, 0);
3517 if (fcport->loop_id != FC_NO_LOOP_ID &&
3518 (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
3519 fcport->port_type != FCT_INITIATOR &&
3520 fcport->port_type != FCT_BROADCAST) {
3521 ha->isp_ops->fabric_logout(vha,
3522 fcport->loop_id,
3523 fcport->d_id.b.domain,
3524 fcport->d_id.b.area,
3525 fcport->d_id.b.al_pa);
3526 qla2x00_clear_loop_id(fcport);
3527 }
3528 } else if (!qla_ini_mode_enabled(base_vha)) {
3529 /*
3530 * In target mode, explicitly kill
3531 * sessions and log out of devices
3532 * that are gone, so that we don't
3533 * end up with an initiator using the
3534 * wrong ACL (if the fabric recycles
3535 * an FC address and we have a stale
3536 * session around) and so that we don't
3537 * report initiators that are no longer
3538 * on the fabric.
3539 */
3540 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf077,
3541 "port gone, logging out/killing session: "
3542 "%8phC state 0x%x flags 0x%x fc4_type 0x%x "
3543 "scan_state %d\n",
3544 fcport->port_name,
3545 atomic_read(&fcport->state),
3546 fcport->flags, fcport->fc4_type,
3547 fcport->scan_state);
Alexei Potashnikdf673272015-07-14 16:00:46 -04003548 qlt_fc_port_deleted(vha, fcport,
3549 discovery_gen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550 }
3551 }
Joe Carnuccioe452ceb2013-02-08 01:57:56 -05003552 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553
Joe Carnuccioe452ceb2013-02-08 01:57:56 -05003554 /* Starting free loop ID. */
3555 next_loopid = ha->min_external_loopid;
3556
3557 /*
3558 * Scan through our port list and login entries that need to be
3559 * logged in.
3560 */
3561 list_for_each_entry(fcport, &vha->vp_fcports, list) {
3562 if (atomic_read(&vha->loop_down_timer) ||
3563 test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
3564 break;
3565
3566 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
3567 (fcport->flags & FCF_LOGIN_NEEDED) == 0)
3568 continue;
3569
Roland Dreierb2032fd2015-07-14 16:00:42 -04003570 /*
3571 * If we're not an initiator, skip looking for devices
3572 * and logging in. There's no reason for us to do it,
3573 * and it seems to actively cause problems in target
3574 * mode if we race with the initiator logging into us
3575 * (we might get the "port ID used" status back from
3576 * our login command and log out the initiator, which
3577 * seems to cause havoc).
3578 */
3579 if (!qla_ini_mode_enabled(base_vha)) {
3580 if (fcport->scan_state == QLA_FCPORT_FOUND) {
3581 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf078,
3582 "port %8phC state 0x%x flags 0x%x fc4_type 0x%x "
3583 "scan_state %d (initiator mode disabled; skipping "
3584 "login)\n", fcport->port_name,
3585 atomic_read(&fcport->state),
3586 fcport->flags, fcport->fc4_type,
3587 fcport->scan_state);
3588 }
3589 continue;
3590 }
3591
Joe Carnuccioe452ceb2013-02-08 01:57:56 -05003592 if (fcport->loop_id == FC_NO_LOOP_ID) {
3593 fcport->loop_id = next_loopid;
3594 rval = qla2x00_find_new_loop_id(
3595 base_vha, fcport);
3596 if (rval != QLA_SUCCESS) {
3597 /* Ran out of IDs to use */
3598 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599 }
3600 }
Joe Carnuccioe452ceb2013-02-08 01:57:56 -05003601 /* Login and update database */
3602 qla2x00_fabric_dev_login(vha, fcport, &next_loopid);
3603 }
3604
3605 /* Exit if out of loop IDs. */
3606 if (rval != QLA_SUCCESS) {
3607 break;
3608 }
3609
3610 /*
3611 * Login and add the new devices to our port list.
3612 */
3613 list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) {
3614 if (atomic_read(&vha->loop_down_timer) ||
3615 test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
3616 break;
3617
Roland Dreierb2032fd2015-07-14 16:00:42 -04003618 /*
3619 * If we're not an initiator, skip looking for devices
3620 * and logging in. There's no reason for us to do it,
3621 * and it seems to actively cause problems in target
3622 * mode if we race with the initiator logging into us
3623 * (we might get the "port ID used" status back from
3624 * our login command and log out the initiator, which
3625 * seems to cause havoc).
3626 */
3627 if (qla_ini_mode_enabled(base_vha)) {
3628 /* Find a new loop ID to use. */
3629 fcport->loop_id = next_loopid;
3630 rval = qla2x00_find_new_loop_id(base_vha,
3631 fcport);
3632 if (rval != QLA_SUCCESS) {
3633 /* Ran out of IDs to use */
3634 break;
3635 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636
Roland Dreierb2032fd2015-07-14 16:00:42 -04003637 /* Login and update database */
3638 qla2x00_fabric_dev_login(vha, fcport,
3639 &next_loopid);
3640 } else {
3641 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf079,
3642 "new port %8phC state 0x%x flags 0x%x fc4_type "
3643 "0x%x scan_state %d (initiator mode disabled; "
3644 "skipping login)\n",
3645 fcport->port_name,
3646 atomic_read(&fcport->state),
3647 fcport->flags, fcport->fc4_type,
3648 fcport->scan_state);
3649 }
Joe Carnuccioe452ceb2013-02-08 01:57:56 -05003650
3651 list_move_tail(&fcport->list, &vha->vp_fcports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652 }
3653 } while (0);
3654
Joe Carnuccioe452ceb2013-02-08 01:57:56 -05003655 /* Free all new device structures not processed. */
3656 list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) {
3657 list_del(&fcport->list);
3658 kfree(fcport);
3659 }
3660
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003662 ql_dbg(ql_dbg_disc, vha, 0x2068,
3663 "Configure fabric error exit rval=%d.\n", rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003664 }
3665
3666 return (rval);
3667}
3668
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669/*
3670 * qla2x00_find_all_fabric_devs
3671 *
3672 * Input:
3673 * ha = adapter block pointer.
3674 * dev = database device entry pointer.
3675 *
3676 * Returns:
3677 * 0 = success.
3678 *
3679 * Context:
3680 * Kernel context.
3681 */
3682static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003683qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
3684 struct list_head *new_fcports)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685{
3686 int rval;
3687 uint16_t loop_id;
3688 fc_port_t *fcport, *new_fcport, *fcptemp;
3689 int found;
3690
3691 sw_info_t *swl;
3692 int swl_idx;
3693 int first_dev, last_dev;
Mike Waychison1516ef42010-05-04 15:01:31 -07003694 port_id_t wrap = {}, nxt_d_id;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003695 struct qla_hw_data *ha = vha->hw;
Chad Dupuisbb4cf5b2013-02-08 01:58:01 -05003696 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697
3698 rval = QLA_SUCCESS;
3699
3700 /* Try GID_PT to get device list, else GAN. */
Andrew Vasquez7a677352012-02-09 11:15:56 -08003701 if (!ha->swl)
Chad Dupuis642ef982012-02-09 11:15:57 -08003702 ha->swl = kcalloc(ha->max_fibre_devices, sizeof(sw_info_t),
Andrew Vasquez7a677352012-02-09 11:15:56 -08003703 GFP_KERNEL);
3704 swl = ha->swl;
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02003705 if (!swl) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 /*EMPTY*/
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003707 ql_dbg(ql_dbg_disc, vha, 0x2054,
3708 "GID_PT allocations failed, fallback on GA_NXT.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709 } else {
Chad Dupuis642ef982012-02-09 11:15:57 -08003710 memset(swl, 0, ha->max_fibre_devices * sizeof(sw_info_t));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003711 if (qla2x00_gid_pt(vha, swl) != QLA_SUCCESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712 swl = NULL;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003713 } else if (qla2x00_gpn_id(vha, swl) != QLA_SUCCESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 swl = NULL;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003715 } else if (qla2x00_gnn_id(vha, swl) != QLA_SUCCESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716 swl = NULL;
Andrew Vasqueze5896bd2008-07-10 16:55:52 -07003717 } else if (ql2xiidmaenable &&
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003718 qla2x00_gfpn_id(vha, swl) == QLA_SUCCESS) {
3719 qla2x00_gpsc(vha, swl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720 }
Chad Dupuise8c72ba2010-07-23 15:28:25 +05003721
3722 /* If other queries succeeded probe for FC-4 type */
3723 if (swl)
3724 qla2x00_gff_id(vha, swl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725 }
3726 swl_idx = 0;
3727
3728 /* Allocate temporary fcport for any new fcports discovered. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003729 new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730 if (new_fcport == NULL) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003731 ql_log(ql_log_warn, vha, 0x205e,
3732 "Failed to allocate memory for fcport.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733 return (QLA_MEMORY_ALLOC_FAILED);
3734 }
3735 new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736 /* Set start port ID scan at adapter ID. */
3737 first_dev = 1;
3738 last_dev = 0;
3739
3740 /* Starting free loop ID. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003741 loop_id = ha->min_external_loopid;
3742 for (; loop_id <= ha->max_loop_id; loop_id++) {
3743 if (qla2x00_is_reserved_id(vha, loop_id))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744 continue;
3745
Giridhar Malavali3a6478d2010-05-28 15:08:20 -07003746 if (ha->current_topology == ISP_CFG_FL &&
3747 (atomic_read(&vha->loop_down_timer) ||
3748 LOOP_TRANSITION(vha))) {
Andrew Vasquezbb2d52b2010-02-18 10:07:27 -08003749 atomic_set(&vha->loop_down_timer, 0);
3750 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
3751 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752 break;
Andrew Vasquezbb2d52b2010-02-18 10:07:27 -08003753 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003754
3755 if (swl != NULL) {
3756 if (last_dev) {
3757 wrap.b24 = new_fcport->d_id.b24;
3758 } else {
3759 new_fcport->d_id.b24 = swl[swl_idx].d_id.b24;
3760 memcpy(new_fcport->node_name,
3761 swl[swl_idx].node_name, WWN_SIZE);
3762 memcpy(new_fcport->port_name,
3763 swl[swl_idx].port_name, WWN_SIZE);
Andrew Vasquezd8b45212006-10-02 12:00:43 -07003764 memcpy(new_fcport->fabric_port_name,
3765 swl[swl_idx].fabric_port_name, WWN_SIZE);
3766 new_fcport->fp_speed = swl[swl_idx].fp_speed;
Chad Dupuise8c72ba2010-07-23 15:28:25 +05003767 new_fcport->fc4_type = swl[swl_idx].fc4_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768
3769 if (swl[swl_idx].d_id.b.rsvd_1 != 0) {
3770 last_dev = 1;
3771 }
3772 swl_idx++;
3773 }
3774 } else {
3775 /* Send GA_NXT to the switch */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003776 rval = qla2x00_ga_nxt(vha, new_fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003778 ql_log(ql_log_warn, vha, 0x2064,
3779 "SNS scan failed -- assuming "
3780 "zero-entry result.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 list_for_each_entry_safe(fcport, fcptemp,
3782 new_fcports, list) {
3783 list_del(&fcport->list);
3784 kfree(fcport);
3785 }
3786 rval = QLA_SUCCESS;
3787 break;
3788 }
3789 }
3790
3791 /* If wrap on switch device list, exit. */
3792 if (first_dev) {
3793 wrap.b24 = new_fcport->d_id.b24;
3794 first_dev = 0;
3795 } else if (new_fcport->d_id.b24 == wrap.b24) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003796 ql_dbg(ql_dbg_disc, vha, 0x2065,
3797 "Device wrap (%02x%02x%02x).\n",
3798 new_fcport->d_id.b.domain,
3799 new_fcport->d_id.b.area,
3800 new_fcport->d_id.b.al_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 break;
3802 }
3803
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003804 /* Bypass if same physical adapter. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003805 if (new_fcport->d_id.b24 == base_vha->d_id.b24)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806 continue;
3807
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003808 /* Bypass virtual ports of the same host. */
Chad Dupuisbb4cf5b2013-02-08 01:58:01 -05003809 if (qla2x00_is_a_vp_did(vha, new_fcport->d_id.b24))
3810 continue;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003811
Andrew Vasquezf7d289f2005-08-26 19:08:40 -07003812 /* Bypass if same domain and area of adapter. */
3813 if (((new_fcport->d_id.b24 & 0xffff00) ==
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003814 (vha->d_id.b24 & 0xffff00)) && ha->current_topology ==
Andrew Vasquezf7d289f2005-08-26 19:08:40 -07003815 ISP_CFG_FL)
3816 continue;
3817
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818 /* Bypass reserved domain fields. */
3819 if ((new_fcport->d_id.b.domain & 0xf0) == 0xf0)
3820 continue;
3821
Chad Dupuise8c72ba2010-07-23 15:28:25 +05003822 /* Bypass ports whose FCP-4 type is not FCP_SCSI */
Chad Dupuis4da26e12010-10-15 11:27:40 -07003823 if (ql2xgffidenable &&
3824 (new_fcport->fc4_type != FC4_TYPE_FCP_SCSI &&
3825 new_fcport->fc4_type != FC4_TYPE_UNKNOWN))
Chad Dupuise8c72ba2010-07-23 15:28:25 +05003826 continue;
3827
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 /* Locate matching device in database. */
3829 found = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003830 list_for_each_entry(fcport, &vha->vp_fcports, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 if (memcmp(new_fcport->port_name, fcport->port_name,
3832 WWN_SIZE))
3833 continue;
3834
Joe Carnuccio827210b2013-02-08 01:57:57 -05003835 fcport->scan_state = QLA_FCPORT_FOUND;
Arun Easib3b02e62012-02-09 11:15:39 -08003836
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837 found++;
3838
Andrew Vasquezd8b45212006-10-02 12:00:43 -07003839 /* Update port state. */
3840 memcpy(fcport->fabric_port_name,
3841 new_fcport->fabric_port_name, WWN_SIZE);
3842 fcport->fp_speed = new_fcport->fp_speed;
3843
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844 /*
Roland Dreierb2032fd2015-07-14 16:00:42 -04003845 * If address the same and state FCS_ONLINE
3846 * (or in target mode), nothing changed.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847 */
3848 if (fcport->d_id.b24 == new_fcport->d_id.b24 &&
Roland Dreierb2032fd2015-07-14 16:00:42 -04003849 (atomic_read(&fcport->state) == FCS_ONLINE ||
3850 !qla_ini_mode_enabled(base_vha))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851 break;
3852 }
3853
3854 /*
3855 * If device was not a fabric device before.
3856 */
3857 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
3858 fcport->d_id.b24 = new_fcport->d_id.b24;
Chad Dupuis5f16b332012-08-22 14:21:00 -04003859 qla2x00_clear_loop_id(fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860 fcport->flags |= (FCF_FABRIC_DEVICE |
3861 FCF_LOGIN_NEEDED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 break;
3863 }
3864
3865 /*
3866 * Port ID changed or device was marked to be updated;
3867 * Log it out if still logged in and mark it for
3868 * relogin later.
3869 */
Roland Dreierb2032fd2015-07-14 16:00:42 -04003870 if (!qla_ini_mode_enabled(base_vha)) {
3871 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf080,
3872 "port changed FC ID, %8phC"
3873 " old %x:%x:%x (loop_id 0x%04x)-> new %x:%x:%x\n",
3874 fcport->port_name,
3875 fcport->d_id.b.domain,
3876 fcport->d_id.b.area,
3877 fcport->d_id.b.al_pa,
3878 fcport->loop_id,
3879 new_fcport->d_id.b.domain,
3880 new_fcport->d_id.b.area,
3881 new_fcport->d_id.b.al_pa);
3882 fcport->d_id.b24 = new_fcport->d_id.b24;
3883 break;
3884 }
3885
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886 fcport->d_id.b24 = new_fcport->d_id.b24;
3887 fcport->flags |= FCF_LOGIN_NEEDED;
3888 if (fcport->loop_id != FC_NO_LOOP_ID &&
Andrew Vasquezf08b7252010-01-12 12:59:48 -08003889 (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
Arun Easi0eba25d2012-02-09 11:15:58 -08003890 (fcport->flags & FCF_ASYNC_SENT) == 0 &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891 fcport->port_type != FCT_INITIATOR &&
3892 fcport->port_type != FCT_BROADCAST) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003893 ha->isp_ops->fabric_logout(vha, fcport->loop_id,
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07003894 fcport->d_id.b.domain, fcport->d_id.b.area,
3895 fcport->d_id.b.al_pa);
Chad Dupuis5f16b332012-08-22 14:21:00 -04003896 qla2x00_clear_loop_id(fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897 }
3898
3899 break;
3900 }
3901
3902 if (found)
3903 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904 /* If device was not in our fcports list, then add it. */
Roland Dreierb2032fd2015-07-14 16:00:42 -04003905 new_fcport->scan_state = QLA_FCPORT_FOUND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906 list_add_tail(&new_fcport->list, new_fcports);
3907
3908 /* Allocate a new replacement fcport. */
3909 nxt_d_id.b24 = new_fcport->d_id.b24;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003910 new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 if (new_fcport == NULL) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003912 ql_log(ql_log_warn, vha, 0x2066,
3913 "Memory allocation failed for fcport.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914 return (QLA_MEMORY_ALLOC_FAILED);
3915 }
3916 new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED);
3917 new_fcport->d_id.b24 = nxt_d_id.b24;
3918 }
3919
Jesper Juhlc9475cb2005-11-07 01:01:26 -08003920 kfree(new_fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922 return (rval);
3923}
3924
3925/*
3926 * qla2x00_find_new_loop_id
3927 * Scan through our port list and find a new usable loop ID.
3928 *
3929 * Input:
3930 * ha: adapter state pointer.
3931 * dev: port structure pointer.
3932 *
3933 * Returns:
3934 * qla2x00 local function return status code.
3935 *
3936 * Context:
3937 * Kernel context.
3938 */
Joe Carnuccio03bcfb52011-03-30 11:46:27 -07003939int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003940qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941{
3942 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003943 struct qla_hw_data *ha = vha->hw;
Arun Easifeafb7b2010-09-03 14:57:00 -07003944 unsigned long flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945
3946 rval = QLA_SUCCESS;
3947
Chad Dupuis5f16b332012-08-22 14:21:00 -04003948 spin_lock_irqsave(&ha->vport_slock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949
Chad Dupuis5f16b332012-08-22 14:21:00 -04003950 dev->loop_id = find_first_zero_bit(ha->loop_id_map,
3951 LOOPID_MAP_SIZE);
3952 if (dev->loop_id >= LOOPID_MAP_SIZE ||
3953 qla2x00_is_reserved_id(vha, dev->loop_id)) {
3954 dev->loop_id = FC_NO_LOOP_ID;
3955 rval = QLA_FUNCTION_FAILED;
3956 } else
3957 set_bit(dev->loop_id, ha->loop_id_map);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958
Chad Dupuis5f16b332012-08-22 14:21:00 -04003959 spin_unlock_irqrestore(&ha->vport_slock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960
Chad Dupuis5f16b332012-08-22 14:21:00 -04003961 if (rval == QLA_SUCCESS)
3962 ql_dbg(ql_dbg_disc, dev->vha, 0x2086,
3963 "Assigning new loopid=%x, portid=%x.\n",
3964 dev->loop_id, dev->d_id.b24);
3965 else
3966 ql_log(ql_log_warn, dev->vha, 0x2087,
3967 "No loop_id's available, portid=%x.\n",
3968 dev->d_id.b24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969
3970 return (rval);
3971}
3972
3973/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 * qla2x00_fabric_dev_login
3975 * Login fabric target device and update FC port database.
3976 *
3977 * Input:
3978 * ha: adapter state pointer.
3979 * fcport: port structure list pointer.
3980 * next_loopid: contains value of a new loop ID that can be used
3981 * by the next login attempt.
3982 *
3983 * Returns:
3984 * qla2x00 local function return status code.
3985 *
3986 * Context:
3987 * Kernel context.
3988 */
3989static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003990qla2x00_fabric_dev_login(scsi_qla_host_t *vha, fc_port_t *fcport,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991 uint16_t *next_loopid)
3992{
3993 int rval;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003994 uint8_t opts;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003995 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996
3997 rval = QLA_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998
Andrew Vasquezac280b62009-08-20 11:06:05 -07003999 if (IS_ALOGIO_CAPABLE(ha)) {
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07004000 if (fcport->flags & FCF_ASYNC_SENT)
4001 return rval;
4002 fcport->flags |= FCF_ASYNC_SENT;
Andrew Vasquezac280b62009-08-20 11:06:05 -07004003 rval = qla2x00_post_async_login_work(vha, fcport, NULL);
4004 if (!rval)
4005 return rval;
4006 }
4007
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07004008 fcport->flags &= ~FCF_ASYNC_SENT;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004009 rval = qla2x00_fabric_login(vha, fcport, next_loopid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010 if (rval == QLA_SUCCESS) {
Andrew Vasquezf08b7252010-01-12 12:59:48 -08004011 /* Send an ADISC to FCP2 devices.*/
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004012 opts = 0;
Andrew Vasquezf08b7252010-01-12 12:59:48 -08004013 if (fcport->flags & FCF_FCP2_DEVICE)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004014 opts |= BIT_1;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004015 rval = qla2x00_get_port_database(vha, fcport, opts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 if (rval != QLA_SUCCESS) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004017 ha->isp_ops->fabric_logout(vha, fcport->loop_id,
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07004018 fcport->d_id.b.domain, fcport->d_id.b.area,
4019 fcport->d_id.b.al_pa);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004020 qla2x00_mark_device_lost(vha, fcport, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021 } else {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004022 qla2x00_update_fcport(vha, fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023 }
Chad Dupuis0b91d112012-02-09 11:15:42 -08004024 } else {
4025 /* Retry Login. */
4026 qla2x00_mark_device_lost(vha, fcport, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027 }
4028
4029 return (rval);
4030}
4031
4032/*
4033 * qla2x00_fabric_login
4034 * Issue fabric login command.
4035 *
4036 * Input:
4037 * ha = adapter block pointer.
4038 * device = pointer to FC device type structure.
4039 *
4040 * Returns:
4041 * 0 - Login successfully
4042 * 1 - Login failed
4043 * 2 - Initiator device
4044 * 3 - Fatal error
4045 */
4046int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004047qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048 uint16_t *next_loopid)
4049{
4050 int rval;
4051 int retry;
4052 uint16_t tmp_loopid;
4053 uint16_t mb[MAILBOX_REGISTER_COUNT];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004054 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055
4056 retry = 0;
4057 tmp_loopid = 0;
4058
4059 for (;;) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004060 ql_dbg(ql_dbg_disc, vha, 0x2000,
4061 "Trying Fabric Login w/loop id 0x%04x for port "
4062 "%02x%02x%02x.\n",
4063 fcport->loop_id, fcport->d_id.b.domain,
4064 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065
4066 /* Login fcport on switch. */
Chad Dupuis0b91d112012-02-09 11:15:42 -08004067 rval = ha->isp_ops->fabric_login(vha, fcport->loop_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068 fcport->d_id.b.domain, fcport->d_id.b.area,
4069 fcport->d_id.b.al_pa, mb, BIT_0);
Chad Dupuis0b91d112012-02-09 11:15:42 -08004070 if (rval != QLA_SUCCESS) {
4071 return rval;
4072 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073 if (mb[0] == MBS_PORT_ID_USED) {
4074 /*
4075 * Device has another loop ID. The firmware team
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004076 * recommends the driver perform an implicit login with
4077 * the specified ID again. The ID we just used is save
4078 * here so we return with an ID that can be tried by
4079 * the next login.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080 */
4081 retry++;
4082 tmp_loopid = fcport->loop_id;
4083 fcport->loop_id = mb[1];
4084
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004085 ql_dbg(ql_dbg_disc, vha, 0x2001,
4086 "Fabric Login: port in use - next loop "
4087 "id=0x%04x, port id= %02x%02x%02x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088 fcport->loop_id, fcport->d_id.b.domain,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004089 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090
4091 } else if (mb[0] == MBS_COMMAND_COMPLETE) {
4092 /*
4093 * Login succeeded.
4094 */
4095 if (retry) {
4096 /* A retry occurred before. */
4097 *next_loopid = tmp_loopid;
4098 } else {
4099 /*
4100 * No retry occurred before. Just increment the
4101 * ID value for next login.
4102 */
4103 *next_loopid = (fcport->loop_id + 1);
4104 }
4105
4106 if (mb[1] & BIT_0) {
4107 fcport->port_type = FCT_INITIATOR;
4108 } else {
4109 fcport->port_type = FCT_TARGET;
4110 if (mb[1] & BIT_1) {
Santosh Vernekar8474f3a2009-08-25 11:36:16 -07004111 fcport->flags |= FCF_FCP2_DEVICE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 }
4113 }
4114
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07004115 if (mb[10] & BIT_0)
4116 fcport->supported_classes |= FC_COS_CLASS2;
4117 if (mb[10] & BIT_1)
4118 fcport->supported_classes |= FC_COS_CLASS3;
4119
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04004120 if (IS_FWI2_CAPABLE(ha)) {
4121 if (mb[10] & BIT_7)
4122 fcport->flags |=
4123 FCF_CONF_COMP_SUPPORTED;
4124 }
4125
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126 rval = QLA_SUCCESS;
4127 break;
4128 } else if (mb[0] == MBS_LOOP_ID_USED) {
4129 /*
4130 * Loop ID already used, try next loop ID.
4131 */
4132 fcport->loop_id++;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004133 rval = qla2x00_find_new_loop_id(vha, fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134 if (rval != QLA_SUCCESS) {
4135 /* Ran out of loop IDs to use */
4136 break;
4137 }
4138 } else if (mb[0] == MBS_COMMAND_ERROR) {
4139 /*
4140 * Firmware possibly timed out during login. If NO
4141 * retries are left to do then the device is declared
4142 * dead.
4143 */
4144 *next_loopid = fcport->loop_id;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004145 ha->isp_ops->fabric_logout(vha, fcport->loop_id,
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07004146 fcport->d_id.b.domain, fcport->d_id.b.area,
4147 fcport->d_id.b.al_pa);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004148 qla2x00_mark_device_lost(vha, fcport, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149
4150 rval = 1;
4151 break;
4152 } else {
4153 /*
4154 * unrecoverable / not handled error
4155 */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004156 ql_dbg(ql_dbg_disc, vha, 0x2002,
4157 "Failed=%x port_id=%02x%02x%02x loop_id=%x "
4158 "jiffies=%lx.\n", mb[0], fcport->d_id.b.domain,
4159 fcport->d_id.b.area, fcport->d_id.b.al_pa,
4160 fcport->loop_id, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161
4162 *next_loopid = fcport->loop_id;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004163 ha->isp_ops->fabric_logout(vha, fcport->loop_id,
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07004164 fcport->d_id.b.domain, fcport->d_id.b.area,
4165 fcport->d_id.b.al_pa);
Chad Dupuis5f16b332012-08-22 14:21:00 -04004166 qla2x00_clear_loop_id(fcport);
Andrew Vasquez0eedfcf2005-10-27 11:09:38 -07004167 fcport->login_retry = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168
4169 rval = 3;
4170 break;
4171 }
4172 }
4173
4174 return (rval);
4175}
4176
4177/*
4178 * qla2x00_local_device_login
4179 * Issue local device login command.
4180 *
4181 * Input:
4182 * ha = adapter block pointer.
4183 * loop_id = loop id of device to login to.
4184 *
4185 * Returns (Where's the #define!!!!):
4186 * 0 - Login successfully
4187 * 1 - Login failed
4188 * 3 - Fatal error
4189 */
4190int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004191qla2x00_local_device_login(scsi_qla_host_t *vha, fc_port_t *fcport)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192{
4193 int rval;
4194 uint16_t mb[MAILBOX_REGISTER_COUNT];
4195
4196 memset(mb, 0, sizeof(mb));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004197 rval = qla2x00_login_local_device(vha, fcport, mb, BIT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198 if (rval == QLA_SUCCESS) {
4199 /* Interrogate mailbox registers for any errors */
4200 if (mb[0] == MBS_COMMAND_ERROR)
4201 rval = 1;
4202 else if (mb[0] == MBS_COMMAND_PARAMETER_ERROR)
4203 /* device not in PCB table */
4204 rval = 3;
4205 }
4206
4207 return (rval);
4208}
4209
4210/*
4211 * qla2x00_loop_resync
4212 * Resync with fibre channel devices.
4213 *
4214 * Input:
4215 * ha = adapter block pointer.
4216 *
4217 * Returns:
4218 * 0 = success
4219 */
4220int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004221qla2x00_loop_resync(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222{
Anirban Chakraborty73208df2008-12-09 16:45:39 -08004223 int rval = QLA_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224 uint32_t wait_time;
Anirban Chakraborty67c2e932009-04-06 22:33:42 -07004225 struct req_que *req;
4226 struct rsp_que *rsp;
4227
Anirban Chakraborty7163ea82009-08-05 09:18:40 -07004228 if (vha->hw->flags.cpu_affinity_enabled)
Anirban Chakraborty67c2e932009-04-06 22:33:42 -07004229 req = vha->hw->req_q_map[0];
4230 else
4231 req = vha->req;
4232 rsp = req->rsp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004234 clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
4235 if (vha->flags.online) {
4236 if (!(rval = qla2x00_fw_ready(vha))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237 /* Wait at most MAX_TARGET RSCNs for a stable link. */
4238 wait_time = 256;
4239 do {
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04004240 if (!IS_QLAFX00(vha->hw)) {
4241 /*
4242 * Issue a marker after FW becomes
4243 * ready.
4244 */
4245 qla2x00_marker(vha, req, rsp, 0, 0,
4246 MK_SYNC_ALL);
4247 vha->marker_needed = 0;
4248 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249
4250 /* Remap devices on Loop. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004251 clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04004253 if (IS_QLAFX00(vha->hw))
4254 qlafx00_configure_devices(vha);
4255 else
4256 qla2x00_configure_loop(vha);
4257
Linus Torvalds1da177e2005-04-16 15:20:36 -07004258 wait_time--;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004259 } while (!atomic_read(&vha->loop_down_timer) &&
4260 !(test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
4261 && wait_time && (test_bit(LOOP_RESYNC_NEEDED,
4262 &vha->dpc_flags)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004263 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264 }
4265
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004266 if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267 return (QLA_FUNCTION_FAILED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004269 if (rval)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004270 ql_dbg(ql_dbg_disc, vha, 0x206c,
4271 "%s *** FAILED ***.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272
4273 return (rval);
4274}
4275
Saurav Kashyap579d12b2010-12-21 16:00:14 -08004276/*
4277* qla2x00_perform_loop_resync
4278* Description: This function will set the appropriate flags and call
4279* qla2x00_loop_resync. If successful loop will be resynced
4280* Arguments : scsi_qla_host_t pointer
4281* returm : Success or Failure
4282*/
4283
4284int qla2x00_perform_loop_resync(scsi_qla_host_t *ha)
4285{
4286 int32_t rval = 0;
4287
4288 if (!test_and_set_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags)) {
4289 /*Configure the flags so that resync happens properly*/
4290 atomic_set(&ha->loop_down_timer, 0);
4291 if (!(ha->device_flags & DFLG_NO_CABLE)) {
4292 atomic_set(&ha->loop_state, LOOP_UP);
4293 set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
4294 set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
4295 set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
4296
4297 rval = qla2x00_loop_resync(ha);
4298 } else
4299 atomic_set(&ha->loop_state, LOOP_DEAD);
4300
4301 clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags);
4302 }
4303
4304 return rval;
4305}
4306
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307void
Andrew Vasquez67becc02009-08-25 11:36:20 -07004308qla2x00_update_fcports(scsi_qla_host_t *base_vha)
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08004309{
4310 fc_port_t *fcport;
Arun Easifeafb7b2010-09-03 14:57:00 -07004311 struct scsi_qla_host *vha;
4312 struct qla_hw_data *ha = base_vha->hw;
4313 unsigned long flags;
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08004314
Arun Easifeafb7b2010-09-03 14:57:00 -07004315 spin_lock_irqsave(&ha->vport_slock, flags);
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08004316 /* Go with deferred removal of rport references. */
Arun Easifeafb7b2010-09-03 14:57:00 -07004317 list_for_each_entry(vha, &base_vha->hw->vp_list, list) {
4318 atomic_inc(&vha->vref_count);
4319 list_for_each_entry(fcport, &vha->vp_fcports, list) {
Dan Carpenter8ae598d2010-12-21 16:00:15 -08004320 if (fcport->drport &&
Arun Easifeafb7b2010-09-03 14:57:00 -07004321 atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
4322 spin_unlock_irqrestore(&ha->vport_slock, flags);
Andrew Vasquez67becc02009-08-25 11:36:20 -07004323 qla2x00_rport_del(fcport);
Alexei Potashnikdf673272015-07-14 16:00:46 -04004324
4325 /*
4326 * Release the target mode FC NEXUS in
4327 * qla_target.c, if target mod is enabled.
4328 */
4329 qlt_fc_port_deleted(vha, fcport,
4330 base_vha->total_fcport_update_gen);
4331
Arun Easifeafb7b2010-09-03 14:57:00 -07004332 spin_lock_irqsave(&ha->vport_slock, flags);
4333 }
4334 }
4335 atomic_dec(&vha->vref_count);
4336 }
4337 spin_unlock_irqrestore(&ha->vport_slock, flags);
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08004338}
4339
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04004340/* Assumes idc_lock always held on entry */
4341void
4342qla83xx_reset_ownership(scsi_qla_host_t *vha)
4343{
4344 struct qla_hw_data *ha = vha->hw;
4345 uint32_t drv_presence, drv_presence_mask;
4346 uint32_t dev_part_info1, dev_part_info2, class_type;
4347 uint32_t class_type_mask = 0x3;
4348 uint16_t fcoe_other_function = 0xffff, i;
4349
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04004350 if (IS_QLA8044(ha)) {
4351 drv_presence = qla8044_rd_direct(vha,
4352 QLA8044_CRB_DRV_ACTIVE_INDEX);
4353 dev_part_info1 = qla8044_rd_direct(vha,
4354 QLA8044_CRB_DEV_PART_INFO_INDEX);
4355 dev_part_info2 = qla8044_rd_direct(vha,
4356 QLA8044_CRB_DEV_PART_INFO2);
4357 } else {
4358 qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence);
4359 qla83xx_rd_reg(vha, QLA83XX_DEV_PARTINFO1, &dev_part_info1);
4360 qla83xx_rd_reg(vha, QLA83XX_DEV_PARTINFO2, &dev_part_info2);
4361 }
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04004362 for (i = 0; i < 8; i++) {
4363 class_type = ((dev_part_info1 >> (i * 4)) & class_type_mask);
4364 if ((class_type == QLA83XX_CLASS_TYPE_FCOE) &&
4365 (i != ha->portnum)) {
4366 fcoe_other_function = i;
4367 break;
4368 }
4369 }
4370 if (fcoe_other_function == 0xffff) {
4371 for (i = 0; i < 8; i++) {
4372 class_type = ((dev_part_info2 >> (i * 4)) &
4373 class_type_mask);
4374 if ((class_type == QLA83XX_CLASS_TYPE_FCOE) &&
4375 ((i + 8) != ha->portnum)) {
4376 fcoe_other_function = i + 8;
4377 break;
4378 }
4379 }
4380 }
4381 /*
4382 * Prepare drv-presence mask based on fcoe functions present.
4383 * However consider only valid physical fcoe function numbers (0-15).
4384 */
4385 drv_presence_mask = ~((1 << (ha->portnum)) |
4386 ((fcoe_other_function == 0xffff) ?
4387 0 : (1 << (fcoe_other_function))));
4388
4389 /* We are the reset owner iff:
4390 * - No other protocol drivers present.
4391 * - This is the lowest among fcoe functions. */
4392 if (!(drv_presence & drv_presence_mask) &&
4393 (ha->portnum < fcoe_other_function)) {
4394 ql_dbg(ql_dbg_p3p, vha, 0xb07f,
4395 "This host is Reset owner.\n");
4396 ha->flags.nic_core_reset_owner = 1;
4397 }
4398}
4399
Saurav Kashyapfa492632012-11-21 02:40:29 -05004400static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04004401__qla83xx_set_drv_ack(scsi_qla_host_t *vha)
4402{
4403 int rval = QLA_SUCCESS;
4404 struct qla_hw_data *ha = vha->hw;
4405 uint32_t drv_ack;
4406
4407 rval = qla83xx_rd_reg(vha, QLA83XX_IDC_DRIVER_ACK, &drv_ack);
4408 if (rval == QLA_SUCCESS) {
4409 drv_ack |= (1 << ha->portnum);
4410 rval = qla83xx_wr_reg(vha, QLA83XX_IDC_DRIVER_ACK, drv_ack);
4411 }
4412
4413 return rval;
4414}
4415
Saurav Kashyapfa492632012-11-21 02:40:29 -05004416static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04004417__qla83xx_clear_drv_ack(scsi_qla_host_t *vha)
4418{
4419 int rval = QLA_SUCCESS;
4420 struct qla_hw_data *ha = vha->hw;
4421 uint32_t drv_ack;
4422
4423 rval = qla83xx_rd_reg(vha, QLA83XX_IDC_DRIVER_ACK, &drv_ack);
4424 if (rval == QLA_SUCCESS) {
4425 drv_ack &= ~(1 << ha->portnum);
4426 rval = qla83xx_wr_reg(vha, QLA83XX_IDC_DRIVER_ACK, drv_ack);
4427 }
4428
4429 return rval;
4430}
4431
Saurav Kashyapfa492632012-11-21 02:40:29 -05004432static const char *
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04004433qla83xx_dev_state_to_string(uint32_t dev_state)
4434{
4435 switch (dev_state) {
4436 case QLA8XXX_DEV_COLD:
4437 return "COLD/RE-INIT";
4438 case QLA8XXX_DEV_INITIALIZING:
4439 return "INITIALIZING";
4440 case QLA8XXX_DEV_READY:
4441 return "READY";
4442 case QLA8XXX_DEV_NEED_RESET:
4443 return "NEED RESET";
4444 case QLA8XXX_DEV_NEED_QUIESCENT:
4445 return "NEED QUIESCENT";
4446 case QLA8XXX_DEV_FAILED:
4447 return "FAILED";
4448 case QLA8XXX_DEV_QUIESCENT:
4449 return "QUIESCENT";
4450 default:
4451 return "Unknown";
4452 }
4453}
4454
4455/* Assumes idc-lock always held on entry */
4456void
4457qla83xx_idc_audit(scsi_qla_host_t *vha, int audit_type)
4458{
4459 struct qla_hw_data *ha = vha->hw;
4460 uint32_t idc_audit_reg = 0, duration_secs = 0;
4461
4462 switch (audit_type) {
4463 case IDC_AUDIT_TIMESTAMP:
4464 ha->idc_audit_ts = (jiffies_to_msecs(jiffies) / 1000);
4465 idc_audit_reg = (ha->portnum) |
4466 (IDC_AUDIT_TIMESTAMP << 7) | (ha->idc_audit_ts << 8);
4467 qla83xx_wr_reg(vha, QLA83XX_IDC_AUDIT, idc_audit_reg);
4468 break;
4469
4470 case IDC_AUDIT_COMPLETION:
4471 duration_secs = ((jiffies_to_msecs(jiffies) -
4472 jiffies_to_msecs(ha->idc_audit_ts)) / 1000);
4473 idc_audit_reg = (ha->portnum) |
4474 (IDC_AUDIT_COMPLETION << 7) | (duration_secs << 8);
4475 qla83xx_wr_reg(vha, QLA83XX_IDC_AUDIT, idc_audit_reg);
4476 break;
4477
4478 default:
4479 ql_log(ql_log_warn, vha, 0xb078,
4480 "Invalid audit type specified.\n");
4481 break;
4482 }
4483}
4484
4485/* Assumes idc_lock always held on entry */
Saurav Kashyapfa492632012-11-21 02:40:29 -05004486static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04004487qla83xx_initiating_reset(scsi_qla_host_t *vha)
4488{
4489 struct qla_hw_data *ha = vha->hw;
4490 uint32_t idc_control, dev_state;
4491
4492 __qla83xx_get_idc_control(vha, &idc_control);
4493 if ((idc_control & QLA83XX_IDC_RESET_DISABLED)) {
4494 ql_log(ql_log_info, vha, 0xb080,
4495 "NIC Core reset has been disabled. idc-control=0x%x\n",
4496 idc_control);
4497 return QLA_FUNCTION_FAILED;
4498 }
4499
4500 /* Set NEED-RESET iff in READY state and we are the reset-owner */
4501 qla83xx_rd_reg(vha, QLA83XX_IDC_DEV_STATE, &dev_state);
4502 if (ha->flags.nic_core_reset_owner && dev_state == QLA8XXX_DEV_READY) {
4503 qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE,
4504 QLA8XXX_DEV_NEED_RESET);
4505 ql_log(ql_log_info, vha, 0xb056, "HW State: NEED RESET.\n");
4506 qla83xx_idc_audit(vha, IDC_AUDIT_TIMESTAMP);
4507 } else {
4508 const char *state = qla83xx_dev_state_to_string(dev_state);
4509 ql_log(ql_log_info, vha, 0xb057, "HW State: %s.\n", state);
4510
4511 /* SV: XXX: Is timeout required here? */
4512 /* Wait for IDC state change READY -> NEED_RESET */
4513 while (dev_state == QLA8XXX_DEV_READY) {
4514 qla83xx_idc_unlock(vha, 0);
4515 msleep(200);
4516 qla83xx_idc_lock(vha, 0);
4517 qla83xx_rd_reg(vha, QLA83XX_IDC_DEV_STATE, &dev_state);
4518 }
4519 }
4520
4521 /* Send IDC ack by writing to drv-ack register */
4522 __qla83xx_set_drv_ack(vha);
4523
4524 return QLA_SUCCESS;
4525}
4526
4527int
4528__qla83xx_set_idc_control(scsi_qla_host_t *vha, uint32_t idc_control)
4529{
4530 return qla83xx_wr_reg(vha, QLA83XX_IDC_CONTROL, idc_control);
4531}
4532
4533int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04004534__qla83xx_get_idc_control(scsi_qla_host_t *vha, uint32_t *idc_control)
4535{
4536 return qla83xx_rd_reg(vha, QLA83XX_IDC_CONTROL, idc_control);
4537}
4538
Saurav Kashyapfa492632012-11-21 02:40:29 -05004539static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04004540qla83xx_check_driver_presence(scsi_qla_host_t *vha)
4541{
4542 uint32_t drv_presence = 0;
4543 struct qla_hw_data *ha = vha->hw;
4544
4545 qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence);
4546 if (drv_presence & (1 << ha->portnum))
4547 return QLA_SUCCESS;
4548 else
4549 return QLA_TEST_FAILED;
4550}
4551
4552int
4553qla83xx_nic_core_reset(scsi_qla_host_t *vha)
4554{
4555 int rval = QLA_SUCCESS;
4556 struct qla_hw_data *ha = vha->hw;
4557
4558 ql_dbg(ql_dbg_p3p, vha, 0xb058,
4559 "Entered %s().\n", __func__);
4560
4561 if (vha->device_flags & DFLG_DEV_FAILED) {
4562 ql_log(ql_log_warn, vha, 0xb059,
4563 "Device in unrecoverable FAILED state.\n");
4564 return QLA_FUNCTION_FAILED;
4565 }
4566
4567 qla83xx_idc_lock(vha, 0);
4568
4569 if (qla83xx_check_driver_presence(vha) != QLA_SUCCESS) {
4570 ql_log(ql_log_warn, vha, 0xb05a,
4571 "Function=0x%x has been removed from IDC participation.\n",
4572 ha->portnum);
4573 rval = QLA_FUNCTION_FAILED;
4574 goto exit;
4575 }
4576
4577 qla83xx_reset_ownership(vha);
4578
4579 rval = qla83xx_initiating_reset(vha);
4580
4581 /*
4582 * Perform reset if we are the reset-owner,
4583 * else wait till IDC state changes to READY/FAILED.
4584 */
4585 if (rval == QLA_SUCCESS) {
4586 rval = qla83xx_idc_state_handler(vha);
4587
4588 if (rval == QLA_SUCCESS)
4589 ha->flags.nic_core_hung = 0;
4590 __qla83xx_clear_drv_ack(vha);
4591 }
4592
4593exit:
4594 qla83xx_idc_unlock(vha, 0);
4595
4596 ql_dbg(ql_dbg_p3p, vha, 0xb05b, "Exiting %s.\n", __func__);
4597
4598 return rval;
4599}
4600
Saurav Kashyap81178772012-08-22 14:21:04 -04004601int
4602qla2xxx_mctp_dump(scsi_qla_host_t *vha)
4603{
4604 struct qla_hw_data *ha = vha->hw;
4605 int rval = QLA_FUNCTION_FAILED;
4606
4607 if (!IS_MCTP_CAPABLE(ha)) {
4608 /* This message can be removed from the final version */
4609 ql_log(ql_log_info, vha, 0x506d,
4610 "This board is not MCTP capable\n");
4611 return rval;
4612 }
4613
4614 if (!ha->mctp_dump) {
4615 ha->mctp_dump = dma_alloc_coherent(&ha->pdev->dev,
4616 MCTP_DUMP_SIZE, &ha->mctp_dump_dma, GFP_KERNEL);
4617
4618 if (!ha->mctp_dump) {
4619 ql_log(ql_log_warn, vha, 0x506e,
4620 "Failed to allocate memory for mctp dump\n");
4621 return rval;
4622 }
4623 }
4624
4625#define MCTP_DUMP_STR_ADDR 0x00000000
4626 rval = qla2x00_dump_mctp_data(vha, ha->mctp_dump_dma,
4627 MCTP_DUMP_STR_ADDR, MCTP_DUMP_SIZE/4);
4628 if (rval != QLA_SUCCESS) {
4629 ql_log(ql_log_warn, vha, 0x506f,
4630 "Failed to capture mctp dump\n");
4631 } else {
4632 ql_log(ql_log_info, vha, 0x5070,
4633 "Mctp dump capture for host (%ld/%p).\n",
4634 vha->host_no, ha->mctp_dump);
4635 ha->mctp_dumped = 1;
4636 }
4637
Saurav Kashyap409ee0f2012-08-22 14:21:29 -04004638 if (!ha->flags.nic_core_reset_hdlr_active && !ha->portnum) {
Saurav Kashyap81178772012-08-22 14:21:04 -04004639 ha->flags.nic_core_reset_hdlr_active = 1;
4640 rval = qla83xx_restart_nic_firmware(vha);
4641 if (rval)
4642 /* NIC Core reset failed. */
4643 ql_log(ql_log_warn, vha, 0x5071,
4644 "Failed to restart nic firmware\n");
4645 else
4646 ql_dbg(ql_dbg_p3p, vha, 0xb084,
4647 "Restarted NIC firmware successfully.\n");
4648 ha->flags.nic_core_reset_hdlr_active = 0;
4649 }
4650
4651 return rval;
4652
4653}
4654
Saurav Kashyap579d12b2010-12-21 16:00:14 -08004655/*
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04004656* qla2x00_quiesce_io
Saurav Kashyap579d12b2010-12-21 16:00:14 -08004657* Description: This function will block the new I/Os
4658* Its not aborting any I/Os as context
4659* is not destroyed during quiescence
4660* Arguments: scsi_qla_host_t
4661* return : void
4662*/
4663void
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04004664qla2x00_quiesce_io(scsi_qla_host_t *vha)
Saurav Kashyap579d12b2010-12-21 16:00:14 -08004665{
4666 struct qla_hw_data *ha = vha->hw;
4667 struct scsi_qla_host *vp;
4668
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04004669 ql_dbg(ql_dbg_dpc, vha, 0x401d,
4670 "Quiescing I/O - ha=%p.\n", ha);
Saurav Kashyap579d12b2010-12-21 16:00:14 -08004671
4672 atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
4673 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
4674 atomic_set(&vha->loop_state, LOOP_DOWN);
4675 qla2x00_mark_all_devices_lost(vha, 0);
4676 list_for_each_entry(vp, &ha->vp_list, list)
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04004677 qla2x00_mark_all_devices_lost(vp, 0);
Saurav Kashyap579d12b2010-12-21 16:00:14 -08004678 } else {
4679 if (!atomic_read(&vha->loop_down_timer))
4680 atomic_set(&vha->loop_down_timer,
4681 LOOP_DOWN_TIME);
4682 }
4683 /* Wait for pending cmds to complete */
4684 qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST);
4685}
4686
Giridhar Malavalia9083012010-04-12 17:59:55 -07004687void
4688qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
4689{
4690 struct qla_hw_data *ha = vha->hw;
Saurav Kashyap579d12b2010-12-21 16:00:14 -08004691 struct scsi_qla_host *vp;
Arun Easifeafb7b2010-09-03 14:57:00 -07004692 unsigned long flags;
Andrew Vasquez6aef87b2011-02-23 15:27:13 -08004693 fc_port_t *fcport;
Giridhar Malavalia9083012010-04-12 17:59:55 -07004694
Saurav Kashyape46ef002011-02-23 15:27:16 -08004695 /* For ISP82XX, driver waits for completion of the commands.
4696 * online flag should be set.
4697 */
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04004698 if (!(IS_P3P_TYPE(ha)))
Saurav Kashyape46ef002011-02-23 15:27:16 -08004699 vha->flags.online = 0;
Giridhar Malavalia9083012010-04-12 17:59:55 -07004700 ha->flags.chip_reset_done = 0;
4701 clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Saurav Kashyap2be21fa2012-05-15 14:34:16 -04004702 vha->qla_stats.total_isp_aborts++;
Giridhar Malavalia9083012010-04-12 17:59:55 -07004703
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004704 ql_log(ql_log_info, vha, 0x00af,
4705 "Performing ISP error recovery - ha=%p.\n", ha);
Giridhar Malavalia9083012010-04-12 17:59:55 -07004706
Saurav Kashyape46ef002011-02-23 15:27:16 -08004707 /* For ISP82XX, reset_chip is just disabling interrupts.
4708 * Driver waits for the completion of the commands.
4709 * the interrupts need to be enabled.
4710 */
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04004711 if (!(IS_P3P_TYPE(ha)))
Giridhar Malavalia9083012010-04-12 17:59:55 -07004712 ha->isp_ops->reset_chip(vha);
4713
4714 atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
4715 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
4716 atomic_set(&vha->loop_state, LOOP_DOWN);
4717 qla2x00_mark_all_devices_lost(vha, 0);
Arun Easifeafb7b2010-09-03 14:57:00 -07004718
4719 spin_lock_irqsave(&ha->vport_slock, flags);
Saurav Kashyap579d12b2010-12-21 16:00:14 -08004720 list_for_each_entry(vp, &ha->vp_list, list) {
Arun Easifeafb7b2010-09-03 14:57:00 -07004721 atomic_inc(&vp->vref_count);
4722 spin_unlock_irqrestore(&ha->vport_slock, flags);
4723
Giridhar Malavalia9083012010-04-12 17:59:55 -07004724 qla2x00_mark_all_devices_lost(vp, 0);
Arun Easifeafb7b2010-09-03 14:57:00 -07004725
4726 spin_lock_irqsave(&ha->vport_slock, flags);
4727 atomic_dec(&vp->vref_count);
4728 }
4729 spin_unlock_irqrestore(&ha->vport_slock, flags);
Giridhar Malavalia9083012010-04-12 17:59:55 -07004730 } else {
4731 if (!atomic_read(&vha->loop_down_timer))
4732 atomic_set(&vha->loop_down_timer,
4733 LOOP_DOWN_TIME);
4734 }
4735
Andrew Vasquez6aef87b2011-02-23 15:27:13 -08004736 /* Clear all async request states across all VPs. */
4737 list_for_each_entry(fcport, &vha->vp_fcports, list)
4738 fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
4739 spin_lock_irqsave(&ha->vport_slock, flags);
4740 list_for_each_entry(vp, &ha->vp_list, list) {
4741 atomic_inc(&vp->vref_count);
4742 spin_unlock_irqrestore(&ha->vport_slock, flags);
4743
4744 list_for_each_entry(fcport, &vp->vp_fcports, list)
4745 fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
4746
4747 spin_lock_irqsave(&ha->vport_slock, flags);
4748 atomic_dec(&vp->vref_count);
4749 }
4750 spin_unlock_irqrestore(&ha->vport_slock, flags);
4751
Lalit Chandivadebddd2d62010-09-03 15:20:53 -07004752 if (!ha->flags.eeh_busy) {
4753 /* Make sure for ISP 82XX IO DMA is complete */
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04004754 if (IS_P3P_TYPE(ha)) {
Giridhar Malavali71905752011-02-23 15:27:10 -08004755 qla82xx_chip_reset_cleanup(vha);
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004756 ql_log(ql_log_info, vha, 0x00b4,
4757 "Done chip reset cleanup.\n");
Giridhar Malavalia9083012010-04-12 17:59:55 -07004758
Saurav Kashyape46ef002011-02-23 15:27:16 -08004759 /* Done waiting for pending commands.
4760 * Reset the online flag.
4761 */
4762 vha->flags.online = 0;
Giridhar Malavalia9083012010-04-12 17:59:55 -07004763 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004764
Lalit Chandivadebddd2d62010-09-03 15:20:53 -07004765 /* Requeue all commands in outstanding command list. */
4766 qla2x00_abort_all_cmds(vha, DID_RESET << 16);
4767 }
Arun Easib6a029e2014-09-25 06:14:52 -04004768
4769 ha->chip_reset++;
4770 /* memory barrier */
4771 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004772}
4773
4774/*
4775* qla2x00_abort_isp
4776* Resets ISP and aborts all outstanding commands.
4777*
4778* Input:
4779* ha = adapter block pointer.
4780*
4781* Returns:
4782* 0 = success
4783*/
4784int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004785qla2x00_abort_isp(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004786{
Andrew Vasquez476e8972006-08-23 14:54:55 -07004787 int rval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004788 uint8_t status = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004789 struct qla_hw_data *ha = vha->hw;
4790 struct scsi_qla_host *vp;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08004791 struct req_que *req = ha->req_q_map[0];
Arun Easifeafb7b2010-09-03 14:57:00 -07004792 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004793
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004794 if (vha->flags.online) {
Giridhar Malavalia9083012010-04-12 17:59:55 -07004795 qla2x00_abort_isp_cleanup(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004796
Santosh Vernekara61712972012-08-22 14:21:13 -04004797 if (IS_QLA8031(ha)) {
4798 ql_dbg(ql_dbg_p3p, vha, 0xb05c,
4799 "Clearing fcoe driver presence.\n");
4800 if (qla83xx_clear_drv_presence(vha) != QLA_SUCCESS)
4801 ql_dbg(ql_dbg_p3p, vha, 0xb073,
4802 "Error while clearing DRV-Presence.\n");
4803 }
4804
Andrew Vasquez85880802009-12-15 21:29:46 -08004805 if (unlikely(pci_channel_offline(ha->pdev) &&
4806 ha->flags.pci_channel_io_perm_failure)) {
4807 clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
4808 status = 0;
4809 return status;
4810 }
4811
Anirban Chakraborty73208df2008-12-09 16:45:39 -08004812 ha->isp_ops->get_flash_version(vha, req->ring);
Andrew Vasquez30c47662007-01-29 10:22:21 -08004813
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004814 ha->isp_ops->nvram_config(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004815
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004816 if (!qla2x00_restart_isp(vha)) {
4817 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004818
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004819 if (!atomic_read(&vha->loop_down_timer)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004820 /*
4821 * Issue marker command only when we are going
4822 * to start the I/O .
4823 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004824 vha->marker_needed = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004825 }
4826
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004827 vha->flags.online = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004828
Andrew Vasquezfd34f552007-07-19 15:06:00 -07004829 ha->isp_ops->enable_intrs(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004830
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07004831 ha->isp_abort_cnt = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004832 clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
Andrew Vasquez476e8972006-08-23 14:54:55 -07004833
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08004834 if (IS_QLA81XX(ha) || IS_QLA8031(ha))
4835 qla2x00_get_fw_version(vha);
Andrew Vasquezdf613b92008-01-17 09:02:17 -08004836 if (ha->fce) {
4837 ha->flags.fce_enabled = 1;
4838 memset(ha->fce, 0,
4839 fce_calc_size(ha->fce_bufs));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004840 rval = qla2x00_enable_fce_trace(vha,
Andrew Vasquezdf613b92008-01-17 09:02:17 -08004841 ha->fce_dma, ha->fce_bufs, ha->fce_mb,
4842 &ha->fce_bufs);
4843 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004844 ql_log(ql_log_warn, vha, 0x8033,
Andrew Vasquezdf613b92008-01-17 09:02:17 -08004845 "Unable to reinitialize FCE "
4846 "(%d).\n", rval);
4847 ha->flags.fce_enabled = 0;
4848 }
4849 }
Andrew Vasquez436a7b12008-07-10 16:55:54 -07004850
4851 if (ha->eft) {
4852 memset(ha->eft, 0, EFT_SIZE);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004853 rval = qla2x00_enable_eft_trace(vha,
Andrew Vasquez436a7b12008-07-10 16:55:54 -07004854 ha->eft_dma, EFT_NUM_BUFFERS);
4855 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004856 ql_log(ql_log_warn, vha, 0x8034,
Andrew Vasquez436a7b12008-07-10 16:55:54 -07004857 "Unable to reinitialize EFT "
4858 "(%d).\n", rval);
4859 }
4860 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004861 } else { /* failed the ISP abort */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004862 vha->flags.online = 1;
4863 if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004864 if (ha->isp_abort_cnt == 0) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004865 ql_log(ql_log_fatal, vha, 0x8035,
4866 "ISP error recover failed - "
4867 "board disabled.\n");
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07004868 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07004869 * The next call disables the board
4870 * completely.
4871 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004872 ha->isp_ops->reset_adapter(vha);
4873 vha->flags.online = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004874 clear_bit(ISP_ABORT_RETRY,
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004875 &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004876 status = 0;
4877 } else { /* schedule another ISP abort */
4878 ha->isp_abort_cnt--;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004879 ql_dbg(ql_dbg_taskm, vha, 0x8020,
4880 "ISP abort - retry remaining %d.\n",
4881 ha->isp_abort_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004882 status = 1;
4883 }
4884 } else {
4885 ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004886 ql_dbg(ql_dbg_taskm, vha, 0x8021,
4887 "ISP error recovery - retrying (%d) "
4888 "more times.\n", ha->isp_abort_cnt);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004889 set_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004890 status = 1;
4891 }
4892 }
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07004893
Linus Torvalds1da177e2005-04-16 15:20:36 -07004894 }
4895
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004896 if (!status) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004897 ql_dbg(ql_dbg_taskm, vha, 0x8022, "%s succeeded.\n", __func__);
Arun Easifeafb7b2010-09-03 14:57:00 -07004898
4899 spin_lock_irqsave(&ha->vport_slock, flags);
4900 list_for_each_entry(vp, &ha->vp_list, list) {
4901 if (vp->vp_idx) {
4902 atomic_inc(&vp->vref_count);
4903 spin_unlock_irqrestore(&ha->vport_slock, flags);
4904
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004905 qla2x00_vp_abort_isp(vp);
Arun Easifeafb7b2010-09-03 14:57:00 -07004906
4907 spin_lock_irqsave(&ha->vport_slock, flags);
4908 atomic_dec(&vp->vref_count);
4909 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004910 }
Arun Easifeafb7b2010-09-03 14:57:00 -07004911 spin_unlock_irqrestore(&ha->vport_slock, flags);
4912
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04004913 if (IS_QLA8031(ha)) {
4914 ql_dbg(ql_dbg_p3p, vha, 0xb05d,
4915 "Setting back fcoe driver presence.\n");
4916 if (qla83xx_set_drv_presence(vha) != QLA_SUCCESS)
4917 ql_dbg(ql_dbg_p3p, vha, 0xb074,
4918 "Error while setting DRV-Presence.\n");
4919 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004920 } else {
Joe Perchesd8424f62011-11-18 09:03:06 -08004921 ql_log(ql_log_warn, vha, 0x8023, "%s **** FAILED ****.\n",
4922 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004923 }
4924
4925 return(status);
4926}
4927
4928/*
4929* qla2x00_restart_isp
4930* restarts the ISP after a reset
4931*
4932* Input:
4933* ha = adapter block pointer.
4934*
4935* Returns:
4936* 0 = success
4937*/
4938static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004939qla2x00_restart_isp(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004940{
Andrew Vasquezc6b2fca2009-03-05 11:07:03 -08004941 int status = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004942 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08004943 struct req_que *req = ha->req_q_map[0];
4944 struct rsp_que *rsp = ha->rsp_q_map[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004945
4946 /* If firmware needs to be loaded */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004947 if (qla2x00_isp_firmware(vha)) {
4948 vha->flags.online = 0;
4949 status = ha->isp_ops->chip_diag(vha);
4950 if (!status)
4951 status = qla2x00_setup_chip(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004952 }
4953
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004954 if (!status && !(status = qla2x00_init_rings(vha))) {
4955 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
Lalit Chandivade2533cf62009-03-24 09:08:07 -07004956 ha->flags.chip_reset_done = 1;
Chad Dupuis7108b762014-04-11 16:54:45 -04004957
Anirban Chakraborty73208df2008-12-09 16:45:39 -08004958 /* Initialize the queues in use */
4959 qla25xx_init_queues(ha);
4960
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004961 status = qla2x00_fw_ready(vha);
4962 if (!status) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004963 /* Issue a marker after FW becomes ready. */
Anirban Chakraborty73208df2008-12-09 16:45:39 -08004964 qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004965
Chad Dupuis7108b762014-04-11 16:54:45 -04004966 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004967 }
4968
4969 /* if no cable then assume it's good */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004970 if ((vha->device_flags & DFLG_NO_CABLE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004971 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004972 }
4973 return (status);
4974}
4975
Anirban Chakraborty73208df2008-12-09 16:45:39 -08004976static int
4977qla25xx_init_queues(struct qla_hw_data *ha)
4978{
4979 struct rsp_que *rsp = NULL;
4980 struct req_que *req = NULL;
4981 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
4982 int ret = -1;
4983 int i;
4984
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07004985 for (i = 1; i < ha->max_rsp_queues; i++) {
Anirban Chakraborty73208df2008-12-09 16:45:39 -08004986 rsp = ha->rsp_q_map[i];
Quinn Trancb432852016-02-04 11:45:16 -05004987 if (rsp && test_bit(i, ha->rsp_qid_map)) {
Anirban Chakraborty73208df2008-12-09 16:45:39 -08004988 rsp->options &= ~BIT_0;
Anirban Chakraborty618a7522009-02-08 20:50:11 -08004989 ret = qla25xx_init_rsp_que(base_vha, rsp);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08004990 if (ret != QLA_SUCCESS)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004991 ql_dbg(ql_dbg_init, base_vha, 0x00ff,
4992 "%s Rsp que: %d init failed.\n",
4993 __func__, rsp->id);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08004994 else
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004995 ql_dbg(ql_dbg_init, base_vha, 0x0100,
4996 "%s Rsp que: %d inited.\n",
4997 __func__, rsp->id);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08004998 }
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07004999 }
5000 for (i = 1; i < ha->max_req_queues; i++) {
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005001 req = ha->req_q_map[i];
Quinn Trancb432852016-02-04 11:45:16 -05005002 if (req && test_bit(i, ha->req_qid_map)) {
5003 /* Clear outstanding commands array. */
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005004 req->options &= ~BIT_0;
Anirban Chakraborty618a7522009-02-08 20:50:11 -08005005 ret = qla25xx_init_req_que(base_vha, req);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005006 if (ret != QLA_SUCCESS)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005007 ql_dbg(ql_dbg_init, base_vha, 0x0101,
5008 "%s Req que: %d init failed.\n",
5009 __func__, req->id);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005010 else
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005011 ql_dbg(ql_dbg_init, base_vha, 0x0102,
5012 "%s Req que: %d inited.\n",
5013 __func__, req->id);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005014 }
5015 }
5016 return ret;
5017}
5018
Linus Torvalds1da177e2005-04-16 15:20:36 -07005019/*
5020* qla2x00_reset_adapter
5021* Reset adapter.
5022*
5023* Input:
5024* ha = adapter block pointer.
5025*/
Andrew Vasquezabbd8872005-07-06 10:30:05 -07005026void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005027qla2x00_reset_adapter(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005028{
5029 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005030 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07005031 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005032
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005033 vha->flags.online = 0;
Andrew Vasquezfd34f552007-07-19 15:06:00 -07005034 ha->isp_ops->disable_intrs(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005035
Linus Torvalds1da177e2005-04-16 15:20:36 -07005036 spin_lock_irqsave(&ha->hardware_lock, flags);
5037 WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
5038 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
5039 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
5040 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
5041 spin_unlock_irqrestore(&ha->hardware_lock, flags);
5042}
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005043
5044void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005045qla24xx_reset_adapter(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005046{
5047 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005048 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005049 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
5050
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04005051 if (IS_P3P_TYPE(ha))
Giridhar Malavalia9083012010-04-12 17:59:55 -07005052 return;
5053
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005054 vha->flags.online = 0;
Andrew Vasquezfd34f552007-07-19 15:06:00 -07005055 ha->isp_ops->disable_intrs(ha);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005056
5057 spin_lock_irqsave(&ha->hardware_lock, flags);
5058 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
5059 RD_REG_DWORD(&reg->hccr);
5060 WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
5061 RD_REG_DWORD(&reg->hccr);
5062 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Andrew Vasquez09ff36d2009-01-22 09:45:30 -08005063
5064 if (IS_NOPOLLING_TYPE(ha))
5065 ha->isp_ops->enable_intrs(ha);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005066}
5067
David Miller4e08df32007-04-16 12:37:43 -07005068/* On sparc systems, obtain port and node WWN from firmware
5069 * properties.
5070 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005071static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *vha,
5072 struct nvram_24xx *nv)
David Miller4e08df32007-04-16 12:37:43 -07005073{
5074#ifdef CONFIG_SPARC
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005075 struct qla_hw_data *ha = vha->hw;
David Miller4e08df32007-04-16 12:37:43 -07005076 struct pci_dev *pdev = ha->pdev;
David S. Miller15576bc2007-05-08 00:36:49 -07005077 struct device_node *dp = pci_device_to_OF_node(pdev);
5078 const u8 *val;
David Miller4e08df32007-04-16 12:37:43 -07005079 int len;
5080
5081 val = of_get_property(dp, "port-wwn", &len);
5082 if (val && len >= WWN_SIZE)
5083 memcpy(nv->port_name, val, WWN_SIZE);
5084
5085 val = of_get_property(dp, "node-wwn", &len);
5086 if (val && len >= WWN_SIZE)
5087 memcpy(nv->node_name, val, WWN_SIZE);
5088#endif
5089}
5090
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005091int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005092qla24xx_nvram_config(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005093{
David Miller4e08df32007-04-16 12:37:43 -07005094 int rval;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005095 struct init_cb_24xx *icb;
5096 struct nvram_24xx *nv;
5097 uint32_t *dptr;
5098 uint8_t *dptr1, *dptr2;
5099 uint32_t chksum;
5100 uint16_t cnt;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005101 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005102
David Miller4e08df32007-04-16 12:37:43 -07005103 rval = QLA_SUCCESS;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005104 icb = (struct init_cb_24xx *)ha->init_cb;
Seokmann Ju281afe12007-07-26 13:43:34 -07005105 nv = ha->nvram;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005106
5107 /* Determine NVRAM starting address. */
Chad Dupuisf73cb692014-02-26 04:15:06 -05005108 if (ha->port_no == 0) {
Anirban Chakrabortye5b68a62009-04-06 22:33:50 -07005109 ha->nvram_base = FA_NVRAM_FUNC0_ADDR;
5110 ha->vpd_base = FA_NVRAM_VPD0_ADDR;
5111 } else {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005112 ha->nvram_base = FA_NVRAM_FUNC1_ADDR;
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -08005113 ha->vpd_base = FA_NVRAM_VPD1_ADDR;
5114 }
Chad Dupuisf73cb692014-02-26 04:15:06 -05005115
Anirban Chakrabortye5b68a62009-04-06 22:33:50 -07005116 ha->nvram_size = sizeof(struct nvram_24xx);
5117 ha->vpd_size = FA_NVRAM_VPD_SIZE;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005118
Seokmann Ju281afe12007-07-26 13:43:34 -07005119 /* Get VPD data into cache */
5120 ha->vpd = ha->nvram + VPD_OFFSET;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005121 ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd,
Seokmann Ju281afe12007-07-26 13:43:34 -07005122 ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4);
5123
5124 /* Get NVRAM data into cache and calculate checksum. */
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005125 dptr = (uint32_t *)nv;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005126 ha->isp_ops->read_nvram(vha, (uint8_t *)dptr, ha->nvram_base,
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005127 ha->nvram_size);
Joe Carnuccioda08ef52016-01-27 12:03:34 -05005128 for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++)
5129 chksum += le32_to_cpu(*dptr);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005130
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005131 ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x006a,
5132 "Contents of NVRAM\n");
5133 ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010d,
5134 (uint8_t *)nv, ha->nvram_size);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005135
5136 /* Bad NVRAM data, set defaults parameters. */
5137 if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P'
5138 || nv->id[3] != ' ' ||
Bart Van Asschead950362015-07-09 07:24:08 -07005139 nv->nvram_version < cpu_to_le16(ICB_VERSION)) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005140 /* Reset NVRAM data. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005141 ql_log(ql_log_warn, vha, 0x006b,
Raul Porcel9e336522012-05-15 14:34:08 -04005142 "Inconsistent NVRAM detected: checksum=0x%x id=%c "
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005143 "version=0x%x.\n", chksum, nv->id[0], nv->nvram_version);
5144 ql_log(ql_log_warn, vha, 0x006c,
5145 "Falling back to functioning (yet invalid -- WWPN) "
5146 "defaults.\n");
David Miller4e08df32007-04-16 12:37:43 -07005147
5148 /*
5149 * Set default initialization control block.
5150 */
5151 memset(nv, 0, ha->nvram_size);
Bart Van Asschead950362015-07-09 07:24:08 -07005152 nv->nvram_version = cpu_to_le16(ICB_VERSION);
5153 nv->version = cpu_to_le16(ICB_VERSION);
Joe Carnuccio98aee702014-09-25 05:16:38 -04005154 nv->frame_payload_size = 2048;
Bart Van Asschead950362015-07-09 07:24:08 -07005155 nv->execution_throttle = cpu_to_le16(0xFFFF);
5156 nv->exchange_count = cpu_to_le16(0);
5157 nv->hard_address = cpu_to_le16(124);
David Miller4e08df32007-04-16 12:37:43 -07005158 nv->port_name[0] = 0x21;
Chad Dupuisf73cb692014-02-26 04:15:06 -05005159 nv->port_name[1] = 0x00 + ha->port_no + 1;
David Miller4e08df32007-04-16 12:37:43 -07005160 nv->port_name[2] = 0x00;
5161 nv->port_name[3] = 0xe0;
5162 nv->port_name[4] = 0x8b;
5163 nv->port_name[5] = 0x1c;
5164 nv->port_name[6] = 0x55;
5165 nv->port_name[7] = 0x86;
5166 nv->node_name[0] = 0x20;
5167 nv->node_name[1] = 0x00;
5168 nv->node_name[2] = 0x00;
5169 nv->node_name[3] = 0xe0;
5170 nv->node_name[4] = 0x8b;
5171 nv->node_name[5] = 0x1c;
5172 nv->node_name[6] = 0x55;
5173 nv->node_name[7] = 0x86;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005174 qla24xx_nvram_wwn_from_ofw(vha, nv);
Bart Van Asschead950362015-07-09 07:24:08 -07005175 nv->login_retry_count = cpu_to_le16(8);
5176 nv->interrupt_delay_timer = cpu_to_le16(0);
5177 nv->login_timeout = cpu_to_le16(0);
David Miller4e08df32007-04-16 12:37:43 -07005178 nv->firmware_options_1 =
Bart Van Asschead950362015-07-09 07:24:08 -07005179 cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1);
5180 nv->firmware_options_2 = cpu_to_le32(2 << 4);
5181 nv->firmware_options_2 |= cpu_to_le32(BIT_12);
5182 nv->firmware_options_3 = cpu_to_le32(2 << 13);
5183 nv->host_p = cpu_to_le32(BIT_11|BIT_10);
5184 nv->efi_parameters = cpu_to_le32(0);
David Miller4e08df32007-04-16 12:37:43 -07005185 nv->reset_delay = 5;
Bart Van Asschead950362015-07-09 07:24:08 -07005186 nv->max_luns_per_target = cpu_to_le16(128);
5187 nv->port_down_retry_count = cpu_to_le16(30);
5188 nv->link_down_timeout = cpu_to_le16(30);
David Miller4e08df32007-04-16 12:37:43 -07005189
5190 rval = 1;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005191 }
5192
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04005193 if (!qla_ini_mode_enabled(vha)) {
5194 /* Don't enable full login after initial LIP */
Bart Van Asschead950362015-07-09 07:24:08 -07005195 nv->firmware_options_1 &= cpu_to_le32(~BIT_13);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04005196 /* Don't enable LIP full login for initiator */
Bart Van Asschead950362015-07-09 07:24:08 -07005197 nv->host_p &= cpu_to_le32(~BIT_10);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04005198 }
5199
5200 qlt_24xx_config_nvram_stage1(vha, nv);
5201
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005202 /* Reset Initialization control block */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005203 memset(icb, 0, ha->init_cb_size);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005204
5205 /* Copy 1st segment. */
5206 dptr1 = (uint8_t *)icb;
5207 dptr2 = (uint8_t *)&nv->version;
5208 cnt = (uint8_t *)&icb->response_q_inpointer - (uint8_t *)&icb->version;
5209 while (cnt--)
5210 *dptr1++ = *dptr2++;
5211
5212 icb->login_retry_count = nv->login_retry_count;
Andrew Vasquez3ea66e22006-06-23 16:11:27 -07005213 icb->link_down_on_nos = nv->link_down_on_nos;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005214
5215 /* Copy 2nd segment. */
5216 dptr1 = (uint8_t *)&icb->interrupt_delay_timer;
5217 dptr2 = (uint8_t *)&nv->interrupt_delay_timer;
5218 cnt = (uint8_t *)&icb->reserved_3 -
5219 (uint8_t *)&icb->interrupt_delay_timer;
5220 while (cnt--)
5221 *dptr1++ = *dptr2++;
5222
5223 /*
5224 * Setup driver NVRAM options.
5225 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005226 qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name),
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08005227 "QLA2462");
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005228
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04005229 qlt_24xx_config_nvram_stage2(vha, icb);
5230
Bart Van Asschead950362015-07-09 07:24:08 -07005231 if (nv->host_p & cpu_to_le32(BIT_15)) {
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04005232 /* Use alternate WWN? */
Andrew Vasquez5341e862006-05-17 15:09:16 -07005233 memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
5234 memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
5235 }
5236
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005237 /* Prepare nodename */
Bart Van Asschead950362015-07-09 07:24:08 -07005238 if ((icb->firmware_options_1 & cpu_to_le32(BIT_14)) == 0) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005239 /*
5240 * Firmware will apply the following mask if the nodename was
5241 * not provided.
5242 */
5243 memcpy(icb->node_name, icb->port_name, WWN_SIZE);
5244 icb->node_name[0] &= 0xF0;
5245 }
5246
5247 /* Set host adapter parameters. */
5248 ha->flags.disable_risc_code_load = 0;
Andrew Vasquez0c8c39a2006-12-13 19:20:30 -08005249 ha->flags.enable_lip_reset = 0;
5250 ha->flags.enable_lip_full_login =
5251 le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0;
5252 ha->flags.enable_target_reset =
5253 le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005254 ha->flags.enable_led_scheme = 0;
Andrew Vasquezd4c760c2006-06-23 16:10:39 -07005255 ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005256
Andrew Vasquezfd0e7e42006-05-17 15:09:11 -07005257 ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) &
5258 (BIT_6 | BIT_5 | BIT_4)) >> 4;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005259
5260 memcpy(ha->fw_seriallink_options24, nv->seriallink_options,
5261 sizeof(ha->fw_seriallink_options24));
5262
5263 /* save HBA serial number */
5264 ha->serial0 = icb->port_name[5];
5265 ha->serial1 = icb->port_name[6];
5266 ha->serial2 = icb->port_name[7];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005267 memcpy(vha->node_name, icb->node_name, WWN_SIZE);
5268 memcpy(vha->port_name, icb->port_name, WWN_SIZE);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005269
Bart Van Asschead950362015-07-09 07:24:08 -07005270 icb->execution_throttle = cpu_to_le16(0xFFFF);
andrew.vasquez@qlogic.combc8fb3c2006-01-13 17:05:42 -08005271
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005272 ha->retry_count = le16_to_cpu(nv->login_retry_count);
5273
5274 /* Set minimum login_timeout to 4 seconds. */
5275 if (le16_to_cpu(nv->login_timeout) < ql2xlogintimeout)
5276 nv->login_timeout = cpu_to_le16(ql2xlogintimeout);
5277 if (le16_to_cpu(nv->login_timeout) < 4)
Bart Van Asschead950362015-07-09 07:24:08 -07005278 nv->login_timeout = cpu_to_le16(4);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005279 ha->login_timeout = le16_to_cpu(nv->login_timeout);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005280
Andrew Vasquez00a537b2008-02-28 14:06:11 -08005281 /* Set minimum RATOV to 100 tenths of a second. */
5282 ha->r_a_tov = 100;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005283
5284 ha->loop_reset_delay = nv->reset_delay;
5285
5286 /* Link Down Timeout = 0:
5287 *
5288 * When Port Down timer expires we will start returning
5289 * I/O's to OS with "DID_NO_CONNECT".
5290 *
5291 * Link Down Timeout != 0:
5292 *
5293 * The driver waits for the link to come up after link down
5294 * before returning I/Os to OS with "DID_NO_CONNECT".
5295 */
5296 if (le16_to_cpu(nv->link_down_timeout) == 0) {
5297 ha->loop_down_abort_time =
5298 (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT);
5299 } else {
5300 ha->link_down_timeout = le16_to_cpu(nv->link_down_timeout);
5301 ha->loop_down_abort_time =
5302 (LOOP_DOWN_TIME - ha->link_down_timeout);
5303 }
5304
5305 /* Need enough time to try and get the port back. */
5306 ha->port_down_retry_count = le16_to_cpu(nv->port_down_retry_count);
5307 if (qlport_down_retry)
5308 ha->port_down_retry_count = qlport_down_retry;
5309
5310 /* Set login_retry_count */
5311 ha->login_retry_count = le16_to_cpu(nv->login_retry_count);
5312 if (ha->port_down_retry_count ==
5313 le16_to_cpu(nv->port_down_retry_count) &&
5314 ha->port_down_retry_count > 3)
5315 ha->login_retry_count = ha->port_down_retry_count;
5316 else if (ha->port_down_retry_count > (int)ha->login_retry_count)
5317 ha->login_retry_count = ha->port_down_retry_count;
5318 if (ql2xloginretrycount)
5319 ha->login_retry_count = ql2xloginretrycount;
5320
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07005321 /* Enable ZIO. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005322 if (!vha->flags.init_done) {
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07005323 ha->zio_mode = le32_to_cpu(icb->firmware_options_2) &
5324 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
5325 ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ?
5326 le16_to_cpu(icb->interrupt_delay_timer): 2;
5327 }
Bart Van Asschead950362015-07-09 07:24:08 -07005328 icb->firmware_options_2 &= cpu_to_le32(
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07005329 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005330 vha->flags.process_response_queue = 0;
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07005331 if (ha->zio_mode != QLA_ZIO_DISABLED) {
andrew.vasquez@qlogic.com4a59f712006-03-09 14:27:39 -08005332 ha->zio_mode = QLA_ZIO_MODE_6;
5333
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005334 ql_log(ql_log_info, vha, 0x006f,
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07005335 "ZIO mode %d enabled; timer delay (%d us).\n",
5336 ha->zio_mode, ha->zio_timer * 100);
5337
5338 icb->firmware_options_2 |= cpu_to_le32(
5339 (uint32_t)ha->zio_mode);
5340 icb->interrupt_delay_timer = cpu_to_le16(ha->zio_timer);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005341 vha->flags.process_response_queue = 1;
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07005342 }
5343
David Miller4e08df32007-04-16 12:37:43 -07005344 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005345 ql_log(ql_log_warn, vha, 0x0070,
5346 "NVRAM configuration failed.\n");
David Miller4e08df32007-04-16 12:37:43 -07005347 }
5348 return (rval);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005349}
5350
Sawan Chandak4243c112016-01-27 12:03:31 -05005351uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha)
5352{
5353 struct qla27xx_image_status pri_image_status, sec_image_status;
5354 uint8_t valid_pri_image, valid_sec_image;
5355 uint32_t *wptr;
5356 uint32_t cnt, chksum, size;
5357 struct qla_hw_data *ha = vha->hw;
5358
5359 valid_pri_image = valid_sec_image = 1;
5360 ha->active_image = 0;
5361 size = sizeof(struct qla27xx_image_status) / sizeof(uint32_t);
5362
5363 if (!ha->flt_region_img_status_pri) {
5364 valid_pri_image = 0;
5365 goto check_sec_image;
5366 }
5367
5368 qla24xx_read_flash_data(vha, (uint32_t *)(&pri_image_status),
5369 ha->flt_region_img_status_pri, size);
5370
5371 if (pri_image_status.signature != QLA27XX_IMG_STATUS_SIGN) {
5372 ql_dbg(ql_dbg_init, vha, 0x018b,
5373 "Primary image signature (0x%x) not valid\n",
5374 pri_image_status.signature);
5375 valid_pri_image = 0;
5376 goto check_sec_image;
5377 }
5378
5379 wptr = (uint32_t *)(&pri_image_status);
5380 cnt = size;
5381
Joe Carnuccioda08ef52016-01-27 12:03:34 -05005382 for (chksum = 0; cnt--; wptr++)
5383 chksum += le32_to_cpu(*wptr);
Sawan Chandak4243c112016-01-27 12:03:31 -05005384 if (chksum) {
5385 ql_dbg(ql_dbg_init, vha, 0x018c,
5386 "Checksum validation failed for primary image (0x%x)\n",
5387 chksum);
5388 valid_pri_image = 0;
5389 }
5390
5391check_sec_image:
5392 if (!ha->flt_region_img_status_sec) {
5393 valid_sec_image = 0;
5394 goto check_valid_image;
5395 }
5396
5397 qla24xx_read_flash_data(vha, (uint32_t *)(&sec_image_status),
5398 ha->flt_region_img_status_sec, size);
5399
5400 if (sec_image_status.signature != QLA27XX_IMG_STATUS_SIGN) {
5401 ql_dbg(ql_dbg_init, vha, 0x018d,
5402 "Secondary image signature(0x%x) not valid\n",
5403 sec_image_status.signature);
5404 valid_sec_image = 0;
5405 goto check_valid_image;
5406 }
5407
5408 wptr = (uint32_t *)(&sec_image_status);
5409 cnt = size;
Joe Carnuccioda08ef52016-01-27 12:03:34 -05005410 for (chksum = 0; cnt--; wptr++)
5411 chksum += le32_to_cpu(*wptr);
Sawan Chandak4243c112016-01-27 12:03:31 -05005412 if (chksum) {
5413 ql_dbg(ql_dbg_init, vha, 0x018e,
5414 "Checksum validation failed for secondary image (0x%x)\n",
5415 chksum);
5416 valid_sec_image = 0;
5417 }
5418
5419check_valid_image:
5420 if (valid_pri_image && (pri_image_status.image_status_mask & 0x1))
5421 ha->active_image = QLA27XX_PRIMARY_IMAGE;
5422 if (valid_sec_image && (sec_image_status.image_status_mask & 0x1)) {
5423 if (!ha->active_image ||
5424 pri_image_status.generation_number <
5425 sec_image_status.generation_number)
5426 ha->active_image = QLA27XX_SECONDARY_IMAGE;
5427 }
5428
5429 ql_dbg(ql_dbg_init, vha, 0x018f, "%s image\n",
5430 ha->active_image == 0 ? "default bootld and fw" :
5431 ha->active_image == 1 ? "primary" :
5432 ha->active_image == 2 ? "secondary" :
5433 "Invalid");
5434
5435 return ha->active_image;
5436}
5437
Adrian Bunk413975a2006-06-30 02:33:06 -07005438static int
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07005439qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
5440 uint32_t faddr)
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005441{
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005442 int rval = QLA_SUCCESS;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005443 int segments, fragment;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005444 uint32_t *dcode, dlen;
5445 uint32_t risc_addr;
5446 uint32_t risc_size;
5447 uint32_t i;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005448 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005449 struct req_que *req = ha->req_q_map[0];
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08005450
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005451 ql_dbg(ql_dbg_init, vha, 0x008b,
Chad Dupuiscfb09192011-11-18 09:03:07 -08005452 "FW: Loading firmware from flash (%x).\n", faddr);
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08005453
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005454 rval = QLA_SUCCESS;
5455
5456 segments = FA_RISC_CODE_SEGMENTS;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005457 dcode = (uint32_t *)req->ring;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005458 *srisc_addr = 0;
5459
Sawan Chandak4243c112016-01-27 12:03:31 -05005460 if (IS_QLA27XX(ha) &&
5461 qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
5462 faddr = ha->flt_region_fw_sec;
5463
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005464 /* Validate firmware image by checking version. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005465 qla24xx_read_flash_data(vha, dcode, faddr + 4, 4);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005466 for (i = 0; i < 4; i++)
5467 dcode[i] = be32_to_cpu(dcode[i]);
5468 if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
5469 dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
5470 (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
5471 dcode[3] == 0)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005472 ql_log(ql_log_fatal, vha, 0x008c,
5473 "Unable to verify the integrity of flash firmware "
5474 "image.\n");
5475 ql_log(ql_log_fatal, vha, 0x008d,
5476 "Firmware data: %08x %08x %08x %08x.\n",
5477 dcode[0], dcode[1], dcode[2], dcode[3]);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005478
5479 return QLA_FUNCTION_FAILED;
5480 }
5481
5482 while (segments && rval == QLA_SUCCESS) {
5483 /* Read segment's load information. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005484 qla24xx_read_flash_data(vha, dcode, faddr, 4);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005485
5486 risc_addr = be32_to_cpu(dcode[2]);
5487 *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr;
5488 risc_size = be32_to_cpu(dcode[3]);
5489
5490 fragment = 0;
5491 while (risc_size > 0 && rval == QLA_SUCCESS) {
5492 dlen = (uint32_t)(ha->fw_transfer_size >> 2);
5493 if (dlen > risc_size)
5494 dlen = risc_size;
5495
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005496 ql_dbg(ql_dbg_init, vha, 0x008e,
5497 "Loading risc segment@ risc addr %x "
5498 "number of dwords 0x%x offset 0x%x.\n",
5499 risc_addr, dlen, faddr);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005500
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005501 qla24xx_read_flash_data(vha, dcode, faddr, dlen);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005502 for (i = 0; i < dlen; i++)
5503 dcode[i] = swab32(dcode[i]);
5504
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005505 rval = qla2x00_load_ram(vha, req->dma, risc_addr,
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005506 dlen);
5507 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005508 ql_log(ql_log_fatal, vha, 0x008f,
5509 "Failed to load segment %d of firmware.\n",
5510 fragment);
Chad Dupuisf261f7a2014-09-25 05:17:03 -04005511 return QLA_FUNCTION_FAILED;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005512 }
5513
5514 faddr += dlen;
5515 risc_addr += dlen;
5516 risc_size -= dlen;
5517 fragment++;
5518 }
5519
5520 /* Next segment. */
5521 segments--;
5522 }
5523
Chad Dupuisf73cb692014-02-26 04:15:06 -05005524 if (!IS_QLA27XX(ha))
5525 return rval;
5526
5527 if (ha->fw_dump_template)
5528 vfree(ha->fw_dump_template);
5529 ha->fw_dump_template = NULL;
5530 ha->fw_dump_template_len = 0;
5531
5532 ql_dbg(ql_dbg_init, vha, 0x0161,
5533 "Loading fwdump template from %x\n", faddr);
5534 qla24xx_read_flash_data(vha, dcode, faddr, 7);
5535 risc_size = be32_to_cpu(dcode[2]);
5536 ql_dbg(ql_dbg_init, vha, 0x0162,
5537 "-> array size %x dwords\n", risc_size);
5538 if (risc_size == 0 || risc_size == ~0)
5539 goto default_template;
5540
5541 dlen = (risc_size - 8) * sizeof(*dcode);
5542 ql_dbg(ql_dbg_init, vha, 0x0163,
5543 "-> template allocating %x bytes...\n", dlen);
5544 ha->fw_dump_template = vmalloc(dlen);
5545 if (!ha->fw_dump_template) {
5546 ql_log(ql_log_warn, vha, 0x0164,
5547 "Failed fwdump template allocate %x bytes.\n", risc_size);
5548 goto default_template;
5549 }
5550
5551 faddr += 7;
5552 risc_size -= 8;
5553 dcode = ha->fw_dump_template;
5554 qla24xx_read_flash_data(vha, dcode, faddr, risc_size);
5555 for (i = 0; i < risc_size; i++)
5556 dcode[i] = le32_to_cpu(dcode[i]);
5557
5558 if (!qla27xx_fwdt_template_valid(dcode)) {
5559 ql_log(ql_log_warn, vha, 0x0165,
5560 "Failed fwdump template validate\n");
5561 goto default_template;
5562 }
5563
5564 dlen = qla27xx_fwdt_template_size(dcode);
5565 ql_dbg(ql_dbg_init, vha, 0x0166,
5566 "-> template size %x bytes\n", dlen);
5567 if (dlen > risc_size * sizeof(*dcode)) {
5568 ql_log(ql_log_warn, vha, 0x0167,
Chad Dupuis97ea7022014-03-13 14:16:40 -04005569 "Failed fwdump template exceeds array by %x bytes\n",
5570 (uint32_t)(dlen - risc_size * sizeof(*dcode)));
Chad Dupuisf73cb692014-02-26 04:15:06 -05005571 goto default_template;
5572 }
5573 ha->fw_dump_template_len = dlen;
5574 return rval;
5575
5576default_template:
5577 ql_log(ql_log_warn, vha, 0x0168, "Using default fwdump template\n");
5578 if (ha->fw_dump_template)
5579 vfree(ha->fw_dump_template);
5580 ha->fw_dump_template = NULL;
5581 ha->fw_dump_template_len = 0;
5582
5583 dlen = qla27xx_fwdt_template_default_size();
5584 ql_dbg(ql_dbg_init, vha, 0x0169,
5585 "-> template allocating %x bytes...\n", dlen);
5586 ha->fw_dump_template = vmalloc(dlen);
5587 if (!ha->fw_dump_template) {
5588 ql_log(ql_log_warn, vha, 0x016a,
5589 "Failed fwdump template allocate %x bytes.\n", risc_size);
5590 goto failed_template;
5591 }
5592
5593 dcode = ha->fw_dump_template;
5594 risc_size = dlen / sizeof(*dcode);
5595 memcpy(dcode, qla27xx_fwdt_template_default(), dlen);
5596 for (i = 0; i < risc_size; i++)
5597 dcode[i] = be32_to_cpu(dcode[i]);
5598
5599 if (!qla27xx_fwdt_template_valid(ha->fw_dump_template)) {
5600 ql_log(ql_log_warn, vha, 0x016b,
5601 "Failed fwdump template validate\n");
5602 goto failed_template;
5603 }
5604
5605 dlen = qla27xx_fwdt_template_size(ha->fw_dump_template);
5606 ql_dbg(ql_dbg_init, vha, 0x016c,
5607 "-> template size %x bytes\n", dlen);
5608 ha->fw_dump_template_len = dlen;
5609 return rval;
5610
5611failed_template:
5612 ql_log(ql_log_warn, vha, 0x016d, "Failed default fwdump template\n");
5613 if (ha->fw_dump_template)
5614 vfree(ha->fw_dump_template);
5615 ha->fw_dump_template = NULL;
5616 ha->fw_dump_template_len = 0;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005617 return rval;
5618}
5619
Giridhar Malavalie9454a82013-02-08 01:57:47 -05005620#define QLA_FW_URL "http://ldriver.qlogic.com/firmware/"
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005621
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005622int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005623qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
Andrew Vasquez54333832005-11-09 15:49:04 -08005624{
5625 int rval;
5626 int i, fragment;
5627 uint16_t *wcode, *fwcode;
5628 uint32_t risc_addr, risc_size, fwclen, wlen, *seg;
5629 struct fw_blob *blob;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005630 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005631 struct req_que *req = ha->req_q_map[0];
Andrew Vasquez54333832005-11-09 15:49:04 -08005632
5633 /* Load firmware blob. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005634 blob = qla2x00_request_firmware(vha);
Andrew Vasquez54333832005-11-09 15:49:04 -08005635 if (!blob) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005636 ql_log(ql_log_info, vha, 0x0083,
Yannick Guerrini94bcf832015-02-26 22:49:34 +01005637 "Firmware image unavailable.\n");
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005638 ql_log(ql_log_info, vha, 0x0084,
5639 "Firmware images can be retrieved from: "QLA_FW_URL ".\n");
Andrew Vasquez54333832005-11-09 15:49:04 -08005640 return QLA_FUNCTION_FAILED;
5641 }
5642
5643 rval = QLA_SUCCESS;
5644
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005645 wcode = (uint16_t *)req->ring;
Andrew Vasquez54333832005-11-09 15:49:04 -08005646 *srisc_addr = 0;
5647 fwcode = (uint16_t *)blob->fw->data;
5648 fwclen = 0;
5649
5650 /* Validate firmware image by checking version. */
5651 if (blob->fw->size < 8 * sizeof(uint16_t)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005652 ql_log(ql_log_fatal, vha, 0x0085,
5653 "Unable to verify integrity of firmware image (%Zd).\n",
Andrew Vasquez54333832005-11-09 15:49:04 -08005654 blob->fw->size);
5655 goto fail_fw_integrity;
5656 }
5657 for (i = 0; i < 4; i++)
5658 wcode[i] = be16_to_cpu(fwcode[i + 4]);
5659 if ((wcode[0] == 0xffff && wcode[1] == 0xffff && wcode[2] == 0xffff &&
5660 wcode[3] == 0xffff) || (wcode[0] == 0 && wcode[1] == 0 &&
5661 wcode[2] == 0 && wcode[3] == 0)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005662 ql_log(ql_log_fatal, vha, 0x0086,
5663 "Unable to verify integrity of firmware image.\n");
5664 ql_log(ql_log_fatal, vha, 0x0087,
5665 "Firmware data: %04x %04x %04x %04x.\n",
5666 wcode[0], wcode[1], wcode[2], wcode[3]);
Andrew Vasquez54333832005-11-09 15:49:04 -08005667 goto fail_fw_integrity;
5668 }
5669
5670 seg = blob->segs;
5671 while (*seg && rval == QLA_SUCCESS) {
5672 risc_addr = *seg;
5673 *srisc_addr = *srisc_addr == 0 ? *seg : *srisc_addr;
5674 risc_size = be16_to_cpu(fwcode[3]);
5675
5676 /* Validate firmware image size. */
5677 fwclen += risc_size * sizeof(uint16_t);
5678 if (blob->fw->size < fwclen) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005679 ql_log(ql_log_fatal, vha, 0x0088,
Andrew Vasquez54333832005-11-09 15:49:04 -08005680 "Unable to verify integrity of firmware image "
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005681 "(%Zd).\n", blob->fw->size);
Andrew Vasquez54333832005-11-09 15:49:04 -08005682 goto fail_fw_integrity;
5683 }
5684
5685 fragment = 0;
5686 while (risc_size > 0 && rval == QLA_SUCCESS) {
5687 wlen = (uint16_t)(ha->fw_transfer_size >> 1);
5688 if (wlen > risc_size)
5689 wlen = risc_size;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005690 ql_dbg(ql_dbg_init, vha, 0x0089,
5691 "Loading risc segment@ risc addr %x number of "
5692 "words 0x%x.\n", risc_addr, wlen);
Andrew Vasquez54333832005-11-09 15:49:04 -08005693
5694 for (i = 0; i < wlen; i++)
5695 wcode[i] = swab16(fwcode[i]);
5696
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005697 rval = qla2x00_load_ram(vha, req->dma, risc_addr,
Andrew Vasquez54333832005-11-09 15:49:04 -08005698 wlen);
5699 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005700 ql_log(ql_log_fatal, vha, 0x008a,
5701 "Failed to load segment %d of firmware.\n",
5702 fragment);
Andrew Vasquez54333832005-11-09 15:49:04 -08005703 break;
5704 }
5705
5706 fwcode += wlen;
5707 risc_addr += wlen;
5708 risc_size -= wlen;
5709 fragment++;
5710 }
5711
5712 /* Next segment. */
5713 seg++;
5714 }
5715 return rval;
5716
5717fail_fw_integrity:
5718 return QLA_FUNCTION_FAILED;
5719}
5720
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08005721static int
5722qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005723{
5724 int rval;
5725 int segments, fragment;
5726 uint32_t *dcode, dlen;
5727 uint32_t risc_addr;
5728 uint32_t risc_size;
5729 uint32_t i;
Andrew Vasquez54333832005-11-09 15:49:04 -08005730 struct fw_blob *blob;
Chad Dupuisf73cb692014-02-26 04:15:06 -05005731 const uint32_t *fwcode;
5732 uint32_t fwclen;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005733 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005734 struct req_que *req = ha->req_q_map[0];
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005735
Andrew Vasquez54333832005-11-09 15:49:04 -08005736 /* Load firmware blob. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005737 blob = qla2x00_request_firmware(vha);
Andrew Vasquez54333832005-11-09 15:49:04 -08005738 if (!blob) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005739 ql_log(ql_log_warn, vha, 0x0090,
Yannick Guerrini94bcf832015-02-26 22:49:34 +01005740 "Firmware image unavailable.\n");
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005741 ql_log(ql_log_warn, vha, 0x0091,
5742 "Firmware images can be retrieved from: "
5743 QLA_FW_URL ".\n");
Andrew Vasquezd1c61902006-05-17 15:09:00 -07005744
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08005745 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005746 }
5747
Chad Dupuiscfb09192011-11-18 09:03:07 -08005748 ql_dbg(ql_dbg_init, vha, 0x0092,
5749 "FW: Loading via request-firmware.\n");
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08005750
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005751 rval = QLA_SUCCESS;
5752
5753 segments = FA_RISC_CODE_SEGMENTS;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005754 dcode = (uint32_t *)req->ring;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005755 *srisc_addr = 0;
Andrew Vasquez54333832005-11-09 15:49:04 -08005756 fwcode = (uint32_t *)blob->fw->data;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005757 fwclen = 0;
5758
5759 /* Validate firmware image by checking version. */
Andrew Vasquez54333832005-11-09 15:49:04 -08005760 if (blob->fw->size < 8 * sizeof(uint32_t)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005761 ql_log(ql_log_fatal, vha, 0x0093,
5762 "Unable to verify integrity of firmware image (%Zd).\n",
Andrew Vasquez54333832005-11-09 15:49:04 -08005763 blob->fw->size);
Chad Dupuisf73cb692014-02-26 04:15:06 -05005764 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005765 }
5766 for (i = 0; i < 4; i++)
5767 dcode[i] = be32_to_cpu(fwcode[i + 4]);
5768 if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
5769 dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
5770 (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
5771 dcode[3] == 0)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005772 ql_log(ql_log_fatal, vha, 0x0094,
5773 "Unable to verify integrity of firmware image (%Zd).\n",
5774 blob->fw->size);
5775 ql_log(ql_log_fatal, vha, 0x0095,
5776 "Firmware data: %08x %08x %08x %08x.\n",
5777 dcode[0], dcode[1], dcode[2], dcode[3]);
Chad Dupuisf73cb692014-02-26 04:15:06 -05005778 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005779 }
5780
5781 while (segments && rval == QLA_SUCCESS) {
5782 risc_addr = be32_to_cpu(fwcode[2]);
5783 *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr;
5784 risc_size = be32_to_cpu(fwcode[3]);
5785
5786 /* Validate firmware image size. */
5787 fwclen += risc_size * sizeof(uint32_t);
Andrew Vasquez54333832005-11-09 15:49:04 -08005788 if (blob->fw->size < fwclen) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005789 ql_log(ql_log_fatal, vha, 0x0096,
Andrew Vasquez54333832005-11-09 15:49:04 -08005790 "Unable to verify integrity of firmware image "
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005791 "(%Zd).\n", blob->fw->size);
Chad Dupuisf73cb692014-02-26 04:15:06 -05005792 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005793 }
5794
5795 fragment = 0;
5796 while (risc_size > 0 && rval == QLA_SUCCESS) {
5797 dlen = (uint32_t)(ha->fw_transfer_size >> 2);
5798 if (dlen > risc_size)
5799 dlen = risc_size;
5800
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005801 ql_dbg(ql_dbg_init, vha, 0x0097,
5802 "Loading risc segment@ risc addr %x "
5803 "number of dwords 0x%x.\n", risc_addr, dlen);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005804
5805 for (i = 0; i < dlen; i++)
5806 dcode[i] = swab32(fwcode[i]);
5807
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005808 rval = qla2x00_load_ram(vha, req->dma, risc_addr,
andrew.vasquez@qlogic.com590f98e2006-01-13 17:05:37 -08005809 dlen);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005810 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005811 ql_log(ql_log_fatal, vha, 0x0098,
5812 "Failed to load segment %d of firmware.\n",
5813 fragment);
Chad Dupuisf261f7a2014-09-25 05:17:03 -04005814 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005815 }
5816
5817 fwcode += dlen;
5818 risc_addr += dlen;
5819 risc_size -= dlen;
5820 fragment++;
5821 }
5822
5823 /* Next segment. */
5824 segments--;
5825 }
Chad Dupuisf73cb692014-02-26 04:15:06 -05005826
5827 if (!IS_QLA27XX(ha))
5828 return rval;
5829
5830 if (ha->fw_dump_template)
5831 vfree(ha->fw_dump_template);
5832 ha->fw_dump_template = NULL;
5833 ha->fw_dump_template_len = 0;
5834
5835 ql_dbg(ql_dbg_init, vha, 0x171,
Chad Dupuis97ea7022014-03-13 14:16:40 -04005836 "Loading fwdump template from %x\n",
5837 (uint32_t)((void *)fwcode - (void *)blob->fw->data));
Chad Dupuisf73cb692014-02-26 04:15:06 -05005838 risc_size = be32_to_cpu(fwcode[2]);
5839 ql_dbg(ql_dbg_init, vha, 0x172,
5840 "-> array size %x dwords\n", risc_size);
5841 if (risc_size == 0 || risc_size == ~0)
5842 goto default_template;
5843
5844 dlen = (risc_size - 8) * sizeof(*fwcode);
5845 ql_dbg(ql_dbg_init, vha, 0x0173,
5846 "-> template allocating %x bytes...\n", dlen);
5847 ha->fw_dump_template = vmalloc(dlen);
5848 if (!ha->fw_dump_template) {
5849 ql_log(ql_log_warn, vha, 0x0174,
5850 "Failed fwdump template allocate %x bytes.\n", risc_size);
5851 goto default_template;
5852 }
5853
5854 fwcode += 7;
5855 risc_size -= 8;
5856 dcode = ha->fw_dump_template;
5857 for (i = 0; i < risc_size; i++)
5858 dcode[i] = le32_to_cpu(fwcode[i]);
5859
5860 if (!qla27xx_fwdt_template_valid(dcode)) {
5861 ql_log(ql_log_warn, vha, 0x0175,
5862 "Failed fwdump template validate\n");
5863 goto default_template;
5864 }
5865
5866 dlen = qla27xx_fwdt_template_size(dcode);
5867 ql_dbg(ql_dbg_init, vha, 0x0176,
5868 "-> template size %x bytes\n", dlen);
5869 if (dlen > risc_size * sizeof(*fwcode)) {
5870 ql_log(ql_log_warn, vha, 0x0177,
Chad Dupuis97ea7022014-03-13 14:16:40 -04005871 "Failed fwdump template exceeds array by %x bytes\n",
5872 (uint32_t)(dlen - risc_size * sizeof(*fwcode)));
Chad Dupuisf73cb692014-02-26 04:15:06 -05005873 goto default_template;
5874 }
5875 ha->fw_dump_template_len = dlen;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005876 return rval;
5877
Chad Dupuisf73cb692014-02-26 04:15:06 -05005878default_template:
5879 ql_log(ql_log_warn, vha, 0x0178, "Using default fwdump template\n");
5880 if (ha->fw_dump_template)
5881 vfree(ha->fw_dump_template);
5882 ha->fw_dump_template = NULL;
5883 ha->fw_dump_template_len = 0;
5884
5885 dlen = qla27xx_fwdt_template_default_size();
5886 ql_dbg(ql_dbg_init, vha, 0x0179,
5887 "-> template allocating %x bytes...\n", dlen);
5888 ha->fw_dump_template = vmalloc(dlen);
5889 if (!ha->fw_dump_template) {
5890 ql_log(ql_log_warn, vha, 0x017a,
5891 "Failed fwdump template allocate %x bytes.\n", risc_size);
5892 goto failed_template;
5893 }
5894
5895 dcode = ha->fw_dump_template;
5896 risc_size = dlen / sizeof(*fwcode);
5897 fwcode = qla27xx_fwdt_template_default();
5898 for (i = 0; i < risc_size; i++)
5899 dcode[i] = be32_to_cpu(fwcode[i]);
5900
5901 if (!qla27xx_fwdt_template_valid(ha->fw_dump_template)) {
5902 ql_log(ql_log_warn, vha, 0x017b,
5903 "Failed fwdump template validate\n");
5904 goto failed_template;
5905 }
5906
5907 dlen = qla27xx_fwdt_template_size(ha->fw_dump_template);
5908 ql_dbg(ql_dbg_init, vha, 0x017c,
5909 "-> template size %x bytes\n", dlen);
5910 ha->fw_dump_template_len = dlen;
5911 return rval;
5912
5913failed_template:
5914 ql_log(ql_log_warn, vha, 0x017d, "Failed default fwdump template\n");
5915 if (ha->fw_dump_template)
5916 vfree(ha->fw_dump_template);
5917 ha->fw_dump_template = NULL;
5918 ha->fw_dump_template_len = 0;
5919 return rval;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005920}
Andrew Vasquez18c6c122006-10-13 09:33:38 -07005921
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08005922int
5923qla24xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
5924{
5925 int rval;
5926
Andrew Vasqueze337d902009-04-06 22:33:49 -07005927 if (ql2xfwloadbin == 1)
5928 return qla81xx_load_risc(vha, srisc_addr);
5929
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08005930 /*
5931 * FW Load priority:
5932 * 1) Firmware via request-firmware interface (.bin file).
5933 * 2) Firmware residing in flash.
5934 */
5935 rval = qla24xx_load_risc_blob(vha, srisc_addr);
5936 if (rval == QLA_SUCCESS)
5937 return rval;
5938
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07005939 return qla24xx_load_risc_flash(vha, srisc_addr,
5940 vha->hw->flt_region_fw);
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08005941}
5942
5943int
5944qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
5945{
5946 int rval;
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07005947 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08005948
Andrew Vasqueze337d902009-04-06 22:33:49 -07005949 if (ql2xfwloadbin == 2)
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07005950 goto try_blob_fw;
Andrew Vasqueze337d902009-04-06 22:33:49 -07005951
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08005952 /*
5953 * FW Load priority:
5954 * 1) Firmware residing in flash.
5955 * 2) Firmware via request-firmware interface (.bin file).
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07005956 * 3) Golden-Firmware residing in flash -- limited operation.
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08005957 */
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07005958 rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_fw);
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08005959 if (rval == QLA_SUCCESS)
5960 return rval;
5961
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07005962try_blob_fw:
5963 rval = qla24xx_load_risc_blob(vha, srisc_addr);
5964 if (rval == QLA_SUCCESS || !ha->flt_region_gold_fw)
5965 return rval;
5966
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005967 ql_log(ql_log_info, vha, 0x0099,
5968 "Attempting to fallback to golden firmware.\n");
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07005969 rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_gold_fw);
5970 if (rval != QLA_SUCCESS)
5971 return rval;
5972
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005973 ql_log(ql_log_info, vha, 0x009a, "Update operational firmware.\n");
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07005974 ha->flags.running_gold_fw = 1;
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07005975 return rval;
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08005976}
5977
Andrew Vasquez18c6c122006-10-13 09:33:38 -07005978void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005979qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha)
Andrew Vasquez18c6c122006-10-13 09:33:38 -07005980{
5981 int ret, retries;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005982 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez18c6c122006-10-13 09:33:38 -07005983
Andrew Vasquez85880802009-12-15 21:29:46 -08005984 if (ha->flags.pci_channel_io_perm_failure)
5985 return;
Andrew Vasqueze4289242007-07-19 15:05:56 -07005986 if (!IS_FWI2_CAPABLE(ha))
Andrew Vasquez18c6c122006-10-13 09:33:38 -07005987 return;
Andrew Vasquez75edf812007-05-07 07:43:00 -07005988 if (!ha->fw_major_version)
5989 return;
Andrew Vasquez18c6c122006-10-13 09:33:38 -07005990
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005991 ret = qla2x00_stop_firmware(vha);
Andrew Vasquez7c7f1f22008-02-28 14:06:09 -08005992 for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT &&
Andrew Vasquezb469a7c2009-04-06 22:33:48 -07005993 ret != QLA_INVALID_COMMAND && retries ; retries--) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005994 ha->isp_ops->reset_chip(vha);
5995 if (ha->isp_ops->chip_diag(vha) != QLA_SUCCESS)
Andrew Vasquez18c6c122006-10-13 09:33:38 -07005996 continue;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005997 if (qla2x00_setup_chip(vha) != QLA_SUCCESS)
Andrew Vasquez18c6c122006-10-13 09:33:38 -07005998 continue;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005999 ql_log(ql_log_info, vha, 0x8015,
6000 "Attempting retry of stop-firmware command.\n");
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006001 ret = qla2x00_stop_firmware(vha);
Andrew Vasquez18c6c122006-10-13 09:33:38 -07006002 }
6003}
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07006004
6005int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006006qla24xx_configure_vhba(scsi_qla_host_t *vha)
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07006007{
6008 int rval = QLA_SUCCESS;
Chad Dupuis0b91d112012-02-09 11:15:42 -08006009 int rval2;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07006010 uint16_t mb[MAILBOX_REGISTER_COUNT];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006011 struct qla_hw_data *ha = vha->hw;
6012 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Anirban Chakraborty67c2e932009-04-06 22:33:42 -07006013 struct req_que *req;
6014 struct rsp_que *rsp;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07006015
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006016 if (!vha->vp_idx)
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07006017 return -EINVAL;
6018
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006019 rval = qla2x00_fw_ready(base_vha);
Anirban Chakraborty7163ea82009-08-05 09:18:40 -07006020 if (ha->flags.cpu_affinity_enabled)
Anirban Chakraborty67c2e932009-04-06 22:33:42 -07006021 req = ha->req_q_map[0];
6022 else
6023 req = vha->req;
6024 rsp = req->rsp;
6025
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07006026 if (rval == QLA_SUCCESS) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006027 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006028 qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07006029 }
6030
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006031 vha->flags.management_server_logged_in = 0;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07006032
6033 /* Login to SNS first */
Chad Dupuis0b91d112012-02-09 11:15:42 -08006034 rval2 = ha->isp_ops->fabric_login(vha, NPH_SNS, 0xff, 0xff, 0xfc, mb,
6035 BIT_1);
6036 if (rval2 != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {
6037 if (rval2 == QLA_MEMORY_ALLOC_FAILED)
6038 ql_dbg(ql_dbg_init, vha, 0x0120,
6039 "Failed SNS login: loop_id=%x, rval2=%d\n",
6040 NPH_SNS, rval2);
6041 else
6042 ql_dbg(ql_dbg_init, vha, 0x0103,
6043 "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x "
6044 "mb[2]=%x mb[6]=%x mb[7]=%x.\n",
6045 NPH_SNS, mb[0], mb[1], mb[2], mb[6], mb[7]);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07006046 return (QLA_FUNCTION_FAILED);
6047 }
6048
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006049 atomic_set(&vha->loop_down_timer, 0);
6050 atomic_set(&vha->loop_state, LOOP_UP);
6051 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
6052 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
6053 rval = qla2x00_loop_resync(base_vha);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07006054
6055 return rval;
6056}
Harihara Kadayam4d4df192008-04-03 13:13:26 -07006057
6058/* 84XX Support **************************************************************/
6059
6060static LIST_HEAD(qla_cs84xx_list);
6061static DEFINE_MUTEX(qla_cs84xx_mutex);
6062
6063static struct qla_chip_state_84xx *
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006064qla84xx_get_chip(struct scsi_qla_host *vha)
Harihara Kadayam4d4df192008-04-03 13:13:26 -07006065{
6066 struct qla_chip_state_84xx *cs84xx;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006067 struct qla_hw_data *ha = vha->hw;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07006068
6069 mutex_lock(&qla_cs84xx_mutex);
6070
6071 /* Find any shared 84xx chip. */
6072 list_for_each_entry(cs84xx, &qla_cs84xx_list, list) {
6073 if (cs84xx->bus == ha->pdev->bus) {
6074 kref_get(&cs84xx->kref);
6075 goto done;
6076 }
6077 }
6078
6079 cs84xx = kzalloc(sizeof(*cs84xx), GFP_KERNEL);
6080 if (!cs84xx)
6081 goto done;
6082
6083 kref_init(&cs84xx->kref);
6084 spin_lock_init(&cs84xx->access_lock);
6085 mutex_init(&cs84xx->fw_update_mutex);
6086 cs84xx->bus = ha->pdev->bus;
6087
6088 list_add_tail(&cs84xx->list, &qla_cs84xx_list);
6089done:
6090 mutex_unlock(&qla_cs84xx_mutex);
6091 return cs84xx;
6092}
6093
6094static void
6095__qla84xx_chip_release(struct kref *kref)
6096{
6097 struct qla_chip_state_84xx *cs84xx =
6098 container_of(kref, struct qla_chip_state_84xx, kref);
6099
6100 mutex_lock(&qla_cs84xx_mutex);
6101 list_del(&cs84xx->list);
6102 mutex_unlock(&qla_cs84xx_mutex);
6103 kfree(cs84xx);
6104}
6105
6106void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006107qla84xx_put_chip(struct scsi_qla_host *vha)
Harihara Kadayam4d4df192008-04-03 13:13:26 -07006108{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006109 struct qla_hw_data *ha = vha->hw;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07006110 if (ha->cs84xx)
6111 kref_put(&ha->cs84xx->kref, __qla84xx_chip_release);
6112}
6113
6114static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006115qla84xx_init_chip(scsi_qla_host_t *vha)
Harihara Kadayam4d4df192008-04-03 13:13:26 -07006116{
6117 int rval;
6118 uint16_t status[2];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006119 struct qla_hw_data *ha = vha->hw;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07006120
6121 mutex_lock(&ha->cs84xx->fw_update_mutex);
6122
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006123 rval = qla84xx_verify_chip(vha, status);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07006124
6125 mutex_unlock(&ha->cs84xx->fw_update_mutex);
6126
6127 return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED:
6128 QLA_SUCCESS;
6129}
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006130
6131/* 81XX Support **************************************************************/
6132
6133int
6134qla81xx_nvram_config(scsi_qla_host_t *vha)
6135{
6136 int rval;
6137 struct init_cb_81xx *icb;
6138 struct nvram_81xx *nv;
6139 uint32_t *dptr;
6140 uint8_t *dptr1, *dptr2;
6141 uint32_t chksum;
6142 uint16_t cnt;
6143 struct qla_hw_data *ha = vha->hw;
6144
6145 rval = QLA_SUCCESS;
6146 icb = (struct init_cb_81xx *)ha->init_cb;
6147 nv = ha->nvram;
6148
6149 /* Determine NVRAM starting address. */
6150 ha->nvram_size = sizeof(struct nvram_81xx);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006151 ha->vpd_size = FA_NVRAM_VPD_SIZE;
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04006152 if (IS_P3P_TYPE(ha) || IS_QLA8031(ha))
6153 ha->vpd_size = FA_VPD_SIZE_82XX;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006154
6155 /* Get VPD data into cache */
6156 ha->vpd = ha->nvram + VPD_OFFSET;
Andrew Vasquez3d79038f2009-03-24 09:08:14 -07006157 ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2,
6158 ha->vpd_size);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006159
6160 /* Get NVRAM data into cache and calculate checksum. */
Andrew Vasquez3d79038f2009-03-24 09:08:14 -07006161 ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2,
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006162 ha->nvram_size);
Andrew Vasquez3d79038f2009-03-24 09:08:14 -07006163 dptr = (uint32_t *)nv;
Joe Carnuccioda08ef52016-01-27 12:03:34 -05006164 for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++)
6165 chksum += le32_to_cpu(*dptr);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006166
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006167 ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0111,
6168 "Contents of NVRAM:\n");
6169 ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0112,
6170 (uint8_t *)nv, ha->nvram_size);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006171
6172 /* Bad NVRAM data, set defaults parameters. */
6173 if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P'
6174 || nv->id[3] != ' ' ||
Bart Van Asschead950362015-07-09 07:24:08 -07006175 nv->nvram_version < cpu_to_le16(ICB_VERSION)) {
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006176 /* Reset NVRAM data. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006177 ql_log(ql_log_info, vha, 0x0073,
Raul Porcel9e336522012-05-15 14:34:08 -04006178 "Inconsistent NVRAM detected: checksum=0x%x id=%c "
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006179 "version=0x%x.\n", chksum, nv->id[0],
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006180 le16_to_cpu(nv->nvram_version));
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006181 ql_log(ql_log_info, vha, 0x0074,
6182 "Falling back to functioning (yet invalid -- WWPN) "
6183 "defaults.\n");
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006184
6185 /*
6186 * Set default initialization control block.
6187 */
6188 memset(nv, 0, ha->nvram_size);
Bart Van Asschead950362015-07-09 07:24:08 -07006189 nv->nvram_version = cpu_to_le16(ICB_VERSION);
6190 nv->version = cpu_to_le16(ICB_VERSION);
Joe Carnuccio98aee702014-09-25 05:16:38 -04006191 nv->frame_payload_size = 2048;
Bart Van Asschead950362015-07-09 07:24:08 -07006192 nv->execution_throttle = cpu_to_le16(0xFFFF);
6193 nv->exchange_count = cpu_to_le16(0);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006194 nv->port_name[0] = 0x21;
Chad Dupuisf73cb692014-02-26 04:15:06 -05006195 nv->port_name[1] = 0x00 + ha->port_no + 1;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006196 nv->port_name[2] = 0x00;
6197 nv->port_name[3] = 0xe0;
6198 nv->port_name[4] = 0x8b;
6199 nv->port_name[5] = 0x1c;
6200 nv->port_name[6] = 0x55;
6201 nv->port_name[7] = 0x86;
6202 nv->node_name[0] = 0x20;
6203 nv->node_name[1] = 0x00;
6204 nv->node_name[2] = 0x00;
6205 nv->node_name[3] = 0xe0;
6206 nv->node_name[4] = 0x8b;
6207 nv->node_name[5] = 0x1c;
6208 nv->node_name[6] = 0x55;
6209 nv->node_name[7] = 0x86;
Bart Van Asschead950362015-07-09 07:24:08 -07006210 nv->login_retry_count = cpu_to_le16(8);
6211 nv->interrupt_delay_timer = cpu_to_le16(0);
6212 nv->login_timeout = cpu_to_le16(0);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006213 nv->firmware_options_1 =
Bart Van Asschead950362015-07-09 07:24:08 -07006214 cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1);
6215 nv->firmware_options_2 = cpu_to_le32(2 << 4);
6216 nv->firmware_options_2 |= cpu_to_le32(BIT_12);
6217 nv->firmware_options_3 = cpu_to_le32(2 << 13);
6218 nv->host_p = cpu_to_le32(BIT_11|BIT_10);
6219 nv->efi_parameters = cpu_to_le32(0);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006220 nv->reset_delay = 5;
Bart Van Asschead950362015-07-09 07:24:08 -07006221 nv->max_luns_per_target = cpu_to_le16(128);
6222 nv->port_down_retry_count = cpu_to_le16(30);
6223 nv->link_down_timeout = cpu_to_le16(180);
Andrew Vasquezeeebcc92009-06-03 09:55:24 -07006224 nv->enode_mac[0] = 0x00;
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08006225 nv->enode_mac[1] = 0xC0;
6226 nv->enode_mac[2] = 0xDD;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006227 nv->enode_mac[3] = 0x04;
6228 nv->enode_mac[4] = 0x05;
Chad Dupuisf73cb692014-02-26 04:15:06 -05006229 nv->enode_mac[5] = 0x06 + ha->port_no + 1;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006230
6231 rval = 1;
6232 }
6233
Arun Easi9e522cd2012-08-22 14:21:31 -04006234 if (IS_T10_PI_CAPABLE(ha))
6235 nv->frame_payload_size &= ~7;
6236
Arun Easiaa230bc2013-01-30 03:34:39 -05006237 qlt_81xx_config_nvram_stage1(vha, nv);
6238
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006239 /* Reset Initialization control block */
Andrew Vasquez773120e2011-05-10 11:30:14 -07006240 memset(icb, 0, ha->init_cb_size);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006241
6242 /* Copy 1st segment. */
6243 dptr1 = (uint8_t *)icb;
6244 dptr2 = (uint8_t *)&nv->version;
6245 cnt = (uint8_t *)&icb->response_q_inpointer - (uint8_t *)&icb->version;
6246 while (cnt--)
6247 *dptr1++ = *dptr2++;
6248
6249 icb->login_retry_count = nv->login_retry_count;
6250
6251 /* Copy 2nd segment. */
6252 dptr1 = (uint8_t *)&icb->interrupt_delay_timer;
6253 dptr2 = (uint8_t *)&nv->interrupt_delay_timer;
6254 cnt = (uint8_t *)&icb->reserved_5 -
6255 (uint8_t *)&icb->interrupt_delay_timer;
6256 while (cnt--)
6257 *dptr1++ = *dptr2++;
6258
6259 memcpy(icb->enode_mac, nv->enode_mac, sizeof(icb->enode_mac));
6260 /* Some boards (with valid NVRAMs) still have NULL enode_mac!! */
6261 if (!memcmp(icb->enode_mac, "\0\0\0\0\0\0", sizeof(icb->enode_mac))) {
Andrew Vasquez69e5f1e2012-02-09 11:15:35 -08006262 icb->enode_mac[0] = 0x00;
6263 icb->enode_mac[1] = 0xC0;
6264 icb->enode_mac[2] = 0xDD;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006265 icb->enode_mac[3] = 0x04;
6266 icb->enode_mac[4] = 0x05;
Chad Dupuisf73cb692014-02-26 04:15:06 -05006267 icb->enode_mac[5] = 0x06 + ha->port_no + 1;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006268 }
6269
Andrew Vasquezb64b0e82009-03-24 09:08:01 -07006270 /* Use extended-initialization control block. */
6271 memcpy(ha->ex_init_cb, &nv->ex_version, sizeof(*ha->ex_init_cb));
6272
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006273 /*
6274 * Setup driver NVRAM options.
6275 */
6276 qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name),
Giridhar Malavalia9083012010-04-12 17:59:55 -07006277 "QLE8XXX");
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006278
Arun Easiaa230bc2013-01-30 03:34:39 -05006279 qlt_81xx_config_nvram_stage2(vha, icb);
6280
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006281 /* Use alternate WWN? */
Bart Van Asschead950362015-07-09 07:24:08 -07006282 if (nv->host_p & cpu_to_le32(BIT_15)) {
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006283 memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
6284 memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
6285 }
6286
6287 /* Prepare nodename */
Bart Van Asschead950362015-07-09 07:24:08 -07006288 if ((icb->firmware_options_1 & cpu_to_le32(BIT_14)) == 0) {
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006289 /*
6290 * Firmware will apply the following mask if the nodename was
6291 * not provided.
6292 */
6293 memcpy(icb->node_name, icb->port_name, WWN_SIZE);
6294 icb->node_name[0] &= 0xF0;
6295 }
6296
6297 /* Set host adapter parameters. */
6298 ha->flags.disable_risc_code_load = 0;
6299 ha->flags.enable_lip_reset = 0;
6300 ha->flags.enable_lip_full_login =
6301 le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0;
6302 ha->flags.enable_target_reset =
6303 le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0;
6304 ha->flags.enable_led_scheme = 0;
6305 ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0;
6306
6307 ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) &
6308 (BIT_6 | BIT_5 | BIT_4)) >> 4;
6309
6310 /* save HBA serial number */
6311 ha->serial0 = icb->port_name[5];
6312 ha->serial1 = icb->port_name[6];
6313 ha->serial2 = icb->port_name[7];
6314 memcpy(vha->node_name, icb->node_name, WWN_SIZE);
6315 memcpy(vha->port_name, icb->port_name, WWN_SIZE);
6316
Bart Van Asschead950362015-07-09 07:24:08 -07006317 icb->execution_throttle = cpu_to_le16(0xFFFF);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006318
6319 ha->retry_count = le16_to_cpu(nv->login_retry_count);
6320
6321 /* Set minimum login_timeout to 4 seconds. */
6322 if (le16_to_cpu(nv->login_timeout) < ql2xlogintimeout)
6323 nv->login_timeout = cpu_to_le16(ql2xlogintimeout);
6324 if (le16_to_cpu(nv->login_timeout) < 4)
Bart Van Asschead950362015-07-09 07:24:08 -07006325 nv->login_timeout = cpu_to_le16(4);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006326 ha->login_timeout = le16_to_cpu(nv->login_timeout);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006327
6328 /* Set minimum RATOV to 100 tenths of a second. */
6329 ha->r_a_tov = 100;
6330
6331 ha->loop_reset_delay = nv->reset_delay;
6332
6333 /* Link Down Timeout = 0:
6334 *
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04006335 * When Port Down timer expires we will start returning
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006336 * I/O's to OS with "DID_NO_CONNECT".
6337 *
6338 * Link Down Timeout != 0:
6339 *
6340 * The driver waits for the link to come up after link down
6341 * before returning I/Os to OS with "DID_NO_CONNECT".
6342 */
6343 if (le16_to_cpu(nv->link_down_timeout) == 0) {
6344 ha->loop_down_abort_time =
6345 (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT);
6346 } else {
6347 ha->link_down_timeout = le16_to_cpu(nv->link_down_timeout);
6348 ha->loop_down_abort_time =
6349 (LOOP_DOWN_TIME - ha->link_down_timeout);
6350 }
6351
6352 /* Need enough time to try and get the port back. */
6353 ha->port_down_retry_count = le16_to_cpu(nv->port_down_retry_count);
6354 if (qlport_down_retry)
6355 ha->port_down_retry_count = qlport_down_retry;
6356
6357 /* Set login_retry_count */
6358 ha->login_retry_count = le16_to_cpu(nv->login_retry_count);
6359 if (ha->port_down_retry_count ==
6360 le16_to_cpu(nv->port_down_retry_count) &&
6361 ha->port_down_retry_count > 3)
6362 ha->login_retry_count = ha->port_down_retry_count;
6363 else if (ha->port_down_retry_count > (int)ha->login_retry_count)
6364 ha->login_retry_count = ha->port_down_retry_count;
6365 if (ql2xloginretrycount)
6366 ha->login_retry_count = ql2xloginretrycount;
6367
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08006368 /* if not running MSI-X we need handshaking on interrupts */
Chad Dupuisf73cb692014-02-26 04:15:06 -05006369 if (!vha->hw->flags.msix_enabled && (IS_QLA83XX(ha) || IS_QLA27XX(ha)))
Bart Van Asschead950362015-07-09 07:24:08 -07006370 icb->firmware_options_2 |= cpu_to_le32(BIT_22);
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08006371
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006372 /* Enable ZIO. */
6373 if (!vha->flags.init_done) {
6374 ha->zio_mode = le32_to_cpu(icb->firmware_options_2) &
6375 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
6376 ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ?
6377 le16_to_cpu(icb->interrupt_delay_timer): 2;
6378 }
Bart Van Asschead950362015-07-09 07:24:08 -07006379 icb->firmware_options_2 &= cpu_to_le32(
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006380 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
6381 vha->flags.process_response_queue = 0;
6382 if (ha->zio_mode != QLA_ZIO_DISABLED) {
6383 ha->zio_mode = QLA_ZIO_MODE_6;
6384
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006385 ql_log(ql_log_info, vha, 0x0075,
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006386 "ZIO mode %d enabled; timer delay (%d us).\n",
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006387 ha->zio_mode,
6388 ha->zio_timer * 100);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006389
6390 icb->firmware_options_2 |= cpu_to_le32(
6391 (uint32_t)ha->zio_mode);
6392 icb->interrupt_delay_timer = cpu_to_le16(ha->zio_timer);
6393 vha->flags.process_response_queue = 1;
6394 }
6395
6396 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006397 ql_log(ql_log_warn, vha, 0x0076,
6398 "NVRAM configuration failed.\n");
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006399 }
6400 return (rval);
6401}
6402
Giridhar Malavalia9083012010-04-12 17:59:55 -07006403int
6404qla82xx_restart_isp(scsi_qla_host_t *vha)
6405{
6406 int status, rval;
Giridhar Malavalia9083012010-04-12 17:59:55 -07006407 struct qla_hw_data *ha = vha->hw;
6408 struct req_que *req = ha->req_q_map[0];
6409 struct rsp_que *rsp = ha->rsp_q_map[0];
6410 struct scsi_qla_host *vp;
Arun Easifeafb7b2010-09-03 14:57:00 -07006411 unsigned long flags;
Giridhar Malavalia9083012010-04-12 17:59:55 -07006412
6413 status = qla2x00_init_rings(vha);
6414 if (!status) {
6415 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
6416 ha->flags.chip_reset_done = 1;
6417
6418 status = qla2x00_fw_ready(vha);
6419 if (!status) {
Giridhar Malavalia9083012010-04-12 17:59:55 -07006420 /* Issue a marker after FW becomes ready. */
6421 qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
Giridhar Malavalia9083012010-04-12 17:59:55 -07006422 vha->flags.online = 1;
Chad Dupuis7108b762014-04-11 16:54:45 -04006423 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
Giridhar Malavalia9083012010-04-12 17:59:55 -07006424 }
6425
6426 /* if no cable then assume it's good */
6427 if ((vha->device_flags & DFLG_NO_CABLE))
6428 status = 0;
Giridhar Malavalia9083012010-04-12 17:59:55 -07006429 }
6430
6431 if (!status) {
6432 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
6433
6434 if (!atomic_read(&vha->loop_down_timer)) {
6435 /*
6436 * Issue marker command only when we are going
6437 * to start the I/O .
6438 */
6439 vha->marker_needed = 1;
6440 }
6441
Giridhar Malavalia9083012010-04-12 17:59:55 -07006442 ha->isp_ops->enable_intrs(ha);
6443
6444 ha->isp_abort_cnt = 0;
6445 clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
6446
Saurav Kashyap53296782011-05-10 11:30:06 -07006447 /* Update the firmware version */
Giridhar Malavali31731672011-08-16 11:31:54 -07006448 status = qla82xx_check_md_needed(vha);
Saurav Kashyap53296782011-05-10 11:30:06 -07006449
Giridhar Malavalia9083012010-04-12 17:59:55 -07006450 if (ha->fce) {
6451 ha->flags.fce_enabled = 1;
6452 memset(ha->fce, 0,
6453 fce_calc_size(ha->fce_bufs));
6454 rval = qla2x00_enable_fce_trace(vha,
6455 ha->fce_dma, ha->fce_bufs, ha->fce_mb,
6456 &ha->fce_bufs);
6457 if (rval) {
Chad Dupuiscfb09192011-11-18 09:03:07 -08006458 ql_log(ql_log_warn, vha, 0x8001,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006459 "Unable to reinitialize FCE (%d).\n",
6460 rval);
Giridhar Malavalia9083012010-04-12 17:59:55 -07006461 ha->flags.fce_enabled = 0;
6462 }
6463 }
6464
6465 if (ha->eft) {
6466 memset(ha->eft, 0, EFT_SIZE);
6467 rval = qla2x00_enable_eft_trace(vha,
6468 ha->eft_dma, EFT_NUM_BUFFERS);
6469 if (rval) {
Chad Dupuiscfb09192011-11-18 09:03:07 -08006470 ql_log(ql_log_warn, vha, 0x8010,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006471 "Unable to reinitialize EFT (%d).\n",
6472 rval);
Giridhar Malavalia9083012010-04-12 17:59:55 -07006473 }
6474 }
Giridhar Malavalia9083012010-04-12 17:59:55 -07006475 }
6476
6477 if (!status) {
Chad Dupuiscfb09192011-11-18 09:03:07 -08006478 ql_dbg(ql_dbg_taskm, vha, 0x8011,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006479 "qla82xx_restart_isp succeeded.\n");
Arun Easifeafb7b2010-09-03 14:57:00 -07006480
6481 spin_lock_irqsave(&ha->vport_slock, flags);
6482 list_for_each_entry(vp, &ha->vp_list, list) {
6483 if (vp->vp_idx) {
6484 atomic_inc(&vp->vref_count);
6485 spin_unlock_irqrestore(&ha->vport_slock, flags);
6486
Giridhar Malavalia9083012010-04-12 17:59:55 -07006487 qla2x00_vp_abort_isp(vp);
Arun Easifeafb7b2010-09-03 14:57:00 -07006488
6489 spin_lock_irqsave(&ha->vport_slock, flags);
6490 atomic_dec(&vp->vref_count);
6491 }
Giridhar Malavalia9083012010-04-12 17:59:55 -07006492 }
Arun Easifeafb7b2010-09-03 14:57:00 -07006493 spin_unlock_irqrestore(&ha->vport_slock, flags);
6494
Giridhar Malavalia9083012010-04-12 17:59:55 -07006495 } else {
Chad Dupuiscfb09192011-11-18 09:03:07 -08006496 ql_log(ql_log_warn, vha, 0x8016,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006497 "qla82xx_restart_isp **** FAILED ****.\n");
Giridhar Malavalia9083012010-04-12 17:59:55 -07006498 }
6499
6500 return status;
6501}
6502
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006503void
Andrew Vasquezae97c912010-02-18 10:07:28 -08006504qla81xx_update_fw_options(scsi_qla_host_t *vha)
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006505{
Andrew Vasquezae97c912010-02-18 10:07:28 -08006506 struct qla_hw_data *ha = vha->hw;
6507
Himanshu Madhanif198caf2016-01-27 12:03:30 -05006508 /* Hold status IOCBs until ABTS response received. */
6509 if (ql2xfwholdabts)
6510 ha->fw_options[3] |= BIT_12;
6511
Andrew Vasquezae97c912010-02-18 10:07:28 -08006512 if (!ql2xetsenable)
Himanshu Madhanif198caf2016-01-27 12:03:30 -05006513 goto out;
Andrew Vasquezae97c912010-02-18 10:07:28 -08006514
6515 /* Enable ETS Burst. */
6516 memset(ha->fw_options, 0, sizeof(ha->fw_options));
6517 ha->fw_options[2] |= BIT_9;
Himanshu Madhanif198caf2016-01-27 12:03:30 -05006518out:
Andrew Vasquezae97c912010-02-18 10:07:28 -08006519 qla2x00_set_fw_options(vha, ha->fw_options);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08006520}
Sarang Radke09ff7012010-03-19 17:03:59 -07006521
6522/*
6523 * qla24xx_get_fcp_prio
6524 * Gets the fcp cmd priority value for the logged in port.
6525 * Looks for a match of the port descriptors within
6526 * each of the fcp prio config entries. If a match is found,
6527 * the tag (priority) value is returned.
6528 *
6529 * Input:
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08006530 * vha = scsi host structure pointer.
Sarang Radke09ff7012010-03-19 17:03:59 -07006531 * fcport = port structure pointer.
6532 *
6533 * Return:
Andrew Vasquez6c452a42010-03-19 17:04:02 -07006534 * non-zero (if found)
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07006535 * -1 (if not found)
Sarang Radke09ff7012010-03-19 17:03:59 -07006536 *
6537 * Context:
6538 * Kernel context
6539 */
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07006540static int
Sarang Radke09ff7012010-03-19 17:03:59 -07006541qla24xx_get_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
6542{
6543 int i, entries;
6544 uint8_t pid_match, wwn_match;
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07006545 int priority;
Sarang Radke09ff7012010-03-19 17:03:59 -07006546 uint32_t pid1, pid2;
6547 uint64_t wwn1, wwn2;
6548 struct qla_fcp_prio_entry *pri_entry;
6549 struct qla_hw_data *ha = vha->hw;
6550
6551 if (!ha->fcp_prio_cfg || !ha->flags.fcp_prio_enabled)
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07006552 return -1;
Sarang Radke09ff7012010-03-19 17:03:59 -07006553
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07006554 priority = -1;
Sarang Radke09ff7012010-03-19 17:03:59 -07006555 entries = ha->fcp_prio_cfg->num_entries;
6556 pri_entry = &ha->fcp_prio_cfg->entry[0];
6557
6558 for (i = 0; i < entries; i++) {
6559 pid_match = wwn_match = 0;
6560
6561 if (!(pri_entry->flags & FCP_PRIO_ENTRY_VALID)) {
6562 pri_entry++;
6563 continue;
6564 }
6565
6566 /* check source pid for a match */
6567 if (pri_entry->flags & FCP_PRIO_ENTRY_SPID_VALID) {
6568 pid1 = pri_entry->src_pid & INVALID_PORT_ID;
6569 pid2 = vha->d_id.b24 & INVALID_PORT_ID;
6570 if (pid1 == INVALID_PORT_ID)
6571 pid_match++;
6572 else if (pid1 == pid2)
6573 pid_match++;
6574 }
6575
6576 /* check destination pid for a match */
6577 if (pri_entry->flags & FCP_PRIO_ENTRY_DPID_VALID) {
6578 pid1 = pri_entry->dst_pid & INVALID_PORT_ID;
6579 pid2 = fcport->d_id.b24 & INVALID_PORT_ID;
6580 if (pid1 == INVALID_PORT_ID)
6581 pid_match++;
6582 else if (pid1 == pid2)
6583 pid_match++;
6584 }
6585
6586 /* check source WWN for a match */
6587 if (pri_entry->flags & FCP_PRIO_ENTRY_SWWN_VALID) {
6588 wwn1 = wwn_to_u64(vha->port_name);
6589 wwn2 = wwn_to_u64(pri_entry->src_wwpn);
6590 if (wwn2 == (uint64_t)-1)
6591 wwn_match++;
6592 else if (wwn1 == wwn2)
6593 wwn_match++;
6594 }
6595
6596 /* check destination WWN for a match */
6597 if (pri_entry->flags & FCP_PRIO_ENTRY_DWWN_VALID) {
6598 wwn1 = wwn_to_u64(fcport->port_name);
6599 wwn2 = wwn_to_u64(pri_entry->dst_wwpn);
6600 if (wwn2 == (uint64_t)-1)
6601 wwn_match++;
6602 else if (wwn1 == wwn2)
6603 wwn_match++;
6604 }
6605
6606 if (pid_match == 2 || wwn_match == 2) {
6607 /* Found a matching entry */
6608 if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID)
6609 priority = pri_entry->tag;
6610 break;
6611 }
6612
6613 pri_entry++;
6614 }
6615
6616 return priority;
6617}
6618
6619/*
6620 * qla24xx_update_fcport_fcp_prio
6621 * Activates fcp priority for the logged in fc port
6622 *
6623 * Input:
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08006624 * vha = scsi host structure pointer.
Sarang Radke09ff7012010-03-19 17:03:59 -07006625 * fcp = port structure pointer.
6626 *
6627 * Return:
6628 * QLA_SUCCESS or QLA_FUNCTION_FAILED
6629 *
6630 * Context:
6631 * Kernel context.
6632 */
6633int
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08006634qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
Sarang Radke09ff7012010-03-19 17:03:59 -07006635{
6636 int ret;
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07006637 int priority;
Sarang Radke09ff7012010-03-19 17:03:59 -07006638 uint16_t mb[5];
6639
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08006640 if (fcport->port_type != FCT_TARGET ||
6641 fcport->loop_id == FC_NO_LOOP_ID)
Sarang Radke09ff7012010-03-19 17:03:59 -07006642 return QLA_FUNCTION_FAILED;
6643
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08006644 priority = qla24xx_get_fcp_prio(vha, fcport);
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07006645 if (priority < 0)
6646 return QLA_FUNCTION_FAILED;
6647
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04006648 if (IS_P3P_TYPE(vha->hw)) {
Saurav Kashyapa00f6292011-11-18 09:03:19 -08006649 fcport->fcp_prio = priority & 0xf;
6650 return QLA_SUCCESS;
6651 }
6652
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08006653 ret = qla24xx_set_fcp_prio(vha, fcport->loop_id, priority, mb);
Chad Dupuiscfb09192011-11-18 09:03:07 -08006654 if (ret == QLA_SUCCESS) {
6655 if (fcport->fcp_prio != priority)
6656 ql_dbg(ql_dbg_user, vha, 0x709e,
6657 "Updated FCP_CMND priority - value=%d loop_id=%d "
6658 "port_id=%02x%02x%02x.\n", priority,
6659 fcport->loop_id, fcport->d_id.b.domain,
6660 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Saurav Kashyapa00f6292011-11-18 09:03:19 -08006661 fcport->fcp_prio = priority & 0xf;
Chad Dupuiscfb09192011-11-18 09:03:07 -08006662 } else
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006663 ql_dbg(ql_dbg_user, vha, 0x704f,
Chad Dupuiscfb09192011-11-18 09:03:07 -08006664 "Unable to update FCP_CMND priority - ret=0x%x for "
6665 "loop_id=%d port_id=%02x%02x%02x.\n", ret, fcport->loop_id,
6666 fcport->d_id.b.domain, fcport->d_id.b.area,
6667 fcport->d_id.b.al_pa);
Sarang Radke09ff7012010-03-19 17:03:59 -07006668 return ret;
6669}
6670
6671/*
6672 * qla24xx_update_all_fcp_prio
6673 * Activates fcp priority for all the logged in ports
6674 *
6675 * Input:
6676 * ha = adapter block pointer.
6677 *
6678 * Return:
6679 * QLA_SUCCESS or QLA_FUNCTION_FAILED
6680 *
6681 * Context:
6682 * Kernel context.
6683 */
6684int
6685qla24xx_update_all_fcp_prio(scsi_qla_host_t *vha)
6686{
6687 int ret;
6688 fc_port_t *fcport;
6689
6690 ret = QLA_FUNCTION_FAILED;
6691 /* We need to set priority for all logged in ports */
6692 list_for_each_entry(fcport, &vha->vp_fcports, list)
6693 ret = qla24xx_update_fcport_fcp_prio(vha, fcport);
6694
6695 return ret;
6696}