1dfb99b05SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2dfb99b05SThomas Gleixner // Copyright 2014 Cisco Systems, Inc. All rights reserved.
3c8806b6cSNarsimhulu Musini
4c8806b6cSNarsimhulu Musini #include <linux/mempool.h>
5c8806b6cSNarsimhulu Musini #include <linux/errno.h>
6c8806b6cSNarsimhulu Musini #include <linux/init.h>
7c8806b6cSNarsimhulu Musini #include <linux/workqueue.h>
8c8806b6cSNarsimhulu Musini #include <linux/pci.h>
9c8806b6cSNarsimhulu Musini #include <linux/spinlock.h>
10c8806b6cSNarsimhulu Musini #include <linux/delay.h>
11c8806b6cSNarsimhulu Musini #include <linux/gfp.h>
12c8806b6cSNarsimhulu Musini #include <scsi/scsi.h>
13c8806b6cSNarsimhulu Musini #include <scsi/scsi_host.h>
14c8806b6cSNarsimhulu Musini #include <scsi/scsi_device.h>
15c8806b6cSNarsimhulu Musini #include <scsi/scsi_cmnd.h>
16c8806b6cSNarsimhulu Musini #include <scsi/scsi_tcq.h>
17c8806b6cSNarsimhulu Musini #include <scsi/scsi_dbg.h>
18c8806b6cSNarsimhulu Musini
19c8806b6cSNarsimhulu Musini #include "snic_io.h"
20c8806b6cSNarsimhulu Musini #include "snic.h"
21c8806b6cSNarsimhulu Musini
22ec808ef9SBart Van Assche #define snic_cmd_tag(sc) (scsi_cmd_to_rq(sc)->tag)
23c8806b6cSNarsimhulu Musini
24c8806b6cSNarsimhulu Musini const char *snic_state_str[] = {
25c8806b6cSNarsimhulu Musini [SNIC_INIT] = "SNIC_INIT",
26c8806b6cSNarsimhulu Musini [SNIC_ERROR] = "SNIC_ERROR",
27c8806b6cSNarsimhulu Musini [SNIC_ONLINE] = "SNIC_ONLINE",
28c8806b6cSNarsimhulu Musini [SNIC_OFFLINE] = "SNIC_OFFLINE",
29c8806b6cSNarsimhulu Musini [SNIC_FWRESET] = "SNIC_FWRESET",
30c8806b6cSNarsimhulu Musini };
31c8806b6cSNarsimhulu Musini
32c8806b6cSNarsimhulu Musini static const char * const snic_req_state_str[] = {
33c8806b6cSNarsimhulu Musini [SNIC_IOREQ_NOT_INITED] = "SNIC_IOREQ_NOT_INITED",
34c8806b6cSNarsimhulu Musini [SNIC_IOREQ_PENDING] = "SNIC_IOREQ_PENDING",
35c8806b6cSNarsimhulu Musini [SNIC_IOREQ_ABTS_PENDING] = "SNIC_IOREQ_ABTS_PENDING",
36017b3f8aSColin Ian King [SNIC_IOREQ_ABTS_COMPLETE] = "SNIC_IOREQ_ABTS_COMPLETE",
37c8806b6cSNarsimhulu Musini [SNIC_IOREQ_LR_PENDING] = "SNIC_IOREQ_LR_PENDING",
38017b3f8aSColin Ian King [SNIC_IOREQ_LR_COMPLETE] = "SNIC_IOREQ_LR_COMPLETE",
39017b3f8aSColin Ian King [SNIC_IOREQ_COMPLETE] = "SNIC_IOREQ_CMD_COMPLETE",
40c8806b6cSNarsimhulu Musini };
41c8806b6cSNarsimhulu Musini
42c8806b6cSNarsimhulu Musini /* snic cmd status strings */
43c8806b6cSNarsimhulu Musini static const char * const snic_io_status_str[] = {
44c8806b6cSNarsimhulu Musini [SNIC_STAT_IO_SUCCESS] = "SNIC_STAT_IO_SUCCESS", /* 0x0 */
45c8806b6cSNarsimhulu Musini [SNIC_STAT_INVALID_HDR] = "SNIC_STAT_INVALID_HDR",
46c8806b6cSNarsimhulu Musini [SNIC_STAT_OUT_OF_RES] = "SNIC_STAT_OUT_OF_RES",
47c8806b6cSNarsimhulu Musini [SNIC_STAT_INVALID_PARM] = "SNIC_STAT_INVALID_PARM",
48c8806b6cSNarsimhulu Musini [SNIC_STAT_REQ_NOT_SUP] = "SNIC_STAT_REQ_NOT_SUP",
49c8806b6cSNarsimhulu Musini [SNIC_STAT_IO_NOT_FOUND] = "SNIC_STAT_IO_NOT_FOUND",
50c8806b6cSNarsimhulu Musini [SNIC_STAT_ABORTED] = "SNIC_STAT_ABORTED",
51c8806b6cSNarsimhulu Musini [SNIC_STAT_TIMEOUT] = "SNIC_STAT_TIMEOUT",
52c8806b6cSNarsimhulu Musini [SNIC_STAT_SGL_INVALID] = "SNIC_STAT_SGL_INVALID",
53c8806b6cSNarsimhulu Musini [SNIC_STAT_DATA_CNT_MISMATCH] = "SNIC_STAT_DATA_CNT_MISMATCH",
54c8806b6cSNarsimhulu Musini [SNIC_STAT_FW_ERR] = "SNIC_STAT_FW_ERR",
55c8806b6cSNarsimhulu Musini [SNIC_STAT_ITMF_REJECT] = "SNIC_STAT_ITMF_REJECT",
56c8806b6cSNarsimhulu Musini [SNIC_STAT_ITMF_FAIL] = "SNIC_STAT_ITMF_FAIL",
57c8806b6cSNarsimhulu Musini [SNIC_STAT_ITMF_INCORRECT_LUN] = "SNIC_STAT_ITMF_INCORRECT_LUN",
58c8806b6cSNarsimhulu Musini [SNIC_STAT_CMND_REJECT] = "SNIC_STAT_CMND_REJECT",
59c8806b6cSNarsimhulu Musini [SNIC_STAT_DEV_OFFLINE] = "SNIC_STAT_DEV_OFFLINE",
60c8806b6cSNarsimhulu Musini [SNIC_STAT_NO_BOOTLUN] = "SNIC_STAT_NO_BOOTLUN",
61c8806b6cSNarsimhulu Musini [SNIC_STAT_SCSI_ERR] = "SNIC_STAT_SCSI_ERR",
62c8806b6cSNarsimhulu Musini [SNIC_STAT_NOT_READY] = "SNIC_STAT_NOT_READY",
63c8806b6cSNarsimhulu Musini [SNIC_STAT_FATAL_ERROR] = "SNIC_STAT_FATAL_ERROR",
64c8806b6cSNarsimhulu Musini };
65c8806b6cSNarsimhulu Musini
66c8806b6cSNarsimhulu Musini static void snic_scsi_cleanup(struct snic *, int);
67c8806b6cSNarsimhulu Musini
68c8806b6cSNarsimhulu Musini const char *
snic_state_to_str(unsigned int state)69c8806b6cSNarsimhulu Musini snic_state_to_str(unsigned int state)
70c8806b6cSNarsimhulu Musini {
71c8806b6cSNarsimhulu Musini if (state >= ARRAY_SIZE(snic_state_str) || !snic_state_str[state])
72c8806b6cSNarsimhulu Musini return "Unknown";
73c8806b6cSNarsimhulu Musini
74c8806b6cSNarsimhulu Musini return snic_state_str[state];
75c8806b6cSNarsimhulu Musini }
76c8806b6cSNarsimhulu Musini
77c8806b6cSNarsimhulu Musini static const char *
snic_io_status_to_str(unsigned int state)78c8806b6cSNarsimhulu Musini snic_io_status_to_str(unsigned int state)
79c8806b6cSNarsimhulu Musini {
80c8806b6cSNarsimhulu Musini if ((state >= ARRAY_SIZE(snic_io_status_str)) ||
81c8806b6cSNarsimhulu Musini (!snic_io_status_str[state]))
82c8806b6cSNarsimhulu Musini return "Unknown";
83c8806b6cSNarsimhulu Musini
84c8806b6cSNarsimhulu Musini return snic_io_status_str[state];
85c8806b6cSNarsimhulu Musini }
86c8806b6cSNarsimhulu Musini
87c8806b6cSNarsimhulu Musini static const char *
snic_ioreq_state_to_str(unsigned int state)88c8806b6cSNarsimhulu Musini snic_ioreq_state_to_str(unsigned int state)
89c8806b6cSNarsimhulu Musini {
90c8806b6cSNarsimhulu Musini if (state >= ARRAY_SIZE(snic_req_state_str) ||
91c8806b6cSNarsimhulu Musini !snic_req_state_str[state])
92c8806b6cSNarsimhulu Musini return "Unknown";
93c8806b6cSNarsimhulu Musini
94c8806b6cSNarsimhulu Musini return snic_req_state_str[state];
95c8806b6cSNarsimhulu Musini }
96c8806b6cSNarsimhulu Musini
97c8806b6cSNarsimhulu Musini static inline spinlock_t *
snic_io_lock_hash(struct snic * snic,struct scsi_cmnd * sc)98c8806b6cSNarsimhulu Musini snic_io_lock_hash(struct snic *snic, struct scsi_cmnd *sc)
99c8806b6cSNarsimhulu Musini {
100c8806b6cSNarsimhulu Musini u32 hash = snic_cmd_tag(sc) & (SNIC_IO_LOCKS - 1);
101c8806b6cSNarsimhulu Musini
102c8806b6cSNarsimhulu Musini return &snic->io_req_lock[hash];
103c8806b6cSNarsimhulu Musini }
104c8806b6cSNarsimhulu Musini
105c8806b6cSNarsimhulu Musini static inline spinlock_t *
snic_io_lock_tag(struct snic * snic,int tag)106c8806b6cSNarsimhulu Musini snic_io_lock_tag(struct snic *snic, int tag)
107c8806b6cSNarsimhulu Musini {
108c8806b6cSNarsimhulu Musini return &snic->io_req_lock[tag & (SNIC_IO_LOCKS - 1)];
109c8806b6cSNarsimhulu Musini }
110c8806b6cSNarsimhulu Musini
111c8806b6cSNarsimhulu Musini /* snic_release_req_buf : Releases snic_req_info */
112c8806b6cSNarsimhulu Musini static void
snic_release_req_buf(struct snic * snic,struct snic_req_info * rqi,struct scsi_cmnd * sc)113c8806b6cSNarsimhulu Musini snic_release_req_buf(struct snic *snic,
114c8806b6cSNarsimhulu Musini struct snic_req_info *rqi,
115c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc)
116c8806b6cSNarsimhulu Musini {
117c8806b6cSNarsimhulu Musini struct snic_host_req *req = rqi_to_req(rqi);
118c8806b6cSNarsimhulu Musini
119c8806b6cSNarsimhulu Musini /* Freeing cmd without marking completion, not okay */
120c8806b6cSNarsimhulu Musini SNIC_BUG_ON(!((CMD_STATE(sc) == SNIC_IOREQ_COMPLETE) ||
121c8806b6cSNarsimhulu Musini (CMD_STATE(sc) == SNIC_IOREQ_ABTS_COMPLETE) ||
122c8806b6cSNarsimhulu Musini (CMD_FLAGS(sc) & SNIC_DEV_RST_NOTSUP) ||
123c8806b6cSNarsimhulu Musini (CMD_FLAGS(sc) & SNIC_IO_INTERNAL_TERM_ISSUED) ||
124c8806b6cSNarsimhulu Musini (CMD_FLAGS(sc) & SNIC_DEV_RST_TERM_ISSUED) ||
125c8806b6cSNarsimhulu Musini (CMD_FLAGS(sc) & SNIC_SCSI_CLEANUP) ||
126c8806b6cSNarsimhulu Musini (CMD_STATE(sc) == SNIC_IOREQ_LR_COMPLETE)));
127c8806b6cSNarsimhulu Musini
128c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
129c8806b6cSNarsimhulu Musini "Rel_req:sc %p:tag %x:rqi %p:ioreq %p:abt %p:dr %p: state %s:flags 0x%llx\n",
130c8806b6cSNarsimhulu Musini sc, snic_cmd_tag(sc), rqi, rqi->req, rqi->abort_req,
131c8806b6cSNarsimhulu Musini rqi->dr_req, snic_ioreq_state_to_str(CMD_STATE(sc)),
132c8806b6cSNarsimhulu Musini CMD_FLAGS(sc));
133c8806b6cSNarsimhulu Musini
134c8806b6cSNarsimhulu Musini if (req->u.icmnd.sense_addr)
135cecfed31SChristoph Hellwig dma_unmap_single(&snic->pdev->dev,
136c8806b6cSNarsimhulu Musini le64_to_cpu(req->u.icmnd.sense_addr),
137c8806b6cSNarsimhulu Musini SCSI_SENSE_BUFFERSIZE,
138cecfed31SChristoph Hellwig DMA_FROM_DEVICE);
139c8806b6cSNarsimhulu Musini
140c8806b6cSNarsimhulu Musini scsi_dma_unmap(sc);
141c8806b6cSNarsimhulu Musini
142c8806b6cSNarsimhulu Musini snic_req_free(snic, rqi);
143c8806b6cSNarsimhulu Musini } /* end of snic_release_req_buf */
144c8806b6cSNarsimhulu Musini
145c8806b6cSNarsimhulu Musini /*
146c8806b6cSNarsimhulu Musini * snic_queue_icmnd_req : Queues snic_icmnd request
147c8806b6cSNarsimhulu Musini */
148c8806b6cSNarsimhulu Musini static int
snic_queue_icmnd_req(struct snic * snic,struct snic_req_info * rqi,struct scsi_cmnd * sc,int sg_cnt)149c8806b6cSNarsimhulu Musini snic_queue_icmnd_req(struct snic *snic,
150c8806b6cSNarsimhulu Musini struct snic_req_info *rqi,
151c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc,
152c8806b6cSNarsimhulu Musini int sg_cnt)
153c8806b6cSNarsimhulu Musini {
154c8806b6cSNarsimhulu Musini struct scatterlist *sg;
155c8806b6cSNarsimhulu Musini struct snic_sg_desc *sgd;
156c8806b6cSNarsimhulu Musini dma_addr_t pa = 0;
157c8806b6cSNarsimhulu Musini struct scsi_lun lun;
158c8806b6cSNarsimhulu Musini u16 flags = 0;
159c8806b6cSNarsimhulu Musini int ret = 0;
160c8806b6cSNarsimhulu Musini unsigned int i;
161c8806b6cSNarsimhulu Musini
162c8806b6cSNarsimhulu Musini if (sg_cnt) {
163c8806b6cSNarsimhulu Musini flags = SNIC_ICMND_ESGL;
164c8806b6cSNarsimhulu Musini sgd = (struct snic_sg_desc *) req_to_sgl(rqi->req);
165c8806b6cSNarsimhulu Musini
166c8806b6cSNarsimhulu Musini for_each_sg(scsi_sglist(sc), sg, sg_cnt, i) {
167c8806b6cSNarsimhulu Musini sgd->addr = cpu_to_le64(sg_dma_address(sg));
168c8806b6cSNarsimhulu Musini sgd->len = cpu_to_le32(sg_dma_len(sg));
169c8806b6cSNarsimhulu Musini sgd->_resvd = 0;
170c8806b6cSNarsimhulu Musini sgd++;
171c8806b6cSNarsimhulu Musini }
172c8806b6cSNarsimhulu Musini }
173c8806b6cSNarsimhulu Musini
174cecfed31SChristoph Hellwig pa = dma_map_single(&snic->pdev->dev,
175c8806b6cSNarsimhulu Musini sc->sense_buffer,
176c8806b6cSNarsimhulu Musini SCSI_SENSE_BUFFERSIZE,
177cecfed31SChristoph Hellwig DMA_FROM_DEVICE);
178cecfed31SChristoph Hellwig if (dma_mapping_error(&snic->pdev->dev, pa)) {
179c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
180c8806b6cSNarsimhulu Musini "QIcmnd:PCI Map Failed for sns buf %p tag %x\n",
181c8806b6cSNarsimhulu Musini sc->sense_buffer, snic_cmd_tag(sc));
182c8806b6cSNarsimhulu Musini ret = -ENOMEM;
183c8806b6cSNarsimhulu Musini
184c8806b6cSNarsimhulu Musini return ret;
185c8806b6cSNarsimhulu Musini }
186c8806b6cSNarsimhulu Musini
187c8806b6cSNarsimhulu Musini int_to_scsilun(sc->device->lun, &lun);
188c8806b6cSNarsimhulu Musini if (sc->sc_data_direction == DMA_FROM_DEVICE)
189c8806b6cSNarsimhulu Musini flags |= SNIC_ICMND_RD;
190c8806b6cSNarsimhulu Musini if (sc->sc_data_direction == DMA_TO_DEVICE)
191c8806b6cSNarsimhulu Musini flags |= SNIC_ICMND_WR;
192c8806b6cSNarsimhulu Musini
193c8806b6cSNarsimhulu Musini /* Initialize icmnd */
194c8806b6cSNarsimhulu Musini snic_icmnd_init(rqi->req,
195c8806b6cSNarsimhulu Musini snic_cmd_tag(sc),
196c8806b6cSNarsimhulu Musini snic->config.hid, /* hid */
197c8806b6cSNarsimhulu Musini (ulong) rqi,
198c8806b6cSNarsimhulu Musini flags, /* command flags */
199c8806b6cSNarsimhulu Musini rqi->tgt_id,
200c8806b6cSNarsimhulu Musini lun.scsi_lun,
201c8806b6cSNarsimhulu Musini sc->cmnd,
202c8806b6cSNarsimhulu Musini sc->cmd_len,
203c8806b6cSNarsimhulu Musini scsi_bufflen(sc),
204c8806b6cSNarsimhulu Musini sg_cnt,
205c8806b6cSNarsimhulu Musini (ulong) req_to_sgl(rqi->req),
206c8806b6cSNarsimhulu Musini pa, /* sense buffer pa */
207c8806b6cSNarsimhulu Musini SCSI_SENSE_BUFFERSIZE);
208c8806b6cSNarsimhulu Musini
2093f5c11a4SNarsimhulu Musini atomic64_inc(&snic->s_stats.io.active);
210c8806b6cSNarsimhulu Musini ret = snic_queue_wq_desc(snic, rqi->req, rqi->req_len);
2113f5c11a4SNarsimhulu Musini if (ret) {
2123f5c11a4SNarsimhulu Musini atomic64_dec(&snic->s_stats.io.active);
213c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
214c8806b6cSNarsimhulu Musini "QIcmnd: Queuing Icmnd Failed. ret = %d\n",
215c8806b6cSNarsimhulu Musini ret);
2163f5c11a4SNarsimhulu Musini } else
2173f5c11a4SNarsimhulu Musini snic_stats_update_active_ios(&snic->s_stats);
218c8806b6cSNarsimhulu Musini
219c8806b6cSNarsimhulu Musini return ret;
220c8806b6cSNarsimhulu Musini } /* end of snic_queue_icmnd_req */
221c8806b6cSNarsimhulu Musini
222c8806b6cSNarsimhulu Musini /*
223c8806b6cSNarsimhulu Musini * snic_issue_scsi_req : Prepares IO request and Issues to FW.
224c8806b6cSNarsimhulu Musini */
225c8806b6cSNarsimhulu Musini static int
snic_issue_scsi_req(struct snic * snic,struct snic_tgt * tgt,struct scsi_cmnd * sc)226c8806b6cSNarsimhulu Musini snic_issue_scsi_req(struct snic *snic,
227c8806b6cSNarsimhulu Musini struct snic_tgt *tgt,
228c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc)
229c8806b6cSNarsimhulu Musini {
230c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
231c8806b6cSNarsimhulu Musini int sg_cnt = 0;
232c8806b6cSNarsimhulu Musini int ret = 0;
233c8806b6cSNarsimhulu Musini u32 tag = snic_cmd_tag(sc);
234c8806b6cSNarsimhulu Musini u64 cmd_trc = 0, cmd_st_flags = 0;
235c8806b6cSNarsimhulu Musini spinlock_t *io_lock = NULL;
236c8806b6cSNarsimhulu Musini unsigned long flags;
237c8806b6cSNarsimhulu Musini
238c8806b6cSNarsimhulu Musini CMD_STATE(sc) = SNIC_IOREQ_NOT_INITED;
239c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) = SNIC_NO_FLAGS;
240c8806b6cSNarsimhulu Musini sg_cnt = scsi_dma_map(sc);
241c8806b6cSNarsimhulu Musini if (sg_cnt < 0) {
242c8806b6cSNarsimhulu Musini SNIC_TRC((u16)snic->shost->host_no, tag, (ulong) sc, 0,
243c8806b6cSNarsimhulu Musini sc->cmnd[0], sg_cnt, CMD_STATE(sc));
244c8806b6cSNarsimhulu Musini
245c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost, "issue_sc:Failed to map SG List.\n");
246c8806b6cSNarsimhulu Musini ret = -ENOMEM;
247c8806b6cSNarsimhulu Musini
248c8806b6cSNarsimhulu Musini goto issue_sc_end;
249c8806b6cSNarsimhulu Musini }
250c8806b6cSNarsimhulu Musini
251c8806b6cSNarsimhulu Musini rqi = snic_req_init(snic, sg_cnt);
252c8806b6cSNarsimhulu Musini if (!rqi) {
253c8806b6cSNarsimhulu Musini scsi_dma_unmap(sc);
254c8806b6cSNarsimhulu Musini ret = -ENOMEM;
255c8806b6cSNarsimhulu Musini
256c8806b6cSNarsimhulu Musini goto issue_sc_end;
257c8806b6cSNarsimhulu Musini }
258c8806b6cSNarsimhulu Musini
259c8806b6cSNarsimhulu Musini rqi->tgt_id = tgt->id;
260c8806b6cSNarsimhulu Musini rqi->sc = sc;
261c8806b6cSNarsimhulu Musini
262c8806b6cSNarsimhulu Musini CMD_STATE(sc) = SNIC_IOREQ_PENDING;
263c8806b6cSNarsimhulu Musini CMD_SP(sc) = (char *) rqi;
264c8806b6cSNarsimhulu Musini cmd_trc = SNIC_TRC_CMD(sc);
265c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= (SNIC_IO_INITIALIZED | SNIC_IO_ISSUED);
266c8806b6cSNarsimhulu Musini cmd_st_flags = SNIC_TRC_CMD_STATE_FLAGS(sc);
267c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_hash(snic, sc);
268c8806b6cSNarsimhulu Musini
269c8806b6cSNarsimhulu Musini /* create wq desc and enqueue it */
270c8806b6cSNarsimhulu Musini ret = snic_queue_icmnd_req(snic, rqi, sc, sg_cnt);
271c8806b6cSNarsimhulu Musini if (ret) {
272c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
273c8806b6cSNarsimhulu Musini "issue_sc: icmnd qing Failed for sc %p, err %d\n",
274c8806b6cSNarsimhulu Musini sc, ret);
275c8806b6cSNarsimhulu Musini
276c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
277c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
278c8806b6cSNarsimhulu Musini CMD_SP(sc) = NULL;
279c8806b6cSNarsimhulu Musini CMD_STATE(sc) = SNIC_IOREQ_COMPLETE;
280c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) &= ~SNIC_IO_ISSUED; /* turn off the flag */
281c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
282c8806b6cSNarsimhulu Musini
283c8806b6cSNarsimhulu Musini if (rqi)
284c8806b6cSNarsimhulu Musini snic_release_req_buf(snic, rqi, sc);
285c8806b6cSNarsimhulu Musini
286c8806b6cSNarsimhulu Musini SNIC_TRC(snic->shost->host_no, tag, (ulong) sc, 0, 0, 0,
287c8806b6cSNarsimhulu Musini SNIC_TRC_CMD_STATE_FLAGS(sc));
288c8806b6cSNarsimhulu Musini } else {
289c8806b6cSNarsimhulu Musini u32 io_sz = scsi_bufflen(sc) >> 9;
290c8806b6cSNarsimhulu Musini u32 qtime = jiffies - rqi->start_time;
291c8806b6cSNarsimhulu Musini struct snic_io_stats *iostats = &snic->s_stats.io;
292c8806b6cSNarsimhulu Musini
293c8806b6cSNarsimhulu Musini if (io_sz > atomic64_read(&iostats->max_io_sz))
294c8806b6cSNarsimhulu Musini atomic64_set(&iostats->max_io_sz, io_sz);
295c8806b6cSNarsimhulu Musini
296c8806b6cSNarsimhulu Musini if (qtime > atomic64_read(&iostats->max_qtime))
297c8806b6cSNarsimhulu Musini atomic64_set(&iostats->max_qtime, qtime);
298c8806b6cSNarsimhulu Musini
299c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
300c8806b6cSNarsimhulu Musini "issue_sc:sc %p, tag %d queued to WQ.\n",
301c8806b6cSNarsimhulu Musini sc, tag);
302c8806b6cSNarsimhulu Musini
303c8806b6cSNarsimhulu Musini SNIC_TRC(snic->shost->host_no, tag, (ulong) sc, (ulong) rqi,
304c8806b6cSNarsimhulu Musini sg_cnt, cmd_trc, cmd_st_flags);
305c8806b6cSNarsimhulu Musini }
306c8806b6cSNarsimhulu Musini
307c8806b6cSNarsimhulu Musini issue_sc_end:
308c8806b6cSNarsimhulu Musini
309c8806b6cSNarsimhulu Musini return ret;
310c8806b6cSNarsimhulu Musini } /* end of snic_issue_scsi_req */
311c8806b6cSNarsimhulu Musini
312c8806b6cSNarsimhulu Musini
313c8806b6cSNarsimhulu Musini /*
314c8806b6cSNarsimhulu Musini * snic_queuecommand
315c8806b6cSNarsimhulu Musini * Routine to send a scsi cdb to LLD
316c8806b6cSNarsimhulu Musini * Called with host_lock held and interrupts disabled
317c8806b6cSNarsimhulu Musini */
318c8806b6cSNarsimhulu Musini int
snic_queuecommand(struct Scsi_Host * shost,struct scsi_cmnd * sc)319c8806b6cSNarsimhulu Musini snic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)
320c8806b6cSNarsimhulu Musini {
321c8806b6cSNarsimhulu Musini struct snic_tgt *tgt = NULL;
322c8806b6cSNarsimhulu Musini struct snic *snic = shost_priv(shost);
323c8806b6cSNarsimhulu Musini int ret;
324c8806b6cSNarsimhulu Musini
325c8806b6cSNarsimhulu Musini tgt = starget_to_tgt(scsi_target(sc->device));
326c8806b6cSNarsimhulu Musini ret = snic_tgt_chkready(tgt);
327c8806b6cSNarsimhulu Musini if (ret) {
328c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(shost, "Tgt %p id %d Not Ready.\n", tgt, tgt->id);
329c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.misc.tgt_not_rdy);
330c8806b6cSNarsimhulu Musini sc->result = ret;
33170a5caf1SBart Van Assche scsi_done(sc);
332c8806b6cSNarsimhulu Musini
333c8806b6cSNarsimhulu Musini return 0;
334c8806b6cSNarsimhulu Musini }
335c8806b6cSNarsimhulu Musini
336c8806b6cSNarsimhulu Musini if (snic_get_state(snic) != SNIC_ONLINE) {
337c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(shost, "snic state is %s\n",
338c8806b6cSNarsimhulu Musini snic_state_str[snic_get_state(snic)]);
339c8806b6cSNarsimhulu Musini
340c8806b6cSNarsimhulu Musini return SCSI_MLQUEUE_HOST_BUSY;
341c8806b6cSNarsimhulu Musini }
342c8806b6cSNarsimhulu Musini atomic_inc(&snic->ios_inflight);
343c8806b6cSNarsimhulu Musini
344c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(shost, "sc %p Tag %d (sc %0x) lun %lld in snic_qcmd\n",
345c8806b6cSNarsimhulu Musini sc, snic_cmd_tag(sc), sc->cmnd[0], sc->device->lun);
346c8806b6cSNarsimhulu Musini
347c8806b6cSNarsimhulu Musini ret = snic_issue_scsi_req(snic, tgt, sc);
348c8806b6cSNarsimhulu Musini if (ret) {
349c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(shost, "Failed to Q, Scsi Req w/ err %d.\n", ret);
350c8806b6cSNarsimhulu Musini ret = SCSI_MLQUEUE_HOST_BUSY;
3513f5c11a4SNarsimhulu Musini }
352c8806b6cSNarsimhulu Musini
353c8806b6cSNarsimhulu Musini atomic_dec(&snic->ios_inflight);
354c8806b6cSNarsimhulu Musini
355c8806b6cSNarsimhulu Musini return ret;
356c8806b6cSNarsimhulu Musini } /* end of snic_queuecommand */
357c8806b6cSNarsimhulu Musini
358c8806b6cSNarsimhulu Musini /*
359c8806b6cSNarsimhulu Musini * snic_process_abts_pending_state:
360c8806b6cSNarsimhulu Musini * caller should hold IO lock
361c8806b6cSNarsimhulu Musini */
362c8806b6cSNarsimhulu Musini static void
snic_proc_tmreq_pending_state(struct snic * snic,struct scsi_cmnd * sc,u8 cmpl_status)363c8806b6cSNarsimhulu Musini snic_proc_tmreq_pending_state(struct snic *snic,
364c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc,
365c8806b6cSNarsimhulu Musini u8 cmpl_status)
366c8806b6cSNarsimhulu Musini {
367c8806b6cSNarsimhulu Musini int state = CMD_STATE(sc);
368c8806b6cSNarsimhulu Musini
369c8806b6cSNarsimhulu Musini if (state == SNIC_IOREQ_ABTS_PENDING)
370c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_ABTS_PENDING;
371c8806b6cSNarsimhulu Musini else if (state == SNIC_IOREQ_LR_PENDING)
372c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_DEV_RST_PENDING;
373c8806b6cSNarsimhulu Musini else
374c8806b6cSNarsimhulu Musini SNIC_BUG_ON(1);
375c8806b6cSNarsimhulu Musini
376c8806b6cSNarsimhulu Musini switch (cmpl_status) {
377c8806b6cSNarsimhulu Musini case SNIC_STAT_IO_SUCCESS:
378c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_DONE;
379c8806b6cSNarsimhulu Musini break;
380c8806b6cSNarsimhulu Musini
381c8806b6cSNarsimhulu Musini case SNIC_STAT_ABORTED:
382c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_ABORTED;
383c8806b6cSNarsimhulu Musini break;
384c8806b6cSNarsimhulu Musini
385c8806b6cSNarsimhulu Musini default:
386c8806b6cSNarsimhulu Musini SNIC_BUG_ON(1);
387c8806b6cSNarsimhulu Musini }
388c8806b6cSNarsimhulu Musini }
389c8806b6cSNarsimhulu Musini
390c8806b6cSNarsimhulu Musini /*
391c8806b6cSNarsimhulu Musini * snic_process_io_failed_state:
392c8806b6cSNarsimhulu Musini * Processes IO's error states
393c8806b6cSNarsimhulu Musini */
394c8806b6cSNarsimhulu Musini static void
snic_process_io_failed_state(struct snic * snic,struct snic_icmnd_cmpl * icmnd_cmpl,struct scsi_cmnd * sc,u8 cmpl_stat)395c8806b6cSNarsimhulu Musini snic_process_io_failed_state(struct snic *snic,
396c8806b6cSNarsimhulu Musini struct snic_icmnd_cmpl *icmnd_cmpl,
397c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc,
398c8806b6cSNarsimhulu Musini u8 cmpl_stat)
399c8806b6cSNarsimhulu Musini {
400c8806b6cSNarsimhulu Musini int res = 0;
401c8806b6cSNarsimhulu Musini
402c8806b6cSNarsimhulu Musini switch (cmpl_stat) {
403c8806b6cSNarsimhulu Musini case SNIC_STAT_TIMEOUT: /* Req was timedout */
404c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.misc.io_tmo);
405c8806b6cSNarsimhulu Musini res = DID_TIME_OUT;
406c8806b6cSNarsimhulu Musini break;
407c8806b6cSNarsimhulu Musini
408c8806b6cSNarsimhulu Musini case SNIC_STAT_ABORTED: /* Req was aborted */
409c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.misc.io_aborted);
410c8806b6cSNarsimhulu Musini res = DID_ABORT;
411c8806b6cSNarsimhulu Musini break;
412c8806b6cSNarsimhulu Musini
413c8806b6cSNarsimhulu Musini case SNIC_STAT_DATA_CNT_MISMATCH:/* Recv/Sent more/less data than exp */
414c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.misc.data_cnt_mismat);
415c8806b6cSNarsimhulu Musini scsi_set_resid(sc, le32_to_cpu(icmnd_cmpl->resid));
416c8806b6cSNarsimhulu Musini res = DID_ERROR;
417c8806b6cSNarsimhulu Musini break;
418c8806b6cSNarsimhulu Musini
419c8806b6cSNarsimhulu Musini case SNIC_STAT_OUT_OF_RES: /* Out of resources to complete request */
420c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.fw.out_of_res);
421c8806b6cSNarsimhulu Musini res = DID_REQUEUE;
422c8806b6cSNarsimhulu Musini break;
423c8806b6cSNarsimhulu Musini
424c8806b6cSNarsimhulu Musini case SNIC_STAT_IO_NOT_FOUND: /* Requested I/O was not found */
425c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.io.io_not_found);
426c8806b6cSNarsimhulu Musini res = DID_ERROR;
427c8806b6cSNarsimhulu Musini break;
428c8806b6cSNarsimhulu Musini
429c8806b6cSNarsimhulu Musini case SNIC_STAT_SGL_INVALID: /* Req was aborted to due to sgl error*/
430c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.misc.sgl_inval);
431c8806b6cSNarsimhulu Musini res = DID_ERROR;
432c8806b6cSNarsimhulu Musini break;
433c8806b6cSNarsimhulu Musini
434c8806b6cSNarsimhulu Musini case SNIC_STAT_FW_ERR: /* Req terminated due to FW Error */
435c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.fw.io_errs);
436c8806b6cSNarsimhulu Musini res = DID_ERROR;
437c8806b6cSNarsimhulu Musini break;
438c8806b6cSNarsimhulu Musini
439c8806b6cSNarsimhulu Musini case SNIC_STAT_SCSI_ERR: /* FW hits SCSI Error */
440c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.fw.scsi_errs);
441c8806b6cSNarsimhulu Musini break;
442c8806b6cSNarsimhulu Musini
443c8806b6cSNarsimhulu Musini case SNIC_STAT_NOT_READY: /* XPT yet to initialize */
444c8806b6cSNarsimhulu Musini case SNIC_STAT_DEV_OFFLINE: /* Device offline */
445c8806b6cSNarsimhulu Musini res = DID_NO_CONNECT;
446c8806b6cSNarsimhulu Musini break;
447c8806b6cSNarsimhulu Musini
448c8806b6cSNarsimhulu Musini case SNIC_STAT_INVALID_HDR: /* Hdr contains invalid data */
449c8806b6cSNarsimhulu Musini case SNIC_STAT_INVALID_PARM: /* Some param in req is invalid */
450c8806b6cSNarsimhulu Musini case SNIC_STAT_REQ_NOT_SUP: /* Req type is not supported */
451c8806b6cSNarsimhulu Musini case SNIC_STAT_CMND_REJECT: /* Req rejected */
452c8806b6cSNarsimhulu Musini case SNIC_STAT_FATAL_ERROR: /* XPT Error */
453c8806b6cSNarsimhulu Musini default:
454c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
455c8806b6cSNarsimhulu Musini "Invalid Hdr/Param or Req Not Supported or Cmnd Rejected or Device Offline. or Unknown\n");
456c8806b6cSNarsimhulu Musini res = DID_ERROR;
457c8806b6cSNarsimhulu Musini break;
458c8806b6cSNarsimhulu Musini }
459c8806b6cSNarsimhulu Musini
460c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost, "fw returns failed status %s flags 0x%llx\n",
461c8806b6cSNarsimhulu Musini snic_io_status_to_str(cmpl_stat), CMD_FLAGS(sc));
462c8806b6cSNarsimhulu Musini
463c8806b6cSNarsimhulu Musini /* Set sc->result */
464c8806b6cSNarsimhulu Musini sc->result = (res << 16) | icmnd_cmpl->scsi_status;
465c8806b6cSNarsimhulu Musini } /* end of snic_process_io_failed_state */
466c8806b6cSNarsimhulu Musini
467c8806b6cSNarsimhulu Musini /*
468c8806b6cSNarsimhulu Musini * snic_tmreq_pending : is task management in progress.
469c8806b6cSNarsimhulu Musini */
470c8806b6cSNarsimhulu Musini static int
snic_tmreq_pending(struct scsi_cmnd * sc)471c8806b6cSNarsimhulu Musini snic_tmreq_pending(struct scsi_cmnd *sc)
472c8806b6cSNarsimhulu Musini {
473c8806b6cSNarsimhulu Musini int state = CMD_STATE(sc);
474c8806b6cSNarsimhulu Musini
475c8806b6cSNarsimhulu Musini return ((state == SNIC_IOREQ_ABTS_PENDING) ||
476c8806b6cSNarsimhulu Musini (state == SNIC_IOREQ_LR_PENDING));
477c8806b6cSNarsimhulu Musini }
478c8806b6cSNarsimhulu Musini
479c8806b6cSNarsimhulu Musini /*
480c8806b6cSNarsimhulu Musini * snic_process_icmnd_cmpl_status:
481c8806b6cSNarsimhulu Musini * Caller should hold io_lock
482c8806b6cSNarsimhulu Musini */
483c8806b6cSNarsimhulu Musini static int
snic_process_icmnd_cmpl_status(struct snic * snic,struct snic_icmnd_cmpl * icmnd_cmpl,u8 cmpl_stat,struct scsi_cmnd * sc)484c8806b6cSNarsimhulu Musini snic_process_icmnd_cmpl_status(struct snic *snic,
485c8806b6cSNarsimhulu Musini struct snic_icmnd_cmpl *icmnd_cmpl,
486c8806b6cSNarsimhulu Musini u8 cmpl_stat,
487c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc)
488c8806b6cSNarsimhulu Musini {
489c8806b6cSNarsimhulu Musini u8 scsi_stat = icmnd_cmpl->scsi_status;
490c8806b6cSNarsimhulu Musini int ret = 0;
491c8806b6cSNarsimhulu Musini
492c8806b6cSNarsimhulu Musini /* Mark the IO as complete */
493c8806b6cSNarsimhulu Musini CMD_STATE(sc) = SNIC_IOREQ_COMPLETE;
494c8806b6cSNarsimhulu Musini
495c8806b6cSNarsimhulu Musini if (likely(cmpl_stat == SNIC_STAT_IO_SUCCESS)) {
496c8806b6cSNarsimhulu Musini sc->result = (DID_OK << 16) | scsi_stat;
497c8806b6cSNarsimhulu Musini
498c8806b6cSNarsimhulu Musini /* Update SCSI Cmd with resid value */
499c8806b6cSNarsimhulu Musini scsi_set_resid(sc, le32_to_cpu(icmnd_cmpl->resid));
500c8806b6cSNarsimhulu Musini
501*4e0966a4STom Rix if (icmnd_cmpl->flags & SNIC_ICMND_CMPL_UNDR_RUN)
502c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.misc.io_under_run);
503c8806b6cSNarsimhulu Musini
504c8806b6cSNarsimhulu Musini if (icmnd_cmpl->scsi_status == SAM_STAT_TASK_SET_FULL)
505c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.misc.qfull);
506c8806b6cSNarsimhulu Musini
507c8806b6cSNarsimhulu Musini ret = 0;
508c8806b6cSNarsimhulu Musini } else {
509c8806b6cSNarsimhulu Musini snic_process_io_failed_state(snic, icmnd_cmpl, sc, cmpl_stat);
510c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.io.fail);
511c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
512c8806b6cSNarsimhulu Musini "icmnd_cmpl: IO Failed : Hdr Status %s flags 0x%llx\n",
513c8806b6cSNarsimhulu Musini snic_io_status_to_str(cmpl_stat), CMD_FLAGS(sc));
514c8806b6cSNarsimhulu Musini ret = 1;
515c8806b6cSNarsimhulu Musini }
516c8806b6cSNarsimhulu Musini
517c8806b6cSNarsimhulu Musini return ret;
518c8806b6cSNarsimhulu Musini } /* end of snic_process_icmnd_cmpl_status */
519c8806b6cSNarsimhulu Musini
520c8806b6cSNarsimhulu Musini
521c8806b6cSNarsimhulu Musini /*
522c8806b6cSNarsimhulu Musini * snic_icmnd_cmpl_handler
523c8806b6cSNarsimhulu Musini * Routine to handle icmnd completions
524c8806b6cSNarsimhulu Musini */
525c8806b6cSNarsimhulu Musini static void
snic_icmnd_cmpl_handler(struct snic * snic,struct snic_fw_req * fwreq)526c8806b6cSNarsimhulu Musini snic_icmnd_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq)
527c8806b6cSNarsimhulu Musini {
528c8806b6cSNarsimhulu Musini u8 typ, hdr_stat;
529c8806b6cSNarsimhulu Musini u32 cmnd_id, hid;
530c8806b6cSNarsimhulu Musini ulong ctx;
531c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc = NULL;
532c8806b6cSNarsimhulu Musini struct snic_icmnd_cmpl *icmnd_cmpl = NULL;
533c8806b6cSNarsimhulu Musini struct snic_host_req *req = NULL;
534c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
535c8806b6cSNarsimhulu Musini unsigned long flags, start_time;
536c8806b6cSNarsimhulu Musini spinlock_t *io_lock;
537c8806b6cSNarsimhulu Musini u8 sc_stat = 0;
538c8806b6cSNarsimhulu Musini
539c8806b6cSNarsimhulu Musini snic_io_hdr_dec(&fwreq->hdr, &typ, &hdr_stat, &cmnd_id, &hid, &ctx);
540c8806b6cSNarsimhulu Musini icmnd_cmpl = &fwreq->u.icmnd_cmpl;
541c8806b6cSNarsimhulu Musini sc_stat = icmnd_cmpl->scsi_status;
542c8806b6cSNarsimhulu Musini
543c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
544c8806b6cSNarsimhulu Musini "Icmnd_cmpl: type = %x, hdr_stat = %x, cmnd_id = %x, hid = %x,i ctx = %lx\n",
545c8806b6cSNarsimhulu Musini typ, hdr_stat, cmnd_id, hid, ctx);
546c8806b6cSNarsimhulu Musini
547c8806b6cSNarsimhulu Musini if (cmnd_id >= snic->max_tag_id) {
548c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
549c8806b6cSNarsimhulu Musini "Icmnd_cmpl:Tag Error:Out of Range Tag %d, hdr status = %s\n",
550c8806b6cSNarsimhulu Musini cmnd_id, snic_io_status_to_str(hdr_stat));
551c8806b6cSNarsimhulu Musini return;
552c8806b6cSNarsimhulu Musini }
553c8806b6cSNarsimhulu Musini
554c8806b6cSNarsimhulu Musini sc = scsi_host_find_tag(snic->shost, cmnd_id);
555c8806b6cSNarsimhulu Musini WARN_ON_ONCE(!sc);
556c8806b6cSNarsimhulu Musini
557c8806b6cSNarsimhulu Musini if (!sc) {
558c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.io.sc_null);
559c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
560c8806b6cSNarsimhulu Musini "Icmnd_cmpl: Scsi Cmnd Not found, sc = NULL Hdr Status = %s tag = 0x%x fwreq = 0x%p\n",
561c8806b6cSNarsimhulu Musini snic_io_status_to_str(hdr_stat),
562c8806b6cSNarsimhulu Musini cmnd_id,
563c8806b6cSNarsimhulu Musini fwreq);
564c8806b6cSNarsimhulu Musini
565c8806b6cSNarsimhulu Musini SNIC_TRC(snic->shost->host_no, cmnd_id, 0,
566c8806b6cSNarsimhulu Musini ((u64)hdr_stat << 16 |
567c8806b6cSNarsimhulu Musini (u64)sc_stat << 8 | (u64)icmnd_cmpl->flags),
568c8806b6cSNarsimhulu Musini (ulong) fwreq, le32_to_cpu(icmnd_cmpl->resid), ctx);
569c8806b6cSNarsimhulu Musini
570c8806b6cSNarsimhulu Musini return;
571c8806b6cSNarsimhulu Musini }
572c8806b6cSNarsimhulu Musini
573c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_hash(snic, sc);
574c8806b6cSNarsimhulu Musini
575c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
576c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
577c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
578c8806b6cSNarsimhulu Musini "Icmnd_cmpl:lun %lld sc %p cmd %xtag %d flags 0x%llx rqi %p\n",
579c8806b6cSNarsimhulu Musini sc->device->lun, sc, sc->cmnd[0], snic_cmd_tag(sc),
580c8806b6cSNarsimhulu Musini CMD_FLAGS(sc), rqi);
581c8806b6cSNarsimhulu Musini
5820da8519bSNarsimhulu Musini if (CMD_FLAGS(sc) & SNIC_HOST_RESET_CMD_TERM) {
5830da8519bSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
5840da8519bSNarsimhulu Musini
5850da8519bSNarsimhulu Musini return;
5860da8519bSNarsimhulu Musini }
5870da8519bSNarsimhulu Musini
588c8806b6cSNarsimhulu Musini SNIC_BUG_ON(rqi != (struct snic_req_info *)ctx);
589c8806b6cSNarsimhulu Musini WARN_ON_ONCE(req);
590c8806b6cSNarsimhulu Musini if (!rqi) {
591c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.io.req_null);
592c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_REQ_NULL;
593c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
594c8806b6cSNarsimhulu Musini
595c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
596c8806b6cSNarsimhulu Musini "Icmnd_cmpl:Host Req Not Found(null), Hdr Status %s, Tag 0x%x, sc 0x%p flags 0x%llx\n",
597c8806b6cSNarsimhulu Musini snic_io_status_to_str(hdr_stat),
598c8806b6cSNarsimhulu Musini cmnd_id, sc, CMD_FLAGS(sc));
599c8806b6cSNarsimhulu Musini return;
600c8806b6cSNarsimhulu Musini }
601c8806b6cSNarsimhulu Musini
602c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) ctx;
603c8806b6cSNarsimhulu Musini start_time = rqi->start_time;
604c8806b6cSNarsimhulu Musini
605c8806b6cSNarsimhulu Musini /* firmware completed the io */
606c8806b6cSNarsimhulu Musini rqi->io_cmpl = 1;
607c8806b6cSNarsimhulu Musini
608c8806b6cSNarsimhulu Musini /*
609c8806b6cSNarsimhulu Musini * if SCSI-ML has already issued abort on this command,
610c8806b6cSNarsimhulu Musini * ignore completion of the IO. The abts path will clean it up
611c8806b6cSNarsimhulu Musini */
612c8806b6cSNarsimhulu Musini if (unlikely(snic_tmreq_pending(sc))) {
613c8806b6cSNarsimhulu Musini snic_proc_tmreq_pending_state(snic, sc, hdr_stat);
614c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
615c8806b6cSNarsimhulu Musini
616c8806b6cSNarsimhulu Musini snic_stats_update_io_cmpl(&snic->s_stats);
617c8806b6cSNarsimhulu Musini
618c8806b6cSNarsimhulu Musini /* Expected value is SNIC_STAT_ABORTED */
619c8806b6cSNarsimhulu Musini if (likely(hdr_stat == SNIC_STAT_ABORTED))
620c8806b6cSNarsimhulu Musini return;
621c8806b6cSNarsimhulu Musini
622c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
623c8806b6cSNarsimhulu Musini "icmnd_cmpl:TM Req Pending(%s), Hdr Status %s sc 0x%p scsi status %x resid %d flags 0x%llx\n",
624c8806b6cSNarsimhulu Musini snic_ioreq_state_to_str(CMD_STATE(sc)),
625c8806b6cSNarsimhulu Musini snic_io_status_to_str(hdr_stat),
626c8806b6cSNarsimhulu Musini sc, sc_stat, le32_to_cpu(icmnd_cmpl->resid),
627c8806b6cSNarsimhulu Musini CMD_FLAGS(sc));
628c8806b6cSNarsimhulu Musini
629c8806b6cSNarsimhulu Musini SNIC_TRC(snic->shost->host_no, cmnd_id, (ulong) sc,
630c8806b6cSNarsimhulu Musini jiffies_to_msecs(jiffies - start_time), (ulong) fwreq,
631c8806b6cSNarsimhulu Musini SNIC_TRC_CMD(sc), SNIC_TRC_CMD_STATE_FLAGS(sc));
632c8806b6cSNarsimhulu Musini
633c8806b6cSNarsimhulu Musini return;
634c8806b6cSNarsimhulu Musini }
635c8806b6cSNarsimhulu Musini
636c8806b6cSNarsimhulu Musini if (snic_process_icmnd_cmpl_status(snic, icmnd_cmpl, hdr_stat, sc)) {
637c8806b6cSNarsimhulu Musini scsi_print_command(sc);
638c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
639c8806b6cSNarsimhulu Musini "icmnd_cmpl:IO Failed, sc 0x%p Tag %d Cmd %x Hdr Status %s flags 0x%llx\n",
640c8806b6cSNarsimhulu Musini sc, sc->cmnd[0], cmnd_id,
641c8806b6cSNarsimhulu Musini snic_io_status_to_str(hdr_stat), CMD_FLAGS(sc));
642c8806b6cSNarsimhulu Musini }
643c8806b6cSNarsimhulu Musini
644c8806b6cSNarsimhulu Musini /* Break link with the SCSI Command */
645c8806b6cSNarsimhulu Musini CMD_SP(sc) = NULL;
646c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_DONE;
647c8806b6cSNarsimhulu Musini
648c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
649c8806b6cSNarsimhulu Musini
650c8806b6cSNarsimhulu Musini /* For now, consider only successful IO. */
651c8806b6cSNarsimhulu Musini snic_calc_io_process_time(snic, rqi);
652c8806b6cSNarsimhulu Musini
653c8806b6cSNarsimhulu Musini snic_release_req_buf(snic, rqi, sc);
654c8806b6cSNarsimhulu Musini
655c8806b6cSNarsimhulu Musini SNIC_TRC(snic->shost->host_no, cmnd_id, (ulong) sc,
656c8806b6cSNarsimhulu Musini jiffies_to_msecs(jiffies - start_time), (ulong) fwreq,
657c8806b6cSNarsimhulu Musini SNIC_TRC_CMD(sc), SNIC_TRC_CMD_STATE_FLAGS(sc));
658c8806b6cSNarsimhulu Musini
659c8806b6cSNarsimhulu Musini
66070a5caf1SBart Van Assche scsi_done(sc);
661c8806b6cSNarsimhulu Musini
662c8806b6cSNarsimhulu Musini snic_stats_update_io_cmpl(&snic->s_stats);
663c8806b6cSNarsimhulu Musini } /* end of snic_icmnd_cmpl_handler */
664c8806b6cSNarsimhulu Musini
665c8806b6cSNarsimhulu Musini static void
snic_proc_dr_cmpl_locked(struct snic * snic,struct snic_fw_req * fwreq,u8 cmpl_stat,u32 cmnd_id,struct scsi_cmnd * sc)666c8806b6cSNarsimhulu Musini snic_proc_dr_cmpl_locked(struct snic *snic,
667c8806b6cSNarsimhulu Musini struct snic_fw_req *fwreq,
668c8806b6cSNarsimhulu Musini u8 cmpl_stat,
669c8806b6cSNarsimhulu Musini u32 cmnd_id,
670c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc)
671c8806b6cSNarsimhulu Musini {
672c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = (struct snic_req_info *) CMD_SP(sc);
673c8806b6cSNarsimhulu Musini u32 start_time = rqi->start_time;
674c8806b6cSNarsimhulu Musini
675c8806b6cSNarsimhulu Musini CMD_LR_STATUS(sc) = cmpl_stat;
676c8806b6cSNarsimhulu Musini
677c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "itmf_cmpl: Cmd State = %s\n",
678c8806b6cSNarsimhulu Musini snic_ioreq_state_to_str(CMD_STATE(sc)));
679c8806b6cSNarsimhulu Musini
680c8806b6cSNarsimhulu Musini if (CMD_STATE(sc) == SNIC_IOREQ_ABTS_PENDING) {
681c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_DEV_RST_ABTS_PENDING;
682c8806b6cSNarsimhulu Musini
683c8806b6cSNarsimhulu Musini SNIC_TRC(snic->shost->host_no, cmnd_id, (ulong) sc,
684c8806b6cSNarsimhulu Musini jiffies_to_msecs(jiffies - start_time),
685c8806b6cSNarsimhulu Musini (ulong) fwreq, 0, SNIC_TRC_CMD_STATE_FLAGS(sc));
686c8806b6cSNarsimhulu Musini
687c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
688c8806b6cSNarsimhulu Musini "itmf_cmpl: Terminate Pending Dev Reset Cmpl Recvd.id %x, status %s flags 0x%llx\n",
689c8806b6cSNarsimhulu Musini (int)(cmnd_id & SNIC_TAG_MASK),
690c8806b6cSNarsimhulu Musini snic_io_status_to_str(cmpl_stat),
691c8806b6cSNarsimhulu Musini CMD_FLAGS(sc));
692c8806b6cSNarsimhulu Musini
693c8806b6cSNarsimhulu Musini return;
694c8806b6cSNarsimhulu Musini }
695c8806b6cSNarsimhulu Musini
696c8806b6cSNarsimhulu Musini
697c8806b6cSNarsimhulu Musini if (CMD_FLAGS(sc) & SNIC_DEV_RST_TIMEDOUT) {
698c8806b6cSNarsimhulu Musini SNIC_TRC(snic->shost->host_no, cmnd_id, (ulong) sc,
699c8806b6cSNarsimhulu Musini jiffies_to_msecs(jiffies - start_time),
700c8806b6cSNarsimhulu Musini (ulong) fwreq, 0, SNIC_TRC_CMD_STATE_FLAGS(sc));
701c8806b6cSNarsimhulu Musini
702c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
703c8806b6cSNarsimhulu Musini "itmf_cmpl:Dev Reset Completion Received after timeout. id %d cmpl status %s flags 0x%llx\n",
704c8806b6cSNarsimhulu Musini (int)(cmnd_id & SNIC_TAG_MASK),
705c8806b6cSNarsimhulu Musini snic_io_status_to_str(cmpl_stat),
706c8806b6cSNarsimhulu Musini CMD_FLAGS(sc));
707c8806b6cSNarsimhulu Musini
708c8806b6cSNarsimhulu Musini return;
709c8806b6cSNarsimhulu Musini }
710c8806b6cSNarsimhulu Musini
711c8806b6cSNarsimhulu Musini CMD_STATE(sc) = SNIC_IOREQ_LR_COMPLETE;
712c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_DEV_RST_DONE;
713c8806b6cSNarsimhulu Musini
714c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
715c8806b6cSNarsimhulu Musini "itmf_cmpl:Dev Reset Cmpl Recvd id %d cmpl status %s flags 0x%llx\n",
716c8806b6cSNarsimhulu Musini (int)(cmnd_id & SNIC_TAG_MASK),
717c8806b6cSNarsimhulu Musini snic_io_status_to_str(cmpl_stat),
718c8806b6cSNarsimhulu Musini CMD_FLAGS(sc));
719c8806b6cSNarsimhulu Musini
720c8806b6cSNarsimhulu Musini if (rqi->dr_done)
721c8806b6cSNarsimhulu Musini complete(rqi->dr_done);
722c8806b6cSNarsimhulu Musini } /* end of snic_proc_dr_cmpl_locked */
723c8806b6cSNarsimhulu Musini
724c8806b6cSNarsimhulu Musini /*
725c8806b6cSNarsimhulu Musini * snic_update_abort_stats : Updates abort stats based on completion status.
726c8806b6cSNarsimhulu Musini */
727c8806b6cSNarsimhulu Musini static void
snic_update_abort_stats(struct snic * snic,u8 cmpl_stat)728c8806b6cSNarsimhulu Musini snic_update_abort_stats(struct snic *snic, u8 cmpl_stat)
729c8806b6cSNarsimhulu Musini {
730c8806b6cSNarsimhulu Musini struct snic_abort_stats *abt_stats = &snic->s_stats.abts;
731c8806b6cSNarsimhulu Musini
732c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "Updating Abort stats.\n");
733c8806b6cSNarsimhulu Musini
734c8806b6cSNarsimhulu Musini switch (cmpl_stat) {
735c8806b6cSNarsimhulu Musini case SNIC_STAT_IO_SUCCESS:
736c8806b6cSNarsimhulu Musini break;
737c8806b6cSNarsimhulu Musini
738c8806b6cSNarsimhulu Musini case SNIC_STAT_TIMEOUT:
739c8806b6cSNarsimhulu Musini atomic64_inc(&abt_stats->fw_tmo);
740c8806b6cSNarsimhulu Musini break;
741c8806b6cSNarsimhulu Musini
742c8806b6cSNarsimhulu Musini case SNIC_STAT_IO_NOT_FOUND:
743c8806b6cSNarsimhulu Musini atomic64_inc(&abt_stats->io_not_found);
744c8806b6cSNarsimhulu Musini break;
745c8806b6cSNarsimhulu Musini
746c8806b6cSNarsimhulu Musini default:
747c8806b6cSNarsimhulu Musini atomic64_inc(&abt_stats->fail);
748c8806b6cSNarsimhulu Musini break;
749c8806b6cSNarsimhulu Musini }
750c8806b6cSNarsimhulu Musini }
751c8806b6cSNarsimhulu Musini
752c8806b6cSNarsimhulu Musini static int
snic_process_itmf_cmpl(struct snic * snic,struct snic_fw_req * fwreq,u32 cmnd_id,u8 cmpl_stat,struct scsi_cmnd * sc)753c8806b6cSNarsimhulu Musini snic_process_itmf_cmpl(struct snic *snic,
754c8806b6cSNarsimhulu Musini struct snic_fw_req *fwreq,
755c8806b6cSNarsimhulu Musini u32 cmnd_id,
756c8806b6cSNarsimhulu Musini u8 cmpl_stat,
757c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc)
758c8806b6cSNarsimhulu Musini {
759c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
760c8806b6cSNarsimhulu Musini u32 tm_tags = 0;
761c8806b6cSNarsimhulu Musini spinlock_t *io_lock = NULL;
762c8806b6cSNarsimhulu Musini unsigned long flags;
763c8806b6cSNarsimhulu Musini u32 start_time = 0;
764c8806b6cSNarsimhulu Musini int ret = 0;
765c8806b6cSNarsimhulu Musini
766c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_hash(snic, sc);
767c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
7680da8519bSNarsimhulu Musini if (CMD_FLAGS(sc) & SNIC_HOST_RESET_CMD_TERM) {
7690da8519bSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
7700da8519bSNarsimhulu Musini
7710da8519bSNarsimhulu Musini return ret;
7720da8519bSNarsimhulu Musini }
773c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
774c8806b6cSNarsimhulu Musini WARN_ON_ONCE(!rqi);
775c8806b6cSNarsimhulu Musini
776c8806b6cSNarsimhulu Musini if (!rqi) {
777c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.io.req_null);
778c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
779c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_ABTS_TERM_REQ_NULL;
780c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
781c8806b6cSNarsimhulu Musini "itmf_cmpl: rqi is null,Hdr stat = %s Tag = 0x%x sc = 0x%p flags 0x%llx\n",
782c8806b6cSNarsimhulu Musini snic_io_status_to_str(cmpl_stat), cmnd_id, sc,
783c8806b6cSNarsimhulu Musini CMD_FLAGS(sc));
784c8806b6cSNarsimhulu Musini
785c8806b6cSNarsimhulu Musini return ret;
786c8806b6cSNarsimhulu Musini }
787c8806b6cSNarsimhulu Musini
788c8806b6cSNarsimhulu Musini /* Extract task management flags */
789c8806b6cSNarsimhulu Musini tm_tags = cmnd_id & ~(SNIC_TAG_MASK);
790c8806b6cSNarsimhulu Musini
791c8806b6cSNarsimhulu Musini start_time = rqi->start_time;
792c8806b6cSNarsimhulu Musini cmnd_id &= (SNIC_TAG_MASK);
793c8806b6cSNarsimhulu Musini
794c8806b6cSNarsimhulu Musini switch (tm_tags) {
795c8806b6cSNarsimhulu Musini case SNIC_TAG_ABORT:
796c8806b6cSNarsimhulu Musini /* Abort only issued on cmd */
797c8806b6cSNarsimhulu Musini snic_update_abort_stats(snic, cmpl_stat);
798c8806b6cSNarsimhulu Musini
799c8806b6cSNarsimhulu Musini if (CMD_STATE(sc) != SNIC_IOREQ_ABTS_PENDING) {
800c8806b6cSNarsimhulu Musini /* This is a late completion. Ignore it. */
801c8806b6cSNarsimhulu Musini ret = -1;
802c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
803c8806b6cSNarsimhulu Musini break;
804c8806b6cSNarsimhulu Musini }
805c8806b6cSNarsimhulu Musini
806c8806b6cSNarsimhulu Musini CMD_STATE(sc) = SNIC_IOREQ_ABTS_COMPLETE;
807c8806b6cSNarsimhulu Musini CMD_ABTS_STATUS(sc) = cmpl_stat;
808c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_ABTS_TERM_DONE;
809c8806b6cSNarsimhulu Musini
810c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
811c8806b6cSNarsimhulu Musini "itmf_cmpl:Abort Cmpl Recvd.Tag 0x%x Status %s flags 0x%llx\n",
812c8806b6cSNarsimhulu Musini cmnd_id,
813c8806b6cSNarsimhulu Musini snic_io_status_to_str(cmpl_stat),
814c8806b6cSNarsimhulu Musini CMD_FLAGS(sc));
815c8806b6cSNarsimhulu Musini
816c8806b6cSNarsimhulu Musini /*
817c8806b6cSNarsimhulu Musini * If scsi_eh thread is blocked waiting for abts complete,
818c8806b6cSNarsimhulu Musini * signal completion to it. IO will be cleaned in the thread,
819c8806b6cSNarsimhulu Musini * else clean it in this context.
820c8806b6cSNarsimhulu Musini */
821c8806b6cSNarsimhulu Musini if (rqi->abts_done) {
822c8806b6cSNarsimhulu Musini complete(rqi->abts_done);
823c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
824c8806b6cSNarsimhulu Musini
825c8806b6cSNarsimhulu Musini break; /* jump out */
826c8806b6cSNarsimhulu Musini }
827c8806b6cSNarsimhulu Musini
828c8806b6cSNarsimhulu Musini CMD_SP(sc) = NULL;
829c8806b6cSNarsimhulu Musini sc->result = (DID_ERROR << 16);
830c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
831c8806b6cSNarsimhulu Musini "itmf_cmpl: Completing IO. sc %p flags 0x%llx\n",
832c8806b6cSNarsimhulu Musini sc, CMD_FLAGS(sc));
833c8806b6cSNarsimhulu Musini
834c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
835c8806b6cSNarsimhulu Musini
836c8806b6cSNarsimhulu Musini snic_release_req_buf(snic, rqi, sc);
837c8806b6cSNarsimhulu Musini
838c8806b6cSNarsimhulu Musini SNIC_TRC(snic->shost->host_no, cmnd_id, (ulong) sc,
839c8806b6cSNarsimhulu Musini jiffies_to_msecs(jiffies - start_time),
840c8806b6cSNarsimhulu Musini (ulong) fwreq, SNIC_TRC_CMD(sc),
841c8806b6cSNarsimhulu Musini SNIC_TRC_CMD_STATE_FLAGS(sc));
842c8806b6cSNarsimhulu Musini
84370a5caf1SBart Van Assche scsi_done(sc);
844c8806b6cSNarsimhulu Musini
845c8806b6cSNarsimhulu Musini break;
846c8806b6cSNarsimhulu Musini
847c8806b6cSNarsimhulu Musini case SNIC_TAG_DEV_RST:
848c8806b6cSNarsimhulu Musini case SNIC_TAG_DEV_RST | SNIC_TAG_IOCTL_DEV_RST:
849c8806b6cSNarsimhulu Musini snic_proc_dr_cmpl_locked(snic, fwreq, cmpl_stat, cmnd_id, sc);
850c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
851c8806b6cSNarsimhulu Musini ret = 0;
852c8806b6cSNarsimhulu Musini
853c8806b6cSNarsimhulu Musini break;
854c8806b6cSNarsimhulu Musini
855c8806b6cSNarsimhulu Musini case SNIC_TAG_ABORT | SNIC_TAG_DEV_RST:
856c8806b6cSNarsimhulu Musini /* Abort and terminate completion of device reset req */
857c8806b6cSNarsimhulu Musini
858c8806b6cSNarsimhulu Musini CMD_STATE(sc) = SNIC_IOREQ_ABTS_COMPLETE;
859c8806b6cSNarsimhulu Musini CMD_ABTS_STATUS(sc) = cmpl_stat;
860c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_DEV_RST_DONE;
861c8806b6cSNarsimhulu Musini
862c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
863c8806b6cSNarsimhulu Musini "itmf_cmpl:dev reset abts cmpl recvd. id %d status %s flags 0x%llx\n",
864c8806b6cSNarsimhulu Musini cmnd_id, snic_io_status_to_str(cmpl_stat),
865c8806b6cSNarsimhulu Musini CMD_FLAGS(sc));
866c8806b6cSNarsimhulu Musini
867c8806b6cSNarsimhulu Musini if (rqi->abts_done)
868c8806b6cSNarsimhulu Musini complete(rqi->abts_done);
869c8806b6cSNarsimhulu Musini
870c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
871c8806b6cSNarsimhulu Musini
872c8806b6cSNarsimhulu Musini break;
873c8806b6cSNarsimhulu Musini
874c8806b6cSNarsimhulu Musini default:
875c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
876c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
877c8806b6cSNarsimhulu Musini "itmf_cmpl: Unknown TM tag bit 0x%x\n", tm_tags);
878c8806b6cSNarsimhulu Musini
879c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
880c8806b6cSNarsimhulu Musini "itmf_cmpl:Unexpected itmf io stat %s Tag = 0x%x flags 0x%llx\n",
881c8806b6cSNarsimhulu Musini snic_ioreq_state_to_str(CMD_STATE(sc)),
882c8806b6cSNarsimhulu Musini cmnd_id,
883c8806b6cSNarsimhulu Musini CMD_FLAGS(sc));
884c8806b6cSNarsimhulu Musini ret = -1;
885c8806b6cSNarsimhulu Musini SNIC_BUG_ON(1);
886c8806b6cSNarsimhulu Musini
887c8806b6cSNarsimhulu Musini break;
888c8806b6cSNarsimhulu Musini }
889c8806b6cSNarsimhulu Musini
890c8806b6cSNarsimhulu Musini return ret;
891c8806b6cSNarsimhulu Musini } /* end of snic_process_itmf_cmpl_status */
892c8806b6cSNarsimhulu Musini
893c8806b6cSNarsimhulu Musini /*
894c8806b6cSNarsimhulu Musini * snic_itmf_cmpl_handler.
895c8806b6cSNarsimhulu Musini * Routine to handle itmf completions.
896c8806b6cSNarsimhulu Musini */
897c8806b6cSNarsimhulu Musini static void
snic_itmf_cmpl_handler(struct snic * snic,struct snic_fw_req * fwreq)898c8806b6cSNarsimhulu Musini snic_itmf_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq)
899c8806b6cSNarsimhulu Musini {
900c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc = NULL;
901c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
902c8806b6cSNarsimhulu Musini struct snic_itmf_cmpl *itmf_cmpl = NULL;
903c8806b6cSNarsimhulu Musini ulong ctx;
904c8806b6cSNarsimhulu Musini u32 cmnd_id;
905c8806b6cSNarsimhulu Musini u32 hid;
906c8806b6cSNarsimhulu Musini u8 typ;
907c8806b6cSNarsimhulu Musini u8 hdr_stat;
908c8806b6cSNarsimhulu Musini
909c8806b6cSNarsimhulu Musini snic_io_hdr_dec(&fwreq->hdr, &typ, &hdr_stat, &cmnd_id, &hid, &ctx);
910c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
911c8806b6cSNarsimhulu Musini "Itmf_cmpl: %s: type = %x, hdr_stat = %x, cmnd_id = %x, hid = %x,ctx = %lx\n",
912c8806b6cSNarsimhulu Musini __func__, typ, hdr_stat, cmnd_id, hid, ctx);
913c8806b6cSNarsimhulu Musini
914c8806b6cSNarsimhulu Musini itmf_cmpl = &fwreq->u.itmf_cmpl;
915c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
916c8806b6cSNarsimhulu Musini "Itmf_cmpl: nterm %u , flags 0x%x\n",
917c8806b6cSNarsimhulu Musini le32_to_cpu(itmf_cmpl->nterminated), itmf_cmpl->flags);
918c8806b6cSNarsimhulu Musini
919c8806b6cSNarsimhulu Musini /* spl case, dev reset issued through ioctl */
920c8806b6cSNarsimhulu Musini if (cmnd_id & SNIC_TAG_IOCTL_DEV_RST) {
921c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) ctx;
922c8806b6cSNarsimhulu Musini sc = rqi->sc;
923c8806b6cSNarsimhulu Musini
924c8806b6cSNarsimhulu Musini goto ioctl_dev_rst;
925c8806b6cSNarsimhulu Musini }
926c8806b6cSNarsimhulu Musini
927c8806b6cSNarsimhulu Musini if ((cmnd_id & SNIC_TAG_MASK) >= snic->max_tag_id) {
928c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
929c8806b6cSNarsimhulu Musini "Itmf_cmpl: Tag 0x%x out of Range,HdrStat %s\n",
930c8806b6cSNarsimhulu Musini cmnd_id, snic_io_status_to_str(hdr_stat));
931c8806b6cSNarsimhulu Musini SNIC_BUG_ON(1);
932c8806b6cSNarsimhulu Musini
933c8806b6cSNarsimhulu Musini return;
934c8806b6cSNarsimhulu Musini }
935c8806b6cSNarsimhulu Musini
936c8806b6cSNarsimhulu Musini sc = scsi_host_find_tag(snic->shost, cmnd_id & SNIC_TAG_MASK);
937c8806b6cSNarsimhulu Musini WARN_ON_ONCE(!sc);
938c8806b6cSNarsimhulu Musini
939c8806b6cSNarsimhulu Musini ioctl_dev_rst:
940c8806b6cSNarsimhulu Musini if (!sc) {
941c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.io.sc_null);
942c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
943c8806b6cSNarsimhulu Musini "Itmf_cmpl: sc is NULL - Hdr Stat %s Tag 0x%x\n",
944c8806b6cSNarsimhulu Musini snic_io_status_to_str(hdr_stat), cmnd_id);
945c8806b6cSNarsimhulu Musini
946c8806b6cSNarsimhulu Musini return;
947c8806b6cSNarsimhulu Musini }
948c8806b6cSNarsimhulu Musini
949c8806b6cSNarsimhulu Musini snic_process_itmf_cmpl(snic, fwreq, cmnd_id, hdr_stat, sc);
950c8806b6cSNarsimhulu Musini } /* end of snic_itmf_cmpl_handler */
951c8806b6cSNarsimhulu Musini
952c8806b6cSNarsimhulu Musini
953c8806b6cSNarsimhulu Musini
954c8806b6cSNarsimhulu Musini static void
snic_hba_reset_scsi_cleanup(struct snic * snic,struct scsi_cmnd * sc)955c8806b6cSNarsimhulu Musini snic_hba_reset_scsi_cleanup(struct snic *snic, struct scsi_cmnd *sc)
956c8806b6cSNarsimhulu Musini {
957c8806b6cSNarsimhulu Musini struct snic_stats *st = &snic->s_stats;
958c8806b6cSNarsimhulu Musini long act_ios = 0, act_fwreqs = 0;
959c8806b6cSNarsimhulu Musini
960c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "HBA Reset scsi cleanup.\n");
961c8806b6cSNarsimhulu Musini snic_scsi_cleanup(snic, snic_cmd_tag(sc));
962c8806b6cSNarsimhulu Musini
963c8806b6cSNarsimhulu Musini /* Update stats on pending IOs */
964c8806b6cSNarsimhulu Musini act_ios = atomic64_read(&st->io.active);
965c8806b6cSNarsimhulu Musini atomic64_add(act_ios, &st->io.compl);
966c8806b6cSNarsimhulu Musini atomic64_sub(act_ios, &st->io.active);
967c8806b6cSNarsimhulu Musini
968c8806b6cSNarsimhulu Musini act_fwreqs = atomic64_read(&st->fw.actv_reqs);
969c8806b6cSNarsimhulu Musini atomic64_sub(act_fwreqs, &st->fw.actv_reqs);
970c8806b6cSNarsimhulu Musini }
971c8806b6cSNarsimhulu Musini
972c8806b6cSNarsimhulu Musini /*
973c8806b6cSNarsimhulu Musini * snic_hba_reset_cmpl_handler :
974c8806b6cSNarsimhulu Musini *
975c8806b6cSNarsimhulu Musini * Notes :
976c8806b6cSNarsimhulu Musini * 1. Cleanup all the scsi cmds, release all snic specific cmds
977c8806b6cSNarsimhulu Musini * 2. Issue Report Targets in case of SAN targets
978c8806b6cSNarsimhulu Musini */
979c8806b6cSNarsimhulu Musini static int
snic_hba_reset_cmpl_handler(struct snic * snic,struct snic_fw_req * fwreq)980c8806b6cSNarsimhulu Musini snic_hba_reset_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq)
981c8806b6cSNarsimhulu Musini {
982c8806b6cSNarsimhulu Musini ulong ctx;
983c8806b6cSNarsimhulu Musini u32 cmnd_id;
984c8806b6cSNarsimhulu Musini u32 hid;
985c8806b6cSNarsimhulu Musini u8 typ;
986c8806b6cSNarsimhulu Musini u8 hdr_stat;
987c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc = NULL;
988c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
989c8806b6cSNarsimhulu Musini spinlock_t *io_lock = NULL;
990c8806b6cSNarsimhulu Musini unsigned long flags, gflags;
991c8806b6cSNarsimhulu Musini int ret = 0;
992c8806b6cSNarsimhulu Musini
993c8806b6cSNarsimhulu Musini snic_io_hdr_dec(&fwreq->hdr, &typ, &hdr_stat, &cmnd_id, &hid, &ctx);
9943f5c11a4SNarsimhulu Musini SNIC_HOST_INFO(snic->shost,
9953f5c11a4SNarsimhulu Musini "reset_cmpl:Tag %d ctx %lx cmpl status %s HBA Reset Completion received.\n",
9963f5c11a4SNarsimhulu Musini cmnd_id, ctx, snic_io_status_to_str(hdr_stat));
9973f5c11a4SNarsimhulu Musini
998c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
999c8806b6cSNarsimhulu Musini "reset_cmpl: type = %x, hdr_stat = %x, cmnd_id = %x, hid = %x, ctx = %lx\n",
1000c8806b6cSNarsimhulu Musini typ, hdr_stat, cmnd_id, hid, ctx);
1001c8806b6cSNarsimhulu Musini
1002c8806b6cSNarsimhulu Musini /* spl case, host reset issued through ioctl */
1003c8806b6cSNarsimhulu Musini if (cmnd_id == SCSI_NO_TAG) {
1004c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) ctx;
10053f5c11a4SNarsimhulu Musini SNIC_HOST_INFO(snic->shost,
10063f5c11a4SNarsimhulu Musini "reset_cmpl:Tag %d ctx %lx cmpl stat %s\n",
10073f5c11a4SNarsimhulu Musini cmnd_id, ctx, snic_io_status_to_str(hdr_stat));
1008c8806b6cSNarsimhulu Musini sc = rqi->sc;
1009c8806b6cSNarsimhulu Musini
1010c8806b6cSNarsimhulu Musini goto ioctl_hba_rst;
1011c8806b6cSNarsimhulu Musini }
1012c8806b6cSNarsimhulu Musini
1013c8806b6cSNarsimhulu Musini if (cmnd_id >= snic->max_tag_id) {
1014c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
1015c8806b6cSNarsimhulu Musini "reset_cmpl: Tag 0x%x out of Range,HdrStat %s\n",
1016c8806b6cSNarsimhulu Musini cmnd_id, snic_io_status_to_str(hdr_stat));
1017c8806b6cSNarsimhulu Musini SNIC_BUG_ON(1);
1018c8806b6cSNarsimhulu Musini
1019c8806b6cSNarsimhulu Musini return 1;
1020c8806b6cSNarsimhulu Musini }
1021c8806b6cSNarsimhulu Musini
1022c8806b6cSNarsimhulu Musini sc = scsi_host_find_tag(snic->shost, cmnd_id);
1023c8806b6cSNarsimhulu Musini ioctl_hba_rst:
1024c8806b6cSNarsimhulu Musini if (!sc) {
1025c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.io.sc_null);
1026c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
1027c8806b6cSNarsimhulu Musini "reset_cmpl: sc is NULL - Hdr Stat %s Tag 0x%x\n",
1028c8806b6cSNarsimhulu Musini snic_io_status_to_str(hdr_stat), cmnd_id);
1029c8806b6cSNarsimhulu Musini ret = 1;
1030c8806b6cSNarsimhulu Musini
1031c8806b6cSNarsimhulu Musini return ret;
1032c8806b6cSNarsimhulu Musini }
1033c8806b6cSNarsimhulu Musini
10343f5c11a4SNarsimhulu Musini SNIC_HOST_INFO(snic->shost,
10353f5c11a4SNarsimhulu Musini "reset_cmpl: sc %p rqi %p Tag %d flags 0x%llx\n",
10363f5c11a4SNarsimhulu Musini sc, rqi, cmnd_id, CMD_FLAGS(sc));
10373f5c11a4SNarsimhulu Musini
1038c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_hash(snic, sc);
1039c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
1040c8806b6cSNarsimhulu Musini
1041c8806b6cSNarsimhulu Musini if (!snic->remove_wait) {
1042c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1043c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
10440a95160eSMasanari Iida "reset_cmpl:host reset completed after timeout\n");
1045c8806b6cSNarsimhulu Musini ret = 1;
1046c8806b6cSNarsimhulu Musini
1047c8806b6cSNarsimhulu Musini return ret;
1048c8806b6cSNarsimhulu Musini }
1049c8806b6cSNarsimhulu Musini
1050c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
1051c8806b6cSNarsimhulu Musini WARN_ON_ONCE(!rqi);
1052c8806b6cSNarsimhulu Musini
1053c8806b6cSNarsimhulu Musini if (!rqi) {
1054c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.io.req_null);
1055c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1056c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_ABTS_TERM_REQ_NULL;
1057c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
1058c8806b6cSNarsimhulu Musini "reset_cmpl: rqi is null,Hdr stat %s Tag 0x%x sc 0x%p flags 0x%llx\n",
1059c8806b6cSNarsimhulu Musini snic_io_status_to_str(hdr_stat), cmnd_id, sc,
1060c8806b6cSNarsimhulu Musini CMD_FLAGS(sc));
1061c8806b6cSNarsimhulu Musini
1062c8806b6cSNarsimhulu Musini ret = 1;
1063c8806b6cSNarsimhulu Musini
1064c8806b6cSNarsimhulu Musini return ret;
1065c8806b6cSNarsimhulu Musini }
1066c8806b6cSNarsimhulu Musini /* stats */
1067c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1068c8806b6cSNarsimhulu Musini
1069c8806b6cSNarsimhulu Musini /* scsi cleanup */
1070c8806b6cSNarsimhulu Musini snic_hba_reset_scsi_cleanup(snic, sc);
1071c8806b6cSNarsimhulu Musini
1072c8806b6cSNarsimhulu Musini SNIC_BUG_ON(snic_get_state(snic) != SNIC_OFFLINE &&
1073c8806b6cSNarsimhulu Musini snic_get_state(snic) != SNIC_FWRESET);
1074c8806b6cSNarsimhulu Musini
1075c8806b6cSNarsimhulu Musini /* Careful locking between snic_lock and io lock */
1076c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
1077c8806b6cSNarsimhulu Musini spin_lock_irqsave(&snic->snic_lock, gflags);
1078c8806b6cSNarsimhulu Musini if (snic_get_state(snic) == SNIC_FWRESET)
1079c8806b6cSNarsimhulu Musini snic_set_state(snic, SNIC_ONLINE);
1080c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(&snic->snic_lock, gflags);
1081c8806b6cSNarsimhulu Musini
1082c8806b6cSNarsimhulu Musini if (snic->remove_wait)
1083c8806b6cSNarsimhulu Musini complete(snic->remove_wait);
1084c8806b6cSNarsimhulu Musini
1085c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1086c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.reset.hba_reset_cmpl);
1087c8806b6cSNarsimhulu Musini
1088c8806b6cSNarsimhulu Musini ret = 0;
1089c8806b6cSNarsimhulu Musini /* Rediscovery is for SAN */
1090c8806b6cSNarsimhulu Musini if (snic->config.xpt_type == SNIC_DAS)
1091c8806b6cSNarsimhulu Musini return ret;
1092c8806b6cSNarsimhulu Musini
1093c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "reset_cmpl: Queuing discovery work.\n");
1094c8806b6cSNarsimhulu Musini queue_work(snic_glob->event_q, &snic->disc_work);
1095c8806b6cSNarsimhulu Musini
1096c8806b6cSNarsimhulu Musini return ret;
1097c8806b6cSNarsimhulu Musini }
1098c8806b6cSNarsimhulu Musini
1099c8806b6cSNarsimhulu Musini static void
snic_msg_ack_handler(struct snic * snic,struct snic_fw_req * fwreq)1100c8806b6cSNarsimhulu Musini snic_msg_ack_handler(struct snic *snic, struct snic_fw_req *fwreq)
1101c8806b6cSNarsimhulu Musini {
1102c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "Message Ack Received.\n");
1103c8806b6cSNarsimhulu Musini
1104c8806b6cSNarsimhulu Musini SNIC_ASSERT_NOT_IMPL(1);
1105c8806b6cSNarsimhulu Musini }
1106c8806b6cSNarsimhulu Musini
1107c8806b6cSNarsimhulu Musini static void
snic_aen_handler(struct snic * snic,struct snic_fw_req * fwreq)1108c8806b6cSNarsimhulu Musini snic_aen_handler(struct snic *snic, struct snic_fw_req *fwreq)
1109c8806b6cSNarsimhulu Musini {
1110c8806b6cSNarsimhulu Musini u8 typ, hdr_stat;
1111c8806b6cSNarsimhulu Musini u32 cmnd_id, hid;
1112c8806b6cSNarsimhulu Musini ulong ctx;
1113c8806b6cSNarsimhulu Musini struct snic_async_evnotify *aen = &fwreq->u.async_ev;
1114c8806b6cSNarsimhulu Musini u32 event_id = 0;
1115c8806b6cSNarsimhulu Musini
1116c8806b6cSNarsimhulu Musini snic_io_hdr_dec(&fwreq->hdr, &typ, &hdr_stat, &cmnd_id, &hid, &ctx);
1117c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1118c8806b6cSNarsimhulu Musini "aen: type = %x, hdr_stat = %x, cmnd_id = %x, hid = %x, ctx = %lx\n",
1119c8806b6cSNarsimhulu Musini typ, hdr_stat, cmnd_id, hid, ctx);
1120c8806b6cSNarsimhulu Musini
1121c8806b6cSNarsimhulu Musini event_id = le32_to_cpu(aen->ev_id);
1122c8806b6cSNarsimhulu Musini
1123c8806b6cSNarsimhulu Musini switch (event_id) {
1124c8806b6cSNarsimhulu Musini case SNIC_EV_TGT_OFFLINE:
1125c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "aen:TGT_OFFLINE Event Recvd.\n");
1126c8806b6cSNarsimhulu Musini break;
1127c8806b6cSNarsimhulu Musini
1128c8806b6cSNarsimhulu Musini case SNIC_EV_TGT_ONLINE:
1129c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "aen:TGT_ONLINE Event Recvd.\n");
1130c8806b6cSNarsimhulu Musini break;
1131c8806b6cSNarsimhulu Musini
1132c8806b6cSNarsimhulu Musini case SNIC_EV_LUN_OFFLINE:
1133c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "aen:LUN_OFFLINE Event Recvd.\n");
1134c8806b6cSNarsimhulu Musini break;
1135c8806b6cSNarsimhulu Musini
1136c8806b6cSNarsimhulu Musini case SNIC_EV_LUN_ONLINE:
1137c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "aen:LUN_ONLINE Event Recvd.\n");
1138c8806b6cSNarsimhulu Musini break;
1139c8806b6cSNarsimhulu Musini
1140c8806b6cSNarsimhulu Musini case SNIC_EV_CONF_CHG:
1141c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "aen:Config Change Event Recvd.\n");
1142c8806b6cSNarsimhulu Musini break;
1143c8806b6cSNarsimhulu Musini
1144c8806b6cSNarsimhulu Musini case SNIC_EV_TGT_ADDED:
1145c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "aen:TGT_ADD Event Recvd.\n");
1146c8806b6cSNarsimhulu Musini break;
1147c8806b6cSNarsimhulu Musini
1148c8806b6cSNarsimhulu Musini case SNIC_EV_TGT_DELTD:
1149c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "aen:TGT_DEL Event Recvd.\n");
1150c8806b6cSNarsimhulu Musini break;
1151c8806b6cSNarsimhulu Musini
1152c8806b6cSNarsimhulu Musini case SNIC_EV_LUN_ADDED:
1153c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "aen:LUN_ADD Event Recvd.\n");
1154c8806b6cSNarsimhulu Musini break;
1155c8806b6cSNarsimhulu Musini
1156c8806b6cSNarsimhulu Musini case SNIC_EV_LUN_DELTD:
1157c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "aen:LUN_DEL Event Recvd.\n");
1158c8806b6cSNarsimhulu Musini break;
1159c8806b6cSNarsimhulu Musini
1160c8806b6cSNarsimhulu Musini case SNIC_EV_DISC_CMPL:
1161c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "aen:DISC_CMPL Event Recvd.\n");
1162c8806b6cSNarsimhulu Musini break;
1163c8806b6cSNarsimhulu Musini
1164c8806b6cSNarsimhulu Musini default:
1165c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "aen:Unknown Event Recvd.\n");
1166c8806b6cSNarsimhulu Musini SNIC_BUG_ON(1);
1167c8806b6cSNarsimhulu Musini break;
1168c8806b6cSNarsimhulu Musini }
1169c8806b6cSNarsimhulu Musini
1170c8806b6cSNarsimhulu Musini SNIC_ASSERT_NOT_IMPL(1);
1171c8806b6cSNarsimhulu Musini } /* end of snic_aen_handler */
1172c8806b6cSNarsimhulu Musini
1173c8806b6cSNarsimhulu Musini /*
1174c8806b6cSNarsimhulu Musini * snic_io_cmpl_handler
1175c8806b6cSNarsimhulu Musini * Routine to process CQ entries(IO Completions) posted by fw.
1176c8806b6cSNarsimhulu Musini */
1177c8806b6cSNarsimhulu Musini static int
snic_io_cmpl_handler(struct vnic_dev * vdev,unsigned int cq_idx,struct snic_fw_req * fwreq)1178c8806b6cSNarsimhulu Musini snic_io_cmpl_handler(struct vnic_dev *vdev,
1179c8806b6cSNarsimhulu Musini unsigned int cq_idx,
1180c8806b6cSNarsimhulu Musini struct snic_fw_req *fwreq)
1181c8806b6cSNarsimhulu Musini {
1182c8806b6cSNarsimhulu Musini struct snic *snic = svnic_dev_priv(vdev);
1183c8806b6cSNarsimhulu Musini u64 start = jiffies, cmpl_time;
1184c8806b6cSNarsimhulu Musini
1185c8806b6cSNarsimhulu Musini snic_print_desc(__func__, (char *)fwreq, sizeof(*fwreq));
1186c8806b6cSNarsimhulu Musini
1187c8806b6cSNarsimhulu Musini /* Update FW Stats */
1188c8806b6cSNarsimhulu Musini if ((fwreq->hdr.type >= SNIC_RSP_REPORT_TGTS_CMPL) &&
1189c8806b6cSNarsimhulu Musini (fwreq->hdr.type <= SNIC_RSP_BOOT_LUNS_CMPL))
1190c8806b6cSNarsimhulu Musini atomic64_dec(&snic->s_stats.fw.actv_reqs);
1191c8806b6cSNarsimhulu Musini
1192c8806b6cSNarsimhulu Musini SNIC_BUG_ON((fwreq->hdr.type > SNIC_RSP_BOOT_LUNS_CMPL) &&
1193c8806b6cSNarsimhulu Musini (fwreq->hdr.type < SNIC_MSG_ASYNC_EVNOTIFY));
1194c8806b6cSNarsimhulu Musini
1195c8806b6cSNarsimhulu Musini /* Check for snic subsys errors */
1196c8806b6cSNarsimhulu Musini switch (fwreq->hdr.status) {
1197c8806b6cSNarsimhulu Musini case SNIC_STAT_NOT_READY: /* XPT yet to initialize */
1198c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
1199c8806b6cSNarsimhulu Musini "sNIC SubSystem is NOT Ready.\n");
1200c8806b6cSNarsimhulu Musini break;
1201c8806b6cSNarsimhulu Musini
1202c8806b6cSNarsimhulu Musini case SNIC_STAT_FATAL_ERROR: /* XPT Error */
1203c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
1204c8806b6cSNarsimhulu Musini "sNIC SubSystem in Unrecoverable State.\n");
1205c8806b6cSNarsimhulu Musini break;
1206c8806b6cSNarsimhulu Musini }
1207c8806b6cSNarsimhulu Musini
1208c8806b6cSNarsimhulu Musini switch (fwreq->hdr.type) {
1209c8806b6cSNarsimhulu Musini case SNIC_RSP_EXCH_VER_CMPL:
1210c8806b6cSNarsimhulu Musini snic_io_exch_ver_cmpl_handler(snic, fwreq);
1211c8806b6cSNarsimhulu Musini break;
1212c8806b6cSNarsimhulu Musini
1213c8806b6cSNarsimhulu Musini case SNIC_RSP_REPORT_TGTS_CMPL:
1214c8806b6cSNarsimhulu Musini snic_report_tgt_cmpl_handler(snic, fwreq);
1215c8806b6cSNarsimhulu Musini break;
1216c8806b6cSNarsimhulu Musini
1217c8806b6cSNarsimhulu Musini case SNIC_RSP_ICMND_CMPL:
1218c8806b6cSNarsimhulu Musini snic_icmnd_cmpl_handler(snic, fwreq);
1219c8806b6cSNarsimhulu Musini break;
1220c8806b6cSNarsimhulu Musini
1221c8806b6cSNarsimhulu Musini case SNIC_RSP_ITMF_CMPL:
1222c8806b6cSNarsimhulu Musini snic_itmf_cmpl_handler(snic, fwreq);
1223c8806b6cSNarsimhulu Musini break;
1224c8806b6cSNarsimhulu Musini
1225c8806b6cSNarsimhulu Musini case SNIC_RSP_HBA_RESET_CMPL:
1226c8806b6cSNarsimhulu Musini snic_hba_reset_cmpl_handler(snic, fwreq);
1227c8806b6cSNarsimhulu Musini break;
1228c8806b6cSNarsimhulu Musini
1229c8806b6cSNarsimhulu Musini case SNIC_MSG_ACK:
1230c8806b6cSNarsimhulu Musini snic_msg_ack_handler(snic, fwreq);
1231c8806b6cSNarsimhulu Musini break;
1232c8806b6cSNarsimhulu Musini
1233c8806b6cSNarsimhulu Musini case SNIC_MSG_ASYNC_EVNOTIFY:
1234c8806b6cSNarsimhulu Musini snic_aen_handler(snic, fwreq);
1235c8806b6cSNarsimhulu Musini break;
1236c8806b6cSNarsimhulu Musini
1237c8806b6cSNarsimhulu Musini default:
1238c8806b6cSNarsimhulu Musini SNIC_BUG_ON(1);
1239c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
12409f80efdaSColin Ian King "Unknown Firmware completion request type %d\n",
1241c8806b6cSNarsimhulu Musini fwreq->hdr.type);
1242c8806b6cSNarsimhulu Musini break;
1243c8806b6cSNarsimhulu Musini }
1244c8806b6cSNarsimhulu Musini
1245c8806b6cSNarsimhulu Musini /* Update Stats */
1246c8806b6cSNarsimhulu Musini cmpl_time = jiffies - start;
1247c8806b6cSNarsimhulu Musini if (cmpl_time > atomic64_read(&snic->s_stats.io.max_cmpl_time))
1248c8806b6cSNarsimhulu Musini atomic64_set(&snic->s_stats.io.max_cmpl_time, cmpl_time);
1249c8806b6cSNarsimhulu Musini
1250c8806b6cSNarsimhulu Musini return 0;
1251c8806b6cSNarsimhulu Musini } /* end of snic_io_cmpl_handler */
1252c8806b6cSNarsimhulu Musini
1253c8806b6cSNarsimhulu Musini /*
1254c8806b6cSNarsimhulu Musini * snic_fwcq_cmpl_handler
1255c8806b6cSNarsimhulu Musini * Routine to process fwCQ
1256c8806b6cSNarsimhulu Musini * This CQ is independent, and not associated with wq/rq/wq_copy queues
1257c8806b6cSNarsimhulu Musini */
1258c8806b6cSNarsimhulu Musini int
snic_fwcq_cmpl_handler(struct snic * snic,int io_cmpl_work)1259c8806b6cSNarsimhulu Musini snic_fwcq_cmpl_handler(struct snic *snic, int io_cmpl_work)
1260c8806b6cSNarsimhulu Musini {
1261c8806b6cSNarsimhulu Musini unsigned int num_ent = 0; /* number cq entries processed */
1262c8806b6cSNarsimhulu Musini unsigned int cq_idx;
1263c8806b6cSNarsimhulu Musini unsigned int nent_per_cq;
1264c8806b6cSNarsimhulu Musini struct snic_misc_stats *misc_stats = &snic->s_stats.misc;
1265c8806b6cSNarsimhulu Musini
1266c8806b6cSNarsimhulu Musini for (cq_idx = snic->wq_count; cq_idx < snic->cq_count; cq_idx++) {
1267c8806b6cSNarsimhulu Musini nent_per_cq = vnic_cq_fw_service(&snic->cq[cq_idx],
1268c8806b6cSNarsimhulu Musini snic_io_cmpl_handler,
1269c8806b6cSNarsimhulu Musini io_cmpl_work);
1270c8806b6cSNarsimhulu Musini num_ent += nent_per_cq;
1271c8806b6cSNarsimhulu Musini
1272c8806b6cSNarsimhulu Musini if (nent_per_cq > atomic64_read(&misc_stats->max_cq_ents))
1273c8806b6cSNarsimhulu Musini atomic64_set(&misc_stats->max_cq_ents, nent_per_cq);
1274c8806b6cSNarsimhulu Musini }
1275c8806b6cSNarsimhulu Musini
1276c8806b6cSNarsimhulu Musini return num_ent;
1277c8806b6cSNarsimhulu Musini } /* end of snic_fwcq_cmpl_handler */
1278c8806b6cSNarsimhulu Musini
1279c8806b6cSNarsimhulu Musini /*
1280c8806b6cSNarsimhulu Musini * snic_queue_itmf_req: Common API to queue Task Management requests.
1281c8806b6cSNarsimhulu Musini * Use rqi->tm_tag for passing special tags.
1282c8806b6cSNarsimhulu Musini * @req_id : aborted request's tag, -1 for lun reset.
1283c8806b6cSNarsimhulu Musini */
1284c8806b6cSNarsimhulu Musini static int
snic_queue_itmf_req(struct snic * snic,struct snic_host_req * tmreq,struct scsi_cmnd * sc,u32 tmf,u32 req_id)1285c8806b6cSNarsimhulu Musini snic_queue_itmf_req(struct snic *snic,
1286c8806b6cSNarsimhulu Musini struct snic_host_req *tmreq,
1287c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc,
1288c8806b6cSNarsimhulu Musini u32 tmf,
1289c8806b6cSNarsimhulu Musini u32 req_id)
1290c8806b6cSNarsimhulu Musini {
1291c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = req_to_rqi(tmreq);
1292c8806b6cSNarsimhulu Musini struct scsi_lun lun;
1293c8806b6cSNarsimhulu Musini int tm_tag = snic_cmd_tag(sc) | rqi->tm_tag;
1294c8806b6cSNarsimhulu Musini int ret = 0;
1295c8806b6cSNarsimhulu Musini
1296c8806b6cSNarsimhulu Musini SNIC_BUG_ON(!rqi);
1297c8806b6cSNarsimhulu Musini SNIC_BUG_ON(!rqi->tm_tag);
1298c8806b6cSNarsimhulu Musini
1299c8806b6cSNarsimhulu Musini /* fill in lun info */
1300c8806b6cSNarsimhulu Musini int_to_scsilun(sc->device->lun, &lun);
1301c8806b6cSNarsimhulu Musini
1302c8806b6cSNarsimhulu Musini /* Initialize snic_host_req: itmf */
1303c8806b6cSNarsimhulu Musini snic_itmf_init(tmreq,
1304c8806b6cSNarsimhulu Musini tm_tag,
1305c8806b6cSNarsimhulu Musini snic->config.hid,
1306c8806b6cSNarsimhulu Musini (ulong) rqi,
1307c8806b6cSNarsimhulu Musini 0 /* flags */,
1308c8806b6cSNarsimhulu Musini req_id, /* Command to be aborted. */
1309c8806b6cSNarsimhulu Musini rqi->tgt_id,
1310c8806b6cSNarsimhulu Musini lun.scsi_lun,
1311c8806b6cSNarsimhulu Musini tmf);
1312c8806b6cSNarsimhulu Musini
1313c8806b6cSNarsimhulu Musini /*
1314c8806b6cSNarsimhulu Musini * In case of multiple aborts on same cmd,
1315c8806b6cSNarsimhulu Musini * use try_wait_for_completion and completion_done() to check
1316c8806b6cSNarsimhulu Musini * whether it queues aborts even after completion of abort issued
1317c8806b6cSNarsimhulu Musini * prior.SNIC_BUG_ON(completion_done(&rqi->done));
1318c8806b6cSNarsimhulu Musini */
1319c8806b6cSNarsimhulu Musini
1320c8806b6cSNarsimhulu Musini ret = snic_queue_wq_desc(snic, tmreq, sizeof(*tmreq));
1321c8806b6cSNarsimhulu Musini if (ret)
1322c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
1323c8806b6cSNarsimhulu Musini "qitmf:Queuing ITMF(%d) Req sc %p, rqi %p, req_id %d tag %d Failed, ret = %d\n",
1324c8806b6cSNarsimhulu Musini tmf, sc, rqi, req_id, snic_cmd_tag(sc), ret);
1325c8806b6cSNarsimhulu Musini else
1326c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1327c8806b6cSNarsimhulu Musini "qitmf:Queuing ITMF(%d) Req sc %p, rqi %p, req_id %d, tag %d (req_id)- Success.",
1328c8806b6cSNarsimhulu Musini tmf, sc, rqi, req_id, snic_cmd_tag(sc));
1329c8806b6cSNarsimhulu Musini
1330c8806b6cSNarsimhulu Musini return ret;
1331c8806b6cSNarsimhulu Musini } /* end of snic_queue_itmf_req */
1332c8806b6cSNarsimhulu Musini
1333c8806b6cSNarsimhulu Musini static int
snic_issue_tm_req(struct snic * snic,struct snic_req_info * rqi,struct scsi_cmnd * sc,int tmf)1334c8806b6cSNarsimhulu Musini snic_issue_tm_req(struct snic *snic,
1335c8806b6cSNarsimhulu Musini struct snic_req_info *rqi,
1336c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc,
1337c8806b6cSNarsimhulu Musini int tmf)
1338c8806b6cSNarsimhulu Musini {
1339c8806b6cSNarsimhulu Musini struct snic_host_req *tmreq = NULL;
1340c8806b6cSNarsimhulu Musini int req_id = 0, tag = snic_cmd_tag(sc);
1341c8806b6cSNarsimhulu Musini int ret = 0;
1342c8806b6cSNarsimhulu Musini
1343c8806b6cSNarsimhulu Musini if (snic_get_state(snic) == SNIC_FWRESET)
1344c8806b6cSNarsimhulu Musini return -EBUSY;
1345c8806b6cSNarsimhulu Musini
1346c8806b6cSNarsimhulu Musini atomic_inc(&snic->ios_inflight);
1347c8806b6cSNarsimhulu Musini
1348c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1349c8806b6cSNarsimhulu Musini "issu_tmreq: Task mgmt req %d. rqi %p w/ tag %x\n",
1350c8806b6cSNarsimhulu Musini tmf, rqi, tag);
1351c8806b6cSNarsimhulu Musini
1352c8806b6cSNarsimhulu Musini
1353c8806b6cSNarsimhulu Musini if (tmf == SNIC_ITMF_LUN_RESET) {
1354c8806b6cSNarsimhulu Musini tmreq = snic_dr_req_init(snic, rqi);
1355c8806b6cSNarsimhulu Musini req_id = SCSI_NO_TAG;
1356c8806b6cSNarsimhulu Musini } else {
1357c8806b6cSNarsimhulu Musini tmreq = snic_abort_req_init(snic, rqi);
1358c8806b6cSNarsimhulu Musini req_id = tag;
1359c8806b6cSNarsimhulu Musini }
1360c8806b6cSNarsimhulu Musini
1361c8806b6cSNarsimhulu Musini if (!tmreq) {
1362c8806b6cSNarsimhulu Musini ret = -ENOMEM;
1363c8806b6cSNarsimhulu Musini
1364c8806b6cSNarsimhulu Musini goto tmreq_err;
1365c8806b6cSNarsimhulu Musini }
1366c8806b6cSNarsimhulu Musini
1367c8806b6cSNarsimhulu Musini ret = snic_queue_itmf_req(snic, tmreq, sc, tmf, req_id);
1368c8806b6cSNarsimhulu Musini
1369c8806b6cSNarsimhulu Musini tmreq_err:
1370c8806b6cSNarsimhulu Musini if (ret) {
1371c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
1372cb562b13SColin Ian King "issu_tmreq: Queueing ITMF(%d) Req, sc %p rqi %p req_id %d tag %x fails err = %d\n",
1373c8806b6cSNarsimhulu Musini tmf, sc, rqi, req_id, tag, ret);
1374c8806b6cSNarsimhulu Musini } else {
1375c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1376cb562b13SColin Ian King "issu_tmreq: Queueing ITMF(%d) Req, sc %p, rqi %p, req_id %d tag %x - Success.\n",
1377c8806b6cSNarsimhulu Musini tmf, sc, rqi, req_id, tag);
1378c8806b6cSNarsimhulu Musini }
1379c8806b6cSNarsimhulu Musini
1380c8806b6cSNarsimhulu Musini atomic_dec(&snic->ios_inflight);
1381c8806b6cSNarsimhulu Musini
1382c8806b6cSNarsimhulu Musini return ret;
1383c8806b6cSNarsimhulu Musini }
1384c8806b6cSNarsimhulu Musini
1385c8806b6cSNarsimhulu Musini /*
1386c8806b6cSNarsimhulu Musini * snic_queue_abort_req : Queues abort req to WQ
1387c8806b6cSNarsimhulu Musini */
1388c8806b6cSNarsimhulu Musini static int
snic_queue_abort_req(struct snic * snic,struct snic_req_info * rqi,struct scsi_cmnd * sc,int tmf)1389c8806b6cSNarsimhulu Musini snic_queue_abort_req(struct snic *snic,
1390c8806b6cSNarsimhulu Musini struct snic_req_info *rqi,
1391c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc,
1392c8806b6cSNarsimhulu Musini int tmf)
1393c8806b6cSNarsimhulu Musini {
1394c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "q_abtreq: sc %p, rqi %p, tag %x, tmf %d\n",
1395c8806b6cSNarsimhulu Musini sc, rqi, snic_cmd_tag(sc), tmf);
1396c8806b6cSNarsimhulu Musini
1397c8806b6cSNarsimhulu Musini /* Add special tag for abort */
1398c8806b6cSNarsimhulu Musini rqi->tm_tag |= SNIC_TAG_ABORT;
1399c8806b6cSNarsimhulu Musini
1400c8806b6cSNarsimhulu Musini return snic_issue_tm_req(snic, rqi, sc, tmf);
1401c8806b6cSNarsimhulu Musini }
1402c8806b6cSNarsimhulu Musini
1403c8806b6cSNarsimhulu Musini /*
1404c8806b6cSNarsimhulu Musini * snic_abort_finish : called by snic_abort_cmd on queuing abort successfully.
1405c8806b6cSNarsimhulu Musini */
1406c8806b6cSNarsimhulu Musini static int
snic_abort_finish(struct snic * snic,struct scsi_cmnd * sc)1407c8806b6cSNarsimhulu Musini snic_abort_finish(struct snic *snic, struct scsi_cmnd *sc)
1408c8806b6cSNarsimhulu Musini {
1409c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
1410c8806b6cSNarsimhulu Musini spinlock_t *io_lock = NULL;
1411c8806b6cSNarsimhulu Musini unsigned long flags;
1412c8806b6cSNarsimhulu Musini int ret = 0, tag = snic_cmd_tag(sc);
1413c8806b6cSNarsimhulu Musini
1414c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_hash(snic, sc);
1415c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
1416c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
1417c8806b6cSNarsimhulu Musini if (!rqi) {
1418c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.io.req_null);
1419c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_ABTS_TERM_REQ_NULL;
1420c8806b6cSNarsimhulu Musini
1421c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1422c8806b6cSNarsimhulu Musini "abt_fini:req info is null tag 0x%x, sc 0x%p flags 0x%llx\n",
1423c8806b6cSNarsimhulu Musini tag, sc, CMD_FLAGS(sc));
1424c8806b6cSNarsimhulu Musini ret = FAILED;
1425c8806b6cSNarsimhulu Musini
1426c8806b6cSNarsimhulu Musini goto abort_fail;
1427c8806b6cSNarsimhulu Musini }
1428c8806b6cSNarsimhulu Musini
1429c8806b6cSNarsimhulu Musini rqi->abts_done = NULL;
1430c8806b6cSNarsimhulu Musini
1431c8806b6cSNarsimhulu Musini ret = FAILED;
1432c8806b6cSNarsimhulu Musini
1433c8806b6cSNarsimhulu Musini /* Check the abort status. */
1434c8806b6cSNarsimhulu Musini switch (CMD_ABTS_STATUS(sc)) {
1435c8806b6cSNarsimhulu Musini case SNIC_INVALID_CODE:
1436c8806b6cSNarsimhulu Musini /* Firmware didn't complete abort req, timedout */
1437c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_ABTS_TIMEDOUT;
1438c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.abts.drv_tmo);
1439c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1440c8806b6cSNarsimhulu Musini "abt_fini:sc %p Tag %x Driver Timeout.flags 0x%llx\n",
1441c8806b6cSNarsimhulu Musini sc, snic_cmd_tag(sc), CMD_FLAGS(sc));
1442c8806b6cSNarsimhulu Musini /* do not release snic request in timedout case */
1443c8806b6cSNarsimhulu Musini rqi = NULL;
1444c8806b6cSNarsimhulu Musini
1445c8806b6cSNarsimhulu Musini goto abort_fail;
1446c8806b6cSNarsimhulu Musini
1447c8806b6cSNarsimhulu Musini case SNIC_STAT_IO_SUCCESS:
1448c8806b6cSNarsimhulu Musini case SNIC_STAT_IO_NOT_FOUND:
1449c8806b6cSNarsimhulu Musini ret = SUCCESS;
1450f352a0d5SNarsimhulu Musini /*
1451f352a0d5SNarsimhulu Musini * If abort path doesn't call scsi_done(),
1452f352a0d5SNarsimhulu Musini * the # IO timeouts == 2, will cause the LUN offline.
1453f352a0d5SNarsimhulu Musini * Call scsi_done to complete the IO.
1454f352a0d5SNarsimhulu Musini */
1455f352a0d5SNarsimhulu Musini sc->result = (DID_ERROR << 16);
145670a5caf1SBart Van Assche scsi_done(sc);
1457c8806b6cSNarsimhulu Musini break;
1458c8806b6cSNarsimhulu Musini
1459c8806b6cSNarsimhulu Musini default:
1460c8806b6cSNarsimhulu Musini /* Firmware completed abort with error */
1461c8806b6cSNarsimhulu Musini ret = FAILED;
1462f352a0d5SNarsimhulu Musini rqi = NULL;
1463c8806b6cSNarsimhulu Musini break;
1464c8806b6cSNarsimhulu Musini }
1465c8806b6cSNarsimhulu Musini
1466c8806b6cSNarsimhulu Musini CMD_SP(sc) = NULL;
1467c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost,
1468c8806b6cSNarsimhulu Musini "abt_fini: Tag %x, Cmpl Status %s flags 0x%llx\n",
1469c8806b6cSNarsimhulu Musini tag, snic_io_status_to_str(CMD_ABTS_STATUS(sc)),
1470c8806b6cSNarsimhulu Musini CMD_FLAGS(sc));
1471c8806b6cSNarsimhulu Musini
1472c8806b6cSNarsimhulu Musini abort_fail:
1473c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1474c8806b6cSNarsimhulu Musini if (rqi)
1475c8806b6cSNarsimhulu Musini snic_release_req_buf(snic, rqi, sc);
1476c8806b6cSNarsimhulu Musini
1477c8806b6cSNarsimhulu Musini return ret;
1478c8806b6cSNarsimhulu Musini } /* end of snic_abort_finish */
1479c8806b6cSNarsimhulu Musini
1480c8806b6cSNarsimhulu Musini /*
1481c8806b6cSNarsimhulu Musini * snic_send_abort_and_wait : Issues Abort, and Waits
1482c8806b6cSNarsimhulu Musini */
1483c8806b6cSNarsimhulu Musini static int
snic_send_abort_and_wait(struct snic * snic,struct scsi_cmnd * sc)1484c8806b6cSNarsimhulu Musini snic_send_abort_and_wait(struct snic *snic, struct scsi_cmnd *sc)
1485c8806b6cSNarsimhulu Musini {
1486c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
1487c8806b6cSNarsimhulu Musini enum snic_ioreq_state sv_state;
1488c8806b6cSNarsimhulu Musini struct snic_tgt *tgt = NULL;
1489c8806b6cSNarsimhulu Musini spinlock_t *io_lock = NULL;
1490c8806b6cSNarsimhulu Musini DECLARE_COMPLETION_ONSTACK(tm_done);
1491c8806b6cSNarsimhulu Musini unsigned long flags;
1492c8806b6cSNarsimhulu Musini int ret = 0, tmf = 0, tag = snic_cmd_tag(sc);
1493c8806b6cSNarsimhulu Musini
1494c8806b6cSNarsimhulu Musini tgt = starget_to_tgt(scsi_target(sc->device));
1495c8806b6cSNarsimhulu Musini if ((snic_tgt_chkready(tgt) != 0) && (tgt->tdata.typ == SNIC_TGT_SAN))
1496c8806b6cSNarsimhulu Musini tmf = SNIC_ITMF_ABTS_TASK_TERM;
1497c8806b6cSNarsimhulu Musini else
1498c8806b6cSNarsimhulu Musini tmf = SNIC_ITMF_ABTS_TASK;
1499c8806b6cSNarsimhulu Musini
1500c8806b6cSNarsimhulu Musini /* stats */
1501c8806b6cSNarsimhulu Musini
1502c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_hash(snic, sc);
1503c8806b6cSNarsimhulu Musini
1504c8806b6cSNarsimhulu Musini /*
1505c8806b6cSNarsimhulu Musini * Avoid a race between SCSI issuing the abort and the device
1506c8806b6cSNarsimhulu Musini * completing the command.
1507c8806b6cSNarsimhulu Musini *
1508c8806b6cSNarsimhulu Musini * If the command is already completed by fw_cmpl code,
1509c8806b6cSNarsimhulu Musini * we just return SUCCESS from here. This means that the abort
1510c8806b6cSNarsimhulu Musini * succeeded. In the SCSI ML, since the timeout for command has
1511c8806b6cSNarsimhulu Musini * happend, the completion wont actually complete the command
1512c8806b6cSNarsimhulu Musini * and it will be considered as an aborted command
1513c8806b6cSNarsimhulu Musini *
1514c8806b6cSNarsimhulu Musini * The CMD_SP will not be cleared except while holding io_lock
1515c8806b6cSNarsimhulu Musini */
1516c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
1517c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
1518c8806b6cSNarsimhulu Musini if (!rqi) {
1519c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1520c8806b6cSNarsimhulu Musini
1521c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
1522c8806b6cSNarsimhulu Musini "abt_cmd: rqi is null. Tag %d flags 0x%llx\n",
1523c8806b6cSNarsimhulu Musini tag, CMD_FLAGS(sc));
1524c8806b6cSNarsimhulu Musini
1525c8806b6cSNarsimhulu Musini ret = SUCCESS;
1526c8806b6cSNarsimhulu Musini
1527c8806b6cSNarsimhulu Musini goto send_abts_end;
1528c8806b6cSNarsimhulu Musini }
1529c8806b6cSNarsimhulu Musini
1530c8806b6cSNarsimhulu Musini rqi->abts_done = &tm_done;
1531c8806b6cSNarsimhulu Musini if (CMD_STATE(sc) == SNIC_IOREQ_ABTS_PENDING) {
1532c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1533c8806b6cSNarsimhulu Musini
1534c8806b6cSNarsimhulu Musini ret = 0;
1535c8806b6cSNarsimhulu Musini goto abts_pending;
1536c8806b6cSNarsimhulu Musini }
1537c8806b6cSNarsimhulu Musini SNIC_BUG_ON(!rqi->abts_done);
1538c8806b6cSNarsimhulu Musini
1539c8806b6cSNarsimhulu Musini /* Save Command State, should be restored on failed to Queue. */
1540c8806b6cSNarsimhulu Musini sv_state = CMD_STATE(sc);
1541c8806b6cSNarsimhulu Musini
1542c8806b6cSNarsimhulu Musini /*
1543c8806b6cSNarsimhulu Musini * Command is still pending, need to abort it
1544c8806b6cSNarsimhulu Musini * If the fw completes the command after this point,
1545c8806b6cSNarsimhulu Musini * the completion won't be done till mid-layer, since abot
1546c8806b6cSNarsimhulu Musini * has already started.
1547c8806b6cSNarsimhulu Musini */
1548c8806b6cSNarsimhulu Musini CMD_STATE(sc) = SNIC_IOREQ_ABTS_PENDING;
1549c8806b6cSNarsimhulu Musini CMD_ABTS_STATUS(sc) = SNIC_INVALID_CODE;
1550c8806b6cSNarsimhulu Musini
1551c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "send_abt_cmd: TAG 0x%x\n", tag);
1552c8806b6cSNarsimhulu Musini
1553c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1554c8806b6cSNarsimhulu Musini
1555c8806b6cSNarsimhulu Musini /* Now Queue the abort command to firmware */
1556c8806b6cSNarsimhulu Musini ret = snic_queue_abort_req(snic, rqi, sc, tmf);
1557c8806b6cSNarsimhulu Musini if (ret) {
15583f5c11a4SNarsimhulu Musini atomic64_inc(&snic->s_stats.abts.q_fail);
1559c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
1560c8806b6cSNarsimhulu Musini "send_abt_cmd: IO w/ Tag 0x%x fail w/ err %d flags 0x%llx\n",
1561c8806b6cSNarsimhulu Musini tag, ret, CMD_FLAGS(sc));
1562c8806b6cSNarsimhulu Musini
1563c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
1564c8806b6cSNarsimhulu Musini /* Restore Command's previous state */
1565c8806b6cSNarsimhulu Musini CMD_STATE(sc) = sv_state;
1566c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
1567c8806b6cSNarsimhulu Musini if (rqi)
1568c8806b6cSNarsimhulu Musini rqi->abts_done = NULL;
1569c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1570c8806b6cSNarsimhulu Musini ret = FAILED;
1571c8806b6cSNarsimhulu Musini
1572c8806b6cSNarsimhulu Musini goto send_abts_end;
1573c8806b6cSNarsimhulu Musini }
1574c8806b6cSNarsimhulu Musini
1575c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
1576c8806b6cSNarsimhulu Musini if (tmf == SNIC_ITMF_ABTS_TASK) {
1577c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_ABTS_ISSUED;
1578c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.abts.num);
1579c8806b6cSNarsimhulu Musini } else {
1580c8806b6cSNarsimhulu Musini /* term stats */
1581c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_TERM_ISSUED;
1582c8806b6cSNarsimhulu Musini }
1583c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1584c8806b6cSNarsimhulu Musini
1585c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1586c8806b6cSNarsimhulu Musini "send_abt_cmd: sc %p Tag %x flags 0x%llx\n",
1587c8806b6cSNarsimhulu Musini sc, tag, CMD_FLAGS(sc));
1588c8806b6cSNarsimhulu Musini
1589c8806b6cSNarsimhulu Musini
1590c8806b6cSNarsimhulu Musini ret = 0;
1591c8806b6cSNarsimhulu Musini
1592c8806b6cSNarsimhulu Musini abts_pending:
1593c8806b6cSNarsimhulu Musini /*
1594c8806b6cSNarsimhulu Musini * Queued an abort IO, wait for its completion.
1595c8806b6cSNarsimhulu Musini * Once the fw completes the abort command, it will
1596c8806b6cSNarsimhulu Musini * wakeup this thread.
1597c8806b6cSNarsimhulu Musini */
1598c8806b6cSNarsimhulu Musini wait_for_completion_timeout(&tm_done, SNIC_ABTS_TIMEOUT);
1599c8806b6cSNarsimhulu Musini
1600c8806b6cSNarsimhulu Musini send_abts_end:
1601c8806b6cSNarsimhulu Musini return ret;
1602c8806b6cSNarsimhulu Musini } /* end of snic_send_abort_and_wait */
1603c8806b6cSNarsimhulu Musini
1604c8806b6cSNarsimhulu Musini /*
1605c8806b6cSNarsimhulu Musini * This function is exported to SCSI for sending abort cmnds.
1606c8806b6cSNarsimhulu Musini * A SCSI IO is represent by snic_ioreq in the driver.
1607c8806b6cSNarsimhulu Musini * The snic_ioreq is linked to the SCSI Cmd, thus a link with the ULP'S IO
1608c8806b6cSNarsimhulu Musini */
1609c8806b6cSNarsimhulu Musini int
snic_abort_cmd(struct scsi_cmnd * sc)1610c8806b6cSNarsimhulu Musini snic_abort_cmd(struct scsi_cmnd *sc)
1611c8806b6cSNarsimhulu Musini {
1612c8806b6cSNarsimhulu Musini struct snic *snic = shost_priv(sc->device->host);
1613c8806b6cSNarsimhulu Musini int ret = SUCCESS, tag = snic_cmd_tag(sc);
1614c8806b6cSNarsimhulu Musini u32 start_time = jiffies;
1615c8806b6cSNarsimhulu Musini
1616c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "abt_cmd:sc %p :0x%x :req = %p :tag = %d\n",
1617ec808ef9SBart Van Assche sc, sc->cmnd[0], scsi_cmd_to_rq(sc), tag);
1618c8806b6cSNarsimhulu Musini
1619c8806b6cSNarsimhulu Musini if (unlikely(snic_get_state(snic) != SNIC_ONLINE)) {
1620c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
1621c8806b6cSNarsimhulu Musini "abt_cmd: tag %x Parent Devs are not rdy\n",
1622c8806b6cSNarsimhulu Musini tag);
1623c8806b6cSNarsimhulu Musini ret = FAST_IO_FAIL;
1624c8806b6cSNarsimhulu Musini
1625c8806b6cSNarsimhulu Musini goto abort_end;
1626c8806b6cSNarsimhulu Musini }
1627c8806b6cSNarsimhulu Musini
1628c8806b6cSNarsimhulu Musini
1629c8806b6cSNarsimhulu Musini ret = snic_send_abort_and_wait(snic, sc);
1630c8806b6cSNarsimhulu Musini if (ret)
1631c8806b6cSNarsimhulu Musini goto abort_end;
1632c8806b6cSNarsimhulu Musini
1633c8806b6cSNarsimhulu Musini ret = snic_abort_finish(snic, sc);
1634c8806b6cSNarsimhulu Musini
1635c8806b6cSNarsimhulu Musini abort_end:
1636c8806b6cSNarsimhulu Musini SNIC_TRC(snic->shost->host_no, tag, (ulong) sc,
1637c8806b6cSNarsimhulu Musini jiffies_to_msecs(jiffies - start_time), 0,
1638c8806b6cSNarsimhulu Musini SNIC_TRC_CMD(sc), SNIC_TRC_CMD_STATE_FLAGS(sc));
1639c8806b6cSNarsimhulu Musini
1640c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1641c8806b6cSNarsimhulu Musini "abts: Abort Req Status = %s\n",
1642c8806b6cSNarsimhulu Musini (ret == SUCCESS) ? "SUCCESS" :
1643c8806b6cSNarsimhulu Musini ((ret == FAST_IO_FAIL) ? "FAST_IO_FAIL" : "FAILED"));
1644c8806b6cSNarsimhulu Musini
1645c8806b6cSNarsimhulu Musini return ret;
1646c8806b6cSNarsimhulu Musini }
1647c8806b6cSNarsimhulu Musini
1648c8806b6cSNarsimhulu Musini
1649c8806b6cSNarsimhulu Musini
1650c8806b6cSNarsimhulu Musini static int
snic_is_abts_pending(struct snic * snic,struct scsi_cmnd * lr_sc)1651c8806b6cSNarsimhulu Musini snic_is_abts_pending(struct snic *snic, struct scsi_cmnd *lr_sc)
1652c8806b6cSNarsimhulu Musini {
1653c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
1654c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc = NULL;
1655c8806b6cSNarsimhulu Musini struct scsi_device *lr_sdev = NULL;
1656c8806b6cSNarsimhulu Musini spinlock_t *io_lock = NULL;
1657c8806b6cSNarsimhulu Musini u32 tag;
1658c8806b6cSNarsimhulu Musini unsigned long flags;
1659c8806b6cSNarsimhulu Musini
1660c8806b6cSNarsimhulu Musini if (lr_sc)
1661c8806b6cSNarsimhulu Musini lr_sdev = lr_sc->device;
1662c8806b6cSNarsimhulu Musini
1663c8806b6cSNarsimhulu Musini /* walk through the tag map, an dcheck if IOs are still pending in fw*/
1664c8806b6cSNarsimhulu Musini for (tag = 0; tag < snic->max_tag_id; tag++) {
1665c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_tag(snic, tag);
1666c8806b6cSNarsimhulu Musini
1667c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
1668c8806b6cSNarsimhulu Musini sc = scsi_host_find_tag(snic->shost, tag);
1669c8806b6cSNarsimhulu Musini
1670c8806b6cSNarsimhulu Musini if (!sc || (lr_sc && (sc->device != lr_sdev || sc == lr_sc))) {
1671c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1672c8806b6cSNarsimhulu Musini
1673c8806b6cSNarsimhulu Musini continue;
1674c8806b6cSNarsimhulu Musini }
1675c8806b6cSNarsimhulu Musini
1676c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
1677c8806b6cSNarsimhulu Musini if (!rqi) {
1678c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1679c8806b6cSNarsimhulu Musini
1680c8806b6cSNarsimhulu Musini continue;
1681c8806b6cSNarsimhulu Musini }
1682c8806b6cSNarsimhulu Musini
1683c8806b6cSNarsimhulu Musini /*
1684c8806b6cSNarsimhulu Musini * Found IO that is still pending w/ firmware and belongs to
1685c8806b6cSNarsimhulu Musini * the LUN that is under reset, if lr_sc != NULL
1686c8806b6cSNarsimhulu Musini */
1687c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "Found IO in %s on LUN\n",
1688c8806b6cSNarsimhulu Musini snic_ioreq_state_to_str(CMD_STATE(sc)));
1689c8806b6cSNarsimhulu Musini
1690c8806b6cSNarsimhulu Musini if (CMD_STATE(sc) == SNIC_IOREQ_ABTS_PENDING) {
1691c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1692c8806b6cSNarsimhulu Musini
1693c8806b6cSNarsimhulu Musini return 1;
1694c8806b6cSNarsimhulu Musini }
1695c8806b6cSNarsimhulu Musini
1696c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1697c8806b6cSNarsimhulu Musini }
1698c8806b6cSNarsimhulu Musini
1699c8806b6cSNarsimhulu Musini return 0;
1700c8806b6cSNarsimhulu Musini } /* end of snic_is_abts_pending */
1701c8806b6cSNarsimhulu Musini
1702c8806b6cSNarsimhulu Musini static int
snic_dr_clean_single_req(struct snic * snic,u32 tag,struct scsi_device * lr_sdev)1703c8806b6cSNarsimhulu Musini snic_dr_clean_single_req(struct snic *snic,
1704c8806b6cSNarsimhulu Musini u32 tag,
1705c8806b6cSNarsimhulu Musini struct scsi_device *lr_sdev)
1706c8806b6cSNarsimhulu Musini {
1707c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
1708c8806b6cSNarsimhulu Musini struct snic_tgt *tgt = NULL;
1709c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc = NULL;
1710c8806b6cSNarsimhulu Musini spinlock_t *io_lock = NULL;
1711c8806b6cSNarsimhulu Musini u32 sv_state = 0, tmf = 0;
1712c8806b6cSNarsimhulu Musini DECLARE_COMPLETION_ONSTACK(tm_done);
1713c8806b6cSNarsimhulu Musini unsigned long flags;
1714c8806b6cSNarsimhulu Musini int ret = 0;
1715c8806b6cSNarsimhulu Musini
1716c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_tag(snic, tag);
1717c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
1718c8806b6cSNarsimhulu Musini sc = scsi_host_find_tag(snic->shost, tag);
1719c8806b6cSNarsimhulu Musini
1720c8806b6cSNarsimhulu Musini /* Ignore Cmd that don't belong to Lun Reset device */
1721c8806b6cSNarsimhulu Musini if (!sc || sc->device != lr_sdev)
1722c8806b6cSNarsimhulu Musini goto skip_clean;
1723c8806b6cSNarsimhulu Musini
1724c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
1725c8806b6cSNarsimhulu Musini
1726c8806b6cSNarsimhulu Musini if (!rqi)
1727c8806b6cSNarsimhulu Musini goto skip_clean;
1728c8806b6cSNarsimhulu Musini
1729c8806b6cSNarsimhulu Musini
1730c8806b6cSNarsimhulu Musini if (CMD_STATE(sc) == SNIC_IOREQ_ABTS_PENDING)
1731c8806b6cSNarsimhulu Musini goto skip_clean;
1732c8806b6cSNarsimhulu Musini
1733c8806b6cSNarsimhulu Musini
1734c8806b6cSNarsimhulu Musini if ((CMD_FLAGS(sc) & SNIC_DEVICE_RESET) &&
1735c8806b6cSNarsimhulu Musini (!(CMD_FLAGS(sc) & SNIC_DEV_RST_ISSUED))) {
1736c8806b6cSNarsimhulu Musini
1737c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1738c8806b6cSNarsimhulu Musini "clean_single_req: devrst is not pending sc 0x%p\n",
1739c8806b6cSNarsimhulu Musini sc);
1740c8806b6cSNarsimhulu Musini
1741c8806b6cSNarsimhulu Musini goto skip_clean;
1742c8806b6cSNarsimhulu Musini }
1743c8806b6cSNarsimhulu Musini
1744c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1745c8806b6cSNarsimhulu Musini "clean_single_req: Found IO in %s on lun\n",
1746c8806b6cSNarsimhulu Musini snic_ioreq_state_to_str(CMD_STATE(sc)));
1747c8806b6cSNarsimhulu Musini
1748c8806b6cSNarsimhulu Musini /* Save Command State */
1749c8806b6cSNarsimhulu Musini sv_state = CMD_STATE(sc);
1750c8806b6cSNarsimhulu Musini
1751c8806b6cSNarsimhulu Musini /*
1752c8806b6cSNarsimhulu Musini * Any pending IO issued prior to reset is expected to be
1753c8806b6cSNarsimhulu Musini * in abts pending state, if not we need to set SNIC_IOREQ_ABTS_PENDING
1754c8806b6cSNarsimhulu Musini * to indicate the IO is abort pending.
1755c8806b6cSNarsimhulu Musini * When IO is completed, the IO will be handed over and handled
1756c8806b6cSNarsimhulu Musini * in this function.
1757c8806b6cSNarsimhulu Musini */
1758c8806b6cSNarsimhulu Musini
1759c8806b6cSNarsimhulu Musini CMD_STATE(sc) = SNIC_IOREQ_ABTS_PENDING;
1760c8806b6cSNarsimhulu Musini SNIC_BUG_ON(rqi->abts_done);
1761c8806b6cSNarsimhulu Musini
1762c8806b6cSNarsimhulu Musini if (CMD_FLAGS(sc) & SNIC_DEVICE_RESET) {
1763c8806b6cSNarsimhulu Musini rqi->tm_tag = SNIC_TAG_DEV_RST;
1764c8806b6cSNarsimhulu Musini
1765c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1766c8806b6cSNarsimhulu Musini "clean_single_req:devrst sc 0x%p\n", sc);
1767c8806b6cSNarsimhulu Musini }
1768c8806b6cSNarsimhulu Musini
1769c8806b6cSNarsimhulu Musini CMD_ABTS_STATUS(sc) = SNIC_INVALID_CODE;
1770c8806b6cSNarsimhulu Musini rqi->abts_done = &tm_done;
1771c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1772c8806b6cSNarsimhulu Musini
1773c8806b6cSNarsimhulu Musini tgt = starget_to_tgt(scsi_target(sc->device));
1774c8806b6cSNarsimhulu Musini if ((snic_tgt_chkready(tgt) != 0) && (tgt->tdata.typ == SNIC_TGT_SAN))
1775c8806b6cSNarsimhulu Musini tmf = SNIC_ITMF_ABTS_TASK_TERM;
1776c8806b6cSNarsimhulu Musini else
1777c8806b6cSNarsimhulu Musini tmf = SNIC_ITMF_ABTS_TASK;
1778c8806b6cSNarsimhulu Musini
1779c8806b6cSNarsimhulu Musini /* Now queue the abort command to firmware */
1780c8806b6cSNarsimhulu Musini ret = snic_queue_abort_req(snic, rqi, sc, tmf);
1781c8806b6cSNarsimhulu Musini if (ret) {
1782c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
1783c8806b6cSNarsimhulu Musini "clean_single_req_err:sc %p, tag %d abt failed. tm_tag %d flags 0x%llx\n",
1784c8806b6cSNarsimhulu Musini sc, tag, rqi->tm_tag, CMD_FLAGS(sc));
1785c8806b6cSNarsimhulu Musini
1786c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
1787c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
1788c8806b6cSNarsimhulu Musini if (rqi)
1789c8806b6cSNarsimhulu Musini rqi->abts_done = NULL;
1790c8806b6cSNarsimhulu Musini
1791c8806b6cSNarsimhulu Musini /* Restore Command State */
1792c8806b6cSNarsimhulu Musini if (CMD_STATE(sc) == SNIC_IOREQ_ABTS_PENDING)
1793c8806b6cSNarsimhulu Musini CMD_STATE(sc) = sv_state;
1794c8806b6cSNarsimhulu Musini
1795c8806b6cSNarsimhulu Musini ret = 1;
1796c8806b6cSNarsimhulu Musini goto skip_clean;
1797c8806b6cSNarsimhulu Musini }
1798c8806b6cSNarsimhulu Musini
1799c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
1800c8806b6cSNarsimhulu Musini if (CMD_FLAGS(sc) & SNIC_DEVICE_RESET)
1801c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_DEV_RST_TERM_ISSUED;
1802c8806b6cSNarsimhulu Musini
1803c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_INTERNAL_TERM_ISSUED;
1804c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1805c8806b6cSNarsimhulu Musini
1806c8806b6cSNarsimhulu Musini wait_for_completion_timeout(&tm_done, SNIC_ABTS_TIMEOUT);
1807c8806b6cSNarsimhulu Musini
1808c8806b6cSNarsimhulu Musini /* Recheck cmd state to check if it now aborted. */
1809c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
1810c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
1811c8806b6cSNarsimhulu Musini if (!rqi) {
1812c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_ABTS_TERM_REQ_NULL;
1813c8806b6cSNarsimhulu Musini goto skip_clean;
1814c8806b6cSNarsimhulu Musini }
1815c8806b6cSNarsimhulu Musini rqi->abts_done = NULL;
1816c8806b6cSNarsimhulu Musini
1817c8806b6cSNarsimhulu Musini /* if abort is still pending w/ fw, fail */
1818c8806b6cSNarsimhulu Musini if (CMD_ABTS_STATUS(sc) == SNIC_INVALID_CODE) {
1819c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
1820c8806b6cSNarsimhulu Musini "clean_single_req_err:sc %p tag %d abt still pending w/ fw, tm_tag %d flags 0x%llx\n",
1821c8806b6cSNarsimhulu Musini sc, tag, rqi->tm_tag, CMD_FLAGS(sc));
1822c8806b6cSNarsimhulu Musini
1823c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_ABTS_TERM_DONE;
1824c8806b6cSNarsimhulu Musini ret = 1;
1825c8806b6cSNarsimhulu Musini
1826c8806b6cSNarsimhulu Musini goto skip_clean;
1827c8806b6cSNarsimhulu Musini }
1828c8806b6cSNarsimhulu Musini
1829c8806b6cSNarsimhulu Musini CMD_STATE(sc) = SNIC_IOREQ_ABTS_COMPLETE;
1830c8806b6cSNarsimhulu Musini CMD_SP(sc) = NULL;
1831c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1832c8806b6cSNarsimhulu Musini
1833c8806b6cSNarsimhulu Musini snic_release_req_buf(snic, rqi, sc);
1834c8806b6cSNarsimhulu Musini
1835f352a0d5SNarsimhulu Musini sc->result = (DID_ERROR << 16);
183670a5caf1SBart Van Assche scsi_done(sc);
1837f352a0d5SNarsimhulu Musini
1838c8806b6cSNarsimhulu Musini ret = 0;
1839c8806b6cSNarsimhulu Musini
1840c8806b6cSNarsimhulu Musini return ret;
1841c8806b6cSNarsimhulu Musini
1842c8806b6cSNarsimhulu Musini skip_clean:
1843c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1844c8806b6cSNarsimhulu Musini
1845c8806b6cSNarsimhulu Musini return ret;
1846c8806b6cSNarsimhulu Musini } /* end of snic_dr_clean_single_req */
1847c8806b6cSNarsimhulu Musini
1848c8806b6cSNarsimhulu Musini static int
snic_dr_clean_pending_req(struct snic * snic,struct scsi_cmnd * lr_sc)1849c8806b6cSNarsimhulu Musini snic_dr_clean_pending_req(struct snic *snic, struct scsi_cmnd *lr_sc)
1850c8806b6cSNarsimhulu Musini {
1851c8806b6cSNarsimhulu Musini struct scsi_device *lr_sdev = lr_sc->device;
1852c8806b6cSNarsimhulu Musini u32 tag = 0;
1853c8806b6cSNarsimhulu Musini int ret = FAILED;
1854c8806b6cSNarsimhulu Musini
1855c8806b6cSNarsimhulu Musini for (tag = 0; tag < snic->max_tag_id; tag++) {
1856c8806b6cSNarsimhulu Musini if (tag == snic_cmd_tag(lr_sc))
1857c8806b6cSNarsimhulu Musini continue;
1858c8806b6cSNarsimhulu Musini
1859c8806b6cSNarsimhulu Musini ret = snic_dr_clean_single_req(snic, tag, lr_sdev);
1860c8806b6cSNarsimhulu Musini if (ret) {
1861c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost, "clean_err:tag = %d\n", tag);
1862c8806b6cSNarsimhulu Musini
1863c8806b6cSNarsimhulu Musini goto clean_err;
1864c8806b6cSNarsimhulu Musini }
1865c8806b6cSNarsimhulu Musini }
1866c8806b6cSNarsimhulu Musini
1867c8806b6cSNarsimhulu Musini schedule_timeout(msecs_to_jiffies(100));
1868c8806b6cSNarsimhulu Musini
1869c8806b6cSNarsimhulu Musini /* Walk through all the cmds and check abts status. */
1870c8806b6cSNarsimhulu Musini if (snic_is_abts_pending(snic, lr_sc)) {
1871c8806b6cSNarsimhulu Musini ret = FAILED;
1872c8806b6cSNarsimhulu Musini
1873c8806b6cSNarsimhulu Musini goto clean_err;
1874c8806b6cSNarsimhulu Musini }
1875c8806b6cSNarsimhulu Musini
1876c8806b6cSNarsimhulu Musini ret = 0;
1877c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "clean_pending_req: Success.\n");
1878c8806b6cSNarsimhulu Musini
1879c8806b6cSNarsimhulu Musini return ret;
1880c8806b6cSNarsimhulu Musini
1881c8806b6cSNarsimhulu Musini clean_err:
1882c8806b6cSNarsimhulu Musini ret = FAILED;
1883c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
1884c8806b6cSNarsimhulu Musini "Failed to Clean Pending IOs on %s device.\n",
1885c8806b6cSNarsimhulu Musini dev_name(&lr_sdev->sdev_gendev));
1886c8806b6cSNarsimhulu Musini
1887c8806b6cSNarsimhulu Musini return ret;
1888c8806b6cSNarsimhulu Musini
1889c8806b6cSNarsimhulu Musini } /* end of snic_dr_clean_pending_req */
1890c8806b6cSNarsimhulu Musini
1891c8806b6cSNarsimhulu Musini /*
1892c8806b6cSNarsimhulu Musini * snic_dr_finish : Called by snic_device_reset
1893c8806b6cSNarsimhulu Musini */
1894c8806b6cSNarsimhulu Musini static int
snic_dr_finish(struct snic * snic,struct scsi_cmnd * sc)1895c8806b6cSNarsimhulu Musini snic_dr_finish(struct snic *snic, struct scsi_cmnd *sc)
1896c8806b6cSNarsimhulu Musini {
1897c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
1898c8806b6cSNarsimhulu Musini spinlock_t *io_lock = NULL;
1899c8806b6cSNarsimhulu Musini unsigned long flags;
1900c8806b6cSNarsimhulu Musini int lr_res = 0;
1901c8806b6cSNarsimhulu Musini int ret = FAILED;
1902c8806b6cSNarsimhulu Musini
1903c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_hash(snic, sc);
1904c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
1905c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
1906c8806b6cSNarsimhulu Musini if (!rqi) {
1907c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1908c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1909c8806b6cSNarsimhulu Musini "dr_fini: rqi is null tag 0x%x sc 0x%p flags 0x%llx\n",
1910c8806b6cSNarsimhulu Musini snic_cmd_tag(sc), sc, CMD_FLAGS(sc));
1911c8806b6cSNarsimhulu Musini
1912c8806b6cSNarsimhulu Musini ret = FAILED;
1913c8806b6cSNarsimhulu Musini goto dr_fini_end;
1914c8806b6cSNarsimhulu Musini }
1915c8806b6cSNarsimhulu Musini
1916c8806b6cSNarsimhulu Musini rqi->dr_done = NULL;
1917c8806b6cSNarsimhulu Musini
1918c8806b6cSNarsimhulu Musini lr_res = CMD_LR_STATUS(sc);
1919c8806b6cSNarsimhulu Musini
1920c8806b6cSNarsimhulu Musini switch (lr_res) {
1921c8806b6cSNarsimhulu Musini case SNIC_INVALID_CODE:
1922c8806b6cSNarsimhulu Musini /* stats */
1923c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1924c8806b6cSNarsimhulu Musini "dr_fini: Tag %x Dev Reset Timedout. flags 0x%llx\n",
1925c8806b6cSNarsimhulu Musini snic_cmd_tag(sc), CMD_FLAGS(sc));
1926c8806b6cSNarsimhulu Musini
1927c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_DEV_RST_TIMEDOUT;
1928c8806b6cSNarsimhulu Musini ret = FAILED;
1929c8806b6cSNarsimhulu Musini
1930c8806b6cSNarsimhulu Musini goto dr_failed;
1931c8806b6cSNarsimhulu Musini
1932c8806b6cSNarsimhulu Musini case SNIC_STAT_IO_SUCCESS:
1933c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1934c8806b6cSNarsimhulu Musini "dr_fini: Tag %x Dev Reset cmpl\n",
1935c8806b6cSNarsimhulu Musini snic_cmd_tag(sc));
1936c8806b6cSNarsimhulu Musini ret = 0;
1937c8806b6cSNarsimhulu Musini break;
1938c8806b6cSNarsimhulu Musini
1939c8806b6cSNarsimhulu Musini default:
1940c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
1941c8806b6cSNarsimhulu Musini "dr_fini:Device Reset completed& failed.Tag = %x lr_status %s flags 0x%llx\n",
1942c8806b6cSNarsimhulu Musini snic_cmd_tag(sc),
1943c8806b6cSNarsimhulu Musini snic_io_status_to_str(lr_res), CMD_FLAGS(sc));
1944c8806b6cSNarsimhulu Musini ret = FAILED;
1945c8806b6cSNarsimhulu Musini goto dr_failed;
1946c8806b6cSNarsimhulu Musini }
1947c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1948c8806b6cSNarsimhulu Musini
1949c8806b6cSNarsimhulu Musini /*
1950c8806b6cSNarsimhulu Musini * Cleanup any IOs on this LUN that have still not completed.
1951c8806b6cSNarsimhulu Musini * If any of these fail, then LUN Reset fails.
1952c8806b6cSNarsimhulu Musini * Cleanup cleans all commands on this LUN except
1953c8806b6cSNarsimhulu Musini * the lun reset command. If all cmds get cleaned, the LUN Reset
1954c8806b6cSNarsimhulu Musini * succeeds.
1955c8806b6cSNarsimhulu Musini */
1956c8806b6cSNarsimhulu Musini
1957c8806b6cSNarsimhulu Musini ret = snic_dr_clean_pending_req(snic, sc);
1958c8806b6cSNarsimhulu Musini if (ret) {
1959c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
1960c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
1961c8806b6cSNarsimhulu Musini "dr_fini: Device Reset Failed since could not abort all IOs. Tag = %x.\n",
1962c8806b6cSNarsimhulu Musini snic_cmd_tag(sc));
1963c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
1964c8806b6cSNarsimhulu Musini
1965c8806b6cSNarsimhulu Musini goto dr_failed;
1966c8806b6cSNarsimhulu Musini } else {
1967c8806b6cSNarsimhulu Musini /* Cleanup LUN Reset Command */
1968c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
1969c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
1970c8806b6cSNarsimhulu Musini if (rqi)
1971c8806b6cSNarsimhulu Musini ret = SUCCESS; /* Completed Successfully */
1972c8806b6cSNarsimhulu Musini else
1973c8806b6cSNarsimhulu Musini ret = FAILED;
1974c8806b6cSNarsimhulu Musini }
1975c8806b6cSNarsimhulu Musini
1976c8806b6cSNarsimhulu Musini dr_failed:
197751aef716SLance Roy lockdep_assert_held(io_lock);
1978c8806b6cSNarsimhulu Musini if (rqi)
1979c8806b6cSNarsimhulu Musini CMD_SP(sc) = NULL;
1980c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
1981c8806b6cSNarsimhulu Musini
1982c8806b6cSNarsimhulu Musini if (rqi)
1983c8806b6cSNarsimhulu Musini snic_release_req_buf(snic, rqi, sc);
1984c8806b6cSNarsimhulu Musini
1985c8806b6cSNarsimhulu Musini dr_fini_end:
1986c8806b6cSNarsimhulu Musini return ret;
1987c8806b6cSNarsimhulu Musini } /* end of snic_dr_finish */
1988c8806b6cSNarsimhulu Musini
1989c8806b6cSNarsimhulu Musini static int
snic_queue_dr_req(struct snic * snic,struct snic_req_info * rqi,struct scsi_cmnd * sc)1990c8806b6cSNarsimhulu Musini snic_queue_dr_req(struct snic *snic,
1991c8806b6cSNarsimhulu Musini struct snic_req_info *rqi,
1992c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc)
1993c8806b6cSNarsimhulu Musini {
1994c8806b6cSNarsimhulu Musini /* Add special tag for device reset */
1995c8806b6cSNarsimhulu Musini rqi->tm_tag |= SNIC_TAG_DEV_RST;
1996c8806b6cSNarsimhulu Musini
1997c8806b6cSNarsimhulu Musini return snic_issue_tm_req(snic, rqi, sc, SNIC_ITMF_LUN_RESET);
1998c8806b6cSNarsimhulu Musini }
1999c8806b6cSNarsimhulu Musini
2000c8806b6cSNarsimhulu Musini static int
snic_send_dr_and_wait(struct snic * snic,struct scsi_cmnd * sc)2001c8806b6cSNarsimhulu Musini snic_send_dr_and_wait(struct snic *snic, struct scsi_cmnd *sc)
2002c8806b6cSNarsimhulu Musini {
2003c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
2004c8806b6cSNarsimhulu Musini enum snic_ioreq_state sv_state;
2005c8806b6cSNarsimhulu Musini spinlock_t *io_lock = NULL;
2006c8806b6cSNarsimhulu Musini unsigned long flags;
2007c8806b6cSNarsimhulu Musini DECLARE_COMPLETION_ONSTACK(tm_done);
2008c8806b6cSNarsimhulu Musini int ret = FAILED, tag = snic_cmd_tag(sc);
2009c8806b6cSNarsimhulu Musini
2010c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_hash(snic, sc);
2011c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
2012c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_DEVICE_RESET;
2013c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
2014c8806b6cSNarsimhulu Musini if (!rqi) {
2015c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
2016c8806b6cSNarsimhulu Musini "send_dr: rqi is null, Tag 0x%x flags 0x%llx\n",
2017c8806b6cSNarsimhulu Musini tag, CMD_FLAGS(sc));
2018c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2019c8806b6cSNarsimhulu Musini
2020c8806b6cSNarsimhulu Musini ret = FAILED;
2021c8806b6cSNarsimhulu Musini goto send_dr_end;
2022c8806b6cSNarsimhulu Musini }
2023c8806b6cSNarsimhulu Musini
2024c8806b6cSNarsimhulu Musini /* Save Command state to restore in case Queuing failed. */
2025c8806b6cSNarsimhulu Musini sv_state = CMD_STATE(sc);
2026c8806b6cSNarsimhulu Musini
2027c8806b6cSNarsimhulu Musini CMD_STATE(sc) = SNIC_IOREQ_LR_PENDING;
2028c8806b6cSNarsimhulu Musini CMD_LR_STATUS(sc) = SNIC_INVALID_CODE;
2029c8806b6cSNarsimhulu Musini
2030c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "dr: TAG = %x\n", tag);
2031c8806b6cSNarsimhulu Musini
2032c8806b6cSNarsimhulu Musini rqi->dr_done = &tm_done;
2033c8806b6cSNarsimhulu Musini SNIC_BUG_ON(!rqi->dr_done);
2034c8806b6cSNarsimhulu Musini
2035c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2036c8806b6cSNarsimhulu Musini /*
2037c8806b6cSNarsimhulu Musini * The Command state is changed to IOREQ_PENDING,
2038c8806b6cSNarsimhulu Musini * in this case, if the command is completed, the icmnd_cmpl will
2039c8806b6cSNarsimhulu Musini * mark the cmd as completed.
2040c8806b6cSNarsimhulu Musini * This logic still makes LUN Reset is inevitable.
2041c8806b6cSNarsimhulu Musini */
2042c8806b6cSNarsimhulu Musini
2043c8806b6cSNarsimhulu Musini ret = snic_queue_dr_req(snic, rqi, sc);
2044c8806b6cSNarsimhulu Musini if (ret) {
2045c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
2046c8806b6cSNarsimhulu Musini "send_dr: IO w/ Tag 0x%x Failed err = %d. flags 0x%llx\n",
2047c8806b6cSNarsimhulu Musini tag, ret, CMD_FLAGS(sc));
2048c8806b6cSNarsimhulu Musini
2049c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
2050c8806b6cSNarsimhulu Musini /* Restore State */
2051c8806b6cSNarsimhulu Musini CMD_STATE(sc) = sv_state;
2052c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
2053c8806b6cSNarsimhulu Musini if (rqi)
2054c8806b6cSNarsimhulu Musini rqi->dr_done = NULL;
2055c8806b6cSNarsimhulu Musini /* rqi is freed in caller. */
2056c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2057c8806b6cSNarsimhulu Musini ret = FAILED;
2058c8806b6cSNarsimhulu Musini
2059c8806b6cSNarsimhulu Musini goto send_dr_end;
2060c8806b6cSNarsimhulu Musini }
2061c8806b6cSNarsimhulu Musini
2062c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
2063c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_DEV_RST_ISSUED;
2064c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2065c8806b6cSNarsimhulu Musini
2066c8806b6cSNarsimhulu Musini ret = 0;
2067c8806b6cSNarsimhulu Musini
2068c8806b6cSNarsimhulu Musini wait_for_completion_timeout(&tm_done, SNIC_LUN_RESET_TIMEOUT);
2069c8806b6cSNarsimhulu Musini
2070c8806b6cSNarsimhulu Musini send_dr_end:
2071c8806b6cSNarsimhulu Musini return ret;
2072c8806b6cSNarsimhulu Musini }
2073c8806b6cSNarsimhulu Musini
2074c8806b6cSNarsimhulu Musini /*
2075c8806b6cSNarsimhulu Musini * auxillary funciton to check lun reset op is supported or not
2076c8806b6cSNarsimhulu Musini * Not supported if returns 0
2077c8806b6cSNarsimhulu Musini */
2078c8806b6cSNarsimhulu Musini static int
snic_dev_reset_supported(struct scsi_device * sdev)2079c8806b6cSNarsimhulu Musini snic_dev_reset_supported(struct scsi_device *sdev)
2080c8806b6cSNarsimhulu Musini {
2081c8806b6cSNarsimhulu Musini struct snic_tgt *tgt = starget_to_tgt(scsi_target(sdev));
2082c8806b6cSNarsimhulu Musini
2083c8806b6cSNarsimhulu Musini if (tgt->tdata.typ == SNIC_TGT_DAS)
2084c8806b6cSNarsimhulu Musini return 0;
2085c8806b6cSNarsimhulu Musini
2086c8806b6cSNarsimhulu Musini return 1;
2087c8806b6cSNarsimhulu Musini }
2088c8806b6cSNarsimhulu Musini
2089c8806b6cSNarsimhulu Musini static void
snic_unlink_and_release_req(struct snic * snic,struct scsi_cmnd * sc,int flag)2090c8806b6cSNarsimhulu Musini snic_unlink_and_release_req(struct snic *snic, struct scsi_cmnd *sc, int flag)
2091c8806b6cSNarsimhulu Musini {
2092c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
2093c8806b6cSNarsimhulu Musini spinlock_t *io_lock = NULL;
2094c8806b6cSNarsimhulu Musini unsigned long flags;
2095c8806b6cSNarsimhulu Musini u32 start_time = jiffies;
2096c8806b6cSNarsimhulu Musini
2097c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_hash(snic, sc);
2098c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
2099c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
2100c8806b6cSNarsimhulu Musini if (rqi) {
2101c8806b6cSNarsimhulu Musini start_time = rqi->start_time;
2102c8806b6cSNarsimhulu Musini CMD_SP(sc) = NULL;
2103c8806b6cSNarsimhulu Musini }
2104c8806b6cSNarsimhulu Musini
2105c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= flag;
2106c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2107c8806b6cSNarsimhulu Musini
2108c8806b6cSNarsimhulu Musini if (rqi)
2109c8806b6cSNarsimhulu Musini snic_release_req_buf(snic, rqi, sc);
2110c8806b6cSNarsimhulu Musini
2111c8806b6cSNarsimhulu Musini SNIC_TRC(snic->shost->host_no, snic_cmd_tag(sc), (ulong) sc,
2112c8806b6cSNarsimhulu Musini jiffies_to_msecs(jiffies - start_time), (ulong) rqi,
2113c8806b6cSNarsimhulu Musini SNIC_TRC_CMD(sc), SNIC_TRC_CMD_STATE_FLAGS(sc));
2114c8806b6cSNarsimhulu Musini }
2115c8806b6cSNarsimhulu Musini
2116c8806b6cSNarsimhulu Musini /*
2117c8806b6cSNarsimhulu Musini * SCSI Eh thread issues a LUN Reset when one or more commands on a LUN
2118c8806b6cSNarsimhulu Musini * fail to get aborted. It calls driver's eh_device_reset with a SCSI
2119c8806b6cSNarsimhulu Musini * command on the LUN.
2120c8806b6cSNarsimhulu Musini */
2121c8806b6cSNarsimhulu Musini int
snic_device_reset(struct scsi_cmnd * sc)2122c8806b6cSNarsimhulu Musini snic_device_reset(struct scsi_cmnd *sc)
2123c8806b6cSNarsimhulu Musini {
2124c8806b6cSNarsimhulu Musini struct Scsi_Host *shost = sc->device->host;
2125c8806b6cSNarsimhulu Musini struct snic *snic = shost_priv(shost);
2126c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
2127c8806b6cSNarsimhulu Musini int tag = snic_cmd_tag(sc);
2128c8806b6cSNarsimhulu Musini int start_time = jiffies;
2129c8806b6cSNarsimhulu Musini int ret = FAILED;
2130c8806b6cSNarsimhulu Musini int dr_supp = 0;
2131c8806b6cSNarsimhulu Musini
2132c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(shost, "dev_reset:sc %p :0x%x :req = %p :tag = %d\n",
2133ec808ef9SBart Van Assche sc, sc->cmnd[0], scsi_cmd_to_rq(sc),
2134c8806b6cSNarsimhulu Musini snic_cmd_tag(sc));
2135c8806b6cSNarsimhulu Musini dr_supp = snic_dev_reset_supported(sc->device);
2136c8806b6cSNarsimhulu Musini if (!dr_supp) {
2137c8806b6cSNarsimhulu Musini /* device reset op is not supported */
2138c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(shost, "LUN Reset Op not supported.\n");
2139c8806b6cSNarsimhulu Musini snic_unlink_and_release_req(snic, sc, SNIC_DEV_RST_NOTSUP);
2140c8806b6cSNarsimhulu Musini
2141c8806b6cSNarsimhulu Musini goto dev_rst_end;
2142c8806b6cSNarsimhulu Musini }
2143c8806b6cSNarsimhulu Musini
2144c8806b6cSNarsimhulu Musini if (unlikely(snic_get_state(snic) != SNIC_ONLINE)) {
2145c8806b6cSNarsimhulu Musini snic_unlink_and_release_req(snic, sc, 0);
2146c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(shost, "Devrst: Parent Devs are not online.\n");
2147c8806b6cSNarsimhulu Musini
2148c8806b6cSNarsimhulu Musini goto dev_rst_end;
2149c8806b6cSNarsimhulu Musini }
2150c8806b6cSNarsimhulu Musini
2151c8806b6cSNarsimhulu Musini /* There is no tag when lun reset is issue through ioctl. */
2152c8806b6cSNarsimhulu Musini if (unlikely(tag <= SNIC_NO_TAG)) {
2153c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost,
2154c8806b6cSNarsimhulu Musini "Devrst: LUN Reset Recvd thru IOCTL.\n");
2155c8806b6cSNarsimhulu Musini
2156c8806b6cSNarsimhulu Musini rqi = snic_req_init(snic, 0);
2157c8806b6cSNarsimhulu Musini if (!rqi)
2158c8806b6cSNarsimhulu Musini goto dev_rst_end;
2159c8806b6cSNarsimhulu Musini
2160c8806b6cSNarsimhulu Musini memset(scsi_cmd_priv(sc), 0,
2161c8806b6cSNarsimhulu Musini sizeof(struct snic_internal_io_state));
2162c8806b6cSNarsimhulu Musini CMD_SP(sc) = (char *)rqi;
2163c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) = SNIC_NO_FLAGS;
2164c8806b6cSNarsimhulu Musini
2165c8806b6cSNarsimhulu Musini /* Add special tag for dr coming from user spc */
2166c8806b6cSNarsimhulu Musini rqi->tm_tag = SNIC_TAG_IOCTL_DEV_RST;
2167c8806b6cSNarsimhulu Musini rqi->sc = sc;
2168c8806b6cSNarsimhulu Musini }
2169c8806b6cSNarsimhulu Musini
2170c8806b6cSNarsimhulu Musini ret = snic_send_dr_and_wait(snic, sc);
2171c8806b6cSNarsimhulu Musini if (ret) {
2172c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
2173c8806b6cSNarsimhulu Musini "Devrst: IO w/ Tag %x Failed w/ err = %d\n",
2174c8806b6cSNarsimhulu Musini tag, ret);
2175c8806b6cSNarsimhulu Musini
2176c8806b6cSNarsimhulu Musini snic_unlink_and_release_req(snic, sc, 0);
2177c8806b6cSNarsimhulu Musini
2178c8806b6cSNarsimhulu Musini goto dev_rst_end;
2179c8806b6cSNarsimhulu Musini }
2180c8806b6cSNarsimhulu Musini
2181c8806b6cSNarsimhulu Musini ret = snic_dr_finish(snic, sc);
2182c8806b6cSNarsimhulu Musini
2183c8806b6cSNarsimhulu Musini dev_rst_end:
2184c8806b6cSNarsimhulu Musini SNIC_TRC(snic->shost->host_no, tag, (ulong) sc,
2185c8806b6cSNarsimhulu Musini jiffies_to_msecs(jiffies - start_time),
2186c8806b6cSNarsimhulu Musini 0, SNIC_TRC_CMD(sc), SNIC_TRC_CMD_STATE_FLAGS(sc));
2187c8806b6cSNarsimhulu Musini
2188c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
2189c8806b6cSNarsimhulu Musini "Devrst: Returning from Device Reset : %s\n",
2190c8806b6cSNarsimhulu Musini (ret == SUCCESS) ? "SUCCESS" : "FAILED");
2191c8806b6cSNarsimhulu Musini
2192c8806b6cSNarsimhulu Musini return ret;
2193c8806b6cSNarsimhulu Musini } /* end of snic_device_reset */
2194c8806b6cSNarsimhulu Musini
2195c8806b6cSNarsimhulu Musini /*
2196c8806b6cSNarsimhulu Musini * SCSI Error handling calls driver's eh_host_reset if all prior
2197c8806b6cSNarsimhulu Musini * error handling levels return FAILED.
2198c8806b6cSNarsimhulu Musini *
2199c8806b6cSNarsimhulu Musini * Host Reset is the highest level of error recovery. If this fails, then
2200c8806b6cSNarsimhulu Musini * host is offlined by SCSI.
2201c8806b6cSNarsimhulu Musini */
2202c8806b6cSNarsimhulu Musini /*
2203c8806b6cSNarsimhulu Musini * snic_issue_hba_reset : Queues FW Reset Request.
2204c8806b6cSNarsimhulu Musini */
2205c8806b6cSNarsimhulu Musini static int
snic_issue_hba_reset(struct snic * snic,struct scsi_cmnd * sc)2206c8806b6cSNarsimhulu Musini snic_issue_hba_reset(struct snic *snic, struct scsi_cmnd *sc)
2207c8806b6cSNarsimhulu Musini {
2208c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
2209c8806b6cSNarsimhulu Musini struct snic_host_req *req = NULL;
2210c8806b6cSNarsimhulu Musini spinlock_t *io_lock = NULL;
2211c8806b6cSNarsimhulu Musini DECLARE_COMPLETION_ONSTACK(wait);
2212c8806b6cSNarsimhulu Musini unsigned long flags;
2213c8806b6cSNarsimhulu Musini int ret = -ENOMEM;
2214c8806b6cSNarsimhulu Musini
2215c8806b6cSNarsimhulu Musini rqi = snic_req_init(snic, 0);
2216c8806b6cSNarsimhulu Musini if (!rqi) {
2217c8806b6cSNarsimhulu Musini ret = -ENOMEM;
2218c8806b6cSNarsimhulu Musini
2219c8806b6cSNarsimhulu Musini goto hba_rst_end;
2220c8806b6cSNarsimhulu Musini }
2221c8806b6cSNarsimhulu Musini
2222c8806b6cSNarsimhulu Musini if (snic_cmd_tag(sc) == SCSI_NO_TAG) {
2223c8806b6cSNarsimhulu Musini memset(scsi_cmd_priv(sc), 0,
2224c8806b6cSNarsimhulu Musini sizeof(struct snic_internal_io_state));
2225c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "issu_hr:Host reset thru ioctl.\n");
2226c8806b6cSNarsimhulu Musini rqi->sc = sc;
2227c8806b6cSNarsimhulu Musini }
2228c8806b6cSNarsimhulu Musini
2229c8806b6cSNarsimhulu Musini req = rqi_to_req(rqi);
2230c8806b6cSNarsimhulu Musini
2231c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_hash(snic, sc);
2232c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
2233c8806b6cSNarsimhulu Musini SNIC_BUG_ON(CMD_SP(sc) != NULL);
2234c8806b6cSNarsimhulu Musini CMD_STATE(sc) = SNIC_IOREQ_PENDING;
2235c8806b6cSNarsimhulu Musini CMD_SP(sc) = (char *) rqi;
2236c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_INITIALIZED;
2237c8806b6cSNarsimhulu Musini snic->remove_wait = &wait;
2238c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2239c8806b6cSNarsimhulu Musini
2240c8806b6cSNarsimhulu Musini /* Initialize Request */
2241c8806b6cSNarsimhulu Musini snic_io_hdr_enc(&req->hdr, SNIC_REQ_HBA_RESET, 0, snic_cmd_tag(sc),
2242c8806b6cSNarsimhulu Musini snic->config.hid, 0, (ulong) rqi);
2243c8806b6cSNarsimhulu Musini
2244c8806b6cSNarsimhulu Musini req->u.reset.flags = 0;
2245c8806b6cSNarsimhulu Musini
2246c8806b6cSNarsimhulu Musini ret = snic_queue_wq_desc(snic, req, sizeof(*req));
2247c8806b6cSNarsimhulu Musini if (ret) {
2248c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
2249c8806b6cSNarsimhulu Musini "issu_hr:Queuing HBA Reset Failed. w err %d\n",
2250c8806b6cSNarsimhulu Musini ret);
2251c8806b6cSNarsimhulu Musini
2252c8806b6cSNarsimhulu Musini goto hba_rst_err;
2253c8806b6cSNarsimhulu Musini }
2254c8806b6cSNarsimhulu Musini
2255c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
2256c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_HOST_RESET_ISSUED;
2257c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2258c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.reset.hba_resets);
2259c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "Queued HBA Reset Successfully.\n");
2260c8806b6cSNarsimhulu Musini
2261c8806b6cSNarsimhulu Musini wait_for_completion_timeout(snic->remove_wait,
2262c8806b6cSNarsimhulu Musini SNIC_HOST_RESET_TIMEOUT);
2263c8806b6cSNarsimhulu Musini
2264c8806b6cSNarsimhulu Musini if (snic_get_state(snic) == SNIC_FWRESET) {
2265c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost, "reset_cmpl: Reset Timedout.\n");
2266c8806b6cSNarsimhulu Musini ret = -ETIMEDOUT;
2267c8806b6cSNarsimhulu Musini
2268c8806b6cSNarsimhulu Musini goto hba_rst_err;
2269c8806b6cSNarsimhulu Musini }
2270c8806b6cSNarsimhulu Musini
2271c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
2272c8806b6cSNarsimhulu Musini snic->remove_wait = NULL;
2273c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
2274c8806b6cSNarsimhulu Musini CMD_SP(sc) = NULL;
2275c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2276c8806b6cSNarsimhulu Musini
2277c8806b6cSNarsimhulu Musini if (rqi)
2278c8806b6cSNarsimhulu Musini snic_req_free(snic, rqi);
2279c8806b6cSNarsimhulu Musini
2280c8806b6cSNarsimhulu Musini ret = 0;
2281c8806b6cSNarsimhulu Musini
2282c8806b6cSNarsimhulu Musini return ret;
2283c8806b6cSNarsimhulu Musini
2284c8806b6cSNarsimhulu Musini hba_rst_err:
2285c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
2286c8806b6cSNarsimhulu Musini snic->remove_wait = NULL;
2287c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
2288c8806b6cSNarsimhulu Musini CMD_SP(sc) = NULL;
2289c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2290c8806b6cSNarsimhulu Musini
2291c8806b6cSNarsimhulu Musini if (rqi)
2292c8806b6cSNarsimhulu Musini snic_req_free(snic, rqi);
2293c8806b6cSNarsimhulu Musini
2294c8806b6cSNarsimhulu Musini hba_rst_end:
2295c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
2296c8806b6cSNarsimhulu Musini "reset:HBA Reset Failed w/ err = %d.\n",
2297c8806b6cSNarsimhulu Musini ret);
2298c8806b6cSNarsimhulu Musini
2299c8806b6cSNarsimhulu Musini return ret;
2300c8806b6cSNarsimhulu Musini } /* end of snic_issue_hba_reset */
2301c8806b6cSNarsimhulu Musini
2302c8806b6cSNarsimhulu Musini int
snic_reset(struct Scsi_Host * shost,struct scsi_cmnd * sc)2303c8806b6cSNarsimhulu Musini snic_reset(struct Scsi_Host *shost, struct scsi_cmnd *sc)
2304c8806b6cSNarsimhulu Musini {
2305c8806b6cSNarsimhulu Musini struct snic *snic = shost_priv(shost);
2306c8806b6cSNarsimhulu Musini enum snic_state sv_state;
2307c8806b6cSNarsimhulu Musini unsigned long flags;
2308c8806b6cSNarsimhulu Musini int ret = FAILED;
2309c8806b6cSNarsimhulu Musini
2310c8806b6cSNarsimhulu Musini /* Set snic state as SNIC_FWRESET*/
2311c8806b6cSNarsimhulu Musini sv_state = snic_get_state(snic);
2312c8806b6cSNarsimhulu Musini
2313c8806b6cSNarsimhulu Musini spin_lock_irqsave(&snic->snic_lock, flags);
2314c8806b6cSNarsimhulu Musini if (snic_get_state(snic) == SNIC_FWRESET) {
2315c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(&snic->snic_lock, flags);
23161259d5f0SColin Ian King SNIC_HOST_INFO(shost, "reset:prev reset is in progress\n");
2317c8806b6cSNarsimhulu Musini
2318c8806b6cSNarsimhulu Musini msleep(SNIC_HOST_RESET_TIMEOUT);
2319c8806b6cSNarsimhulu Musini ret = SUCCESS;
2320c8806b6cSNarsimhulu Musini
2321c8806b6cSNarsimhulu Musini goto reset_end;
2322c8806b6cSNarsimhulu Musini }
2323c8806b6cSNarsimhulu Musini
2324c8806b6cSNarsimhulu Musini snic_set_state(snic, SNIC_FWRESET);
2325c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(&snic->snic_lock, flags);
2326c8806b6cSNarsimhulu Musini
2327c8806b6cSNarsimhulu Musini
2328c8806b6cSNarsimhulu Musini /* Wait for all the IOs that are entered in Qcmd */
2329c8806b6cSNarsimhulu Musini while (atomic_read(&snic->ios_inflight))
2330c8806b6cSNarsimhulu Musini schedule_timeout(msecs_to_jiffies(1));
2331c8806b6cSNarsimhulu Musini
2332c8806b6cSNarsimhulu Musini ret = snic_issue_hba_reset(snic, sc);
2333c8806b6cSNarsimhulu Musini if (ret) {
2334c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(shost,
2335c8806b6cSNarsimhulu Musini "reset:Host Reset Failed w/ err %d.\n",
2336c8806b6cSNarsimhulu Musini ret);
2337c8806b6cSNarsimhulu Musini spin_lock_irqsave(&snic->snic_lock, flags);
2338c8806b6cSNarsimhulu Musini snic_set_state(snic, sv_state);
2339c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(&snic->snic_lock, flags);
2340c8806b6cSNarsimhulu Musini atomic64_inc(&snic->s_stats.reset.hba_reset_fail);
2341c8806b6cSNarsimhulu Musini ret = FAILED;
2342c8806b6cSNarsimhulu Musini
2343c8806b6cSNarsimhulu Musini goto reset_end;
2344c8806b6cSNarsimhulu Musini }
2345c8806b6cSNarsimhulu Musini
2346c8806b6cSNarsimhulu Musini ret = SUCCESS;
2347c8806b6cSNarsimhulu Musini
2348c8806b6cSNarsimhulu Musini reset_end:
2349c8806b6cSNarsimhulu Musini return ret;
2350c8806b6cSNarsimhulu Musini } /* end of snic_reset */
2351c8806b6cSNarsimhulu Musini
2352c8806b6cSNarsimhulu Musini /*
2353c8806b6cSNarsimhulu Musini * SCSI Error handling calls driver's eh_host_reset if all prior
2354c8806b6cSNarsimhulu Musini * error handling levels return FAILED.
2355c8806b6cSNarsimhulu Musini *
2356c8806b6cSNarsimhulu Musini * Host Reset is the highest level of error recovery. If this fails, then
2357c8806b6cSNarsimhulu Musini * host is offlined by SCSI.
2358c8806b6cSNarsimhulu Musini */
2359c8806b6cSNarsimhulu Musini int
snic_host_reset(struct scsi_cmnd * sc)2360c8806b6cSNarsimhulu Musini snic_host_reset(struct scsi_cmnd *sc)
2361c8806b6cSNarsimhulu Musini {
2362c8806b6cSNarsimhulu Musini struct Scsi_Host *shost = sc->device->host;
2363c8806b6cSNarsimhulu Musini u32 start_time = jiffies;
2364e9b1adb7SColin Ian King int ret;
2365c8806b6cSNarsimhulu Musini
2366c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(shost,
2367c8806b6cSNarsimhulu Musini "host reset:sc %p sc_cmd 0x%x req %p tag %d flags 0x%llx\n",
2368ec808ef9SBart Van Assche sc, sc->cmnd[0], scsi_cmd_to_rq(sc),
2369c8806b6cSNarsimhulu Musini snic_cmd_tag(sc), CMD_FLAGS(sc));
2370c8806b6cSNarsimhulu Musini
2371c8806b6cSNarsimhulu Musini ret = snic_reset(shost, sc);
2372c8806b6cSNarsimhulu Musini
2373c8806b6cSNarsimhulu Musini SNIC_TRC(shost->host_no, snic_cmd_tag(sc), (ulong) sc,
2374c8806b6cSNarsimhulu Musini jiffies_to_msecs(jiffies - start_time),
2375c8806b6cSNarsimhulu Musini 0, SNIC_TRC_CMD(sc), SNIC_TRC_CMD_STATE_FLAGS(sc));
2376c8806b6cSNarsimhulu Musini
2377c8806b6cSNarsimhulu Musini return ret;
2378c8806b6cSNarsimhulu Musini } /* end of snic_host_reset */
2379c8806b6cSNarsimhulu Musini
2380c8806b6cSNarsimhulu Musini /*
2381c8806b6cSNarsimhulu Musini * snic_cmpl_pending_tmreq : Caller should hold io_lock
2382c8806b6cSNarsimhulu Musini */
2383c8806b6cSNarsimhulu Musini static void
snic_cmpl_pending_tmreq(struct snic * snic,struct scsi_cmnd * sc)2384c8806b6cSNarsimhulu Musini snic_cmpl_pending_tmreq(struct snic *snic, struct scsi_cmnd *sc)
2385c8806b6cSNarsimhulu Musini {
2386c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
2387c8806b6cSNarsimhulu Musini
2388c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
2389c8806b6cSNarsimhulu Musini "Completing Pending TM Req sc %p, state %s flags 0x%llx\n",
2390c8806b6cSNarsimhulu Musini sc, snic_io_status_to_str(CMD_STATE(sc)), CMD_FLAGS(sc));
2391c8806b6cSNarsimhulu Musini
2392f352a0d5SNarsimhulu Musini /*
2393f352a0d5SNarsimhulu Musini * CASE : FW didn't post itmf completion due to PCIe Errors.
2394f352a0d5SNarsimhulu Musini * Marking the abort status as Success to call scsi completion
2395f352a0d5SNarsimhulu Musini * in snic_abort_finish()
2396f352a0d5SNarsimhulu Musini */
2397f352a0d5SNarsimhulu Musini CMD_ABTS_STATUS(sc) = SNIC_STAT_IO_SUCCESS;
2398f352a0d5SNarsimhulu Musini
2399c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
2400c8806b6cSNarsimhulu Musini if (!rqi)
2401c8806b6cSNarsimhulu Musini return;
2402c8806b6cSNarsimhulu Musini
2403c8806b6cSNarsimhulu Musini if (rqi->dr_done)
2404c8806b6cSNarsimhulu Musini complete(rqi->dr_done);
2405c8806b6cSNarsimhulu Musini else if (rqi->abts_done)
2406c8806b6cSNarsimhulu Musini complete(rqi->abts_done);
2407c8806b6cSNarsimhulu Musini }
2408c8806b6cSNarsimhulu Musini
2409c8806b6cSNarsimhulu Musini /*
2410c8806b6cSNarsimhulu Musini * snic_scsi_cleanup: Walks through tag map and releases the reqs
2411c8806b6cSNarsimhulu Musini */
2412c8806b6cSNarsimhulu Musini static void
snic_scsi_cleanup(struct snic * snic,int ex_tag)2413c8806b6cSNarsimhulu Musini snic_scsi_cleanup(struct snic *snic, int ex_tag)
2414c8806b6cSNarsimhulu Musini {
2415c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
2416c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc = NULL;
2417c8806b6cSNarsimhulu Musini spinlock_t *io_lock = NULL;
2418c8806b6cSNarsimhulu Musini unsigned long flags;
2419c8806b6cSNarsimhulu Musini int tag;
2420c8806b6cSNarsimhulu Musini u64 st_time = 0;
2421c8806b6cSNarsimhulu Musini
2422c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "sc_clean: scsi cleanup.\n");
2423c8806b6cSNarsimhulu Musini
2424c8806b6cSNarsimhulu Musini for (tag = 0; tag < snic->max_tag_id; tag++) {
2425c8806b6cSNarsimhulu Musini /* Skip ex_tag */
2426c8806b6cSNarsimhulu Musini if (tag == ex_tag)
2427c8806b6cSNarsimhulu Musini continue;
2428c8806b6cSNarsimhulu Musini
2429c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_tag(snic, tag);
2430c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
2431c8806b6cSNarsimhulu Musini sc = scsi_host_find_tag(snic->shost, tag);
2432c8806b6cSNarsimhulu Musini if (!sc) {
2433c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2434c8806b6cSNarsimhulu Musini
2435c8806b6cSNarsimhulu Musini continue;
2436c8806b6cSNarsimhulu Musini }
2437c8806b6cSNarsimhulu Musini
2438c8806b6cSNarsimhulu Musini if (unlikely(snic_tmreq_pending(sc))) {
2439c8806b6cSNarsimhulu Musini /*
2440c8806b6cSNarsimhulu Musini * When FW Completes reset w/o sending completions
2441c8806b6cSNarsimhulu Musini * for outstanding ios.
2442c8806b6cSNarsimhulu Musini */
2443c8806b6cSNarsimhulu Musini snic_cmpl_pending_tmreq(snic, sc);
2444c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2445c8806b6cSNarsimhulu Musini
2446c8806b6cSNarsimhulu Musini continue;
2447c8806b6cSNarsimhulu Musini }
2448c8806b6cSNarsimhulu Musini
2449c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
2450c8806b6cSNarsimhulu Musini if (!rqi) {
2451c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2452c8806b6cSNarsimhulu Musini
2453c8806b6cSNarsimhulu Musini goto cleanup;
2454c8806b6cSNarsimhulu Musini }
2455c8806b6cSNarsimhulu Musini
2456c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
2457c8806b6cSNarsimhulu Musini "sc_clean: sc %p, rqi %p, tag %d flags 0x%llx\n",
2458c8806b6cSNarsimhulu Musini sc, rqi, tag, CMD_FLAGS(sc));
2459c8806b6cSNarsimhulu Musini
2460c8806b6cSNarsimhulu Musini CMD_SP(sc) = NULL;
2461c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_SCSI_CLEANUP;
2462c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2463c8806b6cSNarsimhulu Musini st_time = rqi->start_time;
2464c8806b6cSNarsimhulu Musini
2465c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost,
2466c8806b6cSNarsimhulu Musini "sc_clean: Releasing rqi %p : flags 0x%llx\n",
2467c8806b6cSNarsimhulu Musini rqi, CMD_FLAGS(sc));
2468c8806b6cSNarsimhulu Musini
2469c8806b6cSNarsimhulu Musini snic_release_req_buf(snic, rqi, sc);
2470c8806b6cSNarsimhulu Musini
2471c8806b6cSNarsimhulu Musini cleanup:
2472c8806b6cSNarsimhulu Musini sc->result = DID_TRANSPORT_DISRUPTED << 16;
2473c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost,
24743f5c11a4SNarsimhulu Musini "sc_clean: DID_TRANSPORT_DISRUPTED for sc %p, Tag %d flags 0x%llx rqi %p duration %u msecs\n",
2475ec808ef9SBart Van Assche sc, scsi_cmd_to_rq(sc)->tag, CMD_FLAGS(sc), rqi,
24763f5c11a4SNarsimhulu Musini jiffies_to_msecs(jiffies - st_time));
2477c8806b6cSNarsimhulu Musini
2478c8806b6cSNarsimhulu Musini /* Update IO stats */
2479c8806b6cSNarsimhulu Musini snic_stats_update_io_cmpl(&snic->s_stats);
2480c8806b6cSNarsimhulu Musini
2481c8806b6cSNarsimhulu Musini SNIC_TRC(snic->shost->host_no, tag, (ulong) sc,
2482c8806b6cSNarsimhulu Musini jiffies_to_msecs(jiffies - st_time), 0,
2483c8806b6cSNarsimhulu Musini SNIC_TRC_CMD(sc),
2484c8806b6cSNarsimhulu Musini SNIC_TRC_CMD_STATE_FLAGS(sc));
2485c8806b6cSNarsimhulu Musini
248670a5caf1SBart Van Assche scsi_done(sc);
2487c8806b6cSNarsimhulu Musini }
2488c8806b6cSNarsimhulu Musini } /* end of snic_scsi_cleanup */
2489c8806b6cSNarsimhulu Musini
2490c8806b6cSNarsimhulu Musini void
snic_shutdown_scsi_cleanup(struct snic * snic)2491c8806b6cSNarsimhulu Musini snic_shutdown_scsi_cleanup(struct snic *snic)
2492c8806b6cSNarsimhulu Musini {
2493c8806b6cSNarsimhulu Musini SNIC_HOST_INFO(snic->shost, "Shutdown time SCSI Cleanup.\n");
2494c8806b6cSNarsimhulu Musini
2495c8806b6cSNarsimhulu Musini snic_scsi_cleanup(snic, SCSI_NO_TAG);
2496c8806b6cSNarsimhulu Musini } /* end of snic_shutdown_scsi_cleanup */
2497c8806b6cSNarsimhulu Musini
2498c8806b6cSNarsimhulu Musini /*
2499c8806b6cSNarsimhulu Musini * snic_internal_abort_io
2500c8806b6cSNarsimhulu Musini * called by : snic_tgt_scsi_abort_io
2501c8806b6cSNarsimhulu Musini */
2502c8806b6cSNarsimhulu Musini static int
snic_internal_abort_io(struct snic * snic,struct scsi_cmnd * sc,int tmf)2503c8806b6cSNarsimhulu Musini snic_internal_abort_io(struct snic *snic, struct scsi_cmnd *sc, int tmf)
2504c8806b6cSNarsimhulu Musini {
2505c8806b6cSNarsimhulu Musini struct snic_req_info *rqi = NULL;
2506c8806b6cSNarsimhulu Musini spinlock_t *io_lock = NULL;
2507c8806b6cSNarsimhulu Musini unsigned long flags;
2508c8806b6cSNarsimhulu Musini u32 sv_state = 0;
2509c8806b6cSNarsimhulu Musini int ret = 0;
2510c8806b6cSNarsimhulu Musini
2511c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_hash(snic, sc);
2512c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
2513c8806b6cSNarsimhulu Musini rqi = (struct snic_req_info *) CMD_SP(sc);
2514c8806b6cSNarsimhulu Musini if (!rqi)
2515c8806b6cSNarsimhulu Musini goto skip_internal_abts;
2516c8806b6cSNarsimhulu Musini
2517c8806b6cSNarsimhulu Musini if (CMD_STATE(sc) == SNIC_IOREQ_ABTS_PENDING)
2518c8806b6cSNarsimhulu Musini goto skip_internal_abts;
2519c8806b6cSNarsimhulu Musini
2520c8806b6cSNarsimhulu Musini if ((CMD_FLAGS(sc) & SNIC_DEVICE_RESET) &&
2521c8806b6cSNarsimhulu Musini (!(CMD_FLAGS(sc) & SNIC_DEV_RST_ISSUED))) {
2522c8806b6cSNarsimhulu Musini
2523c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
2524c8806b6cSNarsimhulu Musini "internal_abts: dev rst not pending sc 0x%p\n",
2525c8806b6cSNarsimhulu Musini sc);
2526c8806b6cSNarsimhulu Musini
2527c8806b6cSNarsimhulu Musini goto skip_internal_abts;
2528c8806b6cSNarsimhulu Musini }
2529c8806b6cSNarsimhulu Musini
2530c8806b6cSNarsimhulu Musini
2531c8806b6cSNarsimhulu Musini if (!(CMD_FLAGS(sc) & SNIC_IO_ISSUED)) {
2532c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost,
2533c8806b6cSNarsimhulu Musini "internal_abts: IO not yet issued sc 0x%p tag 0x%x flags 0x%llx state %d\n",
2534c8806b6cSNarsimhulu Musini sc, snic_cmd_tag(sc), CMD_FLAGS(sc), CMD_STATE(sc));
2535c8806b6cSNarsimhulu Musini
2536c8806b6cSNarsimhulu Musini goto skip_internal_abts;
2537c8806b6cSNarsimhulu Musini }
2538c8806b6cSNarsimhulu Musini
2539c8806b6cSNarsimhulu Musini sv_state = CMD_STATE(sc);
2540c8806b6cSNarsimhulu Musini CMD_STATE(sc) = SNIC_IOREQ_ABTS_PENDING;
2541c8806b6cSNarsimhulu Musini CMD_ABTS_STATUS(sc) = SNIC_INVALID_CODE;
2542c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_INTERNAL_TERM_PENDING;
2543c8806b6cSNarsimhulu Musini
2544c8806b6cSNarsimhulu Musini if (CMD_FLAGS(sc) & SNIC_DEVICE_RESET) {
2545c8806b6cSNarsimhulu Musini /* stats */
2546c8806b6cSNarsimhulu Musini rqi->tm_tag = SNIC_TAG_DEV_RST;
2547c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "internal_abts:dev rst sc %p\n", sc);
2548c8806b6cSNarsimhulu Musini }
2549c8806b6cSNarsimhulu Musini
2550c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "internal_abts: Issuing abts tag %x\n",
2551c8806b6cSNarsimhulu Musini snic_cmd_tag(sc));
2552c8806b6cSNarsimhulu Musini SNIC_BUG_ON(rqi->abts_done);
2553c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2554c8806b6cSNarsimhulu Musini
2555c8806b6cSNarsimhulu Musini ret = snic_queue_abort_req(snic, rqi, sc, tmf);
2556c8806b6cSNarsimhulu Musini if (ret) {
2557c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
2558c8806b6cSNarsimhulu Musini "internal_abts: Tag = %x , Failed w/ err = %d\n",
2559c8806b6cSNarsimhulu Musini snic_cmd_tag(sc), ret);
2560c8806b6cSNarsimhulu Musini
2561c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
2562c8806b6cSNarsimhulu Musini
2563c8806b6cSNarsimhulu Musini if (CMD_STATE(sc) == SNIC_IOREQ_ABTS_PENDING)
2564c8806b6cSNarsimhulu Musini CMD_STATE(sc) = sv_state;
2565c8806b6cSNarsimhulu Musini
2566c8806b6cSNarsimhulu Musini goto skip_internal_abts;
2567c8806b6cSNarsimhulu Musini }
2568c8806b6cSNarsimhulu Musini
2569c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
2570c8806b6cSNarsimhulu Musini if (CMD_FLAGS(sc) & SNIC_DEVICE_RESET)
2571c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_DEV_RST_TERM_ISSUED;
2572c8806b6cSNarsimhulu Musini else
2573c8806b6cSNarsimhulu Musini CMD_FLAGS(sc) |= SNIC_IO_INTERNAL_TERM_ISSUED;
2574c8806b6cSNarsimhulu Musini
2575c8806b6cSNarsimhulu Musini ret = SUCCESS;
2576c8806b6cSNarsimhulu Musini
2577c8806b6cSNarsimhulu Musini skip_internal_abts:
257851aef716SLance Roy lockdep_assert_held(io_lock);
2579c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2580c8806b6cSNarsimhulu Musini
2581c8806b6cSNarsimhulu Musini return ret;
2582c8806b6cSNarsimhulu Musini } /* end of snic_internal_abort_io */
2583c8806b6cSNarsimhulu Musini
2584c8806b6cSNarsimhulu Musini /*
2585c8806b6cSNarsimhulu Musini * snic_tgt_scsi_abort_io : called by snic_tgt_del
2586c8806b6cSNarsimhulu Musini */
2587c8806b6cSNarsimhulu Musini int
snic_tgt_scsi_abort_io(struct snic_tgt * tgt)2588c8806b6cSNarsimhulu Musini snic_tgt_scsi_abort_io(struct snic_tgt *tgt)
2589c8806b6cSNarsimhulu Musini {
2590c8806b6cSNarsimhulu Musini struct snic *snic = NULL;
2591c8806b6cSNarsimhulu Musini struct scsi_cmnd *sc = NULL;
2592c8806b6cSNarsimhulu Musini struct snic_tgt *sc_tgt = NULL;
2593c8806b6cSNarsimhulu Musini spinlock_t *io_lock = NULL;
2594c8806b6cSNarsimhulu Musini unsigned long flags;
2595c8806b6cSNarsimhulu Musini int ret = 0, tag, abt_cnt = 0, tmf = 0;
2596c8806b6cSNarsimhulu Musini
2597c8806b6cSNarsimhulu Musini if (!tgt)
2598c8806b6cSNarsimhulu Musini return -1;
2599c8806b6cSNarsimhulu Musini
2600c8806b6cSNarsimhulu Musini snic = shost_priv(snic_tgt_to_shost(tgt));
2601c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "tgt_abt_io: Cleaning Pending IOs.\n");
2602c8806b6cSNarsimhulu Musini
2603c8806b6cSNarsimhulu Musini if (tgt->tdata.typ == SNIC_TGT_DAS)
2604c8806b6cSNarsimhulu Musini tmf = SNIC_ITMF_ABTS_TASK;
2605c8806b6cSNarsimhulu Musini else
2606c8806b6cSNarsimhulu Musini tmf = SNIC_ITMF_ABTS_TASK_TERM;
2607c8806b6cSNarsimhulu Musini
2608c8806b6cSNarsimhulu Musini for (tag = 0; tag < snic->max_tag_id; tag++) {
2609c8806b6cSNarsimhulu Musini io_lock = snic_io_lock_tag(snic, tag);
2610c8806b6cSNarsimhulu Musini
2611c8806b6cSNarsimhulu Musini spin_lock_irqsave(io_lock, flags);
2612c8806b6cSNarsimhulu Musini sc = scsi_host_find_tag(snic->shost, tag);
2613c8806b6cSNarsimhulu Musini if (!sc) {
2614c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2615c8806b6cSNarsimhulu Musini
2616c8806b6cSNarsimhulu Musini continue;
2617c8806b6cSNarsimhulu Musini }
2618c8806b6cSNarsimhulu Musini
2619c8806b6cSNarsimhulu Musini sc_tgt = starget_to_tgt(scsi_target(sc->device));
2620c8806b6cSNarsimhulu Musini if (sc_tgt != tgt) {
2621c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2622c8806b6cSNarsimhulu Musini
2623c8806b6cSNarsimhulu Musini continue;
2624c8806b6cSNarsimhulu Musini }
2625c8806b6cSNarsimhulu Musini spin_unlock_irqrestore(io_lock, flags);
2626c8806b6cSNarsimhulu Musini
2627c8806b6cSNarsimhulu Musini ret = snic_internal_abort_io(snic, sc, tmf);
2628c8806b6cSNarsimhulu Musini if (ret < 0) {
2629c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost,
2630c8806b6cSNarsimhulu Musini "tgt_abt_io: Tag %x, Failed w err = %d\n",
2631c8806b6cSNarsimhulu Musini tag, ret);
2632c8806b6cSNarsimhulu Musini
2633c8806b6cSNarsimhulu Musini continue;
2634c8806b6cSNarsimhulu Musini }
2635c8806b6cSNarsimhulu Musini
2636c8806b6cSNarsimhulu Musini if (ret == SUCCESS)
2637c8806b6cSNarsimhulu Musini abt_cnt++;
2638c8806b6cSNarsimhulu Musini }
2639c8806b6cSNarsimhulu Musini
2640c8806b6cSNarsimhulu Musini SNIC_SCSI_DBG(snic->shost, "tgt_abt_io: abt_cnt = %d\n", abt_cnt);
2641c8806b6cSNarsimhulu Musini
2642c8806b6cSNarsimhulu Musini return 0;
2643c8806b6cSNarsimhulu Musini } /* end of snic_tgt_scsi_abort_io */
2644