blob: 7dd19785f8207092bf9c28f58857719c16e26545 [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 *);
Quinn Tran726b8542017-01-19 22:28:00 -080033static int qla2x00_find_all_fabric_devs(scsi_qla_host_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070034static int qla2x00_restart_isp(scsi_qla_host_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Harihara Kadayam4d4df192008-04-03 13:13:26 -070036static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
37static int qla84xx_init_chip(scsi_qla_host_t *);
Anirban Chakraborty73208df2008-12-09 16:45:39 -080038static int qla25xx_init_queues(struct qla_hw_data *);
Duane Grigsbya5d42f42017-06-21 13:48:41 -070039static int qla24xx_post_prli_work(struct scsi_qla_host*, fc_port_t *);
Quinn Tran726b8542017-01-19 22:28:00 -080040static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
41 struct event_arg *);
Duane Grigsbya5d42f42017-06-21 13:48:41 -070042static void qla24xx_handle_prli_done_event(struct scsi_qla_host *,
43 struct event_arg *);
Harihara Kadayam4d4df192008-04-03 13:13:26 -070044
Andrew Vasquezac280b62009-08-20 11:06:05 -070045/* SRB Extensions ---------------------------------------------------------- */
46
Giridhar Malavali9ba56b92012-02-09 11:15:36 -080047void
Kees Cook8e5f4ba2017-09-03 13:23:32 -070048qla2x00_sp_timeout(struct timer_list *t)
Andrew Vasquezac280b62009-08-20 11:06:05 -070049{
Kees Cook8e5f4ba2017-09-03 13:23:32 -070050 srb_t *sp = from_timer(sp, t, u.iocb_cmd.timer);
Madhuranath Iyengar49163922010-05-04 15:01:28 -070051 struct srb_iocb *iocb;
Joe Carnuccio25ff6af2017-01-19 22:28:04 -080052 scsi_qla_host_t *vha = sp->vha;
Andrew Vasquezac280b62009-08-20 11:06:05 -070053 struct req_que *req;
54 unsigned long flags;
55
Joe Carnuccio25ff6af2017-01-19 22:28:04 -080056 spin_lock_irqsave(&vha->hw->hardware_lock, flags);
57 req = vha->hw->req_q_map[0];
Andrew Vasquezac280b62009-08-20 11:06:05 -070058 req->outstanding_cmds[sp->handle] = NULL;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -080059 iocb = &sp->u.iocb_cmd;
Madhuranath Iyengar49163922010-05-04 15:01:28 -070060 iocb->timeout(sp);
Joe Carnuccio25ff6af2017-01-19 22:28:04 -080061 sp->free(sp);
62 spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
Andrew Vasquezac280b62009-08-20 11:06:05 -070063}
64
Giridhar Malavali9ba56b92012-02-09 11:15:36 -080065void
Joe Carnuccio25ff6af2017-01-19 22:28:04 -080066qla2x00_sp_free(void *ptr)
Andrew Vasquezac280b62009-08-20 11:06:05 -070067{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -080068 srb_t *sp = ptr;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -080069 struct srb_iocb *iocb = &sp->u.iocb_cmd;
Andrew Vasquezac280b62009-08-20 11:06:05 -070070
Chad Dupuis4d97cc52010-10-15 11:27:41 -070071 del_timer(&iocb->timer);
Joe Carnuccio25ff6af2017-01-19 22:28:04 -080072 qla2x00_rel_sp(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
Quinn Tran726b8542017-01-19 22:28:00 -080097void
Giridhar Malavali9ba56b92012-02-09 11:15:36 -080098qla2x00_async_iocb_timeout(void *data)
Andrew Vasquezac280b62009-08-20 11:06:05 -070099{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800100 srb_t *sp = data;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700101 fc_port_t *fcport = sp->fcport;
Quinn Tran726b8542017-01-19 22:28:00 -0800102 struct srb_iocb *lio = &sp->u.iocb_cmd;
103 struct event_arg ea;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700104
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700105 ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
Quinn Tran726b8542017-01-19 22:28:00 -0800106 "Async-%s timeout - hdl=%x portid=%06x %8phC.\n",
107 sp->name, sp->handle, fcport->d_id.b24, fcport->port_name);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700108
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700109 fcport->flags &= ~FCF_ASYNC_SENT;
Quinn Tran726b8542017-01-19 22:28:00 -0800110
111 switch (sp->type) {
112 case SRB_LOGIN_CMD:
Andrew Vasquez6ac52602010-05-28 15:08:19 -0700113 /* Retry as needed. */
114 lio->u.logio.data[0] = MBS_COMMAND_ERROR;
115 lio->u.logio.data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
116 QLA_LOGIO_LOGIN_RETRIED : 0;
Quinn Tran726b8542017-01-19 22:28:00 -0800117 memset(&ea, 0, sizeof(ea));
118 ea.event = FCME_PLOGI_DONE;
119 ea.fcport = sp->fcport;
120 ea.data[0] = lio->u.logio.data[0];
121 ea.data[1] = lio->u.logio.data[1];
122 ea.sp = sp;
123 qla24xx_handle_plogi_done_event(fcport->vha, &ea);
124 break;
125 case SRB_LOGOUT_CMD:
Alexei Potashnika6ca8872015-07-14 16:00:44 -0400126 qlt_logo_completion_handler(fcport, QLA_FUNCTION_TIMEOUT);
Quinn Tran726b8542017-01-19 22:28:00 -0800127 break;
128 case SRB_CT_PTHRU_CMD:
129 case SRB_MB_IOCB:
130 case SRB_NACK_PLOGI:
131 case SRB_NACK_PRLI:
132 case SRB_NACK_LOGO:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800133 sp->done(sp, QLA_FUNCTION_TIMEOUT);
Quinn Tran726b8542017-01-19 22:28:00 -0800134 break;
Andrew Vasquez6ac52602010-05-28 15:08:19 -0700135 }
Andrew Vasquezac280b62009-08-20 11:06:05 -0700136}
137
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700138static void
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800139qla2x00_async_login_sp_done(void *ptr, int res)
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700140{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800141 srb_t *sp = ptr;
142 struct scsi_qla_host *vha = sp->vha;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800143 struct srb_iocb *lio = &sp->u.iocb_cmd;
Quinn Tran726b8542017-01-19 22:28:00 -0800144 struct event_arg ea;
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700145
Quinn Tran83548fe2017-06-02 09:12:01 -0700146 ql_dbg(ql_dbg_disc, vha, 0x20dd,
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800147 "%s %8phC res %d \n", __func__, sp->fcport->port_name, res);
Quinn Tran726b8542017-01-19 22:28:00 -0800148
149 sp->fcport->flags &= ~FCF_ASYNC_SENT;
150 if (!test_bit(UNLOADING, &vha->dpc_flags)) {
151 memset(&ea, 0, sizeof(ea));
152 ea.event = FCME_PLOGI_DONE;
153 ea.fcport = sp->fcport;
154 ea.data[0] = lio->u.logio.data[0];
155 ea.data[1] = lio->u.logio.data[1];
156 ea.iop[0] = lio->u.logio.iop[0];
157 ea.iop[1] = lio->u.logio.iop[1];
158 ea.sp = sp;
159 qla2x00_fcport_event_handler(vha, &ea);
160 }
161
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800162 sp->free(sp);
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700163}
164
Andrew Vasquezac280b62009-08-20 11:06:05 -0700165int
166qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
167 uint16_t *data)
168{
Andrew Vasquezac280b62009-08-20 11:06:05 -0700169 srb_t *sp;
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700170 struct srb_iocb *lio;
Quinn Tran726b8542017-01-19 22:28:00 -0800171 int rval = QLA_FUNCTION_FAILED;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700172
Quinn Tran726b8542017-01-19 22:28:00 -0800173 if (!vha->flags.online)
174 goto done;
175
176 if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
177 (fcport->fw_login_state == DSC_LS_PLOGI_COMP) ||
178 (fcport->fw_login_state == DSC_LS_PRLI_PEND))
179 goto done;
180
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800181 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700182 if (!sp)
183 goto done;
184
Quinn Tran726b8542017-01-19 22:28:00 -0800185 fcport->flags |= FCF_ASYNC_SENT;
186 fcport->logout_completed = 0;
187
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800188 sp->type = SRB_LOGIN_CMD;
189 sp->name = "login";
190 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
191
192 lio = &sp->u.iocb_cmd;
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700193 lio->timeout = qla2x00_async_iocb_timeout;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800194 sp->done = qla2x00_async_login_sp_done;
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700195 lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
Duane Grigsbya5d42f42017-06-21 13:48:41 -0700196
197 if (fcport->fc4f_nvme)
198 lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI;
199
Andrew Vasquezac280b62009-08-20 11:06:05 -0700200 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700201 lio->u.logio.flags |= SRB_LOGIN_RETRIED;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700202 rval = qla2x00_start_sp(sp);
Chad Dupuis080c9512016-01-27 12:03:37 -0500203 if (rval != QLA_SUCCESS) {
204 fcport->flags &= ~FCF_ASYNC_SENT;
205 fcport->flags |= FCF_LOGIN_NEEDED;
206 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700207 goto done_free_sp;
Chad Dupuis080c9512016-01-27 12:03:37 -0500208 }
Andrew Vasquezac280b62009-08-20 11:06:05 -0700209
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700210 ql_dbg(ql_dbg_disc, vha, 0x2072,
Quinn Tran726b8542017-01-19 22:28:00 -0800211 "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x "
212 "retries=%d.\n", fcport->port_name, sp->handle, fcport->loop_id,
Chad Dupuiscfb09192011-11-18 09:03:07 -0800213 fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
214 fcport->login_retry);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700215 return rval;
216
217done_free_sp:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800218 sp->free(sp);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700219done:
Quinn Tran726b8542017-01-19 22:28:00 -0800220 fcport->flags &= ~FCF_ASYNC_SENT;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700221 return rval;
222}
223
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700224static void
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800225qla2x00_async_logout_sp_done(void *ptr, int res)
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700226{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800227 srb_t *sp = ptr;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800228 struct srb_iocb *lio = &sp->u.iocb_cmd;
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700229
Quinn Tran726b8542017-01-19 22:28:00 -0800230 sp->fcport->flags &= ~FCF_ASYNC_SENT;
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800231 if (!test_bit(UNLOADING, &sp->vha->dpc_flags))
232 qla2x00_post_async_logout_done_work(sp->vha, sp->fcport,
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800233 lio->u.logio.data);
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800234 sp->free(sp);
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700235}
236
Andrew Vasquezac280b62009-08-20 11:06:05 -0700237int
238qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
239{
Andrew Vasquezac280b62009-08-20 11:06:05 -0700240 srb_t *sp;
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700241 struct srb_iocb *lio;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700242 int rval;
243
244 rval = QLA_FUNCTION_FAILED;
Quinn Tran726b8542017-01-19 22:28:00 -0800245 fcport->flags |= FCF_ASYNC_SENT;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800246 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700247 if (!sp)
248 goto done;
249
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800250 sp->type = SRB_LOGOUT_CMD;
251 sp->name = "logout";
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_logout_sp_done;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700257 rval = qla2x00_start_sp(sp);
258 if (rval != QLA_SUCCESS)
259 goto done_free_sp;
260
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700261 ql_dbg(ql_dbg_disc, vha, 0x2070,
Quinn Tran726b8542017-01-19 22:28:00 -0800262 "Async-logout - hdl=%x loop-id=%x portid=%02x%02x%02x %8phC.\n",
Chad Dupuiscfb09192011-11-18 09:03:07 -0800263 sp->handle, fcport->loop_id, fcport->d_id.b.domain,
Quinn Tran726b8542017-01-19 22:28:00 -0800264 fcport->d_id.b.area, fcport->d_id.b.al_pa,
265 fcport->port_name);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700266 return rval;
267
268done_free_sp:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800269 sp->free(sp);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700270done:
Quinn Tran726b8542017-01-19 22:28:00 -0800271 fcport->flags &= ~FCF_ASYNC_SENT;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700272 return rval;
273}
274
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700275static void
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800276qla2x00_async_adisc_sp_done(void *ptr, int res)
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700277{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800278 srb_t *sp = ptr;
279 struct scsi_qla_host *vha = sp->vha;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800280 struct srb_iocb *lio = &sp->u.iocb_cmd;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700281
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800282 if (!test_bit(UNLOADING, &vha->dpc_flags))
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800283 qla2x00_post_async_adisc_done_work(sp->vha, sp->fcport,
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800284 lio->u.logio.data);
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800285 sp->free(sp);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700286}
287
288int
289qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
290 uint16_t *data)
291{
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700292 srb_t *sp;
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700293 struct srb_iocb *lio;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700294 int rval;
295
296 rval = QLA_FUNCTION_FAILED;
Quinn Tran726b8542017-01-19 22:28:00 -0800297 fcport->flags |= FCF_ASYNC_SENT;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800298 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700299 if (!sp)
300 goto done;
301
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800302 sp->type = SRB_ADISC_CMD;
303 sp->name = "adisc";
304 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
305
306 lio = &sp->u.iocb_cmd;
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700307 lio->timeout = qla2x00_async_iocb_timeout;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800308 sp->done = qla2x00_async_adisc_sp_done;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700309 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700310 lio->u.logio.flags |= SRB_LOGIN_RETRIED;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700311 rval = qla2x00_start_sp(sp);
312 if (rval != QLA_SUCCESS)
313 goto done_free_sp;
314
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700315 ql_dbg(ql_dbg_disc, vha, 0x206f,
Chad Dupuiscfb09192011-11-18 09:03:07 -0800316 "Async-adisc - hdl=%x loopid=%x portid=%02x%02x%02x.\n",
317 sp->handle, fcport->loop_id, fcport->d_id.b.domain,
318 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700319 return rval;
320
321done_free_sp:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800322 sp->free(sp);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700323done:
Quinn Tran726b8542017-01-19 22:28:00 -0800324 fcport->flags &= ~FCF_ASYNC_SENT;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700325 return rval;
326}
327
Quinn Tran726b8542017-01-19 22:28:00 -0800328static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
329 struct event_arg *ea)
330{
331 fc_port_t *fcport, *conflict_fcport;
332 struct get_name_list_extended *e;
333 u16 i, n, found = 0, loop_id;
334 port_id_t id;
335 u64 wwn;
Duane Grigsbya5d42f42017-06-21 13:48:41 -0700336 u8 opt = 0, current_login_state;
Quinn Tran726b8542017-01-19 22:28:00 -0800337
338 fcport = ea->fcport;
339
340 if (ea->rc) { /* rval */
341 if (fcport->login_retry == 0) {
342 fcport->login_retry = vha->hw->login_retry_count;
Quinn Tran83548fe2017-06-02 09:12:01 -0700343 ql_dbg(ql_dbg_disc, vha, 0x20de,
344 "GNL failed Port login retry %8phN, retry cnt=%d.\n",
345 fcport->port_name, fcport->login_retry);
Quinn Tran726b8542017-01-19 22:28:00 -0800346 }
347 return;
348 }
349
350 if (fcport->last_rscn_gen != fcport->rscn_gen) {
Quinn Tran83548fe2017-06-02 09:12:01 -0700351 ql_dbg(ql_dbg_disc, vha, 0x20df,
Quinn Tran726b8542017-01-19 22:28:00 -0800352 "%s %8phC rscn gen changed rscn %d|%d \n",
353 __func__, fcport->port_name,
354 fcport->last_rscn_gen, fcport->rscn_gen);
355 qla24xx_post_gidpn_work(vha, fcport);
356 return;
357 } else if (fcport->last_login_gen != fcport->login_gen) {
Quinn Tran83548fe2017-06-02 09:12:01 -0700358 ql_dbg(ql_dbg_disc, vha, 0x20e0,
359 "%s %8phC login gen changed login %d|%d\n",
360 __func__, fcport->port_name,
361 fcport->last_login_gen, fcport->login_gen);
Quinn Tran726b8542017-01-19 22:28:00 -0800362 return;
363 }
364
365 n = ea->data[0] / sizeof(struct get_name_list_extended);
366
Quinn Tran83548fe2017-06-02 09:12:01 -0700367 ql_dbg(ql_dbg_disc, vha, 0x20e1,
Quinn Tran726b8542017-01-19 22:28:00 -0800368 "%s %d %8phC n %d %02x%02x%02x lid %d \n",
369 __func__, __LINE__, fcport->port_name, n,
370 fcport->d_id.b.domain, fcport->d_id.b.area,
371 fcport->d_id.b.al_pa, fcport->loop_id);
372
373 for (i = 0; i < n; i++) {
374 e = &vha->gnl.l[i];
375 wwn = wwn_to_u64(e->port_name);
376
377 if (memcmp((u8 *)&wwn, fcport->port_name, WWN_SIZE))
378 continue;
379
380 found = 1;
381 id.b.domain = e->port_id[2];
382 id.b.area = e->port_id[1];
383 id.b.al_pa = e->port_id[0];
384 id.b.rsvd_1 = 0;
385
386 loop_id = le16_to_cpu(e->nport_handle);
387 loop_id = (loop_id & 0x7fff);
388
Quinn Tran83548fe2017-06-02 09:12:01 -0700389 ql_dbg(ql_dbg_disc, vha, 0x20e2,
390 "%s found %8phC CLS [%d|%d] ID[%02x%02x%02x|%02x%02x%02x] lid[%d|%d]\n",
391 __func__, fcport->port_name,
392 e->current_login_state, fcport->fw_login_state,
393 id.b.domain, id.b.area, id.b.al_pa,
394 fcport->d_id.b.domain, fcport->d_id.b.area,
395 fcport->d_id.b.al_pa, loop_id, fcport->loop_id);
Quinn Tran726b8542017-01-19 22:28:00 -0800396
397 if ((id.b24 != fcport->d_id.b24) ||
398 ((fcport->loop_id != FC_NO_LOOP_ID) &&
399 (fcport->loop_id != loop_id))) {
Quinn Tran83548fe2017-06-02 09:12:01 -0700400 ql_dbg(ql_dbg_disc, vha, 0x20e3,
401 "%s %d %8phC post del sess\n",
402 __func__, __LINE__, fcport->port_name);
Quinn Tran726b8542017-01-19 22:28:00 -0800403 qlt_schedule_sess_for_deletion(fcport, 1);
404 return;
405 }
406
407 fcport->loop_id = loop_id;
408
409 wwn = wwn_to_u64(fcport->port_name);
410 qlt_find_sess_invalidate_other(vha, wwn,
411 id, loop_id, &conflict_fcport);
412
413 if (conflict_fcport) {
414 /*
415 * Another share fcport share the same loop_id &
416 * nport id. Conflict fcport needs to finish
417 * cleanup before this fcport can proceed to login.
418 */
419 conflict_fcport->conflict = fcport;
420 fcport->login_pause = 1;
421 }
422
Duane Grigsbya5d42f42017-06-21 13:48:41 -0700423 if (fcport->fc4f_nvme)
424 current_login_state = e->current_login_state >> 4;
425 else
426 current_login_state = e->current_login_state & 0xf;
427
428 switch (current_login_state) {
Quinn Tran726b8542017-01-19 22:28:00 -0800429 case DSC_LS_PRLI_COMP:
Quinn Tran83548fe2017-06-02 09:12:01 -0700430 ql_dbg(ql_dbg_disc, vha, 0x20e4,
431 "%s %d %8phC post gpdb\n",
432 __func__, __LINE__, fcport->port_name);
Quinn Tran726b8542017-01-19 22:28:00 -0800433 opt = PDO_FORCE_ADISC;
434 qla24xx_post_gpdb_work(vha, fcport, opt);
435 break;
Quinn Tran726b8542017-01-19 22:28:00 -0800436 case DSC_LS_PORT_UNAVAIL:
437 default:
438 if (fcport->loop_id == FC_NO_LOOP_ID) {
439 qla2x00_find_new_loop_id(vha, fcport);
440 fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
441 }
Quinn Tran83548fe2017-06-02 09:12:01 -0700442 ql_dbg(ql_dbg_disc, vha, 0x20e5,
443 "%s %d %8phC\n",
444 __func__, __LINE__, fcport->port_name);
Quinn Tran726b8542017-01-19 22:28:00 -0800445 qla24xx_fcport_handle_login(vha, fcport);
446 break;
447 }
448 }
449
450 if (!found) {
451 /* fw has no record of this port */
452 if (fcport->loop_id == FC_NO_LOOP_ID) {
453 qla2x00_find_new_loop_id(vha, fcport);
454 fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
455 } else {
456 for (i = 0; i < n; i++) {
457 e = &vha->gnl.l[i];
458 id.b.domain = e->port_id[0];
459 id.b.area = e->port_id[1];
460 id.b.al_pa = e->port_id[2];
461 id.b.rsvd_1 = 0;
462 loop_id = le16_to_cpu(e->nport_handle);
463
464 if (fcport->d_id.b24 == id.b24) {
465 conflict_fcport =
466 qla2x00_find_fcport_by_wwpn(vha,
467 e->port_name, 0);
468
Quinn Tran83548fe2017-06-02 09:12:01 -0700469 ql_dbg(ql_dbg_disc, vha, 0x20e6,
Quinn Tran726b8542017-01-19 22:28:00 -0800470 "%s %d %8phC post del sess\n",
471 __func__, __LINE__,
472 conflict_fcport->port_name);
473 qlt_schedule_sess_for_deletion
474 (conflict_fcport, 1);
475 }
476
477 if (fcport->loop_id == loop_id) {
478 /* FW already picked this loop id for another fcport */
479 qla2x00_find_new_loop_id(vha, fcport);
480 }
481 }
482 }
483 qla24xx_fcport_handle_login(vha, fcport);
484 }
485} /* gnl_event */
486
487static void
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800488qla24xx_async_gnl_sp_done(void *s, int res)
Quinn Tran726b8542017-01-19 22:28:00 -0800489{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800490 struct srb *sp = s;
491 struct scsi_qla_host *vha = sp->vha;
Quinn Tran726b8542017-01-19 22:28:00 -0800492 unsigned long flags;
493 struct fc_port *fcport = NULL, *tf;
494 u16 i, n = 0, loop_id;
495 struct event_arg ea;
496 struct get_name_list_extended *e;
497 u64 wwn;
498 struct list_head h;
499
Quinn Tran83548fe2017-06-02 09:12:01 -0700500 ql_dbg(ql_dbg_disc, vha, 0x20e7,
Quinn Tran726b8542017-01-19 22:28:00 -0800501 "Async done-%s res %x mb[1]=%x mb[2]=%x \n",
502 sp->name, res, sp->u.iocb_cmd.u.mbx.in_mb[1],
503 sp->u.iocb_cmd.u.mbx.in_mb[2]);
504
505 memset(&ea, 0, sizeof(ea));
506 ea.sp = sp;
507 ea.rc = res;
508 ea.event = FCME_GNL_DONE;
509
510 if (sp->u.iocb_cmd.u.mbx.in_mb[1] >=
511 sizeof(struct get_name_list_extended)) {
512 n = sp->u.iocb_cmd.u.mbx.in_mb[1] /
513 sizeof(struct get_name_list_extended);
514 ea.data[0] = sp->u.iocb_cmd.u.mbx.in_mb[1]; /* amnt xfered */
515 }
516
517 for (i = 0; i < n; i++) {
518 e = &vha->gnl.l[i];
519 loop_id = le16_to_cpu(e->nport_handle);
520 /* mask out reserve bit */
521 loop_id = (loop_id & 0x7fff);
522 set_bit(loop_id, vha->hw->loop_id_map);
523 wwn = wwn_to_u64(e->port_name);
524
Quinn Tran83548fe2017-06-02 09:12:01 -0700525 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x20e8,
Quinn Tran726b8542017-01-19 22:28:00 -0800526 "%s %8phC %02x:%02x:%02x state %d/%d lid %x \n",
527 __func__, (void *)&wwn, e->port_id[2], e->port_id[1],
528 e->port_id[0], e->current_login_state, e->last_login_state,
529 (loop_id & 0x7fff));
530 }
531
532 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
533 vha->gnl.sent = 0;
534
535 INIT_LIST_HEAD(&h);
536 fcport = tf = NULL;
537 if (!list_empty(&vha->gnl.fcports))
538 list_splice_init(&vha->gnl.fcports, &h);
539
540 list_for_each_entry_safe(fcport, tf, &h, gnl_entry) {
541 list_del_init(&fcport->gnl_entry);
542 fcport->flags &= ~FCF_ASYNC_SENT;
543 ea.fcport = fcport;
544
545 qla2x00_fcport_event_handler(vha, &ea);
546 }
547
548 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
549
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800550 sp->free(sp);
Quinn Tran726b8542017-01-19 22:28:00 -0800551}
552
553int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
554{
555 srb_t *sp;
556 struct srb_iocb *mbx;
557 int rval = QLA_FUNCTION_FAILED;
558 unsigned long flags;
559 u16 *mb;
560
561 if (!vha->flags.online)
562 goto done;
563
Quinn Tran83548fe2017-06-02 09:12:01 -0700564 ql_dbg(ql_dbg_disc, vha, 0x20d9,
Quinn Tran726b8542017-01-19 22:28:00 -0800565 "Async-gnlist WWPN %8phC \n", fcport->port_name);
566
567 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
568 fcport->flags |= FCF_ASYNC_SENT;
569 fcport->disc_state = DSC_GNL;
570 fcport->last_rscn_gen = fcport->rscn_gen;
571 fcport->last_login_gen = fcport->login_gen;
572
573 list_add_tail(&fcport->gnl_entry, &vha->gnl.fcports);
574 if (vha->gnl.sent) {
575 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
576 rval = QLA_SUCCESS;
577 goto done;
578 }
579 vha->gnl.sent = 1;
580 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
581
582 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
583 if (!sp)
584 goto done;
585 sp->type = SRB_MB_IOCB;
586 sp->name = "gnlist";
587 sp->gen1 = fcport->rscn_gen;
588 sp->gen2 = fcport->login_gen;
589
590 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
591
592 mb = sp->u.iocb_cmd.u.mbx.out_mb;
593 mb[0] = MBC_PORT_NODE_NAME_LIST;
594 mb[1] = BIT_2 | BIT_3;
595 mb[2] = MSW(vha->gnl.ldma);
596 mb[3] = LSW(vha->gnl.ldma);
597 mb[6] = MSW(MSD(vha->gnl.ldma));
598 mb[7] = LSW(MSD(vha->gnl.ldma));
599 mb[8] = vha->gnl.size;
600 mb[9] = vha->vp_idx;
601
602 mbx = &sp->u.iocb_cmd;
603 mbx->timeout = qla2x00_async_iocb_timeout;
604
605 sp->done = qla24xx_async_gnl_sp_done;
606
607 rval = qla2x00_start_sp(sp);
608 if (rval != QLA_SUCCESS)
609 goto done_free_sp;
610
Quinn Tran83548fe2017-06-02 09:12:01 -0700611 ql_dbg(ql_dbg_disc, vha, 0x20da,
612 "Async-%s - OUT WWPN %8phC hndl %x\n",
613 sp->name, fcport->port_name, sp->handle);
Quinn Tran726b8542017-01-19 22:28:00 -0800614
615 return rval;
616
617done_free_sp:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800618 sp->free(sp);
Quinn Tran726b8542017-01-19 22:28:00 -0800619done:
620 fcport->flags &= ~FCF_ASYNC_SENT;
621 return rval;
622}
623
624int qla24xx_post_gnl_work(struct scsi_qla_host *vha, fc_port_t *fcport)
625{
626 struct qla_work_evt *e;
627
628 e = qla2x00_alloc_work(vha, QLA_EVT_GNL);
629 if (!e)
630 return QLA_FUNCTION_FAILED;
631
632 e->u.fcport.fcport = fcport;
633 return qla2x00_post_work(vha, e);
634}
635
636static
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800637void qla24xx_async_gpdb_sp_done(void *s, int res)
Quinn Tran726b8542017-01-19 22:28:00 -0800638{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800639 struct srb *sp = s;
640 struct scsi_qla_host *vha = sp->vha;
Quinn Tran726b8542017-01-19 22:28:00 -0800641 struct qla_hw_data *ha = vha->hw;
Quinn Tran726b8542017-01-19 22:28:00 -0800642 struct port_database_24xx *pd;
643 fc_port_t *fcport = sp->fcport;
644 u16 *mb = sp->u.iocb_cmd.u.mbx.in_mb;
645 int rval = QLA_SUCCESS;
646 struct event_arg ea;
647
Quinn Tran83548fe2017-06-02 09:12:01 -0700648 ql_dbg(ql_dbg_disc, vha, 0x20db,
Quinn Tran726b8542017-01-19 22:28:00 -0800649 "Async done-%s res %x, WWPN %8phC mb[1]=%x mb[2]=%x \n",
650 sp->name, res, fcport->port_name, mb[1], mb[2]);
651
652 fcport->flags &= ~FCF_ASYNC_SENT;
653
654 if (res) {
655 rval = res;
656 goto gpd_error_out;
657 }
658
659 pd = (struct port_database_24xx *)sp->u.iocb_cmd.u.mbx.in;
660
Quinn Tran15f30a52017-03-15 09:48:52 -0700661 rval = __qla24xx_parse_gpdb(vha, fcport, pd);
Quinn Tran726b8542017-01-19 22:28:00 -0800662
663gpd_error_out:
664 memset(&ea, 0, sizeof(ea));
665 ea.event = FCME_GPDB_DONE;
666 ea.rc = rval;
667 ea.fcport = fcport;
668 ea.sp = sp;
669
670 qla2x00_fcport_event_handler(vha, &ea);
671
672 dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
673 sp->u.iocb_cmd.u.mbx.in_dma);
674
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800675 sp->free(sp);
Quinn Tran726b8542017-01-19 22:28:00 -0800676}
677
Duane Grigsbya5d42f42017-06-21 13:48:41 -0700678static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
679{
680 struct qla_work_evt *e;
681
682 e = qla2x00_alloc_work(vha, QLA_EVT_PRLI);
683 if (!e)
684 return QLA_FUNCTION_FAILED;
685
686 e->u.fcport.fcport = fcport;
687
688 return qla2x00_post_work(vha, e);
689}
690
691static void
692qla2x00_async_prli_sp_done(void *ptr, int res)
693{
694 srb_t *sp = ptr;
695 struct scsi_qla_host *vha = sp->vha;
696 struct srb_iocb *lio = &sp->u.iocb_cmd;
697 struct event_arg ea;
698
699 ql_dbg(ql_dbg_disc, vha, 0x2129,
700 "%s %8phC res %d \n", __func__,
701 sp->fcport->port_name, res);
702
703 sp->fcport->flags &= ~FCF_ASYNC_SENT;
704
705 if (!test_bit(UNLOADING, &vha->dpc_flags)) {
706 memset(&ea, 0, sizeof(ea));
707 ea.event = FCME_PRLI_DONE;
708 ea.fcport = sp->fcport;
709 ea.data[0] = lio->u.logio.data[0];
710 ea.data[1] = lio->u.logio.data[1];
711 ea.iop[0] = lio->u.logio.iop[0];
712 ea.iop[1] = lio->u.logio.iop[1];
713 ea.sp = sp;
714
715 qla2x00_fcport_event_handler(vha, &ea);
716 }
717
718 sp->free(sp);
719}
720
721int
722qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
723{
724 srb_t *sp;
725 struct srb_iocb *lio;
726 int rval = QLA_FUNCTION_FAILED;
727
728 if (!vha->flags.online)
729 return rval;
730
731 if (fcport->fw_login_state == DSC_LS_PLOGI_PEND ||
732 fcport->fw_login_state == DSC_LS_PLOGI_COMP ||
733 fcport->fw_login_state == DSC_LS_PRLI_PEND)
734 return rval;
735
736 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
737 if (!sp)
738 return rval;
739
740 fcport->flags |= FCF_ASYNC_SENT;
741 fcport->logout_completed = 0;
742
743 sp->type = SRB_PRLI_CMD;
744 sp->name = "prli";
745 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
746
747 lio = &sp->u.iocb_cmd;
748 lio->timeout = qla2x00_async_iocb_timeout;
749 sp->done = qla2x00_async_prli_sp_done;
750 lio->u.logio.flags = 0;
751
752 if (fcport->fc4f_nvme)
753 lio->u.logio.flags |= SRB_LOGIN_NVME_PRLI;
754
755 rval = qla2x00_start_sp(sp);
756 if (rval != QLA_SUCCESS) {
757 fcport->flags &= ~FCF_ASYNC_SENT;
758 fcport->flags |= FCF_LOGIN_NEEDED;
759 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
760 goto done_free_sp;
761 }
762
763 ql_dbg(ql_dbg_disc, vha, 0x211b,
764 "Async-prli - %8phC hdl=%x, loopid=%x portid=%06x retries=%d.\n",
765 fcport->port_name, sp->handle, fcport->loop_id,
766 fcport->d_id.b24, fcport->login_retry);
767
768 return rval;
769
770done_free_sp:
771 sp->free(sp);
772 fcport->flags &= ~FCF_ASYNC_SENT;
773 return rval;
774}
775
Quinn Trana07fc0a2017-08-23 15:05:21 -0700776int qla24xx_post_gpdb_work(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
Quinn Tran726b8542017-01-19 22:28:00 -0800777{
778 struct qla_work_evt *e;
779
780 e = qla2x00_alloc_work(vha, QLA_EVT_GPDB);
781 if (!e)
782 return QLA_FUNCTION_FAILED;
783
784 e->u.fcport.fcport = fcport;
785 e->u.fcport.opt = opt;
786 return qla2x00_post_work(vha, e);
787}
788
789int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
790{
791 srb_t *sp;
792 struct srb_iocb *mbx;
793 int rval = QLA_FUNCTION_FAILED;
794 u16 *mb;
795 dma_addr_t pd_dma;
796 struct port_database_24xx *pd;
797 struct qla_hw_data *ha = vha->hw;
798
799 if (!vha->flags.online)
800 goto done;
801
802 fcport->flags |= FCF_ASYNC_SENT;
803 fcport->disc_state = DSC_GPDB;
804
805 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
806 if (!sp)
807 goto done;
808
Joe Carnuccioe0824e62017-08-23 15:05:08 -0700809 sp->type = SRB_MB_IOCB;
810 sp->name = "gpdb";
811 sp->gen1 = fcport->rscn_gen;
812 sp->gen2 = fcport->login_gen;
813 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
814
Thomas Meyer08eb7f42017-09-21 08:15:26 +0200815 pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
Quinn Tran726b8542017-01-19 22:28:00 -0800816 if (pd == NULL) {
Quinn Tran83548fe2017-06-02 09:12:01 -0700817 ql_log(ql_log_warn, vha, 0xd043,
818 "Failed to allocate port database structure.\n");
Quinn Tran726b8542017-01-19 22:28:00 -0800819 goto done_free_sp;
820 }
Quinn Tran726b8542017-01-19 22:28:00 -0800821
Quinn Tran726b8542017-01-19 22:28:00 -0800822 mb = sp->u.iocb_cmd.u.mbx.out_mb;
823 mb[0] = MBC_GET_PORT_DATABASE;
824 mb[1] = fcport->loop_id;
825 mb[2] = MSW(pd_dma);
826 mb[3] = LSW(pd_dma);
827 mb[6] = MSW(MSD(pd_dma));
828 mb[7] = LSW(MSD(pd_dma));
829 mb[9] = vha->vp_idx;
830 mb[10] = opt;
831
832 mbx = &sp->u.iocb_cmd;
833 mbx->timeout = qla2x00_async_iocb_timeout;
834 mbx->u.mbx.in = (void *)pd;
835 mbx->u.mbx.in_dma = pd_dma;
836
837 sp->done = qla24xx_async_gpdb_sp_done;
838
839 rval = qla2x00_start_sp(sp);
840 if (rval != QLA_SUCCESS)
841 goto done_free_sp;
842
Quinn Tran83548fe2017-06-02 09:12:01 -0700843 ql_dbg(ql_dbg_disc, vha, 0x20dc,
844 "Async-%s %8phC hndl %x opt %x\n",
845 sp->name, fcport->port_name, sp->handle, opt);
Quinn Tran726b8542017-01-19 22:28:00 -0800846
847 return rval;
848
849done_free_sp:
850 if (pd)
851 dma_pool_free(ha->s_dma_pool, pd, pd_dma);
852
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800853 sp->free(sp);
Quinn Tran726b8542017-01-19 22:28:00 -0800854done:
855 fcport->flags &= ~FCF_ASYNC_SENT;
856 qla24xx_post_gpdb_work(vha, fcport, opt);
857 return rval;
858}
859
860static
861void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
862{
863 int rval = ea->rc;
864 fc_port_t *fcport = ea->fcport;
865 unsigned long flags;
Quinn Tran414d9ff2017-12-04 14:45:03 -0800866 u16 opt = ea->sp->u.iocb_cmd.u.mbx.out_mb[10];
Quinn Tran726b8542017-01-19 22:28:00 -0800867
868 fcport->flags &= ~FCF_ASYNC_SENT;
869
Quinn Tran83548fe2017-06-02 09:12:01 -0700870 ql_dbg(ql_dbg_disc, vha, 0x20d2,
Quinn Tran726b8542017-01-19 22:28:00 -0800871 "%s %8phC DS %d LS %d rval %d\n", __func__, fcport->port_name,
872 fcport->disc_state, fcport->fw_login_state, rval);
873
874 if (ea->sp->gen2 != fcport->login_gen) {
875 /* target side must have changed it. */
Quinn Tran83548fe2017-06-02 09:12:01 -0700876 ql_dbg(ql_dbg_disc, vha, 0x20d3,
Quinn Tran726b8542017-01-19 22:28:00 -0800877 "%s %8phC generation changed rscn %d|%d login %d|%d \n",
878 __func__, fcport->port_name, fcport->last_rscn_gen,
879 fcport->rscn_gen, fcport->last_login_gen,
880 fcport->login_gen);
881 return;
882 } else if (ea->sp->gen1 != fcport->rscn_gen) {
Quinn Tran83548fe2017-06-02 09:12:01 -0700883 ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
Quinn Tran726b8542017-01-19 22:28:00 -0800884 __func__, __LINE__, fcport->port_name);
885 qla24xx_post_gidpn_work(vha, fcport);
886 return;
887 }
888
889 if (rval != QLA_SUCCESS) {
Quinn Tran83548fe2017-06-02 09:12:01 -0700890 ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC post del sess\n",
Quinn Tran726b8542017-01-19 22:28:00 -0800891 __func__, __LINE__, fcport->port_name);
892 qlt_schedule_sess_for_deletion_lock(fcport);
893 return;
894 }
895
896 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
Quinn Tran414d9ff2017-12-04 14:45:03 -0800897 if (opt != PDO_FORCE_ADISC)
898 ea->fcport->login_gen++;
Quinn Tran726b8542017-01-19 22:28:00 -0800899 ea->fcport->deleted = 0;
900 ea->fcport->logout_on_delete = 1;
901
902 if (!ea->fcport->login_succ && !IS_SW_RESV_ADDR(ea->fcport->d_id)) {
903 vha->fcport_count++;
904 ea->fcport->login_succ = 1;
905
906 if (!IS_IIDMA_CAPABLE(vha->hw) ||
907 !vha->hw->flags.gpsc_supported) {
Quinn Tran83548fe2017-06-02 09:12:01 -0700908 ql_dbg(ql_dbg_disc, vha, 0x20d6,
Quinn Tran726b8542017-01-19 22:28:00 -0800909 "%s %d %8phC post upd_fcport fcp_cnt %d\n",
910 __func__, __LINE__, fcport->port_name,
911 vha->fcport_count);
912
913 qla24xx_post_upd_fcport_work(vha, fcport);
914 } else {
Quinn Tran83548fe2017-06-02 09:12:01 -0700915 ql_dbg(ql_dbg_disc, vha, 0x20d7,
Quinn Tran726b8542017-01-19 22:28:00 -0800916 "%s %d %8phC post gpsc fcp_cnt %d\n",
917 __func__, __LINE__, fcport->port_name,
918 vha->fcport_count);
919
920 qla24xx_post_gpsc_work(vha, fcport);
921 }
Quinn Tran414d9ff2017-12-04 14:45:03 -0800922 } else if (ea->fcport->login_succ) {
923 /*
924 * We have an existing session. A late RSCN delivery
925 * must have triggered the session to be re-validate.
926 * session is still valid.
927 */
Quinn Tran5ef696a2017-12-04 14:45:05 -0800928 ql_dbg(ql_dbg_disc, vha, 0x20d6,
929 "%s %d %8phC session revalidate success\n",
930 __func__, __LINE__, fcport->port_name);
Quinn Tran414d9ff2017-12-04 14:45:03 -0800931 fcport->disc_state = DSC_LOGIN_COMPLETE;
Quinn Tran726b8542017-01-19 22:28:00 -0800932 }
933 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
934} /* gpdb event */
935
936int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
937{
938 if (fcport->login_retry == 0)
939 return 0;
940
941 if (fcport->scan_state != QLA_FCPORT_FOUND)
942 return 0;
943
Quinn Tran83548fe2017-06-02 09:12:01 -0700944 ql_dbg(ql_dbg_disc, vha, 0x20d8,
Quinn Tran726b8542017-01-19 22:28:00 -0800945 "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d|%d retry %d lid %d\n",
946 __func__, fcport->port_name, fcport->disc_state,
947 fcport->fw_login_state, fcport->login_pause, fcport->flags,
948 fcport->conflict, fcport->last_rscn_gen, fcport->rscn_gen,
949 fcport->last_login_gen, fcport->login_gen, fcport->login_retry,
950 fcport->loop_id);
951
952 fcport->login_retry--;
953
954 if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
Quinn Tran726b8542017-01-19 22:28:00 -0800955 (fcport->fw_login_state == DSC_LS_PRLI_PEND))
956 return 0;
957
Quinn Tran5b334692017-03-15 09:48:48 -0700958 if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
959 if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline))
960 return 0;
961 }
962
Quinn Tran726b8542017-01-19 22:28:00 -0800963 /* for pure Target Mode. Login will not be initiated */
964 if (vha->host->active_mode == MODE_TARGET)
965 return 0;
966
967 if (fcport->flags & FCF_ASYNC_SENT) {
968 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
969 return 0;
970 }
971
972 switch (fcport->disc_state) {
973 case DSC_DELETED:
974 if (fcport->loop_id == FC_NO_LOOP_ID) {
Quinn Tran83548fe2017-06-02 09:12:01 -0700975 ql_dbg(ql_dbg_disc, vha, 0x20bd,
976 "%s %d %8phC post gnl\n",
977 __func__, __LINE__, fcport->port_name);
Quinn Tran726b8542017-01-19 22:28:00 -0800978 qla24xx_async_gnl(vha, fcport);
979 } else {
Quinn Tran83548fe2017-06-02 09:12:01 -0700980 ql_dbg(ql_dbg_disc, vha, 0x20bf,
981 "%s %d %8phC post login\n",
982 __func__, __LINE__, fcport->port_name);
Quinn Tran726b8542017-01-19 22:28:00 -0800983 fcport->disc_state = DSC_LOGIN_PEND;
984 qla2x00_post_async_login_work(vha, fcport, NULL);
985 }
986 break;
987
988 case DSC_GNL:
989 if (fcport->login_pause) {
990 fcport->last_rscn_gen = fcport->rscn_gen;
991 fcport->last_login_gen = fcport->login_gen;
992 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
993 break;
994 }
995
996 if (fcport->flags & FCF_FCP2_DEVICE) {
997 u8 opt = PDO_FORCE_ADISC;
998
Quinn Tran83548fe2017-06-02 09:12:01 -0700999 ql_dbg(ql_dbg_disc, vha, 0x20c9,
1000 "%s %d %8phC post gpdb\n",
1001 __func__, __LINE__, fcport->port_name);
Quinn Tran726b8542017-01-19 22:28:00 -08001002
1003 fcport->disc_state = DSC_GPDB;
1004 qla24xx_post_gpdb_work(vha, fcport, opt);
1005 } else {
Quinn Tran83548fe2017-06-02 09:12:01 -07001006 ql_dbg(ql_dbg_disc, vha, 0x20cf,
1007 "%s %d %8phC post login\n",
1008 __func__, __LINE__, fcport->port_name);
Quinn Tran726b8542017-01-19 22:28:00 -08001009 fcport->disc_state = DSC_LOGIN_PEND;
1010 qla2x00_post_async_login_work(vha, fcport, NULL);
1011 }
1012
1013 break;
1014
1015 case DSC_LOGIN_FAILED:
Quinn Tran83548fe2017-06-02 09:12:01 -07001016 ql_dbg(ql_dbg_disc, vha, 0x20d0,
1017 "%s %d %8phC post gidpn\n",
1018 __func__, __LINE__, fcport->port_name);
Quinn Tran726b8542017-01-19 22:28:00 -08001019
1020 qla24xx_post_gidpn_work(vha, fcport);
1021 break;
1022
1023 case DSC_LOGIN_COMPLETE:
1024 /* recheck login state */
Quinn Tran83548fe2017-06-02 09:12:01 -07001025 ql_dbg(ql_dbg_disc, vha, 0x20d1,
1026 "%s %d %8phC post gpdb\n",
1027 __func__, __LINE__, fcport->port_name);
Quinn Tran726b8542017-01-19 22:28:00 -08001028
1029 qla24xx_post_gpdb_work(vha, fcport, PDO_FORCE_ADISC);
1030 break;
1031
1032 default:
1033 break;
1034 }
1035
1036 return 0;
1037}
1038
1039static
1040void qla24xx_handle_rscn_event(fc_port_t *fcport, struct event_arg *ea)
1041{
1042 fcport->rscn_gen++;
1043
Quinn Tran83548fe2017-06-02 09:12:01 -07001044 ql_dbg(ql_dbg_disc, fcport->vha, 0x210c,
1045 "%s %8phC DS %d LS %d\n",
1046 __func__, fcport->port_name, fcport->disc_state,
1047 fcport->fw_login_state);
Quinn Tran726b8542017-01-19 22:28:00 -08001048
1049 if (fcport->flags & FCF_ASYNC_SENT)
1050 return;
1051
1052 switch (fcport->disc_state) {
1053 case DSC_DELETED:
1054 case DSC_LOGIN_COMPLETE:
Quinn Tran5ef696a2017-12-04 14:45:05 -08001055 qla24xx_post_gpnid_work(fcport->vha, &ea->id);
Quinn Tran726b8542017-01-19 22:28:00 -08001056 break;
Quinn Tran726b8542017-01-19 22:28:00 -08001057 default:
1058 break;
1059 }
1060}
1061
1062int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
1063 u8 *port_name, void *pla)
1064{
1065 struct qla_work_evt *e;
1066 e = qla2x00_alloc_work(vha, QLA_EVT_NEW_SESS);
1067 if (!e)
1068 return QLA_FUNCTION_FAILED;
1069
1070 e->u.new_sess.id = *id;
1071 e->u.new_sess.pla = pla;
1072 memcpy(e->u.new_sess.port_name, port_name, WWN_SIZE);
1073
1074 return qla2x00_post_work(vha, e);
1075}
1076
1077static
1078int qla24xx_handle_delete_done_event(scsi_qla_host_t *vha,
1079 struct event_arg *ea)
1080{
1081 fc_port_t *fcport = ea->fcport;
1082
1083 if (test_bit(UNLOADING, &vha->dpc_flags))
1084 return 0;
1085
1086 switch (vha->host->active_mode) {
1087 case MODE_INITIATOR:
1088 case MODE_DUAL:
1089 if (fcport->scan_state == QLA_FCPORT_FOUND)
1090 qla24xx_fcport_handle_login(vha, fcport);
1091 break;
1092
1093 case MODE_TARGET:
1094 default:
1095 /* no-op */
1096 break;
1097 }
1098
1099 return 0;
1100}
1101
1102static
1103void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
1104 struct event_arg *ea)
1105{
1106 fc_port_t *fcport = ea->fcport;
1107
1108 if (fcport->scan_state != QLA_FCPORT_FOUND) {
1109 fcport->login_retry++;
1110 return;
1111 }
1112
Quinn Tran83548fe2017-06-02 09:12:01 -07001113 ql_dbg(ql_dbg_disc, vha, 0x2102,
1114 "%s %8phC DS %d LS %d P %d del %d cnfl %p rscn %d|%d login %d|%d fl %x\n",
1115 __func__, fcport->port_name, fcport->disc_state,
1116 fcport->fw_login_state, fcport->login_pause,
1117 fcport->deleted, fcport->conflict,
1118 fcport->last_rscn_gen, fcport->rscn_gen,
1119 fcport->last_login_gen, fcport->login_gen,
1120 fcport->flags);
Quinn Tran726b8542017-01-19 22:28:00 -08001121
1122 if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
Quinn Tran726b8542017-01-19 22:28:00 -08001123 (fcport->fw_login_state == DSC_LS_PRLI_PEND))
1124 return;
1125
Quinn Tran5b334692017-03-15 09:48:48 -07001126 if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
1127 if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline))
1128 return;
1129 }
1130
Quinn Tran726b8542017-01-19 22:28:00 -08001131 if (fcport->flags & FCF_ASYNC_SENT) {
1132 fcport->login_retry++;
1133 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
1134 return;
1135 }
1136
1137 if (fcport->disc_state == DSC_DELETE_PEND) {
1138 fcport->login_retry++;
1139 return;
1140 }
1141
1142 if (fcport->last_rscn_gen != fcport->rscn_gen) {
Quinn Tran83548fe2017-06-02 09:12:01 -07001143 ql_dbg(ql_dbg_disc, vha, 0x20e9, "%s %d %8phC post gidpn\n",
Quinn Tran726b8542017-01-19 22:28:00 -08001144 __func__, __LINE__, fcport->port_name);
1145
1146 qla24xx_async_gidpn(vha, fcport);
1147 return;
1148 }
1149
1150 qla24xx_fcport_handle_login(vha, fcport);
1151}
1152
Quinn Tran41dc5292017-01-19 22:28:03 -08001153void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
Quinn Tran726b8542017-01-19 22:28:00 -08001154{
Quinn Tran41dc5292017-01-19 22:28:03 -08001155 fc_port_t *fcport, *f, *tf;
1156 uint32_t id = 0, mask, rid;
Quinn Tran726b8542017-01-19 22:28:00 -08001157 int rc;
1158
1159 switch (ea->event) {
1160 case FCME_RELOGIN:
Quinn Tranb98ae0d2017-06-02 09:12:00 -07001161 case FCME_RSCN:
1162 case FCME_GIDPN_DONE:
1163 case FCME_GPSC_DONE:
1164 case FCME_GPNID_DONE:
1165 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) ||
1166 test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))
1167 return;
1168 break;
1169 default:
1170 break;
1171 }
1172
1173 switch (ea->event) {
1174 case FCME_RELOGIN:
Quinn Tran726b8542017-01-19 22:28:00 -08001175 if (test_bit(UNLOADING, &vha->dpc_flags))
1176 return;
1177
1178 qla24xx_handle_relogin_event(vha, ea);
1179 break;
1180 case FCME_RSCN:
1181 if (test_bit(UNLOADING, &vha->dpc_flags))
1182 return;
Quinn Tran41dc5292017-01-19 22:28:03 -08001183 switch (ea->id.b.rsvd_1) {
1184 case RSCN_PORT_ADDR:
1185 fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
1186 if (!fcport) {
1187 /* cable moved */
1188 rc = qla24xx_post_gpnid_work(vha, &ea->id);
1189 if (rc) {
Quinn Tran83548fe2017-06-02 09:12:01 -07001190 ql_log(ql_log_warn, vha, 0xd044,
1191 "RSCN GPNID work failed %02x%02x%02x\n",
1192 ea->id.b.domain, ea->id.b.area,
1193 ea->id.b.al_pa);
Quinn Tran41dc5292017-01-19 22:28:03 -08001194 }
1195 } else {
1196 ea->fcport = fcport;
1197 qla24xx_handle_rscn_event(fcport, ea);
Quinn Tran726b8542017-01-19 22:28:00 -08001198 }
Quinn Tran41dc5292017-01-19 22:28:03 -08001199 break;
1200 case RSCN_AREA_ADDR:
1201 case RSCN_DOM_ADDR:
1202 if (ea->id.b.rsvd_1 == RSCN_AREA_ADDR) {
1203 mask = 0xffff00;
Quinn Tran83548fe2017-06-02 09:12:01 -07001204 ql_dbg(ql_dbg_async, vha, 0x5044,
1205 "RSCN: Area 0x%06x was affected\n",
1206 ea->id.b24);
Quinn Tran41dc5292017-01-19 22:28:03 -08001207 } else {
1208 mask = 0xff0000;
Quinn Tran83548fe2017-06-02 09:12:01 -07001209 ql_dbg(ql_dbg_async, vha, 0x507a,
1210 "RSCN: Domain 0x%06x was affected\n",
1211 ea->id.b24);
Quinn Tran41dc5292017-01-19 22:28:03 -08001212 }
1213
1214 rid = ea->id.b24 & mask;
1215 list_for_each_entry_safe(f, tf, &vha->vp_fcports,
1216 list) {
1217 id = f->d_id.b24 & mask;
1218 if (rid == id) {
1219 ea->fcport = f;
1220 qla24xx_handle_rscn_event(f, ea);
1221 }
1222 }
1223 break;
1224 case RSCN_FAB_ADDR:
1225 default:
Quinn Tran83548fe2017-06-02 09:12:01 -07001226 ql_log(ql_log_warn, vha, 0xd045,
1227 "RSCN: Fabric was affected. Addr format %d\n",
1228 ea->id.b.rsvd_1);
Quinn Tran41dc5292017-01-19 22:28:03 -08001229 qla2x00_mark_all_devices_lost(vha, 1);
1230 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
1231 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
Quinn Tran726b8542017-01-19 22:28:00 -08001232 }
1233 break;
1234 case FCME_GIDPN_DONE:
1235 qla24xx_handle_gidpn_event(vha, ea);
1236 break;
1237 case FCME_GNL_DONE:
1238 qla24xx_handle_gnl_done_event(vha, ea);
1239 break;
1240 case FCME_GPSC_DONE:
1241 qla24xx_post_upd_fcport_work(vha, ea->fcport);
1242 break;
1243 case FCME_PLOGI_DONE: /* Initiator side sent LLIOCB */
1244 qla24xx_handle_plogi_done_event(vha, ea);
1245 break;
Duane Grigsbya5d42f42017-06-21 13:48:41 -07001246 case FCME_PRLI_DONE:
1247 qla24xx_handle_prli_done_event(vha, ea);
1248 break;
Quinn Tran726b8542017-01-19 22:28:00 -08001249 case FCME_GPDB_DONE:
1250 qla24xx_handle_gpdb_event(vha, ea);
1251 break;
1252 case FCME_GPNID_DONE:
1253 qla24xx_handle_gpnid_event(vha, ea);
1254 break;
Duane Grigsbyd3bae932017-06-21 13:48:44 -07001255 case FCME_GFFID_DONE:
1256 qla24xx_handle_gffid_event(vha, ea);
1257 break;
Quinn Tran726b8542017-01-19 22:28:00 -08001258 case FCME_DELETE_DONE:
1259 qla24xx_handle_delete_done_event(vha, ea);
1260 break;
1261 default:
1262 BUG_ON(1);
1263 break;
1264 }
1265}
1266
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001267static void
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001268qla2x00_tmf_iocb_timeout(void *data)
1269{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001270 srb_t *sp = data;
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001271 struct srb_iocb *tmf = &sp->u.iocb_cmd;
1272
1273 tmf->u.tmf.comp_status = CS_TIMEOUT;
1274 complete(&tmf->u.tmf.comp);
1275}
1276
1277static void
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001278qla2x00_tmf_sp_done(void *ptr, int res)
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001279{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001280 srb_t *sp = ptr;
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001281 struct srb_iocb *tmf = &sp->u.iocb_cmd;
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001282
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001283 complete(&tmf->u.tmf.comp);
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001284}
1285
1286int
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001287qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001288 uint32_t tag)
1289{
1290 struct scsi_qla_host *vha = fcport->vha;
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001291 struct srb_iocb *tm_iocb;
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001292 srb_t *sp;
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001293 int rval = QLA_FUNCTION_FAILED;
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001294
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001295 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001296 if (!sp)
1297 goto done;
1298
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001299 tm_iocb = &sp->u.iocb_cmd;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001300 sp->type = SRB_TM_CMD;
1301 sp->name = "tmf";
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001302 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
1303 tm_iocb->u.tmf.flags = flags;
1304 tm_iocb->u.tmf.lun = lun;
1305 tm_iocb->u.tmf.data = tag;
1306 sp->done = qla2x00_tmf_sp_done;
1307 tm_iocb->timeout = qla2x00_tmf_iocb_timeout;
1308 init_completion(&tm_iocb->u.tmf.comp);
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001309
1310 rval = qla2x00_start_sp(sp);
1311 if (rval != QLA_SUCCESS)
1312 goto done_free_sp;
1313
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001314 ql_dbg(ql_dbg_taskm, vha, 0x802f,
Chad Dupuiscfb09192011-11-18 09:03:07 -08001315 "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
1316 sp->handle, fcport->loop_id, fcport->d_id.b.domain,
1317 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001318
1319 wait_for_completion(&tm_iocb->u.tmf.comp);
1320
1321 rval = tm_iocb->u.tmf.comp_status == CS_COMPLETE ?
1322 QLA_SUCCESS : QLA_FUNCTION_FAILED;
1323
1324 if ((rval != QLA_SUCCESS) || tm_iocb->u.tmf.data) {
1325 ql_dbg(ql_dbg_taskm, vha, 0x8030,
1326 "TM IOCB failed (%x).\n", rval);
1327 }
1328
1329 if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) {
1330 flags = tm_iocb->u.tmf.flags;
1331 lun = (uint16_t)tm_iocb->u.tmf.lun;
1332
1333 /* Issue Marker IOCB */
1334 qla2x00_marker(vha, vha->hw->req_q_map[0],
1335 vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun,
1336 flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
1337 }
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001338
1339done_free_sp:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001340 sp->free(sp);
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001341done:
1342 return rval;
1343}
1344
Armen Baloyan4440e462014-02-26 04:15:18 -05001345static void
1346qla24xx_abort_iocb_timeout(void *data)
1347{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001348 srb_t *sp = data;
Armen Baloyan4440e462014-02-26 04:15:18 -05001349 struct srb_iocb *abt = &sp->u.iocb_cmd;
1350
1351 abt->u.abt.comp_status = CS_TIMEOUT;
1352 complete(&abt->u.abt.comp);
1353}
1354
1355static void
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001356qla24xx_abort_sp_done(void *ptr, int res)
Armen Baloyan4440e462014-02-26 04:15:18 -05001357{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001358 srb_t *sp = ptr;
Armen Baloyan4440e462014-02-26 04:15:18 -05001359 struct srb_iocb *abt = &sp->u.iocb_cmd;
1360
1361 complete(&abt->u.abt.comp);
1362}
1363
Quinn Tran15f30a52017-03-15 09:48:52 -07001364int
Armen Baloyan4440e462014-02-26 04:15:18 -05001365qla24xx_async_abort_cmd(srb_t *cmd_sp)
1366{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001367 scsi_qla_host_t *vha = cmd_sp->vha;
Armen Baloyan4440e462014-02-26 04:15:18 -05001368 fc_port_t *fcport = cmd_sp->fcport;
1369 struct srb_iocb *abt_iocb;
1370 srb_t *sp;
1371 int rval = QLA_FUNCTION_FAILED;
1372
1373 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
1374 if (!sp)
1375 goto done;
1376
1377 abt_iocb = &sp->u.iocb_cmd;
1378 sp->type = SRB_ABT_CMD;
1379 sp->name = "abort";
1380 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
1381 abt_iocb->u.abt.cmd_hndl = cmd_sp->handle;
1382 sp->done = qla24xx_abort_sp_done;
1383 abt_iocb->timeout = qla24xx_abort_iocb_timeout;
1384 init_completion(&abt_iocb->u.abt.comp);
1385
1386 rval = qla2x00_start_sp(sp);
1387 if (rval != QLA_SUCCESS)
1388 goto done_free_sp;
1389
1390 ql_dbg(ql_dbg_async, vha, 0x507c,
1391 "Abort command issued - hdl=%x, target_id=%x\n",
1392 cmd_sp->handle, fcport->tgt_id);
1393
1394 wait_for_completion(&abt_iocb->u.abt.comp);
1395
1396 rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
1397 QLA_SUCCESS : QLA_FUNCTION_FAILED;
1398
1399done_free_sp:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001400 sp->free(sp);
Armen Baloyan4440e462014-02-26 04:15:18 -05001401done:
1402 return rval;
1403}
1404
1405int
1406qla24xx_async_abort_command(srb_t *sp)
1407{
1408 unsigned long flags = 0;
1409
1410 uint32_t handle;
1411 fc_port_t *fcport = sp->fcport;
1412 struct scsi_qla_host *vha = fcport->vha;
1413 struct qla_hw_data *ha = vha->hw;
1414 struct req_que *req = vha->req;
1415
1416 spin_lock_irqsave(&ha->hardware_lock, flags);
1417 for (handle = 1; handle < req->num_outstanding_cmds; handle++) {
1418 if (req->outstanding_cmds[handle] == sp)
1419 break;
1420 }
1421 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1422 if (handle == req->num_outstanding_cmds) {
1423 /* Command not found. */
1424 return QLA_FUNCTION_FAILED;
1425 }
1426 if (sp->type == SRB_FXIOCB_DCMD)
1427 return qlafx00_fx_disc(vha, &vha->hw->mr.fcport,
1428 FXDISC_ABORT_IOCTL);
1429
1430 return qla24xx_async_abort_cmd(sp);
1431}
1432
Quinn Tran726b8542017-01-19 22:28:00 -08001433static void
Duane Grigsbya5d42f42017-06-21 13:48:41 -07001434qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
1435{
1436 switch (ea->data[0]) {
1437 case MBS_COMMAND_COMPLETE:
1438 ql_dbg(ql_dbg_disc, vha, 0x2118,
1439 "%s %d %8phC post gpdb\n",
1440 __func__, __LINE__, ea->fcport->port_name);
1441
1442 ea->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
1443 ea->fcport->logout_on_delete = 1;
1444 qla24xx_post_gpdb_work(vha, ea->fcport, 0);
1445 break;
1446 default:
Duane Grigsbyedd05de2017-10-13 09:34:06 -07001447 if (ea->fcport->n2n_flag) {
1448 ql_dbg(ql_dbg_disc, vha, 0x2118,
1449 "%s %d %8phC post fc4 prli\n",
1450 __func__, __LINE__, ea->fcport->port_name);
1451 ea->fcport->fc4f_nvme = 0;
1452 ea->fcport->n2n_flag = 0;
1453 qla24xx_post_prli_work(vha, ea->fcport);
1454 }
Duane Grigsbya5d42f42017-06-21 13:48:41 -07001455 ql_dbg(ql_dbg_disc, vha, 0x2119,
1456 "%s %d %8phC unhandle event of %x\n",
1457 __func__, __LINE__, ea->fcport->port_name, ea->data[0]);
1458 break;
1459 }
1460}
1461
1462static void
Quinn Tran726b8542017-01-19 22:28:00 -08001463qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
Andrew Vasquezac280b62009-08-20 11:06:05 -07001464{
Quinn Tran726b8542017-01-19 22:28:00 -08001465 port_id_t cid; /* conflict Nport id */
Quinn Trana084fd62017-12-04 14:45:00 -08001466 u16 lid;
1467 struct fc_port *conflict_fcport;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001468
Quinn Tran726b8542017-01-19 22:28:00 -08001469 switch (ea->data[0]) {
Andrew Vasquezac280b62009-08-20 11:06:05 -07001470 case MBS_COMMAND_COMPLETE:
Andrew Vasqueza4f92a32011-03-30 11:46:31 -07001471 /*
1472 * Driver must validate login state - If PRLI not complete,
1473 * force a relogin attempt via implicit LOGO, PLOGI, and PRLI
1474 * requests.
1475 */
Duane Grigsbya5d42f42017-06-21 13:48:41 -07001476 if (ea->fcport->fc4f_nvme) {
1477 ql_dbg(ql_dbg_disc, vha, 0x2117,
1478 "%s %d %8phC post prli\n",
1479 __func__, __LINE__, ea->fcport->port_name);
1480 qla24xx_post_prli_work(vha, ea->fcport);
1481 } else {
1482 ql_dbg(ql_dbg_disc, vha, 0x20ea,
Quinn Trana084fd62017-12-04 14:45:00 -08001483 "%s %d %8phC LoopID 0x%x in use with %06x. post gnl\n",
1484 __func__, __LINE__, ea->fcport->port_name,
1485 ea->fcport->loop_id, ea->fcport->d_id.b24);
1486
1487 set_bit(ea->fcport->loop_id, vha->hw->loop_id_map);
1488 ea->fcport->loop_id = FC_NO_LOOP_ID;
Duane Grigsbya5d42f42017-06-21 13:48:41 -07001489 ea->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
1490 ea->fcport->logout_on_delete = 1;
Quinn Tran35158322017-08-30 10:16:50 -07001491 ea->fcport->send_els_logo = 0;
Duane Grigsbya5d42f42017-06-21 13:48:41 -07001492 qla24xx_post_gpdb_work(vha, ea->fcport, 0);
1493 }
Andrew Vasquezac280b62009-08-20 11:06:05 -07001494 break;
1495 case MBS_COMMAND_ERROR:
Quinn Tran83548fe2017-06-02 09:12:01 -07001496 ql_dbg(ql_dbg_disc, vha, 0x20eb, "%s %d %8phC cmd error %x\n",
Quinn Tran726b8542017-01-19 22:28:00 -08001497 __func__, __LINE__, ea->fcport->port_name, ea->data[1]);
1498
1499 ea->fcport->flags &= ~FCF_ASYNC_SENT;
1500 ea->fcport->disc_state = DSC_LOGIN_FAILED;
1501 if (ea->data[1] & QLA_LOGIO_LOGIN_RETRIED)
Andrew Vasquezac280b62009-08-20 11:06:05 -07001502 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
1503 else
Quinn Tran726b8542017-01-19 22:28:00 -08001504 qla2x00_mark_device_lost(vha, ea->fcport, 1, 0);
Andrew Vasquezac280b62009-08-20 11:06:05 -07001505 break;
1506 case MBS_LOOP_ID_USED:
Quinn Tran726b8542017-01-19 22:28:00 -08001507 /* data[1] = IO PARAM 1 = nport ID */
1508 cid.b.domain = (ea->iop[1] >> 16) & 0xff;
1509 cid.b.area = (ea->iop[1] >> 8) & 0xff;
1510 cid.b.al_pa = ea->iop[1] & 0xff;
1511 cid.b.rsvd_1 = 0;
1512
Quinn Tran83548fe2017-06-02 09:12:01 -07001513 ql_dbg(ql_dbg_disc, vha, 0x20ec,
1514 "%s %d %8phC LoopID 0x%x in use post gnl\n",
1515 __func__, __LINE__, ea->fcport->port_name,
1516 ea->fcport->loop_id);
Quinn Tran726b8542017-01-19 22:28:00 -08001517
1518 if (IS_SW_RESV_ADDR(cid)) {
1519 set_bit(ea->fcport->loop_id, vha->hw->loop_id_map);
1520 ea->fcport->loop_id = FC_NO_LOOP_ID;
1521 } else {
1522 qla2x00_clear_loop_id(ea->fcport);
Andrew Vasquezac280b62009-08-20 11:06:05 -07001523 }
Quinn Tran726b8542017-01-19 22:28:00 -08001524 qla24xx_post_gnl_work(vha, ea->fcport);
1525 break;
1526 case MBS_PORT_ID_USED:
Quinn Tran83548fe2017-06-02 09:12:01 -07001527 ql_dbg(ql_dbg_disc, vha, 0x20ed,
1528 "%s %d %8phC NPortId %02x%02x%02x inuse post gidpn\n",
1529 __func__, __LINE__, ea->fcport->port_name,
1530 ea->fcport->d_id.b.domain, ea->fcport->d_id.b.area,
1531 ea->fcport->d_id.b.al_pa);
Quinn Tran726b8542017-01-19 22:28:00 -08001532
Quinn Trana084fd62017-12-04 14:45:00 -08001533 lid = ea->iop[1] & 0xffff;
1534 qlt_find_sess_invalidate_other(vha,
1535 wwn_to_u64(ea->fcport->port_name),
1536 ea->fcport->d_id, lid, &conflict_fcport);
1537
1538 if (conflict_fcport) {
1539 /*
1540 * Another fcport share the same loop_id/nport id.
1541 * Conflict fcport needs to finish cleanup before this
1542 * fcport can proceed to login.
1543 */
1544 conflict_fcport->conflict = ea->fcport;
1545 ea->fcport->login_pause = 1;
1546
1547 ql_dbg(ql_dbg_disc, vha, 0x20ed,
1548 "%s %d %8phC NPortId %06x inuse with loopid 0x%x. post gidpn\n",
1549 __func__, __LINE__, ea->fcport->port_name,
1550 ea->fcport->d_id.b24, lid);
1551 qla2x00_clear_loop_id(ea->fcport);
1552 qla24xx_post_gidpn_work(vha, ea->fcport);
1553 } else {
1554 ql_dbg(ql_dbg_disc, vha, 0x20ed,
1555 "%s %d %8phC NPortId %06x inuse with loopid 0x%x. sched delete\n",
1556 __func__, __LINE__, ea->fcport->port_name,
1557 ea->fcport->d_id.b24, lid);
1558
1559 qla2x00_clear_loop_id(ea->fcport);
1560 set_bit(lid, vha->hw->loop_id_map);
1561 ea->fcport->loop_id = lid;
1562 ea->fcport->keep_nport_handle = 0;
1563 qlt_schedule_sess_for_deletion(ea->fcport, false);
1564 }
Andrew Vasquezac280b62009-08-20 11:06:05 -07001565 break;
1566 }
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001567 return;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001568}
1569
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001570void
Andrew Vasquezac280b62009-08-20 11:06:05 -07001571qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
1572 uint16_t *data)
1573{
Quinn Tran726b8542017-01-19 22:28:00 -08001574 qla2x00_mark_device_lost(vha, fcport, 1, 0);
Alexei Potashnika6ca8872015-07-14 16:00:44 -04001575 qlt_logo_completion_handler(fcport, data[0]);
Quinn Tran726b8542017-01-19 22:28:00 -08001576 fcport->login_gen++;
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001577 return;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001578}
1579
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001580void
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001581qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
1582 uint16_t *data)
1583{
1584 if (data[0] == MBS_COMMAND_COMPLETE) {
1585 qla2x00_update_fcport(vha, fcport);
1586
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001587 return;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001588 }
1589
1590 /* Retry login. */
1591 fcport->flags &= ~FCF_ASYNC_SENT;
1592 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
1593 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
1594 else
Andrew Vasquez80d79442011-03-30 11:46:17 -07001595 qla2x00_mark_device_lost(vha, fcport, 1, 0);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001596
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001597 return;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001598}
1599
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600/****************************************************************************/
1601/* QLogic ISP2x00 Hardware Support Functions. */
1602/****************************************************************************/
1603
Saurav Kashyapfa492632012-11-21 02:40:29 -05001604static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04001605qla83xx_nic_core_fw_load(scsi_qla_host_t *vha)
1606{
1607 int rval = QLA_SUCCESS;
1608 struct qla_hw_data *ha = vha->hw;
1609 uint32_t idc_major_ver, idc_minor_ver;
Saurav Kashyap711aa7f2012-08-22 14:21:15 -04001610 uint16_t config[4];
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04001611
1612 qla83xx_idc_lock(vha, 0);
1613
1614 /* SV: TODO: Assign initialization timeout from
1615 * flash-info / other param
1616 */
1617 ha->fcoe_dev_init_timeout = QLA83XX_IDC_INITIALIZATION_TIMEOUT;
1618 ha->fcoe_reset_timeout = QLA83XX_IDC_RESET_ACK_TIMEOUT;
1619
1620 /* Set our fcoe function presence */
1621 if (__qla83xx_set_drv_presence(vha) != QLA_SUCCESS) {
1622 ql_dbg(ql_dbg_p3p, vha, 0xb077,
1623 "Error while setting DRV-Presence.\n");
1624 rval = QLA_FUNCTION_FAILED;
1625 goto exit;
1626 }
1627
1628 /* Decide the reset ownership */
1629 qla83xx_reset_ownership(vha);
1630
1631 /*
1632 * On first protocol driver load:
1633 * Init-Owner: Set IDC-Major-Version and Clear IDC-Lock-Recovery
1634 * register.
1635 * Others: Check compatibility with current IDC Major version.
1636 */
1637 qla83xx_rd_reg(vha, QLA83XX_IDC_MAJOR_VERSION, &idc_major_ver);
1638 if (ha->flags.nic_core_reset_owner) {
1639 /* Set IDC Major version */
1640 idc_major_ver = QLA83XX_SUPP_IDC_MAJOR_VERSION;
1641 qla83xx_wr_reg(vha, QLA83XX_IDC_MAJOR_VERSION, idc_major_ver);
1642
1643 /* Clearing IDC-Lock-Recovery register */
1644 qla83xx_wr_reg(vha, QLA83XX_IDC_LOCK_RECOVERY, 0);
1645 } else if (idc_major_ver != QLA83XX_SUPP_IDC_MAJOR_VERSION) {
1646 /*
1647 * Clear further IDC participation if we are not compatible with
1648 * the current IDC Major Version.
1649 */
1650 ql_log(ql_log_warn, vha, 0xb07d,
1651 "Failing load, idc_major_ver=%d, expected_major_ver=%d.\n",
1652 idc_major_ver, QLA83XX_SUPP_IDC_MAJOR_VERSION);
1653 __qla83xx_clear_drv_presence(vha);
1654 rval = QLA_FUNCTION_FAILED;
1655 goto exit;
1656 }
1657 /* Each function sets its supported Minor version. */
1658 qla83xx_rd_reg(vha, QLA83XX_IDC_MINOR_VERSION, &idc_minor_ver);
1659 idc_minor_ver |= (QLA83XX_SUPP_IDC_MINOR_VERSION << (ha->portnum * 2));
1660 qla83xx_wr_reg(vha, QLA83XX_IDC_MINOR_VERSION, idc_minor_ver);
1661
Saurav Kashyap711aa7f2012-08-22 14:21:15 -04001662 if (ha->flags.nic_core_reset_owner) {
1663 memset(config, 0, sizeof(config));
1664 if (!qla81xx_get_port_config(vha, config))
1665 qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE,
1666 QLA8XXX_DEV_READY);
1667 }
1668
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04001669 rval = qla83xx_idc_state_handler(vha);
1670
1671exit:
1672 qla83xx_idc_unlock(vha, 0);
1673
1674 return rval;
1675}
1676
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677/*
1678* qla2x00_initialize_adapter
1679* Initialize board.
1680*
1681* Input:
1682* ha = adapter block pointer.
1683*
1684* Returns:
1685* 0 = success
1686*/
1687int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001688qla2x00_initialize_adapter(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689{
1690 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001691 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001692 struct req_que *req = ha->req_q_map[0];
Lalit Chandivade2533cf62009-03-24 09:08:07 -07001693
Joe Carnucciofc90ada2016-07-06 11:14:23 -04001694 memset(&vha->qla_stats, 0, sizeof(vha->qla_stats));
1695 memset(&vha->fc_host_stat, 0, sizeof(vha->fc_host_stat));
1696
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 /* Clear adapter flags. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001698 vha->flags.online = 0;
Lalit Chandivade2533cf62009-03-24 09:08:07 -07001699 ha->flags.chip_reset_done = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001700 vha->flags.reset_active = 0;
Andrew Vasquez85880802009-12-15 21:29:46 -08001701 ha->flags.pci_channel_io_perm_failure = 0;
1702 ha->flags.eeh_busy = 0;
Joe Carnucciofabbb8d2013-08-27 01:37:40 -04001703 vha->qla_stats.jiffies_at_last_reset = get_jiffies_64();
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001704 atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
1705 atomic_set(&vha->loop_state, LOOP_DOWN);
1706 vha->device_flags = DFLG_NO_CABLE;
1707 vha->dpc_flags = 0;
1708 vha->flags.management_server_logged_in = 0;
1709 vha->marker_needed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 ha->isp_abort_cnt = 0;
1711 ha->beacon_blink_led = 0;
1712
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001713 set_bit(0, ha->req_qid_map);
1714 set_bit(0, ha->rsp_qid_map);
1715
Chad Dupuiscfb09192011-11-18 09:03:07 -08001716 ql_dbg(ql_dbg_init, vha, 0x0040,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001717 "Configuring PCI space...\n");
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001718 rval = ha->isp_ops->pci_config(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001720 ql_log(ql_log_warn, vha, 0x0044,
1721 "Unable to configure PCI space.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 return (rval);
1723 }
1724
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001725 ha->isp_ops->reset_chip(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001727 rval = qla2xxx_get_flash_info(vha);
Andrew Vasquezc00d8992008-09-11 21:22:49 -07001728 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001729 ql_log(ql_log_fatal, vha, 0x004f,
1730 "Unable to validate FLASH data.\n");
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04001731 return rval;
1732 }
1733
1734 if (IS_QLA8044(ha)) {
1735 qla8044_read_reset_template(vha);
1736
1737 /* NOTE: If ql2xdontresethba==1, set IDC_CTRL DONTRESET_BIT0.
1738 * If DONRESET_BIT0 is set, drivers should not set dev_state
1739 * to NEED_RESET. But if NEED_RESET is set, drivers should
1740 * should honor the reset. */
1741 if (ql2xdontresethba == 1)
1742 qla8044_set_idc_dontreset(vha);
Andrew Vasquezc00d8992008-09-11 21:22:49 -07001743 }
1744
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001745 ha->isp_ops->get_flash_version(vha, req->ring);
Chad Dupuiscfb09192011-11-18 09:03:07 -08001746 ql_dbg(ql_dbg_init, vha, 0x0061,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001747 "Configure NVRAM parameters...\n");
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001748
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001749 ha->isp_ops->nvram_config(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750
Andrew Vasquezd4c760c2006-06-23 16:10:39 -07001751 if (ha->flags.disable_serdes) {
1752 /* Mask HBA via NVRAM settings? */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001753 ql_log(ql_log_info, vha, 0x0077,
Oleksandr Khoshaba7b8335582013-08-27 01:37:27 -04001754 "Masking HBA WWPN %8phN (via NVRAM).\n", vha->port_name);
Andrew Vasquezd4c760c2006-06-23 16:10:39 -07001755 return QLA_FUNCTION_FAILED;
1756 }
1757
Chad Dupuiscfb09192011-11-18 09:03:07 -08001758 ql_dbg(ql_dbg_init, vha, 0x0078,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001759 "Verifying loaded RISC code...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001761 if (qla2x00_isp_firmware(vha) != QLA_SUCCESS) {
1762 rval = ha->isp_ops->chip_diag(vha);
Andrew Vasquezd19044c2006-11-22 08:22:19 -08001763 if (rval)
1764 return (rval);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001765 rval = qla2x00_setup_chip(vha);
Andrew Vasquezd19044c2006-11-22 08:22:19 -08001766 if (rval)
1767 return (rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 }
Giridhar Malavalia9083012010-04-12 17:59:55 -07001769
Harihara Kadayam4d4df192008-04-03 13:13:26 -07001770 if (IS_QLA84XX(ha)) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001771 ha->cs84xx = qla84xx_get_chip(vha);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07001772 if (!ha->cs84xx) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001773 ql_log(ql_log_warn, vha, 0x00d0,
Harihara Kadayam4d4df192008-04-03 13:13:26 -07001774 "Unable to configure ISP84XX.\n");
1775 return QLA_FUNCTION_FAILED;
1776 }
1777 }
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04001778
Quinn Tranead03852017-01-19 22:28:01 -08001779 if (qla_ini_mode_enabled(vha) || qla_dual_mode_enabled(vha))
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04001780 rval = qla2x00_init_rings(vha);
1781
Lalit Chandivade2533cf62009-03-24 09:08:07 -07001782 ha->flags.chip_reset_done = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001784 if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) {
Andrew Vasquez6c452a42010-03-19 17:04:02 -07001785 /* Issue verify 84xx FW IOCB to complete 84xx initialization */
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001786 rval = qla84xx_init_chip(vha);
1787 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001788 ql_log(ql_log_warn, vha, 0x00d4,
1789 "Unable to initialize ISP84XX.\n");
Bart Van Assche8d2b21d2015-06-04 15:58:09 -07001790 qla84xx_put_chip(vha);
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001791 }
1792 }
1793
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04001794 /* Load the NIC Core f/w if we are the first protocol driver. */
1795 if (IS_QLA8031(ha)) {
1796 rval = qla83xx_nic_core_fw_load(vha);
1797 if (rval)
1798 ql_log(ql_log_warn, vha, 0x0124,
1799 "Error in initializing NIC Core f/w.\n");
1800 }
1801
Madhuranath Iyengar2f0f3f42010-07-23 15:28:24 +05001802 if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))
1803 qla24xx_read_fcp_prio_cfg(vha);
Sarang Radke09ff7012010-03-19 17:03:59 -07001804
Joe Carnuccioc46e65c2013-08-27 01:37:35 -04001805 if (IS_P3P_TYPE(ha))
1806 qla82xx_set_driver_version(vha, QLA2XXX_VERSION);
1807 else
1808 qla25xx_set_driver_version(vha, QLA2XXX_VERSION);
1809
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 return (rval);
1811}
1812
1813/**
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001814 * qla2100_pci_config() - Setup ISP21xx PCI configuration registers.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 * @ha: HA context
1816 *
1817 * Returns 0 on success.
1818 */
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001819int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001820qla2100_pci_config(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821{
Andrew Vasqueza157b102007-05-07 07:43:01 -07001822 uint16_t w;
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001823 unsigned long flags;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001824 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07001825 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 pci_set_master(ha->pdev);
Andrew Vasquezaf6177d2007-07-19 15:06:02 -07001828 pci_try_set_mwi(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
Andrew Vasqueza157b102007-05-07 07:43:01 -07001831 w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 pci_write_config_word(ha->pdev, PCI_COMMAND, w);
1833
Andrew Vasquez737faec2008-10-24 15:13:45 -07001834 pci_disable_rom(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001836 /* Get PCI bus information. */
1837 spin_lock_irqsave(&ha->hardware_lock, flags);
Andrew Vasquez3d716442005-07-06 10:30:26 -07001838 ha->pci_attr = RD_REG_WORD(&reg->ctrl_status);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001839 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1840
1841 return QLA_SUCCESS;
1842}
1843
1844/**
1845 * qla2300_pci_config() - Setup ISP23xx PCI configuration registers.
1846 * @ha: HA context
1847 *
1848 * Returns 0 on success.
1849 */
1850int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001851qla2300_pci_config(scsi_qla_host_t *vha)
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001852{
Andrew Vasqueza157b102007-05-07 07:43:01 -07001853 uint16_t w;
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001854 unsigned long flags = 0;
1855 uint32_t cnt;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001856 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07001857 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001858
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001859 pci_set_master(ha->pdev);
Andrew Vasquezaf6177d2007-07-19 15:06:02 -07001860 pci_try_set_mwi(ha->pdev);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001861
1862 pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
Andrew Vasqueza157b102007-05-07 07:43:01 -07001863 w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001864
1865 if (IS_QLA2322(ha) || IS_QLA6322(ha))
1866 w &= ~PCI_COMMAND_INTX_DISABLE;
Andrew Vasqueza157b102007-05-07 07:43:01 -07001867 pci_write_config_word(ha->pdev, PCI_COMMAND, w);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001868
1869 /*
1870 * If this is a 2300 card and not 2312, reset the
1871 * COMMAND_INVALIDATE due to a bug in the 2300. Unfortunately,
1872 * the 2310 also reports itself as a 2300 so we need to get the
1873 * fb revision level -- a 6 indicates it really is a 2300 and
1874 * not a 2310.
1875 */
1876 if (IS_QLA2300(ha)) {
1877 spin_lock_irqsave(&ha->hardware_lock, flags);
1878
1879 /* Pause RISC. */
Andrew Vasquez3d716442005-07-06 10:30:26 -07001880 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001881 for (cnt = 0; cnt < 30000; cnt++) {
Andrew Vasquez3d716442005-07-06 10:30:26 -07001882 if ((RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) != 0)
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001883 break;
1884
1885 udelay(10);
1886 }
1887
1888 /* Select FPM registers. */
Andrew Vasquez3d716442005-07-06 10:30:26 -07001889 WRT_REG_WORD(&reg->ctrl_status, 0x20);
1890 RD_REG_WORD(&reg->ctrl_status);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001891
1892 /* Get the fb rev level */
Andrew Vasquez3d716442005-07-06 10:30:26 -07001893 ha->fb_rev = RD_FB_CMD_REG(ha, reg);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001894
1895 if (ha->fb_rev == FPM_2300)
Andrew Vasqueza157b102007-05-07 07:43:01 -07001896 pci_clear_mwi(ha->pdev);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001897
1898 /* Deselect FPM registers. */
Andrew Vasquez3d716442005-07-06 10:30:26 -07001899 WRT_REG_WORD(&reg->ctrl_status, 0x0);
1900 RD_REG_WORD(&reg->ctrl_status);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001901
1902 /* Release RISC module. */
Andrew Vasquez3d716442005-07-06 10:30:26 -07001903 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001904 for (cnt = 0; cnt < 30000; cnt++) {
Andrew Vasquez3d716442005-07-06 10:30:26 -07001905 if ((RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0)
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001906 break;
1907
1908 udelay(10);
1909 }
1910
1911 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1912 }
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001913
1914 pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
1915
Andrew Vasquez737faec2008-10-24 15:13:45 -07001916 pci_disable_rom(ha->pdev);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001917
1918 /* Get PCI bus information. */
1919 spin_lock_irqsave(&ha->hardware_lock, flags);
Andrew Vasquez3d716442005-07-06 10:30:26 -07001920 ha->pci_attr = RD_REG_WORD(&reg->ctrl_status);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07001921 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1922
1923 return QLA_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924}
1925
1926/**
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001927 * qla24xx_pci_config() - Setup ISP24xx PCI configuration registers.
1928 * @ha: HA context
1929 *
1930 * Returns 0 on success.
1931 */
1932int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001933qla24xx_pci_config(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001934{
Andrew Vasqueza157b102007-05-07 07:43:01 -07001935 uint16_t w;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001936 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001937 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001938 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001939
1940 pci_set_master(ha->pdev);
Andrew Vasquezaf6177d2007-07-19 15:06:02 -07001941 pci_try_set_mwi(ha->pdev);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001942
1943 pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
Andrew Vasqueza157b102007-05-07 07:43:01 -07001944 w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001945 w &= ~PCI_COMMAND_INTX_DISABLE;
1946 pci_write_config_word(ha->pdev, PCI_COMMAND, w);
1947
1948 pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
1949
1950 /* PCI-X -- adjust Maximum Memory Read Byte Count (2048). */
Andrew Vasquezf85ec182007-07-19 15:06:01 -07001951 if (pci_find_capability(ha->pdev, PCI_CAP_ID_PCIX))
1952 pcix_set_mmrbc(ha->pdev, 2048);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001953
1954 /* PCIe -- adjust Maximum Read Request Size (2048). */
Jon Masone67f1322012-07-10 14:57:56 -07001955 if (pci_is_pcie(ha->pdev))
Chad Dupuis5ffd3a52012-08-22 14:21:26 -04001956 pcie_set_readrq(ha->pdev, 4096);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001957
Andrew Vasquez737faec2008-10-24 15:13:45 -07001958 pci_disable_rom(ha->pdev);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001959
Auke Kok44c10132007-06-08 15:46:36 -07001960 ha->chip_revision = ha->pdev->revision;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08001961
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001962 /* Get PCI bus information. */
1963 spin_lock_irqsave(&ha->hardware_lock, flags);
1964 ha->pci_attr = RD_REG_DWORD(&reg->ctrl_status);
1965 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1966
1967 return QLA_SUCCESS;
1968}
1969
1970/**
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001971 * qla25xx_pci_config() - Setup ISP25xx PCI configuration registers.
1972 * @ha: HA context
1973 *
1974 * Returns 0 on success.
1975 */
1976int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001977qla25xx_pci_config(scsi_qla_host_t *vha)
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001978{
1979 uint16_t w;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001980 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001981
1982 pci_set_master(ha->pdev);
1983 pci_try_set_mwi(ha->pdev);
1984
1985 pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
1986 w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
1987 w &= ~PCI_COMMAND_INTX_DISABLE;
1988 pci_write_config_word(ha->pdev, PCI_COMMAND, w);
1989
1990 /* PCIe -- adjust Maximum Read Request Size (2048). */
Jon Masone67f1322012-07-10 14:57:56 -07001991 if (pci_is_pcie(ha->pdev))
Chad Dupuis5ffd3a52012-08-22 14:21:26 -04001992 pcie_set_readrq(ha->pdev, 4096);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001993
Andrew Vasquez737faec2008-10-24 15:13:45 -07001994 pci_disable_rom(ha->pdev);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001995
1996 ha->chip_revision = ha->pdev->revision;
1997
1998 return QLA_SUCCESS;
1999}
2000
2001/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 * qla2x00_isp_firmware() - Choose firmware image.
2003 * @ha: HA context
2004 *
2005 * Returns 0 on success.
2006 */
2007static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002008qla2x00_isp_firmware(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009{
2010 int rval;
Andrew Vasquez42e421b2008-07-10 16:56:01 -07002011 uint16_t loop_id, topo, sw_cap;
2012 uint8_t domain, area, al_pa;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002013 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014
2015 /* Assume loading risc code */
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07002016 rval = QLA_FUNCTION_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017
2018 if (ha->flags.disable_risc_code_load) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002019 ql_log(ql_log_info, vha, 0x0079, "RISC CODE NOT loaded.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020
2021 /* Verify checksum of loaded RISC code. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002022 rval = qla2x00_verify_checksum(vha, ha->fw_srisc_address);
Andrew Vasquez42e421b2008-07-10 16:56:01 -07002023 if (rval == QLA_SUCCESS) {
2024 /* And, verify we are not in ROM code. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002025 rval = qla2x00_get_adapter_id(vha, &loop_id, &al_pa,
Andrew Vasquez42e421b2008-07-10 16:56:01 -07002026 &area, &domain, &topo, &sw_cap);
2027 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 }
2029
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002030 if (rval)
2031 ql_dbg(ql_dbg_init, vha, 0x007a,
2032 "**** Load RISC code ****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033
2034 return (rval);
2035}
2036
2037/**
2038 * qla2x00_reset_chip() - Reset ISP chip.
2039 * @ha: HA context
2040 *
2041 * Returns 0 on success.
2042 */
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002043void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002044qla2x00_reset_chip(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045{
2046 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002047 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07002048 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049 uint32_t cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 uint16_t cmd;
2051
Andrew Vasquez85880802009-12-15 21:29:46 -08002052 if (unlikely(pci_channel_offline(ha->pdev)))
2053 return;
2054
Andrew Vasquezfd34f552007-07-19 15:06:00 -07002055 ha->isp_ops->disable_intrs(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056
2057 spin_lock_irqsave(&ha->hardware_lock, flags);
2058
2059 /* Turn off master enable */
2060 cmd = 0;
2061 pci_read_config_word(ha->pdev, PCI_COMMAND, &cmd);
2062 cmd &= ~PCI_COMMAND_MASTER;
2063 pci_write_config_word(ha->pdev, PCI_COMMAND, cmd);
2064
2065 if (!IS_QLA2100(ha)) {
2066 /* Pause RISC. */
2067 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
2068 if (IS_QLA2200(ha) || IS_QLA2300(ha)) {
2069 for (cnt = 0; cnt < 30000; cnt++) {
2070 if ((RD_REG_WORD(&reg->hccr) &
2071 HCCR_RISC_PAUSE) != 0)
2072 break;
2073 udelay(100);
2074 }
2075 } else {
2076 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
2077 udelay(10);
2078 }
2079
2080 /* Select FPM registers. */
2081 WRT_REG_WORD(&reg->ctrl_status, 0x20);
2082 RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
2083
2084 /* FPM Soft Reset. */
2085 WRT_REG_WORD(&reg->fpm_diag_config, 0x100);
2086 RD_REG_WORD(&reg->fpm_diag_config); /* PCI Posting. */
2087
2088 /* Toggle Fpm Reset. */
2089 if (!IS_QLA2200(ha)) {
2090 WRT_REG_WORD(&reg->fpm_diag_config, 0x0);
2091 RD_REG_WORD(&reg->fpm_diag_config); /* PCI Posting. */
2092 }
2093
2094 /* Select frame buffer registers. */
2095 WRT_REG_WORD(&reg->ctrl_status, 0x10);
2096 RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
2097
2098 /* Reset frame buffer FIFOs. */
2099 if (IS_QLA2200(ha)) {
2100 WRT_FB_CMD_REG(ha, reg, 0xa000);
2101 RD_FB_CMD_REG(ha, reg); /* PCI Posting. */
2102 } else {
2103 WRT_FB_CMD_REG(ha, reg, 0x00fc);
2104
2105 /* Read back fb_cmd until zero or 3 seconds max */
2106 for (cnt = 0; cnt < 3000; cnt++) {
2107 if ((RD_FB_CMD_REG(ha, reg) & 0xff) == 0)
2108 break;
2109 udelay(100);
2110 }
2111 }
2112
2113 /* Select RISC module registers. */
2114 WRT_REG_WORD(&reg->ctrl_status, 0);
2115 RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
2116
2117 /* Reset RISC processor. */
2118 WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
2119 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
2120
2121 /* Release RISC processor. */
2122 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
2123 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
2124 }
2125
2126 WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
2127 WRT_REG_WORD(&reg->hccr, HCCR_CLR_HOST_INT);
2128
2129 /* Reset ISP chip. */
2130 WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
2131
2132 /* Wait for RISC to recover from reset. */
2133 if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
2134 /*
2135 * It is necessary to for a delay here since the card doesn't
2136 * respond to PCI reads during a reset. On some architectures
2137 * this will result in an MCA.
2138 */
2139 udelay(20);
2140 for (cnt = 30000; cnt; cnt--) {
2141 if ((RD_REG_WORD(&reg->ctrl_status) &
2142 CSR_ISP_SOFT_RESET) == 0)
2143 break;
2144 udelay(100);
2145 }
2146 } else
2147 udelay(10);
2148
2149 /* Reset RISC processor. */
2150 WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
2151
2152 WRT_REG_WORD(&reg->semaphore, 0);
2153
2154 /* Release RISC processor. */
2155 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
2156 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
2157
2158 if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
2159 for (cnt = 0; cnt < 30000; cnt++) {
Andrew Vasquezffb39f02006-05-17 15:09:06 -07002160 if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162
2163 udelay(100);
2164 }
2165 } else
2166 udelay(100);
2167
2168 /* Turn on master enable */
2169 cmd |= PCI_COMMAND_MASTER;
2170 pci_write_config_word(ha->pdev, PCI_COMMAND, cmd);
2171
2172 /* Disable RISC pause on FPM parity error. */
2173 if (!IS_QLA2100(ha)) {
2174 WRT_REG_WORD(&reg->hccr, HCCR_DISABLE_PARITY_PAUSE);
2175 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
2176 }
2177
2178 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2179}
2180
2181/**
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07002182 * qla81xx_reset_mpi() - Reset's MPI FW via Write MPI Register MBC.
2183 *
2184 * Returns 0 on success.
2185 */
Saurav Kashyapfa492632012-11-21 02:40:29 -05002186static int
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07002187qla81xx_reset_mpi(scsi_qla_host_t *vha)
2188{
2189 uint16_t mb[4] = {0x1010, 0, 1, 0};
2190
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08002191 if (!IS_QLA81XX(vha->hw))
2192 return QLA_SUCCESS;
2193
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07002194 return qla81xx_write_mpi_register(vha, mb);
2195}
2196
2197/**
Andrew Vasquez88c26662005-07-08 17:59:26 -07002198 * qla24xx_reset_risc() - Perform full reset of ISP24xx RISC.
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002199 * @ha: HA context
2200 *
2201 * Returns 0 on success.
2202 */
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002203static inline int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002204qla24xx_reset_risc(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002205{
2206 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002207 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002208 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
Bart Van Assche52c82822015-07-09 07:23:26 -07002209 uint32_t cnt;
Andrew Vasquez335a1cc2005-11-08 14:37:48 -08002210 uint16_t wd;
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07002211 static int abts_cnt; /* ISP abort retry counts */
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002212 int rval = QLA_SUCCESS;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002213
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002214 spin_lock_irqsave(&ha->hardware_lock, flags);
2215
2216 /* Reset RISC. */
2217 WRT_REG_DWORD(&reg->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
2218 for (cnt = 0; cnt < 30000; cnt++) {
2219 if ((RD_REG_DWORD(&reg->ctrl_status) & CSRX_DMA_ACTIVE) == 0)
2220 break;
2221
2222 udelay(10);
2223 }
2224
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002225 if (!(RD_REG_DWORD(&reg->ctrl_status) & CSRX_DMA_ACTIVE))
2226 set_bit(DMA_SHUTDOWN_CMPL, &ha->fw_dump_cap_flags);
2227
2228 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x017e,
2229 "HCCR: 0x%x, Control Status %x, DMA active status:0x%x\n",
2230 RD_REG_DWORD(&reg->hccr),
2231 RD_REG_DWORD(&reg->ctrl_status),
2232 (RD_REG_DWORD(&reg->ctrl_status) & CSRX_DMA_ACTIVE));
2233
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002234 WRT_REG_DWORD(&reg->ctrl_status,
2235 CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
Andrew Vasquez335a1cc2005-11-08 14:37:48 -08002236 pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
Andrew Vasquez88c26662005-07-08 17:59:26 -07002237
Andrew Vasquez335a1cc2005-11-08 14:37:48 -08002238 udelay(100);
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002239
Andrew Vasquez88c26662005-07-08 17:59:26 -07002240 /* Wait for firmware to complete NVRAM accesses. */
Bart Van Assche52c82822015-07-09 07:23:26 -07002241 RD_REG_WORD(&reg->mailbox0);
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002242 for (cnt = 10000; RD_REG_WORD(&reg->mailbox0) != 0 &&
2243 rval == QLA_SUCCESS; cnt--) {
Andrew Vasquez88c26662005-07-08 17:59:26 -07002244 barrier();
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002245 if (cnt)
2246 udelay(5);
2247 else
2248 rval = QLA_FUNCTION_TIMEOUT;
Andrew Vasquez88c26662005-07-08 17:59:26 -07002249 }
2250
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002251 if (rval == QLA_SUCCESS)
2252 set_bit(ISP_MBX_RDY, &ha->fw_dump_cap_flags);
2253
2254 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x017f,
2255 "HCCR: 0x%x, MailBox0 Status 0x%x\n",
2256 RD_REG_DWORD(&reg->hccr),
2257 RD_REG_DWORD(&reg->mailbox0));
2258
Andrew Vasquez335a1cc2005-11-08 14:37:48 -08002259 /* Wait for soft-reset to complete. */
Bart Van Assche52c82822015-07-09 07:23:26 -07002260 RD_REG_DWORD(&reg->ctrl_status);
Quinn Tran200ffb12016-12-23 18:06:12 -08002261 for (cnt = 0; cnt < 60; cnt++) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002262 barrier();
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002263 if ((RD_REG_DWORD(&reg->ctrl_status) &
2264 CSRX_ISP_SOFT_RESET) == 0)
2265 break;
2266
2267 udelay(5);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002268 }
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002269 if (!(RD_REG_DWORD(&reg->ctrl_status) & CSRX_ISP_SOFT_RESET))
2270 set_bit(ISP_SOFT_RESET_CMPL, &ha->fw_dump_cap_flags);
2271
2272 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x015d,
2273 "HCCR: 0x%x, Soft Reset status: 0x%x\n",
2274 RD_REG_DWORD(&reg->hccr),
2275 RD_REG_DWORD(&reg->ctrl_status));
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002276
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07002277 /* If required, do an MPI FW reset now */
2278 if (test_and_clear_bit(MPI_RESET_NEEDED, &vha->dpc_flags)) {
2279 if (qla81xx_reset_mpi(vha) != QLA_SUCCESS) {
2280 if (++abts_cnt < 5) {
2281 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
2282 set_bit(MPI_RESET_NEEDED, &vha->dpc_flags);
2283 } else {
2284 /*
2285 * We exhausted the ISP abort retries. We have to
2286 * set the board offline.
2287 */
2288 abts_cnt = 0;
2289 vha->flags.online = 0;
2290 }
2291 }
2292 }
2293
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002294 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
2295 RD_REG_DWORD(&reg->hccr);
2296
2297 WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
2298 RD_REG_DWORD(&reg->hccr);
2299
2300 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_RESET);
2301 RD_REG_DWORD(&reg->hccr);
2302
Bart Van Assche52c82822015-07-09 07:23:26 -07002303 RD_REG_WORD(&reg->mailbox0);
Quinn Tran200ffb12016-12-23 18:06:12 -08002304 for (cnt = 60; RD_REG_WORD(&reg->mailbox0) != 0 &&
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002305 rval == QLA_SUCCESS; cnt--) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002306 barrier();
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002307 if (cnt)
2308 udelay(5);
2309 else
2310 rval = QLA_FUNCTION_TIMEOUT;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002311 }
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002312 if (rval == QLA_SUCCESS)
2313 set_bit(RISC_RDY_AFT_RESET, &ha->fw_dump_cap_flags);
2314
2315 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x015e,
2316 "Host Risc 0x%x, mailbox0 0x%x\n",
2317 RD_REG_DWORD(&reg->hccr),
2318 RD_REG_WORD(&reg->mailbox0));
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002319
2320 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Andrew Vasquez124f85e2009-01-05 11:18:06 -08002321
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002322 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x015f,
2323 "Driver in %s mode\n",
2324 IS_NOPOLLING_TYPE(ha) ? "Interrupt" : "Polling");
2325
Andrew Vasquez124f85e2009-01-05 11:18:06 -08002326 if (IS_NOPOLLING_TYPE(ha))
2327 ha->isp_ops->enable_intrs(ha);
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002328
2329 return rval;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002330}
2331
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05002332static void
2333qla25xx_read_risc_sema_reg(scsi_qla_host_t *vha, uint32_t *data)
2334{
2335 struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;
2336
2337 WRT_REG_DWORD(&reg->iobase_addr, RISC_REGISTER_BASE_OFFSET);
2338 *data = RD_REG_DWORD(&reg->iobase_window + RISC_REGISTER_WINDOW_OFFET);
2339
2340}
2341
2342static void
2343qla25xx_write_risc_sema_reg(scsi_qla_host_t *vha, uint32_t data)
2344{
2345 struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;
2346
2347 WRT_REG_DWORD(&reg->iobase_addr, RISC_REGISTER_BASE_OFFSET);
2348 WRT_REG_DWORD(&reg->iobase_window + RISC_REGISTER_WINDOW_OFFET, data);
2349}
2350
2351static void
2352qla25xx_manipulate_risc_semaphore(scsi_qla_host_t *vha)
2353{
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05002354 uint32_t wd32 = 0;
2355 uint delta_msec = 100;
2356 uint elapsed_msec = 0;
2357 uint timeout_msec;
2358 ulong n;
2359
Joe Carnucciocc790762015-08-04 13:37:53 -04002360 if (vha->hw->pdev->subsystem_device != 0x0175 &&
2361 vha->hw->pdev->subsystem_device != 0x0240)
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05002362 return;
2363
Joe Carnuccio8dd7e3a2015-08-04 13:37:54 -04002364 WRT_REG_DWORD(&vha->hw->iobase->isp24.hccr, HCCRX_SET_RISC_PAUSE);
2365 udelay(100);
2366
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05002367attempt:
2368 timeout_msec = TIMEOUT_SEMAPHORE;
2369 n = timeout_msec / delta_msec;
2370 while (n--) {
2371 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_SET);
2372 qla25xx_read_risc_sema_reg(vha, &wd32);
2373 if (wd32 & RISC_SEMAPHORE)
2374 break;
2375 msleep(delta_msec);
2376 elapsed_msec += delta_msec;
2377 if (elapsed_msec > TIMEOUT_TOTAL_ELAPSED)
2378 goto force;
2379 }
2380
2381 if (!(wd32 & RISC_SEMAPHORE))
2382 goto force;
2383
2384 if (!(wd32 & RISC_SEMAPHORE_FORCE))
2385 goto acquired;
2386
2387 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_CLR);
2388 timeout_msec = TIMEOUT_SEMAPHORE_FORCE;
2389 n = timeout_msec / delta_msec;
2390 while (n--) {
2391 qla25xx_read_risc_sema_reg(vha, &wd32);
2392 if (!(wd32 & RISC_SEMAPHORE_FORCE))
2393 break;
2394 msleep(delta_msec);
2395 elapsed_msec += delta_msec;
2396 if (elapsed_msec > TIMEOUT_TOTAL_ELAPSED)
2397 goto force;
2398 }
2399
2400 if (wd32 & RISC_SEMAPHORE_FORCE)
2401 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_FORCE_CLR);
2402
2403 goto attempt;
2404
2405force:
2406 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_FORCE_SET);
2407
2408acquired:
2409 return;
2410}
2411
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002412/**
Andrew Vasquez88c26662005-07-08 17:59:26 -07002413 * qla24xx_reset_chip() - Reset ISP24xx chip.
2414 * @ha: HA context
2415 *
2416 * Returns 0 on success.
2417 */
2418void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002419qla24xx_reset_chip(scsi_qla_host_t *vha)
Andrew Vasquez88c26662005-07-08 17:59:26 -07002420{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002421 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez85880802009-12-15 21:29:46 -08002422
2423 if (pci_channel_offline(ha->pdev) &&
2424 ha->flags.pci_channel_io_perm_failure) {
2425 return;
2426 }
2427
Andrew Vasquezfd34f552007-07-19 15:06:00 -07002428 ha->isp_ops->disable_intrs(ha);
Andrew Vasquez88c26662005-07-08 17:59:26 -07002429
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05002430 qla25xx_manipulate_risc_semaphore(vha);
2431
Andrew Vasquez88c26662005-07-08 17:59:26 -07002432 /* Perform RISC reset. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002433 qla24xx_reset_risc(vha);
Andrew Vasquez88c26662005-07-08 17:59:26 -07002434}
2435
2436/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 * qla2x00_chip_diag() - Test chip for proper operation.
2438 * @ha: HA context
2439 *
2440 * Returns 0 on success.
2441 */
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002442int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002443qla2x00_chip_diag(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444{
2445 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002446 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07002447 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 unsigned long flags = 0;
2449 uint16_t data;
2450 uint32_t cnt;
2451 uint16_t mb[5];
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002452 struct req_que *req = ha->req_q_map[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453
2454 /* Assume a failed state */
2455 rval = QLA_FUNCTION_FAILED;
2456
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002457 ql_dbg(ql_dbg_init, vha, 0x007b,
2458 "Testing device at %lx.\n", (u_long)&reg->flash_address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459
2460 spin_lock_irqsave(&ha->hardware_lock, flags);
2461
2462 /* Reset ISP chip. */
2463 WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
2464
2465 /*
2466 * We need to have a delay here since the card will not respond while
2467 * in reset causing an MCA on some architectures.
2468 */
2469 udelay(20);
2470 data = qla2x00_debounce_register(&reg->ctrl_status);
2471 for (cnt = 6000000 ; cnt && (data & CSR_ISP_SOFT_RESET); cnt--) {
2472 udelay(5);
2473 data = RD_REG_WORD(&reg->ctrl_status);
2474 barrier();
2475 }
2476
2477 if (!cnt)
2478 goto chip_diag_failed;
2479
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002480 ql_dbg(ql_dbg_init, vha, 0x007c,
2481 "Reset register cleared by chip reset.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482
2483 /* Reset RISC processor. */
2484 WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
2485 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
2486
2487 /* Workaround for QLA2312 PCI parity error */
2488 if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
2489 data = qla2x00_debounce_register(MAILBOX_REG(ha, reg, 0));
2490 for (cnt = 6000000; cnt && (data == MBS_BUSY); cnt--) {
2491 udelay(5);
2492 data = RD_MAILBOX_REG(ha, reg, 0);
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07002493 barrier();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 }
2495 } else
2496 udelay(10);
2497
2498 if (!cnt)
2499 goto chip_diag_failed;
2500
2501 /* Check product ID of chip */
Milan P Gandhi5a68a1c2017-03-31 14:37:04 -07002502 ql_dbg(ql_dbg_init, vha, 0x007d, "Checking product ID of chip.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503
2504 mb[1] = RD_MAILBOX_REG(ha, reg, 1);
2505 mb[2] = RD_MAILBOX_REG(ha, reg, 2);
2506 mb[3] = RD_MAILBOX_REG(ha, reg, 3);
2507 mb[4] = qla2x00_debounce_register(MAILBOX_REG(ha, reg, 4));
2508 if (mb[1] != PROD_ID_1 || (mb[2] != PROD_ID_2 && mb[2] != PROD_ID_2a) ||
2509 mb[3] != PROD_ID_3) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002510 ql_log(ql_log_warn, vha, 0x0062,
2511 "Wrong product ID = 0x%x,0x%x,0x%x.\n",
2512 mb[1], mb[2], mb[3]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513
2514 goto chip_diag_failed;
2515 }
2516 ha->product_id[0] = mb[1];
2517 ha->product_id[1] = mb[2];
2518 ha->product_id[2] = mb[3];
2519 ha->product_id[3] = mb[4];
2520
2521 /* Adjust fw RISC transfer size */
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002522 if (req->length > 1024)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523 ha->fw_transfer_size = REQUEST_ENTRY_SIZE * 1024;
2524 else
2525 ha->fw_transfer_size = REQUEST_ENTRY_SIZE *
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002526 req->length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527
2528 if (IS_QLA2200(ha) &&
2529 RD_MAILBOX_REG(ha, reg, 7) == QLA2200A_RISC_ROM_VER) {
2530 /* Limit firmware transfer size with a 2200A */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002531 ql_dbg(ql_dbg_init, vha, 0x007e, "Found QLA2200A Chip.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532
andrew.vasquez@qlogic.comea5b6382006-03-09 14:27:08 -08002533 ha->device_type |= DT_ISP2200A;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534 ha->fw_transfer_size = 128;
2535 }
2536
2537 /* Wrap Incoming Mailboxes Test. */
2538 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2539
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002540 ql_dbg(ql_dbg_init, vha, 0x007f, "Checking mailboxes.\n");
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002541 rval = qla2x00_mbx_reg_test(vha);
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002542 if (rval)
2543 ql_log(ql_log_warn, vha, 0x0080,
2544 "Failed mailbox send register test.\n");
2545 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546 /* Flag a successful rval */
2547 rval = QLA_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 spin_lock_irqsave(&ha->hardware_lock, flags);
2549
2550chip_diag_failed:
2551 if (rval)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002552 ql_log(ql_log_info, vha, 0x0081,
2553 "Chip diagnostics **** FAILED ****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554
2555 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2556
2557 return (rval);
2558}
2559
2560/**
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002561 * qla24xx_chip_diag() - Test ISP24xx for proper operation.
2562 * @ha: HA context
2563 *
2564 * Returns 0 on success.
2565 */
2566int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002567qla24xx_chip_diag(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002568{
2569 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002570 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002571 struct req_que *req = ha->req_q_map[0];
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002572
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04002573 if (IS_P3P_TYPE(ha))
Giridhar Malavalia9083012010-04-12 17:59:55 -07002574 return QLA_SUCCESS;
2575
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002576 ha->fw_transfer_size = REQUEST_ENTRY_SIZE * req->length;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002577
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002578 rval = qla2x00_mbx_reg_test(vha);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002579 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002580 ql_log(ql_log_warn, vha, 0x0082,
2581 "Failed mailbox send register test.\n");
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002582 } else {
2583 /* Flag a successful rval */
2584 rval = QLA_SUCCESS;
2585 }
2586
2587 return rval;
2588}
2589
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002590void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002591qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002592{
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002593 int rval;
2594 uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size,
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002595 eft_size, fce_size, mq_size;
Andrew Vasquezdf613b92008-01-17 09:02:17 -08002596 dma_addr_t tc_dma;
2597 void *tc;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002598 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002599 struct req_que *req = ha->req_q_map[0];
2600 struct rsp_que *rsp = ha->rsp_q_map[0];
Andrew Vasquezd4e3e042006-05-17 15:09:50 -07002601
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002602 if (ha->fw_dump) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002603 ql_dbg(ql_dbg_init, vha, 0x00bd,
2604 "Firmware dump already allocated.\n");
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002605 return;
Andrew Vasquezd4e3e042006-05-17 15:09:50 -07002606 }
2607
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002608 ha->fw_dumped = 0;
Hiral Patel61f098d2014-04-11 16:54:21 -04002609 ha->fw_dump_cap_flags = 0;
Chad Dupuisf73cb692014-02-26 04:15:06 -05002610 dump_size = fixed_size = mem_size = eft_size = fce_size = mq_size = 0;
2611 req_q_size = rsp_q_size = 0;
2612
2613 if (IS_QLA27XX(ha))
2614 goto try_fce;
2615
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002616 if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
2617 fixed_size = sizeof(struct qla2100_fw_dump);
2618 } else if (IS_QLA23XX(ha)) {
2619 fixed_size = offsetof(struct qla2300_fw_dump, data_ram);
2620 mem_size = (ha->fw_memory_size - 0x11000 + 1) *
2621 sizeof(uint16_t);
Andrew Vasqueze4289242007-07-19 15:05:56 -07002622 } else if (IS_FWI2_CAPABLE(ha)) {
Himanshu Madhanib20f02e2015-06-10 11:05:18 -04002623 if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08002624 fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem);
2625 else if (IS_QLA81XX(ha))
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08002626 fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem);
2627 else if (IS_QLA25XX(ha))
2628 fixed_size = offsetof(struct qla25xx_fw_dump, ext_mem);
2629 else
2630 fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem);
Chad Dupuisf73cb692014-02-26 04:15:06 -05002631
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002632 mem_size = (ha->fw_memory_size - 0x100000 + 1) *
2633 sizeof(uint32_t);
Giridhar Malavali050c9bb2012-02-09 11:15:33 -08002634 if (ha->mqenable) {
Himanshu Madhanib20f02e2015-06-10 11:05:18 -04002635 if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08002636 mq_size = sizeof(struct qla2xxx_mq_chain);
Giridhar Malavali050c9bb2012-02-09 11:15:33 -08002637 /*
2638 * Allocate maximum buffer size for all queues.
2639 * Resizing must be done at end-of-dump processing.
2640 */
2641 mq_size += ha->max_req_queues *
2642 (req->length * sizeof(request_t));
2643 mq_size += ha->max_rsp_queues *
2644 (rsp->length * sizeof(response_t));
2645 }
Arun Easi00876ae2013-03-25 02:21:37 -04002646 if (ha->tgt.atio_ring)
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002647 mq_size += ha->tgt.atio_q_length * sizeof(request_t);
Andrew Vasquez436a7b12008-07-10 16:55:54 -07002648 /* Allocate memory for Fibre Channel Event Buffer. */
Chad Dupuisf73cb692014-02-26 04:15:06 -05002649 if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
2650 !IS_QLA27XX(ha))
Andrew Vasquez436a7b12008-07-10 16:55:54 -07002651 goto try_eft;
2652
Chad Dupuisf73cb692014-02-26 04:15:06 -05002653try_fce:
2654 if (ha->fce)
2655 dma_free_coherent(&ha->pdev->dev,
2656 FCE_SIZE, ha->fce, ha->fce_dma);
2657
2658 /* Allocate memory for Fibre Channel Event Buffer. */
Joe Perches0ea85b52014-06-15 13:37:51 -07002659 tc = dma_zalloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
2660 GFP_KERNEL);
Andrew Vasquez436a7b12008-07-10 16:55:54 -07002661 if (!tc) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002662 ql_log(ql_log_warn, vha, 0x00be,
2663 "Unable to allocate (%d KB) for FCE.\n",
2664 FCE_SIZE / 1024);
Anirban Chakraborty17d98632008-12-18 10:06:15 -08002665 goto try_eft;
Andrew Vasquez436a7b12008-07-10 16:55:54 -07002666 }
2667
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002668 rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS,
Andrew Vasquez436a7b12008-07-10 16:55:54 -07002669 ha->fce_mb, &ha->fce_bufs);
2670 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002671 ql_log(ql_log_warn, vha, 0x00bf,
2672 "Unable to initialize FCE (%d).\n", rval);
Andrew Vasquez436a7b12008-07-10 16:55:54 -07002673 dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc,
2674 tc_dma);
2675 ha->flags.fce_enabled = 0;
Anirban Chakraborty17d98632008-12-18 10:06:15 -08002676 goto try_eft;
Andrew Vasquez436a7b12008-07-10 16:55:54 -07002677 }
Chad Dupuiscfb09192011-11-18 09:03:07 -08002678 ql_dbg(ql_dbg_init, vha, 0x00c0,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002679 "Allocate (%d KB) for FCE...\n", FCE_SIZE / 1024);
Andrew Vasquez436a7b12008-07-10 16:55:54 -07002680
Giridhar Malavali7d9dade2009-03-24 09:07:58 -07002681 fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
Andrew Vasquez436a7b12008-07-10 16:55:54 -07002682 ha->flags.fce_enabled = 1;
2683 ha->fce_dma = tc_dma;
2684 ha->fce = tc;
Chad Dupuisf73cb692014-02-26 04:15:06 -05002685
Andrew Vasquez436a7b12008-07-10 16:55:54 -07002686try_eft:
Chad Dupuisf73cb692014-02-26 04:15:06 -05002687 if (ha->eft)
2688 dma_free_coherent(&ha->pdev->dev,
2689 EFT_SIZE, ha->eft, ha->eft_dma);
2690
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002691 /* Allocate memory for Extended Trace Buffer. */
Joe Perches0ea85b52014-06-15 13:37:51 -07002692 tc = dma_zalloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
2693 GFP_KERNEL);
Andrew Vasquezdf613b92008-01-17 09:02:17 -08002694 if (!tc) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002695 ql_log(ql_log_warn, vha, 0x00c1,
2696 "Unable to allocate (%d KB) for EFT.\n",
2697 EFT_SIZE / 1024);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002698 goto cont_alloc;
2699 }
2700
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002701 rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002702 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002703 ql_log(ql_log_warn, vha, 0x00c2,
2704 "Unable to initialize EFT (%d).\n", rval);
Andrew Vasquezdf613b92008-01-17 09:02:17 -08002705 dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc,
2706 tc_dma);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002707 goto cont_alloc;
2708 }
Chad Dupuiscfb09192011-11-18 09:03:07 -08002709 ql_dbg(ql_dbg_init, vha, 0x00c3,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002710 "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002711
2712 eft_size = EFT_SIZE;
Andrew Vasquezdf613b92008-01-17 09:02:17 -08002713 ha->eft_dma = tc_dma;
2714 ha->eft = tc;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002715 }
Chad Dupuisf73cb692014-02-26 04:15:06 -05002716
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002717cont_alloc:
Chad Dupuisf73cb692014-02-26 04:15:06 -05002718 if (IS_QLA27XX(ha)) {
2719 if (!ha->fw_dump_template) {
2720 ql_log(ql_log_warn, vha, 0x00ba,
2721 "Failed missing fwdump template\n");
2722 return;
2723 }
2724 dump_size = qla27xx_fwdt_calculate_dump_size(vha);
2725 ql_dbg(ql_dbg_init, vha, 0x00fa,
2726 "-> allocating fwdump (%x bytes)...\n", dump_size);
2727 goto allocate;
2728 }
2729
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002730 req_q_size = req->length * sizeof(request_t);
2731 rsp_q_size = rsp->length * sizeof(response_t);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002732 dump_size = offsetof(struct qla2xxx_fw_dump, isp);
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002733 dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + eft_size;
Andrew Vasquezbb99de62009-01-05 11:18:08 -08002734 ha->chain_offset = dump_size;
2735 dump_size += mq_size + fce_size;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002736
Quinn Tranb945e772017-06-13 20:47:29 -07002737 if (ha->exchoffld_buf)
2738 dump_size += sizeof(struct qla2xxx_offld_chain) +
2739 ha->exchoffld_size;
2740 if (ha->exlogin_buf)
2741 dump_size += sizeof(struct qla2xxx_offld_chain) +
2742 ha->exlogin_size;
2743
Chad Dupuisf73cb692014-02-26 04:15:06 -05002744allocate:
Andrew Vasquezd4e3e042006-05-17 15:09:50 -07002745 ha->fw_dump = vmalloc(dump_size);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002746 if (!ha->fw_dump) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002747 ql_log(ql_log_warn, vha, 0x00c4,
2748 "Unable to allocate (%d KB) for firmware dump.\n",
2749 dump_size / 1024);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002750
Madhuranath Iyengare30d1752010-10-15 11:27:46 -07002751 if (ha->fce) {
2752 dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
2753 ha->fce_dma);
2754 ha->fce = NULL;
2755 ha->fce_dma = 0;
2756 }
2757
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002758 if (ha->eft) {
2759 dma_free_coherent(&ha->pdev->dev, eft_size, ha->eft,
2760 ha->eft_dma);
2761 ha->eft = NULL;
2762 ha->eft_dma = 0;
2763 }
2764 return;
2765 }
Chad Dupuisf73cb692014-02-26 04:15:06 -05002766 ha->fw_dump_len = dump_size;
Chad Dupuiscfb09192011-11-18 09:03:07 -08002767 ql_dbg(ql_dbg_init, vha, 0x00c5,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002768 "Allocated (%d KB) for firmware dump.\n", dump_size / 1024);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002769
Chad Dupuisf73cb692014-02-26 04:15:06 -05002770 if (IS_QLA27XX(ha))
2771 return;
2772
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002773 ha->fw_dump->signature[0] = 'Q';
2774 ha->fw_dump->signature[1] = 'L';
2775 ha->fw_dump->signature[2] = 'G';
2776 ha->fw_dump->signature[3] = 'C';
Bart Van Asschead950362015-07-09 07:24:08 -07002777 ha->fw_dump->version = htonl(1);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002778
2779 ha->fw_dump->fixed_size = htonl(fixed_size);
2780 ha->fw_dump->mem_size = htonl(mem_size);
2781 ha->fw_dump->req_q_size = htonl(req_q_size);
2782 ha->fw_dump->rsp_q_size = htonl(rsp_q_size);
2783
2784 ha->fw_dump->eft_size = htonl(eft_size);
2785 ha->fw_dump->eft_addr_l = htonl(LSD(ha->eft_dma));
2786 ha->fw_dump->eft_addr_h = htonl(MSD(ha->eft_dma));
2787
2788 ha->fw_dump->header_size =
2789 htonl(offsetof(struct qla2xxx_fw_dump, isp));
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002790}
2791
Andrew Vasquez18e75552009-06-03 09:55:30 -07002792static int
2793qla81xx_mpi_sync(scsi_qla_host_t *vha)
2794{
2795#define MPS_MASK 0xe0
2796 int rval;
2797 uint16_t dc;
2798 uint32_t dw;
Andrew Vasquez18e75552009-06-03 09:55:30 -07002799
2800 if (!IS_QLA81XX(vha->hw))
2801 return QLA_SUCCESS;
2802
2803 rval = qla2x00_write_ram_word(vha, 0x7c00, 1);
2804 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002805 ql_log(ql_log_warn, vha, 0x0105,
2806 "Unable to acquire semaphore.\n");
Andrew Vasquez18e75552009-06-03 09:55:30 -07002807 goto done;
2808 }
2809
2810 pci_read_config_word(vha->hw->pdev, 0x54, &dc);
2811 rval = qla2x00_read_ram_word(vha, 0x7a15, &dw);
2812 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002813 ql_log(ql_log_warn, vha, 0x0067, "Unable to read sync.\n");
Andrew Vasquez18e75552009-06-03 09:55:30 -07002814 goto done_release;
2815 }
2816
2817 dc &= MPS_MASK;
2818 if (dc == (dw & MPS_MASK))
2819 goto done_release;
2820
2821 dw &= ~MPS_MASK;
2822 dw |= dc;
2823 rval = qla2x00_write_ram_word(vha, 0x7a15, dw);
2824 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002825 ql_log(ql_log_warn, vha, 0x0114, "Unable to gain sync.\n");
Andrew Vasquez18e75552009-06-03 09:55:30 -07002826 }
2827
2828done_release:
2829 rval = qla2x00_write_ram_word(vha, 0x7c00, 0);
2830 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002831 ql_log(ql_log_warn, vha, 0x006d,
2832 "Unable to release semaphore.\n");
Andrew Vasquez18e75552009-06-03 09:55:30 -07002833 }
2834
2835done:
2836 return rval;
2837}
2838
Chad Dupuis8d93f552013-01-30 03:34:37 -05002839int
2840qla2x00_alloc_outstanding_cmds(struct qla_hw_data *ha, struct req_que *req)
2841{
2842 /* Don't try to reallocate the array */
2843 if (req->outstanding_cmds)
2844 return QLA_SUCCESS;
2845
Michael Hernandezd7459522016-12-12 14:40:07 -08002846 if (!IS_FWI2_CAPABLE(ha))
Chad Dupuis8d93f552013-01-30 03:34:37 -05002847 req->num_outstanding_cmds = DEFAULT_OUTSTANDING_COMMANDS;
2848 else {
Quinn Tran03e8c682015-12-17 14:56:59 -05002849 if (ha->cur_fw_xcb_count <= ha->cur_fw_iocb_count)
2850 req->num_outstanding_cmds = ha->cur_fw_xcb_count;
Chad Dupuis8d93f552013-01-30 03:34:37 -05002851 else
Quinn Tran03e8c682015-12-17 14:56:59 -05002852 req->num_outstanding_cmds = ha->cur_fw_iocb_count;
Chad Dupuis8d93f552013-01-30 03:34:37 -05002853 }
2854
2855 req->outstanding_cmds = kzalloc(sizeof(srb_t *) *
2856 req->num_outstanding_cmds, GFP_KERNEL);
2857
2858 if (!req->outstanding_cmds) {
2859 /*
2860 * Try to allocate a minimal size just so we can get through
2861 * initialization.
2862 */
2863 req->num_outstanding_cmds = MIN_OUTSTANDING_COMMANDS;
2864 req->outstanding_cmds = kzalloc(sizeof(srb_t *) *
2865 req->num_outstanding_cmds, GFP_KERNEL);
2866
2867 if (!req->outstanding_cmds) {
2868 ql_log(ql_log_fatal, NULL, 0x0126,
2869 "Failed to allocate memory for "
2870 "outstanding_cmds for req_que %p.\n", req);
2871 req->num_outstanding_cmds = 0;
2872 return QLA_FUNCTION_FAILED;
2873 }
2874 }
2875
2876 return QLA_SUCCESS;
2877}
2878
Quinn Trane4e3a2c2017-08-23 15:05:07 -07002879#define PRINT_FIELD(_field, _flag, _str) { \
2880 if (a0->_field & _flag) {\
2881 if (p) {\
2882 strcat(ptr, "|");\
2883 ptr++;\
2884 leftover--;\
2885 } \
2886 len = snprintf(ptr, leftover, "%s", _str); \
2887 p = 1;\
2888 leftover -= len;\
2889 ptr += len; \
2890 } \
2891}
2892
2893static void qla2xxx_print_sfp_info(struct scsi_qla_host *vha)
2894{
2895#define STR_LEN 64
2896 struct sff_8247_a0 *a0 = (struct sff_8247_a0 *)vha->hw->sfp_data;
2897 u8 str[STR_LEN], *ptr, p;
2898 int leftover, len;
2899
2900 memset(str, 0, STR_LEN);
2901 snprintf(str, SFF_VEN_NAME_LEN+1, a0->vendor_name);
2902 ql_dbg(ql_dbg_init, vha, 0x015a,
2903 "SFP MFG Name: %s\n", str);
2904
2905 memset(str, 0, STR_LEN);
2906 snprintf(str, SFF_PART_NAME_LEN+1, a0->vendor_pn);
2907 ql_dbg(ql_dbg_init, vha, 0x015c,
2908 "SFP Part Name: %s\n", str);
2909
2910 /* media */
2911 memset(str, 0, STR_LEN);
2912 ptr = str;
2913 leftover = STR_LEN;
2914 p = len = 0;
2915 PRINT_FIELD(fc_med_cc9, FC_MED_TW, "Twin AX");
2916 PRINT_FIELD(fc_med_cc9, FC_MED_TP, "Twisted Pair");
2917 PRINT_FIELD(fc_med_cc9, FC_MED_MI, "Min Coax");
2918 PRINT_FIELD(fc_med_cc9, FC_MED_TV, "Video Coax");
2919 PRINT_FIELD(fc_med_cc9, FC_MED_M6, "MultiMode 62.5um");
2920 PRINT_FIELD(fc_med_cc9, FC_MED_M5, "MultiMode 50um");
2921 PRINT_FIELD(fc_med_cc9, FC_MED_SM, "SingleMode");
2922 ql_dbg(ql_dbg_init, vha, 0x0160,
2923 "SFP Media: %s\n", str);
2924
2925 /* link length */
2926 memset(str, 0, STR_LEN);
2927 ptr = str;
2928 leftover = STR_LEN;
2929 p = len = 0;
2930 PRINT_FIELD(fc_ll_cc7, FC_LL_VL, "Very Long");
2931 PRINT_FIELD(fc_ll_cc7, FC_LL_S, "Short");
2932 PRINT_FIELD(fc_ll_cc7, FC_LL_I, "Intermediate");
2933 PRINT_FIELD(fc_ll_cc7, FC_LL_L, "Long");
2934 PRINT_FIELD(fc_ll_cc7, FC_LL_M, "Medium");
2935 ql_dbg(ql_dbg_init, vha, 0x0196,
2936 "SFP Link Length: %s\n", str);
2937
2938 memset(str, 0, STR_LEN);
2939 ptr = str;
2940 leftover = STR_LEN;
2941 p = len = 0;
2942 PRINT_FIELD(fc_ll_cc7, FC_LL_SA, "Short Wave (SA)");
2943 PRINT_FIELD(fc_ll_cc7, FC_LL_LC, "Long Wave(LC)");
2944 PRINT_FIELD(fc_tec_cc8, FC_TEC_SN, "Short Wave (SN)");
2945 PRINT_FIELD(fc_tec_cc8, FC_TEC_SL, "Short Wave (SL)");
2946 PRINT_FIELD(fc_tec_cc8, FC_TEC_LL, "Long Wave (LL)");
2947 ql_dbg(ql_dbg_init, vha, 0x016e,
2948 "SFP FC Link Tech: %s\n", str);
2949
2950 if (a0->length_km)
2951 ql_dbg(ql_dbg_init, vha, 0x016f,
2952 "SFP Distant: %d km\n", a0->length_km);
2953 if (a0->length_100m)
2954 ql_dbg(ql_dbg_init, vha, 0x0170,
2955 "SFP Distant: %d m\n", a0->length_100m*100);
2956 if (a0->length_50um_10m)
2957 ql_dbg(ql_dbg_init, vha, 0x0189,
2958 "SFP Distant (WL=50um): %d m\n", a0->length_50um_10m * 10);
2959 if (a0->length_62um_10m)
2960 ql_dbg(ql_dbg_init, vha, 0x018a,
2961 "SFP Distant (WL=62.5um): %d m\n", a0->length_62um_10m * 10);
2962 if (a0->length_om4_10m)
2963 ql_dbg(ql_dbg_init, vha, 0x0194,
2964 "SFP Distant (OM4): %d m\n", a0->length_om4_10m * 10);
2965 if (a0->length_om3_10m)
2966 ql_dbg(ql_dbg_init, vha, 0x0195,
2967 "SFP Distant (OM3): %d m\n", a0->length_om3_10m * 10);
2968}
2969
2970
2971/*
2972 * Return Code:
2973 * QLA_SUCCESS: no action
2974 * QLA_INTERFACE_ERROR: SFP is not there.
2975 * QLA_FUNCTION_FAILED: detected New SFP
2976 */
2977int
2978qla24xx_detect_sfp(scsi_qla_host_t *vha)
2979{
2980 int rc = QLA_SUCCESS;
2981 struct sff_8247_a0 *a;
2982 struct qla_hw_data *ha = vha->hw;
2983
2984 if (!AUTO_DETECT_SFP_SUPPORT(vha))
2985 goto out;
2986
2987 rc = qla2x00_read_sfp_dev(vha, NULL, 0);
2988 if (rc)
2989 goto out;
2990
2991 a = (struct sff_8247_a0 *)vha->hw->sfp_data;
2992 qla2xxx_print_sfp_info(vha);
2993
2994 if (a->fc_ll_cc7 & FC_LL_VL || a->fc_ll_cc7 & FC_LL_L) {
2995 /* long range */
2996 ha->flags.detected_lr_sfp = 1;
2997
2998 if (a->length_km > 5 || a->length_100m > 50)
2999 ha->long_range_distance = LR_DISTANCE_10K;
3000 else
3001 ha->long_range_distance = LR_DISTANCE_5K;
3002
3003 if (ha->flags.detected_lr_sfp != ha->flags.using_lr_setting)
3004 ql_dbg(ql_dbg_async, vha, 0x507b,
3005 "Detected Long Range SFP.\n");
3006 } else {
3007 /* short range */
3008 ha->flags.detected_lr_sfp = 0;
3009 if (ha->flags.using_lr_setting)
3010 ql_dbg(ql_dbg_async, vha, 0x5084,
3011 "Detected Short Range SFP.\n");
3012 }
3013
3014 if (!vha->flags.init_done)
3015 rc = QLA_SUCCESS;
3016out:
3017 return rc;
3018}
3019
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003020/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021 * qla2x00_setup_chip() - Load and start RISC firmware.
3022 * @ha: HA context
3023 *
3024 * Returns 0 on success.
3025 */
3026static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003027qla2x00_setup_chip(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028{
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003029 int rval;
3030 uint32_t srisc_address = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003031 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3db06522008-01-31 12:33:49 -08003032 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
3033 unsigned long flags;
Andrew Vasquezdda772e2009-03-24 09:08:00 -07003034 uint16_t fw_major_version;
Andrew Vasquez3db06522008-01-31 12:33:49 -08003035
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04003036 if (IS_P3P_TYPE(ha)) {
Giridhar Malavalia9083012010-04-12 17:59:55 -07003037 rval = ha->isp_ops->load_risc(vha, &srisc_address);
Andrew Vasquez14e303d2010-07-23 15:28:29 +05003038 if (rval == QLA_SUCCESS) {
3039 qla2x00_stop_firmware(vha);
Giridhar Malavalia9083012010-04-12 17:59:55 -07003040 goto enable_82xx_npiv;
Andrew Vasquez14e303d2010-07-23 15:28:29 +05003041 } else
Giridhar Malavalib9637522010-05-28 15:08:15 -07003042 goto failed;
Giridhar Malavalia9083012010-04-12 17:59:55 -07003043 }
3044
Andrew Vasquez3db06522008-01-31 12:33:49 -08003045 if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) {
3046 /* Disable SRAM, Instruction RAM and GP RAM parity. */
3047 spin_lock_irqsave(&ha->hardware_lock, flags);
3048 WRT_REG_WORD(&reg->hccr, (HCCR_ENABLE_PARITY + 0x0));
3049 RD_REG_WORD(&reg->hccr);
3050 spin_unlock_irqrestore(&ha->hardware_lock, flags);
3051 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052
Andrew Vasquez18e75552009-06-03 09:55:30 -07003053 qla81xx_mpi_sync(vha);
3054
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055 /* Load firmware sequences */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003056 rval = ha->isp_ops->load_risc(vha, &srisc_address);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003057 if (rval == QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003058 ql_dbg(ql_dbg_init, vha, 0x00c9,
3059 "Verifying Checksum of loaded RISC code.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003061 rval = qla2x00_verify_checksum(vha, srisc_address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062 if (rval == QLA_SUCCESS) {
3063 /* Start firmware execution. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003064 ql_dbg(ql_dbg_init, vha, 0x00ca,
3065 "Starting firmware.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066
Himanshu Madhanib0d6cab2015-12-17 14:56:56 -05003067 if (ql2xexlogins)
3068 ha->flags.exlogins_enabled = 1;
3069
Quinn Tran99e1b682017-06-02 09:12:03 -07003070 if (qla_is_exch_offld_enabled(vha))
Himanshu Madhani2f56a7f2015-12-17 14:56:57 -05003071 ha->flags.exchoffld_enabled = 1;
3072
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003073 rval = qla2x00_execute_fw(vha, srisc_address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 /* Retrieve firmware information. */
Andrew Vasquezdda772e2009-03-24 09:08:00 -07003075 if (rval == QLA_SUCCESS) {
Quinn Trane4e3a2c2017-08-23 15:05:07 -07003076 qla24xx_detect_sfp(vha);
3077
Himanshu Madhanib0d6cab2015-12-17 14:56:56 -05003078 rval = qla2x00_set_exlogins_buffer(vha);
3079 if (rval != QLA_SUCCESS)
3080 goto failed;
3081
Himanshu Madhani2f56a7f2015-12-17 14:56:57 -05003082 rval = qla2x00_set_exchoffld_buffer(vha);
3083 if (rval != QLA_SUCCESS)
3084 goto failed;
3085
Giridhar Malavalia9083012010-04-12 17:59:55 -07003086enable_82xx_npiv:
Andrew Vasquezdda772e2009-03-24 09:08:00 -07003087 fw_major_version = ha->fw_major_version;
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04003088 if (IS_P3P_TYPE(ha))
Giridhar Malavali31731672011-08-16 11:31:54 -07003089 qla82xx_check_md_needed(vha);
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003090 else
3091 rval = qla2x00_get_fw_version(vha);
Andrew Vasquezca9e9c32009-06-03 09:55:20 -07003092 if (rval != QLA_SUCCESS)
3093 goto failed;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003094 ha->flags.npiv_supported = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003095 if (IS_QLA2XXX_MIDTYPE(ha) &&
Mike Hernandez946fb892008-08-13 21:36:59 -07003096 (ha->fw_attributes & BIT_2)) {
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003097 ha->flags.npiv_supported = 1;
Seokmann Ju4d0ea242007-09-20 14:07:43 -07003098 if ((!ha->max_npiv_vports) ||
3099 ((ha->max_npiv_vports + 1) %
Andrew Vasquezeb66dc62007-11-12 10:30:58 -08003100 MIN_MULTI_ID_FABRIC))
Seokmann Ju4d0ea242007-09-20 14:07:43 -07003101 ha->max_npiv_vports =
Andrew Vasquezeb66dc62007-11-12 10:30:58 -08003102 MIN_MULTI_ID_FABRIC - 1;
Seokmann Ju4d0ea242007-09-20 14:07:43 -07003103 }
Quinn Tran03e8c682015-12-17 14:56:59 -05003104 qla2x00_get_resource_cnts(vha);
Andrew Vasquezd743de62009-03-24 09:08:15 -07003105
Chad Dupuis8d93f552013-01-30 03:34:37 -05003106 /*
3107 * Allocate the array of outstanding commands
3108 * now that we know the firmware resources.
3109 */
3110 rval = qla2x00_alloc_outstanding_cmds(ha,
3111 vha->req);
3112 if (rval != QLA_SUCCESS)
3113 goto failed;
3114
Saurav Kashyapbe5ea3c2011-11-18 09:02:11 -08003115 if (!fw_major_version && ql2xallocfwdump
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04003116 && !(IS_P3P_TYPE(ha)))
Giridhar Malavali08de2842011-08-16 11:31:44 -07003117 qla2x00_alloc_fw_dump(vha);
Chad Dupuis3b6e5b92013-10-30 03:38:09 -04003118 } else {
3119 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120 }
3121 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003122 ql_log(ql_log_fatal, vha, 0x00cd,
3123 "ISP Firmware failed checksum.\n");
3124 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125 }
Andrew Vasquezc74d88a2012-08-22 14:21:19 -04003126 } else
3127 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128
Andrew Vasquez3db06522008-01-31 12:33:49 -08003129 if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) {
3130 /* Enable proper parity. */
3131 spin_lock_irqsave(&ha->hardware_lock, flags);
3132 if (IS_QLA2300(ha))
3133 /* SRAM parity */
3134 WRT_REG_WORD(&reg->hccr, HCCR_ENABLE_PARITY + 0x1);
3135 else
3136 /* SRAM, Instruction RAM and GP RAM parity */
3137 WRT_REG_WORD(&reg->hccr, HCCR_ENABLE_PARITY + 0x7);
3138 RD_REG_WORD(&reg->hccr);
3139 spin_unlock_irqrestore(&ha->hardware_lock, flags);
3140 }
3141
Chad Dupuisf3982d82014-09-25 05:16:57 -04003142 if (IS_QLA27XX(ha))
3143 ha->flags.fac_supported = 1;
3144 else if (rval == QLA_SUCCESS && IS_FAC_REQUIRED(ha)) {
Joe Carnuccio1d2874d2009-03-24 09:08:06 -07003145 uint32_t size;
3146
3147 rval = qla81xx_fac_get_sector_size(vha, &size);
3148 if (rval == QLA_SUCCESS) {
3149 ha->flags.fac_supported = 1;
3150 ha->fdt_block_size = size << 2;
3151 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003152 ql_log(ql_log_warn, vha, 0x00ce,
Joe Carnuccio1d2874d2009-03-24 09:08:06 -07003153 "Unsupported FAC firmware (%d.%02d.%02d).\n",
3154 ha->fw_major_version, ha->fw_minor_version,
3155 ha->fw_subminor_version);
Joe Carnuccio1ca60e32014-02-26 04:15:02 -05003156
Chad Dupuisf73cb692014-02-26 04:15:06 -05003157 if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003158 ha->flags.fac_supported = 0;
3159 rval = QLA_SUCCESS;
3160 }
Joe Carnuccio1d2874d2009-03-24 09:08:06 -07003161 }
3162 }
Andrew Vasquezca9e9c32009-06-03 09:55:20 -07003163failed:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003165 ql_log(ql_log_fatal, vha, 0x00cf,
3166 "Setup chip ****FAILED****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167 }
3168
3169 return (rval);
3170}
3171
3172/**
3173 * qla2x00_init_response_q_entries() - Initializes response queue entries.
3174 * @ha: HA context
3175 *
3176 * Beginning of request ring has initialization control block already built
3177 * by nvram config routine.
3178 *
3179 * Returns 0 on success.
3180 */
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003181void
3182qla2x00_init_response_q_entries(struct rsp_que *rsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183{
3184 uint16_t cnt;
3185 response_t *pkt;
3186
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003187 rsp->ring_ptr = rsp->ring;
3188 rsp->ring_index = 0;
3189 rsp->status_srb = NULL;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003190 pkt = rsp->ring_ptr;
3191 for (cnt = 0; cnt < rsp->length; cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192 pkt->signature = RESPONSE_PROCESSED;
3193 pkt++;
3194 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195}
3196
3197/**
3198 * qla2x00_update_fw_options() - Read and process firmware options.
3199 * @ha: HA context
3200 *
3201 * Returns 0 on success.
3202 */
Andrew Vasquezabbd8872005-07-06 10:30:05 -07003203void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003204qla2x00_update_fw_options(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205{
3206 uint16_t swing, emphasis, tx_sens, rx_sens;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003207 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208
3209 memset(ha->fw_options, 0, sizeof(ha->fw_options));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003210 qla2x00_get_fw_options(vha, ha->fw_options);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211
3212 if (IS_QLA2100(ha) || IS_QLA2200(ha))
3213 return;
3214
3215 /* Serial Link options. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003216 ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0115,
3217 "Serial link options.\n");
3218 ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0109,
3219 (uint8_t *)&ha->fw_seriallink_options,
3220 sizeof(ha->fw_seriallink_options));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221
3222 ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
3223 if (ha->fw_seriallink_options[3] & BIT_2) {
3224 ha->fw_options[1] |= FO1_SET_EMPHASIS_SWING;
3225
3226 /* 1G settings */
3227 swing = ha->fw_seriallink_options[2] & (BIT_2 | BIT_1 | BIT_0);
3228 emphasis = (ha->fw_seriallink_options[2] &
3229 (BIT_4 | BIT_3)) >> 3;
3230 tx_sens = ha->fw_seriallink_options[0] &
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07003231 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232 rx_sens = (ha->fw_seriallink_options[0] &
3233 (BIT_7 | BIT_6 | BIT_5 | BIT_4)) >> 4;
3234 ha->fw_options[10] = (emphasis << 14) | (swing << 8);
3235 if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {
3236 if (rx_sens == 0x0)
3237 rx_sens = 0x3;
3238 ha->fw_options[10] |= (tx_sens << 4) | rx_sens;
3239 } else if (IS_QLA2322(ha) || IS_QLA6322(ha))
3240 ha->fw_options[10] |= BIT_5 |
3241 ((rx_sens & (BIT_1 | BIT_0)) << 2) |
3242 (tx_sens & (BIT_1 | BIT_0));
3243
3244 /* 2G settings */
3245 swing = (ha->fw_seriallink_options[2] &
3246 (BIT_7 | BIT_6 | BIT_5)) >> 5;
3247 emphasis = ha->fw_seriallink_options[3] & (BIT_1 | BIT_0);
3248 tx_sens = ha->fw_seriallink_options[1] &
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07003249 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250 rx_sens = (ha->fw_seriallink_options[1] &
3251 (BIT_7 | BIT_6 | BIT_5 | BIT_4)) >> 4;
3252 ha->fw_options[11] = (emphasis << 14) | (swing << 8);
3253 if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {
3254 if (rx_sens == 0x0)
3255 rx_sens = 0x3;
3256 ha->fw_options[11] |= (tx_sens << 4) | rx_sens;
3257 } else if (IS_QLA2322(ha) || IS_QLA6322(ha))
3258 ha->fw_options[11] |= BIT_5 |
3259 ((rx_sens & (BIT_1 | BIT_0)) << 2) |
3260 (tx_sens & (BIT_1 | BIT_0));
3261 }
3262
3263 /* FCP2 options. */
3264 /* Return command IOCBs without waiting for an ABTS to complete. */
3265 ha->fw_options[3] |= BIT_13;
3266
3267 /* LED scheme. */
3268 if (ha->flags.enable_led_scheme)
3269 ha->fw_options[2] |= BIT_12;
3270
andrew.vasquez@qlogic.com48c02fd2006-03-09 14:27:18 -08003271 /* Detect ISP6312. */
3272 if (IS_QLA6312(ha))
3273 ha->fw_options[2] |= BIT_13;
3274
Giridhar Malavali088d09d2016-07-06 11:14:20 -04003275 /* Set Retry FLOGI in case of P2P connection */
3276 if (ha->operating_mode == P2P) {
3277 ha->fw_options[2] |= BIT_3;
3278 ql_dbg(ql_dbg_disc, vha, 0x2100,
3279 "(%s): Setting FLOGI retry BIT in fw_options[2]: 0x%x\n",
3280 __func__, ha->fw_options[2]);
3281 }
3282
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283 /* Update firmware options. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003284 qla2x00_set_fw_options(vha, ha->fw_options);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285}
3286
Andrew Vasquezabbd8872005-07-06 10:30:05 -07003287void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003288qla24xx_update_fw_options(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003289{
3290 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003291 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003292
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04003293 if (IS_P3P_TYPE(ha))
Giridhar Malavalia9083012010-04-12 17:59:55 -07003294 return;
3295
Himanshu Madhanif198caf2016-01-27 12:03:30 -05003296 /* Hold status IOCBs until ABTS response received. */
3297 if (ql2xfwholdabts)
3298 ha->fw_options[3] |= BIT_12;
3299
Giridhar Malavali088d09d2016-07-06 11:14:20 -04003300 /* Set Retry FLOGI in case of P2P connection */
3301 if (ha->operating_mode == P2P) {
3302 ha->fw_options[2] |= BIT_3;
3303 ql_dbg(ql_dbg_disc, vha, 0x2101,
3304 "(%s): Setting FLOGI retry BIT in fw_options[2]: 0x%x\n",
3305 __func__, ha->fw_options[2]);
3306 }
3307
Quinn Tran41dc5292017-01-19 22:28:03 -08003308 /* Move PUREX, ABTS RX & RIDA to ATIOQ */
Quinn Tran3c4810f2017-06-02 09:11:53 -07003309 if (ql2xmvasynctoatio &&
3310 (IS_QLA83XX(ha) || IS_QLA27XX(ha))) {
Quinn Tran41dc5292017-01-19 22:28:03 -08003311 if (qla_tgt_mode_enabled(vha) ||
3312 qla_dual_mode_enabled(vha))
3313 ha->fw_options[2] |= BIT_11;
3314 else
3315 ha->fw_options[2] &= ~BIT_11;
3316 }
3317
Quinn Tranf7e761f2017-06-02 09:12:02 -07003318 if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
3319 /*
3320 * Tell FW to track each exchange to prevent
3321 * driver from using stale exchange.
3322 */
3323 if (qla_tgt_mode_enabled(vha) ||
3324 qla_dual_mode_enabled(vha))
3325 ha->fw_options[2] |= BIT_4;
3326 else
3327 ha->fw_options[2] &= ~BIT_4;
3328 }
3329
Quinn Tran83548fe2017-06-02 09:12:01 -07003330 ql_dbg(ql_dbg_init, vha, 0x00e8,
3331 "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n",
3332 __func__, ha->fw_options[1], ha->fw_options[2],
3333 ha->fw_options[3], vha->host->active_mode);
Quinn Tran3c4810f2017-06-02 09:11:53 -07003334
3335 if (ha->fw_options[1] || ha->fw_options[2] || ha->fw_options[3])
3336 qla2x00_set_fw_options(vha, ha->fw_options);
Quinn Tran41dc5292017-01-19 22:28:03 -08003337
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003338 /* Update Serial Link options. */
andrew.vasquez@qlogic.comf94097e2006-01-13 17:05:32 -08003339 if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003340 return;
3341
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003342 rval = qla2x00_set_serdes_params(vha,
andrew.vasquez@qlogic.comf94097e2006-01-13 17:05:32 -08003343 le16_to_cpu(ha->fw_seriallink_options24[1]),
3344 le16_to_cpu(ha->fw_seriallink_options24[2]),
3345 le16_to_cpu(ha->fw_seriallink_options24[3]));
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003346 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003347 ql_log(ql_log_warn, vha, 0x0104,
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003348 "Unable to update Serial Link options (%x).\n", rval);
3349 }
3350}
3351
3352void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003353qla2x00_config_rings(struct scsi_qla_host *vha)
Andrew Vasquezabbd8872005-07-06 10:30:05 -07003354{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003355 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07003356 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003357 struct req_que *req = ha->req_q_map[0];
3358 struct rsp_que *rsp = ha->rsp_q_map[0];
Andrew Vasquezabbd8872005-07-06 10:30:05 -07003359
3360 /* Setup ring parameters in initialization control block. */
Bart Van Asschead950362015-07-09 07:24:08 -07003361 ha->init_cb->request_q_outpointer = cpu_to_le16(0);
3362 ha->init_cb->response_q_inpointer = cpu_to_le16(0);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003363 ha->init_cb->request_q_length = cpu_to_le16(req->length);
3364 ha->init_cb->response_q_length = cpu_to_le16(rsp->length);
3365 ha->init_cb->request_q_address[0] = cpu_to_le32(LSD(req->dma));
3366 ha->init_cb->request_q_address[1] = cpu_to_le32(MSD(req->dma));
3367 ha->init_cb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma));
3368 ha->init_cb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma));
Andrew Vasquezabbd8872005-07-06 10:30:05 -07003369
3370 WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), 0);
3371 WRT_REG_WORD(ISP_REQ_Q_OUT(ha, reg), 0);
3372 WRT_REG_WORD(ISP_RSP_Q_IN(ha, reg), 0);
3373 WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), 0);
3374 RD_REG_WORD(ISP_RSP_Q_OUT(ha, reg)); /* PCI Posting. */
3375}
3376
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003377void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003378qla24xx_config_rings(struct scsi_qla_host *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003379{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003380 struct qla_hw_data *ha = vha->hw;
Bart Van Assche118e2ef2015-07-09 07:24:27 -07003381 device_reg_t *reg = ISP_QUE_REG(ha, 0);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003382 struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp;
3383 struct qla_msix_entry *msix;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003384 struct init_cb_24xx *icb;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003385 uint16_t rid = 0;
3386 struct req_que *req = ha->req_q_map[0];
3387 struct rsp_que *rsp = ha->rsp_q_map[0];
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003388
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003389 /* Setup ring parameters in initialization control block. */
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003390 icb = (struct init_cb_24xx *)ha->init_cb;
Bart Van Asschead950362015-07-09 07:24:08 -07003391 icb->request_q_outpointer = cpu_to_le16(0);
3392 icb->response_q_inpointer = cpu_to_le16(0);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003393 icb->request_q_length = cpu_to_le16(req->length);
3394 icb->response_q_length = cpu_to_le16(rsp->length);
3395 icb->request_q_address[0] = cpu_to_le32(LSD(req->dma));
3396 icb->request_q_address[1] = cpu_to_le32(MSD(req->dma));
3397 icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma));
3398 icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma));
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003399
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003400 /* Setup ATIO queue dma pointers for target mode */
Bart Van Asschead950362015-07-09 07:24:08 -07003401 icb->atio_q_inpointer = cpu_to_le16(0);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003402 icb->atio_q_length = cpu_to_le16(ha->tgt.atio_q_length);
3403 icb->atio_q_address[0] = cpu_to_le32(LSD(ha->tgt.atio_dma));
3404 icb->atio_q_address[1] = cpu_to_le32(MSD(ha->tgt.atio_dma));
3405
Joe Carnuccio7c6300e2014-04-11 16:54:37 -04003406 if (IS_SHADOW_REG_CAPABLE(ha))
Bart Van Asschead950362015-07-09 07:24:08 -07003407 icb->firmware_options_2 |= cpu_to_le32(BIT_30|BIT_29);
Joe Carnuccio7c6300e2014-04-11 16:54:37 -04003408
Chad Dupuisf73cb692014-02-26 04:15:06 -05003409 if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
Bart Van Asschead950362015-07-09 07:24:08 -07003410 icb->qos = cpu_to_le16(QLA_DEFAULT_QUE_QOS);
3411 icb->rid = cpu_to_le16(rid);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003412 if (ha->flags.msix_enabled) {
3413 msix = &ha->msix_entries[1];
Quinn Tran83548fe2017-06-02 09:12:01 -07003414 ql_dbg(ql_dbg_init, vha, 0x0019,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003415 "Registering vector 0x%x for base que.\n",
3416 msix->entry);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003417 icb->msix = cpu_to_le16(msix->entry);
3418 }
3419 /* Use alternate PCI bus number */
3420 if (MSB(rid))
Bart Van Asschead950362015-07-09 07:24:08 -07003421 icb->firmware_options_2 |= cpu_to_le32(BIT_19);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003422 /* Use alternate PCI devfn */
3423 if (LSB(rid))
Bart Van Asschead950362015-07-09 07:24:08 -07003424 icb->firmware_options_2 |= cpu_to_le32(BIT_18);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003425
Anirban Chakraborty31557542009-12-02 10:36:55 -08003426 /* Use Disable MSIX Handshake mode for capable adapters */
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003427 if ((ha->fw_attributes & BIT_6) && (IS_MSIX_NACK_CAPABLE(ha)) &&
3428 (ha->flags.msix_enabled)) {
Bart Van Asschead950362015-07-09 07:24:08 -07003429 icb->firmware_options_2 &= cpu_to_le32(~BIT_22);
Anirban Chakraborty31557542009-12-02 10:36:55 -08003430 ha->flags.disable_msix_handshake = 1;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003431 ql_dbg(ql_dbg_init, vha, 0x00fe,
3432 "MSIX Handshake Disable Mode turned on.\n");
Anirban Chakraborty31557542009-12-02 10:36:55 -08003433 } else {
Bart Van Asschead950362015-07-09 07:24:08 -07003434 icb->firmware_options_2 |= cpu_to_le32(BIT_22);
Anirban Chakraborty31557542009-12-02 10:36:55 -08003435 }
Bart Van Asschead950362015-07-09 07:24:08 -07003436 icb->firmware_options_2 |= cpu_to_le32(BIT_23);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003437
3438 WRT_REG_DWORD(&reg->isp25mq.req_q_in, 0);
3439 WRT_REG_DWORD(&reg->isp25mq.req_q_out, 0);
3440 WRT_REG_DWORD(&reg->isp25mq.rsp_q_in, 0);
3441 WRT_REG_DWORD(&reg->isp25mq.rsp_q_out, 0);
3442 } else {
3443 WRT_REG_DWORD(&reg->isp24.req_q_in, 0);
3444 WRT_REG_DWORD(&reg->isp24.req_q_out, 0);
3445 WRT_REG_DWORD(&reg->isp24.rsp_q_in, 0);
3446 WRT_REG_DWORD(&reg->isp24.rsp_q_out, 0);
3447 }
Arun Easiaa230bc2013-01-30 03:34:39 -05003448 qlt_24xx_config_rings(vha);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003449
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003450 /* PCI posting */
3451 RD_REG_DWORD(&ioreg->hccr);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003452}
3453
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454/**
3455 * qla2x00_init_rings() - Initializes firmware.
3456 * @ha: HA context
3457 *
3458 * Beginning of request ring has initialization control block already built
3459 * by nvram config routine.
3460 *
3461 * Returns 0 on success.
3462 */
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04003463int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003464qla2x00_init_rings(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465{
3466 int rval;
3467 unsigned long flags = 0;
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003468 int cnt, que;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003469 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003470 struct req_que *req;
3471 struct rsp_que *rsp;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003472 struct mid_init_cb_24xx *mid_init_cb =
3473 (struct mid_init_cb_24xx *) ha->init_cb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474
3475 spin_lock_irqsave(&ha->hardware_lock, flags);
3476
3477 /* Clear outstanding commands array. */
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003478 for (que = 0; que < ha->max_req_queues; que++) {
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003479 req = ha->req_q_map[que];
Quinn Trancb432852016-02-04 11:45:16 -05003480 if (!req || !test_bit(que, ha->req_qid_map))
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003481 continue;
Joe Carnuccio7c6300e2014-04-11 16:54:37 -04003482 req->out_ptr = (void *)(req->ring + req->length);
3483 *req->out_ptr = 0;
Chad Dupuis8d93f552013-01-30 03:34:37 -05003484 for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++)
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003485 req->outstanding_cmds[cnt] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003487 req->current_outstanding_cmd = 1;
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003488
3489 /* Initialize firmware. */
3490 req->ring_ptr = req->ring;
3491 req->ring_index = 0;
3492 req->cnt = req->length;
3493 }
3494
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003495 for (que = 0; que < ha->max_rsp_queues; que++) {
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003496 rsp = ha->rsp_q_map[que];
Quinn Trancb432852016-02-04 11:45:16 -05003497 if (!rsp || !test_bit(que, ha->rsp_qid_map))
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003498 continue;
Joe Carnuccio7c6300e2014-04-11 16:54:37 -04003499 rsp->in_ptr = (void *)(rsp->ring + rsp->length);
3500 *rsp->in_ptr = 0;
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003501 /* Initialize response queue entries */
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04003502 if (IS_QLAFX00(ha))
3503 qlafx00_init_response_q_entries(rsp);
3504 else
3505 qla2x00_init_response_q_entries(rsp);
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003506 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003508 ha->tgt.atio_ring_ptr = ha->tgt.atio_ring;
3509 ha->tgt.atio_ring_index = 0;
3510 /* Initialize ATIO queue entries */
3511 qlt_init_atio_q_entries(vha);
3512
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003513 ha->isp_ops->config_rings(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514
3515 spin_unlock_irqrestore(&ha->hardware_lock, flags);
3516
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04003517 ql_dbg(ql_dbg_init, vha, 0x00d1, "Issue init firmware.\n");
3518
3519 if (IS_QLAFX00(ha)) {
3520 rval = qlafx00_init_firmware(vha, ha->init_cb_size);
3521 goto next_check;
3522 }
3523
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 /* Update any ISP specific firmware options before initialization. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003525 ha->isp_ops->update_fw_options(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526
Lalit Chandivade605aa2b2009-03-05 11:07:01 -08003527 if (ha->flags.npiv_supported) {
Saurav Kashyap45980cc2012-08-22 14:21:21 -04003528 if (ha->operating_mode == LOOP && !IS_CNA_CAPABLE(ha))
Lalit Chandivade605aa2b2009-03-05 11:07:01 -08003529 ha->max_npiv_vports = MIN_MULTI_ID_FABRIC - 1;
Seokmann Juc48339d2008-01-17 09:02:19 -08003530 mid_init_cb->count = cpu_to_le16(ha->max_npiv_vports);
Lalit Chandivade605aa2b2009-03-05 11:07:01 -08003531 }
3532
Andrew Vasquez24a08132009-03-24 09:08:16 -07003533 if (IS_FWI2_CAPABLE(ha)) {
Bart Van Asschead950362015-07-09 07:24:08 -07003534 mid_init_cb->options = cpu_to_le16(BIT_1);
Andrew Vasquez24a08132009-03-24 09:08:16 -07003535 mid_init_cb->init_cb.execution_throttle =
Quinn Tran03e8c682015-12-17 14:56:59 -05003536 cpu_to_le16(ha->cur_fw_xcb_count);
Joe Carnuccio40f38622016-07-06 11:14:28 -04003537 ha->flags.dport_enabled =
3538 (mid_init_cb->init_cb.firmware_options_1 & BIT_7) != 0;
3539 ql_dbg(ql_dbg_init, vha, 0x0191, "DPORT Support: %s.\n",
3540 (ha->flags.dport_enabled) ? "enabled" : "disabled");
3541 /* FA-WWPN Status */
Himanshu Madhani2486c622014-09-25 05:17:00 -04003542 ha->flags.fawwpn_enabled =
Joe Carnuccio40f38622016-07-06 11:14:28 -04003543 (mid_init_cb->init_cb.firmware_options_1 & BIT_6) != 0;
Quinn Tran83548fe2017-06-02 09:12:01 -07003544 ql_dbg(ql_dbg_init, vha, 0x00bc, "FA-WWPN Support: %s.\n",
Himanshu Madhani2486c622014-09-25 05:17:00 -04003545 (ha->flags.fawwpn_enabled) ? "enabled" : "disabled");
Andrew Vasquez24a08132009-03-24 09:08:16 -07003546 }
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003547
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003548 rval = qla2x00_init_firmware(vha, ha->init_cb_size);
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04003549next_check:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003551 ql_log(ql_log_fatal, vha, 0x00d2,
3552 "Init Firmware **** FAILED ****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003554 ql_dbg(ql_dbg_init, vha, 0x00d3,
3555 "Init Firmware -- success.\n");
Quinn Tran4b60c822017-06-13 20:47:21 -07003556 QLA_FW_STARTED(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557 }
3558
3559 return (rval);
3560}
3561
3562/**
3563 * qla2x00_fw_ready() - Waits for firmware ready.
3564 * @ha: HA context
3565 *
3566 * Returns 0 on success.
3567 */
3568static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003569qla2x00_fw_ready(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003570{
3571 int rval;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003572 unsigned long wtime, mtime, cs84xx_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573 uint16_t min_wait; /* Minimum wait time if loop is down */
3574 uint16_t wait_time; /* Wait time if loop is coming ready */
Joe Carnucciob5a340d2014-09-25 05:16:48 -04003575 uint16_t state[6];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003576 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04003578 if (IS_QLAFX00(vha->hw))
3579 return qlafx00_fw_ready(vha);
3580
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581 rval = QLA_SUCCESS;
3582
Chad Dupuis334614912015-04-09 14:59:57 -04003583 /* Time to wait for loop down */
3584 if (IS_P3P_TYPE(ha))
3585 min_wait = 30;
3586 else
3587 min_wait = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588
3589 /*
3590 * Firmware should take at most one RATOV to login, plus 5 seconds for
3591 * our own processing.
3592 */
3593 if ((wait_time = (ha->retry_count*ha->login_timeout) + 5) < min_wait) {
3594 wait_time = min_wait;
3595 }
3596
3597 /* Min wait time if loop down */
3598 mtime = jiffies + (min_wait * HZ);
3599
3600 /* wait time before firmware ready */
3601 wtime = jiffies + (wait_time * HZ);
3602
3603 /* Wait for ISP to finish LIP */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003604 if (!vha->flags.init_done)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003605 ql_log(ql_log_info, vha, 0x801e,
3606 "Waiting for LIP to complete.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607
3608 do {
Andrew Vasquez5b939032012-11-21 02:40:26 -05003609 memset(state, -1, sizeof(state));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003610 rval = qla2x00_get_firmware_state(vha, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611 if (rval == QLA_SUCCESS) {
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003612 if (state[0] < FSTATE_LOSS_OF_SYNC) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003613 vha->device_flags &= ~DFLG_NO_CABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 }
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003615 if (IS_QLA84XX(ha) && state[0] != FSTATE_READY) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003616 ql_dbg(ql_dbg_taskm, vha, 0x801f,
3617 "fw_state=%x 84xx=%x.\n", state[0],
3618 state[2]);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003619 if ((state[2] & FSTATE_LOGGED_IN) &&
3620 (state[2] & FSTATE_WAITING_FOR_VERIFY)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003621 ql_dbg(ql_dbg_taskm, vha, 0x8028,
3622 "Sending verify iocb.\n");
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003623
3624 cs84xx_time = jiffies;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003625 rval = qla84xx_init_chip(vha);
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003626 if (rval != QLA_SUCCESS) {
3627 ql_log(ql_log_warn,
Chad Dupuiscfb09192011-11-18 09:03:07 -08003628 vha, 0x8007,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003629 "Init chip failed.\n");
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003630 break;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003631 }
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003632
3633 /* Add time taken to initialize. */
3634 cs84xx_time = jiffies - cs84xx_time;
3635 wtime += cs84xx_time;
3636 mtime += cs84xx_time;
Chad Dupuiscfb09192011-11-18 09:03:07 -08003637 ql_dbg(ql_dbg_taskm, vha, 0x8008,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003638 "Increasing wait time by %ld. "
3639 "New time %ld.\n", cs84xx_time,
3640 wtime);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003641 }
3642 } else if (state[0] == FSTATE_READY) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003643 ql_dbg(ql_dbg_taskm, vha, 0x8037,
3644 "F/W Ready - OK.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003646 qla2x00_get_retry_cnt(vha, &ha->retry_count,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 &ha->login_timeout, &ha->r_a_tov);
3648
3649 rval = QLA_SUCCESS;
3650 break;
3651 }
3652
3653 rval = QLA_FUNCTION_FAILED;
3654
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003655 if (atomic_read(&vha->loop_down_timer) &&
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003656 state[0] != FSTATE_READY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657 /* Loop down. Timeout on min_wait for states
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07003658 * other than Wait for Login.
3659 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 if (time_after_eq(jiffies, mtime)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003661 ql_log(ql_log_info, vha, 0x8038,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003662 "Cable is unplugged...\n");
3663
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003664 vha->device_flags |= DFLG_NO_CABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665 break;
3666 }
3667 }
3668 } else {
3669 /* Mailbox cmd failed. Timeout on min_wait. */
Santosh Vernekarcdbb0a4f2010-05-28 15:08:25 -07003670 if (time_after_eq(jiffies, mtime) ||
Giridhar Malavali71905752011-02-23 15:27:10 -08003671 ha->flags.isp82xx_fw_hung)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672 break;
3673 }
3674
3675 if (time_after_eq(jiffies, wtime))
3676 break;
3677
3678 /* Delay for a while */
3679 msleep(500);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680 } while (1);
3681
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003682 ql_dbg(ql_dbg_taskm, vha, 0x803a,
Joe Carnucciob5a340d2014-09-25 05:16:48 -04003683 "fw_state=%x (%x, %x, %x, %x %x) curr time=%lx.\n", state[0],
3684 state[1], state[2], state[3], state[4], state[5], jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685
Chad Dupuiscfb09192011-11-18 09:03:07 -08003686 if (rval && !(vha->device_flags & DFLG_NO_CABLE)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003687 ql_log(ql_log_warn, vha, 0x803b,
3688 "Firmware ready **** FAILED ****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 }
3690
3691 return (rval);
3692}
3693
3694/*
3695* qla2x00_configure_hba
3696* Setup adapter context.
3697*
3698* Input:
3699* ha = adapter state pointer.
3700*
3701* Returns:
3702* 0 = success
3703*
3704* Context:
3705* Kernel context.
3706*/
3707static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003708qla2x00_configure_hba(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709{
3710 int rval;
3711 uint16_t loop_id;
3712 uint16_t topo;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003713 uint16_t sw_cap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 uint8_t al_pa;
3715 uint8_t area;
3716 uint8_t domain;
3717 char connect_type[22];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003718 struct qla_hw_data *ha = vha->hw;
Joe Carnuccio61e1b262013-02-08 01:57:48 -05003719 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
Quinn Tran482c9dc2017-03-15 09:48:54 -07003720 port_id_t id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721
3722 /* Get host addresses. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003723 rval = qla2x00_get_adapter_id(vha,
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003724 &loop_id, &al_pa, &area, &domain, &topo, &sw_cap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725 if (rval != QLA_SUCCESS) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003726 if (LOOP_TRANSITION(vha) || atomic_read(&ha->loop_down_timer) ||
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003727 IS_CNA_CAPABLE(ha) ||
Ravi Anand33135aa2005-11-08 14:37:20 -08003728 (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003729 ql_dbg(ql_dbg_disc, vha, 0x2008,
3730 "Loop is in a transition state.\n");
Ravi Anand33135aa2005-11-08 14:37:20 -08003731 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003732 ql_log(ql_log_warn, vha, 0x2009,
3733 "Unable to get host loop ID.\n");
Joe Carnuccio61e1b262013-02-08 01:57:48 -05003734 if (IS_FWI2_CAPABLE(ha) && (vha == base_vha) &&
3735 (rval == QLA_COMMAND_ERROR && loop_id == 0x1b)) {
3736 ql_log(ql_log_warn, vha, 0x1151,
3737 "Doing link init.\n");
3738 if (qla24xx_link_initialize(vha) == QLA_SUCCESS)
3739 return rval;
3740 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003741 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Ravi Anand33135aa2005-11-08 14:37:20 -08003742 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743 return (rval);
3744 }
3745
3746 if (topo == 4) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003747 ql_log(ql_log_info, vha, 0x200a,
3748 "Cannot get topology - retrying.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749 return (QLA_FUNCTION_FAILED);
3750 }
3751
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003752 vha->loop_id = loop_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753
3754 /* initialize */
3755 ha->min_external_loopid = SNS_FIRST_LOOP_ID;
3756 ha->operating_mode = LOOP;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003757 ha->switch_cap = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758
3759 switch (topo) {
3760 case 0:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003761 ql_dbg(ql_dbg_disc, vha, 0x200b, "HBA in NL topology.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762 ha->current_topology = ISP_CFG_NL;
3763 strcpy(connect_type, "(Loop)");
3764 break;
3765
3766 case 1:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003767 ql_dbg(ql_dbg_disc, vha, 0x200c, "HBA in FL topology.\n");
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003768 ha->switch_cap = sw_cap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769 ha->current_topology = ISP_CFG_FL;
3770 strcpy(connect_type, "(FL_Port)");
3771 break;
3772
3773 case 2:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003774 ql_dbg(ql_dbg_disc, vha, 0x200d, "HBA in N P2P topology.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 ha->operating_mode = P2P;
3776 ha->current_topology = ISP_CFG_N;
3777 strcpy(connect_type, "(N_Port-to-N_Port)");
3778 break;
3779
3780 case 3:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003781 ql_dbg(ql_dbg_disc, vha, 0x200e, "HBA in F P2P topology.\n");
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003782 ha->switch_cap = sw_cap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003783 ha->operating_mode = P2P;
3784 ha->current_topology = ISP_CFG_F;
3785 strcpy(connect_type, "(F_Port)");
3786 break;
3787
3788 default:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003789 ql_dbg(ql_dbg_disc, vha, 0x200f,
3790 "HBA in unknown topology %x, using NL.\n", topo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 ha->current_topology = ISP_CFG_NL;
3792 strcpy(connect_type, "(Loop)");
3793 break;
3794 }
3795
3796 /* Save Host port and loop ID. */
3797 /* byte order - Big Endian */
Quinn Tran482c9dc2017-03-15 09:48:54 -07003798 id.b.domain = domain;
3799 id.b.area = area;
3800 id.b.al_pa = al_pa;
3801 id.b.rsvd_1 = 0;
3802 qlt_update_host_map(vha, id);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003803
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003804 if (!vha->flags.init_done)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003805 ql_log(ql_log_info, vha, 0x2010,
3806 "Topology - %s, Host Loop address 0x%x.\n",
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003807 connect_type, vha->loop_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809 return(rval);
3810}
3811
Giridhar Malavalia9083012010-04-12 17:59:55 -07003812inline void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003813qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
3814 char *def)
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08003815{
3816 char *st, *en;
3817 uint16_t index;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003818 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezab671142009-08-25 11:36:17 -07003819 int use_tbl = !IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) &&
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003820 !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha);
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08003821
3822 if (memcmp(model, BINZERO, len) != 0) {
3823 strncpy(ha->model_number, model, len);
3824 st = en = ha->model_number;
3825 en += len - 1;
3826 while (en > st) {
3827 if (*en != 0x20 && *en != 0x00)
3828 break;
3829 *en-- = '\0';
3830 }
3831
3832 index = (ha->pdev->subsystem_device & 0xff);
Andrew Vasquez7d0dba12009-04-06 22:33:45 -07003833 if (use_tbl &&
3834 ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08003835 index < QLA_MODEL_NAMES)
Joe Carnuccio1ee27142008-07-10 16:55:53 -07003836 strncpy(ha->model_desc,
3837 qla2x00_model_name[index * 2 + 1],
3838 sizeof(ha->model_desc) - 1);
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08003839 } else {
3840 index = (ha->pdev->subsystem_device & 0xff);
Andrew Vasquez7d0dba12009-04-06 22:33:45 -07003841 if (use_tbl &&
3842 ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08003843 index < QLA_MODEL_NAMES) {
3844 strcpy(ha->model_number,
3845 qla2x00_model_name[index * 2]);
Joe Carnuccio1ee27142008-07-10 16:55:53 -07003846 strncpy(ha->model_desc,
3847 qla2x00_model_name[index * 2 + 1],
3848 sizeof(ha->model_desc) - 1);
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08003849 } else {
3850 strcpy(ha->model_number, def);
3851 }
3852 }
Joe Carnuccio1ee27142008-07-10 16:55:53 -07003853 if (IS_FWI2_CAPABLE(ha))
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003854 qla2xxx_get_vpd_field(vha, "\x82", ha->model_desc,
Joe Carnuccio1ee27142008-07-10 16:55:53 -07003855 sizeof(ha->model_desc));
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08003856}
3857
David Miller4e08df32007-04-16 12:37:43 -07003858/* On sparc systems, obtain port and node WWN from firmware
3859 * properties.
3860 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003861static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
David Miller4e08df32007-04-16 12:37:43 -07003862{
3863#ifdef CONFIG_SPARC
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003864 struct qla_hw_data *ha = vha->hw;
David Miller4e08df32007-04-16 12:37:43 -07003865 struct pci_dev *pdev = ha->pdev;
David S. Miller15576bc2007-05-08 00:36:49 -07003866 struct device_node *dp = pci_device_to_OF_node(pdev);
3867 const u8 *val;
David Miller4e08df32007-04-16 12:37:43 -07003868 int len;
3869
3870 val = of_get_property(dp, "port-wwn", &len);
3871 if (val && len >= WWN_SIZE)
3872 memcpy(nv->port_name, val, WWN_SIZE);
3873
3874 val = of_get_property(dp, "node-wwn", &len);
3875 if (val && len >= WWN_SIZE)
3876 memcpy(nv->node_name, val, WWN_SIZE);
3877#endif
3878}
3879
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880/*
3881* NVRAM configuration for ISP 2xxx
3882*
3883* Input:
3884* ha = adapter block pointer.
3885*
3886* Output:
3887* initialization control block in response_ring
3888* host adapters parameters in host adapter block
3889*
3890* Returns:
3891* 0 = success.
3892*/
Andrew Vasquezabbd8872005-07-06 10:30:05 -07003893int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003894qla2x00_nvram_config(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895{
David Miller4e08df32007-04-16 12:37:43 -07003896 int rval;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003897 uint8_t chksum = 0;
3898 uint16_t cnt;
3899 uint8_t *dptr1, *dptr2;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003900 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003901 init_cb_t *icb = ha->init_cb;
Seokmann Ju281afe12007-07-26 13:43:34 -07003902 nvram_t *nv = ha->nvram;
3903 uint8_t *ptr = ha->nvram;
Andrew Vasquez3d716442005-07-06 10:30:26 -07003904 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905
David Miller4e08df32007-04-16 12:37:43 -07003906 rval = QLA_SUCCESS;
3907
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 /* Determine NVRAM starting address. */
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003909 ha->nvram_size = sizeof(nvram_t);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 ha->nvram_base = 0;
3911 if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha))
3912 if ((RD_REG_WORD(&reg->ctrl_status) >> 14) == 1)
3913 ha->nvram_base = 0x80;
3914
3915 /* Get NVRAM data and calculate checksum. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003916 ha->isp_ops->read_nvram(vha, ptr, ha->nvram_base, ha->nvram_size);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003917 for (cnt = 0, chksum = 0; cnt < ha->nvram_size; cnt++)
3918 chksum += *ptr++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003920 ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x010f,
3921 "Contents of NVRAM.\n");
3922 ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0110,
3923 (uint8_t *)nv, ha->nvram_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924
3925 /* Bad NVRAM data, set defaults parameters. */
3926 if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
3927 nv->id[2] != 'P' || nv->id[3] != ' ' || nv->nvram_version < 1) {
3928 /* Reset NVRAM data. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003929 ql_log(ql_log_warn, vha, 0x0064,
Raul Porcel9e336522012-05-15 14:34:08 -04003930 "Inconsistent NVRAM "
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003931 "detected: checksum=0x%x id=%c version=0x%x.\n",
3932 chksum, nv->id[0], nv->nvram_version);
3933 ql_log(ql_log_warn, vha, 0x0065,
3934 "Falling back to "
3935 "functioning (yet invalid -- WWPN) defaults.\n");
David Miller4e08df32007-04-16 12:37:43 -07003936
3937 /*
3938 * Set default initialization control block.
3939 */
3940 memset(nv, 0, ha->nvram_size);
3941 nv->parameter_block_version = ICB_VERSION;
3942
3943 if (IS_QLA23XX(ha)) {
3944 nv->firmware_options[0] = BIT_2 | BIT_1;
3945 nv->firmware_options[1] = BIT_7 | BIT_5;
3946 nv->add_firmware_options[0] = BIT_5;
3947 nv->add_firmware_options[1] = BIT_5 | BIT_4;
Joe Carnuccio98aee702014-09-25 05:16:38 -04003948 nv->frame_payload_size = 2048;
David Miller4e08df32007-04-16 12:37:43 -07003949 nv->special_options[1] = BIT_7;
3950 } else if (IS_QLA2200(ha)) {
3951 nv->firmware_options[0] = BIT_2 | BIT_1;
3952 nv->firmware_options[1] = BIT_7 | BIT_5;
3953 nv->add_firmware_options[0] = BIT_5;
3954 nv->add_firmware_options[1] = BIT_5 | BIT_4;
Joe Carnuccio98aee702014-09-25 05:16:38 -04003955 nv->frame_payload_size = 1024;
David Miller4e08df32007-04-16 12:37:43 -07003956 } else if (IS_QLA2100(ha)) {
3957 nv->firmware_options[0] = BIT_3 | BIT_1;
3958 nv->firmware_options[1] = BIT_5;
Joe Carnuccio98aee702014-09-25 05:16:38 -04003959 nv->frame_payload_size = 1024;
David Miller4e08df32007-04-16 12:37:43 -07003960 }
3961
Bart Van Asschead950362015-07-09 07:24:08 -07003962 nv->max_iocb_allocation = cpu_to_le16(256);
3963 nv->execution_throttle = cpu_to_le16(16);
David Miller4e08df32007-04-16 12:37:43 -07003964 nv->retry_count = 8;
3965 nv->retry_delay = 1;
3966
3967 nv->port_name[0] = 33;
3968 nv->port_name[3] = 224;
3969 nv->port_name[4] = 139;
3970
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003971 qla2xxx_nvram_wwn_from_ofw(vha, nv);
David Miller4e08df32007-04-16 12:37:43 -07003972
3973 nv->login_timeout = 4;
3974
3975 /*
3976 * Set default host adapter parameters
3977 */
3978 nv->host_p[1] = BIT_2;
3979 nv->reset_delay = 5;
3980 nv->port_down_retry_count = 8;
Bart Van Asschead950362015-07-09 07:24:08 -07003981 nv->max_luns_per_target = cpu_to_le16(8);
David Miller4e08df32007-04-16 12:37:43 -07003982 nv->link_down_timeout = 60;
3983
3984 rval = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985 }
3986
3987#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
3988 /*
3989 * The SN2 does not provide BIOS emulation which means you can't change
3990 * potentially bogus BIOS settings. Force the use of default settings
3991 * for link rate and frame size. Hope that the rest of the settings
3992 * are valid.
3993 */
3994 if (ia64_platform_is("sn2")) {
Joe Carnuccio98aee702014-09-25 05:16:38 -04003995 nv->frame_payload_size = 2048;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996 if (IS_QLA23XX(ha))
3997 nv->special_options[1] = BIT_7;
3998 }
3999#endif
4000
4001 /* Reset Initialization control block */
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004002 memset(icb, 0, ha->init_cb_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003
4004 /*
4005 * Setup driver NVRAM options.
4006 */
4007 nv->firmware_options[0] |= (BIT_6 | BIT_1);
4008 nv->firmware_options[0] &= ~(BIT_5 | BIT_4);
4009 nv->firmware_options[1] |= (BIT_5 | BIT_0);
4010 nv->firmware_options[1] &= ~BIT_4;
4011
4012 if (IS_QLA23XX(ha)) {
4013 nv->firmware_options[0] |= BIT_2;
4014 nv->firmware_options[0] &= ~BIT_3;
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04004015 nv->special_options[0] &= ~BIT_6;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004016 nv->add_firmware_options[1] |= BIT_5 | BIT_4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017
4018 if (IS_QLA2300(ha)) {
4019 if (ha->fb_rev == FPM_2310) {
4020 strcpy(ha->model_number, "QLA2310");
4021 } else {
4022 strcpy(ha->model_number, "QLA2300");
4023 }
4024 } else {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004025 qla2x00_set_model_info(vha, nv->model_number,
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08004026 sizeof(nv->model_number), "QLA23xx");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027 }
4028 } else if (IS_QLA2200(ha)) {
4029 nv->firmware_options[0] |= BIT_2;
4030 /*
4031 * 'Point-to-point preferred, else loop' is not a safe
4032 * connection mode setting.
4033 */
4034 if ((nv->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) ==
4035 (BIT_5 | BIT_4)) {
4036 /* Force 'loop preferred, else point-to-point'. */
4037 nv->add_firmware_options[0] &= ~(BIT_6 | BIT_5 | BIT_4);
4038 nv->add_firmware_options[0] |= BIT_5;
4039 }
4040 strcpy(ha->model_number, "QLA22xx");
4041 } else /*if (IS_QLA2100(ha))*/ {
4042 strcpy(ha->model_number, "QLA2100");
4043 }
4044
4045 /*
4046 * Copy over NVRAM RISC parameter block to initialization control block.
4047 */
4048 dptr1 = (uint8_t *)icb;
4049 dptr2 = (uint8_t *)&nv->parameter_block_version;
4050 cnt = (uint8_t *)&icb->request_q_outpointer - (uint8_t *)&icb->version;
4051 while (cnt--)
4052 *dptr1++ = *dptr2++;
4053
4054 /* Copy 2nd half. */
4055 dptr1 = (uint8_t *)icb->add_firmware_options;
4056 cnt = (uint8_t *)icb->reserved_3 - (uint8_t *)icb->add_firmware_options;
4057 while (cnt--)
4058 *dptr1++ = *dptr2++;
4059
Andrew Vasquez5341e862006-05-17 15:09:16 -07004060 /* Use alternate WWN? */
4061 if (nv->host_p[1] & BIT_7) {
4062 memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
4063 memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
4064 }
4065
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 /* Prepare nodename */
4067 if ((icb->firmware_options[1] & BIT_6) == 0) {
4068 /*
4069 * Firmware will apply the following mask if the nodename was
4070 * not provided.
4071 */
4072 memcpy(icb->node_name, icb->port_name, WWN_SIZE);
4073 icb->node_name[0] &= 0xF0;
4074 }
4075
4076 /*
4077 * Set host adapter parameters.
4078 */
Saurav Kashyap3ce88662011-07-14 12:00:12 -07004079
4080 /*
4081 * BIT_7 in the host-parameters section allows for modification to
4082 * internal driver logging.
4083 */
Andrew Vasquez01819442006-06-23 16:11:10 -07004084 if (nv->host_p[0] & BIT_7)
Chad Dupuiscfb09192011-11-18 09:03:07 -08004085 ql2xextended_error_logging = QL_DBG_DEFAULT1_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086 ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0);
4087 /* Always load RISC code on non ISP2[12]00 chips. */
4088 if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
4089 ha->flags.disable_risc_code_load = 0;
4090 ha->flags.enable_lip_reset = ((nv->host_p[1] & BIT_1) ? 1 : 0);
4091 ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0);
4092 ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0);
Andrew Vasquez06c22bd2005-08-26 19:09:00 -07004093 ha->flags.enable_led_scheme = (nv->special_options[1] & BIT_4) ? 1 : 0;
Andrew Vasquezd4c760c2006-06-23 16:10:39 -07004094 ha->flags.disable_serdes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095
4096 ha->operating_mode =
4097 (icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4;
4098
4099 memcpy(ha->fw_seriallink_options, nv->seriallink_options,
4100 sizeof(ha->fw_seriallink_options));
4101
4102 /* save HBA serial number */
4103 ha->serial0 = icb->port_name[5];
4104 ha->serial1 = icb->port_name[6];
4105 ha->serial2 = icb->port_name[7];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004106 memcpy(vha->node_name, icb->node_name, WWN_SIZE);
4107 memcpy(vha->port_name, icb->port_name, WWN_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108
Bart Van Asschead950362015-07-09 07:24:08 -07004109 icb->execution_throttle = cpu_to_le16(0xFFFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110
4111 ha->retry_count = nv->retry_count;
4112
4113 /* Set minimum login_timeout to 4 seconds. */
Andrew Vasquez5b914902010-05-28 15:08:30 -07004114 if (nv->login_timeout != ql2xlogintimeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115 nv->login_timeout = ql2xlogintimeout;
4116 if (nv->login_timeout < 4)
4117 nv->login_timeout = 4;
4118 ha->login_timeout = nv->login_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119
Andrew Vasquez00a537b2008-02-28 14:06:11 -08004120 /* Set minimum RATOV to 100 tenths of a second. */
4121 ha->r_a_tov = 100;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 ha->loop_reset_delay = nv->reset_delay;
4124
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125 /* Link Down Timeout = 0:
4126 *
4127 * When Port Down timer expires we will start returning
4128 * I/O's to OS with "DID_NO_CONNECT".
4129 *
4130 * Link Down Timeout != 0:
4131 *
4132 * The driver waits for the link to come up after link down
4133 * before returning I/Os to OS with "DID_NO_CONNECT".
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07004134 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135 if (nv->link_down_timeout == 0) {
4136 ha->loop_down_abort_time =
Andrew Vasquez 354d6b22005-04-23 02:47:27 -04004137 (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138 } else {
4139 ha->link_down_timeout = nv->link_down_timeout;
4140 ha->loop_down_abort_time =
4141 (LOOP_DOWN_TIME - ha->link_down_timeout);
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07004142 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144 /*
4145 * Need enough time to try and get the port back.
4146 */
4147 ha->port_down_retry_count = nv->port_down_retry_count;
4148 if (qlport_down_retry)
4149 ha->port_down_retry_count = qlport_down_retry;
4150 /* Set login_retry_count */
4151 ha->login_retry_count = nv->retry_count;
4152 if (ha->port_down_retry_count == nv->port_down_retry_count &&
4153 ha->port_down_retry_count > 3)
4154 ha->login_retry_count = ha->port_down_retry_count;
4155 else if (ha->port_down_retry_count > (int)ha->login_retry_count)
4156 ha->login_retry_count = ha->port_down_retry_count;
4157 if (ql2xloginretrycount)
4158 ha->login_retry_count = ql2xloginretrycount;
4159
Bart Van Asschead950362015-07-09 07:24:08 -07004160 icb->lun_enables = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161 icb->command_resource_count = 0;
4162 icb->immediate_notify_resource_count = 0;
Bart Van Asschead950362015-07-09 07:24:08 -07004163 icb->timeout = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164
4165 if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
4166 /* Enable RIO */
4167 icb->firmware_options[0] &= ~BIT_3;
4168 icb->add_firmware_options[0] &=
4169 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0);
4170 icb->add_firmware_options[0] |= BIT_2;
4171 icb->response_accumulation_timer = 3;
4172 icb->interrupt_delay_timer = 5;
4173
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004174 vha->flags.process_response_queue = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 } else {
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07004176 /* Enable ZIO. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004177 if (!vha->flags.init_done) {
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07004178 ha->zio_mode = icb->add_firmware_options[0] &
4179 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
4180 ha->zio_timer = icb->interrupt_delay_timer ?
4181 icb->interrupt_delay_timer: 2;
4182 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 icb->add_firmware_options[0] &=
4184 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004185 vha->flags.process_response_queue = 0;
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07004186 if (ha->zio_mode != QLA_ZIO_DISABLED) {
andrew.vasquez@qlogic.com4a59f712006-03-09 14:27:39 -08004187 ha->zio_mode = QLA_ZIO_MODE_6;
4188
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004189 ql_log(ql_log_info, vha, 0x0068,
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07004190 "ZIO mode %d enabled; timer delay (%d us).\n",
4191 ha->zio_mode, ha->zio_timer * 100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07004193 icb->add_firmware_options[0] |= (uint8_t)ha->zio_mode;
4194 icb->interrupt_delay_timer = (uint8_t)ha->zio_timer;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004195 vha->flags.process_response_queue = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196 }
4197 }
4198
David Miller4e08df32007-04-16 12:37:43 -07004199 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004200 ql_log(ql_log_warn, vha, 0x0069,
4201 "NVRAM configuration failed.\n");
David Miller4e08df32007-04-16 12:37:43 -07004202 }
4203 return (rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204}
4205
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04004206static void
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04004207qla2x00_rport_del(void *data)
4208{
4209 fc_port_t *fcport = data;
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08004210 struct fc_rport *rport;
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08004211 unsigned long flags;
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04004212
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08004213 spin_lock_irqsave(fcport->vha->host->host_lock, flags);
Andrew Vasquezac280b62009-08-20 11:06:05 -07004214 rport = fcport->drport ? fcport->drport: fcport->rport;
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08004215 fcport->drport = NULL;
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08004216 spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
Quinn Tran726b8542017-01-19 22:28:00 -08004217 if (rport) {
Quinn Tran83548fe2017-06-02 09:12:01 -07004218 ql_dbg(ql_dbg_disc, fcport->vha, 0x210b,
4219 "%s %8phN. rport %p roles %x\n",
4220 __func__, fcport->port_name, rport,
4221 rport->roles);
Quinn Tran726b8542017-01-19 22:28:00 -08004222
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08004223 fc_remote_port_delete(rport);
Quinn Tran726b8542017-01-19 22:28:00 -08004224 }
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04004225}
4226
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227/**
4228 * qla2x00_alloc_fcport() - Allocate a generic fcport.
4229 * @ha: HA context
4230 * @flags: allocation flags
4231 *
4232 * Returns a pointer to the allocated fcport, or NULL, if none available.
4233 */
Giridhar Malavali9a069e12010-01-12 13:02:47 -08004234fc_port_t *
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004235qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236{
4237 fc_port_t *fcport;
4238
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02004239 fcport = kzalloc(sizeof(fc_port_t), flags);
4240 if (!fcport)
4241 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242
4243 /* Setup fcport template structure. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004244 fcport->vha = vha;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245 fcport->port_type = FCT_UNKNOWN;
4246 fcport->loop_id = FC_NO_LOOP_ID;
Chad Dupuisec426e12011-03-30 11:46:32 -07004247 qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED);
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07004248 fcport->supported_classes = FC_COS_UNSPECIFIED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249
Quinn Tran726b8542017-01-19 22:28:00 -08004250 fcport->ct_desc.ct_sns = dma_alloc_coherent(&vha->hw->pdev->dev,
4251 sizeof(struct ct_sns_pkt), &fcport->ct_desc.ct_sns_dma,
Quinn Tran6cb32162017-02-13 12:18:29 -08004252 flags);
Quinn Tran726b8542017-01-19 22:28:00 -08004253 fcport->disc_state = DSC_DELETED;
4254 fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
4255 fcport->deleted = QLA_SESS_DELETED;
4256 fcport->login_retry = vha->hw->login_retry_count;
4257 fcport->login_retry = 5;
4258 fcport->logout_on_delete = 1;
4259
4260 if (!fcport->ct_desc.ct_sns) {
Quinn Tran83548fe2017-06-02 09:12:01 -07004261 ql_log(ql_log_warn, vha, 0xd049,
Quinn Tran726b8542017-01-19 22:28:00 -08004262 "Failed to allocate ct_sns request.\n");
4263 kfree(fcport);
4264 fcport = NULL;
4265 }
4266 INIT_WORK(&fcport->del_work, qla24xx_delete_sess_fn);
4267 INIT_LIST_HEAD(&fcport->gnl_entry);
4268 INIT_LIST_HEAD(&fcport->list);
4269
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02004270 return fcport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271}
4272
Quinn Tran726b8542017-01-19 22:28:00 -08004273void
4274qla2x00_free_fcport(fc_port_t *fcport)
4275{
4276 if (fcport->ct_desc.ct_sns) {
4277 dma_free_coherent(&fcport->vha->hw->pdev->dev,
4278 sizeof(struct ct_sns_pkt), fcport->ct_desc.ct_sns,
4279 fcport->ct_desc.ct_sns_dma);
4280
4281 fcport->ct_desc.ct_sns = NULL;
4282 }
4283 kfree(fcport);
4284}
4285
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286/*
4287 * qla2x00_configure_loop
4288 * Updates Fibre Channel Device Database with what is actually on loop.
4289 *
4290 * Input:
4291 * ha = adapter block pointer.
4292 *
4293 * Returns:
4294 * 0 = success.
4295 * 1 = error.
4296 * 2 = database was full and device was not configured.
4297 */
4298static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004299qla2x00_configure_loop(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300{
4301 int rval;
4302 unsigned long flags, save_flags;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004303 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304 rval = QLA_SUCCESS;
4305
4306 /* Get Initiator ID */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004307 if (test_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags)) {
4308 rval = qla2x00_configure_hba(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004310 ql_dbg(ql_dbg_disc, vha, 0x2013,
4311 "Unable to configure HBA.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312 return (rval);
4313 }
4314 }
4315
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004316 save_flags = flags = vha->dpc_flags;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004317 ql_dbg(ql_dbg_disc, vha, 0x2014,
4318 "Configure loop -- dpc flags = 0x%lx.\n", flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319
4320 /*
4321 * If we have both an RSCN and PORT UPDATE pending then handle them
4322 * both at the same time.
4323 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004324 clear_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
4325 clear_bit(RSCN_UPDATE, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326
Michael Hernandez3064ff32009-12-15 21:29:44 -08004327 qla2x00_get_data_rate(vha);
4328
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329 /* Determine what we need to do */
4330 if (ha->current_topology == ISP_CFG_FL &&
4331 (test_bit(LOCAL_LOOP_UPDATE, &flags))) {
4332
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333 set_bit(RSCN_UPDATE, &flags);
4334
4335 } else if (ha->current_topology == ISP_CFG_F &&
4336 (test_bit(LOCAL_LOOP_UPDATE, &flags))) {
4337
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 set_bit(RSCN_UPDATE, &flags);
4339 clear_bit(LOCAL_LOOP_UPDATE, &flags);
4340
Andrew Vasquez21333b42006-05-17 15:09:56 -07004341 } else if (ha->current_topology == ISP_CFG_N) {
4342 clear_bit(RSCN_UPDATE, &flags);
Quinn Tran41dc5292017-01-19 22:28:03 -08004343 } else if (ha->current_topology == ISP_CFG_NL) {
4344 clear_bit(RSCN_UPDATE, &flags);
4345 set_bit(LOCAL_LOOP_UPDATE, &flags);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004346 } else if (!vha->flags.online ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347 (test_bit(ABORT_ISP_ACTIVE, &flags))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348 set_bit(RSCN_UPDATE, &flags);
4349 set_bit(LOCAL_LOOP_UPDATE, &flags);
4350 }
4351
4352 if (test_bit(LOCAL_LOOP_UPDATE, &flags)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004353 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
4354 ql_dbg(ql_dbg_disc, vha, 0x2015,
4355 "Loop resync needed, failing.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004356 rval = QLA_FUNCTION_FAILED;
Chad Dupuis642ef982012-02-09 11:15:57 -08004357 } else
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004358 rval = qla2x00_configure_local_loop(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359 }
4360
4361 if (rval == QLA_SUCCESS && test_bit(RSCN_UPDATE, &flags)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004362 if (LOOP_TRANSITION(vha)) {
Quinn Tran83548fe2017-06-02 09:12:01 -07004363 ql_dbg(ql_dbg_disc, vha, 0x2099,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004364 "Needs RSCN update and loop transition.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365 rval = QLA_FUNCTION_FAILED;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004366 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004367 else
4368 rval = qla2x00_configure_fabric(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369 }
4370
4371 if (rval == QLA_SUCCESS) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004372 if (atomic_read(&vha->loop_down_timer) ||
4373 test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374 rval = QLA_FUNCTION_FAILED;
4375 } else {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004376 atomic_set(&vha->loop_state, LOOP_READY);
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004377 ql_dbg(ql_dbg_disc, vha, 0x2069,
4378 "LOOP READY.\n");
Quinn Tranec7193e2017-03-15 09:48:55 -07004379 ha->flags.fw_init_done = 1;
Dilip Kumar Uppugandla3bb67df2015-12-17 14:57:11 -05004380
4381 /*
4382 * Process any ATIO queue entries that came in
4383 * while we weren't online.
4384 */
Quinn Tranead03852017-01-19 22:28:01 -08004385 if (qla_tgt_mode_enabled(vha) ||
4386 qla_dual_mode_enabled(vha)) {
Dilip Kumar Uppugandla3bb67df2015-12-17 14:57:11 -05004387 if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) {
4388 spin_lock_irqsave(&ha->tgt.atio_lock,
4389 flags);
4390 qlt_24xx_process_atio_queue(vha, 0);
4391 spin_unlock_irqrestore(
4392 &ha->tgt.atio_lock, flags);
4393 } else {
4394 spin_lock_irqsave(&ha->hardware_lock,
4395 flags);
4396 qlt_24xx_process_atio_queue(vha, 1);
4397 spin_unlock_irqrestore(
4398 &ha->hardware_lock, flags);
4399 }
4400 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401 }
4402 }
4403
4404 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004405 ql_dbg(ql_dbg_disc, vha, 0x206a,
4406 "%s *** FAILED ***.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004407 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004408 ql_dbg(ql_dbg_disc, vha, 0x206b,
4409 "%s: exiting normally.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410 }
4411
Bjorn Helgaascc3ef7b2008-09-11 21:22:51 -07004412 /* Restore state if a resync event occurred during processing */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004413 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414 if (test_bit(LOCAL_LOOP_UPDATE, &save_flags))
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004415 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
Andrew Vasquezf4658b62009-06-03 09:55:21 -07004416 if (test_bit(RSCN_UPDATE, &save_flags)) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004417 set_bit(RSCN_UPDATE, &vha->dpc_flags);
Andrew Vasquezf4658b62009-06-03 09:55:21 -07004418 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419 }
4420
4421 return (rval);
4422}
4423
Duane Grigsbyedd05de2017-10-13 09:34:06 -07004424/*
4425 * N2N Login
4426 * Updates Fibre Channel Device Database with local loop devices.
4427 *
4428 * Input:
4429 * ha = adapter block pointer.
4430 *
4431 * Returns:
4432 */
4433static int qla24xx_n2n_handle_login(struct scsi_qla_host *vha,
4434 fc_port_t *fcport)
4435{
4436 struct qla_hw_data *ha = vha->hw;
4437 int res = QLA_SUCCESS, rval;
4438 int greater_wwpn = 0;
4439 int logged_in = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440
Duane Grigsbyedd05de2017-10-13 09:34:06 -07004441 if (ha->current_topology != ISP_CFG_N)
4442 return res;
4443
4444 if (wwn_to_u64(vha->port_name) >
4445 wwn_to_u64(vha->n2n_port_name)) {
4446 ql_dbg(ql_dbg_disc, vha, 0x2002,
4447 "HBA WWPN is greater %llx > target %llx\n",
4448 wwn_to_u64(vha->port_name),
4449 wwn_to_u64(vha->n2n_port_name));
4450 greater_wwpn = 1;
4451 fcport->d_id.b24 = vha->n2n_id;
4452 }
4453
4454 fcport->loop_id = vha->loop_id;
4455 fcport->fc4f_nvme = 0;
4456 fcport->query = 1;
4457
4458 ql_dbg(ql_dbg_disc, vha, 0x4001,
4459 "Initiate N2N login handler: HBA port_id=%06x loopid=%d\n",
4460 fcport->d_id.b24, vha->loop_id);
4461
4462 /* Fill in member data. */
4463 if (!greater_wwpn) {
4464 rval = qla2x00_get_port_database(vha, fcport, 0);
4465 ql_dbg(ql_dbg_disc, vha, 0x1051,
4466 "Remote login-state (%x/%x) port_id=%06x loop_id=%x, rval=%d\n",
4467 fcport->current_login_state, fcport->last_login_state,
4468 fcport->d_id.b24, fcport->loop_id, rval);
4469
4470 if (((fcport->current_login_state & 0xf) == 0x4) ||
4471 ((fcport->current_login_state & 0xf) == 0x6))
4472 logged_in = 1;
4473 }
4474
4475 if (logged_in || greater_wwpn) {
4476 if (!vha->nvme_local_port && vha->flags.nvme_enabled)
4477 qla_nvme_register_hba(vha);
4478
4479 /* Set connected N_Port d_id */
4480 if (vha->flags.nvme_enabled)
4481 fcport->fc4f_nvme = 1;
4482
4483 fcport->scan_state = QLA_FCPORT_FOUND;
4484 fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
4485 fcport->disc_state = DSC_GNL;
4486 fcport->n2n_flag = 1;
4487 fcport->flags = 3;
4488 vha->hw->flags.gpsc_supported = 0;
4489
4490 if (greater_wwpn) {
4491 ql_dbg(ql_dbg_disc, vha, 0x20e5,
4492 "%s %d PLOGI ELS %8phC\n",
4493 __func__, __LINE__, fcport->port_name);
4494
4495 res = qla24xx_els_dcmd2_iocb(vha, ELS_DCMD_PLOGI,
4496 fcport, fcport->d_id);
4497 }
4498
4499 if (res != QLA_SUCCESS) {
4500 ql_log(ql_log_info, vha, 0xd04d,
4501 "PLOGI Failed: portid=%06x - retrying\n",
4502 fcport->d_id.b24);
4503 res = QLA_SUCCESS;
4504 } else {
4505 /* State 0x6 means FCP PRLI complete */
4506 if ((fcport->current_login_state & 0xf) == 0x6) {
4507 ql_dbg(ql_dbg_disc, vha, 0x2118,
4508 "%s %d %8phC post GPDB work\n",
4509 __func__, __LINE__, fcport->port_name);
4510 fcport->chip_reset =
4511 vha->hw->base_qpair->chip_reset;
4512 qla24xx_post_gpdb_work(vha, fcport, 0);
4513 } else {
4514 ql_dbg(ql_dbg_disc, vha, 0x2118,
4515 "%s %d %8phC post NVMe PRLI\n",
4516 __func__, __LINE__, fcport->port_name);
4517 qla24xx_post_prli_work(vha, fcport);
4518 }
4519 }
4520 } else {
4521 /* Wait for next database change */
4522 set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags);
4523 }
4524
4525 return res;
4526}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527
4528/*
4529 * qla2x00_configure_local_loop
4530 * Updates Fibre Channel Device Database with local loop devices.
4531 *
4532 * Input:
4533 * ha = adapter block pointer.
4534 *
4535 * Returns:
4536 * 0 = success.
4537 */
4538static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004539qla2x00_configure_local_loop(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540{
4541 int rval, rval2;
4542 int found_devs;
4543 int found;
4544 fc_port_t *fcport, *new_fcport;
4545
4546 uint16_t index;
4547 uint16_t entries;
4548 char *id_iter;
4549 uint16_t loop_id;
4550 uint8_t domain, area, al_pa;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004551 struct qla_hw_data *ha = vha->hw;
Quinn Tran41dc5292017-01-19 22:28:03 -08004552 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004553
4554 found_devs = 0;
4555 new_fcport = NULL;
Chad Dupuis642ef982012-02-09 11:15:57 -08004556 entries = MAX_FIBRE_DEVICES_LOOP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558 /* Get list of logged in devices. */
Chad Dupuis642ef982012-02-09 11:15:57 -08004559 memset(ha->gid_list, 0, qla2x00_gid_list_size(ha));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004560 rval = qla2x00_get_id_list(vha, ha->gid_list, ha->gid_list_dma,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004561 &entries);
4562 if (rval != QLA_SUCCESS)
4563 goto cleanup_allocation;
4564
Quinn Tran83548fe2017-06-02 09:12:01 -07004565 ql_dbg(ql_dbg_disc, vha, 0x2011,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004566 "Entries in ID list (%d).\n", entries);
4567 ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2075,
4568 (uint8_t *)ha->gid_list,
4569 entries * sizeof(struct gid_list_info));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570
4571 /* Allocate temporary fcport for any new fcports discovered. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004572 new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004573 if (new_fcport == NULL) {
Quinn Tran83548fe2017-06-02 09:12:01 -07004574 ql_log(ql_log_warn, vha, 0x2012,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004575 "Memory allocation failed for fcport.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004576 rval = QLA_MEMORY_ALLOC_FAILED;
4577 goto cleanup_allocation;
4578 }
4579 new_fcport->flags &= ~FCF_FABRIC_DEVICE;
4580
4581 /*
4582 * Mark local devices that were present with FCF_DEVICE_LOST for now.
4583 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004584 list_for_each_entry(fcport, &vha->vp_fcports, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004585 if (atomic_read(&fcport->state) == FCS_ONLINE &&
4586 fcport->port_type != FCT_BROADCAST &&
4587 (fcport->flags & FCF_FABRIC_DEVICE) == 0) {
4588
Quinn Tran83548fe2017-06-02 09:12:01 -07004589 ql_dbg(ql_dbg_disc, vha, 0x2096,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004590 "Marking port lost loop_id=0x%04x.\n",
4591 fcport->loop_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592
Quinn Tran41dc5292017-01-19 22:28:03 -08004593 qla2x00_mark_device_lost(vha, fcport, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594 }
4595 }
4596
Duane Grigsbyedd05de2017-10-13 09:34:06 -07004597 /* Inititae N2N login. */
4598 if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) {
4599 rval = qla24xx_n2n_handle_login(vha, new_fcport);
4600 if (rval != QLA_SUCCESS)
4601 goto cleanup_allocation;
4602 return QLA_SUCCESS;
4603 }
4604
Linus Torvalds1da177e2005-04-16 15:20:36 -07004605 /* Add devices to port list. */
4606 id_iter = (char *)ha->gid_list;
4607 for (index = 0; index < entries; index++) {
4608 domain = ((struct gid_list_info *)id_iter)->domain;
4609 area = ((struct gid_list_info *)id_iter)->area;
4610 al_pa = ((struct gid_list_info *)id_iter)->al_pa;
Andrew Vasquezabbd8872005-07-06 10:30:05 -07004611 if (IS_QLA2100(ha) || IS_QLA2200(ha))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004612 loop_id = (uint16_t)
4613 ((struct gid_list_info *)id_iter)->loop_id_2100;
Andrew Vasquezabbd8872005-07-06 10:30:05 -07004614 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004615 loop_id = le16_to_cpu(
4616 ((struct gid_list_info *)id_iter)->loop_id);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07004617 id_iter += ha->gid_list_info_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618
4619 /* Bypass reserved domain fields. */
4620 if ((domain & 0xf0) == 0xf0)
4621 continue;
4622
4623 /* Bypass if not same domain and area of adapter. */
Andrew Vasquezf7d289f2005-08-26 19:08:40 -07004624 if (area && domain &&
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004625 (area != vha->d_id.b.area || domain != vha->d_id.b.domain))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626 continue;
4627
4628 /* Bypass invalid local loop ID. */
4629 if (loop_id > LAST_LOCAL_LOOP_ID)
4630 continue;
4631
Quinn Tran41dc5292017-01-19 22:28:03 -08004632 memset(new_fcport->port_name, 0, WWN_SIZE);
Arun Easi370d5502012-08-22 14:21:10 -04004633
Linus Torvalds1da177e2005-04-16 15:20:36 -07004634 /* Fill in member data. */
4635 new_fcport->d_id.b.domain = domain;
4636 new_fcport->d_id.b.area = area;
4637 new_fcport->d_id.b.al_pa = al_pa;
4638 new_fcport->loop_id = loop_id;
Quinn Tran41dc5292017-01-19 22:28:03 -08004639
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004640 rval2 = qla2x00_get_port_database(vha, new_fcport, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004641 if (rval2 != QLA_SUCCESS) {
Quinn Tran83548fe2017-06-02 09:12:01 -07004642 ql_dbg(ql_dbg_disc, vha, 0x2097,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004643 "Failed to retrieve fcport information "
4644 "-- get_port_database=%x, loop_id=0x%04x.\n",
4645 rval2, new_fcport->loop_id);
Duane Grigsbyedd05de2017-10-13 09:34:06 -07004646 /* Skip retry if N2N */
4647 if (ha->current_topology != ISP_CFG_N) {
4648 ql_dbg(ql_dbg_disc, vha, 0x2105,
4649 "Scheduling resync.\n");
4650 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
4651 continue;
4652 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004653 }
4654
Quinn Tran41dc5292017-01-19 22:28:03 -08004655 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656 /* Check for matching device in port list. */
4657 found = 0;
4658 fcport = NULL;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004659 list_for_each_entry(fcport, &vha->vp_fcports, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004660 if (memcmp(new_fcport->port_name, fcport->port_name,
4661 WWN_SIZE))
4662 continue;
4663
Shyam Sundarddb9b122009-03-24 09:08:10 -07004664 fcport->flags &= ~FCF_FABRIC_DEVICE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004665 fcport->loop_id = new_fcport->loop_id;
4666 fcport->port_type = new_fcport->port_type;
4667 fcport->d_id.b24 = new_fcport->d_id.b24;
4668 memcpy(fcport->node_name, new_fcport->node_name,
4669 WWN_SIZE);
4670
Quinn Tran41dc5292017-01-19 22:28:03 -08004671 if (!fcport->login_succ) {
4672 vha->fcport_count++;
4673 fcport->login_succ = 1;
4674 fcport->disc_state = DSC_LOGIN_COMPLETE;
4675 }
4676
Linus Torvalds1da177e2005-04-16 15:20:36 -07004677 found++;
4678 break;
4679 }
4680
4681 if (!found) {
4682 /* New device, add to fcports list. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004683 list_add_tail(&new_fcport->list, &vha->vp_fcports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004684
4685 /* Allocate a new replacement fcport. */
4686 fcport = new_fcport;
Quinn Tran41dc5292017-01-19 22:28:03 -08004687 if (!fcport->login_succ) {
4688 vha->fcport_count++;
4689 fcport->login_succ = 1;
4690 fcport->disc_state = DSC_LOGIN_COMPLETE;
4691 }
4692
4693 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
4694
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004695 new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
Quinn Tran41dc5292017-01-19 22:28:03 -08004696
Linus Torvalds1da177e2005-04-16 15:20:36 -07004697 if (new_fcport == NULL) {
Quinn Tran83548fe2017-06-02 09:12:01 -07004698 ql_log(ql_log_warn, vha, 0xd031,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004699 "Failed to allocate memory for fcport.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004700 rval = QLA_MEMORY_ALLOC_FAILED;
4701 goto cleanup_allocation;
4702 }
Quinn Tran41dc5292017-01-19 22:28:03 -08004703 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004704 new_fcport->flags &= ~FCF_FABRIC_DEVICE;
4705 }
4706
Quinn Tran41dc5292017-01-19 22:28:03 -08004707 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
4708
Andrew Vasquezd8b45212006-10-02 12:00:43 -07004709 /* Base iIDMA settings on HBA port speed. */
Andrew Vasqueza3cbdfa2007-08-13 10:13:18 -07004710 fcport->fp_speed = ha->link_data_rate;
Andrew Vasquezd8b45212006-10-02 12:00:43 -07004711
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004712 qla2x00_update_fcport(vha, fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004713
4714 found_devs++;
4715 }
4716
4717cleanup_allocation:
Jesper Juhlc9475cb2005-11-07 01:01:26 -08004718 kfree(new_fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004719
4720 if (rval != QLA_SUCCESS) {
Quinn Tran83548fe2017-06-02 09:12:01 -07004721 ql_dbg(ql_dbg_disc, vha, 0x2098,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004722 "Configure local loop error exit: rval=%x.\n", rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004723 }
4724
Linus Torvalds1da177e2005-04-16 15:20:36 -07004725 return (rval);
4726}
4727
4728static void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004729qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
Andrew Vasquezd8b45212006-10-02 12:00:43 -07004730{
Andrew Vasquezd8b45212006-10-02 12:00:43 -07004731 int rval;
Quinn Tran93f2bd62014-09-25 05:16:53 -04004732 uint16_t mb[MAILBOX_REGISTER_COUNT];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004733 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezd8b45212006-10-02 12:00:43 -07004734
Andrew Vasquezc76f2c02007-07-19 15:05:57 -07004735 if (!IS_IIDMA_CAPABLE(ha))
Andrew Vasquezd8b45212006-10-02 12:00:43 -07004736 return;
4737
Giridhar Malavalic9afb9a2010-09-03 15:20:48 -07004738 if (atomic_read(&fcport->state) != FCS_ONLINE)
4739 return;
4740
Andrew Vasquez39bd9622007-09-20 14:07:34 -07004741 if (fcport->fp_speed == PORT_SPEED_UNKNOWN ||
4742 fcport->fp_speed > ha->link_data_rate)
Andrew Vasquezd8b45212006-10-02 12:00:43 -07004743 return;
4744
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004745 rval = qla2x00_set_idma_speed(vha, fcport->loop_id, fcport->fp_speed,
Andrew Vasqueza3cbdfa2007-08-13 10:13:18 -07004746 mb);
Andrew Vasquezd8b45212006-10-02 12:00:43 -07004747 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004748 ql_dbg(ql_dbg_disc, vha, 0x2004,
Oleksandr Khoshaba7b8335582013-08-27 01:37:27 -04004749 "Unable to adjust iIDMA %8phN -- %04x %x %04x %04x.\n",
4750 fcport->port_name, rval, fcport->fp_speed, mb[0], mb[1]);
Andrew Vasquezd8b45212006-10-02 12:00:43 -07004751 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004752 ql_dbg(ql_dbg_disc, vha, 0x2005,
Oleksandr Khoshaba7b8335582013-08-27 01:37:27 -04004753 "iIDMA adjusted to %s GB/s on %8phN.\n",
Joe Carnucciod0297c92012-11-21 02:40:40 -05004754 qla2x00_get_link_speed_str(ha, fcport->fp_speed),
Oleksandr Khoshaba7b8335582013-08-27 01:37:27 -04004755 fcport->port_name);
Andrew Vasquezd8b45212006-10-02 12:00:43 -07004756 }
4757}
4758
Quinn Tran726b8542017-01-19 22:28:00 -08004759/* qla2x00_reg_remote_port is reserved for Initiator Mode only.*/
Adrian Bunk23be3312006-11-24 02:46:01 +01004760static void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004761qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
8482e1182005-04-17 15:04:54 -05004762{
4763 struct fc_rport_identifiers rport_ids;
bdf79622005-04-17 15:06:53 -05004764 struct fc_rport *rport;
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08004765 unsigned long flags;
8482e1182005-04-17 15:04:54 -05004766
Andrew Vasquezf8b02a82005-08-31 15:21:20 -07004767 rport_ids.node_name = wwn_to_u64(fcport->node_name);
4768 rport_ids.port_name = wwn_to_u64(fcport->port_name);
8482e1182005-04-17 15:04:54 -05004769 rport_ids.port_id = fcport->d_id.b.domain << 16 |
4770 fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
4771 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004772 fcport->rport = rport = fc_remote_port_add(vha->host, 0, &rport_ids);
Andrew Vasquez77d74142005-07-08 18:00:36 -07004773 if (!rport) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004774 ql_log(ql_log_warn, vha, 0x2006,
4775 "Unable to allocate fc remote port.\n");
Andrew Vasquez77d74142005-07-08 18:00:36 -07004776 return;
4777 }
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04004778
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08004779 spin_lock_irqsave(fcport->vha->host->host_lock, flags);
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04004780 *((fc_port_t **)rport->dd_data) = fcport;
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08004781 spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08004782
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07004783 rport->supported_classes = fcport->supported_classes;
Andrew Vasquez77d74142005-07-08 18:00:36 -07004784
4785 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
8482e1182005-04-17 15:04:54 -05004786 if (fcport->port_type == FCT_INITIATOR)
4787 rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
4788 if (fcport->port_type == FCT_TARGET)
4789 rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
Quinn Tran726b8542017-01-19 22:28:00 -08004790
Quinn Tran83548fe2017-06-02 09:12:01 -07004791 ql_dbg(ql_dbg_disc, vha, 0x20ee,
4792 "%s %8phN. rport %p is %s mode\n",
4793 __func__, fcport->port_name, rport,
4794 (fcport->port_type == FCT_TARGET) ? "tgt" : "ini");
Quinn Tran726b8542017-01-19 22:28:00 -08004795
Andrew Vasquez77d74142005-07-08 18:00:36 -07004796 fc_remote_port_rolechg(rport, rport_ids.roles);
8482e1182005-04-17 15:04:54 -05004797}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004798
4799/*
Adrian Bunk23be3312006-11-24 02:46:01 +01004800 * qla2x00_update_fcport
4801 * Updates device on list.
4802 *
4803 * Input:
4804 * ha = adapter block pointer.
4805 * fcport = port structure pointer.
4806 *
4807 * Return:
4808 * 0 - Success
4809 * BIT_0 - error
4810 *
4811 * Context:
4812 * Kernel context.
4813 */
4814void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004815qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
Adrian Bunk23be3312006-11-24 02:46:01 +01004816{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004817 fcport->vha = vha;
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04004818
Quinn Tran726b8542017-01-19 22:28:00 -08004819 if (IS_SW_RESV_ADDR(fcport->d_id))
4820 return;
4821
Quinn Tran83548fe2017-06-02 09:12:01 -07004822 ql_dbg(ql_dbg_disc, vha, 0x20ef, "%s %8phC\n",
Quinn Tran726b8542017-01-19 22:28:00 -08004823 __func__, fcport->port_name);
4824
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04004825 if (IS_QLAFX00(vha->hw)) {
4826 qla2x00_set_fcport_state(fcport, FCS_ONLINE);
Alexei Potashnikd20ed912015-07-14 16:00:47 -04004827 goto reg_port;
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04004828 }
Adrian Bunk23be3312006-11-24 02:46:01 +01004829 fcport->login_retry = 0;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07004830 fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
Quinn Tran726b8542017-01-19 22:28:00 -08004831 fcport->disc_state = DSC_LOGIN_COMPLETE;
4832 fcport->deleted = 0;
4833 fcport->logout_on_delete = 1;
Adrian Bunk23be3312006-11-24 02:46:01 +01004834
Duane Grigsbye84067d2017-06-21 13:48:43 -07004835 if (fcport->fc4f_nvme) {
4836 qla_nvme_register_remote(vha, fcport);
4837 return;
4838 }
4839
Joe Carnuccio1f93da522012-11-21 02:40:38 -05004840 qla2x00_set_fcport_state(fcport, FCS_ONLINE);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004841 qla2x00_iidma_fcport(vha, fcport);
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08004842 qla24xx_update_fcport_fcp_prio(vha, fcport);
Alexei Potashnikd20ed912015-07-14 16:00:47 -04004843
4844reg_port:
Quinn Tran726b8542017-01-19 22:28:00 -08004845 switch (vha->host->active_mode) {
4846 case MODE_INITIATOR:
Alexei Potashnikd20ed912015-07-14 16:00:47 -04004847 qla2x00_reg_remote_port(vha, fcport);
Quinn Tran726b8542017-01-19 22:28:00 -08004848 break;
4849 case MODE_TARGET:
4850 if (!vha->vha_tgt.qla_tgt->tgt_stop &&
4851 !vha->vha_tgt.qla_tgt->tgt_stopped)
4852 qlt_fc_port_added(vha, fcport);
4853 break;
4854 case MODE_DUAL:
4855 qla2x00_reg_remote_port(vha, fcport);
4856 if (!vha->vha_tgt.qla_tgt->tgt_stop &&
4857 !vha->vha_tgt.qla_tgt->tgt_stopped)
4858 qlt_fc_port_added(vha, fcport);
4859 break;
4860 default:
4861 break;
Alexei Potashnikd20ed912015-07-14 16:00:47 -04004862 }
Adrian Bunk23be3312006-11-24 02:46:01 +01004863}
4864
4865/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07004866 * qla2x00_configure_fabric
4867 * Setup SNS devices with loop ID's.
4868 *
4869 * Input:
4870 * ha = adapter block pointer.
4871 *
4872 * Returns:
4873 * 0 = success.
4874 * BIT_0 = error
4875 */
4876static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004877qla2x00_configure_fabric(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004878{
Arun Easib3b02e62012-02-09 11:15:39 -08004879 int rval;
Quinn Tran726b8542017-01-19 22:28:00 -08004880 fc_port_t *fcport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004881 uint16_t mb[MAILBOX_REGISTER_COUNT];
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004882 uint16_t loop_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004883 LIST_HEAD(new_fcports);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004884 struct qla_hw_data *ha = vha->hw;
Alexei Potashnikdf673272015-07-14 16:00:46 -04004885 int discovery_gen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004886
4887 /* If FL port exists, then SNS is present */
Andrew Vasqueze4289242007-07-19 15:05:56 -07004888 if (IS_FWI2_CAPABLE(ha))
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004889 loop_id = NPH_F_PORT;
4890 else
4891 loop_id = SNS_FL_PORT;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004892 rval = qla2x00_get_port_name(vha, loop_id, vha->fabric_node_name, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004893 if (rval != QLA_SUCCESS) {
Quinn Tran83548fe2017-06-02 09:12:01 -07004894 ql_dbg(ql_dbg_disc, vha, 0x20a0,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004895 "MBX_GET_PORT_NAME failed, No FL Port.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004896
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004897 vha->device_flags &= ~SWITCH_FOUND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004898 return (QLA_SUCCESS);
4899 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004900 vha->device_flags |= SWITCH_FOUND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004901
Quinn Tran41dc5292017-01-19 22:28:03 -08004902
4903 if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) {
4904 rval = qla2x00_send_change_request(vha, 0x3, 0);
4905 if (rval != QLA_SUCCESS)
4906 ql_log(ql_log_warn, vha, 0x121,
4907 "Failed to enable receiving of RSCN requests: 0x%x.\n",
4908 rval);
4909 }
4910
4911
Linus Torvalds1da177e2005-04-16 15:20:36 -07004912 do {
Quinn Tran726b8542017-01-19 22:28:00 -08004913 qla2x00_mgmt_svr_login(vha);
4914
Andrew Vasquezcca53352005-08-26 19:08:30 -07004915 /* FDMI support. */
4916 if (ql2xfdmienable &&
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004917 test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags))
4918 qla2x00_fdmi_register(vha);
Andrew Vasquezcca53352005-08-26 19:08:30 -07004919
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920 /* Ensure we are logged into the SNS. */
Joe Carnuccioa14c7712017-08-23 15:05:12 -07004921 loop_id = NPH_SNS_LID(ha);
Chad Dupuis0b91d112012-02-09 11:15:42 -08004922 rval = ha->isp_ops->fabric_login(vha, loop_id, 0xff, 0xff,
4923 0xfc, mb, BIT_1|BIT_0);
Joe Carnuccioa14c7712017-08-23 15:05:12 -07004924 if (rval != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {
4925 ql_dbg(ql_dbg_disc, vha, 0x20a1,
4926 "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x (%x).\n",
4927 loop_id, mb[0], mb[1], mb[2], mb[6], mb[7], rval);
Chad Dupuis0b91d112012-02-09 11:15:42 -08004928 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
Joe Carnuccioe452ceb2013-02-08 01:57:56 -05004929 return rval;
Chad Dupuis0b91d112012-02-09 11:15:42 -08004930 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004931 if (test_and_clear_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags)) {
4932 if (qla2x00_rft_id(vha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004933 /* EMPTY */
Quinn Tran83548fe2017-06-02 09:12:01 -07004934 ql_dbg(ql_dbg_disc, vha, 0x20a2,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004935 "Register FC-4 TYPE failed.\n");
Quinn Tranb98ae0d2017-06-02 09:12:00 -07004936 if (test_bit(LOOP_RESYNC_NEEDED,
4937 &vha->dpc_flags))
4938 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004939 }
Duane Grigsbyd3bae932017-06-21 13:48:44 -07004940 if (qla2x00_rff_id(vha, FC4_TYPE_FCP_SCSI)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004941 /* EMPTY */
Quinn Tran83548fe2017-06-02 09:12:01 -07004942 ql_dbg(ql_dbg_disc, vha, 0x209a,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004943 "Register FC-4 Features failed.\n");
Quinn Tranb98ae0d2017-06-02 09:12:00 -07004944 if (test_bit(LOOP_RESYNC_NEEDED,
4945 &vha->dpc_flags))
4946 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004947 }
Duane Grigsbyd3bae932017-06-21 13:48:44 -07004948 if (vha->flags.nvme_enabled) {
4949 if (qla2x00_rff_id(vha, FC_TYPE_NVME)) {
4950 ql_dbg(ql_dbg_disc, vha, 0x2049,
4951 "Register NVME FC Type Features failed.\n");
4952 }
4953 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004954 if (qla2x00_rnn_id(vha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004955 /* EMPTY */
Quinn Tran83548fe2017-06-02 09:12:01 -07004956 ql_dbg(ql_dbg_disc, vha, 0x2104,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004957 "Register Node Name failed.\n");
Quinn Tranb98ae0d2017-06-02 09:12:00 -07004958 if (test_bit(LOOP_RESYNC_NEEDED,
4959 &vha->dpc_flags))
4960 break;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004961 } else if (qla2x00_rsnn_nn(vha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004962 /* EMPTY */
Quinn Tran83548fe2017-06-02 09:12:01 -07004963 ql_dbg(ql_dbg_disc, vha, 0x209b,
Colin Ian King0bf0efa2017-06-30 14:47:41 +01004964 "Register Symbolic Node Name failed.\n");
Quinn Tranb98ae0d2017-06-02 09:12:00 -07004965 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
4966 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004967 }
4968 }
4969
Joe Carnuccio827210b2013-02-08 01:57:57 -05004970 list_for_each_entry(fcport, &vha->vp_fcports, list) {
4971 fcport->scan_state = QLA_FCPORT_SCAN;
4972 }
4973
Alexei Potashnikdf673272015-07-14 16:00:46 -04004974 /* Mark the time right before querying FW for connected ports.
4975 * This process is long, asynchronous and by the time it's done,
4976 * collected information might not be accurate anymore. E.g.
4977 * disconnected port might have re-connected and a brand new
4978 * session has been created. In this case session's generation
4979 * will be newer than discovery_gen. */
4980 qlt_do_generation_tick(vha, &discovery_gen);
4981
Quinn Tran726b8542017-01-19 22:28:00 -08004982 rval = qla2x00_find_all_fabric_devs(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004983 if (rval != QLA_SUCCESS)
4984 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004985 } while (0);
4986
Duane Grigsbye84067d2017-06-21 13:48:43 -07004987 if (!vha->nvme_local_port && vha->flags.nvme_enabled)
4988 qla_nvme_register_hba(vha);
4989
Quinn Tran726b8542017-01-19 22:28:00 -08004990 if (rval)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004991 ql_dbg(ql_dbg_disc, vha, 0x2068,
4992 "Configure fabric error exit rval=%d.\n", rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004993
4994 return (rval);
4995}
4996
Linus Torvalds1da177e2005-04-16 15:20:36 -07004997/*
4998 * qla2x00_find_all_fabric_devs
4999 *
5000 * Input:
5001 * ha = adapter block pointer.
5002 * dev = database device entry pointer.
5003 *
5004 * Returns:
5005 * 0 = success.
5006 *
5007 * Context:
5008 * Kernel context.
5009 */
5010static int
Quinn Tran726b8542017-01-19 22:28:00 -08005011qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005012{
5013 int rval;
5014 uint16_t loop_id;
Quinn Tran726b8542017-01-19 22:28:00 -08005015 fc_port_t *fcport, *new_fcport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005016 int found;
5017
5018 sw_info_t *swl;
5019 int swl_idx;
5020 int first_dev, last_dev;
Mike Waychison1516ef42010-05-04 15:01:31 -07005021 port_id_t wrap = {}, nxt_d_id;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005022 struct qla_hw_data *ha = vha->hw;
Chad Dupuisbb4cf5b2013-02-08 01:58:01 -05005023 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Quinn Tran726b8542017-01-19 22:28:00 -08005024 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005025
5026 rval = QLA_SUCCESS;
5027
5028 /* Try GID_PT to get device list, else GAN. */
Andrew Vasquez7a677352012-02-09 11:15:56 -08005029 if (!ha->swl)
Chad Dupuis642ef982012-02-09 11:15:57 -08005030 ha->swl = kcalloc(ha->max_fibre_devices, sizeof(sw_info_t),
Andrew Vasquez7a677352012-02-09 11:15:56 -08005031 GFP_KERNEL);
5032 swl = ha->swl;
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02005033 if (!swl) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005034 /*EMPTY*/
Quinn Tran83548fe2017-06-02 09:12:01 -07005035 ql_dbg(ql_dbg_disc, vha, 0x209c,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005036 "GID_PT allocations failed, fallback on GA_NXT.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005037 } else {
Chad Dupuis642ef982012-02-09 11:15:57 -08005038 memset(swl, 0, ha->max_fibre_devices * sizeof(sw_info_t));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005039 if (qla2x00_gid_pt(vha, swl) != QLA_SUCCESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040 swl = NULL;
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005041 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
5042 return rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005043 } else if (qla2x00_gpn_id(vha, swl) != QLA_SUCCESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005044 swl = NULL;
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005045 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
5046 return rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005047 } else if (qla2x00_gnn_id(vha, swl) != QLA_SUCCESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005048 swl = NULL;
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005049 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
5050 return rval;
Quinn Tran726b8542017-01-19 22:28:00 -08005051 } else if (qla2x00_gfpn_id(vha, swl) != QLA_SUCCESS) {
5052 swl = NULL;
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005053 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
5054 return rval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055 }
Chad Dupuise8c72ba2010-07-23 15:28:25 +05005056
5057 /* If other queries succeeded probe for FC-4 type */
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005058 if (swl) {
Chad Dupuise8c72ba2010-07-23 15:28:25 +05005059 qla2x00_gff_id(vha, swl);
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005060 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
5061 return rval;
5062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005063 }
5064 swl_idx = 0;
5065
5066 /* Allocate temporary fcport for any new fcports discovered. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005067 new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068 if (new_fcport == NULL) {
Quinn Tran83548fe2017-06-02 09:12:01 -07005069 ql_log(ql_log_warn, vha, 0x209d,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005070 "Failed to allocate memory for fcport.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005071 return (QLA_MEMORY_ALLOC_FAILED);
5072 }
5073 new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005074 /* Set start port ID scan at adapter ID. */
5075 first_dev = 1;
5076 last_dev = 0;
5077
5078 /* Starting free loop ID. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005079 loop_id = ha->min_external_loopid;
5080 for (; loop_id <= ha->max_loop_id; loop_id++) {
5081 if (qla2x00_is_reserved_id(vha, loop_id))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005082 continue;
5083
Giridhar Malavali3a6478d2010-05-28 15:08:20 -07005084 if (ha->current_topology == ISP_CFG_FL &&
5085 (atomic_read(&vha->loop_down_timer) ||
5086 LOOP_TRANSITION(vha))) {
Andrew Vasquezbb2d52b2010-02-18 10:07:27 -08005087 atomic_set(&vha->loop_down_timer, 0);
5088 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
5089 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005090 break;
Andrew Vasquezbb2d52b2010-02-18 10:07:27 -08005091 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005092
5093 if (swl != NULL) {
5094 if (last_dev) {
5095 wrap.b24 = new_fcport->d_id.b24;
5096 } else {
5097 new_fcport->d_id.b24 = swl[swl_idx].d_id.b24;
5098 memcpy(new_fcport->node_name,
5099 swl[swl_idx].node_name, WWN_SIZE);
5100 memcpy(new_fcport->port_name,
5101 swl[swl_idx].port_name, WWN_SIZE);
Andrew Vasquezd8b45212006-10-02 12:00:43 -07005102 memcpy(new_fcport->fabric_port_name,
5103 swl[swl_idx].fabric_port_name, WWN_SIZE);
5104 new_fcport->fp_speed = swl[swl_idx].fp_speed;
Chad Dupuise8c72ba2010-07-23 15:28:25 +05005105 new_fcport->fc4_type = swl[swl_idx].fc4_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005106
Duane Grigsbya5d42f42017-06-21 13:48:41 -07005107 new_fcport->nvme_flag = 0;
Darren Trap1a28faa2017-08-30 10:16:48 -07005108 new_fcport->fc4f_nvme = 0;
Duane Grigsbya5d42f42017-06-21 13:48:41 -07005109 if (vha->flags.nvme_enabled &&
5110 swl[swl_idx].fc4f_nvme) {
5111 new_fcport->fc4f_nvme =
5112 swl[swl_idx].fc4f_nvme;
5113 ql_log(ql_log_info, vha, 0x2131,
5114 "FOUND: NVME port %8phC as FC Type 28h\n",
5115 new_fcport->port_name);
5116 }
5117
Linus Torvalds1da177e2005-04-16 15:20:36 -07005118 if (swl[swl_idx].d_id.b.rsvd_1 != 0) {
5119 last_dev = 1;
5120 }
5121 swl_idx++;
5122 }
5123 } else {
5124 /* Send GA_NXT to the switch */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005125 rval = qla2x00_ga_nxt(vha, new_fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005126 if (rval != QLA_SUCCESS) {
Quinn Tran83548fe2017-06-02 09:12:01 -07005127 ql_log(ql_log_warn, vha, 0x209e,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005128 "SNS scan failed -- assuming "
5129 "zero-entry result.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005130 rval = QLA_SUCCESS;
5131 break;
5132 }
5133 }
5134
5135 /* If wrap on switch device list, exit. */
5136 if (first_dev) {
5137 wrap.b24 = new_fcport->d_id.b24;
5138 first_dev = 0;
5139 } else if (new_fcport->d_id.b24 == wrap.b24) {
Quinn Tran83548fe2017-06-02 09:12:01 -07005140 ql_dbg(ql_dbg_disc, vha, 0x209f,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005141 "Device wrap (%02x%02x%02x).\n",
5142 new_fcport->d_id.b.domain,
5143 new_fcport->d_id.b.area,
5144 new_fcport->d_id.b.al_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005145 break;
5146 }
5147
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07005148 /* Bypass if same physical adapter. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005149 if (new_fcport->d_id.b24 == base_vha->d_id.b24)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005150 continue;
5151
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07005152 /* Bypass virtual ports of the same host. */
Chad Dupuisbb4cf5b2013-02-08 01:58:01 -05005153 if (qla2x00_is_a_vp_did(vha, new_fcport->d_id.b24))
5154 continue;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07005155
Andrew Vasquezf7d289f2005-08-26 19:08:40 -07005156 /* Bypass if same domain and area of adapter. */
5157 if (((new_fcport->d_id.b24 & 0xffff00) ==
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005158 (vha->d_id.b24 & 0xffff00)) && ha->current_topology ==
Andrew Vasquezf7d289f2005-08-26 19:08:40 -07005159 ISP_CFG_FL)
5160 continue;
5161
Linus Torvalds1da177e2005-04-16 15:20:36 -07005162 /* Bypass reserved domain fields. */
5163 if ((new_fcport->d_id.b.domain & 0xf0) == 0xf0)
5164 continue;
5165
Chad Dupuise8c72ba2010-07-23 15:28:25 +05005166 /* Bypass ports whose FCP-4 type is not FCP_SCSI */
Chad Dupuis4da26e12010-10-15 11:27:40 -07005167 if (ql2xgffidenable &&
5168 (new_fcport->fc4_type != FC4_TYPE_FCP_SCSI &&
5169 new_fcport->fc4_type != FC4_TYPE_UNKNOWN))
Chad Dupuise8c72ba2010-07-23 15:28:25 +05005170 continue;
5171
Quinn Tran726b8542017-01-19 22:28:00 -08005172 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
5173
Linus Torvalds1da177e2005-04-16 15:20:36 -07005174 /* Locate matching device in database. */
5175 found = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005176 list_for_each_entry(fcport, &vha->vp_fcports, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005177 if (memcmp(new_fcport->port_name, fcport->port_name,
5178 WWN_SIZE))
5179 continue;
5180
Joe Carnuccio827210b2013-02-08 01:57:57 -05005181 fcport->scan_state = QLA_FCPORT_FOUND;
Arun Easib3b02e62012-02-09 11:15:39 -08005182
Linus Torvalds1da177e2005-04-16 15:20:36 -07005183 found++;
5184
Andrew Vasquezd8b45212006-10-02 12:00:43 -07005185 /* Update port state. */
5186 memcpy(fcport->fabric_port_name,
5187 new_fcport->fabric_port_name, WWN_SIZE);
5188 fcport->fp_speed = new_fcport->fp_speed;
5189
Linus Torvalds1da177e2005-04-16 15:20:36 -07005190 /*
Roland Dreierb2032fd2015-07-14 16:00:42 -04005191 * If address the same and state FCS_ONLINE
5192 * (or in target mode), nothing changed.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005193 */
5194 if (fcport->d_id.b24 == new_fcport->d_id.b24 &&
Roland Dreierb2032fd2015-07-14 16:00:42 -04005195 (atomic_read(&fcport->state) == FCS_ONLINE ||
Quinn Tran726b8542017-01-19 22:28:00 -08005196 (vha->host->active_mode == MODE_TARGET))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005197 break;
5198 }
5199
5200 /*
5201 * If device was not a fabric device before.
5202 */
5203 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
5204 fcport->d_id.b24 = new_fcport->d_id.b24;
Chad Dupuis5f16b332012-08-22 14:21:00 -04005205 qla2x00_clear_loop_id(fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005206 fcport->flags |= (FCF_FABRIC_DEVICE |
5207 FCF_LOGIN_NEEDED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005208 break;
5209 }
5210
5211 /*
5212 * Port ID changed or device was marked to be updated;
5213 * Log it out if still logged in and mark it for
5214 * relogin later.
5215 */
Quinn Tran726b8542017-01-19 22:28:00 -08005216 if (qla_tgt_mode_enabled(base_vha)) {
Roland Dreierb2032fd2015-07-14 16:00:42 -04005217 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf080,
5218 "port changed FC ID, %8phC"
5219 " old %x:%x:%x (loop_id 0x%04x)-> new %x:%x:%x\n",
5220 fcport->port_name,
5221 fcport->d_id.b.domain,
5222 fcport->d_id.b.area,
5223 fcport->d_id.b.al_pa,
5224 fcport->loop_id,
5225 new_fcport->d_id.b.domain,
5226 new_fcport->d_id.b.area,
5227 new_fcport->d_id.b.al_pa);
5228 fcport->d_id.b24 = new_fcport->d_id.b24;
5229 break;
5230 }
5231
Linus Torvalds1da177e2005-04-16 15:20:36 -07005232 fcport->d_id.b24 = new_fcport->d_id.b24;
5233 fcport->flags |= FCF_LOGIN_NEEDED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005234 break;
5235 }
5236
Quinn Tran726b8542017-01-19 22:28:00 -08005237 if (found) {
5238 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005239 continue;
Quinn Tran726b8542017-01-19 22:28:00 -08005240 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005241 /* If device was not in our fcports list, then add it. */
Roland Dreierb2032fd2015-07-14 16:00:42 -04005242 new_fcport->scan_state = QLA_FCPORT_FOUND;
Quinn Tran726b8542017-01-19 22:28:00 -08005243 list_add_tail(&new_fcport->list, &vha->vp_fcports);
5244
5245 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
5246
Linus Torvalds1da177e2005-04-16 15:20:36 -07005247
5248 /* Allocate a new replacement fcport. */
5249 nxt_d_id.b24 = new_fcport->d_id.b24;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005250 new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251 if (new_fcport == NULL) {
Quinn Tran83548fe2017-06-02 09:12:01 -07005252 ql_log(ql_log_warn, vha, 0xd032,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005253 "Memory allocation failed for fcport.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005254 return (QLA_MEMORY_ALLOC_FAILED);
5255 }
5256 new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED);
5257 new_fcport->d_id.b24 = nxt_d_id.b24;
5258 }
5259
Quinn Tran726b8542017-01-19 22:28:00 -08005260 qla2x00_free_fcport(new_fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005261
Quinn Tran726b8542017-01-19 22:28:00 -08005262 /*
5263 * Logout all previous fabric dev marked lost, except FCP2 devices.
5264 */
5265 list_for_each_entry(fcport, &vha->vp_fcports, list) {
5266 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
5267 break;
5268
5269 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
5270 (fcport->flags & FCF_LOGIN_NEEDED) == 0)
5271 continue;
5272
5273 if (fcport->scan_state == QLA_FCPORT_SCAN) {
5274 if ((qla_dual_mode_enabled(vha) ||
5275 qla_ini_mode_enabled(vha)) &&
5276 atomic_read(&fcport->state) == FCS_ONLINE) {
5277 qla2x00_mark_device_lost(vha, fcport,
5278 ql2xplogiabsentdevice, 0);
5279 if (fcport->loop_id != FC_NO_LOOP_ID &&
5280 (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
5281 fcport->port_type != FCT_INITIATOR &&
5282 fcport->port_type != FCT_BROADCAST) {
Quinn Tran83548fe2017-06-02 09:12:01 -07005283 ql_dbg(ql_dbg_disc, vha, 0x20f0,
Quinn Tran726b8542017-01-19 22:28:00 -08005284 "%s %d %8phC post del sess\n",
5285 __func__, __LINE__,
5286 fcport->port_name);
5287
5288 qlt_schedule_sess_for_deletion_lock
5289 (fcport);
5290 continue;
5291 }
5292 }
5293 }
5294
5295 if (fcport->scan_state == QLA_FCPORT_FOUND)
5296 qla24xx_fcport_handle_login(vha, fcport);
5297 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005298 return (rval);
5299}
5300
5301/*
5302 * qla2x00_find_new_loop_id
5303 * Scan through our port list and find a new usable loop ID.
5304 *
5305 * Input:
5306 * ha: adapter state pointer.
5307 * dev: port structure pointer.
5308 *
5309 * Returns:
5310 * qla2x00 local function return status code.
5311 *
5312 * Context:
5313 * Kernel context.
5314 */
Joe Carnuccio03bcfb52011-03-30 11:46:27 -07005315int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005316qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005317{
5318 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005319 struct qla_hw_data *ha = vha->hw;
Arun Easifeafb7b2010-09-03 14:57:00 -07005320 unsigned long flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005321
5322 rval = QLA_SUCCESS;
5323
Chad Dupuis5f16b332012-08-22 14:21:00 -04005324 spin_lock_irqsave(&ha->vport_slock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005325
Chad Dupuis5f16b332012-08-22 14:21:00 -04005326 dev->loop_id = find_first_zero_bit(ha->loop_id_map,
5327 LOOPID_MAP_SIZE);
5328 if (dev->loop_id >= LOOPID_MAP_SIZE ||
5329 qla2x00_is_reserved_id(vha, dev->loop_id)) {
5330 dev->loop_id = FC_NO_LOOP_ID;
5331 rval = QLA_FUNCTION_FAILED;
5332 } else
5333 set_bit(dev->loop_id, ha->loop_id_map);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005334
Chad Dupuis5f16b332012-08-22 14:21:00 -04005335 spin_unlock_irqrestore(&ha->vport_slock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005336
Chad Dupuis5f16b332012-08-22 14:21:00 -04005337 if (rval == QLA_SUCCESS)
5338 ql_dbg(ql_dbg_disc, dev->vha, 0x2086,
5339 "Assigning new loopid=%x, portid=%x.\n",
5340 dev->loop_id, dev->d_id.b24);
5341 else
5342 ql_log(ql_log_warn, dev->vha, 0x2087,
5343 "No loop_id's available, portid=%x.\n",
5344 dev->d_id.b24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005345
5346 return (rval);
5347}
5348
Linus Torvalds1da177e2005-04-16 15:20:36 -07005349
5350/*
5351 * qla2x00_fabric_login
5352 * Issue fabric login command.
5353 *
5354 * Input:
5355 * ha = adapter block pointer.
5356 * device = pointer to FC device type structure.
5357 *
5358 * Returns:
5359 * 0 - Login successfully
5360 * 1 - Login failed
5361 * 2 - Initiator device
5362 * 3 - Fatal error
5363 */
5364int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005365qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005366 uint16_t *next_loopid)
5367{
5368 int rval;
5369 int retry;
5370 uint16_t tmp_loopid;
5371 uint16_t mb[MAILBOX_REGISTER_COUNT];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005372 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005373
5374 retry = 0;
5375 tmp_loopid = 0;
5376
5377 for (;;) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005378 ql_dbg(ql_dbg_disc, vha, 0x2000,
5379 "Trying Fabric Login w/loop id 0x%04x for port "
5380 "%02x%02x%02x.\n",
5381 fcport->loop_id, fcport->d_id.b.domain,
5382 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005383
5384 /* Login fcport on switch. */
Chad Dupuis0b91d112012-02-09 11:15:42 -08005385 rval = ha->isp_ops->fabric_login(vha, fcport->loop_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005386 fcport->d_id.b.domain, fcport->d_id.b.area,
5387 fcport->d_id.b.al_pa, mb, BIT_0);
Chad Dupuis0b91d112012-02-09 11:15:42 -08005388 if (rval != QLA_SUCCESS) {
5389 return rval;
5390 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005391 if (mb[0] == MBS_PORT_ID_USED) {
5392 /*
5393 * Device has another loop ID. The firmware team
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005394 * recommends the driver perform an implicit login with
5395 * the specified ID again. The ID we just used is save
5396 * here so we return with an ID that can be tried by
5397 * the next login.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005398 */
5399 retry++;
5400 tmp_loopid = fcport->loop_id;
5401 fcport->loop_id = mb[1];
5402
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005403 ql_dbg(ql_dbg_disc, vha, 0x2001,
5404 "Fabric Login: port in use - next loop "
5405 "id=0x%04x, port id= %02x%02x%02x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07005406 fcport->loop_id, fcport->d_id.b.domain,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005407 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005408
5409 } else if (mb[0] == MBS_COMMAND_COMPLETE) {
5410 /*
5411 * Login succeeded.
5412 */
5413 if (retry) {
5414 /* A retry occurred before. */
5415 *next_loopid = tmp_loopid;
5416 } else {
5417 /*
5418 * No retry occurred before. Just increment the
5419 * ID value for next login.
5420 */
5421 *next_loopid = (fcport->loop_id + 1);
5422 }
5423
5424 if (mb[1] & BIT_0) {
5425 fcport->port_type = FCT_INITIATOR;
5426 } else {
5427 fcport->port_type = FCT_TARGET;
5428 if (mb[1] & BIT_1) {
Santosh Vernekar8474f3a2009-08-25 11:36:16 -07005429 fcport->flags |= FCF_FCP2_DEVICE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005430 }
5431 }
5432
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07005433 if (mb[10] & BIT_0)
5434 fcport->supported_classes |= FC_COS_CLASS2;
5435 if (mb[10] & BIT_1)
5436 fcport->supported_classes |= FC_COS_CLASS3;
5437
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04005438 if (IS_FWI2_CAPABLE(ha)) {
5439 if (mb[10] & BIT_7)
5440 fcport->flags |=
5441 FCF_CONF_COMP_SUPPORTED;
5442 }
5443
Linus Torvalds1da177e2005-04-16 15:20:36 -07005444 rval = QLA_SUCCESS;
5445 break;
5446 } else if (mb[0] == MBS_LOOP_ID_USED) {
5447 /*
5448 * Loop ID already used, try next loop ID.
5449 */
5450 fcport->loop_id++;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005451 rval = qla2x00_find_new_loop_id(vha, fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005452 if (rval != QLA_SUCCESS) {
5453 /* Ran out of loop IDs to use */
5454 break;
5455 }
5456 } else if (mb[0] == MBS_COMMAND_ERROR) {
5457 /*
5458 * Firmware possibly timed out during login. If NO
5459 * retries are left to do then the device is declared
5460 * dead.
5461 */
5462 *next_loopid = fcport->loop_id;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005463 ha->isp_ops->fabric_logout(vha, fcport->loop_id,
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07005464 fcport->d_id.b.domain, fcport->d_id.b.area,
5465 fcport->d_id.b.al_pa);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005466 qla2x00_mark_device_lost(vha, fcport, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005467
5468 rval = 1;
5469 break;
5470 } else {
5471 /*
5472 * unrecoverable / not handled error
5473 */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005474 ql_dbg(ql_dbg_disc, vha, 0x2002,
5475 "Failed=%x port_id=%02x%02x%02x loop_id=%x "
5476 "jiffies=%lx.\n", mb[0], fcport->d_id.b.domain,
5477 fcport->d_id.b.area, fcport->d_id.b.al_pa,
5478 fcport->loop_id, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005479
5480 *next_loopid = fcport->loop_id;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005481 ha->isp_ops->fabric_logout(vha, fcport->loop_id,
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07005482 fcport->d_id.b.domain, fcport->d_id.b.area,
5483 fcport->d_id.b.al_pa);
Chad Dupuis5f16b332012-08-22 14:21:00 -04005484 qla2x00_clear_loop_id(fcport);
Andrew Vasquez0eedfcf2005-10-27 11:09:38 -07005485 fcport->login_retry = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005486
5487 rval = 3;
5488 break;
5489 }
5490 }
5491
5492 return (rval);
5493}
5494
5495/*
5496 * qla2x00_local_device_login
5497 * Issue local device login command.
5498 *
5499 * Input:
5500 * ha = adapter block pointer.
5501 * loop_id = loop id of device to login to.
5502 *
5503 * Returns (Where's the #define!!!!):
5504 * 0 - Login successfully
5505 * 1 - Login failed
5506 * 3 - Fatal error
5507 */
5508int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005509qla2x00_local_device_login(scsi_qla_host_t *vha, fc_port_t *fcport)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005510{
5511 int rval;
5512 uint16_t mb[MAILBOX_REGISTER_COUNT];
5513
5514 memset(mb, 0, sizeof(mb));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005515 rval = qla2x00_login_local_device(vha, fcport, mb, BIT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005516 if (rval == QLA_SUCCESS) {
5517 /* Interrogate mailbox registers for any errors */
5518 if (mb[0] == MBS_COMMAND_ERROR)
5519 rval = 1;
5520 else if (mb[0] == MBS_COMMAND_PARAMETER_ERROR)
5521 /* device not in PCB table */
5522 rval = 3;
5523 }
5524
5525 return (rval);
5526}
5527
5528/*
5529 * qla2x00_loop_resync
5530 * Resync with fibre channel devices.
5531 *
5532 * Input:
5533 * ha = adapter block pointer.
5534 *
5535 * Returns:
5536 * 0 = success
5537 */
5538int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005539qla2x00_loop_resync(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005540{
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005541 int rval = QLA_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005542 uint32_t wait_time;
Anirban Chakraborty67c2e932009-04-06 22:33:42 -07005543 struct req_que *req;
5544 struct rsp_que *rsp;
5545
Michael Hernandezd7459522016-12-12 14:40:07 -08005546 req = vha->req;
Anirban Chakraborty67c2e932009-04-06 22:33:42 -07005547 rsp = req->rsp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005548
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005549 clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
5550 if (vha->flags.online) {
5551 if (!(rval = qla2x00_fw_ready(vha))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005552 /* Wait at most MAX_TARGET RSCNs for a stable link. */
5553 wait_time = 256;
5554 do {
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04005555 if (!IS_QLAFX00(vha->hw)) {
5556 /*
5557 * Issue a marker after FW becomes
5558 * ready.
5559 */
5560 qla2x00_marker(vha, req, rsp, 0, 0,
5561 MK_SYNC_ALL);
5562 vha->marker_needed = 0;
5563 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005564
5565 /* Remap devices on Loop. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005566 clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005567
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04005568 if (IS_QLAFX00(vha->hw))
5569 qlafx00_configure_devices(vha);
5570 else
5571 qla2x00_configure_loop(vha);
5572
Linus Torvalds1da177e2005-04-16 15:20:36 -07005573 wait_time--;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005574 } while (!atomic_read(&vha->loop_down_timer) &&
5575 !(test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
5576 && wait_time && (test_bit(LOOP_RESYNC_NEEDED,
5577 &vha->dpc_flags)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005578 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005579 }
5580
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005581 if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005582 return (QLA_FUNCTION_FAILED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005583
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005584 if (rval)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005585 ql_dbg(ql_dbg_disc, vha, 0x206c,
5586 "%s *** FAILED ***.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005587
5588 return (rval);
5589}
5590
Saurav Kashyap579d12b2010-12-21 16:00:14 -08005591/*
5592* qla2x00_perform_loop_resync
5593* Description: This function will set the appropriate flags and call
5594* qla2x00_loop_resync. If successful loop will be resynced
5595* Arguments : scsi_qla_host_t pointer
5596* returm : Success or Failure
5597*/
5598
5599int qla2x00_perform_loop_resync(scsi_qla_host_t *ha)
5600{
5601 int32_t rval = 0;
5602
5603 if (!test_and_set_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags)) {
5604 /*Configure the flags so that resync happens properly*/
5605 atomic_set(&ha->loop_down_timer, 0);
5606 if (!(ha->device_flags & DFLG_NO_CABLE)) {
5607 atomic_set(&ha->loop_state, LOOP_UP);
5608 set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
5609 set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
5610 set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
5611
5612 rval = qla2x00_loop_resync(ha);
5613 } else
5614 atomic_set(&ha->loop_state, LOOP_DEAD);
5615
5616 clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags);
5617 }
5618
5619 return rval;
5620}
5621
Linus Torvalds1da177e2005-04-16 15:20:36 -07005622void
Andrew Vasquez67becc02009-08-25 11:36:20 -07005623qla2x00_update_fcports(scsi_qla_host_t *base_vha)
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08005624{
5625 fc_port_t *fcport;
Arun Easifeafb7b2010-09-03 14:57:00 -07005626 struct scsi_qla_host *vha;
5627 struct qla_hw_data *ha = base_vha->hw;
5628 unsigned long flags;
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08005629
Arun Easifeafb7b2010-09-03 14:57:00 -07005630 spin_lock_irqsave(&ha->vport_slock, flags);
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08005631 /* Go with deferred removal of rport references. */
Arun Easifeafb7b2010-09-03 14:57:00 -07005632 list_for_each_entry(vha, &base_vha->hw->vp_list, list) {
5633 atomic_inc(&vha->vref_count);
5634 list_for_each_entry(fcport, &vha->vp_fcports, list) {
Dan Carpenter8ae598d2010-12-21 16:00:15 -08005635 if (fcport->drport &&
Arun Easifeafb7b2010-09-03 14:57:00 -07005636 atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
5637 spin_unlock_irqrestore(&ha->vport_slock, flags);
Andrew Vasquez67becc02009-08-25 11:36:20 -07005638 qla2x00_rport_del(fcport);
Alexei Potashnikdf673272015-07-14 16:00:46 -04005639
Arun Easifeafb7b2010-09-03 14:57:00 -07005640 spin_lock_irqsave(&ha->vport_slock, flags);
5641 }
5642 }
5643 atomic_dec(&vha->vref_count);
Joe Carnuccioc4a9b532017-03-15 09:48:43 -07005644 wake_up(&vha->vref_waitq);
Arun Easifeafb7b2010-09-03 14:57:00 -07005645 }
5646 spin_unlock_irqrestore(&ha->vport_slock, flags);
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08005647}
5648
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04005649/* Assumes idc_lock always held on entry */
5650void
5651qla83xx_reset_ownership(scsi_qla_host_t *vha)
5652{
5653 struct qla_hw_data *ha = vha->hw;
5654 uint32_t drv_presence, drv_presence_mask;
5655 uint32_t dev_part_info1, dev_part_info2, class_type;
5656 uint32_t class_type_mask = 0x3;
5657 uint16_t fcoe_other_function = 0xffff, i;
5658
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04005659 if (IS_QLA8044(ha)) {
5660 drv_presence = qla8044_rd_direct(vha,
5661 QLA8044_CRB_DRV_ACTIVE_INDEX);
5662 dev_part_info1 = qla8044_rd_direct(vha,
5663 QLA8044_CRB_DEV_PART_INFO_INDEX);
5664 dev_part_info2 = qla8044_rd_direct(vha,
5665 QLA8044_CRB_DEV_PART_INFO2);
5666 } else {
5667 qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence);
5668 qla83xx_rd_reg(vha, QLA83XX_DEV_PARTINFO1, &dev_part_info1);
5669 qla83xx_rd_reg(vha, QLA83XX_DEV_PARTINFO2, &dev_part_info2);
5670 }
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04005671 for (i = 0; i < 8; i++) {
5672 class_type = ((dev_part_info1 >> (i * 4)) & class_type_mask);
5673 if ((class_type == QLA83XX_CLASS_TYPE_FCOE) &&
5674 (i != ha->portnum)) {
5675 fcoe_other_function = i;
5676 break;
5677 }
5678 }
5679 if (fcoe_other_function == 0xffff) {
5680 for (i = 0; i < 8; i++) {
5681 class_type = ((dev_part_info2 >> (i * 4)) &
5682 class_type_mask);
5683 if ((class_type == QLA83XX_CLASS_TYPE_FCOE) &&
5684 ((i + 8) != ha->portnum)) {
5685 fcoe_other_function = i + 8;
5686 break;
5687 }
5688 }
5689 }
5690 /*
5691 * Prepare drv-presence mask based on fcoe functions present.
5692 * However consider only valid physical fcoe function numbers (0-15).
5693 */
5694 drv_presence_mask = ~((1 << (ha->portnum)) |
5695 ((fcoe_other_function == 0xffff) ?
5696 0 : (1 << (fcoe_other_function))));
5697
5698 /* We are the reset owner iff:
5699 * - No other protocol drivers present.
5700 * - This is the lowest among fcoe functions. */
5701 if (!(drv_presence & drv_presence_mask) &&
5702 (ha->portnum < fcoe_other_function)) {
5703 ql_dbg(ql_dbg_p3p, vha, 0xb07f,
5704 "This host is Reset owner.\n");
5705 ha->flags.nic_core_reset_owner = 1;
5706 }
5707}
5708
Saurav Kashyapfa492632012-11-21 02:40:29 -05005709static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04005710__qla83xx_set_drv_ack(scsi_qla_host_t *vha)
5711{
5712 int rval = QLA_SUCCESS;
5713 struct qla_hw_data *ha = vha->hw;
5714 uint32_t drv_ack;
5715
5716 rval = qla83xx_rd_reg(vha, QLA83XX_IDC_DRIVER_ACK, &drv_ack);
5717 if (rval == QLA_SUCCESS) {
5718 drv_ack |= (1 << ha->portnum);
5719 rval = qla83xx_wr_reg(vha, QLA83XX_IDC_DRIVER_ACK, drv_ack);
5720 }
5721
5722 return rval;
5723}
5724
Saurav Kashyapfa492632012-11-21 02:40:29 -05005725static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04005726__qla83xx_clear_drv_ack(scsi_qla_host_t *vha)
5727{
5728 int rval = QLA_SUCCESS;
5729 struct qla_hw_data *ha = vha->hw;
5730 uint32_t drv_ack;
5731
5732 rval = qla83xx_rd_reg(vha, QLA83XX_IDC_DRIVER_ACK, &drv_ack);
5733 if (rval == QLA_SUCCESS) {
5734 drv_ack &= ~(1 << ha->portnum);
5735 rval = qla83xx_wr_reg(vha, QLA83XX_IDC_DRIVER_ACK, drv_ack);
5736 }
5737
5738 return rval;
5739}
5740
Saurav Kashyapfa492632012-11-21 02:40:29 -05005741static const char *
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04005742qla83xx_dev_state_to_string(uint32_t dev_state)
5743{
5744 switch (dev_state) {
5745 case QLA8XXX_DEV_COLD:
5746 return "COLD/RE-INIT";
5747 case QLA8XXX_DEV_INITIALIZING:
5748 return "INITIALIZING";
5749 case QLA8XXX_DEV_READY:
5750 return "READY";
5751 case QLA8XXX_DEV_NEED_RESET:
5752 return "NEED RESET";
5753 case QLA8XXX_DEV_NEED_QUIESCENT:
5754 return "NEED QUIESCENT";
5755 case QLA8XXX_DEV_FAILED:
5756 return "FAILED";
5757 case QLA8XXX_DEV_QUIESCENT:
5758 return "QUIESCENT";
5759 default:
5760 return "Unknown";
5761 }
5762}
5763
5764/* Assumes idc-lock always held on entry */
5765void
5766qla83xx_idc_audit(scsi_qla_host_t *vha, int audit_type)
5767{
5768 struct qla_hw_data *ha = vha->hw;
5769 uint32_t idc_audit_reg = 0, duration_secs = 0;
5770
5771 switch (audit_type) {
5772 case IDC_AUDIT_TIMESTAMP:
5773 ha->idc_audit_ts = (jiffies_to_msecs(jiffies) / 1000);
5774 idc_audit_reg = (ha->portnum) |
5775 (IDC_AUDIT_TIMESTAMP << 7) | (ha->idc_audit_ts << 8);
5776 qla83xx_wr_reg(vha, QLA83XX_IDC_AUDIT, idc_audit_reg);
5777 break;
5778
5779 case IDC_AUDIT_COMPLETION:
5780 duration_secs = ((jiffies_to_msecs(jiffies) -
5781 jiffies_to_msecs(ha->idc_audit_ts)) / 1000);
5782 idc_audit_reg = (ha->portnum) |
5783 (IDC_AUDIT_COMPLETION << 7) | (duration_secs << 8);
5784 qla83xx_wr_reg(vha, QLA83XX_IDC_AUDIT, idc_audit_reg);
5785 break;
5786
5787 default:
5788 ql_log(ql_log_warn, vha, 0xb078,
5789 "Invalid audit type specified.\n");
5790 break;
5791 }
5792}
5793
5794/* Assumes idc_lock always held on entry */
Saurav Kashyapfa492632012-11-21 02:40:29 -05005795static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04005796qla83xx_initiating_reset(scsi_qla_host_t *vha)
5797{
5798 struct qla_hw_data *ha = vha->hw;
5799 uint32_t idc_control, dev_state;
5800
5801 __qla83xx_get_idc_control(vha, &idc_control);
5802 if ((idc_control & QLA83XX_IDC_RESET_DISABLED)) {
5803 ql_log(ql_log_info, vha, 0xb080,
5804 "NIC Core reset has been disabled. idc-control=0x%x\n",
5805 idc_control);
5806 return QLA_FUNCTION_FAILED;
5807 }
5808
5809 /* Set NEED-RESET iff in READY state and we are the reset-owner */
5810 qla83xx_rd_reg(vha, QLA83XX_IDC_DEV_STATE, &dev_state);
5811 if (ha->flags.nic_core_reset_owner && dev_state == QLA8XXX_DEV_READY) {
5812 qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE,
5813 QLA8XXX_DEV_NEED_RESET);
5814 ql_log(ql_log_info, vha, 0xb056, "HW State: NEED RESET.\n");
5815 qla83xx_idc_audit(vha, IDC_AUDIT_TIMESTAMP);
5816 } else {
5817 const char *state = qla83xx_dev_state_to_string(dev_state);
5818 ql_log(ql_log_info, vha, 0xb057, "HW State: %s.\n", state);
5819
5820 /* SV: XXX: Is timeout required here? */
5821 /* Wait for IDC state change READY -> NEED_RESET */
5822 while (dev_state == QLA8XXX_DEV_READY) {
5823 qla83xx_idc_unlock(vha, 0);
5824 msleep(200);
5825 qla83xx_idc_lock(vha, 0);
5826 qla83xx_rd_reg(vha, QLA83XX_IDC_DEV_STATE, &dev_state);
5827 }
5828 }
5829
5830 /* Send IDC ack by writing to drv-ack register */
5831 __qla83xx_set_drv_ack(vha);
5832
5833 return QLA_SUCCESS;
5834}
5835
5836int
5837__qla83xx_set_idc_control(scsi_qla_host_t *vha, uint32_t idc_control)
5838{
5839 return qla83xx_wr_reg(vha, QLA83XX_IDC_CONTROL, idc_control);
5840}
5841
5842int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04005843__qla83xx_get_idc_control(scsi_qla_host_t *vha, uint32_t *idc_control)
5844{
5845 return qla83xx_rd_reg(vha, QLA83XX_IDC_CONTROL, idc_control);
5846}
5847
Saurav Kashyapfa492632012-11-21 02:40:29 -05005848static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04005849qla83xx_check_driver_presence(scsi_qla_host_t *vha)
5850{
5851 uint32_t drv_presence = 0;
5852 struct qla_hw_data *ha = vha->hw;
5853
5854 qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence);
5855 if (drv_presence & (1 << ha->portnum))
5856 return QLA_SUCCESS;
5857 else
5858 return QLA_TEST_FAILED;
5859}
5860
5861int
5862qla83xx_nic_core_reset(scsi_qla_host_t *vha)
5863{
5864 int rval = QLA_SUCCESS;
5865 struct qla_hw_data *ha = vha->hw;
5866
5867 ql_dbg(ql_dbg_p3p, vha, 0xb058,
5868 "Entered %s().\n", __func__);
5869
5870 if (vha->device_flags & DFLG_DEV_FAILED) {
5871 ql_log(ql_log_warn, vha, 0xb059,
5872 "Device in unrecoverable FAILED state.\n");
5873 return QLA_FUNCTION_FAILED;
5874 }
5875
5876 qla83xx_idc_lock(vha, 0);
5877
5878 if (qla83xx_check_driver_presence(vha) != QLA_SUCCESS) {
5879 ql_log(ql_log_warn, vha, 0xb05a,
5880 "Function=0x%x has been removed from IDC participation.\n",
5881 ha->portnum);
5882 rval = QLA_FUNCTION_FAILED;
5883 goto exit;
5884 }
5885
5886 qla83xx_reset_ownership(vha);
5887
5888 rval = qla83xx_initiating_reset(vha);
5889
5890 /*
5891 * Perform reset if we are the reset-owner,
5892 * else wait till IDC state changes to READY/FAILED.
5893 */
5894 if (rval == QLA_SUCCESS) {
5895 rval = qla83xx_idc_state_handler(vha);
5896
5897 if (rval == QLA_SUCCESS)
5898 ha->flags.nic_core_hung = 0;
5899 __qla83xx_clear_drv_ack(vha);
5900 }
5901
5902exit:
5903 qla83xx_idc_unlock(vha, 0);
5904
5905 ql_dbg(ql_dbg_p3p, vha, 0xb05b, "Exiting %s.\n", __func__);
5906
5907 return rval;
5908}
5909
Saurav Kashyap81178772012-08-22 14:21:04 -04005910int
5911qla2xxx_mctp_dump(scsi_qla_host_t *vha)
5912{
5913 struct qla_hw_data *ha = vha->hw;
5914 int rval = QLA_FUNCTION_FAILED;
5915
5916 if (!IS_MCTP_CAPABLE(ha)) {
5917 /* This message can be removed from the final version */
5918 ql_log(ql_log_info, vha, 0x506d,
5919 "This board is not MCTP capable\n");
5920 return rval;
5921 }
5922
5923 if (!ha->mctp_dump) {
5924 ha->mctp_dump = dma_alloc_coherent(&ha->pdev->dev,
5925 MCTP_DUMP_SIZE, &ha->mctp_dump_dma, GFP_KERNEL);
5926
5927 if (!ha->mctp_dump) {
5928 ql_log(ql_log_warn, vha, 0x506e,
5929 "Failed to allocate memory for mctp dump\n");
5930 return rval;
5931 }
5932 }
5933
5934#define MCTP_DUMP_STR_ADDR 0x00000000
5935 rval = qla2x00_dump_mctp_data(vha, ha->mctp_dump_dma,
5936 MCTP_DUMP_STR_ADDR, MCTP_DUMP_SIZE/4);
5937 if (rval != QLA_SUCCESS) {
5938 ql_log(ql_log_warn, vha, 0x506f,
5939 "Failed to capture mctp dump\n");
5940 } else {
5941 ql_log(ql_log_info, vha, 0x5070,
5942 "Mctp dump capture for host (%ld/%p).\n",
5943 vha->host_no, ha->mctp_dump);
5944 ha->mctp_dumped = 1;
5945 }
5946
Saurav Kashyap409ee0f2012-08-22 14:21:29 -04005947 if (!ha->flags.nic_core_reset_hdlr_active && !ha->portnum) {
Saurav Kashyap81178772012-08-22 14:21:04 -04005948 ha->flags.nic_core_reset_hdlr_active = 1;
5949 rval = qla83xx_restart_nic_firmware(vha);
5950 if (rval)
5951 /* NIC Core reset failed. */
5952 ql_log(ql_log_warn, vha, 0x5071,
5953 "Failed to restart nic firmware\n");
5954 else
5955 ql_dbg(ql_dbg_p3p, vha, 0xb084,
5956 "Restarted NIC firmware successfully.\n");
5957 ha->flags.nic_core_reset_hdlr_active = 0;
5958 }
5959
5960 return rval;
5961
5962}
5963
Saurav Kashyap579d12b2010-12-21 16:00:14 -08005964/*
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04005965* qla2x00_quiesce_io
Saurav Kashyap579d12b2010-12-21 16:00:14 -08005966* Description: This function will block the new I/Os
5967* Its not aborting any I/Os as context
5968* is not destroyed during quiescence
5969* Arguments: scsi_qla_host_t
5970* return : void
5971*/
5972void
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04005973qla2x00_quiesce_io(scsi_qla_host_t *vha)
Saurav Kashyap579d12b2010-12-21 16:00:14 -08005974{
5975 struct qla_hw_data *ha = vha->hw;
5976 struct scsi_qla_host *vp;
5977
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04005978 ql_dbg(ql_dbg_dpc, vha, 0x401d,
5979 "Quiescing I/O - ha=%p.\n", ha);
Saurav Kashyap579d12b2010-12-21 16:00:14 -08005980
5981 atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
5982 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
5983 atomic_set(&vha->loop_state, LOOP_DOWN);
5984 qla2x00_mark_all_devices_lost(vha, 0);
5985 list_for_each_entry(vp, &ha->vp_list, list)
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04005986 qla2x00_mark_all_devices_lost(vp, 0);
Saurav Kashyap579d12b2010-12-21 16:00:14 -08005987 } else {
5988 if (!atomic_read(&vha->loop_down_timer))
5989 atomic_set(&vha->loop_down_timer,
5990 LOOP_DOWN_TIME);
5991 }
5992 /* Wait for pending cmds to complete */
5993 qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST);
5994}
5995
Giridhar Malavalia9083012010-04-12 17:59:55 -07005996void
5997qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
5998{
5999 struct qla_hw_data *ha = vha->hw;
Saurav Kashyap579d12b2010-12-21 16:00:14 -08006000 struct scsi_qla_host *vp;
Arun Easifeafb7b2010-09-03 14:57:00 -07006001 unsigned long flags;
Andrew Vasquez6aef87b2011-02-23 15:27:13 -08006002 fc_port_t *fcport;
Quinn Tran7c3f8fd2017-06-13 20:47:22 -07006003 u16 i;
Giridhar Malavalia9083012010-04-12 17:59:55 -07006004
Saurav Kashyape46ef002011-02-23 15:27:16 -08006005 /* For ISP82XX, driver waits for completion of the commands.
6006 * online flag should be set.
6007 */
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04006008 if (!(IS_P3P_TYPE(ha)))
Saurav Kashyape46ef002011-02-23 15:27:16 -08006009 vha->flags.online = 0;
Giridhar Malavalia9083012010-04-12 17:59:55 -07006010 ha->flags.chip_reset_done = 0;
6011 clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Saurav Kashyap2be21fa2012-05-15 14:34:16 -04006012 vha->qla_stats.total_isp_aborts++;
Giridhar Malavalia9083012010-04-12 17:59:55 -07006013
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006014 ql_log(ql_log_info, vha, 0x00af,
6015 "Performing ISP error recovery - ha=%p.\n", ha);
Giridhar Malavalia9083012010-04-12 17:59:55 -07006016
Saurav Kashyape46ef002011-02-23 15:27:16 -08006017 /* For ISP82XX, reset_chip is just disabling interrupts.
6018 * Driver waits for the completion of the commands.
6019 * the interrupts need to be enabled.
6020 */
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04006021 if (!(IS_P3P_TYPE(ha)))
Giridhar Malavalia9083012010-04-12 17:59:55 -07006022 ha->isp_ops->reset_chip(vha);
6023
Quinn Tranec7193e2017-03-15 09:48:55 -07006024 ha->flags.n2n_ae = 0;
6025 ha->flags.lip_ae = 0;
6026 ha->current_topology = 0;
6027 ha->flags.fw_started = 0;
6028 ha->flags.fw_init_done = 0;
Quinn Tran7c3f8fd2017-06-13 20:47:22 -07006029 ha->base_qpair->chip_reset++;
6030 for (i = 0; i < ha->max_qpairs; i++) {
6031 if (ha->queue_pair_map[i])
6032 ha->queue_pair_map[i]->chip_reset =
6033 ha->base_qpair->chip_reset;
6034 }
Quinn Tran726b8542017-01-19 22:28:00 -08006035
Giridhar Malavalia9083012010-04-12 17:59:55 -07006036 atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
6037 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
6038 atomic_set(&vha->loop_state, LOOP_DOWN);
6039 qla2x00_mark_all_devices_lost(vha, 0);
Arun Easifeafb7b2010-09-03 14:57:00 -07006040
6041 spin_lock_irqsave(&ha->vport_slock, flags);
Saurav Kashyap579d12b2010-12-21 16:00:14 -08006042 list_for_each_entry(vp, &ha->vp_list, list) {
Arun Easifeafb7b2010-09-03 14:57:00 -07006043 atomic_inc(&vp->vref_count);
6044 spin_unlock_irqrestore(&ha->vport_slock, flags);
6045
Giridhar Malavalia9083012010-04-12 17:59:55 -07006046 qla2x00_mark_all_devices_lost(vp, 0);
Arun Easifeafb7b2010-09-03 14:57:00 -07006047
6048 spin_lock_irqsave(&ha->vport_slock, flags);
6049 atomic_dec(&vp->vref_count);
6050 }
6051 spin_unlock_irqrestore(&ha->vport_slock, flags);
Giridhar Malavalia9083012010-04-12 17:59:55 -07006052 } else {
6053 if (!atomic_read(&vha->loop_down_timer))
6054 atomic_set(&vha->loop_down_timer,
6055 LOOP_DOWN_TIME);
6056 }
6057
Andrew Vasquez6aef87b2011-02-23 15:27:13 -08006058 /* Clear all async request states across all VPs. */
6059 list_for_each_entry(fcport, &vha->vp_fcports, list)
6060 fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
6061 spin_lock_irqsave(&ha->vport_slock, flags);
6062 list_for_each_entry(vp, &ha->vp_list, list) {
6063 atomic_inc(&vp->vref_count);
6064 spin_unlock_irqrestore(&ha->vport_slock, flags);
6065
6066 list_for_each_entry(fcport, &vp->vp_fcports, list)
6067 fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
6068
6069 spin_lock_irqsave(&ha->vport_slock, flags);
6070 atomic_dec(&vp->vref_count);
6071 }
6072 spin_unlock_irqrestore(&ha->vport_slock, flags);
6073
Lalit Chandivadebddd2d62010-09-03 15:20:53 -07006074 if (!ha->flags.eeh_busy) {
6075 /* Make sure for ISP 82XX IO DMA is complete */
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04006076 if (IS_P3P_TYPE(ha)) {
Giridhar Malavali71905752011-02-23 15:27:10 -08006077 qla82xx_chip_reset_cleanup(vha);
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006078 ql_log(ql_log_info, vha, 0x00b4,
6079 "Done chip reset cleanup.\n");
Giridhar Malavalia9083012010-04-12 17:59:55 -07006080
Saurav Kashyape46ef002011-02-23 15:27:16 -08006081 /* Done waiting for pending commands.
6082 * Reset the online flag.
6083 */
6084 vha->flags.online = 0;
Giridhar Malavalia9083012010-04-12 17:59:55 -07006085 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006086
Lalit Chandivadebddd2d62010-09-03 15:20:53 -07006087 /* Requeue all commands in outstanding command list. */
6088 qla2x00_abort_all_cmds(vha, DID_RESET << 16);
6089 }
Arun Easib6a029e2014-09-25 06:14:52 -04006090 /* memory barrier */
6091 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006092}
6093
6094/*
6095* qla2x00_abort_isp
6096* Resets ISP and aborts all outstanding commands.
6097*
6098* Input:
6099* ha = adapter block pointer.
6100*
6101* Returns:
6102* 0 = success
6103*/
6104int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006105qla2x00_abort_isp(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006106{
Andrew Vasquez476e8972006-08-23 14:54:55 -07006107 int rval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006108 uint8_t status = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006109 struct qla_hw_data *ha = vha->hw;
6110 struct scsi_qla_host *vp;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006111 struct req_que *req = ha->req_q_map[0];
Arun Easifeafb7b2010-09-03 14:57:00 -07006112 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006113
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006114 if (vha->flags.online) {
Giridhar Malavalia9083012010-04-12 17:59:55 -07006115 qla2x00_abort_isp_cleanup(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006116
Santosh Vernekara61712972012-08-22 14:21:13 -04006117 if (IS_QLA8031(ha)) {
6118 ql_dbg(ql_dbg_p3p, vha, 0xb05c,
6119 "Clearing fcoe driver presence.\n");
6120 if (qla83xx_clear_drv_presence(vha) != QLA_SUCCESS)
6121 ql_dbg(ql_dbg_p3p, vha, 0xb073,
6122 "Error while clearing DRV-Presence.\n");
6123 }
6124
Andrew Vasquez85880802009-12-15 21:29:46 -08006125 if (unlikely(pci_channel_offline(ha->pdev) &&
6126 ha->flags.pci_channel_io_perm_failure)) {
6127 clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
6128 status = 0;
6129 return status;
6130 }
6131
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006132 ha->isp_ops->get_flash_version(vha, req->ring);
Andrew Vasquez30c47662007-01-29 10:22:21 -08006133
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006134 ha->isp_ops->nvram_config(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006135
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006136 if (!qla2x00_restart_isp(vha)) {
6137 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006138
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006139 if (!atomic_read(&vha->loop_down_timer)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006140 /*
6141 * Issue marker command only when we are going
6142 * to start the I/O .
6143 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006144 vha->marker_needed = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006145 }
6146
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006147 vha->flags.online = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006148
Andrew Vasquezfd34f552007-07-19 15:06:00 -07006149 ha->isp_ops->enable_intrs(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006150
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07006151 ha->isp_abort_cnt = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006152 clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
Andrew Vasquez476e8972006-08-23 14:54:55 -07006153
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08006154 if (IS_QLA81XX(ha) || IS_QLA8031(ha))
6155 qla2x00_get_fw_version(vha);
Andrew Vasquezdf613b92008-01-17 09:02:17 -08006156 if (ha->fce) {
6157 ha->flags.fce_enabled = 1;
6158 memset(ha->fce, 0,
6159 fce_calc_size(ha->fce_bufs));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006160 rval = qla2x00_enable_fce_trace(vha,
Andrew Vasquezdf613b92008-01-17 09:02:17 -08006161 ha->fce_dma, ha->fce_bufs, ha->fce_mb,
6162 &ha->fce_bufs);
6163 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006164 ql_log(ql_log_warn, vha, 0x8033,
Andrew Vasquezdf613b92008-01-17 09:02:17 -08006165 "Unable to reinitialize FCE "
6166 "(%d).\n", rval);
6167 ha->flags.fce_enabled = 0;
6168 }
6169 }
Andrew Vasquez436a7b12008-07-10 16:55:54 -07006170
6171 if (ha->eft) {
6172 memset(ha->eft, 0, EFT_SIZE);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006173 rval = qla2x00_enable_eft_trace(vha,
Andrew Vasquez436a7b12008-07-10 16:55:54 -07006174 ha->eft_dma, EFT_NUM_BUFFERS);
6175 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006176 ql_log(ql_log_warn, vha, 0x8034,
Andrew Vasquez436a7b12008-07-10 16:55:54 -07006177 "Unable to reinitialize EFT "
6178 "(%d).\n", rval);
6179 }
6180 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006181 } else { /* failed the ISP abort */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006182 vha->flags.online = 1;
6183 if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006184 if (ha->isp_abort_cnt == 0) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006185 ql_log(ql_log_fatal, vha, 0x8035,
6186 "ISP error recover failed - "
6187 "board disabled.\n");
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07006188 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006189 * The next call disables the board
6190 * completely.
6191 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006192 ha->isp_ops->reset_adapter(vha);
6193 vha->flags.online = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006194 clear_bit(ISP_ABORT_RETRY,
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006195 &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006196 status = 0;
6197 } else { /* schedule another ISP abort */
6198 ha->isp_abort_cnt--;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006199 ql_dbg(ql_dbg_taskm, vha, 0x8020,
6200 "ISP abort - retry remaining %d.\n",
6201 ha->isp_abort_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006202 status = 1;
6203 }
6204 } else {
6205 ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006206 ql_dbg(ql_dbg_taskm, vha, 0x8021,
6207 "ISP error recovery - retrying (%d) "
6208 "more times.\n", ha->isp_abort_cnt);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006209 set_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006210 status = 1;
6211 }
6212 }
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07006213
Linus Torvalds1da177e2005-04-16 15:20:36 -07006214 }
6215
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006216 if (!status) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006217 ql_dbg(ql_dbg_taskm, vha, 0x8022, "%s succeeded.\n", __func__);
Quinn Tran1608cc42017-08-23 15:05:03 -07006218 qla2x00_configure_hba(vha);
Arun Easifeafb7b2010-09-03 14:57:00 -07006219 spin_lock_irqsave(&ha->vport_slock, flags);
6220 list_for_each_entry(vp, &ha->vp_list, list) {
6221 if (vp->vp_idx) {
6222 atomic_inc(&vp->vref_count);
6223 spin_unlock_irqrestore(&ha->vport_slock, flags);
6224
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006225 qla2x00_vp_abort_isp(vp);
Arun Easifeafb7b2010-09-03 14:57:00 -07006226
6227 spin_lock_irqsave(&ha->vport_slock, flags);
6228 atomic_dec(&vp->vref_count);
6229 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006230 }
Arun Easifeafb7b2010-09-03 14:57:00 -07006231 spin_unlock_irqrestore(&ha->vport_slock, flags);
6232
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04006233 if (IS_QLA8031(ha)) {
6234 ql_dbg(ql_dbg_p3p, vha, 0xb05d,
6235 "Setting back fcoe driver presence.\n");
6236 if (qla83xx_set_drv_presence(vha) != QLA_SUCCESS)
6237 ql_dbg(ql_dbg_p3p, vha, 0xb074,
6238 "Error while setting DRV-Presence.\n");
6239 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006240 } else {
Joe Perchesd8424f62011-11-18 09:03:06 -08006241 ql_log(ql_log_warn, vha, 0x8023, "%s **** FAILED ****.\n",
6242 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006243 }
6244
6245 return(status);
6246}
6247
6248/*
6249* qla2x00_restart_isp
6250* restarts the ISP after a reset
6251*
6252* Input:
6253* ha = adapter block pointer.
6254*
6255* Returns:
6256* 0 = success
6257*/
6258static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006259qla2x00_restart_isp(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006260{
Andrew Vasquezc6b2fca2009-03-05 11:07:03 -08006261 int status = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006262 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006263 struct req_que *req = ha->req_q_map[0];
6264 struct rsp_que *rsp = ha->rsp_q_map[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006265
6266 /* If firmware needs to be loaded */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006267 if (qla2x00_isp_firmware(vha)) {
6268 vha->flags.online = 0;
6269 status = ha->isp_ops->chip_diag(vha);
6270 if (!status)
6271 status = qla2x00_setup_chip(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006272 }
6273
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006274 if (!status && !(status = qla2x00_init_rings(vha))) {
6275 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
Lalit Chandivade2533cf62009-03-24 09:08:07 -07006276 ha->flags.chip_reset_done = 1;
Chad Dupuis7108b762014-04-11 16:54:45 -04006277
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006278 /* Initialize the queues in use */
6279 qla25xx_init_queues(ha);
6280
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006281 status = qla2x00_fw_ready(vha);
6282 if (!status) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006283 /* Issue a marker after FW becomes ready. */
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006284 qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
Chad Dupuis7108b762014-04-11 16:54:45 -04006285 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006286 }
6287
6288 /* if no cable then assume it's good */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006289 if ((vha->device_flags & DFLG_NO_CABLE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006290 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006291 }
6292 return (status);
6293}
6294
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006295static int
6296qla25xx_init_queues(struct qla_hw_data *ha)
6297{
6298 struct rsp_que *rsp = NULL;
6299 struct req_que *req = NULL;
6300 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
6301 int ret = -1;
6302 int i;
6303
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07006304 for (i = 1; i < ha->max_rsp_queues; i++) {
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006305 rsp = ha->rsp_q_map[i];
Quinn Trancb432852016-02-04 11:45:16 -05006306 if (rsp && test_bit(i, ha->rsp_qid_map)) {
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006307 rsp->options &= ~BIT_0;
Anirban Chakraborty618a7522009-02-08 20:50:11 -08006308 ret = qla25xx_init_rsp_que(base_vha, rsp);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006309 if (ret != QLA_SUCCESS)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006310 ql_dbg(ql_dbg_init, base_vha, 0x00ff,
6311 "%s Rsp que: %d init failed.\n",
6312 __func__, rsp->id);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006313 else
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006314 ql_dbg(ql_dbg_init, base_vha, 0x0100,
6315 "%s Rsp que: %d inited.\n",
6316 __func__, rsp->id);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006317 }
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07006318 }
6319 for (i = 1; i < ha->max_req_queues; i++) {
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006320 req = ha->req_q_map[i];
Quinn Trancb432852016-02-04 11:45:16 -05006321 if (req && test_bit(i, ha->req_qid_map)) {
6322 /* Clear outstanding commands array. */
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006323 req->options &= ~BIT_0;
Anirban Chakraborty618a7522009-02-08 20:50:11 -08006324 ret = qla25xx_init_req_que(base_vha, req);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006325 if (ret != QLA_SUCCESS)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006326 ql_dbg(ql_dbg_init, base_vha, 0x0101,
6327 "%s Req que: %d init failed.\n",
6328 __func__, req->id);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006329 else
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006330 ql_dbg(ql_dbg_init, base_vha, 0x0102,
6331 "%s Req que: %d inited.\n",
6332 __func__, req->id);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006333 }
6334 }
6335 return ret;
6336}
6337
Linus Torvalds1da177e2005-04-16 15:20:36 -07006338/*
6339* qla2x00_reset_adapter
6340* Reset adapter.
6341*
6342* Input:
6343* ha = adapter block pointer.
6344*/
Andrew Vasquezabbd8872005-07-06 10:30:05 -07006345void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006346qla2x00_reset_adapter(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006347{
6348 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006349 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07006350 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006351
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006352 vha->flags.online = 0;
Andrew Vasquezfd34f552007-07-19 15:06:00 -07006353 ha->isp_ops->disable_intrs(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006354
Linus Torvalds1da177e2005-04-16 15:20:36 -07006355 spin_lock_irqsave(&ha->hardware_lock, flags);
6356 WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
6357 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
6358 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
6359 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
6360 spin_unlock_irqrestore(&ha->hardware_lock, flags);
6361}
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006362
6363void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006364qla24xx_reset_adapter(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006365{
6366 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006367 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006368 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
6369
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04006370 if (IS_P3P_TYPE(ha))
Giridhar Malavalia9083012010-04-12 17:59:55 -07006371 return;
6372
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006373 vha->flags.online = 0;
Andrew Vasquezfd34f552007-07-19 15:06:00 -07006374 ha->isp_ops->disable_intrs(ha);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006375
6376 spin_lock_irqsave(&ha->hardware_lock, flags);
6377 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
6378 RD_REG_DWORD(&reg->hccr);
6379 WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
6380 RD_REG_DWORD(&reg->hccr);
6381 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Andrew Vasquez09ff36d2009-01-22 09:45:30 -08006382
6383 if (IS_NOPOLLING_TYPE(ha))
6384 ha->isp_ops->enable_intrs(ha);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006385}
6386
David Miller4e08df32007-04-16 12:37:43 -07006387/* On sparc systems, obtain port and node WWN from firmware
6388 * properties.
6389 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006390static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *vha,
6391 struct nvram_24xx *nv)
David Miller4e08df32007-04-16 12:37:43 -07006392{
6393#ifdef CONFIG_SPARC
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006394 struct qla_hw_data *ha = vha->hw;
David Miller4e08df32007-04-16 12:37:43 -07006395 struct pci_dev *pdev = ha->pdev;
David S. Miller15576bc2007-05-08 00:36:49 -07006396 struct device_node *dp = pci_device_to_OF_node(pdev);
6397 const u8 *val;
David Miller4e08df32007-04-16 12:37:43 -07006398 int len;
6399
6400 val = of_get_property(dp, "port-wwn", &len);
6401 if (val && len >= WWN_SIZE)
6402 memcpy(nv->port_name, val, WWN_SIZE);
6403
6404 val = of_get_property(dp, "node-wwn", &len);
6405 if (val && len >= WWN_SIZE)
6406 memcpy(nv->node_name, val, WWN_SIZE);
6407#endif
6408}
6409
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006410int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006411qla24xx_nvram_config(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006412{
David Miller4e08df32007-04-16 12:37:43 -07006413 int rval;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006414 struct init_cb_24xx *icb;
6415 struct nvram_24xx *nv;
6416 uint32_t *dptr;
6417 uint8_t *dptr1, *dptr2;
6418 uint32_t chksum;
6419 uint16_t cnt;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006420 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006421
David Miller4e08df32007-04-16 12:37:43 -07006422 rval = QLA_SUCCESS;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006423 icb = (struct init_cb_24xx *)ha->init_cb;
Seokmann Ju281afe12007-07-26 13:43:34 -07006424 nv = ha->nvram;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006425
6426 /* Determine NVRAM starting address. */
Chad Dupuisf73cb692014-02-26 04:15:06 -05006427 if (ha->port_no == 0) {
Anirban Chakrabortye5b68a62009-04-06 22:33:50 -07006428 ha->nvram_base = FA_NVRAM_FUNC0_ADDR;
6429 ha->vpd_base = FA_NVRAM_VPD0_ADDR;
6430 } else {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006431 ha->nvram_base = FA_NVRAM_FUNC1_ADDR;
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -08006432 ha->vpd_base = FA_NVRAM_VPD1_ADDR;
6433 }
Chad Dupuisf73cb692014-02-26 04:15:06 -05006434
Anirban Chakrabortye5b68a62009-04-06 22:33:50 -07006435 ha->nvram_size = sizeof(struct nvram_24xx);
6436 ha->vpd_size = FA_NVRAM_VPD_SIZE;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006437
Seokmann Ju281afe12007-07-26 13:43:34 -07006438 /* Get VPD data into cache */
6439 ha->vpd = ha->nvram + VPD_OFFSET;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006440 ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd,
Seokmann Ju281afe12007-07-26 13:43:34 -07006441 ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4);
6442
6443 /* Get NVRAM data into cache and calculate checksum. */
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006444 dptr = (uint32_t *)nv;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006445 ha->isp_ops->read_nvram(vha, (uint8_t *)dptr, ha->nvram_base,
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006446 ha->nvram_size);
Joe Carnuccioda08ef52016-01-27 12:03:34 -05006447 for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++)
6448 chksum += le32_to_cpu(*dptr);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006449
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006450 ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x006a,
6451 "Contents of NVRAM\n");
6452 ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010d,
6453 (uint8_t *)nv, ha->nvram_size);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006454
6455 /* Bad NVRAM data, set defaults parameters. */
6456 if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P'
6457 || nv->id[3] != ' ' ||
Bart Van Asschead950362015-07-09 07:24:08 -07006458 nv->nvram_version < cpu_to_le16(ICB_VERSION)) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006459 /* Reset NVRAM data. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006460 ql_log(ql_log_warn, vha, 0x006b,
Raul Porcel9e336522012-05-15 14:34:08 -04006461 "Inconsistent NVRAM detected: checksum=0x%x id=%c "
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006462 "version=0x%x.\n", chksum, nv->id[0], nv->nvram_version);
6463 ql_log(ql_log_warn, vha, 0x006c,
6464 "Falling back to functioning (yet invalid -- WWPN) "
6465 "defaults.\n");
David Miller4e08df32007-04-16 12:37:43 -07006466
6467 /*
6468 * Set default initialization control block.
6469 */
6470 memset(nv, 0, ha->nvram_size);
Bart Van Asschead950362015-07-09 07:24:08 -07006471 nv->nvram_version = cpu_to_le16(ICB_VERSION);
6472 nv->version = cpu_to_le16(ICB_VERSION);
Joe Carnuccio98aee702014-09-25 05:16:38 -04006473 nv->frame_payload_size = 2048;
Bart Van Asschead950362015-07-09 07:24:08 -07006474 nv->execution_throttle = cpu_to_le16(0xFFFF);
6475 nv->exchange_count = cpu_to_le16(0);
6476 nv->hard_address = cpu_to_le16(124);
David Miller4e08df32007-04-16 12:37:43 -07006477 nv->port_name[0] = 0x21;
Chad Dupuisf73cb692014-02-26 04:15:06 -05006478 nv->port_name[1] = 0x00 + ha->port_no + 1;
David Miller4e08df32007-04-16 12:37:43 -07006479 nv->port_name[2] = 0x00;
6480 nv->port_name[3] = 0xe0;
6481 nv->port_name[4] = 0x8b;
6482 nv->port_name[5] = 0x1c;
6483 nv->port_name[6] = 0x55;
6484 nv->port_name[7] = 0x86;
6485 nv->node_name[0] = 0x20;
6486 nv->node_name[1] = 0x00;
6487 nv->node_name[2] = 0x00;
6488 nv->node_name[3] = 0xe0;
6489 nv->node_name[4] = 0x8b;
6490 nv->node_name[5] = 0x1c;
6491 nv->node_name[6] = 0x55;
6492 nv->node_name[7] = 0x86;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006493 qla24xx_nvram_wwn_from_ofw(vha, nv);
Bart Van Asschead950362015-07-09 07:24:08 -07006494 nv->login_retry_count = cpu_to_le16(8);
6495 nv->interrupt_delay_timer = cpu_to_le16(0);
6496 nv->login_timeout = cpu_to_le16(0);
David Miller4e08df32007-04-16 12:37:43 -07006497 nv->firmware_options_1 =
Bart Van Asschead950362015-07-09 07:24:08 -07006498 cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1);
6499 nv->firmware_options_2 = cpu_to_le32(2 << 4);
6500 nv->firmware_options_2 |= cpu_to_le32(BIT_12);
6501 nv->firmware_options_3 = cpu_to_le32(2 << 13);
6502 nv->host_p = cpu_to_le32(BIT_11|BIT_10);
6503 nv->efi_parameters = cpu_to_le32(0);
David Miller4e08df32007-04-16 12:37:43 -07006504 nv->reset_delay = 5;
Bart Van Asschead950362015-07-09 07:24:08 -07006505 nv->max_luns_per_target = cpu_to_le16(128);
6506 nv->port_down_retry_count = cpu_to_le16(30);
6507 nv->link_down_timeout = cpu_to_le16(30);
David Miller4e08df32007-04-16 12:37:43 -07006508
6509 rval = 1;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006510 }
6511
Quinn Tran726b8542017-01-19 22:28:00 -08006512 if (qla_tgt_mode_enabled(vha)) {
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04006513 /* Don't enable full login after initial LIP */
Bart Van Asschead950362015-07-09 07:24:08 -07006514 nv->firmware_options_1 &= cpu_to_le32(~BIT_13);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04006515 /* Don't enable LIP full login for initiator */
Bart Van Asschead950362015-07-09 07:24:08 -07006516 nv->host_p &= cpu_to_le32(~BIT_10);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04006517 }
6518
6519 qlt_24xx_config_nvram_stage1(vha, nv);
6520
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006521 /* Reset Initialization control block */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006522 memset(icb, 0, ha->init_cb_size);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006523
6524 /* Copy 1st segment. */
6525 dptr1 = (uint8_t *)icb;
6526 dptr2 = (uint8_t *)&nv->version;
6527 cnt = (uint8_t *)&icb->response_q_inpointer - (uint8_t *)&icb->version;
6528 while (cnt--)
6529 *dptr1++ = *dptr2++;
6530
6531 icb->login_retry_count = nv->login_retry_count;
Andrew Vasquez3ea66e22006-06-23 16:11:27 -07006532 icb->link_down_on_nos = nv->link_down_on_nos;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006533
6534 /* Copy 2nd segment. */
6535 dptr1 = (uint8_t *)&icb->interrupt_delay_timer;
6536 dptr2 = (uint8_t *)&nv->interrupt_delay_timer;
6537 cnt = (uint8_t *)&icb->reserved_3 -
6538 (uint8_t *)&icb->interrupt_delay_timer;
6539 while (cnt--)
6540 *dptr1++ = *dptr2++;
6541
6542 /*
6543 * Setup driver NVRAM options.
6544 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006545 qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name),
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08006546 "QLA2462");
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006547
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04006548 qlt_24xx_config_nvram_stage2(vha, icb);
6549
Bart Van Asschead950362015-07-09 07:24:08 -07006550 if (nv->host_p & cpu_to_le32(BIT_15)) {
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04006551 /* Use alternate WWN? */
Andrew Vasquez5341e862006-05-17 15:09:16 -07006552 memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
6553 memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
6554 }
6555
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006556 /* Prepare nodename */
Bart Van Asschead950362015-07-09 07:24:08 -07006557 if ((icb->firmware_options_1 & cpu_to_le32(BIT_14)) == 0) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006558 /*
6559 * Firmware will apply the following mask if the nodename was
6560 * not provided.
6561 */
6562 memcpy(icb->node_name, icb->port_name, WWN_SIZE);
6563 icb->node_name[0] &= 0xF0;
6564 }
6565
6566 /* Set host adapter parameters. */
6567 ha->flags.disable_risc_code_load = 0;
Andrew Vasquez0c8c39a2006-12-13 19:20:30 -08006568 ha->flags.enable_lip_reset = 0;
6569 ha->flags.enable_lip_full_login =
6570 le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0;
6571 ha->flags.enable_target_reset =
6572 le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006573 ha->flags.enable_led_scheme = 0;
Andrew Vasquezd4c760c2006-06-23 16:10:39 -07006574 ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006575
Andrew Vasquezfd0e7e42006-05-17 15:09:11 -07006576 ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) &
6577 (BIT_6 | BIT_5 | BIT_4)) >> 4;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006578
6579 memcpy(ha->fw_seriallink_options24, nv->seriallink_options,
6580 sizeof(ha->fw_seriallink_options24));
6581
6582 /* save HBA serial number */
6583 ha->serial0 = icb->port_name[5];
6584 ha->serial1 = icb->port_name[6];
6585 ha->serial2 = icb->port_name[7];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006586 memcpy(vha->node_name, icb->node_name, WWN_SIZE);
6587 memcpy(vha->port_name, icb->port_name, WWN_SIZE);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006588
Bart Van Asschead950362015-07-09 07:24:08 -07006589 icb->execution_throttle = cpu_to_le16(0xFFFF);
andrew.vasquez@qlogic.combc8fb3c2006-01-13 17:05:42 -08006590
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006591 ha->retry_count = le16_to_cpu(nv->login_retry_count);
6592
6593 /* Set minimum login_timeout to 4 seconds. */
6594 if (le16_to_cpu(nv->login_timeout) < ql2xlogintimeout)
6595 nv->login_timeout = cpu_to_le16(ql2xlogintimeout);
6596 if (le16_to_cpu(nv->login_timeout) < 4)
Bart Van Asschead950362015-07-09 07:24:08 -07006597 nv->login_timeout = cpu_to_le16(4);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006598 ha->login_timeout = le16_to_cpu(nv->login_timeout);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006599
Andrew Vasquez00a537b2008-02-28 14:06:11 -08006600 /* Set minimum RATOV to 100 tenths of a second. */
6601 ha->r_a_tov = 100;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006602
6603 ha->loop_reset_delay = nv->reset_delay;
6604
6605 /* Link Down Timeout = 0:
6606 *
6607 * When Port Down timer expires we will start returning
6608 * I/O's to OS with "DID_NO_CONNECT".
6609 *
6610 * Link Down Timeout != 0:
6611 *
6612 * The driver waits for the link to come up after link down
6613 * before returning I/Os to OS with "DID_NO_CONNECT".
6614 */
6615 if (le16_to_cpu(nv->link_down_timeout) == 0) {
6616 ha->loop_down_abort_time =
6617 (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT);
6618 } else {
6619 ha->link_down_timeout = le16_to_cpu(nv->link_down_timeout);
6620 ha->loop_down_abort_time =
6621 (LOOP_DOWN_TIME - ha->link_down_timeout);
6622 }
6623
6624 /* Need enough time to try and get the port back. */
6625 ha->port_down_retry_count = le16_to_cpu(nv->port_down_retry_count);
6626 if (qlport_down_retry)
6627 ha->port_down_retry_count = qlport_down_retry;
6628
6629 /* Set login_retry_count */
6630 ha->login_retry_count = le16_to_cpu(nv->login_retry_count);
6631 if (ha->port_down_retry_count ==
6632 le16_to_cpu(nv->port_down_retry_count) &&
6633 ha->port_down_retry_count > 3)
6634 ha->login_retry_count = ha->port_down_retry_count;
6635 else if (ha->port_down_retry_count > (int)ha->login_retry_count)
6636 ha->login_retry_count = ha->port_down_retry_count;
6637 if (ql2xloginretrycount)
6638 ha->login_retry_count = ql2xloginretrycount;
6639
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07006640 /* Enable ZIO. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006641 if (!vha->flags.init_done) {
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07006642 ha->zio_mode = le32_to_cpu(icb->firmware_options_2) &
6643 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
6644 ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ?
6645 le16_to_cpu(icb->interrupt_delay_timer): 2;
6646 }
Bart Van Asschead950362015-07-09 07:24:08 -07006647 icb->firmware_options_2 &= cpu_to_le32(
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07006648 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006649 vha->flags.process_response_queue = 0;
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07006650 if (ha->zio_mode != QLA_ZIO_DISABLED) {
andrew.vasquez@qlogic.com4a59f712006-03-09 14:27:39 -08006651 ha->zio_mode = QLA_ZIO_MODE_6;
6652
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006653 ql_log(ql_log_info, vha, 0x006f,
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07006654 "ZIO mode %d enabled; timer delay (%d us).\n",
6655 ha->zio_mode, ha->zio_timer * 100);
6656
6657 icb->firmware_options_2 |= cpu_to_le32(
6658 (uint32_t)ha->zio_mode);
6659 icb->interrupt_delay_timer = cpu_to_le16(ha->zio_timer);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006660 vha->flags.process_response_queue = 1;
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07006661 }
6662
David Miller4e08df32007-04-16 12:37:43 -07006663 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006664 ql_log(ql_log_warn, vha, 0x0070,
6665 "NVRAM configuration failed.\n");
David Miller4e08df32007-04-16 12:37:43 -07006666 }
6667 return (rval);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006668}
6669
Sawan Chandak4243c112016-01-27 12:03:31 -05006670uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha)
6671{
6672 struct qla27xx_image_status pri_image_status, sec_image_status;
6673 uint8_t valid_pri_image, valid_sec_image;
6674 uint32_t *wptr;
6675 uint32_t cnt, chksum, size;
6676 struct qla_hw_data *ha = vha->hw;
6677
6678 valid_pri_image = valid_sec_image = 1;
6679 ha->active_image = 0;
6680 size = sizeof(struct qla27xx_image_status) / sizeof(uint32_t);
6681
6682 if (!ha->flt_region_img_status_pri) {
6683 valid_pri_image = 0;
6684 goto check_sec_image;
6685 }
6686
6687 qla24xx_read_flash_data(vha, (uint32_t *)(&pri_image_status),
6688 ha->flt_region_img_status_pri, size);
6689
6690 if (pri_image_status.signature != QLA27XX_IMG_STATUS_SIGN) {
6691 ql_dbg(ql_dbg_init, vha, 0x018b,
6692 "Primary image signature (0x%x) not valid\n",
6693 pri_image_status.signature);
6694 valid_pri_image = 0;
6695 goto check_sec_image;
6696 }
6697
6698 wptr = (uint32_t *)(&pri_image_status);
6699 cnt = size;
6700
Joe Carnuccioda08ef52016-01-27 12:03:34 -05006701 for (chksum = 0; cnt--; wptr++)
6702 chksum += le32_to_cpu(*wptr);
Quinn Tran41dc5292017-01-19 22:28:03 -08006703
Sawan Chandak4243c112016-01-27 12:03:31 -05006704 if (chksum) {
6705 ql_dbg(ql_dbg_init, vha, 0x018c,
6706 "Checksum validation failed for primary image (0x%x)\n",
6707 chksum);
6708 valid_pri_image = 0;
6709 }
6710
6711check_sec_image:
6712 if (!ha->flt_region_img_status_sec) {
6713 valid_sec_image = 0;
6714 goto check_valid_image;
6715 }
6716
6717 qla24xx_read_flash_data(vha, (uint32_t *)(&sec_image_status),
6718 ha->flt_region_img_status_sec, size);
6719
6720 if (sec_image_status.signature != QLA27XX_IMG_STATUS_SIGN) {
6721 ql_dbg(ql_dbg_init, vha, 0x018d,
6722 "Secondary image signature(0x%x) not valid\n",
6723 sec_image_status.signature);
6724 valid_sec_image = 0;
6725 goto check_valid_image;
6726 }
6727
6728 wptr = (uint32_t *)(&sec_image_status);
6729 cnt = size;
Joe Carnuccioda08ef52016-01-27 12:03:34 -05006730 for (chksum = 0; cnt--; wptr++)
6731 chksum += le32_to_cpu(*wptr);
Sawan Chandak4243c112016-01-27 12:03:31 -05006732 if (chksum) {
6733 ql_dbg(ql_dbg_init, vha, 0x018e,
6734 "Checksum validation failed for secondary image (0x%x)\n",
6735 chksum);
6736 valid_sec_image = 0;
6737 }
6738
6739check_valid_image:
6740 if (valid_pri_image && (pri_image_status.image_status_mask & 0x1))
6741 ha->active_image = QLA27XX_PRIMARY_IMAGE;
6742 if (valid_sec_image && (sec_image_status.image_status_mask & 0x1)) {
6743 if (!ha->active_image ||
6744 pri_image_status.generation_number <
6745 sec_image_status.generation_number)
6746 ha->active_image = QLA27XX_SECONDARY_IMAGE;
6747 }
6748
6749 ql_dbg(ql_dbg_init, vha, 0x018f, "%s image\n",
6750 ha->active_image == 0 ? "default bootld and fw" :
6751 ha->active_image == 1 ? "primary" :
6752 ha->active_image == 2 ? "secondary" :
6753 "Invalid");
6754
6755 return ha->active_image;
6756}
6757
Adrian Bunk413975a2006-06-30 02:33:06 -07006758static int
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07006759qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
6760 uint32_t faddr)
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006761{
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006762 int rval = QLA_SUCCESS;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006763 int segments, fragment;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006764 uint32_t *dcode, dlen;
6765 uint32_t risc_addr;
6766 uint32_t risc_size;
6767 uint32_t i;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006768 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006769 struct req_que *req = ha->req_q_map[0];
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08006770
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006771 ql_dbg(ql_dbg_init, vha, 0x008b,
Chad Dupuiscfb09192011-11-18 09:03:07 -08006772 "FW: Loading firmware from flash (%x).\n", faddr);
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08006773
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006774 rval = QLA_SUCCESS;
6775
6776 segments = FA_RISC_CODE_SEGMENTS;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006777 dcode = (uint32_t *)req->ring;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006778 *srisc_addr = 0;
6779
Sawan Chandak4243c112016-01-27 12:03:31 -05006780 if (IS_QLA27XX(ha) &&
6781 qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
6782 faddr = ha->flt_region_fw_sec;
6783
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006784 /* Validate firmware image by checking version. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006785 qla24xx_read_flash_data(vha, dcode, faddr + 4, 4);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006786 for (i = 0; i < 4; i++)
6787 dcode[i] = be32_to_cpu(dcode[i]);
6788 if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
6789 dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
6790 (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
6791 dcode[3] == 0)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006792 ql_log(ql_log_fatal, vha, 0x008c,
6793 "Unable to verify the integrity of flash firmware "
6794 "image.\n");
6795 ql_log(ql_log_fatal, vha, 0x008d,
6796 "Firmware data: %08x %08x %08x %08x.\n",
6797 dcode[0], dcode[1], dcode[2], dcode[3]);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006798
6799 return QLA_FUNCTION_FAILED;
6800 }
6801
6802 while (segments && rval == QLA_SUCCESS) {
6803 /* Read segment's load information. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006804 qla24xx_read_flash_data(vha, dcode, faddr, 4);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006805
6806 risc_addr = be32_to_cpu(dcode[2]);
6807 *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr;
6808 risc_size = be32_to_cpu(dcode[3]);
6809
6810 fragment = 0;
6811 while (risc_size > 0 && rval == QLA_SUCCESS) {
6812 dlen = (uint32_t)(ha->fw_transfer_size >> 2);
6813 if (dlen > risc_size)
6814 dlen = risc_size;
6815
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006816 ql_dbg(ql_dbg_init, vha, 0x008e,
6817 "Loading risc segment@ risc addr %x "
6818 "number of dwords 0x%x offset 0x%x.\n",
6819 risc_addr, dlen, faddr);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006820
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006821 qla24xx_read_flash_data(vha, dcode, faddr, dlen);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006822 for (i = 0; i < dlen; i++)
6823 dcode[i] = swab32(dcode[i]);
6824
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006825 rval = qla2x00_load_ram(vha, req->dma, risc_addr,
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006826 dlen);
6827 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006828 ql_log(ql_log_fatal, vha, 0x008f,
6829 "Failed to load segment %d of firmware.\n",
6830 fragment);
Chad Dupuisf261f7a2014-09-25 05:17:03 -04006831 return QLA_FUNCTION_FAILED;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006832 }
6833
6834 faddr += dlen;
6835 risc_addr += dlen;
6836 risc_size -= dlen;
6837 fragment++;
6838 }
6839
6840 /* Next segment. */
6841 segments--;
6842 }
6843
Chad Dupuisf73cb692014-02-26 04:15:06 -05006844 if (!IS_QLA27XX(ha))
6845 return rval;
6846
6847 if (ha->fw_dump_template)
6848 vfree(ha->fw_dump_template);
6849 ha->fw_dump_template = NULL;
6850 ha->fw_dump_template_len = 0;
6851
6852 ql_dbg(ql_dbg_init, vha, 0x0161,
6853 "Loading fwdump template from %x\n", faddr);
6854 qla24xx_read_flash_data(vha, dcode, faddr, 7);
6855 risc_size = be32_to_cpu(dcode[2]);
6856 ql_dbg(ql_dbg_init, vha, 0x0162,
6857 "-> array size %x dwords\n", risc_size);
6858 if (risc_size == 0 || risc_size == ~0)
6859 goto default_template;
6860
6861 dlen = (risc_size - 8) * sizeof(*dcode);
6862 ql_dbg(ql_dbg_init, vha, 0x0163,
6863 "-> template allocating %x bytes...\n", dlen);
6864 ha->fw_dump_template = vmalloc(dlen);
6865 if (!ha->fw_dump_template) {
6866 ql_log(ql_log_warn, vha, 0x0164,
6867 "Failed fwdump template allocate %x bytes.\n", risc_size);
6868 goto default_template;
6869 }
6870
6871 faddr += 7;
6872 risc_size -= 8;
6873 dcode = ha->fw_dump_template;
6874 qla24xx_read_flash_data(vha, dcode, faddr, risc_size);
6875 for (i = 0; i < risc_size; i++)
6876 dcode[i] = le32_to_cpu(dcode[i]);
6877
6878 if (!qla27xx_fwdt_template_valid(dcode)) {
6879 ql_log(ql_log_warn, vha, 0x0165,
6880 "Failed fwdump template validate\n");
6881 goto default_template;
6882 }
6883
6884 dlen = qla27xx_fwdt_template_size(dcode);
6885 ql_dbg(ql_dbg_init, vha, 0x0166,
6886 "-> template size %x bytes\n", dlen);
6887 if (dlen > risc_size * sizeof(*dcode)) {
6888 ql_log(ql_log_warn, vha, 0x0167,
Himanshu Madhani4fae52b2017-06-06 13:55:23 -07006889 "Failed fwdump template exceeds array by %zx bytes\n",
Joe Carnuccio383a2982017-06-02 09:11:55 -07006890 (size_t)(dlen - risc_size * sizeof(*dcode)));
Chad Dupuisf73cb692014-02-26 04:15:06 -05006891 goto default_template;
6892 }
6893 ha->fw_dump_template_len = dlen;
6894 return rval;
6895
6896default_template:
6897 ql_log(ql_log_warn, vha, 0x0168, "Using default fwdump template\n");
6898 if (ha->fw_dump_template)
6899 vfree(ha->fw_dump_template);
6900 ha->fw_dump_template = NULL;
6901 ha->fw_dump_template_len = 0;
6902
6903 dlen = qla27xx_fwdt_template_default_size();
6904 ql_dbg(ql_dbg_init, vha, 0x0169,
6905 "-> template allocating %x bytes...\n", dlen);
6906 ha->fw_dump_template = vmalloc(dlen);
6907 if (!ha->fw_dump_template) {
6908 ql_log(ql_log_warn, vha, 0x016a,
6909 "Failed fwdump template allocate %x bytes.\n", risc_size);
6910 goto failed_template;
6911 }
6912
6913 dcode = ha->fw_dump_template;
6914 risc_size = dlen / sizeof(*dcode);
6915 memcpy(dcode, qla27xx_fwdt_template_default(), dlen);
6916 for (i = 0; i < risc_size; i++)
6917 dcode[i] = be32_to_cpu(dcode[i]);
6918
6919 if (!qla27xx_fwdt_template_valid(ha->fw_dump_template)) {
6920 ql_log(ql_log_warn, vha, 0x016b,
6921 "Failed fwdump template validate\n");
6922 goto failed_template;
6923 }
6924
6925 dlen = qla27xx_fwdt_template_size(ha->fw_dump_template);
6926 ql_dbg(ql_dbg_init, vha, 0x016c,
6927 "-> template size %x bytes\n", dlen);
6928 ha->fw_dump_template_len = dlen;
6929 return rval;
6930
6931failed_template:
6932 ql_log(ql_log_warn, vha, 0x016d, "Failed default fwdump template\n");
6933 if (ha->fw_dump_template)
6934 vfree(ha->fw_dump_template);
6935 ha->fw_dump_template = NULL;
6936 ha->fw_dump_template_len = 0;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006937 return rval;
6938}
6939
Giridhar Malavalie9454a82013-02-08 01:57:47 -05006940#define QLA_FW_URL "http://ldriver.qlogic.com/firmware/"
Andrew Vasquezd1c61902006-05-17 15:09:00 -07006941
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006942int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006943qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
Andrew Vasquez54333832005-11-09 15:49:04 -08006944{
6945 int rval;
6946 int i, fragment;
6947 uint16_t *wcode, *fwcode;
6948 uint32_t risc_addr, risc_size, fwclen, wlen, *seg;
6949 struct fw_blob *blob;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006950 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006951 struct req_que *req = ha->req_q_map[0];
Andrew Vasquez54333832005-11-09 15:49:04 -08006952
6953 /* Load firmware blob. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006954 blob = qla2x00_request_firmware(vha);
Andrew Vasquez54333832005-11-09 15:49:04 -08006955 if (!blob) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006956 ql_log(ql_log_info, vha, 0x0083,
Yannick Guerrini94bcf832015-02-26 22:49:34 +01006957 "Firmware image unavailable.\n");
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006958 ql_log(ql_log_info, vha, 0x0084,
6959 "Firmware images can be retrieved from: "QLA_FW_URL ".\n");
Andrew Vasquez54333832005-11-09 15:49:04 -08006960 return QLA_FUNCTION_FAILED;
6961 }
6962
6963 rval = QLA_SUCCESS;
6964
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006965 wcode = (uint16_t *)req->ring;
Andrew Vasquez54333832005-11-09 15:49:04 -08006966 *srisc_addr = 0;
6967 fwcode = (uint16_t *)blob->fw->data;
6968 fwclen = 0;
6969
6970 /* Validate firmware image by checking version. */
6971 if (blob->fw->size < 8 * sizeof(uint16_t)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006972 ql_log(ql_log_fatal, vha, 0x0085,
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08006973 "Unable to verify integrity of firmware image (%zd).\n",
Andrew Vasquez54333832005-11-09 15:49:04 -08006974 blob->fw->size);
6975 goto fail_fw_integrity;
6976 }
6977 for (i = 0; i < 4; i++)
6978 wcode[i] = be16_to_cpu(fwcode[i + 4]);
6979 if ((wcode[0] == 0xffff && wcode[1] == 0xffff && wcode[2] == 0xffff &&
6980 wcode[3] == 0xffff) || (wcode[0] == 0 && wcode[1] == 0 &&
6981 wcode[2] == 0 && wcode[3] == 0)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006982 ql_log(ql_log_fatal, vha, 0x0086,
6983 "Unable to verify integrity of firmware image.\n");
6984 ql_log(ql_log_fatal, vha, 0x0087,
6985 "Firmware data: %04x %04x %04x %04x.\n",
6986 wcode[0], wcode[1], wcode[2], wcode[3]);
Andrew Vasquez54333832005-11-09 15:49:04 -08006987 goto fail_fw_integrity;
6988 }
6989
6990 seg = blob->segs;
6991 while (*seg && rval == QLA_SUCCESS) {
6992 risc_addr = *seg;
6993 *srisc_addr = *srisc_addr == 0 ? *seg : *srisc_addr;
6994 risc_size = be16_to_cpu(fwcode[3]);
6995
6996 /* Validate firmware image size. */
6997 fwclen += risc_size * sizeof(uint16_t);
6998 if (blob->fw->size < fwclen) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006999 ql_log(ql_log_fatal, vha, 0x0088,
Andrew Vasquez54333832005-11-09 15:49:04 -08007000 "Unable to verify integrity of firmware image "
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08007001 "(%zd).\n", blob->fw->size);
Andrew Vasquez54333832005-11-09 15:49:04 -08007002 goto fail_fw_integrity;
7003 }
7004
7005 fragment = 0;
7006 while (risc_size > 0 && rval == QLA_SUCCESS) {
7007 wlen = (uint16_t)(ha->fw_transfer_size >> 1);
7008 if (wlen > risc_size)
7009 wlen = risc_size;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007010 ql_dbg(ql_dbg_init, vha, 0x0089,
7011 "Loading risc segment@ risc addr %x number of "
7012 "words 0x%x.\n", risc_addr, wlen);
Andrew Vasquez54333832005-11-09 15:49:04 -08007013
7014 for (i = 0; i < wlen; i++)
7015 wcode[i] = swab16(fwcode[i]);
7016
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007017 rval = qla2x00_load_ram(vha, req->dma, risc_addr,
Andrew Vasquez54333832005-11-09 15:49:04 -08007018 wlen);
7019 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007020 ql_log(ql_log_fatal, vha, 0x008a,
7021 "Failed to load segment %d of firmware.\n",
7022 fragment);
Andrew Vasquez54333832005-11-09 15:49:04 -08007023 break;
7024 }
7025
7026 fwcode += wlen;
7027 risc_addr += wlen;
7028 risc_size -= wlen;
7029 fragment++;
7030 }
7031
7032 /* Next segment. */
7033 seg++;
7034 }
7035 return rval;
7036
7037fail_fw_integrity:
7038 return QLA_FUNCTION_FAILED;
7039}
7040
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007041static int
7042qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007043{
7044 int rval;
7045 int segments, fragment;
7046 uint32_t *dcode, dlen;
7047 uint32_t risc_addr;
7048 uint32_t risc_size;
7049 uint32_t i;
Andrew Vasquez54333832005-11-09 15:49:04 -08007050 struct fw_blob *blob;
Chad Dupuisf73cb692014-02-26 04:15:06 -05007051 const uint32_t *fwcode;
7052 uint32_t fwclen;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007053 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007054 struct req_que *req = ha->req_q_map[0];
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007055
Andrew Vasquez54333832005-11-09 15:49:04 -08007056 /* Load firmware blob. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007057 blob = qla2x00_request_firmware(vha);
Andrew Vasquez54333832005-11-09 15:49:04 -08007058 if (!blob) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007059 ql_log(ql_log_warn, vha, 0x0090,
Yannick Guerrini94bcf832015-02-26 22:49:34 +01007060 "Firmware image unavailable.\n");
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007061 ql_log(ql_log_warn, vha, 0x0091,
7062 "Firmware images can be retrieved from: "
7063 QLA_FW_URL ".\n");
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007064
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007065 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007066 }
7067
Chad Dupuiscfb09192011-11-18 09:03:07 -08007068 ql_dbg(ql_dbg_init, vha, 0x0092,
7069 "FW: Loading via request-firmware.\n");
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007070
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007071 rval = QLA_SUCCESS;
7072
7073 segments = FA_RISC_CODE_SEGMENTS;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007074 dcode = (uint32_t *)req->ring;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007075 *srisc_addr = 0;
Andrew Vasquez54333832005-11-09 15:49:04 -08007076 fwcode = (uint32_t *)blob->fw->data;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007077 fwclen = 0;
7078
7079 /* Validate firmware image by checking version. */
Andrew Vasquez54333832005-11-09 15:49:04 -08007080 if (blob->fw->size < 8 * sizeof(uint32_t)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007081 ql_log(ql_log_fatal, vha, 0x0093,
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08007082 "Unable to verify integrity of firmware image (%zd).\n",
Andrew Vasquez54333832005-11-09 15:49:04 -08007083 blob->fw->size);
Chad Dupuisf73cb692014-02-26 04:15:06 -05007084 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007085 }
7086 for (i = 0; i < 4; i++)
7087 dcode[i] = be32_to_cpu(fwcode[i + 4]);
7088 if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
7089 dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
7090 (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
7091 dcode[3] == 0)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007092 ql_log(ql_log_fatal, vha, 0x0094,
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08007093 "Unable to verify integrity of firmware image (%zd).\n",
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007094 blob->fw->size);
7095 ql_log(ql_log_fatal, vha, 0x0095,
7096 "Firmware data: %08x %08x %08x %08x.\n",
7097 dcode[0], dcode[1], dcode[2], dcode[3]);
Chad Dupuisf73cb692014-02-26 04:15:06 -05007098 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007099 }
7100
7101 while (segments && rval == QLA_SUCCESS) {
7102 risc_addr = be32_to_cpu(fwcode[2]);
7103 *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr;
7104 risc_size = be32_to_cpu(fwcode[3]);
7105
7106 /* Validate firmware image size. */
7107 fwclen += risc_size * sizeof(uint32_t);
Andrew Vasquez54333832005-11-09 15:49:04 -08007108 if (blob->fw->size < fwclen) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007109 ql_log(ql_log_fatal, vha, 0x0096,
Andrew Vasquez54333832005-11-09 15:49:04 -08007110 "Unable to verify integrity of firmware image "
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08007111 "(%zd).\n", blob->fw->size);
Chad Dupuisf73cb692014-02-26 04:15:06 -05007112 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007113 }
7114
7115 fragment = 0;
7116 while (risc_size > 0 && rval == QLA_SUCCESS) {
7117 dlen = (uint32_t)(ha->fw_transfer_size >> 2);
7118 if (dlen > risc_size)
7119 dlen = risc_size;
7120
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007121 ql_dbg(ql_dbg_init, vha, 0x0097,
7122 "Loading risc segment@ risc addr %x "
7123 "number of dwords 0x%x.\n", risc_addr, dlen);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007124
7125 for (i = 0; i < dlen; i++)
7126 dcode[i] = swab32(fwcode[i]);
7127
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007128 rval = qla2x00_load_ram(vha, req->dma, risc_addr,
andrew.vasquez@qlogic.com590f98e2006-01-13 17:05:37 -08007129 dlen);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007130 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007131 ql_log(ql_log_fatal, vha, 0x0098,
7132 "Failed to load segment %d of firmware.\n",
7133 fragment);
Chad Dupuisf261f7a2014-09-25 05:17:03 -04007134 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007135 }
7136
7137 fwcode += dlen;
7138 risc_addr += dlen;
7139 risc_size -= dlen;
7140 fragment++;
7141 }
7142
7143 /* Next segment. */
7144 segments--;
7145 }
Chad Dupuisf73cb692014-02-26 04:15:06 -05007146
7147 if (!IS_QLA27XX(ha))
7148 return rval;
7149
7150 if (ha->fw_dump_template)
7151 vfree(ha->fw_dump_template);
7152 ha->fw_dump_template = NULL;
7153 ha->fw_dump_template_len = 0;
7154
7155 ql_dbg(ql_dbg_init, vha, 0x171,
Chad Dupuis97ea7022014-03-13 14:16:40 -04007156 "Loading fwdump template from %x\n",
7157 (uint32_t)((void *)fwcode - (void *)blob->fw->data));
Chad Dupuisf73cb692014-02-26 04:15:06 -05007158 risc_size = be32_to_cpu(fwcode[2]);
7159 ql_dbg(ql_dbg_init, vha, 0x172,
7160 "-> array size %x dwords\n", risc_size);
7161 if (risc_size == 0 || risc_size == ~0)
7162 goto default_template;
7163
7164 dlen = (risc_size - 8) * sizeof(*fwcode);
7165 ql_dbg(ql_dbg_init, vha, 0x0173,
7166 "-> template allocating %x bytes...\n", dlen);
7167 ha->fw_dump_template = vmalloc(dlen);
7168 if (!ha->fw_dump_template) {
7169 ql_log(ql_log_warn, vha, 0x0174,
7170 "Failed fwdump template allocate %x bytes.\n", risc_size);
7171 goto default_template;
7172 }
7173
7174 fwcode += 7;
7175 risc_size -= 8;
7176 dcode = ha->fw_dump_template;
7177 for (i = 0; i < risc_size; i++)
7178 dcode[i] = le32_to_cpu(fwcode[i]);
7179
7180 if (!qla27xx_fwdt_template_valid(dcode)) {
7181 ql_log(ql_log_warn, vha, 0x0175,
7182 "Failed fwdump template validate\n");
7183 goto default_template;
7184 }
7185
7186 dlen = qla27xx_fwdt_template_size(dcode);
7187 ql_dbg(ql_dbg_init, vha, 0x0176,
7188 "-> template size %x bytes\n", dlen);
7189 if (dlen > risc_size * sizeof(*fwcode)) {
7190 ql_log(ql_log_warn, vha, 0x0177,
Himanshu Madhani4fae52b2017-06-06 13:55:23 -07007191 "Failed fwdump template exceeds array by %zx bytes\n",
Joe Carnuccio383a2982017-06-02 09:11:55 -07007192 (size_t)(dlen - risc_size * sizeof(*fwcode)));
Chad Dupuisf73cb692014-02-26 04:15:06 -05007193 goto default_template;
7194 }
7195 ha->fw_dump_template_len = dlen;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007196 return rval;
7197
Chad Dupuisf73cb692014-02-26 04:15:06 -05007198default_template:
7199 ql_log(ql_log_warn, vha, 0x0178, "Using default fwdump template\n");
7200 if (ha->fw_dump_template)
7201 vfree(ha->fw_dump_template);
7202 ha->fw_dump_template = NULL;
7203 ha->fw_dump_template_len = 0;
7204
7205 dlen = qla27xx_fwdt_template_default_size();
7206 ql_dbg(ql_dbg_init, vha, 0x0179,
7207 "-> template allocating %x bytes...\n", dlen);
7208 ha->fw_dump_template = vmalloc(dlen);
7209 if (!ha->fw_dump_template) {
7210 ql_log(ql_log_warn, vha, 0x017a,
7211 "Failed fwdump template allocate %x bytes.\n", risc_size);
7212 goto failed_template;
7213 }
7214
7215 dcode = ha->fw_dump_template;
7216 risc_size = dlen / sizeof(*fwcode);
7217 fwcode = qla27xx_fwdt_template_default();
7218 for (i = 0; i < risc_size; i++)
7219 dcode[i] = be32_to_cpu(fwcode[i]);
7220
7221 if (!qla27xx_fwdt_template_valid(ha->fw_dump_template)) {
7222 ql_log(ql_log_warn, vha, 0x017b,
7223 "Failed fwdump template validate\n");
7224 goto failed_template;
7225 }
7226
7227 dlen = qla27xx_fwdt_template_size(ha->fw_dump_template);
7228 ql_dbg(ql_dbg_init, vha, 0x017c,
7229 "-> template size %x bytes\n", dlen);
7230 ha->fw_dump_template_len = dlen;
7231 return rval;
7232
7233failed_template:
7234 ql_log(ql_log_warn, vha, 0x017d, "Failed default fwdump template\n");
7235 if (ha->fw_dump_template)
7236 vfree(ha->fw_dump_template);
7237 ha->fw_dump_template = NULL;
7238 ha->fw_dump_template_len = 0;
7239 return rval;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007240}
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007241
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007242int
7243qla24xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
7244{
7245 int rval;
7246
Andrew Vasqueze337d902009-04-06 22:33:49 -07007247 if (ql2xfwloadbin == 1)
7248 return qla81xx_load_risc(vha, srisc_addr);
7249
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007250 /*
7251 * FW Load priority:
7252 * 1) Firmware via request-firmware interface (.bin file).
7253 * 2) Firmware residing in flash.
7254 */
7255 rval = qla24xx_load_risc_blob(vha, srisc_addr);
7256 if (rval == QLA_SUCCESS)
7257 return rval;
7258
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007259 return qla24xx_load_risc_flash(vha, srisc_addr,
7260 vha->hw->flt_region_fw);
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007261}
7262
7263int
7264qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
7265{
7266 int rval;
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007267 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007268
Andrew Vasqueze337d902009-04-06 22:33:49 -07007269 if (ql2xfwloadbin == 2)
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007270 goto try_blob_fw;
Andrew Vasqueze337d902009-04-06 22:33:49 -07007271
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007272 /*
7273 * FW Load priority:
7274 * 1) Firmware residing in flash.
7275 * 2) Firmware via request-firmware interface (.bin file).
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007276 * 3) Golden-Firmware residing in flash -- limited operation.
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007277 */
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007278 rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_fw);
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007279 if (rval == QLA_SUCCESS)
7280 return rval;
7281
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007282try_blob_fw:
7283 rval = qla24xx_load_risc_blob(vha, srisc_addr);
7284 if (rval == QLA_SUCCESS || !ha->flt_region_gold_fw)
7285 return rval;
7286
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007287 ql_log(ql_log_info, vha, 0x0099,
7288 "Attempting to fallback to golden firmware.\n");
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007289 rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_gold_fw);
7290 if (rval != QLA_SUCCESS)
7291 return rval;
7292
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007293 ql_log(ql_log_info, vha, 0x009a, "Update operational firmware.\n");
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007294 ha->flags.running_gold_fw = 1;
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007295 return rval;
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007296}
7297
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007298void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007299qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha)
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007300{
7301 int ret, retries;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007302 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007303
Andrew Vasquez85880802009-12-15 21:29:46 -08007304 if (ha->flags.pci_channel_io_perm_failure)
7305 return;
Andrew Vasqueze4289242007-07-19 15:05:56 -07007306 if (!IS_FWI2_CAPABLE(ha))
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007307 return;
Andrew Vasquez75edf812007-05-07 07:43:00 -07007308 if (!ha->fw_major_version)
7309 return;
Quinn Tranec7193e2017-03-15 09:48:55 -07007310 if (!ha->flags.fw_started)
7311 return;
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007312
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007313 ret = qla2x00_stop_firmware(vha);
Andrew Vasquez7c7f1f22008-02-28 14:06:09 -08007314 for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT &&
Andrew Vasquezb469a7c2009-04-06 22:33:48 -07007315 ret != QLA_INVALID_COMMAND && retries ; retries--) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007316 ha->isp_ops->reset_chip(vha);
7317 if (ha->isp_ops->chip_diag(vha) != QLA_SUCCESS)
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007318 continue;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007319 if (qla2x00_setup_chip(vha) != QLA_SUCCESS)
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007320 continue;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007321 ql_log(ql_log_info, vha, 0x8015,
7322 "Attempting retry of stop-firmware command.\n");
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007323 ret = qla2x00_stop_firmware(vha);
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007324 }
Quinn Tranec7193e2017-03-15 09:48:55 -07007325
Quinn Tran4b60c822017-06-13 20:47:21 -07007326 QLA_FW_STOPPED(ha);
Quinn Tranec7193e2017-03-15 09:48:55 -07007327 ha->flags.fw_init_done = 0;
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007328}
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007329
7330int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007331qla24xx_configure_vhba(scsi_qla_host_t *vha)
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007332{
7333 int rval = QLA_SUCCESS;
Chad Dupuis0b91d112012-02-09 11:15:42 -08007334 int rval2;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007335 uint16_t mb[MAILBOX_REGISTER_COUNT];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007336 struct qla_hw_data *ha = vha->hw;
7337 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Anirban Chakraborty67c2e932009-04-06 22:33:42 -07007338 struct req_que *req;
7339 struct rsp_que *rsp;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007340
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007341 if (!vha->vp_idx)
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007342 return -EINVAL;
7343
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007344 rval = qla2x00_fw_ready(base_vha);
Michael Hernandezd7459522016-12-12 14:40:07 -08007345 if (vha->qpair)
7346 req = vha->qpair->req;
Anirban Chakraborty67c2e932009-04-06 22:33:42 -07007347 else
Michael Hernandezd7459522016-12-12 14:40:07 -08007348 req = ha->req_q_map[0];
Anirban Chakraborty67c2e932009-04-06 22:33:42 -07007349 rsp = req->rsp;
7350
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007351 if (rval == QLA_SUCCESS) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007352 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007353 qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007354 }
7355
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007356 vha->flags.management_server_logged_in = 0;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007357
7358 /* Login to SNS first */
Chad Dupuis0b91d112012-02-09 11:15:42 -08007359 rval2 = ha->isp_ops->fabric_login(vha, NPH_SNS, 0xff, 0xff, 0xfc, mb,
7360 BIT_1);
7361 if (rval2 != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {
7362 if (rval2 == QLA_MEMORY_ALLOC_FAILED)
7363 ql_dbg(ql_dbg_init, vha, 0x0120,
7364 "Failed SNS login: loop_id=%x, rval2=%d\n",
7365 NPH_SNS, rval2);
7366 else
7367 ql_dbg(ql_dbg_init, vha, 0x0103,
7368 "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x "
7369 "mb[2]=%x mb[6]=%x mb[7]=%x.\n",
7370 NPH_SNS, mb[0], mb[1], mb[2], mb[6], mb[7]);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007371 return (QLA_FUNCTION_FAILED);
7372 }
7373
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007374 atomic_set(&vha->loop_down_timer, 0);
7375 atomic_set(&vha->loop_state, LOOP_UP);
7376 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
7377 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
7378 rval = qla2x00_loop_resync(base_vha);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007379
7380 return rval;
7381}
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007382
7383/* 84XX Support **************************************************************/
7384
7385static LIST_HEAD(qla_cs84xx_list);
7386static DEFINE_MUTEX(qla_cs84xx_mutex);
7387
7388static struct qla_chip_state_84xx *
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007389qla84xx_get_chip(struct scsi_qla_host *vha)
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007390{
7391 struct qla_chip_state_84xx *cs84xx;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007392 struct qla_hw_data *ha = vha->hw;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007393
7394 mutex_lock(&qla_cs84xx_mutex);
7395
7396 /* Find any shared 84xx chip. */
7397 list_for_each_entry(cs84xx, &qla_cs84xx_list, list) {
7398 if (cs84xx->bus == ha->pdev->bus) {
7399 kref_get(&cs84xx->kref);
7400 goto done;
7401 }
7402 }
7403
7404 cs84xx = kzalloc(sizeof(*cs84xx), GFP_KERNEL);
7405 if (!cs84xx)
7406 goto done;
7407
7408 kref_init(&cs84xx->kref);
7409 spin_lock_init(&cs84xx->access_lock);
7410 mutex_init(&cs84xx->fw_update_mutex);
7411 cs84xx->bus = ha->pdev->bus;
7412
7413 list_add_tail(&cs84xx->list, &qla_cs84xx_list);
7414done:
7415 mutex_unlock(&qla_cs84xx_mutex);
7416 return cs84xx;
7417}
7418
7419static void
7420__qla84xx_chip_release(struct kref *kref)
7421{
7422 struct qla_chip_state_84xx *cs84xx =
7423 container_of(kref, struct qla_chip_state_84xx, kref);
7424
7425 mutex_lock(&qla_cs84xx_mutex);
7426 list_del(&cs84xx->list);
7427 mutex_unlock(&qla_cs84xx_mutex);
7428 kfree(cs84xx);
7429}
7430
7431void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007432qla84xx_put_chip(struct scsi_qla_host *vha)
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007433{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007434 struct qla_hw_data *ha = vha->hw;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007435 if (ha->cs84xx)
7436 kref_put(&ha->cs84xx->kref, __qla84xx_chip_release);
7437}
7438
7439static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007440qla84xx_init_chip(scsi_qla_host_t *vha)
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007441{
7442 int rval;
7443 uint16_t status[2];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007444 struct qla_hw_data *ha = vha->hw;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007445
7446 mutex_lock(&ha->cs84xx->fw_update_mutex);
7447
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007448 rval = qla84xx_verify_chip(vha, status);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007449
7450 mutex_unlock(&ha->cs84xx->fw_update_mutex);
7451
7452 return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED:
7453 QLA_SUCCESS;
7454}
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007455
7456/* 81XX Support **************************************************************/
7457
7458int
7459qla81xx_nvram_config(scsi_qla_host_t *vha)
7460{
7461 int rval;
7462 struct init_cb_81xx *icb;
7463 struct nvram_81xx *nv;
7464 uint32_t *dptr;
7465 uint8_t *dptr1, *dptr2;
7466 uint32_t chksum;
7467 uint16_t cnt;
7468 struct qla_hw_data *ha = vha->hw;
7469
7470 rval = QLA_SUCCESS;
7471 icb = (struct init_cb_81xx *)ha->init_cb;
7472 nv = ha->nvram;
7473
7474 /* Determine NVRAM starting address. */
7475 ha->nvram_size = sizeof(struct nvram_81xx);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007476 ha->vpd_size = FA_NVRAM_VPD_SIZE;
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04007477 if (IS_P3P_TYPE(ha) || IS_QLA8031(ha))
7478 ha->vpd_size = FA_VPD_SIZE_82XX;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007479
7480 /* Get VPD data into cache */
7481 ha->vpd = ha->nvram + VPD_OFFSET;
Andrew Vasquez3d79038f2009-03-24 09:08:14 -07007482 ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2,
7483 ha->vpd_size);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007484
7485 /* Get NVRAM data into cache and calculate checksum. */
Andrew Vasquez3d79038f2009-03-24 09:08:14 -07007486 ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2,
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007487 ha->nvram_size);
Andrew Vasquez3d79038f2009-03-24 09:08:14 -07007488 dptr = (uint32_t *)nv;
Joe Carnuccioda08ef52016-01-27 12:03:34 -05007489 for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++)
7490 chksum += le32_to_cpu(*dptr);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007491
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007492 ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0111,
7493 "Contents of NVRAM:\n");
7494 ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0112,
7495 (uint8_t *)nv, ha->nvram_size);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007496
7497 /* Bad NVRAM data, set defaults parameters. */
7498 if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P'
7499 || nv->id[3] != ' ' ||
Bart Van Asschead950362015-07-09 07:24:08 -07007500 nv->nvram_version < cpu_to_le16(ICB_VERSION)) {
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007501 /* Reset NVRAM data. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007502 ql_log(ql_log_info, vha, 0x0073,
Raul Porcel9e336522012-05-15 14:34:08 -04007503 "Inconsistent NVRAM detected: checksum=0x%x id=%c "
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007504 "version=0x%x.\n", chksum, nv->id[0],
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007505 le16_to_cpu(nv->nvram_version));
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007506 ql_log(ql_log_info, vha, 0x0074,
7507 "Falling back to functioning (yet invalid -- WWPN) "
7508 "defaults.\n");
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007509
7510 /*
7511 * Set default initialization control block.
7512 */
7513 memset(nv, 0, ha->nvram_size);
Bart Van Asschead950362015-07-09 07:24:08 -07007514 nv->nvram_version = cpu_to_le16(ICB_VERSION);
7515 nv->version = cpu_to_le16(ICB_VERSION);
Joe Carnuccio98aee702014-09-25 05:16:38 -04007516 nv->frame_payload_size = 2048;
Bart Van Asschead950362015-07-09 07:24:08 -07007517 nv->execution_throttle = cpu_to_le16(0xFFFF);
7518 nv->exchange_count = cpu_to_le16(0);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007519 nv->port_name[0] = 0x21;
Chad Dupuisf73cb692014-02-26 04:15:06 -05007520 nv->port_name[1] = 0x00 + ha->port_no + 1;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007521 nv->port_name[2] = 0x00;
7522 nv->port_name[3] = 0xe0;
7523 nv->port_name[4] = 0x8b;
7524 nv->port_name[5] = 0x1c;
7525 nv->port_name[6] = 0x55;
7526 nv->port_name[7] = 0x86;
7527 nv->node_name[0] = 0x20;
7528 nv->node_name[1] = 0x00;
7529 nv->node_name[2] = 0x00;
7530 nv->node_name[3] = 0xe0;
7531 nv->node_name[4] = 0x8b;
7532 nv->node_name[5] = 0x1c;
7533 nv->node_name[6] = 0x55;
7534 nv->node_name[7] = 0x86;
Bart Van Asschead950362015-07-09 07:24:08 -07007535 nv->login_retry_count = cpu_to_le16(8);
7536 nv->interrupt_delay_timer = cpu_to_le16(0);
7537 nv->login_timeout = cpu_to_le16(0);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007538 nv->firmware_options_1 =
Bart Van Asschead950362015-07-09 07:24:08 -07007539 cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1);
7540 nv->firmware_options_2 = cpu_to_le32(2 << 4);
7541 nv->firmware_options_2 |= cpu_to_le32(BIT_12);
7542 nv->firmware_options_3 = cpu_to_le32(2 << 13);
7543 nv->host_p = cpu_to_le32(BIT_11|BIT_10);
7544 nv->efi_parameters = cpu_to_le32(0);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007545 nv->reset_delay = 5;
Bart Van Asschead950362015-07-09 07:24:08 -07007546 nv->max_luns_per_target = cpu_to_le16(128);
7547 nv->port_down_retry_count = cpu_to_le16(30);
7548 nv->link_down_timeout = cpu_to_le16(180);
Andrew Vasquezeeebcc92009-06-03 09:55:24 -07007549 nv->enode_mac[0] = 0x00;
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08007550 nv->enode_mac[1] = 0xC0;
7551 nv->enode_mac[2] = 0xDD;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007552 nv->enode_mac[3] = 0x04;
7553 nv->enode_mac[4] = 0x05;
Chad Dupuisf73cb692014-02-26 04:15:06 -05007554 nv->enode_mac[5] = 0x06 + ha->port_no + 1;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007555
7556 rval = 1;
7557 }
7558
Arun Easi9e522cd2012-08-22 14:21:31 -04007559 if (IS_T10_PI_CAPABLE(ha))
7560 nv->frame_payload_size &= ~7;
7561
Arun Easiaa230bc2013-01-30 03:34:39 -05007562 qlt_81xx_config_nvram_stage1(vha, nv);
7563
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007564 /* Reset Initialization control block */
Andrew Vasquez773120e2011-05-10 11:30:14 -07007565 memset(icb, 0, ha->init_cb_size);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007566
7567 /* Copy 1st segment. */
7568 dptr1 = (uint8_t *)icb;
7569 dptr2 = (uint8_t *)&nv->version;
7570 cnt = (uint8_t *)&icb->response_q_inpointer - (uint8_t *)&icb->version;
7571 while (cnt--)
7572 *dptr1++ = *dptr2++;
7573
7574 icb->login_retry_count = nv->login_retry_count;
7575
7576 /* Copy 2nd segment. */
7577 dptr1 = (uint8_t *)&icb->interrupt_delay_timer;
7578 dptr2 = (uint8_t *)&nv->interrupt_delay_timer;
7579 cnt = (uint8_t *)&icb->reserved_5 -
7580 (uint8_t *)&icb->interrupt_delay_timer;
7581 while (cnt--)
7582 *dptr1++ = *dptr2++;
7583
7584 memcpy(icb->enode_mac, nv->enode_mac, sizeof(icb->enode_mac));
7585 /* Some boards (with valid NVRAMs) still have NULL enode_mac!! */
7586 if (!memcmp(icb->enode_mac, "\0\0\0\0\0\0", sizeof(icb->enode_mac))) {
Andrew Vasquez69e5f1e2012-02-09 11:15:35 -08007587 icb->enode_mac[0] = 0x00;
7588 icb->enode_mac[1] = 0xC0;
7589 icb->enode_mac[2] = 0xDD;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007590 icb->enode_mac[3] = 0x04;
7591 icb->enode_mac[4] = 0x05;
Chad Dupuisf73cb692014-02-26 04:15:06 -05007592 icb->enode_mac[5] = 0x06 + ha->port_no + 1;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007593 }
7594
Andrew Vasquezb64b0e82009-03-24 09:08:01 -07007595 /* Use extended-initialization control block. */
7596 memcpy(ha->ex_init_cb, &nv->ex_version, sizeof(*ha->ex_init_cb));
7597
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007598 /*
7599 * Setup driver NVRAM options.
7600 */
7601 qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name),
Giridhar Malavalia9083012010-04-12 17:59:55 -07007602 "QLE8XXX");
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007603
Arun Easiaa230bc2013-01-30 03:34:39 -05007604 qlt_81xx_config_nvram_stage2(vha, icb);
7605
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007606 /* Use alternate WWN? */
Bart Van Asschead950362015-07-09 07:24:08 -07007607 if (nv->host_p & cpu_to_le32(BIT_15)) {
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007608 memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
7609 memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
7610 }
7611
7612 /* Prepare nodename */
Bart Van Asschead950362015-07-09 07:24:08 -07007613 if ((icb->firmware_options_1 & cpu_to_le32(BIT_14)) == 0) {
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007614 /*
7615 * Firmware will apply the following mask if the nodename was
7616 * not provided.
7617 */
7618 memcpy(icb->node_name, icb->port_name, WWN_SIZE);
7619 icb->node_name[0] &= 0xF0;
7620 }
7621
7622 /* Set host adapter parameters. */
7623 ha->flags.disable_risc_code_load = 0;
7624 ha->flags.enable_lip_reset = 0;
7625 ha->flags.enable_lip_full_login =
7626 le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0;
7627 ha->flags.enable_target_reset =
7628 le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0;
7629 ha->flags.enable_led_scheme = 0;
7630 ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0;
7631
7632 ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) &
7633 (BIT_6 | BIT_5 | BIT_4)) >> 4;
7634
7635 /* save HBA serial number */
7636 ha->serial0 = icb->port_name[5];
7637 ha->serial1 = icb->port_name[6];
7638 ha->serial2 = icb->port_name[7];
7639 memcpy(vha->node_name, icb->node_name, WWN_SIZE);
7640 memcpy(vha->port_name, icb->port_name, WWN_SIZE);
7641
Bart Van Asschead950362015-07-09 07:24:08 -07007642 icb->execution_throttle = cpu_to_le16(0xFFFF);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007643
7644 ha->retry_count = le16_to_cpu(nv->login_retry_count);
7645
7646 /* Set minimum login_timeout to 4 seconds. */
7647 if (le16_to_cpu(nv->login_timeout) < ql2xlogintimeout)
7648 nv->login_timeout = cpu_to_le16(ql2xlogintimeout);
7649 if (le16_to_cpu(nv->login_timeout) < 4)
Bart Van Asschead950362015-07-09 07:24:08 -07007650 nv->login_timeout = cpu_to_le16(4);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007651 ha->login_timeout = le16_to_cpu(nv->login_timeout);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007652
7653 /* Set minimum RATOV to 100 tenths of a second. */
7654 ha->r_a_tov = 100;
7655
7656 ha->loop_reset_delay = nv->reset_delay;
7657
7658 /* Link Down Timeout = 0:
7659 *
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04007660 * When Port Down timer expires we will start returning
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007661 * I/O's to OS with "DID_NO_CONNECT".
7662 *
7663 * Link Down Timeout != 0:
7664 *
7665 * The driver waits for the link to come up after link down
7666 * before returning I/Os to OS with "DID_NO_CONNECT".
7667 */
7668 if (le16_to_cpu(nv->link_down_timeout) == 0) {
7669 ha->loop_down_abort_time =
7670 (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT);
7671 } else {
7672 ha->link_down_timeout = le16_to_cpu(nv->link_down_timeout);
7673 ha->loop_down_abort_time =
7674 (LOOP_DOWN_TIME - ha->link_down_timeout);
7675 }
7676
7677 /* Need enough time to try and get the port back. */
7678 ha->port_down_retry_count = le16_to_cpu(nv->port_down_retry_count);
7679 if (qlport_down_retry)
7680 ha->port_down_retry_count = qlport_down_retry;
7681
7682 /* Set login_retry_count */
7683 ha->login_retry_count = le16_to_cpu(nv->login_retry_count);
7684 if (ha->port_down_retry_count ==
7685 le16_to_cpu(nv->port_down_retry_count) &&
7686 ha->port_down_retry_count > 3)
7687 ha->login_retry_count = ha->port_down_retry_count;
7688 else if (ha->port_down_retry_count > (int)ha->login_retry_count)
7689 ha->login_retry_count = ha->port_down_retry_count;
7690 if (ql2xloginretrycount)
7691 ha->login_retry_count = ql2xloginretrycount;
7692
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08007693 /* if not running MSI-X we need handshaking on interrupts */
Chad Dupuisf73cb692014-02-26 04:15:06 -05007694 if (!vha->hw->flags.msix_enabled && (IS_QLA83XX(ha) || IS_QLA27XX(ha)))
Bart Van Asschead950362015-07-09 07:24:08 -07007695 icb->firmware_options_2 |= cpu_to_le32(BIT_22);
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08007696
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007697 /* Enable ZIO. */
7698 if (!vha->flags.init_done) {
7699 ha->zio_mode = le32_to_cpu(icb->firmware_options_2) &
7700 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
7701 ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ?
7702 le16_to_cpu(icb->interrupt_delay_timer): 2;
7703 }
Bart Van Asschead950362015-07-09 07:24:08 -07007704 icb->firmware_options_2 &= cpu_to_le32(
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007705 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
7706 vha->flags.process_response_queue = 0;
7707 if (ha->zio_mode != QLA_ZIO_DISABLED) {
7708 ha->zio_mode = QLA_ZIO_MODE_6;
7709
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007710 ql_log(ql_log_info, vha, 0x0075,
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007711 "ZIO mode %d enabled; timer delay (%d us).\n",
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007712 ha->zio_mode,
7713 ha->zio_timer * 100);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007714
7715 icb->firmware_options_2 |= cpu_to_le32(
7716 (uint32_t)ha->zio_mode);
7717 icb->interrupt_delay_timer = cpu_to_le16(ha->zio_timer);
7718 vha->flags.process_response_queue = 1;
7719 }
7720
Quinn Tran41dc5292017-01-19 22:28:03 -08007721 /* enable RIDA Format2 */
7722 if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha))
7723 icb->firmware_options_3 |= BIT_0;
7724
Duane Grigsbyedd05de2017-10-13 09:34:06 -07007725 if (IS_QLA27XX(ha)) {
7726 icb->firmware_options_3 |= BIT_8;
7727 ql_dbg(ql_log_info, vha, 0x0075,
7728 "Enabling direct connection.\n");
7729 }
7730
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007731 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007732 ql_log(ql_log_warn, vha, 0x0076,
7733 "NVRAM configuration failed.\n");
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007734 }
7735 return (rval);
7736}
7737
Giridhar Malavalia9083012010-04-12 17:59:55 -07007738int
7739qla82xx_restart_isp(scsi_qla_host_t *vha)
7740{
7741 int status, rval;
Giridhar Malavalia9083012010-04-12 17:59:55 -07007742 struct qla_hw_data *ha = vha->hw;
7743 struct req_que *req = ha->req_q_map[0];
7744 struct rsp_que *rsp = ha->rsp_q_map[0];
7745 struct scsi_qla_host *vp;
Arun Easifeafb7b2010-09-03 14:57:00 -07007746 unsigned long flags;
Giridhar Malavalia9083012010-04-12 17:59:55 -07007747
7748 status = qla2x00_init_rings(vha);
7749 if (!status) {
7750 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
7751 ha->flags.chip_reset_done = 1;
7752
7753 status = qla2x00_fw_ready(vha);
7754 if (!status) {
Giridhar Malavalia9083012010-04-12 17:59:55 -07007755 /* Issue a marker after FW becomes ready. */
7756 qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
Giridhar Malavalia9083012010-04-12 17:59:55 -07007757 vha->flags.online = 1;
Chad Dupuis7108b762014-04-11 16:54:45 -04007758 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
Giridhar Malavalia9083012010-04-12 17:59:55 -07007759 }
7760
7761 /* if no cable then assume it's good */
7762 if ((vha->device_flags & DFLG_NO_CABLE))
7763 status = 0;
Giridhar Malavalia9083012010-04-12 17:59:55 -07007764 }
7765
7766 if (!status) {
7767 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
7768
7769 if (!atomic_read(&vha->loop_down_timer)) {
7770 /*
7771 * Issue marker command only when we are going
7772 * to start the I/O .
7773 */
7774 vha->marker_needed = 1;
7775 }
7776
Giridhar Malavalia9083012010-04-12 17:59:55 -07007777 ha->isp_ops->enable_intrs(ha);
7778
7779 ha->isp_abort_cnt = 0;
7780 clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
7781
Saurav Kashyap53296782011-05-10 11:30:06 -07007782 /* Update the firmware version */
Giridhar Malavali31731672011-08-16 11:31:54 -07007783 status = qla82xx_check_md_needed(vha);
Saurav Kashyap53296782011-05-10 11:30:06 -07007784
Giridhar Malavalia9083012010-04-12 17:59:55 -07007785 if (ha->fce) {
7786 ha->flags.fce_enabled = 1;
7787 memset(ha->fce, 0,
7788 fce_calc_size(ha->fce_bufs));
7789 rval = qla2x00_enable_fce_trace(vha,
7790 ha->fce_dma, ha->fce_bufs, ha->fce_mb,
7791 &ha->fce_bufs);
7792 if (rval) {
Chad Dupuiscfb09192011-11-18 09:03:07 -08007793 ql_log(ql_log_warn, vha, 0x8001,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007794 "Unable to reinitialize FCE (%d).\n",
7795 rval);
Giridhar Malavalia9083012010-04-12 17:59:55 -07007796 ha->flags.fce_enabled = 0;
7797 }
7798 }
7799
7800 if (ha->eft) {
7801 memset(ha->eft, 0, EFT_SIZE);
7802 rval = qla2x00_enable_eft_trace(vha,
7803 ha->eft_dma, EFT_NUM_BUFFERS);
7804 if (rval) {
Chad Dupuiscfb09192011-11-18 09:03:07 -08007805 ql_log(ql_log_warn, vha, 0x8010,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007806 "Unable to reinitialize EFT (%d).\n",
7807 rval);
Giridhar Malavalia9083012010-04-12 17:59:55 -07007808 }
7809 }
Giridhar Malavalia9083012010-04-12 17:59:55 -07007810 }
7811
7812 if (!status) {
Chad Dupuiscfb09192011-11-18 09:03:07 -08007813 ql_dbg(ql_dbg_taskm, vha, 0x8011,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007814 "qla82xx_restart_isp succeeded.\n");
Arun Easifeafb7b2010-09-03 14:57:00 -07007815
7816 spin_lock_irqsave(&ha->vport_slock, flags);
7817 list_for_each_entry(vp, &ha->vp_list, list) {
7818 if (vp->vp_idx) {
7819 atomic_inc(&vp->vref_count);
7820 spin_unlock_irqrestore(&ha->vport_slock, flags);
7821
Giridhar Malavalia9083012010-04-12 17:59:55 -07007822 qla2x00_vp_abort_isp(vp);
Arun Easifeafb7b2010-09-03 14:57:00 -07007823
7824 spin_lock_irqsave(&ha->vport_slock, flags);
7825 atomic_dec(&vp->vref_count);
7826 }
Giridhar Malavalia9083012010-04-12 17:59:55 -07007827 }
Arun Easifeafb7b2010-09-03 14:57:00 -07007828 spin_unlock_irqrestore(&ha->vport_slock, flags);
7829
Giridhar Malavalia9083012010-04-12 17:59:55 -07007830 } else {
Chad Dupuiscfb09192011-11-18 09:03:07 -08007831 ql_log(ql_log_warn, vha, 0x8016,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007832 "qla82xx_restart_isp **** FAILED ****.\n");
Giridhar Malavalia9083012010-04-12 17:59:55 -07007833 }
7834
7835 return status;
7836}
7837
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007838void
Andrew Vasquezae97c912010-02-18 10:07:28 -08007839qla81xx_update_fw_options(scsi_qla_host_t *vha)
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007840{
Andrew Vasquezae97c912010-02-18 10:07:28 -08007841 struct qla_hw_data *ha = vha->hw;
7842
Himanshu Madhanif198caf2016-01-27 12:03:30 -05007843 /* Hold status IOCBs until ABTS response received. */
7844 if (ql2xfwholdabts)
7845 ha->fw_options[3] |= BIT_12;
7846
Giridhar Malavali088d09d2016-07-06 11:14:20 -04007847 /* Set Retry FLOGI in case of P2P connection */
7848 if (ha->operating_mode == P2P) {
7849 ha->fw_options[2] |= BIT_3;
7850 ql_dbg(ql_dbg_disc, vha, 0x2103,
7851 "(%s): Setting FLOGI retry BIT in fw_options[2]: 0x%x\n",
7852 __func__, ha->fw_options[2]);
7853 }
7854
Quinn Tran41dc5292017-01-19 22:28:03 -08007855 /* Move PUREX, ABTS RX & RIDA to ATIOQ */
7856 if (ql2xmvasynctoatio) {
7857 if (qla_tgt_mode_enabled(vha) ||
7858 qla_dual_mode_enabled(vha))
7859 ha->fw_options[2] |= BIT_11;
7860 else
7861 ha->fw_options[2] &= ~BIT_11;
7862 }
Andrew Vasquezae97c912010-02-18 10:07:28 -08007863
Quinn Tranf7e761f2017-06-02 09:12:02 -07007864 if (qla_tgt_mode_enabled(vha) ||
Quinn Tran2da52732017-06-02 09:12:05 -07007865 qla_dual_mode_enabled(vha)) {
7866 /* FW auto send SCSI status during */
7867 ha->fw_options[1] |= BIT_8;
7868 ha->fw_options[10] |= (u16)SAM_STAT_BUSY << 8;
7869
7870 /* FW perform Exchange validation */
Quinn Tranf7e761f2017-06-02 09:12:02 -07007871 ha->fw_options[2] |= BIT_4;
Quinn Tran2da52732017-06-02 09:12:05 -07007872 } else {
7873 ha->fw_options[1] &= ~BIT_8;
7874 ha->fw_options[10] &= 0x00ff;
7875
Quinn Tranf7e761f2017-06-02 09:12:02 -07007876 ha->fw_options[2] &= ~BIT_4;
Quinn Tran2da52732017-06-02 09:12:05 -07007877 }
Quinn Tranf7e761f2017-06-02 09:12:02 -07007878
Quinn Tran41dc5292017-01-19 22:28:03 -08007879 if (ql2xetsenable) {
7880 /* Enable ETS Burst. */
7881 memset(ha->fw_options, 0, sizeof(ha->fw_options));
7882 ha->fw_options[2] |= BIT_9;
7883 }
7884
Quinn Tran83548fe2017-06-02 09:12:01 -07007885 ql_dbg(ql_dbg_init, vha, 0x00e9,
7886 "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n",
7887 __func__, ha->fw_options[1], ha->fw_options[2],
7888 ha->fw_options[3], vha->host->active_mode);
Quinn Tran41dc5292017-01-19 22:28:03 -08007889
Andrew Vasquezae97c912010-02-18 10:07:28 -08007890 qla2x00_set_fw_options(vha, ha->fw_options);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007891}
Sarang Radke09ff7012010-03-19 17:03:59 -07007892
7893/*
7894 * qla24xx_get_fcp_prio
7895 * Gets the fcp cmd priority value for the logged in port.
7896 * Looks for a match of the port descriptors within
7897 * each of the fcp prio config entries. If a match is found,
7898 * the tag (priority) value is returned.
7899 *
7900 * Input:
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08007901 * vha = scsi host structure pointer.
Sarang Radke09ff7012010-03-19 17:03:59 -07007902 * fcport = port structure pointer.
7903 *
7904 * Return:
Andrew Vasquez6c452a42010-03-19 17:04:02 -07007905 * non-zero (if found)
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07007906 * -1 (if not found)
Sarang Radke09ff7012010-03-19 17:03:59 -07007907 *
7908 * Context:
7909 * Kernel context
7910 */
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07007911static int
Sarang Radke09ff7012010-03-19 17:03:59 -07007912qla24xx_get_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
7913{
7914 int i, entries;
7915 uint8_t pid_match, wwn_match;
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07007916 int priority;
Sarang Radke09ff7012010-03-19 17:03:59 -07007917 uint32_t pid1, pid2;
7918 uint64_t wwn1, wwn2;
7919 struct qla_fcp_prio_entry *pri_entry;
7920 struct qla_hw_data *ha = vha->hw;
7921
7922 if (!ha->fcp_prio_cfg || !ha->flags.fcp_prio_enabled)
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07007923 return -1;
Sarang Radke09ff7012010-03-19 17:03:59 -07007924
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07007925 priority = -1;
Sarang Radke09ff7012010-03-19 17:03:59 -07007926 entries = ha->fcp_prio_cfg->num_entries;
7927 pri_entry = &ha->fcp_prio_cfg->entry[0];
7928
7929 for (i = 0; i < entries; i++) {
7930 pid_match = wwn_match = 0;
7931
7932 if (!(pri_entry->flags & FCP_PRIO_ENTRY_VALID)) {
7933 pri_entry++;
7934 continue;
7935 }
7936
7937 /* check source pid for a match */
7938 if (pri_entry->flags & FCP_PRIO_ENTRY_SPID_VALID) {
7939 pid1 = pri_entry->src_pid & INVALID_PORT_ID;
7940 pid2 = vha->d_id.b24 & INVALID_PORT_ID;
7941 if (pid1 == INVALID_PORT_ID)
7942 pid_match++;
7943 else if (pid1 == pid2)
7944 pid_match++;
7945 }
7946
7947 /* check destination pid for a match */
7948 if (pri_entry->flags & FCP_PRIO_ENTRY_DPID_VALID) {
7949 pid1 = pri_entry->dst_pid & INVALID_PORT_ID;
7950 pid2 = fcport->d_id.b24 & INVALID_PORT_ID;
7951 if (pid1 == INVALID_PORT_ID)
7952 pid_match++;
7953 else if (pid1 == pid2)
7954 pid_match++;
7955 }
7956
7957 /* check source WWN for a match */
7958 if (pri_entry->flags & FCP_PRIO_ENTRY_SWWN_VALID) {
7959 wwn1 = wwn_to_u64(vha->port_name);
7960 wwn2 = wwn_to_u64(pri_entry->src_wwpn);
7961 if (wwn2 == (uint64_t)-1)
7962 wwn_match++;
7963 else if (wwn1 == wwn2)
7964 wwn_match++;
7965 }
7966
7967 /* check destination WWN for a match */
7968 if (pri_entry->flags & FCP_PRIO_ENTRY_DWWN_VALID) {
7969 wwn1 = wwn_to_u64(fcport->port_name);
7970 wwn2 = wwn_to_u64(pri_entry->dst_wwpn);
7971 if (wwn2 == (uint64_t)-1)
7972 wwn_match++;
7973 else if (wwn1 == wwn2)
7974 wwn_match++;
7975 }
7976
7977 if (pid_match == 2 || wwn_match == 2) {
7978 /* Found a matching entry */
7979 if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID)
7980 priority = pri_entry->tag;
7981 break;
7982 }
7983
7984 pri_entry++;
7985 }
7986
7987 return priority;
7988}
7989
7990/*
7991 * qla24xx_update_fcport_fcp_prio
7992 * Activates fcp priority for the logged in fc port
7993 *
7994 * Input:
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08007995 * vha = scsi host structure pointer.
Sarang Radke09ff7012010-03-19 17:03:59 -07007996 * fcp = port structure pointer.
7997 *
7998 * Return:
7999 * QLA_SUCCESS or QLA_FUNCTION_FAILED
8000 *
8001 * Context:
8002 * Kernel context.
8003 */
8004int
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08008005qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
Sarang Radke09ff7012010-03-19 17:03:59 -07008006{
8007 int ret;
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07008008 int priority;
Sarang Radke09ff7012010-03-19 17:03:59 -07008009 uint16_t mb[5];
8010
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08008011 if (fcport->port_type != FCT_TARGET ||
8012 fcport->loop_id == FC_NO_LOOP_ID)
Sarang Radke09ff7012010-03-19 17:03:59 -07008013 return QLA_FUNCTION_FAILED;
8014
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08008015 priority = qla24xx_get_fcp_prio(vha, fcport);
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07008016 if (priority < 0)
8017 return QLA_FUNCTION_FAILED;
8018
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04008019 if (IS_P3P_TYPE(vha->hw)) {
Saurav Kashyapa00f6292011-11-18 09:03:19 -08008020 fcport->fcp_prio = priority & 0xf;
8021 return QLA_SUCCESS;
8022 }
8023
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08008024 ret = qla24xx_set_fcp_prio(vha, fcport->loop_id, priority, mb);
Chad Dupuiscfb09192011-11-18 09:03:07 -08008025 if (ret == QLA_SUCCESS) {
8026 if (fcport->fcp_prio != priority)
8027 ql_dbg(ql_dbg_user, vha, 0x709e,
8028 "Updated FCP_CMND priority - value=%d loop_id=%d "
8029 "port_id=%02x%02x%02x.\n", priority,
8030 fcport->loop_id, fcport->d_id.b.domain,
8031 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Saurav Kashyapa00f6292011-11-18 09:03:19 -08008032 fcport->fcp_prio = priority & 0xf;
Chad Dupuiscfb09192011-11-18 09:03:07 -08008033 } else
Saurav Kashyap7c3df132011-07-14 12:00:13 -07008034 ql_dbg(ql_dbg_user, vha, 0x704f,
Chad Dupuiscfb09192011-11-18 09:03:07 -08008035 "Unable to update FCP_CMND priority - ret=0x%x for "
8036 "loop_id=%d port_id=%02x%02x%02x.\n", ret, fcport->loop_id,
8037 fcport->d_id.b.domain, fcport->d_id.b.area,
8038 fcport->d_id.b.al_pa);
Sarang Radke09ff7012010-03-19 17:03:59 -07008039 return ret;
8040}
8041
8042/*
8043 * qla24xx_update_all_fcp_prio
8044 * Activates fcp priority for all the logged in ports
8045 *
8046 * Input:
8047 * ha = adapter block pointer.
8048 *
8049 * Return:
8050 * QLA_SUCCESS or QLA_FUNCTION_FAILED
8051 *
8052 * Context:
8053 * Kernel context.
8054 */
8055int
8056qla24xx_update_all_fcp_prio(scsi_qla_host_t *vha)
8057{
8058 int ret;
8059 fc_port_t *fcport;
8060
8061 ret = QLA_FUNCTION_FAILED;
8062 /* We need to set priority for all logged in ports */
8063 list_for_each_entry(fcport, &vha->vp_fcports, list)
8064 ret = qla24xx_update_fcport_fcp_prio(vha, fcport);
8065
8066 return ret;
8067}
Michael Hernandezd7459522016-12-12 14:40:07 -08008068
Quinn Tran82de8022017-06-13 20:47:17 -07008069struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos,
8070 int vp_idx, bool startqp)
Michael Hernandezd7459522016-12-12 14:40:07 -08008071{
8072 int rsp_id = 0;
8073 int req_id = 0;
8074 int i;
8075 struct qla_hw_data *ha = vha->hw;
8076 uint16_t qpair_id = 0;
8077 struct qla_qpair *qpair = NULL;
8078 struct qla_msix_entry *msix;
8079
8080 if (!(ha->fw_attributes & BIT_6) || !ha->flags.msix_enabled) {
8081 ql_log(ql_log_warn, vha, 0x00181,
8082 "FW/Driver is not multi-queue capable.\n");
8083 return NULL;
8084 }
8085
Himanshu Madhanic38d1ba2017-10-13 15:43:22 -07008086 if (ql2xmqsupport || ql2xnvmeenable) {
Michael Hernandezd7459522016-12-12 14:40:07 -08008087 qpair = kzalloc(sizeof(struct qla_qpair), GFP_KERNEL);
8088 if (qpair == NULL) {
8089 ql_log(ql_log_warn, vha, 0x0182,
8090 "Failed to allocate memory for queue pair.\n");
8091 return NULL;
8092 }
8093 memset(qpair, 0, sizeof(struct qla_qpair));
8094
8095 qpair->hw = vha->hw;
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08008096 qpair->vha = vha;
Quinn Tran82de8022017-06-13 20:47:17 -07008097 qpair->qp_lock_ptr = &qpair->qp_lock;
8098 spin_lock_init(&qpair->qp_lock);
Quinn Tranaf7bb382017-06-13 20:47:23 -07008099 qpair->use_shadow_reg = IS_SHADOW_REG_CAPABLE(ha) ? 1 : 0;
Michael Hernandezd7459522016-12-12 14:40:07 -08008100
8101 /* Assign available que pair id */
8102 mutex_lock(&ha->mq_lock);
8103 qpair_id = find_first_zero_bit(ha->qpair_qid_map, ha->max_qpairs);
Sawan Chandakb95b9452017-05-24 18:06:20 -07008104 if (ha->num_qpairs >= ha->max_qpairs) {
Michael Hernandezd7459522016-12-12 14:40:07 -08008105 mutex_unlock(&ha->mq_lock);
8106 ql_log(ql_log_warn, vha, 0x0183,
8107 "No resources to create additional q pair.\n");
8108 goto fail_qid_map;
8109 }
Sawan Chandakb95b9452017-05-24 18:06:20 -07008110 ha->num_qpairs++;
Michael Hernandezd7459522016-12-12 14:40:07 -08008111 set_bit(qpair_id, ha->qpair_qid_map);
8112 ha->queue_pair_map[qpair_id] = qpair;
8113 qpair->id = qpair_id;
8114 qpair->vp_idx = vp_idx;
himanshu.madhani@cavium.come6373f332017-08-23 15:04:57 -07008115 qpair->fw_started = ha->flags.fw_started;
Quinn Trane326d222017-06-13 20:47:18 -07008116 INIT_LIST_HEAD(&qpair->hints_list);
Duane Grigsbycf19c452017-08-23 15:04:58 -07008117 INIT_LIST_HEAD(&qpair->nvme_done_list);
Quinn Tran7c3f8fd2017-06-13 20:47:22 -07008118 qpair->chip_reset = ha->base_qpair->chip_reset;
8119 qpair->enable_class_2 = ha->base_qpair->enable_class_2;
8120 qpair->enable_explicit_conf =
8121 ha->base_qpair->enable_explicit_conf;
Michael Hernandezd7459522016-12-12 14:40:07 -08008122
8123 for (i = 0; i < ha->msix_count; i++) {
Quinn Tran093df732016-12-12 14:40:09 -08008124 msix = &ha->msix_entries[i];
Michael Hernandezd7459522016-12-12 14:40:07 -08008125 if (msix->in_use)
8126 continue;
8127 qpair->msix = msix;
Quinn Tran83548fe2017-06-02 09:12:01 -07008128 ql_dbg(ql_dbg_multiq, vha, 0xc00f,
Michael Hernandezd7459522016-12-12 14:40:07 -08008129 "Vector %x selected for qpair\n", msix->vector);
8130 break;
8131 }
8132 if (!qpair->msix) {
8133 ql_log(ql_log_warn, vha, 0x0184,
8134 "Out of MSI-X vectors!.\n");
8135 goto fail_msix;
8136 }
8137
8138 qpair->msix->in_use = 1;
8139 list_add_tail(&qpair->qp_list_elem, &vha->qp_list);
Quinn Tran8abfa9e2017-06-13 20:47:24 -07008140 qpair->pdev = ha->pdev;
8141 if (IS_QLA27XX(ha) || IS_QLA83XX(ha))
8142 qpair->reqq_start_iocbs = qla_83xx_start_iocbs;
Michael Hernandezd7459522016-12-12 14:40:07 -08008143
8144 mutex_unlock(&ha->mq_lock);
8145
8146 /* Create response queue first */
Quinn Tran82de8022017-06-13 20:47:17 -07008147 rsp_id = qla25xx_create_rsp_que(ha, 0, 0, 0, qpair, startqp);
Michael Hernandezd7459522016-12-12 14:40:07 -08008148 if (!rsp_id) {
8149 ql_log(ql_log_warn, vha, 0x0185,
8150 "Failed to create response queue.\n");
8151 goto fail_rsp;
8152 }
8153
8154 qpair->rsp = ha->rsp_q_map[rsp_id];
8155
8156 /* Create request queue */
Quinn Tran82de8022017-06-13 20:47:17 -07008157 req_id = qla25xx_create_req_que(ha, 0, vp_idx, 0, rsp_id, qos,
8158 startqp);
Michael Hernandezd7459522016-12-12 14:40:07 -08008159 if (!req_id) {
8160 ql_log(ql_log_warn, vha, 0x0186,
8161 "Failed to create request queue.\n");
8162 goto fail_req;
8163 }
8164
8165 qpair->req = ha->req_q_map[req_id];
8166 qpair->rsp->req = qpair->req;
Quinn Tran82de8022017-06-13 20:47:17 -07008167 qpair->rsp->qpair = qpair;
Quinn Trane326d222017-06-13 20:47:18 -07008168 /* init qpair to this cpu. Will adjust at run time. */
8169 qla_cpu_update(qpair, smp_processor_id());
Michael Hernandezd7459522016-12-12 14:40:07 -08008170
8171 if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) {
8172 if (ha->fw_attributes & BIT_4)
8173 qpair->difdix_supported = 1;
8174 }
8175
8176 qpair->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
8177 if (!qpair->srb_mempool) {
Quinn Tran83548fe2017-06-02 09:12:01 -07008178 ql_log(ql_log_warn, vha, 0xd036,
Michael Hernandezd7459522016-12-12 14:40:07 -08008179 "Failed to create srb mempool for qpair %d\n",
8180 qpair->id);
8181 goto fail_mempool;
8182 }
8183
8184 /* Mark as online */
8185 qpair->online = 1;
8186
8187 if (!vha->flags.qpairs_available)
8188 vha->flags.qpairs_available = 1;
8189
8190 ql_dbg(ql_dbg_multiq, vha, 0xc00d,
8191 "Request/Response queue pair created, id %d\n",
8192 qpair->id);
8193 ql_dbg(ql_dbg_init, vha, 0x0187,
8194 "Request/Response queue pair created, id %d\n",
8195 qpair->id);
8196 }
8197 return qpair;
8198
8199fail_mempool:
8200fail_req:
8201 qla25xx_delete_rsp_que(vha, qpair->rsp);
8202fail_rsp:
8203 mutex_lock(&ha->mq_lock);
8204 qpair->msix->in_use = 0;
8205 list_del(&qpair->qp_list_elem);
8206 if (list_empty(&vha->qp_list))
8207 vha->flags.qpairs_available = 0;
8208fail_msix:
8209 ha->queue_pair_map[qpair_id] = NULL;
8210 clear_bit(qpair_id, ha->qpair_qid_map);
Sawan Chandakb95b9452017-05-24 18:06:20 -07008211 ha->num_qpairs--;
Michael Hernandezd7459522016-12-12 14:40:07 -08008212 mutex_unlock(&ha->mq_lock);
8213fail_qid_map:
8214 kfree(qpair);
8215 return NULL;
8216}
8217
8218int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair)
8219{
Sawan Chandakd65237c2017-06-13 20:47:19 -07008220 int ret = QLA_FUNCTION_FAILED;
Michael Hernandezd7459522016-12-12 14:40:07 -08008221 struct qla_hw_data *ha = qpair->hw;
8222
Sawan Chandakd65237c2017-06-13 20:47:19 -07008223 if (!vha->flags.qpairs_req_created && !vha->flags.qpairs_rsp_created)
8224 goto fail;
8225
Michael Hernandezd7459522016-12-12 14:40:07 -08008226 qpair->delete_in_progress = 1;
8227 while (atomic_read(&qpair->ref_count))
8228 msleep(500);
8229
8230 ret = qla25xx_delete_req_que(vha, qpair->req);
8231 if (ret != QLA_SUCCESS)
8232 goto fail;
8233 ret = qla25xx_delete_rsp_que(vha, qpair->rsp);
8234 if (ret != QLA_SUCCESS)
8235 goto fail;
8236
8237 mutex_lock(&ha->mq_lock);
8238 ha->queue_pair_map[qpair->id] = NULL;
8239 clear_bit(qpair->id, ha->qpair_qid_map);
Sawan Chandakb95b9452017-05-24 18:06:20 -07008240 ha->num_qpairs--;
Michael Hernandezd7459522016-12-12 14:40:07 -08008241 list_del(&qpair->qp_list_elem);
Sawan Chandakd65237c2017-06-13 20:47:19 -07008242 if (list_empty(&vha->qp_list)) {
Michael Hernandezd7459522016-12-12 14:40:07 -08008243 vha->flags.qpairs_available = 0;
Sawan Chandakd65237c2017-06-13 20:47:19 -07008244 vha->flags.qpairs_req_created = 0;
8245 vha->flags.qpairs_rsp_created = 0;
8246 }
Michael Hernandezd7459522016-12-12 14:40:07 -08008247 mempool_destroy(qpair->srb_mempool);
8248 kfree(qpair);
8249 mutex_unlock(&ha->mq_lock);
8250
8251 return QLA_SUCCESS;
8252fail:
8253 return ret;
8254}