blob: 792c09470c5ad0641b241b9f368a372a7e3dfc57 [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 *);
Quinn Trana4239942017-12-28 12:33:26 -080044static void __qla24xx_handle_gpdb_event(scsi_qla_host_t *, struct event_arg *);
Harihara Kadayam4d4df192008-04-03 13:13:26 -070045
Andrew Vasquezac280b62009-08-20 11:06:05 -070046/* SRB Extensions ---------------------------------------------------------- */
47
Giridhar Malavali9ba56b92012-02-09 11:15:36 -080048void
Kees Cook8e5f4ba2017-09-03 13:23:32 -070049qla2x00_sp_timeout(struct timer_list *t)
Andrew Vasquezac280b62009-08-20 11:06:05 -070050{
Kees Cook8e5f4ba2017-09-03 13:23:32 -070051 srb_t *sp = from_timer(sp, t, u.iocb_cmd.timer);
Madhuranath Iyengar49163922010-05-04 15:01:28 -070052 struct srb_iocb *iocb;
Joe Carnuccio25ff6af2017-01-19 22:28:04 -080053 scsi_qla_host_t *vha = sp->vha;
Andrew Vasquezac280b62009-08-20 11:06:05 -070054 struct req_que *req;
55 unsigned long flags;
56
Joe Carnuccio25ff6af2017-01-19 22:28:04 -080057 spin_lock_irqsave(&vha->hw->hardware_lock, flags);
58 req = vha->hw->req_q_map[0];
Andrew Vasquezac280b62009-08-20 11:06:05 -070059 req->outstanding_cmds[sp->handle] = NULL;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -080060 iocb = &sp->u.iocb_cmd;
Madhuranath Iyengar49163922010-05-04 15:01:28 -070061 iocb->timeout(sp);
Joe Carnuccio25ff6af2017-01-19 22:28:04 -080062 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;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700103
Quinn Tran5c25d452017-12-28 12:33:09 -0800104 if (fcport) {
105 ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
106 "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
Quinn Tran6d6749272017-12-28 12:33:41 -0800109 fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
Quinn Tran5c25d452017-12-28 12:33:09 -0800110 } else {
111 pr_info("Async-%s timeout - hdl=%x.\n",
112 sp->name, sp->handle);
113 }
Quinn Tran726b8542017-01-19 22:28:00 -0800114
115 switch (sp->type) {
116 case SRB_LOGIN_CMD:
Andrew Vasquez6ac52602010-05-28 15:08:19 -0700117 /* Retry as needed. */
118 lio->u.logio.data[0] = MBS_COMMAND_ERROR;
119 lio->u.logio.data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
120 QLA_LOGIO_LOGIN_RETRIED : 0;
Quinn Traneaf75d12018-02-01 10:33:17 -0800121 sp->done(sp, QLA_FUNCTION_TIMEOUT);
Quinn Tran726b8542017-01-19 22:28:00 -0800122 break;
123 case SRB_LOGOUT_CMD:
Quinn Tran726b8542017-01-19 22:28:00 -0800124 case SRB_CT_PTHRU_CMD:
125 case SRB_MB_IOCB:
126 case SRB_NACK_PLOGI:
127 case SRB_NACK_PRLI:
128 case SRB_NACK_LOGO:
Quinn Tran28531922017-12-28 12:33:10 -0800129 case SRB_CTRL_VP:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800130 sp->done(sp, QLA_FUNCTION_TIMEOUT);
Quinn Tran726b8542017-01-19 22:28:00 -0800131 break;
Andrew Vasquez6ac52602010-05-28 15:08:19 -0700132 }
Andrew Vasquezac280b62009-08-20 11:06:05 -0700133}
134
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700135static void
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800136qla2x00_async_login_sp_done(void *ptr, int res)
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700137{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800138 srb_t *sp = ptr;
139 struct scsi_qla_host *vha = sp->vha;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800140 struct srb_iocb *lio = &sp->u.iocb_cmd;
Quinn Tran726b8542017-01-19 22:28:00 -0800141 struct event_arg ea;
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700142
Quinn Tran83548fe2017-06-02 09:12:01 -0700143 ql_dbg(ql_dbg_disc, vha, 0x20dd,
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800144 "%s %8phC res %d \n", __func__, sp->fcport->port_name, res);
Quinn Tran726b8542017-01-19 22:28:00 -0800145
Quinn Tran6d6749272017-12-28 12:33:41 -0800146 sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
147
Quinn Tran726b8542017-01-19 22:28:00 -0800148 if (!test_bit(UNLOADING, &vha->dpc_flags)) {
149 memset(&ea, 0, sizeof(ea));
150 ea.event = FCME_PLOGI_DONE;
151 ea.fcport = sp->fcport;
152 ea.data[0] = lio->u.logio.data[0];
153 ea.data[1] = lio->u.logio.data[1];
154 ea.iop[0] = lio->u.logio.iop[0];
155 ea.iop[1] = lio->u.logio.iop[1];
156 ea.sp = sp;
157 qla2x00_fcport_event_handler(vha, &ea);
158 }
159
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800160 sp->free(sp);
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700161}
162
Andrew Vasquezac280b62009-08-20 11:06:05 -0700163int
164qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
165 uint16_t *data)
166{
Andrew Vasquezac280b62009-08-20 11:06:05 -0700167 srb_t *sp;
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700168 struct srb_iocb *lio;
Quinn Tran726b8542017-01-19 22:28:00 -0800169 int rval = QLA_FUNCTION_FAILED;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700170
Quinn Tran726b8542017-01-19 22:28:00 -0800171 if (!vha->flags.online)
172 goto done;
173
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800174 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700175 if (!sp)
176 goto done;
177
Quinn Tran726b8542017-01-19 22:28:00 -0800178 fcport->flags |= FCF_ASYNC_SENT;
179 fcport->logout_completed = 0;
180
Quinn Trana4239942017-12-28 12:33:26 -0800181 fcport->disc_state = DSC_LOGIN_PEND;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800182 sp->type = SRB_LOGIN_CMD;
183 sp->name = "login";
Quinn Trana4239942017-12-28 12:33:26 -0800184 sp->gen1 = fcport->rscn_gen;
185 sp->gen2 = fcport->login_gen;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800186
187 lio = &sp->u.iocb_cmd;
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700188 lio->timeout = qla2x00_async_iocb_timeout;
Ben Hutchingse74e7d92018-03-20 21:36:14 +0000189 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
190
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800191 sp->done = qla2x00_async_login_sp_done;
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700192 lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
Duane Grigsbya5d42f42017-06-21 13:48:41 -0700193
194 if (fcport->fc4f_nvme)
195 lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI;
196
Andrew Vasquezac280b62009-08-20 11:06:05 -0700197 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700198 lio->u.logio.flags |= SRB_LOGIN_RETRIED;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700199 rval = qla2x00_start_sp(sp);
Chad Dupuis080c9512016-01-27 12:03:37 -0500200 if (rval != QLA_SUCCESS) {
Chad Dupuis080c9512016-01-27 12:03:37 -0500201 fcport->flags |= FCF_LOGIN_NEEDED;
202 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700203 goto done_free_sp;
Chad Dupuis080c9512016-01-27 12:03:37 -0500204 }
Andrew Vasquezac280b62009-08-20 11:06:05 -0700205
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700206 ql_dbg(ql_dbg_disc, vha, 0x2072,
Quinn Tran726b8542017-01-19 22:28:00 -0800207 "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x "
208 "retries=%d.\n", fcport->port_name, sp->handle, fcport->loop_id,
Chad Dupuiscfb09192011-11-18 09:03:07 -0800209 fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
210 fcport->login_retry);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700211 return rval;
212
213done_free_sp:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800214 sp->free(sp);
Quinn Tran726b8542017-01-19 22:28:00 -0800215 fcport->flags &= ~FCF_ASYNC_SENT;
Quinn Tran3dbec592017-12-28 12:33:40 -0800216done:
Hannes Reineckefa83e652018-02-22 09:49:37 +0100217 fcport->flags &= ~FCF_ASYNC_ACTIVE;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700218 return rval;
219}
220
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700221static void
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800222qla2x00_async_logout_sp_done(void *ptr, int res)
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700223{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800224 srb_t *sp = ptr;
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700225
Quinn Tran6d6749272017-12-28 12:33:41 -0800226 sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
Quinn Traneaf75d12018-02-01 10:33:17 -0800227 sp->fcport->login_gen++;
228 qlt_logo_completion_handler(sp->fcport, res);
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800229 sp->free(sp);
Andrew Vasquez99b0bec2010-05-04 15:01:25 -0700230}
231
Andrew Vasquezac280b62009-08-20 11:06:05 -0700232int
233qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
234{
Andrew Vasquezac280b62009-08-20 11:06:05 -0700235 srb_t *sp;
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700236 struct srb_iocb *lio;
Quinn Tran3dbec592017-12-28 12:33:40 -0800237 int rval = QLA_FUNCTION_FAILED;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700238
Quinn Tran3dbec592017-12-28 12:33:40 -0800239 if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
240 return rval;
241
Quinn Tran726b8542017-01-19 22:28:00 -0800242 fcport->flags |= FCF_ASYNC_SENT;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800243 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700244 if (!sp)
245 goto done;
246
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800247 sp->type = SRB_LOGOUT_CMD;
248 sp->name = "logout";
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800249
250 lio = &sp->u.iocb_cmd;
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700251 lio->timeout = qla2x00_async_iocb_timeout;
Ben Hutchingse74e7d92018-03-20 21:36:14 +0000252 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
253
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800254 sp->done = qla2x00_async_logout_sp_done;
Andrew Vasquezac280b62009-08-20 11:06:05 -0700255 rval = qla2x00_start_sp(sp);
256 if (rval != QLA_SUCCESS)
257 goto done_free_sp;
258
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700259 ql_dbg(ql_dbg_disc, vha, 0x2070,
Quinn Tran726b8542017-01-19 22:28:00 -0800260 "Async-logout - hdl=%x loop-id=%x portid=%02x%02x%02x %8phC.\n",
Chad Dupuiscfb09192011-11-18 09:03:07 -0800261 sp->handle, fcport->loop_id, fcport->d_id.b.domain,
Quinn Tran726b8542017-01-19 22:28:00 -0800262 fcport->d_id.b.area, fcport->d_id.b.al_pa,
263 fcport->port_name);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700264 return rval;
265
266done_free_sp:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800267 sp->free(sp);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700268done:
Hannes Reineckefa83e652018-02-22 09:49:37 +0100269 fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
Andrew Vasquezac280b62009-08-20 11:06:05 -0700270 return rval;
271}
Quinn Tran11aea162017-12-28 12:33:20 -0800272
273void
274qla2x00_async_prlo_done(struct scsi_qla_host *vha, fc_port_t *fcport,
275 uint16_t *data)
276{
Hannes Reineckefa83e652018-02-22 09:49:37 +0100277 fcport->flags &= ~FCF_ASYNC_ACTIVE;
Quinn Tran11aea162017-12-28 12:33:20 -0800278 /* Don't re-login in target mode */
279 if (!fcport->tgt_session)
280 qla2x00_mark_device_lost(vha, fcport, 1, 0);
281 qlt_logo_completion_handler(fcport, data[0]);
282}
283
284static void
285qla2x00_async_prlo_sp_done(void *s, int res)
286{
287 srb_t *sp = (srb_t *)s;
288 struct srb_iocb *lio = &sp->u.iocb_cmd;
289 struct scsi_qla_host *vha = sp->vha;
290
Hannes Reineckefa83e652018-02-22 09:49:37 +0100291 sp->fcport->flags &= ~FCF_ASYNC_ACTIVE;
Quinn Tran11aea162017-12-28 12:33:20 -0800292 if (!test_bit(UNLOADING, &vha->dpc_flags))
293 qla2x00_post_async_prlo_done_work(sp->fcport->vha, sp->fcport,
294 lio->u.logio.data);
295 sp->free(sp);
296}
297
298int
299qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
300{
301 srb_t *sp;
302 struct srb_iocb *lio;
303 int rval;
304
305 rval = QLA_FUNCTION_FAILED;
306 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
307 if (!sp)
308 goto done;
309
310 sp->type = SRB_PRLO_CMD;
311 sp->name = "prlo";
Quinn Tran11aea162017-12-28 12:33:20 -0800312
313 lio = &sp->u.iocb_cmd;
314 lio->timeout = qla2x00_async_iocb_timeout;
Ben Hutchingse74e7d92018-03-20 21:36:14 +0000315 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
316
Quinn Tran11aea162017-12-28 12:33:20 -0800317 sp->done = qla2x00_async_prlo_sp_done;
318 rval = qla2x00_start_sp(sp);
319 if (rval != QLA_SUCCESS)
320 goto done_free_sp;
321
322 ql_dbg(ql_dbg_disc, vha, 0x2070,
323 "Async-prlo - hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
324 sp->handle, fcport->loop_id, fcport->d_id.b.domain,
325 fcport->d_id.b.area, fcport->d_id.b.al_pa);
326 return rval;
327
328done_free_sp:
329 sp->free(sp);
330done:
Hannes Reineckefa83e652018-02-22 09:49:37 +0100331 fcport->flags &= ~FCF_ASYNC_ACTIVE;
Quinn Tran11aea162017-12-28 12:33:20 -0800332 return rval;
333}
334
Quinn Tranf13515a2017-12-28 12:33:15 -0800335static
336void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
337{
Quinn Tran0616e962017-12-28 12:33:34 -0800338 struct fc_port *fcport = ea->fcport;
339
340 ql_dbg(ql_dbg_disc, vha, 0x20d2,
341 "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",
342 __func__, fcport->port_name, fcport->disc_state,
343 fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2,
344 fcport->rscn_gen, ea->sp->gen1, fcport->loop_id);
345
346 if (ea->data[0] != MBS_COMMAND_COMPLETE) {
Quinn Trana4239942017-12-28 12:33:26 -0800347 ql_dbg(ql_dbg_disc, vha, 0x2066,
348 "%s %8phC: adisc fail: post delete\n",
349 __func__, ea->fcport->port_name);
Quinn Tran94cff6e2017-12-28 12:33:42 -0800350 qlt_schedule_sess_for_deletion(ea->fcport);
Quinn Trana4239942017-12-28 12:33:26 -0800351 return;
352 }
Quinn Trana4239942017-12-28 12:33:26 -0800353
354 if (ea->fcport->disc_state == DSC_DELETE_PEND)
355 return;
356
357 if (ea->sp->gen2 != ea->fcport->login_gen) {
358 /* target side must have changed it. */
359 ql_dbg(ql_dbg_disc, vha, 0x20d3,
Quinn Tran0616e962017-12-28 12:33:34 -0800360 "%s %8phC generation changed\n",
361 __func__, ea->fcport->port_name);
Quinn Trana4239942017-12-28 12:33:26 -0800362 return;
363 } else if (ea->sp->gen1 != ea->fcport->rscn_gen) {
364 ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
365 __func__, __LINE__, ea->fcport->port_name);
366 qla24xx_post_gidpn_work(vha, ea->fcport);
367 return;
368 }
369
370 __qla24xx_handle_gpdb_event(vha, ea);
Quinn Tranf13515a2017-12-28 12:33:15 -0800371}
Andrew Vasquezac280b62009-08-20 11:06:05 -0700372
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700373static void
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800374qla2x00_async_adisc_sp_done(void *ptr, int res)
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700375{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800376 srb_t *sp = ptr;
377 struct scsi_qla_host *vha = sp->vha;
Quinn Tranf13515a2017-12-28 12:33:15 -0800378 struct event_arg ea;
Quinn Tran0616e962017-12-28 12:33:34 -0800379 struct srb_iocb *lio = &sp->u.iocb_cmd;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700380
Quinn Tranf13515a2017-12-28 12:33:15 -0800381 ql_dbg(ql_dbg_disc, vha, 0x2066,
382 "Async done-%s res %x %8phC\n",
383 sp->name, res, sp->fcport->port_name);
384
Hannes Reineckefa83e652018-02-22 09:49:37 +0100385 sp->fcport->flags &= ~FCF_ASYNC_SENT;
386
Quinn Tranf13515a2017-12-28 12:33:15 -0800387 memset(&ea, 0, sizeof(ea));
388 ea.event = FCME_ADISC_DONE;
389 ea.rc = res;
Quinn Tran0616e962017-12-28 12:33:34 -0800390 ea.data[0] = lio->u.logio.data[0];
391 ea.data[1] = lio->u.logio.data[1];
392 ea.iop[0] = lio->u.logio.iop[0];
393 ea.iop[1] = lio->u.logio.iop[1];
Quinn Tranf13515a2017-12-28 12:33:15 -0800394 ea.fcport = sp->fcport;
395 ea.sp = sp;
396
397 qla2x00_fcport_event_handler(vha, &ea);
398
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800399 sp->free(sp);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700400}
401
402int
403qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
404 uint16_t *data)
405{
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700406 srb_t *sp;
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700407 struct srb_iocb *lio;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700408 int rval;
409
410 rval = QLA_FUNCTION_FAILED;
Quinn Tran726b8542017-01-19 22:28:00 -0800411 fcport->flags |= FCF_ASYNC_SENT;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800412 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700413 if (!sp)
414 goto done;
415
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800416 sp->type = SRB_ADISC_CMD;
417 sp->name = "adisc";
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800418
419 lio = &sp->u.iocb_cmd;
Madhuranath Iyengar38222632010-05-04 15:01:29 -0700420 lio->timeout = qla2x00_async_iocb_timeout;
Ben Hutchingse74e7d92018-03-20 21:36:14 +0000421 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
422
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800423 sp->done = qla2x00_async_adisc_sp_done;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700424 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
Madhuranath Iyengar49163922010-05-04 15:01:28 -0700425 lio->u.logio.flags |= SRB_LOGIN_RETRIED;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700426 rval = qla2x00_start_sp(sp);
427 if (rval != QLA_SUCCESS)
428 goto done_free_sp;
429
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700430 ql_dbg(ql_dbg_disc, vha, 0x206f,
Quinn Tranf13515a2017-12-28 12:33:15 -0800431 "Async-adisc - hdl=%x loopid=%x portid=%06x %8phC.\n",
432 sp->handle, fcport->loop_id, fcport->d_id.b24, fcport->port_name);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700433 return rval;
434
435done_free_sp:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800436 sp->free(sp);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700437done:
Hannes Reineckefa83e652018-02-22 09:49:37 +0100438 fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
Quinn Tranf13515a2017-12-28 12:33:15 -0800439 qla2x00_post_async_adisc_work(vha, fcport, data);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -0700440 return rval;
441}
442
Quinn Tran726b8542017-01-19 22:28:00 -0800443static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
444 struct event_arg *ea)
445{
446 fc_port_t *fcport, *conflict_fcport;
447 struct get_name_list_extended *e;
448 u16 i, n, found = 0, loop_id;
449 port_id_t id;
450 u64 wwn;
Quinn Trana4239942017-12-28 12:33:26 -0800451 u16 data[2];
452 u8 current_login_state;
Quinn Tran726b8542017-01-19 22:28:00 -0800453
454 fcport = ea->fcport;
Quinn Tranf352eeb2017-12-28 12:33:35 -0800455 ql_dbg(ql_dbg_disc, vha, 0xffff,
456 "%s %8phC DS %d LS rc %d %d login %d|%d rscn %d|%d lid %d\n",
457 __func__, fcport->port_name, fcport->disc_state,
458 fcport->fw_login_state, ea->rc,
459 fcport->login_gen, fcport->last_login_gen,
460 fcport->rscn_gen, fcport->last_rscn_gen, vha->loop_id);
Quinn Tran726b8542017-01-19 22:28:00 -0800461
Quinn Trana4239942017-12-28 12:33:26 -0800462 if (fcport->disc_state == DSC_DELETE_PEND)
463 return;
464
Quinn Tran726b8542017-01-19 22:28:00 -0800465 if (ea->rc) { /* rval */
466 if (fcport->login_retry == 0) {
467 fcport->login_retry = vha->hw->login_retry_count;
Quinn Tran83548fe2017-06-02 09:12:01 -0700468 ql_dbg(ql_dbg_disc, vha, 0x20de,
469 "GNL failed Port login retry %8phN, retry cnt=%d.\n",
470 fcport->port_name, fcport->login_retry);
Quinn Tran726b8542017-01-19 22:28:00 -0800471 }
472 return;
473 }
474
475 if (fcport->last_rscn_gen != fcport->rscn_gen) {
Quinn Tran83548fe2017-06-02 09:12:01 -0700476 ql_dbg(ql_dbg_disc, vha, 0x20df,
Quinn Tran726b8542017-01-19 22:28:00 -0800477 "%s %8phC rscn gen changed rscn %d|%d \n",
478 __func__, fcport->port_name,
479 fcport->last_rscn_gen, fcport->rscn_gen);
480 qla24xx_post_gidpn_work(vha, fcport);
481 return;
482 } else if (fcport->last_login_gen != fcport->login_gen) {
Quinn Tran83548fe2017-06-02 09:12:01 -0700483 ql_dbg(ql_dbg_disc, vha, 0x20e0,
Quinn Tranf352eeb2017-12-28 12:33:35 -0800484 "%s %8phC login gen changed\n",
485 __func__, fcport->port_name);
Quinn Tran726b8542017-01-19 22:28:00 -0800486 return;
487 }
488
489 n = ea->data[0] / sizeof(struct get_name_list_extended);
490
Quinn Tran83548fe2017-06-02 09:12:01 -0700491 ql_dbg(ql_dbg_disc, vha, 0x20e1,
Quinn Tran726b8542017-01-19 22:28:00 -0800492 "%s %d %8phC n %d %02x%02x%02x lid %d \n",
493 __func__, __LINE__, fcport->port_name, n,
494 fcport->d_id.b.domain, fcport->d_id.b.area,
495 fcport->d_id.b.al_pa, fcport->loop_id);
496
497 for (i = 0; i < n; i++) {
498 e = &vha->gnl.l[i];
499 wwn = wwn_to_u64(e->port_name);
500
501 if (memcmp((u8 *)&wwn, fcport->port_name, WWN_SIZE))
502 continue;
503
504 found = 1;
505 id.b.domain = e->port_id[2];
506 id.b.area = e->port_id[1];
507 id.b.al_pa = e->port_id[0];
508 id.b.rsvd_1 = 0;
509
510 loop_id = le16_to_cpu(e->nport_handle);
511 loop_id = (loop_id & 0x7fff);
512
Quinn Tran83548fe2017-06-02 09:12:01 -0700513 ql_dbg(ql_dbg_disc, vha, 0x20e2,
514 "%s found %8phC CLS [%d|%d] ID[%02x%02x%02x|%02x%02x%02x] lid[%d|%d]\n",
515 __func__, fcport->port_name,
516 e->current_login_state, fcport->fw_login_state,
517 id.b.domain, id.b.area, id.b.al_pa,
518 fcport->d_id.b.domain, fcport->d_id.b.area,
519 fcport->d_id.b.al_pa, loop_id, fcport->loop_id);
Quinn Tran726b8542017-01-19 22:28:00 -0800520
521 if ((id.b24 != fcport->d_id.b24) ||
522 ((fcport->loop_id != FC_NO_LOOP_ID) &&
523 (fcport->loop_id != loop_id))) {
Quinn Tran83548fe2017-06-02 09:12:01 -0700524 ql_dbg(ql_dbg_disc, vha, 0x20e3,
525 "%s %d %8phC post del sess\n",
526 __func__, __LINE__, fcport->port_name);
Quinn Tran94cff6e2017-12-28 12:33:42 -0800527 qlt_schedule_sess_for_deletion(fcport);
Quinn Tran726b8542017-01-19 22:28:00 -0800528 return;
529 }
530
531 fcport->loop_id = loop_id;
532
533 wwn = wwn_to_u64(fcport->port_name);
534 qlt_find_sess_invalidate_other(vha, wwn,
535 id, loop_id, &conflict_fcport);
536
537 if (conflict_fcport) {
538 /*
539 * Another share fcport share the same loop_id &
540 * nport id. Conflict fcport needs to finish
541 * cleanup before this fcport can proceed to login.
542 */
543 conflict_fcport->conflict = fcport;
544 fcport->login_pause = 1;
545 }
546
Duane Grigsbya5d42f42017-06-21 13:48:41 -0700547 if (fcport->fc4f_nvme)
548 current_login_state = e->current_login_state >> 4;
549 else
550 current_login_state = e->current_login_state & 0xf;
551
552 switch (current_login_state) {
Quinn Tran726b8542017-01-19 22:28:00 -0800553 case DSC_LS_PRLI_COMP:
Quinn Tran83548fe2017-06-02 09:12:01 -0700554 ql_dbg(ql_dbg_disc, vha, 0x20e4,
555 "%s %d %8phC post gpdb\n",
556 __func__, __LINE__, fcport->port_name);
Quinn Trana4239942017-12-28 12:33:26 -0800557
558 if ((e->prli_svc_param_word_3[0] & BIT_4) == 0)
559 fcport->port_type = FCT_INITIATOR;
560 else
561 fcport->port_type = FCT_TARGET;
562
563 data[0] = data[1] = 0;
564 qla2x00_post_async_adisc_work(vha, fcport, data);
Quinn Tran726b8542017-01-19 22:28:00 -0800565 break;
Quinn Tran726b8542017-01-19 22:28:00 -0800566 case DSC_LS_PORT_UNAVAIL:
567 default:
568 if (fcport->loop_id == FC_NO_LOOP_ID) {
569 qla2x00_find_new_loop_id(vha, fcport);
570 fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
571 }
Quinn Tran83548fe2017-06-02 09:12:01 -0700572 ql_dbg(ql_dbg_disc, vha, 0x20e5,
573 "%s %d %8phC\n",
574 __func__, __LINE__, fcport->port_name);
Quinn Tran726b8542017-01-19 22:28:00 -0800575 qla24xx_fcport_handle_login(vha, fcport);
576 break;
577 }
578 }
579
580 if (!found) {
581 /* fw has no record of this port */
Quinn Tran040036b2017-12-28 12:33:38 -0800582 for (i = 0; i < n; i++) {
583 e = &vha->gnl.l[i];
584 id.b.domain = e->port_id[0];
585 id.b.area = e->port_id[1];
586 id.b.al_pa = e->port_id[2];
587 id.b.rsvd_1 = 0;
588 loop_id = le16_to_cpu(e->nport_handle);
Quinn Tran726b8542017-01-19 22:28:00 -0800589
Quinn Tran040036b2017-12-28 12:33:38 -0800590 if (fcport->d_id.b24 == id.b24) {
591 conflict_fcport =
592 qla2x00_find_fcport_by_wwpn(vha,
593 e->port_name, 0);
594 ql_dbg(ql_dbg_disc, vha, 0x20e6,
595 "%s %d %8phC post del sess\n",
596 __func__, __LINE__,
597 conflict_fcport->port_name);
598 qlt_schedule_sess_for_deletion
Quinn Tran94cff6e2017-12-28 12:33:42 -0800599 (conflict_fcport);
Quinn Tran726b8542017-01-19 22:28:00 -0800600 }
Quinn Tran040036b2017-12-28 12:33:38 -0800601
602 /* FW already picked this loop id for another fcport */
603 if (fcport->loop_id == loop_id)
604 fcport->loop_id = FC_NO_LOOP_ID;
Quinn Tran726b8542017-01-19 22:28:00 -0800605 }
606 qla24xx_fcport_handle_login(vha, fcport);
607 }
608} /* gnl_event */
609
610static void
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800611qla24xx_async_gnl_sp_done(void *s, int res)
Quinn Tran726b8542017-01-19 22:28:00 -0800612{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800613 struct srb *sp = s;
614 struct scsi_qla_host *vha = sp->vha;
Quinn Tran726b8542017-01-19 22:28:00 -0800615 unsigned long flags;
616 struct fc_port *fcport = NULL, *tf;
617 u16 i, n = 0, loop_id;
618 struct event_arg ea;
619 struct get_name_list_extended *e;
620 u64 wwn;
621 struct list_head h;
Quinn Trana4239942017-12-28 12:33:26 -0800622 bool found = false;
Quinn Tran726b8542017-01-19 22:28:00 -0800623
Quinn Tran83548fe2017-06-02 09:12:01 -0700624 ql_dbg(ql_dbg_disc, vha, 0x20e7,
Quinn Tran726b8542017-01-19 22:28:00 -0800625 "Async done-%s res %x mb[1]=%x mb[2]=%x \n",
626 sp->name, res, sp->u.iocb_cmd.u.mbx.in_mb[1],
627 sp->u.iocb_cmd.u.mbx.in_mb[2]);
628
629 memset(&ea, 0, sizeof(ea));
630 ea.sp = sp;
631 ea.rc = res;
632 ea.event = FCME_GNL_DONE;
633
634 if (sp->u.iocb_cmd.u.mbx.in_mb[1] >=
635 sizeof(struct get_name_list_extended)) {
636 n = sp->u.iocb_cmd.u.mbx.in_mb[1] /
637 sizeof(struct get_name_list_extended);
638 ea.data[0] = sp->u.iocb_cmd.u.mbx.in_mb[1]; /* amnt xfered */
639 }
640
641 for (i = 0; i < n; i++) {
642 e = &vha->gnl.l[i];
643 loop_id = le16_to_cpu(e->nport_handle);
644 /* mask out reserve bit */
645 loop_id = (loop_id & 0x7fff);
646 set_bit(loop_id, vha->hw->loop_id_map);
647 wwn = wwn_to_u64(e->port_name);
648
Quinn Tran83548fe2017-06-02 09:12:01 -0700649 ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x20e8,
Quinn Tran726b8542017-01-19 22:28:00 -0800650 "%s %8phC %02x:%02x:%02x state %d/%d lid %x \n",
651 __func__, (void *)&wwn, e->port_id[2], e->port_id[1],
652 e->port_id[0], e->current_login_state, e->last_login_state,
653 (loop_id & 0x7fff));
654 }
655
Hannes Reinecke1c6cacf2018-02-22 09:49:35 +0100656 spin_lock_irqsave(&vha->gnl.fcports_lock, flags);
Quinn Tran726b8542017-01-19 22:28:00 -0800657
658 INIT_LIST_HEAD(&h);
659 fcport = tf = NULL;
660 if (!list_empty(&vha->gnl.fcports))
661 list_splice_init(&vha->gnl.fcports, &h);
662
663 list_for_each_entry_safe(fcport, tf, &h, gnl_entry) {
664 list_del_init(&fcport->gnl_entry);
Hannes Reinecke1c6cacf2018-02-22 09:49:35 +0100665 spin_lock(&vha->hw->tgt.sess_lock);
Quinn Tran6d6749272017-12-28 12:33:41 -0800666 fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
Hannes Reinecke1c6cacf2018-02-22 09:49:35 +0100667 spin_unlock(&vha->hw->tgt.sess_lock);
Quinn Tran726b8542017-01-19 22:28:00 -0800668 ea.fcport = fcport;
669
670 qla2x00_fcport_event_handler(vha, &ea);
671 }
Hannes Reinecke1c6cacf2018-02-22 09:49:35 +0100672 spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags);
Quinn Tran726b8542017-01-19 22:28:00 -0800673
Hannes Reinecke1c6cacf2018-02-22 09:49:35 +0100674 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
Quinn Trana4239942017-12-28 12:33:26 -0800675 /* create new fcport if fw has knowledge of new sessions */
676 for (i = 0; i < n; i++) {
677 port_id_t id;
678 u64 wwnn;
679
680 e = &vha->gnl.l[i];
681 wwn = wwn_to_u64(e->port_name);
682
683 found = false;
684 list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
685 if (!memcmp((u8 *)&wwn, fcport->port_name,
686 WWN_SIZE)) {
687 found = true;
688 break;
689 }
690 }
691
Quinn Trancf055fb2017-12-28 12:33:33 -0800692 id.b.domain = e->port_id[2];
Quinn Trana4239942017-12-28 12:33:26 -0800693 id.b.area = e->port_id[1];
Quinn Trancf055fb2017-12-28 12:33:33 -0800694 id.b.al_pa = e->port_id[0];
Quinn Trana4239942017-12-28 12:33:26 -0800695 id.b.rsvd_1 = 0;
696
697 if (!found && wwn && !IS_SW_RESV_ADDR(id)) {
698 ql_dbg(ql_dbg_disc, vha, 0x2065,
Quinn Trancf055fb2017-12-28 12:33:33 -0800699 "%s %d %8phC %06x post new sess\n",
700 __func__, __LINE__, (u8 *)&wwn, id.b24);
Quinn Trana4239942017-12-28 12:33:26 -0800701 wwnn = wwn_to_u64(e->node_name);
702 qla24xx_post_newsess_work(vha, &id, (u8 *)&wwn,
703 (u8 *)&wwnn, NULL, FC4_TYPE_UNKNOWN);
704 }
705 }
706
Quinn Tran726b8542017-01-19 22:28:00 -0800707 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
708
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800709 sp->free(sp);
Quinn Tran726b8542017-01-19 22:28:00 -0800710}
711
712int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
713{
714 srb_t *sp;
715 struct srb_iocb *mbx;
716 int rval = QLA_FUNCTION_FAILED;
717 unsigned long flags;
718 u16 *mb;
719
Quinn Tran3dbec592017-12-28 12:33:40 -0800720 if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
721 return rval;
Quinn Tran726b8542017-01-19 22:28:00 -0800722
Quinn Tran83548fe2017-06-02 09:12:01 -0700723 ql_dbg(ql_dbg_disc, vha, 0x20d9,
Quinn Tran726b8542017-01-19 22:28:00 -0800724 "Async-gnlist WWPN %8phC \n", fcport->port_name);
725
Hannes Reinecke1c6cacf2018-02-22 09:49:35 +0100726 spin_lock_irqsave(&vha->gnl.fcports_lock, flags);
727 if (!list_empty(&fcport->gnl_entry)) {
728 spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags);
729 rval = QLA_SUCCESS;
730 goto done;
731 }
732
733 spin_lock(&vha->hw->tgt.sess_lock);
Quinn Tran726b8542017-01-19 22:28:00 -0800734 fcport->disc_state = DSC_GNL;
735 fcport->last_rscn_gen = fcport->rscn_gen;
736 fcport->last_login_gen = fcport->login_gen;
Hannes Reinecke1c6cacf2018-02-22 09:49:35 +0100737 spin_unlock(&vha->hw->tgt.sess_lock);
Quinn Tran726b8542017-01-19 22:28:00 -0800738
739 list_add_tail(&fcport->gnl_entry, &vha->gnl.fcports);
Hannes Reinecke1c6cacf2018-02-22 09:49:35 +0100740 spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags);
Quinn Tran726b8542017-01-19 22:28:00 -0800741
742 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
743 if (!sp)
744 goto done;
Quinn Tran3dbec592017-12-28 12:33:40 -0800745
746 fcport->flags |= FCF_ASYNC_SENT;
Quinn Tran726b8542017-01-19 22:28:00 -0800747 sp->type = SRB_MB_IOCB;
748 sp->name = "gnlist";
749 sp->gen1 = fcport->rscn_gen;
750 sp->gen2 = fcport->login_gen;
751
Ben Hutchingse74e7d92018-03-20 21:36:14 +0000752 mbx = &sp->u.iocb_cmd;
753 mbx->timeout = qla2x00_async_iocb_timeout;
Quinn Tran726b8542017-01-19 22:28:00 -0800754 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
755
756 mb = sp->u.iocb_cmd.u.mbx.out_mb;
757 mb[0] = MBC_PORT_NODE_NAME_LIST;
758 mb[1] = BIT_2 | BIT_3;
759 mb[2] = MSW(vha->gnl.ldma);
760 mb[3] = LSW(vha->gnl.ldma);
761 mb[6] = MSW(MSD(vha->gnl.ldma));
762 mb[7] = LSW(MSD(vha->gnl.ldma));
763 mb[8] = vha->gnl.size;
764 mb[9] = vha->vp_idx;
765
Quinn Tran726b8542017-01-19 22:28:00 -0800766 sp->done = qla24xx_async_gnl_sp_done;
767
768 rval = qla2x00_start_sp(sp);
769 if (rval != QLA_SUCCESS)
770 goto done_free_sp;
771
Quinn Tran83548fe2017-06-02 09:12:01 -0700772 ql_dbg(ql_dbg_disc, vha, 0x20da,
773 "Async-%s - OUT WWPN %8phC hndl %x\n",
774 sp->name, fcport->port_name, sp->handle);
Quinn Tran726b8542017-01-19 22:28:00 -0800775
776 return rval;
777
778done_free_sp:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800779 sp->free(sp);
Quinn Tran726b8542017-01-19 22:28:00 -0800780 fcport->flags &= ~FCF_ASYNC_SENT;
Quinn Tran3dbec592017-12-28 12:33:40 -0800781done:
Quinn Tran726b8542017-01-19 22:28:00 -0800782 return rval;
783}
784
785int qla24xx_post_gnl_work(struct scsi_qla_host *vha, fc_port_t *fcport)
786{
787 struct qla_work_evt *e;
788
789 e = qla2x00_alloc_work(vha, QLA_EVT_GNL);
790 if (!e)
791 return QLA_FUNCTION_FAILED;
792
793 e->u.fcport.fcport = fcport;
Quinn Tran6d6749272017-12-28 12:33:41 -0800794 fcport->flags |= FCF_ASYNC_ACTIVE;
Quinn Tran726b8542017-01-19 22:28:00 -0800795 return qla2x00_post_work(vha, e);
796}
797
798static
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800799void qla24xx_async_gpdb_sp_done(void *s, int res)
Quinn Tran726b8542017-01-19 22:28:00 -0800800{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800801 struct srb *sp = s;
802 struct scsi_qla_host *vha = sp->vha;
Quinn Tran726b8542017-01-19 22:28:00 -0800803 struct qla_hw_data *ha = vha->hw;
Quinn Tran726b8542017-01-19 22:28:00 -0800804 fc_port_t *fcport = sp->fcport;
805 u16 *mb = sp->u.iocb_cmd.u.mbx.in_mb;
Quinn Tran726b8542017-01-19 22:28:00 -0800806 struct event_arg ea;
807
Quinn Tran83548fe2017-06-02 09:12:01 -0700808 ql_dbg(ql_dbg_disc, vha, 0x20db,
Quinn Tran726b8542017-01-19 22:28:00 -0800809 "Async done-%s res %x, WWPN %8phC mb[1]=%x mb[2]=%x \n",
810 sp->name, res, fcport->port_name, mb[1], mb[2]);
811
Quinn Tran6d6749272017-12-28 12:33:41 -0800812 fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
Quinn Tran726b8542017-01-19 22:28:00 -0800813
Quinn Tran726b8542017-01-19 22:28:00 -0800814 memset(&ea, 0, sizeof(ea));
815 ea.event = FCME_GPDB_DONE;
Quinn Tran726b8542017-01-19 22:28:00 -0800816 ea.fcport = fcport;
817 ea.sp = sp;
818
819 qla2x00_fcport_event_handler(vha, &ea);
820
821 dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
822 sp->u.iocb_cmd.u.mbx.in_dma);
823
Joe Carnuccio25ff6af2017-01-19 22:28:04 -0800824 sp->free(sp);
Quinn Tran726b8542017-01-19 22:28:00 -0800825}
826
Duane Grigsbya5d42f42017-06-21 13:48:41 -0700827static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
828{
829 struct qla_work_evt *e;
830
831 e = qla2x00_alloc_work(vha, QLA_EVT_PRLI);
832 if (!e)
833 return QLA_FUNCTION_FAILED;
834
835 e->u.fcport.fcport = fcport;
836
837 return qla2x00_post_work(vha, e);
838}
839
840static void
841qla2x00_async_prli_sp_done(void *ptr, int res)
842{
843 srb_t *sp = ptr;
844 struct scsi_qla_host *vha = sp->vha;
845 struct srb_iocb *lio = &sp->u.iocb_cmd;
846 struct event_arg ea;
847
848 ql_dbg(ql_dbg_disc, vha, 0x2129,
849 "%s %8phC res %d \n", __func__,
850 sp->fcport->port_name, res);
851
852 sp->fcport->flags &= ~FCF_ASYNC_SENT;
853
854 if (!test_bit(UNLOADING, &vha->dpc_flags)) {
855 memset(&ea, 0, sizeof(ea));
856 ea.event = FCME_PRLI_DONE;
857 ea.fcport = sp->fcport;
858 ea.data[0] = lio->u.logio.data[0];
859 ea.data[1] = lio->u.logio.data[1];
860 ea.iop[0] = lio->u.logio.iop[0];
861 ea.iop[1] = lio->u.logio.iop[1];
862 ea.sp = sp;
863
864 qla2x00_fcport_event_handler(vha, &ea);
865 }
866
867 sp->free(sp);
868}
869
870int
871qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
872{
873 srb_t *sp;
874 struct srb_iocb *lio;
875 int rval = QLA_FUNCTION_FAILED;
876
877 if (!vha->flags.online)
878 return rval;
879
880 if (fcport->fw_login_state == DSC_LS_PLOGI_PEND ||
Duane Grigsbya5d42f42017-06-21 13:48:41 -0700881 fcport->fw_login_state == DSC_LS_PRLI_PEND)
882 return rval;
883
884 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
885 if (!sp)
886 return rval;
887
888 fcport->flags |= FCF_ASYNC_SENT;
889 fcport->logout_completed = 0;
890
891 sp->type = SRB_PRLI_CMD;
892 sp->name = "prli";
Duane Grigsbya5d42f42017-06-21 13:48:41 -0700893
894 lio = &sp->u.iocb_cmd;
895 lio->timeout = qla2x00_async_iocb_timeout;
Ben Hutchingse74e7d92018-03-20 21:36:14 +0000896 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
897
Duane Grigsbya5d42f42017-06-21 13:48:41 -0700898 sp->done = qla2x00_async_prli_sp_done;
899 lio->u.logio.flags = 0;
900
901 if (fcport->fc4f_nvme)
902 lio->u.logio.flags |= SRB_LOGIN_NVME_PRLI;
903
904 rval = qla2x00_start_sp(sp);
905 if (rval != QLA_SUCCESS) {
Duane Grigsbya5d42f42017-06-21 13:48:41 -0700906 fcport->flags |= FCF_LOGIN_NEEDED;
907 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
908 goto done_free_sp;
909 }
910
911 ql_dbg(ql_dbg_disc, vha, 0x211b,
912 "Async-prli - %8phC hdl=%x, loopid=%x portid=%06x retries=%d.\n",
913 fcport->port_name, sp->handle, fcport->loop_id,
914 fcport->d_id.b24, fcport->login_retry);
915
916 return rval;
917
918done_free_sp:
919 sp->free(sp);
920 fcport->flags &= ~FCF_ASYNC_SENT;
921 return rval;
922}
923
Quinn Trana07fc0a2017-08-23 15:05:21 -0700924int qla24xx_post_gpdb_work(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
Quinn Tran726b8542017-01-19 22:28:00 -0800925{
926 struct qla_work_evt *e;
927
928 e = qla2x00_alloc_work(vha, QLA_EVT_GPDB);
929 if (!e)
930 return QLA_FUNCTION_FAILED;
931
932 e->u.fcport.fcport = fcport;
933 e->u.fcport.opt = opt;
Quinn Tran6d6749272017-12-28 12:33:41 -0800934 fcport->flags |= FCF_ASYNC_ACTIVE;
Quinn Tran726b8542017-01-19 22:28:00 -0800935 return qla2x00_post_work(vha, e);
936}
937
938int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
939{
940 srb_t *sp;
941 struct srb_iocb *mbx;
942 int rval = QLA_FUNCTION_FAILED;
943 u16 *mb;
944 dma_addr_t pd_dma;
945 struct port_database_24xx *pd;
946 struct qla_hw_data *ha = vha->hw;
947
Quinn Tran3dbec592017-12-28 12:33:40 -0800948 if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
949 return rval;
Quinn Tran726b8542017-01-19 22:28:00 -0800950
Quinn Tran726b8542017-01-19 22:28:00 -0800951 fcport->disc_state = DSC_GPDB;
952
953 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
954 if (!sp)
955 goto done;
956
Quinn Tran3dbec592017-12-28 12:33:40 -0800957 fcport->flags |= FCF_ASYNC_SENT;
Joe Carnuccioe0824e62017-08-23 15:05:08 -0700958 sp->type = SRB_MB_IOCB;
959 sp->name = "gpdb";
960 sp->gen1 = fcport->rscn_gen;
961 sp->gen2 = fcport->login_gen;
Ben Hutchingse74e7d92018-03-20 21:36:14 +0000962
963 mbx = &sp->u.iocb_cmd;
964 mbx->timeout = qla2x00_async_iocb_timeout;
Joe Carnuccioe0824e62017-08-23 15:05:08 -0700965 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
966
Thomas Meyer08eb7f42017-09-21 08:15:26 +0200967 pd = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
Quinn Tran726b8542017-01-19 22:28:00 -0800968 if (pd == NULL) {
Quinn Tran83548fe2017-06-02 09:12:01 -0700969 ql_log(ql_log_warn, vha, 0xd043,
970 "Failed to allocate port database structure.\n");
Quinn Tran726b8542017-01-19 22:28:00 -0800971 goto done_free_sp;
972 }
Quinn Tran726b8542017-01-19 22:28:00 -0800973
Quinn Tran726b8542017-01-19 22:28:00 -0800974 mb = sp->u.iocb_cmd.u.mbx.out_mb;
975 mb[0] = MBC_GET_PORT_DATABASE;
976 mb[1] = fcport->loop_id;
977 mb[2] = MSW(pd_dma);
978 mb[3] = LSW(pd_dma);
979 mb[6] = MSW(MSD(pd_dma));
980 mb[7] = LSW(MSD(pd_dma));
981 mb[9] = vha->vp_idx;
982 mb[10] = opt;
983
Quinn Tran726b8542017-01-19 22:28:00 -0800984 mbx->u.mbx.in = (void *)pd;
985 mbx->u.mbx.in_dma = pd_dma;
986
987 sp->done = qla24xx_async_gpdb_sp_done;
988
989 rval = qla2x00_start_sp(sp);
990 if (rval != QLA_SUCCESS)
991 goto done_free_sp;
992
Quinn Tran83548fe2017-06-02 09:12:01 -0700993 ql_dbg(ql_dbg_disc, vha, 0x20dc,
994 "Async-%s %8phC hndl %x opt %x\n",
995 sp->name, fcport->port_name, sp->handle, opt);
Quinn Tran726b8542017-01-19 22:28:00 -0800996
997 return rval;
998
999done_free_sp:
1000 if (pd)
1001 dma_pool_free(ha->s_dma_pool, pd, pd_dma);
1002
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001003 sp->free(sp);
Quinn Tran726b8542017-01-19 22:28:00 -08001004 fcport->flags &= ~FCF_ASYNC_SENT;
Quinn Tran3dbec592017-12-28 12:33:40 -08001005done:
Quinn Tran726b8542017-01-19 22:28:00 -08001006 qla24xx_post_gpdb_work(vha, fcport, opt);
1007 return rval;
1008}
1009
1010static
Quinn Trana4239942017-12-28 12:33:26 -08001011void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
Quinn Tran726b8542017-01-19 22:28:00 -08001012{
Quinn Tran726b8542017-01-19 22:28:00 -08001013 unsigned long flags;
1014
Quinn Tran726b8542017-01-19 22:28:00 -08001015 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
Quinn Tranf13515a2017-12-28 12:33:15 -08001016 ea->fcport->login_gen++;
Quinn Tran726b8542017-01-19 22:28:00 -08001017 ea->fcport->deleted = 0;
1018 ea->fcport->logout_on_delete = 1;
1019
1020 if (!ea->fcport->login_succ && !IS_SW_RESV_ADDR(ea->fcport->d_id)) {
1021 vha->fcport_count++;
1022 ea->fcport->login_succ = 1;
1023
Quinn Trancc28e0a2018-05-01 09:01:48 -07001024 ql_dbg(ql_dbg_disc, vha, 0x20d6,
1025 "%s %d %8phC post upd_fcport fcp_cnt %d\n",
1026 __func__, __LINE__, ea->fcport->port_name,
1027 vha->fcport_count);
1028 qla24xx_post_upd_fcport_work(vha, ea->fcport);
Quinn Tran414d9ff2017-12-04 14:45:03 -08001029 } else if (ea->fcport->login_succ) {
1030 /*
1031 * We have an existing session. A late RSCN delivery
1032 * must have triggered the session to be re-validate.
Quinn Trana4239942017-12-28 12:33:26 -08001033 * Session is still valid.
Quinn Tran414d9ff2017-12-04 14:45:03 -08001034 */
Quinn Tran5ef696a2017-12-04 14:45:05 -08001035 ql_dbg(ql_dbg_disc, vha, 0x20d6,
1036 "%s %d %8phC session revalidate success\n",
Quinn Trana4239942017-12-28 12:33:26 -08001037 __func__, __LINE__, ea->fcport->port_name);
himanshu.madhani@cavium.com8a7eac22018-01-15 20:46:50 -08001038 ea->fcport->disc_state = DSC_LOGIN_COMPLETE;
Quinn Tran726b8542017-01-19 22:28:00 -08001039 }
1040 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
Quinn Trana4239942017-12-28 12:33:26 -08001041}
Quinn Tran726b8542017-01-19 22:28:00 -08001042
Quinn Trana4239942017-12-28 12:33:26 -08001043static
1044void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
1045{
Quinn Trana4239942017-12-28 12:33:26 -08001046 fc_port_t *fcport = ea->fcport;
1047 struct port_database_24xx *pd;
1048 struct srb *sp = ea->sp;
Darren Trapp2b5b9642018-02-27 16:31:12 -08001049 uint8_t ls;
Quinn Trana4239942017-12-28 12:33:26 -08001050
1051 pd = (struct port_database_24xx *)sp->u.iocb_cmd.u.mbx.in;
1052
1053 fcport->flags &= ~FCF_ASYNC_SENT;
1054
1055 ql_dbg(ql_dbg_disc, vha, 0x20d2,
Quinn Tranf352eeb2017-12-28 12:33:35 -08001056 "%s %8phC DS %d LS %d rc %d\n", __func__, fcport->port_name,
1057 fcport->disc_state, pd->current_login_state, ea->rc);
Quinn Trana4239942017-12-28 12:33:26 -08001058
1059 if (fcport->disc_state == DSC_DELETE_PEND)
1060 return;
1061
Darren Trapp2b5b9642018-02-27 16:31:12 -08001062 if (fcport->fc4f_nvme)
1063 ls = pd->current_login_state >> 4;
1064 else
1065 ls = pd->current_login_state & 0xf;
1066
1067 switch (ls) {
Quinn Trana4239942017-12-28 12:33:26 -08001068 case PDS_PRLI_COMPLETE:
1069 __qla24xx_parse_gpdb(vha, fcport, pd);
1070 break;
1071 case PDS_PLOGI_PENDING:
1072 case PDS_PLOGI_COMPLETE:
1073 case PDS_PRLI_PENDING:
1074 case PDS_PRLI2_PENDING:
1075 ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC relogin needed\n",
1076 __func__, __LINE__, fcport->port_name);
1077 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
1078 return;
1079 case PDS_LOGO_PENDING:
1080 case PDS_PORT_UNAVAILABLE:
1081 default:
1082 ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC post del sess\n",
1083 __func__, __LINE__, fcport->port_name);
Quinn Trand8630bb2017-12-28 12:33:43 -08001084 qlt_schedule_sess_for_deletion(fcport);
Quinn Trana4239942017-12-28 12:33:26 -08001085 return;
1086 }
1087 __qla24xx_handle_gpdb_event(vha, ea);
1088} /* gpdb event */
Quinn Tran9cd883f2017-12-28 12:33:24 -08001089
1090static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
1091{
1092 u8 login = 0;
Quinn Tran040036b2017-12-28 12:33:38 -08001093 int rc;
Quinn Tran9cd883f2017-12-28 12:33:24 -08001094
1095 if (qla_tgt_mode_enabled(vha))
1096 return;
1097
1098 if (qla_dual_mode_enabled(vha)) {
1099 if (N2N_TOPO(vha->hw)) {
1100 u64 mywwn, wwn;
1101
1102 mywwn = wwn_to_u64(vha->port_name);
1103 wwn = wwn_to_u64(fcport->port_name);
1104 if (mywwn > wwn)
1105 login = 1;
1106 else if ((fcport->fw_login_state == DSC_LS_PLOGI_COMP)
1107 && time_after_eq(jiffies,
1108 fcport->plogi_nack_done_deadline))
1109 login = 1;
1110 } else {
1111 login = 1;
1112 }
1113 } else {
1114 /* initiator mode */
1115 login = 1;
1116 }
1117
1118 if (login) {
Quinn Tran040036b2017-12-28 12:33:38 -08001119 if (fcport->loop_id == FC_NO_LOOP_ID) {
1120 fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
1121 rc = qla2x00_find_new_loop_id(vha, fcport);
1122 if (rc) {
1123 ql_dbg(ql_dbg_disc, vha, 0x20e6,
1124 "%s %d %8phC post del sess - out of loopid\n",
1125 __func__, __LINE__, fcport->port_name);
1126 fcport->scan_state = 0;
Quinn Tran94cff6e2017-12-28 12:33:42 -08001127 qlt_schedule_sess_for_deletion(fcport);
Quinn Tran040036b2017-12-28 12:33:38 -08001128 return;
1129 }
1130 }
Quinn Tran9cd883f2017-12-28 12:33:24 -08001131 ql_dbg(ql_dbg_disc, vha, 0x20bf,
1132 "%s %d %8phC post login\n",
1133 __func__, __LINE__, fcport->port_name);
Quinn Tran9cd883f2017-12-28 12:33:24 -08001134 qla2x00_post_async_login_work(vha, fcport, NULL);
1135 }
1136}
1137
Quinn Tran726b8542017-01-19 22:28:00 -08001138int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
1139{
Quinn Tranf13515a2017-12-28 12:33:15 -08001140 u16 data[2];
Quinn Trana4239942017-12-28 12:33:26 -08001141 u64 wwn;
1142
1143 ql_dbg(ql_dbg_disc, vha, 0x20d8,
Quinn Tranf352eeb2017-12-28 12:33:35 -08001144 "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d retry %d lid %d scan %d\n",
Quinn Trana4239942017-12-28 12:33:26 -08001145 __func__, fcport->port_name, fcport->disc_state,
1146 fcport->fw_login_state, fcport->login_pause, fcport->flags,
1147 fcport->conflict, fcport->last_rscn_gen, fcport->rscn_gen,
Quinn Tranf352eeb2017-12-28 12:33:35 -08001148 fcport->login_gen, fcport->login_retry,
Quinn Trana4239942017-12-28 12:33:26 -08001149 fcport->loop_id, fcport->scan_state);
1150
Quinn Tran726b8542017-01-19 22:28:00 -08001151 if (fcport->scan_state != QLA_FCPORT_FOUND)
1152 return 0;
1153
Hannes Reinecke07ea4b62018-02-22 09:49:36 +01001154 if ((fcport->loop_id != FC_NO_LOOP_ID) &&
1155 ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
1156 (fcport->fw_login_state == DSC_LS_PRLI_PEND)))
Quinn Tran726b8542017-01-19 22:28:00 -08001157 return 0;
1158
Quinn Tran5b334692017-03-15 09:48:48 -07001159 if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
Quinn Tran9cd883f2017-12-28 12:33:24 -08001160 if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline)) {
1161 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
Quinn Tran5b334692017-03-15 09:48:48 -07001162 return 0;
Quinn Tran9cd883f2017-12-28 12:33:24 -08001163 }
Quinn Tran5b334692017-03-15 09:48:48 -07001164 }
1165
Quinn Tran726b8542017-01-19 22:28:00 -08001166 /* for pure Target Mode. Login will not be initiated */
1167 if (vha->host->active_mode == MODE_TARGET)
1168 return 0;
1169
1170 if (fcport->flags & FCF_ASYNC_SENT) {
1171 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
1172 return 0;
1173 }
1174
Quinn Tran625a1ca2018-05-01 09:01:44 -07001175 if (fcport->login_retry > 0)
1176 fcport->login_retry--;
Quinn Trana4239942017-12-28 12:33:26 -08001177
Quinn Tran726b8542017-01-19 22:28:00 -08001178 switch (fcport->disc_state) {
1179 case DSC_DELETED:
Quinn Trana4239942017-12-28 12:33:26 -08001180 wwn = wwn_to_u64(fcport->node_name);
1181 if (wwn == 0) {
1182 ql_dbg(ql_dbg_disc, vha, 0xffff,
1183 "%s %d %8phC post GNNID\n",
1184 __func__, __LINE__, fcport->port_name);
1185 qla24xx_post_gnnid_work(vha, fcport);
1186 } else if (fcport->loop_id == FC_NO_LOOP_ID) {
Quinn Tran83548fe2017-06-02 09:12:01 -07001187 ql_dbg(ql_dbg_disc, vha, 0x20bd,
1188 "%s %d %8phC post gnl\n",
1189 __func__, __LINE__, fcport->port_name);
Giridhar Malavali5d3300a2017-12-04 14:45:13 -08001190 qla24xx_post_gnl_work(vha, fcport);
Quinn Tran726b8542017-01-19 22:28:00 -08001191 } else {
Quinn Tran9cd883f2017-12-28 12:33:24 -08001192 qla_chk_n2n_b4_login(vha, fcport);
Quinn Tran726b8542017-01-19 22:28:00 -08001193 }
1194 break;
1195
1196 case DSC_GNL:
1197 if (fcport->login_pause) {
1198 fcport->last_rscn_gen = fcport->rscn_gen;
1199 fcport->last_login_gen = fcport->login_gen;
1200 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
1201 break;
1202 }
1203
Quinn Tran9cd883f2017-12-28 12:33:24 -08001204 qla_chk_n2n_b4_login(vha, fcport);
Quinn Tran726b8542017-01-19 22:28:00 -08001205 break;
1206
1207 case DSC_LOGIN_FAILED:
Quinn Tran83548fe2017-06-02 09:12:01 -07001208 ql_dbg(ql_dbg_disc, vha, 0x20d0,
1209 "%s %d %8phC post gidpn\n",
1210 __func__, __LINE__, fcport->port_name);
Quinn Tran9cd883f2017-12-28 12:33:24 -08001211 if (N2N_TOPO(vha->hw))
1212 qla_chk_n2n_b4_login(vha, fcport);
1213 else
1214 qla24xx_post_gidpn_work(vha, fcport);
Quinn Tran726b8542017-01-19 22:28:00 -08001215 break;
1216
1217 case DSC_LOGIN_COMPLETE:
1218 /* recheck login state */
Quinn Tran83548fe2017-06-02 09:12:01 -07001219 ql_dbg(ql_dbg_disc, vha, 0x20d1,
Quinn Tranf13515a2017-12-28 12:33:15 -08001220 "%s %d %8phC post adisc\n",
Quinn Tran83548fe2017-06-02 09:12:01 -07001221 __func__, __LINE__, fcport->port_name);
Quinn Tranf13515a2017-12-28 12:33:15 -08001222 data[0] = data[1] = 0;
1223 qla2x00_post_async_adisc_work(vha, fcport, data);
Quinn Tran726b8542017-01-19 22:28:00 -08001224 break;
1225
Darren Trapp1cbc0ef2018-03-20 23:09:37 -07001226 case DSC_LOGIN_PEND:
1227 if (fcport->fw_login_state == DSC_LS_PLOGI_COMP)
1228 qla24xx_post_prli_work(vha, fcport);
1229 break;
1230
Quinn Tran726b8542017-01-19 22:28:00 -08001231 default:
1232 break;
1233 }
1234
1235 return 0;
1236}
1237
1238static
1239void qla24xx_handle_rscn_event(fc_port_t *fcport, struct event_arg *ea)
1240{
1241 fcport->rscn_gen++;
1242
Quinn Tran83548fe2017-06-02 09:12:01 -07001243 ql_dbg(ql_dbg_disc, fcport->vha, 0x210c,
1244 "%s %8phC DS %d LS %d\n",
1245 __func__, fcport->port_name, fcport->disc_state,
1246 fcport->fw_login_state);
Quinn Tran726b8542017-01-19 22:28:00 -08001247
1248 if (fcport->flags & FCF_ASYNC_SENT)
1249 return;
1250
1251 switch (fcport->disc_state) {
1252 case DSC_DELETED:
1253 case DSC_LOGIN_COMPLETE:
Quinn Tran5ef696a2017-12-04 14:45:05 -08001254 qla24xx_post_gpnid_work(fcport->vha, &ea->id);
Quinn Tran726b8542017-01-19 22:28:00 -08001255 break;
Quinn Tran726b8542017-01-19 22:28:00 -08001256 default:
1257 break;
1258 }
1259}
1260
1261int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
Quinn Trana4239942017-12-28 12:33:26 -08001262 u8 *port_name, u8 *node_name, void *pla, u8 fc4_type)
Quinn Tran726b8542017-01-19 22:28:00 -08001263{
1264 struct qla_work_evt *e;
1265 e = qla2x00_alloc_work(vha, QLA_EVT_NEW_SESS);
1266 if (!e)
1267 return QLA_FUNCTION_FAILED;
1268
1269 e->u.new_sess.id = *id;
1270 e->u.new_sess.pla = pla;
Quinn Trana4239942017-12-28 12:33:26 -08001271 e->u.new_sess.fc4_type = fc4_type;
Quinn Tran726b8542017-01-19 22:28:00 -08001272 memcpy(e->u.new_sess.port_name, port_name, WWN_SIZE);
Quinn Trana4239942017-12-28 12:33:26 -08001273 if (node_name)
1274 memcpy(e->u.new_sess.node_name, node_name, WWN_SIZE);
Quinn Tran726b8542017-01-19 22:28:00 -08001275
1276 return qla2x00_post_work(vha, e);
1277}
1278
1279static
Quinn Tran726b8542017-01-19 22:28:00 -08001280void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
1281 struct event_arg *ea)
1282{
1283 fc_port_t *fcport = ea->fcport;
1284
Quinn Tran83548fe2017-06-02 09:12:01 -07001285 ql_dbg(ql_dbg_disc, vha, 0x2102,
1286 "%s %8phC DS %d LS %d P %d del %d cnfl %p rscn %d|%d login %d|%d fl %x\n",
1287 __func__, fcport->port_name, fcport->disc_state,
1288 fcport->fw_login_state, fcport->login_pause,
1289 fcport->deleted, fcport->conflict,
1290 fcport->last_rscn_gen, fcport->rscn_gen,
1291 fcport->last_login_gen, fcport->login_gen,
1292 fcport->flags);
Quinn Tran726b8542017-01-19 22:28:00 -08001293
1294 if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
Quinn Tran726b8542017-01-19 22:28:00 -08001295 (fcport->fw_login_state == DSC_LS_PRLI_PEND))
1296 return;
1297
Quinn Tran5b334692017-03-15 09:48:48 -07001298 if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
Quinn Tran9cd883f2017-12-28 12:33:24 -08001299 if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline)) {
1300 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
Quinn Tran5b334692017-03-15 09:48:48 -07001301 return;
Quinn Tran9cd883f2017-12-28 12:33:24 -08001302 }
Quinn Tran5b334692017-03-15 09:48:48 -07001303 }
1304
Quinn Tran726b8542017-01-19 22:28:00 -08001305 if (fcport->flags & FCF_ASYNC_SENT) {
1306 fcport->login_retry++;
1307 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
1308 return;
1309 }
1310
1311 if (fcport->disc_state == DSC_DELETE_PEND) {
1312 fcport->login_retry++;
1313 return;
1314 }
1315
1316 if (fcport->last_rscn_gen != fcport->rscn_gen) {
Quinn Tran83548fe2017-06-02 09:12:01 -07001317 ql_dbg(ql_dbg_disc, vha, 0x20e9, "%s %d %8phC post gidpn\n",
Quinn Tran726b8542017-01-19 22:28:00 -08001318 __func__, __LINE__, fcport->port_name);
1319
Giridhar Malavali5d3300a2017-12-04 14:45:13 -08001320 qla24xx_post_gidpn_work(vha, fcport);
Quinn Tran726b8542017-01-19 22:28:00 -08001321 return;
1322 }
1323
1324 qla24xx_fcport_handle_login(vha, fcport);
1325}
1326
Quinn Tran41dc5292017-01-19 22:28:03 -08001327void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
Quinn Tran726b8542017-01-19 22:28:00 -08001328{
Quinn Tranf352eeb2017-12-28 12:33:35 -08001329 fc_port_t *f, *tf;
Quinn Tran41dc5292017-01-19 22:28:03 -08001330 uint32_t id = 0, mask, rid;
Quinn Tranf352eeb2017-12-28 12:33:35 -08001331 unsigned long flags;
Quinn Tranbee8b8462018-05-01 09:01:47 -07001332 fc_port_t *fcport;
Quinn Tran726b8542017-01-19 22:28:00 -08001333
1334 switch (ea->event) {
Quinn Tranb98ae0d2017-06-02 09:12:00 -07001335 case FCME_RSCN:
1336 case FCME_GIDPN_DONE:
1337 case FCME_GPSC_DONE:
1338 case FCME_GPNID_DONE:
Quinn Trana4239942017-12-28 12:33:26 -08001339 case FCME_GNNID_DONE:
Quinn Tranb98ae0d2017-06-02 09:12:00 -07001340 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) ||
1341 test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))
1342 return;
1343 break;
1344 default:
1345 break;
1346 }
1347
1348 switch (ea->event) {
1349 case FCME_RELOGIN:
Quinn Tran726b8542017-01-19 22:28:00 -08001350 if (test_bit(UNLOADING, &vha->dpc_flags))
1351 return;
1352
1353 qla24xx_handle_relogin_event(vha, ea);
1354 break;
1355 case FCME_RSCN:
1356 if (test_bit(UNLOADING, &vha->dpc_flags))
1357 return;
Quinn Tran41dc5292017-01-19 22:28:03 -08001358 switch (ea->id.b.rsvd_1) {
1359 case RSCN_PORT_ADDR:
Quinn Tranbee8b8462018-05-01 09:01:47 -07001360 fcport = qla2x00_find_fcport_by_nportid
1361 (vha, &ea->id, 1);
1362 if (fcport)
1363 fcport->rscn_rcvd = 1;
1364
Quinn Tranf352eeb2017-12-28 12:33:35 -08001365 spin_lock_irqsave(&vha->work_lock, flags);
1366 if (vha->scan.scan_flags == 0) {
1367 ql_dbg(ql_dbg_disc, vha, 0xffff,
1368 "%s: schedule\n", __func__);
1369 vha->scan.scan_flags |= SF_QUEUED;
1370 schedule_delayed_work(&vha->scan.scan_work, 5);
Quinn Tran726b8542017-01-19 22:28:00 -08001371 }
Quinn Tranf352eeb2017-12-28 12:33:35 -08001372 spin_unlock_irqrestore(&vha->work_lock, flags);
1373
Quinn Tran41dc5292017-01-19 22:28:03 -08001374 break;
1375 case RSCN_AREA_ADDR:
1376 case RSCN_DOM_ADDR:
1377 if (ea->id.b.rsvd_1 == RSCN_AREA_ADDR) {
1378 mask = 0xffff00;
Quinn Tran83548fe2017-06-02 09:12:01 -07001379 ql_dbg(ql_dbg_async, vha, 0x5044,
1380 "RSCN: Area 0x%06x was affected\n",
1381 ea->id.b24);
Quinn Tran41dc5292017-01-19 22:28:03 -08001382 } else {
1383 mask = 0xff0000;
Quinn Tran83548fe2017-06-02 09:12:01 -07001384 ql_dbg(ql_dbg_async, vha, 0x507a,
1385 "RSCN: Domain 0x%06x was affected\n",
1386 ea->id.b24);
Quinn Tran41dc5292017-01-19 22:28:03 -08001387 }
1388
1389 rid = ea->id.b24 & mask;
1390 list_for_each_entry_safe(f, tf, &vha->vp_fcports,
1391 list) {
1392 id = f->d_id.b24 & mask;
1393 if (rid == id) {
1394 ea->fcport = f;
1395 qla24xx_handle_rscn_event(f, ea);
1396 }
1397 }
1398 break;
1399 case RSCN_FAB_ADDR:
1400 default:
Quinn Tran83548fe2017-06-02 09:12:01 -07001401 ql_log(ql_log_warn, vha, 0xd045,
1402 "RSCN: Fabric was affected. Addr format %d\n",
1403 ea->id.b.rsvd_1);
Quinn Tran41dc5292017-01-19 22:28:03 -08001404 qla2x00_mark_all_devices_lost(vha, 1);
1405 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
1406 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
Quinn Tran726b8542017-01-19 22:28:00 -08001407 }
1408 break;
1409 case FCME_GIDPN_DONE:
1410 qla24xx_handle_gidpn_event(vha, ea);
1411 break;
1412 case FCME_GNL_DONE:
1413 qla24xx_handle_gnl_done_event(vha, ea);
1414 break;
1415 case FCME_GPSC_DONE:
Quinn Trana4239942017-12-28 12:33:26 -08001416 qla24xx_handle_gpsc_event(vha, ea);
Quinn Tran726b8542017-01-19 22:28:00 -08001417 break;
1418 case FCME_PLOGI_DONE: /* Initiator side sent LLIOCB */
1419 qla24xx_handle_plogi_done_event(vha, ea);
1420 break;
Duane Grigsbya5d42f42017-06-21 13:48:41 -07001421 case FCME_PRLI_DONE:
1422 qla24xx_handle_prli_done_event(vha, ea);
1423 break;
Quinn Tran726b8542017-01-19 22:28:00 -08001424 case FCME_GPDB_DONE:
1425 qla24xx_handle_gpdb_event(vha, ea);
1426 break;
1427 case FCME_GPNID_DONE:
1428 qla24xx_handle_gpnid_event(vha, ea);
1429 break;
Duane Grigsbyd3bae932017-06-21 13:48:44 -07001430 case FCME_GFFID_DONE:
1431 qla24xx_handle_gffid_event(vha, ea);
1432 break;
Quinn Tranf13515a2017-12-28 12:33:15 -08001433 case FCME_ADISC_DONE:
1434 qla24xx_handle_adisc_event(vha, ea);
1435 break;
Quinn Trana4239942017-12-28 12:33:26 -08001436 case FCME_GNNID_DONE:
1437 qla24xx_handle_gnnid_event(vha, ea);
1438 break;
1439 case FCME_GFPNID_DONE:
1440 qla24xx_handle_gfpnid_event(vha, ea);
1441 break;
Quinn Tran726b8542017-01-19 22:28:00 -08001442 default:
1443 BUG_ON(1);
1444 break;
1445 }
1446}
1447
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001448static void
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001449qla2x00_tmf_iocb_timeout(void *data)
1450{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001451 srb_t *sp = data;
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001452 struct srb_iocb *tmf = &sp->u.iocb_cmd;
1453
1454 tmf->u.tmf.comp_status = CS_TIMEOUT;
1455 complete(&tmf->u.tmf.comp);
1456}
1457
1458static void
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001459qla2x00_tmf_sp_done(void *ptr, int res)
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001460{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001461 srb_t *sp = ptr;
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001462 struct srb_iocb *tmf = &sp->u.iocb_cmd;
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001463
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001464 complete(&tmf->u.tmf.comp);
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001465}
1466
1467int
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001468qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001469 uint32_t tag)
1470{
1471 struct scsi_qla_host *vha = fcport->vha;
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001472 struct srb_iocb *tm_iocb;
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001473 srb_t *sp;
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001474 int rval = QLA_FUNCTION_FAILED;
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001475
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001476 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001477 if (!sp)
1478 goto done;
1479
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001480 tm_iocb = &sp->u.iocb_cmd;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001481 sp->type = SRB_TM_CMD;
1482 sp->name = "tmf";
Ben Hutchingse74e7d92018-03-20 21:36:14 +00001483
1484 tm_iocb->timeout = qla2x00_tmf_iocb_timeout;
1485 init_completion(&tm_iocb->u.tmf.comp);
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001486 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
Ben Hutchingse74e7d92018-03-20 21:36:14 +00001487
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001488 tm_iocb->u.tmf.flags = flags;
1489 tm_iocb->u.tmf.lun = lun;
1490 tm_iocb->u.tmf.data = tag;
1491 sp->done = qla2x00_tmf_sp_done;
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001492
1493 rval = qla2x00_start_sp(sp);
1494 if (rval != QLA_SUCCESS)
1495 goto done_free_sp;
1496
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001497 ql_dbg(ql_dbg_taskm, vha, 0x802f,
Chad Dupuiscfb09192011-11-18 09:03:07 -08001498 "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
1499 sp->handle, fcport->loop_id, fcport->d_id.b.domain,
1500 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001501
1502 wait_for_completion(&tm_iocb->u.tmf.comp);
1503
1504 rval = tm_iocb->u.tmf.comp_status == CS_COMPLETE ?
1505 QLA_SUCCESS : QLA_FUNCTION_FAILED;
1506
1507 if ((rval != QLA_SUCCESS) || tm_iocb->u.tmf.data) {
1508 ql_dbg(ql_dbg_taskm, vha, 0x8030,
1509 "TM IOCB failed (%x).\n", rval);
1510 }
1511
1512 if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) {
1513 flags = tm_iocb->u.tmf.flags;
1514 lun = (uint16_t)tm_iocb->u.tmf.lun;
1515
1516 /* Issue Marker IOCB */
1517 qla2x00_marker(vha, vha->hw->req_q_map[0],
1518 vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun,
1519 flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
1520 }
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001521
1522done_free_sp:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001523 sp->free(sp);
Quinn Tran6d6749272017-12-28 12:33:41 -08001524 sp->fcport->flags &= ~FCF_ASYNC_SENT;
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001525done:
1526 return rval;
1527}
1528
Armen Baloyan4440e462014-02-26 04:15:18 -05001529static void
1530qla24xx_abort_iocb_timeout(void *data)
1531{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001532 srb_t *sp = data;
Armen Baloyan4440e462014-02-26 04:15:18 -05001533 struct srb_iocb *abt = &sp->u.iocb_cmd;
1534
1535 abt->u.abt.comp_status = CS_TIMEOUT;
1536 complete(&abt->u.abt.comp);
1537}
1538
1539static void
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001540qla24xx_abort_sp_done(void *ptr, int res)
Armen Baloyan4440e462014-02-26 04:15:18 -05001541{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001542 srb_t *sp = ptr;
Armen Baloyan4440e462014-02-26 04:15:18 -05001543 struct srb_iocb *abt = &sp->u.iocb_cmd;
1544
Ben Hutchings3a9910d2018-03-20 21:05:48 +00001545 if (del_timer(&sp->u.iocb_cmd.timer))
1546 complete(&abt->u.abt.comp);
Armen Baloyan4440e462014-02-26 04:15:18 -05001547}
1548
Quinn Tran15f30a52017-03-15 09:48:52 -07001549int
Armen Baloyan4440e462014-02-26 04:15:18 -05001550qla24xx_async_abort_cmd(srb_t *cmd_sp)
1551{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001552 scsi_qla_host_t *vha = cmd_sp->vha;
Armen Baloyan4440e462014-02-26 04:15:18 -05001553 fc_port_t *fcport = cmd_sp->fcport;
1554 struct srb_iocb *abt_iocb;
1555 srb_t *sp;
1556 int rval = QLA_FUNCTION_FAILED;
1557
1558 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
1559 if (!sp)
1560 goto done;
1561
1562 abt_iocb = &sp->u.iocb_cmd;
1563 sp->type = SRB_ABT_CMD;
1564 sp->name = "abort";
Ben Hutchingse74e7d92018-03-20 21:36:14 +00001565
1566 abt_iocb->timeout = qla24xx_abort_iocb_timeout;
1567 init_completion(&abt_iocb->u.abt.comp);
Armen Baloyan4440e462014-02-26 04:15:18 -05001568 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
Ben Hutchingse74e7d92018-03-20 21:36:14 +00001569
Armen Baloyan4440e462014-02-26 04:15:18 -05001570 abt_iocb->u.abt.cmd_hndl = cmd_sp->handle;
Darren Trappb027a5a2018-01-15 20:46:51 -08001571
1572 if (vha->flags.qpairs_available && cmd_sp->qpair)
1573 abt_iocb->u.abt.req_que_no =
1574 cpu_to_le16(cmd_sp->qpair->req->id);
1575 else
1576 abt_iocb->u.abt.req_que_no = cpu_to_le16(vha->req->id);
1577
Armen Baloyan4440e462014-02-26 04:15:18 -05001578 sp->done = qla24xx_abort_sp_done;
Armen Baloyan4440e462014-02-26 04:15:18 -05001579
1580 rval = qla2x00_start_sp(sp);
1581 if (rval != QLA_SUCCESS)
1582 goto done_free_sp;
1583
1584 ql_dbg(ql_dbg_async, vha, 0x507c,
1585 "Abort command issued - hdl=%x, target_id=%x\n",
1586 cmd_sp->handle, fcport->tgt_id);
1587
1588 wait_for_completion(&abt_iocb->u.abt.comp);
1589
1590 rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
1591 QLA_SUCCESS : QLA_FUNCTION_FAILED;
1592
1593done_free_sp:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001594 sp->free(sp);
Armen Baloyan4440e462014-02-26 04:15:18 -05001595done:
1596 return rval;
1597}
1598
1599int
1600qla24xx_async_abort_command(srb_t *sp)
1601{
1602 unsigned long flags = 0;
1603
1604 uint32_t handle;
1605 fc_port_t *fcport = sp->fcport;
1606 struct scsi_qla_host *vha = fcport->vha;
1607 struct qla_hw_data *ha = vha->hw;
1608 struct req_que *req = vha->req;
1609
Darren Trappb027a5a2018-01-15 20:46:51 -08001610 if (vha->flags.qpairs_available && sp->qpair)
1611 req = sp->qpair->req;
1612
Armen Baloyan4440e462014-02-26 04:15:18 -05001613 spin_lock_irqsave(&ha->hardware_lock, flags);
1614 for (handle = 1; handle < req->num_outstanding_cmds; handle++) {
1615 if (req->outstanding_cmds[handle] == sp)
1616 break;
1617 }
1618 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1619 if (handle == req->num_outstanding_cmds) {
1620 /* Command not found. */
1621 return QLA_FUNCTION_FAILED;
1622 }
1623 if (sp->type == SRB_FXIOCB_DCMD)
1624 return qlafx00_fx_disc(vha, &vha->hw->mr.fcport,
1625 FXDISC_ABORT_IOCTL);
1626
1627 return qla24xx_async_abort_cmd(sp);
1628}
1629
Quinn Tran726b8542017-01-19 22:28:00 -08001630static void
Duane Grigsbya5d42f42017-06-21 13:48:41 -07001631qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
1632{
1633 switch (ea->data[0]) {
1634 case MBS_COMMAND_COMPLETE:
1635 ql_dbg(ql_dbg_disc, vha, 0x2118,
1636 "%s %d %8phC post gpdb\n",
1637 __func__, __LINE__, ea->fcport->port_name);
1638
1639 ea->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
1640 ea->fcport->logout_on_delete = 1;
1641 qla24xx_post_gpdb_work(vha, ea->fcport, 0);
1642 break;
1643 default:
Darren Trapp1cbc0ef2018-03-20 23:09:37 -07001644 if ((ea->iop[0] == LSC_SCODE_ELS_REJECT) &&
1645 (ea->iop[1] == 0x50000)) { /* reson 5=busy expl:0x0 */
1646 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
1647 ea->fcport->fw_login_state = DSC_LS_PLOGI_COMP;
1648 break;
1649 }
1650
Duane Grigsbyedd05de2017-10-13 09:34:06 -07001651 if (ea->fcport->n2n_flag) {
1652 ql_dbg(ql_dbg_disc, vha, 0x2118,
1653 "%s %d %8phC post fc4 prli\n",
1654 __func__, __LINE__, ea->fcport->port_name);
1655 ea->fcport->fc4f_nvme = 0;
1656 ea->fcport->n2n_flag = 0;
1657 qla24xx_post_prli_work(vha, ea->fcport);
1658 }
Duane Grigsbya5d42f42017-06-21 13:48:41 -07001659 ql_dbg(ql_dbg_disc, vha, 0x2119,
1660 "%s %d %8phC unhandle event of %x\n",
1661 __func__, __LINE__, ea->fcport->port_name, ea->data[0]);
1662 break;
1663 }
1664}
1665
1666static void
Quinn Tran726b8542017-01-19 22:28:00 -08001667qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
Andrew Vasquezac280b62009-08-20 11:06:05 -07001668{
Quinn Tran726b8542017-01-19 22:28:00 -08001669 port_id_t cid; /* conflict Nport id */
Quinn Trana084fd62017-12-04 14:45:00 -08001670 u16 lid;
1671 struct fc_port *conflict_fcport;
Quinn Tran82abdca2017-12-28 12:33:22 -08001672 unsigned long flags;
Quinn Trana4239942017-12-28 12:33:26 -08001673 struct fc_port *fcport = ea->fcport;
1674
Quinn Tranf352eeb2017-12-28 12:33:35 -08001675 ql_dbg(ql_dbg_disc, vha, 0xffff,
1676 "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d data %x|%x iop %x|%x\n",
1677 __func__, fcport->port_name, fcport->disc_state,
1678 fcport->fw_login_state, ea->rc, ea->sp->gen2, fcport->login_gen,
1679 ea->sp->gen2, fcport->rscn_gen|ea->sp->gen1,
1680 ea->data[0], ea->data[1], ea->iop[0], ea->iop[1]);
1681
Quinn Trana4239942017-12-28 12:33:26 -08001682 if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
1683 (fcport->fw_login_state == DSC_LS_PRLI_PEND)) {
1684 ql_dbg(ql_dbg_disc, vha, 0x20ea,
1685 "%s %d %8phC Remote is trying to login\n",
1686 __func__, __LINE__, fcport->port_name);
1687 return;
1688 }
1689
1690 if (fcport->disc_state == DSC_DELETE_PEND)
1691 return;
1692
1693 if (ea->sp->gen2 != fcport->login_gen) {
1694 /* target side must have changed it. */
1695 ql_dbg(ql_dbg_disc, vha, 0x20d3,
Quinn Tranf352eeb2017-12-28 12:33:35 -08001696 "%s %8phC generation changed\n",
1697 __func__, fcport->port_name);
1698 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
Quinn Trana4239942017-12-28 12:33:26 -08001699 return;
1700 } else if (ea->sp->gen1 != fcport->rscn_gen) {
1701 ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
1702 __func__, __LINE__, fcport->port_name);
1703 qla24xx_post_gidpn_work(vha, fcport);
1704 return;
1705 }
Andrew Vasquezac280b62009-08-20 11:06:05 -07001706
Quinn Tran726b8542017-01-19 22:28:00 -08001707 switch (ea->data[0]) {
Andrew Vasquezac280b62009-08-20 11:06:05 -07001708 case MBS_COMMAND_COMPLETE:
Andrew Vasqueza4f92a32011-03-30 11:46:31 -07001709 /*
1710 * Driver must validate login state - If PRLI not complete,
1711 * force a relogin attempt via implicit LOGO, PLOGI, and PRLI
1712 * requests.
1713 */
Duane Grigsbya5d42f42017-06-21 13:48:41 -07001714 if (ea->fcport->fc4f_nvme) {
1715 ql_dbg(ql_dbg_disc, vha, 0x2117,
1716 "%s %d %8phC post prli\n",
1717 __func__, __LINE__, ea->fcport->port_name);
1718 qla24xx_post_prli_work(vha, ea->fcport);
1719 } else {
1720 ql_dbg(ql_dbg_disc, vha, 0x20ea,
Quinn Trana084fd62017-12-04 14:45:00 -08001721 "%s %d %8phC LoopID 0x%x in use with %06x. post gnl\n",
1722 __func__, __LINE__, ea->fcport->port_name,
1723 ea->fcport->loop_id, ea->fcport->d_id.b24);
1724
1725 set_bit(ea->fcport->loop_id, vha->hw->loop_id_map);
Quinn Tran82abdca2017-12-28 12:33:22 -08001726 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
Duane Grigsbya5d42f42017-06-21 13:48:41 -07001727 ea->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
1728 ea->fcport->logout_on_delete = 1;
Quinn Tran35158322017-08-30 10:16:50 -07001729 ea->fcport->send_els_logo = 0;
Quinn Tran82abdca2017-12-28 12:33:22 -08001730 ea->fcport->fw_login_state = DSC_LS_PRLI_COMP;
1731 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
1732
Duane Grigsbya5d42f42017-06-21 13:48:41 -07001733 qla24xx_post_gpdb_work(vha, ea->fcport, 0);
1734 }
Andrew Vasquezac280b62009-08-20 11:06:05 -07001735 break;
1736 case MBS_COMMAND_ERROR:
Quinn Tran83548fe2017-06-02 09:12:01 -07001737 ql_dbg(ql_dbg_disc, vha, 0x20eb, "%s %d %8phC cmd error %x\n",
Quinn Tran726b8542017-01-19 22:28:00 -08001738 __func__, __LINE__, ea->fcport->port_name, ea->data[1]);
1739
1740 ea->fcport->flags &= ~FCF_ASYNC_SENT;
1741 ea->fcport->disc_state = DSC_LOGIN_FAILED;
1742 if (ea->data[1] & QLA_LOGIO_LOGIN_RETRIED)
Andrew Vasquezac280b62009-08-20 11:06:05 -07001743 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
1744 else
Quinn Tran726b8542017-01-19 22:28:00 -08001745 qla2x00_mark_device_lost(vha, ea->fcport, 1, 0);
Andrew Vasquezac280b62009-08-20 11:06:05 -07001746 break;
1747 case MBS_LOOP_ID_USED:
Quinn Tran726b8542017-01-19 22:28:00 -08001748 /* data[1] = IO PARAM 1 = nport ID */
1749 cid.b.domain = (ea->iop[1] >> 16) & 0xff;
1750 cid.b.area = (ea->iop[1] >> 8) & 0xff;
1751 cid.b.al_pa = ea->iop[1] & 0xff;
1752 cid.b.rsvd_1 = 0;
1753
Quinn Tran83548fe2017-06-02 09:12:01 -07001754 ql_dbg(ql_dbg_disc, vha, 0x20ec,
1755 "%s %d %8phC LoopID 0x%x in use post gnl\n",
1756 __func__, __LINE__, ea->fcport->port_name,
1757 ea->fcport->loop_id);
Quinn Tran726b8542017-01-19 22:28:00 -08001758
1759 if (IS_SW_RESV_ADDR(cid)) {
1760 set_bit(ea->fcport->loop_id, vha->hw->loop_id_map);
1761 ea->fcport->loop_id = FC_NO_LOOP_ID;
1762 } else {
1763 qla2x00_clear_loop_id(ea->fcport);
Andrew Vasquezac280b62009-08-20 11:06:05 -07001764 }
Quinn Tran726b8542017-01-19 22:28:00 -08001765 qla24xx_post_gnl_work(vha, ea->fcport);
1766 break;
1767 case MBS_PORT_ID_USED:
Quinn Tran83548fe2017-06-02 09:12:01 -07001768 ql_dbg(ql_dbg_disc, vha, 0x20ed,
1769 "%s %d %8phC NPortId %02x%02x%02x inuse post gidpn\n",
1770 __func__, __LINE__, ea->fcport->port_name,
1771 ea->fcport->d_id.b.domain, ea->fcport->d_id.b.area,
1772 ea->fcport->d_id.b.al_pa);
Quinn Tran726b8542017-01-19 22:28:00 -08001773
Quinn Trana084fd62017-12-04 14:45:00 -08001774 lid = ea->iop[1] & 0xffff;
1775 qlt_find_sess_invalidate_other(vha,
1776 wwn_to_u64(ea->fcport->port_name),
1777 ea->fcport->d_id, lid, &conflict_fcport);
1778
1779 if (conflict_fcport) {
1780 /*
1781 * Another fcport share the same loop_id/nport id.
1782 * Conflict fcport needs to finish cleanup before this
1783 * fcport can proceed to login.
1784 */
1785 conflict_fcport->conflict = ea->fcport;
1786 ea->fcport->login_pause = 1;
1787
1788 ql_dbg(ql_dbg_disc, vha, 0x20ed,
1789 "%s %d %8phC NPortId %06x inuse with loopid 0x%x. post gidpn\n",
1790 __func__, __LINE__, ea->fcport->port_name,
1791 ea->fcport->d_id.b24, lid);
1792 qla2x00_clear_loop_id(ea->fcport);
1793 qla24xx_post_gidpn_work(vha, ea->fcport);
1794 } else {
1795 ql_dbg(ql_dbg_disc, vha, 0x20ed,
1796 "%s %d %8phC NPortId %06x inuse with loopid 0x%x. sched delete\n",
1797 __func__, __LINE__, ea->fcport->port_name,
1798 ea->fcport->d_id.b24, lid);
1799
1800 qla2x00_clear_loop_id(ea->fcport);
1801 set_bit(lid, vha->hw->loop_id_map);
1802 ea->fcport->loop_id = lid;
1803 ea->fcport->keep_nport_handle = 0;
Quinn Tran94cff6e2017-12-28 12:33:42 -08001804 qlt_schedule_sess_for_deletion(ea->fcport);
Quinn Trana084fd62017-12-04 14:45:00 -08001805 }
Andrew Vasquezac280b62009-08-20 11:06:05 -07001806 break;
1807 }
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001808 return;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001809}
1810
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001811void
Andrew Vasquezac280b62009-08-20 11:06:05 -07001812qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
1813 uint16_t *data)
1814{
Quinn Tran726b8542017-01-19 22:28:00 -08001815 qla2x00_mark_device_lost(vha, fcport, 1, 0);
Alexei Potashnika6ca8872015-07-14 16:00:44 -04001816 qlt_logo_completion_handler(fcport, data[0]);
Quinn Tran726b8542017-01-19 22:28:00 -08001817 fcport->login_gen++;
Hannes Reineckefa83e652018-02-22 09:49:37 +01001818 fcport->flags &= ~FCF_ASYNC_ACTIVE;
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001819 return;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001820}
1821
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001822void
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001823qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
1824 uint16_t *data)
1825{
Hannes Reineckefa83e652018-02-22 09:49:37 +01001826 fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001827 if (data[0] == MBS_COMMAND_COMPLETE) {
1828 qla2x00_update_fcport(vha, fcport);
1829
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001830 return;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001831 }
1832
1833 /* Retry login. */
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001834 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
1835 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
1836 else
Andrew Vasquez80d79442011-03-30 11:46:17 -07001837 qla2x00_mark_device_lost(vha, fcport, 1, 0);
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001838
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001839 return;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001840}
1841
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842/****************************************************************************/
1843/* QLogic ISP2x00 Hardware Support Functions. */
1844/****************************************************************************/
1845
Saurav Kashyapfa492632012-11-21 02:40:29 -05001846static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04001847qla83xx_nic_core_fw_load(scsi_qla_host_t *vha)
1848{
1849 int rval = QLA_SUCCESS;
1850 struct qla_hw_data *ha = vha->hw;
1851 uint32_t idc_major_ver, idc_minor_ver;
Saurav Kashyap711aa7f2012-08-22 14:21:15 -04001852 uint16_t config[4];
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04001853
1854 qla83xx_idc_lock(vha, 0);
1855
1856 /* SV: TODO: Assign initialization timeout from
1857 * flash-info / other param
1858 */
1859 ha->fcoe_dev_init_timeout = QLA83XX_IDC_INITIALIZATION_TIMEOUT;
1860 ha->fcoe_reset_timeout = QLA83XX_IDC_RESET_ACK_TIMEOUT;
1861
1862 /* Set our fcoe function presence */
1863 if (__qla83xx_set_drv_presence(vha) != QLA_SUCCESS) {
1864 ql_dbg(ql_dbg_p3p, vha, 0xb077,
1865 "Error while setting DRV-Presence.\n");
1866 rval = QLA_FUNCTION_FAILED;
1867 goto exit;
1868 }
1869
1870 /* Decide the reset ownership */
1871 qla83xx_reset_ownership(vha);
1872
1873 /*
1874 * On first protocol driver load:
1875 * Init-Owner: Set IDC-Major-Version and Clear IDC-Lock-Recovery
1876 * register.
1877 * Others: Check compatibility with current IDC Major version.
1878 */
1879 qla83xx_rd_reg(vha, QLA83XX_IDC_MAJOR_VERSION, &idc_major_ver);
1880 if (ha->flags.nic_core_reset_owner) {
1881 /* Set IDC Major version */
1882 idc_major_ver = QLA83XX_SUPP_IDC_MAJOR_VERSION;
1883 qla83xx_wr_reg(vha, QLA83XX_IDC_MAJOR_VERSION, idc_major_ver);
1884
1885 /* Clearing IDC-Lock-Recovery register */
1886 qla83xx_wr_reg(vha, QLA83XX_IDC_LOCK_RECOVERY, 0);
1887 } else if (idc_major_ver != QLA83XX_SUPP_IDC_MAJOR_VERSION) {
1888 /*
1889 * Clear further IDC participation if we are not compatible with
1890 * the current IDC Major Version.
1891 */
1892 ql_log(ql_log_warn, vha, 0xb07d,
1893 "Failing load, idc_major_ver=%d, expected_major_ver=%d.\n",
1894 idc_major_ver, QLA83XX_SUPP_IDC_MAJOR_VERSION);
1895 __qla83xx_clear_drv_presence(vha);
1896 rval = QLA_FUNCTION_FAILED;
1897 goto exit;
1898 }
1899 /* Each function sets its supported Minor version. */
1900 qla83xx_rd_reg(vha, QLA83XX_IDC_MINOR_VERSION, &idc_minor_ver);
1901 idc_minor_ver |= (QLA83XX_SUPP_IDC_MINOR_VERSION << (ha->portnum * 2));
1902 qla83xx_wr_reg(vha, QLA83XX_IDC_MINOR_VERSION, idc_minor_ver);
1903
Saurav Kashyap711aa7f2012-08-22 14:21:15 -04001904 if (ha->flags.nic_core_reset_owner) {
1905 memset(config, 0, sizeof(config));
1906 if (!qla81xx_get_port_config(vha, config))
1907 qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE,
1908 QLA8XXX_DEV_READY);
1909 }
1910
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04001911 rval = qla83xx_idc_state_handler(vha);
1912
1913exit:
1914 qla83xx_idc_unlock(vha, 0);
1915
1916 return rval;
1917}
1918
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919/*
1920* qla2x00_initialize_adapter
1921* Initialize board.
1922*
1923* Input:
1924* ha = adapter block pointer.
1925*
1926* Returns:
1927* 0 = success
1928*/
1929int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001930qla2x00_initialize_adapter(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931{
1932 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001933 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001934 struct req_que *req = ha->req_q_map[0];
Lalit Chandivade2533cf62009-03-24 09:08:07 -07001935
Joe Carnucciofc90ada2016-07-06 11:14:23 -04001936 memset(&vha->qla_stats, 0, sizeof(vha->qla_stats));
1937 memset(&vha->fc_host_stat, 0, sizeof(vha->fc_host_stat));
1938
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 /* Clear adapter flags. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001940 vha->flags.online = 0;
Lalit Chandivade2533cf62009-03-24 09:08:07 -07001941 ha->flags.chip_reset_done = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001942 vha->flags.reset_active = 0;
Andrew Vasquez85880802009-12-15 21:29:46 -08001943 ha->flags.pci_channel_io_perm_failure = 0;
1944 ha->flags.eeh_busy = 0;
Joe Carnucciofabbb8d2013-08-27 01:37:40 -04001945 vha->qla_stats.jiffies_at_last_reset = get_jiffies_64();
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001946 atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
1947 atomic_set(&vha->loop_state, LOOP_DOWN);
1948 vha->device_flags = DFLG_NO_CABLE;
1949 vha->dpc_flags = 0;
1950 vha->flags.management_server_logged_in = 0;
1951 vha->marker_needed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 ha->isp_abort_cnt = 0;
1953 ha->beacon_blink_led = 0;
1954
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001955 set_bit(0, ha->req_qid_map);
1956 set_bit(0, ha->rsp_qid_map);
1957
Chad Dupuiscfb09192011-11-18 09:03:07 -08001958 ql_dbg(ql_dbg_init, vha, 0x0040,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001959 "Configuring PCI space...\n");
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001960 rval = ha->isp_ops->pci_config(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001962 ql_log(ql_log_warn, vha, 0x0044,
1963 "Unable to configure PCI space.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 return (rval);
1965 }
1966
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001967 ha->isp_ops->reset_chip(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001969 rval = qla2xxx_get_flash_info(vha);
Andrew Vasquezc00d8992008-09-11 21:22:49 -07001970 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001971 ql_log(ql_log_fatal, vha, 0x004f,
1972 "Unable to validate FLASH data.\n");
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04001973 return rval;
1974 }
1975
1976 if (IS_QLA8044(ha)) {
1977 qla8044_read_reset_template(vha);
1978
1979 /* NOTE: If ql2xdontresethba==1, set IDC_CTRL DONTRESET_BIT0.
1980 * If DONRESET_BIT0 is set, drivers should not set dev_state
1981 * to NEED_RESET. But if NEED_RESET is set, drivers should
1982 * should honor the reset. */
1983 if (ql2xdontresethba == 1)
1984 qla8044_set_idc_dontreset(vha);
Andrew Vasquezc00d8992008-09-11 21:22:49 -07001985 }
1986
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001987 ha->isp_ops->get_flash_version(vha, req->ring);
Chad Dupuiscfb09192011-11-18 09:03:07 -08001988 ql_dbg(ql_dbg_init, vha, 0x0061,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001989 "Configure NVRAM parameters...\n");
Andrew Vasquez0107109e2005-07-06 10:31:37 -07001990
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001991 ha->isp_ops->nvram_config(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
Andrew Vasquezd4c760c2006-06-23 16:10:39 -07001993 if (ha->flags.disable_serdes) {
1994 /* Mask HBA via NVRAM settings? */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001995 ql_log(ql_log_info, vha, 0x0077,
Oleksandr Khoshaba7b8335582013-08-27 01:37:27 -04001996 "Masking HBA WWPN %8phN (via NVRAM).\n", vha->port_name);
Andrew Vasquezd4c760c2006-06-23 16:10:39 -07001997 return QLA_FUNCTION_FAILED;
1998 }
1999
Chad Dupuiscfb09192011-11-18 09:03:07 -08002000 ql_dbg(ql_dbg_init, vha, 0x0078,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002001 "Verifying loaded RISC code...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002003 if (qla2x00_isp_firmware(vha) != QLA_SUCCESS) {
2004 rval = ha->isp_ops->chip_diag(vha);
Andrew Vasquezd19044c2006-11-22 08:22:19 -08002005 if (rval)
2006 return (rval);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002007 rval = qla2x00_setup_chip(vha);
Andrew Vasquezd19044c2006-11-22 08:22:19 -08002008 if (rval)
2009 return (rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 }
Giridhar Malavalia9083012010-04-12 17:59:55 -07002011
Harihara Kadayam4d4df192008-04-03 13:13:26 -07002012 if (IS_QLA84XX(ha)) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002013 ha->cs84xx = qla84xx_get_chip(vha);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07002014 if (!ha->cs84xx) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002015 ql_log(ql_log_warn, vha, 0x00d0,
Harihara Kadayam4d4df192008-04-03 13:13:26 -07002016 "Unable to configure ISP84XX.\n");
2017 return QLA_FUNCTION_FAILED;
2018 }
2019 }
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002020
Quinn Tranead03852017-01-19 22:28:01 -08002021 if (qla_ini_mode_enabled(vha) || qla_dual_mode_enabled(vha))
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002022 rval = qla2x00_init_rings(vha);
2023
Lalit Chandivade2533cf62009-03-24 09:08:07 -07002024 ha->flags.chip_reset_done = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025
Giridhar Malavali9a069e12010-01-12 13:02:47 -08002026 if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) {
Andrew Vasquez6c452a42010-03-19 17:04:02 -07002027 /* Issue verify 84xx FW IOCB to complete 84xx initialization */
Giridhar Malavali9a069e12010-01-12 13:02:47 -08002028 rval = qla84xx_init_chip(vha);
2029 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002030 ql_log(ql_log_warn, vha, 0x00d4,
2031 "Unable to initialize ISP84XX.\n");
Bart Van Assche8d2b21d2015-06-04 15:58:09 -07002032 qla84xx_put_chip(vha);
Giridhar Malavali9a069e12010-01-12 13:02:47 -08002033 }
2034 }
2035
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04002036 /* Load the NIC Core f/w if we are the first protocol driver. */
2037 if (IS_QLA8031(ha)) {
2038 rval = qla83xx_nic_core_fw_load(vha);
2039 if (rval)
2040 ql_log(ql_log_warn, vha, 0x0124,
2041 "Error in initializing NIC Core f/w.\n");
2042 }
2043
Madhuranath Iyengar2f0f3f42010-07-23 15:28:24 +05002044 if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))
2045 qla24xx_read_fcp_prio_cfg(vha);
Sarang Radke09ff7012010-03-19 17:03:59 -07002046
Joe Carnuccioc46e65c2013-08-27 01:37:35 -04002047 if (IS_P3P_TYPE(ha))
2048 qla82xx_set_driver_version(vha, QLA2XXX_VERSION);
2049 else
2050 qla25xx_set_driver_version(vha, QLA2XXX_VERSION);
2051
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 return (rval);
2053}
2054
2055/**
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002056 * qla2100_pci_config() - Setup ISP21xx PCI configuration registers.
Bart Van Assche2db62282018-01-23 16:33:51 -08002057 * @vha: HA context
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 *
2059 * Returns 0 on success.
2060 */
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002061int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002062qla2100_pci_config(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063{
Andrew Vasqueza157b102007-05-07 07:43:01 -07002064 uint16_t w;
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002065 unsigned long flags;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002066 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07002067 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 pci_set_master(ha->pdev);
Andrew Vasquezaf6177d2007-07-19 15:06:02 -07002070 pci_try_set_mwi(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
Andrew Vasqueza157b102007-05-07 07:43:01 -07002073 w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 pci_write_config_word(ha->pdev, PCI_COMMAND, w);
2075
Andrew Vasquez737faec2008-10-24 15:13:45 -07002076 pci_disable_rom(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002078 /* Get PCI bus information. */
2079 spin_lock_irqsave(&ha->hardware_lock, flags);
Andrew Vasquez3d716442005-07-06 10:30:26 -07002080 ha->pci_attr = RD_REG_WORD(&reg->ctrl_status);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002081 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2082
2083 return QLA_SUCCESS;
2084}
2085
2086/**
2087 * qla2300_pci_config() - Setup ISP23xx PCI configuration registers.
Bart Van Assche2db62282018-01-23 16:33:51 -08002088 * @vha: HA context
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002089 *
2090 * Returns 0 on success.
2091 */
2092int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002093qla2300_pci_config(scsi_qla_host_t *vha)
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002094{
Andrew Vasqueza157b102007-05-07 07:43:01 -07002095 uint16_t w;
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002096 unsigned long flags = 0;
2097 uint32_t cnt;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002098 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07002099 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002100
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002101 pci_set_master(ha->pdev);
Andrew Vasquezaf6177d2007-07-19 15:06:02 -07002102 pci_try_set_mwi(ha->pdev);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002103
2104 pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
Andrew Vasqueza157b102007-05-07 07:43:01 -07002105 w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002106
2107 if (IS_QLA2322(ha) || IS_QLA6322(ha))
2108 w &= ~PCI_COMMAND_INTX_DISABLE;
Andrew Vasqueza157b102007-05-07 07:43:01 -07002109 pci_write_config_word(ha->pdev, PCI_COMMAND, w);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002110
2111 /*
2112 * If this is a 2300 card and not 2312, reset the
2113 * COMMAND_INVALIDATE due to a bug in the 2300. Unfortunately,
2114 * the 2310 also reports itself as a 2300 so we need to get the
2115 * fb revision level -- a 6 indicates it really is a 2300 and
2116 * not a 2310.
2117 */
2118 if (IS_QLA2300(ha)) {
2119 spin_lock_irqsave(&ha->hardware_lock, flags);
2120
2121 /* Pause RISC. */
Andrew Vasquez3d716442005-07-06 10:30:26 -07002122 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002123 for (cnt = 0; cnt < 30000; cnt++) {
Andrew Vasquez3d716442005-07-06 10:30:26 -07002124 if ((RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) != 0)
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002125 break;
2126
2127 udelay(10);
2128 }
2129
2130 /* Select FPM registers. */
Andrew Vasquez3d716442005-07-06 10:30:26 -07002131 WRT_REG_WORD(&reg->ctrl_status, 0x20);
2132 RD_REG_WORD(&reg->ctrl_status);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002133
2134 /* Get the fb rev level */
Andrew Vasquez3d716442005-07-06 10:30:26 -07002135 ha->fb_rev = RD_FB_CMD_REG(ha, reg);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002136
2137 if (ha->fb_rev == FPM_2300)
Andrew Vasqueza157b102007-05-07 07:43:01 -07002138 pci_clear_mwi(ha->pdev);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002139
2140 /* Deselect FPM registers. */
Andrew Vasquez3d716442005-07-06 10:30:26 -07002141 WRT_REG_WORD(&reg->ctrl_status, 0x0);
2142 RD_REG_WORD(&reg->ctrl_status);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002143
2144 /* Release RISC module. */
Andrew Vasquez3d716442005-07-06 10:30:26 -07002145 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002146 for (cnt = 0; cnt < 30000; cnt++) {
Andrew Vasquez3d716442005-07-06 10:30:26 -07002147 if ((RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0)
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002148 break;
2149
2150 udelay(10);
2151 }
2152
2153 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2154 }
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002155
2156 pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
2157
Andrew Vasquez737faec2008-10-24 15:13:45 -07002158 pci_disable_rom(ha->pdev);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002159
2160 /* Get PCI bus information. */
2161 spin_lock_irqsave(&ha->hardware_lock, flags);
Andrew Vasquez3d716442005-07-06 10:30:26 -07002162 ha->pci_attr = RD_REG_WORD(&reg->ctrl_status);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002163 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2164
2165 return QLA_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166}
2167
2168/**
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002169 * qla24xx_pci_config() - Setup ISP24xx PCI configuration registers.
Bart Van Assche2db62282018-01-23 16:33:51 -08002170 * @vha: HA context
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002171 *
2172 * Returns 0 on success.
2173 */
2174int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002175qla24xx_pci_config(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002176{
Andrew Vasqueza157b102007-05-07 07:43:01 -07002177 uint16_t w;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002178 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002179 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002180 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002181
2182 pci_set_master(ha->pdev);
Andrew Vasquezaf6177d2007-07-19 15:06:02 -07002183 pci_try_set_mwi(ha->pdev);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002184
2185 pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
Andrew Vasqueza157b102007-05-07 07:43:01 -07002186 w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002187 w &= ~PCI_COMMAND_INTX_DISABLE;
2188 pci_write_config_word(ha->pdev, PCI_COMMAND, w);
2189
2190 pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
2191
2192 /* PCI-X -- adjust Maximum Memory Read Byte Count (2048). */
Andrew Vasquezf85ec182007-07-19 15:06:01 -07002193 if (pci_find_capability(ha->pdev, PCI_CAP_ID_PCIX))
2194 pcix_set_mmrbc(ha->pdev, 2048);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002195
2196 /* PCIe -- adjust Maximum Read Request Size (2048). */
Jon Masone67f1322012-07-10 14:57:56 -07002197 if (pci_is_pcie(ha->pdev))
Chad Dupuis5ffd3a52012-08-22 14:21:26 -04002198 pcie_set_readrq(ha->pdev, 4096);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002199
Andrew Vasquez737faec2008-10-24 15:13:45 -07002200 pci_disable_rom(ha->pdev);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002201
Auke Kok44c10132007-06-08 15:46:36 -07002202 ha->chip_revision = ha->pdev->revision;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08002203
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002204 /* Get PCI bus information. */
2205 spin_lock_irqsave(&ha->hardware_lock, flags);
2206 ha->pci_attr = RD_REG_DWORD(&reg->ctrl_status);
2207 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2208
2209 return QLA_SUCCESS;
2210}
2211
2212/**
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07002213 * qla25xx_pci_config() - Setup ISP25xx PCI configuration registers.
Bart Van Assche2db62282018-01-23 16:33:51 -08002214 * @vha: HA context
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07002215 *
2216 * Returns 0 on success.
2217 */
2218int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002219qla25xx_pci_config(scsi_qla_host_t *vha)
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07002220{
2221 uint16_t w;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002222 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07002223
2224 pci_set_master(ha->pdev);
2225 pci_try_set_mwi(ha->pdev);
2226
2227 pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
2228 w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
2229 w &= ~PCI_COMMAND_INTX_DISABLE;
2230 pci_write_config_word(ha->pdev, PCI_COMMAND, w);
2231
2232 /* PCIe -- adjust Maximum Read Request Size (2048). */
Jon Masone67f1322012-07-10 14:57:56 -07002233 if (pci_is_pcie(ha->pdev))
Chad Dupuis5ffd3a52012-08-22 14:21:26 -04002234 pcie_set_readrq(ha->pdev, 4096);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07002235
Andrew Vasquez737faec2008-10-24 15:13:45 -07002236 pci_disable_rom(ha->pdev);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07002237
2238 ha->chip_revision = ha->pdev->revision;
2239
2240 return QLA_SUCCESS;
2241}
2242
2243/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 * qla2x00_isp_firmware() - Choose firmware image.
Bart Van Assche2db62282018-01-23 16:33:51 -08002245 * @vha: HA context
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 *
2247 * Returns 0 on success.
2248 */
2249static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002250qla2x00_isp_firmware(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251{
2252 int rval;
Andrew Vasquez42e421b2008-07-10 16:56:01 -07002253 uint16_t loop_id, topo, sw_cap;
2254 uint8_t domain, area, al_pa;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002255 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256
2257 /* Assume loading risc code */
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07002258 rval = QLA_FUNCTION_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259
2260 if (ha->flags.disable_risc_code_load) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002261 ql_log(ql_log_info, vha, 0x0079, "RISC CODE NOT loaded.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262
2263 /* Verify checksum of loaded RISC code. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002264 rval = qla2x00_verify_checksum(vha, ha->fw_srisc_address);
Andrew Vasquez42e421b2008-07-10 16:56:01 -07002265 if (rval == QLA_SUCCESS) {
2266 /* And, verify we are not in ROM code. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002267 rval = qla2x00_get_adapter_id(vha, &loop_id, &al_pa,
Andrew Vasquez42e421b2008-07-10 16:56:01 -07002268 &area, &domain, &topo, &sw_cap);
2269 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 }
2271
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002272 if (rval)
2273 ql_dbg(ql_dbg_init, vha, 0x007a,
2274 "**** Load RISC code ****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275
2276 return (rval);
2277}
2278
2279/**
2280 * qla2x00_reset_chip() - Reset ISP chip.
Bart Van Assche2db62282018-01-23 16:33:51 -08002281 * @vha: HA context
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 *
2283 * Returns 0 on success.
2284 */
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002285void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002286qla2x00_reset_chip(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287{
2288 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002289 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07002290 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 uint32_t cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 uint16_t cmd;
2293
Andrew Vasquez85880802009-12-15 21:29:46 -08002294 if (unlikely(pci_channel_offline(ha->pdev)))
2295 return;
2296
Andrew Vasquezfd34f552007-07-19 15:06:00 -07002297 ha->isp_ops->disable_intrs(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298
2299 spin_lock_irqsave(&ha->hardware_lock, flags);
2300
2301 /* Turn off master enable */
2302 cmd = 0;
2303 pci_read_config_word(ha->pdev, PCI_COMMAND, &cmd);
2304 cmd &= ~PCI_COMMAND_MASTER;
2305 pci_write_config_word(ha->pdev, PCI_COMMAND, cmd);
2306
2307 if (!IS_QLA2100(ha)) {
2308 /* Pause RISC. */
2309 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
2310 if (IS_QLA2200(ha) || IS_QLA2300(ha)) {
2311 for (cnt = 0; cnt < 30000; cnt++) {
2312 if ((RD_REG_WORD(&reg->hccr) &
2313 HCCR_RISC_PAUSE) != 0)
2314 break;
2315 udelay(100);
2316 }
2317 } else {
2318 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
2319 udelay(10);
2320 }
2321
2322 /* Select FPM registers. */
2323 WRT_REG_WORD(&reg->ctrl_status, 0x20);
2324 RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
2325
2326 /* FPM Soft Reset. */
2327 WRT_REG_WORD(&reg->fpm_diag_config, 0x100);
2328 RD_REG_WORD(&reg->fpm_diag_config); /* PCI Posting. */
2329
2330 /* Toggle Fpm Reset. */
2331 if (!IS_QLA2200(ha)) {
2332 WRT_REG_WORD(&reg->fpm_diag_config, 0x0);
2333 RD_REG_WORD(&reg->fpm_diag_config); /* PCI Posting. */
2334 }
2335
2336 /* Select frame buffer registers. */
2337 WRT_REG_WORD(&reg->ctrl_status, 0x10);
2338 RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
2339
2340 /* Reset frame buffer FIFOs. */
2341 if (IS_QLA2200(ha)) {
2342 WRT_FB_CMD_REG(ha, reg, 0xa000);
2343 RD_FB_CMD_REG(ha, reg); /* PCI Posting. */
2344 } else {
2345 WRT_FB_CMD_REG(ha, reg, 0x00fc);
2346
2347 /* Read back fb_cmd until zero or 3 seconds max */
2348 for (cnt = 0; cnt < 3000; cnt++) {
2349 if ((RD_FB_CMD_REG(ha, reg) & 0xff) == 0)
2350 break;
2351 udelay(100);
2352 }
2353 }
2354
2355 /* Select RISC module registers. */
2356 WRT_REG_WORD(&reg->ctrl_status, 0);
2357 RD_REG_WORD(&reg->ctrl_status); /* PCI Posting. */
2358
2359 /* Reset RISC processor. */
2360 WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
2361 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
2362
2363 /* Release RISC processor. */
2364 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
2365 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
2366 }
2367
2368 WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
2369 WRT_REG_WORD(&reg->hccr, HCCR_CLR_HOST_INT);
2370
2371 /* Reset ISP chip. */
2372 WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
2373
2374 /* Wait for RISC to recover from reset. */
2375 if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
2376 /*
2377 * It is necessary to for a delay here since the card doesn't
2378 * respond to PCI reads during a reset. On some architectures
2379 * this will result in an MCA.
2380 */
2381 udelay(20);
2382 for (cnt = 30000; cnt; cnt--) {
2383 if ((RD_REG_WORD(&reg->ctrl_status) &
2384 CSR_ISP_SOFT_RESET) == 0)
2385 break;
2386 udelay(100);
2387 }
2388 } else
2389 udelay(10);
2390
2391 /* Reset RISC processor. */
2392 WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
2393
2394 WRT_REG_WORD(&reg->semaphore, 0);
2395
2396 /* Release RISC processor. */
2397 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
2398 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
2399
2400 if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
2401 for (cnt = 0; cnt < 30000; cnt++) {
Andrew Vasquezffb39f02006-05-17 15:09:06 -07002402 if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404
2405 udelay(100);
2406 }
2407 } else
2408 udelay(100);
2409
2410 /* Turn on master enable */
2411 cmd |= PCI_COMMAND_MASTER;
2412 pci_write_config_word(ha->pdev, PCI_COMMAND, cmd);
2413
2414 /* Disable RISC pause on FPM parity error. */
2415 if (!IS_QLA2100(ha)) {
2416 WRT_REG_WORD(&reg->hccr, HCCR_DISABLE_PARITY_PAUSE);
2417 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
2418 }
2419
2420 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2421}
2422
2423/**
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07002424 * qla81xx_reset_mpi() - Reset's MPI FW via Write MPI Register MBC.
Bart Van Assche2db62282018-01-23 16:33:51 -08002425 * @vha: HA context
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07002426 *
2427 * Returns 0 on success.
2428 */
Saurav Kashyapfa492632012-11-21 02:40:29 -05002429static int
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07002430qla81xx_reset_mpi(scsi_qla_host_t *vha)
2431{
2432 uint16_t mb[4] = {0x1010, 0, 1, 0};
2433
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08002434 if (!IS_QLA81XX(vha->hw))
2435 return QLA_SUCCESS;
2436
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07002437 return qla81xx_write_mpi_register(vha, mb);
2438}
2439
2440/**
Andrew Vasquez88c26662005-07-08 17:59:26 -07002441 * qla24xx_reset_risc() - Perform full reset of ISP24xx RISC.
Bart Van Assche2db62282018-01-23 16:33:51 -08002442 * @vha: HA context
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002443 *
2444 * Returns 0 on success.
2445 */
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002446static inline int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002447qla24xx_reset_risc(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002448{
2449 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002450 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002451 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
Bart Van Assche52c82822015-07-09 07:23:26 -07002452 uint32_t cnt;
Andrew Vasquez335a1cc2005-11-08 14:37:48 -08002453 uint16_t wd;
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07002454 static int abts_cnt; /* ISP abort retry counts */
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002455 int rval = QLA_SUCCESS;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002456
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002457 spin_lock_irqsave(&ha->hardware_lock, flags);
2458
2459 /* Reset RISC. */
2460 WRT_REG_DWORD(&reg->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
2461 for (cnt = 0; cnt < 30000; cnt++) {
2462 if ((RD_REG_DWORD(&reg->ctrl_status) & CSRX_DMA_ACTIVE) == 0)
2463 break;
2464
2465 udelay(10);
2466 }
2467
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002468 if (!(RD_REG_DWORD(&reg->ctrl_status) & CSRX_DMA_ACTIVE))
2469 set_bit(DMA_SHUTDOWN_CMPL, &ha->fw_dump_cap_flags);
2470
2471 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x017e,
2472 "HCCR: 0x%x, Control Status %x, DMA active status:0x%x\n",
2473 RD_REG_DWORD(&reg->hccr),
2474 RD_REG_DWORD(&reg->ctrl_status),
2475 (RD_REG_DWORD(&reg->ctrl_status) & CSRX_DMA_ACTIVE));
2476
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002477 WRT_REG_DWORD(&reg->ctrl_status,
2478 CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
Andrew Vasquez335a1cc2005-11-08 14:37:48 -08002479 pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
Andrew Vasquez88c26662005-07-08 17:59:26 -07002480
Andrew Vasquez335a1cc2005-11-08 14:37:48 -08002481 udelay(100);
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002482
Andrew Vasquez88c26662005-07-08 17:59:26 -07002483 /* Wait for firmware to complete NVRAM accesses. */
Bart Van Assche52c82822015-07-09 07:23:26 -07002484 RD_REG_WORD(&reg->mailbox0);
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002485 for (cnt = 10000; RD_REG_WORD(&reg->mailbox0) != 0 &&
2486 rval == QLA_SUCCESS; cnt--) {
Andrew Vasquez88c26662005-07-08 17:59:26 -07002487 barrier();
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002488 if (cnt)
2489 udelay(5);
2490 else
2491 rval = QLA_FUNCTION_TIMEOUT;
Andrew Vasquez88c26662005-07-08 17:59:26 -07002492 }
2493
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002494 if (rval == QLA_SUCCESS)
2495 set_bit(ISP_MBX_RDY, &ha->fw_dump_cap_flags);
2496
2497 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x017f,
2498 "HCCR: 0x%x, MailBox0 Status 0x%x\n",
2499 RD_REG_DWORD(&reg->hccr),
2500 RD_REG_DWORD(&reg->mailbox0));
2501
Andrew Vasquez335a1cc2005-11-08 14:37:48 -08002502 /* Wait for soft-reset to complete. */
Bart Van Assche52c82822015-07-09 07:23:26 -07002503 RD_REG_DWORD(&reg->ctrl_status);
Quinn Tran200ffb12016-12-23 18:06:12 -08002504 for (cnt = 0; cnt < 60; cnt++) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002505 barrier();
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002506 if ((RD_REG_DWORD(&reg->ctrl_status) &
2507 CSRX_ISP_SOFT_RESET) == 0)
2508 break;
2509
2510 udelay(5);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002511 }
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002512 if (!(RD_REG_DWORD(&reg->ctrl_status) & CSRX_ISP_SOFT_RESET))
2513 set_bit(ISP_SOFT_RESET_CMPL, &ha->fw_dump_cap_flags);
2514
2515 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x015d,
2516 "HCCR: 0x%x, Soft Reset status: 0x%x\n",
2517 RD_REG_DWORD(&reg->hccr),
2518 RD_REG_DWORD(&reg->ctrl_status));
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002519
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -07002520 /* If required, do an MPI FW reset now */
2521 if (test_and_clear_bit(MPI_RESET_NEEDED, &vha->dpc_flags)) {
2522 if (qla81xx_reset_mpi(vha) != QLA_SUCCESS) {
2523 if (++abts_cnt < 5) {
2524 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
2525 set_bit(MPI_RESET_NEEDED, &vha->dpc_flags);
2526 } else {
2527 /*
2528 * We exhausted the ISP abort retries. We have to
2529 * set the board offline.
2530 */
2531 abts_cnt = 0;
2532 vha->flags.online = 0;
2533 }
2534 }
2535 }
2536
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002537 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
2538 RD_REG_DWORD(&reg->hccr);
2539
2540 WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
2541 RD_REG_DWORD(&reg->hccr);
2542
2543 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_RESET);
2544 RD_REG_DWORD(&reg->hccr);
2545
Bart Van Assche52c82822015-07-09 07:23:26 -07002546 RD_REG_WORD(&reg->mailbox0);
Quinn Tran200ffb12016-12-23 18:06:12 -08002547 for (cnt = 60; RD_REG_WORD(&reg->mailbox0) != 0 &&
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002548 rval == QLA_SUCCESS; cnt--) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002549 barrier();
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002550 if (cnt)
2551 udelay(5);
2552 else
2553 rval = QLA_FUNCTION_TIMEOUT;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002554 }
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002555 if (rval == QLA_SUCCESS)
2556 set_bit(RISC_RDY_AFT_RESET, &ha->fw_dump_cap_flags);
2557
2558 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x015e,
2559 "Host Risc 0x%x, mailbox0 0x%x\n",
2560 RD_REG_DWORD(&reg->hccr),
2561 RD_REG_WORD(&reg->mailbox0));
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002562
2563 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Andrew Vasquez124f85e2009-01-05 11:18:06 -08002564
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002565 ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x015f,
2566 "Driver in %s mode\n",
2567 IS_NOPOLLING_TYPE(ha) ? "Interrupt" : "Polling");
2568
Andrew Vasquez124f85e2009-01-05 11:18:06 -08002569 if (IS_NOPOLLING_TYPE(ha))
2570 ha->isp_ops->enable_intrs(ha);
Himanshu Madhanid14e72f2015-04-09 15:00:03 -04002571
2572 return rval;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002573}
2574
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05002575static void
2576qla25xx_read_risc_sema_reg(scsi_qla_host_t *vha, uint32_t *data)
2577{
2578 struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;
2579
2580 WRT_REG_DWORD(&reg->iobase_addr, RISC_REGISTER_BASE_OFFSET);
2581 *data = RD_REG_DWORD(&reg->iobase_window + RISC_REGISTER_WINDOW_OFFET);
2582
2583}
2584
2585static void
2586qla25xx_write_risc_sema_reg(scsi_qla_host_t *vha, uint32_t data)
2587{
2588 struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;
2589
2590 WRT_REG_DWORD(&reg->iobase_addr, RISC_REGISTER_BASE_OFFSET);
2591 WRT_REG_DWORD(&reg->iobase_window + RISC_REGISTER_WINDOW_OFFET, data);
2592}
2593
2594static void
2595qla25xx_manipulate_risc_semaphore(scsi_qla_host_t *vha)
2596{
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05002597 uint32_t wd32 = 0;
2598 uint delta_msec = 100;
2599 uint elapsed_msec = 0;
2600 uint timeout_msec;
2601 ulong n;
2602
Joe Carnucciocc790762015-08-04 13:37:53 -04002603 if (vha->hw->pdev->subsystem_device != 0x0175 &&
2604 vha->hw->pdev->subsystem_device != 0x0240)
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05002605 return;
2606
Joe Carnuccio8dd7e3a2015-08-04 13:37:54 -04002607 WRT_REG_DWORD(&vha->hw->iobase->isp24.hccr, HCCRX_SET_RISC_PAUSE);
2608 udelay(100);
2609
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05002610attempt:
2611 timeout_msec = TIMEOUT_SEMAPHORE;
2612 n = timeout_msec / delta_msec;
2613 while (n--) {
2614 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_SET);
2615 qla25xx_read_risc_sema_reg(vha, &wd32);
2616 if (wd32 & RISC_SEMAPHORE)
2617 break;
2618 msleep(delta_msec);
2619 elapsed_msec += delta_msec;
2620 if (elapsed_msec > TIMEOUT_TOTAL_ELAPSED)
2621 goto force;
2622 }
2623
2624 if (!(wd32 & RISC_SEMAPHORE))
2625 goto force;
2626
2627 if (!(wd32 & RISC_SEMAPHORE_FORCE))
2628 goto acquired;
2629
2630 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_CLR);
2631 timeout_msec = TIMEOUT_SEMAPHORE_FORCE;
2632 n = timeout_msec / delta_msec;
2633 while (n--) {
2634 qla25xx_read_risc_sema_reg(vha, &wd32);
2635 if (!(wd32 & RISC_SEMAPHORE_FORCE))
2636 break;
2637 msleep(delta_msec);
2638 elapsed_msec += delta_msec;
2639 if (elapsed_msec > TIMEOUT_TOTAL_ELAPSED)
2640 goto force;
2641 }
2642
2643 if (wd32 & RISC_SEMAPHORE_FORCE)
2644 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_FORCE_CLR);
2645
2646 goto attempt;
2647
2648force:
2649 qla25xx_write_risc_sema_reg(vha, RISC_SEMAPHORE_FORCE_SET);
2650
2651acquired:
2652 return;
2653}
2654
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002655/**
Andrew Vasquez88c26662005-07-08 17:59:26 -07002656 * qla24xx_reset_chip() - Reset ISP24xx chip.
Bart Van Assche2db62282018-01-23 16:33:51 -08002657 * @vha: HA context
Andrew Vasquez88c26662005-07-08 17:59:26 -07002658 *
2659 * Returns 0 on success.
2660 */
2661void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002662qla24xx_reset_chip(scsi_qla_host_t *vha)
Andrew Vasquez88c26662005-07-08 17:59:26 -07002663{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002664 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez85880802009-12-15 21:29:46 -08002665
2666 if (pci_channel_offline(ha->pdev) &&
2667 ha->flags.pci_channel_io_perm_failure) {
2668 return;
2669 }
2670
Andrew Vasquezfd34f552007-07-19 15:06:00 -07002671 ha->isp_ops->disable_intrs(ha);
Andrew Vasquez88c26662005-07-08 17:59:26 -07002672
Joe Carnuccio4ea2c9c2012-11-21 02:40:37 -05002673 qla25xx_manipulate_risc_semaphore(vha);
2674
Andrew Vasquez88c26662005-07-08 17:59:26 -07002675 /* Perform RISC reset. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002676 qla24xx_reset_risc(vha);
Andrew Vasquez88c26662005-07-08 17:59:26 -07002677}
2678
2679/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 * qla2x00_chip_diag() - Test chip for proper operation.
Bart Van Assche2db62282018-01-23 16:33:51 -08002681 * @vha: HA context
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 *
2683 * Returns 0 on success.
2684 */
Andrew Vasquezabbd8872005-07-06 10:30:05 -07002685int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002686qla2x00_chip_diag(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687{
2688 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002689 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07002690 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 unsigned long flags = 0;
2692 uint16_t data;
2693 uint32_t cnt;
2694 uint16_t mb[5];
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002695 struct req_que *req = ha->req_q_map[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696
2697 /* Assume a failed state */
2698 rval = QLA_FUNCTION_FAILED;
2699
Bart Van Asscheda4704d2018-01-23 16:33:47 -08002700 ql_dbg(ql_dbg_init, vha, 0x007b, "Testing device at %p.\n",
2701 &reg->flash_address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702
2703 spin_lock_irqsave(&ha->hardware_lock, flags);
2704
2705 /* Reset ISP chip. */
2706 WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
2707
2708 /*
2709 * We need to have a delay here since the card will not respond while
2710 * in reset causing an MCA on some architectures.
2711 */
2712 udelay(20);
2713 data = qla2x00_debounce_register(&reg->ctrl_status);
2714 for (cnt = 6000000 ; cnt && (data & CSR_ISP_SOFT_RESET); cnt--) {
2715 udelay(5);
2716 data = RD_REG_WORD(&reg->ctrl_status);
2717 barrier();
2718 }
2719
2720 if (!cnt)
2721 goto chip_diag_failed;
2722
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002723 ql_dbg(ql_dbg_init, vha, 0x007c,
2724 "Reset register cleared by chip reset.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725
2726 /* Reset RISC processor. */
2727 WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
2728 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
2729
2730 /* Workaround for QLA2312 PCI parity error */
2731 if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
2732 data = qla2x00_debounce_register(MAILBOX_REG(ha, reg, 0));
2733 for (cnt = 6000000; cnt && (data == MBS_BUSY); cnt--) {
2734 udelay(5);
2735 data = RD_MAILBOX_REG(ha, reg, 0);
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07002736 barrier();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 }
2738 } else
2739 udelay(10);
2740
2741 if (!cnt)
2742 goto chip_diag_failed;
2743
2744 /* Check product ID of chip */
Milan P Gandhi5a68a1c2017-03-31 14:37:04 -07002745 ql_dbg(ql_dbg_init, vha, 0x007d, "Checking product ID of chip.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746
2747 mb[1] = RD_MAILBOX_REG(ha, reg, 1);
2748 mb[2] = RD_MAILBOX_REG(ha, reg, 2);
2749 mb[3] = RD_MAILBOX_REG(ha, reg, 3);
2750 mb[4] = qla2x00_debounce_register(MAILBOX_REG(ha, reg, 4));
2751 if (mb[1] != PROD_ID_1 || (mb[2] != PROD_ID_2 && mb[2] != PROD_ID_2a) ||
2752 mb[3] != PROD_ID_3) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002753 ql_log(ql_log_warn, vha, 0x0062,
2754 "Wrong product ID = 0x%x,0x%x,0x%x.\n",
2755 mb[1], mb[2], mb[3]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756
2757 goto chip_diag_failed;
2758 }
2759 ha->product_id[0] = mb[1];
2760 ha->product_id[1] = mb[2];
2761 ha->product_id[2] = mb[3];
2762 ha->product_id[3] = mb[4];
2763
2764 /* Adjust fw RISC transfer size */
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002765 if (req->length > 1024)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 ha->fw_transfer_size = REQUEST_ENTRY_SIZE * 1024;
2767 else
2768 ha->fw_transfer_size = REQUEST_ENTRY_SIZE *
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002769 req->length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770
2771 if (IS_QLA2200(ha) &&
2772 RD_MAILBOX_REG(ha, reg, 7) == QLA2200A_RISC_ROM_VER) {
2773 /* Limit firmware transfer size with a 2200A */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002774 ql_dbg(ql_dbg_init, vha, 0x007e, "Found QLA2200A Chip.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775
andrew.vasquez@qlogic.comea5b6382006-03-09 14:27:08 -08002776 ha->device_type |= DT_ISP2200A;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777 ha->fw_transfer_size = 128;
2778 }
2779
2780 /* Wrap Incoming Mailboxes Test. */
2781 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2782
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002783 ql_dbg(ql_dbg_init, vha, 0x007f, "Checking mailboxes.\n");
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002784 rval = qla2x00_mbx_reg_test(vha);
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002785 if (rval)
2786 ql_log(ql_log_warn, vha, 0x0080,
2787 "Failed mailbox send register test.\n");
2788 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 /* Flag a successful rval */
2790 rval = QLA_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 spin_lock_irqsave(&ha->hardware_lock, flags);
2792
2793chip_diag_failed:
2794 if (rval)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002795 ql_log(ql_log_info, vha, 0x0081,
2796 "Chip diagnostics **** FAILED ****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
2798 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2799
2800 return (rval);
2801}
2802
2803/**
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002804 * qla24xx_chip_diag() - Test ISP24xx for proper operation.
Bart Van Assche2db62282018-01-23 16:33:51 -08002805 * @vha: HA context
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002806 *
2807 * Returns 0 on success.
2808 */
2809int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002810qla24xx_chip_diag(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002811{
2812 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002813 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002814 struct req_que *req = ha->req_q_map[0];
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002815
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04002816 if (IS_P3P_TYPE(ha))
Giridhar Malavalia9083012010-04-12 17:59:55 -07002817 return QLA_SUCCESS;
2818
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002819 ha->fw_transfer_size = REQUEST_ENTRY_SIZE * req->length;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002820
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002821 rval = qla2x00_mbx_reg_test(vha);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002822 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002823 ql_log(ql_log_warn, vha, 0x0082,
2824 "Failed mailbox send register test.\n");
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002825 } else {
2826 /* Flag a successful rval */
2827 rval = QLA_SUCCESS;
2828 }
2829
2830 return rval;
2831}
2832
Quinn Tranad0a0b02017-12-28 12:33:14 -08002833static void
2834qla2x00_alloc_offload_mem(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07002835{
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002836 int rval;
Andrew Vasquezdf613b92008-01-17 09:02:17 -08002837 dma_addr_t tc_dma;
2838 void *tc;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002839 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezd4e3e042006-05-17 15:09:50 -07002840
Quinn Tranad0a0b02017-12-28 12:33:14 -08002841 if (ha->eft) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002842 ql_dbg(ql_dbg_init, vha, 0x00bd,
Quinn Tranad0a0b02017-12-28 12:33:14 -08002843 "%s: Offload Mem is already allocated.\n",
2844 __func__);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002845 return;
Andrew Vasquezd4e3e042006-05-17 15:09:50 -07002846 }
2847
Quinn Tranad0a0b02017-12-28 12:33:14 -08002848 if (IS_FWI2_CAPABLE(ha)) {
2849 /* Allocate memory for Fibre Channel Event Buffer. */
2850 if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
2851 !IS_QLA27XX(ha))
2852 goto try_eft;
2853
2854 if (ha->fce)
2855 dma_free_coherent(&ha->pdev->dev,
2856 FCE_SIZE, ha->fce, ha->fce_dma);
2857
2858 /* Allocate memory for Fibre Channel Event Buffer. */
2859 tc = dma_zalloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
2860 GFP_KERNEL);
2861 if (!tc) {
2862 ql_log(ql_log_warn, vha, 0x00be,
2863 "Unable to allocate (%d KB) for FCE.\n",
2864 FCE_SIZE / 1024);
2865 goto try_eft;
2866 }
2867
2868 rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS,
2869 ha->fce_mb, &ha->fce_bufs);
2870 if (rval) {
2871 ql_log(ql_log_warn, vha, 0x00bf,
2872 "Unable to initialize FCE (%d).\n", rval);
2873 dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc,
2874 tc_dma);
2875 ha->flags.fce_enabled = 0;
2876 goto try_eft;
2877 }
2878 ql_dbg(ql_dbg_init, vha, 0x00c0,
2879 "Allocate (%d KB) for FCE...\n", FCE_SIZE / 1024);
2880
2881 ha->flags.fce_enabled = 1;
2882 ha->fce_dma = tc_dma;
2883 ha->fce = tc;
2884
2885try_eft:
2886 if (ha->eft)
2887 dma_free_coherent(&ha->pdev->dev,
2888 EFT_SIZE, ha->eft, ha->eft_dma);
2889
2890 /* Allocate memory for Extended Trace Buffer. */
2891 tc = dma_zalloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
2892 GFP_KERNEL);
2893 if (!tc) {
2894 ql_log(ql_log_warn, vha, 0x00c1,
2895 "Unable to allocate (%d KB) for EFT.\n",
2896 EFT_SIZE / 1024);
2897 goto eft_err;
2898 }
2899
2900 rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
2901 if (rval) {
2902 ql_log(ql_log_warn, vha, 0x00c2,
2903 "Unable to initialize EFT (%d).\n", rval);
2904 dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc,
2905 tc_dma);
2906 goto eft_err;
2907 }
2908 ql_dbg(ql_dbg_init, vha, 0x00c3,
2909 "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
2910
2911 ha->eft_dma = tc_dma;
2912 ha->eft = tc;
2913 }
2914
2915eft_err:
2916 return;
2917}
2918
2919void
2920qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
2921{
2922 uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size,
2923 eft_size, fce_size, mq_size;
2924 struct qla_hw_data *ha = vha->hw;
2925 struct req_que *req = ha->req_q_map[0];
2926 struct rsp_que *rsp = ha->rsp_q_map[0];
2927 struct qla2xxx_fw_dump *fw_dump;
2928
Chad Dupuisf73cb692014-02-26 04:15:06 -05002929 dump_size = fixed_size = mem_size = eft_size = fce_size = mq_size = 0;
2930 req_q_size = rsp_q_size = 0;
2931
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002932 if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
2933 fixed_size = sizeof(struct qla2100_fw_dump);
2934 } else if (IS_QLA23XX(ha)) {
2935 fixed_size = offsetof(struct qla2300_fw_dump, data_ram);
2936 mem_size = (ha->fw_memory_size - 0x11000 + 1) *
2937 sizeof(uint16_t);
Andrew Vasqueze4289242007-07-19 15:05:56 -07002938 } else if (IS_FWI2_CAPABLE(ha)) {
Himanshu Madhanib20f02e2015-06-10 11:05:18 -04002939 if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08002940 fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem);
2941 else if (IS_QLA81XX(ha))
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08002942 fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem);
2943 else if (IS_QLA25XX(ha))
2944 fixed_size = offsetof(struct qla25xx_fw_dump, ext_mem);
2945 else
2946 fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem);
Chad Dupuisf73cb692014-02-26 04:15:06 -05002947
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002948 mem_size = (ha->fw_memory_size - 0x100000 + 1) *
2949 sizeof(uint32_t);
Giridhar Malavali050c9bb2012-02-09 11:15:33 -08002950 if (ha->mqenable) {
Himanshu Madhanib20f02e2015-06-10 11:05:18 -04002951 if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08002952 mq_size = sizeof(struct qla2xxx_mq_chain);
Giridhar Malavali050c9bb2012-02-09 11:15:33 -08002953 /*
2954 * Allocate maximum buffer size for all queues.
2955 * Resizing must be done at end-of-dump processing.
2956 */
2957 mq_size += ha->max_req_queues *
2958 (req->length * sizeof(request_t));
2959 mq_size += ha->max_rsp_queues *
2960 (rsp->length * sizeof(response_t));
2961 }
Arun Easi00876ae2013-03-25 02:21:37 -04002962 if (ha->tgt.atio_ring)
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002963 mq_size += ha->tgt.atio_q_length * sizeof(request_t);
Andrew Vasquez436a7b12008-07-10 16:55:54 -07002964 /* Allocate memory for Fibre Channel Event Buffer. */
Chad Dupuisf73cb692014-02-26 04:15:06 -05002965 if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
2966 !IS_QLA27XX(ha))
Andrew Vasquez436a7b12008-07-10 16:55:54 -07002967 goto try_eft;
2968
Giridhar Malavali7d9dade2009-03-24 09:07:58 -07002969 fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
Andrew Vasquez436a7b12008-07-10 16:55:54 -07002970try_eft:
Chad Dupuiscfb09192011-11-18 09:03:07 -08002971 ql_dbg(ql_dbg_init, vha, 0x00c3,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002972 "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002973 eft_size = EFT_SIZE;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002974 }
Chad Dupuisf73cb692014-02-26 04:15:06 -05002975
Chad Dupuisf73cb692014-02-26 04:15:06 -05002976 if (IS_QLA27XX(ha)) {
2977 if (!ha->fw_dump_template) {
2978 ql_log(ql_log_warn, vha, 0x00ba,
2979 "Failed missing fwdump template\n");
2980 return;
2981 }
2982 dump_size = qla27xx_fwdt_calculate_dump_size(vha);
2983 ql_dbg(ql_dbg_init, vha, 0x00fa,
2984 "-> allocating fwdump (%x bytes)...\n", dump_size);
2985 goto allocate;
2986 }
2987
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002988 req_q_size = req->length * sizeof(request_t);
2989 rsp_q_size = rsp->length * sizeof(response_t);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002990 dump_size = offsetof(struct qla2xxx_fw_dump, isp);
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002991 dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + eft_size;
Andrew Vasquezbb99de62009-01-05 11:18:08 -08002992 ha->chain_offset = dump_size;
2993 dump_size += mq_size + fce_size;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07002994
Quinn Tranb945e772017-06-13 20:47:29 -07002995 if (ha->exchoffld_buf)
2996 dump_size += sizeof(struct qla2xxx_offld_chain) +
2997 ha->exchoffld_size;
2998 if (ha->exlogin_buf)
2999 dump_size += sizeof(struct qla2xxx_offld_chain) +
3000 ha->exlogin_size;
3001
Chad Dupuisf73cb692014-02-26 04:15:06 -05003002allocate:
Quinn Tranad0a0b02017-12-28 12:33:14 -08003003 if (!ha->fw_dump_len || dump_size != ha->fw_dump_len) {
3004 fw_dump = vmalloc(dump_size);
3005 if (!fw_dump) {
3006 ql_log(ql_log_warn, vha, 0x00c4,
3007 "Unable to allocate (%d KB) for firmware dump.\n",
3008 dump_size / 1024);
3009 } else {
3010 if (ha->fw_dump)
3011 vfree(ha->fw_dump);
3012 ha->fw_dump = fw_dump;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07003013
Quinn Tranad0a0b02017-12-28 12:33:14 -08003014 ha->fw_dump_len = dump_size;
3015 ql_dbg(ql_dbg_init, vha, 0x00c5,
3016 "Allocated (%d KB) for firmware dump.\n",
3017 dump_size / 1024);
Madhuranath Iyengare30d1752010-10-15 11:27:46 -07003018
Quinn Tranad0a0b02017-12-28 12:33:14 -08003019 if (IS_QLA27XX(ha))
3020 return;
3021
3022 ha->fw_dump->signature[0] = 'Q';
3023 ha->fw_dump->signature[1] = 'L';
3024 ha->fw_dump->signature[2] = 'G';
3025 ha->fw_dump->signature[3] = 'C';
3026 ha->fw_dump->version = htonl(1);
3027
3028 ha->fw_dump->fixed_size = htonl(fixed_size);
3029 ha->fw_dump->mem_size = htonl(mem_size);
3030 ha->fw_dump->req_q_size = htonl(req_q_size);
3031 ha->fw_dump->rsp_q_size = htonl(rsp_q_size);
3032
3033 ha->fw_dump->eft_size = htonl(eft_size);
3034 ha->fw_dump->eft_addr_l = htonl(LSD(ha->eft_dma));
3035 ha->fw_dump->eft_addr_h = htonl(MSD(ha->eft_dma));
3036
3037 ha->fw_dump->header_size =
3038 htonl(offsetof(struct qla2xxx_fw_dump, isp));
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07003039 }
Andrew Vasqueza7a167b2006-06-23 16:10:29 -07003040 }
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003041}
3042
Andrew Vasquez18e75552009-06-03 09:55:30 -07003043static int
3044qla81xx_mpi_sync(scsi_qla_host_t *vha)
3045{
3046#define MPS_MASK 0xe0
3047 int rval;
3048 uint16_t dc;
3049 uint32_t dw;
Andrew Vasquez18e75552009-06-03 09:55:30 -07003050
3051 if (!IS_QLA81XX(vha->hw))
3052 return QLA_SUCCESS;
3053
3054 rval = qla2x00_write_ram_word(vha, 0x7c00, 1);
3055 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003056 ql_log(ql_log_warn, vha, 0x0105,
3057 "Unable to acquire semaphore.\n");
Andrew Vasquez18e75552009-06-03 09:55:30 -07003058 goto done;
3059 }
3060
3061 pci_read_config_word(vha->hw->pdev, 0x54, &dc);
3062 rval = qla2x00_read_ram_word(vha, 0x7a15, &dw);
3063 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003064 ql_log(ql_log_warn, vha, 0x0067, "Unable to read sync.\n");
Andrew Vasquez18e75552009-06-03 09:55:30 -07003065 goto done_release;
3066 }
3067
3068 dc &= MPS_MASK;
3069 if (dc == (dw & MPS_MASK))
3070 goto done_release;
3071
3072 dw &= ~MPS_MASK;
3073 dw |= dc;
3074 rval = qla2x00_write_ram_word(vha, 0x7a15, dw);
3075 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003076 ql_log(ql_log_warn, vha, 0x0114, "Unable to gain sync.\n");
Andrew Vasquez18e75552009-06-03 09:55:30 -07003077 }
3078
3079done_release:
3080 rval = qla2x00_write_ram_word(vha, 0x7c00, 0);
3081 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003082 ql_log(ql_log_warn, vha, 0x006d,
3083 "Unable to release semaphore.\n");
Andrew Vasquez18e75552009-06-03 09:55:30 -07003084 }
3085
3086done:
3087 return rval;
3088}
3089
Chad Dupuis8d93f552013-01-30 03:34:37 -05003090int
3091qla2x00_alloc_outstanding_cmds(struct qla_hw_data *ha, struct req_que *req)
3092{
3093 /* Don't try to reallocate the array */
3094 if (req->outstanding_cmds)
3095 return QLA_SUCCESS;
3096
Michael Hernandezd7459522016-12-12 14:40:07 -08003097 if (!IS_FWI2_CAPABLE(ha))
Chad Dupuis8d93f552013-01-30 03:34:37 -05003098 req->num_outstanding_cmds = DEFAULT_OUTSTANDING_COMMANDS;
3099 else {
Quinn Tran03e8c682015-12-17 14:56:59 -05003100 if (ha->cur_fw_xcb_count <= ha->cur_fw_iocb_count)
3101 req->num_outstanding_cmds = ha->cur_fw_xcb_count;
Chad Dupuis8d93f552013-01-30 03:34:37 -05003102 else
Quinn Tran03e8c682015-12-17 14:56:59 -05003103 req->num_outstanding_cmds = ha->cur_fw_iocb_count;
Chad Dupuis8d93f552013-01-30 03:34:37 -05003104 }
3105
3106 req->outstanding_cmds = kzalloc(sizeof(srb_t *) *
3107 req->num_outstanding_cmds, GFP_KERNEL);
3108
3109 if (!req->outstanding_cmds) {
3110 /*
3111 * Try to allocate a minimal size just so we can get through
3112 * initialization.
3113 */
3114 req->num_outstanding_cmds = MIN_OUTSTANDING_COMMANDS;
3115 req->outstanding_cmds = kzalloc(sizeof(srb_t *) *
3116 req->num_outstanding_cmds, GFP_KERNEL);
3117
3118 if (!req->outstanding_cmds) {
3119 ql_log(ql_log_fatal, NULL, 0x0126,
3120 "Failed to allocate memory for "
3121 "outstanding_cmds for req_que %p.\n", req);
3122 req->num_outstanding_cmds = 0;
3123 return QLA_FUNCTION_FAILED;
3124 }
3125 }
3126
3127 return QLA_SUCCESS;
3128}
3129
Quinn Trane4e3a2c2017-08-23 15:05:07 -07003130#define PRINT_FIELD(_field, _flag, _str) { \
3131 if (a0->_field & _flag) {\
3132 if (p) {\
3133 strcat(ptr, "|");\
3134 ptr++;\
3135 leftover--;\
3136 } \
3137 len = snprintf(ptr, leftover, "%s", _str); \
3138 p = 1;\
3139 leftover -= len;\
3140 ptr += len; \
3141 } \
3142}
3143
3144static void qla2xxx_print_sfp_info(struct scsi_qla_host *vha)
3145{
3146#define STR_LEN 64
3147 struct sff_8247_a0 *a0 = (struct sff_8247_a0 *)vha->hw->sfp_data;
3148 u8 str[STR_LEN], *ptr, p;
3149 int leftover, len;
3150
3151 memset(str, 0, STR_LEN);
3152 snprintf(str, SFF_VEN_NAME_LEN+1, a0->vendor_name);
3153 ql_dbg(ql_dbg_init, vha, 0x015a,
3154 "SFP MFG Name: %s\n", str);
3155
3156 memset(str, 0, STR_LEN);
3157 snprintf(str, SFF_PART_NAME_LEN+1, a0->vendor_pn);
3158 ql_dbg(ql_dbg_init, vha, 0x015c,
3159 "SFP Part Name: %s\n", str);
3160
3161 /* media */
3162 memset(str, 0, STR_LEN);
3163 ptr = str;
3164 leftover = STR_LEN;
3165 p = len = 0;
3166 PRINT_FIELD(fc_med_cc9, FC_MED_TW, "Twin AX");
3167 PRINT_FIELD(fc_med_cc9, FC_MED_TP, "Twisted Pair");
3168 PRINT_FIELD(fc_med_cc9, FC_MED_MI, "Min Coax");
3169 PRINT_FIELD(fc_med_cc9, FC_MED_TV, "Video Coax");
3170 PRINT_FIELD(fc_med_cc9, FC_MED_M6, "MultiMode 62.5um");
3171 PRINT_FIELD(fc_med_cc9, FC_MED_M5, "MultiMode 50um");
3172 PRINT_FIELD(fc_med_cc9, FC_MED_SM, "SingleMode");
3173 ql_dbg(ql_dbg_init, vha, 0x0160,
3174 "SFP Media: %s\n", str);
3175
3176 /* link length */
3177 memset(str, 0, STR_LEN);
3178 ptr = str;
3179 leftover = STR_LEN;
3180 p = len = 0;
3181 PRINT_FIELD(fc_ll_cc7, FC_LL_VL, "Very Long");
3182 PRINT_FIELD(fc_ll_cc7, FC_LL_S, "Short");
3183 PRINT_FIELD(fc_ll_cc7, FC_LL_I, "Intermediate");
3184 PRINT_FIELD(fc_ll_cc7, FC_LL_L, "Long");
3185 PRINT_FIELD(fc_ll_cc7, FC_LL_M, "Medium");
3186 ql_dbg(ql_dbg_init, vha, 0x0196,
3187 "SFP Link Length: %s\n", str);
3188
3189 memset(str, 0, STR_LEN);
3190 ptr = str;
3191 leftover = STR_LEN;
3192 p = len = 0;
3193 PRINT_FIELD(fc_ll_cc7, FC_LL_SA, "Short Wave (SA)");
3194 PRINT_FIELD(fc_ll_cc7, FC_LL_LC, "Long Wave(LC)");
3195 PRINT_FIELD(fc_tec_cc8, FC_TEC_SN, "Short Wave (SN)");
3196 PRINT_FIELD(fc_tec_cc8, FC_TEC_SL, "Short Wave (SL)");
3197 PRINT_FIELD(fc_tec_cc8, FC_TEC_LL, "Long Wave (LL)");
3198 ql_dbg(ql_dbg_init, vha, 0x016e,
3199 "SFP FC Link Tech: %s\n", str);
3200
3201 if (a0->length_km)
3202 ql_dbg(ql_dbg_init, vha, 0x016f,
3203 "SFP Distant: %d km\n", a0->length_km);
3204 if (a0->length_100m)
3205 ql_dbg(ql_dbg_init, vha, 0x0170,
3206 "SFP Distant: %d m\n", a0->length_100m*100);
3207 if (a0->length_50um_10m)
3208 ql_dbg(ql_dbg_init, vha, 0x0189,
3209 "SFP Distant (WL=50um): %d m\n", a0->length_50um_10m * 10);
3210 if (a0->length_62um_10m)
3211 ql_dbg(ql_dbg_init, vha, 0x018a,
3212 "SFP Distant (WL=62.5um): %d m\n", a0->length_62um_10m * 10);
3213 if (a0->length_om4_10m)
3214 ql_dbg(ql_dbg_init, vha, 0x0194,
3215 "SFP Distant (OM4): %d m\n", a0->length_om4_10m * 10);
3216 if (a0->length_om3_10m)
3217 ql_dbg(ql_dbg_init, vha, 0x0195,
3218 "SFP Distant (OM3): %d m\n", a0->length_om3_10m * 10);
3219}
3220
3221
3222/*
3223 * Return Code:
3224 * QLA_SUCCESS: no action
3225 * QLA_INTERFACE_ERROR: SFP is not there.
3226 * QLA_FUNCTION_FAILED: detected New SFP
3227 */
3228int
3229qla24xx_detect_sfp(scsi_qla_host_t *vha)
3230{
3231 int rc = QLA_SUCCESS;
3232 struct sff_8247_a0 *a;
3233 struct qla_hw_data *ha = vha->hw;
3234
3235 if (!AUTO_DETECT_SFP_SUPPORT(vha))
3236 goto out;
3237
3238 rc = qla2x00_read_sfp_dev(vha, NULL, 0);
3239 if (rc)
3240 goto out;
3241
3242 a = (struct sff_8247_a0 *)vha->hw->sfp_data;
3243 qla2xxx_print_sfp_info(vha);
3244
3245 if (a->fc_ll_cc7 & FC_LL_VL || a->fc_ll_cc7 & FC_LL_L) {
3246 /* long range */
3247 ha->flags.detected_lr_sfp = 1;
3248
3249 if (a->length_km > 5 || a->length_100m > 50)
3250 ha->long_range_distance = LR_DISTANCE_10K;
3251 else
3252 ha->long_range_distance = LR_DISTANCE_5K;
3253
3254 if (ha->flags.detected_lr_sfp != ha->flags.using_lr_setting)
3255 ql_dbg(ql_dbg_async, vha, 0x507b,
3256 "Detected Long Range SFP.\n");
3257 } else {
3258 /* short range */
3259 ha->flags.detected_lr_sfp = 0;
3260 if (ha->flags.using_lr_setting)
3261 ql_dbg(ql_dbg_async, vha, 0x5084,
3262 "Detected Short Range SFP.\n");
3263 }
3264
3265 if (!vha->flags.init_done)
3266 rc = QLA_SUCCESS;
3267out:
3268 return rc;
3269}
3270
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003271/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272 * qla2x00_setup_chip() - Load and start RISC firmware.
Bart Van Assche2db62282018-01-23 16:33:51 -08003273 * @vha: HA context
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274 *
3275 * Returns 0 on success.
3276 */
3277static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003278qla2x00_setup_chip(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279{
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003280 int rval;
3281 uint32_t srisc_address = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003282 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3db06522008-01-31 12:33:49 -08003283 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
3284 unsigned long flags;
Andrew Vasquezdda772e2009-03-24 09:08:00 -07003285 uint16_t fw_major_version;
Andrew Vasquez3db06522008-01-31 12:33:49 -08003286
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04003287 if (IS_P3P_TYPE(ha)) {
Giridhar Malavalia9083012010-04-12 17:59:55 -07003288 rval = ha->isp_ops->load_risc(vha, &srisc_address);
Andrew Vasquez14e303d2010-07-23 15:28:29 +05003289 if (rval == QLA_SUCCESS) {
3290 qla2x00_stop_firmware(vha);
Giridhar Malavalia9083012010-04-12 17:59:55 -07003291 goto enable_82xx_npiv;
Andrew Vasquez14e303d2010-07-23 15:28:29 +05003292 } else
Giridhar Malavalib9637522010-05-28 15:08:15 -07003293 goto failed;
Giridhar Malavalia9083012010-04-12 17:59:55 -07003294 }
3295
Andrew Vasquez3db06522008-01-31 12:33:49 -08003296 if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) {
3297 /* Disable SRAM, Instruction RAM and GP RAM parity. */
3298 spin_lock_irqsave(&ha->hardware_lock, flags);
3299 WRT_REG_WORD(&reg->hccr, (HCCR_ENABLE_PARITY + 0x0));
3300 RD_REG_WORD(&reg->hccr);
3301 spin_unlock_irqrestore(&ha->hardware_lock, flags);
3302 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003303
Andrew Vasquez18e75552009-06-03 09:55:30 -07003304 qla81xx_mpi_sync(vha);
3305
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306 /* Load firmware sequences */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003307 rval = ha->isp_ops->load_risc(vha, &srisc_address);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003308 if (rval == QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003309 ql_dbg(ql_dbg_init, vha, 0x00c9,
3310 "Verifying Checksum of loaded RISC code.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003312 rval = qla2x00_verify_checksum(vha, srisc_address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313 if (rval == QLA_SUCCESS) {
3314 /* Start firmware execution. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003315 ql_dbg(ql_dbg_init, vha, 0x00ca,
3316 "Starting firmware.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317
Himanshu Madhanib0d6cab2015-12-17 14:56:56 -05003318 if (ql2xexlogins)
3319 ha->flags.exlogins_enabled = 1;
3320
Quinn Tran99e1b682017-06-02 09:12:03 -07003321 if (qla_is_exch_offld_enabled(vha))
Himanshu Madhani2f56a7f2015-12-17 14:56:57 -05003322 ha->flags.exchoffld_enabled = 1;
3323
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003324 rval = qla2x00_execute_fw(vha, srisc_address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325 /* Retrieve firmware information. */
Andrew Vasquezdda772e2009-03-24 09:08:00 -07003326 if (rval == QLA_SUCCESS) {
Quinn Trane4e3a2c2017-08-23 15:05:07 -07003327 qla24xx_detect_sfp(vha);
3328
Himanshu Madhanib0d6cab2015-12-17 14:56:56 -05003329 rval = qla2x00_set_exlogins_buffer(vha);
3330 if (rval != QLA_SUCCESS)
3331 goto failed;
3332
Himanshu Madhani2f56a7f2015-12-17 14:56:57 -05003333 rval = qla2x00_set_exchoffld_buffer(vha);
3334 if (rval != QLA_SUCCESS)
3335 goto failed;
3336
Giridhar Malavalia9083012010-04-12 17:59:55 -07003337enable_82xx_npiv:
Andrew Vasquezdda772e2009-03-24 09:08:00 -07003338 fw_major_version = ha->fw_major_version;
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04003339 if (IS_P3P_TYPE(ha))
Giridhar Malavali31731672011-08-16 11:31:54 -07003340 qla82xx_check_md_needed(vha);
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003341 else
3342 rval = qla2x00_get_fw_version(vha);
Andrew Vasquezca9e9c32009-06-03 09:55:20 -07003343 if (rval != QLA_SUCCESS)
3344 goto failed;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003345 ha->flags.npiv_supported = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003346 if (IS_QLA2XXX_MIDTYPE(ha) &&
Mike Hernandez946fb892008-08-13 21:36:59 -07003347 (ha->fw_attributes & BIT_2)) {
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003348 ha->flags.npiv_supported = 1;
Seokmann Ju4d0ea242007-09-20 14:07:43 -07003349 if ((!ha->max_npiv_vports) ||
3350 ((ha->max_npiv_vports + 1) %
Andrew Vasquezeb66dc62007-11-12 10:30:58 -08003351 MIN_MULTI_ID_FABRIC))
Seokmann Ju4d0ea242007-09-20 14:07:43 -07003352 ha->max_npiv_vports =
Andrew Vasquezeb66dc62007-11-12 10:30:58 -08003353 MIN_MULTI_ID_FABRIC - 1;
Seokmann Ju4d0ea242007-09-20 14:07:43 -07003354 }
Quinn Tran03e8c682015-12-17 14:56:59 -05003355 qla2x00_get_resource_cnts(vha);
Andrew Vasquezd743de62009-03-24 09:08:15 -07003356
Chad Dupuis8d93f552013-01-30 03:34:37 -05003357 /*
3358 * Allocate the array of outstanding commands
3359 * now that we know the firmware resources.
3360 */
3361 rval = qla2x00_alloc_outstanding_cmds(ha,
3362 vha->req);
3363 if (rval != QLA_SUCCESS)
3364 goto failed;
3365
Quinn Tranad0a0b02017-12-28 12:33:14 -08003366 if (!fw_major_version && !(IS_P3P_TYPE(ha)))
3367 qla2x00_alloc_offload_mem(vha);
3368
3369 if (ql2xallocfwdump && !(IS_P3P_TYPE(ha)))
Giridhar Malavali08de2842011-08-16 11:31:44 -07003370 qla2x00_alloc_fw_dump(vha);
Quinn Tranad0a0b02017-12-28 12:33:14 -08003371
Chad Dupuis3b6e5b92013-10-30 03:38:09 -04003372 } else {
3373 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 }
3375 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003376 ql_log(ql_log_fatal, vha, 0x00cd,
3377 "ISP Firmware failed checksum.\n");
3378 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379 }
Andrew Vasquezc74d88a2012-08-22 14:21:19 -04003380 } else
3381 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382
Andrew Vasquez3db06522008-01-31 12:33:49 -08003383 if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) {
3384 /* Enable proper parity. */
3385 spin_lock_irqsave(&ha->hardware_lock, flags);
3386 if (IS_QLA2300(ha))
3387 /* SRAM parity */
3388 WRT_REG_WORD(&reg->hccr, HCCR_ENABLE_PARITY + 0x1);
3389 else
3390 /* SRAM, Instruction RAM and GP RAM parity */
3391 WRT_REG_WORD(&reg->hccr, HCCR_ENABLE_PARITY + 0x7);
3392 RD_REG_WORD(&reg->hccr);
3393 spin_unlock_irqrestore(&ha->hardware_lock, flags);
3394 }
3395
Chad Dupuisf3982d82014-09-25 05:16:57 -04003396 if (IS_QLA27XX(ha))
3397 ha->flags.fac_supported = 1;
3398 else if (rval == QLA_SUCCESS && IS_FAC_REQUIRED(ha)) {
Joe Carnuccio1d2874d2009-03-24 09:08:06 -07003399 uint32_t size;
3400
3401 rval = qla81xx_fac_get_sector_size(vha, &size);
3402 if (rval == QLA_SUCCESS) {
3403 ha->flags.fac_supported = 1;
3404 ha->fdt_block_size = size << 2;
3405 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003406 ql_log(ql_log_warn, vha, 0x00ce,
Joe Carnuccio1d2874d2009-03-24 09:08:06 -07003407 "Unsupported FAC firmware (%d.%02d.%02d).\n",
3408 ha->fw_major_version, ha->fw_minor_version,
3409 ha->fw_subminor_version);
Joe Carnuccio1ca60e32014-02-26 04:15:02 -05003410
Chad Dupuisf73cb692014-02-26 04:15:06 -05003411 if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003412 ha->flags.fac_supported = 0;
3413 rval = QLA_SUCCESS;
3414 }
Joe Carnuccio1d2874d2009-03-24 09:08:06 -07003415 }
3416 }
Andrew Vasquezca9e9c32009-06-03 09:55:20 -07003417failed:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003419 ql_log(ql_log_fatal, vha, 0x00cf,
3420 "Setup chip ****FAILED****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421 }
3422
3423 return (rval);
3424}
3425
3426/**
3427 * qla2x00_init_response_q_entries() - Initializes response queue entries.
Bart Van Assche2db62282018-01-23 16:33:51 -08003428 * @rsp: response queue
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 *
3430 * Beginning of request ring has initialization control block already built
3431 * by nvram config routine.
3432 *
3433 * Returns 0 on success.
3434 */
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003435void
3436qla2x00_init_response_q_entries(struct rsp_que *rsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437{
3438 uint16_t cnt;
3439 response_t *pkt;
3440
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003441 rsp->ring_ptr = rsp->ring;
3442 rsp->ring_index = 0;
3443 rsp->status_srb = NULL;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003444 pkt = rsp->ring_ptr;
3445 for (cnt = 0; cnt < rsp->length; cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446 pkt->signature = RESPONSE_PROCESSED;
3447 pkt++;
3448 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449}
3450
3451/**
3452 * qla2x00_update_fw_options() - Read and process firmware options.
Bart Van Assche2db62282018-01-23 16:33:51 -08003453 * @vha: HA context
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454 *
3455 * Returns 0 on success.
3456 */
Andrew Vasquezabbd8872005-07-06 10:30:05 -07003457void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003458qla2x00_update_fw_options(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459{
3460 uint16_t swing, emphasis, tx_sens, rx_sens;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003461 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462
3463 memset(ha->fw_options, 0, sizeof(ha->fw_options));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003464 qla2x00_get_fw_options(vha, ha->fw_options);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465
3466 if (IS_QLA2100(ha) || IS_QLA2200(ha))
3467 return;
3468
3469 /* Serial Link options. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003470 ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0115,
3471 "Serial link options.\n");
3472 ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0109,
3473 (uint8_t *)&ha->fw_seriallink_options,
3474 sizeof(ha->fw_seriallink_options));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475
3476 ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
3477 if (ha->fw_seriallink_options[3] & BIT_2) {
3478 ha->fw_options[1] |= FO1_SET_EMPHASIS_SWING;
3479
3480 /* 1G settings */
3481 swing = ha->fw_seriallink_options[2] & (BIT_2 | BIT_1 | BIT_0);
3482 emphasis = (ha->fw_seriallink_options[2] &
3483 (BIT_4 | BIT_3)) >> 3;
3484 tx_sens = ha->fw_seriallink_options[0] &
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07003485 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486 rx_sens = (ha->fw_seriallink_options[0] &
3487 (BIT_7 | BIT_6 | BIT_5 | BIT_4)) >> 4;
3488 ha->fw_options[10] = (emphasis << 14) | (swing << 8);
3489 if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {
3490 if (rx_sens == 0x0)
3491 rx_sens = 0x3;
3492 ha->fw_options[10] |= (tx_sens << 4) | rx_sens;
3493 } else if (IS_QLA2322(ha) || IS_QLA6322(ha))
3494 ha->fw_options[10] |= BIT_5 |
3495 ((rx_sens & (BIT_1 | BIT_0)) << 2) |
3496 (tx_sens & (BIT_1 | BIT_0));
3497
3498 /* 2G settings */
3499 swing = (ha->fw_seriallink_options[2] &
3500 (BIT_7 | BIT_6 | BIT_5)) >> 5;
3501 emphasis = ha->fw_seriallink_options[3] & (BIT_1 | BIT_0);
3502 tx_sens = ha->fw_seriallink_options[1] &
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07003503 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504 rx_sens = (ha->fw_seriallink_options[1] &
3505 (BIT_7 | BIT_6 | BIT_5 | BIT_4)) >> 4;
3506 ha->fw_options[11] = (emphasis << 14) | (swing << 8);
3507 if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {
3508 if (rx_sens == 0x0)
3509 rx_sens = 0x3;
3510 ha->fw_options[11] |= (tx_sens << 4) | rx_sens;
3511 } else if (IS_QLA2322(ha) || IS_QLA6322(ha))
3512 ha->fw_options[11] |= BIT_5 |
3513 ((rx_sens & (BIT_1 | BIT_0)) << 2) |
3514 (tx_sens & (BIT_1 | BIT_0));
3515 }
3516
3517 /* FCP2 options. */
3518 /* Return command IOCBs without waiting for an ABTS to complete. */
3519 ha->fw_options[3] |= BIT_13;
3520
3521 /* LED scheme. */
3522 if (ha->flags.enable_led_scheme)
3523 ha->fw_options[2] |= BIT_12;
3524
andrew.vasquez@qlogic.com48c02fd2006-03-09 14:27:18 -08003525 /* Detect ISP6312. */
3526 if (IS_QLA6312(ha))
3527 ha->fw_options[2] |= BIT_13;
3528
Giridhar Malavali088d09d2016-07-06 11:14:20 -04003529 /* Set Retry FLOGI in case of P2P connection */
3530 if (ha->operating_mode == P2P) {
3531 ha->fw_options[2] |= BIT_3;
3532 ql_dbg(ql_dbg_disc, vha, 0x2100,
3533 "(%s): Setting FLOGI retry BIT in fw_options[2]: 0x%x\n",
3534 __func__, ha->fw_options[2]);
3535 }
3536
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537 /* Update firmware options. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003538 qla2x00_set_fw_options(vha, ha->fw_options);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539}
3540
Andrew Vasquezabbd8872005-07-06 10:30:05 -07003541void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003542qla24xx_update_fw_options(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003543{
3544 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003545 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003546
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04003547 if (IS_P3P_TYPE(ha))
Giridhar Malavalia9083012010-04-12 17:59:55 -07003548 return;
3549
Himanshu Madhanif198caf2016-01-27 12:03:30 -05003550 /* Hold status IOCBs until ABTS response received. */
3551 if (ql2xfwholdabts)
3552 ha->fw_options[3] |= BIT_12;
3553
Giridhar Malavali088d09d2016-07-06 11:14:20 -04003554 /* Set Retry FLOGI in case of P2P connection */
3555 if (ha->operating_mode == P2P) {
3556 ha->fw_options[2] |= BIT_3;
3557 ql_dbg(ql_dbg_disc, vha, 0x2101,
3558 "(%s): Setting FLOGI retry BIT in fw_options[2]: 0x%x\n",
3559 __func__, ha->fw_options[2]);
3560 }
3561
Quinn Tran41dc5292017-01-19 22:28:03 -08003562 /* Move PUREX, ABTS RX & RIDA to ATIOQ */
Quinn Tran3c4810f2017-06-02 09:11:53 -07003563 if (ql2xmvasynctoatio &&
3564 (IS_QLA83XX(ha) || IS_QLA27XX(ha))) {
Quinn Tran41dc5292017-01-19 22:28:03 -08003565 if (qla_tgt_mode_enabled(vha) ||
3566 qla_dual_mode_enabled(vha))
3567 ha->fw_options[2] |= BIT_11;
3568 else
3569 ha->fw_options[2] &= ~BIT_11;
3570 }
3571
Quinn Tranf7e761f2017-06-02 09:12:02 -07003572 if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
3573 /*
3574 * Tell FW to track each exchange to prevent
3575 * driver from using stale exchange.
3576 */
3577 if (qla_tgt_mode_enabled(vha) ||
3578 qla_dual_mode_enabled(vha))
3579 ha->fw_options[2] |= BIT_4;
3580 else
3581 ha->fw_options[2] &= ~BIT_4;
Quinn Tran9ecf0b02017-12-28 12:33:19 -08003582
3583 /* Reserve 1/2 of emergency exchanges for ELS.*/
3584 if (qla2xuseresexchforels)
3585 ha->fw_options[2] |= BIT_8;
3586 else
3587 ha->fw_options[2] &= ~BIT_8;
Quinn Tranf7e761f2017-06-02 09:12:02 -07003588 }
3589
Quinn Tran83548fe2017-06-02 09:12:01 -07003590 ql_dbg(ql_dbg_init, vha, 0x00e8,
3591 "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n",
3592 __func__, ha->fw_options[1], ha->fw_options[2],
3593 ha->fw_options[3], vha->host->active_mode);
Quinn Tran3c4810f2017-06-02 09:11:53 -07003594
3595 if (ha->fw_options[1] || ha->fw_options[2] || ha->fw_options[3])
3596 qla2x00_set_fw_options(vha, ha->fw_options);
Quinn Tran41dc5292017-01-19 22:28:03 -08003597
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003598 /* Update Serial Link options. */
andrew.vasquez@qlogic.comf94097e2006-01-13 17:05:32 -08003599 if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003600 return;
3601
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003602 rval = qla2x00_set_serdes_params(vha,
andrew.vasquez@qlogic.comf94097e2006-01-13 17:05:32 -08003603 le16_to_cpu(ha->fw_seriallink_options24[1]),
3604 le16_to_cpu(ha->fw_seriallink_options24[2]),
3605 le16_to_cpu(ha->fw_seriallink_options24[3]));
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003606 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003607 ql_log(ql_log_warn, vha, 0x0104,
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003608 "Unable to update Serial Link options (%x).\n", rval);
3609 }
3610}
3611
3612void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003613qla2x00_config_rings(struct scsi_qla_host *vha)
Andrew Vasquezabbd8872005-07-06 10:30:05 -07003614{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003615 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07003616 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003617 struct req_que *req = ha->req_q_map[0];
3618 struct rsp_que *rsp = ha->rsp_q_map[0];
Andrew Vasquezabbd8872005-07-06 10:30:05 -07003619
3620 /* Setup ring parameters in initialization control block. */
Bart Van Asschead950362015-07-09 07:24:08 -07003621 ha->init_cb->request_q_outpointer = cpu_to_le16(0);
3622 ha->init_cb->response_q_inpointer = cpu_to_le16(0);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003623 ha->init_cb->request_q_length = cpu_to_le16(req->length);
3624 ha->init_cb->response_q_length = cpu_to_le16(rsp->length);
3625 ha->init_cb->request_q_address[0] = cpu_to_le32(LSD(req->dma));
3626 ha->init_cb->request_q_address[1] = cpu_to_le32(MSD(req->dma));
3627 ha->init_cb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma));
3628 ha->init_cb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma));
Andrew Vasquezabbd8872005-07-06 10:30:05 -07003629
3630 WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), 0);
3631 WRT_REG_WORD(ISP_REQ_Q_OUT(ha, reg), 0);
3632 WRT_REG_WORD(ISP_RSP_Q_IN(ha, reg), 0);
3633 WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), 0);
3634 RD_REG_WORD(ISP_RSP_Q_OUT(ha, reg)); /* PCI Posting. */
3635}
3636
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003637void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003638qla24xx_config_rings(struct scsi_qla_host *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003639{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003640 struct qla_hw_data *ha = vha->hw;
Bart Van Assche118e2ef2015-07-09 07:24:27 -07003641 device_reg_t *reg = ISP_QUE_REG(ha, 0);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003642 struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp;
3643 struct qla_msix_entry *msix;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003644 struct init_cb_24xx *icb;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003645 uint16_t rid = 0;
3646 struct req_que *req = ha->req_q_map[0];
3647 struct rsp_que *rsp = ha->rsp_q_map[0];
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003648
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003649 /* Setup ring parameters in initialization control block. */
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003650 icb = (struct init_cb_24xx *)ha->init_cb;
Bart Van Asschead950362015-07-09 07:24:08 -07003651 icb->request_q_outpointer = cpu_to_le16(0);
3652 icb->response_q_inpointer = cpu_to_le16(0);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003653 icb->request_q_length = cpu_to_le16(req->length);
3654 icb->response_q_length = cpu_to_le16(rsp->length);
3655 icb->request_q_address[0] = cpu_to_le32(LSD(req->dma));
3656 icb->request_q_address[1] = cpu_to_le32(MSD(req->dma));
3657 icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma));
3658 icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma));
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003659
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003660 /* Setup ATIO queue dma pointers for target mode */
Bart Van Asschead950362015-07-09 07:24:08 -07003661 icb->atio_q_inpointer = cpu_to_le16(0);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003662 icb->atio_q_length = cpu_to_le16(ha->tgt.atio_q_length);
3663 icb->atio_q_address[0] = cpu_to_le32(LSD(ha->tgt.atio_dma));
3664 icb->atio_q_address[1] = cpu_to_le32(MSD(ha->tgt.atio_dma));
3665
Joe Carnuccio7c6300e2014-04-11 16:54:37 -04003666 if (IS_SHADOW_REG_CAPABLE(ha))
Bart Van Asschead950362015-07-09 07:24:08 -07003667 icb->firmware_options_2 |= cpu_to_le32(BIT_30|BIT_29);
Joe Carnuccio7c6300e2014-04-11 16:54:37 -04003668
Chad Dupuisf73cb692014-02-26 04:15:06 -05003669 if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
Bart Van Asschead950362015-07-09 07:24:08 -07003670 icb->qos = cpu_to_le16(QLA_DEFAULT_QUE_QOS);
3671 icb->rid = cpu_to_le16(rid);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003672 if (ha->flags.msix_enabled) {
3673 msix = &ha->msix_entries[1];
Quinn Tran83548fe2017-06-02 09:12:01 -07003674 ql_dbg(ql_dbg_init, vha, 0x0019,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003675 "Registering vector 0x%x for base que.\n",
3676 msix->entry);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003677 icb->msix = cpu_to_le16(msix->entry);
3678 }
3679 /* Use alternate PCI bus number */
3680 if (MSB(rid))
Bart Van Asschead950362015-07-09 07:24:08 -07003681 icb->firmware_options_2 |= cpu_to_le32(BIT_19);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003682 /* Use alternate PCI devfn */
3683 if (LSB(rid))
Bart Van Asschead950362015-07-09 07:24:08 -07003684 icb->firmware_options_2 |= cpu_to_le32(BIT_18);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003685
Anirban Chakraborty31557542009-12-02 10:36:55 -08003686 /* Use Disable MSIX Handshake mode for capable adapters */
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003687 if ((ha->fw_attributes & BIT_6) && (IS_MSIX_NACK_CAPABLE(ha)) &&
3688 (ha->flags.msix_enabled)) {
Bart Van Asschead950362015-07-09 07:24:08 -07003689 icb->firmware_options_2 &= cpu_to_le32(~BIT_22);
Anirban Chakraborty31557542009-12-02 10:36:55 -08003690 ha->flags.disable_msix_handshake = 1;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003691 ql_dbg(ql_dbg_init, vha, 0x00fe,
3692 "MSIX Handshake Disable Mode turned on.\n");
Anirban Chakraborty31557542009-12-02 10:36:55 -08003693 } else {
Bart Van Asschead950362015-07-09 07:24:08 -07003694 icb->firmware_options_2 |= cpu_to_le32(BIT_22);
Anirban Chakraborty31557542009-12-02 10:36:55 -08003695 }
Bart Van Asschead950362015-07-09 07:24:08 -07003696 icb->firmware_options_2 |= cpu_to_le32(BIT_23);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003697
3698 WRT_REG_DWORD(&reg->isp25mq.req_q_in, 0);
3699 WRT_REG_DWORD(&reg->isp25mq.req_q_out, 0);
3700 WRT_REG_DWORD(&reg->isp25mq.rsp_q_in, 0);
3701 WRT_REG_DWORD(&reg->isp25mq.rsp_q_out, 0);
3702 } else {
3703 WRT_REG_DWORD(&reg->isp24.req_q_in, 0);
3704 WRT_REG_DWORD(&reg->isp24.req_q_out, 0);
3705 WRT_REG_DWORD(&reg->isp24.rsp_q_in, 0);
3706 WRT_REG_DWORD(&reg->isp24.rsp_q_out, 0);
3707 }
Arun Easiaa230bc2013-01-30 03:34:39 -05003708 qlt_24xx_config_rings(vha);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003709
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003710 /* PCI posting */
3711 RD_REG_DWORD(&ioreg->hccr);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07003712}
3713
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714/**
3715 * qla2x00_init_rings() - Initializes firmware.
Bart Van Assche2db62282018-01-23 16:33:51 -08003716 * @vha: HA context
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717 *
3718 * Beginning of request ring has initialization control block already built
3719 * by nvram config routine.
3720 *
3721 * Returns 0 on success.
3722 */
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04003723int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003724qla2x00_init_rings(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725{
3726 int rval;
3727 unsigned long flags = 0;
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003728 int cnt, que;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003729 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003730 struct req_que *req;
3731 struct rsp_que *rsp;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003732 struct mid_init_cb_24xx *mid_init_cb =
3733 (struct mid_init_cb_24xx *) ha->init_cb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734
3735 spin_lock_irqsave(&ha->hardware_lock, flags);
3736
3737 /* Clear outstanding commands array. */
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003738 for (que = 0; que < ha->max_req_queues; que++) {
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003739 req = ha->req_q_map[que];
Quinn Trancb432852016-02-04 11:45:16 -05003740 if (!req || !test_bit(que, ha->req_qid_map))
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003741 continue;
Joe Carnuccio7c6300e2014-04-11 16:54:37 -04003742 req->out_ptr = (void *)(req->ring + req->length);
3743 *req->out_ptr = 0;
Chad Dupuis8d93f552013-01-30 03:34:37 -05003744 for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++)
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003745 req->outstanding_cmds[cnt] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003747 req->current_outstanding_cmd = 1;
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003748
3749 /* Initialize firmware. */
3750 req->ring_ptr = req->ring;
3751 req->ring_index = 0;
3752 req->cnt = req->length;
3753 }
3754
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003755 for (que = 0; que < ha->max_rsp_queues; que++) {
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003756 rsp = ha->rsp_q_map[que];
Quinn Trancb432852016-02-04 11:45:16 -05003757 if (!rsp || !test_bit(que, ha->rsp_qid_map))
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003758 continue;
Joe Carnuccio7c6300e2014-04-11 16:54:37 -04003759 rsp->in_ptr = (void *)(rsp->ring + rsp->length);
3760 *rsp->in_ptr = 0;
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003761 /* Initialize response queue entries */
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04003762 if (IS_QLAFX00(ha))
3763 qlafx00_init_response_q_entries(rsp);
3764 else
3765 qla2x00_init_response_q_entries(rsp);
Anirban Chakraborty29bdccb2009-01-08 15:41:08 -08003766 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003768 ha->tgt.atio_ring_ptr = ha->tgt.atio_ring;
3769 ha->tgt.atio_ring_index = 0;
3770 /* Initialize ATIO queue entries */
3771 qlt_init_atio_q_entries(vha);
3772
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003773 ha->isp_ops->config_rings(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774
3775 spin_unlock_irqrestore(&ha->hardware_lock, flags);
3776
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04003777 ql_dbg(ql_dbg_init, vha, 0x00d1, "Issue init firmware.\n");
3778
3779 if (IS_QLAFX00(ha)) {
3780 rval = qlafx00_init_firmware(vha, ha->init_cb_size);
3781 goto next_check;
3782 }
3783
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 /* Update any ISP specific firmware options before initialization. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003785 ha->isp_ops->update_fw_options(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786
Lalit Chandivade605aa2b2009-03-05 11:07:01 -08003787 if (ha->flags.npiv_supported) {
Saurav Kashyap45980cc2012-08-22 14:21:21 -04003788 if (ha->operating_mode == LOOP && !IS_CNA_CAPABLE(ha))
Lalit Chandivade605aa2b2009-03-05 11:07:01 -08003789 ha->max_npiv_vports = MIN_MULTI_ID_FABRIC - 1;
Seokmann Juc48339d2008-01-17 09:02:19 -08003790 mid_init_cb->count = cpu_to_le16(ha->max_npiv_vports);
Lalit Chandivade605aa2b2009-03-05 11:07:01 -08003791 }
3792
Andrew Vasquez24a08132009-03-24 09:08:16 -07003793 if (IS_FWI2_CAPABLE(ha)) {
Bart Van Asschead950362015-07-09 07:24:08 -07003794 mid_init_cb->options = cpu_to_le16(BIT_1);
Andrew Vasquez24a08132009-03-24 09:08:16 -07003795 mid_init_cb->init_cb.execution_throttle =
Quinn Tran03e8c682015-12-17 14:56:59 -05003796 cpu_to_le16(ha->cur_fw_xcb_count);
Joe Carnuccio40f38622016-07-06 11:14:28 -04003797 ha->flags.dport_enabled =
3798 (mid_init_cb->init_cb.firmware_options_1 & BIT_7) != 0;
3799 ql_dbg(ql_dbg_init, vha, 0x0191, "DPORT Support: %s.\n",
3800 (ha->flags.dport_enabled) ? "enabled" : "disabled");
3801 /* FA-WWPN Status */
Himanshu Madhani2486c622014-09-25 05:17:00 -04003802 ha->flags.fawwpn_enabled =
Joe Carnuccio40f38622016-07-06 11:14:28 -04003803 (mid_init_cb->init_cb.firmware_options_1 & BIT_6) != 0;
Quinn Tran83548fe2017-06-02 09:12:01 -07003804 ql_dbg(ql_dbg_init, vha, 0x00bc, "FA-WWPN Support: %s.\n",
Himanshu Madhani2486c622014-09-25 05:17:00 -04003805 (ha->flags.fawwpn_enabled) ? "enabled" : "disabled");
Andrew Vasquez24a08132009-03-24 09:08:16 -07003806 }
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003807
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003808 rval = qla2x00_init_firmware(vha, ha->init_cb_size);
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04003809next_check:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003811 ql_log(ql_log_fatal, vha, 0x00d2,
3812 "Init Firmware **** FAILED ****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003814 ql_dbg(ql_dbg_init, vha, 0x00d3,
3815 "Init Firmware -- success.\n");
Quinn Tran4b60c822017-06-13 20:47:21 -07003816 QLA_FW_STARTED(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 }
3818
3819 return (rval);
3820}
3821
3822/**
3823 * qla2x00_fw_ready() - Waits for firmware ready.
Bart Van Assche2db62282018-01-23 16:33:51 -08003824 * @vha: HA context
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825 *
3826 * Returns 0 on success.
3827 */
3828static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003829qla2x00_fw_ready(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830{
3831 int rval;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003832 unsigned long wtime, mtime, cs84xx_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833 uint16_t min_wait; /* Minimum wait time if loop is down */
3834 uint16_t wait_time; /* Wait time if loop is coming ready */
Joe Carnucciob5a340d2014-09-25 05:16:48 -04003835 uint16_t state[6];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003836 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04003838 if (IS_QLAFX00(vha->hw))
3839 return qlafx00_fw_ready(vha);
3840
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 rval = QLA_SUCCESS;
3842
Chad Dupuis334614912015-04-09 14:59:57 -04003843 /* Time to wait for loop down */
3844 if (IS_P3P_TYPE(ha))
3845 min_wait = 30;
3846 else
3847 min_wait = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848
3849 /*
3850 * Firmware should take at most one RATOV to login, plus 5 seconds for
3851 * our own processing.
3852 */
3853 if ((wait_time = (ha->retry_count*ha->login_timeout) + 5) < min_wait) {
3854 wait_time = min_wait;
3855 }
3856
3857 /* Min wait time if loop down */
3858 mtime = jiffies + (min_wait * HZ);
3859
3860 /* wait time before firmware ready */
3861 wtime = jiffies + (wait_time * HZ);
3862
3863 /* Wait for ISP to finish LIP */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003864 if (!vha->flags.init_done)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003865 ql_log(ql_log_info, vha, 0x801e,
3866 "Waiting for LIP to complete.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867
3868 do {
Andrew Vasquez5b939032012-11-21 02:40:26 -05003869 memset(state, -1, sizeof(state));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003870 rval = qla2x00_get_firmware_state(vha, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 if (rval == QLA_SUCCESS) {
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003872 if (state[0] < FSTATE_LOSS_OF_SYNC) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003873 vha->device_flags &= ~DFLG_NO_CABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874 }
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003875 if (IS_QLA84XX(ha) && state[0] != FSTATE_READY) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003876 ql_dbg(ql_dbg_taskm, vha, 0x801f,
3877 "fw_state=%x 84xx=%x.\n", state[0],
3878 state[2]);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003879 if ((state[2] & FSTATE_LOGGED_IN) &&
3880 (state[2] & FSTATE_WAITING_FOR_VERIFY)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003881 ql_dbg(ql_dbg_taskm, vha, 0x8028,
3882 "Sending verify iocb.\n");
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003883
3884 cs84xx_time = jiffies;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003885 rval = qla84xx_init_chip(vha);
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003886 if (rval != QLA_SUCCESS) {
3887 ql_log(ql_log_warn,
Chad Dupuiscfb09192011-11-18 09:03:07 -08003888 vha, 0x8007,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003889 "Init chip failed.\n");
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003890 break;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003891 }
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003892
3893 /* Add time taken to initialize. */
3894 cs84xx_time = jiffies - cs84xx_time;
3895 wtime += cs84xx_time;
3896 mtime += cs84xx_time;
Chad Dupuiscfb09192011-11-18 09:03:07 -08003897 ql_dbg(ql_dbg_taskm, vha, 0x8008,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003898 "Increasing wait time by %ld. "
3899 "New time %ld.\n", cs84xx_time,
3900 wtime);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003901 }
3902 } else if (state[0] == FSTATE_READY) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003903 ql_dbg(ql_dbg_taskm, vha, 0x8037,
3904 "F/W Ready - OK.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003906 qla2x00_get_retry_cnt(vha, &ha->retry_count,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907 &ha->login_timeout, &ha->r_a_tov);
3908
3909 rval = QLA_SUCCESS;
3910 break;
3911 }
3912
3913 rval = QLA_FUNCTION_FAILED;
3914
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003915 if (atomic_read(&vha->loop_down_timer) &&
Harihara Kadayam4d4df192008-04-03 13:13:26 -07003916 state[0] != FSTATE_READY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917 /* Loop down. Timeout on min_wait for states
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07003918 * other than Wait for Login.
3919 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 if (time_after_eq(jiffies, mtime)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003921 ql_log(ql_log_info, vha, 0x8038,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922 "Cable is unplugged...\n");
3923
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003924 vha->device_flags |= DFLG_NO_CABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925 break;
3926 }
3927 }
3928 } else {
3929 /* Mailbox cmd failed. Timeout on min_wait. */
Santosh Vernekarcdbb0a4f2010-05-28 15:08:25 -07003930 if (time_after_eq(jiffies, mtime) ||
Giridhar Malavali71905752011-02-23 15:27:10 -08003931 ha->flags.isp82xx_fw_hung)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 break;
3933 }
3934
3935 if (time_after_eq(jiffies, wtime))
3936 break;
3937
3938 /* Delay for a while */
3939 msleep(500);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 } while (1);
3941
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003942 ql_dbg(ql_dbg_taskm, vha, 0x803a,
Joe Carnucciob5a340d2014-09-25 05:16:48 -04003943 "fw_state=%x (%x, %x, %x, %x %x) curr time=%lx.\n", state[0],
3944 state[1], state[2], state[3], state[4], state[5], jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945
Chad Dupuiscfb09192011-11-18 09:03:07 -08003946 if (rval && !(vha->device_flags & DFLG_NO_CABLE)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003947 ql_log(ql_log_warn, vha, 0x803b,
3948 "Firmware ready **** FAILED ****.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 }
3950
3951 return (rval);
3952}
3953
3954/*
3955* qla2x00_configure_hba
3956* Setup adapter context.
3957*
3958* Input:
3959* ha = adapter state pointer.
3960*
3961* Returns:
3962* 0 = success
3963*
3964* Context:
3965* Kernel context.
3966*/
3967static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003968qla2x00_configure_hba(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969{
3970 int rval;
3971 uint16_t loop_id;
3972 uint16_t topo;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003973 uint16_t sw_cap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 uint8_t al_pa;
3975 uint8_t area;
3976 uint8_t domain;
3977 char connect_type[22];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003978 struct qla_hw_data *ha = vha->hw;
Joe Carnuccio61e1b262013-02-08 01:57:48 -05003979 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
Quinn Tran482c9dc2017-03-15 09:48:54 -07003980 port_id_t id;
Quinn Tran9d1aa4e2017-12-28 12:33:27 -08003981 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982
3983 /* Get host addresses. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003984 rval = qla2x00_get_adapter_id(vha,
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07003985 &loop_id, &al_pa, &area, &domain, &topo, &sw_cap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986 if (rval != QLA_SUCCESS) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003987 if (LOOP_TRANSITION(vha) || atomic_read(&ha->loop_down_timer) ||
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003988 IS_CNA_CAPABLE(ha) ||
Ravi Anand33135aa2005-11-08 14:37:20 -08003989 (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003990 ql_dbg(ql_dbg_disc, vha, 0x2008,
3991 "Loop is in a transition state.\n");
Ravi Anand33135aa2005-11-08 14:37:20 -08003992 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003993 ql_log(ql_log_warn, vha, 0x2009,
3994 "Unable to get host loop ID.\n");
Joe Carnuccio61e1b262013-02-08 01:57:48 -05003995 if (IS_FWI2_CAPABLE(ha) && (vha == base_vha) &&
3996 (rval == QLA_COMMAND_ERROR && loop_id == 0x1b)) {
3997 ql_log(ql_log_warn, vha, 0x1151,
3998 "Doing link init.\n");
3999 if (qla24xx_link_initialize(vha) == QLA_SUCCESS)
4000 return rval;
4001 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004002 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Ravi Anand33135aa2005-11-08 14:37:20 -08004003 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004 return (rval);
4005 }
4006
4007 if (topo == 4) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004008 ql_log(ql_log_info, vha, 0x200a,
4009 "Cannot get topology - retrying.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010 return (QLA_FUNCTION_FAILED);
4011 }
4012
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004013 vha->loop_id = loop_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014
4015 /* initialize */
4016 ha->min_external_loopid = SNS_FIRST_LOOP_ID;
4017 ha->operating_mode = LOOP;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07004018 ha->switch_cap = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019
4020 switch (topo) {
4021 case 0:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004022 ql_dbg(ql_dbg_disc, vha, 0x200b, "HBA in NL topology.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023 ha->current_topology = ISP_CFG_NL;
4024 strcpy(connect_type, "(Loop)");
4025 break;
4026
4027 case 1:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004028 ql_dbg(ql_dbg_disc, vha, 0x200c, "HBA in FL topology.\n");
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07004029 ha->switch_cap = sw_cap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030 ha->current_topology = ISP_CFG_FL;
4031 strcpy(connect_type, "(FL_Port)");
4032 break;
4033
4034 case 2:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004035 ql_dbg(ql_dbg_disc, vha, 0x200d, "HBA in N P2P topology.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036 ha->operating_mode = P2P;
4037 ha->current_topology = ISP_CFG_N;
4038 strcpy(connect_type, "(N_Port-to-N_Port)");
4039 break;
4040
4041 case 3:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004042 ql_dbg(ql_dbg_disc, vha, 0x200e, "HBA in F P2P topology.\n");
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07004043 ha->switch_cap = sw_cap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 ha->operating_mode = P2P;
4045 ha->current_topology = ISP_CFG_F;
4046 strcpy(connect_type, "(F_Port)");
4047 break;
4048
4049 default:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004050 ql_dbg(ql_dbg_disc, vha, 0x200f,
4051 "HBA in unknown topology %x, using NL.\n", topo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052 ha->current_topology = ISP_CFG_NL;
4053 strcpy(connect_type, "(Loop)");
4054 break;
4055 }
4056
4057 /* Save Host port and loop ID. */
4058 /* byte order - Big Endian */
Quinn Tran482c9dc2017-03-15 09:48:54 -07004059 id.b.domain = domain;
4060 id.b.area = area;
4061 id.b.al_pa = al_pa;
4062 id.b.rsvd_1 = 0;
Quinn Tran9d1aa4e2017-12-28 12:33:27 -08004063 spin_lock_irqsave(&ha->hardware_lock, flags);
Quinn Tran482c9dc2017-03-15 09:48:54 -07004064 qlt_update_host_map(vha, id);
Quinn Tran9d1aa4e2017-12-28 12:33:27 -08004065 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04004066
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004067 if (!vha->flags.init_done)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004068 ql_log(ql_log_info, vha, 0x2010,
4069 "Topology - %s, Host Loop address 0x%x.\n",
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004070 connect_type, vha->loop_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072 return(rval);
4073}
4074
Giridhar Malavalia9083012010-04-12 17:59:55 -07004075inline void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004076qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
4077 char *def)
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08004078{
4079 char *st, *en;
4080 uint16_t index;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004081 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezab671142009-08-25 11:36:17 -07004082 int use_tbl = !IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) &&
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08004083 !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha);
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08004084
4085 if (memcmp(model, BINZERO, len) != 0) {
4086 strncpy(ha->model_number, model, len);
4087 st = en = ha->model_number;
4088 en += len - 1;
4089 while (en > st) {
4090 if (*en != 0x20 && *en != 0x00)
4091 break;
4092 *en-- = '\0';
4093 }
4094
4095 index = (ha->pdev->subsystem_device & 0xff);
Andrew Vasquez7d0dba12009-04-06 22:33:45 -07004096 if (use_tbl &&
4097 ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08004098 index < QLA_MODEL_NAMES)
Joe Carnuccio1ee27142008-07-10 16:55:53 -07004099 strncpy(ha->model_desc,
4100 qla2x00_model_name[index * 2 + 1],
4101 sizeof(ha->model_desc) - 1);
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08004102 } else {
4103 index = (ha->pdev->subsystem_device & 0xff);
Andrew Vasquez7d0dba12009-04-06 22:33:45 -07004104 if (use_tbl &&
4105 ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08004106 index < QLA_MODEL_NAMES) {
4107 strcpy(ha->model_number,
4108 qla2x00_model_name[index * 2]);
Joe Carnuccio1ee27142008-07-10 16:55:53 -07004109 strncpy(ha->model_desc,
4110 qla2x00_model_name[index * 2 + 1],
4111 sizeof(ha->model_desc) - 1);
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08004112 } else {
4113 strcpy(ha->model_number, def);
4114 }
4115 }
Joe Carnuccio1ee27142008-07-10 16:55:53 -07004116 if (IS_FWI2_CAPABLE(ha))
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004117 qla2xxx_get_vpd_field(vha, "\x82", ha->model_desc,
Joe Carnuccio1ee27142008-07-10 16:55:53 -07004118 sizeof(ha->model_desc));
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08004119}
4120
David Miller4e08df32007-04-16 12:37:43 -07004121/* On sparc systems, obtain port and node WWN from firmware
4122 * properties.
4123 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004124static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
David Miller4e08df32007-04-16 12:37:43 -07004125{
4126#ifdef CONFIG_SPARC
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004127 struct qla_hw_data *ha = vha->hw;
David Miller4e08df32007-04-16 12:37:43 -07004128 struct pci_dev *pdev = ha->pdev;
David S. Miller15576bc2007-05-08 00:36:49 -07004129 struct device_node *dp = pci_device_to_OF_node(pdev);
4130 const u8 *val;
David Miller4e08df32007-04-16 12:37:43 -07004131 int len;
4132
4133 val = of_get_property(dp, "port-wwn", &len);
4134 if (val && len >= WWN_SIZE)
4135 memcpy(nv->port_name, val, WWN_SIZE);
4136
4137 val = of_get_property(dp, "node-wwn", &len);
4138 if (val && len >= WWN_SIZE)
4139 memcpy(nv->node_name, val, WWN_SIZE);
4140#endif
4141}
4142
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143/*
4144* NVRAM configuration for ISP 2xxx
4145*
4146* Input:
4147* ha = adapter block pointer.
4148*
4149* Output:
4150* initialization control block in response_ring
4151* host adapters parameters in host adapter block
4152*
4153* Returns:
4154* 0 = success.
4155*/
Andrew Vasquezabbd8872005-07-06 10:30:05 -07004156int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004157qla2x00_nvram_config(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158{
David Miller4e08df32007-04-16 12:37:43 -07004159 int rval;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004160 uint8_t chksum = 0;
4161 uint16_t cnt;
4162 uint8_t *dptr1, *dptr2;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004163 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004164 init_cb_t *icb = ha->init_cb;
Seokmann Ju281afe12007-07-26 13:43:34 -07004165 nvram_t *nv = ha->nvram;
4166 uint8_t *ptr = ha->nvram;
Andrew Vasquez3d716442005-07-06 10:30:26 -07004167 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168
David Miller4e08df32007-04-16 12:37:43 -07004169 rval = QLA_SUCCESS;
4170
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 /* Determine NVRAM starting address. */
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004172 ha->nvram_size = sizeof(nvram_t);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 ha->nvram_base = 0;
4174 if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha))
4175 if ((RD_REG_WORD(&reg->ctrl_status) >> 14) == 1)
4176 ha->nvram_base = 0x80;
4177
4178 /* Get NVRAM data and calculate checksum. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004179 ha->isp_ops->read_nvram(vha, ptr, ha->nvram_base, ha->nvram_size);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004180 for (cnt = 0, chksum = 0; cnt < ha->nvram_size; cnt++)
4181 chksum += *ptr++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004183 ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x010f,
4184 "Contents of NVRAM.\n");
4185 ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0110,
4186 (uint8_t *)nv, ha->nvram_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187
4188 /* Bad NVRAM data, set defaults parameters. */
4189 if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
4190 nv->id[2] != 'P' || nv->id[3] != ' ' || nv->nvram_version < 1) {
4191 /* Reset NVRAM data. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004192 ql_log(ql_log_warn, vha, 0x0064,
Raul Porcel9e336522012-05-15 14:34:08 -04004193 "Inconsistent NVRAM "
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004194 "detected: checksum=0x%x id=%c version=0x%x.\n",
4195 chksum, nv->id[0], nv->nvram_version);
4196 ql_log(ql_log_warn, vha, 0x0065,
4197 "Falling back to "
4198 "functioning (yet invalid -- WWPN) defaults.\n");
David Miller4e08df32007-04-16 12:37:43 -07004199
4200 /*
4201 * Set default initialization control block.
4202 */
4203 memset(nv, 0, ha->nvram_size);
4204 nv->parameter_block_version = ICB_VERSION;
4205
4206 if (IS_QLA23XX(ha)) {
4207 nv->firmware_options[0] = BIT_2 | BIT_1;
4208 nv->firmware_options[1] = BIT_7 | BIT_5;
4209 nv->add_firmware_options[0] = BIT_5;
4210 nv->add_firmware_options[1] = BIT_5 | BIT_4;
Joe Carnuccio98aee702014-09-25 05:16:38 -04004211 nv->frame_payload_size = 2048;
David Miller4e08df32007-04-16 12:37:43 -07004212 nv->special_options[1] = BIT_7;
4213 } else if (IS_QLA2200(ha)) {
4214 nv->firmware_options[0] = BIT_2 | BIT_1;
4215 nv->firmware_options[1] = BIT_7 | BIT_5;
4216 nv->add_firmware_options[0] = BIT_5;
4217 nv->add_firmware_options[1] = BIT_5 | BIT_4;
Joe Carnuccio98aee702014-09-25 05:16:38 -04004218 nv->frame_payload_size = 1024;
David Miller4e08df32007-04-16 12:37:43 -07004219 } else if (IS_QLA2100(ha)) {
4220 nv->firmware_options[0] = BIT_3 | BIT_1;
4221 nv->firmware_options[1] = BIT_5;
Joe Carnuccio98aee702014-09-25 05:16:38 -04004222 nv->frame_payload_size = 1024;
David Miller4e08df32007-04-16 12:37:43 -07004223 }
4224
Bart Van Asschead950362015-07-09 07:24:08 -07004225 nv->max_iocb_allocation = cpu_to_le16(256);
4226 nv->execution_throttle = cpu_to_le16(16);
David Miller4e08df32007-04-16 12:37:43 -07004227 nv->retry_count = 8;
4228 nv->retry_delay = 1;
4229
4230 nv->port_name[0] = 33;
4231 nv->port_name[3] = 224;
4232 nv->port_name[4] = 139;
4233
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004234 qla2xxx_nvram_wwn_from_ofw(vha, nv);
David Miller4e08df32007-04-16 12:37:43 -07004235
4236 nv->login_timeout = 4;
4237
4238 /*
4239 * Set default host adapter parameters
4240 */
4241 nv->host_p[1] = BIT_2;
4242 nv->reset_delay = 5;
4243 nv->port_down_retry_count = 8;
Bart Van Asschead950362015-07-09 07:24:08 -07004244 nv->max_luns_per_target = cpu_to_le16(8);
David Miller4e08df32007-04-16 12:37:43 -07004245 nv->link_down_timeout = 60;
4246
4247 rval = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 }
4249
4250#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
4251 /*
4252 * The SN2 does not provide BIOS emulation which means you can't change
4253 * potentially bogus BIOS settings. Force the use of default settings
4254 * for link rate and frame size. Hope that the rest of the settings
4255 * are valid.
4256 */
4257 if (ia64_platform_is("sn2")) {
Joe Carnuccio98aee702014-09-25 05:16:38 -04004258 nv->frame_payload_size = 2048;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259 if (IS_QLA23XX(ha))
4260 nv->special_options[1] = BIT_7;
4261 }
4262#endif
4263
4264 /* Reset Initialization control block */
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004265 memset(icb, 0, ha->init_cb_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266
4267 /*
4268 * Setup driver NVRAM options.
4269 */
4270 nv->firmware_options[0] |= (BIT_6 | BIT_1);
4271 nv->firmware_options[0] &= ~(BIT_5 | BIT_4);
4272 nv->firmware_options[1] |= (BIT_5 | BIT_0);
4273 nv->firmware_options[1] &= ~BIT_4;
4274
4275 if (IS_QLA23XX(ha)) {
4276 nv->firmware_options[0] |= BIT_2;
4277 nv->firmware_options[0] &= ~BIT_3;
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04004278 nv->special_options[0] &= ~BIT_6;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07004279 nv->add_firmware_options[1] |= BIT_5 | BIT_4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280
4281 if (IS_QLA2300(ha)) {
4282 if (ha->fb_rev == FPM_2310) {
4283 strcpy(ha->model_number, "QLA2310");
4284 } else {
4285 strcpy(ha->model_number, "QLA2300");
4286 }
4287 } else {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004288 qla2x00_set_model_info(vha, nv->model_number,
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08004289 sizeof(nv->model_number), "QLA23xx");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290 }
4291 } else if (IS_QLA2200(ha)) {
4292 nv->firmware_options[0] |= BIT_2;
4293 /*
4294 * 'Point-to-point preferred, else loop' is not a safe
4295 * connection mode setting.
4296 */
4297 if ((nv->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) ==
4298 (BIT_5 | BIT_4)) {
4299 /* Force 'loop preferred, else point-to-point'. */
4300 nv->add_firmware_options[0] &= ~(BIT_6 | BIT_5 | BIT_4);
4301 nv->add_firmware_options[0] |= BIT_5;
4302 }
4303 strcpy(ha->model_number, "QLA22xx");
4304 } else /*if (IS_QLA2100(ha))*/ {
4305 strcpy(ha->model_number, "QLA2100");
4306 }
4307
4308 /*
4309 * Copy over NVRAM RISC parameter block to initialization control block.
4310 */
4311 dptr1 = (uint8_t *)icb;
4312 dptr2 = (uint8_t *)&nv->parameter_block_version;
4313 cnt = (uint8_t *)&icb->request_q_outpointer - (uint8_t *)&icb->version;
4314 while (cnt--)
4315 *dptr1++ = *dptr2++;
4316
4317 /* Copy 2nd half. */
4318 dptr1 = (uint8_t *)icb->add_firmware_options;
4319 cnt = (uint8_t *)icb->reserved_3 - (uint8_t *)icb->add_firmware_options;
4320 while (cnt--)
4321 *dptr1++ = *dptr2++;
4322
Andrew Vasquez5341e862006-05-17 15:09:16 -07004323 /* Use alternate WWN? */
4324 if (nv->host_p[1] & BIT_7) {
4325 memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
4326 memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
4327 }
4328
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329 /* Prepare nodename */
4330 if ((icb->firmware_options[1] & BIT_6) == 0) {
4331 /*
4332 * Firmware will apply the following mask if the nodename was
4333 * not provided.
4334 */
4335 memcpy(icb->node_name, icb->port_name, WWN_SIZE);
4336 icb->node_name[0] &= 0xF0;
4337 }
4338
4339 /*
4340 * Set host adapter parameters.
4341 */
Saurav Kashyap3ce88662011-07-14 12:00:12 -07004342
4343 /*
4344 * BIT_7 in the host-parameters section allows for modification to
4345 * internal driver logging.
4346 */
Andrew Vasquez01819442006-06-23 16:11:10 -07004347 if (nv->host_p[0] & BIT_7)
Chad Dupuiscfb09192011-11-18 09:03:07 -08004348 ql2xextended_error_logging = QL_DBG_DEFAULT1_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349 ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0);
4350 /* Always load RISC code on non ISP2[12]00 chips. */
4351 if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
4352 ha->flags.disable_risc_code_load = 0;
4353 ha->flags.enable_lip_reset = ((nv->host_p[1] & BIT_1) ? 1 : 0);
4354 ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0);
4355 ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0);
Andrew Vasquez06c22bd2005-08-26 19:09:00 -07004356 ha->flags.enable_led_scheme = (nv->special_options[1] & BIT_4) ? 1 : 0;
Andrew Vasquezd4c760c2006-06-23 16:10:39 -07004357 ha->flags.disable_serdes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358
4359 ha->operating_mode =
4360 (icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4;
4361
4362 memcpy(ha->fw_seriallink_options, nv->seriallink_options,
4363 sizeof(ha->fw_seriallink_options));
4364
4365 /* save HBA serial number */
4366 ha->serial0 = icb->port_name[5];
4367 ha->serial1 = icb->port_name[6];
4368 ha->serial2 = icb->port_name[7];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004369 memcpy(vha->node_name, icb->node_name, WWN_SIZE);
4370 memcpy(vha->port_name, icb->port_name, WWN_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371
Bart Van Asschead950362015-07-09 07:24:08 -07004372 icb->execution_throttle = cpu_to_le16(0xFFFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373
4374 ha->retry_count = nv->retry_count;
4375
4376 /* Set minimum login_timeout to 4 seconds. */
Andrew Vasquez5b914902010-05-28 15:08:30 -07004377 if (nv->login_timeout != ql2xlogintimeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378 nv->login_timeout = ql2xlogintimeout;
4379 if (nv->login_timeout < 4)
4380 nv->login_timeout = 4;
4381 ha->login_timeout = nv->login_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382
Andrew Vasquez00a537b2008-02-28 14:06:11 -08004383 /* Set minimum RATOV to 100 tenths of a second. */
4384 ha->r_a_tov = 100;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386 ha->loop_reset_delay = nv->reset_delay;
4387
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388 /* Link Down Timeout = 0:
4389 *
4390 * When Port Down timer expires we will start returning
4391 * I/O's to OS with "DID_NO_CONNECT".
4392 *
4393 * Link Down Timeout != 0:
4394 *
4395 * The driver waits for the link to come up after link down
4396 * before returning I/Os to OS with "DID_NO_CONNECT".
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07004397 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 if (nv->link_down_timeout == 0) {
4399 ha->loop_down_abort_time =
Andrew Vasquez 354d6b22005-04-23 02:47:27 -04004400 (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401 } else {
4402 ha->link_down_timeout = nv->link_down_timeout;
4403 ha->loop_down_abort_time =
4404 (LOOP_DOWN_TIME - ha->link_down_timeout);
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07004405 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406
Linus Torvalds1da177e2005-04-16 15:20:36 -07004407 /*
4408 * Need enough time to try and get the port back.
4409 */
4410 ha->port_down_retry_count = nv->port_down_retry_count;
4411 if (qlport_down_retry)
4412 ha->port_down_retry_count = qlport_down_retry;
4413 /* Set login_retry_count */
4414 ha->login_retry_count = nv->retry_count;
4415 if (ha->port_down_retry_count == nv->port_down_retry_count &&
4416 ha->port_down_retry_count > 3)
4417 ha->login_retry_count = ha->port_down_retry_count;
4418 else if (ha->port_down_retry_count > (int)ha->login_retry_count)
4419 ha->login_retry_count = ha->port_down_retry_count;
4420 if (ql2xloginretrycount)
4421 ha->login_retry_count = ql2xloginretrycount;
4422
Bart Van Asschead950362015-07-09 07:24:08 -07004423 icb->lun_enables = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424 icb->command_resource_count = 0;
4425 icb->immediate_notify_resource_count = 0;
Bart Van Asschead950362015-07-09 07:24:08 -07004426 icb->timeout = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427
4428 if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
4429 /* Enable RIO */
4430 icb->firmware_options[0] &= ~BIT_3;
4431 icb->add_firmware_options[0] &=
4432 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0);
4433 icb->add_firmware_options[0] |= BIT_2;
4434 icb->response_accumulation_timer = 3;
4435 icb->interrupt_delay_timer = 5;
4436
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004437 vha->flags.process_response_queue = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438 } else {
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07004439 /* Enable ZIO. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004440 if (!vha->flags.init_done) {
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07004441 ha->zio_mode = icb->add_firmware_options[0] &
4442 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
4443 ha->zio_timer = icb->interrupt_delay_timer ?
4444 icb->interrupt_delay_timer: 2;
4445 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446 icb->add_firmware_options[0] &=
4447 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004448 vha->flags.process_response_queue = 0;
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07004449 if (ha->zio_mode != QLA_ZIO_DISABLED) {
andrew.vasquez@qlogic.com4a59f712006-03-09 14:27:39 -08004450 ha->zio_mode = QLA_ZIO_MODE_6;
4451
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004452 ql_log(ql_log_info, vha, 0x0068,
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07004453 "ZIO mode %d enabled; timer delay (%d us).\n",
4454 ha->zio_mode, ha->zio_timer * 100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004455
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07004456 icb->add_firmware_options[0] |= (uint8_t)ha->zio_mode;
4457 icb->interrupt_delay_timer = (uint8_t)ha->zio_timer;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004458 vha->flags.process_response_queue = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459 }
4460 }
4461
David Miller4e08df32007-04-16 12:37:43 -07004462 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004463 ql_log(ql_log_warn, vha, 0x0069,
4464 "NVRAM configuration failed.\n");
David Miller4e08df32007-04-16 12:37:43 -07004465 }
4466 return (rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467}
4468
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04004469static void
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04004470qla2x00_rport_del(void *data)
4471{
4472 fc_port_t *fcport = data;
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08004473 struct fc_rport *rport;
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08004474 unsigned long flags;
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04004475
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08004476 spin_lock_irqsave(fcport->vha->host->host_lock, flags);
Andrew Vasquezac280b62009-08-20 11:06:05 -07004477 rport = fcport->drport ? fcport->drport: fcport->rport;
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08004478 fcport->drport = NULL;
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08004479 spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
Quinn Tran726b8542017-01-19 22:28:00 -08004480 if (rport) {
Quinn Tran83548fe2017-06-02 09:12:01 -07004481 ql_dbg(ql_dbg_disc, fcport->vha, 0x210b,
4482 "%s %8phN. rport %p roles %x\n",
4483 __func__, fcport->port_name, rport,
4484 rport->roles);
Quinn Tran726b8542017-01-19 22:28:00 -08004485
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08004486 fc_remote_port_delete(rport);
Quinn Tran726b8542017-01-19 22:28:00 -08004487 }
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04004488}
4489
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490/**
4491 * qla2x00_alloc_fcport() - Allocate a generic fcport.
Bart Van Assche2db62282018-01-23 16:33:51 -08004492 * @vha: HA context
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493 * @flags: allocation flags
4494 *
4495 * Returns a pointer to the allocated fcport, or NULL, if none available.
4496 */
Giridhar Malavali9a069e12010-01-12 13:02:47 -08004497fc_port_t *
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004498qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499{
4500 fc_port_t *fcport;
4501
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02004502 fcport = kzalloc(sizeof(fc_port_t), flags);
4503 if (!fcport)
4504 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004505
4506 /* Setup fcport template structure. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004507 fcport->vha = vha;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004508 fcport->port_type = FCT_UNKNOWN;
4509 fcport->loop_id = FC_NO_LOOP_ID;
Chad Dupuisec426e12011-03-30 11:46:32 -07004510 qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED);
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07004511 fcport->supported_classes = FC_COS_UNSPECIFIED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512
Quinn Tran726b8542017-01-19 22:28:00 -08004513 fcport->ct_desc.ct_sns = dma_alloc_coherent(&vha->hw->pdev->dev,
4514 sizeof(struct ct_sns_pkt), &fcport->ct_desc.ct_sns_dma,
Quinn Tran6cb32162017-02-13 12:18:29 -08004515 flags);
Quinn Tran726b8542017-01-19 22:28:00 -08004516 fcport->disc_state = DSC_DELETED;
4517 fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
4518 fcport->deleted = QLA_SESS_DELETED;
4519 fcport->login_retry = vha->hw->login_retry_count;
4520 fcport->login_retry = 5;
4521 fcport->logout_on_delete = 1;
4522
4523 if (!fcport->ct_desc.ct_sns) {
Quinn Tran83548fe2017-06-02 09:12:01 -07004524 ql_log(ql_log_warn, vha, 0xd049,
Quinn Tran726b8542017-01-19 22:28:00 -08004525 "Failed to allocate ct_sns request.\n");
4526 kfree(fcport);
4527 fcport = NULL;
4528 }
4529 INIT_WORK(&fcport->del_work, qla24xx_delete_sess_fn);
4530 INIT_LIST_HEAD(&fcport->gnl_entry);
4531 INIT_LIST_HEAD(&fcport->list);
4532
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02004533 return fcport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004534}
4535
Quinn Tran726b8542017-01-19 22:28:00 -08004536void
4537qla2x00_free_fcport(fc_port_t *fcport)
4538{
4539 if (fcport->ct_desc.ct_sns) {
4540 dma_free_coherent(&fcport->vha->hw->pdev->dev,
4541 sizeof(struct ct_sns_pkt), fcport->ct_desc.ct_sns,
4542 fcport->ct_desc.ct_sns_dma);
4543
4544 fcport->ct_desc.ct_sns = NULL;
4545 }
4546 kfree(fcport);
4547}
4548
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549/*
4550 * qla2x00_configure_loop
4551 * Updates Fibre Channel Device Database with what is actually on loop.
4552 *
4553 * Input:
4554 * ha = adapter block pointer.
4555 *
4556 * Returns:
4557 * 0 = success.
4558 * 1 = error.
4559 * 2 = database was full and device was not configured.
4560 */
4561static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004562qla2x00_configure_loop(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004563{
4564 int rval;
4565 unsigned long flags, save_flags;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004566 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567 rval = QLA_SUCCESS;
4568
4569 /* Get Initiator ID */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004570 if (test_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags)) {
4571 rval = qla2x00_configure_hba(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004573 ql_dbg(ql_dbg_disc, vha, 0x2013,
4574 "Unable to configure HBA.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004575 return (rval);
4576 }
4577 }
4578
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004579 save_flags = flags = vha->dpc_flags;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004580 ql_dbg(ql_dbg_disc, vha, 0x2014,
4581 "Configure loop -- dpc flags = 0x%lx.\n", flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582
4583 /*
4584 * If we have both an RSCN and PORT UPDATE pending then handle them
4585 * both at the same time.
4586 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004587 clear_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
4588 clear_bit(RSCN_UPDATE, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589
Michael Hernandez3064ff32009-12-15 21:29:44 -08004590 qla2x00_get_data_rate(vha);
4591
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592 /* Determine what we need to do */
4593 if (ha->current_topology == ISP_CFG_FL &&
4594 (test_bit(LOCAL_LOOP_UPDATE, &flags))) {
4595
Linus Torvalds1da177e2005-04-16 15:20:36 -07004596 set_bit(RSCN_UPDATE, &flags);
4597
4598 } else if (ha->current_topology == ISP_CFG_F &&
4599 (test_bit(LOCAL_LOOP_UPDATE, &flags))) {
4600
Linus Torvalds1da177e2005-04-16 15:20:36 -07004601 set_bit(RSCN_UPDATE, &flags);
4602 clear_bit(LOCAL_LOOP_UPDATE, &flags);
4603
Andrew Vasquez21333b42006-05-17 15:09:56 -07004604 } else if (ha->current_topology == ISP_CFG_N) {
4605 clear_bit(RSCN_UPDATE, &flags);
Quinn Tran9cd883f2017-12-28 12:33:24 -08004606 if (ha->flags.rida_fmt2) {
4607 /* With Rida Format 2, the login is already triggered.
4608 * We know who is on the other side of the wire.
4609 * No need to login to do login to find out or drop into
4610 * qla2x00_configure_local_loop().
4611 */
4612 clear_bit(LOCAL_LOOP_UPDATE, &flags);
4613 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
4614 } else {
4615 if (qla_tgt_mode_enabled(vha)) {
4616 /* allow the other side to start the login */
4617 clear_bit(LOCAL_LOOP_UPDATE, &flags);
4618 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
4619 }
4620 }
Quinn Tran41dc5292017-01-19 22:28:03 -08004621 } else if (ha->current_topology == ISP_CFG_NL) {
4622 clear_bit(RSCN_UPDATE, &flags);
4623 set_bit(LOCAL_LOOP_UPDATE, &flags);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004624 } else if (!vha->flags.online ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07004625 (test_bit(ABORT_ISP_ACTIVE, &flags))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626 set_bit(RSCN_UPDATE, &flags);
4627 set_bit(LOCAL_LOOP_UPDATE, &flags);
4628 }
4629
4630 if (test_bit(LOCAL_LOOP_UPDATE, &flags)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004631 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
4632 ql_dbg(ql_dbg_disc, vha, 0x2015,
4633 "Loop resync needed, failing.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004634 rval = QLA_FUNCTION_FAILED;
Chad Dupuis642ef982012-02-09 11:15:57 -08004635 } else
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004636 rval = qla2x00_configure_local_loop(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004637 }
4638
4639 if (rval == QLA_SUCCESS && test_bit(RSCN_UPDATE, &flags)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004640 if (LOOP_TRANSITION(vha)) {
Quinn Tran83548fe2017-06-02 09:12:01 -07004641 ql_dbg(ql_dbg_disc, vha, 0x2099,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004642 "Needs RSCN update and loop transition.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004643 rval = QLA_FUNCTION_FAILED;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004644 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004645 else
4646 rval = qla2x00_configure_fabric(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647 }
4648
4649 if (rval == QLA_SUCCESS) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004650 if (atomic_read(&vha->loop_down_timer) ||
4651 test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652 rval = QLA_FUNCTION_FAILED;
4653 } else {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004654 atomic_set(&vha->loop_state, LOOP_READY);
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004655 ql_dbg(ql_dbg_disc, vha, 0x2069,
4656 "LOOP READY.\n");
Quinn Tranec7193e2017-03-15 09:48:55 -07004657 ha->flags.fw_init_done = 1;
Dilip Kumar Uppugandla3bb67df2015-12-17 14:57:11 -05004658
4659 /*
4660 * Process any ATIO queue entries that came in
4661 * while we weren't online.
4662 */
Quinn Tranead03852017-01-19 22:28:01 -08004663 if (qla_tgt_mode_enabled(vha) ||
4664 qla_dual_mode_enabled(vha)) {
Dilip Kumar Uppugandla3bb67df2015-12-17 14:57:11 -05004665 if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) {
4666 spin_lock_irqsave(&ha->tgt.atio_lock,
4667 flags);
4668 qlt_24xx_process_atio_queue(vha, 0);
4669 spin_unlock_irqrestore(
4670 &ha->tgt.atio_lock, flags);
4671 } else {
4672 spin_lock_irqsave(&ha->hardware_lock,
4673 flags);
4674 qlt_24xx_process_atio_queue(vha, 1);
4675 spin_unlock_irqrestore(
4676 &ha->hardware_lock, flags);
4677 }
4678 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004679 }
4680 }
4681
4682 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004683 ql_dbg(ql_dbg_disc, vha, 0x206a,
4684 "%s *** FAILED ***.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004685 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004686 ql_dbg(ql_dbg_disc, vha, 0x206b,
4687 "%s: exiting normally.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004688 }
4689
Bjorn Helgaascc3ef7b2008-09-11 21:22:51 -07004690 /* Restore state if a resync event occurred during processing */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004691 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004692 if (test_bit(LOCAL_LOOP_UPDATE, &save_flags))
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004693 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
Andrew Vasquezf4658b62009-06-03 09:55:21 -07004694 if (test_bit(RSCN_UPDATE, &save_flags)) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004695 set_bit(RSCN_UPDATE, &vha->dpc_flags);
Andrew Vasquezf4658b62009-06-03 09:55:21 -07004696 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004697 }
4698
4699 return (rval);
4700}
4701
Duane Grigsbyedd05de2017-10-13 09:34:06 -07004702/*
4703 * N2N Login
4704 * Updates Fibre Channel Device Database with local loop devices.
4705 *
4706 * Input:
4707 * ha = adapter block pointer.
4708 *
4709 * Returns:
4710 */
4711static int qla24xx_n2n_handle_login(struct scsi_qla_host *vha,
4712 fc_port_t *fcport)
4713{
4714 struct qla_hw_data *ha = vha->hw;
4715 int res = QLA_SUCCESS, rval;
4716 int greater_wwpn = 0;
4717 int logged_in = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718
Duane Grigsbyedd05de2017-10-13 09:34:06 -07004719 if (ha->current_topology != ISP_CFG_N)
4720 return res;
4721
4722 if (wwn_to_u64(vha->port_name) >
4723 wwn_to_u64(vha->n2n_port_name)) {
4724 ql_dbg(ql_dbg_disc, vha, 0x2002,
4725 "HBA WWPN is greater %llx > target %llx\n",
4726 wwn_to_u64(vha->port_name),
4727 wwn_to_u64(vha->n2n_port_name));
4728 greater_wwpn = 1;
4729 fcport->d_id.b24 = vha->n2n_id;
4730 }
4731
4732 fcport->loop_id = vha->loop_id;
4733 fcport->fc4f_nvme = 0;
4734 fcport->query = 1;
4735
4736 ql_dbg(ql_dbg_disc, vha, 0x4001,
4737 "Initiate N2N login handler: HBA port_id=%06x loopid=%d\n",
4738 fcport->d_id.b24, vha->loop_id);
4739
4740 /* Fill in member data. */
4741 if (!greater_wwpn) {
4742 rval = qla2x00_get_port_database(vha, fcport, 0);
4743 ql_dbg(ql_dbg_disc, vha, 0x1051,
4744 "Remote login-state (%x/%x) port_id=%06x loop_id=%x, rval=%d\n",
4745 fcport->current_login_state, fcport->last_login_state,
4746 fcport->d_id.b24, fcport->loop_id, rval);
4747
4748 if (((fcport->current_login_state & 0xf) == 0x4) ||
4749 ((fcport->current_login_state & 0xf) == 0x6))
4750 logged_in = 1;
4751 }
4752
4753 if (logged_in || greater_wwpn) {
4754 if (!vha->nvme_local_port && vha->flags.nvme_enabled)
4755 qla_nvme_register_hba(vha);
4756
4757 /* Set connected N_Port d_id */
4758 if (vha->flags.nvme_enabled)
4759 fcport->fc4f_nvme = 1;
4760
4761 fcport->scan_state = QLA_FCPORT_FOUND;
4762 fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
4763 fcport->disc_state = DSC_GNL;
4764 fcport->n2n_flag = 1;
4765 fcport->flags = 3;
4766 vha->hw->flags.gpsc_supported = 0;
4767
4768 if (greater_wwpn) {
4769 ql_dbg(ql_dbg_disc, vha, 0x20e5,
4770 "%s %d PLOGI ELS %8phC\n",
4771 __func__, __LINE__, fcport->port_name);
4772
4773 res = qla24xx_els_dcmd2_iocb(vha, ELS_DCMD_PLOGI,
4774 fcport, fcport->d_id);
4775 }
4776
4777 if (res != QLA_SUCCESS) {
4778 ql_log(ql_log_info, vha, 0xd04d,
4779 "PLOGI Failed: portid=%06x - retrying\n",
4780 fcport->d_id.b24);
4781 res = QLA_SUCCESS;
4782 } else {
4783 /* State 0x6 means FCP PRLI complete */
4784 if ((fcport->current_login_state & 0xf) == 0x6) {
4785 ql_dbg(ql_dbg_disc, vha, 0x2118,
4786 "%s %d %8phC post GPDB work\n",
4787 __func__, __LINE__, fcport->port_name);
4788 fcport->chip_reset =
4789 vha->hw->base_qpair->chip_reset;
4790 qla24xx_post_gpdb_work(vha, fcport, 0);
4791 } else {
4792 ql_dbg(ql_dbg_disc, vha, 0x2118,
4793 "%s %d %8phC post NVMe PRLI\n",
4794 __func__, __LINE__, fcport->port_name);
4795 qla24xx_post_prli_work(vha, fcport);
4796 }
4797 }
4798 } else {
4799 /* Wait for next database change */
4800 set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags);
4801 }
4802
4803 return res;
4804}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004805
4806/*
4807 * qla2x00_configure_local_loop
4808 * Updates Fibre Channel Device Database with local loop devices.
4809 *
4810 * Input:
4811 * ha = adapter block pointer.
4812 *
4813 * Returns:
4814 * 0 = success.
4815 */
4816static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004817qla2x00_configure_local_loop(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004818{
4819 int rval, rval2;
4820 int found_devs;
4821 int found;
4822 fc_port_t *fcport, *new_fcport;
4823
4824 uint16_t index;
4825 uint16_t entries;
4826 char *id_iter;
4827 uint16_t loop_id;
4828 uint8_t domain, area, al_pa;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004829 struct qla_hw_data *ha = vha->hw;
Quinn Tran41dc5292017-01-19 22:28:03 -08004830 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004831
4832 found_devs = 0;
4833 new_fcport = NULL;
Chad Dupuis642ef982012-02-09 11:15:57 -08004834 entries = MAX_FIBRE_DEVICES_LOOP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004835
Linus Torvalds1da177e2005-04-16 15:20:36 -07004836 /* Get list of logged in devices. */
Chad Dupuis642ef982012-02-09 11:15:57 -08004837 memset(ha->gid_list, 0, qla2x00_gid_list_size(ha));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004838 rval = qla2x00_get_id_list(vha, ha->gid_list, ha->gid_list_dma,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004839 &entries);
4840 if (rval != QLA_SUCCESS)
4841 goto cleanup_allocation;
4842
Quinn Tran83548fe2017-06-02 09:12:01 -07004843 ql_dbg(ql_dbg_disc, vha, 0x2011,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004844 "Entries in ID list (%d).\n", entries);
4845 ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2075,
4846 (uint8_t *)ha->gid_list,
4847 entries * sizeof(struct gid_list_info));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004848
Quinn Tran9cd883f2017-12-28 12:33:24 -08004849 list_for_each_entry(fcport, &vha->vp_fcports, list) {
4850 fcport->scan_state = QLA_FCPORT_SCAN;
4851 }
4852
Linus Torvalds1da177e2005-04-16 15:20:36 -07004853 /* Allocate temporary fcport for any new fcports discovered. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004854 new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004855 if (new_fcport == NULL) {
Quinn Tran83548fe2017-06-02 09:12:01 -07004856 ql_log(ql_log_warn, vha, 0x2012,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004857 "Memory allocation failed for fcport.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004858 rval = QLA_MEMORY_ALLOC_FAILED;
4859 goto cleanup_allocation;
4860 }
4861 new_fcport->flags &= ~FCF_FABRIC_DEVICE;
4862
Duane Grigsbyedd05de2017-10-13 09:34:06 -07004863 /* Inititae N2N login. */
4864 if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) {
4865 rval = qla24xx_n2n_handle_login(vha, new_fcport);
4866 if (rval != QLA_SUCCESS)
4867 goto cleanup_allocation;
4868 return QLA_SUCCESS;
4869 }
4870
Linus Torvalds1da177e2005-04-16 15:20:36 -07004871 /* Add devices to port list. */
4872 id_iter = (char *)ha->gid_list;
4873 for (index = 0; index < entries; index++) {
4874 domain = ((struct gid_list_info *)id_iter)->domain;
4875 area = ((struct gid_list_info *)id_iter)->area;
4876 al_pa = ((struct gid_list_info *)id_iter)->al_pa;
Andrew Vasquezabbd8872005-07-06 10:30:05 -07004877 if (IS_QLA2100(ha) || IS_QLA2200(ha))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004878 loop_id = (uint16_t)
4879 ((struct gid_list_info *)id_iter)->loop_id_2100;
Andrew Vasquezabbd8872005-07-06 10:30:05 -07004880 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004881 loop_id = le16_to_cpu(
4882 ((struct gid_list_info *)id_iter)->loop_id);
Andrew Vasquezabbd8872005-07-06 10:30:05 -07004883 id_iter += ha->gid_list_info_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004884
4885 /* Bypass reserved domain fields. */
4886 if ((domain & 0xf0) == 0xf0)
4887 continue;
4888
4889 /* Bypass if not same domain and area of adapter. */
Andrew Vasquezf7d289f2005-08-26 19:08:40 -07004890 if (area && domain &&
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004891 (area != vha->d_id.b.area || domain != vha->d_id.b.domain))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004892 continue;
4893
4894 /* Bypass invalid local loop ID. */
4895 if (loop_id > LAST_LOCAL_LOOP_ID)
4896 continue;
4897
Quinn Tran41dc5292017-01-19 22:28:03 -08004898 memset(new_fcport->port_name, 0, WWN_SIZE);
Arun Easi370d5502012-08-22 14:21:10 -04004899
Linus Torvalds1da177e2005-04-16 15:20:36 -07004900 /* Fill in member data. */
4901 new_fcport->d_id.b.domain = domain;
4902 new_fcport->d_id.b.area = area;
4903 new_fcport->d_id.b.al_pa = al_pa;
4904 new_fcport->loop_id = loop_id;
Quinn Tran9cd883f2017-12-28 12:33:24 -08004905 new_fcport->scan_state = QLA_FCPORT_FOUND;
Quinn Tran41dc5292017-01-19 22:28:03 -08004906
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004907 rval2 = qla2x00_get_port_database(vha, new_fcport, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004908 if (rval2 != QLA_SUCCESS) {
Quinn Tran83548fe2017-06-02 09:12:01 -07004909 ql_dbg(ql_dbg_disc, vha, 0x2097,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004910 "Failed to retrieve fcport information "
4911 "-- get_port_database=%x, loop_id=0x%04x.\n",
4912 rval2, new_fcport->loop_id);
Duane Grigsbyedd05de2017-10-13 09:34:06 -07004913 /* Skip retry if N2N */
4914 if (ha->current_topology != ISP_CFG_N) {
4915 ql_dbg(ql_dbg_disc, vha, 0x2105,
4916 "Scheduling resync.\n");
4917 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
4918 continue;
4919 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920 }
4921
Quinn Tran41dc5292017-01-19 22:28:03 -08004922 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004923 /* Check for matching device in port list. */
4924 found = 0;
4925 fcport = NULL;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004926 list_for_each_entry(fcport, &vha->vp_fcports, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004927 if (memcmp(new_fcport->port_name, fcport->port_name,
4928 WWN_SIZE))
4929 continue;
4930
Shyam Sundarddb9b122009-03-24 09:08:10 -07004931 fcport->flags &= ~FCF_FABRIC_DEVICE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004932 fcport->loop_id = new_fcport->loop_id;
4933 fcport->port_type = new_fcport->port_type;
4934 fcport->d_id.b24 = new_fcport->d_id.b24;
4935 memcpy(fcport->node_name, new_fcport->node_name,
4936 WWN_SIZE);
Quinn Tran9cd883f2017-12-28 12:33:24 -08004937 fcport->scan_state = QLA_FCPORT_FOUND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004938 found++;
4939 break;
4940 }
4941
4942 if (!found) {
4943 /* New device, add to fcports list. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004944 list_add_tail(&new_fcport->list, &vha->vp_fcports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004945
4946 /* Allocate a new replacement fcport. */
4947 fcport = new_fcport;
Quinn Tran41dc5292017-01-19 22:28:03 -08004948
4949 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
4950
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08004951 new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
Quinn Tran41dc5292017-01-19 22:28:03 -08004952
Linus Torvalds1da177e2005-04-16 15:20:36 -07004953 if (new_fcport == NULL) {
Quinn Tran83548fe2017-06-02 09:12:01 -07004954 ql_log(ql_log_warn, vha, 0xd031,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07004955 "Failed to allocate memory for fcport.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004956 rval = QLA_MEMORY_ALLOC_FAILED;
4957 goto cleanup_allocation;
4958 }
Quinn Tran41dc5292017-01-19 22:28:03 -08004959 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004960 new_fcport->flags &= ~FCF_FABRIC_DEVICE;
4961 }
4962
Quinn Tran41dc5292017-01-19 22:28:03 -08004963 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
4964
Andrew Vasquezd8b45212006-10-02 12:00:43 -07004965 /* Base iIDMA settings on HBA port speed. */
Andrew Vasqueza3cbdfa2007-08-13 10:13:18 -07004966 fcport->fp_speed = ha->link_data_rate;
Andrew Vasquezd8b45212006-10-02 12:00:43 -07004967
Linus Torvalds1da177e2005-04-16 15:20:36 -07004968 found_devs++;
4969 }
4970
Quinn Tran9cd883f2017-12-28 12:33:24 -08004971 list_for_each_entry(fcport, &vha->vp_fcports, list) {
4972 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
4973 break;
4974
4975 if (fcport->scan_state == QLA_FCPORT_SCAN) {
4976 if ((qla_dual_mode_enabled(vha) ||
4977 qla_ini_mode_enabled(vha)) &&
4978 atomic_read(&fcport->state) == FCS_ONLINE) {
4979 qla2x00_mark_device_lost(vha, fcport,
4980 ql2xplogiabsentdevice, 0);
4981 if (fcport->loop_id != FC_NO_LOOP_ID &&
4982 (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
4983 fcport->port_type != FCT_INITIATOR &&
4984 fcport->port_type != FCT_BROADCAST) {
4985 ql_dbg(ql_dbg_disc, vha, 0x20f0,
4986 "%s %d %8phC post del sess\n",
4987 __func__, __LINE__,
4988 fcport->port_name);
4989
Quinn Trand8630bb2017-12-28 12:33:43 -08004990 qlt_schedule_sess_for_deletion(fcport);
Quinn Tran9cd883f2017-12-28 12:33:24 -08004991 continue;
4992 }
4993 }
4994 }
4995
4996 if (fcport->scan_state == QLA_FCPORT_FOUND)
4997 qla24xx_fcport_handle_login(vha, fcport);
4998 }
4999
Linus Torvalds1da177e2005-04-16 15:20:36 -07005000cleanup_allocation:
Jesper Juhlc9475cb2005-11-07 01:01:26 -08005001 kfree(new_fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005002
5003 if (rval != QLA_SUCCESS) {
Quinn Tran83548fe2017-06-02 09:12:01 -07005004 ql_dbg(ql_dbg_disc, vha, 0x2098,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005005 "Configure local loop error exit: rval=%x.\n", rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005006 }
5007
Linus Torvalds1da177e2005-04-16 15:20:36 -07005008 return (rval);
5009}
5010
5011static void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005012qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
Andrew Vasquezd8b45212006-10-02 12:00:43 -07005013{
Andrew Vasquezd8b45212006-10-02 12:00:43 -07005014 int rval;
Quinn Tran93f2bd62014-09-25 05:16:53 -04005015 uint16_t mb[MAILBOX_REGISTER_COUNT];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005016 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezd8b45212006-10-02 12:00:43 -07005017
Andrew Vasquezc76f2c02007-07-19 15:05:57 -07005018 if (!IS_IIDMA_CAPABLE(ha))
Andrew Vasquezd8b45212006-10-02 12:00:43 -07005019 return;
5020
Giridhar Malavalic9afb9a2010-09-03 15:20:48 -07005021 if (atomic_read(&fcport->state) != FCS_ONLINE)
5022 return;
5023
Andrew Vasquez39bd9622007-09-20 14:07:34 -07005024 if (fcport->fp_speed == PORT_SPEED_UNKNOWN ||
5025 fcport->fp_speed > ha->link_data_rate)
Andrew Vasquezd8b45212006-10-02 12:00:43 -07005026 return;
5027
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005028 rval = qla2x00_set_idma_speed(vha, fcport->loop_id, fcport->fp_speed,
Andrew Vasqueza3cbdfa2007-08-13 10:13:18 -07005029 mb);
Andrew Vasquezd8b45212006-10-02 12:00:43 -07005030 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005031 ql_dbg(ql_dbg_disc, vha, 0x2004,
Oleksandr Khoshaba7b8335582013-08-27 01:37:27 -04005032 "Unable to adjust iIDMA %8phN -- %04x %x %04x %04x.\n",
5033 fcport->port_name, rval, fcport->fp_speed, mb[0], mb[1]);
Andrew Vasquezd8b45212006-10-02 12:00:43 -07005034 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005035 ql_dbg(ql_dbg_disc, vha, 0x2005,
Quinn Tran33b28352018-03-20 23:09:40 -07005036 "iIDMA adjusted to %s GB/s (%X) on %8phN.\n",
Joe Carnucciod0297c92012-11-21 02:40:40 -05005037 qla2x00_get_link_speed_str(ha, fcport->fp_speed),
Quinn Tran33b28352018-03-20 23:09:40 -07005038 fcport->fp_speed, fcport->port_name);
Andrew Vasquezd8b45212006-10-02 12:00:43 -07005039 }
5040}
5041
Quinn Trancc28e0a2018-05-01 09:01:48 -07005042void qla_do_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport)
5043{
5044 qla2x00_iidma_fcport(vha, fcport);
5045 qla24xx_update_fcport_fcp_prio(vha, fcport);
5046}
5047
5048int qla_post_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport)
5049{
5050 struct qla_work_evt *e;
5051
5052 e = qla2x00_alloc_work(vha, QLA_EVT_IIDMA);
5053 if (!e)
5054 return QLA_FUNCTION_FAILED;
5055
5056 e->u.fcport.fcport = fcport;
5057 return qla2x00_post_work(vha, e);
5058}
5059
Quinn Tran726b8542017-01-19 22:28:00 -08005060/* qla2x00_reg_remote_port is reserved for Initiator Mode only.*/
Adrian Bunk23be3312006-11-24 02:46:01 +01005061static void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005062qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
8482e1182005-04-17 15:04:54 -05005063{
5064 struct fc_rport_identifiers rport_ids;
bdf79622005-04-17 15:06:53 -05005065 struct fc_rport *rport;
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08005066 unsigned long flags;
8482e1182005-04-17 15:04:54 -05005067
Andrew Vasquezf8b02a82005-08-31 15:21:20 -07005068 rport_ids.node_name = wwn_to_u64(fcport->node_name);
5069 rport_ids.port_name = wwn_to_u64(fcport->port_name);
8482e1182005-04-17 15:04:54 -05005070 rport_ids.port_id = fcport->d_id.b.domain << 16 |
5071 fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
5072 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005073 fcport->rport = rport = fc_remote_port_add(vha->host, 0, &rport_ids);
Andrew Vasquez77d74142005-07-08 18:00:36 -07005074 if (!rport) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005075 ql_log(ql_log_warn, vha, 0x2006,
5076 "Unable to allocate fc remote port.\n");
Andrew Vasquez77d74142005-07-08 18:00:36 -07005077 return;
5078 }
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04005079
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08005080 spin_lock_irqsave(fcport->vha->host->host_lock, flags);
James.Smart@Emulex.Com19a7b4a2005-10-18 12:03:35 -04005081 *((fc_port_t **)rport->dd_data) = fcport;
Madhuranath Iyengar044d78e2011-01-28 15:17:56 -08005082 spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08005083
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07005084 rport->supported_classes = fcport->supported_classes;
Andrew Vasquez77d74142005-07-08 18:00:36 -07005085
5086 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
8482e1182005-04-17 15:04:54 -05005087 if (fcport->port_type == FCT_INITIATOR)
5088 rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
5089 if (fcport->port_type == FCT_TARGET)
5090 rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
Quinn Tran726b8542017-01-19 22:28:00 -08005091
Quinn Tran83548fe2017-06-02 09:12:01 -07005092 ql_dbg(ql_dbg_disc, vha, 0x20ee,
5093 "%s %8phN. rport %p is %s mode\n",
5094 __func__, fcport->port_name, rport,
5095 (fcport->port_type == FCT_TARGET) ? "tgt" : "ini");
Quinn Tran726b8542017-01-19 22:28:00 -08005096
Andrew Vasquez77d74142005-07-08 18:00:36 -07005097 fc_remote_port_rolechg(rport, rport_ids.roles);
8482e1182005-04-17 15:04:54 -05005098}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005099
5100/*
Adrian Bunk23be3312006-11-24 02:46:01 +01005101 * qla2x00_update_fcport
5102 * Updates device on list.
5103 *
5104 * Input:
5105 * ha = adapter block pointer.
5106 * fcport = port structure pointer.
5107 *
5108 * Return:
5109 * 0 - Success
5110 * BIT_0 - error
5111 *
5112 * Context:
5113 * Kernel context.
5114 */
5115void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005116qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
Adrian Bunk23be3312006-11-24 02:46:01 +01005117{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005118 fcport->vha = vha;
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04005119
Quinn Tran726b8542017-01-19 22:28:00 -08005120 if (IS_SW_RESV_ADDR(fcport->d_id))
5121 return;
5122
Quinn Tran83548fe2017-06-02 09:12:01 -07005123 ql_dbg(ql_dbg_disc, vha, 0x20ef, "%s %8phC\n",
Quinn Tran726b8542017-01-19 22:28:00 -08005124 __func__, fcport->port_name);
5125
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04005126 if (IS_QLAFX00(vha->hw)) {
5127 qla2x00_set_fcport_state(fcport, FCS_ONLINE);
Quinn Trancc28e0a2018-05-01 09:01:48 -07005128 } else {
5129 fcport->login_retry = 0;
5130 fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
5131 fcport->disc_state = DSC_LOGIN_COMPLETE;
5132 fcport->deleted = 0;
5133 fcport->logout_on_delete = 1;
5134 qla2x00_set_fcport_state(fcport, FCS_ONLINE);
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04005135 }
Adrian Bunk23be3312006-11-24 02:46:01 +01005136
Darren Trappdbe18012018-03-20 23:09:31 -07005137 qla2x00_set_fcport_state(fcport, FCS_ONLINE);
5138 qla2x00_iidma_fcport(vha, fcport);
5139
Duane Grigsbye84067d2017-06-21 13:48:43 -07005140 if (fcport->fc4f_nvme) {
5141 qla_nvme_register_remote(vha, fcport);
5142 return;
5143 }
5144
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08005145 qla24xx_update_fcport_fcp_prio(vha, fcport);
Alexei Potashnikd20ed912015-07-14 16:00:47 -04005146
Quinn Tran726b8542017-01-19 22:28:00 -08005147 switch (vha->host->active_mode) {
5148 case MODE_INITIATOR:
Alexei Potashnikd20ed912015-07-14 16:00:47 -04005149 qla2x00_reg_remote_port(vha, fcport);
Quinn Tran726b8542017-01-19 22:28:00 -08005150 break;
5151 case MODE_TARGET:
5152 if (!vha->vha_tgt.qla_tgt->tgt_stop &&
5153 !vha->vha_tgt.qla_tgt->tgt_stopped)
5154 qlt_fc_port_added(vha, fcport);
5155 break;
5156 case MODE_DUAL:
5157 qla2x00_reg_remote_port(vha, fcport);
5158 if (!vha->vha_tgt.qla_tgt->tgt_stop &&
5159 !vha->vha_tgt.qla_tgt->tgt_stopped)
5160 qlt_fc_port_added(vha, fcport);
5161 break;
5162 default:
5163 break;
Alexei Potashnikd20ed912015-07-14 16:00:47 -04005164 }
Quinn Trancc28e0a2018-05-01 09:01:48 -07005165
5166 if (IS_IIDMA_CAPABLE(vha->hw) && vha->hw->flags.gpsc_supported) {
5167 if (fcport->id_changed) {
5168 fcport->id_changed = 0;
5169 ql_dbg(ql_dbg_disc, vha, 0x20d7,
5170 "%s %d %8phC post gfpnid fcp_cnt %d\n",
5171 __func__, __LINE__, fcport->port_name,
5172 vha->fcport_count);
5173 qla24xx_post_gfpnid_work(vha, fcport);
5174 } else {
5175 ql_dbg(ql_dbg_disc, vha, 0x20d7,
5176 "%s %d %8phC post gpsc fcp_cnt %d\n",
5177 __func__, __LINE__, fcport->port_name,
5178 vha->fcport_count);
5179 qla24xx_post_gpsc_work(vha, fcport);
5180 }
5181 }
Adrian Bunk23be3312006-11-24 02:46:01 +01005182}
5183
5184/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005185 * qla2x00_configure_fabric
5186 * Setup SNS devices with loop ID's.
5187 *
5188 * Input:
5189 * ha = adapter block pointer.
5190 *
5191 * Returns:
5192 * 0 = success.
5193 * BIT_0 = error
5194 */
5195static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005196qla2x00_configure_fabric(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005197{
Arun Easib3b02e62012-02-09 11:15:39 -08005198 int rval;
Quinn Tran726b8542017-01-19 22:28:00 -08005199 fc_port_t *fcport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005200 uint16_t mb[MAILBOX_REGISTER_COUNT];
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005201 uint16_t loop_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005202 LIST_HEAD(new_fcports);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005203 struct qla_hw_data *ha = vha->hw;
Alexei Potashnikdf673272015-07-14 16:00:46 -04005204 int discovery_gen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005205
5206 /* If FL port exists, then SNS is present */
Andrew Vasqueze4289242007-07-19 15:05:56 -07005207 if (IS_FWI2_CAPABLE(ha))
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005208 loop_id = NPH_F_PORT;
5209 else
5210 loop_id = SNS_FL_PORT;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005211 rval = qla2x00_get_port_name(vha, loop_id, vha->fabric_node_name, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005212 if (rval != QLA_SUCCESS) {
Quinn Tran83548fe2017-06-02 09:12:01 -07005213 ql_dbg(ql_dbg_disc, vha, 0x20a0,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005214 "MBX_GET_PORT_NAME failed, No FL Port.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005215
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005216 vha->device_flags &= ~SWITCH_FOUND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005217 return (QLA_SUCCESS);
5218 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005219 vha->device_flags |= SWITCH_FOUND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005220
Quinn Tran41dc5292017-01-19 22:28:03 -08005221
5222 if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) {
5223 rval = qla2x00_send_change_request(vha, 0x3, 0);
5224 if (rval != QLA_SUCCESS)
5225 ql_log(ql_log_warn, vha, 0x121,
5226 "Failed to enable receiving of RSCN requests: 0x%x.\n",
5227 rval);
5228 }
5229
5230
Linus Torvalds1da177e2005-04-16 15:20:36 -07005231 do {
Quinn Tran726b8542017-01-19 22:28:00 -08005232 qla2x00_mgmt_svr_login(vha);
5233
Andrew Vasquezcca53352005-08-26 19:08:30 -07005234 /* FDMI support. */
5235 if (ql2xfdmienable &&
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005236 test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags))
5237 qla2x00_fdmi_register(vha);
Andrew Vasquezcca53352005-08-26 19:08:30 -07005238
Linus Torvalds1da177e2005-04-16 15:20:36 -07005239 /* Ensure we are logged into the SNS. */
Joe Carnuccioa14c7712017-08-23 15:05:12 -07005240 loop_id = NPH_SNS_LID(ha);
Chad Dupuis0b91d112012-02-09 11:15:42 -08005241 rval = ha->isp_ops->fabric_login(vha, loop_id, 0xff, 0xff,
5242 0xfc, mb, BIT_1|BIT_0);
Joe Carnuccioa14c7712017-08-23 15:05:12 -07005243 if (rval != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {
5244 ql_dbg(ql_dbg_disc, vha, 0x20a1,
5245 "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x (%x).\n",
5246 loop_id, mb[0], mb[1], mb[2], mb[6], mb[7], rval);
Chad Dupuis0b91d112012-02-09 11:15:42 -08005247 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
Joe Carnuccioe452ceb2013-02-08 01:57:56 -05005248 return rval;
Chad Dupuis0b91d112012-02-09 11:15:42 -08005249 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005250 if (test_and_clear_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags)) {
5251 if (qla2x00_rft_id(vha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005252 /* EMPTY */
Quinn Tran83548fe2017-06-02 09:12:01 -07005253 ql_dbg(ql_dbg_disc, vha, 0x20a2,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005254 "Register FC-4 TYPE failed.\n");
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005255 if (test_bit(LOOP_RESYNC_NEEDED,
5256 &vha->dpc_flags))
5257 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258 }
Duane Grigsbyd3bae932017-06-21 13:48:44 -07005259 if (qla2x00_rff_id(vha, FC4_TYPE_FCP_SCSI)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005260 /* EMPTY */
Quinn Tran83548fe2017-06-02 09:12:01 -07005261 ql_dbg(ql_dbg_disc, vha, 0x209a,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005262 "Register FC-4 Features failed.\n");
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005263 if (test_bit(LOOP_RESYNC_NEEDED,
5264 &vha->dpc_flags))
5265 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005266 }
Duane Grigsbyd3bae932017-06-21 13:48:44 -07005267 if (vha->flags.nvme_enabled) {
5268 if (qla2x00_rff_id(vha, FC_TYPE_NVME)) {
5269 ql_dbg(ql_dbg_disc, vha, 0x2049,
5270 "Register NVME FC Type Features failed.\n");
5271 }
5272 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005273 if (qla2x00_rnn_id(vha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005274 /* EMPTY */
Quinn Tran83548fe2017-06-02 09:12:01 -07005275 ql_dbg(ql_dbg_disc, vha, 0x2104,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005276 "Register Node Name failed.\n");
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005277 if (test_bit(LOOP_RESYNC_NEEDED,
5278 &vha->dpc_flags))
5279 break;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005280 } else if (qla2x00_rsnn_nn(vha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005281 /* EMPTY */
Quinn Tran83548fe2017-06-02 09:12:01 -07005282 ql_dbg(ql_dbg_disc, vha, 0x209b,
Colin Ian King0bf0efa2017-06-30 14:47:41 +01005283 "Register Symbolic Node Name failed.\n");
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005284 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
5285 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005286 }
5287 }
5288
Joe Carnuccio827210b2013-02-08 01:57:57 -05005289
Alexei Potashnikdf673272015-07-14 16:00:46 -04005290 /* Mark the time right before querying FW for connected ports.
5291 * This process is long, asynchronous and by the time it's done,
5292 * collected information might not be accurate anymore. E.g.
5293 * disconnected port might have re-connected and a brand new
5294 * session has been created. In this case session's generation
5295 * will be newer than discovery_gen. */
5296 qlt_do_generation_tick(vha, &discovery_gen);
5297
Quinn Trana4239942017-12-28 12:33:26 -08005298 if (USE_ASYNC_SCAN(ha)) {
Quinn Tran33b28352018-03-20 23:09:40 -07005299 rval = qla24xx_async_gpnft(vha, FC4_TYPE_FCP_SCSI,
5300 NULL);
Quinn Trana4239942017-12-28 12:33:26 -08005301 if (rval)
5302 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
5303 } else {
Quinn Tranf352eeb2017-12-28 12:33:35 -08005304 list_for_each_entry(fcport, &vha->vp_fcports, list)
5305 fcport->scan_state = QLA_FCPORT_SCAN;
5306
Quinn Trana4239942017-12-28 12:33:26 -08005307 rval = qla2x00_find_all_fabric_devs(vha);
5308 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005309 if (rval != QLA_SUCCESS)
5310 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005311 } while (0);
5312
Duane Grigsbye84067d2017-06-21 13:48:43 -07005313 if (!vha->nvme_local_port && vha->flags.nvme_enabled)
5314 qla_nvme_register_hba(vha);
5315
Quinn Tran726b8542017-01-19 22:28:00 -08005316 if (rval)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005317 ql_dbg(ql_dbg_disc, vha, 0x2068,
5318 "Configure fabric error exit rval=%d.\n", rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005319
5320 return (rval);
5321}
5322
Linus Torvalds1da177e2005-04-16 15:20:36 -07005323/*
5324 * qla2x00_find_all_fabric_devs
5325 *
5326 * Input:
5327 * ha = adapter block pointer.
5328 * dev = database device entry pointer.
5329 *
5330 * Returns:
5331 * 0 = success.
5332 *
5333 * Context:
5334 * Kernel context.
5335 */
5336static int
Quinn Tran726b8542017-01-19 22:28:00 -08005337qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005338{
5339 int rval;
5340 uint16_t loop_id;
Quinn Tran726b8542017-01-19 22:28:00 -08005341 fc_port_t *fcport, *new_fcport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005342 int found;
5343
5344 sw_info_t *swl;
5345 int swl_idx;
5346 int first_dev, last_dev;
Mike Waychison1516ef42010-05-04 15:01:31 -07005347 port_id_t wrap = {}, nxt_d_id;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005348 struct qla_hw_data *ha = vha->hw;
Chad Dupuisbb4cf5b2013-02-08 01:58:01 -05005349 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Quinn Tran726b8542017-01-19 22:28:00 -08005350 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005351
5352 rval = QLA_SUCCESS;
5353
5354 /* Try GID_PT to get device list, else GAN. */
Andrew Vasquez7a677352012-02-09 11:15:56 -08005355 if (!ha->swl)
Chad Dupuis642ef982012-02-09 11:15:57 -08005356 ha->swl = kcalloc(ha->max_fibre_devices, sizeof(sw_info_t),
Andrew Vasquez7a677352012-02-09 11:15:56 -08005357 GFP_KERNEL);
5358 swl = ha->swl;
Mariusz Kozlowskibbfbbbc2007-08-11 10:13:24 +02005359 if (!swl) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005360 /*EMPTY*/
Quinn Tran83548fe2017-06-02 09:12:01 -07005361 ql_dbg(ql_dbg_disc, vha, 0x209c,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005362 "GID_PT allocations failed, fallback on GA_NXT.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005363 } else {
Chad Dupuis642ef982012-02-09 11:15:57 -08005364 memset(swl, 0, ha->max_fibre_devices * sizeof(sw_info_t));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005365 if (qla2x00_gid_pt(vha, swl) != QLA_SUCCESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005366 swl = NULL;
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005367 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
5368 return rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005369 } else if (qla2x00_gpn_id(vha, swl) != QLA_SUCCESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005370 swl = NULL;
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005371 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
5372 return rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005373 } else if (qla2x00_gnn_id(vha, swl) != QLA_SUCCESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005374 swl = NULL;
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005375 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
5376 return rval;
Quinn Tran726b8542017-01-19 22:28:00 -08005377 } else if (qla2x00_gfpn_id(vha, swl) != QLA_SUCCESS) {
5378 swl = NULL;
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005379 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
5380 return rval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005381 }
Chad Dupuise8c72ba2010-07-23 15:28:25 +05005382
5383 /* If other queries succeeded probe for FC-4 type */
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005384 if (swl) {
Chad Dupuise8c72ba2010-07-23 15:28:25 +05005385 qla2x00_gff_id(vha, swl);
Quinn Tranb98ae0d2017-06-02 09:12:00 -07005386 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
5387 return rval;
5388 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005389 }
5390 swl_idx = 0;
5391
5392 /* Allocate temporary fcport for any new fcports discovered. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005393 new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005394 if (new_fcport == NULL) {
Quinn Tran83548fe2017-06-02 09:12:01 -07005395 ql_log(ql_log_warn, vha, 0x209d,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005396 "Failed to allocate memory for fcport.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005397 return (QLA_MEMORY_ALLOC_FAILED);
5398 }
5399 new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005400 /* Set start port ID scan at adapter ID. */
5401 first_dev = 1;
5402 last_dev = 0;
5403
5404 /* Starting free loop ID. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005405 loop_id = ha->min_external_loopid;
5406 for (; loop_id <= ha->max_loop_id; loop_id++) {
5407 if (qla2x00_is_reserved_id(vha, loop_id))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005408 continue;
5409
Giridhar Malavali3a6478d2010-05-28 15:08:20 -07005410 if (ha->current_topology == ISP_CFG_FL &&
5411 (atomic_read(&vha->loop_down_timer) ||
5412 LOOP_TRANSITION(vha))) {
Andrew Vasquezbb2d52b2010-02-18 10:07:27 -08005413 atomic_set(&vha->loop_down_timer, 0);
5414 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
5415 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005416 break;
Andrew Vasquezbb2d52b2010-02-18 10:07:27 -08005417 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005418
5419 if (swl != NULL) {
5420 if (last_dev) {
5421 wrap.b24 = new_fcport->d_id.b24;
5422 } else {
5423 new_fcport->d_id.b24 = swl[swl_idx].d_id.b24;
5424 memcpy(new_fcport->node_name,
5425 swl[swl_idx].node_name, WWN_SIZE);
5426 memcpy(new_fcport->port_name,
5427 swl[swl_idx].port_name, WWN_SIZE);
Andrew Vasquezd8b45212006-10-02 12:00:43 -07005428 memcpy(new_fcport->fabric_port_name,
5429 swl[swl_idx].fabric_port_name, WWN_SIZE);
5430 new_fcport->fp_speed = swl[swl_idx].fp_speed;
Chad Dupuise8c72ba2010-07-23 15:28:25 +05005431 new_fcport->fc4_type = swl[swl_idx].fc4_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005432
Duane Grigsbya5d42f42017-06-21 13:48:41 -07005433 new_fcport->nvme_flag = 0;
Darren Trap1a28faa2017-08-30 10:16:48 -07005434 new_fcport->fc4f_nvme = 0;
Duane Grigsbya5d42f42017-06-21 13:48:41 -07005435 if (vha->flags.nvme_enabled &&
5436 swl[swl_idx].fc4f_nvme) {
5437 new_fcport->fc4f_nvme =
5438 swl[swl_idx].fc4f_nvme;
5439 ql_log(ql_log_info, vha, 0x2131,
5440 "FOUND: NVME port %8phC as FC Type 28h\n",
5441 new_fcport->port_name);
5442 }
5443
Linus Torvalds1da177e2005-04-16 15:20:36 -07005444 if (swl[swl_idx].d_id.b.rsvd_1 != 0) {
5445 last_dev = 1;
5446 }
5447 swl_idx++;
5448 }
5449 } else {
5450 /* Send GA_NXT to the switch */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005451 rval = qla2x00_ga_nxt(vha, new_fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005452 if (rval != QLA_SUCCESS) {
Quinn Tran83548fe2017-06-02 09:12:01 -07005453 ql_log(ql_log_warn, vha, 0x209e,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005454 "SNS scan failed -- assuming "
5455 "zero-entry result.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005456 rval = QLA_SUCCESS;
5457 break;
5458 }
5459 }
5460
5461 /* If wrap on switch device list, exit. */
5462 if (first_dev) {
5463 wrap.b24 = new_fcport->d_id.b24;
5464 first_dev = 0;
5465 } else if (new_fcport->d_id.b24 == wrap.b24) {
Quinn Tran83548fe2017-06-02 09:12:01 -07005466 ql_dbg(ql_dbg_disc, vha, 0x209f,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005467 "Device wrap (%02x%02x%02x).\n",
5468 new_fcport->d_id.b.domain,
5469 new_fcport->d_id.b.area,
5470 new_fcport->d_id.b.al_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005471 break;
5472 }
5473
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07005474 /* Bypass if same physical adapter. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005475 if (new_fcport->d_id.b24 == base_vha->d_id.b24)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005476 continue;
5477
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07005478 /* Bypass virtual ports of the same host. */
Chad Dupuisbb4cf5b2013-02-08 01:58:01 -05005479 if (qla2x00_is_a_vp_did(vha, new_fcport->d_id.b24))
5480 continue;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07005481
Andrew Vasquezf7d289f2005-08-26 19:08:40 -07005482 /* Bypass if same domain and area of adapter. */
5483 if (((new_fcport->d_id.b24 & 0xffff00) ==
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005484 (vha->d_id.b24 & 0xffff00)) && ha->current_topology ==
Andrew Vasquezf7d289f2005-08-26 19:08:40 -07005485 ISP_CFG_FL)
5486 continue;
5487
Linus Torvalds1da177e2005-04-16 15:20:36 -07005488 /* Bypass reserved domain fields. */
5489 if ((new_fcport->d_id.b.domain & 0xf0) == 0xf0)
5490 continue;
5491
Chad Dupuise8c72ba2010-07-23 15:28:25 +05005492 /* Bypass ports whose FCP-4 type is not FCP_SCSI */
Chad Dupuis4da26e12010-10-15 11:27:40 -07005493 if (ql2xgffidenable &&
5494 (new_fcport->fc4_type != FC4_TYPE_FCP_SCSI &&
5495 new_fcport->fc4_type != FC4_TYPE_UNKNOWN))
Chad Dupuise8c72ba2010-07-23 15:28:25 +05005496 continue;
5497
Quinn Tran726b8542017-01-19 22:28:00 -08005498 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
5499
Linus Torvalds1da177e2005-04-16 15:20:36 -07005500 /* Locate matching device in database. */
5501 found = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005502 list_for_each_entry(fcport, &vha->vp_fcports, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005503 if (memcmp(new_fcport->port_name, fcport->port_name,
5504 WWN_SIZE))
5505 continue;
5506
Joe Carnuccio827210b2013-02-08 01:57:57 -05005507 fcport->scan_state = QLA_FCPORT_FOUND;
Arun Easib3b02e62012-02-09 11:15:39 -08005508
Linus Torvalds1da177e2005-04-16 15:20:36 -07005509 found++;
5510
Andrew Vasquezd8b45212006-10-02 12:00:43 -07005511 /* Update port state. */
5512 memcpy(fcport->fabric_port_name,
5513 new_fcport->fabric_port_name, WWN_SIZE);
5514 fcport->fp_speed = new_fcport->fp_speed;
5515
Linus Torvalds1da177e2005-04-16 15:20:36 -07005516 /*
Roland Dreierb2032fd2015-07-14 16:00:42 -04005517 * If address the same and state FCS_ONLINE
5518 * (or in target mode), nothing changed.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005519 */
5520 if (fcport->d_id.b24 == new_fcport->d_id.b24 &&
Roland Dreierb2032fd2015-07-14 16:00:42 -04005521 (atomic_read(&fcport->state) == FCS_ONLINE ||
Quinn Tran726b8542017-01-19 22:28:00 -08005522 (vha->host->active_mode == MODE_TARGET))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005523 break;
5524 }
5525
5526 /*
5527 * If device was not a fabric device before.
5528 */
5529 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
5530 fcport->d_id.b24 = new_fcport->d_id.b24;
Chad Dupuis5f16b332012-08-22 14:21:00 -04005531 qla2x00_clear_loop_id(fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005532 fcport->flags |= (FCF_FABRIC_DEVICE |
5533 FCF_LOGIN_NEEDED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005534 break;
5535 }
5536
5537 /*
5538 * Port ID changed or device was marked to be updated;
5539 * Log it out if still logged in and mark it for
5540 * relogin later.
5541 */
Quinn Tran726b8542017-01-19 22:28:00 -08005542 if (qla_tgt_mode_enabled(base_vha)) {
Roland Dreierb2032fd2015-07-14 16:00:42 -04005543 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf080,
5544 "port changed FC ID, %8phC"
5545 " old %x:%x:%x (loop_id 0x%04x)-> new %x:%x:%x\n",
5546 fcport->port_name,
5547 fcport->d_id.b.domain,
5548 fcport->d_id.b.area,
5549 fcport->d_id.b.al_pa,
5550 fcport->loop_id,
5551 new_fcport->d_id.b.domain,
5552 new_fcport->d_id.b.area,
5553 new_fcport->d_id.b.al_pa);
5554 fcport->d_id.b24 = new_fcport->d_id.b24;
5555 break;
5556 }
5557
Linus Torvalds1da177e2005-04-16 15:20:36 -07005558 fcport->d_id.b24 = new_fcport->d_id.b24;
5559 fcport->flags |= FCF_LOGIN_NEEDED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005560 break;
5561 }
5562
Darren Trapp9dd96862018-03-20 23:09:32 -07005563 if (fcport->fc4f_nvme) {
5564 if (fcport->disc_state == DSC_DELETE_PEND) {
5565 fcport->disc_state = DSC_GNL;
5566 vha->fcport_count--;
5567 fcport->login_succ = 0;
5568 }
5569 }
5570
Quinn Tran726b8542017-01-19 22:28:00 -08005571 if (found) {
5572 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005573 continue;
Quinn Tran726b8542017-01-19 22:28:00 -08005574 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005575 /* If device was not in our fcports list, then add it. */
Roland Dreierb2032fd2015-07-14 16:00:42 -04005576 new_fcport->scan_state = QLA_FCPORT_FOUND;
Quinn Tran726b8542017-01-19 22:28:00 -08005577 list_add_tail(&new_fcport->list, &vha->vp_fcports);
5578
5579 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
5580
Linus Torvalds1da177e2005-04-16 15:20:36 -07005581
5582 /* Allocate a new replacement fcport. */
5583 nxt_d_id.b24 = new_fcport->d_id.b24;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005584 new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005585 if (new_fcport == NULL) {
Quinn Tran83548fe2017-06-02 09:12:01 -07005586 ql_log(ql_log_warn, vha, 0xd032,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005587 "Memory allocation failed for fcport.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005588 return (QLA_MEMORY_ALLOC_FAILED);
5589 }
5590 new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED);
5591 new_fcport->d_id.b24 = nxt_d_id.b24;
5592 }
5593
Quinn Tran726b8542017-01-19 22:28:00 -08005594 qla2x00_free_fcport(new_fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005595
Quinn Tran726b8542017-01-19 22:28:00 -08005596 /*
5597 * Logout all previous fabric dev marked lost, except FCP2 devices.
5598 */
5599 list_for_each_entry(fcport, &vha->vp_fcports, list) {
5600 if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
5601 break;
5602
5603 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
5604 (fcport->flags & FCF_LOGIN_NEEDED) == 0)
5605 continue;
5606
5607 if (fcport->scan_state == QLA_FCPORT_SCAN) {
5608 if ((qla_dual_mode_enabled(vha) ||
5609 qla_ini_mode_enabled(vha)) &&
5610 atomic_read(&fcport->state) == FCS_ONLINE) {
5611 qla2x00_mark_device_lost(vha, fcport,
5612 ql2xplogiabsentdevice, 0);
5613 if (fcport->loop_id != FC_NO_LOOP_ID &&
5614 (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
5615 fcport->port_type != FCT_INITIATOR &&
5616 fcport->port_type != FCT_BROADCAST) {
Quinn Tran83548fe2017-06-02 09:12:01 -07005617 ql_dbg(ql_dbg_disc, vha, 0x20f0,
Quinn Tran726b8542017-01-19 22:28:00 -08005618 "%s %d %8phC post del sess\n",
5619 __func__, __LINE__,
5620 fcport->port_name);
Quinn Trand8630bb2017-12-28 12:33:43 -08005621 qlt_schedule_sess_for_deletion(fcport);
Quinn Tran726b8542017-01-19 22:28:00 -08005622 continue;
5623 }
5624 }
5625 }
5626
5627 if (fcport->scan_state == QLA_FCPORT_FOUND)
5628 qla24xx_fcport_handle_login(vha, fcport);
5629 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005630 return (rval);
5631}
5632
5633/*
5634 * qla2x00_find_new_loop_id
5635 * Scan through our port list and find a new usable loop ID.
5636 *
5637 * Input:
5638 * ha: adapter state pointer.
5639 * dev: port structure pointer.
5640 *
5641 * Returns:
5642 * qla2x00 local function return status code.
5643 *
5644 * Context:
5645 * Kernel context.
5646 */
Joe Carnuccio03bcfb52011-03-30 11:46:27 -07005647int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005648qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005649{
5650 int rval;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005651 struct qla_hw_data *ha = vha->hw;
Arun Easifeafb7b2010-09-03 14:57:00 -07005652 unsigned long flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005653
5654 rval = QLA_SUCCESS;
5655
Chad Dupuis5f16b332012-08-22 14:21:00 -04005656 spin_lock_irqsave(&ha->vport_slock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005657
Chad Dupuis5f16b332012-08-22 14:21:00 -04005658 dev->loop_id = find_first_zero_bit(ha->loop_id_map,
5659 LOOPID_MAP_SIZE);
5660 if (dev->loop_id >= LOOPID_MAP_SIZE ||
5661 qla2x00_is_reserved_id(vha, dev->loop_id)) {
5662 dev->loop_id = FC_NO_LOOP_ID;
5663 rval = QLA_FUNCTION_FAILED;
5664 } else
5665 set_bit(dev->loop_id, ha->loop_id_map);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005666
Chad Dupuis5f16b332012-08-22 14:21:00 -04005667 spin_unlock_irqrestore(&ha->vport_slock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005668
Chad Dupuis5f16b332012-08-22 14:21:00 -04005669 if (rval == QLA_SUCCESS)
5670 ql_dbg(ql_dbg_disc, dev->vha, 0x2086,
5671 "Assigning new loopid=%x, portid=%x.\n",
5672 dev->loop_id, dev->d_id.b24);
5673 else
5674 ql_log(ql_log_warn, dev->vha, 0x2087,
5675 "No loop_id's available, portid=%x.\n",
5676 dev->d_id.b24);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005677
5678 return (rval);
5679}
5680
Linus Torvalds1da177e2005-04-16 15:20:36 -07005681
5682/*
5683 * qla2x00_fabric_login
5684 * Issue fabric login command.
5685 *
5686 * Input:
5687 * ha = adapter block pointer.
5688 * device = pointer to FC device type structure.
5689 *
5690 * Returns:
5691 * 0 - Login successfully
5692 * 1 - Login failed
5693 * 2 - Initiator device
5694 * 3 - Fatal error
5695 */
5696int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005697qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005698 uint16_t *next_loopid)
5699{
5700 int rval;
5701 int retry;
5702 uint16_t tmp_loopid;
5703 uint16_t mb[MAILBOX_REGISTER_COUNT];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005704 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005705
5706 retry = 0;
5707 tmp_loopid = 0;
5708
5709 for (;;) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005710 ql_dbg(ql_dbg_disc, vha, 0x2000,
5711 "Trying Fabric Login w/loop id 0x%04x for port "
5712 "%02x%02x%02x.\n",
5713 fcport->loop_id, fcport->d_id.b.domain,
5714 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005715
5716 /* Login fcport on switch. */
Chad Dupuis0b91d112012-02-09 11:15:42 -08005717 rval = ha->isp_ops->fabric_login(vha, fcport->loop_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005718 fcport->d_id.b.domain, fcport->d_id.b.area,
5719 fcport->d_id.b.al_pa, mb, BIT_0);
Chad Dupuis0b91d112012-02-09 11:15:42 -08005720 if (rval != QLA_SUCCESS) {
5721 return rval;
5722 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005723 if (mb[0] == MBS_PORT_ID_USED) {
5724 /*
5725 * Device has another loop ID. The firmware team
Andrew Vasquez0107109e2005-07-06 10:31:37 -07005726 * recommends the driver perform an implicit login with
5727 * the specified ID again. The ID we just used is save
5728 * here so we return with an ID that can be tried by
5729 * the next login.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005730 */
5731 retry++;
5732 tmp_loopid = fcport->loop_id;
5733 fcport->loop_id = mb[1];
5734
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005735 ql_dbg(ql_dbg_disc, vha, 0x2001,
5736 "Fabric Login: port in use - next loop "
5737 "id=0x%04x, port id= %02x%02x%02x.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07005738 fcport->loop_id, fcport->d_id.b.domain,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005739 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005740
5741 } else if (mb[0] == MBS_COMMAND_COMPLETE) {
5742 /*
5743 * Login succeeded.
5744 */
5745 if (retry) {
5746 /* A retry occurred before. */
5747 *next_loopid = tmp_loopid;
5748 } else {
5749 /*
5750 * No retry occurred before. Just increment the
5751 * ID value for next login.
5752 */
5753 *next_loopid = (fcport->loop_id + 1);
5754 }
5755
5756 if (mb[1] & BIT_0) {
5757 fcport->port_type = FCT_INITIATOR;
5758 } else {
5759 fcport->port_type = FCT_TARGET;
5760 if (mb[1] & BIT_1) {
Santosh Vernekar8474f3a2009-08-25 11:36:16 -07005761 fcport->flags |= FCF_FCP2_DEVICE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005762 }
5763 }
5764
Andrew Vasquezad3e0ed2005-08-26 19:08:10 -07005765 if (mb[10] & BIT_0)
5766 fcport->supported_classes |= FC_COS_CLASS2;
5767 if (mb[10] & BIT_1)
5768 fcport->supported_classes |= FC_COS_CLASS3;
5769
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04005770 if (IS_FWI2_CAPABLE(ha)) {
5771 if (mb[10] & BIT_7)
5772 fcport->flags |=
5773 FCF_CONF_COMP_SUPPORTED;
5774 }
5775
Linus Torvalds1da177e2005-04-16 15:20:36 -07005776 rval = QLA_SUCCESS;
5777 break;
5778 } else if (mb[0] == MBS_LOOP_ID_USED) {
5779 /*
5780 * Loop ID already used, try next loop ID.
5781 */
5782 fcport->loop_id++;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005783 rval = qla2x00_find_new_loop_id(vha, fcport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005784 if (rval != QLA_SUCCESS) {
5785 /* Ran out of loop IDs to use */
5786 break;
5787 }
5788 } else if (mb[0] == MBS_COMMAND_ERROR) {
5789 /*
5790 * Firmware possibly timed out during login. If NO
5791 * retries are left to do then the device is declared
5792 * dead.
5793 */
5794 *next_loopid = fcport->loop_id;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005795 ha->isp_ops->fabric_logout(vha, fcport->loop_id,
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07005796 fcport->d_id.b.domain, fcport->d_id.b.area,
5797 fcport->d_id.b.al_pa);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005798 qla2x00_mark_device_lost(vha, fcport, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005799
5800 rval = 1;
5801 break;
5802 } else {
5803 /*
5804 * unrecoverable / not handled error
5805 */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005806 ql_dbg(ql_dbg_disc, vha, 0x2002,
5807 "Failed=%x port_id=%02x%02x%02x loop_id=%x "
5808 "jiffies=%lx.\n", mb[0], fcport->d_id.b.domain,
5809 fcport->d_id.b.area, fcport->d_id.b.al_pa,
5810 fcport->loop_id, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005811
5812 *next_loopid = fcport->loop_id;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005813 ha->isp_ops->fabric_logout(vha, fcport->loop_id,
Andrew Vasquez1c7c6352005-07-06 10:30:57 -07005814 fcport->d_id.b.domain, fcport->d_id.b.area,
5815 fcport->d_id.b.al_pa);
Chad Dupuis5f16b332012-08-22 14:21:00 -04005816 qla2x00_clear_loop_id(fcport);
Andrew Vasquez0eedfcf2005-10-27 11:09:38 -07005817 fcport->login_retry = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005818
5819 rval = 3;
5820 break;
5821 }
5822 }
5823
5824 return (rval);
5825}
5826
5827/*
5828 * qla2x00_local_device_login
5829 * Issue local device login command.
5830 *
5831 * Input:
5832 * ha = adapter block pointer.
5833 * loop_id = loop id of device to login to.
5834 *
5835 * Returns (Where's the #define!!!!):
5836 * 0 - Login successfully
5837 * 1 - Login failed
5838 * 3 - Fatal error
5839 */
5840int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005841qla2x00_local_device_login(scsi_qla_host_t *vha, fc_port_t *fcport)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005842{
5843 int rval;
5844 uint16_t mb[MAILBOX_REGISTER_COUNT];
5845
5846 memset(mb, 0, sizeof(mb));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005847 rval = qla2x00_login_local_device(vha, fcport, mb, BIT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005848 if (rval == QLA_SUCCESS) {
5849 /* Interrogate mailbox registers for any errors */
5850 if (mb[0] == MBS_COMMAND_ERROR)
5851 rval = 1;
5852 else if (mb[0] == MBS_COMMAND_PARAMETER_ERROR)
5853 /* device not in PCB table */
5854 rval = 3;
5855 }
5856
5857 return (rval);
5858}
5859
5860/*
5861 * qla2x00_loop_resync
5862 * Resync with fibre channel devices.
5863 *
5864 * Input:
5865 * ha = adapter block pointer.
5866 *
5867 * Returns:
5868 * 0 = success
5869 */
5870int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005871qla2x00_loop_resync(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005872{
Anirban Chakraborty73208df2008-12-09 16:45:39 -08005873 int rval = QLA_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005874 uint32_t wait_time;
Anirban Chakraborty67c2e932009-04-06 22:33:42 -07005875 struct req_que *req;
5876 struct rsp_que *rsp;
5877
Michael Hernandezd7459522016-12-12 14:40:07 -08005878 req = vha->req;
Anirban Chakraborty67c2e932009-04-06 22:33:42 -07005879 rsp = req->rsp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005880
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005881 clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
5882 if (vha->flags.online) {
5883 if (!(rval = qla2x00_fw_ready(vha))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005884 /* Wait at most MAX_TARGET RSCNs for a stable link. */
5885 wait_time = 256;
5886 do {
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04005887 if (!IS_QLAFX00(vha->hw)) {
5888 /*
5889 * Issue a marker after FW becomes
5890 * ready.
5891 */
5892 qla2x00_marker(vha, req, rsp, 0, 0,
5893 MK_SYNC_ALL);
5894 vha->marker_needed = 0;
5895 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005896
5897 /* Remap devices on Loop. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005898 clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04005900 if (IS_QLAFX00(vha->hw))
5901 qlafx00_configure_devices(vha);
5902 else
5903 qla2x00_configure_loop(vha);
5904
Linus Torvalds1da177e2005-04-16 15:20:36 -07005905 wait_time--;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005906 } while (!atomic_read(&vha->loop_down_timer) &&
5907 !(test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
5908 && wait_time && (test_bit(LOOP_RESYNC_NEEDED,
5909 &vha->dpc_flags)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005910 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005911 }
5912
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005913 if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005914 return (QLA_FUNCTION_FAILED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08005916 if (rval)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07005917 ql_dbg(ql_dbg_disc, vha, 0x206c,
5918 "%s *** FAILED ***.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005919
5920 return (rval);
5921}
5922
Saurav Kashyap579d12b2010-12-21 16:00:14 -08005923/*
5924* qla2x00_perform_loop_resync
5925* Description: This function will set the appropriate flags and call
5926* qla2x00_loop_resync. If successful loop will be resynced
5927* Arguments : scsi_qla_host_t pointer
5928* returm : Success or Failure
5929*/
5930
5931int qla2x00_perform_loop_resync(scsi_qla_host_t *ha)
5932{
5933 int32_t rval = 0;
5934
5935 if (!test_and_set_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags)) {
5936 /*Configure the flags so that resync happens properly*/
5937 atomic_set(&ha->loop_down_timer, 0);
5938 if (!(ha->device_flags & DFLG_NO_CABLE)) {
5939 atomic_set(&ha->loop_state, LOOP_UP);
5940 set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
5941 set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
5942 set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
5943
5944 rval = qla2x00_loop_resync(ha);
5945 } else
5946 atomic_set(&ha->loop_state, LOOP_DEAD);
5947
5948 clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags);
5949 }
5950
5951 return rval;
5952}
5953
Linus Torvalds1da177e2005-04-16 15:20:36 -07005954void
Andrew Vasquez67becc02009-08-25 11:36:20 -07005955qla2x00_update_fcports(scsi_qla_host_t *base_vha)
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08005956{
5957 fc_port_t *fcport;
Arun Easifeafb7b2010-09-03 14:57:00 -07005958 struct scsi_qla_host *vha;
5959 struct qla_hw_data *ha = base_vha->hw;
5960 unsigned long flags;
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08005961
Arun Easifeafb7b2010-09-03 14:57:00 -07005962 spin_lock_irqsave(&ha->vport_slock, flags);
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08005963 /* Go with deferred removal of rport references. */
Arun Easifeafb7b2010-09-03 14:57:00 -07005964 list_for_each_entry(vha, &base_vha->hw->vp_list, list) {
5965 atomic_inc(&vha->vref_count);
5966 list_for_each_entry(fcport, &vha->vp_fcports, list) {
Dan Carpenter8ae598d2010-12-21 16:00:15 -08005967 if (fcport->drport &&
Arun Easifeafb7b2010-09-03 14:57:00 -07005968 atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
5969 spin_unlock_irqrestore(&ha->vport_slock, flags);
Andrew Vasquez67becc02009-08-25 11:36:20 -07005970 qla2x00_rport_del(fcport);
Alexei Potashnikdf673272015-07-14 16:00:46 -04005971
Arun Easifeafb7b2010-09-03 14:57:00 -07005972 spin_lock_irqsave(&ha->vport_slock, flags);
5973 }
5974 }
5975 atomic_dec(&vha->vref_count);
Joe Carnuccioc4a9b532017-03-15 09:48:43 -07005976 wake_up(&vha->vref_waitq);
Arun Easifeafb7b2010-09-03 14:57:00 -07005977 }
5978 spin_unlock_irqrestore(&ha->vport_slock, flags);
andrew.vasquez@qlogic.comd97994d2006-01-20 14:53:13 -08005979}
5980
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04005981/* Assumes idc_lock always held on entry */
5982void
5983qla83xx_reset_ownership(scsi_qla_host_t *vha)
5984{
5985 struct qla_hw_data *ha = vha->hw;
5986 uint32_t drv_presence, drv_presence_mask;
5987 uint32_t dev_part_info1, dev_part_info2, class_type;
5988 uint32_t class_type_mask = 0x3;
5989 uint16_t fcoe_other_function = 0xffff, i;
5990
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04005991 if (IS_QLA8044(ha)) {
5992 drv_presence = qla8044_rd_direct(vha,
5993 QLA8044_CRB_DRV_ACTIVE_INDEX);
5994 dev_part_info1 = qla8044_rd_direct(vha,
5995 QLA8044_CRB_DEV_PART_INFO_INDEX);
5996 dev_part_info2 = qla8044_rd_direct(vha,
5997 QLA8044_CRB_DEV_PART_INFO2);
5998 } else {
5999 qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence);
6000 qla83xx_rd_reg(vha, QLA83XX_DEV_PARTINFO1, &dev_part_info1);
6001 qla83xx_rd_reg(vha, QLA83XX_DEV_PARTINFO2, &dev_part_info2);
6002 }
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04006003 for (i = 0; i < 8; i++) {
6004 class_type = ((dev_part_info1 >> (i * 4)) & class_type_mask);
6005 if ((class_type == QLA83XX_CLASS_TYPE_FCOE) &&
6006 (i != ha->portnum)) {
6007 fcoe_other_function = i;
6008 break;
6009 }
6010 }
6011 if (fcoe_other_function == 0xffff) {
6012 for (i = 0; i < 8; i++) {
6013 class_type = ((dev_part_info2 >> (i * 4)) &
6014 class_type_mask);
6015 if ((class_type == QLA83XX_CLASS_TYPE_FCOE) &&
6016 ((i + 8) != ha->portnum)) {
6017 fcoe_other_function = i + 8;
6018 break;
6019 }
6020 }
6021 }
6022 /*
6023 * Prepare drv-presence mask based on fcoe functions present.
6024 * However consider only valid physical fcoe function numbers (0-15).
6025 */
6026 drv_presence_mask = ~((1 << (ha->portnum)) |
6027 ((fcoe_other_function == 0xffff) ?
6028 0 : (1 << (fcoe_other_function))));
6029
6030 /* We are the reset owner iff:
6031 * - No other protocol drivers present.
6032 * - This is the lowest among fcoe functions. */
6033 if (!(drv_presence & drv_presence_mask) &&
6034 (ha->portnum < fcoe_other_function)) {
6035 ql_dbg(ql_dbg_p3p, vha, 0xb07f,
6036 "This host is Reset owner.\n");
6037 ha->flags.nic_core_reset_owner = 1;
6038 }
6039}
6040
Saurav Kashyapfa492632012-11-21 02:40:29 -05006041static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04006042__qla83xx_set_drv_ack(scsi_qla_host_t *vha)
6043{
6044 int rval = QLA_SUCCESS;
6045 struct qla_hw_data *ha = vha->hw;
6046 uint32_t drv_ack;
6047
6048 rval = qla83xx_rd_reg(vha, QLA83XX_IDC_DRIVER_ACK, &drv_ack);
6049 if (rval == QLA_SUCCESS) {
6050 drv_ack |= (1 << ha->portnum);
6051 rval = qla83xx_wr_reg(vha, QLA83XX_IDC_DRIVER_ACK, drv_ack);
6052 }
6053
6054 return rval;
6055}
6056
Saurav Kashyapfa492632012-11-21 02:40:29 -05006057static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04006058__qla83xx_clear_drv_ack(scsi_qla_host_t *vha)
6059{
6060 int rval = QLA_SUCCESS;
6061 struct qla_hw_data *ha = vha->hw;
6062 uint32_t drv_ack;
6063
6064 rval = qla83xx_rd_reg(vha, QLA83XX_IDC_DRIVER_ACK, &drv_ack);
6065 if (rval == QLA_SUCCESS) {
6066 drv_ack &= ~(1 << ha->portnum);
6067 rval = qla83xx_wr_reg(vha, QLA83XX_IDC_DRIVER_ACK, drv_ack);
6068 }
6069
6070 return rval;
6071}
6072
Saurav Kashyapfa492632012-11-21 02:40:29 -05006073static const char *
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04006074qla83xx_dev_state_to_string(uint32_t dev_state)
6075{
6076 switch (dev_state) {
6077 case QLA8XXX_DEV_COLD:
6078 return "COLD/RE-INIT";
6079 case QLA8XXX_DEV_INITIALIZING:
6080 return "INITIALIZING";
6081 case QLA8XXX_DEV_READY:
6082 return "READY";
6083 case QLA8XXX_DEV_NEED_RESET:
6084 return "NEED RESET";
6085 case QLA8XXX_DEV_NEED_QUIESCENT:
6086 return "NEED QUIESCENT";
6087 case QLA8XXX_DEV_FAILED:
6088 return "FAILED";
6089 case QLA8XXX_DEV_QUIESCENT:
6090 return "QUIESCENT";
6091 default:
6092 return "Unknown";
6093 }
6094}
6095
6096/* Assumes idc-lock always held on entry */
6097void
6098qla83xx_idc_audit(scsi_qla_host_t *vha, int audit_type)
6099{
6100 struct qla_hw_data *ha = vha->hw;
6101 uint32_t idc_audit_reg = 0, duration_secs = 0;
6102
6103 switch (audit_type) {
6104 case IDC_AUDIT_TIMESTAMP:
6105 ha->idc_audit_ts = (jiffies_to_msecs(jiffies) / 1000);
6106 idc_audit_reg = (ha->portnum) |
6107 (IDC_AUDIT_TIMESTAMP << 7) | (ha->idc_audit_ts << 8);
6108 qla83xx_wr_reg(vha, QLA83XX_IDC_AUDIT, idc_audit_reg);
6109 break;
6110
6111 case IDC_AUDIT_COMPLETION:
6112 duration_secs = ((jiffies_to_msecs(jiffies) -
6113 jiffies_to_msecs(ha->idc_audit_ts)) / 1000);
6114 idc_audit_reg = (ha->portnum) |
6115 (IDC_AUDIT_COMPLETION << 7) | (duration_secs << 8);
6116 qla83xx_wr_reg(vha, QLA83XX_IDC_AUDIT, idc_audit_reg);
6117 break;
6118
6119 default:
6120 ql_log(ql_log_warn, vha, 0xb078,
6121 "Invalid audit type specified.\n");
6122 break;
6123 }
6124}
6125
6126/* Assumes idc_lock always held on entry */
Saurav Kashyapfa492632012-11-21 02:40:29 -05006127static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04006128qla83xx_initiating_reset(scsi_qla_host_t *vha)
6129{
6130 struct qla_hw_data *ha = vha->hw;
6131 uint32_t idc_control, dev_state;
6132
6133 __qla83xx_get_idc_control(vha, &idc_control);
6134 if ((idc_control & QLA83XX_IDC_RESET_DISABLED)) {
6135 ql_log(ql_log_info, vha, 0xb080,
6136 "NIC Core reset has been disabled. idc-control=0x%x\n",
6137 idc_control);
6138 return QLA_FUNCTION_FAILED;
6139 }
6140
6141 /* Set NEED-RESET iff in READY state and we are the reset-owner */
6142 qla83xx_rd_reg(vha, QLA83XX_IDC_DEV_STATE, &dev_state);
6143 if (ha->flags.nic_core_reset_owner && dev_state == QLA8XXX_DEV_READY) {
6144 qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE,
6145 QLA8XXX_DEV_NEED_RESET);
6146 ql_log(ql_log_info, vha, 0xb056, "HW State: NEED RESET.\n");
6147 qla83xx_idc_audit(vha, IDC_AUDIT_TIMESTAMP);
6148 } else {
6149 const char *state = qla83xx_dev_state_to_string(dev_state);
6150 ql_log(ql_log_info, vha, 0xb057, "HW State: %s.\n", state);
6151
6152 /* SV: XXX: Is timeout required here? */
6153 /* Wait for IDC state change READY -> NEED_RESET */
6154 while (dev_state == QLA8XXX_DEV_READY) {
6155 qla83xx_idc_unlock(vha, 0);
6156 msleep(200);
6157 qla83xx_idc_lock(vha, 0);
6158 qla83xx_rd_reg(vha, QLA83XX_IDC_DEV_STATE, &dev_state);
6159 }
6160 }
6161
6162 /* Send IDC ack by writing to drv-ack register */
6163 __qla83xx_set_drv_ack(vha);
6164
6165 return QLA_SUCCESS;
6166}
6167
6168int
6169__qla83xx_set_idc_control(scsi_qla_host_t *vha, uint32_t idc_control)
6170{
6171 return qla83xx_wr_reg(vha, QLA83XX_IDC_CONTROL, idc_control);
6172}
6173
6174int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04006175__qla83xx_get_idc_control(scsi_qla_host_t *vha, uint32_t *idc_control)
6176{
6177 return qla83xx_rd_reg(vha, QLA83XX_IDC_CONTROL, idc_control);
6178}
6179
Saurav Kashyapfa492632012-11-21 02:40:29 -05006180static int
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04006181qla83xx_check_driver_presence(scsi_qla_host_t *vha)
6182{
6183 uint32_t drv_presence = 0;
6184 struct qla_hw_data *ha = vha->hw;
6185
6186 qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence);
6187 if (drv_presence & (1 << ha->portnum))
6188 return QLA_SUCCESS;
6189 else
6190 return QLA_TEST_FAILED;
6191}
6192
6193int
6194qla83xx_nic_core_reset(scsi_qla_host_t *vha)
6195{
6196 int rval = QLA_SUCCESS;
6197 struct qla_hw_data *ha = vha->hw;
6198
6199 ql_dbg(ql_dbg_p3p, vha, 0xb058,
6200 "Entered %s().\n", __func__);
6201
6202 if (vha->device_flags & DFLG_DEV_FAILED) {
6203 ql_log(ql_log_warn, vha, 0xb059,
6204 "Device in unrecoverable FAILED state.\n");
6205 return QLA_FUNCTION_FAILED;
6206 }
6207
6208 qla83xx_idc_lock(vha, 0);
6209
6210 if (qla83xx_check_driver_presence(vha) != QLA_SUCCESS) {
6211 ql_log(ql_log_warn, vha, 0xb05a,
6212 "Function=0x%x has been removed from IDC participation.\n",
6213 ha->portnum);
6214 rval = QLA_FUNCTION_FAILED;
6215 goto exit;
6216 }
6217
6218 qla83xx_reset_ownership(vha);
6219
6220 rval = qla83xx_initiating_reset(vha);
6221
6222 /*
6223 * Perform reset if we are the reset-owner,
6224 * else wait till IDC state changes to READY/FAILED.
6225 */
6226 if (rval == QLA_SUCCESS) {
6227 rval = qla83xx_idc_state_handler(vha);
6228
6229 if (rval == QLA_SUCCESS)
6230 ha->flags.nic_core_hung = 0;
6231 __qla83xx_clear_drv_ack(vha);
6232 }
6233
6234exit:
6235 qla83xx_idc_unlock(vha, 0);
6236
6237 ql_dbg(ql_dbg_p3p, vha, 0xb05b, "Exiting %s.\n", __func__);
6238
6239 return rval;
6240}
6241
Saurav Kashyap81178772012-08-22 14:21:04 -04006242int
6243qla2xxx_mctp_dump(scsi_qla_host_t *vha)
6244{
6245 struct qla_hw_data *ha = vha->hw;
6246 int rval = QLA_FUNCTION_FAILED;
6247
6248 if (!IS_MCTP_CAPABLE(ha)) {
6249 /* This message can be removed from the final version */
6250 ql_log(ql_log_info, vha, 0x506d,
6251 "This board is not MCTP capable\n");
6252 return rval;
6253 }
6254
6255 if (!ha->mctp_dump) {
6256 ha->mctp_dump = dma_alloc_coherent(&ha->pdev->dev,
6257 MCTP_DUMP_SIZE, &ha->mctp_dump_dma, GFP_KERNEL);
6258
6259 if (!ha->mctp_dump) {
6260 ql_log(ql_log_warn, vha, 0x506e,
6261 "Failed to allocate memory for mctp dump\n");
6262 return rval;
6263 }
6264 }
6265
6266#define MCTP_DUMP_STR_ADDR 0x00000000
6267 rval = qla2x00_dump_mctp_data(vha, ha->mctp_dump_dma,
6268 MCTP_DUMP_STR_ADDR, MCTP_DUMP_SIZE/4);
6269 if (rval != QLA_SUCCESS) {
6270 ql_log(ql_log_warn, vha, 0x506f,
6271 "Failed to capture mctp dump\n");
6272 } else {
6273 ql_log(ql_log_info, vha, 0x5070,
6274 "Mctp dump capture for host (%ld/%p).\n",
6275 vha->host_no, ha->mctp_dump);
6276 ha->mctp_dumped = 1;
6277 }
6278
Saurav Kashyap409ee0f2012-08-22 14:21:29 -04006279 if (!ha->flags.nic_core_reset_hdlr_active && !ha->portnum) {
Saurav Kashyap81178772012-08-22 14:21:04 -04006280 ha->flags.nic_core_reset_hdlr_active = 1;
6281 rval = qla83xx_restart_nic_firmware(vha);
6282 if (rval)
6283 /* NIC Core reset failed. */
6284 ql_log(ql_log_warn, vha, 0x5071,
6285 "Failed to restart nic firmware\n");
6286 else
6287 ql_dbg(ql_dbg_p3p, vha, 0xb084,
6288 "Restarted NIC firmware successfully.\n");
6289 ha->flags.nic_core_reset_hdlr_active = 0;
6290 }
6291
6292 return rval;
6293
6294}
6295
Saurav Kashyap579d12b2010-12-21 16:00:14 -08006296/*
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04006297* qla2x00_quiesce_io
Saurav Kashyap579d12b2010-12-21 16:00:14 -08006298* Description: This function will block the new I/Os
6299* Its not aborting any I/Os as context
6300* is not destroyed during quiescence
6301* Arguments: scsi_qla_host_t
6302* return : void
6303*/
6304void
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04006305qla2x00_quiesce_io(scsi_qla_host_t *vha)
Saurav Kashyap579d12b2010-12-21 16:00:14 -08006306{
6307 struct qla_hw_data *ha = vha->hw;
6308 struct scsi_qla_host *vp;
6309
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04006310 ql_dbg(ql_dbg_dpc, vha, 0x401d,
6311 "Quiescing I/O - ha=%p.\n", ha);
Saurav Kashyap579d12b2010-12-21 16:00:14 -08006312
6313 atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
6314 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
6315 atomic_set(&vha->loop_state, LOOP_DOWN);
6316 qla2x00_mark_all_devices_lost(vha, 0);
6317 list_for_each_entry(vp, &ha->vp_list, list)
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04006318 qla2x00_mark_all_devices_lost(vp, 0);
Saurav Kashyap579d12b2010-12-21 16:00:14 -08006319 } else {
6320 if (!atomic_read(&vha->loop_down_timer))
6321 atomic_set(&vha->loop_down_timer,
6322 LOOP_DOWN_TIME);
6323 }
6324 /* Wait for pending cmds to complete */
6325 qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST);
6326}
6327
Giridhar Malavalia9083012010-04-12 17:59:55 -07006328void
6329qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
6330{
6331 struct qla_hw_data *ha = vha->hw;
Saurav Kashyap579d12b2010-12-21 16:00:14 -08006332 struct scsi_qla_host *vp;
Arun Easifeafb7b2010-09-03 14:57:00 -07006333 unsigned long flags;
Andrew Vasquez6aef87b2011-02-23 15:27:13 -08006334 fc_port_t *fcport;
Quinn Tran7c3f8fd2017-06-13 20:47:22 -07006335 u16 i;
Giridhar Malavalia9083012010-04-12 17:59:55 -07006336
Saurav Kashyape46ef002011-02-23 15:27:16 -08006337 /* For ISP82XX, driver waits for completion of the commands.
6338 * online flag should be set.
6339 */
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04006340 if (!(IS_P3P_TYPE(ha)))
Saurav Kashyape46ef002011-02-23 15:27:16 -08006341 vha->flags.online = 0;
Giridhar Malavalia9083012010-04-12 17:59:55 -07006342 ha->flags.chip_reset_done = 0;
6343 clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Saurav Kashyap2be21fa2012-05-15 14:34:16 -04006344 vha->qla_stats.total_isp_aborts++;
Giridhar Malavalia9083012010-04-12 17:59:55 -07006345
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006346 ql_log(ql_log_info, vha, 0x00af,
6347 "Performing ISP error recovery - ha=%p.\n", ha);
Giridhar Malavalia9083012010-04-12 17:59:55 -07006348
Saurav Kashyape46ef002011-02-23 15:27:16 -08006349 /* For ISP82XX, reset_chip is just disabling interrupts.
6350 * Driver waits for the completion of the commands.
6351 * the interrupts need to be enabled.
6352 */
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04006353 if (!(IS_P3P_TYPE(ha)))
Giridhar Malavalia9083012010-04-12 17:59:55 -07006354 ha->isp_ops->reset_chip(vha);
6355
Quinn Tran9cd883f2017-12-28 12:33:24 -08006356 SAVE_TOPO(ha);
6357 ha->flags.rida_fmt2 = 0;
Quinn Tranec7193e2017-03-15 09:48:55 -07006358 ha->flags.n2n_ae = 0;
6359 ha->flags.lip_ae = 0;
6360 ha->current_topology = 0;
6361 ha->flags.fw_started = 0;
6362 ha->flags.fw_init_done = 0;
Quinn Tran7c3f8fd2017-06-13 20:47:22 -07006363 ha->base_qpair->chip_reset++;
6364 for (i = 0; i < ha->max_qpairs; i++) {
6365 if (ha->queue_pair_map[i])
6366 ha->queue_pair_map[i]->chip_reset =
6367 ha->base_qpair->chip_reset;
6368 }
Quinn Tran726b8542017-01-19 22:28:00 -08006369
Giridhar Malavalia9083012010-04-12 17:59:55 -07006370 atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
6371 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
6372 atomic_set(&vha->loop_state, LOOP_DOWN);
6373 qla2x00_mark_all_devices_lost(vha, 0);
Arun Easifeafb7b2010-09-03 14:57:00 -07006374
6375 spin_lock_irqsave(&ha->vport_slock, flags);
Saurav Kashyap579d12b2010-12-21 16:00:14 -08006376 list_for_each_entry(vp, &ha->vp_list, list) {
Arun Easifeafb7b2010-09-03 14:57:00 -07006377 atomic_inc(&vp->vref_count);
6378 spin_unlock_irqrestore(&ha->vport_slock, flags);
6379
Giridhar Malavalia9083012010-04-12 17:59:55 -07006380 qla2x00_mark_all_devices_lost(vp, 0);
Arun Easifeafb7b2010-09-03 14:57:00 -07006381
6382 spin_lock_irqsave(&ha->vport_slock, flags);
6383 atomic_dec(&vp->vref_count);
6384 }
6385 spin_unlock_irqrestore(&ha->vport_slock, flags);
Giridhar Malavalia9083012010-04-12 17:59:55 -07006386 } else {
6387 if (!atomic_read(&vha->loop_down_timer))
6388 atomic_set(&vha->loop_down_timer,
6389 LOOP_DOWN_TIME);
6390 }
6391
Andrew Vasquez6aef87b2011-02-23 15:27:13 -08006392 /* Clear all async request states across all VPs. */
6393 list_for_each_entry(fcport, &vha->vp_fcports, list)
6394 fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
6395 spin_lock_irqsave(&ha->vport_slock, flags);
6396 list_for_each_entry(vp, &ha->vp_list, list) {
6397 atomic_inc(&vp->vref_count);
6398 spin_unlock_irqrestore(&ha->vport_slock, flags);
6399
6400 list_for_each_entry(fcport, &vp->vp_fcports, list)
6401 fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
6402
6403 spin_lock_irqsave(&ha->vport_slock, flags);
6404 atomic_dec(&vp->vref_count);
6405 }
6406 spin_unlock_irqrestore(&ha->vport_slock, flags);
6407
Lalit Chandivadebddd2d62010-09-03 15:20:53 -07006408 if (!ha->flags.eeh_busy) {
6409 /* Make sure for ISP 82XX IO DMA is complete */
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04006410 if (IS_P3P_TYPE(ha)) {
Giridhar Malavali71905752011-02-23 15:27:10 -08006411 qla82xx_chip_reset_cleanup(vha);
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006412 ql_log(ql_log_info, vha, 0x00b4,
6413 "Done chip reset cleanup.\n");
Giridhar Malavalia9083012010-04-12 17:59:55 -07006414
Saurav Kashyape46ef002011-02-23 15:27:16 -08006415 /* Done waiting for pending commands.
6416 * Reset the online flag.
6417 */
6418 vha->flags.online = 0;
Giridhar Malavalia9083012010-04-12 17:59:55 -07006419 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006420
Lalit Chandivadebddd2d62010-09-03 15:20:53 -07006421 /* Requeue all commands in outstanding command list. */
6422 qla2x00_abort_all_cmds(vha, DID_RESET << 16);
6423 }
Arun Easib6a029e2014-09-25 06:14:52 -04006424 /* memory barrier */
6425 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006426}
6427
6428/*
6429* qla2x00_abort_isp
6430* Resets ISP and aborts all outstanding commands.
6431*
6432* Input:
6433* ha = adapter block pointer.
6434*
6435* Returns:
6436* 0 = success
6437*/
6438int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006439qla2x00_abort_isp(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006440{
Andrew Vasquez476e8972006-08-23 14:54:55 -07006441 int rval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006442 uint8_t status = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006443 struct qla_hw_data *ha = vha->hw;
6444 struct scsi_qla_host *vp;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006445 struct req_que *req = ha->req_q_map[0];
Arun Easifeafb7b2010-09-03 14:57:00 -07006446 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006447
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006448 if (vha->flags.online) {
Giridhar Malavalia9083012010-04-12 17:59:55 -07006449 qla2x00_abort_isp_cleanup(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006450
Santosh Vernekara61712972012-08-22 14:21:13 -04006451 if (IS_QLA8031(ha)) {
6452 ql_dbg(ql_dbg_p3p, vha, 0xb05c,
6453 "Clearing fcoe driver presence.\n");
6454 if (qla83xx_clear_drv_presence(vha) != QLA_SUCCESS)
6455 ql_dbg(ql_dbg_p3p, vha, 0xb073,
6456 "Error while clearing DRV-Presence.\n");
6457 }
6458
Andrew Vasquez85880802009-12-15 21:29:46 -08006459 if (unlikely(pci_channel_offline(ha->pdev) &&
6460 ha->flags.pci_channel_io_perm_failure)) {
6461 clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
6462 status = 0;
6463 return status;
6464 }
6465
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006466 ha->isp_ops->get_flash_version(vha, req->ring);
Andrew Vasquez30c47662007-01-29 10:22:21 -08006467
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006468 ha->isp_ops->nvram_config(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006469
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006470 if (!qla2x00_restart_isp(vha)) {
6471 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006472
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006473 if (!atomic_read(&vha->loop_down_timer)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006474 /*
6475 * Issue marker command only when we are going
6476 * to start the I/O .
6477 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006478 vha->marker_needed = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006479 }
6480
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006481 vha->flags.online = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006482
Andrew Vasquezfd34f552007-07-19 15:06:00 -07006483 ha->isp_ops->enable_intrs(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006484
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07006485 ha->isp_abort_cnt = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006486 clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
Andrew Vasquez476e8972006-08-23 14:54:55 -07006487
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08006488 if (IS_QLA81XX(ha) || IS_QLA8031(ha))
6489 qla2x00_get_fw_version(vha);
Andrew Vasquezdf613b92008-01-17 09:02:17 -08006490 if (ha->fce) {
6491 ha->flags.fce_enabled = 1;
6492 memset(ha->fce, 0,
6493 fce_calc_size(ha->fce_bufs));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006494 rval = qla2x00_enable_fce_trace(vha,
Andrew Vasquezdf613b92008-01-17 09:02:17 -08006495 ha->fce_dma, ha->fce_bufs, ha->fce_mb,
6496 &ha->fce_bufs);
6497 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006498 ql_log(ql_log_warn, vha, 0x8033,
Andrew Vasquezdf613b92008-01-17 09:02:17 -08006499 "Unable to reinitialize FCE "
6500 "(%d).\n", rval);
6501 ha->flags.fce_enabled = 0;
6502 }
6503 }
Andrew Vasquez436a7b12008-07-10 16:55:54 -07006504
6505 if (ha->eft) {
6506 memset(ha->eft, 0, EFT_SIZE);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006507 rval = qla2x00_enable_eft_trace(vha,
Andrew Vasquez436a7b12008-07-10 16:55:54 -07006508 ha->eft_dma, EFT_NUM_BUFFERS);
6509 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006510 ql_log(ql_log_warn, vha, 0x8034,
Andrew Vasquez436a7b12008-07-10 16:55:54 -07006511 "Unable to reinitialize EFT "
6512 "(%d).\n", rval);
6513 }
6514 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006515 } else { /* failed the ISP abort */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006516 vha->flags.online = 1;
6517 if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006518 if (ha->isp_abort_cnt == 0) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006519 ql_log(ql_log_fatal, vha, 0x8035,
6520 "ISP error recover failed - "
6521 "board disabled.\n");
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07006522 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006523 * The next call disables the board
6524 * completely.
6525 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006526 ha->isp_ops->reset_adapter(vha);
6527 vha->flags.online = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006528 clear_bit(ISP_ABORT_RETRY,
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006529 &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006530 status = 0;
6531 } else { /* schedule another ISP abort */
6532 ha->isp_abort_cnt--;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006533 ql_dbg(ql_dbg_taskm, vha, 0x8020,
6534 "ISP abort - retry remaining %d.\n",
6535 ha->isp_abort_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006536 status = 1;
6537 }
6538 } else {
6539 ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006540 ql_dbg(ql_dbg_taskm, vha, 0x8021,
6541 "ISP error recovery - retrying (%d) "
6542 "more times.\n", ha->isp_abort_cnt);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006543 set_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006544 status = 1;
6545 }
6546 }
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07006547
Linus Torvalds1da177e2005-04-16 15:20:36 -07006548 }
6549
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006550 if (!status) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006551 ql_dbg(ql_dbg_taskm, vha, 0x8022, "%s succeeded.\n", __func__);
Quinn Tran1608cc42017-08-23 15:05:03 -07006552 qla2x00_configure_hba(vha);
Arun Easifeafb7b2010-09-03 14:57:00 -07006553 spin_lock_irqsave(&ha->vport_slock, flags);
6554 list_for_each_entry(vp, &ha->vp_list, list) {
6555 if (vp->vp_idx) {
6556 atomic_inc(&vp->vref_count);
6557 spin_unlock_irqrestore(&ha->vport_slock, flags);
6558
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006559 qla2x00_vp_abort_isp(vp);
Arun Easifeafb7b2010-09-03 14:57:00 -07006560
6561 spin_lock_irqsave(&ha->vport_slock, flags);
6562 atomic_dec(&vp->vref_count);
6563 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006564 }
Arun Easifeafb7b2010-09-03 14:57:00 -07006565 spin_unlock_irqrestore(&ha->vport_slock, flags);
6566
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04006567 if (IS_QLA8031(ha)) {
6568 ql_dbg(ql_dbg_p3p, vha, 0xb05d,
6569 "Setting back fcoe driver presence.\n");
6570 if (qla83xx_set_drv_presence(vha) != QLA_SUCCESS)
6571 ql_dbg(ql_dbg_p3p, vha, 0xb074,
6572 "Error while setting DRV-Presence.\n");
6573 }
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006574 } else {
Joe Perchesd8424f62011-11-18 09:03:06 -08006575 ql_log(ql_log_warn, vha, 0x8023, "%s **** FAILED ****.\n",
6576 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006577 }
6578
6579 return(status);
6580}
6581
6582/*
6583* qla2x00_restart_isp
6584* restarts the ISP after a reset
6585*
6586* Input:
6587* ha = adapter block pointer.
6588*
6589* Returns:
6590* 0 = success
6591*/
6592static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006593qla2x00_restart_isp(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006594{
Andrew Vasquezc6b2fca2009-03-05 11:07:03 -08006595 int status = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006596 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006597 struct req_que *req = ha->req_q_map[0];
6598 struct rsp_que *rsp = ha->rsp_q_map[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006599
6600 /* If firmware needs to be loaded */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006601 if (qla2x00_isp_firmware(vha)) {
6602 vha->flags.online = 0;
6603 status = ha->isp_ops->chip_diag(vha);
6604 if (!status)
6605 status = qla2x00_setup_chip(vha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006606 }
6607
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006608 if (!status && !(status = qla2x00_init_rings(vha))) {
6609 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
Lalit Chandivade2533cf62009-03-24 09:08:07 -07006610 ha->flags.chip_reset_done = 1;
Chad Dupuis7108b762014-04-11 16:54:45 -04006611
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006612 /* Initialize the queues in use */
6613 qla25xx_init_queues(ha);
6614
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006615 status = qla2x00_fw_ready(vha);
6616 if (!status) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006617 /* Issue a marker after FW becomes ready. */
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006618 qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
Chad Dupuis7108b762014-04-11 16:54:45 -04006619 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006620 }
6621
6622 /* if no cable then assume it's good */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006623 if ((vha->device_flags & DFLG_NO_CABLE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006624 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006625 }
6626 return (status);
6627}
6628
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006629static int
6630qla25xx_init_queues(struct qla_hw_data *ha)
6631{
6632 struct rsp_que *rsp = NULL;
6633 struct req_que *req = NULL;
6634 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
6635 int ret = -1;
6636 int i;
6637
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07006638 for (i = 1; i < ha->max_rsp_queues; i++) {
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006639 rsp = ha->rsp_q_map[i];
Quinn Trancb432852016-02-04 11:45:16 -05006640 if (rsp && test_bit(i, ha->rsp_qid_map)) {
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006641 rsp->options &= ~BIT_0;
Anirban Chakraborty618a7522009-02-08 20:50:11 -08006642 ret = qla25xx_init_rsp_que(base_vha, rsp);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006643 if (ret != QLA_SUCCESS)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006644 ql_dbg(ql_dbg_init, base_vha, 0x00ff,
6645 "%s Rsp que: %d init failed.\n",
6646 __func__, rsp->id);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006647 else
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006648 ql_dbg(ql_dbg_init, base_vha, 0x0100,
6649 "%s Rsp que: %d inited.\n",
6650 __func__, rsp->id);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006651 }
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07006652 }
6653 for (i = 1; i < ha->max_req_queues; i++) {
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006654 req = ha->req_q_map[i];
Quinn Trancb432852016-02-04 11:45:16 -05006655 if (req && test_bit(i, ha->req_qid_map)) {
6656 /* Clear outstanding commands array. */
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006657 req->options &= ~BIT_0;
Anirban Chakraborty618a7522009-02-08 20:50:11 -08006658 ret = qla25xx_init_req_que(base_vha, req);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006659 if (ret != QLA_SUCCESS)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006660 ql_dbg(ql_dbg_init, base_vha, 0x0101,
6661 "%s Req que: %d init failed.\n",
6662 __func__, req->id);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006663 else
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006664 ql_dbg(ql_dbg_init, base_vha, 0x0102,
6665 "%s Req que: %d inited.\n",
6666 __func__, req->id);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08006667 }
6668 }
6669 return ret;
6670}
6671
Linus Torvalds1da177e2005-04-16 15:20:36 -07006672/*
6673* qla2x00_reset_adapter
6674* Reset adapter.
6675*
6676* Input:
6677* ha = adapter block pointer.
6678*/
Andrew Vasquezabbd8872005-07-06 10:30:05 -07006679void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006680qla2x00_reset_adapter(scsi_qla_host_t *vha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006681{
6682 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006683 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07006684 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006685
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006686 vha->flags.online = 0;
Andrew Vasquezfd34f552007-07-19 15:06:00 -07006687 ha->isp_ops->disable_intrs(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006688
Linus Torvalds1da177e2005-04-16 15:20:36 -07006689 spin_lock_irqsave(&ha->hardware_lock, flags);
6690 WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
6691 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
6692 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
6693 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
6694 spin_unlock_irqrestore(&ha->hardware_lock, flags);
6695}
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006696
6697void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006698qla24xx_reset_adapter(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006699{
6700 unsigned long flags = 0;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006701 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006702 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
6703
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04006704 if (IS_P3P_TYPE(ha))
Giridhar Malavalia9083012010-04-12 17:59:55 -07006705 return;
6706
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006707 vha->flags.online = 0;
Andrew Vasquezfd34f552007-07-19 15:06:00 -07006708 ha->isp_ops->disable_intrs(ha);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006709
6710 spin_lock_irqsave(&ha->hardware_lock, flags);
6711 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
6712 RD_REG_DWORD(&reg->hccr);
6713 WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
6714 RD_REG_DWORD(&reg->hccr);
6715 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Andrew Vasquez09ff36d2009-01-22 09:45:30 -08006716
6717 if (IS_NOPOLLING_TYPE(ha))
6718 ha->isp_ops->enable_intrs(ha);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006719}
6720
David Miller4e08df32007-04-16 12:37:43 -07006721/* On sparc systems, obtain port and node WWN from firmware
6722 * properties.
6723 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006724static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *vha,
6725 struct nvram_24xx *nv)
David Miller4e08df32007-04-16 12:37:43 -07006726{
6727#ifdef CONFIG_SPARC
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006728 struct qla_hw_data *ha = vha->hw;
David Miller4e08df32007-04-16 12:37:43 -07006729 struct pci_dev *pdev = ha->pdev;
David S. Miller15576bc2007-05-08 00:36:49 -07006730 struct device_node *dp = pci_device_to_OF_node(pdev);
6731 const u8 *val;
David Miller4e08df32007-04-16 12:37:43 -07006732 int len;
6733
6734 val = of_get_property(dp, "port-wwn", &len);
6735 if (val && len >= WWN_SIZE)
6736 memcpy(nv->port_name, val, WWN_SIZE);
6737
6738 val = of_get_property(dp, "node-wwn", &len);
6739 if (val && len >= WWN_SIZE)
6740 memcpy(nv->node_name, val, WWN_SIZE);
6741#endif
6742}
6743
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006744int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006745qla24xx_nvram_config(scsi_qla_host_t *vha)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006746{
David Miller4e08df32007-04-16 12:37:43 -07006747 int rval;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006748 struct init_cb_24xx *icb;
6749 struct nvram_24xx *nv;
6750 uint32_t *dptr;
6751 uint8_t *dptr1, *dptr2;
6752 uint32_t chksum;
6753 uint16_t cnt;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006754 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006755
David Miller4e08df32007-04-16 12:37:43 -07006756 rval = QLA_SUCCESS;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006757 icb = (struct init_cb_24xx *)ha->init_cb;
Seokmann Ju281afe12007-07-26 13:43:34 -07006758 nv = ha->nvram;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006759
6760 /* Determine NVRAM starting address. */
Chad Dupuisf73cb692014-02-26 04:15:06 -05006761 if (ha->port_no == 0) {
Anirban Chakrabortye5b68a62009-04-06 22:33:50 -07006762 ha->nvram_base = FA_NVRAM_FUNC0_ADDR;
6763 ha->vpd_base = FA_NVRAM_VPD0_ADDR;
6764 } else {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006765 ha->nvram_base = FA_NVRAM_FUNC1_ADDR;
andrew.vasquez@qlogic.com6f641792006-03-09 14:27:34 -08006766 ha->vpd_base = FA_NVRAM_VPD1_ADDR;
6767 }
Chad Dupuisf73cb692014-02-26 04:15:06 -05006768
Anirban Chakrabortye5b68a62009-04-06 22:33:50 -07006769 ha->nvram_size = sizeof(struct nvram_24xx);
6770 ha->vpd_size = FA_NVRAM_VPD_SIZE;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006771
Seokmann Ju281afe12007-07-26 13:43:34 -07006772 /* Get VPD data into cache */
6773 ha->vpd = ha->nvram + VPD_OFFSET;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006774 ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd,
Seokmann Ju281afe12007-07-26 13:43:34 -07006775 ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4);
6776
6777 /* Get NVRAM data into cache and calculate checksum. */
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006778 dptr = (uint32_t *)nv;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006779 ha->isp_ops->read_nvram(vha, (uint8_t *)dptr, ha->nvram_base,
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006780 ha->nvram_size);
Joe Carnuccioda08ef52016-01-27 12:03:34 -05006781 for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++)
6782 chksum += le32_to_cpu(*dptr);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006783
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006784 ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x006a,
6785 "Contents of NVRAM\n");
6786 ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010d,
6787 (uint8_t *)nv, ha->nvram_size);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006788
6789 /* Bad NVRAM data, set defaults parameters. */
6790 if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P'
6791 || nv->id[3] != ' ' ||
Bart Van Asschead950362015-07-09 07:24:08 -07006792 nv->nvram_version < cpu_to_le16(ICB_VERSION)) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006793 /* Reset NVRAM data. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006794 ql_log(ql_log_warn, vha, 0x006b,
Raul Porcel9e336522012-05-15 14:34:08 -04006795 "Inconsistent NVRAM detected: checksum=0x%x id=%c "
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006796 "version=0x%x.\n", chksum, nv->id[0], nv->nvram_version);
6797 ql_log(ql_log_warn, vha, 0x006c,
6798 "Falling back to functioning (yet invalid -- WWPN) "
6799 "defaults.\n");
David Miller4e08df32007-04-16 12:37:43 -07006800
6801 /*
6802 * Set default initialization control block.
6803 */
6804 memset(nv, 0, ha->nvram_size);
Bart Van Asschead950362015-07-09 07:24:08 -07006805 nv->nvram_version = cpu_to_le16(ICB_VERSION);
6806 nv->version = cpu_to_le16(ICB_VERSION);
Joe Carnuccio98aee702014-09-25 05:16:38 -04006807 nv->frame_payload_size = 2048;
Bart Van Asschead950362015-07-09 07:24:08 -07006808 nv->execution_throttle = cpu_to_le16(0xFFFF);
6809 nv->exchange_count = cpu_to_le16(0);
6810 nv->hard_address = cpu_to_le16(124);
David Miller4e08df32007-04-16 12:37:43 -07006811 nv->port_name[0] = 0x21;
Chad Dupuisf73cb692014-02-26 04:15:06 -05006812 nv->port_name[1] = 0x00 + ha->port_no + 1;
David Miller4e08df32007-04-16 12:37:43 -07006813 nv->port_name[2] = 0x00;
6814 nv->port_name[3] = 0xe0;
6815 nv->port_name[4] = 0x8b;
6816 nv->port_name[5] = 0x1c;
6817 nv->port_name[6] = 0x55;
6818 nv->port_name[7] = 0x86;
6819 nv->node_name[0] = 0x20;
6820 nv->node_name[1] = 0x00;
6821 nv->node_name[2] = 0x00;
6822 nv->node_name[3] = 0xe0;
6823 nv->node_name[4] = 0x8b;
6824 nv->node_name[5] = 0x1c;
6825 nv->node_name[6] = 0x55;
6826 nv->node_name[7] = 0x86;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006827 qla24xx_nvram_wwn_from_ofw(vha, nv);
Bart Van Asschead950362015-07-09 07:24:08 -07006828 nv->login_retry_count = cpu_to_le16(8);
6829 nv->interrupt_delay_timer = cpu_to_le16(0);
6830 nv->login_timeout = cpu_to_le16(0);
David Miller4e08df32007-04-16 12:37:43 -07006831 nv->firmware_options_1 =
Bart Van Asschead950362015-07-09 07:24:08 -07006832 cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1);
6833 nv->firmware_options_2 = cpu_to_le32(2 << 4);
6834 nv->firmware_options_2 |= cpu_to_le32(BIT_12);
6835 nv->firmware_options_3 = cpu_to_le32(2 << 13);
6836 nv->host_p = cpu_to_le32(BIT_11|BIT_10);
6837 nv->efi_parameters = cpu_to_le32(0);
David Miller4e08df32007-04-16 12:37:43 -07006838 nv->reset_delay = 5;
Bart Van Asschead950362015-07-09 07:24:08 -07006839 nv->max_luns_per_target = cpu_to_le16(128);
6840 nv->port_down_retry_count = cpu_to_le16(30);
6841 nv->link_down_timeout = cpu_to_le16(30);
David Miller4e08df32007-04-16 12:37:43 -07006842
6843 rval = 1;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006844 }
6845
Quinn Tran726b8542017-01-19 22:28:00 -08006846 if (qla_tgt_mode_enabled(vha)) {
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04006847 /* Don't enable full login after initial LIP */
Bart Van Asschead950362015-07-09 07:24:08 -07006848 nv->firmware_options_1 &= cpu_to_le32(~BIT_13);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04006849 /* Don't enable LIP full login for initiator */
Bart Van Asschead950362015-07-09 07:24:08 -07006850 nv->host_p &= cpu_to_le32(~BIT_10);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04006851 }
6852
6853 qlt_24xx_config_nvram_stage1(vha, nv);
6854
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006855 /* Reset Initialization control block */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006856 memset(icb, 0, ha->init_cb_size);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006857
6858 /* Copy 1st segment. */
6859 dptr1 = (uint8_t *)icb;
6860 dptr2 = (uint8_t *)&nv->version;
6861 cnt = (uint8_t *)&icb->response_q_inpointer - (uint8_t *)&icb->version;
6862 while (cnt--)
6863 *dptr1++ = *dptr2++;
6864
6865 icb->login_retry_count = nv->login_retry_count;
Andrew Vasquez3ea66e22006-06-23 16:11:27 -07006866 icb->link_down_on_nos = nv->link_down_on_nos;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006867
6868 /* Copy 2nd segment. */
6869 dptr1 = (uint8_t *)&icb->interrupt_delay_timer;
6870 dptr2 = (uint8_t *)&nv->interrupt_delay_timer;
6871 cnt = (uint8_t *)&icb->reserved_3 -
6872 (uint8_t *)&icb->interrupt_delay_timer;
6873 while (cnt--)
6874 *dptr1++ = *dptr2++;
6875
6876 /*
6877 * Setup driver NVRAM options.
6878 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006879 qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name),
Andrew Vasquez9bb9fcf2007-01-29 10:22:24 -08006880 "QLA2462");
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006881
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04006882 qlt_24xx_config_nvram_stage2(vha, icb);
6883
Bart Van Asschead950362015-07-09 07:24:08 -07006884 if (nv->host_p & cpu_to_le32(BIT_15)) {
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04006885 /* Use alternate WWN? */
Andrew Vasquez5341e862006-05-17 15:09:16 -07006886 memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
6887 memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
6888 }
6889
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006890 /* Prepare nodename */
Bart Van Asschead950362015-07-09 07:24:08 -07006891 if ((icb->firmware_options_1 & cpu_to_le32(BIT_14)) == 0) {
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006892 /*
6893 * Firmware will apply the following mask if the nodename was
6894 * not provided.
6895 */
6896 memcpy(icb->node_name, icb->port_name, WWN_SIZE);
6897 icb->node_name[0] &= 0xF0;
6898 }
6899
6900 /* Set host adapter parameters. */
6901 ha->flags.disable_risc_code_load = 0;
Andrew Vasquez0c8c39a2006-12-13 19:20:30 -08006902 ha->flags.enable_lip_reset = 0;
6903 ha->flags.enable_lip_full_login =
6904 le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0;
6905 ha->flags.enable_target_reset =
6906 le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006907 ha->flags.enable_led_scheme = 0;
Andrew Vasquezd4c760c2006-06-23 16:10:39 -07006908 ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006909
Andrew Vasquezfd0e7e42006-05-17 15:09:11 -07006910 ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) &
6911 (BIT_6 | BIT_5 | BIT_4)) >> 4;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006912
6913 memcpy(ha->fw_seriallink_options24, nv->seriallink_options,
6914 sizeof(ha->fw_seriallink_options24));
6915
6916 /* save HBA serial number */
6917 ha->serial0 = icb->port_name[5];
6918 ha->serial1 = icb->port_name[6];
6919 ha->serial2 = icb->port_name[7];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006920 memcpy(vha->node_name, icb->node_name, WWN_SIZE);
6921 memcpy(vha->port_name, icb->port_name, WWN_SIZE);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006922
Bart Van Asschead950362015-07-09 07:24:08 -07006923 icb->execution_throttle = cpu_to_le16(0xFFFF);
andrew.vasquez@qlogic.combc8fb3c2006-01-13 17:05:42 -08006924
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006925 ha->retry_count = le16_to_cpu(nv->login_retry_count);
6926
6927 /* Set minimum login_timeout to 4 seconds. */
6928 if (le16_to_cpu(nv->login_timeout) < ql2xlogintimeout)
6929 nv->login_timeout = cpu_to_le16(ql2xlogintimeout);
6930 if (le16_to_cpu(nv->login_timeout) < 4)
Bart Van Asschead950362015-07-09 07:24:08 -07006931 nv->login_timeout = cpu_to_le16(4);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006932 ha->login_timeout = le16_to_cpu(nv->login_timeout);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006933
Andrew Vasquez00a537b2008-02-28 14:06:11 -08006934 /* Set minimum RATOV to 100 tenths of a second. */
6935 ha->r_a_tov = 100;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07006936
6937 ha->loop_reset_delay = nv->reset_delay;
6938
6939 /* Link Down Timeout = 0:
6940 *
6941 * When Port Down timer expires we will start returning
6942 * I/O's to OS with "DID_NO_CONNECT".
6943 *
6944 * Link Down Timeout != 0:
6945 *
6946 * The driver waits for the link to come up after link down
6947 * before returning I/Os to OS with "DID_NO_CONNECT".
6948 */
6949 if (le16_to_cpu(nv->link_down_timeout) == 0) {
6950 ha->loop_down_abort_time =
6951 (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT);
6952 } else {
6953 ha->link_down_timeout = le16_to_cpu(nv->link_down_timeout);
6954 ha->loop_down_abort_time =
6955 (LOOP_DOWN_TIME - ha->link_down_timeout);
6956 }
6957
6958 /* Need enough time to try and get the port back. */
6959 ha->port_down_retry_count = le16_to_cpu(nv->port_down_retry_count);
6960 if (qlport_down_retry)
6961 ha->port_down_retry_count = qlport_down_retry;
6962
6963 /* Set login_retry_count */
6964 ha->login_retry_count = le16_to_cpu(nv->login_retry_count);
6965 if (ha->port_down_retry_count ==
6966 le16_to_cpu(nv->port_down_retry_count) &&
6967 ha->port_down_retry_count > 3)
6968 ha->login_retry_count = ha->port_down_retry_count;
6969 else if (ha->port_down_retry_count > (int)ha->login_retry_count)
6970 ha->login_retry_count = ha->port_down_retry_count;
6971 if (ql2xloginretrycount)
6972 ha->login_retry_count = ql2xloginretrycount;
6973
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07006974 /* Enable ZIO. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006975 if (!vha->flags.init_done) {
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07006976 ha->zio_mode = le32_to_cpu(icb->firmware_options_2) &
6977 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
6978 ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ?
6979 le16_to_cpu(icb->interrupt_delay_timer): 2;
6980 }
Bart Van Asschead950362015-07-09 07:24:08 -07006981 icb->firmware_options_2 &= cpu_to_le32(
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07006982 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006983 vha->flags.process_response_queue = 0;
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07006984 if (ha->zio_mode != QLA_ZIO_DISABLED) {
andrew.vasquez@qlogic.com4a59f712006-03-09 14:27:39 -08006985 ha->zio_mode = QLA_ZIO_MODE_6;
6986
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006987 ql_log(ql_log_info, vha, 0x006f,
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07006988 "ZIO mode %d enabled; timer delay (%d us).\n",
6989 ha->zio_mode, ha->zio_timer * 100);
6990
6991 icb->firmware_options_2 |= cpu_to_le32(
6992 (uint32_t)ha->zio_mode);
6993 icb->interrupt_delay_timer = cpu_to_le16(ha->zio_timer);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08006994 vha->flags.process_response_queue = 1;
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07006995 }
6996
David Miller4e08df32007-04-16 12:37:43 -07006997 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07006998 ql_log(ql_log_warn, vha, 0x0070,
6999 "NVRAM configuration failed.\n");
David Miller4e08df32007-04-16 12:37:43 -07007000 }
7001 return (rval);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007002}
7003
Sawan Chandak4243c112016-01-27 12:03:31 -05007004uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha)
7005{
7006 struct qla27xx_image_status pri_image_status, sec_image_status;
7007 uint8_t valid_pri_image, valid_sec_image;
7008 uint32_t *wptr;
7009 uint32_t cnt, chksum, size;
7010 struct qla_hw_data *ha = vha->hw;
7011
7012 valid_pri_image = valid_sec_image = 1;
7013 ha->active_image = 0;
7014 size = sizeof(struct qla27xx_image_status) / sizeof(uint32_t);
7015
7016 if (!ha->flt_region_img_status_pri) {
7017 valid_pri_image = 0;
7018 goto check_sec_image;
7019 }
7020
7021 qla24xx_read_flash_data(vha, (uint32_t *)(&pri_image_status),
7022 ha->flt_region_img_status_pri, size);
7023
7024 if (pri_image_status.signature != QLA27XX_IMG_STATUS_SIGN) {
7025 ql_dbg(ql_dbg_init, vha, 0x018b,
7026 "Primary image signature (0x%x) not valid\n",
7027 pri_image_status.signature);
7028 valid_pri_image = 0;
7029 goto check_sec_image;
7030 }
7031
7032 wptr = (uint32_t *)(&pri_image_status);
7033 cnt = size;
7034
Joe Carnuccioda08ef52016-01-27 12:03:34 -05007035 for (chksum = 0; cnt--; wptr++)
7036 chksum += le32_to_cpu(*wptr);
Quinn Tran41dc5292017-01-19 22:28:03 -08007037
Sawan Chandak4243c112016-01-27 12:03:31 -05007038 if (chksum) {
7039 ql_dbg(ql_dbg_init, vha, 0x018c,
7040 "Checksum validation failed for primary image (0x%x)\n",
7041 chksum);
7042 valid_pri_image = 0;
7043 }
7044
7045check_sec_image:
7046 if (!ha->flt_region_img_status_sec) {
7047 valid_sec_image = 0;
7048 goto check_valid_image;
7049 }
7050
7051 qla24xx_read_flash_data(vha, (uint32_t *)(&sec_image_status),
7052 ha->flt_region_img_status_sec, size);
7053
7054 if (sec_image_status.signature != QLA27XX_IMG_STATUS_SIGN) {
7055 ql_dbg(ql_dbg_init, vha, 0x018d,
7056 "Secondary image signature(0x%x) not valid\n",
7057 sec_image_status.signature);
7058 valid_sec_image = 0;
7059 goto check_valid_image;
7060 }
7061
7062 wptr = (uint32_t *)(&sec_image_status);
7063 cnt = size;
Joe Carnuccioda08ef52016-01-27 12:03:34 -05007064 for (chksum = 0; cnt--; wptr++)
7065 chksum += le32_to_cpu(*wptr);
Sawan Chandak4243c112016-01-27 12:03:31 -05007066 if (chksum) {
7067 ql_dbg(ql_dbg_init, vha, 0x018e,
7068 "Checksum validation failed for secondary image (0x%x)\n",
7069 chksum);
7070 valid_sec_image = 0;
7071 }
7072
7073check_valid_image:
7074 if (valid_pri_image && (pri_image_status.image_status_mask & 0x1))
7075 ha->active_image = QLA27XX_PRIMARY_IMAGE;
7076 if (valid_sec_image && (sec_image_status.image_status_mask & 0x1)) {
7077 if (!ha->active_image ||
7078 pri_image_status.generation_number <
7079 sec_image_status.generation_number)
7080 ha->active_image = QLA27XX_SECONDARY_IMAGE;
7081 }
7082
7083 ql_dbg(ql_dbg_init, vha, 0x018f, "%s image\n",
7084 ha->active_image == 0 ? "default bootld and fw" :
7085 ha->active_image == 1 ? "primary" :
7086 ha->active_image == 2 ? "secondary" :
7087 "Invalid");
7088
7089 return ha->active_image;
7090}
7091
Adrian Bunk413975a2006-06-30 02:33:06 -07007092static int
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007093qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
7094 uint32_t faddr)
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007095{
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007096 int rval = QLA_SUCCESS;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007097 int segments, fragment;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007098 uint32_t *dcode, dlen;
7099 uint32_t risc_addr;
7100 uint32_t risc_size;
7101 uint32_t i;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007102 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007103 struct req_que *req = ha->req_q_map[0];
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007104
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007105 ql_dbg(ql_dbg_init, vha, 0x008b,
Chad Dupuiscfb09192011-11-18 09:03:07 -08007106 "FW: Loading firmware from flash (%x).\n", faddr);
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007107
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007108 rval = QLA_SUCCESS;
7109
7110 segments = FA_RISC_CODE_SEGMENTS;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007111 dcode = (uint32_t *)req->ring;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007112 *srisc_addr = 0;
7113
Sawan Chandak4243c112016-01-27 12:03:31 -05007114 if (IS_QLA27XX(ha) &&
7115 qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
7116 faddr = ha->flt_region_fw_sec;
7117
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007118 /* Validate firmware image by checking version. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007119 qla24xx_read_flash_data(vha, dcode, faddr + 4, 4);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007120 for (i = 0; i < 4; i++)
7121 dcode[i] = be32_to_cpu(dcode[i]);
7122 if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
7123 dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
7124 (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
7125 dcode[3] == 0)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007126 ql_log(ql_log_fatal, vha, 0x008c,
7127 "Unable to verify the integrity of flash firmware "
7128 "image.\n");
7129 ql_log(ql_log_fatal, vha, 0x008d,
7130 "Firmware data: %08x %08x %08x %08x.\n",
7131 dcode[0], dcode[1], dcode[2], dcode[3]);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007132
7133 return QLA_FUNCTION_FAILED;
7134 }
7135
7136 while (segments && rval == QLA_SUCCESS) {
7137 /* Read segment's load information. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007138 qla24xx_read_flash_data(vha, dcode, faddr, 4);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007139
7140 risc_addr = be32_to_cpu(dcode[2]);
7141 *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr;
7142 risc_size = be32_to_cpu(dcode[3]);
7143
7144 fragment = 0;
7145 while (risc_size > 0 && rval == QLA_SUCCESS) {
7146 dlen = (uint32_t)(ha->fw_transfer_size >> 2);
7147 if (dlen > risc_size)
7148 dlen = risc_size;
7149
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007150 ql_dbg(ql_dbg_init, vha, 0x008e,
7151 "Loading risc segment@ risc addr %x "
7152 "number of dwords 0x%x offset 0x%x.\n",
7153 risc_addr, dlen, faddr);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007154
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007155 qla24xx_read_flash_data(vha, dcode, faddr, dlen);
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007156 for (i = 0; i < dlen; i++)
7157 dcode[i] = swab32(dcode[i]);
7158
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007159 rval = qla2x00_load_ram(vha, req->dma, risc_addr,
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007160 dlen);
7161 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007162 ql_log(ql_log_fatal, vha, 0x008f,
7163 "Failed to load segment %d of firmware.\n",
7164 fragment);
Chad Dupuisf261f7a2014-09-25 05:17:03 -04007165 return QLA_FUNCTION_FAILED;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007166 }
7167
7168 faddr += dlen;
7169 risc_addr += dlen;
7170 risc_size -= dlen;
7171 fragment++;
7172 }
7173
7174 /* Next segment. */
7175 segments--;
7176 }
7177
Chad Dupuisf73cb692014-02-26 04:15:06 -05007178 if (!IS_QLA27XX(ha))
7179 return rval;
7180
7181 if (ha->fw_dump_template)
7182 vfree(ha->fw_dump_template);
7183 ha->fw_dump_template = NULL;
7184 ha->fw_dump_template_len = 0;
7185
7186 ql_dbg(ql_dbg_init, vha, 0x0161,
7187 "Loading fwdump template from %x\n", faddr);
7188 qla24xx_read_flash_data(vha, dcode, faddr, 7);
7189 risc_size = be32_to_cpu(dcode[2]);
7190 ql_dbg(ql_dbg_init, vha, 0x0162,
7191 "-> array size %x dwords\n", risc_size);
7192 if (risc_size == 0 || risc_size == ~0)
7193 goto default_template;
7194
7195 dlen = (risc_size - 8) * sizeof(*dcode);
7196 ql_dbg(ql_dbg_init, vha, 0x0163,
7197 "-> template allocating %x bytes...\n", dlen);
7198 ha->fw_dump_template = vmalloc(dlen);
7199 if (!ha->fw_dump_template) {
7200 ql_log(ql_log_warn, vha, 0x0164,
7201 "Failed fwdump template allocate %x bytes.\n", risc_size);
7202 goto default_template;
7203 }
7204
7205 faddr += 7;
7206 risc_size -= 8;
7207 dcode = ha->fw_dump_template;
7208 qla24xx_read_flash_data(vha, dcode, faddr, risc_size);
7209 for (i = 0; i < risc_size; i++)
7210 dcode[i] = le32_to_cpu(dcode[i]);
7211
7212 if (!qla27xx_fwdt_template_valid(dcode)) {
7213 ql_log(ql_log_warn, vha, 0x0165,
7214 "Failed fwdump template validate\n");
7215 goto default_template;
7216 }
7217
7218 dlen = qla27xx_fwdt_template_size(dcode);
7219 ql_dbg(ql_dbg_init, vha, 0x0166,
7220 "-> template size %x bytes\n", dlen);
7221 if (dlen > risc_size * sizeof(*dcode)) {
7222 ql_log(ql_log_warn, vha, 0x0167,
Himanshu Madhani4fae52b2017-06-06 13:55:23 -07007223 "Failed fwdump template exceeds array by %zx bytes\n",
Joe Carnuccio383a2982017-06-02 09:11:55 -07007224 (size_t)(dlen - risc_size * sizeof(*dcode)));
Chad Dupuisf73cb692014-02-26 04:15:06 -05007225 goto default_template;
7226 }
7227 ha->fw_dump_template_len = dlen;
7228 return rval;
7229
7230default_template:
7231 ql_log(ql_log_warn, vha, 0x0168, "Using default fwdump template\n");
7232 if (ha->fw_dump_template)
7233 vfree(ha->fw_dump_template);
7234 ha->fw_dump_template = NULL;
7235 ha->fw_dump_template_len = 0;
7236
7237 dlen = qla27xx_fwdt_template_default_size();
7238 ql_dbg(ql_dbg_init, vha, 0x0169,
7239 "-> template allocating %x bytes...\n", dlen);
7240 ha->fw_dump_template = vmalloc(dlen);
7241 if (!ha->fw_dump_template) {
7242 ql_log(ql_log_warn, vha, 0x016a,
7243 "Failed fwdump template allocate %x bytes.\n", risc_size);
7244 goto failed_template;
7245 }
7246
7247 dcode = ha->fw_dump_template;
7248 risc_size = dlen / sizeof(*dcode);
7249 memcpy(dcode, qla27xx_fwdt_template_default(), dlen);
7250 for (i = 0; i < risc_size; i++)
7251 dcode[i] = be32_to_cpu(dcode[i]);
7252
7253 if (!qla27xx_fwdt_template_valid(ha->fw_dump_template)) {
7254 ql_log(ql_log_warn, vha, 0x016b,
7255 "Failed fwdump template validate\n");
7256 goto failed_template;
7257 }
7258
7259 dlen = qla27xx_fwdt_template_size(ha->fw_dump_template);
7260 ql_dbg(ql_dbg_init, vha, 0x016c,
7261 "-> template size %x bytes\n", dlen);
7262 ha->fw_dump_template_len = dlen;
7263 return rval;
7264
7265failed_template:
7266 ql_log(ql_log_warn, vha, 0x016d, "Failed default fwdump template\n");
7267 if (ha->fw_dump_template)
7268 vfree(ha->fw_dump_template);
7269 ha->fw_dump_template = NULL;
7270 ha->fw_dump_template_len = 0;
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007271 return rval;
7272}
7273
Giridhar Malavalie9454a82013-02-08 01:57:47 -05007274#define QLA_FW_URL "http://ldriver.qlogic.com/firmware/"
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007275
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007276int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007277qla2x00_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
Andrew Vasquez54333832005-11-09 15:49:04 -08007278{
7279 int rval;
7280 int i, fragment;
7281 uint16_t *wcode, *fwcode;
7282 uint32_t risc_addr, risc_size, fwclen, wlen, *seg;
7283 struct fw_blob *blob;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007284 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007285 struct req_que *req = ha->req_q_map[0];
Andrew Vasquez54333832005-11-09 15:49:04 -08007286
7287 /* Load firmware blob. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007288 blob = qla2x00_request_firmware(vha);
Andrew Vasquez54333832005-11-09 15:49:04 -08007289 if (!blob) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007290 ql_log(ql_log_info, vha, 0x0083,
Yannick Guerrini94bcf832015-02-26 22:49:34 +01007291 "Firmware image unavailable.\n");
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007292 ql_log(ql_log_info, vha, 0x0084,
7293 "Firmware images can be retrieved from: "QLA_FW_URL ".\n");
Andrew Vasquez54333832005-11-09 15:49:04 -08007294 return QLA_FUNCTION_FAILED;
7295 }
7296
7297 rval = QLA_SUCCESS;
7298
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007299 wcode = (uint16_t *)req->ring;
Andrew Vasquez54333832005-11-09 15:49:04 -08007300 *srisc_addr = 0;
7301 fwcode = (uint16_t *)blob->fw->data;
7302 fwclen = 0;
7303
7304 /* Validate firmware image by checking version. */
7305 if (blob->fw->size < 8 * sizeof(uint16_t)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007306 ql_log(ql_log_fatal, vha, 0x0085,
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08007307 "Unable to verify integrity of firmware image (%zd).\n",
Andrew Vasquez54333832005-11-09 15:49:04 -08007308 blob->fw->size);
7309 goto fail_fw_integrity;
7310 }
7311 for (i = 0; i < 4; i++)
7312 wcode[i] = be16_to_cpu(fwcode[i + 4]);
7313 if ((wcode[0] == 0xffff && wcode[1] == 0xffff && wcode[2] == 0xffff &&
7314 wcode[3] == 0xffff) || (wcode[0] == 0 && wcode[1] == 0 &&
7315 wcode[2] == 0 && wcode[3] == 0)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007316 ql_log(ql_log_fatal, vha, 0x0086,
7317 "Unable to verify integrity of firmware image.\n");
7318 ql_log(ql_log_fatal, vha, 0x0087,
7319 "Firmware data: %04x %04x %04x %04x.\n",
7320 wcode[0], wcode[1], wcode[2], wcode[3]);
Andrew Vasquez54333832005-11-09 15:49:04 -08007321 goto fail_fw_integrity;
7322 }
7323
7324 seg = blob->segs;
7325 while (*seg && rval == QLA_SUCCESS) {
7326 risc_addr = *seg;
7327 *srisc_addr = *srisc_addr == 0 ? *seg : *srisc_addr;
7328 risc_size = be16_to_cpu(fwcode[3]);
7329
7330 /* Validate firmware image size. */
7331 fwclen += risc_size * sizeof(uint16_t);
7332 if (blob->fw->size < fwclen) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007333 ql_log(ql_log_fatal, vha, 0x0088,
Andrew Vasquez54333832005-11-09 15:49:04 -08007334 "Unable to verify integrity of firmware image "
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08007335 "(%zd).\n", blob->fw->size);
Andrew Vasquez54333832005-11-09 15:49:04 -08007336 goto fail_fw_integrity;
7337 }
7338
7339 fragment = 0;
7340 while (risc_size > 0 && rval == QLA_SUCCESS) {
7341 wlen = (uint16_t)(ha->fw_transfer_size >> 1);
7342 if (wlen > risc_size)
7343 wlen = risc_size;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007344 ql_dbg(ql_dbg_init, vha, 0x0089,
7345 "Loading risc segment@ risc addr %x number of "
7346 "words 0x%x.\n", risc_addr, wlen);
Andrew Vasquez54333832005-11-09 15:49:04 -08007347
7348 for (i = 0; i < wlen; i++)
7349 wcode[i] = swab16(fwcode[i]);
7350
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007351 rval = qla2x00_load_ram(vha, req->dma, risc_addr,
Andrew Vasquez54333832005-11-09 15:49:04 -08007352 wlen);
7353 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007354 ql_log(ql_log_fatal, vha, 0x008a,
7355 "Failed to load segment %d of firmware.\n",
7356 fragment);
Andrew Vasquez54333832005-11-09 15:49:04 -08007357 break;
7358 }
7359
7360 fwcode += wlen;
7361 risc_addr += wlen;
7362 risc_size -= wlen;
7363 fragment++;
7364 }
7365
7366 /* Next segment. */
7367 seg++;
7368 }
7369 return rval;
7370
7371fail_fw_integrity:
7372 return QLA_FUNCTION_FAILED;
7373}
7374
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007375static int
7376qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007377{
7378 int rval;
7379 int segments, fragment;
7380 uint32_t *dcode, dlen;
7381 uint32_t risc_addr;
7382 uint32_t risc_size;
7383 uint32_t i;
Andrew Vasquez54333832005-11-09 15:49:04 -08007384 struct fw_blob *blob;
Chad Dupuisf73cb692014-02-26 04:15:06 -05007385 const uint32_t *fwcode;
7386 uint32_t fwclen;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007387 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007388 struct req_que *req = ha->req_q_map[0];
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007389
Andrew Vasquez54333832005-11-09 15:49:04 -08007390 /* Load firmware blob. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007391 blob = qla2x00_request_firmware(vha);
Andrew Vasquez54333832005-11-09 15:49:04 -08007392 if (!blob) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007393 ql_log(ql_log_warn, vha, 0x0090,
Yannick Guerrini94bcf832015-02-26 22:49:34 +01007394 "Firmware image unavailable.\n");
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007395 ql_log(ql_log_warn, vha, 0x0091,
7396 "Firmware images can be retrieved from: "
7397 QLA_FW_URL ".\n");
Andrew Vasquezd1c61902006-05-17 15:09:00 -07007398
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007399 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007400 }
7401
Chad Dupuiscfb09192011-11-18 09:03:07 -08007402 ql_dbg(ql_dbg_init, vha, 0x0092,
7403 "FW: Loading via request-firmware.\n");
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007404
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007405 rval = QLA_SUCCESS;
7406
7407 segments = FA_RISC_CODE_SEGMENTS;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007408 dcode = (uint32_t *)req->ring;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007409 *srisc_addr = 0;
Andrew Vasquez54333832005-11-09 15:49:04 -08007410 fwcode = (uint32_t *)blob->fw->data;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007411 fwclen = 0;
7412
7413 /* Validate firmware image by checking version. */
Andrew Vasquez54333832005-11-09 15:49:04 -08007414 if (blob->fw->size < 8 * sizeof(uint32_t)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007415 ql_log(ql_log_fatal, vha, 0x0093,
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08007416 "Unable to verify integrity of firmware image (%zd).\n",
Andrew Vasquez54333832005-11-09 15:49:04 -08007417 blob->fw->size);
Chad Dupuisf73cb692014-02-26 04:15:06 -05007418 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007419 }
7420 for (i = 0; i < 4; i++)
7421 dcode[i] = be32_to_cpu(fwcode[i + 4]);
7422 if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
7423 dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
7424 (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
7425 dcode[3] == 0)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007426 ql_log(ql_log_fatal, vha, 0x0094,
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08007427 "Unable to verify integrity of firmware image (%zd).\n",
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007428 blob->fw->size);
7429 ql_log(ql_log_fatal, vha, 0x0095,
7430 "Firmware data: %08x %08x %08x %08x.\n",
7431 dcode[0], dcode[1], dcode[2], dcode[3]);
Chad Dupuisf73cb692014-02-26 04:15:06 -05007432 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007433 }
7434
7435 while (segments && rval == QLA_SUCCESS) {
7436 risc_addr = be32_to_cpu(fwcode[2]);
7437 *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr;
7438 risc_size = be32_to_cpu(fwcode[3]);
7439
7440 /* Validate firmware image size. */
7441 fwclen += risc_size * sizeof(uint32_t);
Andrew Vasquez54333832005-11-09 15:49:04 -08007442 if (blob->fw->size < fwclen) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007443 ql_log(ql_log_fatal, vha, 0x0096,
Andrew Vasquez54333832005-11-09 15:49:04 -08007444 "Unable to verify integrity of firmware image "
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08007445 "(%zd).\n", blob->fw->size);
Chad Dupuisf73cb692014-02-26 04:15:06 -05007446 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007447 }
7448
7449 fragment = 0;
7450 while (risc_size > 0 && rval == QLA_SUCCESS) {
7451 dlen = (uint32_t)(ha->fw_transfer_size >> 2);
7452 if (dlen > risc_size)
7453 dlen = risc_size;
7454
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007455 ql_dbg(ql_dbg_init, vha, 0x0097,
7456 "Loading risc segment@ risc addr %x "
7457 "number of dwords 0x%x.\n", risc_addr, dlen);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007458
7459 for (i = 0; i < dlen; i++)
7460 dcode[i] = swab32(fwcode[i]);
7461
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007462 rval = qla2x00_load_ram(vha, req->dma, risc_addr,
andrew.vasquez@qlogic.com590f98e2006-01-13 17:05:37 -08007463 dlen);
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007464 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007465 ql_log(ql_log_fatal, vha, 0x0098,
7466 "Failed to load segment %d of firmware.\n",
7467 fragment);
Chad Dupuisf261f7a2014-09-25 05:17:03 -04007468 return QLA_FUNCTION_FAILED;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007469 }
7470
7471 fwcode += dlen;
7472 risc_addr += dlen;
7473 risc_size -= dlen;
7474 fragment++;
7475 }
7476
7477 /* Next segment. */
7478 segments--;
7479 }
Chad Dupuisf73cb692014-02-26 04:15:06 -05007480
7481 if (!IS_QLA27XX(ha))
7482 return rval;
7483
7484 if (ha->fw_dump_template)
7485 vfree(ha->fw_dump_template);
7486 ha->fw_dump_template = NULL;
7487 ha->fw_dump_template_len = 0;
7488
7489 ql_dbg(ql_dbg_init, vha, 0x171,
Chad Dupuis97ea7022014-03-13 14:16:40 -04007490 "Loading fwdump template from %x\n",
7491 (uint32_t)((void *)fwcode - (void *)blob->fw->data));
Chad Dupuisf73cb692014-02-26 04:15:06 -05007492 risc_size = be32_to_cpu(fwcode[2]);
7493 ql_dbg(ql_dbg_init, vha, 0x172,
7494 "-> array size %x dwords\n", risc_size);
7495 if (risc_size == 0 || risc_size == ~0)
7496 goto default_template;
7497
7498 dlen = (risc_size - 8) * sizeof(*fwcode);
7499 ql_dbg(ql_dbg_init, vha, 0x0173,
7500 "-> template allocating %x bytes...\n", dlen);
7501 ha->fw_dump_template = vmalloc(dlen);
7502 if (!ha->fw_dump_template) {
7503 ql_log(ql_log_warn, vha, 0x0174,
7504 "Failed fwdump template allocate %x bytes.\n", risc_size);
7505 goto default_template;
7506 }
7507
7508 fwcode += 7;
7509 risc_size -= 8;
7510 dcode = ha->fw_dump_template;
7511 for (i = 0; i < risc_size; i++)
7512 dcode[i] = le32_to_cpu(fwcode[i]);
7513
7514 if (!qla27xx_fwdt_template_valid(dcode)) {
7515 ql_log(ql_log_warn, vha, 0x0175,
7516 "Failed fwdump template validate\n");
7517 goto default_template;
7518 }
7519
7520 dlen = qla27xx_fwdt_template_size(dcode);
7521 ql_dbg(ql_dbg_init, vha, 0x0176,
7522 "-> template size %x bytes\n", dlen);
7523 if (dlen > risc_size * sizeof(*fwcode)) {
7524 ql_log(ql_log_warn, vha, 0x0177,
Himanshu Madhani4fae52b2017-06-06 13:55:23 -07007525 "Failed fwdump template exceeds array by %zx bytes\n",
Joe Carnuccio383a2982017-06-02 09:11:55 -07007526 (size_t)(dlen - risc_size * sizeof(*fwcode)));
Chad Dupuisf73cb692014-02-26 04:15:06 -05007527 goto default_template;
7528 }
7529 ha->fw_dump_template_len = dlen;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007530 return rval;
7531
Chad Dupuisf73cb692014-02-26 04:15:06 -05007532default_template:
7533 ql_log(ql_log_warn, vha, 0x0178, "Using default fwdump template\n");
7534 if (ha->fw_dump_template)
7535 vfree(ha->fw_dump_template);
7536 ha->fw_dump_template = NULL;
7537 ha->fw_dump_template_len = 0;
7538
7539 dlen = qla27xx_fwdt_template_default_size();
7540 ql_dbg(ql_dbg_init, vha, 0x0179,
7541 "-> template allocating %x bytes...\n", dlen);
7542 ha->fw_dump_template = vmalloc(dlen);
7543 if (!ha->fw_dump_template) {
7544 ql_log(ql_log_warn, vha, 0x017a,
7545 "Failed fwdump template allocate %x bytes.\n", risc_size);
7546 goto failed_template;
7547 }
7548
7549 dcode = ha->fw_dump_template;
7550 risc_size = dlen / sizeof(*fwcode);
7551 fwcode = qla27xx_fwdt_template_default();
7552 for (i = 0; i < risc_size; i++)
7553 dcode[i] = be32_to_cpu(fwcode[i]);
7554
7555 if (!qla27xx_fwdt_template_valid(ha->fw_dump_template)) {
7556 ql_log(ql_log_warn, vha, 0x017b,
7557 "Failed fwdump template validate\n");
7558 goto failed_template;
7559 }
7560
7561 dlen = qla27xx_fwdt_template_size(ha->fw_dump_template);
7562 ql_dbg(ql_dbg_init, vha, 0x017c,
7563 "-> template size %x bytes\n", dlen);
7564 ha->fw_dump_template_len = dlen;
7565 return rval;
7566
7567failed_template:
7568 ql_log(ql_log_warn, vha, 0x017d, "Failed default fwdump template\n");
7569 if (ha->fw_dump_template)
7570 vfree(ha->fw_dump_template);
7571 ha->fw_dump_template = NULL;
7572 ha->fw_dump_template_len = 0;
7573 return rval;
Andrew Vasquez0107109e2005-07-06 10:31:37 -07007574}
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007575
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007576int
7577qla24xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
7578{
7579 int rval;
7580
Andrew Vasqueze337d902009-04-06 22:33:49 -07007581 if (ql2xfwloadbin == 1)
7582 return qla81xx_load_risc(vha, srisc_addr);
7583
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007584 /*
7585 * FW Load priority:
7586 * 1) Firmware via request-firmware interface (.bin file).
7587 * 2) Firmware residing in flash.
7588 */
7589 rval = qla24xx_load_risc_blob(vha, srisc_addr);
7590 if (rval == QLA_SUCCESS)
7591 return rval;
7592
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007593 return qla24xx_load_risc_flash(vha, srisc_addr,
7594 vha->hw->flt_region_fw);
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007595}
7596
7597int
7598qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
7599{
7600 int rval;
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007601 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007602
Andrew Vasqueze337d902009-04-06 22:33:49 -07007603 if (ql2xfwloadbin == 2)
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007604 goto try_blob_fw;
Andrew Vasqueze337d902009-04-06 22:33:49 -07007605
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007606 /*
7607 * FW Load priority:
7608 * 1) Firmware residing in flash.
7609 * 2) Firmware via request-firmware interface (.bin file).
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007610 * 3) Golden-Firmware residing in flash -- limited operation.
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007611 */
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007612 rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_fw);
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007613 if (rval == QLA_SUCCESS)
7614 return rval;
7615
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007616try_blob_fw:
7617 rval = qla24xx_load_risc_blob(vha, srisc_addr);
7618 if (rval == QLA_SUCCESS || !ha->flt_region_gold_fw)
7619 return rval;
7620
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007621 ql_log(ql_log_info, vha, 0x0099,
7622 "Attempting to fallback to golden firmware.\n");
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007623 rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_gold_fw);
7624 if (rval != QLA_SUCCESS)
7625 return rval;
7626
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007627 ql_log(ql_log_info, vha, 0x009a, "Update operational firmware.\n");
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007628 ha->flags.running_gold_fw = 1;
Andrew Vasquezcbc8eb62009-06-03 09:55:17 -07007629 return rval;
Andrew Vasquezeaac30b2009-01-22 09:45:32 -08007630}
7631
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007632void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007633qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha)
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007634{
7635 int ret, retries;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007636 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007637
Andrew Vasquez85880802009-12-15 21:29:46 -08007638 if (ha->flags.pci_channel_io_perm_failure)
7639 return;
Andrew Vasqueze4289242007-07-19 15:05:56 -07007640 if (!IS_FWI2_CAPABLE(ha))
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007641 return;
Andrew Vasquez75edf812007-05-07 07:43:00 -07007642 if (!ha->fw_major_version)
7643 return;
Quinn Tranec7193e2017-03-15 09:48:55 -07007644 if (!ha->flags.fw_started)
7645 return;
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007646
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007647 ret = qla2x00_stop_firmware(vha);
Andrew Vasquez7c7f1f22008-02-28 14:06:09 -08007648 for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT &&
Andrew Vasquezb469a7c2009-04-06 22:33:48 -07007649 ret != QLA_INVALID_COMMAND && retries ; retries--) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007650 ha->isp_ops->reset_chip(vha);
7651 if (ha->isp_ops->chip_diag(vha) != QLA_SUCCESS)
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007652 continue;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007653 if (qla2x00_setup_chip(vha) != QLA_SUCCESS)
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007654 continue;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007655 ql_log(ql_log_info, vha, 0x8015,
7656 "Attempting retry of stop-firmware command.\n");
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007657 ret = qla2x00_stop_firmware(vha);
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007658 }
Quinn Tranec7193e2017-03-15 09:48:55 -07007659
Quinn Tran4b60c822017-06-13 20:47:21 -07007660 QLA_FW_STOPPED(ha);
Quinn Tranec7193e2017-03-15 09:48:55 -07007661 ha->flags.fw_init_done = 0;
Andrew Vasquez18c6c122006-10-13 09:33:38 -07007662}
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007663
7664int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007665qla24xx_configure_vhba(scsi_qla_host_t *vha)
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007666{
7667 int rval = QLA_SUCCESS;
Chad Dupuis0b91d112012-02-09 11:15:42 -08007668 int rval2;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007669 uint16_t mb[MAILBOX_REGISTER_COUNT];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007670 struct qla_hw_data *ha = vha->hw;
7671 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Anirban Chakraborty67c2e932009-04-06 22:33:42 -07007672 struct req_que *req;
7673 struct rsp_que *rsp;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007674
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007675 if (!vha->vp_idx)
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007676 return -EINVAL;
7677
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007678 rval = qla2x00_fw_ready(base_vha);
Michael Hernandezd7459522016-12-12 14:40:07 -08007679 if (vha->qpair)
7680 req = vha->qpair->req;
Anirban Chakraborty67c2e932009-04-06 22:33:42 -07007681 else
Michael Hernandezd7459522016-12-12 14:40:07 -08007682 req = ha->req_q_map[0];
Anirban Chakraborty67c2e932009-04-06 22:33:42 -07007683 rsp = req->rsp;
7684
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007685 if (rval == QLA_SUCCESS) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007686 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08007687 qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007688 }
7689
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007690 vha->flags.management_server_logged_in = 0;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007691
7692 /* Login to SNS first */
Chad Dupuis0b91d112012-02-09 11:15:42 -08007693 rval2 = ha->isp_ops->fabric_login(vha, NPH_SNS, 0xff, 0xff, 0xfc, mb,
7694 BIT_1);
7695 if (rval2 != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {
7696 if (rval2 == QLA_MEMORY_ALLOC_FAILED)
7697 ql_dbg(ql_dbg_init, vha, 0x0120,
7698 "Failed SNS login: loop_id=%x, rval2=%d\n",
7699 NPH_SNS, rval2);
7700 else
7701 ql_dbg(ql_dbg_init, vha, 0x0103,
7702 "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x "
7703 "mb[2]=%x mb[6]=%x mb[7]=%x.\n",
7704 NPH_SNS, mb[0], mb[1], mb[2], mb[6], mb[7]);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007705 return (QLA_FUNCTION_FAILED);
7706 }
7707
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007708 atomic_set(&vha->loop_down_timer, 0);
7709 atomic_set(&vha->loop_state, LOOP_UP);
7710 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
7711 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
7712 rval = qla2x00_loop_resync(base_vha);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07007713
7714 return rval;
7715}
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007716
7717/* 84XX Support **************************************************************/
7718
7719static LIST_HEAD(qla_cs84xx_list);
7720static DEFINE_MUTEX(qla_cs84xx_mutex);
7721
7722static struct qla_chip_state_84xx *
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007723qla84xx_get_chip(struct scsi_qla_host *vha)
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007724{
7725 struct qla_chip_state_84xx *cs84xx;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007726 struct qla_hw_data *ha = vha->hw;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007727
7728 mutex_lock(&qla_cs84xx_mutex);
7729
7730 /* Find any shared 84xx chip. */
7731 list_for_each_entry(cs84xx, &qla_cs84xx_list, list) {
7732 if (cs84xx->bus == ha->pdev->bus) {
7733 kref_get(&cs84xx->kref);
7734 goto done;
7735 }
7736 }
7737
7738 cs84xx = kzalloc(sizeof(*cs84xx), GFP_KERNEL);
7739 if (!cs84xx)
7740 goto done;
7741
7742 kref_init(&cs84xx->kref);
7743 spin_lock_init(&cs84xx->access_lock);
7744 mutex_init(&cs84xx->fw_update_mutex);
7745 cs84xx->bus = ha->pdev->bus;
7746
7747 list_add_tail(&cs84xx->list, &qla_cs84xx_list);
7748done:
7749 mutex_unlock(&qla_cs84xx_mutex);
7750 return cs84xx;
7751}
7752
7753static void
7754__qla84xx_chip_release(struct kref *kref)
7755{
7756 struct qla_chip_state_84xx *cs84xx =
7757 container_of(kref, struct qla_chip_state_84xx, kref);
7758
7759 mutex_lock(&qla_cs84xx_mutex);
7760 list_del(&cs84xx->list);
7761 mutex_unlock(&qla_cs84xx_mutex);
7762 kfree(cs84xx);
7763}
7764
7765void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007766qla84xx_put_chip(struct scsi_qla_host *vha)
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007767{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007768 struct qla_hw_data *ha = vha->hw;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007769 if (ha->cs84xx)
7770 kref_put(&ha->cs84xx->kref, __qla84xx_chip_release);
7771}
7772
7773static int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007774qla84xx_init_chip(scsi_qla_host_t *vha)
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007775{
7776 int rval;
7777 uint16_t status[2];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007778 struct qla_hw_data *ha = vha->hw;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007779
7780 mutex_lock(&ha->cs84xx->fw_update_mutex);
7781
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08007782 rval = qla84xx_verify_chip(vha, status);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07007783
7784 mutex_unlock(&ha->cs84xx->fw_update_mutex);
7785
7786 return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED:
7787 QLA_SUCCESS;
7788}
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007789
7790/* 81XX Support **************************************************************/
7791
7792int
7793qla81xx_nvram_config(scsi_qla_host_t *vha)
7794{
7795 int rval;
7796 struct init_cb_81xx *icb;
7797 struct nvram_81xx *nv;
7798 uint32_t *dptr;
7799 uint8_t *dptr1, *dptr2;
7800 uint32_t chksum;
7801 uint16_t cnt;
7802 struct qla_hw_data *ha = vha->hw;
7803
7804 rval = QLA_SUCCESS;
7805 icb = (struct init_cb_81xx *)ha->init_cb;
7806 nv = ha->nvram;
7807
7808 /* Determine NVRAM starting address. */
7809 ha->nvram_size = sizeof(struct nvram_81xx);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007810 ha->vpd_size = FA_NVRAM_VPD_SIZE;
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04007811 if (IS_P3P_TYPE(ha) || IS_QLA8031(ha))
7812 ha->vpd_size = FA_VPD_SIZE_82XX;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007813
7814 /* Get VPD data into cache */
7815 ha->vpd = ha->nvram + VPD_OFFSET;
Andrew Vasquez3d79038f2009-03-24 09:08:14 -07007816 ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2,
7817 ha->vpd_size);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007818
7819 /* Get NVRAM data into cache and calculate checksum. */
Andrew Vasquez3d79038f2009-03-24 09:08:14 -07007820 ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2,
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007821 ha->nvram_size);
Andrew Vasquez3d79038f2009-03-24 09:08:14 -07007822 dptr = (uint32_t *)nv;
Joe Carnuccioda08ef52016-01-27 12:03:34 -05007823 for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++)
7824 chksum += le32_to_cpu(*dptr);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007825
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007826 ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0111,
7827 "Contents of NVRAM:\n");
7828 ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0112,
7829 (uint8_t *)nv, ha->nvram_size);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007830
7831 /* Bad NVRAM data, set defaults parameters. */
7832 if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P'
7833 || nv->id[3] != ' ' ||
Bart Van Asschead950362015-07-09 07:24:08 -07007834 nv->nvram_version < cpu_to_le16(ICB_VERSION)) {
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007835 /* Reset NVRAM data. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007836 ql_log(ql_log_info, vha, 0x0073,
Raul Porcel9e336522012-05-15 14:34:08 -04007837 "Inconsistent NVRAM detected: checksum=0x%x id=%c "
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007838 "version=0x%x.\n", chksum, nv->id[0],
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007839 le16_to_cpu(nv->nvram_version));
Saurav Kashyap7c3df132011-07-14 12:00:13 -07007840 ql_log(ql_log_info, vha, 0x0074,
7841 "Falling back to functioning (yet invalid -- WWPN) "
7842 "defaults.\n");
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007843
7844 /*
7845 * Set default initialization control block.
7846 */
7847 memset(nv, 0, ha->nvram_size);
Bart Van Asschead950362015-07-09 07:24:08 -07007848 nv->nvram_version = cpu_to_le16(ICB_VERSION);
7849 nv->version = cpu_to_le16(ICB_VERSION);
Joe Carnuccio98aee702014-09-25 05:16:38 -04007850 nv->frame_payload_size = 2048;
Bart Van Asschead950362015-07-09 07:24:08 -07007851 nv->execution_throttle = cpu_to_le16(0xFFFF);
7852 nv->exchange_count = cpu_to_le16(0);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007853 nv->port_name[0] = 0x21;
Chad Dupuisf73cb692014-02-26 04:15:06 -05007854 nv->port_name[1] = 0x00 + ha->port_no + 1;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007855 nv->port_name[2] = 0x00;
7856 nv->port_name[3] = 0xe0;
7857 nv->port_name[4] = 0x8b;
7858 nv->port_name[5] = 0x1c;
7859 nv->port_name[6] = 0x55;
7860 nv->port_name[7] = 0x86;
7861 nv->node_name[0] = 0x20;
7862 nv->node_name[1] = 0x00;
7863 nv->node_name[2] = 0x00;
7864 nv->node_name[3] = 0xe0;
7865 nv->node_name[4] = 0x8b;
7866 nv->node_name[5] = 0x1c;
7867 nv->node_name[6] = 0x55;
7868 nv->node_name[7] = 0x86;
Bart Van Asschead950362015-07-09 07:24:08 -07007869 nv->login_retry_count = cpu_to_le16(8);
7870 nv->interrupt_delay_timer = cpu_to_le16(0);
7871 nv->login_timeout = cpu_to_le16(0);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007872 nv->firmware_options_1 =
Bart Van Asschead950362015-07-09 07:24:08 -07007873 cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1);
7874 nv->firmware_options_2 = cpu_to_le32(2 << 4);
7875 nv->firmware_options_2 |= cpu_to_le32(BIT_12);
7876 nv->firmware_options_3 = cpu_to_le32(2 << 13);
7877 nv->host_p = cpu_to_le32(BIT_11|BIT_10);
7878 nv->efi_parameters = cpu_to_le32(0);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007879 nv->reset_delay = 5;
Bart Van Asschead950362015-07-09 07:24:08 -07007880 nv->max_luns_per_target = cpu_to_le16(128);
7881 nv->port_down_retry_count = cpu_to_le16(30);
7882 nv->link_down_timeout = cpu_to_le16(180);
Andrew Vasquezeeebcc92009-06-03 09:55:24 -07007883 nv->enode_mac[0] = 0x00;
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08007884 nv->enode_mac[1] = 0xC0;
7885 nv->enode_mac[2] = 0xDD;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007886 nv->enode_mac[3] = 0x04;
7887 nv->enode_mac[4] = 0x05;
Chad Dupuisf73cb692014-02-26 04:15:06 -05007888 nv->enode_mac[5] = 0x06 + ha->port_no + 1;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007889
7890 rval = 1;
7891 }
7892
Arun Easi9e522cd2012-08-22 14:21:31 -04007893 if (IS_T10_PI_CAPABLE(ha))
7894 nv->frame_payload_size &= ~7;
7895
Arun Easiaa230bc2013-01-30 03:34:39 -05007896 qlt_81xx_config_nvram_stage1(vha, nv);
7897
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007898 /* Reset Initialization control block */
Andrew Vasquez773120e2011-05-10 11:30:14 -07007899 memset(icb, 0, ha->init_cb_size);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007900
7901 /* Copy 1st segment. */
7902 dptr1 = (uint8_t *)icb;
7903 dptr2 = (uint8_t *)&nv->version;
7904 cnt = (uint8_t *)&icb->response_q_inpointer - (uint8_t *)&icb->version;
7905 while (cnt--)
7906 *dptr1++ = *dptr2++;
7907
7908 icb->login_retry_count = nv->login_retry_count;
7909
7910 /* Copy 2nd segment. */
7911 dptr1 = (uint8_t *)&icb->interrupt_delay_timer;
7912 dptr2 = (uint8_t *)&nv->interrupt_delay_timer;
7913 cnt = (uint8_t *)&icb->reserved_5 -
7914 (uint8_t *)&icb->interrupt_delay_timer;
7915 while (cnt--)
7916 *dptr1++ = *dptr2++;
7917
7918 memcpy(icb->enode_mac, nv->enode_mac, sizeof(icb->enode_mac));
7919 /* Some boards (with valid NVRAMs) still have NULL enode_mac!! */
7920 if (!memcmp(icb->enode_mac, "\0\0\0\0\0\0", sizeof(icb->enode_mac))) {
Andrew Vasquez69e5f1e2012-02-09 11:15:35 -08007921 icb->enode_mac[0] = 0x00;
7922 icb->enode_mac[1] = 0xC0;
7923 icb->enode_mac[2] = 0xDD;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007924 icb->enode_mac[3] = 0x04;
7925 icb->enode_mac[4] = 0x05;
Chad Dupuisf73cb692014-02-26 04:15:06 -05007926 icb->enode_mac[5] = 0x06 + ha->port_no + 1;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007927 }
7928
Andrew Vasquezb64b0e82009-03-24 09:08:01 -07007929 /* Use extended-initialization control block. */
7930 memcpy(ha->ex_init_cb, &nv->ex_version, sizeof(*ha->ex_init_cb));
7931
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007932 /*
7933 * Setup driver NVRAM options.
7934 */
7935 qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name),
Giridhar Malavalia9083012010-04-12 17:59:55 -07007936 "QLE8XXX");
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007937
Arun Easiaa230bc2013-01-30 03:34:39 -05007938 qlt_81xx_config_nvram_stage2(vha, icb);
7939
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007940 /* Use alternate WWN? */
Bart Van Asschead950362015-07-09 07:24:08 -07007941 if (nv->host_p & cpu_to_le32(BIT_15)) {
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007942 memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
7943 memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
7944 }
7945
7946 /* Prepare nodename */
Bart Van Asschead950362015-07-09 07:24:08 -07007947 if ((icb->firmware_options_1 & cpu_to_le32(BIT_14)) == 0) {
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007948 /*
7949 * Firmware will apply the following mask if the nodename was
7950 * not provided.
7951 */
7952 memcpy(icb->node_name, icb->port_name, WWN_SIZE);
7953 icb->node_name[0] &= 0xF0;
7954 }
7955
7956 /* Set host adapter parameters. */
7957 ha->flags.disable_risc_code_load = 0;
7958 ha->flags.enable_lip_reset = 0;
7959 ha->flags.enable_lip_full_login =
7960 le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0;
7961 ha->flags.enable_target_reset =
7962 le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0;
7963 ha->flags.enable_led_scheme = 0;
7964 ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0;
7965
7966 ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) &
7967 (BIT_6 | BIT_5 | BIT_4)) >> 4;
7968
7969 /* save HBA serial number */
7970 ha->serial0 = icb->port_name[5];
7971 ha->serial1 = icb->port_name[6];
7972 ha->serial2 = icb->port_name[7];
7973 memcpy(vha->node_name, icb->node_name, WWN_SIZE);
7974 memcpy(vha->port_name, icb->port_name, WWN_SIZE);
7975
Bart Van Asschead950362015-07-09 07:24:08 -07007976 icb->execution_throttle = cpu_to_le16(0xFFFF);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007977
7978 ha->retry_count = le16_to_cpu(nv->login_retry_count);
7979
7980 /* Set minimum login_timeout to 4 seconds. */
7981 if (le16_to_cpu(nv->login_timeout) < ql2xlogintimeout)
7982 nv->login_timeout = cpu_to_le16(ql2xlogintimeout);
7983 if (le16_to_cpu(nv->login_timeout) < 4)
Bart Van Asschead950362015-07-09 07:24:08 -07007984 nv->login_timeout = cpu_to_le16(4);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007985 ha->login_timeout = le16_to_cpu(nv->login_timeout);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007986
7987 /* Set minimum RATOV to 100 tenths of a second. */
7988 ha->r_a_tov = 100;
7989
7990 ha->loop_reset_delay = nv->reset_delay;
7991
7992 /* Link Down Timeout = 0:
7993 *
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04007994 * When Port Down timer expires we will start returning
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08007995 * I/O's to OS with "DID_NO_CONNECT".
7996 *
7997 * Link Down Timeout != 0:
7998 *
7999 * The driver waits for the link to come up after link down
8000 * before returning I/Os to OS with "DID_NO_CONNECT".
8001 */
8002 if (le16_to_cpu(nv->link_down_timeout) == 0) {
8003 ha->loop_down_abort_time =
8004 (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT);
8005 } else {
8006 ha->link_down_timeout = le16_to_cpu(nv->link_down_timeout);
8007 ha->loop_down_abort_time =
8008 (LOOP_DOWN_TIME - ha->link_down_timeout);
8009 }
8010
8011 /* Need enough time to try and get the port back. */
8012 ha->port_down_retry_count = le16_to_cpu(nv->port_down_retry_count);
8013 if (qlport_down_retry)
8014 ha->port_down_retry_count = qlport_down_retry;
8015
8016 /* Set login_retry_count */
8017 ha->login_retry_count = le16_to_cpu(nv->login_retry_count);
8018 if (ha->port_down_retry_count ==
8019 le16_to_cpu(nv->port_down_retry_count) &&
8020 ha->port_down_retry_count > 3)
8021 ha->login_retry_count = ha->port_down_retry_count;
8022 else if (ha->port_down_retry_count > (int)ha->login_retry_count)
8023 ha->login_retry_count = ha->port_down_retry_count;
8024 if (ql2xloginretrycount)
8025 ha->login_retry_count = ql2xloginretrycount;
8026
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08008027 /* if not running MSI-X we need handshaking on interrupts */
Chad Dupuisf73cb692014-02-26 04:15:06 -05008028 if (!vha->hw->flags.msix_enabled && (IS_QLA83XX(ha) || IS_QLA27XX(ha)))
Bart Van Asschead950362015-07-09 07:24:08 -07008029 icb->firmware_options_2 |= cpu_to_le32(BIT_22);
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08008030
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08008031 /* Enable ZIO. */
8032 if (!vha->flags.init_done) {
8033 ha->zio_mode = le32_to_cpu(icb->firmware_options_2) &
8034 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
8035 ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ?
8036 le16_to_cpu(icb->interrupt_delay_timer): 2;
8037 }
Bart Van Asschead950362015-07-09 07:24:08 -07008038 icb->firmware_options_2 &= cpu_to_le32(
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08008039 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
8040 vha->flags.process_response_queue = 0;
8041 if (ha->zio_mode != QLA_ZIO_DISABLED) {
8042 ha->zio_mode = QLA_ZIO_MODE_6;
8043
Saurav Kashyap7c3df132011-07-14 12:00:13 -07008044 ql_log(ql_log_info, vha, 0x0075,
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08008045 "ZIO mode %d enabled; timer delay (%d us).\n",
Saurav Kashyap7c3df132011-07-14 12:00:13 -07008046 ha->zio_mode,
8047 ha->zio_timer * 100);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08008048
8049 icb->firmware_options_2 |= cpu_to_le32(
8050 (uint32_t)ha->zio_mode);
8051 icb->interrupt_delay_timer = cpu_to_le16(ha->zio_timer);
8052 vha->flags.process_response_queue = 1;
8053 }
8054
Quinn Tran41dc5292017-01-19 22:28:03 -08008055 /* enable RIDA Format2 */
8056 if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha))
8057 icb->firmware_options_3 |= BIT_0;
8058
Duane Grigsbyedd05de2017-10-13 09:34:06 -07008059 if (IS_QLA27XX(ha)) {
8060 icb->firmware_options_3 |= BIT_8;
8061 ql_dbg(ql_log_info, vha, 0x0075,
8062 "Enabling direct connection.\n");
8063 }
8064
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08008065 if (rval) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07008066 ql_log(ql_log_warn, vha, 0x0076,
8067 "NVRAM configuration failed.\n");
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08008068 }
8069 return (rval);
8070}
8071
Giridhar Malavalia9083012010-04-12 17:59:55 -07008072int
8073qla82xx_restart_isp(scsi_qla_host_t *vha)
8074{
8075 int status, rval;
Giridhar Malavalia9083012010-04-12 17:59:55 -07008076 struct qla_hw_data *ha = vha->hw;
8077 struct req_que *req = ha->req_q_map[0];
8078 struct rsp_que *rsp = ha->rsp_q_map[0];
8079 struct scsi_qla_host *vp;
Arun Easifeafb7b2010-09-03 14:57:00 -07008080 unsigned long flags;
Giridhar Malavalia9083012010-04-12 17:59:55 -07008081
8082 status = qla2x00_init_rings(vha);
8083 if (!status) {
8084 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
8085 ha->flags.chip_reset_done = 1;
8086
8087 status = qla2x00_fw_ready(vha);
8088 if (!status) {
Giridhar Malavalia9083012010-04-12 17:59:55 -07008089 /* Issue a marker after FW becomes ready. */
8090 qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
Giridhar Malavalia9083012010-04-12 17:59:55 -07008091 vha->flags.online = 1;
Chad Dupuis7108b762014-04-11 16:54:45 -04008092 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
Giridhar Malavalia9083012010-04-12 17:59:55 -07008093 }
8094
8095 /* if no cable then assume it's good */
8096 if ((vha->device_flags & DFLG_NO_CABLE))
8097 status = 0;
Giridhar Malavalia9083012010-04-12 17:59:55 -07008098 }
8099
8100 if (!status) {
8101 clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
8102
8103 if (!atomic_read(&vha->loop_down_timer)) {
8104 /*
8105 * Issue marker command only when we are going
8106 * to start the I/O .
8107 */
8108 vha->marker_needed = 1;
8109 }
8110
Giridhar Malavalia9083012010-04-12 17:59:55 -07008111 ha->isp_ops->enable_intrs(ha);
8112
8113 ha->isp_abort_cnt = 0;
8114 clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
8115
Saurav Kashyap53296782011-05-10 11:30:06 -07008116 /* Update the firmware version */
Giridhar Malavali31731672011-08-16 11:31:54 -07008117 status = qla82xx_check_md_needed(vha);
Saurav Kashyap53296782011-05-10 11:30:06 -07008118
Giridhar Malavalia9083012010-04-12 17:59:55 -07008119 if (ha->fce) {
8120 ha->flags.fce_enabled = 1;
8121 memset(ha->fce, 0,
8122 fce_calc_size(ha->fce_bufs));
8123 rval = qla2x00_enable_fce_trace(vha,
8124 ha->fce_dma, ha->fce_bufs, ha->fce_mb,
8125 &ha->fce_bufs);
8126 if (rval) {
Chad Dupuiscfb09192011-11-18 09:03:07 -08008127 ql_log(ql_log_warn, vha, 0x8001,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07008128 "Unable to reinitialize FCE (%d).\n",
8129 rval);
Giridhar Malavalia9083012010-04-12 17:59:55 -07008130 ha->flags.fce_enabled = 0;
8131 }
8132 }
8133
8134 if (ha->eft) {
8135 memset(ha->eft, 0, EFT_SIZE);
8136 rval = qla2x00_enable_eft_trace(vha,
8137 ha->eft_dma, EFT_NUM_BUFFERS);
8138 if (rval) {
Chad Dupuiscfb09192011-11-18 09:03:07 -08008139 ql_log(ql_log_warn, vha, 0x8010,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07008140 "Unable to reinitialize EFT (%d).\n",
8141 rval);
Giridhar Malavalia9083012010-04-12 17:59:55 -07008142 }
8143 }
Giridhar Malavalia9083012010-04-12 17:59:55 -07008144 }
8145
8146 if (!status) {
Chad Dupuiscfb09192011-11-18 09:03:07 -08008147 ql_dbg(ql_dbg_taskm, vha, 0x8011,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07008148 "qla82xx_restart_isp succeeded.\n");
Arun Easifeafb7b2010-09-03 14:57:00 -07008149
8150 spin_lock_irqsave(&ha->vport_slock, flags);
8151 list_for_each_entry(vp, &ha->vp_list, list) {
8152 if (vp->vp_idx) {
8153 atomic_inc(&vp->vref_count);
8154 spin_unlock_irqrestore(&ha->vport_slock, flags);
8155
Giridhar Malavalia9083012010-04-12 17:59:55 -07008156 qla2x00_vp_abort_isp(vp);
Arun Easifeafb7b2010-09-03 14:57:00 -07008157
8158 spin_lock_irqsave(&ha->vport_slock, flags);
8159 atomic_dec(&vp->vref_count);
8160 }
Giridhar Malavalia9083012010-04-12 17:59:55 -07008161 }
Arun Easifeafb7b2010-09-03 14:57:00 -07008162 spin_unlock_irqrestore(&ha->vport_slock, flags);
8163
Giridhar Malavalia9083012010-04-12 17:59:55 -07008164 } else {
Chad Dupuiscfb09192011-11-18 09:03:07 -08008165 ql_log(ql_log_warn, vha, 0x8016,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07008166 "qla82xx_restart_isp **** FAILED ****.\n");
Giridhar Malavalia9083012010-04-12 17:59:55 -07008167 }
8168
8169 return status;
8170}
8171
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08008172void
Andrew Vasquezae97c912010-02-18 10:07:28 -08008173qla81xx_update_fw_options(scsi_qla_host_t *vha)
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08008174{
Andrew Vasquezae97c912010-02-18 10:07:28 -08008175 struct qla_hw_data *ha = vha->hw;
8176
Himanshu Madhanif198caf2016-01-27 12:03:30 -05008177 /* Hold status IOCBs until ABTS response received. */
8178 if (ql2xfwholdabts)
8179 ha->fw_options[3] |= BIT_12;
8180
Giridhar Malavali088d09d2016-07-06 11:14:20 -04008181 /* Set Retry FLOGI in case of P2P connection */
8182 if (ha->operating_mode == P2P) {
8183 ha->fw_options[2] |= BIT_3;
8184 ql_dbg(ql_dbg_disc, vha, 0x2103,
8185 "(%s): Setting FLOGI retry BIT in fw_options[2]: 0x%x\n",
8186 __func__, ha->fw_options[2]);
8187 }
8188
Quinn Tran41dc5292017-01-19 22:28:03 -08008189 /* Move PUREX, ABTS RX & RIDA to ATIOQ */
8190 if (ql2xmvasynctoatio) {
8191 if (qla_tgt_mode_enabled(vha) ||
8192 qla_dual_mode_enabled(vha))
8193 ha->fw_options[2] |= BIT_11;
8194 else
8195 ha->fw_options[2] &= ~BIT_11;
8196 }
Andrew Vasquezae97c912010-02-18 10:07:28 -08008197
Quinn Tranf7e761f2017-06-02 09:12:02 -07008198 if (qla_tgt_mode_enabled(vha) ||
Quinn Tran2da52732017-06-02 09:12:05 -07008199 qla_dual_mode_enabled(vha)) {
8200 /* FW auto send SCSI status during */
8201 ha->fw_options[1] |= BIT_8;
8202 ha->fw_options[10] |= (u16)SAM_STAT_BUSY << 8;
8203
8204 /* FW perform Exchange validation */
Quinn Tranf7e761f2017-06-02 09:12:02 -07008205 ha->fw_options[2] |= BIT_4;
Quinn Tran2da52732017-06-02 09:12:05 -07008206 } else {
8207 ha->fw_options[1] &= ~BIT_8;
8208 ha->fw_options[10] &= 0x00ff;
8209
Quinn Tranf7e761f2017-06-02 09:12:02 -07008210 ha->fw_options[2] &= ~BIT_4;
Quinn Tran2da52732017-06-02 09:12:05 -07008211 }
Quinn Tranf7e761f2017-06-02 09:12:02 -07008212
Quinn Tran41dc5292017-01-19 22:28:03 -08008213 if (ql2xetsenable) {
8214 /* Enable ETS Burst. */
8215 memset(ha->fw_options, 0, sizeof(ha->fw_options));
8216 ha->fw_options[2] |= BIT_9;
8217 }
8218
Quinn Tran83548fe2017-06-02 09:12:01 -07008219 ql_dbg(ql_dbg_init, vha, 0x00e9,
8220 "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n",
8221 __func__, ha->fw_options[1], ha->fw_options[2],
8222 ha->fw_options[3], vha->host->active_mode);
Quinn Tran41dc5292017-01-19 22:28:03 -08008223
Andrew Vasquezae97c912010-02-18 10:07:28 -08008224 qla2x00_set_fw_options(vha, ha->fw_options);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08008225}
Sarang Radke09ff7012010-03-19 17:03:59 -07008226
8227/*
8228 * qla24xx_get_fcp_prio
8229 * Gets the fcp cmd priority value for the logged in port.
8230 * Looks for a match of the port descriptors within
8231 * each of the fcp prio config entries. If a match is found,
8232 * the tag (priority) value is returned.
8233 *
8234 * Input:
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08008235 * vha = scsi host structure pointer.
Sarang Radke09ff7012010-03-19 17:03:59 -07008236 * fcport = port structure pointer.
8237 *
8238 * Return:
Andrew Vasquez6c452a42010-03-19 17:04:02 -07008239 * non-zero (if found)
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07008240 * -1 (if not found)
Sarang Radke09ff7012010-03-19 17:03:59 -07008241 *
8242 * Context:
8243 * Kernel context
8244 */
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07008245static int
Sarang Radke09ff7012010-03-19 17:03:59 -07008246qla24xx_get_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
8247{
8248 int i, entries;
8249 uint8_t pid_match, wwn_match;
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07008250 int priority;
Sarang Radke09ff7012010-03-19 17:03:59 -07008251 uint32_t pid1, pid2;
8252 uint64_t wwn1, wwn2;
8253 struct qla_fcp_prio_entry *pri_entry;
8254 struct qla_hw_data *ha = vha->hw;
8255
8256 if (!ha->fcp_prio_cfg || !ha->flags.fcp_prio_enabled)
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07008257 return -1;
Sarang Radke09ff7012010-03-19 17:03:59 -07008258
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07008259 priority = -1;
Sarang Radke09ff7012010-03-19 17:03:59 -07008260 entries = ha->fcp_prio_cfg->num_entries;
8261 pri_entry = &ha->fcp_prio_cfg->entry[0];
8262
8263 for (i = 0; i < entries; i++) {
8264 pid_match = wwn_match = 0;
8265
8266 if (!(pri_entry->flags & FCP_PRIO_ENTRY_VALID)) {
8267 pri_entry++;
8268 continue;
8269 }
8270
8271 /* check source pid for a match */
8272 if (pri_entry->flags & FCP_PRIO_ENTRY_SPID_VALID) {
8273 pid1 = pri_entry->src_pid & INVALID_PORT_ID;
8274 pid2 = vha->d_id.b24 & INVALID_PORT_ID;
8275 if (pid1 == INVALID_PORT_ID)
8276 pid_match++;
8277 else if (pid1 == pid2)
8278 pid_match++;
8279 }
8280
8281 /* check destination pid for a match */
8282 if (pri_entry->flags & FCP_PRIO_ENTRY_DPID_VALID) {
8283 pid1 = pri_entry->dst_pid & INVALID_PORT_ID;
8284 pid2 = fcport->d_id.b24 & INVALID_PORT_ID;
8285 if (pid1 == INVALID_PORT_ID)
8286 pid_match++;
8287 else if (pid1 == pid2)
8288 pid_match++;
8289 }
8290
8291 /* check source WWN for a match */
8292 if (pri_entry->flags & FCP_PRIO_ENTRY_SWWN_VALID) {
8293 wwn1 = wwn_to_u64(vha->port_name);
8294 wwn2 = wwn_to_u64(pri_entry->src_wwpn);
8295 if (wwn2 == (uint64_t)-1)
8296 wwn_match++;
8297 else if (wwn1 == wwn2)
8298 wwn_match++;
8299 }
8300
8301 /* check destination WWN for a match */
8302 if (pri_entry->flags & FCP_PRIO_ENTRY_DWWN_VALID) {
8303 wwn1 = wwn_to_u64(fcport->port_name);
8304 wwn2 = wwn_to_u64(pri_entry->dst_wwpn);
8305 if (wwn2 == (uint64_t)-1)
8306 wwn_match++;
8307 else if (wwn1 == wwn2)
8308 wwn_match++;
8309 }
8310
8311 if (pid_match == 2 || wwn_match == 2) {
8312 /* Found a matching entry */
8313 if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID)
8314 priority = pri_entry->tag;
8315 break;
8316 }
8317
8318 pri_entry++;
8319 }
8320
8321 return priority;
8322}
8323
8324/*
8325 * qla24xx_update_fcport_fcp_prio
8326 * Activates fcp priority for the logged in fc port
8327 *
8328 * Input:
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08008329 * vha = scsi host structure pointer.
Sarang Radke09ff7012010-03-19 17:03:59 -07008330 * fcp = port structure pointer.
8331 *
8332 * Return:
8333 * QLA_SUCCESS or QLA_FUNCTION_FAILED
8334 *
8335 * Context:
8336 * Kernel context.
8337 */
8338int
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08008339qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
Sarang Radke09ff7012010-03-19 17:03:59 -07008340{
8341 int ret;
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07008342 int priority;
Sarang Radke09ff7012010-03-19 17:03:59 -07008343 uint16_t mb[5];
8344
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08008345 if (fcport->port_type != FCT_TARGET ||
8346 fcport->loop_id == FC_NO_LOOP_ID)
Sarang Radke09ff7012010-03-19 17:03:59 -07008347 return QLA_FUNCTION_FAILED;
8348
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08008349 priority = qla24xx_get_fcp_prio(vha, fcport);
Andrew Vasquezf28a0a92011-03-30 11:46:18 -07008350 if (priority < 0)
8351 return QLA_FUNCTION_FAILED;
8352
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04008353 if (IS_P3P_TYPE(vha->hw)) {
Saurav Kashyapa00f6292011-11-18 09:03:19 -08008354 fcport->fcp_prio = priority & 0xf;
8355 return QLA_SUCCESS;
8356 }
8357
Madhuranath Iyengar21090cb2010-12-21 16:00:18 -08008358 ret = qla24xx_set_fcp_prio(vha, fcport->loop_id, priority, mb);
Chad Dupuiscfb09192011-11-18 09:03:07 -08008359 if (ret == QLA_SUCCESS) {
8360 if (fcport->fcp_prio != priority)
8361 ql_dbg(ql_dbg_user, vha, 0x709e,
8362 "Updated FCP_CMND priority - value=%d loop_id=%d "
8363 "port_id=%02x%02x%02x.\n", priority,
8364 fcport->loop_id, fcport->d_id.b.domain,
8365 fcport->d_id.b.area, fcport->d_id.b.al_pa);
Saurav Kashyapa00f6292011-11-18 09:03:19 -08008366 fcport->fcp_prio = priority & 0xf;
Chad Dupuiscfb09192011-11-18 09:03:07 -08008367 } else
Saurav Kashyap7c3df132011-07-14 12:00:13 -07008368 ql_dbg(ql_dbg_user, vha, 0x704f,
Chad Dupuiscfb09192011-11-18 09:03:07 -08008369 "Unable to update FCP_CMND priority - ret=0x%x for "
8370 "loop_id=%d port_id=%02x%02x%02x.\n", ret, fcport->loop_id,
8371 fcport->d_id.b.domain, fcport->d_id.b.area,
8372 fcport->d_id.b.al_pa);
Sarang Radke09ff7012010-03-19 17:03:59 -07008373 return ret;
8374}
8375
8376/*
8377 * qla24xx_update_all_fcp_prio
8378 * Activates fcp priority for all the logged in ports
8379 *
8380 * Input:
8381 * ha = adapter block pointer.
8382 *
8383 * Return:
8384 * QLA_SUCCESS or QLA_FUNCTION_FAILED
8385 *
8386 * Context:
8387 * Kernel context.
8388 */
8389int
8390qla24xx_update_all_fcp_prio(scsi_qla_host_t *vha)
8391{
8392 int ret;
8393 fc_port_t *fcport;
8394
8395 ret = QLA_FUNCTION_FAILED;
8396 /* We need to set priority for all logged in ports */
8397 list_for_each_entry(fcport, &vha->vp_fcports, list)
8398 ret = qla24xx_update_fcport_fcp_prio(vha, fcport);
8399
8400 return ret;
8401}
Michael Hernandezd7459522016-12-12 14:40:07 -08008402
Quinn Tran82de8022017-06-13 20:47:17 -07008403struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos,
8404 int vp_idx, bool startqp)
Michael Hernandezd7459522016-12-12 14:40:07 -08008405{
8406 int rsp_id = 0;
8407 int req_id = 0;
8408 int i;
8409 struct qla_hw_data *ha = vha->hw;
8410 uint16_t qpair_id = 0;
8411 struct qla_qpair *qpair = NULL;
8412 struct qla_msix_entry *msix;
8413
8414 if (!(ha->fw_attributes & BIT_6) || !ha->flags.msix_enabled) {
8415 ql_log(ql_log_warn, vha, 0x00181,
8416 "FW/Driver is not multi-queue capable.\n");
8417 return NULL;
8418 }
8419
Himanshu Madhanic38d1ba2017-10-13 15:43:22 -07008420 if (ql2xmqsupport || ql2xnvmeenable) {
Michael Hernandezd7459522016-12-12 14:40:07 -08008421 qpair = kzalloc(sizeof(struct qla_qpair), GFP_KERNEL);
8422 if (qpair == NULL) {
8423 ql_log(ql_log_warn, vha, 0x0182,
8424 "Failed to allocate memory for queue pair.\n");
8425 return NULL;
8426 }
8427 memset(qpair, 0, sizeof(struct qla_qpair));
8428
8429 qpair->hw = vha->hw;
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08008430 qpair->vha = vha;
Quinn Tran82de8022017-06-13 20:47:17 -07008431 qpair->qp_lock_ptr = &qpair->qp_lock;
8432 spin_lock_init(&qpair->qp_lock);
Quinn Tranaf7bb382017-06-13 20:47:23 -07008433 qpair->use_shadow_reg = IS_SHADOW_REG_CAPABLE(ha) ? 1 : 0;
Michael Hernandezd7459522016-12-12 14:40:07 -08008434
8435 /* Assign available que pair id */
8436 mutex_lock(&ha->mq_lock);
8437 qpair_id = find_first_zero_bit(ha->qpair_qid_map, ha->max_qpairs);
Sawan Chandakb95b9452017-05-24 18:06:20 -07008438 if (ha->num_qpairs >= ha->max_qpairs) {
Michael Hernandezd7459522016-12-12 14:40:07 -08008439 mutex_unlock(&ha->mq_lock);
8440 ql_log(ql_log_warn, vha, 0x0183,
8441 "No resources to create additional q pair.\n");
8442 goto fail_qid_map;
8443 }
Sawan Chandakb95b9452017-05-24 18:06:20 -07008444 ha->num_qpairs++;
Michael Hernandezd7459522016-12-12 14:40:07 -08008445 set_bit(qpair_id, ha->qpair_qid_map);
8446 ha->queue_pair_map[qpair_id] = qpair;
8447 qpair->id = qpair_id;
8448 qpair->vp_idx = vp_idx;
himanshu.madhani@cavium.come6373f332017-08-23 15:04:57 -07008449 qpair->fw_started = ha->flags.fw_started;
Quinn Trane326d222017-06-13 20:47:18 -07008450 INIT_LIST_HEAD(&qpair->hints_list);
Quinn Tran7c3f8fd2017-06-13 20:47:22 -07008451 qpair->chip_reset = ha->base_qpair->chip_reset;
8452 qpair->enable_class_2 = ha->base_qpair->enable_class_2;
8453 qpair->enable_explicit_conf =
8454 ha->base_qpair->enable_explicit_conf;
Michael Hernandezd7459522016-12-12 14:40:07 -08008455
8456 for (i = 0; i < ha->msix_count; i++) {
Quinn Tran093df732016-12-12 14:40:09 -08008457 msix = &ha->msix_entries[i];
Michael Hernandezd7459522016-12-12 14:40:07 -08008458 if (msix->in_use)
8459 continue;
8460 qpair->msix = msix;
Quinn Tran83548fe2017-06-02 09:12:01 -07008461 ql_dbg(ql_dbg_multiq, vha, 0xc00f,
Michael Hernandezd7459522016-12-12 14:40:07 -08008462 "Vector %x selected for qpair\n", msix->vector);
8463 break;
8464 }
8465 if (!qpair->msix) {
8466 ql_log(ql_log_warn, vha, 0x0184,
8467 "Out of MSI-X vectors!.\n");
8468 goto fail_msix;
8469 }
8470
8471 qpair->msix->in_use = 1;
8472 list_add_tail(&qpair->qp_list_elem, &vha->qp_list);
Quinn Tran8abfa9e2017-06-13 20:47:24 -07008473 qpair->pdev = ha->pdev;
8474 if (IS_QLA27XX(ha) || IS_QLA83XX(ha))
8475 qpair->reqq_start_iocbs = qla_83xx_start_iocbs;
Michael Hernandezd7459522016-12-12 14:40:07 -08008476
8477 mutex_unlock(&ha->mq_lock);
8478
8479 /* Create response queue first */
Quinn Tran82de8022017-06-13 20:47:17 -07008480 rsp_id = qla25xx_create_rsp_que(ha, 0, 0, 0, qpair, startqp);
Michael Hernandezd7459522016-12-12 14:40:07 -08008481 if (!rsp_id) {
8482 ql_log(ql_log_warn, vha, 0x0185,
8483 "Failed to create response queue.\n");
8484 goto fail_rsp;
8485 }
8486
8487 qpair->rsp = ha->rsp_q_map[rsp_id];
8488
8489 /* Create request queue */
Quinn Tran82de8022017-06-13 20:47:17 -07008490 req_id = qla25xx_create_req_que(ha, 0, vp_idx, 0, rsp_id, qos,
8491 startqp);
Michael Hernandezd7459522016-12-12 14:40:07 -08008492 if (!req_id) {
8493 ql_log(ql_log_warn, vha, 0x0186,
8494 "Failed to create request queue.\n");
8495 goto fail_req;
8496 }
8497
8498 qpair->req = ha->req_q_map[req_id];
8499 qpair->rsp->req = qpair->req;
Quinn Tran82de8022017-06-13 20:47:17 -07008500 qpair->rsp->qpair = qpair;
Quinn Trane326d222017-06-13 20:47:18 -07008501 /* init qpair to this cpu. Will adjust at run time. */
8502 qla_cpu_update(qpair, smp_processor_id());
Michael Hernandezd7459522016-12-12 14:40:07 -08008503
8504 if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) {
8505 if (ha->fw_attributes & BIT_4)
8506 qpair->difdix_supported = 1;
8507 }
8508
8509 qpair->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
8510 if (!qpair->srb_mempool) {
Quinn Tran83548fe2017-06-02 09:12:01 -07008511 ql_log(ql_log_warn, vha, 0xd036,
Michael Hernandezd7459522016-12-12 14:40:07 -08008512 "Failed to create srb mempool for qpair %d\n",
8513 qpair->id);
8514 goto fail_mempool;
8515 }
8516
8517 /* Mark as online */
8518 qpair->online = 1;
8519
8520 if (!vha->flags.qpairs_available)
8521 vha->flags.qpairs_available = 1;
8522
8523 ql_dbg(ql_dbg_multiq, vha, 0xc00d,
8524 "Request/Response queue pair created, id %d\n",
8525 qpair->id);
8526 ql_dbg(ql_dbg_init, vha, 0x0187,
8527 "Request/Response queue pair created, id %d\n",
8528 qpair->id);
8529 }
8530 return qpair;
8531
8532fail_mempool:
8533fail_req:
8534 qla25xx_delete_rsp_que(vha, qpair->rsp);
8535fail_rsp:
8536 mutex_lock(&ha->mq_lock);
8537 qpair->msix->in_use = 0;
8538 list_del(&qpair->qp_list_elem);
8539 if (list_empty(&vha->qp_list))
8540 vha->flags.qpairs_available = 0;
8541fail_msix:
8542 ha->queue_pair_map[qpair_id] = NULL;
8543 clear_bit(qpair_id, ha->qpair_qid_map);
Sawan Chandakb95b9452017-05-24 18:06:20 -07008544 ha->num_qpairs--;
Michael Hernandezd7459522016-12-12 14:40:07 -08008545 mutex_unlock(&ha->mq_lock);
8546fail_qid_map:
8547 kfree(qpair);
8548 return NULL;
8549}
8550
8551int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair)
8552{
Sawan Chandakd65237c2017-06-13 20:47:19 -07008553 int ret = QLA_FUNCTION_FAILED;
Michael Hernandezd7459522016-12-12 14:40:07 -08008554 struct qla_hw_data *ha = qpair->hw;
8555
8556 qpair->delete_in_progress = 1;
8557 while (atomic_read(&qpair->ref_count))
8558 msleep(500);
8559
8560 ret = qla25xx_delete_req_que(vha, qpair->req);
8561 if (ret != QLA_SUCCESS)
8562 goto fail;
himanshu.madhani@cavium.com7867b982017-12-04 14:45:16 -08008563
Michael Hernandezd7459522016-12-12 14:40:07 -08008564 ret = qla25xx_delete_rsp_que(vha, qpair->rsp);
8565 if (ret != QLA_SUCCESS)
8566 goto fail;
8567
8568 mutex_lock(&ha->mq_lock);
8569 ha->queue_pair_map[qpair->id] = NULL;
8570 clear_bit(qpair->id, ha->qpair_qid_map);
Sawan Chandakb95b9452017-05-24 18:06:20 -07008571 ha->num_qpairs--;
Michael Hernandezd7459522016-12-12 14:40:07 -08008572 list_del(&qpair->qp_list_elem);
Sawan Chandakd65237c2017-06-13 20:47:19 -07008573 if (list_empty(&vha->qp_list)) {
Michael Hernandezd7459522016-12-12 14:40:07 -08008574 vha->flags.qpairs_available = 0;
Sawan Chandakd65237c2017-06-13 20:47:19 -07008575 vha->flags.qpairs_req_created = 0;
8576 vha->flags.qpairs_rsp_created = 0;
8577 }
Michael Hernandezd7459522016-12-12 14:40:07 -08008578 mempool_destroy(qpair->srb_mempool);
8579 kfree(qpair);
8580 mutex_unlock(&ha->mq_lock);
8581
8582 return QLA_SUCCESS;
8583fail:
8584 return ret;
8585}