scsi: qla2xxx: Add debug logging routine for qpair
[linux-2.6-block.git] / drivers / scsi / qla2xxx / qla_target.c
CommitLineData
2d70c103
NB
1/*
2 * qla_target.c SCSI LLD infrastructure for QLogic 22xx/23xx/24xx/25xx
3 *
4 * based on qla2x00t.c code:
5 *
6 * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
7 * Copyright (C) 2004 - 2005 Leonid Stoljar
8 * Copyright (C) 2006 Nathaniel Clark <nate@misrule.us>
9 * Copyright (C) 2006 - 2010 ID7 Ltd.
10 *
11 * Forward port and refactoring to modern qla2xxx and target/configfs
12 *
4c76251e 13 * Copyright (C) 2010-2013 Nicholas A. Bellinger <nab@kernel.org>
2d70c103
NB
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation, version 2
18 * of the License.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 */
25
26#include <linux/module.h>
27#include <linux/init.h>
28#include <linux/types.h>
2d70c103
NB
29#include <linux/blkdev.h>
30#include <linux/interrupt.h>
31#include <linux/pci.h>
32#include <linux/delay.h>
33#include <linux/list.h>
34#include <linux/workqueue.h>
35#include <asm/unaligned.h>
36#include <scsi/scsi.h>
37#include <scsi/scsi_host.h>
38#include <scsi/scsi_tcq.h>
39#include <target/target_core_base.h>
40#include <target/target_core_fabric.h>
41
42#include "qla_def.h"
43#include "qla_target.h"
44
d154f350
AE
45static int ql2xtgt_tape_enable;
46module_param(ql2xtgt_tape_enable, int, S_IRUGO|S_IWUSR);
47MODULE_PARM_DESC(ql2xtgt_tape_enable,
48 "Enables Sequence level error recovery (aka FC Tape). Default is 0 - no SLER. 1 - Enable SLER.");
49
2d70c103
NB
50static char *qlini_mode = QLA2XXX_INI_MODE_STR_ENABLED;
51module_param(qlini_mode, charp, S_IRUGO);
52MODULE_PARM_DESC(qlini_mode,
53 "Determines when initiator mode will be enabled. Possible values: "
54 "\"exclusive\" - initiator mode will be enabled on load, "
55 "disabled on enabling target mode and then on disabling target mode "
56 "enabled back; "
57 "\"disabled\" - initiator mode will never be enabled; "
ead03855
QT
58 "\"dual\" - Initiator Modes will be enabled. Target Mode can be activated "
59 "when ready "
2d70c103
NB
60 "\"enabled\" (default) - initiator mode will always stay enabled.");
61
99e1b683 62static int ql_dm_tgt_ex_pct = 0;
ead03855
QT
63module_param(ql_dm_tgt_ex_pct, int, S_IRUGO|S_IWUSR);
64MODULE_PARM_DESC(ql_dm_tgt_ex_pct,
65 "For Dual Mode (qlini_mode=dual), this parameter determines "
66 "the percentage of exchanges/cmds FW will allocate resources "
67 "for Target mode.");
68
09620eeb
QT
69int ql2xuctrlirq = 1;
70module_param(ql2xuctrlirq, int, 0644);
71MODULE_PARM_DESC(ql2xuctrlirq,
72 "User to control IRQ placement via smp_affinity."
73 "Valid with qlini_mode=disabled."
74 "1(default): enable");
75
aa230bc5 76int ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE;
2d70c103 77
33e79977
QT
78static int temp_sam_status = SAM_STAT_BUSY;
79
2d70c103
NB
80/*
81 * From scsi/fc/fc_fcp.h
82 */
83enum fcp_resp_rsp_codes {
84 FCP_TMF_CMPL = 0,
85 FCP_DATA_LEN_INVALID = 1,
86 FCP_CMND_FIELDS_INVALID = 2,
87 FCP_DATA_PARAM_MISMATCH = 3,
88 FCP_TMF_REJECTED = 4,
89 FCP_TMF_FAILED = 5,
90 FCP_TMF_INVALID_LUN = 9,
91};
92
93/*
94 * fc_pri_ta from scsi/fc/fc_fcp.h
95 */
96#define FCP_PTA_SIMPLE 0 /* simple task attribute */
97#define FCP_PTA_HEADQ 1 /* head of queue task attribute */
98#define FCP_PTA_ORDERED 2 /* ordered task attribute */
6efb3c0a 99#define FCP_PTA_ACA 4 /* auto. contingent allegiance */
2d70c103
NB
100#define FCP_PTA_MASK 7 /* mask for task attribute field */
101#define FCP_PRI_SHIFT 3 /* priority field starts in bit 3 */
102#define FCP_PRI_RESVD_MASK 0x80 /* reserved bits in priority field */
103
104/*
105 * This driver calls qla2x00_alloc_iocbs() and qla2x00_issue_marker(), which
106 * must be called under HW lock and could unlock/lock it inside.
107 * It isn't an issue, since in the current implementation on the time when
108 * those functions are called:
109 *
110 * - Either context is IRQ and only IRQ handler can modify HW data,
111 * including rings related fields,
112 *
113 * - Or access to target mode variables from struct qla_tgt doesn't
114 * cross those functions boundaries, except tgt_stop, which
115 * additionally protected by irq_cmd_count.
116 */
117/* Predefs for callbacks handed to qla2xxx LLD */
118static void qlt_24xx_atio_pkt(struct scsi_qla_host *ha,
2f424b9b 119 struct atio_from_isp *pkt, uint8_t);
82de802a
QT
120static void qlt_response_pkt(struct scsi_qla_host *ha, struct rsp_que *rsp,
121 response_t *pkt);
5d964837 122static int qlt_issue_task_mgmt(struct fc_port *sess, u64 lun,
2d70c103 123 int fn, void *iocb, int flags);
82de802a 124static void qlt_send_term_exchange(struct qla_qpair *, struct qla_tgt_cmd
a07100e0 125 *cmd, struct atio_from_isp *atio, int ha_locked, int ul_abort);
33e79977
QT
126static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
127 struct atio_from_isp *atio, uint16_t status, int qfull);
55a9066f 128static void qlt_disable_vha(struct scsi_qla_host *vha);
b2032fd5 129static void qlt_clear_tgt_db(struct qla_tgt *tgt);
82de802a 130static void qlt_send_notify_ack(struct qla_qpair *qpair,
a6ca8878
AP
131 struct imm_ntfy_from_isp *ntfy,
132 uint32_t add_flags, uint16_t resp_code, int resp_code_valid,
133 uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan);
b7bd104e
AP
134static void qlt_send_term_imm_notif(struct scsi_qla_host *vha,
135 struct imm_ntfy_from_isp *imm, int ha_locked);
726b8548
QT
136static struct fc_port *qlt_create_sess(struct scsi_qla_host *vha,
137 fc_port_t *fcport, bool local);
138void qlt_unreg_sess(struct fc_port *sess);
8f6fc8d4
QT
139static void qlt_24xx_handle_abts(struct scsi_qla_host *,
140 struct abts_recv_from_24xx *);
82de802a
QT
141static void qlt_send_busy(struct qla_qpair *, struct atio_from_isp *,
142 uint16_t);
8f6fc8d4 143
2d70c103
NB
144/*
145 * Global Variables
146 */
2d70c103 147static struct kmem_cache *qla_tgt_mgmt_cmd_cachep;
b7bd104e 148static struct kmem_cache *qla_tgt_plogi_cachep;
2d70c103
NB
149static mempool_t *qla_tgt_mgmt_cmd_mempool;
150static struct workqueue_struct *qla_tgt_wq;
151static DEFINE_MUTEX(qla_tgt_mutex);
152static LIST_HEAD(qla_tgt_glist);
153
be25152c
QT
154static const char *prot_op_str(u32 prot_op)
155{
156 switch (prot_op) {
157 case TARGET_PROT_NORMAL: return "NORMAL";
158 case TARGET_PROT_DIN_INSERT: return "DIN_INSERT";
159 case TARGET_PROT_DOUT_INSERT: return "DOUT_INSERT";
160 case TARGET_PROT_DIN_STRIP: return "DIN_STRIP";
161 case TARGET_PROT_DOUT_STRIP: return "DOUT_STRIP";
162 case TARGET_PROT_DIN_PASS: return "DIN_PASS";
163 case TARGET_PROT_DOUT_PASS: return "DOUT_PASS";
164 default: return "UNKNOWN";
165 }
166}
167
df673274
AP
168/* This API intentionally takes dest as a parameter, rather than returning
169 * int value to avoid caller forgetting to issue wmb() after the store */
170void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest)
171{
172 scsi_qla_host_t *base_vha = pci_get_drvdata(vha->hw->pdev);
173 *dest = atomic_inc_return(&base_vha->generation_tick);
174 /* memory barrier */
175 wmb();
176}
177
2d70c103
NB
178/* Might release hw lock, then reaquire!! */
179static inline int qlt_issue_marker(struct scsi_qla_host *vha, int vha_locked)
180{
181 /* Send marker if required */
182 if (unlikely(vha->marker_needed != 0)) {
183 int rc = qla2x00_issue_marker(vha, vha_locked);
184 if (rc != QLA_SUCCESS) {
185 ql_dbg(ql_dbg_tgt, vha, 0xe03d,
186 "qla_target(%d): issue_marker() failed\n",
187 vha->vp_idx);
188 }
189 return rc;
190 }
191 return QLA_SUCCESS;
192}
193
194static inline
195struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha,
196 uint8_t *d_id)
197{
482c9dc7
QT
198 struct scsi_qla_host *host;
199 uint32_t key = 0;
2d70c103 200
482c9dc7
QT
201 if ((vha->d_id.b.area == d_id[1]) && (vha->d_id.b.domain == d_id[0]) &&
202 (vha->d_id.b.al_pa == d_id[2]))
2d70c103
NB
203 return vha;
204
482c9dc7
QT
205 key = (uint32_t)d_id[0] << 16;
206 key |= (uint32_t)d_id[1] << 8;
207 key |= (uint32_t)d_id[2];
2d70c103 208
482c9dc7
QT
209 host = btree_lookup32(&vha->hw->tgt.host_map, key);
210 if (!host)
83548fe2
QT
211 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf005,
212 "Unable to find host %06x\n", key);
482c9dc7
QT
213
214 return host;
2d70c103
NB
215}
216
217static inline
218struct scsi_qla_host *qlt_find_host_by_vp_idx(struct scsi_qla_host *vha,
219 uint16_t vp_idx)
220{
221 struct qla_hw_data *ha = vha->hw;
222
223 if (vha->vp_idx == vp_idx)
224 return vha;
225
226 BUG_ON(ha->tgt.tgt_vp_map == NULL);
227 if (likely(test_bit(vp_idx, ha->vp_idx_map)))
228 return ha->tgt.tgt_vp_map[vp_idx].vha;
229
230 return NULL;
231}
232
33e79977
QT
233static inline void qlt_incr_num_pend_cmds(struct scsi_qla_host *vha)
234{
235 unsigned long flags;
236
237 spin_lock_irqsave(&vha->hw->tgt.q_full_lock, flags);
238
239 vha->hw->tgt.num_pend_cmds++;
fc90adaf
JC
240 if (vha->hw->tgt.num_pend_cmds > vha->qla_stats.stat_max_pend_cmds)
241 vha->qla_stats.stat_max_pend_cmds =
33e79977
QT
242 vha->hw->tgt.num_pend_cmds;
243 spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags);
244}
245static inline void qlt_decr_num_pend_cmds(struct scsi_qla_host *vha)
246{
247 unsigned long flags;
248
249 spin_lock_irqsave(&vha->hw->tgt.q_full_lock, flags);
250 vha->hw->tgt.num_pend_cmds--;
251 spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags);
252}
253
41dc529a
QT
254
255static void qlt_queue_unknown_atio(scsi_qla_host_t *vha,
82de802a 256 struct atio_from_isp *atio, uint8_t ha_locked)
41dc529a
QT
257{
258 struct qla_tgt_sess_op *u;
259 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
260 unsigned long flags;
261
262 if (tgt->tgt_stop) {
83548fe2
QT
263 ql_dbg(ql_dbg_async, vha, 0x502c,
264 "qla_target(%d): dropping unknown ATIO_TYPE7, because tgt is being stopped",
265 vha->vp_idx);
41dc529a
QT
266 goto out_term;
267 }
268
269 u = kzalloc(sizeof(*u), GFP_ATOMIC);
83548fe2 270 if (u == NULL)
41dc529a 271 goto out_term;
41dc529a
QT
272
273 u->vha = vha;
274 memcpy(&u->atio, atio, sizeof(*atio));
275 INIT_LIST_HEAD(&u->cmd_list);
276
277 spin_lock_irqsave(&vha->cmd_list_lock, flags);
278 list_add_tail(&u->cmd_list, &vha->unknown_atio_list);
279 spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
280
281 schedule_delayed_work(&vha->unknown_atio_work, 1);
282
283out:
284 return;
285
286out_term:
82de802a 287 qlt_send_term_exchange(vha->hw->base_qpair, NULL, atio, ha_locked, 0);
41dc529a
QT
288 goto out;
289}
290
291static void qlt_try_to_dequeue_unknown_atios(struct scsi_qla_host *vha,
292 uint8_t ha_locked)
293{
294 struct qla_tgt_sess_op *u, *t;
295 scsi_qla_host_t *host;
296 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
297 unsigned long flags;
298 uint8_t queued = 0;
299
300 list_for_each_entry_safe(u, t, &vha->unknown_atio_list, cmd_list) {
301 if (u->aborted) {
83548fe2
QT
302 ql_dbg(ql_dbg_async, vha, 0x502e,
303 "Freeing unknown %s %p, because of Abort\n",
41dc529a 304 "ATIO_TYPE7", u);
82de802a
QT
305 qlt_send_term_exchange(vha->hw->base_qpair, NULL,
306 &u->atio, ha_locked, 0);
41dc529a
QT
307 goto abort;
308 }
309
310 host = qlt_find_host_by_d_id(vha, u->atio.u.isp24.fcp_hdr.d_id);
311 if (host != NULL) {
83548fe2
QT
312 ql_dbg(ql_dbg_async, vha, 0x502f,
313 "Requeuing unknown ATIO_TYPE7 %p\n", u);
41dc529a
QT
314 qlt_24xx_atio_pkt(host, &u->atio, ha_locked);
315 } else if (tgt->tgt_stop) {
83548fe2
QT
316 ql_dbg(ql_dbg_async, vha, 0x503a,
317 "Freeing unknown %s %p, because tgt is being stopped\n",
318 "ATIO_TYPE7", u);
82de802a
QT
319 qlt_send_term_exchange(vha->hw->base_qpair, NULL,
320 &u->atio, ha_locked, 0);
41dc529a 321 } else {
83548fe2
QT
322 ql_dbg(ql_dbg_async, vha, 0x503d,
323 "Reschedule u %p, vha %p, host %p\n", u, vha, host);
41dc529a
QT
324 if (!queued) {
325 queued = 1;
326 schedule_delayed_work(&vha->unknown_atio_work,
327 1);
328 }
329 continue;
330 }
331
332abort:
333 spin_lock_irqsave(&vha->cmd_list_lock, flags);
334 list_del(&u->cmd_list);
335 spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
336 kfree(u);
337 }
338}
339
340void qlt_unknown_atio_work_fn(struct work_struct *work)
341{
342 struct scsi_qla_host *vha = container_of(to_delayed_work(work),
343 struct scsi_qla_host, unknown_atio_work);
344
345 qlt_try_to_dequeue_unknown_atios(vha, 0);
346}
347
3bb67df5 348static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha,
2f424b9b 349 struct atio_from_isp *atio, uint8_t ha_locked)
2d70c103 350{
f83adb61
QT
351 ql_dbg(ql_dbg_tgt, vha, 0xe072,
352 "%s: qla_target(%d): type %x ox_id %04x\n",
353 __func__, vha->vp_idx, atio->u.raw.entry_type,
354 be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id));
355
2d70c103
NB
356 switch (atio->u.raw.entry_type) {
357 case ATIO_TYPE7:
358 {
359 struct scsi_qla_host *host = qlt_find_host_by_d_id(vha,
360 atio->u.isp24.fcp_hdr.d_id);
361 if (unlikely(NULL == host)) {
362 ql_dbg(ql_dbg_tgt, vha, 0xe03e,
363 "qla_target(%d): Received ATIO_TYPE7 "
364 "with unknown d_id %x:%x:%x\n", vha->vp_idx,
365 atio->u.isp24.fcp_hdr.d_id[0],
366 atio->u.isp24.fcp_hdr.d_id[1],
367 atio->u.isp24.fcp_hdr.d_id[2]);
41dc529a
QT
368
369
370 qlt_queue_unknown_atio(vha, atio, ha_locked);
2d70c103
NB
371 break;
372 }
41dc529a
QT
373 if (unlikely(!list_empty(&vha->unknown_atio_list)))
374 qlt_try_to_dequeue_unknown_atios(vha, ha_locked);
375
2f424b9b 376 qlt_24xx_atio_pkt(host, atio, ha_locked);
2d70c103
NB
377 break;
378 }
379
380 case IMMED_NOTIFY_TYPE:
381 {
382 struct scsi_qla_host *host = vha;
383 struct imm_ntfy_from_isp *entry =
384 (struct imm_ntfy_from_isp *)atio;
385
82de802a
QT
386 qlt_issue_marker(vha, ha_locked);
387
2d70c103
NB
388 if ((entry->u.isp24.vp_index != 0xFF) &&
389 (entry->u.isp24.nport_handle != 0xFFFF)) {
390 host = qlt_find_host_by_vp_idx(vha,
391 entry->u.isp24.vp_index);
392 if (unlikely(!host)) {
393 ql_dbg(ql_dbg_tgt, vha, 0xe03f,
394 "qla_target(%d): Received "
395 "ATIO (IMMED_NOTIFY_TYPE) "
396 "with unknown vp_index %d\n",
397 vha->vp_idx, entry->u.isp24.vp_index);
398 break;
399 }
400 }
2f424b9b 401 qlt_24xx_atio_pkt(host, atio, ha_locked);
2d70c103
NB
402 break;
403 }
404
41dc529a
QT
405 case VP_RPT_ID_IOCB_TYPE:
406 qla24xx_report_id_acquisition(vha,
407 (struct vp_rpt_id_entry_24xx *)atio);
408 break;
409
410 case ABTS_RECV_24XX:
411 {
412 struct abts_recv_from_24xx *entry =
413 (struct abts_recv_from_24xx *)atio;
414 struct scsi_qla_host *host = qlt_find_host_by_vp_idx(vha,
415 entry->vp_index);
8f6fc8d4
QT
416 unsigned long flags;
417
41dc529a 418 if (unlikely(!host)) {
83548fe2 419 ql_dbg(ql_dbg_tgt, vha, 0xe00a,
41dc529a
QT
420 "qla_target(%d): Response pkt (ABTS_RECV_24XX) "
421 "received, with unknown vp_index %d\n",
422 vha->vp_idx, entry->vp_index);
423 break;
424 }
8f6fc8d4
QT
425 if (!ha_locked)
426 spin_lock_irqsave(&host->hw->hardware_lock, flags);
427 qlt_24xx_handle_abts(host, (struct abts_recv_from_24xx *)atio);
428 if (!ha_locked)
429 spin_unlock_irqrestore(&host->hw->hardware_lock, flags);
41dc529a 430 break;
41dc529a
QT
431 }
432
433 /* case PUREX_IOCB_TYPE: ql2xmvasynctoatio */
434
2d70c103
NB
435 default:
436 ql_dbg(ql_dbg_tgt, vha, 0xe040,
437 "qla_target(%d): Received unknown ATIO atio "
438 "type %x\n", vha->vp_idx, atio->u.raw.entry_type);
439 break;
440 }
441
3bb67df5 442 return false;
2d70c103
NB
443}
444
82de802a
QT
445void qlt_response_pkt_all_vps(struct scsi_qla_host *vha,
446 struct rsp_que *rsp, response_t *pkt)
2d70c103
NB
447{
448 switch (pkt->entry_type) {
f83adb61
QT
449 case CTIO_CRC2:
450 ql_dbg(ql_dbg_tgt, vha, 0xe073,
451 "qla_target(%d):%s: CRC2 Response pkt\n",
452 vha->vp_idx, __func__);
2d70c103
NB
453 case CTIO_TYPE7:
454 {
455 struct ctio7_from_24xx *entry = (struct ctio7_from_24xx *)pkt;
456 struct scsi_qla_host *host = qlt_find_host_by_vp_idx(vha,
457 entry->vp_index);
458 if (unlikely(!host)) {
459 ql_dbg(ql_dbg_tgt, vha, 0xe041,
460 "qla_target(%d): Response pkt (CTIO_TYPE7) "
461 "received, with unknown vp_index %d\n",
462 vha->vp_idx, entry->vp_index);
463 break;
464 }
82de802a 465 qlt_response_pkt(host, rsp, pkt);
2d70c103
NB
466 break;
467 }
468
469 case IMMED_NOTIFY_TYPE:
470 {
471 struct scsi_qla_host *host = vha;
472 struct imm_ntfy_from_isp *entry =
473 (struct imm_ntfy_from_isp *)pkt;
474
475 host = qlt_find_host_by_vp_idx(vha, entry->u.isp24.vp_index);
476 if (unlikely(!host)) {
477 ql_dbg(ql_dbg_tgt, vha, 0xe042,
478 "qla_target(%d): Response pkt (IMMED_NOTIFY_TYPE) "
479 "received, with unknown vp_index %d\n",
480 vha->vp_idx, entry->u.isp24.vp_index);
481 break;
482 }
82de802a 483 qlt_response_pkt(host, rsp, pkt);
2d70c103
NB
484 break;
485 }
486
487 case NOTIFY_ACK_TYPE:
488 {
489 struct scsi_qla_host *host = vha;
490 struct nack_to_isp *entry = (struct nack_to_isp *)pkt;
491
492 if (0xFF != entry->u.isp24.vp_index) {
493 host = qlt_find_host_by_vp_idx(vha,
494 entry->u.isp24.vp_index);
495 if (unlikely(!host)) {
496 ql_dbg(ql_dbg_tgt, vha, 0xe043,
497 "qla_target(%d): Response "
498 "pkt (NOTIFY_ACK_TYPE) "
499 "received, with unknown "
500 "vp_index %d\n", vha->vp_idx,
501 entry->u.isp24.vp_index);
502 break;
503 }
504 }
82de802a 505 qlt_response_pkt(host, rsp, pkt);
2d70c103
NB
506 break;
507 }
508
509 case ABTS_RECV_24XX:
510 {
511 struct abts_recv_from_24xx *entry =
512 (struct abts_recv_from_24xx *)pkt;
513 struct scsi_qla_host *host = qlt_find_host_by_vp_idx(vha,
514 entry->vp_index);
515 if (unlikely(!host)) {
516 ql_dbg(ql_dbg_tgt, vha, 0xe044,
517 "qla_target(%d): Response pkt "
518 "(ABTS_RECV_24XX) received, with unknown "
519 "vp_index %d\n", vha->vp_idx, entry->vp_index);
520 break;
521 }
82de802a 522 qlt_response_pkt(host, rsp, pkt);
2d70c103
NB
523 break;
524 }
525
526 case ABTS_RESP_24XX:
527 {
528 struct abts_resp_to_24xx *entry =
529 (struct abts_resp_to_24xx *)pkt;
530 struct scsi_qla_host *host = qlt_find_host_by_vp_idx(vha,
531 entry->vp_index);
532 if (unlikely(!host)) {
533 ql_dbg(ql_dbg_tgt, vha, 0xe045,
534 "qla_target(%d): Response pkt "
535 "(ABTS_RECV_24XX) received, with unknown "
536 "vp_index %d\n", vha->vp_idx, entry->vp_index);
537 break;
538 }
82de802a 539 qlt_response_pkt(host, rsp, pkt);
2d70c103
NB
540 break;
541 }
542
543 default:
82de802a 544 qlt_response_pkt(vha, rsp, pkt);
2d70c103
NB
545 break;
546 }
547
548}
549
b7bd104e
AP
550/*
551 * All qlt_plogi_ack_t operations are protected by hardware_lock
552 */
726b8548
QT
553static int qla24xx_post_nack_work(struct scsi_qla_host *vha, fc_port_t *fcport,
554 struct imm_ntfy_from_isp *ntfy, int type)
555{
556 struct qla_work_evt *e;
557 e = qla2x00_alloc_work(vha, QLA_EVT_NACK);
558 if (!e)
559 return QLA_FUNCTION_FAILED;
560
561 e->u.nack.fcport = fcport;
562 e->u.nack.type = type;
563 memcpy(e->u.nack.iocb, ntfy, sizeof(struct imm_ntfy_from_isp));
564 return qla2x00_post_work(vha, e);
565}
566
567static
25ff6af1 568void qla2x00_async_nack_sp_done(void *s, int res)
726b8548 569{
726b8548 570 struct srb *sp = (struct srb *)s;
25ff6af1 571 struct scsi_qla_host *vha = sp->vha;
726b8548
QT
572 unsigned long flags;
573
83548fe2
QT
574 ql_dbg(ql_dbg_disc, vha, 0x20f2,
575 "Async done-%s res %x %8phC type %d\n",
576 sp->name, res, sp->fcport->port_name, sp->type);
726b8548
QT
577
578 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
579 sp->fcport->flags &= ~FCF_ASYNC_SENT;
7c3f8fd1 580 sp->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
726b8548
QT
581
582 switch (sp->type) {
583 case SRB_NACK_PLOGI:
584 sp->fcport->login_gen++;
585 sp->fcport->fw_login_state = DSC_LS_PLOGI_COMP;
586 sp->fcport->logout_on_delete = 1;
5b33469a 587 sp->fcport->plogi_nack_done_deadline = jiffies + HZ;
726b8548
QT
588 break;
589
590 case SRB_NACK_PRLI:
591 sp->fcport->fw_login_state = DSC_LS_PRLI_COMP;
592 sp->fcport->deleted = 0;
593
594 if (!sp->fcport->login_succ &&
595 !IS_SW_RESV_ADDR(sp->fcport->d_id)) {
596 sp->fcport->login_succ = 1;
597
598 vha->fcport_count++;
599
600 if (!IS_IIDMA_CAPABLE(vha->hw) ||
601 !vha->hw->flags.gpsc_supported) {
83548fe2
QT
602 ql_dbg(ql_dbg_disc, vha, 0x20f3,
603 "%s %d %8phC post upd_fcport fcp_cnt %d\n",
604 __func__, __LINE__,
605 sp->fcport->port_name,
606 vha->fcport_count);
726b8548
QT
607
608 qla24xx_post_upd_fcport_work(vha, sp->fcport);
609 } else {
83548fe2
QT
610 ql_dbg(ql_dbg_disc, vha, 0x20f5,
611 "%s %d %8phC post gpsc fcp_cnt %d\n",
612 __func__, __LINE__,
613 sp->fcport->port_name,
614 vha->fcport_count);
726b8548
QT
615
616 qla24xx_post_gpsc_work(vha, sp->fcport);
617 }
618 }
619 break;
620
621 case SRB_NACK_LOGO:
622 sp->fcport->login_gen++;
623 sp->fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
624 qlt_logo_completion_handler(sp->fcport, MBS_COMMAND_COMPLETE);
625 break;
626 }
627 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
628
25ff6af1 629 sp->free(sp);
726b8548
QT
630}
631
632int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
633 struct imm_ntfy_from_isp *ntfy, int type)
634{
635 int rval = QLA_FUNCTION_FAILED;
636 srb_t *sp;
637 char *c = NULL;
638
639 fcport->flags |= FCF_ASYNC_SENT;
640 switch (type) {
641 case SRB_NACK_PLOGI:
642 fcport->fw_login_state = DSC_LS_PLOGI_PEND;
643 c = "PLOGI";
644 break;
645 case SRB_NACK_PRLI:
646 fcport->fw_login_state = DSC_LS_PRLI_PEND;
ec7193e2 647 fcport->deleted = 0;
726b8548
QT
648 c = "PRLI";
649 break;
650 case SRB_NACK_LOGO:
651 fcport->fw_login_state = DSC_LS_LOGO_PEND;
652 c = "LOGO";
653 break;
654 }
655
656 sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
657 if (!sp)
658 goto done;
659
660 sp->type = type;
661 sp->name = "nack";
662
663 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
664
665 sp->u.iocb_cmd.u.nack.ntfy = ntfy;
666
667 sp->done = qla2x00_async_nack_sp_done;
668
669 rval = qla2x00_start_sp(sp);
670 if (rval != QLA_SUCCESS)
671 goto done_free_sp;
672
83548fe2
QT
673 ql_dbg(ql_dbg_disc, vha, 0x20f4,
674 "Async-%s %8phC hndl %x %s\n",
675 sp->name, fcport->port_name, sp->handle, c);
726b8548
QT
676
677 return rval;
678
679done_free_sp:
25ff6af1 680 sp->free(sp);
726b8548
QT
681done:
682 fcport->flags &= ~FCF_ASYNC_SENT;
683 return rval;
684}
685
686void qla24xx_do_nack_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
687{
688 fc_port_t *t;
689 unsigned long flags;
690
691 switch (e->u.nack.type) {
692 case SRB_NACK_PRLI:
693 mutex_lock(&vha->vha_tgt.tgt_mutex);
694 t = qlt_create_sess(vha, e->u.nack.fcport, 0);
695 mutex_unlock(&vha->vha_tgt.tgt_mutex);
696 if (t) {
83548fe2 697 ql_log(ql_log_info, vha, 0xd034,
726b8548
QT
698 "%s create sess success %p", __func__, t);
699 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
700 /* create sess has an extra kref */
701 vha->hw->tgt.tgt_ops->put_sess(e->u.nack.fcport);
702 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
703 }
704 break;
705 }
706 qla24xx_async_notify_ack(vha, e->u.nack.fcport,
707 (struct imm_ntfy_from_isp*)e->u.nack.iocb, e->u.nack.type);
708}
709
710void qla24xx_delete_sess_fn(struct work_struct *work)
711{
712 fc_port_t *fcport = container_of(work, struct fc_port, del_work);
713 struct qla_hw_data *ha = fcport->vha->hw;
714 unsigned long flags;
715
716 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
717
718 if (fcport->se_sess) {
719 ha->tgt.tgt_ops->shutdown_sess(fcport);
720 ha->tgt.tgt_ops->put_sess(fcport);
721 } else {
722 qlt_unreg_sess(fcport);
723 }
724 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
725}
726
727/*
728 * Called from qla2x00_reg_remote_port()
729 */
730void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
731{
732 struct qla_hw_data *ha = vha->hw;
733 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
734 struct fc_port *sess = fcport;
735 unsigned long flags;
736
737 if (!vha->hw->tgt.tgt_ops)
738 return;
739
740 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
741 if (tgt->tgt_stop) {
742 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
743 return;
744 }
745
746 if (fcport->disc_state == DSC_DELETE_PEND) {
747 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
748 return;
749 }
750
751 if (!sess->se_sess) {
752 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
753
754 mutex_lock(&vha->vha_tgt.tgt_mutex);
755 sess = qlt_create_sess(vha, fcport, false);
756 mutex_unlock(&vha->vha_tgt.tgt_mutex);
757
758 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
759 } else {
760 if (fcport->fw_login_state == DSC_LS_PRLI_COMP) {
761 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
762 return;
763 }
764
765 if (!kref_get_unless_zero(&sess->sess_kref)) {
83548fe2 766 ql_dbg(ql_dbg_disc, vha, 0x2107,
726b8548
QT
767 "%s: kref_get fail sess %8phC \n",
768 __func__, sess->port_name);
769 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
770 return;
771 }
772
773 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04c,
774 "qla_target(%u): %ssession for port %8phC "
775 "(loop ID %d) reappeared\n", vha->vp_idx,
776 sess->local ? "local " : "", sess->port_name, sess->loop_id);
777
778 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,
779 "Reappeared sess %p\n", sess);
780
781 ha->tgt.tgt_ops->update_sess(sess, fcport->d_id,
782 fcport->loop_id,
783 (fcport->flags & FCF_CONF_COMP_SUPPORTED));
784 }
785
786 if (sess && sess->local) {
787 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04d,
788 "qla_target(%u): local session for "
789 "port %8phC (loop ID %d) became global\n", vha->vp_idx,
790 fcport->port_name, sess->loop_id);
791 sess->local = 0;
792 }
793 ha->tgt.tgt_ops->put_sess(sess);
794 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
795}
b7bd104e
AP
796
797/*
798 * This is a zero-base ref-counting solution, since hardware_lock
799 * guarantees that ref_count is not modified concurrently.
800 * Upon successful return content of iocb is undefined
801 */
5d964837 802static struct qlt_plogi_ack_t *
b7bd104e
AP
803qlt_plogi_ack_find_add(struct scsi_qla_host *vha, port_id_t *id,
804 struct imm_ntfy_from_isp *iocb)
805{
5d964837 806 struct qlt_plogi_ack_t *pla;
b7bd104e
AP
807
808 list_for_each_entry(pla, &vha->plogi_ack_list, list) {
809 if (pla->id.b24 == id->b24) {
810 qlt_send_term_imm_notif(vha, &pla->iocb, 1);
5d964837 811 memcpy(&pla->iocb, iocb, sizeof(pla->iocb));
b7bd104e
AP
812 return pla;
813 }
814 }
815
816 pla = kmem_cache_zalloc(qla_tgt_plogi_cachep, GFP_ATOMIC);
817 if (!pla) {
818 ql_dbg(ql_dbg_async, vha, 0x5088,
819 "qla_target(%d): Allocation of plogi_ack failed\n",
820 vha->vp_idx);
821 return NULL;
822 }
823
5d964837 824 memcpy(&pla->iocb, iocb, sizeof(pla->iocb));
b7bd104e
AP
825 pla->id = *id;
826 list_add_tail(&pla->list, &vha->plogi_ack_list);
827
828 return pla;
829}
830
726b8548 831void qlt_plogi_ack_unref(struct scsi_qla_host *vha,
5d964837 832 struct qlt_plogi_ack_t *pla)
b7bd104e 833{
5d964837 834 struct imm_ntfy_from_isp *iocb = &pla->iocb;
726b8548
QT
835 port_id_t port_id;
836 uint16_t loop_id;
837 fc_port_t *fcport = pla->fcport;
838
b7bd104e
AP
839 BUG_ON(!pla->ref_count);
840 pla->ref_count--;
841
842 if (pla->ref_count)
843 return;
844
726b8548 845 ql_dbg(ql_dbg_disc, vha, 0x5089,
b7bd104e 846 "Sending PLOGI ACK to wwn %8phC s_id %02x:%02x:%02x loop_id %#04x"
5d964837
QT
847 " exch %#x ox_id %#x\n", iocb->u.isp24.port_name,
848 iocb->u.isp24.port_id[2], iocb->u.isp24.port_id[1],
849 iocb->u.isp24.port_id[0],
850 le16_to_cpu(iocb->u.isp24.nport_handle),
851 iocb->u.isp24.exchange_address, iocb->ox_id);
726b8548
QT
852
853 port_id.b.domain = iocb->u.isp24.port_id[2];
854 port_id.b.area = iocb->u.isp24.port_id[1];
855 port_id.b.al_pa = iocb->u.isp24.port_id[0];
856 port_id.b.rsvd_1 = 0;
857
858 loop_id = le16_to_cpu(iocb->u.isp24.nport_handle);
859
860 fcport->loop_id = loop_id;
861 fcport->d_id = port_id;
862 qla24xx_post_nack_work(vha, fcport, iocb, SRB_NACK_PLOGI);
863
864 list_for_each_entry(fcport, &vha->vp_fcports, list) {
865 if (fcport->plogi_link[QLT_PLOGI_LINK_SAME_WWN] == pla)
866 fcport->plogi_link[QLT_PLOGI_LINK_SAME_WWN] = NULL;
867 if (fcport->plogi_link[QLT_PLOGI_LINK_CONFLICT] == pla)
868 fcport->plogi_link[QLT_PLOGI_LINK_CONFLICT] = NULL;
869 }
b7bd104e
AP
870
871 list_del(&pla->list);
872 kmem_cache_free(qla_tgt_plogi_cachep, pla);
873}
874
726b8548 875void
5d964837
QT
876qlt_plogi_ack_link(struct scsi_qla_host *vha, struct qlt_plogi_ack_t *pla,
877 struct fc_port *sess, enum qlt_plogi_link_t link)
b7bd104e 878{
5d964837 879 struct imm_ntfy_from_isp *iocb = &pla->iocb;
b7bd104e
AP
880 /* Inc ref_count first because link might already be pointing at pla */
881 pla->ref_count++;
882
726b8548
QT
883 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf097,
884 "Linking sess %p [%d] wwn %8phC with PLOGI ACK to wwn %8phC"
885 " s_id %02x:%02x:%02x, ref=%d pla %p link %d\n",
886 sess, link, sess->port_name,
887 iocb->u.isp24.port_name, iocb->u.isp24.port_id[2],
888 iocb->u.isp24.port_id[1], iocb->u.isp24.port_id[0],
889 pla->ref_count, pla, link);
890
b7bd104e
AP
891 if (sess->plogi_link[link])
892 qlt_plogi_ack_unref(vha, sess->plogi_link[link]);
893
726b8548
QT
894 if (link == QLT_PLOGI_LINK_SAME_WWN)
895 pla->fcport = sess;
b7bd104e
AP
896
897 sess->plogi_link[link] = pla;
898}
899
71cdc079
AP
900typedef struct {
901 /* These fields must be initialized by the caller */
902 port_id_t id;
903 /*
904 * number of cmds dropped while we were waiting for
905 * initiator to ack LOGO initialize to 1 if LOGO is
906 * triggered by a command, otherwise, to 0
907 */
908 int cmd_count;
909
910 /* These fields are used by callee */
911 struct list_head list;
912} qlt_port_logo_t;
913
914static void
915qlt_send_first_logo(struct scsi_qla_host *vha, qlt_port_logo_t *logo)
916{
917 qlt_port_logo_t *tmp;
918 int res;
919
920 mutex_lock(&vha->vha_tgt.tgt_mutex);
921
922 list_for_each_entry(tmp, &vha->logo_list, list) {
923 if (tmp->id.b24 == logo->id.b24) {
924 tmp->cmd_count += logo->cmd_count;
925 mutex_unlock(&vha->vha_tgt.tgt_mutex);
926 return;
927 }
928 }
929
930 list_add_tail(&logo->list, &vha->logo_list);
931
932 mutex_unlock(&vha->vha_tgt.tgt_mutex);
933
934 res = qla24xx_els_dcmd_iocb(vha, ELS_DCMD_LOGO, logo->id);
935
936 mutex_lock(&vha->vha_tgt.tgt_mutex);
937 list_del(&logo->list);
938 mutex_unlock(&vha->vha_tgt.tgt_mutex);
939
b7bd104e
AP
940 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf098,
941 "Finished LOGO to %02x:%02x:%02x, dropped %d cmds, res = %#x\n",
942 logo->id.b.domain, logo->id.b.area, logo->id.b.al_pa,
943 logo->cmd_count, res);
71cdc079
AP
944}
945
2d70c103
NB
946static void qlt_free_session_done(struct work_struct *work)
947{
5d964837 948 struct fc_port *sess = container_of(work, struct fc_port,
2d70c103
NB
949 free_work);
950 struct qla_tgt *tgt = sess->tgt;
951 struct scsi_qla_host *vha = sess->vha;
952 struct qla_hw_data *ha = vha->hw;
a6ca8878
AP
953 unsigned long flags;
954 bool logout_started = false;
726b8548 955 struct event_arg ea;
41dc529a 956 scsi_qla_host_t *base_vha;
a6ca8878
AP
957
958 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf084,
959 "%s: se_sess %p / sess %p from port %8phC loop_id %#04x"
b7bd104e 960 " s_id %02x:%02x:%02x logout %d keep %d els_logo %d\n",
a6ca8878 961 __func__, sess->se_sess, sess, sess->port_name, sess->loop_id,
37cacc0a 962 sess->d_id.b.domain, sess->d_id.b.area, sess->d_id.b.al_pa,
a6ca8878 963 sess->logout_on_delete, sess->keep_nport_handle,
b7bd104e 964 sess->send_els_logo);
2d70c103 965
a6ca8878 966
726b8548 967 if (!IS_SW_RESV_ADDR(sess->d_id)) {
41dc529a
QT
968 if (sess->send_els_logo) {
969 qlt_port_logo_t logo;
71cdc079 970
41dc529a
QT
971 logo.id = sess->d_id;
972 logo.cmd_count = 0;
973 qlt_send_first_logo(vha, &logo);
974 }
975
976 if (sess->logout_on_delete) {
977 int rc;
978
979 rc = qla2x00_post_async_logout_work(vha, sess, NULL);
980 if (rc != QLA_SUCCESS)
981 ql_log(ql_log_warn, vha, 0xf085,
982 "Schedule logo failed sess %p rc %d\n",
983 sess, rc);
984 else
985 logout_started = true;
986 }
726b8548 987 }
a6ca8878 988
2d70c103
NB
989 /*
990 * Release the target session for FC Nexus from fabric module code.
991 */
992 if (sess->se_sess != NULL)
993 ha->tgt.tgt_ops->free_session(sess);
994
a6ca8878
AP
995 if (logout_started) {
996 bool traced = false;
997
998 while (!ACCESS_ONCE(sess->logout_completed)) {
999 if (!traced) {
1000 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf086,
1001 "%s: waiting for sess %p logout\n",
1002 __func__, sess);
1003 traced = true;
1004 }
1005 msleep(100);
1006 }
1007
726b8548 1008 ql_dbg(ql_dbg_disc, vha, 0xf087,
41dc529a
QT
1009 "%s: sess %p logout completed\n",__func__, sess);
1010 }
1011
1012 if (sess->logo_ack_needed) {
1013 sess->logo_ack_needed = 0;
1014 qla24xx_async_notify_ack(vha, sess,
1015 (struct imm_ntfy_from_isp *)sess->iocb, SRB_NACK_LOGO);
a6ca8878
AP
1016 }
1017
726b8548
QT
1018 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
1019 if (sess->se_sess) {
1020 sess->se_sess = NULL;
1021 if (tgt && !IS_SW_RESV_ADDR(sess->d_id))
1022 tgt->sess_count--;
1023 }
1024
1025 sess->disc_state = DSC_DELETED;
1026 sess->fw_login_state = DSC_LS_PORT_UNAVAIL;
1027 sess->deleted = QLA_SESS_DELETED;
1028 sess->login_retry = vha->hw->login_retry_count;
1029
1030 if (sess->login_succ && !IS_SW_RESV_ADDR(sess->d_id)) {
1031 vha->fcport_count--;
1032 sess->login_succ = 0;
1033 }
1034
7c3f8fd1 1035 if (sess->chip_reset != ha->base_qpair->chip_reset)
726b8548
QT
1036 qla2x00_clear_loop_id(sess);
1037
1038 if (sess->conflict) {
1039 sess->conflict->login_pause = 0;
1040 sess->conflict = NULL;
1041 if (!test_bit(UNLOADING, &vha->dpc_flags))
1042 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
1043 }
1044
b7bd104e 1045 {
5d964837 1046 struct qlt_plogi_ack_t *own =
b7bd104e 1047 sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN];
5d964837 1048 struct qlt_plogi_ack_t *con =
b7bd104e 1049 sess->plogi_link[QLT_PLOGI_LINK_CONFLICT];
5d964837 1050 struct imm_ntfy_from_isp *iocb;
b7bd104e
AP
1051
1052 if (con) {
5d964837 1053 iocb = &con->iocb;
b7bd104e 1054 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf099,
5d964837
QT
1055 "se_sess %p / sess %p port %8phC is gone,"
1056 " %s (ref=%d), releasing PLOGI for %8phC (ref=%d)\n",
1057 sess->se_sess, sess, sess->port_name,
1058 own ? "releasing own PLOGI" : "no own PLOGI pending",
1059 own ? own->ref_count : -1,
1060 iocb->u.isp24.port_name, con->ref_count);
b7bd104e 1061 qlt_plogi_ack_unref(vha, con);
726b8548 1062 sess->plogi_link[QLT_PLOGI_LINK_CONFLICT] = NULL;
b7bd104e
AP
1063 } else {
1064 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf09a,
1065 "se_sess %p / sess %p port %8phC is gone, %s (ref=%d)\n",
1066 sess->se_sess, sess, sess->port_name,
1067 own ? "releasing own PLOGI" :
1068 "no own PLOGI pending",
1069 own ? own->ref_count : -1);
1070 }
1071
726b8548
QT
1072 if (own) {
1073 sess->fw_login_state = DSC_LS_PLOGI_PEND;
b7bd104e 1074 qlt_plogi_ack_unref(vha, own);
726b8548
QT
1075 sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN] = NULL;
1076 }
b7bd104e 1077 }
5d964837
QT
1078 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
1079
2d70c103 1080 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001,
726b8548
QT
1081 "Unregistration of sess %p %8phC finished fcp_cnt %d\n",
1082 sess, sess->port_name, vha->fcport_count);
2d70c103 1083
726b8548 1084 if (tgt && (tgt->sess_count == 0))
2d70c103 1085 wake_up_all(&tgt->waitQ);
726b8548
QT
1086
1087 if (vha->fcport_count == 0)
1088 wake_up_all(&vha->fcport_waitQ);
1089
41dc529a
QT
1090 base_vha = pci_get_drvdata(ha->pdev);
1091 if (test_bit(PFLG_DRIVER_REMOVING, &base_vha->pci_flags))
1092 return;
1093
726b8548
QT
1094 if (!tgt || !tgt->tgt_stop) {
1095 memset(&ea, 0, sizeof(ea));
1096 ea.event = FCME_DELETE_DONE;
1097 ea.fcport = sess;
1098 qla2x00_fcport_event_handler(vha, &ea);
1099 }
2d70c103
NB
1100}
1101
7560151b 1102/* ha->tgt.sess_lock supposed to be held on entry */
5d964837 1103void qlt_unreg_sess(struct fc_port *sess)
2d70c103
NB
1104{
1105 struct scsi_qla_host *vha = sess->vha;
1106
83548fe2 1107 ql_dbg(ql_dbg_disc, sess->vha, 0x210a,
5d964837
QT
1108 "%s sess %p for deletion %8phC\n",
1109 __func__, sess, sess->port_name);
1110
36c78452
QT
1111 if (sess->se_sess)
1112 vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess);
2d70c103 1113
5d964837
QT
1114 qla2x00_mark_device_lost(vha, sess, 1, 1);
1115
a6ca8878 1116 sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
726b8548
QT
1117 sess->disc_state = DSC_DELETE_PEND;
1118 sess->last_rscn_gen = sess->rscn_gen;
1119 sess->last_login_gen = sess->login_gen;
2d70c103
NB
1120
1121 INIT_WORK(&sess->free_work, qlt_free_session_done);
1122 schedule_work(&sess->free_work);
1123}
5d964837 1124EXPORT_SYMBOL(qlt_unreg_sess);
7560151b 1125
2d70c103
NB
1126static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
1127{
1128 struct qla_hw_data *ha = vha->hw;
5d964837 1129 struct fc_port *sess = NULL;
2d70c103
NB
1130 uint16_t loop_id;
1131 int res = 0;
1132 struct imm_ntfy_from_isp *n = (struct imm_ntfy_from_isp *)iocb;
7560151b 1133 unsigned long flags;
2d70c103
NB
1134
1135 loop_id = le16_to_cpu(n->u.isp24.nport_handle);
1136 if (loop_id == 0xFFFF) {
2d70c103 1137 /* Global event */
b2032fd5 1138 atomic_inc(&vha->vha_tgt.qla_tgt->tgt_global_resets_count);
7560151b 1139 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
b2032fd5 1140 qlt_clear_tgt_db(vha->vha_tgt.qla_tgt);
7560151b 1141 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
2d70c103 1142 } else {
7560151b 1143 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
2d70c103 1144 sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id);
7560151b 1145 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
2d70c103
NB
1146 }
1147
1148 ql_dbg(ql_dbg_tgt, vha, 0xe000,
1149 "Using sess for qla_tgt_reset: %p\n", sess);
1150 if (!sess) {
1151 res = -ESRCH;
1152 return res;
1153 }
1154
1155 ql_dbg(ql_dbg_tgt, vha, 0xe047,
7b833558
OK
1156 "scsi(%ld): resetting (session %p from port %8phC mcmd %x, "
1157 "loop_id %d)\n", vha->host_no, sess, sess->port_name,
2d70c103
NB
1158 mcmd, loop_id);
1159
bb1181c9 1160 return qlt_issue_task_mgmt(sess, 0, mcmd, iocb, QLA24XX_MGMT_SEND_NACK);
2d70c103
NB
1161}
1162
726b8548
QT
1163static void qla24xx_chk_fcp_state(struct fc_port *sess)
1164{
7c3f8fd1 1165 if (sess->chip_reset != sess->vha->hw->base_qpair->chip_reset) {
726b8548
QT
1166 sess->logout_on_delete = 0;
1167 sess->logo_ack_needed = 0;
1168 sess->fw_login_state = DSC_LS_PORT_UNAVAIL;
1169 sess->scan_state = 0;
1170 }
1171}
1172
7560151b 1173/* ha->tgt.sess_lock supposed to be held on entry */
726b8548 1174void qlt_schedule_sess_for_deletion(struct fc_port *sess,
2d70c103
NB
1175 bool immediate)
1176{
1177 struct qla_tgt *tgt = sess->tgt;
2d70c103 1178
726b8548
QT
1179 if (sess->disc_state == DSC_DELETE_PEND)
1180 return;
1181
1182 if (sess->disc_state == DSC_DELETED) {
1183 if (tgt && tgt->tgt_stop && (tgt->sess_count == 0))
1184 wake_up_all(&tgt->waitQ);
1185 if (sess->vha->fcport_count == 0)
1186 wake_up_all(&sess->vha->fcport_waitQ);
1187
1188 if (!sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN] &&
1189 !sess->plogi_link[QLT_PLOGI_LINK_CONFLICT])
a6ca8878
AP
1190 return;
1191 }
2d70c103 1192
726b8548 1193 sess->disc_state = DSC_DELETE_PEND;
2d70c103 1194
726b8548
QT
1195 if (sess->deleted == QLA_SESS_DELETED)
1196 sess->logout_on_delete = 0;
1197
1198 sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
1199 qla24xx_chk_fcp_state(sess);
2d70c103 1200
726b8548
QT
1201 ql_dbg(ql_dbg_tgt, sess->vha, 0xe001,
1202 "Scheduling sess %p for deletion\n", sess);
2d70c103 1203
726b8548
QT
1204 schedule_work(&sess->del_work);
1205}
2d70c103 1206
726b8548
QT
1207void qlt_schedule_sess_for_deletion_lock(struct fc_port *sess)
1208{
1209 unsigned long flags;
1210 struct qla_hw_data *ha = sess->vha->hw;
1211 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
1212 qlt_schedule_sess_for_deletion(sess, 1);
1213 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
2d70c103
NB
1214}
1215
7560151b 1216/* ha->tgt.sess_lock supposed to be held on entry */
c5701042 1217static void qlt_clear_tgt_db(struct qla_tgt *tgt)
2d70c103 1218{
5d964837
QT
1219 struct fc_port *sess;
1220 scsi_qla_host_t *vha = tgt->vha;
2d70c103 1221
5d964837
QT
1222 list_for_each_entry(sess, &vha->vp_fcports, list) {
1223 if (sess->se_sess)
726b8548 1224 qlt_schedule_sess_for_deletion(sess, 1);
5d964837 1225 }
2d70c103
NB
1226
1227 /* At this point tgt could be already dead */
1228}
1229
1230static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id,
1231 uint16_t *loop_id)
1232{
1233 struct qla_hw_data *ha = vha->hw;
1234 dma_addr_t gid_list_dma;
1235 struct gid_list_info *gid_list;
1236 char *id_iter;
1237 int res, rc, i;
1238 uint16_t entries;
1239
1240 gid_list = dma_alloc_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha),
1241 &gid_list_dma, GFP_KERNEL);
1242 if (!gid_list) {
1243 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf044,
1244 "qla_target(%d): DMA Alloc failed of %u\n",
1245 vha->vp_idx, qla2x00_gid_list_size(ha));
1246 return -ENOMEM;
1247 }
1248
1249 /* Get list of logged in devices */
15f30a57 1250 rc = qla24xx_gidlist_wait(vha, gid_list, gid_list_dma, &entries);
2d70c103
NB
1251 if (rc != QLA_SUCCESS) {
1252 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf045,
1253 "qla_target(%d): get_id_list() failed: %x\n",
1254 vha->vp_idx, rc);
71cdc079 1255 res = -EBUSY;
2d70c103
NB
1256 goto out_free_id_list;
1257 }
1258
1259 id_iter = (char *)gid_list;
71cdc079 1260 res = -ENOENT;
2d70c103
NB
1261 for (i = 0; i < entries; i++) {
1262 struct gid_list_info *gid = (struct gid_list_info *)id_iter;
1263 if ((gid->al_pa == s_id[2]) &&
1264 (gid->area == s_id[1]) &&
1265 (gid->domain == s_id[0])) {
1266 *loop_id = le16_to_cpu(gid->loop_id);
1267 res = 0;
1268 break;
1269 }
1270 id_iter += ha->gid_list_info_size;
1271 }
1272
1273out_free_id_list:
1274 dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha),
1275 gid_list, gid_list_dma);
1276 return res;
1277}
1278
2d70c103
NB
1279/*
1280 * Adds an extra ref to allow to drop hw lock after adding sess to the list.
1281 * Caller must put it.
1282 */
5d964837 1283static struct fc_port *qlt_create_sess(
2d70c103
NB
1284 struct scsi_qla_host *vha,
1285 fc_port_t *fcport,
1286 bool local)
1287{
1288 struct qla_hw_data *ha = vha->hw;
726b8548 1289 struct fc_port *sess = fcport;
2d70c103 1290 unsigned long flags;
2d70c103 1291
726b8548
QT
1292 if (vha->vha_tgt.qla_tgt->tgt_stop)
1293 return NULL;
2d70c103 1294
726b8548
QT
1295 if (fcport->se_sess) {
1296 if (!kref_get_unless_zero(&sess->sess_kref)) {
83548fe2 1297 ql_dbg(ql_dbg_disc, vha, 0x20f6,
726b8548
QT
1298 "%s: kref_get_unless_zero failed for %8phC\n",
1299 __func__, sess->port_name);
1300 return NULL;
2d70c103 1301 }
726b8548 1302 return fcport;
2d70c103 1303 }
0e8cd71c 1304 sess->tgt = vha->vha_tgt.qla_tgt;
2d70c103 1305 sess->local = local;
a6ca8878 1306
726b8548
QT
1307 /*
1308 * Under normal circumstances we want to logout from firmware when
a6ca8878
AP
1309 * session eventually ends and release corresponding nport handle.
1310 * In the exception cases (e.g. when new PLOGI is waiting) corresponding
726b8548
QT
1311 * code will adjust these flags as necessary.
1312 */
a6ca8878
AP
1313 sess->logout_on_delete = 1;
1314 sess->keep_nport_handle = 0;
726b8548 1315 sess->logout_completed = 0;
2d70c103 1316
726b8548
QT
1317 if (ha->tgt.tgt_ops->check_initiator_node_acl(vha,
1318 &fcport->port_name[0], sess) < 0) {
83548fe2 1319 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf015,
726b8548
QT
1320 "(%d) %8phC check_initiator_node_acl failed\n",
1321 vha->vp_idx, fcport->port_name);
1322 return NULL;
1323 } else {
1324 kref_init(&fcport->sess_kref);
1325 /*
1326 * Take an extra reference to ->sess_kref here to handle
1327 * fc_port access across ->tgt.sess_lock reaquire.
1328 */
1329 if (!kref_get_unless_zero(&sess->sess_kref)) {
83548fe2 1330 ql_dbg(ql_dbg_disc, vha, 0x20f7,
726b8548
QT
1331 "%s: kref_get_unless_zero failed for %8phC\n",
1332 __func__, sess->port_name);
1333 return NULL;
1334 }
2d70c103 1335
726b8548
QT
1336 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
1337 if (!IS_SW_RESV_ADDR(sess->d_id))
1338 vha->vha_tgt.qla_tgt->sess_count++;
2d70c103 1339
726b8548
QT
1340 qlt_do_generation_tick(vha, &sess->generation);
1341 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
1342 }
1343
1344 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006,
1345 "Adding sess %p se_sess %p to tgt %p sess_count %d\n",
1346 sess, sess->se_sess, vha->vha_tgt.qla_tgt,
1347 vha->vha_tgt.qla_tgt->sess_count);
2d70c103
NB
1348
1349 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b,
7b833558
OK
1350 "qla_target(%d): %ssession for wwn %8phC (loop_id %d, "
1351 "s_id %x:%x:%x, confirmed completion %ssupported) added\n",
1352 vha->vp_idx, local ? "local " : "", fcport->port_name,
37cacc0a
QT
1353 fcport->loop_id, sess->d_id.b.domain, sess->d_id.b.area,
1354 sess->d_id.b.al_pa, sess->conf_compl_supported ? "" : "not ");
2d70c103
NB
1355
1356 return sess;
1357}
1358
df673274
AP
1359/*
1360 * max_gen - specifies maximum session generation
1361 * at which this deletion requestion is still valid
1362 */
1363void
1364qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen)
2d70c103 1365{
0e8cd71c 1366 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
5d964837 1367 struct fc_port *sess = fcport;
7560151b 1368 unsigned long flags;
2d70c103
NB
1369
1370 if (!vha->hw->tgt.tgt_ops)
1371 return;
1372
b2032fd5 1373 if (!tgt)
2d70c103
NB
1374 return;
1375
7560151b 1376 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
2d70c103 1377 if (tgt->tgt_stop) {
7560151b 1378 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
2d70c103
NB
1379 return;
1380 }
5d964837 1381 if (!sess->se_sess) {
7560151b 1382 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
2d70c103
NB
1383 return;
1384 }
1385
df673274 1386 if (max_gen - sess->generation < 0) {
7560151b 1387 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
df673274
AP
1388 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf092,
1389 "Ignoring stale deletion request for se_sess %p / sess %p"
1390 " for port %8phC, req_gen %d, sess_gen %d\n",
1391 sess->se_sess, sess, sess->port_name, max_gen,
1392 sess->generation);
1393 return;
1394 }
1395
2d70c103
NB
1396 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf008, "qla_tgt_fc_port_deleted %p", sess);
1397
1398 sess->local = 1;
1399 qlt_schedule_sess_for_deletion(sess, false);
7560151b 1400 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
2d70c103
NB
1401}
1402
1403static inline int test_tgt_sess_count(struct qla_tgt *tgt)
1404{
1405 struct qla_hw_data *ha = tgt->ha;
1406 unsigned long flags;
1407 int res;
1408 /*
1409 * We need to protect against race, when tgt is freed before or
1410 * inside wake_up()
1411 */
726b8548 1412 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
2d70c103 1413 ql_dbg(ql_dbg_tgt, tgt->vha, 0xe002,
5d964837
QT
1414 "tgt %p, sess_count=%d\n",
1415 tgt, tgt->sess_count);
2d70c103 1416 res = (tgt->sess_count == 0);
726b8548 1417 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
2d70c103
NB
1418
1419 return res;
1420}
1421
1422/* Called by tcm_qla2xxx configfs code */
3c231bda 1423int qlt_stop_phase1(struct qla_tgt *tgt)
2d70c103
NB
1424{
1425 struct scsi_qla_host *vha = tgt->vha;
1426 struct qla_hw_data *ha = tgt->ha;
1427 unsigned long flags;
1428
3c231bda
NB
1429 mutex_lock(&qla_tgt_mutex);
1430 if (!vha->fc_vport) {
1431 struct Scsi_Host *sh = vha->host;
1432 struct fc_host_attrs *fc_host = shost_to_fc_host(sh);
1433 bool npiv_vports;
1434
1435 spin_lock_irqsave(sh->host_lock, flags);
1436 npiv_vports = (fc_host->npiv_vports_inuse);
1437 spin_unlock_irqrestore(sh->host_lock, flags);
1438
1439 if (npiv_vports) {
1440 mutex_unlock(&qla_tgt_mutex);
3a33dc95
QT
1441 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf021,
1442 "NPIV is in use. Can not stop target\n");
3c231bda
NB
1443 return -EPERM;
1444 }
1445 }
2d70c103
NB
1446 if (tgt->tgt_stop || tgt->tgt_stopped) {
1447 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04e,
1448 "Already in tgt->tgt_stop or tgt_stopped state\n");
3c231bda
NB
1449 mutex_unlock(&qla_tgt_mutex);
1450 return -EPERM;
2d70c103
NB
1451 }
1452
3a33dc95 1453 ql_dbg(ql_dbg_tgt_mgt, vha, 0xe003, "Stopping target for host %ld(%p)\n",
2d70c103
NB
1454 vha->host_no, vha);
1455 /*
1456 * Mutex needed to sync with qla_tgt_fc_port_[added,deleted].
1457 * Lock is needed, because we still can get an incoming packet.
1458 */
0e8cd71c 1459 mutex_lock(&vha->vha_tgt.tgt_mutex);
7560151b 1460 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
2d70c103 1461 tgt->tgt_stop = 1;
c5701042 1462 qlt_clear_tgt_db(tgt);
7560151b 1463 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
0e8cd71c 1464 mutex_unlock(&vha->vha_tgt.tgt_mutex);
3c231bda 1465 mutex_unlock(&qla_tgt_mutex);
2d70c103 1466
2d70c103
NB
1467 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf009,
1468 "Waiting for sess works (tgt %p)", tgt);
1469 spin_lock_irqsave(&tgt->sess_work_lock, flags);
1470 while (!list_empty(&tgt->sess_works_list)) {
1471 spin_unlock_irqrestore(&tgt->sess_work_lock, flags);
1472 flush_scheduled_work();
1473 spin_lock_irqsave(&tgt->sess_work_lock, flags);
1474 }
1475 spin_unlock_irqrestore(&tgt->sess_work_lock, flags);
1476
1477 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00a,
5d964837 1478 "Waiting for tgt %p: sess_count=%d\n", tgt, tgt->sess_count);
2d70c103
NB
1479
1480 wait_event(tgt->waitQ, test_tgt_sess_count(tgt));
1481
1482 /* Big hammer */
ead03855
QT
1483 if (!ha->flags.host_shutting_down &&
1484 (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)))
2d70c103
NB
1485 qlt_disable_vha(vha);
1486
1487 /* Wait for sessions to clear out (just in case) */
1488 wait_event(tgt->waitQ, test_tgt_sess_count(tgt));
3c231bda 1489 return 0;
2d70c103
NB
1490}
1491EXPORT_SYMBOL(qlt_stop_phase1);
1492
1493/* Called by tcm_qla2xxx configfs code */
1494void qlt_stop_phase2(struct qla_tgt *tgt)
1495{
3a33dc95 1496 scsi_qla_host_t *vha = tgt->vha;
2d70c103
NB
1497
1498 if (tgt->tgt_stopped) {
0e8cd71c 1499 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04f,
2d70c103
NB
1500 "Already in tgt->tgt_stopped state\n");
1501 dump_stack();
1502 return;
1503 }
3a33dc95
QT
1504 if (!tgt->tgt_stop) {
1505 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00b,
1506 "%s: phase1 stop is not completed\n", __func__);
1507 dump_stack();
1508 return;
1509 }
2d70c103 1510
0e8cd71c 1511 mutex_lock(&vha->vha_tgt.tgt_mutex);
2d70c103
NB
1512 tgt->tgt_stop = 0;
1513 tgt->tgt_stopped = 1;
0e8cd71c 1514 mutex_unlock(&vha->vha_tgt.tgt_mutex);
2d70c103 1515
3a33dc95 1516 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00c, "Stop of tgt %p finished\n",
2d70c103
NB
1517 tgt);
1518}
1519EXPORT_SYMBOL(qlt_stop_phase2);
1520
1521/* Called from qlt_remove_target() -> qla2x00_remove_one() */
fa492630 1522static void qlt_release(struct qla_tgt *tgt)
2d70c103 1523{
0e8cd71c 1524 scsi_qla_host_t *vha = tgt->vha;
e326d22a
QT
1525 void *node;
1526 u64 key = 0;
1527 u16 i;
1528 struct qla_qpair_hint *h;
2d70c103 1529
3a33dc95
QT
1530 if ((vha->vha_tgt.qla_tgt != NULL) && !tgt->tgt_stop &&
1531 !tgt->tgt_stopped)
1532 qlt_stop_phase1(tgt);
1533
0e8cd71c 1534 if ((vha->vha_tgt.qla_tgt != NULL) && !tgt->tgt_stopped)
2d70c103
NB
1535 qlt_stop_phase2(tgt);
1536
e326d22a
QT
1537 for (i = 0; i < vha->hw->max_qpairs + 1; i++) {
1538 unsigned long flags;
1539
1540 h = &tgt->qphints[i];
1541 if (h->qpair) {
1542 spin_lock_irqsave(h->qpair->qp_lock_ptr, flags);
1543 list_del(&h->hint_elem);
1544 spin_unlock_irqrestore(h->qpair->qp_lock_ptr, flags);
1545 h->qpair = NULL;
1546 }
1547 }
1548 kfree(tgt->qphints);
1549
1550 btree_for_each_safe64(&tgt->lun_qpair_map, key, node)
1551 btree_remove64(&tgt->lun_qpair_map, key);
1552
1553 btree_destroy64(&tgt->lun_qpair_map);
1554
0e8cd71c 1555 vha->vha_tgt.qla_tgt = NULL;
2d70c103 1556
0e8cd71c 1557 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00d,
2d70c103
NB
1558 "Release of tgt %p finished\n", tgt);
1559
1560 kfree(tgt);
1561}
1562
1563/* ha->hardware_lock supposed to be held on entry */
1564static int qlt_sched_sess_work(struct qla_tgt *tgt, int type,
1565 const void *param, unsigned int param_size)
1566{
1567 struct qla_tgt_sess_work_param *prm;
1568 unsigned long flags;
1569
1570 prm = kzalloc(sizeof(*prm), GFP_ATOMIC);
1571 if (!prm) {
1572 ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf050,
1573 "qla_target(%d): Unable to create session "
1574 "work, command will be refused", 0);
1575 return -ENOMEM;
1576 }
1577
1578 ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf00e,
1579 "Scheduling work (type %d, prm %p)"
1580 " to find session for param %p (size %d, tgt %p)\n",
1581 type, prm, param, param_size, tgt);
1582
1583 prm->type = type;
1584 memcpy(&prm->tm_iocb, param, param_size);
1585
1586 spin_lock_irqsave(&tgt->sess_work_lock, flags);
1587 list_add_tail(&prm->sess_works_list_entry, &tgt->sess_works_list);
1588 spin_unlock_irqrestore(&tgt->sess_work_lock, flags);
1589
1590 schedule_work(&tgt->sess_work);
1591
1592 return 0;
1593}
1594
1595/*
1596 * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
1597 */
82de802a 1598static void qlt_send_notify_ack(struct qla_qpair *qpair,
2d70c103
NB
1599 struct imm_ntfy_from_isp *ntfy,
1600 uint32_t add_flags, uint16_t resp_code, int resp_code_valid,
1601 uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan)
1602{
82de802a 1603 struct scsi_qla_host *vha = qpair->vha;
2d70c103
NB
1604 struct qla_hw_data *ha = vha->hw;
1605 request_t *pkt;
1606 struct nack_to_isp *nack;
1607
ec7193e2
QT
1608 if (!ha->flags.fw_started)
1609 return;
1610
2d70c103
NB
1611 ql_dbg(ql_dbg_tgt, vha, 0xe004, "Sending NOTIFY_ACK (ha=%p)\n", ha);
1612
82de802a 1613 pkt = (request_t *)__qla2x00_alloc_iocbs(qpair, NULL);
2d70c103
NB
1614 if (!pkt) {
1615 ql_dbg(ql_dbg_tgt, vha, 0xe049,
1616 "qla_target(%d): %s failed: unable to allocate "
1617 "request packet\n", vha->vp_idx, __func__);
1618 return;
1619 }
1620
0e8cd71c
SK
1621 if (vha->vha_tgt.qla_tgt != NULL)
1622 vha->vha_tgt.qla_tgt->notify_ack_expected++;
2d70c103
NB
1623
1624 pkt->entry_type = NOTIFY_ACK_TYPE;
1625 pkt->entry_count = 1;
1626
1627 nack = (struct nack_to_isp *)pkt;
1628 nack->ox_id = ntfy->ox_id;
1629
726b8548 1630 nack->u.isp24.handle = QLA_TGT_SKIP_HANDLE;
2d70c103
NB
1631 nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle;
1632 if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) {
1633 nack->u.isp24.flags = ntfy->u.isp24.flags &
ad950360 1634 cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB);
2d70c103
NB
1635 }
1636 nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id;
1637 nack->u.isp24.status = ntfy->u.isp24.status;
1638 nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode;
aa230bc5 1639 nack->u.isp24.fw_handle = ntfy->u.isp24.fw_handle;
2d70c103
NB
1640 nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address;
1641 nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs;
1642 nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui;
1643 nack->u.isp24.srr_flags = cpu_to_le16(srr_flags);
1644 nack->u.isp24.srr_reject_code = srr_reject_code;
1645 nack->u.isp24.srr_reject_code_expl = srr_explan;
1646 nack->u.isp24.vp_index = ntfy->u.isp24.vp_index;
1647
1648 ql_dbg(ql_dbg_tgt, vha, 0xe005,
1649 "qla_target(%d): Sending 24xx Notify Ack %d\n",
1650 vha->vp_idx, nack->u.isp24.status);
1651
63163e06
HM
1652 /* Memory Barrier */
1653 wmb();
82de802a 1654 qla2x00_start_iocbs(vha, qpair->req);
2d70c103
NB
1655}
1656
1657/*
1658 * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
1659 */
82de802a 1660static void qlt_24xx_send_abts_resp(struct qla_qpair *qpair,
2d70c103
NB
1661 struct abts_recv_from_24xx *abts, uint32_t status,
1662 bool ids_reversed)
1663{
82de802a 1664 struct scsi_qla_host *vha = qpair->vha;
2d70c103
NB
1665 struct qla_hw_data *ha = vha->hw;
1666 struct abts_resp_to_24xx *resp;
1667 uint32_t f_ctl;
1668 uint8_t *p;
1669
1670 ql_dbg(ql_dbg_tgt, vha, 0xe006,
1671 "Sending task mgmt ABTS response (ha=%p, atio=%p, status=%x\n",
1672 ha, abts, status);
1673
82de802a
QT
1674 resp = (struct abts_resp_to_24xx *)qla2x00_alloc_iocbs_ready(qpair,
1675 NULL);
2d70c103
NB
1676 if (!resp) {
1677 ql_dbg(ql_dbg_tgt, vha, 0xe04a,
1678 "qla_target(%d): %s failed: unable to allocate "
1679 "request packet", vha->vp_idx, __func__);
1680 return;
1681 }
1682
1683 resp->entry_type = ABTS_RESP_24XX;
1684 resp->entry_count = 1;
1685 resp->nport_handle = abts->nport_handle;
1686 resp->vp_index = vha->vp_idx;
1687 resp->sof_type = abts->sof_type;
1688 resp->exchange_address = abts->exchange_address;
1689 resp->fcp_hdr_le = abts->fcp_hdr_le;
ad950360 1690 f_ctl = cpu_to_le32(F_CTL_EXCH_CONTEXT_RESP |
2d70c103
NB
1691 F_CTL_LAST_SEQ | F_CTL_END_SEQ |
1692 F_CTL_SEQ_INITIATIVE);
1693 p = (uint8_t *)&f_ctl;
1694 resp->fcp_hdr_le.f_ctl[0] = *p++;
1695 resp->fcp_hdr_le.f_ctl[1] = *p++;
1696 resp->fcp_hdr_le.f_ctl[2] = *p;
1697 if (ids_reversed) {
1698 resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.d_id[0];
1699 resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.d_id[1];
1700 resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.d_id[2];
1701 resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.s_id[0];
1702 resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.s_id[1];
1703 resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.s_id[2];
1704 } else {
1705 resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.s_id[0];
1706 resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.s_id[1];
1707 resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.s_id[2];
1708 resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.d_id[0];
1709 resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.d_id[1];
1710 resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.d_id[2];
1711 }
1712 resp->exchange_addr_to_abort = abts->exchange_addr_to_abort;
1713 if (status == FCP_TMF_CMPL) {
1714 resp->fcp_hdr_le.r_ctl = R_CTL_BASIC_LINK_SERV | R_CTL_B_ACC;
1715 resp->payload.ba_acct.seq_id_valid = SEQ_ID_INVALID;
1716 resp->payload.ba_acct.low_seq_cnt = 0x0000;
1717 resp->payload.ba_acct.high_seq_cnt = 0xFFFF;
1718 resp->payload.ba_acct.ox_id = abts->fcp_hdr_le.ox_id;
1719 resp->payload.ba_acct.rx_id = abts->fcp_hdr_le.rx_id;
1720 } else {
1721 resp->fcp_hdr_le.r_ctl = R_CTL_BASIC_LINK_SERV | R_CTL_B_RJT;
1722 resp->payload.ba_rjt.reason_code =
1723 BA_RJT_REASON_CODE_UNABLE_TO_PERFORM;
1724 /* Other bytes are zero */
1725 }
1726
0e8cd71c 1727 vha->vha_tgt.qla_tgt->abts_resp_expected++;
2d70c103 1728
63163e06
HM
1729 /* Memory Barrier */
1730 wmb();
8abfa9e2
QT
1731 if (qpair->reqq_start_iocbs)
1732 qpair->reqq_start_iocbs(qpair);
1733 else
1734 qla2x00_start_iocbs(vha, qpair->req);
2d70c103
NB
1735}
1736
1737/*
1738 * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
1739 */
1740static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha,
1741 struct abts_resp_from_24xx_fw *entry)
1742{
1743 struct ctio7_to_24xx *ctio;
1744
1745 ql_dbg(ql_dbg_tgt, vha, 0xe007,
1746 "Sending retry TERM EXCH CTIO7 (ha=%p)\n", vha->hw);
2d70c103 1747
82de802a
QT
1748 ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs_ready(
1749 vha->hw->base_qpair, NULL);
2d70c103
NB
1750 if (ctio == NULL) {
1751 ql_dbg(ql_dbg_tgt, vha, 0xe04b,
1752 "qla_target(%d): %s failed: unable to allocate "
1753 "request packet\n", vha->vp_idx, __func__);
1754 return;
1755 }
1756
1757 /*
1758 * We've got on entrance firmware's response on by us generated
1759 * ABTS response. So, in it ID fields are reversed.
1760 */
1761
1762 ctio->entry_type = CTIO_TYPE7;
1763 ctio->entry_count = 1;
1764 ctio->nport_handle = entry->nport_handle;
1765 ctio->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
ad950360 1766 ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
2d70c103
NB
1767 ctio->vp_index = vha->vp_idx;
1768 ctio->initiator_id[0] = entry->fcp_hdr_le.d_id[0];
1769 ctio->initiator_id[1] = entry->fcp_hdr_le.d_id[1];
1770 ctio->initiator_id[2] = entry->fcp_hdr_le.d_id[2];
1771 ctio->exchange_addr = entry->exchange_addr_to_abort;
ad950360
BVA
1772 ctio->u.status1.flags = cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 |
1773 CTIO7_FLAGS_TERMINATE);
33a5fcee 1774 ctio->u.status1.ox_id = cpu_to_le16(entry->fcp_hdr_le.ox_id);
2d70c103 1775
63163e06
HM
1776 /* Memory Barrier */
1777 wmb();
2d70c103
NB
1778 qla2x00_start_iocbs(vha, vha->req);
1779
82de802a
QT
1780 qlt_24xx_send_abts_resp(vha->hw->base_qpair,
1781 (struct abts_recv_from_24xx *)entry,
2d70c103
NB
1782 FCP_TMF_CMPL, true);
1783}
1784
8b2f5ff3
SN
1785static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag)
1786{
1787 struct qla_tgt_sess_op *op;
1788 struct qla_tgt_cmd *cmd;
8b631d87 1789 unsigned long flags;
8b2f5ff3 1790
8b631d87 1791 spin_lock_irqsave(&vha->cmd_list_lock, flags);
8b2f5ff3
SN
1792 list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
1793 if (tag == op->atio.u.isp24.exchange_addr) {
1794 op->aborted = true;
8b631d87 1795 spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
8b2f5ff3
SN
1796 return 1;
1797 }
1798 }
1799
41dc529a
QT
1800 list_for_each_entry(op, &vha->unknown_atio_list, cmd_list) {
1801 if (tag == op->atio.u.isp24.exchange_addr) {
1802 op->aborted = true;
8b631d87 1803 spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
41dc529a
QT
1804 return 1;
1805 }
1806 }
1807
8b2f5ff3
SN
1808 list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
1809 if (tag == cmd->atio.u.isp24.exchange_addr) {
193b50b9 1810 cmd->aborted = 1;
8b631d87 1811 spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
8b2f5ff3
SN
1812 return 1;
1813 }
1814 }
8b631d87 1815 spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
8b2f5ff3 1816
8b2f5ff3
SN
1817 return 0;
1818}
1819
1820/* drop cmds for the given lun
1821 * XXX only looks for cmds on the port through which lun reset was recieved
1822 * XXX does not go through the list of other port (which may have cmds
1823 * for the same lun)
1824 */
1825static void abort_cmds_for_lun(struct scsi_qla_host *vha,
f775bd14 1826 u64 lun, uint8_t *s_id)
8b2f5ff3
SN
1827{
1828 struct qla_tgt_sess_op *op;
1829 struct qla_tgt_cmd *cmd;
1830 uint32_t key;
8b631d87 1831 unsigned long flags;
8b2f5ff3
SN
1832
1833 key = sid_to_key(s_id);
8b631d87 1834 spin_lock_irqsave(&vha->cmd_list_lock, flags);
8b2f5ff3
SN
1835 list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
1836 uint32_t op_key;
f775bd14 1837 u64 op_lun;
8b2f5ff3
SN
1838
1839 op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
1840 op_lun = scsilun_to_int(
1841 (struct scsi_lun *)&op->atio.u.isp24.fcp_cmnd.lun);
1842 if (op_key == key && op_lun == lun)
1843 op->aborted = true;
1844 }
41dc529a
QT
1845
1846 list_for_each_entry(op, &vha->unknown_atio_list, cmd_list) {
1847 uint32_t op_key;
1848 u64 op_lun;
1849
1850 op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
1851 op_lun = scsilun_to_int(
1852 (struct scsi_lun *)&op->atio.u.isp24.fcp_cmnd.lun);
1853 if (op_key == key && op_lun == lun)
1854 op->aborted = true;
1855 }
1856
8b2f5ff3
SN
1857 list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
1858 uint32_t cmd_key;
f775bd14 1859 u64 cmd_lun;
8b2f5ff3
SN
1860
1861 cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id);
1862 cmd_lun = scsilun_to_int(
1863 (struct scsi_lun *)&cmd->atio.u.isp24.fcp_cmnd.lun);
1864 if (cmd_key == key && cmd_lun == lun)
193b50b9 1865 cmd->aborted = 1;
8b2f5ff3 1866 }
8b631d87 1867 spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
8b2f5ff3
SN
1868}
1869
2d70c103
NB
1870/* ha->hardware_lock supposed to be held on entry */
1871static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
5d964837 1872 struct abts_recv_from_24xx *abts, struct fc_port *sess)
2d70c103
NB
1873{
1874 struct qla_hw_data *ha = vha->hw;
06e97b48 1875 struct se_session *se_sess = sess->se_sess;
2d70c103 1876 struct qla_tgt_mgmt_cmd *mcmd;
f775bd14 1877 struct qla_tgt_cmd *cmd;
06e97b48 1878 struct se_cmd *se_cmd;
2d70c103 1879 int rc;
06e97b48 1880 bool found_lun = false;
5d964837 1881 unsigned long flags;
06e97b48 1882
5d964837 1883 spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
06e97b48 1884 list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) {
649ee054 1885 if (se_cmd->tag == abts->exchange_addr_to_abort) {
06e97b48
SH
1886 found_lun = true;
1887 break;
1888 }
1889 }
5d964837 1890 spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
06e97b48 1891
8b2f5ff3
SN
1892 /* cmd not in LIO lists, look in qla list */
1893 if (!found_lun) {
1894 if (abort_cmd_for_tag(vha, abts->exchange_addr_to_abort)) {
1895 /* send TASK_ABORT response immediately */
82de802a
QT
1896 qlt_24xx_send_abts_resp(ha->base_qpair, abts,
1897 FCP_TMF_CMPL, false);
8b2f5ff3
SN
1898 return 0;
1899 } else {
1900 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf081,
1901 "unable to find cmd in driver or LIO for tag 0x%x\n",
1902 abts->exchange_addr_to_abort);
1903 return -ENOENT;
1904 }
1905 }
2d70c103
NB
1906
1907 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f,
1908 "qla_target(%d): task abort (tag=%d)\n",
1909 vha->vp_idx, abts->exchange_addr_to_abort);
1910
1911 mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC);
1912 if (mcmd == NULL) {
1913 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf051,
1914 "qla_target(%d): %s: Allocation of ABORT cmd failed",
1915 vha->vp_idx, __func__);
1916 return -ENOMEM;
1917 }
1918 memset(mcmd, 0, sizeof(*mcmd));
1919
f775bd14 1920 cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd);
2d70c103
NB
1921 mcmd->sess = sess;
1922 memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts));
7c3f8fd1 1923 mcmd->reset_count = ha->base_qpair->chip_reset;
be92fc3f 1924 mcmd->tmr_func = QLA_TGT_ABTS;
82de802a 1925 mcmd->qpair = ha->base_qpair;
2d70c103 1926
f775bd14 1927 rc = ha->tgt.tgt_ops->handle_tmr(mcmd, cmd->unpacked_lun, mcmd->tmr_func,
2d70c103
NB
1928 abts->exchange_addr_to_abort);
1929 if (rc != 0) {
1930 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052,
1931 "qla_target(%d): tgt_ops->handle_tmr()"
1932 " failed: %d", vha->vp_idx, rc);
1933 mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool);
1934 return -EFAULT;
1935 }
1936
1937 return 0;
1938}
1939
1940/*
1941 * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
1942 */
1943static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
1944 struct abts_recv_from_24xx *abts)
1945{
1946 struct qla_hw_data *ha = vha->hw;
5d964837 1947 struct fc_port *sess;
2d70c103
NB
1948 uint32_t tag = abts->exchange_addr_to_abort;
1949 uint8_t s_id[3];
1950 int rc;
7560151b 1951 unsigned long flags;
2d70c103
NB
1952
1953 if (le32_to_cpu(abts->fcp_hdr_le.parameter) & ABTS_PARAM_ABORT_SEQ) {
1954 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf053,
1955 "qla_target(%d): ABTS: Abort Sequence not "
1956 "supported\n", vha->vp_idx);
82de802a
QT
1957 qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED,
1958 false);
2d70c103
NB
1959 return;
1960 }
1961
1962 if (tag == ATIO_EXCHANGE_ADDRESS_UNKNOWN) {
1963 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf010,
1964 "qla_target(%d): ABTS: Unknown Exchange "
1965 "Address received\n", vha->vp_idx);
82de802a
QT
1966 qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED,
1967 false);
2d70c103
NB
1968 return;
1969 }
1970
1971 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf011,
1972 "qla_target(%d): task abort (s_id=%x:%x:%x, "
1973 "tag=%d, param=%x)\n", vha->vp_idx, abts->fcp_hdr_le.s_id[2],
1974 abts->fcp_hdr_le.s_id[1], abts->fcp_hdr_le.s_id[0], tag,
1975 le32_to_cpu(abts->fcp_hdr_le.parameter));
1976
1977 s_id[0] = abts->fcp_hdr_le.s_id[2];
1978 s_id[1] = abts->fcp_hdr_le.s_id[1];
1979 s_id[2] = abts->fcp_hdr_le.s_id[0];
1980
7560151b 1981 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
2d70c103
NB
1982 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id);
1983 if (!sess) {
1984 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf012,
1985 "qla_target(%d): task abort for non-existant session\n",
1986 vha->vp_idx);
0e8cd71c 1987 rc = qlt_sched_sess_work(vha->vha_tgt.qla_tgt,
2d70c103 1988 QLA_TGT_SESS_WORK_ABORT, abts, sizeof(*abts));
7560151b
QT
1989
1990 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
1991
2d70c103 1992 if (rc != 0) {
82de802a
QT
1993 qlt_24xx_send_abts_resp(ha->base_qpair, abts,
1994 FCP_TMF_REJECTED, false);
2d70c103
NB
1995 }
1996 return;
1997 }
7560151b
QT
1998 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
1999
2d70c103 2000
726b8548 2001 if (sess->deleted) {
82de802a
QT
2002 qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED,
2003 false);
e52a8b45
AP
2004 return;
2005 }
2006
2d70c103
NB
2007 rc = __qlt_24xx_handle_abts(vha, abts, sess);
2008 if (rc != 0) {
2009 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf054,
2010 "qla_target(%d): __qlt_24xx_handle_abts() failed: %d\n",
2011 vha->vp_idx, rc);
82de802a
QT
2012 qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED,
2013 false);
2d70c103
NB
2014 return;
2015 }
2016}
2017
2018/*
2019 * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
2020 */
82de802a 2021static void qlt_24xx_send_task_mgmt_ctio(struct qla_qpair *qpair,
2d70c103
NB
2022 struct qla_tgt_mgmt_cmd *mcmd, uint32_t resp_code)
2023{
82de802a 2024 struct scsi_qla_host *ha = qpair->vha;
2d70c103
NB
2025 struct atio_from_isp *atio = &mcmd->orig_iocb.atio;
2026 struct ctio7_to_24xx *ctio;
33a5fcee 2027 uint16_t temp;
2d70c103
NB
2028
2029 ql_dbg(ql_dbg_tgt, ha, 0xe008,
2030 "Sending task mgmt CTIO7 (ha=%p, atio=%p, resp_code=%x\n",
2031 ha, atio, resp_code);
2032
2d70c103 2033
82de802a 2034 ctio = (struct ctio7_to_24xx *)__qla2x00_alloc_iocbs(qpair, NULL);
2d70c103
NB
2035 if (ctio == NULL) {
2036 ql_dbg(ql_dbg_tgt, ha, 0xe04c,
2037 "qla_target(%d): %s failed: unable to allocate "
2038 "request packet\n", ha->vp_idx, __func__);
2039 return;
2040 }
2041
2042 ctio->entry_type = CTIO_TYPE7;
2043 ctio->entry_count = 1;
2044 ctio->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
2045 ctio->nport_handle = mcmd->sess->loop_id;
ad950360 2046 ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
2d70c103
NB
2047 ctio->vp_index = ha->vp_idx;
2048 ctio->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
2049 ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
2050 ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
2051 ctio->exchange_addr = atio->u.isp24.exchange_addr;
f7e761f5
QT
2052 temp = (atio->u.isp24.attr << 9)|
2053 CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS;
2054 ctio->u.status1.flags = cpu_to_le16(temp);
33a5fcee
QT
2055 temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
2056 ctio->u.status1.ox_id = cpu_to_le16(temp);
2d70c103 2057 ctio->u.status1.scsi_status =
ad950360
BVA
2058 cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID);
2059 ctio->u.status1.response_len = cpu_to_le16(8);
e4b11b89 2060 ctio->u.status1.sense_data[0] = resp_code;
2d70c103 2061
63163e06
HM
2062 /* Memory Barrier */
2063 wmb();
8abfa9e2
QT
2064 if (qpair->reqq_start_iocbs)
2065 qpair->reqq_start_iocbs(qpair);
2066 else
2067 qla2x00_start_iocbs(ha, qpair->req);
2d70c103
NB
2068}
2069
2070void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd)
2071{
2072 mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool);
2073}
2074EXPORT_SYMBOL(qlt_free_mcmd);
2075
be25152c
QT
2076/*
2077 * ha->hardware_lock supposed to be held on entry. Might drop it, then
2078 * reacquire
2079 */
8abfa9e2 2080void qlt_send_resp_ctio(struct qla_qpair *qpair, struct qla_tgt_cmd *cmd,
be25152c
QT
2081 uint8_t scsi_status, uint8_t sense_key, uint8_t asc, uint8_t ascq)
2082{
2083 struct atio_from_isp *atio = &cmd->atio;
2084 struct ctio7_to_24xx *ctio;
2085 uint16_t temp;
8abfa9e2 2086 struct scsi_qla_host *vha = cmd->vha;
be25152c
QT
2087
2088 ql_dbg(ql_dbg_tgt_dif, vha, 0x3066,
2089 "Sending response CTIO7 (vha=%p, atio=%p, scsi_status=%02x, "
2090 "sense_key=%02x, asc=%02x, ascq=%02x",
2091 vha, atio, scsi_status, sense_key, asc, ascq);
2092
2093 ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs(vha, NULL);
2094 if (!ctio) {
2095 ql_dbg(ql_dbg_async, vha, 0x3067,
2096 "qla2x00t(%ld): %s failed: unable to allocate request packet",
2097 vha->host_no, __func__);
2098 goto out;
2099 }
2100
2101 ctio->entry_type = CTIO_TYPE7;
2102 ctio->entry_count = 1;
2103 ctio->handle = QLA_TGT_SKIP_HANDLE;
2104 ctio->nport_handle = cmd->sess->loop_id;
2105 ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
2106 ctio->vp_index = vha->vp_idx;
2107 ctio->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
2108 ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
2109 ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
2110 ctio->exchange_addr = atio->u.isp24.exchange_addr;
f7e761f5
QT
2111 temp = (atio->u.isp24.attr << 9) |
2112 CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS;
2113 ctio->u.status1.flags = cpu_to_le16(temp);
be25152c
QT
2114 temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
2115 ctio->u.status1.ox_id = cpu_to_le16(temp);
2116 ctio->u.status1.scsi_status =
2117 cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID | scsi_status);
2118 ctio->u.status1.response_len = cpu_to_le16(18);
2119 ctio->u.status1.residual = cpu_to_le32(get_datalen_for_atio(atio));
2120
2121 if (ctio->u.status1.residual != 0)
2122 ctio->u.status1.scsi_status |=
2123 cpu_to_le16(SS_RESIDUAL_UNDER);
2124
2125 /* Response code and sense key */
2126 put_unaligned_le32(((0x70 << 24) | (sense_key << 8)),
2127 (&ctio->u.status1.sense_data)[0]);
2128 /* Additional sense length */
2129 put_unaligned_le32(0x0a, (&ctio->u.status1.sense_data)[1]);
2130 /* ASC and ASCQ */
2131 put_unaligned_le32(((asc << 24) | (ascq << 16)),
2132 (&ctio->u.status1.sense_data)[3]);
2133
2134 /* Memory Barrier */
2135 wmb();
2136
8abfa9e2
QT
2137 if (qpair->reqq_start_iocbs)
2138 qpair->reqq_start_iocbs(qpair);
2139 else
2140 qla2x00_start_iocbs(vha, qpair->req);
2141
be25152c
QT
2142out:
2143 return;
2144}
2145
2d70c103
NB
2146/* callback from target fabric module code */
2147void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
2148{
2149 struct scsi_qla_host *vha = mcmd->sess->vha;
2150 struct qla_hw_data *ha = vha->hw;
2151 unsigned long flags;
82de802a 2152 struct qla_qpair *qpair = mcmd->qpair;
2d70c103
NB
2153
2154 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf013,
2155 "TM response mcmd (%p) status %#x state %#x",
2156 mcmd, mcmd->fc_tm_rsp, mcmd->flags);
2157
82de802a 2158 spin_lock_irqsave(qpair->qp_lock_ptr, flags);
b6a029e1 2159
7c3f8fd1 2160 if (!vha->flags.online || mcmd->reset_count != qpair->chip_reset) {
b6a029e1 2161 /*
3bb67df5 2162 * Either the port is not online or this request was from
b6a029e1
AE
2163 * previous life, just abort the processing.
2164 */
2165 ql_dbg(ql_dbg_async, vha, 0xe100,
3bb67df5
DKU
2166 "RESET-TMR online/active/old-count/new-count = %d/%d/%d/%d.\n",
2167 vha->flags.online, qla2x00_reset_active(vha),
7c3f8fd1 2168 mcmd->reset_count, qpair->chip_reset);
b6a029e1 2169 ha->tgt.tgt_ops->free_mcmd(mcmd);
82de802a 2170 spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
b6a029e1
AE
2171 return;
2172 }
2173
726b8548
QT
2174 if (mcmd->flags == QLA24XX_MGMT_SEND_NACK) {
2175 if (mcmd->orig_iocb.imm_ntfy.u.isp24.status_subcode ==
41dc529a
QT
2176 ELS_LOGO ||
2177 mcmd->orig_iocb.imm_ntfy.u.isp24.status_subcode ==
2178 ELS_PRLO ||
2179 mcmd->orig_iocb.imm_ntfy.u.isp24.status_subcode ==
2180 ELS_TPRLO) {
83548fe2 2181 ql_dbg(ql_dbg_disc, vha, 0x2106,
726b8548
QT
2182 "TM response logo %phC status %#x state %#x",
2183 mcmd->sess->port_name, mcmd->fc_tm_rsp,
2184 mcmd->flags);
2185 qlt_schedule_sess_for_deletion_lock(mcmd->sess);
2186 } else {
82de802a
QT
2187 qlt_send_notify_ack(vha->hw->base_qpair,
2188 &mcmd->orig_iocb.imm_ntfy, 0, 0, 0, 0, 0, 0);
726b8548
QT
2189 }
2190 } else {
d7236ac3 2191 if (mcmd->orig_iocb.atio.u.raw.entry_type == ABTS_RECV_24XX)
82de802a 2192 qlt_24xx_send_abts_resp(qpair, &mcmd->orig_iocb.abts,
2d70c103
NB
2193 mcmd->fc_tm_rsp, false);
2194 else
82de802a 2195 qlt_24xx_send_task_mgmt_ctio(qpair, mcmd,
2d70c103
NB
2196 mcmd->fc_tm_rsp);
2197 }
2198 /*
2199 * Make the callback for ->free_mcmd() to queue_work() and invoke
2200 * target_put_sess_cmd() to drop cmd_kref to 1. The final
2201 * target_put_sess_cmd() call will be made from TFO->check_stop_free()
2202 * -> tcm_qla2xxx_check_stop_free() to release the TMR associated se_cmd
2203 * descriptor after TFO->queue_tm_rsp() -> tcm_qla2xxx_queue_tm_rsp() ->
2204 * qlt_xmit_tm_rsp() returns here..
2205 */
2206 ha->tgt.tgt_ops->free_mcmd(mcmd);
82de802a 2207 spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
2d70c103
NB
2208}
2209EXPORT_SYMBOL(qlt_xmit_tm_rsp);
2210
2211/* No locks */
2212static int qlt_pci_map_calc_cnt(struct qla_tgt_prm *prm)
2213{
2214 struct qla_tgt_cmd *cmd = prm->cmd;
2215
2216 BUG_ON(cmd->sg_cnt == 0);
2217
2218 prm->sg = (struct scatterlist *)cmd->sg;
8abfa9e2 2219 prm->seg_cnt = pci_map_sg(cmd->qpair->pdev, cmd->sg,
2d70c103
NB
2220 cmd->sg_cnt, cmd->dma_data_direction);
2221 if (unlikely(prm->seg_cnt == 0))
2222 goto out_err;
2223
2224 prm->cmd->sg_mapped = 1;
2225
f83adb61
QT
2226 if (cmd->se_cmd.prot_op == TARGET_PROT_NORMAL) {
2227 /*
2228 * If greater than four sg entries then we need to allocate
2229 * the continuation entries
2230 */
2231 if (prm->seg_cnt > prm->tgt->datasegs_per_cmd)
2232 prm->req_cnt += DIV_ROUND_UP(prm->seg_cnt -
2233 prm->tgt->datasegs_per_cmd,
2234 prm->tgt->datasegs_per_cont);
2235 } else {
2236 /* DIF */
2237 if ((cmd->se_cmd.prot_op == TARGET_PROT_DIN_INSERT) ||
2238 (cmd->se_cmd.prot_op == TARGET_PROT_DOUT_STRIP)) {
2239 prm->seg_cnt = DIV_ROUND_UP(cmd->bufflen, cmd->blk_sz);
2240 prm->tot_dsds = prm->seg_cnt;
2241 } else
2242 prm->tot_dsds = prm->seg_cnt;
2243
2244 if (cmd->prot_sg_cnt) {
2245 prm->prot_sg = cmd->prot_sg;
8abfa9e2 2246 prm->prot_seg_cnt = pci_map_sg(cmd->qpair->pdev,
f83adb61
QT
2247 cmd->prot_sg, cmd->prot_sg_cnt,
2248 cmd->dma_data_direction);
2249 if (unlikely(prm->prot_seg_cnt == 0))
2250 goto out_err;
2251
2252 if ((cmd->se_cmd.prot_op == TARGET_PROT_DIN_INSERT) ||
2253 (cmd->se_cmd.prot_op == TARGET_PROT_DOUT_STRIP)) {
2254 /* Dif Bundling not support here */
2255 prm->prot_seg_cnt = DIV_ROUND_UP(cmd->bufflen,
2256 cmd->blk_sz);
2257 prm->tot_dsds += prm->prot_seg_cnt;
2258 } else
2259 prm->tot_dsds += prm->prot_seg_cnt;
2260 }
2261 }
2d70c103 2262
2d70c103
NB
2263 return 0;
2264
2265out_err:
22d84726 2266 ql_dbg_qp(ql_dbg_tgt, prm->cmd->qpair, 0xe04d,
2d70c103
NB
2267 "qla_target(%d): PCI mapping failed: sg_cnt=%d",
2268 0, prm->cmd->sg_cnt);
2269 return -1;
2270}
2271
f9b6721a 2272static void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
2d70c103 2273{
8abfa9e2
QT
2274 struct qla_hw_data *ha;
2275 struct qla_qpair *qpair;
f9b6721a
JE
2276 if (!cmd->sg_mapped)
2277 return;
2278
8abfa9e2
QT
2279 qpair = cmd->qpair;
2280
2281 pci_unmap_sg(qpair->pdev, cmd->sg, cmd->sg_cnt,
2282 cmd->dma_data_direction);
2d70c103 2283 cmd->sg_mapped = 0;
f83adb61
QT
2284
2285 if (cmd->prot_sg_cnt)
8abfa9e2 2286 pci_unmap_sg(qpair->pdev, cmd->prot_sg, cmd->prot_sg_cnt,
f83adb61
QT
2287 cmd->dma_data_direction);
2288
d5ff0eed
JC
2289 if (!cmd->ctx)
2290 return;
8abfa9e2 2291 ha = vha->hw;
f83adb61 2292 if (cmd->ctx_dsd_alloced)
d5ff0eed 2293 qla2x00_clean_dsd_pool(ha, cmd->ctx);
f83adb61 2294
d5ff0eed 2295 dma_pool_free(ha->dl_dma_pool, cmd->ctx, cmd->ctx->crc_ctx_dma);
2d70c103
NB
2296}
2297
82de802a 2298static int qlt_check_reserve_free_req(struct qla_qpair *qpair,
2d70c103
NB
2299 uint32_t req_cnt)
2300{
d63b328f 2301 uint32_t cnt;
82de802a 2302 struct req_que *req = qpair->req;
2d70c103 2303
82de802a 2304 if (req->cnt < (req_cnt + 2)) {
af7bb382
QT
2305 cnt = (uint16_t)(qpair->use_shadow_reg ? *req->out_ptr :
2306 RD_REG_DWORD_RELAXED(req->req_q_out));
2d70c103 2307
82de802a
QT
2308 if (req->ring_index < cnt)
2309 req->cnt = cnt - req->ring_index;
2d70c103 2310 else
82de802a 2311 req->cnt = req->length - (req->ring_index - cnt);
2d70c103 2312
82de802a 2313 if (unlikely(req->cnt < (req_cnt + 2)))
bc7095a9 2314 return -EAGAIN;
2d70c103 2315 }
bc7095a9 2316
82de802a 2317 req->cnt -= req_cnt;
2d70c103
NB
2318
2319 return 0;
2320}
2321
2322/*
2323 * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
2324 */
82de802a 2325static inline void *qlt_get_req_pkt(struct req_que *req)
2d70c103
NB
2326{
2327 /* Adjust ring index. */
82de802a
QT
2328 req->ring_index++;
2329 if (req->ring_index == req->length) {
2330 req->ring_index = 0;
2331 req->ring_ptr = req->ring;
2d70c103 2332 } else {
82de802a 2333 req->ring_ptr++;
2d70c103 2334 }
82de802a 2335 return (cont_entry_t *)req->ring_ptr;
2d70c103
NB
2336}
2337
2338/* ha->hardware_lock supposed to be held on entry */
82de802a 2339static inline uint32_t qlt_make_handle(struct qla_qpair *qpair)
2d70c103 2340{
2d70c103 2341 uint32_t h;
c5419e26
QT
2342 int index;
2343 uint8_t found = 0;
82de802a 2344 struct req_que *req = qpair->req;
c5419e26
QT
2345
2346 h = req->current_outstanding_cmd;
2d70c103 2347
c5419e26
QT
2348 for (index = 1; index < req->num_outstanding_cmds; index++) {
2349 h++;
2350 if (h == req->num_outstanding_cmds)
2351 h = 1;
2352
2353 if (h == QLA_TGT_SKIP_HANDLE)
2354 continue;
2355
2356 if (!req->outstanding_cmds[h]) {
2357 found = 1;
2d70c103
NB
2358 break;
2359 }
c5419e26 2360 }
2d70c103 2361
c5419e26
QT
2362 if (found) {
2363 req->current_outstanding_cmd = h;
2364 } else {
8abfa9e2
QT
2365 ql_dbg(ql_dbg_io, qpair->vha, 0x305b,
2366 "qla_target(%d): Ran out of empty cmd slots\n",
2367 qpair->vha->vp_idx);
c5419e26
QT
2368 h = QLA_TGT_NULL_HANDLE;
2369 }
2d70c103
NB
2370
2371 return h;
2372}
2373
2374/* ha->hardware_lock supposed to be held on entry */
82de802a
QT
2375static int qlt_24xx_build_ctio_pkt(struct qla_qpair *qpair,
2376 struct qla_tgt_prm *prm)
2d70c103
NB
2377{
2378 uint32_t h;
2379 struct ctio7_to_24xx *pkt;
2d70c103 2380 struct atio_from_isp *atio = &prm->cmd->atio;
33a5fcee 2381 uint16_t temp;
2d70c103 2382
82de802a 2383 pkt = (struct ctio7_to_24xx *)qpair->req->ring_ptr;
2d70c103
NB
2384 prm->pkt = pkt;
2385 memset(pkt, 0, sizeof(*pkt));
2386
2387 pkt->entry_type = CTIO_TYPE7;
2388 pkt->entry_count = (uint8_t)prm->req_cnt;
22d84726 2389 pkt->vp_index = prm->cmd->vp_idx;
2d70c103 2390
82de802a 2391 h = qlt_make_handle(qpair);
2d70c103
NB
2392 if (unlikely(h == QLA_TGT_NULL_HANDLE)) {
2393 /*
2394 * CTIO type 7 from the firmware doesn't provide a way to
2395 * know the initiator's LOOP ID, hence we can't find
2396 * the session and, so, the command.
2397 */
2398 return -EAGAIN;
e326d22a
QT
2399 } else
2400 qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd;
2d70c103 2401
82de802a
QT
2402 pkt->handle = MAKE_HANDLE(qpair->req->id, h);
2403 pkt->handle |= CTIO_COMPLETION_HANDLE_MARK;
2404 pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id);
ad950360 2405 pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
2d70c103
NB
2406 pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
2407 pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
2408 pkt->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
2409 pkt->exchange_addr = atio->u.isp24.exchange_addr;
f7e761f5
QT
2410 temp = atio->u.isp24.attr << 9;
2411 pkt->u.status0.flags |= cpu_to_le16(temp);
33a5fcee
QT
2412 temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
2413 pkt->u.status0.ox_id = cpu_to_le16(temp);
2d70c103
NB
2414 pkt->u.status0.relative_offset = cpu_to_le32(prm->cmd->offset);
2415
2d70c103
NB
2416 return 0;
2417}
2418
2419/*
2420 * ha->hardware_lock supposed to be held on entry. We have already made sure
2421 * that there is sufficient amount of request entries to not drop it.
2422 */
2423static void qlt_load_cont_data_segments(struct qla_tgt_prm *prm,
2424 struct scsi_qla_host *vha)
2425{
2426 int cnt;
2427 uint32_t *dword_ptr;
2428 int enable_64bit_addressing = prm->tgt->tgt_enable_64bit_addr;
2429
2430 /* Build continuation packets */
2431 while (prm->seg_cnt > 0) {
2432 cont_a64_entry_t *cont_pkt64 =
82de802a
QT
2433 (cont_a64_entry_t *)qlt_get_req_pkt(
2434 prm->cmd->qpair->req);
2d70c103
NB
2435
2436 /*
2437 * Make sure that from cont_pkt64 none of
2438 * 64-bit specific fields used for 32-bit
2439 * addressing. Cast to (cont_entry_t *) for
2440 * that.
2441 */
2442
2443 memset(cont_pkt64, 0, sizeof(*cont_pkt64));
2444
2445 cont_pkt64->entry_count = 1;
2446 cont_pkt64->sys_define = 0;
2447
2448 if (enable_64bit_addressing) {
2449 cont_pkt64->entry_type = CONTINUE_A64_TYPE;
2450 dword_ptr =
2451 (uint32_t *)&cont_pkt64->dseg_0_address;
2452 } else {
2453 cont_pkt64->entry_type = CONTINUE_TYPE;
2454 dword_ptr =
2455 (uint32_t *)&((cont_entry_t *)
2456 cont_pkt64)->dseg_0_address;
2457 }
2458
2459 /* Load continuation entry data segments */
2460 for (cnt = 0;
2461 cnt < prm->tgt->datasegs_per_cont && prm->seg_cnt;
2462 cnt++, prm->seg_cnt--) {
2463 *dword_ptr++ =
2464 cpu_to_le32(pci_dma_lo32
2465 (sg_dma_address(prm->sg)));
2466 if (enable_64bit_addressing) {
2467 *dword_ptr++ =
2468 cpu_to_le32(pci_dma_hi32
2469 (sg_dma_address
2470 (prm->sg)));
2471 }
2472 *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg));
2473
2d70c103
NB
2474 prm->sg = sg_next(prm->sg);
2475 }
2476 }
2477}
2478
2479/*
2480 * ha->hardware_lock supposed to be held on entry. We have already made sure
2481 * that there is sufficient amount of request entries to not drop it.
2482 */
2483static void qlt_load_data_segments(struct qla_tgt_prm *prm,
2484 struct scsi_qla_host *vha)
2485{
2486 int cnt;
2487 uint32_t *dword_ptr;
2488 int enable_64bit_addressing = prm->tgt->tgt_enable_64bit_addr;
2489 struct ctio7_to_24xx *pkt24 = (struct ctio7_to_24xx *)prm->pkt;
2490
2d70c103
NB
2491 pkt24->u.status0.transfer_length = cpu_to_le32(prm->cmd->bufflen);
2492
2493 /* Setup packet address segment pointer */
2494 dword_ptr = pkt24->u.status0.dseg_0_address;
2495
2496 /* Set total data segment count */
2497 if (prm->seg_cnt)
2498 pkt24->dseg_count = cpu_to_le16(prm->seg_cnt);
2499
2500 if (prm->seg_cnt == 0) {
2501 /* No data transfer */
2502 *dword_ptr++ = 0;
2503 *dword_ptr = 0;
2504 return;
2505 }
2506
2507 /* If scatter gather */
2d70c103
NB
2508
2509 /* Load command entry data segments */
2510 for (cnt = 0;
2511 (cnt < prm->tgt->datasegs_per_cmd) && prm->seg_cnt;
2512 cnt++, prm->seg_cnt--) {
2513 *dword_ptr++ =
2514 cpu_to_le32(pci_dma_lo32(sg_dma_address(prm->sg)));
2515 if (enable_64bit_addressing) {
2516 *dword_ptr++ =
2517 cpu_to_le32(pci_dma_hi32(
2518 sg_dma_address(prm->sg)));
2519 }
2520 *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg));
2521
2d70c103
NB
2522 prm->sg = sg_next(prm->sg);
2523 }
2524
2525 qlt_load_cont_data_segments(prm, vha);
2526}
2527
2528static inline int qlt_has_data(struct qla_tgt_cmd *cmd)
2529{
2530 return cmd->bufflen > 0;
2531}
2532
be25152c
QT
2533static void qlt_print_dif_err(struct qla_tgt_prm *prm)
2534{
2535 struct qla_tgt_cmd *cmd;
2536 struct scsi_qla_host *vha;
2537
2538 /* asc 0x10=dif error */
2539 if (prm->sense_buffer && (prm->sense_buffer[12] == 0x10)) {
2540 cmd = prm->cmd;
2541 vha = cmd->vha;
2542 /* ASCQ */
2543 switch (prm->sense_buffer[13]) {
2544 case 1:
83548fe2 2545 ql_dbg(ql_dbg_tgt_dif, vha, 0xe00b,
be25152c
QT
2546 "BE detected Guard TAG ERR: lba[0x%llx|%lld] len[0x%x] "
2547 "se_cmd=%p tag[%x]",
2548 cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
2549 cmd->atio.u.isp24.exchange_addr);
2550 break;
2551 case 2:
83548fe2 2552 ql_dbg(ql_dbg_tgt_dif, vha, 0xe00c,
be25152c
QT
2553 "BE detected APP TAG ERR: lba[0x%llx|%lld] len[0x%x] "
2554 "se_cmd=%p tag[%x]",
2555 cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
2556 cmd->atio.u.isp24.exchange_addr);
2557 break;
2558 case 3:
83548fe2 2559 ql_dbg(ql_dbg_tgt_dif, vha, 0xe00f,
be25152c
QT
2560 "BE detected REF TAG ERR: lba[0x%llx|%lld] len[0x%x] "
2561 "se_cmd=%p tag[%x]",
2562 cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
2563 cmd->atio.u.isp24.exchange_addr);
2564 break;
2565 default:
83548fe2 2566 ql_dbg(ql_dbg_tgt_dif, vha, 0xe010,
be25152c
QT
2567 "BE detected Dif ERR: lba[%llx|%lld] len[%x] "
2568 "se_cmd=%p tag[%x]",
2569 cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
2570 cmd->atio.u.isp24.exchange_addr);
2571 break;
2572 }
83548fe2 2573 ql_dump_buffer(ql_dbg_tgt_dif, vha, 0xe011, cmd->cdb, 16);
be25152c
QT
2574 }
2575}
2576
2d70c103
NB
2577/*
2578 * Called without ha->hardware_lock held
2579 */
2580static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd,
2581 struct qla_tgt_prm *prm, int xmit_type, uint8_t scsi_status,
2582 uint32_t *full_req_cnt)
2583{
2d70c103 2584 struct se_cmd *se_cmd = &cmd->se_cmd;
22d84726 2585 struct qla_qpair *qpair = cmd->qpair;
2d70c103 2586
2d70c103 2587 prm->cmd = cmd;
7c3f8fd1
QT
2588 prm->tgt = cmd->tgt;
2589 prm->pkt = NULL;
2d70c103
NB
2590 prm->rq_result = scsi_status;
2591 prm->sense_buffer = &cmd->sense_buffer[0];
2592 prm->sense_buffer_len = TRANSPORT_SENSE_BUFFER;
2593 prm->sg = NULL;
2594 prm->seg_cnt = -1;
2595 prm->req_cnt = 1;
7c3f8fd1 2596 prm->residual = 0;
2d70c103 2597 prm->add_status_pkt = 0;
7c3f8fd1
QT
2598 prm->prot_sg = NULL;
2599 prm->prot_seg_cnt = 0;
2600 prm->tot_dsds = 0;
2d70c103 2601
2d70c103
NB
2602 if ((xmit_type & QLA_TGT_XMIT_DATA) && qlt_has_data(cmd)) {
2603 if (qlt_pci_map_calc_cnt(prm) != 0)
2604 return -EAGAIN;
2605 }
2606
2607 *full_req_cnt = prm->req_cnt;
2608
2609 if (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
2610 prm->residual = se_cmd->residual_count;
22d84726 2611 ql_dbg_qp(ql_dbg_io + ql_dbg_verbose, qpair, 0x305c,
649ee054
BVA
2612 "Residual underflow: %d (tag %lld, op %x, bufflen %d, rq_result %x)\n",
2613 prm->residual, se_cmd->tag,
2614 se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0,
2615 cmd->bufflen, prm->rq_result);
2d70c103
NB
2616 prm->rq_result |= SS_RESIDUAL_UNDER;
2617 } else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
2618 prm->residual = se_cmd->residual_count;
22d84726 2619 ql_dbg_qp(ql_dbg_io, qpair, 0x305d,
649ee054
BVA
2620 "Residual overflow: %d (tag %lld, op %x, bufflen %d, rq_result %x)\n",
2621 prm->residual, se_cmd->tag, se_cmd->t_task_cdb ?
2622 se_cmd->t_task_cdb[0] : 0, cmd->bufflen, prm->rq_result);
2d70c103
NB
2623 prm->rq_result |= SS_RESIDUAL_OVER;
2624 }
2625
2626 if (xmit_type & QLA_TGT_XMIT_STATUS) {
2627 /*
2628 * If QLA_TGT_XMIT_DATA is not set, add_status_pkt will be
2629 * ignored in *xmit_response() below
2630 */
2631 if (qlt_has_data(cmd)) {
2632 if (QLA_TGT_SENSE_VALID(prm->sense_buffer) ||
7c3f8fd1 2633 (IS_FWI2_CAPABLE(cmd->vha->hw) &&
2d70c103
NB
2634 (prm->rq_result != 0))) {
2635 prm->add_status_pkt = 1;
2636 (*full_req_cnt)++;
2637 }
2638 }
2639 }
2640
2d70c103
NB
2641 return 0;
2642}
2643
7c3f8fd1
QT
2644static inline int qlt_need_explicit_conf(struct qla_tgt_cmd *cmd,
2645 int sending_sense)
2d70c103 2646{
7c3f8fd1 2647 if (cmd->qpair->enable_class_2)
2d70c103
NB
2648 return 0;
2649
2650 if (sending_sense)
2651 return cmd->conf_compl_supported;
2652 else
7c3f8fd1
QT
2653 return cmd->qpair->enable_explicit_conf &&
2654 cmd->conf_compl_supported;
2d70c103
NB
2655}
2656
2d70c103
NB
2657static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
2658 struct qla_tgt_prm *prm)
2659{
2660 prm->sense_buffer_len = min_t(uint32_t, prm->sense_buffer_len,
2661 (uint32_t)sizeof(ctio->u.status1.sense_data));
ad950360 2662 ctio->u.status0.flags |= cpu_to_le16(CTIO7_FLAGS_SEND_STATUS);
7c3f8fd1 2663 if (qlt_need_explicit_conf(prm->cmd, 0)) {
ad950360 2664 ctio->u.status0.flags |= cpu_to_le16(
2d70c103
NB
2665 CTIO7_FLAGS_EXPLICIT_CONFORM |
2666 CTIO7_FLAGS_CONFORM_REQ);
2667 }
2668 ctio->u.status0.residual = cpu_to_le32(prm->residual);
2669 ctio->u.status0.scsi_status = cpu_to_le16(prm->rq_result);
2670 if (QLA_TGT_SENSE_VALID(prm->sense_buffer)) {
2671 int i;
2672
7c3f8fd1 2673 if (qlt_need_explicit_conf(prm->cmd, 1)) {
df2e32c5 2674 if ((prm->rq_result & SS_SCSI_STATUS_BYTE) != 0) {
22d84726 2675 ql_dbg_qp(ql_dbg_tgt, prm->cmd->qpair, 0xe017,
2d70c103
NB
2676 "Skipping EXPLICIT_CONFORM and "
2677 "CTIO7_FLAGS_CONFORM_REQ for FCP READ w/ "
2678 "non GOOD status\n");
2679 goto skip_explict_conf;
2680 }
ad950360 2681 ctio->u.status1.flags |= cpu_to_le16(
2d70c103
NB
2682 CTIO7_FLAGS_EXPLICIT_CONFORM |
2683 CTIO7_FLAGS_CONFORM_REQ);
2684 }
2685skip_explict_conf:
2686 ctio->u.status1.flags &=
ad950360 2687 ~cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0);
2d70c103 2688 ctio->u.status1.flags |=
ad950360 2689 cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1);
2d70c103 2690 ctio->u.status1.scsi_status |=
ad950360 2691 cpu_to_le16(SS_SENSE_LEN_VALID);
2d70c103
NB
2692 ctio->u.status1.sense_length =
2693 cpu_to_le16(prm->sense_buffer_len);
2694 for (i = 0; i < prm->sense_buffer_len/4; i++)
2695 ((uint32_t *)ctio->u.status1.sense_data)[i] =
2696 cpu_to_be32(((uint32_t *)prm->sense_buffer)[i]);
be25152c
QT
2697
2698 qlt_print_dif_err(prm);
2699
2d70c103
NB
2700 } else {
2701 ctio->u.status1.flags &=
ad950360 2702 ~cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0);
2d70c103 2703 ctio->u.status1.flags |=
ad950360 2704 cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1);
2d70c103
NB
2705 ctio->u.status1.sense_length = 0;
2706 memset(ctio->u.status1.sense_data, 0,
2707 sizeof(ctio->u.status1.sense_data));
2708 }
2709
2710 /* Sense with len > 24, is it possible ??? */
2711}
2712
f83adb61
QT
2713static inline int
2714qlt_hba_err_chk_enabled(struct se_cmd *se_cmd)
2715{
f83adb61
QT
2716 switch (se_cmd->prot_op) {
2717 case TARGET_PROT_DOUT_INSERT:
2718 case TARGET_PROT_DIN_STRIP:
2719 if (ql2xenablehba_err_chk >= 1)
2720 return 1;
2721 break;
2722 case TARGET_PROT_DOUT_PASS:
2723 case TARGET_PROT_DIN_PASS:
2724 if (ql2xenablehba_err_chk >= 2)
2725 return 1;
2726 break;
2727 case TARGET_PROT_DIN_INSERT:
2728 case TARGET_PROT_DOUT_STRIP:
2729 return 1;
2730 default:
2731 break;
2732 }
2733 return 0;
2734}
2735
be25152c
QT
2736static inline int
2737qla_tgt_ref_mask_check(struct se_cmd *se_cmd)
2738{
2739 switch (se_cmd->prot_op) {
2740 case TARGET_PROT_DIN_INSERT:
2741 case TARGET_PROT_DOUT_INSERT:
2742 case TARGET_PROT_DIN_STRIP:
2743 case TARGET_PROT_DOUT_STRIP:
2744 case TARGET_PROT_DIN_PASS:
2745 case TARGET_PROT_DOUT_PASS:
2746 return 1;
2747 default:
2748 return 0;
2749 }
2750 return 0;
2751}
2752
f83adb61 2753/*
be25152c 2754 * qla_tgt_set_dif_tags - Extract Ref and App tags from SCSI command
f83adb61 2755 */
be25152c
QT
2756static void
2757qla_tgt_set_dif_tags(struct qla_tgt_cmd *cmd, struct crc_context *ctx,
2758 uint16_t *pfw_prot_opts)
f83adb61 2759{
be25152c 2760 struct se_cmd *se_cmd = &cmd->se_cmd;
f83adb61 2761 uint32_t lba = 0xffffffff & se_cmd->t_task_lba;
be25152c
QT
2762 scsi_qla_host_t *vha = cmd->tgt->vha;
2763 struct qla_hw_data *ha = vha->hw;
2764 uint32_t t32 = 0;
f83adb61 2765
be25152c
QT
2766 /*
2767 * wait till Mode Sense/Select cmd, modepage Ah, subpage 2
f83adb61
QT
2768 * have been immplemented by TCM, before AppTag is avail.
2769 * Look for modesense_handlers[]
2770 */
c7ee3bd4 2771 ctx->app_tag = 0;
f83adb61
QT
2772 ctx->app_tag_mask[0] = 0x0;
2773 ctx->app_tag_mask[1] = 0x0;
2774
be25152c
QT
2775 if (IS_PI_UNINIT_CAPABLE(ha)) {
2776 if ((se_cmd->prot_type == TARGET_DIF_TYPE1_PROT) ||
2777 (se_cmd->prot_type == TARGET_DIF_TYPE2_PROT))
2778 *pfw_prot_opts |= PO_DIS_VALD_APP_ESC;
2779 else if (se_cmd->prot_type == TARGET_DIF_TYPE3_PROT)
2780 *pfw_prot_opts |= PO_DIS_VALD_APP_REF_ESC;
2781 }
2782
2783 t32 = ha->tgt.tgt_ops->get_dif_tags(cmd, pfw_prot_opts);
2784
f83adb61
QT
2785 switch (se_cmd->prot_type) {
2786 case TARGET_DIF_TYPE0_PROT:
2787 /*
be25152c
QT
2788 * No check for ql2xenablehba_err_chk, as it
2789 * would be an I/O error if hba tag generation
2790 * is not done.
f83adb61
QT
2791 */
2792 ctx->ref_tag = cpu_to_le32(lba);
f83adb61
QT
2793 /* enable ALL bytes of the ref tag */
2794 ctx->ref_tag_mask[0] = 0xff;
2795 ctx->ref_tag_mask[1] = 0xff;
2796 ctx->ref_tag_mask[2] = 0xff;
2797 ctx->ref_tag_mask[3] = 0xff;
2798 break;
f83adb61 2799 case TARGET_DIF_TYPE1_PROT:
be25152c
QT
2800 /*
2801 * For TYPE 1 protection: 16 bit GUARD tag, 32 bit
2802 * REF tag, and 16 bit app tag.
2803 */
2804 ctx->ref_tag = cpu_to_le32(lba);
2805 if (!qla_tgt_ref_mask_check(se_cmd) ||
2806 !(ha->tgt.tgt_ops->chk_dif_tags(t32))) {
2807 *pfw_prot_opts |= PO_DIS_REF_TAG_VALD;
2808 break;
2809 }
2810 /* enable ALL bytes of the ref tag */
2811 ctx->ref_tag_mask[0] = 0xff;
2812 ctx->ref_tag_mask[1] = 0xff;
2813 ctx->ref_tag_mask[2] = 0xff;
2814 ctx->ref_tag_mask[3] = 0xff;
2815 break;
f83adb61 2816 case TARGET_DIF_TYPE2_PROT:
be25152c
QT
2817 /*
2818 * For TYPE 2 protection: 16 bit GUARD + 32 bit REF
2819 * tag has to match LBA in CDB + N
2820 */
2821 ctx->ref_tag = cpu_to_le32(lba);
2822 if (!qla_tgt_ref_mask_check(se_cmd) ||
2823 !(ha->tgt.tgt_ops->chk_dif_tags(t32))) {
2824 *pfw_prot_opts |= PO_DIS_REF_TAG_VALD;
2825 break;
2826 }
2827 /* enable ALL bytes of the ref tag */
2828 ctx->ref_tag_mask[0] = 0xff;
2829 ctx->ref_tag_mask[1] = 0xff;
2830 ctx->ref_tag_mask[2] = 0xff;
2831 ctx->ref_tag_mask[3] = 0xff;
2832 break;
f83adb61 2833 case TARGET_DIF_TYPE3_PROT:
be25152c
QT
2834 /* For TYPE 3 protection: 16 bit GUARD only */
2835 *pfw_prot_opts |= PO_DIS_REF_TAG_VALD;
2836 ctx->ref_tag_mask[0] = ctx->ref_tag_mask[1] =
2837 ctx->ref_tag_mask[2] = ctx->ref_tag_mask[3] = 0x00;
2838 break;
f83adb61
QT
2839 }
2840}
2841
f83adb61 2842static inline int
82de802a 2843qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm)
f83adb61
QT
2844{
2845 uint32_t *cur_dsd;
f83adb61
QT
2846 uint32_t transfer_length = 0;
2847 uint32_t data_bytes;
2848 uint32_t dif_bytes;
2849 uint8_t bundling = 1;
2850 uint8_t *clr_ptr;
2851 struct crc_context *crc_ctx_pkt = NULL;
2852 struct qla_hw_data *ha;
2853 struct ctio_crc2_to_fw *pkt;
2854 dma_addr_t crc_ctx_dma;
2855 uint16_t fw_prot_opts = 0;
2856 struct qla_tgt_cmd *cmd = prm->cmd;
2857 struct se_cmd *se_cmd = &cmd->se_cmd;
2858 uint32_t h;
2859 struct atio_from_isp *atio = &prm->cmd->atio;
be25152c 2860 struct qla_tc_param tc;
c7ee3bd4 2861 uint16_t t16;
82de802a 2862 scsi_qla_host_t *vha = cmd->vha;
f83adb61 2863
f83adb61
QT
2864 ha = vha->hw;
2865
82de802a 2866 pkt = (struct ctio_crc2_to_fw *)qpair->req->ring_ptr;
f83adb61
QT
2867 prm->pkt = pkt;
2868 memset(pkt, 0, sizeof(*pkt));
2869
22d84726 2870 ql_dbg_qp(ql_dbg_tgt, cmd->qpair, 0xe071,
f83adb61 2871 "qla_target(%d):%s: se_cmd[%p] CRC2 prot_op[0x%x] cmd prot sg:cnt[%p:%x] lba[%llu]\n",
22d84726 2872 cmd->vp_idx, __func__, se_cmd, se_cmd->prot_op,
f83adb61
QT
2873 prm->prot_sg, prm->prot_seg_cnt, se_cmd->t_task_lba);
2874
2875 if ((se_cmd->prot_op == TARGET_PROT_DIN_INSERT) ||
2876 (se_cmd->prot_op == TARGET_PROT_DOUT_STRIP))
2877 bundling = 0;
2878
2879 /* Compute dif len and adjust data len to incude protection */
2880 data_bytes = cmd->bufflen;
2881 dif_bytes = (data_bytes / cmd->blk_sz) * 8;
2882
2883 switch (se_cmd->prot_op) {
2884 case TARGET_PROT_DIN_INSERT:
2885 case TARGET_PROT_DOUT_STRIP:
2886 transfer_length = data_bytes;
be25152c
QT
2887 if (cmd->prot_sg_cnt)
2888 data_bytes += dif_bytes;
f83adb61 2889 break;
f83adb61
QT
2890 case TARGET_PROT_DIN_STRIP:
2891 case TARGET_PROT_DOUT_INSERT:
2892 case TARGET_PROT_DIN_PASS:
2893 case TARGET_PROT_DOUT_PASS:
2894 transfer_length = data_bytes + dif_bytes;
2895 break;
f83adb61
QT
2896 default:
2897 BUG();
2898 break;
2899 }
2900
2901 if (!qlt_hba_err_chk_enabled(se_cmd))
2902 fw_prot_opts |= 0x10; /* Disable Guard tag checking */
2903 /* HBA error checking enabled */
2904 else if (IS_PI_UNINIT_CAPABLE(ha)) {
2905 if ((se_cmd->prot_type == TARGET_DIF_TYPE1_PROT) ||
2906 (se_cmd->prot_type == TARGET_DIF_TYPE2_PROT))
2907 fw_prot_opts |= PO_DIS_VALD_APP_ESC;
2908 else if (se_cmd->prot_type == TARGET_DIF_TYPE3_PROT)
2909 fw_prot_opts |= PO_DIS_VALD_APP_REF_ESC;
2910 }
2911
2912 switch (se_cmd->prot_op) {
2913 case TARGET_PROT_DIN_INSERT:
2914 case TARGET_PROT_DOUT_INSERT:
2915 fw_prot_opts |= PO_MODE_DIF_INSERT;
2916 break;
2917 case TARGET_PROT_DIN_STRIP:
2918 case TARGET_PROT_DOUT_STRIP:
2919 fw_prot_opts |= PO_MODE_DIF_REMOVE;
2920 break;
2921 case TARGET_PROT_DIN_PASS:
2922 case TARGET_PROT_DOUT_PASS:
2923 fw_prot_opts |= PO_MODE_DIF_PASS;
2924 /* FUTURE: does tcm require T10CRC<->IPCKSUM conversion? */
2925 break;
2926 default:/* Normal Request */
2927 fw_prot_opts |= PO_MODE_DIF_PASS;
2928 break;
2929 }
2930
f83adb61
QT
2931 /* ---- PKT ---- */
2932 /* Update entry type to indicate Command Type CRC_2 IOCB */
2933 pkt->entry_type = CTIO_CRC2;
2934 pkt->entry_count = 1;
22d84726 2935 pkt->vp_index = cmd->vp_idx;
f83adb61 2936
82de802a 2937 h = qlt_make_handle(qpair);
f83adb61
QT
2938 if (unlikely(h == QLA_TGT_NULL_HANDLE)) {
2939 /*
2940 * CTIO type 7 from the firmware doesn't provide a way to
2941 * know the initiator's LOOP ID, hence we can't find
2942 * the session and, so, the command.
2943 */
2944 return -EAGAIN;
2945 } else
82de802a 2946 qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd;
f83adb61 2947
82de802a
QT
2948 pkt->handle = MAKE_HANDLE(qpair->req->id, h);
2949 pkt->handle |= CTIO_COMPLETION_HANDLE_MARK;
be25152c 2950 pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id);
ad950360 2951 pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
f83adb61
QT
2952 pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
2953 pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
2954 pkt->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
2955 pkt->exchange_addr = atio->u.isp24.exchange_addr;
c7ee3bd4
QT
2956
2957 /* silence compile warning */
2958 t16 = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
2959 pkt->ox_id = cpu_to_le16(t16);
2960
2961 t16 = (atio->u.isp24.attr << 9);
2962 pkt->flags |= cpu_to_le16(t16);
f83adb61
QT
2963 pkt->relative_offset = cpu_to_le32(prm->cmd->offset);
2964
2965 /* Set transfer direction */
2966 if (cmd->dma_data_direction == DMA_TO_DEVICE)
ad950360 2967 pkt->flags = cpu_to_le16(CTIO7_FLAGS_DATA_IN);
f83adb61 2968 else if (cmd->dma_data_direction == DMA_FROM_DEVICE)
ad950360 2969 pkt->flags = cpu_to_le16(CTIO7_FLAGS_DATA_OUT);
f83adb61 2970
f83adb61
QT
2971 pkt->dseg_count = prm->tot_dsds;
2972 /* Fibre channel byte count */
2973 pkt->transfer_length = cpu_to_le32(transfer_length);
2974
f83adb61
QT
2975 /* ----- CRC context -------- */
2976
2977 /* Allocate CRC context from global pool */
2978 crc_ctx_pkt = cmd->ctx =
2979 dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC, &crc_ctx_dma);
2980
2981 if (!crc_ctx_pkt)
2982 goto crc_queuing_error;
2983
2984 /* Zero out CTX area. */
2985 clr_ptr = (uint8_t *)crc_ctx_pkt;
2986 memset(clr_ptr, 0, sizeof(*crc_ctx_pkt));
2987
2988 crc_ctx_pkt->crc_ctx_dma = crc_ctx_dma;
2989 INIT_LIST_HEAD(&crc_ctx_pkt->dsd_list);
2990
2991 /* Set handle */
2992 crc_ctx_pkt->handle = pkt->handle;
2993
be25152c 2994 qla_tgt_set_dif_tags(cmd, crc_ctx_pkt, &fw_prot_opts);
f83adb61
QT
2995
2996 pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma));
2997 pkt->crc_context_address[1] = cpu_to_le32(MSD(crc_ctx_dma));
2998 pkt->crc_context_len = CRC_CONTEXT_LEN_FW;
2999
f83adb61
QT
3000 if (!bundling) {
3001 cur_dsd = (uint32_t *) &crc_ctx_pkt->u.nobundling.data_address;
3002 } else {
3003 /*
3004 * Configure Bundling if we need to fetch interlaving
3005 * protection PCI accesses
3006 */
3007 fw_prot_opts |= PO_ENABLE_DIF_BUNDLING;
3008 crc_ctx_pkt->u.bundling.dif_byte_count = cpu_to_le32(dif_bytes);
3009 crc_ctx_pkt->u.bundling.dseg_count =
3010 cpu_to_le16(prm->tot_dsds - prm->prot_seg_cnt);
3011 cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.data_address;
3012 }
3013
3014 /* Finish the common fields of CRC pkt */
3015 crc_ctx_pkt->blk_size = cpu_to_le16(cmd->blk_sz);
3016 crc_ctx_pkt->prot_opts = cpu_to_le16(fw_prot_opts);
3017 crc_ctx_pkt->byte_count = cpu_to_le32(data_bytes);
ad950360 3018 crc_ctx_pkt->guard_seed = cpu_to_le16(0);
f83adb61 3019
be25152c
QT
3020 memset((uint8_t *)&tc, 0 , sizeof(tc));
3021 tc.vha = vha;
3022 tc.blk_sz = cmd->blk_sz;
3023 tc.bufflen = cmd->bufflen;
3024 tc.sg = cmd->sg;
3025 tc.prot_sg = cmd->prot_sg;
3026 tc.ctx = crc_ctx_pkt;
3027 tc.ctx_dsd_alloced = &cmd->ctx_dsd_alloced;
f83adb61
QT
3028
3029 /* Walks data segments */
ad950360 3030 pkt->flags |= cpu_to_le16(CTIO7_FLAGS_DSD_PTR);
f83adb61
QT
3031
3032 if (!bundling && prm->prot_seg_cnt) {
3033 if (qla24xx_walk_and_build_sglist_no_difb(ha, NULL, cur_dsd,
be25152c 3034 prm->tot_dsds, &tc))
f83adb61
QT
3035 goto crc_queuing_error;
3036 } else if (qla24xx_walk_and_build_sglist(ha, NULL, cur_dsd,
be25152c 3037 (prm->tot_dsds - prm->prot_seg_cnt), &tc))
f83adb61
QT
3038 goto crc_queuing_error;
3039
3040 if (bundling && prm->prot_seg_cnt) {
3041 /* Walks dif segments */
c7ee3bd4 3042 pkt->add_flags |= CTIO_CRC2_AF_DIF_DSD_ENA;
f83adb61
QT
3043
3044 cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address;
3045 if (qla24xx_walk_and_build_prot_sglist(ha, NULL, cur_dsd,
be25152c 3046 prm->prot_seg_cnt, &tc))
f83adb61
QT
3047 goto crc_queuing_error;
3048 }
3049 return QLA_SUCCESS;
3050
3051crc_queuing_error:
3052 /* Cleanup will be performed by the caller */
82de802a 3053 qpair->req->outstanding_cmds[h] = NULL;
f83adb61
QT
3054
3055 return QLA_FUNCTION_FAILED;
3056}
3057
2d70c103
NB
3058/*
3059 * Callback to setup response of xmit_type of QLA_TGT_XMIT_DATA and *
3060 * QLA_TGT_XMIT_STATUS for >= 24xx silicon
3061 */
3062int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
3063 uint8_t scsi_status)
3064{
3065 struct scsi_qla_host *vha = cmd->vha;
82de802a 3066 struct qla_qpair *qpair = cmd->qpair;
2d70c103
NB
3067 struct ctio7_to_24xx *pkt;
3068 struct qla_tgt_prm prm;
3069 uint32_t full_req_cnt = 0;
3070 unsigned long flags = 0;
3071 int res;
3072
726b8548 3073 if (cmd->sess && cmd->sess->deleted) {
a6ca8878
AP
3074 cmd->state = QLA_TGT_STATE_PROCESSED;
3075 if (cmd->sess->logout_completed)
3076 /* no need to terminate. FW already freed exchange. */
3077 qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
3078 else
82de802a 3079 qlt_send_term_exchange(qpair, cmd, &cmd->atio, 0, 0);
a6ca8878
AP
3080 return 0;
3081 }
a6ca8878 3082
22d84726 3083 ql_dbg_qp(ql_dbg_tgt, qpair, 0xe018,
82de802a 3084 "is_send_status=%d, cmd->bufflen=%d, cmd->sg_cnt=%d, cmd->dma_data_direction=%d se_cmd[%p] qp %d\n",
f83adb61
QT
3085 (xmit_type & QLA_TGT_XMIT_STATUS) ?
3086 1 : 0, cmd->bufflen, cmd->sg_cnt, cmd->dma_data_direction,
82de802a 3087 &cmd->se_cmd, qpair->id);
2d70c103
NB
3088
3089 res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status,
3090 &full_req_cnt);
3091 if (unlikely(res != 0)) {
2d70c103
NB
3092 return res;
3093 }
3094
82de802a 3095 spin_lock_irqsave(qpair->qp_lock_ptr, flags);
2d70c103 3096
ce1025cd
HM
3097 if (xmit_type == QLA_TGT_XMIT_STATUS)
3098 vha->tgt_counters.core_qla_snd_status++;
3099 else
3100 vha->tgt_counters.core_qla_que_buf++;
3101
7c3f8fd1 3102 if (!qpair->fw_started || cmd->reset_count != qpair->chip_reset) {
b6a029e1 3103 /*
3bb67df5 3104 * Either the port is not online or this request was from
b6a029e1
AE
3105 * previous life, just abort the processing.
3106 */
3107 cmd->state = QLA_TGT_STATE_PROCESSED;
3108 qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
22d84726 3109 ql_dbg_qp(ql_dbg_async, qpair, 0xe101,
3bb67df5
DKU
3110 "RESET-RSP online/active/old-count/new-count = %d/%d/%d/%d.\n",
3111 vha->flags.online, qla2x00_reset_active(vha),
7c3f8fd1 3112 cmd->reset_count, qpair->chip_reset);
82de802a 3113 spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
b6a029e1
AE
3114 return 0;
3115 }
3116
2d70c103 3117 /* Does F/W have an IOCBs for this request */
82de802a 3118 res = qlt_check_reserve_free_req(qpair, full_req_cnt);
2d70c103
NB
3119 if (unlikely(res))
3120 goto out_unmap_unlock;
3121
f83adb61 3122 if (cmd->se_cmd.prot_op && (xmit_type & QLA_TGT_XMIT_DATA))
82de802a 3123 res = qlt_build_ctio_crc2_pkt(qpair, &prm);
f83adb61 3124 else
82de802a 3125 res = qlt_24xx_build_ctio_pkt(qpair, &prm);
810e30bc 3126 if (unlikely(res != 0)) {
82de802a 3127 qpair->req->cnt += full_req_cnt;
2d70c103 3128 goto out_unmap_unlock;
810e30bc 3129 }
2d70c103
NB
3130
3131 pkt = (struct ctio7_to_24xx *)prm.pkt;
3132
3133 if (qlt_has_data(cmd) && (xmit_type & QLA_TGT_XMIT_DATA)) {
3134 pkt->u.status0.flags |=
ad950360 3135 cpu_to_le16(CTIO7_FLAGS_DATA_IN |
2d70c103
NB
3136 CTIO7_FLAGS_STATUS_MODE_0);
3137
f83adb61
QT
3138 if (cmd->se_cmd.prot_op == TARGET_PROT_NORMAL)
3139 qlt_load_data_segments(&prm, vha);
2d70c103
NB
3140
3141 if (prm.add_status_pkt == 0) {
3142 if (xmit_type & QLA_TGT_XMIT_STATUS) {
3143 pkt->u.status0.scsi_status =
3144 cpu_to_le16(prm.rq_result);
3145 pkt->u.status0.residual =
3146 cpu_to_le32(prm.residual);
ad950360 3147 pkt->u.status0.flags |= cpu_to_le16(
2d70c103 3148 CTIO7_FLAGS_SEND_STATUS);
7c3f8fd1 3149 if (qlt_need_explicit_conf(cmd, 0)) {
2d70c103 3150 pkt->u.status0.flags |=
ad950360 3151 cpu_to_le16(
2d70c103
NB
3152 CTIO7_FLAGS_EXPLICIT_CONFORM |
3153 CTIO7_FLAGS_CONFORM_REQ);
3154 }
3155 }
3156
3157 } else {
3158 /*
3159 * We have already made sure that there is sufficient
3160 * amount of request entries to not drop HW lock in
3161 * req_pkt().
3162 */
3163 struct ctio7_to_24xx *ctio =
82de802a
QT
3164 (struct ctio7_to_24xx *)qlt_get_req_pkt(
3165 qpair->req);
2d70c103 3166
22d84726 3167 ql_dbg_qp(ql_dbg_tgt, qpair, 0x305e,
667024a3
AE
3168 "Building additional status packet 0x%p.\n",
3169 ctio);
2d70c103 3170
f83adb61
QT
3171 /*
3172 * T10Dif: ctio_crc2_to_fw overlay ontop of
3173 * ctio7_to_24xx
3174 */
2d70c103 3175 memcpy(ctio, pkt, sizeof(*ctio));
f83adb61 3176 /* reset back to CTIO7 */
2d70c103 3177 ctio->entry_count = 1;
f83adb61 3178 ctio->entry_type = CTIO_TYPE7;
2d70c103 3179 ctio->dseg_count = 0;
ad950360 3180 ctio->u.status1.flags &= ~cpu_to_le16(
2d70c103
NB
3181 CTIO7_FLAGS_DATA_IN);
3182
3183 /* Real finish is ctio_m1's finish */
3184 pkt->handle |= CTIO_INTERMEDIATE_HANDLE_MARK;
ad950360 3185 pkt->u.status0.flags |= cpu_to_le16(
2d70c103 3186 CTIO7_FLAGS_DONT_RET_CTIO);
f83adb61
QT
3187
3188 /* qlt_24xx_init_ctio_to_isp will correct
3189 * all neccessary fields that's part of CTIO7.
3190 * There should be no residual of CTIO-CRC2 data.
3191 */
2d70c103
NB
3192 qlt_24xx_init_ctio_to_isp((struct ctio7_to_24xx *)ctio,
3193 &prm);
2d70c103
NB
3194 }
3195 } else
3196 qlt_24xx_init_ctio_to_isp(pkt, &prm);
3197
3198
3199 cmd->state = QLA_TGT_STATE_PROCESSED; /* Mid-level is done processing */
d564a372 3200 cmd->cmd_sent_to_fw = 1;
2d70c103 3201
63163e06
HM
3202 /* Memory Barrier */
3203 wmb();
8abfa9e2
QT
3204 if (qpair->reqq_start_iocbs)
3205 qpair->reqq_start_iocbs(qpair);
3206 else
3207 qla2x00_start_iocbs(vha, qpair->req);
82de802a 3208 spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
2d70c103
NB
3209
3210 return 0;
3211
3212out_unmap_unlock:
f9b6721a 3213 qlt_unmap_sg(vha, cmd);
82de802a 3214 spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
2d70c103
NB
3215
3216 return res;
3217}
3218EXPORT_SYMBOL(qlt_xmit_response);
3219
3220int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
3221{
3222 struct ctio7_to_24xx *pkt;
3223 struct scsi_qla_host *vha = cmd->vha;
2d70c103
NB
3224 struct qla_tgt *tgt = cmd->tgt;
3225 struct qla_tgt_prm prm;
82de802a 3226 unsigned long flags = 0;
2d70c103 3227 int res = 0;
82de802a 3228 struct qla_qpair *qpair = cmd->qpair;
2d70c103
NB
3229
3230 memset(&prm, 0, sizeof(prm));
3231 prm.cmd = cmd;
3232 prm.tgt = tgt;
3233 prm.sg = NULL;
3234 prm.req_cnt = 1;
3235
2d70c103
NB
3236 /* Calculate number of entries and segments required */
3237 if (qlt_pci_map_calc_cnt(&prm) != 0)
3238 return -EAGAIN;
3239
7c3f8fd1 3240 if (!qpair->fw_started || (cmd->reset_count != qpair->chip_reset) ||
726b8548 3241 (cmd->sess && cmd->sess->deleted)) {
b6a029e1 3242 /*
3bb67df5 3243 * Either the port is not online or this request was from
b6a029e1
AE
3244 * previous life, just abort the processing.
3245 */
3246 cmd->state = QLA_TGT_STATE_NEED_DATA;
3247 qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
22d84726 3248 ql_dbg_qp(ql_dbg_async, qpair, 0xe102,
3bb67df5
DKU
3249 "RESET-XFR online/active/old-count/new-count = %d/%d/%d/%d.\n",
3250 vha->flags.online, qla2x00_reset_active(vha),
7c3f8fd1 3251 cmd->reset_count, qpair->chip_reset);
b6a029e1
AE
3252 return 0;
3253 }
3254
82de802a 3255 spin_lock_irqsave(qpair->qp_lock_ptr, flags);
2d70c103 3256 /* Does F/W have an IOCBs for this request */
82de802a 3257 res = qlt_check_reserve_free_req(qpair, prm.req_cnt);
2d70c103
NB
3258 if (res != 0)
3259 goto out_unlock_free_unmap;
f83adb61 3260 if (cmd->se_cmd.prot_op)
82de802a 3261 res = qlt_build_ctio_crc2_pkt(qpair, &prm);
f83adb61 3262 else
82de802a 3263 res = qlt_24xx_build_ctio_pkt(qpair, &prm);
2d70c103 3264
810e30bc 3265 if (unlikely(res != 0)) {
82de802a 3266 qpair->req->cnt += prm.req_cnt;
2d70c103 3267 goto out_unlock_free_unmap;
810e30bc
QT
3268 }
3269
2d70c103 3270 pkt = (struct ctio7_to_24xx *)prm.pkt;
ad950360 3271 pkt->u.status0.flags |= cpu_to_le16(CTIO7_FLAGS_DATA_OUT |
2d70c103 3272 CTIO7_FLAGS_STATUS_MODE_0);
f83adb61
QT
3273
3274 if (cmd->se_cmd.prot_op == TARGET_PROT_NORMAL)
3275 qlt_load_data_segments(&prm, vha);
2d70c103
NB
3276
3277 cmd->state = QLA_TGT_STATE_NEED_DATA;
d564a372 3278 cmd->cmd_sent_to_fw = 1;
2d70c103 3279
63163e06
HM
3280 /* Memory Barrier */
3281 wmb();
8abfa9e2
QT
3282 if (qpair->reqq_start_iocbs)
3283 qpair->reqq_start_iocbs(qpair);
3284 else
3285 qla2x00_start_iocbs(vha, qpair->req);
82de802a 3286 spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
2d70c103
NB
3287
3288 return res;
3289
3290out_unlock_free_unmap:
f9b6721a 3291 qlt_unmap_sg(vha, cmd);
82de802a 3292 spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
2d70c103
NB
3293
3294 return res;
3295}
3296EXPORT_SYMBOL(qlt_rdy_to_xfer);
3297
f83adb61
QT
3298
3299/*
be25152c 3300 * it is assumed either hardware_lock or qpair lock is held.
f83adb61 3301 */
be25152c 3302static void
8abfa9e2 3303qlt_handle_dif_error(struct qla_qpair *qpair, struct qla_tgt_cmd *cmd,
be25152c 3304 struct ctio_crc_from_fw *sts)
f83adb61
QT
3305{
3306 uint8_t *ap = &sts->actual_dif[0];
3307 uint8_t *ep = &sts->expected_dif[0];
f83adb61 3308 uint64_t lba = cmd->se_cmd.t_task_lba;
be25152c
QT
3309 uint8_t scsi_status, sense_key, asc, ascq;
3310 unsigned long flags;
8abfa9e2 3311 struct scsi_qla_host *vha = cmd->vha;
f83adb61 3312
be25152c 3313 cmd->trc_flags |= TRC_DIF_ERR;
f83adb61 3314
be25152c
QT
3315 cmd->a_guard = be16_to_cpu(*(uint16_t *)(ap + 0));
3316 cmd->a_app_tag = be16_to_cpu(*(uint16_t *)(ap + 2));
3317 cmd->a_ref_tag = be32_to_cpu(*(uint32_t *)(ap + 4));
f83adb61 3318
be25152c
QT
3319 cmd->e_guard = be16_to_cpu(*(uint16_t *)(ep + 0));
3320 cmd->e_app_tag = be16_to_cpu(*(uint16_t *)(ep + 2));
3321 cmd->e_ref_tag = be32_to_cpu(*(uint32_t *)(ep + 4));
f83adb61 3322
be25152c
QT
3323 ql_dbg(ql_dbg_tgt_dif, vha, 0xf075,
3324 "%s: aborted %d state %d\n", __func__, cmd->aborted, cmd->state);
f83adb61 3325
be25152c 3326 scsi_status = sense_key = asc = ascq = 0;
f83adb61 3327
be25152c
QT
3328 /* check appl tag */
3329 if (cmd->e_app_tag != cmd->a_app_tag) {
83548fe2
QT
3330 ql_dbg(ql_dbg_tgt_dif, vha, 0xe00d,
3331 "App Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] Ref[%x|%x], App[%x|%x], Guard [%x|%x] cmd=%p ox_id[%04x]",
3332 cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
3333 cmd->a_ref_tag, cmd->e_ref_tag, cmd->a_app_tag,
3334 cmd->e_app_tag, cmd->a_guard, cmd->e_guard, cmd,
3335 cmd->atio.u.isp24.fcp_hdr.ox_id);
be25152c
QT
3336
3337 cmd->dif_err_code = DIF_ERR_APP;
3338 scsi_status = SAM_STAT_CHECK_CONDITION;
3339 sense_key = ABORTED_COMMAND;
3340 asc = 0x10;
3341 ascq = 0x2;
f83adb61
QT
3342 }
3343
3344 /* check ref tag */
be25152c 3345 if (cmd->e_ref_tag != cmd->a_ref_tag) {
83548fe2
QT
3346 ql_dbg(ql_dbg_tgt_dif, vha, 0xe00e,
3347 "Ref Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] Ref[%x|%x], App[%x|%x], Guard[%x|%x] cmd=%p ox_id[%04x] ",
3348 cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
3349 cmd->a_ref_tag, cmd->e_ref_tag, cmd->a_app_tag,
3350 cmd->e_app_tag, cmd->a_guard, cmd->e_guard, cmd,
3351 cmd->atio.u.isp24.fcp_hdr.ox_id);
be25152c
QT
3352
3353 cmd->dif_err_code = DIF_ERR_REF;
3354 scsi_status = SAM_STAT_CHECK_CONDITION;
3355 sense_key = ABORTED_COMMAND;
3356 asc = 0x10;
3357 ascq = 0x3;
f83adb61
QT
3358 goto out;
3359 }
3360
be25152c
QT
3361 /* check guard */
3362 if (cmd->e_guard != cmd->a_guard) {
83548fe2
QT
3363 ql_dbg(ql_dbg_tgt_dif, vha, 0xe012,
3364 "Guard ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] Ref[%x|%x], App[%x|%x], Guard [%x|%x] cmd=%p ox_id[%04x]",
3365 cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
3366 cmd->a_ref_tag, cmd->e_ref_tag, cmd->a_app_tag,
3367 cmd->e_app_tag, cmd->a_guard, cmd->e_guard, cmd,
3368 cmd->atio.u.isp24.fcp_hdr.ox_id);
3369
be25152c
QT
3370 cmd->dif_err_code = DIF_ERR_GRD;
3371 scsi_status = SAM_STAT_CHECK_CONDITION;
3372 sense_key = ABORTED_COMMAND;
3373 asc = 0x10;
3374 ascq = 0x1;
f83adb61
QT
3375 }
3376out:
be25152c
QT
3377 switch (cmd->state) {
3378 case QLA_TGT_STATE_NEED_DATA:
3379 /* handle_data will load DIF error code */
3380 cmd->state = QLA_TGT_STATE_DATA_IN;
3381 vha->hw->tgt.tgt_ops->handle_data(cmd);
3382 break;
3383 default:
3384 spin_lock_irqsave(&cmd->cmd_lock, flags);
3385 if (cmd->aborted) {
3386 spin_unlock_irqrestore(&cmd->cmd_lock, flags);
3387 vha->hw->tgt.tgt_ops->free_cmd(cmd);
3388 break;
3389 }
3390 spin_unlock_irqrestore(&cmd->cmd_lock, flags);
f83adb61 3391
8abfa9e2
QT
3392 qlt_send_resp_ctio(qpair, cmd, scsi_status, sense_key, asc,
3393 ascq);
be25152c
QT
3394 /* assume scsi status gets out on the wire.
3395 * Will not wait for completion.
3396 */
3397 vha->hw->tgt.tgt_ops->free_cmd(cmd);
3398 break;
3399 }
3400}
f83adb61 3401
a6ca8878
AP
3402/* If hardware_lock held on entry, might drop it, then reaquire */
3403/* This function sends the appropriate CTIO to ISP 2xxx or 24xx */
3404static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha,
3405 struct imm_ntfy_from_isp *ntfy)
3406{
3407 struct nack_to_isp *nack;
3408 struct qla_hw_data *ha = vha->hw;
3409 request_t *pkt;
3410 int ret = 0;
3411
3412 ql_dbg(ql_dbg_tgt_tmr, vha, 0xe01c,
3413 "Sending TERM ELS CTIO (ha=%p)\n", ha);
3414
ec7193e2 3415 pkt = (request_t *)qla2x00_alloc_iocbs(vha, NULL);
a6ca8878
AP
3416 if (pkt == NULL) {
3417 ql_dbg(ql_dbg_tgt, vha, 0xe080,
3418 "qla_target(%d): %s failed: unable to allocate "
3419 "request packet\n", vha->vp_idx, __func__);
3420 return -ENOMEM;
3421 }
3422
3423 pkt->entry_type = NOTIFY_ACK_TYPE;
3424 pkt->entry_count = 1;
4f060736 3425 pkt->handle = QLA_TGT_SKIP_HANDLE;
a6ca8878
AP
3426
3427 nack = (struct nack_to_isp *)pkt;
3428 nack->ox_id = ntfy->ox_id;
3429
3430 nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle;
3431 if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) {
3432 nack->u.isp24.flags = ntfy->u.isp24.flags &
3433 __constant_cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB);
3434 }
3435
3436 /* terminate */
3437 nack->u.isp24.flags |=
3438 __constant_cpu_to_le16(NOTIFY_ACK_FLAGS_TERMINATE);
3439
3440 nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id;
3441 nack->u.isp24.status = ntfy->u.isp24.status;
3442 nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode;
3443 nack->u.isp24.fw_handle = ntfy->u.isp24.fw_handle;
3444 nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address;
3445 nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs;
3446 nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui;
3447 nack->u.isp24.vp_index = ntfy->u.isp24.vp_index;
3448
3449 qla2x00_start_iocbs(vha, vha->req);
3450 return ret;
3451}
3452
3453static void qlt_send_term_imm_notif(struct scsi_qla_host *vha,
3454 struct imm_ntfy_from_isp *imm, int ha_locked)
3455{
3456 unsigned long flags = 0;
3457 int rc;
3458
a6ca8878
AP
3459 if (ha_locked) {
3460 rc = __qlt_send_term_imm_notif(vha, imm);
3461
3462#if 0 /* Todo */
3463 if (rc == -ENOMEM)
3464 qlt_alloc_qfull_cmd(vha, imm, 0, 0);
91f42b33
BVA
3465#else
3466 if (rc) {
3467 }
a6ca8878
AP
3468#endif
3469 goto done;
3470 }
3471
3472 spin_lock_irqsave(&vha->hw->hardware_lock, flags);
3473 rc = __qlt_send_term_imm_notif(vha, imm);
3474
3475#if 0 /* Todo */
3476 if (rc == -ENOMEM)
3477 qlt_alloc_qfull_cmd(vha, imm, 0, 0);
3478#endif
3479
3480done:
3481 if (!ha_locked)
3482 spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
3483}
3484
83548fe2
QT
3485/*
3486 * If hardware_lock held on entry, might drop it, then reaquire
3487 * This function sends the appropriate CTIO to ISP 2xxx or 24xx
3488 */
82de802a 3489static int __qlt_send_term_exchange(struct qla_qpair *qpair,
2d70c103
NB
3490 struct qla_tgt_cmd *cmd,
3491 struct atio_from_isp *atio)
3492{
82de802a 3493 struct scsi_qla_host *vha = qpair->vha;
2d70c103
NB
3494 struct ctio7_to_24xx *ctio24;
3495 struct qla_hw_data *ha = vha->hw;
3496 request_t *pkt;
3497 int ret = 0;
33a5fcee 3498 uint16_t temp;
2d70c103 3499
83548fe2 3500 ql_dbg(ql_dbg_tgt, vha, 0xe009, "Sending TERM EXCH CTIO (ha=%p)\n", ha);
2d70c103 3501
82de802a 3502 pkt = (request_t *)qla2x00_alloc_iocbs_ready(qpair, NULL);
2d70c103
NB
3503 if (pkt == NULL) {
3504 ql_dbg(ql_dbg_tgt, vha, 0xe050,
3505 "qla_target(%d): %s failed: unable to allocate "
3506 "request packet\n", vha->vp_idx, __func__);
3507 return -ENOMEM;
3508 }
3509
3510 if (cmd != NULL) {
3511 if (cmd->state < QLA_TGT_STATE_PROCESSED) {
3512 ql_dbg(ql_dbg_tgt, vha, 0xe051,
3513 "qla_target(%d): Terminating cmd %p with "
3514 "incorrect state %d\n", vha->vp_idx, cmd,
3515 cmd->state);
3516 } else
3517 ret = 1;
3518 }
3519
ce1025cd 3520 vha->tgt_counters.num_term_xchg_sent++;
2d70c103
NB
3521 pkt->entry_count = 1;
3522 pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
3523
3524 ctio24 = (struct ctio7_to_24xx *)pkt;
3525 ctio24->entry_type = CTIO_TYPE7;
71cdc079 3526 ctio24->nport_handle = CTIO7_NHANDLE_UNRECOGNIZED;
ad950360 3527 ctio24->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
2d70c103
NB
3528 ctio24->vp_index = vha->vp_idx;
3529 ctio24->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
3530 ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
3531 ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
3532 ctio24->exchange_addr = atio->u.isp24.exchange_addr;
f7e761f5
QT
3533 temp = (atio->u.isp24.attr << 9) | CTIO7_FLAGS_STATUS_MODE_1 |
3534 CTIO7_FLAGS_TERMINATE;
3535 ctio24->u.status1.flags = cpu_to_le16(temp);
33a5fcee
QT
3536 temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
3537 ctio24->u.status1.ox_id = cpu_to_le16(temp);
2d70c103
NB
3538
3539 /* Most likely, it isn't needed */
3540 ctio24->u.status1.residual = get_unaligned((uint32_t *)
3541 &atio->u.isp24.fcp_cmnd.add_cdb[
3542 atio->u.isp24.fcp_cmnd.add_cdb_len]);
3543 if (ctio24->u.status1.residual != 0)
3544 ctio24->u.status1.scsi_status |= SS_RESIDUAL_UNDER;
3545
63163e06
HM
3546 /* Memory Barrier */
3547 wmb();
8abfa9e2
QT
3548 if (qpair->reqq_start_iocbs)
3549 qpair->reqq_start_iocbs(qpair);
3550 else
3551 qla2x00_start_iocbs(vha, qpair->req);
2d70c103
NB
3552 return ret;
3553}
3554
82de802a 3555static void qlt_send_term_exchange(struct qla_qpair *qpair,
a07100e0
QT
3556 struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked,
3557 int ul_abort)
2d70c103 3558{
82de802a 3559 struct scsi_qla_host *vha;
6bc85dd5 3560 unsigned long flags = 0;
2d70c103
NB
3561 int rc;
3562
82de802a
QT
3563 /* why use different vha? NPIV */
3564 if (cmd)
3565 vha = cmd->vha;
3566 else
3567 vha = qpair->vha;
2d70c103
NB
3568
3569 if (ha_locked) {
82de802a 3570 rc = __qlt_send_term_exchange(qpair, cmd, atio);
33e79977
QT
3571 if (rc == -ENOMEM)
3572 qlt_alloc_qfull_cmd(vha, atio, 0, 0);
2d70c103
NB
3573 goto done;
3574 }
82de802a
QT
3575 spin_lock_irqsave(qpair->qp_lock_ptr, flags);
3576 rc = __qlt_send_term_exchange(qpair, cmd, atio);
33e79977
QT
3577 if (rc == -ENOMEM)
3578 qlt_alloc_qfull_cmd(vha, atio, 0, 0);
d564a372 3579
2d70c103 3580done:
a07100e0 3581 if (cmd && !ul_abort && !cmd->aborted) {
6bc85dd5
HM
3582 if (cmd->sg_mapped)
3583 qlt_unmap_sg(vha, cmd);
2d70c103
NB
3584 vha->hw->tgt.tgt_ops->free_cmd(cmd);
3585 }
6bc85dd5
HM
3586
3587 if (!ha_locked)
82de802a 3588 spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
6bc85dd5 3589
7b898542 3590 return;
2d70c103
NB
3591}
3592
33e79977
QT
3593static void qlt_init_term_exchange(struct scsi_qla_host *vha)
3594{
3595 struct list_head free_list;
3596 struct qla_tgt_cmd *cmd, *tcmd;
3597
3598 vha->hw->tgt.leak_exchg_thresh_hold =
03e8c680 3599 (vha->hw->cur_fw_xcb_count/100) * LEAK_EXCHG_THRESH_HOLD_PERCENT;
33e79977
QT
3600
3601 cmd = tcmd = NULL;
3602 if (!list_empty(&vha->hw->tgt.q_full_list)) {
3603 INIT_LIST_HEAD(&free_list);
3604 list_splice_init(&vha->hw->tgt.q_full_list, &free_list);
3605
3606 list_for_each_entry_safe(cmd, tcmd, &free_list, cmd_list) {
3607 list_del(&cmd->cmd_list);
3608 /* This cmd was never sent to TCM. There is no need
3609 * to schedule free or call free_cmd
3610 */
3611 qlt_free_cmd(cmd);
3612 vha->hw->tgt.num_qfull_cmds_alloc--;
3613 }
3614 }
3615 vha->hw->tgt.num_qfull_cmds_dropped = 0;
3616}
3617
3618static void qlt_chk_exch_leak_thresh_hold(struct scsi_qla_host *vha)
3619{
3620 uint32_t total_leaked;
3621
3622 total_leaked = vha->hw->tgt.num_qfull_cmds_dropped;
3623
3624 if (vha->hw->tgt.leak_exchg_thresh_hold &&
3625 (total_leaked > vha->hw->tgt.leak_exchg_thresh_hold)) {
3626
3627 ql_dbg(ql_dbg_tgt, vha, 0xe079,
3628 "Chip reset due to exchange starvation: %d/%d.\n",
03e8c680 3629 total_leaked, vha->hw->cur_fw_xcb_count);
33e79977
QT
3630
3631 if (IS_P3P_TYPE(vha->hw))
3632 set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
3633 else
3634 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
3635 qla2xxx_wake_dpc(vha);
3636 }
3637
3638}
3639
a07100e0 3640int qlt_abort_cmd(struct qla_tgt_cmd *cmd)
7359df25
AP
3641{
3642 struct qla_tgt *tgt = cmd->tgt;
3643 struct scsi_qla_host *vha = tgt->vha;
3644 struct se_cmd *se_cmd = &cmd->se_cmd;
a07100e0 3645 unsigned long flags;
7359df25
AP
3646
3647 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014,
3648 "qla_target(%d): terminating exchange for aborted cmd=%p "
3649 "(se_cmd=%p, tag=%llu)", vha->vp_idx, cmd, &cmd->se_cmd,
3650 se_cmd->tag);
3651
a07100e0
QT
3652 spin_lock_irqsave(&cmd->cmd_lock, flags);
3653 if (cmd->aborted) {
3654 spin_unlock_irqrestore(&cmd->cmd_lock, flags);
3655 /*
3656 * It's normal to see 2 calls in this path:
3657 * 1) XFER Rdy completion + CMD_T_ABORT
3658 * 2) TCM TMR - drain_state_list
3659 */
83548fe2
QT
3660 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf016,
3661 "multiple abort. %p transport_state %x, t_state %x, "
3662 "se_cmd_flags %x\n", cmd, cmd->se_cmd.transport_state,
3663 cmd->se_cmd.t_state, cmd->se_cmd.se_cmd_flags);
a07100e0
QT
3664 return EIO;
3665 }
193b50b9 3666 cmd->aborted = 1;
1eb42f96 3667 cmd->trc_flags |= TRC_ABORT;
a07100e0 3668 spin_unlock_irqrestore(&cmd->cmd_lock, flags);
7359df25 3669
82de802a 3670 qlt_send_term_exchange(cmd->qpair, cmd, &cmd->atio, 0, 1);
a07100e0 3671 return 0;
7359df25
AP
3672}
3673EXPORT_SYMBOL(qlt_abort_cmd);
3674
2d70c103
NB
3675void qlt_free_cmd(struct qla_tgt_cmd *cmd)
3676{
5d964837 3677 struct fc_port *sess = cmd->sess;
51a07f84 3678
f83adb61
QT
3679 ql_dbg(ql_dbg_tgt, cmd->vha, 0xe074,
3680 "%s: se_cmd[%p] ox_id %04x\n",
3681 __func__, &cmd->se_cmd,
3682 be16_to_cpu(cmd->atio.u.isp24.fcp_hdr.ox_id));
2d70c103 3683
e07f8f65
SK
3684 BUG_ON(cmd->cmd_in_wq);
3685
a07100e0
QT
3686 if (cmd->sg_mapped)
3687 qlt_unmap_sg(cmd->vha, cmd);
3688
33e79977
QT
3689 if (!cmd->q_full)
3690 qlt_decr_num_pend_cmds(cmd->vha);
3691
f83adb61 3692 BUG_ON(cmd->sg_mapped);
e07f8f65 3693 cmd->jiffies_at_free = get_jiffies_64();
2d70c103
NB
3694 if (unlikely(cmd->free_sg))
3695 kfree(cmd->sg);
51a07f84
NB
3696
3697 if (!sess || !sess->se_sess) {
3698 WARN_ON(1);
3699 return;
3700 }
e07f8f65 3701 cmd->jiffies_at_free = get_jiffies_64();
51a07f84 3702 percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
2d70c103
NB
3703}
3704EXPORT_SYMBOL(qlt_free_cmd);
3705
2d70c103
NB
3706/*
3707 * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
3708 */
82de802a 3709static int qlt_term_ctio_exchange(struct qla_qpair *qpair, void *ctio,
2d70c103
NB
3710 struct qla_tgt_cmd *cmd, uint32_t status)
3711{
3712 int term = 0;
82de802a 3713 struct scsi_qla_host *vha = qpair->vha;
2d70c103 3714
be25152c 3715 if (cmd->se_cmd.prot_op)
83548fe2 3716 ql_dbg(ql_dbg_tgt_dif, vha, 0xe013,
be25152c
QT
3717 "Term DIF cmd: lba[0x%llx|%lld] len[0x%x] "
3718 "se_cmd=%p tag[%x] op %#x/%s",
3719 cmd->lba, cmd->lba,
3720 cmd->num_blks, &cmd->se_cmd,
3721 cmd->atio.u.isp24.exchange_addr,
3722 cmd->se_cmd.prot_op,
3723 prot_op_str(cmd->se_cmd.prot_op));
3724
2d70c103
NB
3725 if (ctio != NULL) {
3726 struct ctio7_from_24xx *c = (struct ctio7_from_24xx *)ctio;
3727 term = !(c->flags &
ad950360 3728 cpu_to_le16(OF_TERM_EXCH));
2d70c103
NB
3729 } else
3730 term = 1;
3731
3732 if (term)
82de802a 3733 qlt_term_ctio_exchange(qpair, ctio, cmd, status);
2d70c103
NB
3734
3735 return term;
3736}
3737
2d70c103
NB
3738
3739/* ha->hardware_lock supposed to be held on entry */
3740static struct qla_tgt_cmd *qlt_ctio_to_cmd(struct scsi_qla_host *vha,
82de802a 3741 struct rsp_que *rsp, uint32_t handle, void *ctio)
2d70c103
NB
3742{
3743 struct qla_tgt_cmd *cmd = NULL;
82de802a
QT
3744 struct req_que *req;
3745 int qid = GET_QID(handle);
3746 uint32_t h = handle & ~QLA_TGT_HANDLE_MASK;
2d70c103 3747
82de802a
QT
3748 if (unlikely(h == QLA_TGT_SKIP_HANDLE))
3749 return NULL;
2d70c103 3750
82de802a
QT
3751 if (qid == rsp->req->id) {
3752 req = rsp->req;
3753 } else if (vha->hw->req_q_map[qid]) {
3754 ql_dbg(ql_dbg_tgt_mgt, vha, 0x1000a,
3755 "qla_target(%d): CTIO completion with different QID %d handle %x\n",
3756 vha->vp_idx, rsp->id, handle);
3757 req = vha->hw->req_q_map[qid];
3758 } else {
3759 return NULL;
3760 }
667024a3 3761
82de802a 3762 h &= QLA_CMD_HANDLE_MASK;
c5419e26 3763
82de802a
QT
3764 if (h != QLA_TGT_NULL_HANDLE) {
3765 if (unlikely(h > req->num_outstanding_cmds)) {
2d70c103
NB
3766 ql_dbg(ql_dbg_tgt, vha, 0xe052,
3767 "qla_target(%d): Wrong handle %x received\n",
3768 vha->vp_idx, handle);
3769 return NULL;
3770 }
82de802a
QT
3771
3772 cmd = (struct qla_tgt_cmd *)req->outstanding_cmds[h];
3773 if (unlikely(cmd == NULL)) {
c5419e26 3774 ql_dbg(ql_dbg_async, vha, 0xe053,
82de802a
QT
3775 "qla_target(%d): Suspicious: unable to find the command with handle %x req->id %d rsp->id %d\n",
3776 vha->vp_idx, handle, req->id, rsp->id);
2d70c103
NB
3777 return NULL;
3778 }
82de802a 3779 req->outstanding_cmds[h] = NULL;
2d70c103
NB
3780 } else if (ctio != NULL) {
3781 /* We can't get loop ID from CTIO7 */
3782 ql_dbg(ql_dbg_tgt, vha, 0xe054,
3783 "qla_target(%d): Wrong CTIO received: QLA24xx doesn't "
3784 "support NULL handles\n", vha->vp_idx);
3785 return NULL;
3786 }
3787
3788 return cmd;
3789}
3790
c0cb4496 3791/* hardware_lock should be held by caller. */
c5419e26 3792void
c0cb4496
AE
3793qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
3794{
3795 struct qla_hw_data *ha = vha->hw;
c0cb4496
AE
3796
3797 if (cmd->sg_mapped)
3798 qlt_unmap_sg(vha, cmd);
3799
c0cb4496
AE
3800 /* TODO: fix debug message type and ids. */
3801 if (cmd->state == QLA_TGT_STATE_PROCESSED) {
3802 ql_dbg(ql_dbg_io, vha, 0xff00,
82de802a 3803 "HOST-ABORT: state=PROCESSED.\n");
c0cb4496
AE
3804 } else if (cmd->state == QLA_TGT_STATE_NEED_DATA) {
3805 cmd->write_data_transferred = 0;
3806 cmd->state = QLA_TGT_STATE_DATA_IN;
3807
3808 ql_dbg(ql_dbg_io, vha, 0xff01,
82de802a 3809 "HOST-ABORT: state=DATA_IN.\n");
c0cb4496
AE
3810
3811 ha->tgt.tgt_ops->handle_data(cmd);
3812 return;
c0cb4496
AE
3813 } else {
3814 ql_dbg(ql_dbg_io, vha, 0xff03,
82de802a 3815 "HOST-ABORT: state=BAD(%d).\n",
c0cb4496
AE
3816 cmd->state);
3817 dump_stack();
3818 }
3819
1eb42f96 3820 cmd->trc_flags |= TRC_FLUSH;
c0cb4496
AE
3821 ha->tgt.tgt_ops->free_cmd(cmd);
3822}
3823
2d70c103
NB
3824/*
3825 * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
3826 */
82de802a
QT
3827static void qlt_do_ctio_completion(struct scsi_qla_host *vha,
3828 struct rsp_que *rsp, uint32_t handle, uint32_t status, void *ctio)
2d70c103
NB
3829{
3830 struct qla_hw_data *ha = vha->hw;
3831 struct se_cmd *se_cmd;
2d70c103 3832 struct qla_tgt_cmd *cmd;
82de802a 3833 struct qla_qpair *qpair = rsp->qpair;
2d70c103 3834
2d70c103
NB
3835 if (handle & CTIO_INTERMEDIATE_HANDLE_MARK) {
3836 /* That could happen only in case of an error/reset/abort */
3837 if (status != CTIO_SUCCESS) {
3838 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01d,
3839 "Intermediate CTIO received"
3840 " (status %x)\n", status);
3841 }
3842 return;
3843 }
3844
82de802a 3845 cmd = qlt_ctio_to_cmd(vha, rsp, handle, ctio);
092e1dc3 3846 if (cmd == NULL)
2d70c103 3847 return;
092e1dc3 3848
2d70c103 3849 se_cmd = &cmd->se_cmd;
d564a372 3850 cmd->cmd_sent_to_fw = 0;
2d70c103 3851
f9b6721a 3852 qlt_unmap_sg(vha, cmd);
2d70c103
NB
3853
3854 if (unlikely(status != CTIO_SUCCESS)) {
3855 switch (status & 0xFFFF) {
3856 case CTIO_LIP_RESET:
3857 case CTIO_TARGET_RESET:
3858 case CTIO_ABORTED:
7b898542 3859 /* driver request abort via Terminate exchange */
2d70c103
NB
3860 case CTIO_TIMEOUT:
3861 case CTIO_INVALID_RX_ID:
3862 /* They are OK */
3863 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf058,
3864 "qla_target(%d): CTIO with "
3865 "status %#x received, state %x, se_cmd %p, "
3866 "(LIP_RESET=e, ABORTED=2, TARGET_RESET=17, "
3867 "TIMEOUT=b, INVALID_RX_ID=8)\n", vha->vp_idx,
3868 status, cmd->state, se_cmd);
3869 break;
3870
3871 case CTIO_PORT_LOGGED_OUT:
3872 case CTIO_PORT_UNAVAILABLE:
71cdc079 3873 {
dacb5822
HM
3874 int logged_out =
3875 (status & 0xFFFF) == CTIO_PORT_LOGGED_OUT;
3876
2d70c103 3877 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf059,
71cdc079 3878 "qla_target(%d): CTIO with %s status %x "
2d70c103 3879 "received (state %x, se_cmd %p)\n", vha->vp_idx,
dacb5822 3880 logged_out ? "PORT LOGGED OUT" : "PORT UNAVAILABLE",
2d70c103 3881 status, cmd->state, se_cmd);
2d70c103 3882
71cdc079
AP
3883 if (logged_out && cmd->sess) {
3884 /*
3885 * Session is already logged out, but we need
3886 * to notify initiator, who's not aware of this
3887 */
3888 cmd->sess->logout_on_delete = 0;
3889 cmd->sess->send_els_logo = 1;
83548fe2 3890 ql_dbg(ql_dbg_disc, vha, 0x20f8,
726b8548
QT
3891 "%s %d %8phC post del sess\n",
3892 __func__, __LINE__, cmd->sess->port_name);
3893
3894 qlt_schedule_sess_for_deletion_lock(cmd->sess);
71cdc079
AP
3895 }
3896 break;
3897 }
f83adb61
QT
3898 case CTIO_DIF_ERROR: {
3899 struct ctio_crc_from_fw *crc =
3900 (struct ctio_crc_from_fw *)ctio;
3901 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf073,
be25152c
QT
3902 "qla_target(%d): CTIO with DIF_ERROR status %x "
3903 "received (state %x, ulp_cmd %p) actual_dif[0x%llx] "
3904 "expect_dif[0x%llx]\n",
f83adb61
QT
3905 vha->vp_idx, status, cmd->state, se_cmd,
3906 *((u64 *)&crc->actual_dif[0]),
3907 *((u64 *)&crc->expected_dif[0]));
3908
8abfa9e2 3909 qlt_handle_dif_error(qpair, cmd, ctio);
be25152c 3910 return;
f83adb61 3911 }
2d70c103
NB
3912 default:
3913 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b,
f83adb61 3914 "qla_target(%d): CTIO with error status 0x%x received (state %x, se_cmd %p\n",
2d70c103
NB
3915 vha->vp_idx, status, cmd->state, se_cmd);
3916 break;
3917 }
3918
7b898542 3919
193b50b9 3920 /* "cmd->aborted" means
7b898542
QT
3921 * cmd is already aborted/terminated, we don't
3922 * need to terminate again. The exchange is already
3923 * cleaned up/freed at FW level. Just cleanup at driver
3924 * level.
3925 */
3926 if ((cmd->state != QLA_TGT_STATE_NEED_DATA) &&
193b50b9 3927 (!cmd->aborted)) {
1eb42f96 3928 cmd->trc_flags |= TRC_CTIO_ERR;
82de802a 3929 if (qlt_term_ctio_exchange(qpair, ctio, cmd, status))
2d70c103 3930 return;
7b898542 3931 }
2d70c103
NB
3932 }
3933
3934 if (cmd->state == QLA_TGT_STATE_PROCESSED) {
1eb42f96 3935 cmd->trc_flags |= TRC_CTIO_DONE;
2d70c103 3936 } else if (cmd->state == QLA_TGT_STATE_NEED_DATA) {
2d70c103
NB
3937 cmd->state = QLA_TGT_STATE_DATA_IN;
3938
52c82823 3939 if (status == CTIO_SUCCESS)
2d70c103
NB
3940 cmd->write_data_transferred = 1;
3941
2d70c103
NB
3942 ha->tgt.tgt_ops->handle_data(cmd);
3943 return;
193b50b9 3944 } else if (cmd->aborted) {
1eb42f96 3945 cmd->trc_flags |= TRC_CTIO_ABORTED;
2d70c103 3946 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01e,
649ee054 3947 "Aborted command %p (tag %lld) finished\n", cmd, se_cmd->tag);
2d70c103 3948 } else {
1eb42f96 3949 cmd->trc_flags |= TRC_CTIO_STRANGE;
2d70c103
NB
3950 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05c,
3951 "qla_target(%d): A command in state (%d) should "
3952 "not return a CTIO complete\n", vha->vp_idx, cmd->state);
3953 }
3954
7b898542 3955 if (unlikely(status != CTIO_SUCCESS) &&
193b50b9 3956 !cmd->aborted) {
2d70c103
NB
3957 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01f, "Finishing failed CTIO\n");
3958 dump_stack();
3959 }
3960
3961 ha->tgt.tgt_ops->free_cmd(cmd);
3962}
3963
2d70c103
NB
3964static inline int qlt_get_fcp_task_attr(struct scsi_qla_host *vha,
3965 uint8_t task_codes)
3966{
3967 int fcp_task_attr;
3968
3969 switch (task_codes) {
3970 case ATIO_SIMPLE_QUEUE:
68d81f40 3971 fcp_task_attr = TCM_SIMPLE_TAG;
2d70c103
NB
3972 break;
3973 case ATIO_HEAD_OF_QUEUE:
68d81f40 3974 fcp_task_attr = TCM_HEAD_TAG;
2d70c103
NB
3975 break;
3976 case ATIO_ORDERED_QUEUE:
68d81f40 3977 fcp_task_attr = TCM_ORDERED_TAG;
2d70c103
NB
3978 break;
3979 case ATIO_ACA_QUEUE:
68d81f40 3980 fcp_task_attr = TCM_ACA_TAG;
2d70c103
NB
3981 break;
3982 case ATIO_UNTAGGED:
68d81f40 3983 fcp_task_attr = TCM_SIMPLE_TAG;
2d70c103
NB
3984 break;
3985 default:
3986 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05d,
3987 "qla_target: unknown task code %x, use ORDERED instead\n",
3988 task_codes);
68d81f40 3989 fcp_task_attr = TCM_ORDERED_TAG;
2d70c103
NB
3990 break;
3991 }
3992
3993 return fcp_task_attr;
3994}
3995
5d964837 3996static struct fc_port *qlt_make_local_sess(struct scsi_qla_host *,
2d70c103
NB
3997 uint8_t *);
3998/*
3999 * Process context for I/O path into tcm_qla2xxx code
4000 */
51a07f84 4001static void __qlt_do_work(struct qla_tgt_cmd *cmd)
2d70c103 4002{
2d70c103
NB
4003 scsi_qla_host_t *vha = cmd->vha;
4004 struct qla_hw_data *ha = vha->hw;
5d964837 4005 struct fc_port *sess = cmd->sess;
2d70c103
NB
4006 struct atio_from_isp *atio = &cmd->atio;
4007 unsigned char *cdb;
4008 unsigned long flags;
4009 uint32_t data_length;
4010 int ret, fcp_task_attr, data_dir, bidi = 0;
82de802a 4011 struct qla_qpair *qpair = cmd->qpair;
2d70c103 4012
e07f8f65 4013 cmd->cmd_in_wq = 0;
1eb42f96 4014 cmd->trc_flags |= TRC_DO_WORK;
2d70c103 4015
193b50b9 4016 if (cmd->aborted) {
8b2f5ff3
SN
4017 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf082,
4018 "cmd with tag %u is aborted\n",
4019 cmd->atio.u.isp24.exchange_addr);
4020 goto out_term;
4021 }
4022
a07100e0 4023 spin_lock_init(&cmd->cmd_lock);
2d70c103 4024 cdb = &atio->u.isp24.fcp_cmnd.cdb[0];
649ee054 4025 cmd->se_cmd.tag = atio->u.isp24.exchange_addr;
2d70c103
NB
4026
4027 if (atio->u.isp24.fcp_cmnd.rddata &&
4028 atio->u.isp24.fcp_cmnd.wrdata) {
4029 bidi = 1;
4030 data_dir = DMA_TO_DEVICE;
4031 } else if (atio->u.isp24.fcp_cmnd.rddata)
4032 data_dir = DMA_FROM_DEVICE;
4033 else if (atio->u.isp24.fcp_cmnd.wrdata)
4034 data_dir = DMA_TO_DEVICE;
4035 else
4036 data_dir = DMA_NONE;
4037
4038 fcp_task_attr = qlt_get_fcp_task_attr(vha,
4039 atio->u.isp24.fcp_cmnd.task_attr);
4040 data_length = be32_to_cpu(get_unaligned((uint32_t *)
4041 &atio->u.isp24.fcp_cmnd.add_cdb[
4042 atio->u.isp24.fcp_cmnd.add_cdb_len]));
4043
51a07f84
NB
4044 ret = ha->tgt.tgt_ops->handle_cmd(vha, cmd, cdb, data_length,
4045 fcp_task_attr, data_dir, bidi);
2d70c103
NB
4046 if (ret != 0)
4047 goto out_term;
4048 /*
4049 * Drop extra session reference from qla_tgt_handle_cmd_for_atio*(
4050 */
7560151b 4051 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
5d964837 4052 ha->tgt.tgt_ops->put_sess(sess);
7560151b 4053 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
2d70c103
NB
4054 return;
4055
4056out_term:
667024a3 4057 ql_dbg(ql_dbg_io, vha, 0x3060, "Terminating work cmd %p", cmd);
2d70c103 4058 /*
fae9eaf8
RD
4059 * cmd has not sent to target yet, so pass NULL as the second
4060 * argument to qlt_send_term_exchange() and free the memory here.
2d70c103 4061 */
1eb42f96 4062 cmd->trc_flags |= TRC_DO_WORK_ERR;
82de802a
QT
4063 spin_lock_irqsave(qpair->qp_lock_ptr, flags);
4064 qlt_send_term_exchange(qpair, NULL, &cmd->atio, 1, 0);
33e79977
QT
4065
4066 qlt_decr_num_pend_cmds(vha);
51a07f84 4067 percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
82de802a 4068 spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
7560151b
QT
4069
4070 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
5d964837 4071 ha->tgt.tgt_ops->put_sess(sess);
7560151b 4072 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
51a07f84
NB
4073}
4074
4075static void qlt_do_work(struct work_struct *work)
4076{
4077 struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
8b2f5ff3
SN
4078 scsi_qla_host_t *vha = cmd->vha;
4079 unsigned long flags;
4080
4081 spin_lock_irqsave(&vha->cmd_list_lock, flags);
4082 list_del(&cmd->cmd_list);
4083 spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
51a07f84
NB
4084
4085 __qlt_do_work(cmd);
4086}
4087
09620eeb
QT
4088void qlt_clr_qp_table(struct scsi_qla_host *vha)
4089{
4090 unsigned long flags;
4091 struct qla_hw_data *ha = vha->hw;
4092 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
4093 void *node;
4094 u64 key = 0;
4095
4096 ql_log(ql_log_info, vha, 0x706c,
4097 "User update Number of Active Qpairs %d\n",
4098 ha->tgt.num_act_qpairs);
4099
4100 spin_lock_irqsave(&ha->tgt.atio_lock, flags);
4101
4102 btree_for_each_safe64(&tgt->lun_qpair_map, key, node)
4103 btree_remove64(&tgt->lun_qpair_map, key);
4104
4105 ha->base_qpair->lun_cnt = 0;
4106 for (key = 0; key < ha->max_qpairs; key++)
4107 if (ha->queue_pair_map[key])
4108 ha->queue_pair_map[key]->lun_cnt = 0;
4109
4110 spin_unlock_irqrestore(&ha->tgt.atio_lock, flags);
4111}
4112
e326d22a
QT
4113static void qlt_assign_qpair(struct scsi_qla_host *vha,
4114 struct qla_tgt_cmd *cmd)
4115{
4116 struct qla_qpair *qpair, *qp;
4117 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
4118 struct qla_qpair_hint *h;
4119
4120 if (vha->flags.qpairs_available) {
4121 h = btree_lookup64(&tgt->lun_qpair_map, cmd->unpacked_lun);
4122 if (unlikely(!h)) {
4123 /* spread lun to qpair ratio evently */
4124 int lcnt = 0, rc;
4125 struct scsi_qla_host *base_vha =
4126 pci_get_drvdata(vha->hw->pdev);
4127
4128 qpair = vha->hw->base_qpair;
4129 if (qpair->lun_cnt == 0) {
4130 qpair->lun_cnt++;
4131 h = qla_qpair_to_hint(tgt, qpair);
4132 BUG_ON(!h);
4133 rc = btree_insert64(&tgt->lun_qpair_map,
4134 cmd->unpacked_lun, h, GFP_ATOMIC);
4135 if (rc) {
4136 qpair->lun_cnt--;
4137 ql_log(ql_log_info, vha, 0xd037,
4138 "Unable to insert lun %llx into lun_qpair_map\n",
4139 cmd->unpacked_lun);
4140 }
4141 goto out;
4142 } else {
4143 lcnt = qpair->lun_cnt;
4144 }
4145
4146 h = NULL;
4147 list_for_each_entry(qp, &base_vha->qp_list,
4148 qp_list_elem) {
4149 if (qp->lun_cnt == 0) {
4150 qp->lun_cnt++;
4151 h = qla_qpair_to_hint(tgt, qp);
4152 BUG_ON(!h);
4153 rc = btree_insert64(&tgt->lun_qpair_map,
4154 cmd->unpacked_lun, h, GFP_ATOMIC);
4155 if (rc) {
4156 qp->lun_cnt--;
4157 ql_log(ql_log_info, vha, 0xd038,
4158 "Unable to insert lun %llx into lun_qpair_map\n",
4159 cmd->unpacked_lun);
4160 }
4161 qpair = qp;
4162 goto out;
4163 } else {
4164 if (qp->lun_cnt < lcnt) {
4165 lcnt = qp->lun_cnt;
4166 qpair = qp;
4167 continue;
4168 }
4169 }
4170 }
4171 BUG_ON(!qpair);
4172 qpair->lun_cnt++;
4173 h = qla_qpair_to_hint(tgt, qpair);
4174 BUG_ON(!h);
4175 rc = btree_insert64(&tgt->lun_qpair_map,
4176 cmd->unpacked_lun, h, GFP_ATOMIC);
4177 if (rc) {
4178 qpair->lun_cnt--;
4179 ql_log(ql_log_info, vha, 0xd039,
4180 "Unable to insert lun %llx into lun_qpair_map\n",
4181 cmd->unpacked_lun);
4182 }
4183 }
4184 } else {
4185 h = &tgt->qphints[0];
4186 }
4187out:
4188 cmd->qpair = h->qpair;
4189 cmd->se_cmd.cpuid = h->cpuid;
4190}
4191
51a07f84 4192static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
5d964837 4193 struct fc_port *sess,
51a07f84
NB
4194 struct atio_from_isp *atio)
4195{
4196 struct se_session *se_sess = sess->se_sess;
4197 struct qla_tgt_cmd *cmd;
4198 int tag;
4199
4200 tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
4201 if (tag < 0)
4202 return NULL;
4203
4204 cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag];
4205 memset(cmd, 0, sizeof(struct qla_tgt_cmd));
c5419e26 4206 cmd->cmd_type = TYPE_TGT_CMD;
51a07f84
NB
4207 memcpy(&cmd->atio, atio, sizeof(*atio));
4208 cmd->state = QLA_TGT_STATE_NEW;
4209 cmd->tgt = vha->vha_tgt.qla_tgt;
33e79977 4210 qlt_incr_num_pend_cmds(vha);
51a07f84
NB
4211 cmd->vha = vha;
4212 cmd->se_cmd.map_tag = tag;
4213 cmd->sess = sess;
4214 cmd->loop_id = sess->loop_id;
4215 cmd->conf_compl_supported = sess->conf_compl_supported;
4216
1eb42f96 4217 cmd->trc_flags = 0;
9fce1254
KS
4218 cmd->jiffies_at_alloc = get_jiffies_64();
4219
e326d22a
QT
4220 cmd->unpacked_lun = scsilun_to_int(
4221 (struct scsi_lun *)&atio->u.isp24.fcp_cmnd.lun);
4222 qlt_assign_qpair(vha, cmd);
7c3f8fd1 4223 cmd->reset_count = vha->hw->base_qpair->chip_reset;
22d84726 4224 cmd->vp_idx = vha->vp_idx;
9fce1254 4225
51a07f84
NB
4226 return cmd;
4227}
4228
51a07f84
NB
4229static void qlt_create_sess_from_atio(struct work_struct *work)
4230{
4231 struct qla_tgt_sess_op *op = container_of(work,
4232 struct qla_tgt_sess_op, work);
4233 scsi_qla_host_t *vha = op->vha;
4234 struct qla_hw_data *ha = vha->hw;
5d964837 4235 struct fc_port *sess;
51a07f84
NB
4236 struct qla_tgt_cmd *cmd;
4237 unsigned long flags;
4238 uint8_t *s_id = op->atio.u.isp24.fcp_hdr.s_id;
4239
8b2f5ff3
SN
4240 spin_lock_irqsave(&vha->cmd_list_lock, flags);
4241 list_del(&op->cmd_list);
4242 spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
4243
4244 if (op->aborted) {
4245 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf083,
4246 "sess_op with tag %u is aborted\n",
4247 op->atio.u.isp24.exchange_addr);
4248 goto out_term;
4249 }
4250
51a07f84 4251 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022,
8b2f5ff3
SN
4252 "qla_target(%d): Unable to find wwn login"
4253 " (s_id %x:%x:%x), trying to create it manually\n",
4254 vha->vp_idx, s_id[0], s_id[1], s_id[2]);
51a07f84
NB
4255
4256 if (op->atio.u.raw.entry_count > 1) {
4257 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023,
8b2f5ff3 4258 "Dropping multy entry atio %p\n", &op->atio);
51a07f84
NB
4259 goto out_term;
4260 }
4261
51a07f84
NB
4262 sess = qlt_make_local_sess(vha, s_id);
4263 /* sess has an extra creation ref. */
51a07f84
NB
4264
4265 if (!sess)
4266 goto out_term;
4267 /*
4268 * Now obtain a pre-allocated session tag using the original op->atio
4269 * packet header, and dispatch into __qlt_do_work() using the existing
4270 * process context.
4271 */
4272 cmd = qlt_get_tag(vha, sess, &op->atio);
4273 if (!cmd) {
82de802a
QT
4274 struct qla_qpair *qpair = ha->base_qpair;
4275
4276 spin_lock_irqsave(qpair->qp_lock_ptr, flags);
4277 qlt_send_busy(qpair, &op->atio, SAM_STAT_BUSY);
4278 spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
4279
4280 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
5d964837 4281 ha->tgt.tgt_ops->put_sess(sess);
82de802a 4282 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
51a07f84
NB
4283 kfree(op);
4284 return;
4285 }
726b8548 4286
51a07f84 4287 /*
e3dc0e31 4288 * __qlt_do_work() will call qlt_put_sess() to release
51a07f84
NB
4289 * the extra reference taken above by qlt_make_local_sess()
4290 */
4291 __qlt_do_work(cmd);
4292 kfree(op);
4293 return;
51a07f84 4294out_term:
82de802a 4295 qlt_send_term_exchange(vha->hw->base_qpair, NULL, &op->atio, 0, 0);
51a07f84 4296 kfree(op);
2d70c103
NB
4297}
4298
4299/* ha->hardware_lock supposed to be held on entry */
4300static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
4301 struct atio_from_isp *atio)
4302{
51a07f84 4303 struct qla_hw_data *ha = vha->hw;
0e8cd71c 4304 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
5d964837 4305 struct fc_port *sess;
2d70c103 4306 struct qla_tgt_cmd *cmd;
5d964837 4307 unsigned long flags;
2d70c103
NB
4308
4309 if (unlikely(tgt->tgt_stop)) {
667024a3 4310 ql_dbg(ql_dbg_io, vha, 0x3061,
2d70c103
NB
4311 "New command while device %p is shutting down\n", tgt);
4312 return -EFAULT;
4313 }
4314
51a07f84
NB
4315 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, atio->u.isp24.fcp_hdr.s_id);
4316 if (unlikely(!sess)) {
4317 struct qla_tgt_sess_op *op = kzalloc(sizeof(struct qla_tgt_sess_op),
4318 GFP_ATOMIC);
4319 if (!op)
4320 return -ENOMEM;
4321
4322 memcpy(&op->atio, atio, sizeof(*atio));
78c2106a 4323 op->vha = vha;
8b2f5ff3 4324
8b631d87 4325 spin_lock_irqsave(&vha->cmd_list_lock, flags);
8b2f5ff3 4326 list_add_tail(&op->cmd_list, &vha->qla_sess_op_cmd_list);
8b631d87 4327 spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
8b2f5ff3 4328
51a07f84
NB
4329 INIT_WORK(&op->work, qlt_create_sess_from_atio);
4330 queue_work(qla_tgt_wq, &op->work);
4331 return 0;
4332 }
e52a8b45
AP
4333
4334 /* Another WWN used to have our s_id. Our PLOGI scheduled its
4335 * session deletion, but it's still in sess_del_work wq */
726b8548 4336 if (sess->deleted) {
83548fe2 4337 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf002,
e52a8b45
AP
4338 "New command while old session %p is being deleted\n",
4339 sess);
4340 return -EFAULT;
4341 }
4342
51a07f84
NB
4343 /*
4344 * Do kref_get() before returning + dropping qla_hw_data->hardware_lock.
4345 */
726b8548 4346 if (!kref_get_unless_zero(&sess->sess_kref)) {
83548fe2 4347 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004,
726b8548
QT
4348 "%s: kref_get fail, %8phC oxid %x \n",
4349 __func__, sess->port_name,
4350 be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id));
4351 return -EFAULT;
4352 }
51a07f84
NB
4353
4354 cmd = qlt_get_tag(vha, sess, atio);
2d70c103 4355 if (!cmd) {
667024a3 4356 ql_dbg(ql_dbg_io, vha, 0x3062,
2d70c103 4357 "qla_target(%d): Allocation of cmd failed\n", vha->vp_idx);
5d964837
QT
4358 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
4359 ha->tgt.tgt_ops->put_sess(sess);
4360 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
2d70c103
NB
4361 return -ENOMEM;
4362 }
4363
e07f8f65 4364 cmd->cmd_in_wq = 1;
1eb42f96 4365 cmd->trc_flags |= TRC_NEW_CMD;
8b2f5ff3 4366
726b8548 4367 spin_lock_irqsave(&vha->cmd_list_lock, flags);
8b2f5ff3 4368 list_add_tail(&cmd->cmd_list, &vha->qla_cmd_list);
726b8548 4369 spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
8b2f5ff3 4370
2d70c103 4371 INIT_WORK(&cmd->work, qlt_do_work);
e326d22a
QT
4372 if (vha->flags.qpairs_available) {
4373 queue_work_on(cmd->se_cmd.cpuid, qla_tgt_wq, &cmd->work);
4374 } else if (ha->msix_count) {
fb3269ba
QT
4375 if (cmd->atio.u.isp24.fcp_cmnd.rddata)
4376 queue_work_on(smp_processor_id(), qla_tgt_wq,
4377 &cmd->work);
4378 else
4379 queue_work_on(cmd->se_cmd.cpuid, qla_tgt_wq,
4380 &cmd->work);
4381 } else {
4382 queue_work(qla_tgt_wq, &cmd->work);
4383 }
2d70c103 4384
82de802a 4385 return 0;
2d70c103
NB
4386}
4387
4388/* ha->hardware_lock supposed to be held on entry */
5d964837 4389static int qlt_issue_task_mgmt(struct fc_port *sess, u64 lun,
2d70c103
NB
4390 int fn, void *iocb, int flags)
4391{
4392 struct scsi_qla_host *vha = sess->vha;
4393 struct qla_hw_data *ha = vha->hw;
4394 struct qla_tgt_mgmt_cmd *mcmd;
8b2f5ff3 4395 struct atio_from_isp *a = (struct atio_from_isp *)iocb;
2d70c103 4396 int res;
2d70c103
NB
4397
4398 mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC);
4399 if (!mcmd) {
4400 ql_dbg(ql_dbg_tgt_tmr, vha, 0x10009,
4401 "qla_target(%d): Allocation of management "
4402 "command failed, some commands and their data could "
4403 "leak\n", vha->vp_idx);
4404 return -ENOMEM;
4405 }
4406 memset(mcmd, 0, sizeof(*mcmd));
4407 mcmd->sess = sess;
4408
4409 if (iocb) {
4410 memcpy(&mcmd->orig_iocb.imm_ntfy, iocb,
4411 sizeof(mcmd->orig_iocb.imm_ntfy));
4412 }
4413 mcmd->tmr_func = fn;
4414 mcmd->flags = flags;
7c3f8fd1 4415 mcmd->reset_count = ha->base_qpair->chip_reset;
82de802a 4416 mcmd->qpair = ha->base_qpair;
2d70c103
NB
4417
4418 switch (fn) {
2d70c103 4419 case QLA_TGT_LUN_RESET:
be92fc3f
QT
4420 abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id);
4421 break;
2d70c103
NB
4422 }
4423
be92fc3f 4424 res = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, mcmd->tmr_func, 0);
2d70c103
NB
4425 if (res != 0) {
4426 ql_dbg(ql_dbg_tgt_tmr, vha, 0x1000b,
4427 "qla_target(%d): tgt.tgt_ops->handle_tmr() failed: %d\n",
4428 sess->vha->vp_idx, res);
4429 mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool);
4430 return -EFAULT;
4431 }
4432
4433 return 0;
4434}
4435
4436/* ha->hardware_lock supposed to be held on entry */
4437static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb)
4438{
4439 struct atio_from_isp *a = (struct atio_from_isp *)iocb;
4440 struct qla_hw_data *ha = vha->hw;
4441 struct qla_tgt *tgt;
5d964837 4442 struct fc_port *sess;
f775bd14 4443 u64 unpacked_lun;
52c82823 4444 int fn;
7560151b 4445 unsigned long flags;
2d70c103 4446
0e8cd71c 4447 tgt = vha->vha_tgt.qla_tgt;
2d70c103 4448
2d70c103 4449 fn = a->u.isp24.fcp_cmnd.task_mgmt_flags;
7560151b
QT
4450
4451 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
2d70c103
NB
4452 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha,
4453 a->u.isp24.fcp_hdr.s_id);
7560151b
QT
4454 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
4455
f775bd14
QT
4456 unpacked_lun =
4457 scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun);
2d70c103
NB
4458
4459 if (!sess) {
4460 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf024,
4461 "qla_target(%d): task mgmt fn 0x%x for "
4462 "non-existant session\n", vha->vp_idx, fn);
4463 return qlt_sched_sess_work(tgt, QLA_TGT_SESS_WORK_TM, iocb,
4464 sizeof(struct atio_from_isp));
4465 }
4466
726b8548 4467 if (sess->deleted)
e52a8b45
AP
4468 return -EFAULT;
4469
2d70c103
NB
4470 return qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0);
4471}
4472
4473/* ha->hardware_lock supposed to be held on entry */
4474static int __qlt_abort_task(struct scsi_qla_host *vha,
5d964837 4475 struct imm_ntfy_from_isp *iocb, struct fc_port *sess)
2d70c103
NB
4476{
4477 struct atio_from_isp *a = (struct atio_from_isp *)iocb;
4478 struct qla_hw_data *ha = vha->hw;
4479 struct qla_tgt_mgmt_cmd *mcmd;
f775bd14 4480 u64 unpacked_lun;
2d70c103
NB
4481 int rc;
4482
4483 mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC);
4484 if (mcmd == NULL) {
4485 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05f,
4486 "qla_target(%d): %s: Allocation of ABORT cmd failed\n",
4487 vha->vp_idx, __func__);
4488 return -ENOMEM;
4489 }
4490 memset(mcmd, 0, sizeof(*mcmd));
4491
4492 mcmd->sess = sess;
4493 memcpy(&mcmd->orig_iocb.imm_ntfy, iocb,
4494 sizeof(mcmd->orig_iocb.imm_ntfy));
4495
f775bd14
QT
4496 unpacked_lun =
4497 scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun);
7c3f8fd1 4498 mcmd->reset_count = ha->base_qpair->chip_reset;
be92fc3f 4499 mcmd->tmr_func = QLA_TGT_2G_ABORT_TASK;
82de802a 4500 mcmd->qpair = ha->base_qpair;
2d70c103 4501
be92fc3f 4502 rc = ha->tgt.tgt_ops->handle_tmr(mcmd, unpacked_lun, mcmd->tmr_func,
2d70c103
NB
4503 le16_to_cpu(iocb->u.isp2x.seq_id));
4504 if (rc != 0) {
4505 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf060,
4506 "qla_target(%d): tgt_ops->handle_tmr() failed: %d\n",
4507 vha->vp_idx, rc);
4508 mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool);
4509 return -EFAULT;
4510 }
4511
4512 return 0;
4513}
4514
4515/* ha->hardware_lock supposed to be held on entry */
4516static int qlt_abort_task(struct scsi_qla_host *vha,
4517 struct imm_ntfy_from_isp *iocb)
4518{
4519 struct qla_hw_data *ha = vha->hw;
5d964837 4520 struct fc_port *sess;
2d70c103 4521 int loop_id;
7560151b 4522 unsigned long flags;
2d70c103
NB
4523
4524 loop_id = GET_TARGET_ID(ha, (struct atio_from_isp *)iocb);
4525
7560151b 4526 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
2d70c103 4527 sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id);
7560151b
QT
4528 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
4529
2d70c103
NB
4530 if (sess == NULL) {
4531 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf025,
4532 "qla_target(%d): task abort for unexisting "
4533 "session\n", vha->vp_idx);
0e8cd71c 4534 return qlt_sched_sess_work(vha->vha_tgt.qla_tgt,
2d70c103
NB
4535 QLA_TGT_SESS_WORK_ABORT, iocb, sizeof(*iocb));
4536 }
4537
4538 return __qlt_abort_task(vha, iocb, sess);
4539}
4540
a6ca8878
AP
4541void qlt_logo_completion_handler(fc_port_t *fcport, int rc)
4542{
726b8548
QT
4543 if (rc != MBS_COMMAND_COMPLETE) {
4544 ql_dbg(ql_dbg_tgt_mgt, fcport->vha, 0xf093,
4545 "%s: se_sess %p / sess %p from"
4546 " port %8phC loop_id %#04x s_id %02x:%02x:%02x"
4547 " LOGO failed: %#x\n",
4548 __func__,
4549 fcport->se_sess,
4550 fcport,
4551 fcport->port_name, fcport->loop_id,
4552 fcport->d_id.b.domain, fcport->d_id.b.area,
4553 fcport->d_id.b.al_pa, rc);
4554 }
4555
4556 fcport->logout_completed = 1;
a6ca8878
AP
4557}
4558
a6ca8878
AP
4559/*
4560* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list)
4561*
4562* Schedules sessions with matching port_id/loop_id but different wwn for
4563* deletion. Returns existing session with matching wwn if present.
4564* Null otherwise.
4565*/
726b8548
QT
4566struct fc_port *
4567qlt_find_sess_invalidate_other(scsi_qla_host_t *vha, uint64_t wwn,
5d964837 4568 port_id_t port_id, uint16_t loop_id, struct fc_port **conflict_sess)
a6ca8878 4569{
5d964837 4570 struct fc_port *sess = NULL, *other_sess;
a6ca8878
AP
4571 uint64_t other_wwn;
4572
b7bd104e
AP
4573 *conflict_sess = NULL;
4574
5d964837 4575 list_for_each_entry(other_sess, &vha->vp_fcports, list) {
a6ca8878
AP
4576
4577 other_wwn = wwn_to_u64(other_sess->port_name);
4578
4579 if (wwn == other_wwn) {
4580 WARN_ON(sess);
4581 sess = other_sess;
4582 continue;
4583 }
4584
4585 /* find other sess with nport_id collision */
37cacc0a 4586 if (port_id.b24 == other_sess->d_id.b24) {
a6ca8878 4587 if (loop_id != other_sess->loop_id) {
726b8548 4588 ql_dbg(ql_dbg_tgt_tmr, vha, 0x1000c,
a6ca8878
AP
4589 "Invalidating sess %p loop_id %d wwn %llx.\n",
4590 other_sess, other_sess->loop_id, other_wwn);
4591
4592 /*
4593 * logout_on_delete is set by default, but another
4594 * session that has the same s_id/loop_id combo
4595 * might have cleared it when requested this session
4596 * deletion, so don't touch it
4597 */
4598 qlt_schedule_sess_for_deletion(other_sess, true);
4599 } else {
4600 /*
4601 * Another wwn used to have our s_id/loop_id
b7bd104e 4602 * kill the session, but don't free the loop_id
a6ca8878 4603 */
83548fe2 4604 ql_dbg(ql_dbg_tgt_tmr, vha, 0xf01b,
726b8548
QT
4605 "Invalidating sess %p loop_id %d wwn %llx.\n",
4606 other_sess, other_sess->loop_id, other_wwn);
4607
4608
b7bd104e
AP
4609 other_sess->keep_nport_handle = 1;
4610 *conflict_sess = other_sess;
a6ca8878
AP
4611 qlt_schedule_sess_for_deletion(other_sess,
4612 true);
4613 }
4614 continue;
4615 }
4616
4617 /* find other sess with nport handle collision */
726b8548
QT
4618 if ((loop_id == other_sess->loop_id) &&
4619 (loop_id != FC_NO_LOOP_ID)) {
4620 ql_dbg(ql_dbg_tgt_tmr, vha, 0x1000d,
a6ca8878
AP
4621 "Invalidating sess %p loop_id %d wwn %llx.\n",
4622 other_sess, other_sess->loop_id, other_wwn);
4623
4624 /* Same loop_id but different s_id
4625 * Ok to kill and logout */
4626 qlt_schedule_sess_for_deletion(other_sess, true);
4627 }
4628 }
4629
4630 return sess;
4631}
4632
daddf5cf
AP
4633/* Abort any commands for this s_id waiting on qla_tgt_wq workqueue */
4634static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id)
4635{
4636 struct qla_tgt_sess_op *op;
4637 struct qla_tgt_cmd *cmd;
4638 uint32_t key;
4639 int count = 0;
8b631d87 4640 unsigned long flags;
daddf5cf
AP
4641
4642 key = (((u32)s_id->b.domain << 16) |
4643 ((u32)s_id->b.area << 8) |
4644 ((u32)s_id->b.al_pa));
4645
8b631d87 4646 spin_lock_irqsave(&vha->cmd_list_lock, flags);
daddf5cf
AP
4647 list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
4648 uint32_t op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
41dc529a 4649
daddf5cf
AP
4650 if (op_key == key) {
4651 op->aborted = true;
4652 count++;
4653 }
4654 }
41dc529a
QT
4655
4656 list_for_each_entry(op, &vha->unknown_atio_list, cmd_list) {
4657 uint32_t op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
4658 if (op_key == key) {
4659 op->aborted = true;
4660 count++;
4661 }
4662 }
4663
daddf5cf
AP
4664 list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
4665 uint32_t cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id);
4666 if (cmd_key == key) {
193b50b9 4667 cmd->aborted = 1;
daddf5cf
AP
4668 count++;
4669 }
4670 }
8b631d87 4671 spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
daddf5cf
AP
4672
4673 return count;
4674}
4675
2d70c103
NB
4676/*
4677 * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
4678 */
4679static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
4680 struct imm_ntfy_from_isp *iocb)
4681{
a6ca8878 4682 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
df673274 4683 struct qla_hw_data *ha = vha->hw;
5d964837 4684 struct fc_port *sess = NULL, *conflict_sess = NULL;
a6ca8878
AP
4685 uint64_t wwn;
4686 port_id_t port_id;
4687 uint16_t loop_id;
4688 uint16_t wd3_lo;
2d70c103 4689 int res = 0;
5d964837 4690 struct qlt_plogi_ack_t *pla;
7560151b 4691 unsigned long flags;
2d70c103 4692
a6ca8878
AP
4693 wwn = wwn_to_u64(iocb->u.isp24.port_name);
4694
4695 port_id.b.domain = iocb->u.isp24.port_id[2];
4696 port_id.b.area = iocb->u.isp24.port_id[1];
4697 port_id.b.al_pa = iocb->u.isp24.port_id[0];
4698 port_id.b.rsvd_1 = 0;
4699
4700 loop_id = le16_to_cpu(iocb->u.isp24.nport_handle);
4701
726b8548
QT
4702 ql_dbg(ql_dbg_disc, vha, 0xf026,
4703 "qla_target(%d): Port ID: %02x:%02x:%02x ELS opcode: 0x%02x lid %d %8phC\n",
4704 vha->vp_idx, iocb->u.isp24.port_id[2],
4705 iocb->u.isp24.port_id[1], iocb->u.isp24.port_id[0],
4706 iocb->u.isp24.status_subcode, loop_id,
4707 iocb->u.isp24.port_name);
2d70c103 4708
a6ca8878
AP
4709 /* res = 1 means ack at the end of thread
4710 * res = 0 means ack async/later.
4711 */
2d70c103
NB
4712 switch (iocb->u.isp24.status_subcode) {
4713 case ELS_PLOGI:
a6ca8878 4714
daddf5cf
AP
4715 /* Mark all stale commands in qla_tgt_wq for deletion */
4716 abort_cmds_for_s_id(vha, &port_id);
4717
7560151b
QT
4718 if (wwn) {
4719 spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
726b8548
QT
4720 sess = qlt_find_sess_invalidate_other(vha, wwn,
4721 port_id, loop_id, &conflict_sess);
7560151b
QT
4722 spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock, flags);
4723 }
a6ca8878 4724
726b8548 4725 if (IS_SW_RESV_ADDR(port_id)) {
a6ca8878
AP
4726 res = 1;
4727 break;
4728 }
4729
b7bd104e
AP
4730 pla = qlt_plogi_ack_find_add(vha, &port_id, iocb);
4731 if (!pla) {
a6ca8878 4732 qlt_send_term_imm_notif(vha, iocb, 1);
a6ca8878
AP
4733 break;
4734 }
4735
4736 res = 0;
4737
726b8548
QT
4738 if (conflict_sess) {
4739 conflict_sess->login_gen++;
b7bd104e 4740 qlt_plogi_ack_link(vha, pla, conflict_sess,
726b8548
QT
4741 QLT_PLOGI_LINK_CONFLICT);
4742 }
a6ca8878 4743
726b8548
QT
4744 if (!sess) {
4745 pla->ref_count++;
4746 qla24xx_post_newsess_work(vha, &port_id,
4747 iocb->u.isp24.port_name, pla);
4748 res = 0;
b7bd104e 4749 break;
726b8548 4750 }
b7bd104e
AP
4751
4752 qlt_plogi_ack_link(vha, pla, sess, QLT_PLOGI_LINK_SAME_WWN);
726b8548
QT
4753 sess->fw_login_state = DSC_LS_PLOGI_PEND;
4754 sess->d_id = port_id;
4755 sess->login_gen++;
4756
4757 switch (sess->disc_state) {
4758 case DSC_DELETED:
4759 qlt_plogi_ack_unref(vha, pla);
4760 break;
4761
4762 default:
4763 /*
4764 * Under normal circumstances we want to release nport handle
4765 * during LOGO process to avoid nport handle leaks inside FW.
4766 * The exception is when LOGO is done while another PLOGI with
4767 * the same nport handle is waiting as might be the case here.
4768 * Note: there is always a possibily of a race where session
4769 * deletion has already started for other reasons (e.g. ACL
4770 * removal) and now PLOGI arrives:
4771 * 1. if PLOGI arrived in FW after nport handle has been freed,
4772 * FW must have assigned this PLOGI a new/same handle and we
4773 * can proceed ACK'ing it as usual when session deletion
4774 * completes.
4775 * 2. if PLOGI arrived in FW before LOGO with LCF_FREE_NPORT
4776 * bit reached it, the handle has now been released. We'll
4777 * get an error when we ACK this PLOGI. Nothing will be sent
4778 * back to initiator. Initiator should eventually retry
4779 * PLOGI and situation will correct itself.
4780 */
4781 sess->keep_nport_handle = ((sess->loop_id == loop_id) &&
4782 (sess->d_id.b24 == port_id.b24));
4783
83548fe2
QT
4784 ql_dbg(ql_dbg_disc, vha, 0x20f9,
4785 "%s %d %8phC post del sess\n",
4786 __func__, __LINE__, sess->port_name);
726b8548
QT
4787
4788
4789 qlt_schedule_sess_for_deletion_lock(sess);
4790 break;
4791 }
4792
a6ca8878
AP
4793 break;
4794
2d70c103 4795 case ELS_PRLI:
a6ca8878
AP
4796 wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo);
4797
7560151b
QT
4798 if (wwn) {
4799 spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
726b8548
QT
4800 sess = qlt_find_sess_invalidate_other(vha, wwn, port_id,
4801 loop_id, &conflict_sess);
7560151b
QT
4802 spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock, flags);
4803 }
b7bd104e
AP
4804
4805 if (conflict_sess) {
4806 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf09b,
4807 "PRLI with conflicting sess %p port %8phC\n",
4808 conflict_sess, conflict_sess->port_name);
4809 qlt_send_term_imm_notif(vha, iocb, 1);
4810 res = 0;
4811 break;
4812 }
a6ca8878
AP
4813
4814 if (sess != NULL) {
ec7193e2
QT
4815 if (sess->fw_login_state != DSC_LS_PLOGI_PEND &&
4816 sess->fw_login_state != DSC_LS_PLOGI_COMP) {
a6ca8878
AP
4817 /*
4818 * Impatient initiator sent PRLI before last
4819 * PLOGI could finish. Will force him to re-try,
4820 * while last one finishes.
4821 */
df673274 4822 ql_log(ql_log_warn, sess->vha, 0xf095,
a6ca8878
AP
4823 "sess %p PRLI received, before plogi ack.\n",
4824 sess);
4825 qlt_send_term_imm_notif(vha, iocb, 1);
4826 res = 0;
4827 break;
4828 }
4829
4830 /*
4831 * This shouldn't happen under normal circumstances,
4832 * since we have deleted the old session during PLOGI
4833 */
df673274 4834 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf096,
a6ca8878
AP
4835 "PRLI (loop_id %#04x) for existing sess %p (loop_id %#04x)\n",
4836 sess->loop_id, sess, iocb->u.isp24.nport_handle);
4837
4838 sess->local = 0;
4839 sess->loop_id = loop_id;
37cacc0a 4840 sess->d_id = port_id;
726b8548 4841 sess->fw_login_state = DSC_LS_PRLI_PEND;
a6ca8878
AP
4842
4843 if (wd3_lo & BIT_7)
4844 sess->conf_compl_supported = 1;
4845
726b8548
QT
4846 if ((wd3_lo & BIT_4) == 0)
4847 sess->port_type = FCT_INITIATOR;
4848 else
4849 sess->port_type = FCT_TARGET;
df673274
AP
4850 }
4851 res = 1; /* send notify ack */
4852
4853 /* Make session global (not used in fabric mode) */
4854 if (ha->current_topology != ISP_CFG_F) {
ec7193e2 4855 if (sess) {
83548fe2 4856 ql_dbg(ql_dbg_disc, vha, 0x20fa,
ec7193e2
QT
4857 "%s %d %8phC post nack\n",
4858 __func__, __LINE__, sess->port_name);
4859 qla24xx_post_nack_work(vha, sess, iocb,
4860 SRB_NACK_PRLI);
4861 res = 0;
4862 } else {
4863 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
4864 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
4865 qla2xxx_wake_dpc(vha);
4866 }
a6ca8878 4867 } else {
726b8548 4868 if (sess) {
83548fe2 4869 ql_dbg(ql_dbg_disc, vha, 0x20fb,
ec7193e2
QT
4870 "%s %d %8phC post nack\n",
4871 __func__, __LINE__, sess->port_name);
726b8548
QT
4872 qla24xx_post_nack_work(vha, sess, iocb,
4873 SRB_NACK_PRLI);
4874 res = 0;
4875 }
4876 }
a6ca8878
AP
4877 break;
4878
41dc529a
QT
4879 case ELS_TPRLO:
4880 if (le16_to_cpu(iocb->u.isp24.flags) &
4881 NOTIFY24XX_FLAGS_GLOBAL_TPRLO) {
4882 loop_id = 0xFFFF;
4883 qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS);
4884 res = 1;
4885 break;
4886 }
4887 /* drop through */
2d70c103
NB
4888 case ELS_LOGO:
4889 case ELS_PRLO:
726b8548
QT
4890 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
4891 sess = qla2x00_find_fcport_by_loopid(vha, loop_id);
4892 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
4893
4894 if (sess) {
4895 sess->login_gen++;
4896 sess->fw_login_state = DSC_LS_LOGO_PEND;
726b8548
QT
4897 sess->logo_ack_needed = 1;
4898 memcpy(sess->iocb, iocb, IOCB_SIZE);
4899 }
4900
2d70c103 4901 res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS);
726b8548 4902
83548fe2 4903 ql_dbg(ql_dbg_disc, vha, 0x20fc,
726b8548
QT
4904 "%s: logo %llx res %d sess %p ",
4905 __func__, wwn, res, sess);
4906 if (res == 0) {
41dc529a
QT
4907 /*
4908 * cmd went upper layer, look for qlt_xmit_tm_rsp()
4909 * for LOGO_ACK & sess delete
4910 */
726b8548
QT
4911 BUG_ON(!sess);
4912 res = 0;
4913 } else {
41dc529a 4914 /* cmd did not go to upper layer. */
726b8548
QT
4915 if (sess) {
4916 qlt_schedule_sess_for_deletion_lock(sess);
4917 res = 0;
4918 }
4919 /* else logo will be ack */
4920 }
2d70c103
NB
4921 break;
4922 case ELS_PDISC:
4923 case ELS_ADISC:
4924 {
0e8cd71c 4925 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
2d70c103 4926 if (tgt->link_reinit_iocb_pending) {
82de802a
QT
4927 qlt_send_notify_ack(ha->base_qpair,
4928 &tgt->link_reinit_iocb, 0, 0, 0, 0, 0, 0);
2d70c103
NB
4929 tgt->link_reinit_iocb_pending = 0;
4930 }
726b8548
QT
4931
4932 sess = qla2x00_find_fcport_by_wwpn(vha,
4933 iocb->u.isp24.port_name, 1);
4934 if (sess) {
83548fe2 4935 ql_dbg(ql_dbg_disc, vha, 0x20fd,
726b8548
QT
4936 "sess %p lid %d|%d DS %d LS %d\n",
4937 sess, sess->loop_id, loop_id,
4938 sess->disc_state, sess->fw_login_state);
4939 }
4940
2d70c103
NB
4941 res = 1; /* send notify ack */
4942 break;
4943 }
4944
a6ca8878 4945 case ELS_FLOGI: /* should never happen */
2d70c103
NB
4946 default:
4947 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf061,
4948 "qla_target(%d): Unsupported ELS command %x "
4949 "received\n", vha->vp_idx, iocb->u.isp24.status_subcode);
4950 res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS);
4951 break;
4952 }
4953
4954 return res;
4955}
4956
2d70c103
NB
4957/*
4958 * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
4959 */
4960static void qlt_handle_imm_notify(struct scsi_qla_host *vha,
4961 struct imm_ntfy_from_isp *iocb)
4962{
4963 struct qla_hw_data *ha = vha->hw;
4964 uint32_t add_flags = 0;
4965 int send_notify_ack = 1;
4966 uint16_t status;
4967
4968 status = le16_to_cpu(iocb->u.isp2x.status);
4969 switch (status) {
4970 case IMM_NTFY_LIP_RESET:
4971 {
4972 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf032,
4973 "qla_target(%d): LIP reset (loop %#x), subcode %x\n",
4974 vha->vp_idx, le16_to_cpu(iocb->u.isp24.nport_handle),
4975 iocb->u.isp24.status_subcode);
4976
4977 if (qlt_reset(vha, iocb, QLA_TGT_ABORT_ALL) == 0)
4978 send_notify_ack = 0;
4979 break;
4980 }
4981
4982 case IMM_NTFY_LIP_LINK_REINIT:
4983 {
0e8cd71c 4984 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
2d70c103
NB
4985 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf033,
4986 "qla_target(%d): LINK REINIT (loop %#x, "
4987 "subcode %x)\n", vha->vp_idx,
4988 le16_to_cpu(iocb->u.isp24.nport_handle),
4989 iocb->u.isp24.status_subcode);
4990 if (tgt->link_reinit_iocb_pending) {
82de802a
QT
4991 qlt_send_notify_ack(ha->base_qpair,
4992 &tgt->link_reinit_iocb, 0, 0, 0, 0, 0, 0);
2d70c103
NB
4993 }
4994 memcpy(&tgt->link_reinit_iocb, iocb, sizeof(*iocb));
4995 tgt->link_reinit_iocb_pending = 1;
4996 /*
4997 * QLogic requires to wait after LINK REINIT for possible
4998 * PDISC or ADISC ELS commands
4999 */
5000 send_notify_ack = 0;
5001 break;
5002 }
5003
5004 case IMM_NTFY_PORT_LOGOUT:
5005 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf034,
5006 "qla_target(%d): Port logout (loop "
5007 "%#x, subcode %x)\n", vha->vp_idx,
5008 le16_to_cpu(iocb->u.isp24.nport_handle),
5009 iocb->u.isp24.status_subcode);
5010
5011 if (qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS) == 0)
5012 send_notify_ack = 0;
5013 /* The sessions will be cleared in the callback, if needed */
5014 break;
5015
5016 case IMM_NTFY_GLBL_TPRLO:
5017 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf035,
5018 "qla_target(%d): Global TPRLO (%x)\n", vha->vp_idx, status);
5019 if (qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS) == 0)
5020 send_notify_ack = 0;
5021 /* The sessions will be cleared in the callback, if needed */
5022 break;
5023
5024 case IMM_NTFY_PORT_CONFIG:
5025 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf036,
5026 "qla_target(%d): Port config changed (%x)\n", vha->vp_idx,
5027 status);
5028 if (qlt_reset(vha, iocb, QLA_TGT_ABORT_ALL) == 0)
5029 send_notify_ack = 0;
5030 /* The sessions will be cleared in the callback, if needed */
5031 break;
5032
5033 case IMM_NTFY_GLBL_LOGO:
5034 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06a,
5035 "qla_target(%d): Link failure detected\n",
5036 vha->vp_idx);
5037 /* I_T nexus loss */
5038 if (qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS) == 0)
5039 send_notify_ack = 0;
5040 break;
5041
5042 case IMM_NTFY_IOCB_OVERFLOW:
5043 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06b,
5044 "qla_target(%d): Cannot provide requested "
5045 "capability (IOCB overflowed the immediate notify "
5046 "resource count)\n", vha->vp_idx);
5047 break;
5048
5049 case IMM_NTFY_ABORT_TASK:
5050 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf037,
5051 "qla_target(%d): Abort Task (S %08x I %#x -> "
5052 "L %#x)\n", vha->vp_idx,
5053 le16_to_cpu(iocb->u.isp2x.seq_id),
5054 GET_TARGET_ID(ha, (struct atio_from_isp *)iocb),
5055 le16_to_cpu(iocb->u.isp2x.lun));
5056 if (qlt_abort_task(vha, iocb) == 0)
5057 send_notify_ack = 0;
5058 break;
5059
5060 case IMM_NTFY_RESOURCE:
5061 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06c,
5062 "qla_target(%d): Out of resources, host %ld\n",
5063 vha->vp_idx, vha->host_no);
5064 break;
5065
5066 case IMM_NTFY_MSG_RX:
5067 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf038,
5068 "qla_target(%d): Immediate notify task %x\n",
5069 vha->vp_idx, iocb->u.isp2x.task_flags);
5070 if (qlt_handle_task_mgmt(vha, iocb) == 0)
5071 send_notify_ack = 0;
5072 break;
5073
5074 case IMM_NTFY_ELS:
5075 if (qlt_24xx_handle_els(vha, iocb) == 0)
5076 send_notify_ack = 0;
5077 break;
2d70c103
NB
5078 default:
5079 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06d,
5080 "qla_target(%d): Received unknown immediate "
5081 "notify status %x\n", vha->vp_idx, status);
5082 break;
5083 }
5084
5085 if (send_notify_ack)
82de802a
QT
5086 qlt_send_notify_ack(ha->base_qpair, iocb, add_flags, 0, 0, 0,
5087 0, 0);
2d70c103
NB
5088}
5089
5090/*
5091 * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
5092 * This function sends busy to ISP 2xxx or 24xx.
5093 */
82de802a 5094static int __qlt_send_busy(struct qla_qpair *qpair,
2d70c103
NB
5095 struct atio_from_isp *atio, uint16_t status)
5096{
82de802a 5097 struct scsi_qla_host *vha = qpair->vha;
2d70c103
NB
5098 struct ctio7_to_24xx *ctio24;
5099 struct qla_hw_data *ha = vha->hw;
5100 request_t *pkt;
5d964837 5101 struct fc_port *sess = NULL;
7560151b 5102 unsigned long flags;
f7e761f5 5103 u16 temp;
2d70c103 5104
7560151b 5105 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
2d70c103
NB
5106 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha,
5107 atio->u.isp24.fcp_hdr.s_id);
7560151b 5108 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
2d70c103 5109 if (!sess) {
82de802a 5110 qlt_send_term_exchange(qpair, NULL, atio, 1, 0);
33e79977 5111 return 0;
2d70c103
NB
5112 }
5113 /* Sending marker isn't necessary, since we called from ISR */
5114
82de802a 5115 pkt = (request_t *)__qla2x00_alloc_iocbs(qpair, NULL);
2d70c103 5116 if (!pkt) {
667024a3 5117 ql_dbg(ql_dbg_io, vha, 0x3063,
2d70c103
NB
5118 "qla_target(%d): %s failed: unable to allocate "
5119 "request packet", vha->vp_idx, __func__);
33e79977 5120 return -ENOMEM;
2d70c103
NB
5121 }
5122
ce1025cd 5123 vha->tgt_counters.num_q_full_sent++;
2d70c103
NB
5124 pkt->entry_count = 1;
5125 pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
5126
5127 ctio24 = (struct ctio7_to_24xx *)pkt;
5128 ctio24->entry_type = CTIO_TYPE7;
5129 ctio24->nport_handle = sess->loop_id;
ad950360 5130 ctio24->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
2d70c103
NB
5131 ctio24->vp_index = vha->vp_idx;
5132 ctio24->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
5133 ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
5134 ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
5135 ctio24->exchange_addr = atio->u.isp24.exchange_addr;
f7e761f5 5136 temp = (atio->u.isp24.attr << 9) |
2d70c103 5137 CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS |
f7e761f5
QT
5138 CTIO7_FLAGS_DONT_RET_CTIO;
5139 ctio24->u.status1.flags = cpu_to_le16(temp);
2d70c103
NB
5140 /*
5141 * CTIO from fw w/o se_cmd doesn't provide enough info to retry it,
5142 * if the explicit conformation is used.
5143 */
5144 ctio24->u.status1.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id);
5145 ctio24->u.status1.scsi_status = cpu_to_le16(status);
63163e06
HM
5146 /* Memory Barrier */
5147 wmb();
8abfa9e2
QT
5148 if (qpair->reqq_start_iocbs)
5149 qpair->reqq_start_iocbs(qpair);
5150 else
5151 qla2x00_start_iocbs(vha, qpair->req);
33e79977
QT
5152 return 0;
5153}
5154
5155/*
5156 * This routine is used to allocate a command for either a QFull condition
5157 * (ie reply SAM_STAT_BUSY) or to terminate an exchange that did not go
5158 * out previously.
5159 */
5160static void
5161qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
5162 struct atio_from_isp *atio, uint16_t status, int qfull)
5163{
5164 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
5165 struct qla_hw_data *ha = vha->hw;
5d964837 5166 struct fc_port *sess;
33e79977
QT
5167 struct se_session *se_sess;
5168 struct qla_tgt_cmd *cmd;
5169 int tag;
82de802a 5170 unsigned long flags;
33e79977
QT
5171
5172 if (unlikely(tgt->tgt_stop)) {
5173 ql_dbg(ql_dbg_io, vha, 0x300a,
5174 "New command while device %p is shutting down\n", tgt);
5175 return;
5176 }
5177
5178 if ((vha->hw->tgt.num_qfull_cmds_alloc + 1) > MAX_QFULL_CMDS_ALLOC) {
5179 vha->hw->tgt.num_qfull_cmds_dropped++;
5180 if (vha->hw->tgt.num_qfull_cmds_dropped >
fc90adaf
JC
5181 vha->qla_stats.stat_max_qfull_cmds_dropped)
5182 vha->qla_stats.stat_max_qfull_cmds_dropped =
33e79977
QT
5183 vha->hw->tgt.num_qfull_cmds_dropped;
5184
5185 ql_dbg(ql_dbg_io, vha, 0x3068,
5186 "qla_target(%d): %s: QFull CMD dropped[%d]\n",
5187 vha->vp_idx, __func__,
5188 vha->hw->tgt.num_qfull_cmds_dropped);
5189
5190 qlt_chk_exch_leak_thresh_hold(vha);
5191 return;
5192 }
5193
5194 sess = ha->tgt.tgt_ops->find_sess_by_s_id
5195 (vha, atio->u.isp24.fcp_hdr.s_id);
5196 if (!sess)
5197 return;
5198
5199 se_sess = sess->se_sess;
5200
5201 tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
5202 if (tag < 0)
5203 return;
5204
5205 cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag];
5206 if (!cmd) {
5207 ql_dbg(ql_dbg_io, vha, 0x3009,
5208 "qla_target(%d): %s: Allocation of cmd failed\n",
5209 vha->vp_idx, __func__);
5210
5211 vha->hw->tgt.num_qfull_cmds_dropped++;
5212 if (vha->hw->tgt.num_qfull_cmds_dropped >
fc90adaf
JC
5213 vha->qla_stats.stat_max_qfull_cmds_dropped)
5214 vha->qla_stats.stat_max_qfull_cmds_dropped =
33e79977
QT
5215 vha->hw->tgt.num_qfull_cmds_dropped;
5216
5217 qlt_chk_exch_leak_thresh_hold(vha);
5218 return;
5219 }
5220
5221 memset(cmd, 0, sizeof(struct qla_tgt_cmd));
5222
5223 qlt_incr_num_pend_cmds(vha);
5224 INIT_LIST_HEAD(&cmd->cmd_list);
5225 memcpy(&cmd->atio, atio, sizeof(*atio));
5226
5227 cmd->tgt = vha->vha_tgt.qla_tgt;
5228 cmd->vha = vha;
7c3f8fd1 5229 cmd->reset_count = ha->base_qpair->chip_reset;
33e79977 5230 cmd->q_full = 1;
82de802a 5231 cmd->qpair = ha->base_qpair;
33e79977
QT
5232
5233 if (qfull) {
5234 cmd->q_full = 1;
5235 /* NOTE: borrowing the state field to carry the status */
5236 cmd->state = status;
5237 } else
5238 cmd->term_exchg = 1;
5239
82de802a 5240 spin_lock_irqsave(&vha->hw->tgt.q_full_lock, flags);
33e79977
QT
5241 list_add_tail(&cmd->cmd_list, &vha->hw->tgt.q_full_list);
5242
5243 vha->hw->tgt.num_qfull_cmds_alloc++;
5244 if (vha->hw->tgt.num_qfull_cmds_alloc >
fc90adaf
JC
5245 vha->qla_stats.stat_max_qfull_cmds_alloc)
5246 vha->qla_stats.stat_max_qfull_cmds_alloc =
33e79977 5247 vha->hw->tgt.num_qfull_cmds_alloc;
82de802a 5248 spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags);
33e79977
QT
5249}
5250
5251int
82de802a 5252qlt_free_qfull_cmds(struct qla_qpair *qpair)
33e79977 5253{
82de802a 5254 struct scsi_qla_host *vha = qpair->vha;
33e79977
QT
5255 struct qla_hw_data *ha = vha->hw;
5256 unsigned long flags;
5257 struct qla_tgt_cmd *cmd, *tcmd;
82de802a 5258 struct list_head free_list, q_full_list;
33e79977
QT
5259 int rc = 0;
5260
5261 if (list_empty(&ha->tgt.q_full_list))
5262 return 0;
5263
5264 INIT_LIST_HEAD(&free_list);
82de802a 5265 INIT_LIST_HEAD(&q_full_list);
33e79977 5266
82de802a 5267 spin_lock_irqsave(&vha->hw->tgt.q_full_lock, flags);
33e79977 5268 if (list_empty(&ha->tgt.q_full_list)) {
82de802a 5269 spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags);
33e79977
QT
5270 return 0;
5271 }
5272
82de802a
QT
5273 list_splice_init(&vha->hw->tgt.q_full_list, &q_full_list);
5274 spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags);
5275
5276 spin_lock_irqsave(qpair->qp_lock_ptr, flags);
5277 list_for_each_entry_safe(cmd, tcmd, &q_full_list, cmd_list) {
33e79977
QT
5278 if (cmd->q_full)
5279 /* cmd->state is a borrowed field to hold status */
82de802a 5280 rc = __qlt_send_busy(qpair, &cmd->atio, cmd->state);
33e79977 5281 else if (cmd->term_exchg)
82de802a 5282 rc = __qlt_send_term_exchange(qpair, NULL, &cmd->atio);
33e79977
QT
5283
5284 if (rc == -ENOMEM)
5285 break;
5286
5287 if (cmd->q_full)
5288 ql_dbg(ql_dbg_io, vha, 0x3006,
5289 "%s: busy sent for ox_id[%04x]\n", __func__,
5290 be16_to_cpu(cmd->atio.u.isp24.fcp_hdr.ox_id));
5291 else if (cmd->term_exchg)
5292 ql_dbg(ql_dbg_io, vha, 0x3007,
5293 "%s: Term exchg sent for ox_id[%04x]\n", __func__,
5294 be16_to_cpu(cmd->atio.u.isp24.fcp_hdr.ox_id));
5295 else
5296 ql_dbg(ql_dbg_io, vha, 0x3008,
5297 "%s: Unexpected cmd in QFull list %p\n", __func__,
5298 cmd);
5299
5300 list_del(&cmd->cmd_list);
5301 list_add_tail(&cmd->cmd_list, &free_list);
5302
5303 /* piggy back on hardware_lock for protection */
5304 vha->hw->tgt.num_qfull_cmds_alloc--;
5305 }
82de802a 5306 spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
33e79977
QT
5307
5308 cmd = NULL;
5309
5310 list_for_each_entry_safe(cmd, tcmd, &free_list, cmd_list) {
5311 list_del(&cmd->cmd_list);
5312 /* This cmd was never sent to TCM. There is no need
5313 * to schedule free or call free_cmd
5314 */
5315 qlt_free_cmd(cmd);
5316 }
82de802a
QT
5317
5318 if (!list_empty(&q_full_list)) {
5319 spin_lock_irqsave(&vha->hw->tgt.q_full_lock, flags);
5320 list_splice(&q_full_list, &vha->hw->tgt.q_full_list);
5321 spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags);
5322 }
5323
33e79977
QT
5324 return rc;
5325}
5326
5327static void
82de802a
QT
5328qlt_send_busy(struct qla_qpair *qpair, struct atio_from_isp *atio,
5329 uint16_t status)
33e79977
QT
5330{
5331 int rc = 0;
82de802a 5332 struct scsi_qla_host *vha = qpair->vha;
33e79977 5333
82de802a 5334 rc = __qlt_send_busy(qpair, atio, status);
33e79977
QT
5335 if (rc == -ENOMEM)
5336 qlt_alloc_qfull_cmd(vha, atio, status, 1);
5337}
5338
5339static int
82de802a
QT
5340qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha, struct qla_qpair *qpair,
5341 struct atio_from_isp *atio, uint8_t ha_locked)
33e79977
QT
5342{
5343 struct qla_hw_data *ha = vha->hw;
5344 uint16_t status;
8b666809 5345 unsigned long flags;
33e79977
QT
5346
5347 if (ha->tgt.num_pend_cmds < Q_FULL_THRESH_HOLD(ha))
5348 return 0;
5349
8b666809
QT
5350 if (!ha_locked)
5351 spin_lock_irqsave(&ha->hardware_lock, flags);
33e79977 5352 status = temp_sam_status;
82de802a 5353 qlt_send_busy(qpair, atio, status);
8b666809
QT
5354 if (!ha_locked)
5355 spin_unlock_irqrestore(&ha->hardware_lock, flags);
5356
33e79977 5357 return 1;
2d70c103
NB
5358}
5359
5360/* ha->hardware_lock supposed to be held on entry */
5361/* called via callback from qla2xxx */
5362static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
2f424b9b 5363 struct atio_from_isp *atio, uint8_t ha_locked)
2d70c103
NB
5364{
5365 struct qla_hw_data *ha = vha->hw;
0e8cd71c 5366 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
2d70c103 5367 int rc;
2f424b9b 5368 unsigned long flags;
2d70c103
NB
5369
5370 if (unlikely(tgt == NULL)) {
ec7193e2 5371 ql_dbg(ql_dbg_tgt, vha, 0x3064,
2d70c103
NB
5372 "ATIO pkt, but no tgt (ha %p)", ha);
5373 return;
5374 }
2d70c103
NB
5375 /*
5376 * In tgt_stop mode we also should allow all requests to pass.
5377 * Otherwise, some commands can stuck.
5378 */
5379
2f424b9b 5380 tgt->atio_irq_cmd_count++;
2d70c103
NB
5381
5382 switch (atio->u.raw.entry_type) {
5383 case ATIO_TYPE7:
2d70c103
NB
5384 if (unlikely(atio->u.isp24.exchange_addr ==
5385 ATIO_EXCHANGE_ADDRESS_UNKNOWN)) {
667024a3 5386 ql_dbg(ql_dbg_io, vha, 0x3065,
2d70c103
NB
5387 "qla_target(%d): ATIO_TYPE7 "
5388 "received with UNKNOWN exchange address, "
5389 "sending QUEUE_FULL\n", vha->vp_idx);
2f424b9b
QT
5390 if (!ha_locked)
5391 spin_lock_irqsave(&ha->hardware_lock, flags);
82de802a
QT
5392 qlt_send_busy(ha->base_qpair, atio,
5393 SAM_STAT_TASK_SET_FULL);
2f424b9b 5394 if (!ha_locked)
82de802a
QT
5395 spin_unlock_irqrestore(&ha->hardware_lock,
5396 flags);
2d70c103
NB
5397 break;
5398 }
33e79977 5399
33e79977 5400 if (likely(atio->u.isp24.fcp_cmnd.task_mgmt_flags == 0)) {
82de802a
QT
5401 rc = qlt_chk_qfull_thresh_hold(vha, ha->base_qpair,
5402 atio, ha_locked);
33e79977 5403 if (rc != 0) {
2f424b9b 5404 tgt->atio_irq_cmd_count--;
33e79977
QT
5405 return;
5406 }
2d70c103 5407 rc = qlt_handle_cmd_for_atio(vha, atio);
33e79977 5408 } else {
2d70c103 5409 rc = qlt_handle_task_mgmt(vha, atio);
33e79977 5410 }
2d70c103
NB
5411 if (unlikely(rc != 0)) {
5412 if (rc == -ESRCH) {
2f424b9b 5413 if (!ha_locked)
82de802a
QT
5414 spin_lock_irqsave(&ha->hardware_lock,
5415 flags);
2f424b9b 5416
2d70c103 5417#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
82de802a
QT
5418 qlt_send_busy(ha->base_qpair, atio,
5419 SAM_STAT_BUSY);
2d70c103 5420#else
82de802a
QT
5421 qlt_send_term_exchange(ha->base_qpair, NULL,
5422 atio, 1, 0);
2d70c103 5423#endif
2f424b9b 5424 if (!ha_locked)
82de802a
QT
5425 spin_unlock_irqrestore(
5426 &ha->hardware_lock, flags);
2d70c103
NB
5427 } else {
5428 if (tgt->tgt_stop) {
5429 ql_dbg(ql_dbg_tgt, vha, 0xe059,
5430 "qla_target: Unable to send "
5431 "command to target for req, "
5432 "ignoring.\n");
5433 } else {
5434 ql_dbg(ql_dbg_tgt, vha, 0xe05a,
5435 "qla_target(%d): Unable to send "
5436 "command to target, sending BUSY "
5437 "status.\n", vha->vp_idx);
2f424b9b
QT
5438 if (!ha_locked)
5439 spin_lock_irqsave(
5440 &ha->hardware_lock, flags);
82de802a
QT
5441 qlt_send_busy(ha->base_qpair,
5442 atio, SAM_STAT_BUSY);
2f424b9b
QT
5443 if (!ha_locked)
5444 spin_unlock_irqrestore(
5445 &ha->hardware_lock, flags);
2d70c103
NB
5446 }
5447 }
5448 }
5449 break;
5450
5451 case IMMED_NOTIFY_TYPE:
5452 {
5453 if (unlikely(atio->u.isp2x.entry_status != 0)) {
5454 ql_dbg(ql_dbg_tgt, vha, 0xe05b,
5455 "qla_target(%d): Received ATIO packet %x "
5456 "with error status %x\n", vha->vp_idx,
5457 atio->u.raw.entry_type,
5458 atio->u.isp2x.entry_status);
5459 break;
5460 }
5461 ql_dbg(ql_dbg_tgt, vha, 0xe02e, "%s", "IMMED_NOTIFY ATIO");
2f424b9b
QT
5462
5463 if (!ha_locked)
5464 spin_lock_irqsave(&ha->hardware_lock, flags);
2d70c103 5465 qlt_handle_imm_notify(vha, (struct imm_ntfy_from_isp *)atio);
2f424b9b
QT
5466 if (!ha_locked)
5467 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2d70c103
NB
5468 break;
5469 }
5470
5471 default:
5472 ql_dbg(ql_dbg_tgt, vha, 0xe05c,
5473 "qla_target(%d): Received unknown ATIO atio "
5474 "type %x\n", vha->vp_idx, atio->u.raw.entry_type);
5475 break;
5476 }
5477
2f424b9b 5478 tgt->atio_irq_cmd_count--;
2d70c103
NB
5479}
5480
5481/* ha->hardware_lock supposed to be held on entry */
5482/* called via callback from qla2xxx */
82de802a
QT
5483static void qlt_response_pkt(struct scsi_qla_host *vha,
5484 struct rsp_que *rsp, response_t *pkt)
2d70c103
NB
5485{
5486 struct qla_hw_data *ha = vha->hw;
0e8cd71c 5487 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
2d70c103
NB
5488
5489 if (unlikely(tgt == NULL)) {
5490 ql_dbg(ql_dbg_tgt, vha, 0xe05d,
5491 "qla_target(%d): Response pkt %x received, but no "
5492 "tgt (ha %p)\n", vha->vp_idx, pkt->entry_type, ha);
5493 return;
5494 }
5495
2d70c103
NB
5496 /*
5497 * In tgt_stop mode we also should allow all requests to pass.
5498 * Otherwise, some commands can stuck.
5499 */
5500
2d70c103 5501 switch (pkt->entry_type) {
f83adb61 5502 case CTIO_CRC2:
2d70c103
NB
5503 case CTIO_TYPE7:
5504 {
5505 struct ctio7_from_24xx *entry = (struct ctio7_from_24xx *)pkt;
82de802a 5506 qlt_do_ctio_completion(vha, rsp, entry->handle,
2d70c103
NB
5507 le16_to_cpu(entry->status)|(pkt->entry_status << 16),
5508 entry);
5509 break;
5510 }
5511
5512 case ACCEPT_TGT_IO_TYPE:
5513 {
5514 struct atio_from_isp *atio = (struct atio_from_isp *)pkt;
5515 int rc;
2d70c103 5516 if (atio->u.isp2x.status !=
ad950360 5517 cpu_to_le16(ATIO_CDB_VALID)) {
2d70c103
NB
5518 ql_dbg(ql_dbg_tgt, vha, 0xe05e,
5519 "qla_target(%d): ATIO with error "
5520 "status %x received\n", vha->vp_idx,
5521 le16_to_cpu(atio->u.isp2x.status));
5522 break;
5523 }
2d70c103 5524
82de802a 5525 rc = qlt_chk_qfull_thresh_hold(vha, rsp->qpair, atio, 1);
ba68a635 5526 if (rc != 0)
33e79977 5527 return;
33e79977 5528
2d70c103
NB
5529 rc = qlt_handle_cmd_for_atio(vha, atio);
5530 if (unlikely(rc != 0)) {
5531 if (rc == -ESRCH) {
5532#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
82de802a 5533 qlt_send_busy(rsp->qpair, atio, 0);
2d70c103 5534#else
82de802a 5535 qlt_send_term_exchange(rsp->qpair, NULL, atio, 1, 0);
2d70c103
NB
5536#endif
5537 } else {
5538 if (tgt->tgt_stop) {
5539 ql_dbg(ql_dbg_tgt, vha, 0xe05f,
5540 "qla_target: Unable to send "
5541 "command to target, sending TERM "
5542 "EXCHANGE for rsp\n");
82de802a 5543 qlt_send_term_exchange(rsp->qpair, NULL,
a07100e0 5544 atio, 1, 0);
2d70c103
NB
5545 } else {
5546 ql_dbg(ql_dbg_tgt, vha, 0xe060,
5547 "qla_target(%d): Unable to send "
5548 "command to target, sending BUSY "
5549 "status\n", vha->vp_idx);
82de802a 5550 qlt_send_busy(rsp->qpair, atio, 0);
2d70c103
NB
5551 }
5552 }
5553 }
5554 }
5555 break;
5556
5557 case CONTINUE_TGT_IO_TYPE:
5558 {
5559 struct ctio_to_2xxx *entry = (struct ctio_to_2xxx *)pkt;
82de802a 5560 qlt_do_ctio_completion(vha, rsp, entry->handle,
2d70c103
NB
5561 le16_to_cpu(entry->status)|(pkt->entry_status << 16),
5562 entry);
5563 break;
5564 }
5565
5566 case CTIO_A64_TYPE:
5567 {
5568 struct ctio_to_2xxx *entry = (struct ctio_to_2xxx *)pkt;
82de802a 5569 qlt_do_ctio_completion(vha, rsp, entry->handle,
2d70c103
NB
5570 le16_to_cpu(entry->status)|(pkt->entry_status << 16),
5571 entry);
5572 break;
5573 }
5574
5575 case IMMED_NOTIFY_TYPE:
5576 ql_dbg(ql_dbg_tgt, vha, 0xe035, "%s", "IMMED_NOTIFY\n");
5577 qlt_handle_imm_notify(vha, (struct imm_ntfy_from_isp *)pkt);
5578 break;
5579
5580 case NOTIFY_ACK_TYPE:
5581 if (tgt->notify_ack_expected > 0) {
5582 struct nack_to_isp *entry = (struct nack_to_isp *)pkt;
5583 ql_dbg(ql_dbg_tgt, vha, 0xe036,
5584 "NOTIFY_ACK seq %08x status %x\n",
5585 le16_to_cpu(entry->u.isp2x.seq_id),
5586 le16_to_cpu(entry->u.isp2x.status));
5587 tgt->notify_ack_expected--;
5588 if (entry->u.isp2x.status !=
ad950360 5589 cpu_to_le16(NOTIFY_ACK_SUCCESS)) {
2d70c103
NB
5590 ql_dbg(ql_dbg_tgt, vha, 0xe061,
5591 "qla_target(%d): NOTIFY_ACK "
5592 "failed %x\n", vha->vp_idx,
5593 le16_to_cpu(entry->u.isp2x.status));
5594 }
5595 } else {
5596 ql_dbg(ql_dbg_tgt, vha, 0xe062,
5597 "qla_target(%d): Unexpected NOTIFY_ACK received\n",
5598 vha->vp_idx);
5599 }
5600 break;
5601
5602 case ABTS_RECV_24XX:
5603 ql_dbg(ql_dbg_tgt, vha, 0xe037,
5604 "ABTS_RECV_24XX: instance %d\n", vha->vp_idx);
5605 qlt_24xx_handle_abts(vha, (struct abts_recv_from_24xx *)pkt);
5606 break;
5607
5608 case ABTS_RESP_24XX:
5609 if (tgt->abts_resp_expected > 0) {
5610 struct abts_resp_from_24xx_fw *entry =
5611 (struct abts_resp_from_24xx_fw *)pkt;
5612 ql_dbg(ql_dbg_tgt, vha, 0xe038,
5613 "ABTS_RESP_24XX: compl_status %x\n",
5614 entry->compl_status);
5615 tgt->abts_resp_expected--;
5616 if (le16_to_cpu(entry->compl_status) !=
5617 ABTS_RESP_COMPL_SUCCESS) {
5618 if ((entry->error_subcode1 == 0x1E) &&
5619 (entry->error_subcode2 == 0)) {
5620 /*
5621 * We've got a race here: aborted
5622 * exchange not terminated, i.e.
5623 * response for the aborted command was
5624 * sent between the abort request was
5625 * received and processed.
5626 * Unfortunately, the firmware has a
5627 * silly requirement that all aborted
5628 * exchanges must be explicitely
5629 * terminated, otherwise it refuses to
5630 * send responses for the abort
5631 * requests. So, we have to
5632 * (re)terminate the exchange and retry
5633 * the abort response.
5634 */
5635 qlt_24xx_retry_term_exchange(vha,
5636 entry);
5637 } else
5638 ql_dbg(ql_dbg_tgt, vha, 0xe063,
5639 "qla_target(%d): ABTS_RESP_24XX "
5640 "failed %x (subcode %x:%x)",
5641 vha->vp_idx, entry->compl_status,
5642 entry->error_subcode1,
5643 entry->error_subcode2);
5644 }
5645 } else {
5646 ql_dbg(ql_dbg_tgt, vha, 0xe064,
5647 "qla_target(%d): Unexpected ABTS_RESP_24XX "
5648 "received\n", vha->vp_idx);
5649 }
5650 break;
5651
5652 default:
5653 ql_dbg(ql_dbg_tgt, vha, 0xe065,
5654 "qla_target(%d): Received unknown response pkt "
5655 "type %x\n", vha->vp_idx, pkt->entry_type);
5656 break;
5657 }
5658
2d70c103
NB
5659}
5660
5661/*
5662 * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
5663 */
5664void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
5665 uint16_t *mailbox)
5666{
5667 struct qla_hw_data *ha = vha->hw;
0e8cd71c 5668 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
4f1d0f19 5669 int login_code;
2d70c103 5670
3a33dc95 5671 if (!tgt || tgt->tgt_stop || tgt->tgt_stopped)
2d70c103
NB
5672 return;
5673
2d70c103
NB
5674 if (((code == MBA_POINT_TO_POINT) || (code == MBA_CHG_IN_CONNECTION)) &&
5675 IS_QLA2100(ha))
5676 return;
5677 /*
5678 * In tgt_stop mode we also should allow all requests to pass.
5679 * Otherwise, some commands can stuck.
5680 */
5681
2d70c103
NB
5682
5683 switch (code) {
5684 case MBA_RESET: /* Reset */
5685 case MBA_SYSTEM_ERR: /* System Error */
5686 case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */
5687 case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */
5688 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03a,
5689 "qla_target(%d): System error async event %#x "
6efb3c0a 5690 "occurred", vha->vp_idx, code);
2d70c103
NB
5691 break;
5692 case MBA_WAKEUP_THRES: /* Request Queue Wake-up. */
5693 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
5694 break;
5695
5696 case MBA_LOOP_UP:
5697 {
5698 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03b,
6efb3c0a 5699 "qla_target(%d): Async LOOP_UP occurred "
4f1d0f19
AC
5700 "(m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx,
5701 le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
5702 le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
2d70c103 5703 if (tgt->link_reinit_iocb_pending) {
82de802a
QT
5704 qlt_send_notify_ack(ha->base_qpair,
5705 (void *)&tgt->link_reinit_iocb,
2d70c103
NB
5706 0, 0, 0, 0, 0, 0);
5707 tgt->link_reinit_iocb_pending = 0;
5708 }
5709 break;
5710 }
5711
5712 case MBA_LIP_OCCURRED:
5713 case MBA_LOOP_DOWN:
5714 case MBA_LIP_RESET:
5715 case MBA_RSCN_UPDATE:
5716 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03c,
6efb3c0a 5717 "qla_target(%d): Async event %#x occurred "
4f1d0f19
AC
5718 "(m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx, code,
5719 le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
5720 le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
2d70c103
NB
5721 break;
5722
ead03855 5723 case MBA_REJECTED_FCP_CMD:
83548fe2
QT
5724 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf017,
5725 "qla_target(%d): Async event LS_REJECT occurred (m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)",
5726 vha->vp_idx,
5727 le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
5728 le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
ead03855
QT
5729
5730 if (le16_to_cpu(mailbox[3]) == 1) {
5731 /* exchange starvation. */
5732 vha->hw->exch_starvation++;
5733 if (vha->hw->exch_starvation > 5) {
83548fe2 5734 ql_log(ql_log_warn, vha, 0xd03a,
ead03855
QT
5735 "Exchange starvation-. Resetting RISC\n");
5736
5737 vha->hw->exch_starvation = 0;
5738 if (IS_P3P_TYPE(vha->hw))
5739 set_bit(FCOE_CTX_RESET_NEEDED,
5740 &vha->dpc_flags);
5741 else
5742 set_bit(ISP_ABORT_NEEDED,
5743 &vha->dpc_flags);
5744 qla2xxx_wake_dpc(vha);
5745 }
5746 }
5747 break;
5748
2d70c103
NB
5749 case MBA_PORT_UPDATE:
5750 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03d,
5751 "qla_target(%d): Port update async event %#x "
6efb3c0a 5752 "occurred: updating the ports database (m[0]=%x, m[1]=%x, "
4f1d0f19
AC
5753 "m[2]=%x, m[3]=%x)", vha->vp_idx, code,
5754 le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
5755 le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
5756
5757 login_code = le16_to_cpu(mailbox[2]);
ead03855 5758 if (login_code == 0x4) {
2d70c103
NB
5759 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03e,
5760 "Async MB 2: Got PLOGI Complete\n");
ead03855
QT
5761 vha->hw->exch_starvation = 0;
5762 } else if (login_code == 0x7)
2d70c103
NB
5763 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03f,
5764 "Async MB 2: Port Logged Out\n");
5765 break;
2d70c103 5766 default:
2d70c103
NB
5767 break;
5768 }
5769
2d70c103
NB
5770}
5771
5772static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha,
5773 uint16_t loop_id)
5774{
726b8548 5775 fc_port_t *fcport, *tfcp, *del;
2d70c103 5776 int rc;
726b8548
QT
5777 unsigned long flags;
5778 u8 newfcport = 0;
2d70c103
NB
5779
5780 fcport = kzalloc(sizeof(*fcport), GFP_KERNEL);
5781 if (!fcport) {
5782 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06f,
5783 "qla_target(%d): Allocation of tmp FC port failed",
5784 vha->vp_idx);
5785 return NULL;
5786 }
5787
2d70c103
NB
5788 fcport->loop_id = loop_id;
5789
15f30a57 5790 rc = qla24xx_gpdb_wait(vha, fcport, 0);
2d70c103
NB
5791 if (rc != QLA_SUCCESS) {
5792 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf070,
5793 "qla_target(%d): Failed to retrieve fcport "
5794 "information -- get_port_database() returned %x "
5795 "(loop_id=0x%04x)", vha->vp_idx, rc, loop_id);
5796 kfree(fcport);
5797 return NULL;
5798 }
5799
726b8548
QT
5800 del = NULL;
5801 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
5802 tfcp = qla2x00_find_fcport_by_wwpn(vha, fcport->port_name, 1);
5803
5804 if (tfcp) {
5805 tfcp->d_id = fcport->d_id;
5806 tfcp->port_type = fcport->port_type;
5807 tfcp->supported_classes = fcport->supported_classes;
5808 tfcp->flags |= fcport->flags;
5809
5810 del = fcport;
5811 fcport = tfcp;
5812 } else {
5813 if (vha->hw->current_topology == ISP_CFG_F)
5814 fcport->flags |= FCF_FABRIC_DEVICE;
5815
5816 list_add_tail(&fcport->list, &vha->vp_fcports);
5817 if (!IS_SW_RESV_ADDR(fcport->d_id))
5818 vha->fcport_count++;
5819 fcport->login_gen++;
5820 fcport->disc_state = DSC_LOGIN_COMPLETE;
5821 fcport->login_succ = 1;
5822 newfcport = 1;
5823 }
5824
5825 fcport->deleted = 0;
5826 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
5827
5828 switch (vha->host->active_mode) {
5829 case MODE_INITIATOR:
5830 case MODE_DUAL:
5831 if (newfcport) {
5832 if (!IS_IIDMA_CAPABLE(vha->hw) || !vha->hw->flags.gpsc_supported) {
83548fe2 5833 ql_dbg(ql_dbg_disc, vha, 0x20fe,
726b8548
QT
5834 "%s %d %8phC post upd_fcport fcp_cnt %d\n",
5835 __func__, __LINE__, fcport->port_name, vha->fcport_count);
5836 qla24xx_post_upd_fcport_work(vha, fcport);
5837 } else {
83548fe2 5838 ql_dbg(ql_dbg_disc, vha, 0x20ff,
726b8548
QT
5839 "%s %d %8phC post gpsc fcp_cnt %d\n",
5840 __func__, __LINE__, fcport->port_name, vha->fcport_count);
5841 qla24xx_post_gpsc_work(vha, fcport);
5842 }
5843 }
5844 break;
5845
5846 case MODE_TARGET:
5847 default:
5848 break;
5849 }
5850 if (del)
5851 qla2x00_free_fcport(del);
5852
2d70c103
NB
5853 return fcport;
5854}
5855
5856/* Must be called under tgt_mutex */
5d964837 5857static struct fc_port *qlt_make_local_sess(struct scsi_qla_host *vha,
2d70c103
NB
5858 uint8_t *s_id)
5859{
5d964837 5860 struct fc_port *sess = NULL;
2d70c103
NB
5861 fc_port_t *fcport = NULL;
5862 int rc, global_resets;
5863 uint16_t loop_id = 0;
5864
726b8548
QT
5865 if ((s_id[0] == 0xFF) && (s_id[1] == 0xFC)) {
5866 /*
5867 * This is Domain Controller, so it should be
5868 * OK to drop SCSI commands from it.
5869 */
5870 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf042,
5871 "Unable to find initiator with S_ID %x:%x:%x",
5872 s_id[0], s_id[1], s_id[2]);
5873 return NULL;
5874 }
5875
71cdc079
AP
5876 mutex_lock(&vha->vha_tgt.tgt_mutex);
5877
2d70c103 5878retry:
0e8cd71c
SK
5879 global_resets =
5880 atomic_read(&vha->vha_tgt.qla_tgt->tgt_global_resets_count);
2d70c103
NB
5881
5882 rc = qla24xx_get_loop_id(vha, s_id, &loop_id);
5883 if (rc != 0) {
71cdc079
AP
5884 mutex_unlock(&vha->vha_tgt.tgt_mutex);
5885
726b8548
QT
5886 ql_log(ql_log_info, vha, 0xf071,
5887 "qla_target(%d): Unable to find "
5888 "initiator with S_ID %x:%x:%x",
5889 vha->vp_idx, s_id[0], s_id[1],
5890 s_id[2]);
71cdc079
AP
5891
5892 if (rc == -ENOENT) {
5893 qlt_port_logo_t logo;
5894 sid_to_portid(s_id, &logo.id);
5895 logo.cmd_count = 1;
5896 qlt_send_first_logo(vha, &logo);
5897 }
5898
2d70c103
NB
5899 return NULL;
5900 }
5901
5902 fcport = qlt_get_port_database(vha, loop_id);
71cdc079
AP
5903 if (!fcport) {
5904 mutex_unlock(&vha->vha_tgt.tgt_mutex);
2d70c103 5905 return NULL;
71cdc079 5906 }
2d70c103
NB
5907
5908 if (global_resets !=
0e8cd71c 5909 atomic_read(&vha->vha_tgt.qla_tgt->tgt_global_resets_count)) {
2d70c103
NB
5910 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf043,
5911 "qla_target(%d): global reset during session discovery "
5912 "(counter was %d, new %d), retrying", vha->vp_idx,
5913 global_resets,
0e8cd71c
SK
5914 atomic_read(&vha->vha_tgt.
5915 qla_tgt->tgt_global_resets_count));
2d70c103
NB
5916 goto retry;
5917 }
5918
5919 sess = qlt_create_sess(vha, fcport, true);
5920
71cdc079
AP
5921 mutex_unlock(&vha->vha_tgt.tgt_mutex);
5922
2d70c103
NB
5923 return sess;
5924}
5925
5926static void qlt_abort_work(struct qla_tgt *tgt,
5927 struct qla_tgt_sess_work_param *prm)
5928{
5929 struct scsi_qla_host *vha = tgt->vha;
5930 struct qla_hw_data *ha = vha->hw;
5d964837 5931 struct fc_port *sess = NULL;
7560151b 5932 unsigned long flags = 0, flags2 = 0;
2d70c103
NB
5933 uint32_t be_s_id;
5934 uint8_t s_id[3];
5935 int rc;
5936
7560151b 5937 spin_lock_irqsave(&ha->tgt.sess_lock, flags2);
2d70c103
NB
5938
5939 if (tgt->tgt_stop)
7560151b 5940 goto out_term2;
2d70c103
NB
5941
5942 s_id[0] = prm->abts.fcp_hdr_le.s_id[2];
5943 s_id[1] = prm->abts.fcp_hdr_le.s_id[1];
5944 s_id[2] = prm->abts.fcp_hdr_le.s_id[0];
5945
5946 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha,
5947 (unsigned char *)&be_s_id);
5948 if (!sess) {
7560151b 5949 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
2d70c103 5950
2d70c103
NB
5951 sess = qlt_make_local_sess(vha, s_id);
5952 /* sess has got an extra creation ref */
2d70c103 5953
7560151b 5954 spin_lock_irqsave(&ha->tgt.sess_lock, flags2);
2d70c103 5955 if (!sess)
7560151b 5956 goto out_term2;
2d70c103 5957 } else {
726b8548 5958 if (sess->deleted) {
e52a8b45 5959 sess = NULL;
7560151b 5960 goto out_term2;
e52a8b45
AP
5961 }
5962
726b8548 5963 if (!kref_get_unless_zero(&sess->sess_kref)) {
83548fe2 5964 ql_dbg(ql_dbg_tgt_tmr, vha, 0xf01c,
726b8548
QT
5965 "%s: kref_get fail %8phC \n",
5966 __func__, sess->port_name);
5967 sess = NULL;
5968 goto out_term2;
5969 }
2d70c103
NB
5970 }
5971
2d70c103 5972 rc = __qlt_24xx_handle_abts(vha, &prm->abts, sess);
f159b3c7
QT
5973 ha->tgt.tgt_ops->put_sess(sess);
5974 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
5975
2d70c103
NB
5976 if (rc != 0)
5977 goto out_term;
2d70c103
NB
5978 return;
5979
7560151b 5980out_term2:
f159b3c7
QT
5981 if (sess)
5982 ha->tgt.tgt_ops->put_sess(sess);
5983 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
7560151b 5984
2d70c103 5985out_term:
f159b3c7 5986 spin_lock_irqsave(&ha->hardware_lock, flags);
82de802a
QT
5987 qlt_24xx_send_abts_resp(ha->base_qpair, &prm->abts,
5988 FCP_TMF_REJECTED, false);
7560151b 5989 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2d70c103
NB
5990}
5991
5992static void qlt_tmr_work(struct qla_tgt *tgt,
5993 struct qla_tgt_sess_work_param *prm)
5994{
5995 struct atio_from_isp *a = &prm->tm_iocb2;
5996 struct scsi_qla_host *vha = tgt->vha;
5997 struct qla_hw_data *ha = vha->hw;
5d964837 5998 struct fc_port *sess = NULL;
2d70c103
NB
5999 unsigned long flags;
6000 uint8_t *s_id = NULL; /* to hide compiler warnings */
6001 int rc;
f775bd14 6002 u64 unpacked_lun;
52c82823 6003 int fn;
2d70c103
NB
6004 void *iocb;
6005
7560151b 6006 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
2d70c103
NB
6007
6008 if (tgt->tgt_stop)
f159b3c7 6009 goto out_term2;
2d70c103
NB
6010
6011 s_id = prm->tm_iocb2.u.isp24.fcp_hdr.s_id;
6012 sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id);
6013 if (!sess) {
7560151b 6014 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
2d70c103 6015
2d70c103
NB
6016 sess = qlt_make_local_sess(vha, s_id);
6017 /* sess has got an extra creation ref */
2d70c103 6018
7560151b 6019 spin_lock_irqsave(&ha->tgt.sess_lock, flags);
2d70c103 6020 if (!sess)
f159b3c7 6021 goto out_term2;
2d70c103 6022 } else {
726b8548 6023 if (sess->deleted) {
e52a8b45 6024 sess = NULL;
f159b3c7 6025 goto out_term2;
e52a8b45
AP
6026 }
6027
726b8548 6028 if (!kref_get_unless_zero(&sess->sess_kref)) {
83548fe2 6029 ql_dbg(ql_dbg_tgt_tmr, vha, 0xf020,
726b8548
QT
6030 "%s: kref_get fail %8phC\n",
6031 __func__, sess->port_name);
6032 sess = NULL;
f159b3c7 6033 goto out_term2;
726b8548 6034 }
2d70c103
NB
6035 }
6036
6037 iocb = a;
2d70c103 6038 fn = a->u.isp24.fcp_cmnd.task_mgmt_flags;
f775bd14
QT
6039 unpacked_lun =
6040 scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun);
2d70c103
NB
6041
6042 rc = qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0);
5d964837 6043 ha->tgt.tgt_ops->put_sess(sess);
7560151b 6044 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
f159b3c7
QT
6045
6046 if (rc != 0)
6047 goto out_term;
2d70c103
NB
6048 return;
6049
f159b3c7
QT
6050out_term2:
6051 if (sess)
6052 ha->tgt.tgt_ops->put_sess(sess);
6053 spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
2d70c103 6054out_term:
82de802a 6055 qlt_send_term_exchange(ha->base_qpair, NULL, &prm->tm_iocb2, 1, 0);
2d70c103
NB
6056}
6057
6058static void qlt_sess_work_fn(struct work_struct *work)
6059{
6060 struct qla_tgt *tgt = container_of(work, struct qla_tgt, sess_work);
6061 struct scsi_qla_host *vha = tgt->vha;
6062 unsigned long flags;
6063
6064 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf000, "Sess work (tgt %p)", tgt);
6065
6066 spin_lock_irqsave(&tgt->sess_work_lock, flags);
6067 while (!list_empty(&tgt->sess_works_list)) {
6068 struct qla_tgt_sess_work_param *prm = list_entry(
6069 tgt->sess_works_list.next, typeof(*prm),
6070 sess_works_list_entry);
6071
6072 /*
6073 * This work can be scheduled on several CPUs at time, so we
6074 * must delete the entry to eliminate double processing
6075 */
6076 list_del(&prm->sess_works_list_entry);
6077
6078 spin_unlock_irqrestore(&tgt->sess_work_lock, flags);
6079
6080 switch (prm->type) {
6081 case QLA_TGT_SESS_WORK_ABORT:
6082 qlt_abort_work(tgt, prm);
6083 break;
6084 case QLA_TGT_SESS_WORK_TM:
6085 qlt_tmr_work(tgt, prm);
6086 break;
6087 default:
6088 BUG_ON(1);
6089 break;
6090 }
6091
6092 spin_lock_irqsave(&tgt->sess_work_lock, flags);
6093
6094 kfree(prm);
6095 }
6096 spin_unlock_irqrestore(&tgt->sess_work_lock, flags);
6097}
6098
6099/* Must be called under tgt_host_action_mutex */
6100int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
6101{
6102 struct qla_tgt *tgt;
e326d22a
QT
6103 int rc, i;
6104 struct qla_qpair_hint *h;
2d70c103
NB
6105
6106 if (!QLA_TGT_MODE_ENABLED())
6107 return 0;
6108
33c36c0a
AE
6109 if (!IS_TGT_MODE_CAPABLE(ha)) {
6110 ql_log(ql_log_warn, base_vha, 0xe070,
6111 "This adapter does not support target mode.\n");
6112 return 0;
6113 }
6114
2d70c103 6115 ql_dbg(ql_dbg_tgt, base_vha, 0xe03b,
0e8cd71c 6116 "Registering target for host %ld(%p).\n", base_vha->host_no, ha);
2d70c103 6117
0e8cd71c 6118 BUG_ON(base_vha->vha_tgt.qla_tgt != NULL);
2d70c103
NB
6119
6120 tgt = kzalloc(sizeof(struct qla_tgt), GFP_KERNEL);
6121 if (!tgt) {
6122 ql_dbg(ql_dbg_tgt, base_vha, 0xe066,
6123 "Unable to allocate struct qla_tgt\n");
6124 return -ENOMEM;
6125 }
6126
e326d22a
QT
6127 tgt->qphints = kzalloc((ha->max_qpairs + 1) *
6128 sizeof(struct qla_qpair_hint), GFP_KERNEL);
6129 if (!tgt->qphints) {
6130 kfree(tgt);
6131 ql_log(ql_log_warn, base_vha, 0x0197,
6132 "Unable to allocate qpair hints.\n");
6133 return -ENOMEM;
6134 }
6135
2d70c103
NB
6136 if (!(base_vha->host->hostt->supported_mode & MODE_TARGET))
6137 base_vha->host->hostt->supported_mode |= MODE_TARGET;
6138
e326d22a
QT
6139 rc = btree_init64(&tgt->lun_qpair_map);
6140 if (rc) {
6141 kfree(tgt->qphints);
6142 kfree(tgt);
6143 ql_log(ql_log_info, base_vha, 0x0198,
6144 "Unable to initialize lun_qpair_map btree\n");
6145 return -EIO;
6146 }
6147 h = &tgt->qphints[0];
6148 h->qpair = ha->base_qpair;
6149 INIT_LIST_HEAD(&h->hint_elem);
6150 h->cpuid = ha->base_qpair->cpuid;
6151 list_add_tail(&h->hint_elem, &ha->base_qpair->hints_list);
6152
6153 for (i = 0; i < ha->max_qpairs; i++) {
6154 unsigned long flags;
6155
6156 struct qla_qpair *qpair = ha->queue_pair_map[i];
6157 h = &tgt->qphints[i + 1];
6158 INIT_LIST_HEAD(&h->hint_elem);
6159 if (qpair) {
6160 h->qpair = qpair;
6161 spin_lock_irqsave(qpair->qp_lock_ptr, flags);
6162 list_add_tail(&h->hint_elem, &qpair->hints_list);
6163 spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
6164 h->cpuid = qpair->cpuid;
6165 }
6166 }
6167
2d70c103
NB
6168 tgt->ha = ha;
6169 tgt->vha = base_vha;
6170 init_waitqueue_head(&tgt->waitQ);
2d70c103 6171 INIT_LIST_HEAD(&tgt->del_sess_list);
2d70c103
NB
6172 spin_lock_init(&tgt->sess_work_lock);
6173 INIT_WORK(&tgt->sess_work, qlt_sess_work_fn);
6174 INIT_LIST_HEAD(&tgt->sess_works_list);
2d70c103
NB
6175 atomic_set(&tgt->tgt_global_resets_count, 0);
6176
0e8cd71c 6177 base_vha->vha_tgt.qla_tgt = tgt;
2d70c103
NB
6178
6179 ql_dbg(ql_dbg_tgt, base_vha, 0xe067,
6180 "qla_target(%d): using 64 Bit PCI addressing",
6181 base_vha->vp_idx);
6182 tgt->tgt_enable_64bit_addr = 1;
6183 /* 3 is reserved */
6184 tgt->sg_tablesize = QLA_TGT_MAX_SG_24XX(base_vha->req->length - 3);
6185 tgt->datasegs_per_cmd = QLA_TGT_DATASEGS_PER_CMD_24XX;
6186 tgt->datasegs_per_cont = QLA_TGT_DATASEGS_PER_CONT_24XX;
6187
6188 mutex_lock(&qla_tgt_mutex);
6189 list_add_tail(&tgt->tgt_list_entry, &qla_tgt_glist);
6190 mutex_unlock(&qla_tgt_mutex);
6191
f1443eeb
QT
6192 if (ha->tgt.tgt_ops && ha->tgt.tgt_ops->add_target)
6193 ha->tgt.tgt_ops->add_target(base_vha);
6194
2d70c103
NB
6195 return 0;
6196}
6197
6198/* Must be called under tgt_host_action_mutex */
6199int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha)
6200{
0e8cd71c 6201 if (!vha->vha_tgt.qla_tgt)
2d70c103
NB
6202 return 0;
6203
ddb95145
NB
6204 if (vha->fc_vport) {
6205 qlt_release(vha->vha_tgt.qla_tgt);
6206 return 0;
6207 }
33e79977
QT
6208
6209 /* free left over qfull cmds */
6210 qlt_init_term_exchange(vha);
6211
2d70c103 6212 mutex_lock(&qla_tgt_mutex);
0e8cd71c 6213 list_del(&vha->vha_tgt.qla_tgt->tgt_list_entry);
2d70c103
NB
6214 mutex_unlock(&qla_tgt_mutex);
6215
6216 ql_dbg(ql_dbg_tgt, vha, 0xe03c, "Unregistering target for host %ld(%p)",
6217 vha->host_no, ha);
0e8cd71c 6218 qlt_release(vha->vha_tgt.qla_tgt);
2d70c103
NB
6219
6220 return 0;
6221}
6222
482c9dc7
QT
6223void qlt_remove_target_resources(struct qla_hw_data *ha)
6224{
6225 struct scsi_qla_host *node;
6226 u32 key = 0;
6227
6228 btree_for_each_safe32(&ha->tgt.host_map, key, node)
6229 btree_remove32(&ha->tgt.host_map, key);
6230
6231 btree_destroy32(&ha->tgt.host_map);
6232}
6233
2d70c103
NB
6234static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn,
6235 unsigned char *b)
6236{
6237 int i;
6238
6239 pr_debug("qla2xxx HW vha->node_name: ");
6240 for (i = 0; i < WWN_SIZE; i++)
6241 pr_debug("%02x ", vha->node_name[i]);
6242 pr_debug("\n");
6243 pr_debug("qla2xxx HW vha->port_name: ");
6244 for (i = 0; i < WWN_SIZE; i++)
6245 pr_debug("%02x ", vha->port_name[i]);
6246 pr_debug("\n");
6247
6248 pr_debug("qla2xxx passed configfs WWPN: ");
6249 put_unaligned_be64(wwpn, b);
6250 for (i = 0; i < WWN_SIZE; i++)
6251 pr_debug("%02x ", b[i]);
6252 pr_debug("\n");
6253}
6254
6255/**
6256 * qla_tgt_lport_register - register lport with external module
6257 *
6258 * @qla_tgt_ops: Pointer for tcm_qla2xxx qla_tgt_ops
6259 * @wwpn: Passwd FC target WWPN
6260 * @callback: lport initialization callback for tcm_qla2xxx code
6261 * @target_lport_ptr: pointer for tcm_qla2xxx specific lport data
6262 */
49a47f2c
NB
6263int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn,
6264 u64 npiv_wwpn, u64 npiv_wwnn,
6265 int (*callback)(struct scsi_qla_host *, void *, u64, u64))
2d70c103
NB
6266{
6267 struct qla_tgt *tgt;
6268 struct scsi_qla_host *vha;
6269 struct qla_hw_data *ha;
6270 struct Scsi_Host *host;
6271 unsigned long flags;
6272 int rc;
6273 u8 b[WWN_SIZE];
6274
6275 mutex_lock(&qla_tgt_mutex);
6276 list_for_each_entry(tgt, &qla_tgt_glist, tgt_list_entry) {
6277 vha = tgt->vha;
6278 ha = vha->hw;
6279
6280 host = vha->host;
6281 if (!host)
6282 continue;
6283
2d70c103
NB
6284 if (!(host->hostt->supported_mode & MODE_TARGET))
6285 continue;
6286
6287 spin_lock_irqsave(&ha->hardware_lock, flags);
49a47f2c 6288 if ((!npiv_wwpn || !npiv_wwnn) && host->active_mode & MODE_TARGET) {
2d70c103
NB
6289 pr_debug("MODE_TARGET already active on qla2xxx(%d)\n",
6290 host->host_no);
6291 spin_unlock_irqrestore(&ha->hardware_lock, flags);
6292 continue;
6293 }
ddb95145
NB
6294 if (tgt->tgt_stop) {
6295 pr_debug("MODE_TARGET in shutdown on qla2xxx(%d)\n",
6296 host->host_no);
6297 spin_unlock_irqrestore(&ha->hardware_lock, flags);
6298 continue;
6299 }
2d70c103
NB
6300 spin_unlock_irqrestore(&ha->hardware_lock, flags);
6301
6302 if (!scsi_host_get(host)) {
6303 ql_dbg(ql_dbg_tgt, vha, 0xe068,
6304 "Unable to scsi_host_get() for"
6305 " qla2xxx scsi_host\n");
6306 continue;
6307 }
49a47f2c 6308 qlt_lport_dump(vha, phys_wwpn, b);
2d70c103
NB
6309
6310 if (memcmp(vha->port_name, b, WWN_SIZE)) {
6311 scsi_host_put(host);
6312 continue;
6313 }
49a47f2c
NB
6314 rc = (*callback)(vha, target_lport_ptr, npiv_wwpn, npiv_wwnn);
6315 if (rc != 0)
6316 scsi_host_put(host);
6317
ddb95145 6318 mutex_unlock(&qla_tgt_mutex);
2d70c103
NB
6319 return rc;
6320 }
6321 mutex_unlock(&qla_tgt_mutex);
6322
6323 return -ENODEV;
6324}
6325EXPORT_SYMBOL(qlt_lport_register);
6326
6327/**
6328 * qla_tgt_lport_deregister - Degister lport
6329 *
6330 * @vha: Registered scsi_qla_host pointer
6331 */
6332void qlt_lport_deregister(struct scsi_qla_host *vha)
6333{
6334 struct qla_hw_data *ha = vha->hw;
6335 struct Scsi_Host *sh = vha->host;
6336 /*
6337 * Clear the target_lport_ptr qla_target_template pointer in qla_hw_data
6338 */
0e8cd71c 6339 vha->vha_tgt.target_lport_ptr = NULL;
2d70c103
NB
6340 ha->tgt.tgt_ops = NULL;
6341 /*
6342 * Release the Scsi_Host reference for the underlying qla2xxx host
6343 */
6344 scsi_host_put(sh);
6345}
6346EXPORT_SYMBOL(qlt_lport_deregister);
6347
6348/* Must be called under HW lock */
55a9066f 6349static void qlt_set_mode(struct scsi_qla_host *vha)
2d70c103 6350{
2d70c103
NB
6351 switch (ql2x_ini_mode) {
6352 case QLA2XXX_INI_MODE_DISABLED:
6353 case QLA2XXX_INI_MODE_EXCLUSIVE:
6354 vha->host->active_mode = MODE_TARGET;
6355 break;
6356 case QLA2XXX_INI_MODE_ENABLED:
ead03855
QT
6357 vha->host->active_mode = MODE_UNKNOWN;
6358 break;
6359 case QLA2XXX_INI_MODE_DUAL:
6360 vha->host->active_mode = MODE_DUAL;
2d70c103
NB
6361 break;
6362 default:
6363 break;
6364 }
2d70c103
NB
6365}
6366
6367/* Must be called under HW lock */
55a9066f 6368static void qlt_clear_mode(struct scsi_qla_host *vha)
2d70c103 6369{
2d70c103
NB
6370 switch (ql2x_ini_mode) {
6371 case QLA2XXX_INI_MODE_DISABLED:
6372 vha->host->active_mode = MODE_UNKNOWN;
6373 break;
6374 case QLA2XXX_INI_MODE_EXCLUSIVE:
6375 vha->host->active_mode = MODE_INITIATOR;
6376 break;
6377 case QLA2XXX_INI_MODE_ENABLED:
ead03855
QT
6378 case QLA2XXX_INI_MODE_DUAL:
6379 vha->host->active_mode = MODE_INITIATOR;
2d70c103
NB
6380 break;
6381 default:
6382 break;
6383 }
2d70c103
NB
6384}
6385
6386/*
6387 * qla_tgt_enable_vha - NO LOCK HELD
6388 *
6389 * host_reset, bring up w/ Target Mode Enabled
6390 */
6391void
6392qlt_enable_vha(struct scsi_qla_host *vha)
6393{
6394 struct qla_hw_data *ha = vha->hw;
0e8cd71c 6395 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
2d70c103 6396 unsigned long flags;
0e8cd71c 6397 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
2d70c103
NB
6398
6399 if (!tgt) {
6400 ql_dbg(ql_dbg_tgt, vha, 0xe069,
6401 "Unable to locate qla_tgt pointer from"
6402 " struct qla_hw_data\n");
6403 dump_stack();
6404 return;
6405 }
6406
6407 spin_lock_irqsave(&ha->hardware_lock, flags);
6408 tgt->tgt_stopped = 0;
6409 qlt_set_mode(vha);
6410 spin_unlock_irqrestore(&ha->hardware_lock, flags);
6411
0e8cd71c
SK
6412 if (vha->vp_idx) {
6413 qla24xx_disable_vp(vha);
6414 qla24xx_enable_vp(vha);
6415 } else {
6416 set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
6417 qla2xxx_wake_dpc(base_vha);
6418 qla2x00_wait_for_hba_online(base_vha);
6419 }
2d70c103
NB
6420}
6421EXPORT_SYMBOL(qlt_enable_vha);
6422
6423/*
6424 * qla_tgt_disable_vha - NO LOCK HELD
6425 *
6426 * Disable Target Mode and reset the adapter
6427 */
55a9066f 6428static void qlt_disable_vha(struct scsi_qla_host *vha)
2d70c103
NB
6429{
6430 struct qla_hw_data *ha = vha->hw;
0e8cd71c 6431 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
2d70c103
NB
6432 unsigned long flags;
6433
6434 if (!tgt) {
6435 ql_dbg(ql_dbg_tgt, vha, 0xe06a,
6436 "Unable to locate qla_tgt pointer from"
6437 " struct qla_hw_data\n");
6438 dump_stack();
6439 return;
6440 }
6441
6442 spin_lock_irqsave(&ha->hardware_lock, flags);
6443 qlt_clear_mode(vha);
6444 spin_unlock_irqrestore(&ha->hardware_lock, flags);
6445
6446 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
6447 qla2xxx_wake_dpc(vha);
6448 qla2x00_wait_for_hba_online(vha);
6449}
6450
6451/*
6452 * Called from qla_init.c:qla24xx_vport_create() contex to setup
6453 * the target mode specific struct scsi_qla_host and struct qla_hw_data
6454 * members.
6455 */
6456void
6457qlt_vport_create(struct scsi_qla_host *vha, struct qla_hw_data *ha)
6458{
0e8cd71c
SK
6459 vha->vha_tgt.qla_tgt = NULL;
6460
6461 mutex_init(&vha->vha_tgt.tgt_mutex);
6462 mutex_init(&vha->vha_tgt.tgt_host_action_mutex);
2d70c103
NB
6463
6464 qlt_clear_mode(vha);
6465
6466 /*
6467 * NOTE: Currently the value is kept the same for <24xx and
6468 * >=24xx ISPs. If it is necessary to change it,
6469 * the check should be added for specific ISPs,
6470 * assigning the value appropriately.
6471 */
6472 ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX;
0e8cd71c
SK
6473
6474 qlt_add_target(ha, vha);
2d70c103
NB
6475}
6476
6477void
6478qlt_rff_id(struct scsi_qla_host *vha, struct ct_sns_req *ct_req)
6479{
6480 /*
6481 * FC-4 Feature bit 0 indicates target functionality to the name server.
6482 */
6483 if (qla_tgt_mode_enabled(vha)) {
726b8548 6484 ct_req->req.rff_id.fc4_feature = BIT_0;
2d70c103
NB
6485 } else if (qla_ini_mode_enabled(vha)) {
6486 ct_req->req.rff_id.fc4_feature = BIT_1;
726b8548
QT
6487 } else if (qla_dual_mode_enabled(vha))
6488 ct_req->req.rff_id.fc4_feature = BIT_0 | BIT_1;
2d70c103
NB
6489}
6490
6491/*
6492 * qlt_init_atio_q_entries() - Initializes ATIO queue entries.
6493 * @ha: HA context
6494 *
6495 * Beginning of ATIO ring has initialization control block already built
6496 * by nvram config routine.
6497 *
6498 * Returns 0 on success.
6499 */
6500void
6501qlt_init_atio_q_entries(struct scsi_qla_host *vha)
6502{
6503 struct qla_hw_data *ha = vha->hw;
6504 uint16_t cnt;
6505 struct atio_from_isp *pkt = (struct atio_from_isp *)ha->tgt.atio_ring;
6506
ead03855 6507 if (qla_ini_mode_enabled(vha))
2d70c103
NB
6508 return;
6509
6510 for (cnt = 0; cnt < ha->tgt.atio_q_length; cnt++) {
6511 pkt->u.raw.signature = ATIO_PROCESSED;
6512 pkt++;
6513 }
6514
6515}
6516
6517/*
6518 * qlt_24xx_process_atio_queue() - Process ATIO queue entries.
6519 * @ha: SCSI driver HA context
6520 */
6521void
2f424b9b 6522qlt_24xx_process_atio_queue(struct scsi_qla_host *vha, uint8_t ha_locked)
2d70c103
NB
6523{
6524 struct qla_hw_data *ha = vha->hw;
2d70c103
NB
6525 struct atio_from_isp *pkt;
6526 int cnt, i;
6527
ec7193e2 6528 if (!ha->flags.fw_started)
2d70c103
NB
6529 return;
6530
5f35509d
QT
6531 while ((ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) ||
6532 fcpcmd_is_corrupted(ha->tgt.atio_ring_ptr)) {
2d70c103
NB
6533 pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr;
6534 cnt = pkt->u.raw.entry_count;
6535
5f35509d
QT
6536 if (unlikely(fcpcmd_is_corrupted(ha->tgt.atio_ring_ptr))) {
6537 /*
6538 * This packet is corrupted. The header + payload
6539 * can not be trusted. There is no point in passing
6540 * it further up.
6541 */
83548fe2 6542 ql_log(ql_log_warn, vha, 0xd03c,
5f35509d
QT
6543 "corrupted fcp frame SID[%3phN] OXID[%04x] EXCG[%x] %64phN\n",
6544 pkt->u.isp24.fcp_hdr.s_id,
6545 be16_to_cpu(pkt->u.isp24.fcp_hdr.ox_id),
6546 le32_to_cpu(pkt->u.isp24.exchange_addr), pkt);
6547
6548 adjust_corrupted_atio(pkt);
82de802a
QT
6549 qlt_send_term_exchange(ha->base_qpair, NULL, pkt,
6550 ha_locked, 0);
5f35509d
QT
6551 } else {
6552 qlt_24xx_atio_pkt_all_vps(vha,
6553 (struct atio_from_isp *)pkt, ha_locked);
6554 }
2d70c103
NB
6555
6556 for (i = 0; i < cnt; i++) {
6557 ha->tgt.atio_ring_index++;
6558 if (ha->tgt.atio_ring_index == ha->tgt.atio_q_length) {
6559 ha->tgt.atio_ring_index = 0;
6560 ha->tgt.atio_ring_ptr = ha->tgt.atio_ring;
6561 } else
6562 ha->tgt.atio_ring_ptr++;
6563
6564 pkt->u.raw.signature = ATIO_PROCESSED;
6565 pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr;
6566 }
6567 wmb();
6568 }
6569
6570 /* Adjust ring index */
aa230bc5 6571 WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), ha->tgt.atio_ring_index);
3761f3e8 6572 RD_REG_DWORD_RELAXED(ISP_ATIO_Q_OUT(vha));
2d70c103
NB
6573}
6574
6575void
aa230bc5 6576qlt_24xx_config_rings(struct scsi_qla_host *vha)
2d70c103
NB
6577{
6578 struct qla_hw_data *ha = vha->hw;
aa230bc5
AE
6579 if (!QLA_TGT_MODE_ENABLED())
6580 return;
2d70c103 6581
aa230bc5
AE
6582 WRT_REG_DWORD(ISP_ATIO_Q_IN(vha), 0);
6583 WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), 0);
6584 RD_REG_DWORD(ISP_ATIO_Q_OUT(vha));
6585
6586 if (IS_ATIO_MSIX_CAPABLE(ha)) {
6587 struct qla_msix_entry *msix = &ha->msix_entries[2];
6588 struct init_cb_24xx *icb = (struct init_cb_24xx *)ha->init_cb;
6589
6590 icb->msix_atio = cpu_to_le16(msix->entry);
6591 ql_dbg(ql_dbg_init, vha, 0xf072,
6592 "Registering ICB vector 0x%x for atio que.\n",
6593 msix->entry);
2d70c103
NB
6594 }
6595}
6596
6597void
6598qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv)
6599{
6600 struct qla_hw_data *ha = vha->hw;
99e1b683
QT
6601
6602 if (!QLA_TGT_MODE_ENABLED())
6603 return;
2d70c103 6604
ead03855 6605 if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) {
2d70c103
NB
6606 if (!ha->tgt.saved_set) {
6607 /* We save only once */
6608 ha->tgt.saved_exchange_count = nv->exchange_count;
6609 ha->tgt.saved_firmware_options_1 =
6610 nv->firmware_options_1;
6611 ha->tgt.saved_firmware_options_2 =
6612 nv->firmware_options_2;
6613 ha->tgt.saved_firmware_options_3 =
6614 nv->firmware_options_3;
6615 ha->tgt.saved_set = 1;
6616 }
6617
99e1b683 6618 if (qla_tgt_mode_enabled(vha))
ead03855 6619 nv->exchange_count = cpu_to_le16(0xFFFF);
99e1b683
QT
6620 else /* dual */
6621 nv->exchange_count = cpu_to_le16(ql2xexchoffld);
2d70c103
NB
6622
6623 /* Enable target mode */
ad950360 6624 nv->firmware_options_1 |= cpu_to_le32(BIT_4);
2d70c103
NB
6625
6626 /* Disable ini mode, if requested */
726b8548 6627 if (qla_tgt_mode_enabled(vha))
ad950360 6628 nv->firmware_options_1 |= cpu_to_le32(BIT_5);
2d70c103
NB
6629
6630 /* Disable Full Login after LIP */
ad950360 6631 nv->firmware_options_1 &= cpu_to_le32(~BIT_13);
2d70c103 6632 /* Enable initial LIP */
ad950360 6633 nv->firmware_options_1 &= cpu_to_le32(~BIT_9);
d154f350
AE
6634 if (ql2xtgt_tape_enable)
6635 /* Enable FC Tape support */
6636 nv->firmware_options_2 |= cpu_to_le32(BIT_12);
6637 else
6638 /* Disable FC Tape support */
6639 nv->firmware_options_2 &= cpu_to_le32(~BIT_12);
6640
2d70c103 6641 /* Disable Full Login after LIP */
ad950360 6642 nv->host_p &= cpu_to_le32(~BIT_10);
c0f64627
HM
6643
6644 /*
6645 * clear BIT 15 explicitly as we have seen at least
6646 * a couple of instances where this was set and this
6647 * was causing the firmware to not be initialized.
6648 */
6649 nv->firmware_options_1 &= cpu_to_le32(~BIT_15);
2d70c103 6650 /* Enable target PRLI control */
ad950360 6651 nv->firmware_options_2 |= cpu_to_le32(BIT_14);
2d70c103
NB
6652 } else {
6653 if (ha->tgt.saved_set) {
6654 nv->exchange_count = ha->tgt.saved_exchange_count;
6655 nv->firmware_options_1 =
6656 ha->tgt.saved_firmware_options_1;
6657 nv->firmware_options_2 =
6658 ha->tgt.saved_firmware_options_2;
6659 nv->firmware_options_3 =
6660 ha->tgt.saved_firmware_options_3;
6661 }
6662 return;
6663 }
6664
7c3f8fd1 6665 if (ha->base_qpair->enable_class_2) {
2d70c103
NB
6666 if (vha->flags.init_done)
6667 fc_host_supported_classes(vha->host) =
6668 FC_COS_CLASS2 | FC_COS_CLASS3;
6669
ad950360 6670 nv->firmware_options_2 |= cpu_to_le32(BIT_8);
2d70c103
NB
6671 } else {
6672 if (vha->flags.init_done)
6673 fc_host_supported_classes(vha->host) = FC_COS_CLASS3;
6674
ad950360 6675 nv->firmware_options_2 &= ~cpu_to_le32(BIT_8);
2d70c103
NB
6676 }
6677}
6678
6679void
6680qlt_24xx_config_nvram_stage2(struct scsi_qla_host *vha,
6681 struct init_cb_24xx *icb)
6682{
6683 struct qla_hw_data *ha = vha->hw;
6684
481ce733
QT
6685 if (!QLA_TGT_MODE_ENABLED())
6686 return;
6687
2d70c103
NB
6688 if (ha->tgt.node_name_set) {
6689 memcpy(icb->node_name, ha->tgt.tgt_node_name, WWN_SIZE);
ad950360 6690 icb->firmware_options_1 |= cpu_to_le32(BIT_14);
2d70c103 6691 }
481ce733
QT
6692
6693 /* disable ZIO at start time. */
6694 if (!vha->flags.init_done) {
6695 uint32_t tmp;
6696 tmp = le32_to_cpu(icb->firmware_options_2);
6697 tmp &= ~(BIT_3 | BIT_2 | BIT_1 | BIT_0);
6698 icb->firmware_options_2 = cpu_to_le32(tmp);
6699 }
2d70c103
NB
6700}
6701
aa230bc5
AE
6702void
6703qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv)
6704{
6705 struct qla_hw_data *ha = vha->hw;
6706
6707 if (!QLA_TGT_MODE_ENABLED())
6708 return;
6709
ead03855 6710 if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) {
aa230bc5
AE
6711 if (!ha->tgt.saved_set) {
6712 /* We save only once */
6713 ha->tgt.saved_exchange_count = nv->exchange_count;
6714 ha->tgt.saved_firmware_options_1 =
6715 nv->firmware_options_1;
6716 ha->tgt.saved_firmware_options_2 =
6717 nv->firmware_options_2;
6718 ha->tgt.saved_firmware_options_3 =
6719 nv->firmware_options_3;
6720 ha->tgt.saved_set = 1;
6721 }
6722
99e1b683 6723 if (qla_tgt_mode_enabled(vha))
ead03855 6724 nv->exchange_count = cpu_to_le16(0xFFFF);
99e1b683
QT
6725 else /* dual */
6726 nv->exchange_count = cpu_to_le16(ql2xexchoffld);
aa230bc5
AE
6727
6728 /* Enable target mode */
ad950360 6729 nv->firmware_options_1 |= cpu_to_le32(BIT_4);
aa230bc5
AE
6730
6731 /* Disable ini mode, if requested */
726b8548 6732 if (qla_tgt_mode_enabled(vha))
ad950360 6733 nv->firmware_options_1 |= cpu_to_le32(BIT_5);
aa230bc5 6734 /* Disable Full Login after LIP */
ad950360 6735 nv->firmware_options_1 &= cpu_to_le32(~BIT_13);
aa230bc5 6736 /* Enable initial LIP */
ad950360 6737 nv->firmware_options_1 &= cpu_to_le32(~BIT_9);
c0f64627
HM
6738 /*
6739 * clear BIT 15 explicitly as we have seen at
6740 * least a couple of instances where this was set
6741 * and this was causing the firmware to not be
6742 * initialized.
6743 */
6744 nv->firmware_options_1 &= cpu_to_le32(~BIT_15);
d154f350
AE
6745 if (ql2xtgt_tape_enable)
6746 /* Enable FC tape support */
6747 nv->firmware_options_2 |= cpu_to_le32(BIT_12);
6748 else
6749 /* Disable FC tape support */
6750 nv->firmware_options_2 &= cpu_to_le32(~BIT_12);
6751
aa230bc5 6752 /* Disable Full Login after LIP */
ad950360 6753 nv->host_p &= cpu_to_le32(~BIT_10);
aa230bc5 6754 /* Enable target PRLI control */
ad950360 6755 nv->firmware_options_2 |= cpu_to_le32(BIT_14);
aa230bc5
AE
6756 } else {
6757 if (ha->tgt.saved_set) {
6758 nv->exchange_count = ha->tgt.saved_exchange_count;
6759 nv->firmware_options_1 =
6760 ha->tgt.saved_firmware_options_1;
6761 nv->firmware_options_2 =
6762 ha->tgt.saved_firmware_options_2;
6763 nv->firmware_options_3 =
6764 ha->tgt.saved_firmware_options_3;
6765 }
6766 return;
6767 }
6768
7c3f8fd1 6769 if (ha->base_qpair->enable_class_2) {
aa230bc5
AE
6770 if (vha->flags.init_done)
6771 fc_host_supported_classes(vha->host) =
6772 FC_COS_CLASS2 | FC_COS_CLASS3;
6773
ad950360 6774 nv->firmware_options_2 |= cpu_to_le32(BIT_8);
aa230bc5
AE
6775 } else {
6776 if (vha->flags.init_done)
6777 fc_host_supported_classes(vha->host) = FC_COS_CLASS3;
6778
ad950360 6779 nv->firmware_options_2 &= ~cpu_to_le32(BIT_8);
aa230bc5
AE
6780 }
6781}
6782
6783void
6784qlt_81xx_config_nvram_stage2(struct scsi_qla_host *vha,
6785 struct init_cb_81xx *icb)
6786{
6787 struct qla_hw_data *ha = vha->hw;
6788
6789 if (!QLA_TGT_MODE_ENABLED())
6790 return;
6791
6792 if (ha->tgt.node_name_set) {
6793 memcpy(icb->node_name, ha->tgt.tgt_node_name, WWN_SIZE);
ad950360 6794 icb->firmware_options_1 |= cpu_to_le32(BIT_14);
aa230bc5 6795 }
481ce733
QT
6796
6797 /* disable ZIO at start time. */
6798 if (!vha->flags.init_done) {
6799 uint32_t tmp;
6800 tmp = le32_to_cpu(icb->firmware_options_2);
6801 tmp &= ~(BIT_3 | BIT_2 | BIT_1 | BIT_0);
6802 icb->firmware_options_2 = cpu_to_le32(tmp);
6803 }
6804
aa230bc5
AE
6805}
6806
6807void
6808qlt_83xx_iospace_config(struct qla_hw_data *ha)
6809{
6810 if (!QLA_TGT_MODE_ENABLED())
6811 return;
6812
6813 ha->msix_count += 1; /* For ATIO Q */
6814}
6815
2d70c103
NB
6816
6817void
6818qlt_modify_vp_config(struct scsi_qla_host *vha,
6819 struct vp_config_entry_24xx *vpmod)
6820{
ead03855
QT
6821 /* enable target mode. Bit5 = 1 => disable */
6822 if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha))
2d70c103 6823 vpmod->options_idx1 &= ~BIT_5;
726b8548 6824
ead03855 6825 /* Disable ini mode, if requested. bit4 = 1 => disable */
726b8548 6826 if (qla_tgt_mode_enabled(vha))
2d70c103
NB
6827 vpmod->options_idx1 &= ~BIT_4;
6828}
6829
6830void
6831qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
6832{
482c9dc7
QT
6833 int rc;
6834
2d70c103
NB
6835 if (!QLA_TGT_MODE_ENABLED())
6836 return;
6837
b20f02e1 6838 if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
aa230bc5
AE
6839 ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in;
6840 ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out;
6841 } else {
6842 ISP_ATIO_Q_IN(base_vha) = &ha->iobase->isp24.atio_q_in;
6843 ISP_ATIO_Q_OUT(base_vha) = &ha->iobase->isp24.atio_q_out;
6844 }
6845
0e8cd71c
SK
6846 mutex_init(&base_vha->vha_tgt.tgt_mutex);
6847 mutex_init(&base_vha->vha_tgt.tgt_host_action_mutex);
41dc529a
QT
6848
6849 INIT_LIST_HEAD(&base_vha->unknown_atio_list);
6850 INIT_DELAYED_WORK(&base_vha->unknown_atio_work,
6851 qlt_unknown_atio_work_fn);
6852
2d70c103 6853 qlt_clear_mode(base_vha);
482c9dc7
QT
6854
6855 rc = btree_init32(&ha->tgt.host_map);
6856 if (rc)
83548fe2 6857 ql_log(ql_log_info, base_vha, 0xd03d,
482c9dc7
QT
6858 "Unable to initialize ha->host_map btree\n");
6859
6860 qlt_update_vp_map(base_vha, SET_VP_IDX);
2d70c103
NB
6861}
6862
aa230bc5
AE
6863irqreturn_t
6864qla83xx_msix_atio_q(int irq, void *dev_id)
6865{
6866 struct rsp_que *rsp;
6867 scsi_qla_host_t *vha;
6868 struct qla_hw_data *ha;
6869 unsigned long flags;
6870
6871 rsp = (struct rsp_que *) dev_id;
6872 ha = rsp->hw;
6873 vha = pci_get_drvdata(ha->pdev);
6874
2f424b9b 6875 spin_lock_irqsave(&ha->tgt.atio_lock, flags);
aa230bc5 6876
2f424b9b 6877 qlt_24xx_process_atio_queue(vha, 0);
aa230bc5 6878
2f424b9b 6879 spin_unlock_irqrestore(&ha->tgt.atio_lock, flags);
aa230bc5
AE
6880
6881 return IRQ_HANDLED;
6882}
6883
2f424b9b
QT
6884static void
6885qlt_handle_abts_recv_work(struct work_struct *work)
6886{
6887 struct qla_tgt_sess_op *op = container_of(work,
6888 struct qla_tgt_sess_op, work);
6889 scsi_qla_host_t *vha = op->vha;
6890 struct qla_hw_data *ha = vha->hw;
6891 unsigned long flags;
6892
7c3f8fd1
QT
6893 if (qla2x00_reset_active(vha) ||
6894 (op->chip_reset != ha->base_qpair->chip_reset))
2f424b9b
QT
6895 return;
6896
6897 spin_lock_irqsave(&ha->tgt.atio_lock, flags);
6898 qlt_24xx_process_atio_queue(vha, 0);
6899 spin_unlock_irqrestore(&ha->tgt.atio_lock, flags);
6900
6901 spin_lock_irqsave(&ha->hardware_lock, flags);
82de802a 6902 qlt_response_pkt_all_vps(vha, op->rsp, (response_t *)&op->atio);
2f424b9b 6903 spin_unlock_irqrestore(&ha->hardware_lock, flags);
ae940f2c
QT
6904
6905 kfree(op);
2f424b9b
QT
6906}
6907
6908void
82de802a
QT
6909qlt_handle_abts_recv(struct scsi_qla_host *vha, struct rsp_que *rsp,
6910 response_t *pkt)
2f424b9b
QT
6911{
6912 struct qla_tgt_sess_op *op;
6913
6914 op = kzalloc(sizeof(*op), GFP_ATOMIC);
6915
6916 if (!op) {
6917 /* do not reach for ATIO queue here. This is best effort err
6918 * recovery at this point.
6919 */
82de802a 6920 qlt_response_pkt_all_vps(vha, rsp, pkt);
2f424b9b
QT
6921 return;
6922 }
6923
6924 memcpy(&op->atio, pkt, sizeof(*pkt));
6925 op->vha = vha;
7c3f8fd1 6926 op->chip_reset = vha->hw->base_qpair->chip_reset;
82de802a 6927 op->rsp = rsp;
2f424b9b
QT
6928 INIT_WORK(&op->work, qlt_handle_abts_recv_work);
6929 queue_work(qla_tgt_wq, &op->work);
6930 return;
6931}
6932
2d70c103
NB
6933int
6934qlt_mem_alloc(struct qla_hw_data *ha)
6935{
6936 if (!QLA_TGT_MODE_ENABLED())
6937 return 0;
6938
6939 ha->tgt.tgt_vp_map = kzalloc(sizeof(struct qla_tgt_vp_map) *
6940 MAX_MULTI_ID_FABRIC, GFP_KERNEL);
6941 if (!ha->tgt.tgt_vp_map)
6942 return -ENOMEM;
6943
6944 ha->tgt.atio_ring = dma_alloc_coherent(&ha->pdev->dev,
6945 (ha->tgt.atio_q_length + 1) * sizeof(struct atio_from_isp),
6946 &ha->tgt.atio_dma, GFP_KERNEL);
6947 if (!ha->tgt.atio_ring) {
6948 kfree(ha->tgt.tgt_vp_map);
6949 return -ENOMEM;
6950 }
6951 return 0;
6952}
6953
6954void
6955qlt_mem_free(struct qla_hw_data *ha)
6956{
6957 if (!QLA_TGT_MODE_ENABLED())
6958 return;
6959
6960 if (ha->tgt.atio_ring) {
6961 dma_free_coherent(&ha->pdev->dev, (ha->tgt.atio_q_length + 1) *
6962 sizeof(struct atio_from_isp), ha->tgt.atio_ring,
6963 ha->tgt.atio_dma);
6964 }
6965 kfree(ha->tgt.tgt_vp_map);
6966}
6967
6968/* vport_slock to be held by the caller */
6969void
6970qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
6971{
482c9dc7
QT
6972 void *slot;
6973 u32 key;
6974 int rc;
6975
2d70c103
NB
6976 if (!QLA_TGT_MODE_ENABLED())
6977 return;
6978
482c9dc7
QT
6979 key = vha->d_id.b24;
6980
2d70c103
NB
6981 switch (cmd) {
6982 case SET_VP_IDX:
6983 vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = vha;
6984 break;
6985 case SET_AL_PA:
482c9dc7
QT
6986 slot = btree_lookup32(&vha->hw->tgt.host_map, key);
6987 if (!slot) {
83548fe2 6988 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf018,
482c9dc7
QT
6989 "Save vha in host_map %p %06x\n", vha, key);
6990 rc = btree_insert32(&vha->hw->tgt.host_map,
6991 key, vha, GFP_ATOMIC);
6992 if (rc)
83548fe2 6993 ql_log(ql_log_info, vha, 0xd03e,
482c9dc7
QT
6994 "Unable to insert s_id into host_map: %06x\n",
6995 key);
6996 return;
6997 }
83548fe2
QT
6998 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf019,
6999 "replace existing vha in host_map %p %06x\n", vha, key);
482c9dc7 7000 btree_update32(&vha->hw->tgt.host_map, key, vha);
2d70c103
NB
7001 break;
7002 case RESET_VP_IDX:
7003 vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = NULL;
7004 break;
7005 case RESET_AL_PA:
83548fe2 7006 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01a,
482c9dc7
QT
7007 "clear vha in host_map %p %06x\n", vha, key);
7008 slot = btree_lookup32(&vha->hw->tgt.host_map, key);
7009 if (slot)
7010 btree_remove32(&vha->hw->tgt.host_map, key);
7011 vha->d_id.b24 = 0;
2d70c103
NB
7012 break;
7013 }
7014}
7015
482c9dc7
QT
7016void qlt_update_host_map(struct scsi_qla_host *vha, port_id_t id)
7017{
7018 unsigned long flags;
7019 struct qla_hw_data *ha = vha->hw;
7020
7021 if (!vha->d_id.b24) {
7022 spin_lock_irqsave(&ha->vport_slock, flags);
7023 vha->d_id = id;
7024 qlt_update_vp_map(vha, SET_AL_PA);
7025 spin_unlock_irqrestore(&ha->vport_slock, flags);
7026 } else if (vha->d_id.b24 != id.b24) {
7027 spin_lock_irqsave(&ha->vport_slock, flags);
7028 qlt_update_vp_map(vha, RESET_AL_PA);
7029 vha->d_id = id;
7030 qlt_update_vp_map(vha, SET_AL_PA);
7031 spin_unlock_irqrestore(&ha->vport_slock, flags);
7032 }
7033}
7034
2d70c103
NB
7035static int __init qlt_parse_ini_mode(void)
7036{
7037 if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_EXCLUSIVE) == 0)
7038 ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE;
7039 else if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_DISABLED) == 0)
7040 ql2x_ini_mode = QLA2XXX_INI_MODE_DISABLED;
7041 else if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_ENABLED) == 0)
7042 ql2x_ini_mode = QLA2XXX_INI_MODE_ENABLED;
ead03855
QT
7043 else if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_DUAL) == 0)
7044 ql2x_ini_mode = QLA2XXX_INI_MODE_DUAL;
2d70c103
NB
7045 else
7046 return false;
7047
7048 return true;
7049}
7050
7051int __init qlt_init(void)
7052{
7053 int ret;
7054
7055 if (!qlt_parse_ini_mode()) {
7056 ql_log(ql_log_fatal, NULL, 0xe06b,
7057 "qlt_parse_ini_mode() failed\n");
7058 return -EINVAL;
7059 }
7060
7061 if (!QLA_TGT_MODE_ENABLED())
7062 return 0;
7063
2d70c103
NB
7064 qla_tgt_mgmt_cmd_cachep = kmem_cache_create("qla_tgt_mgmt_cmd_cachep",
7065 sizeof(struct qla_tgt_mgmt_cmd), __alignof__(struct
7066 qla_tgt_mgmt_cmd), 0, NULL);
7067 if (!qla_tgt_mgmt_cmd_cachep) {
83548fe2 7068 ql_log(ql_log_fatal, NULL, 0xd04b,
2d70c103 7069 "kmem_cache_create for qla_tgt_mgmt_cmd_cachep failed\n");
51a07f84 7070 return -ENOMEM;
2d70c103
NB
7071 }
7072
b7bd104e 7073 qla_tgt_plogi_cachep = kmem_cache_create("qla_tgt_plogi_cachep",
5d964837
QT
7074 sizeof(struct qlt_plogi_ack_t), __alignof__(struct qlt_plogi_ack_t),
7075 0, NULL);
b7bd104e
AP
7076
7077 if (!qla_tgt_plogi_cachep) {
7078 ql_log(ql_log_fatal, NULL, 0xe06d,
7079 "kmem_cache_create for qla_tgt_plogi_cachep failed\n");
7080 ret = -ENOMEM;
7081 goto out_mgmt_cmd_cachep;
7082 }
7083
2d70c103
NB
7084 qla_tgt_mgmt_cmd_mempool = mempool_create(25, mempool_alloc_slab,
7085 mempool_free_slab, qla_tgt_mgmt_cmd_cachep);
7086 if (!qla_tgt_mgmt_cmd_mempool) {
7087 ql_log(ql_log_fatal, NULL, 0xe06e,
7088 "mempool_create for qla_tgt_mgmt_cmd_mempool failed\n");
7089 ret = -ENOMEM;
b7bd104e 7090 goto out_plogi_cachep;
2d70c103
NB
7091 }
7092
7093 qla_tgt_wq = alloc_workqueue("qla_tgt_wq", 0, 0);
7094 if (!qla_tgt_wq) {
7095 ql_log(ql_log_fatal, NULL, 0xe06f,
7096 "alloc_workqueue for qla_tgt_wq failed\n");
7097 ret = -ENOMEM;
7098 goto out_cmd_mempool;
7099 }
7100 /*
7101 * Return 1 to signal that initiator-mode is being disabled
7102 */
7103 return (ql2x_ini_mode == QLA2XXX_INI_MODE_DISABLED) ? 1 : 0;
7104
7105out_cmd_mempool:
7106 mempool_destroy(qla_tgt_mgmt_cmd_mempool);
b7bd104e
AP
7107out_plogi_cachep:
7108 kmem_cache_destroy(qla_tgt_plogi_cachep);
2d70c103
NB
7109out_mgmt_cmd_cachep:
7110 kmem_cache_destroy(qla_tgt_mgmt_cmd_cachep);
2d70c103
NB
7111 return ret;
7112}
7113
7114void qlt_exit(void)
7115{
7116 if (!QLA_TGT_MODE_ENABLED())
7117 return;
7118
7119 destroy_workqueue(qla_tgt_wq);
7120 mempool_destroy(qla_tgt_mgmt_cmd_mempool);
b7bd104e 7121 kmem_cache_destroy(qla_tgt_plogi_cachep);
2d70c103 7122 kmem_cache_destroy(qla_tgt_mgmt_cmd_cachep);
2d70c103 7123}