blob: 1ee131f124b9b448e84005501529155f6a3715c5 [file] [log] [blame]
James Smartf1c3b0f2009-07-19 10:01:32 -04001/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. *
James Smartf25e8e72015-04-07 15:07:28 -04004 * Copyright (C) 2009-2015 Emulex. All rights reserved. *
James Smartf1c3b0f2009-07-19 10:01:32 -04005 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com *
7 * *
8 * This program is free software; you can redistribute it and/or *
9 * modify it under the terms of version 2 of the GNU General *
10 * Public License as published by the Free Software Foundation. *
11 * This program is distributed in the hope that it will be useful. *
12 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
13 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
14 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
15 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
16 * TO BE LEGALLY INVALID. See the GNU General Public License for *
17 * more details, a copy of which can be found in the file COPYING *
18 * included with this package. *
19 *******************************************************************/
20
21#include <linux/interrupt.h>
22#include <linux/mempool.h>
23#include <linux/pci.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090024#include <linux/slab.h>
James Smart277e76f2010-02-18 11:07:15 -050025#include <linux/delay.h>
James Smart7ad20aa2011-05-24 11:44:28 -040026#include <linux/list.h>
Johannes Thumshirneb340942016-11-17 10:31:11 +010027#include <linux/bsg-lib.h>
James Smartf1c3b0f2009-07-19 10:01:32 -040028
29#include <scsi/scsi.h>
30#include <scsi/scsi_host.h>
31#include <scsi/scsi_transport_fc.h>
32#include <scsi/scsi_bsg_fc.h>
James Smart6a9c52c2009-10-02 15:16:51 -040033#include <scsi/fc/fc_fs.h>
James Smartf1c3b0f2009-07-19 10:01:32 -040034
35#include "lpfc_hw4.h"
36#include "lpfc_hw.h"
37#include "lpfc_sli.h"
38#include "lpfc_sli4.h"
39#include "lpfc_nl.h"
James Smart4fede782010-01-26 23:08:55 -050040#include "lpfc_bsg.h"
James Smartf1c3b0f2009-07-19 10:01:32 -040041#include "lpfc_disc.h"
42#include "lpfc_scsi.h"
43#include "lpfc.h"
44#include "lpfc_logmsg.h"
45#include "lpfc_crtn.h"
James Smartb76f2dc2011-07-22 18:37:42 -040046#include "lpfc_debugfs.h"
James Smartf1c3b0f2009-07-19 10:01:32 -040047#include "lpfc_vport.h"
48#include "lpfc_version.h"
49
James Smart4cc0e562010-01-26 23:09:48 -050050struct lpfc_bsg_event {
51 struct list_head node;
52 struct kref kref;
53 wait_queue_head_t wq;
54
55 /* Event type and waiter identifiers */
56 uint32_t type_mask;
57 uint32_t req_id;
58 uint32_t reg_id;
59
60 /* next two flags are here for the auto-delete logic */
61 unsigned long wait_time_stamp;
62 int waiting;
63
64 /* seen and not seen events */
65 struct list_head events_to_get;
66 struct list_head events_to_see;
67
James Smarta33c4f72013-03-01 16:36:00 -050068 /* driver data associated with the job */
69 void *dd_data;
James Smart4cc0e562010-01-26 23:09:48 -050070};
71
72struct lpfc_bsg_iocb {
73 struct lpfc_iocbq *cmdiocbq;
James Smarta33c4f72013-03-01 16:36:00 -050074 struct lpfc_dmabuf *rmp;
James Smart4cc0e562010-01-26 23:09:48 -050075 struct lpfc_nodelist *ndlp;
James Smart4cc0e562010-01-26 23:09:48 -050076};
77
James Smart3b5dd522010-01-26 23:10:15 -050078struct lpfc_bsg_mbox {
79 LPFC_MBOXQ_t *pmboxq;
80 MAILBOX_t *mb;
James Smart7ad20aa2011-05-24 11:44:28 -040081 struct lpfc_dmabuf *dmabuffers; /* for BIU diags */
James Smart7a470272010-03-15 11:25:20 -040082 uint8_t *ext; /* extended mailbox data */
83 uint32_t mbOffset; /* from app */
84 uint32_t inExtWLen; /* from app */
James Smartc7495932010-04-06 15:05:28 -040085 uint32_t outExtWLen; /* from app */
James Smart3b5dd522010-01-26 23:10:15 -050086};
87
James Smarte2aed292010-02-26 14:15:00 -050088#define MENLO_DID 0x0000FC0E
89
90struct lpfc_bsg_menlo {
91 struct lpfc_iocbq *cmdiocbq;
James Smarta33c4f72013-03-01 16:36:00 -050092 struct lpfc_dmabuf *rmp;
James Smarte2aed292010-02-26 14:15:00 -050093};
94
James Smart4cc0e562010-01-26 23:09:48 -050095#define TYPE_EVT 1
96#define TYPE_IOCB 2
James Smart3b5dd522010-01-26 23:10:15 -050097#define TYPE_MBOX 3
James Smarte2aed292010-02-26 14:15:00 -050098#define TYPE_MENLO 4
James Smart4cc0e562010-01-26 23:09:48 -050099struct bsg_job_data {
100 uint32_t type;
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +0100101 struct bsg_job *set_job; /* job waiting for this iocb to finish */
James Smart4cc0e562010-01-26 23:09:48 -0500102 union {
103 struct lpfc_bsg_event *evt;
104 struct lpfc_bsg_iocb iocb;
James Smart3b5dd522010-01-26 23:10:15 -0500105 struct lpfc_bsg_mbox mbox;
James Smarte2aed292010-02-26 14:15:00 -0500106 struct lpfc_bsg_menlo menlo;
James Smart4cc0e562010-01-26 23:09:48 -0500107 } context_un;
108};
109
110struct event_data {
111 struct list_head node;
112 uint32_t type;
113 uint32_t immed_dat;
114 void *data;
115 uint32_t len;
116};
117
James Smart3b5dd522010-01-26 23:10:15 -0500118#define BUF_SZ_4K 4096
James Smart4cc0e562010-01-26 23:09:48 -0500119#define SLI_CT_ELX_LOOPBACK 0x10
120
121enum ELX_LOOPBACK_CMD {
122 ELX_LOOPBACK_XRI_SETUP,
123 ELX_LOOPBACK_DATA,
124};
125
James Smart3b5dd522010-01-26 23:10:15 -0500126#define ELX_LOOPBACK_HEADER_SZ \
127 (size_t)(&((struct lpfc_sli_ct_request *)NULL)->un)
128
James Smart4cc0e562010-01-26 23:09:48 -0500129struct lpfc_dmabufext {
130 struct lpfc_dmabuf dma;
131 uint32_t size;
132 uint32_t flag;
133};
134
James Smarta33c4f72013-03-01 16:36:00 -0500135static void
136lpfc_free_bsg_buffers(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
137{
138 struct lpfc_dmabuf *mlast, *next_mlast;
139
140 if (mlist) {
141 list_for_each_entry_safe(mlast, next_mlast, &mlist->list,
142 list) {
143 lpfc_mbuf_free(phba, mlast->virt, mlast->phys);
144 list_del(&mlast->list);
145 kfree(mlast);
146 }
147 lpfc_mbuf_free(phba, mlist->virt, mlist->phys);
148 kfree(mlist);
149 }
150 return;
151}
152
153static struct lpfc_dmabuf *
154lpfc_alloc_bsg_buffers(struct lpfc_hba *phba, unsigned int size,
155 int outbound_buffers, struct ulp_bde64 *bpl,
156 int *bpl_entries)
157{
158 struct lpfc_dmabuf *mlist = NULL;
159 struct lpfc_dmabuf *mp;
160 unsigned int bytes_left = size;
161
162 /* Verify we can support the size specified */
163 if (!size || (size > (*bpl_entries * LPFC_BPL_SIZE)))
164 return NULL;
165
166 /* Determine the number of dma buffers to allocate */
167 *bpl_entries = (size % LPFC_BPL_SIZE ? size/LPFC_BPL_SIZE + 1 :
168 size/LPFC_BPL_SIZE);
169
170 /* Allocate dma buffer and place in BPL passed */
171 while (bytes_left) {
172 /* Allocate dma buffer */
173 mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
174 if (!mp) {
175 if (mlist)
176 lpfc_free_bsg_buffers(phba, mlist);
177 return NULL;
178 }
179
180 INIT_LIST_HEAD(&mp->list);
181 mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
182
183 if (!mp->virt) {
184 kfree(mp);
185 if (mlist)
186 lpfc_free_bsg_buffers(phba, mlist);
187 return NULL;
188 }
189
190 /* Queue it to a linked list */
191 if (!mlist)
192 mlist = mp;
193 else
194 list_add_tail(&mp->list, &mlist->list);
195
196 /* Add buffer to buffer pointer list */
197 if (outbound_buffers)
198 bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
199 else
200 bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;
201 bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys));
202 bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys));
203 bpl->tus.f.bdeSize = (uint16_t)
204 (bytes_left >= LPFC_BPL_SIZE ? LPFC_BPL_SIZE :
205 bytes_left);
206 bytes_left -= bpl->tus.f.bdeSize;
207 bpl->tus.w = le32_to_cpu(bpl->tus.w);
208 bpl++;
209 }
210 return mlist;
211}
212
213static unsigned int
214lpfc_bsg_copy_data(struct lpfc_dmabuf *dma_buffers,
Johannes Thumshirneb340942016-11-17 10:31:11 +0100215 struct bsg_buffer *bsg_buffers,
James Smarta33c4f72013-03-01 16:36:00 -0500216 unsigned int bytes_to_transfer, int to_buffers)
217{
218
219 struct lpfc_dmabuf *mp;
220 unsigned int transfer_bytes, bytes_copied = 0;
221 unsigned int sg_offset, dma_offset;
222 unsigned char *dma_address, *sg_address;
James Smarta33c4f72013-03-01 16:36:00 -0500223 LIST_HEAD(temp_list);
James Smartd5ce53b2013-04-17 20:17:26 -0400224 struct sg_mapping_iter miter;
225 unsigned long flags;
226 unsigned int sg_flags = SG_MITER_ATOMIC;
227 bool sg_valid;
James Smarta33c4f72013-03-01 16:36:00 -0500228
229 list_splice_init(&dma_buffers->list, &temp_list);
230 list_add(&dma_buffers->list, &temp_list);
231 sg_offset = 0;
James Smartd5ce53b2013-04-17 20:17:26 -0400232 if (to_buffers)
233 sg_flags |= SG_MITER_FROM_SG;
234 else
235 sg_flags |= SG_MITER_TO_SG;
236 sg_miter_start(&miter, bsg_buffers->sg_list, bsg_buffers->sg_cnt,
237 sg_flags);
238 local_irq_save(flags);
239 sg_valid = sg_miter_next(&miter);
James Smarta33c4f72013-03-01 16:36:00 -0500240 list_for_each_entry(mp, &temp_list, list) {
241 dma_offset = 0;
James Smartd5ce53b2013-04-17 20:17:26 -0400242 while (bytes_to_transfer && sg_valid &&
James Smarta33c4f72013-03-01 16:36:00 -0500243 (dma_offset < LPFC_BPL_SIZE)) {
244 dma_address = mp->virt + dma_offset;
245 if (sg_offset) {
246 /* Continue previous partial transfer of sg */
James Smartd5ce53b2013-04-17 20:17:26 -0400247 sg_address = miter.addr + sg_offset;
248 transfer_bytes = miter.length - sg_offset;
James Smarta33c4f72013-03-01 16:36:00 -0500249 } else {
James Smartd5ce53b2013-04-17 20:17:26 -0400250 sg_address = miter.addr;
251 transfer_bytes = miter.length;
James Smarta33c4f72013-03-01 16:36:00 -0500252 }
253 if (bytes_to_transfer < transfer_bytes)
254 transfer_bytes = bytes_to_transfer;
255 if (transfer_bytes > (LPFC_BPL_SIZE - dma_offset))
256 transfer_bytes = LPFC_BPL_SIZE - dma_offset;
257 if (to_buffers)
258 memcpy(dma_address, sg_address, transfer_bytes);
259 else
260 memcpy(sg_address, dma_address, transfer_bytes);
261 dma_offset += transfer_bytes;
262 sg_offset += transfer_bytes;
263 bytes_to_transfer -= transfer_bytes;
264 bytes_copied += transfer_bytes;
James Smartd5ce53b2013-04-17 20:17:26 -0400265 if (sg_offset >= miter.length) {
James Smarta33c4f72013-03-01 16:36:00 -0500266 sg_offset = 0;
James Smartd5ce53b2013-04-17 20:17:26 -0400267 sg_valid = sg_miter_next(&miter);
James Smarta33c4f72013-03-01 16:36:00 -0500268 }
269 }
270 }
James Smartd5ce53b2013-04-17 20:17:26 -0400271 sg_miter_stop(&miter);
272 local_irq_restore(flags);
James Smarta33c4f72013-03-01 16:36:00 -0500273 list_del_init(&dma_buffers->list);
274 list_splice(&temp_list, &dma_buffers->list);
275 return bytes_copied;
276}
277
James Smartf1c3b0f2009-07-19 10:01:32 -0400278/**
James Smart4cc0e562010-01-26 23:09:48 -0500279 * lpfc_bsg_send_mgmt_cmd_cmp - lpfc_bsg_send_mgmt_cmd's completion handler
280 * @phba: Pointer to HBA context object.
281 * @cmdiocbq: Pointer to command iocb.
282 * @rspiocbq: Pointer to response iocb.
283 *
284 * This function is the completion handler for iocbs issued using
285 * lpfc_bsg_send_mgmt_cmd function. This function is called by the
286 * ring event handler function without any lock held. This function
287 * can be called from both worker thread context and interrupt
288 * context. This function also can be called from another thread which
289 * cleans up the SLI layer objects.
290 * This function copies the contents of the response iocb to the
291 * response iocb memory object provided by the caller of
292 * lpfc_sli_issue_iocb_wait and then wakes up the thread which
293 * sleeps for the iocb completion.
294 **/
295static void
296lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
297 struct lpfc_iocbq *cmdiocbq,
298 struct lpfc_iocbq *rspiocbq)
299{
James Smart4cc0e562010-01-26 23:09:48 -0500300 struct bsg_job_data *dd_data;
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +0100301 struct bsg_job *job;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100302 struct fc_bsg_reply *bsg_reply;
James Smart4cc0e562010-01-26 23:09:48 -0500303 IOCB_t *rsp;
James Smarta33c4f72013-03-01 16:36:00 -0500304 struct lpfc_dmabuf *bmp, *cmp, *rmp;
James Smart4cc0e562010-01-26 23:09:48 -0500305 struct lpfc_nodelist *ndlp;
306 struct lpfc_bsg_iocb *iocb;
307 unsigned long flags;
James Smarta33c4f72013-03-01 16:36:00 -0500308 unsigned int rsp_size;
James Smart4cc0e562010-01-26 23:09:48 -0500309 int rc = 0;
310
James Smarta33c4f72013-03-01 16:36:00 -0500311 dd_data = cmdiocbq->context1;
312
313 /* Determine if job has been aborted */
James Smart4cc0e562010-01-26 23:09:48 -0500314 spin_lock_irqsave(&phba->ct_ev_lock, flags);
James Smarta33c4f72013-03-01 16:36:00 -0500315 job = dd_data->set_job;
316 if (job) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100317 bsg_reply = job->reply;
James Smarta33c4f72013-03-01 16:36:00 -0500318 /* Prevent timeout handling from trying to abort job */
319 job->dd_data = NULL;
James Smart4cc0e562010-01-26 23:09:48 -0500320 }
James Smarta33c4f72013-03-01 16:36:00 -0500321 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
James Smart4cc0e562010-01-26 23:09:48 -0500322
James Smartb5a9b2d2013-09-06 12:19:45 -0400323 /* Close the timeout handler abort window */
324 spin_lock_irqsave(&phba->hbalock, flags);
James Smart1b8d11a2013-09-06 12:20:51 -0400325 cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING;
James Smartb5a9b2d2013-09-06 12:19:45 -0400326 spin_unlock_irqrestore(&phba->hbalock, flags);
327
James Smart4cc0e562010-01-26 23:09:48 -0500328 iocb = &dd_data->context_un.iocb;
James Smarta33c4f72013-03-01 16:36:00 -0500329 ndlp = iocb->ndlp;
330 rmp = iocb->rmp;
331 cmp = cmdiocbq->context2;
332 bmp = cmdiocbq->context3;
James Smart4cc0e562010-01-26 23:09:48 -0500333 rsp = &rspiocbq->iocb;
James Smart4cc0e562010-01-26 23:09:48 -0500334
James Smarta33c4f72013-03-01 16:36:00 -0500335 /* Copy the completed data or set the error status */
James Smart4cc0e562010-01-26 23:09:48 -0500336
James Smarta33c4f72013-03-01 16:36:00 -0500337 if (job) {
338 if (rsp->ulpStatus) {
339 if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
340 switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) {
341 case IOERR_SEQUENCE_TIMEOUT:
342 rc = -ETIMEDOUT;
343 break;
344 case IOERR_INVALID_RPI:
345 rc = -EFAULT;
346 break;
347 default:
348 rc = -EACCES;
349 break;
350 }
351 } else {
James Smart4cc0e562010-01-26 23:09:48 -0500352 rc = -EACCES;
James Smart4cc0e562010-01-26 23:09:48 -0500353 }
James Smarta33c4f72013-03-01 16:36:00 -0500354 } else {
355 rsp_size = rsp->un.genreq64.bdl.bdeSize;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100356 bsg_reply->reply_payload_rcv_len =
James Smarta33c4f72013-03-01 16:36:00 -0500357 lpfc_bsg_copy_data(rmp, &job->reply_payload,
358 rsp_size, 0);
359 }
360 }
James Smart4cc0e562010-01-26 23:09:48 -0500361
James Smarta33c4f72013-03-01 16:36:00 -0500362 lpfc_free_bsg_buffers(phba, cmp);
363 lpfc_free_bsg_buffers(phba, rmp);
James Smart4cc0e562010-01-26 23:09:48 -0500364 lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
James Smarta33c4f72013-03-01 16:36:00 -0500365 kfree(bmp);
James Smart4cc0e562010-01-26 23:09:48 -0500366 lpfc_sli_release_iocbq(phba, cmdiocbq);
367 lpfc_nlp_put(ndlp);
James Smart4cc0e562010-01-26 23:09:48 -0500368 kfree(dd_data);
James Smarta33c4f72013-03-01 16:36:00 -0500369
370 /* Complete the job if the job is still active */
371
372 if (job) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100373 bsg_reply->result = rc;
Johannes Thumshirn06548162016-11-17 10:31:22 +0100374 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +0100375 bsg_reply->reply_payload_rcv_len);
James Smarta33c4f72013-03-01 16:36:00 -0500376 }
James Smart4cc0e562010-01-26 23:09:48 -0500377 return;
378}
379
380/**
381 * lpfc_bsg_send_mgmt_cmd - send a CT command from a bsg request
James Smartf1c3b0f2009-07-19 10:01:32 -0400382 * @job: fc_bsg_job to handle
James Smart3b5dd522010-01-26 23:10:15 -0500383 **/
James Smartf1c3b0f2009-07-19 10:01:32 -0400384static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +0100385lpfc_bsg_send_mgmt_cmd(struct bsg_job *job)
James Smartf1c3b0f2009-07-19 10:01:32 -0400386{
Johannes Thumshirncd21c602016-11-17 10:31:14 +0100387 struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
James Smartf1c3b0f2009-07-19 10:01:32 -0400388 struct lpfc_hba *phba = vport->phba;
Johannes Thumshirn1d69b122016-11-17 10:31:15 +0100389 struct lpfc_rport_data *rdata = fc_bsg_to_rport(job)->dd_data;
James Smartf1c3b0f2009-07-19 10:01:32 -0400390 struct lpfc_nodelist *ndlp = rdata->pnode;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100391 struct fc_bsg_reply *bsg_reply = job->reply;
James Smartf1c3b0f2009-07-19 10:01:32 -0400392 struct ulp_bde64 *bpl = NULL;
393 uint32_t timeout;
394 struct lpfc_iocbq *cmdiocbq = NULL;
James Smartf1c3b0f2009-07-19 10:01:32 -0400395 IOCB_t *cmd;
James Smarta33c4f72013-03-01 16:36:00 -0500396 struct lpfc_dmabuf *bmp = NULL, *cmp = NULL, *rmp = NULL;
James Smartf1c3b0f2009-07-19 10:01:32 -0400397 int request_nseg;
398 int reply_nseg;
James Smart4cc0e562010-01-26 23:09:48 -0500399 struct bsg_job_data *dd_data;
James Smartb5a9b2d2013-09-06 12:19:45 -0400400 unsigned long flags;
James Smart4cc0e562010-01-26 23:09:48 -0500401 uint32_t creg_val;
James Smartf1c3b0f2009-07-19 10:01:32 -0400402 int rc = 0;
James Smartd439d282010-09-29 11:18:45 -0400403 int iocb_stat;
James Smartf1c3b0f2009-07-19 10:01:32 -0400404
405 /* in case no data is transferred */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100406 bsg_reply->reply_payload_rcv_len = 0;
James Smartf1c3b0f2009-07-19 10:01:32 -0400407
James Smart4cc0e562010-01-26 23:09:48 -0500408 /* allocate our bsg tracking structure */
409 dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
410 if (!dd_data) {
411 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
412 "2733 Failed allocation of dd_data\n");
413 rc = -ENOMEM;
414 goto no_dd_data;
415 }
416
James Smartf1c3b0f2009-07-19 10:01:32 -0400417 if (!lpfc_nlp_get(ndlp)) {
James Smart4cc0e562010-01-26 23:09:48 -0500418 rc = -ENODEV;
419 goto no_ndlp;
420 }
421
James Smartf1c3b0f2009-07-19 10:01:32 -0400422 if (ndlp->nlp_flag & NLP_ELS_SND_MASK) {
423 rc = -ENODEV;
James Smarta33c4f72013-03-01 16:36:00 -0500424 goto free_ndlp;
James Smartf1c3b0f2009-07-19 10:01:32 -0400425 }
426
James Smartf1c3b0f2009-07-19 10:01:32 -0400427 cmdiocbq = lpfc_sli_get_iocbq(phba);
428 if (!cmdiocbq) {
429 rc = -ENOMEM;
James Smarta33c4f72013-03-01 16:36:00 -0500430 goto free_ndlp;
James Smartf1c3b0f2009-07-19 10:01:32 -0400431 }
James Smartf1c3b0f2009-07-19 10:01:32 -0400432
James Smart4cc0e562010-01-26 23:09:48 -0500433 cmd = &cmdiocbq->iocb;
James Smarta33c4f72013-03-01 16:36:00 -0500434
435 bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
436 if (!bmp) {
James Smartf1c3b0f2009-07-19 10:01:32 -0400437 rc = -ENOMEM;
James Smartbe858b62010-12-15 17:57:20 -0500438 goto free_cmdiocbq;
James Smartf1c3b0f2009-07-19 10:01:32 -0400439 }
James Smarta33c4f72013-03-01 16:36:00 -0500440 bmp->virt = lpfc_mbuf_alloc(phba, 0, &bmp->phys);
441 if (!bmp->virt) {
442 rc = -ENOMEM;
443 goto free_bmp;
James Smartf1c3b0f2009-07-19 10:01:32 -0400444 }
445
James Smarta33c4f72013-03-01 16:36:00 -0500446 INIT_LIST_HEAD(&bmp->list);
447
448 bpl = (struct ulp_bde64 *) bmp->virt;
449 request_nseg = LPFC_BPL_SIZE/sizeof(struct ulp_bde64);
450 cmp = lpfc_alloc_bsg_buffers(phba, job->request_payload.payload_len,
451 1, bpl, &request_nseg);
452 if (!cmp) {
453 rc = -ENOMEM;
454 goto free_bmp;
455 }
456 lpfc_bsg_copy_data(cmp, &job->request_payload,
457 job->request_payload.payload_len, 1);
458
459 bpl += request_nseg;
460 reply_nseg = LPFC_BPL_SIZE/sizeof(struct ulp_bde64) - request_nseg;
461 rmp = lpfc_alloc_bsg_buffers(phba, job->reply_payload.payload_len, 0,
462 bpl, &reply_nseg);
463 if (!rmp) {
464 rc = -ENOMEM;
465 goto free_cmp;
James Smartf1c3b0f2009-07-19 10:01:32 -0400466 }
467
468 cmd->un.genreq64.bdl.ulpIoTag32 = 0;
469 cmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
470 cmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys);
471 cmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
472 cmd->un.genreq64.bdl.bdeSize =
473 (request_nseg + reply_nseg) * sizeof(struct ulp_bde64);
474 cmd->ulpCommand = CMD_GEN_REQUEST64_CR;
475 cmd->un.genreq64.w5.hcsw.Fctl = (SI | LA);
476 cmd->un.genreq64.w5.hcsw.Dfctl = 0;
James Smart6a9c52c2009-10-02 15:16:51 -0400477 cmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL;
478 cmd->un.genreq64.w5.hcsw.Type = FC_TYPE_CT;
James Smartf1c3b0f2009-07-19 10:01:32 -0400479 cmd->ulpBdeCount = 1;
480 cmd->ulpLe = 1;
481 cmd->ulpClass = CLASS3;
482 cmd->ulpContext = ndlp->nlp_rpi;
James Smart6d368e52011-05-24 11:44:12 -0400483 if (phba->sli_rev == LPFC_SLI_REV4)
484 cmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
James Smartf1c3b0f2009-07-19 10:01:32 -0400485 cmd->ulpOwner = OWN_CHIP;
486 cmdiocbq->vport = phba->pport;
James Smart4cc0e562010-01-26 23:09:48 -0500487 cmdiocbq->context3 = bmp;
James Smartf1c3b0f2009-07-19 10:01:32 -0400488 cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
James Smartf1c3b0f2009-07-19 10:01:32 -0400489 timeout = phba->fc_ratov * 2;
James Smart4cc0e562010-01-26 23:09:48 -0500490 cmd->ulpTimeout = timeout;
James Smartf1c3b0f2009-07-19 10:01:32 -0400491
James Smart4cc0e562010-01-26 23:09:48 -0500492 cmdiocbq->iocb_cmpl = lpfc_bsg_send_mgmt_cmd_cmp;
James Smarta33c4f72013-03-01 16:36:00 -0500493 cmdiocbq->context1 = dd_data;
494 cmdiocbq->context2 = cmp;
495 cmdiocbq->context3 = bmp;
James Smartd5ce53b2013-04-17 20:17:26 -0400496 cmdiocbq->context_un.ndlp = ndlp;
James Smart4cc0e562010-01-26 23:09:48 -0500497 dd_data->type = TYPE_IOCB;
James Smarta33c4f72013-03-01 16:36:00 -0500498 dd_data->set_job = job;
James Smart4cc0e562010-01-26 23:09:48 -0500499 dd_data->context_un.iocb.cmdiocbq = cmdiocbq;
James Smarta33c4f72013-03-01 16:36:00 -0500500 dd_data->context_un.iocb.ndlp = ndlp;
501 dd_data->context_un.iocb.rmp = rmp;
502 job->dd_data = dd_data;
James Smartf1c3b0f2009-07-19 10:01:32 -0400503
James Smart4cc0e562010-01-26 23:09:48 -0500504 if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
James Smart9940b972011-03-11 16:06:12 -0500505 if (lpfc_readl(phba->HCregaddr, &creg_val)) {
506 rc = -EIO ;
James Smarta33c4f72013-03-01 16:36:00 -0500507 goto free_rmp;
James Smart9940b972011-03-11 16:06:12 -0500508 }
James Smart4cc0e562010-01-26 23:09:48 -0500509 creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
510 writel(creg_val, phba->HCregaddr);
511 readl(phba->HCregaddr); /* flush */
James Smartf1c3b0f2009-07-19 10:01:32 -0400512 }
513
James Smartd439d282010-09-29 11:18:45 -0400514 iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);
James Smartb5a9b2d2013-09-06 12:19:45 -0400515
516 if (iocb_stat == IOCB_SUCCESS) {
517 spin_lock_irqsave(&phba->hbalock, flags);
518 /* make sure the I/O had not been completed yet */
519 if (cmdiocbq->iocb_flag & LPFC_IO_LIBDFC) {
520 /* open up abort window to timeout handler */
James Smart1b8d11a2013-09-06 12:20:51 -0400521 cmdiocbq->iocb_flag |= LPFC_IO_CMD_OUTSTANDING;
James Smartb5a9b2d2013-09-06 12:19:45 -0400522 }
523 spin_unlock_irqrestore(&phba->hbalock, flags);
James Smart4cc0e562010-01-26 23:09:48 -0500524 return 0; /* done for now */
James Smartb5a9b2d2013-09-06 12:19:45 -0400525 } else if (iocb_stat == IOCB_BUSY) {
James Smartd439d282010-09-29 11:18:45 -0400526 rc = -EAGAIN;
James Smartb5a9b2d2013-09-06 12:19:45 -0400527 } else {
James Smartd439d282010-09-29 11:18:45 -0400528 rc = -EIO;
James Smartb5a9b2d2013-09-06 12:19:45 -0400529 }
James Smart2a9bf3d2010-06-07 15:24:45 -0400530
James Smart4cc0e562010-01-26 23:09:48 -0500531 /* iocb failed so cleanup */
James Smartb5a9b2d2013-09-06 12:19:45 -0400532 job->dd_data = NULL;
James Smartf1c3b0f2009-07-19 10:01:32 -0400533
James Smarta33c4f72013-03-01 16:36:00 -0500534free_rmp:
535 lpfc_free_bsg_buffers(phba, rmp);
536free_cmp:
537 lpfc_free_bsg_buffers(phba, cmp);
538free_bmp:
539 if (bmp->virt)
540 lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
541 kfree(bmp);
James Smartf1c3b0f2009-07-19 10:01:32 -0400542free_cmdiocbq:
543 lpfc_sli_release_iocbq(phba, cmdiocbq);
James Smart4cc0e562010-01-26 23:09:48 -0500544free_ndlp:
James Smartf1c3b0f2009-07-19 10:01:32 -0400545 lpfc_nlp_put(ndlp);
James Smart4cc0e562010-01-26 23:09:48 -0500546no_ndlp:
547 kfree(dd_data);
548no_dd_data:
James Smartf1c3b0f2009-07-19 10:01:32 -0400549 /* make error code available to userspace */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100550 bsg_reply->result = rc;
James Smart4cc0e562010-01-26 23:09:48 -0500551 job->dd_data = NULL;
552 return rc;
553}
554
555/**
556 * lpfc_bsg_rport_els_cmp - lpfc_bsg_rport_els's completion handler
557 * @phba: Pointer to HBA context object.
558 * @cmdiocbq: Pointer to command iocb.
559 * @rspiocbq: Pointer to response iocb.
560 *
561 * This function is the completion handler for iocbs issued using
562 * lpfc_bsg_rport_els_cmp function. This function is called by the
563 * ring event handler function without any lock held. This function
564 * can be called from both worker thread context and interrupt
565 * context. This function also can be called from other thread which
566 * cleans up the SLI layer objects.
James Smart3b5dd522010-01-26 23:10:15 -0500567 * This function copies the contents of the response iocb to the
James Smart4cc0e562010-01-26 23:09:48 -0500568 * response iocb memory object provided by the caller of
569 * lpfc_sli_issue_iocb_wait and then wakes up the thread which
570 * sleeps for the iocb completion.
571 **/
572static void
573lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba,
574 struct lpfc_iocbq *cmdiocbq,
575 struct lpfc_iocbq *rspiocbq)
576{
577 struct bsg_job_data *dd_data;
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +0100578 struct bsg_job *job;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100579 struct fc_bsg_reply *bsg_reply;
James Smart4cc0e562010-01-26 23:09:48 -0500580 IOCB_t *rsp;
581 struct lpfc_nodelist *ndlp;
James Smarta33c4f72013-03-01 16:36:00 -0500582 struct lpfc_dmabuf *pcmd = NULL, *prsp = NULL;
James Smart4cc0e562010-01-26 23:09:48 -0500583 struct fc_bsg_ctels_reply *els_reply;
584 uint8_t *rjt_data;
585 unsigned long flags;
James Smarta33c4f72013-03-01 16:36:00 -0500586 unsigned int rsp_size;
James Smart4cc0e562010-01-26 23:09:48 -0500587 int rc = 0;
588
James Smart4cc0e562010-01-26 23:09:48 -0500589 dd_data = cmdiocbq->context1;
James Smarta33c4f72013-03-01 16:36:00 -0500590 ndlp = dd_data->context_un.iocb.ndlp;
591 cmdiocbq->context1 = ndlp;
592
593 /* Determine if job has been aborted */
594 spin_lock_irqsave(&phba->ct_ev_lock, flags);
595 job = dd_data->set_job;
596 if (job) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100597 bsg_reply = job->reply;
James Smarta33c4f72013-03-01 16:36:00 -0500598 /* Prevent timeout handling from trying to abort job */
599 job->dd_data = NULL;
600 }
601 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
602
James Smartb5a9b2d2013-09-06 12:19:45 -0400603 /* Close the timeout handler abort window */
604 spin_lock_irqsave(&phba->hbalock, flags);
James Smart1b8d11a2013-09-06 12:20:51 -0400605 cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING;
James Smartb5a9b2d2013-09-06 12:19:45 -0400606 spin_unlock_irqrestore(&phba->hbalock, flags);
607
James Smarta33c4f72013-03-01 16:36:00 -0500608 rsp = &rspiocbq->iocb;
609 pcmd = (struct lpfc_dmabuf *)cmdiocbq->context2;
610 prsp = (struct lpfc_dmabuf *)pcmd->list.next;
611
612 /* Copy the completed job data or determine the job status if job is
613 * still active
614 */
615
616 if (job) {
617 if (rsp->ulpStatus == IOSTAT_SUCCESS) {
618 rsp_size = rsp->un.elsreq64.bdl.bdeSize;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100619 bsg_reply->reply_payload_rcv_len =
James Smarta33c4f72013-03-01 16:36:00 -0500620 sg_copy_from_buffer(job->reply_payload.sg_list,
621 job->reply_payload.sg_cnt,
622 prsp->virt,
623 rsp_size);
624 } else if (rsp->ulpStatus == IOSTAT_LS_RJT) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100625 bsg_reply->reply_payload_rcv_len =
James Smarta33c4f72013-03-01 16:36:00 -0500626 sizeof(struct fc_bsg_ctels_reply);
627 /* LS_RJT data returned in word 4 */
628 rjt_data = (uint8_t *)&rsp->un.ulpWord[4];
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100629 els_reply = &bsg_reply->reply_data.ctels_reply;
James Smarta33c4f72013-03-01 16:36:00 -0500630 els_reply->status = FC_CTELS_STATUS_REJECT;
631 els_reply->rjt_data.action = rjt_data[3];
632 els_reply->rjt_data.reason_code = rjt_data[2];
633 els_reply->rjt_data.reason_explanation = rjt_data[1];
634 els_reply->rjt_data.vendor_unique = rjt_data[0];
635 } else {
636 rc = -EIO;
637 }
James Smart4cc0e562010-01-26 23:09:48 -0500638 }
639
James Smart4cc0e562010-01-26 23:09:48 -0500640 lpfc_nlp_put(ndlp);
James Smarta33c4f72013-03-01 16:36:00 -0500641 lpfc_els_free_iocb(phba, cmdiocbq);
James Smart4cc0e562010-01-26 23:09:48 -0500642 kfree(dd_data);
James Smarta33c4f72013-03-01 16:36:00 -0500643
644 /* Complete the job if the job is still active */
645
646 if (job) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100647 bsg_reply->result = rc;
Johannes Thumshirn06548162016-11-17 10:31:22 +0100648 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +0100649 bsg_reply->reply_payload_rcv_len);
James Smarta33c4f72013-03-01 16:36:00 -0500650 }
James Smart4cc0e562010-01-26 23:09:48 -0500651 return;
James Smartf1c3b0f2009-07-19 10:01:32 -0400652}
653
654/**
655 * lpfc_bsg_rport_els - send an ELS command from a bsg request
656 * @job: fc_bsg_job to handle
James Smart3b5dd522010-01-26 23:10:15 -0500657 **/
James Smartf1c3b0f2009-07-19 10:01:32 -0400658static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +0100659lpfc_bsg_rport_els(struct bsg_job *job)
James Smartf1c3b0f2009-07-19 10:01:32 -0400660{
Johannes Thumshirncd21c602016-11-17 10:31:14 +0100661 struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
James Smartf1c3b0f2009-07-19 10:01:32 -0400662 struct lpfc_hba *phba = vport->phba;
Johannes Thumshirn1d69b122016-11-17 10:31:15 +0100663 struct lpfc_rport_data *rdata = fc_bsg_to_rport(job)->dd_data;
James Smartf1c3b0f2009-07-19 10:01:32 -0400664 struct lpfc_nodelist *ndlp = rdata->pnode;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100665 struct fc_bsg_request *bsg_request = job->request;
666 struct fc_bsg_reply *bsg_reply = job->reply;
James Smartf1c3b0f2009-07-19 10:01:32 -0400667 uint32_t elscmd;
668 uint32_t cmdsize;
James Smartf1c3b0f2009-07-19 10:01:32 -0400669 struct lpfc_iocbq *cmdiocbq;
James Smartf1c3b0f2009-07-19 10:01:32 -0400670 uint16_t rpi = 0;
James Smart4cc0e562010-01-26 23:09:48 -0500671 struct bsg_job_data *dd_data;
James Smartb5a9b2d2013-09-06 12:19:45 -0400672 unsigned long flags;
James Smart4cc0e562010-01-26 23:09:48 -0500673 uint32_t creg_val;
James Smartf1c3b0f2009-07-19 10:01:32 -0400674 int rc = 0;
675
676 /* in case no data is transferred */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100677 bsg_reply->reply_payload_rcv_len = 0;
James Smartf1c3b0f2009-07-19 10:01:32 -0400678
James Smarta33c4f72013-03-01 16:36:00 -0500679 /* verify the els command is not greater than the
680 * maximum ELS transfer size.
681 */
682
683 if (job->request_payload.payload_len > FCELSSIZE) {
684 rc = -EINVAL;
685 goto no_dd_data;
686 }
687
James Smart4cc0e562010-01-26 23:09:48 -0500688 /* allocate our bsg tracking structure */
689 dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
690 if (!dd_data) {
691 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
692 "2735 Failed allocation of dd_data\n");
693 rc = -ENOMEM;
694 goto no_dd_data;
695 }
696
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100697 elscmd = bsg_request->rqst_data.r_els.els_code;
James Smarta33c4f72013-03-01 16:36:00 -0500698 cmdsize = job->request_payload.payload_len;
James Smarta33c4f72013-03-01 16:36:00 -0500699
James Smartf1c3b0f2009-07-19 10:01:32 -0400700 if (!lpfc_nlp_get(ndlp)) {
701 rc = -ENODEV;
James Smart4cc0e562010-01-26 23:09:48 -0500702 goto free_dd_data;
James Smartf1c3b0f2009-07-19 10:01:32 -0400703 }
704
James Smarta33c4f72013-03-01 16:36:00 -0500705 /* We will use the allocated dma buffers by prep els iocb for command
706 * and response to ensure if the job times out and the request is freed,
707 * we won't be dma into memory that is no longer allocated to for the
708 * request.
709 */
James Smartf1c3b0f2009-07-19 10:01:32 -0400710
James Smart4cc0e562010-01-26 23:09:48 -0500711 cmdiocbq = lpfc_prep_els_iocb(vport, 1, cmdsize, 0, ndlp,
James Smartf1c3b0f2009-07-19 10:01:32 -0400712 ndlp->nlp_DID, elscmd);
James Smartf1c3b0f2009-07-19 10:01:32 -0400713 if (!cmdiocbq) {
James Smart4cc0e562010-01-26 23:09:48 -0500714 rc = -EIO;
James Smarta33c4f72013-03-01 16:36:00 -0500715 goto release_ndlp;
James Smartf1c3b0f2009-07-19 10:01:32 -0400716 }
717
James Smarta33c4f72013-03-01 16:36:00 -0500718 rpi = ndlp->nlp_rpi;
James Smartf1c3b0f2009-07-19 10:01:32 -0400719
James Smarta33c4f72013-03-01 16:36:00 -0500720 /* Transfer the request payload to allocated command dma buffer */
James Smartf1c3b0f2009-07-19 10:01:32 -0400721
James Smarta33c4f72013-03-01 16:36:00 -0500722 sg_copy_to_buffer(job->request_payload.sg_list,
723 job->request_payload.sg_cnt,
724 ((struct lpfc_dmabuf *)cmdiocbq->context2)->virt,
725 cmdsize);
James Smartf1c3b0f2009-07-19 10:01:32 -0400726
James Smart3ef6d242012-01-18 16:23:48 -0500727 if (phba->sli_rev == LPFC_SLI_REV4)
728 cmdiocbq->iocb.ulpContext = phba->sli4_hba.rpi_ids[rpi];
729 else
730 cmdiocbq->iocb.ulpContext = rpi;
James Smartf1c3b0f2009-07-19 10:01:32 -0400731 cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
James Smart4cc0e562010-01-26 23:09:48 -0500732 cmdiocbq->context1 = dd_data;
James Smart93d1379e2012-05-09 21:19:34 -0400733 cmdiocbq->context_un.ndlp = ndlp;
James Smarta33c4f72013-03-01 16:36:00 -0500734 cmdiocbq->iocb_cmpl = lpfc_bsg_rport_els_cmp;
James Smart4cc0e562010-01-26 23:09:48 -0500735 dd_data->type = TYPE_IOCB;
James Smarta33c4f72013-03-01 16:36:00 -0500736 dd_data->set_job = job;
James Smart4cc0e562010-01-26 23:09:48 -0500737 dd_data->context_un.iocb.cmdiocbq = cmdiocbq;
James Smart4cc0e562010-01-26 23:09:48 -0500738 dd_data->context_un.iocb.ndlp = ndlp;
James Smarta33c4f72013-03-01 16:36:00 -0500739 dd_data->context_un.iocb.rmp = NULL;
740 job->dd_data = dd_data;
James Smartf1c3b0f2009-07-19 10:01:32 -0400741
James Smart4cc0e562010-01-26 23:09:48 -0500742 if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
James Smart9940b972011-03-11 16:06:12 -0500743 if (lpfc_readl(phba->HCregaddr, &creg_val)) {
744 rc = -EIO;
745 goto linkdown_err;
746 }
James Smart4cc0e562010-01-26 23:09:48 -0500747 creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
748 writel(creg_val, phba->HCregaddr);
749 readl(phba->HCregaddr); /* flush */
James Smartf1c3b0f2009-07-19 10:01:32 -0400750 }
James Smarta33c4f72013-03-01 16:36:00 -0500751
James Smart4cc0e562010-01-26 23:09:48 -0500752 rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);
James Smarta33c4f72013-03-01 16:36:00 -0500753
James Smartb5a9b2d2013-09-06 12:19:45 -0400754 if (rc == IOCB_SUCCESS) {
755 spin_lock_irqsave(&phba->hbalock, flags);
756 /* make sure the I/O had not been completed/released */
757 if (cmdiocbq->iocb_flag & LPFC_IO_LIBDFC) {
758 /* open up abort window to timeout handler */
James Smart1b8d11a2013-09-06 12:20:51 -0400759 cmdiocbq->iocb_flag |= LPFC_IO_CMD_OUTSTANDING;
James Smartb5a9b2d2013-09-06 12:19:45 -0400760 }
761 spin_unlock_irqrestore(&phba->hbalock, flags);
James Smart4cc0e562010-01-26 23:09:48 -0500762 return 0; /* done for now */
James Smartb5a9b2d2013-09-06 12:19:45 -0400763 } else if (rc == IOCB_BUSY) {
James Smartd439d282010-09-29 11:18:45 -0400764 rc = -EAGAIN;
James Smartb5a9b2d2013-09-06 12:19:45 -0400765 } else {
James Smartd439d282010-09-29 11:18:45 -0400766 rc = -EIO;
James Smartb5a9b2d2013-09-06 12:19:45 -0400767 }
768
769 /* iocb failed so cleanup */
770 job->dd_data = NULL;
James Smartf1c3b0f2009-07-19 10:01:32 -0400771
James Smart9940b972011-03-11 16:06:12 -0500772linkdown_err:
James Smarta33c4f72013-03-01 16:36:00 -0500773 cmdiocbq->context1 = ndlp;
774 lpfc_els_free_iocb(phba, cmdiocbq);
James Smartf1c3b0f2009-07-19 10:01:32 -0400775
James Smarta33c4f72013-03-01 16:36:00 -0500776release_ndlp:
777 lpfc_nlp_put(ndlp);
James Smartf1c3b0f2009-07-19 10:01:32 -0400778
James Smart4cc0e562010-01-26 23:09:48 -0500779free_dd_data:
780 kfree(dd_data);
781
782no_dd_data:
James Smartf1c3b0f2009-07-19 10:01:32 -0400783 /* make error code available to userspace */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100784 bsg_reply->result = rc;
James Smart4cc0e562010-01-26 23:09:48 -0500785 job->dd_data = NULL;
786 return rc;
James Smartf1c3b0f2009-07-19 10:01:32 -0400787}
788
James Smart3b5dd522010-01-26 23:10:15 -0500789/**
790 * lpfc_bsg_event_free - frees an allocated event structure
791 * @kref: Pointer to a kref.
792 *
793 * Called from kref_put. Back cast the kref into an event structure address.
794 * Free any events to get, delete associated nodes, free any events to see,
795 * free any data then free the event itself.
796 **/
James Smartf1c3b0f2009-07-19 10:01:32 -0400797static void
James Smart4cc0e562010-01-26 23:09:48 -0500798lpfc_bsg_event_free(struct kref *kref)
James Smartf1c3b0f2009-07-19 10:01:32 -0400799{
James Smart4cc0e562010-01-26 23:09:48 -0500800 struct lpfc_bsg_event *evt = container_of(kref, struct lpfc_bsg_event,
801 kref);
James Smartf1c3b0f2009-07-19 10:01:32 -0400802 struct event_data *ed;
803
804 list_del(&evt->node);
805
806 while (!list_empty(&evt->events_to_get)) {
807 ed = list_entry(evt->events_to_get.next, typeof(*ed), node);
808 list_del(&ed->node);
809 kfree(ed->data);
810 kfree(ed);
811 }
812
813 while (!list_empty(&evt->events_to_see)) {
814 ed = list_entry(evt->events_to_see.next, typeof(*ed), node);
815 list_del(&ed->node);
816 kfree(ed->data);
817 kfree(ed);
818 }
819
James Smarta33c4f72013-03-01 16:36:00 -0500820 kfree(evt->dd_data);
James Smartf1c3b0f2009-07-19 10:01:32 -0400821 kfree(evt);
822}
823
James Smart3b5dd522010-01-26 23:10:15 -0500824/**
825 * lpfc_bsg_event_ref - increments the kref for an event
826 * @evt: Pointer to an event structure.
827 **/
James Smartf1c3b0f2009-07-19 10:01:32 -0400828static inline void
James Smart4cc0e562010-01-26 23:09:48 -0500829lpfc_bsg_event_ref(struct lpfc_bsg_event *evt)
James Smartf1c3b0f2009-07-19 10:01:32 -0400830{
James Smart4cc0e562010-01-26 23:09:48 -0500831 kref_get(&evt->kref);
James Smartf1c3b0f2009-07-19 10:01:32 -0400832}
833
James Smart3b5dd522010-01-26 23:10:15 -0500834/**
835 * lpfc_bsg_event_unref - Uses kref_put to free an event structure
836 * @evt: Pointer to an event structure.
837 **/
James Smartf1c3b0f2009-07-19 10:01:32 -0400838static inline void
James Smart4cc0e562010-01-26 23:09:48 -0500839lpfc_bsg_event_unref(struct lpfc_bsg_event *evt)
James Smartf1c3b0f2009-07-19 10:01:32 -0400840{
James Smart4cc0e562010-01-26 23:09:48 -0500841 kref_put(&evt->kref, lpfc_bsg_event_free);
James Smartf1c3b0f2009-07-19 10:01:32 -0400842}
843
James Smart3b5dd522010-01-26 23:10:15 -0500844/**
845 * lpfc_bsg_event_new - allocate and initialize a event structure
846 * @ev_mask: Mask of events.
847 * @ev_reg_id: Event reg id.
848 * @ev_req_id: Event request id.
849 **/
James Smart4cc0e562010-01-26 23:09:48 -0500850static struct lpfc_bsg_event *
851lpfc_bsg_event_new(uint32_t ev_mask, int ev_reg_id, uint32_t ev_req_id)
852{
853 struct lpfc_bsg_event *evt = kzalloc(sizeof(*evt), GFP_KERNEL);
James Smartf1c3b0f2009-07-19 10:01:32 -0400854
James Smart4cc0e562010-01-26 23:09:48 -0500855 if (!evt)
856 return NULL;
857
858 INIT_LIST_HEAD(&evt->events_to_get);
859 INIT_LIST_HEAD(&evt->events_to_see);
860 evt->type_mask = ev_mask;
861 evt->req_id = ev_req_id;
862 evt->reg_id = ev_reg_id;
863 evt->wait_time_stamp = jiffies;
James Smarta33c4f72013-03-01 16:36:00 -0500864 evt->dd_data = NULL;
James Smart4cc0e562010-01-26 23:09:48 -0500865 init_waitqueue_head(&evt->wq);
866 kref_init(&evt->kref);
867 return evt;
868}
869
James Smart3b5dd522010-01-26 23:10:15 -0500870/**
871 * diag_cmd_data_free - Frees an lpfc dma buffer extension
872 * @phba: Pointer to HBA context object.
873 * @mlist: Pointer to an lpfc dma buffer extension.
874 **/
James Smart4cc0e562010-01-26 23:09:48 -0500875static int
James Smart3b5dd522010-01-26 23:10:15 -0500876diag_cmd_data_free(struct lpfc_hba *phba, struct lpfc_dmabufext *mlist)
James Smart4cc0e562010-01-26 23:09:48 -0500877{
878 struct lpfc_dmabufext *mlast;
879 struct pci_dev *pcidev;
880 struct list_head head, *curr, *next;
881
882 if ((!mlist) || (!lpfc_is_link_up(phba) &&
883 (phba->link_flag & LS_LOOPBACK_MODE))) {
884 return 0;
885 }
886
887 pcidev = phba->pcidev;
888 list_add_tail(&head, &mlist->dma.list);
889
890 list_for_each_safe(curr, next, &head) {
891 mlast = list_entry(curr, struct lpfc_dmabufext , dma.list);
892 if (mlast->dma.virt)
893 dma_free_coherent(&pcidev->dev,
894 mlast->size,
895 mlast->dma.virt,
896 mlast->dma.phys);
897 kfree(mlast);
898 }
899 return 0;
900}
James Smartf1c3b0f2009-07-19 10:01:32 -0400901
902/**
903 * lpfc_bsg_ct_unsol_event - process an unsolicited CT command
904 * @phba:
905 * @pring:
906 * @piocbq:
907 *
908 * This function is called when an unsolicited CT command is received. It
James Smart4cc0e562010-01-26 23:09:48 -0500909 * forwards the event to any processes registered to receive CT events.
James Smart3b5dd522010-01-26 23:10:15 -0500910 **/
James Smart4fede782010-01-26 23:08:55 -0500911int
James Smartf1c3b0f2009-07-19 10:01:32 -0400912lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
913 struct lpfc_iocbq *piocbq)
914{
915 uint32_t evt_req_id = 0;
916 uint32_t cmd;
James Smartf1c3b0f2009-07-19 10:01:32 -0400917 struct lpfc_dmabuf *dmabuf = NULL;
James Smart4cc0e562010-01-26 23:09:48 -0500918 struct lpfc_bsg_event *evt;
James Smartf1c3b0f2009-07-19 10:01:32 -0400919 struct event_data *evt_dat = NULL;
920 struct lpfc_iocbq *iocbq;
921 size_t offset = 0;
922 struct list_head head;
923 struct ulp_bde64 *bde;
924 dma_addr_t dma_addr;
925 int i;
926 struct lpfc_dmabuf *bdeBuf1 = piocbq->context2;
927 struct lpfc_dmabuf *bdeBuf2 = piocbq->context3;
928 struct lpfc_hbq_entry *hbqe;
929 struct lpfc_sli_ct_request *ct_req;
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +0100930 struct bsg_job *job = NULL;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +0100931 struct fc_bsg_reply *bsg_reply;
James Smarta33c4f72013-03-01 16:36:00 -0500932 struct bsg_job_data *dd_data = NULL;
James Smart4fede782010-01-26 23:08:55 -0500933 unsigned long flags;
James Smart4cc0e562010-01-26 23:09:48 -0500934 int size = 0;
James Smartf1c3b0f2009-07-19 10:01:32 -0400935
936 INIT_LIST_HEAD(&head);
937 list_add_tail(&head, &piocbq->list);
938
939 if (piocbq->iocb.ulpBdeCount == 0 ||
940 piocbq->iocb.un.cont64[0].tus.f.bdeSize == 0)
941 goto error_ct_unsol_exit;
942
James Smart4cc0e562010-01-26 23:09:48 -0500943 if (phba->link_state == LPFC_HBA_ERROR ||
944 (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE)))
945 goto error_ct_unsol_exit;
946
James Smartf1c3b0f2009-07-19 10:01:32 -0400947 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
948 dmabuf = bdeBuf1;
949 else {
950 dma_addr = getPaddr(piocbq->iocb.un.cont64[0].addrHigh,
951 piocbq->iocb.un.cont64[0].addrLow);
952 dmabuf = lpfc_sli_ringpostbuf_get(phba, pring, dma_addr);
953 }
James Smart4cc0e562010-01-26 23:09:48 -0500954 if (dmabuf == NULL)
955 goto error_ct_unsol_exit;
James Smartf1c3b0f2009-07-19 10:01:32 -0400956 ct_req = (struct lpfc_sli_ct_request *)dmabuf->virt;
957 evt_req_id = ct_req->FsType;
958 cmd = ct_req->CommandResponse.bits.CmdRsp;
James Smartf1c3b0f2009-07-19 10:01:32 -0400959 if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
960 lpfc_sli_ringpostbuf_put(phba, pring, dmabuf);
961
James Smart4fede782010-01-26 23:08:55 -0500962 spin_lock_irqsave(&phba->ct_ev_lock, flags);
James Smartf1c3b0f2009-07-19 10:01:32 -0400963 list_for_each_entry(evt, &phba->ct_ev_waiters, node) {
James Smart4cc0e562010-01-26 23:09:48 -0500964 if (!(evt->type_mask & FC_REG_CT_EVENT) ||
965 evt->req_id != evt_req_id)
James Smartf1c3b0f2009-07-19 10:01:32 -0400966 continue;
967
James Smart4cc0e562010-01-26 23:09:48 -0500968 lpfc_bsg_event_ref(evt);
969 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
James Smartf1c3b0f2009-07-19 10:01:32 -0400970 evt_dat = kzalloc(sizeof(*evt_dat), GFP_KERNEL);
James Smart4cc0e562010-01-26 23:09:48 -0500971 if (evt_dat == NULL) {
972 spin_lock_irqsave(&phba->ct_ev_lock, flags);
973 lpfc_bsg_event_unref(evt);
James Smartf1c3b0f2009-07-19 10:01:32 -0400974 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
975 "2614 Memory allocation failed for "
976 "CT event\n");
977 break;
978 }
979
James Smartf1c3b0f2009-07-19 10:01:32 -0400980 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
981 /* take accumulated byte count from the last iocbq */
982 iocbq = list_entry(head.prev, typeof(*iocbq), list);
983 evt_dat->len = iocbq->iocb.unsli3.rcvsli3.acc_len;
984 } else {
985 list_for_each_entry(iocbq, &head, list) {
986 for (i = 0; i < iocbq->iocb.ulpBdeCount; i++)
987 evt_dat->len +=
988 iocbq->iocb.un.cont64[i].tus.f.bdeSize;
989 }
990 }
991
992 evt_dat->data = kzalloc(evt_dat->len, GFP_KERNEL);
James Smart4cc0e562010-01-26 23:09:48 -0500993 if (evt_dat->data == NULL) {
James Smartf1c3b0f2009-07-19 10:01:32 -0400994 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
995 "2615 Memory allocation failed for "
996 "CT event data, size %d\n",
997 evt_dat->len);
998 kfree(evt_dat);
James Smart4fede782010-01-26 23:08:55 -0500999 spin_lock_irqsave(&phba->ct_ev_lock, flags);
James Smart4cc0e562010-01-26 23:09:48 -05001000 lpfc_bsg_event_unref(evt);
James Smart4fede782010-01-26 23:08:55 -05001001 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
James Smartf1c3b0f2009-07-19 10:01:32 -04001002 goto error_ct_unsol_exit;
1003 }
1004
1005 list_for_each_entry(iocbq, &head, list) {
James Smart4cc0e562010-01-26 23:09:48 -05001006 size = 0;
James Smartf1c3b0f2009-07-19 10:01:32 -04001007 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
1008 bdeBuf1 = iocbq->context2;
1009 bdeBuf2 = iocbq->context3;
1010 }
1011 for (i = 0; i < iocbq->iocb.ulpBdeCount; i++) {
James Smartf1c3b0f2009-07-19 10:01:32 -04001012 if (phba->sli3_options &
1013 LPFC_SLI3_HBQ_ENABLED) {
1014 if (i == 0) {
1015 hbqe = (struct lpfc_hbq_entry *)
1016 &iocbq->iocb.un.ulpWord[0];
1017 size = hbqe->bde.tus.f.bdeSize;
1018 dmabuf = bdeBuf1;
1019 } else if (i == 1) {
1020 hbqe = (struct lpfc_hbq_entry *)
1021 &iocbq->iocb.unsli3.
1022 sli3Words[4];
1023 size = hbqe->bde.tus.f.bdeSize;
1024 dmabuf = bdeBuf2;
1025 }
1026 if ((offset + size) > evt_dat->len)
1027 size = evt_dat->len - offset;
1028 } else {
1029 size = iocbq->iocb.un.cont64[i].
1030 tus.f.bdeSize;
1031 bde = &iocbq->iocb.un.cont64[i];
1032 dma_addr = getPaddr(bde->addrHigh,
1033 bde->addrLow);
1034 dmabuf = lpfc_sli_ringpostbuf_get(phba,
1035 pring, dma_addr);
1036 }
1037 if (!dmabuf) {
1038 lpfc_printf_log(phba, KERN_ERR,
1039 LOG_LIBDFC, "2616 No dmabuf "
1040 "found for iocbq 0x%p\n",
1041 iocbq);
1042 kfree(evt_dat->data);
1043 kfree(evt_dat);
James Smart4fede782010-01-26 23:08:55 -05001044 spin_lock_irqsave(&phba->ct_ev_lock,
1045 flags);
James Smart4cc0e562010-01-26 23:09:48 -05001046 lpfc_bsg_event_unref(evt);
James Smart4fede782010-01-26 23:08:55 -05001047 spin_unlock_irqrestore(
1048 &phba->ct_ev_lock, flags);
James Smartf1c3b0f2009-07-19 10:01:32 -04001049 goto error_ct_unsol_exit;
1050 }
1051 memcpy((char *)(evt_dat->data) + offset,
1052 dmabuf->virt, size);
1053 offset += size;
1054 if (evt_req_id != SLI_CT_ELX_LOOPBACK &&
1055 !(phba->sli3_options &
1056 LPFC_SLI3_HBQ_ENABLED)) {
1057 lpfc_sli_ringpostbuf_put(phba, pring,
1058 dmabuf);
1059 } else {
1060 switch (cmd) {
James Smart4cc0e562010-01-26 23:09:48 -05001061 case ELX_LOOPBACK_DATA:
James Smart1b511972011-12-13 13:23:09 -05001062 if (phba->sli_rev <
1063 LPFC_SLI_REV4)
1064 diag_cmd_data_free(phba,
1065 (struct lpfc_dmabufext
1066 *)dmabuf);
James Smart4cc0e562010-01-26 23:09:48 -05001067 break;
James Smartf1c3b0f2009-07-19 10:01:32 -04001068 case ELX_LOOPBACK_XRI_SETUP:
James Smart4cc0e562010-01-26 23:09:48 -05001069 if ((phba->sli_rev ==
1070 LPFC_SLI_REV2) ||
1071 (phba->sli3_options &
1072 LPFC_SLI3_HBQ_ENABLED
1073 )) {
1074 lpfc_in_buf_free(phba,
1075 dmabuf);
1076 } else {
James Smartf1c3b0f2009-07-19 10:01:32 -04001077 lpfc_post_buffer(phba,
1078 pring,
1079 1);
James Smart4cc0e562010-01-26 23:09:48 -05001080 }
James Smartf1c3b0f2009-07-19 10:01:32 -04001081 break;
1082 default:
1083 if (!(phba->sli3_options &
1084 LPFC_SLI3_HBQ_ENABLED))
1085 lpfc_post_buffer(phba,
1086 pring,
1087 1);
1088 break;
1089 }
1090 }
1091 }
1092 }
1093
James Smart4fede782010-01-26 23:08:55 -05001094 spin_lock_irqsave(&phba->ct_ev_lock, flags);
James Smartf1c3b0f2009-07-19 10:01:32 -04001095 if (phba->sli_rev == LPFC_SLI_REV4) {
1096 evt_dat->immed_dat = phba->ctx_idx;
James Smart6dd9e312013-01-03 15:43:37 -05001097 phba->ctx_idx = (phba->ctx_idx + 1) % LPFC_CT_CTX_MAX;
James Smart589a52d2010-07-14 15:30:54 -04001098 /* Provide warning for over-run of the ct_ctx array */
James Smart6dd9e312013-01-03 15:43:37 -05001099 if (phba->ct_ctx[evt_dat->immed_dat].valid ==
James Smart589a52d2010-07-14 15:30:54 -04001100 UNSOL_VALID)
1101 lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
1102 "2717 CT context array entry "
1103 "[%d] over-run: oxid:x%x, "
1104 "sid:x%x\n", phba->ctx_idx,
1105 phba->ct_ctx[
1106 evt_dat->immed_dat].oxid,
1107 phba->ct_ctx[
1108 evt_dat->immed_dat].SID);
James Smart7851fe22011-07-22 18:36:52 -04001109 phba->ct_ctx[evt_dat->immed_dat].rxid =
1110 piocbq->iocb.ulpContext;
James Smartf1c3b0f2009-07-19 10:01:32 -04001111 phba->ct_ctx[evt_dat->immed_dat].oxid =
James Smart7851fe22011-07-22 18:36:52 -04001112 piocbq->iocb.unsli3.rcvsli3.ox_id;
James Smartf1c3b0f2009-07-19 10:01:32 -04001113 phba->ct_ctx[evt_dat->immed_dat].SID =
1114 piocbq->iocb.un.rcvels.remoteID;
James Smart6dd9e312013-01-03 15:43:37 -05001115 phba->ct_ctx[evt_dat->immed_dat].valid = UNSOL_VALID;
James Smartf1c3b0f2009-07-19 10:01:32 -04001116 } else
1117 evt_dat->immed_dat = piocbq->iocb.ulpContext;
1118
1119 evt_dat->type = FC_REG_CT_EVENT;
1120 list_add(&evt_dat->node, &evt->events_to_see);
James Smart4cc0e562010-01-26 23:09:48 -05001121 if (evt_req_id == SLI_CT_ELX_LOOPBACK) {
1122 wake_up_interruptible(&evt->wq);
1123 lpfc_bsg_event_unref(evt);
James Smartf1c3b0f2009-07-19 10:01:32 -04001124 break;
James Smart4cc0e562010-01-26 23:09:48 -05001125 }
1126
1127 list_move(evt->events_to_see.prev, &evt->events_to_get);
James Smart4cc0e562010-01-26 23:09:48 -05001128
James Smarta33c4f72013-03-01 16:36:00 -05001129 dd_data = (struct bsg_job_data *)evt->dd_data;
1130 job = dd_data->set_job;
1131 dd_data->set_job = NULL;
1132 lpfc_bsg_event_unref(evt);
James Smart4cc0e562010-01-26 23:09:48 -05001133 if (job) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001134 bsg_reply = job->reply;
1135 bsg_reply->reply_payload_rcv_len = size;
James Smart4cc0e562010-01-26 23:09:48 -05001136 /* make error code available to userspace */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001137 bsg_reply->result = 0;
James Smart4cc0e562010-01-26 23:09:48 -05001138 job->dd_data = NULL;
1139 /* complete the job back to userspace */
1140 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
Johannes Thumshirn06548162016-11-17 10:31:22 +01001141 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01001142 bsg_reply->reply_payload_rcv_len);
James Smart4cc0e562010-01-26 23:09:48 -05001143 spin_lock_irqsave(&phba->ct_ev_lock, flags);
1144 }
James Smartf1c3b0f2009-07-19 10:01:32 -04001145 }
James Smart4fede782010-01-26 23:08:55 -05001146 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
James Smartf1c3b0f2009-07-19 10:01:32 -04001147
1148error_ct_unsol_exit:
1149 if (!list_empty(&head))
1150 list_del(&head);
James Smart1b511972011-12-13 13:23:09 -05001151 if ((phba->sli_rev < LPFC_SLI_REV4) &&
1152 (evt_req_id == SLI_CT_ELX_LOOPBACK))
James Smart4cc0e562010-01-26 23:09:48 -05001153 return 0;
James Smart4fede782010-01-26 23:08:55 -05001154 return 1;
James Smartf1c3b0f2009-07-19 10:01:32 -04001155}
1156
1157/**
James Smart6dd9e312013-01-03 15:43:37 -05001158 * lpfc_bsg_ct_unsol_abort - handler ct abort to management plane
1159 * @phba: Pointer to HBA context object.
1160 * @dmabuf: pointer to a dmabuf that describes the FC sequence
1161 *
1162 * This function handles abort to the CT command toward management plane
1163 * for SLI4 port.
1164 *
1165 * If the pending context of a CT command to management plane present, clears
1166 * such context and returns 1 for handled; otherwise, it returns 0 indicating
1167 * no context exists.
1168 **/
1169int
1170lpfc_bsg_ct_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf)
1171{
1172 struct fc_frame_header fc_hdr;
1173 struct fc_frame_header *fc_hdr_ptr = &fc_hdr;
1174 int ctx_idx, handled = 0;
1175 uint16_t oxid, rxid;
1176 uint32_t sid;
1177
1178 memcpy(fc_hdr_ptr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header));
1179 sid = sli4_sid_from_fc_hdr(fc_hdr_ptr);
1180 oxid = be16_to_cpu(fc_hdr_ptr->fh_ox_id);
1181 rxid = be16_to_cpu(fc_hdr_ptr->fh_rx_id);
1182
1183 for (ctx_idx = 0; ctx_idx < LPFC_CT_CTX_MAX; ctx_idx++) {
1184 if (phba->ct_ctx[ctx_idx].valid != UNSOL_VALID)
1185 continue;
1186 if (phba->ct_ctx[ctx_idx].rxid != rxid)
1187 continue;
1188 if (phba->ct_ctx[ctx_idx].oxid != oxid)
1189 continue;
1190 if (phba->ct_ctx[ctx_idx].SID != sid)
1191 continue;
1192 phba->ct_ctx[ctx_idx].valid = UNSOL_INVALID;
1193 handled = 1;
1194 }
1195 return handled;
1196}
1197
1198/**
James Smart4cc0e562010-01-26 23:09:48 -05001199 * lpfc_bsg_hba_set_event - process a SET_EVENT bsg vendor command
James Smartf1c3b0f2009-07-19 10:01:32 -04001200 * @job: SET_EVENT fc_bsg_job
James Smart3b5dd522010-01-26 23:10:15 -05001201 **/
James Smartf1c3b0f2009-07-19 10:01:32 -04001202static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01001203lpfc_bsg_hba_set_event(struct bsg_job *job)
James Smartf1c3b0f2009-07-19 10:01:32 -04001204{
Johannes Thumshirncd21c602016-11-17 10:31:14 +01001205 struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
James Smartf1c3b0f2009-07-19 10:01:32 -04001206 struct lpfc_hba *phba = vport->phba;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001207 struct fc_bsg_request *bsg_request = job->request;
James Smartf1c3b0f2009-07-19 10:01:32 -04001208 struct set_ct_event *event_req;
James Smart4cc0e562010-01-26 23:09:48 -05001209 struct lpfc_bsg_event *evt;
James Smartf1c3b0f2009-07-19 10:01:32 -04001210 int rc = 0;
James Smart4cc0e562010-01-26 23:09:48 -05001211 struct bsg_job_data *dd_data = NULL;
1212 uint32_t ev_mask;
1213 unsigned long flags;
James Smartf1c3b0f2009-07-19 10:01:32 -04001214
1215 if (job->request_len <
1216 sizeof(struct fc_bsg_request) + sizeof(struct set_ct_event)) {
1217 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
1218 "2612 Received SET_CT_EVENT below minimum "
1219 "size\n");
James Smart4cc0e562010-01-26 23:09:48 -05001220 rc = -EINVAL;
1221 goto job_error;
1222 }
1223
James Smartf1c3b0f2009-07-19 10:01:32 -04001224 event_req = (struct set_ct_event *)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001225 bsg_request->rqst_data.h_vendor.vendor_cmd;
James Smart4cc0e562010-01-26 23:09:48 -05001226 ev_mask = ((uint32_t)(unsigned long)event_req->type_mask &
1227 FC_REG_EVENT_MASK);
James Smart4fede782010-01-26 23:08:55 -05001228 spin_lock_irqsave(&phba->ct_ev_lock, flags);
James Smartf1c3b0f2009-07-19 10:01:32 -04001229 list_for_each_entry(evt, &phba->ct_ev_waiters, node) {
1230 if (evt->reg_id == event_req->ev_reg_id) {
James Smart4cc0e562010-01-26 23:09:48 -05001231 lpfc_bsg_event_ref(evt);
James Smartf1c3b0f2009-07-19 10:01:32 -04001232 evt->wait_time_stamp = jiffies;
James Smarta33c4f72013-03-01 16:36:00 -05001233 dd_data = (struct bsg_job_data *)evt->dd_data;
James Smartf1c3b0f2009-07-19 10:01:32 -04001234 break;
1235 }
1236 }
James Smart4fede782010-01-26 23:08:55 -05001237 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
James Smartf1c3b0f2009-07-19 10:01:32 -04001238
1239 if (&evt->node == &phba->ct_ev_waiters) {
1240 /* no event waiting struct yet - first call */
James Smarta33c4f72013-03-01 16:36:00 -05001241 dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
1242 if (dd_data == NULL) {
1243 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
1244 "2734 Failed allocation of dd_data\n");
1245 rc = -ENOMEM;
1246 goto job_error;
1247 }
James Smart4cc0e562010-01-26 23:09:48 -05001248 evt = lpfc_bsg_event_new(ev_mask, event_req->ev_reg_id,
James Smartf1c3b0f2009-07-19 10:01:32 -04001249 event_req->ev_req_id);
1250 if (!evt) {
1251 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
1252 "2617 Failed allocation of event "
1253 "waiter\n");
James Smart4cc0e562010-01-26 23:09:48 -05001254 rc = -ENOMEM;
1255 goto job_error;
James Smartf1c3b0f2009-07-19 10:01:32 -04001256 }
James Smarta33c4f72013-03-01 16:36:00 -05001257 dd_data->type = TYPE_EVT;
1258 dd_data->set_job = NULL;
1259 dd_data->context_un.evt = evt;
1260 evt->dd_data = (void *)dd_data;
James Smart4fede782010-01-26 23:08:55 -05001261 spin_lock_irqsave(&phba->ct_ev_lock, flags);
James Smartf1c3b0f2009-07-19 10:01:32 -04001262 list_add(&evt->node, &phba->ct_ev_waiters);
James Smart4cc0e562010-01-26 23:09:48 -05001263 lpfc_bsg_event_ref(evt);
1264 evt->wait_time_stamp = jiffies;
James Smart4fede782010-01-26 23:08:55 -05001265 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
James Smartf1c3b0f2009-07-19 10:01:32 -04001266 }
1267
James Smart4fede782010-01-26 23:08:55 -05001268 spin_lock_irqsave(&phba->ct_ev_lock, flags);
James Smart4cc0e562010-01-26 23:09:48 -05001269 evt->waiting = 1;
James Smarta33c4f72013-03-01 16:36:00 -05001270 dd_data->set_job = job; /* for unsolicited command */
James Smart4cc0e562010-01-26 23:09:48 -05001271 job->dd_data = dd_data; /* for fc transport timeout callback*/
James Smart4fede782010-01-26 23:08:55 -05001272 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
James Smart4cc0e562010-01-26 23:09:48 -05001273 return 0; /* call job done later */
James Smartf1c3b0f2009-07-19 10:01:32 -04001274
James Smart4cc0e562010-01-26 23:09:48 -05001275job_error:
1276 if (dd_data != NULL)
1277 kfree(dd_data);
James Smartf1c3b0f2009-07-19 10:01:32 -04001278
James Smart4cc0e562010-01-26 23:09:48 -05001279 job->dd_data = NULL;
1280 return rc;
James Smartf1c3b0f2009-07-19 10:01:32 -04001281}
1282
1283/**
James Smart4cc0e562010-01-26 23:09:48 -05001284 * lpfc_bsg_hba_get_event - process a GET_EVENT bsg vendor command
James Smartf1c3b0f2009-07-19 10:01:32 -04001285 * @job: GET_EVENT fc_bsg_job
James Smart3b5dd522010-01-26 23:10:15 -05001286 **/
James Smartf1c3b0f2009-07-19 10:01:32 -04001287static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01001288lpfc_bsg_hba_get_event(struct bsg_job *job)
James Smartf1c3b0f2009-07-19 10:01:32 -04001289{
Johannes Thumshirncd21c602016-11-17 10:31:14 +01001290 struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
James Smartf1c3b0f2009-07-19 10:01:32 -04001291 struct lpfc_hba *phba = vport->phba;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001292 struct fc_bsg_request *bsg_request = job->request;
1293 struct fc_bsg_reply *bsg_reply = job->reply;
James Smartf1c3b0f2009-07-19 10:01:32 -04001294 struct get_ct_event *event_req;
1295 struct get_ct_event_reply *event_reply;
James Smart9a803a72013-09-06 12:17:56 -04001296 struct lpfc_bsg_event *evt, *evt_next;
James Smartf1c3b0f2009-07-19 10:01:32 -04001297 struct event_data *evt_dat = NULL;
James Smart4fede782010-01-26 23:08:55 -05001298 unsigned long flags;
James Smart4cc0e562010-01-26 23:09:48 -05001299 uint32_t rc = 0;
James Smartf1c3b0f2009-07-19 10:01:32 -04001300
1301 if (job->request_len <
1302 sizeof(struct fc_bsg_request) + sizeof(struct get_ct_event)) {
1303 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
1304 "2613 Received GET_CT_EVENT request below "
1305 "minimum size\n");
James Smart4cc0e562010-01-26 23:09:48 -05001306 rc = -EINVAL;
1307 goto job_error;
James Smartf1c3b0f2009-07-19 10:01:32 -04001308 }
1309
1310 event_req = (struct get_ct_event *)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001311 bsg_request->rqst_data.h_vendor.vendor_cmd;
James Smartf1c3b0f2009-07-19 10:01:32 -04001312
1313 event_reply = (struct get_ct_event_reply *)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001314 bsg_reply->reply_data.vendor_reply.vendor_rsp;
James Smart4fede782010-01-26 23:08:55 -05001315 spin_lock_irqsave(&phba->ct_ev_lock, flags);
James Smart9a803a72013-09-06 12:17:56 -04001316 list_for_each_entry_safe(evt, evt_next, &phba->ct_ev_waiters, node) {
James Smartf1c3b0f2009-07-19 10:01:32 -04001317 if (evt->reg_id == event_req->ev_reg_id) {
1318 if (list_empty(&evt->events_to_get))
1319 break;
James Smart4cc0e562010-01-26 23:09:48 -05001320 lpfc_bsg_event_ref(evt);
James Smartf1c3b0f2009-07-19 10:01:32 -04001321 evt->wait_time_stamp = jiffies;
1322 evt_dat = list_entry(evt->events_to_get.prev,
1323 struct event_data, node);
1324 list_del(&evt_dat->node);
1325 break;
1326 }
1327 }
James Smart4fede782010-01-26 23:08:55 -05001328 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
James Smartf1c3b0f2009-07-19 10:01:32 -04001329
James Smart4cc0e562010-01-26 23:09:48 -05001330 /* The app may continue to ask for event data until it gets
1331 * an error indicating that there isn't anymore
1332 */
1333 if (evt_dat == NULL) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001334 bsg_reply->reply_payload_rcv_len = 0;
James Smartf1c3b0f2009-07-19 10:01:32 -04001335 rc = -ENOENT;
James Smart4cc0e562010-01-26 23:09:48 -05001336 goto job_error;
James Smartf1c3b0f2009-07-19 10:01:32 -04001337 }
1338
James Smart4cc0e562010-01-26 23:09:48 -05001339 if (evt_dat->len > job->request_payload.payload_len) {
1340 evt_dat->len = job->request_payload.payload_len;
1341 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
1342 "2618 Truncated event data at %d "
1343 "bytes\n",
1344 job->request_payload.payload_len);
James Smartf1c3b0f2009-07-19 10:01:32 -04001345 }
1346
James Smart4cc0e562010-01-26 23:09:48 -05001347 event_reply->type = evt_dat->type;
James Smartf1c3b0f2009-07-19 10:01:32 -04001348 event_reply->immed_data = evt_dat->immed_dat;
James Smartf1c3b0f2009-07-19 10:01:32 -04001349 if (evt_dat->len > 0)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001350 bsg_reply->reply_payload_rcv_len =
James Smart4cc0e562010-01-26 23:09:48 -05001351 sg_copy_from_buffer(job->request_payload.sg_list,
1352 job->request_payload.sg_cnt,
James Smartf1c3b0f2009-07-19 10:01:32 -04001353 evt_dat->data, evt_dat->len);
1354 else
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001355 bsg_reply->reply_payload_rcv_len = 0;
James Smartf1c3b0f2009-07-19 10:01:32 -04001356
James Smart4cc0e562010-01-26 23:09:48 -05001357 if (evt_dat) {
James Smartf1c3b0f2009-07-19 10:01:32 -04001358 kfree(evt_dat->data);
James Smart4cc0e562010-01-26 23:09:48 -05001359 kfree(evt_dat);
1360 }
1361
James Smart4fede782010-01-26 23:08:55 -05001362 spin_lock_irqsave(&phba->ct_ev_lock, flags);
James Smart4cc0e562010-01-26 23:09:48 -05001363 lpfc_bsg_event_unref(evt);
James Smart4fede782010-01-26 23:08:55 -05001364 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
James Smart4cc0e562010-01-26 23:09:48 -05001365 job->dd_data = NULL;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001366 bsg_reply->result = 0;
Johannes Thumshirn06548162016-11-17 10:31:22 +01001367 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01001368 bsg_reply->reply_payload_rcv_len);
James Smart4cc0e562010-01-26 23:09:48 -05001369 return 0;
James Smartf1c3b0f2009-07-19 10:01:32 -04001370
James Smart4cc0e562010-01-26 23:09:48 -05001371job_error:
1372 job->dd_data = NULL;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001373 bsg_reply->result = rc;
James Smartf1c3b0f2009-07-19 10:01:32 -04001374 return rc;
1375}
1376
1377/**
James Smart3b5dd522010-01-26 23:10:15 -05001378 * lpfc_issue_ct_rsp_cmp - lpfc_issue_ct_rsp's completion handler
1379 * @phba: Pointer to HBA context object.
1380 * @cmdiocbq: Pointer to command iocb.
1381 * @rspiocbq: Pointer to response iocb.
1382 *
1383 * This function is the completion handler for iocbs issued using
1384 * lpfc_issue_ct_rsp_cmp function. This function is called by the
1385 * ring event handler function without any lock held. This function
1386 * can be called from both worker thread context and interrupt
1387 * context. This function also can be called from other thread which
1388 * cleans up the SLI layer objects.
1389 * This function copy the contents of the response iocb to the
1390 * response iocb memory object provided by the caller of
1391 * lpfc_sli_issue_iocb_wait and then wakes up the thread which
1392 * sleeps for the iocb completion.
1393 **/
1394static void
1395lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba,
1396 struct lpfc_iocbq *cmdiocbq,
1397 struct lpfc_iocbq *rspiocbq)
1398{
1399 struct bsg_job_data *dd_data;
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01001400 struct bsg_job *job;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001401 struct fc_bsg_reply *bsg_reply;
James Smart3b5dd522010-01-26 23:10:15 -05001402 IOCB_t *rsp;
James Smarta33c4f72013-03-01 16:36:00 -05001403 struct lpfc_dmabuf *bmp, *cmp;
James Smart3b5dd522010-01-26 23:10:15 -05001404 struct lpfc_nodelist *ndlp;
1405 unsigned long flags;
1406 int rc = 0;
1407
James Smarta33c4f72013-03-01 16:36:00 -05001408 dd_data = cmdiocbq->context1;
1409
1410 /* Determine if job has been aborted */
James Smart3b5dd522010-01-26 23:10:15 -05001411 spin_lock_irqsave(&phba->ct_ev_lock, flags);
James Smarta33c4f72013-03-01 16:36:00 -05001412 job = dd_data->set_job;
1413 if (job) {
1414 /* Prevent timeout handling from trying to abort job */
1415 job->dd_data = NULL;
1416 }
1417 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
1418
James Smartb5a9b2d2013-09-06 12:19:45 -04001419 /* Close the timeout handler abort window */
1420 spin_lock_irqsave(&phba->hbalock, flags);
James Smart1b8d11a2013-09-06 12:20:51 -04001421 cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING;
James Smartb5a9b2d2013-09-06 12:19:45 -04001422 spin_unlock_irqrestore(&phba->hbalock, flags);
1423
James Smarta33c4f72013-03-01 16:36:00 -05001424 ndlp = dd_data->context_un.iocb.ndlp;
1425 cmp = cmdiocbq->context2;
1426 bmp = cmdiocbq->context3;
1427 rsp = &rspiocbq->iocb;
1428
1429 /* Copy the completed job data or set the error status */
1430
1431 if (job) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001432 bsg_reply = job->reply;
James Smarta33c4f72013-03-01 16:36:00 -05001433 if (rsp->ulpStatus) {
1434 if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
1435 switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) {
1436 case IOERR_SEQUENCE_TIMEOUT:
1437 rc = -ETIMEDOUT;
1438 break;
1439 case IOERR_INVALID_RPI:
1440 rc = -EFAULT;
1441 break;
1442 default:
1443 rc = -EACCES;
1444 break;
1445 }
1446 } else {
1447 rc = -EACCES;
1448 }
1449 } else {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001450 bsg_reply->reply_payload_rcv_len = 0;
James Smarta33c4f72013-03-01 16:36:00 -05001451 }
James Smart3b5dd522010-01-26 23:10:15 -05001452 }
1453
James Smarta33c4f72013-03-01 16:36:00 -05001454 lpfc_free_bsg_buffers(phba, cmp);
James Smart3b5dd522010-01-26 23:10:15 -05001455 lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
James Smarta33c4f72013-03-01 16:36:00 -05001456 kfree(bmp);
James Smart3b5dd522010-01-26 23:10:15 -05001457 lpfc_sli_release_iocbq(phba, cmdiocbq);
1458 lpfc_nlp_put(ndlp);
James Smart3b5dd522010-01-26 23:10:15 -05001459 kfree(dd_data);
James Smarta33c4f72013-03-01 16:36:00 -05001460
1461 /* Complete the job if the job is still active */
1462
1463 if (job) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001464 bsg_reply->result = rc;
Johannes Thumshirn06548162016-11-17 10:31:22 +01001465 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01001466 bsg_reply->reply_payload_rcv_len);
James Smarta33c4f72013-03-01 16:36:00 -05001467 }
James Smart3b5dd522010-01-26 23:10:15 -05001468 return;
1469}
1470
1471/**
1472 * lpfc_issue_ct_rsp - issue a ct response
1473 * @phba: Pointer to HBA context object.
1474 * @job: Pointer to the job object.
1475 * @tag: tag index value into the ports context exchange array.
1476 * @bmp: Pointer to a dma buffer descriptor.
1477 * @num_entry: Number of enties in the bde.
1478 **/
1479static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01001480lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag,
James Smarta33c4f72013-03-01 16:36:00 -05001481 struct lpfc_dmabuf *cmp, struct lpfc_dmabuf *bmp,
1482 int num_entry)
James Smart3b5dd522010-01-26 23:10:15 -05001483{
1484 IOCB_t *icmd;
1485 struct lpfc_iocbq *ctiocb = NULL;
1486 int rc = 0;
1487 struct lpfc_nodelist *ndlp = NULL;
1488 struct bsg_job_data *dd_data;
James Smartb5a9b2d2013-09-06 12:19:45 -04001489 unsigned long flags;
James Smart3b5dd522010-01-26 23:10:15 -05001490 uint32_t creg_val;
1491
1492 /* allocate our bsg tracking structure */
1493 dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
1494 if (!dd_data) {
1495 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
1496 "2736 Failed allocation of dd_data\n");
1497 rc = -ENOMEM;
1498 goto no_dd_data;
1499 }
1500
1501 /* Allocate buffer for command iocb */
1502 ctiocb = lpfc_sli_get_iocbq(phba);
1503 if (!ctiocb) {
James Smartd439d282010-09-29 11:18:45 -04001504 rc = -ENOMEM;
James Smart3b5dd522010-01-26 23:10:15 -05001505 goto no_ctiocb;
1506 }
1507
1508 icmd = &ctiocb->iocb;
1509 icmd->un.xseq64.bdl.ulpIoTag32 = 0;
1510 icmd->un.xseq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
1511 icmd->un.xseq64.bdl.addrLow = putPaddrLow(bmp->phys);
1512 icmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
1513 icmd->un.xseq64.bdl.bdeSize = (num_entry * sizeof(struct ulp_bde64));
1514 icmd->un.xseq64.w5.hcsw.Fctl = (LS | LA);
1515 icmd->un.xseq64.w5.hcsw.Dfctl = 0;
1516 icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_DD_SOL_CTL;
1517 icmd->un.xseq64.w5.hcsw.Type = FC_TYPE_CT;
1518
1519 /* Fill in rest of iocb */
1520 icmd->ulpCommand = CMD_XMIT_SEQUENCE64_CX;
1521 icmd->ulpBdeCount = 1;
1522 icmd->ulpLe = 1;
1523 icmd->ulpClass = CLASS3;
1524 if (phba->sli_rev == LPFC_SLI_REV4) {
1525 /* Do not issue unsol response if oxid not marked as valid */
James Smart6dd9e312013-01-03 15:43:37 -05001526 if (phba->ct_ctx[tag].valid != UNSOL_VALID) {
James Smart3b5dd522010-01-26 23:10:15 -05001527 rc = IOCB_ERROR;
1528 goto issue_ct_rsp_exit;
1529 }
James Smart7851fe22011-07-22 18:36:52 -04001530 icmd->ulpContext = phba->ct_ctx[tag].rxid;
1531 icmd->unsli3.rcvsli3.ox_id = phba->ct_ctx[tag].oxid;
James Smart3b5dd522010-01-26 23:10:15 -05001532 ndlp = lpfc_findnode_did(phba->pport, phba->ct_ctx[tag].SID);
1533 if (!ndlp) {
1534 lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
1535 "2721 ndlp null for oxid %x SID %x\n",
1536 icmd->ulpContext,
1537 phba->ct_ctx[tag].SID);
1538 rc = IOCB_ERROR;
1539 goto issue_ct_rsp_exit;
1540 }
James Smart589a52d2010-07-14 15:30:54 -04001541
1542 /* Check if the ndlp is active */
1543 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
James Smarta33c4f72013-03-01 16:36:00 -05001544 rc = IOCB_ERROR;
James Smart589a52d2010-07-14 15:30:54 -04001545 goto issue_ct_rsp_exit;
1546 }
1547
1548 /* get a refernece count so the ndlp doesn't go away while
1549 * we respond
1550 */
1551 if (!lpfc_nlp_get(ndlp)) {
James Smarta33c4f72013-03-01 16:36:00 -05001552 rc = IOCB_ERROR;
James Smart589a52d2010-07-14 15:30:54 -04001553 goto issue_ct_rsp_exit;
1554 }
1555
James Smart7851fe22011-07-22 18:36:52 -04001556 icmd->un.ulpWord[3] =
James Smart6d368e52011-05-24 11:44:12 -04001557 phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
1558
James Smart3b5dd522010-01-26 23:10:15 -05001559 /* The exchange is done, mark the entry as invalid */
James Smart6dd9e312013-01-03 15:43:37 -05001560 phba->ct_ctx[tag].valid = UNSOL_INVALID;
James Smart3b5dd522010-01-26 23:10:15 -05001561 } else
1562 icmd->ulpContext = (ushort) tag;
1563
1564 icmd->ulpTimeout = phba->fc_ratov * 2;
1565
1566 /* Xmit CT response on exchange <xid> */
1567 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart7851fe22011-07-22 18:36:52 -04001568 "2722 Xmit CT response on exchange x%x Data: x%x x%x x%x\n",
1569 icmd->ulpContext, icmd->ulpIoTag, tag, phba->link_state);
James Smart3b5dd522010-01-26 23:10:15 -05001570
1571 ctiocb->iocb_cmpl = NULL;
1572 ctiocb->iocb_flag |= LPFC_IO_LIBDFC;
1573 ctiocb->vport = phba->pport;
James Smarta33c4f72013-03-01 16:36:00 -05001574 ctiocb->context1 = dd_data;
1575 ctiocb->context2 = cmp;
James Smart3b5dd522010-01-26 23:10:15 -05001576 ctiocb->context3 = bmp;
James Smartd5ce53b2013-04-17 20:17:26 -04001577 ctiocb->context_un.ndlp = ndlp;
James Smart3b5dd522010-01-26 23:10:15 -05001578 ctiocb->iocb_cmpl = lpfc_issue_ct_rsp_cmp;
James Smarta33c4f72013-03-01 16:36:00 -05001579
James Smart3b5dd522010-01-26 23:10:15 -05001580 dd_data->type = TYPE_IOCB;
James Smarta33c4f72013-03-01 16:36:00 -05001581 dd_data->set_job = job;
James Smart3b5dd522010-01-26 23:10:15 -05001582 dd_data->context_un.iocb.cmdiocbq = ctiocb;
James Smart3b5dd522010-01-26 23:10:15 -05001583 dd_data->context_un.iocb.ndlp = ndlp;
James Smarta33c4f72013-03-01 16:36:00 -05001584 dd_data->context_un.iocb.rmp = NULL;
1585 job->dd_data = dd_data;
James Smart3b5dd522010-01-26 23:10:15 -05001586
1587 if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
James Smart9940b972011-03-11 16:06:12 -05001588 if (lpfc_readl(phba->HCregaddr, &creg_val)) {
1589 rc = -IOCB_ERROR;
1590 goto issue_ct_rsp_exit;
1591 }
James Smart3b5dd522010-01-26 23:10:15 -05001592 creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
1593 writel(creg_val, phba->HCregaddr);
1594 readl(phba->HCregaddr); /* flush */
1595 }
1596
1597 rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0);
1598
James Smartb5a9b2d2013-09-06 12:19:45 -04001599 if (rc == IOCB_SUCCESS) {
1600 spin_lock_irqsave(&phba->hbalock, flags);
1601 /* make sure the I/O had not been completed/released */
1602 if (ctiocb->iocb_flag & LPFC_IO_LIBDFC) {
1603 /* open up abort window to timeout handler */
James Smart1b8d11a2013-09-06 12:20:51 -04001604 ctiocb->iocb_flag |= LPFC_IO_CMD_OUTSTANDING;
James Smartb5a9b2d2013-09-06 12:19:45 -04001605 }
1606 spin_unlock_irqrestore(&phba->hbalock, flags);
James Smart3b5dd522010-01-26 23:10:15 -05001607 return 0; /* done for now */
James Smartb5a9b2d2013-09-06 12:19:45 -04001608 }
1609
1610 /* iocb failed so cleanup */
1611 job->dd_data = NULL;
James Smart3b5dd522010-01-26 23:10:15 -05001612
1613issue_ct_rsp_exit:
1614 lpfc_sli_release_iocbq(phba, ctiocb);
1615no_ctiocb:
1616 kfree(dd_data);
1617no_dd_data:
1618 return rc;
1619}
1620
1621/**
1622 * lpfc_bsg_send_mgmt_rsp - process a SEND_MGMT_RESP bsg vendor command
1623 * @job: SEND_MGMT_RESP fc_bsg_job
1624 **/
1625static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01001626lpfc_bsg_send_mgmt_rsp(struct bsg_job *job)
James Smart3b5dd522010-01-26 23:10:15 -05001627{
Johannes Thumshirncd21c602016-11-17 10:31:14 +01001628 struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
James Smart3b5dd522010-01-26 23:10:15 -05001629 struct lpfc_hba *phba = vport->phba;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001630 struct fc_bsg_request *bsg_request = job->request;
1631 struct fc_bsg_reply *bsg_reply = job->reply;
James Smart3b5dd522010-01-26 23:10:15 -05001632 struct send_mgmt_resp *mgmt_resp = (struct send_mgmt_resp *)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001633 bsg_request->rqst_data.h_vendor.vendor_cmd;
James Smart3b5dd522010-01-26 23:10:15 -05001634 struct ulp_bde64 *bpl;
James Smarta33c4f72013-03-01 16:36:00 -05001635 struct lpfc_dmabuf *bmp = NULL, *cmp = NULL;
1636 int bpl_entries;
James Smart3b5dd522010-01-26 23:10:15 -05001637 uint32_t tag = mgmt_resp->tag;
1638 unsigned long reqbfrcnt =
1639 (unsigned long)job->request_payload.payload_len;
1640 int rc = 0;
1641
1642 /* in case no data is transferred */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001643 bsg_reply->reply_payload_rcv_len = 0;
James Smart3b5dd522010-01-26 23:10:15 -05001644
1645 if (!reqbfrcnt || (reqbfrcnt > (80 * BUF_SZ_4K))) {
1646 rc = -ERANGE;
1647 goto send_mgmt_rsp_exit;
1648 }
1649
1650 bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
1651 if (!bmp) {
1652 rc = -ENOMEM;
1653 goto send_mgmt_rsp_exit;
1654 }
1655
1656 bmp->virt = lpfc_mbuf_alloc(phba, 0, &bmp->phys);
1657 if (!bmp->virt) {
1658 rc = -ENOMEM;
1659 goto send_mgmt_rsp_free_bmp;
1660 }
1661
1662 INIT_LIST_HEAD(&bmp->list);
1663 bpl = (struct ulp_bde64 *) bmp->virt;
James Smarta33c4f72013-03-01 16:36:00 -05001664 bpl_entries = (LPFC_BPL_SIZE/sizeof(struct ulp_bde64));
1665 cmp = lpfc_alloc_bsg_buffers(phba, job->request_payload.payload_len,
1666 1, bpl, &bpl_entries);
1667 if (!cmp) {
1668 rc = -ENOMEM;
1669 goto send_mgmt_rsp_free_bmp;
James Smart3b5dd522010-01-26 23:10:15 -05001670 }
James Smarta33c4f72013-03-01 16:36:00 -05001671 lpfc_bsg_copy_data(cmp, &job->request_payload,
1672 job->request_payload.payload_len, 1);
James Smart3b5dd522010-01-26 23:10:15 -05001673
James Smarta33c4f72013-03-01 16:36:00 -05001674 rc = lpfc_issue_ct_rsp(phba, job, tag, cmp, bmp, bpl_entries);
James Smart3b5dd522010-01-26 23:10:15 -05001675
1676 if (rc == IOCB_SUCCESS)
1677 return 0; /* done for now */
1678
James Smart3b5dd522010-01-26 23:10:15 -05001679 rc = -EACCES;
James Smarta33c4f72013-03-01 16:36:00 -05001680
1681 lpfc_free_bsg_buffers(phba, cmp);
James Smart3b5dd522010-01-26 23:10:15 -05001682
1683send_mgmt_rsp_free_bmp:
James Smarta33c4f72013-03-01 16:36:00 -05001684 if (bmp->virt)
1685 lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
James Smart3b5dd522010-01-26 23:10:15 -05001686 kfree(bmp);
1687send_mgmt_rsp_exit:
1688 /* make error code available to userspace */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001689 bsg_reply->result = rc;
James Smart3b5dd522010-01-26 23:10:15 -05001690 job->dd_data = NULL;
1691 return rc;
1692}
1693
1694/**
James Smart7ad20aa2011-05-24 11:44:28 -04001695 * lpfc_bsg_diag_mode_enter - process preparing into device diag loopback mode
1696 * @phba: Pointer to HBA context object.
James Smart3b5dd522010-01-26 23:10:15 -05001697 *
James Smart7ad20aa2011-05-24 11:44:28 -04001698 * This function is responsible for preparing driver for diag loopback
1699 * on device.
1700 */
1701static int
James Smart88a2cfb2011-07-22 18:36:33 -04001702lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba)
James Smart7ad20aa2011-05-24 11:44:28 -04001703{
1704 struct lpfc_vport **vports;
1705 struct Scsi_Host *shost;
1706 struct lpfc_sli *psli;
1707 struct lpfc_sli_ring *pring;
1708 int i = 0;
1709
1710 psli = &phba->sli;
1711 if (!psli)
1712 return -ENODEV;
1713
1714 pring = &psli->ring[LPFC_FCP_RING];
1715 if (!pring)
1716 return -ENODEV;
1717
1718 if ((phba->link_state == LPFC_HBA_ERROR) ||
1719 (psli->sli_flag & LPFC_BLOCK_MGMT_IO) ||
1720 (!(psli->sli_flag & LPFC_SLI_ACTIVE)))
1721 return -EACCES;
1722
1723 vports = lpfc_create_vport_work_array(phba);
1724 if (vports) {
1725 for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
1726 shost = lpfc_shost_from_vport(vports[i]);
1727 scsi_block_requests(shost);
1728 }
1729 lpfc_destroy_vport_work_array(phba, vports);
1730 } else {
1731 shost = lpfc_shost_from_vport(phba->pport);
1732 scsi_block_requests(shost);
1733 }
1734
James Smart0e9bb8d2013-03-01 16:35:12 -05001735 while (!list_empty(&pring->txcmplq)) {
James Smart7ad20aa2011-05-24 11:44:28 -04001736 if (i++ > 500) /* wait up to 5 seconds */
1737 break;
1738 msleep(10);
1739 }
1740 return 0;
1741}
1742
1743/**
1744 * lpfc_bsg_diag_mode_exit - exit process from device diag loopback mode
1745 * @phba: Pointer to HBA context object.
James Smart7ad20aa2011-05-24 11:44:28 -04001746 *
1747 * This function is responsible for driver exit processing of setting up
1748 * diag loopback mode on device.
1749 */
1750static void
1751lpfc_bsg_diag_mode_exit(struct lpfc_hba *phba)
1752{
1753 struct Scsi_Host *shost;
1754 struct lpfc_vport **vports;
1755 int i;
1756
1757 vports = lpfc_create_vport_work_array(phba);
1758 if (vports) {
1759 for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
1760 shost = lpfc_shost_from_vport(vports[i]);
1761 scsi_unblock_requests(shost);
1762 }
1763 lpfc_destroy_vport_work_array(phba, vports);
1764 } else {
1765 shost = lpfc_shost_from_vport(phba->pport);
1766 scsi_unblock_requests(shost);
1767 }
1768 return;
1769}
1770
1771/**
1772 * lpfc_sli3_bsg_diag_loopback_mode - process an sli3 bsg vendor command
1773 * @phba: Pointer to HBA context object.
1774 * @job: LPFC_BSG_VENDOR_DIAG_MODE
1775 *
1776 * This function is responsible for placing an sli3 port into diagnostic
1777 * loopback mode in order to perform a diagnostic loopback test.
James Smart3b5dd522010-01-26 23:10:15 -05001778 * All new scsi requests are blocked, a small delay is used to allow the
1779 * scsi requests to complete then the link is brought down. If the link is
1780 * is placed in loopback mode then scsi requests are again allowed
1781 * so the scsi mid-layer doesn't give up on the port.
1782 * All of this is done in-line.
1783 */
1784static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01001785lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct bsg_job *job)
James Smart3b5dd522010-01-26 23:10:15 -05001786{
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001787 struct fc_bsg_request *bsg_request = job->request;
1788 struct fc_bsg_reply *bsg_reply = job->reply;
James Smart3b5dd522010-01-26 23:10:15 -05001789 struct diag_mode_set *loopback_mode;
James Smart3b5dd522010-01-26 23:10:15 -05001790 uint32_t link_flags;
1791 uint32_t timeout;
James Smart1b511972011-12-13 13:23:09 -05001792 LPFC_MBOXQ_t *pmboxq = NULL;
James Smartb76f2dc2011-07-22 18:37:42 -04001793 int mbxstatus = MBX_SUCCESS;
James Smart3b5dd522010-01-26 23:10:15 -05001794 int i = 0;
1795 int rc = 0;
1796
1797 /* no data to return just the return code */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001798 bsg_reply->reply_payload_rcv_len = 0;
James Smart3b5dd522010-01-26 23:10:15 -05001799
James Smart7ad20aa2011-05-24 11:44:28 -04001800 if (job->request_len < sizeof(struct fc_bsg_request) +
1801 sizeof(struct diag_mode_set)) {
James Smart3b5dd522010-01-26 23:10:15 -05001802 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
James Smart7ad20aa2011-05-24 11:44:28 -04001803 "2738 Received DIAG MODE request size:%d "
1804 "below the minimum size:%d\n",
1805 job->request_len,
1806 (int)(sizeof(struct fc_bsg_request) +
1807 sizeof(struct diag_mode_set)));
James Smart3b5dd522010-01-26 23:10:15 -05001808 rc = -EINVAL;
1809 goto job_error;
1810 }
1811
James Smart88a2cfb2011-07-22 18:36:33 -04001812 rc = lpfc_bsg_diag_mode_enter(phba);
James Smart7ad20aa2011-05-24 11:44:28 -04001813 if (rc)
1814 goto job_error;
1815
1816 /* bring the link to diagnostic mode */
James Smart3b5dd522010-01-26 23:10:15 -05001817 loopback_mode = (struct diag_mode_set *)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001818 bsg_request->rqst_data.h_vendor.vendor_cmd;
James Smart3b5dd522010-01-26 23:10:15 -05001819 link_flags = loopback_mode->type;
James Smart515e0aa2010-09-29 11:19:00 -04001820 timeout = loopback_mode->timeout * 100;
James Smart3b5dd522010-01-26 23:10:15 -05001821
James Smart3b5dd522010-01-26 23:10:15 -05001822 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
1823 if (!pmboxq) {
1824 rc = -ENOMEM;
James Smart7ad20aa2011-05-24 11:44:28 -04001825 goto loopback_mode_exit;
James Smart3b5dd522010-01-26 23:10:15 -05001826 }
James Smart3b5dd522010-01-26 23:10:15 -05001827 memset((void *)pmboxq, 0, sizeof(LPFC_MBOXQ_t));
1828 pmboxq->u.mb.mbxCommand = MBX_DOWN_LINK;
1829 pmboxq->u.mb.mbxOwner = OWN_HOST;
1830
1831 mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO);
1832
1833 if ((mbxstatus == MBX_SUCCESS) && (pmboxq->u.mb.mbxStatus == 0)) {
1834 /* wait for link down before proceeding */
1835 i = 0;
1836 while (phba->link_state != LPFC_LINK_DOWN) {
1837 if (i++ > timeout) {
1838 rc = -ETIMEDOUT;
1839 goto loopback_mode_exit;
1840 }
James Smart3b5dd522010-01-26 23:10:15 -05001841 msleep(10);
1842 }
1843
1844 memset((void *)pmboxq, 0, sizeof(LPFC_MBOXQ_t));
1845 if (link_flags == INTERNAL_LOOP_BACK)
1846 pmboxq->u.mb.un.varInitLnk.link_flags = FLAGS_LOCAL_LB;
1847 else
1848 pmboxq->u.mb.un.varInitLnk.link_flags =
1849 FLAGS_TOPOLOGY_MODE_LOOP;
1850
1851 pmboxq->u.mb.mbxCommand = MBX_INIT_LINK;
1852 pmboxq->u.mb.mbxOwner = OWN_HOST;
1853
1854 mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq,
1855 LPFC_MBOX_TMO);
1856
1857 if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus))
1858 rc = -ENODEV;
1859 else {
James Smart1b511972011-12-13 13:23:09 -05001860 spin_lock_irq(&phba->hbalock);
James Smart3b5dd522010-01-26 23:10:15 -05001861 phba->link_flag |= LS_LOOPBACK_MODE;
James Smart1b511972011-12-13 13:23:09 -05001862 spin_unlock_irq(&phba->hbalock);
James Smart3b5dd522010-01-26 23:10:15 -05001863 /* wait for the link attention interrupt */
1864 msleep(100);
1865
1866 i = 0;
1867 while (phba->link_state != LPFC_HBA_READY) {
1868 if (i++ > timeout) {
1869 rc = -ETIMEDOUT;
1870 break;
1871 }
1872
1873 msleep(10);
1874 }
1875 }
1876
1877 } else
1878 rc = -ENODEV;
1879
1880loopback_mode_exit:
James Smart7ad20aa2011-05-24 11:44:28 -04001881 lpfc_bsg_diag_mode_exit(phba);
James Smart3b5dd522010-01-26 23:10:15 -05001882
1883 /*
1884 * Let SLI layer release mboxq if mbox command completed after timeout.
1885 */
James Smart1b511972011-12-13 13:23:09 -05001886 if (pmboxq && mbxstatus != MBX_TIMEOUT)
James Smart3b5dd522010-01-26 23:10:15 -05001887 mempool_free(pmboxq, phba->mbox_mem_pool);
1888
1889job_error:
1890 /* make error code available to userspace */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001891 bsg_reply->result = rc;
James Smart3b5dd522010-01-26 23:10:15 -05001892 /* complete the job back to userspace if no error */
1893 if (rc == 0)
Johannes Thumshirn06548162016-11-17 10:31:22 +01001894 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01001895 bsg_reply->reply_payload_rcv_len);
James Smart3b5dd522010-01-26 23:10:15 -05001896 return rc;
1897}
1898
1899/**
James Smart7ad20aa2011-05-24 11:44:28 -04001900 * lpfc_sli4_bsg_set_link_diag_state - set sli4 link diag state
1901 * @phba: Pointer to HBA context object.
1902 * @diag: Flag for set link to diag or nomral operation state.
1903 *
1904 * This function is responsible for issuing a sli4 mailbox command for setting
1905 * link to either diag state or normal operation state.
1906 */
1907static int
1908lpfc_sli4_bsg_set_link_diag_state(struct lpfc_hba *phba, uint32_t diag)
1909{
1910 LPFC_MBOXQ_t *pmboxq;
1911 struct lpfc_mbx_set_link_diag_state *link_diag_state;
1912 uint32_t req_len, alloc_len;
1913 int mbxstatus = MBX_SUCCESS, rc;
1914
1915 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
1916 if (!pmboxq)
1917 return -ENOMEM;
1918
1919 req_len = (sizeof(struct lpfc_mbx_set_link_diag_state) -
1920 sizeof(struct lpfc_sli4_cfg_mhdr));
1921 alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
1922 LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE,
1923 req_len, LPFC_SLI4_MBX_EMBED);
1924 if (alloc_len != req_len) {
1925 rc = -ENOMEM;
1926 goto link_diag_state_set_out;
1927 }
James Smart1b511972011-12-13 13:23:09 -05001928 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
1929 "3128 Set link to diagnostic state:x%x (x%x/x%x)\n",
1930 diag, phba->sli4_hba.lnk_info.lnk_tp,
1931 phba->sli4_hba.lnk_info.lnk_no);
1932
James Smart7ad20aa2011-05-24 11:44:28 -04001933 link_diag_state = &pmboxq->u.mqe.un.link_diag_state;
James Smart97315922012-08-03 12:32:52 -04001934 bf_set(lpfc_mbx_set_diag_state_diag_bit_valid, &link_diag_state->u.req,
1935 LPFC_DIAG_STATE_DIAG_BIT_VALID_CHANGE);
James Smart7ad20aa2011-05-24 11:44:28 -04001936 bf_set(lpfc_mbx_set_diag_state_link_num, &link_diag_state->u.req,
James Smart1b511972011-12-13 13:23:09 -05001937 phba->sli4_hba.lnk_info.lnk_no);
James Smart7ad20aa2011-05-24 11:44:28 -04001938 bf_set(lpfc_mbx_set_diag_state_link_type, &link_diag_state->u.req,
James Smart1b511972011-12-13 13:23:09 -05001939 phba->sli4_hba.lnk_info.lnk_tp);
James Smart7ad20aa2011-05-24 11:44:28 -04001940 if (diag)
1941 bf_set(lpfc_mbx_set_diag_state_diag,
1942 &link_diag_state->u.req, 1);
1943 else
1944 bf_set(lpfc_mbx_set_diag_state_diag,
1945 &link_diag_state->u.req, 0);
1946
1947 mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO);
1948
1949 if ((mbxstatus == MBX_SUCCESS) && (pmboxq->u.mb.mbxStatus == 0))
1950 rc = 0;
1951 else
1952 rc = -ENODEV;
1953
1954link_diag_state_set_out:
1955 if (pmboxq && (mbxstatus != MBX_TIMEOUT))
1956 mempool_free(pmboxq, phba->mbox_mem_pool);
1957
1958 return rc;
1959}
1960
1961/**
James Smart1b511972011-12-13 13:23:09 -05001962 * lpfc_sli4_bsg_set_internal_loopback - set sli4 internal loopback diagnostic
1963 * @phba: Pointer to HBA context object.
1964 *
1965 * This function is responsible for issuing a sli4 mailbox command for setting
1966 * up internal loopback diagnostic.
1967 */
1968static int
1969lpfc_sli4_bsg_set_internal_loopback(struct lpfc_hba *phba)
1970{
1971 LPFC_MBOXQ_t *pmboxq;
1972 uint32_t req_len, alloc_len;
1973 struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback;
1974 int mbxstatus = MBX_SUCCESS, rc = 0;
1975
1976 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
1977 if (!pmboxq)
1978 return -ENOMEM;
1979 req_len = (sizeof(struct lpfc_mbx_set_link_diag_loopback) -
1980 sizeof(struct lpfc_sli4_cfg_mhdr));
1981 alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
1982 LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK,
1983 req_len, LPFC_SLI4_MBX_EMBED);
1984 if (alloc_len != req_len) {
1985 mempool_free(pmboxq, phba->mbox_mem_pool);
1986 return -ENOMEM;
1987 }
1988 link_diag_loopback = &pmboxq->u.mqe.un.link_diag_loopback;
1989 bf_set(lpfc_mbx_set_diag_state_link_num,
1990 &link_diag_loopback->u.req, phba->sli4_hba.lnk_info.lnk_no);
1991 bf_set(lpfc_mbx_set_diag_state_link_type,
1992 &link_diag_loopback->u.req, phba->sli4_hba.lnk_info.lnk_tp);
1993 bf_set(lpfc_mbx_set_diag_lpbk_type, &link_diag_loopback->u.req,
James Smart3ef6d242012-01-18 16:23:48 -05001994 LPFC_DIAG_LOOPBACK_TYPE_INTERNAL);
James Smart1b511972011-12-13 13:23:09 -05001995
1996 mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO);
1997 if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus)) {
1998 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
1999 "3127 Failed setup loopback mode mailbox "
2000 "command, rc:x%x, status:x%x\n", mbxstatus,
2001 pmboxq->u.mb.mbxStatus);
2002 rc = -ENODEV;
2003 }
2004 if (pmboxq && (mbxstatus != MBX_TIMEOUT))
2005 mempool_free(pmboxq, phba->mbox_mem_pool);
2006 return rc;
2007}
2008
2009/**
2010 * lpfc_sli4_diag_fcport_reg_setup - setup port registrations for diagnostic
2011 * @phba: Pointer to HBA context object.
2012 *
2013 * This function set up SLI4 FC port registrations for diagnostic run, which
2014 * includes all the rpis, vfi, and also vpi.
2015 */
2016static int
2017lpfc_sli4_diag_fcport_reg_setup(struct lpfc_hba *phba)
2018{
2019 int rc;
2020
2021 if (phba->pport->fc_flag & FC_VFI_REGISTERED) {
2022 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
2023 "3136 Port still had vfi registered: "
2024 "mydid:x%x, fcfi:%d, vfi:%d, vpi:%d\n",
2025 phba->pport->fc_myDID, phba->fcf.fcfi,
2026 phba->sli4_hba.vfi_ids[phba->pport->vfi],
2027 phba->vpi_ids[phba->pport->vpi]);
2028 return -EINVAL;
2029 }
2030 rc = lpfc_issue_reg_vfi(phba->pport);
2031 return rc;
2032}
2033
2034/**
James Smart7ad20aa2011-05-24 11:44:28 -04002035 * lpfc_sli4_bsg_diag_loopback_mode - process an sli4 bsg vendor command
2036 * @phba: Pointer to HBA context object.
2037 * @job: LPFC_BSG_VENDOR_DIAG_MODE
2038 *
2039 * This function is responsible for placing an sli4 port into diagnostic
2040 * loopback mode in order to perform a diagnostic loopback test.
2041 */
2042static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01002043lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct bsg_job *job)
James Smart7ad20aa2011-05-24 11:44:28 -04002044{
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002045 struct fc_bsg_request *bsg_request = job->request;
2046 struct fc_bsg_reply *bsg_reply = job->reply;
James Smart7ad20aa2011-05-24 11:44:28 -04002047 struct diag_mode_set *loopback_mode;
James Smart1b511972011-12-13 13:23:09 -05002048 uint32_t link_flags, timeout;
2049 int i, rc = 0;
James Smart7ad20aa2011-05-24 11:44:28 -04002050
2051 /* no data to return just the return code */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002052 bsg_reply->reply_payload_rcv_len = 0;
James Smart7ad20aa2011-05-24 11:44:28 -04002053
2054 if (job->request_len < sizeof(struct fc_bsg_request) +
2055 sizeof(struct diag_mode_set)) {
2056 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
2057 "3011 Received DIAG MODE request size:%d "
2058 "below the minimum size:%d\n",
2059 job->request_len,
2060 (int)(sizeof(struct fc_bsg_request) +
2061 sizeof(struct diag_mode_set)));
2062 rc = -EINVAL;
2063 goto job_error;
2064 }
2065
James Smart88a2cfb2011-07-22 18:36:33 -04002066 rc = lpfc_bsg_diag_mode_enter(phba);
James Smart7ad20aa2011-05-24 11:44:28 -04002067 if (rc)
2068 goto job_error;
2069
James Smart1b511972011-12-13 13:23:09 -05002070 /* indicate we are in loobpack diagnostic mode */
2071 spin_lock_irq(&phba->hbalock);
2072 phba->link_flag |= LS_LOOPBACK_MODE;
2073 spin_unlock_irq(&phba->hbalock);
2074
2075 /* reset port to start frome scratch */
2076 rc = lpfc_selective_reset(phba);
2077 if (rc)
2078 goto job_error;
2079
James Smart7ad20aa2011-05-24 11:44:28 -04002080 /* bring the link to diagnostic mode */
James Smart1b511972011-12-13 13:23:09 -05002081 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
2082 "3129 Bring link to diagnostic state.\n");
James Smart7ad20aa2011-05-24 11:44:28 -04002083 loopback_mode = (struct diag_mode_set *)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002084 bsg_request->rqst_data.h_vendor.vendor_cmd;
James Smart7ad20aa2011-05-24 11:44:28 -04002085 link_flags = loopback_mode->type;
2086 timeout = loopback_mode->timeout * 100;
2087
2088 rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1);
James Smart1b511972011-12-13 13:23:09 -05002089 if (rc) {
2090 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
2091 "3130 Failed to bring link to diagnostic "
2092 "state, rc:x%x\n", rc);
James Smart7ad20aa2011-05-24 11:44:28 -04002093 goto loopback_mode_exit;
James Smart1b511972011-12-13 13:23:09 -05002094 }
James Smart7ad20aa2011-05-24 11:44:28 -04002095
2096 /* wait for link down before proceeding */
2097 i = 0;
2098 while (phba->link_state != LPFC_LINK_DOWN) {
2099 if (i++ > timeout) {
2100 rc = -ETIMEDOUT;
James Smart1b511972011-12-13 13:23:09 -05002101 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
2102 "3131 Timeout waiting for link to "
2103 "diagnostic mode, timeout:%d ms\n",
2104 timeout * 10);
James Smart7ad20aa2011-05-24 11:44:28 -04002105 goto loopback_mode_exit;
2106 }
2107 msleep(10);
2108 }
James Smart7ad20aa2011-05-24 11:44:28 -04002109
James Smart1b511972011-12-13 13:23:09 -05002110 /* set up loopback mode */
2111 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
2112 "3132 Set up loopback mode:x%x\n", link_flags);
2113
2114 if (link_flags == INTERNAL_LOOP_BACK)
2115 rc = lpfc_sli4_bsg_set_internal_loopback(phba);
2116 else if (link_flags == EXTERNAL_LOOP_BACK)
2117 rc = lpfc_hba_init_link_fc_topology(phba,
2118 FLAGS_TOPOLOGY_MODE_PT_PT,
2119 MBX_NOWAIT);
James Smart7ad20aa2011-05-24 11:44:28 -04002120 else {
James Smart1b511972011-12-13 13:23:09 -05002121 rc = -EINVAL;
2122 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
2123 "3141 Loopback mode:x%x not supported\n",
2124 link_flags);
2125 goto loopback_mode_exit;
2126 }
2127
2128 if (!rc) {
James Smart7ad20aa2011-05-24 11:44:28 -04002129 /* wait for the link attention interrupt */
2130 msleep(100);
2131 i = 0;
James Smart1b511972011-12-13 13:23:09 -05002132 while (phba->link_state < LPFC_LINK_UP) {
2133 if (i++ > timeout) {
2134 rc = -ETIMEDOUT;
2135 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
2136 "3137 Timeout waiting for link up "
2137 "in loopback mode, timeout:%d ms\n",
2138 timeout * 10);
2139 break;
2140 }
2141 msleep(10);
2142 }
2143 }
2144
2145 /* port resource registration setup for loopback diagnostic */
2146 if (!rc) {
2147 /* set up a none zero myDID for loopback test */
2148 phba->pport->fc_myDID = 1;
2149 rc = lpfc_sli4_diag_fcport_reg_setup(phba);
2150 } else
2151 goto loopback_mode_exit;
2152
2153 if (!rc) {
2154 /* wait for the port ready */
2155 msleep(100);
2156 i = 0;
James Smart7ad20aa2011-05-24 11:44:28 -04002157 while (phba->link_state != LPFC_HBA_READY) {
2158 if (i++ > timeout) {
2159 rc = -ETIMEDOUT;
James Smart1b511972011-12-13 13:23:09 -05002160 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
2161 "3133 Timeout waiting for port "
2162 "loopback mode ready, timeout:%d ms\n",
2163 timeout * 10);
James Smart7ad20aa2011-05-24 11:44:28 -04002164 break;
2165 }
2166 msleep(10);
2167 }
2168 }
2169
2170loopback_mode_exit:
James Smart1b511972011-12-13 13:23:09 -05002171 /* clear loopback diagnostic mode */
2172 if (rc) {
2173 spin_lock_irq(&phba->hbalock);
2174 phba->link_flag &= ~LS_LOOPBACK_MODE;
2175 spin_unlock_irq(&phba->hbalock);
2176 }
James Smart7ad20aa2011-05-24 11:44:28 -04002177 lpfc_bsg_diag_mode_exit(phba);
2178
James Smart7ad20aa2011-05-24 11:44:28 -04002179job_error:
2180 /* make error code available to userspace */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002181 bsg_reply->result = rc;
James Smart7ad20aa2011-05-24 11:44:28 -04002182 /* complete the job back to userspace if no error */
2183 if (rc == 0)
Johannes Thumshirn06548162016-11-17 10:31:22 +01002184 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01002185 bsg_reply->reply_payload_rcv_len);
James Smart7ad20aa2011-05-24 11:44:28 -04002186 return rc;
2187}
2188
2189/**
2190 * lpfc_bsg_diag_loopback_mode - bsg vendor command for diag loopback mode
2191 * @job: LPFC_BSG_VENDOR_DIAG_MODE
2192 *
2193 * This function is responsible for responding to check and dispatch bsg diag
2194 * command from the user to proper driver action routines.
2195 */
2196static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01002197lpfc_bsg_diag_loopback_mode(struct bsg_job *job)
James Smart7ad20aa2011-05-24 11:44:28 -04002198{
2199 struct Scsi_Host *shost;
2200 struct lpfc_vport *vport;
2201 struct lpfc_hba *phba;
2202 int rc;
2203
Johannes Thumshirncd21c602016-11-17 10:31:14 +01002204 shost = fc_bsg_to_shost(job);
James Smart7ad20aa2011-05-24 11:44:28 -04002205 if (!shost)
2206 return -ENODEV;
Johannes Thumshirncd21c602016-11-17 10:31:14 +01002207 vport = shost_priv(shost);
James Smart7ad20aa2011-05-24 11:44:28 -04002208 if (!vport)
2209 return -ENODEV;
2210 phba = vport->phba;
2211 if (!phba)
2212 return -ENODEV;
2213
2214 if (phba->sli_rev < LPFC_SLI_REV4)
2215 rc = lpfc_sli3_bsg_diag_loopback_mode(phba, job);
2216 else if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
2217 LPFC_SLI_INTF_IF_TYPE_2)
2218 rc = lpfc_sli4_bsg_diag_loopback_mode(phba, job);
2219 else
2220 rc = -ENODEV;
2221
2222 return rc;
James Smart7ad20aa2011-05-24 11:44:28 -04002223}
2224
2225/**
2226 * lpfc_sli4_bsg_diag_mode_end - sli4 bsg vendor command for ending diag mode
2227 * @job: LPFC_BSG_VENDOR_DIAG_MODE_END
2228 *
2229 * This function is responsible for responding to check and dispatch bsg diag
2230 * command from the user to proper driver action routines.
2231 */
2232static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01002233lpfc_sli4_bsg_diag_mode_end(struct bsg_job *job)
James Smart7ad20aa2011-05-24 11:44:28 -04002234{
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002235 struct fc_bsg_request *bsg_request = job->request;
2236 struct fc_bsg_reply *bsg_reply = job->reply;
James Smart7ad20aa2011-05-24 11:44:28 -04002237 struct Scsi_Host *shost;
2238 struct lpfc_vport *vport;
2239 struct lpfc_hba *phba;
James Smart1b511972011-12-13 13:23:09 -05002240 struct diag_mode_set *loopback_mode_end_cmd;
2241 uint32_t timeout;
2242 int rc, i;
James Smart7ad20aa2011-05-24 11:44:28 -04002243
Johannes Thumshirncd21c602016-11-17 10:31:14 +01002244 shost = fc_bsg_to_shost(job);
James Smart7ad20aa2011-05-24 11:44:28 -04002245 if (!shost)
2246 return -ENODEV;
Johannes Thumshirncd21c602016-11-17 10:31:14 +01002247 vport = shost_priv(shost);
James Smart7ad20aa2011-05-24 11:44:28 -04002248 if (!vport)
2249 return -ENODEV;
2250 phba = vport->phba;
2251 if (!phba)
2252 return -ENODEV;
2253
2254 if (phba->sli_rev < LPFC_SLI_REV4)
2255 return -ENODEV;
2256 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
2257 LPFC_SLI_INTF_IF_TYPE_2)
2258 return -ENODEV;
2259
James Smart1b511972011-12-13 13:23:09 -05002260 /* clear loopback diagnostic mode */
2261 spin_lock_irq(&phba->hbalock);
2262 phba->link_flag &= ~LS_LOOPBACK_MODE;
2263 spin_unlock_irq(&phba->hbalock);
2264 loopback_mode_end_cmd = (struct diag_mode_set *)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002265 bsg_request->rqst_data.h_vendor.vendor_cmd;
James Smart1b511972011-12-13 13:23:09 -05002266 timeout = loopback_mode_end_cmd->timeout * 100;
2267
James Smart7ad20aa2011-05-24 11:44:28 -04002268 rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0);
James Smart1b511972011-12-13 13:23:09 -05002269 if (rc) {
2270 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
2271 "3139 Failed to bring link to diagnostic "
2272 "state, rc:x%x\n", rc);
2273 goto loopback_mode_end_exit;
2274 }
James Smart7ad20aa2011-05-24 11:44:28 -04002275
James Smart1b511972011-12-13 13:23:09 -05002276 /* wait for link down before proceeding */
2277 i = 0;
2278 while (phba->link_state != LPFC_LINK_DOWN) {
2279 if (i++ > timeout) {
James Smart1b511972011-12-13 13:23:09 -05002280 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
2281 "3140 Timeout waiting for link to "
2282 "diagnostic mode_end, timeout:%d ms\n",
2283 timeout * 10);
2284 /* there is nothing much we can do here */
2285 break;
2286 }
2287 msleep(10);
2288 }
James Smart7ad20aa2011-05-24 11:44:28 -04002289
James Smart1b511972011-12-13 13:23:09 -05002290 /* reset port resource registrations */
2291 rc = lpfc_selective_reset(phba);
2292 phba->pport->fc_myDID = 0;
2293
2294loopback_mode_end_exit:
2295 /* make return code available to userspace */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002296 bsg_reply->result = rc;
James Smart1b511972011-12-13 13:23:09 -05002297 /* complete the job back to userspace if no error */
2298 if (rc == 0)
Johannes Thumshirn06548162016-11-17 10:31:22 +01002299 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01002300 bsg_reply->reply_payload_rcv_len);
James Smart7ad20aa2011-05-24 11:44:28 -04002301 return rc;
2302}
2303
2304/**
2305 * lpfc_sli4_bsg_link_diag_test - sli4 bsg vendor command for diag link test
2306 * @job: LPFC_BSG_VENDOR_DIAG_LINK_TEST
2307 *
2308 * This function is to perform SLI4 diag link test request from the user
2309 * applicaiton.
2310 */
2311static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01002312lpfc_sli4_bsg_link_diag_test(struct bsg_job *job)
James Smart7ad20aa2011-05-24 11:44:28 -04002313{
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002314 struct fc_bsg_request *bsg_request = job->request;
2315 struct fc_bsg_reply *bsg_reply = job->reply;
James Smart7ad20aa2011-05-24 11:44:28 -04002316 struct Scsi_Host *shost;
2317 struct lpfc_vport *vport;
2318 struct lpfc_hba *phba;
2319 LPFC_MBOXQ_t *pmboxq;
2320 struct sli4_link_diag *link_diag_test_cmd;
2321 uint32_t req_len, alloc_len;
James Smart7ad20aa2011-05-24 11:44:28 -04002322 struct lpfc_mbx_run_link_diag_test *run_link_diag_test;
2323 union lpfc_sli4_cfg_shdr *shdr;
2324 uint32_t shdr_status, shdr_add_status;
2325 struct diag_status *diag_status_reply;
2326 int mbxstatus, rc = 0;
2327
Johannes Thumshirncd21c602016-11-17 10:31:14 +01002328 shost = fc_bsg_to_shost(job);
James Smart7ad20aa2011-05-24 11:44:28 -04002329 if (!shost) {
2330 rc = -ENODEV;
2331 goto job_error;
2332 }
Johannes Thumshirncd21c602016-11-17 10:31:14 +01002333 vport = shost_priv(shost);
James Smart7ad20aa2011-05-24 11:44:28 -04002334 if (!vport) {
2335 rc = -ENODEV;
2336 goto job_error;
2337 }
2338 phba = vport->phba;
2339 if (!phba) {
2340 rc = -ENODEV;
2341 goto job_error;
2342 }
2343
2344 if (phba->sli_rev < LPFC_SLI_REV4) {
2345 rc = -ENODEV;
2346 goto job_error;
2347 }
2348 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
2349 LPFC_SLI_INTF_IF_TYPE_2) {
2350 rc = -ENODEV;
2351 goto job_error;
2352 }
2353
2354 if (job->request_len < sizeof(struct fc_bsg_request) +
2355 sizeof(struct sli4_link_diag)) {
2356 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
2357 "3013 Received LINK DIAG TEST request "
2358 " size:%d below the minimum size:%d\n",
2359 job->request_len,
2360 (int)(sizeof(struct fc_bsg_request) +
2361 sizeof(struct sli4_link_diag)));
2362 rc = -EINVAL;
2363 goto job_error;
2364 }
2365
James Smart88a2cfb2011-07-22 18:36:33 -04002366 rc = lpfc_bsg_diag_mode_enter(phba);
James Smart7ad20aa2011-05-24 11:44:28 -04002367 if (rc)
2368 goto job_error;
2369
2370 link_diag_test_cmd = (struct sli4_link_diag *)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002371 bsg_request->rqst_data.h_vendor.vendor_cmd;
James Smart7ad20aa2011-05-24 11:44:28 -04002372
2373 rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1);
2374
2375 if (rc)
2376 goto job_error;
2377
2378 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
2379 if (!pmboxq) {
2380 rc = -ENOMEM;
2381 goto link_diag_test_exit;
2382 }
2383
2384 req_len = (sizeof(struct lpfc_mbx_set_link_diag_state) -
2385 sizeof(struct lpfc_sli4_cfg_mhdr));
2386 alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
2387 LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE,
2388 req_len, LPFC_SLI4_MBX_EMBED);
2389 if (alloc_len != req_len) {
2390 rc = -ENOMEM;
2391 goto link_diag_test_exit;
2392 }
2393 run_link_diag_test = &pmboxq->u.mqe.un.link_diag_test;
2394 bf_set(lpfc_mbx_run_diag_test_link_num, &run_link_diag_test->u.req,
James Smart1b511972011-12-13 13:23:09 -05002395 phba->sli4_hba.lnk_info.lnk_no);
James Smart7ad20aa2011-05-24 11:44:28 -04002396 bf_set(lpfc_mbx_run_diag_test_link_type, &run_link_diag_test->u.req,
James Smart1b511972011-12-13 13:23:09 -05002397 phba->sli4_hba.lnk_info.lnk_tp);
James Smart7ad20aa2011-05-24 11:44:28 -04002398 bf_set(lpfc_mbx_run_diag_test_test_id, &run_link_diag_test->u.req,
2399 link_diag_test_cmd->test_id);
2400 bf_set(lpfc_mbx_run_diag_test_loops, &run_link_diag_test->u.req,
2401 link_diag_test_cmd->loops);
2402 bf_set(lpfc_mbx_run_diag_test_test_ver, &run_link_diag_test->u.req,
2403 link_diag_test_cmd->test_version);
2404 bf_set(lpfc_mbx_run_diag_test_err_act, &run_link_diag_test->u.req,
2405 link_diag_test_cmd->error_action);
2406
2407 mbxstatus = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
2408
2409 shdr = (union lpfc_sli4_cfg_shdr *)
2410 &pmboxq->u.mqe.un.sli4_config.header.cfg_shdr;
2411 shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
2412 shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
2413 if (shdr_status || shdr_add_status || mbxstatus) {
2414 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
2415 "3010 Run link diag test mailbox failed with "
2416 "mbx_status x%x status x%x, add_status x%x\n",
2417 mbxstatus, shdr_status, shdr_add_status);
2418 }
2419
2420 diag_status_reply = (struct diag_status *)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002421 bsg_reply->reply_data.vendor_reply.vendor_rsp;
James Smart7ad20aa2011-05-24 11:44:28 -04002422
2423 if (job->reply_len <
2424 sizeof(struct fc_bsg_request) + sizeof(struct diag_status)) {
2425 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
2426 "3012 Received Run link diag test reply "
2427 "below minimum size (%d): reply_len:%d\n",
2428 (int)(sizeof(struct fc_bsg_request) +
2429 sizeof(struct diag_status)),
2430 job->reply_len);
2431 rc = -EINVAL;
2432 goto job_error;
2433 }
2434
2435 diag_status_reply->mbox_status = mbxstatus;
2436 diag_status_reply->shdr_status = shdr_status;
2437 diag_status_reply->shdr_add_status = shdr_add_status;
2438
2439link_diag_test_exit:
2440 rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0);
2441
2442 if (pmboxq)
2443 mempool_free(pmboxq, phba->mbox_mem_pool);
2444
2445 lpfc_bsg_diag_mode_exit(phba);
2446
2447job_error:
2448 /* make error code available to userspace */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002449 bsg_reply->result = rc;
James Smart7ad20aa2011-05-24 11:44:28 -04002450 /* complete the job back to userspace if no error */
2451 if (rc == 0)
Johannes Thumshirn06548162016-11-17 10:31:22 +01002452 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01002453 bsg_reply->reply_payload_rcv_len);
James Smart7ad20aa2011-05-24 11:44:28 -04002454 return rc;
2455}
2456
2457/**
James Smart3b5dd522010-01-26 23:10:15 -05002458 * lpfcdiag_loop_self_reg - obtains a remote port login id
2459 * @phba: Pointer to HBA context object
2460 * @rpi: Pointer to a remote port login id
2461 *
2462 * This function obtains a remote port login id so the diag loopback test
2463 * can send and receive its own unsolicited CT command.
2464 **/
James Smart40426292010-12-15 17:58:10 -05002465static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t *rpi)
James Smart3b5dd522010-01-26 23:10:15 -05002466{
2467 LPFC_MBOXQ_t *mbox;
2468 struct lpfc_dmabuf *dmabuff;
2469 int status;
2470
2471 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
2472 if (!mbox)
James Smartd439d282010-09-29 11:18:45 -04002473 return -ENOMEM;
James Smart3b5dd522010-01-26 23:10:15 -05002474
James Smart1b511972011-12-13 13:23:09 -05002475 if (phba->sli_rev < LPFC_SLI_REV4)
2476 status = lpfc_reg_rpi(phba, 0, phba->pport->fc_myDID,
2477 (uint8_t *)&phba->pport->fc_sparam,
2478 mbox, *rpi);
2479 else {
James Smart40426292010-12-15 17:58:10 -05002480 *rpi = lpfc_sli4_alloc_rpi(phba);
James Smart1b511972011-12-13 13:23:09 -05002481 status = lpfc_reg_rpi(phba, phba->pport->vpi,
2482 phba->pport->fc_myDID,
2483 (uint8_t *)&phba->pport->fc_sparam,
2484 mbox, *rpi);
2485 }
2486
James Smart3b5dd522010-01-26 23:10:15 -05002487 if (status) {
2488 mempool_free(mbox, phba->mbox_mem_pool);
James Smart40426292010-12-15 17:58:10 -05002489 if (phba->sli_rev == LPFC_SLI_REV4)
2490 lpfc_sli4_free_rpi(phba, *rpi);
James Smartd439d282010-09-29 11:18:45 -04002491 return -ENOMEM;
James Smart3b5dd522010-01-26 23:10:15 -05002492 }
2493
2494 dmabuff = (struct lpfc_dmabuf *) mbox->context1;
2495 mbox->context1 = NULL;
James Smartd439d282010-09-29 11:18:45 -04002496 mbox->context2 = NULL;
James Smart3b5dd522010-01-26 23:10:15 -05002497 status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
2498
2499 if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) {
2500 lpfc_mbuf_free(phba, dmabuff->virt, dmabuff->phys);
2501 kfree(dmabuff);
2502 if (status != MBX_TIMEOUT)
2503 mempool_free(mbox, phba->mbox_mem_pool);
James Smart40426292010-12-15 17:58:10 -05002504 if (phba->sli_rev == LPFC_SLI_REV4)
2505 lpfc_sli4_free_rpi(phba, *rpi);
James Smartd439d282010-09-29 11:18:45 -04002506 return -ENODEV;
James Smart3b5dd522010-01-26 23:10:15 -05002507 }
2508
James Smart1b511972011-12-13 13:23:09 -05002509 if (phba->sli_rev < LPFC_SLI_REV4)
2510 *rpi = mbox->u.mb.un.varWords[0];
James Smart3b5dd522010-01-26 23:10:15 -05002511
2512 lpfc_mbuf_free(phba, dmabuff->virt, dmabuff->phys);
2513 kfree(dmabuff);
2514 mempool_free(mbox, phba->mbox_mem_pool);
2515 return 0;
2516}
2517
2518/**
2519 * lpfcdiag_loop_self_unreg - unregs from the rpi
2520 * @phba: Pointer to HBA context object
2521 * @rpi: Remote port login id
2522 *
2523 * This function unregisters the rpi obtained in lpfcdiag_loop_self_reg
2524 **/
2525static int lpfcdiag_loop_self_unreg(struct lpfc_hba *phba, uint16_t rpi)
2526{
2527 LPFC_MBOXQ_t *mbox;
2528 int status;
2529
2530 /* Allocate mboxq structure */
2531 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
2532 if (mbox == NULL)
James Smartd439d282010-09-29 11:18:45 -04002533 return -ENOMEM;
James Smart3b5dd522010-01-26 23:10:15 -05002534
James Smart1b511972011-12-13 13:23:09 -05002535 if (phba->sli_rev < LPFC_SLI_REV4)
2536 lpfc_unreg_login(phba, 0, rpi, mbox);
2537 else
2538 lpfc_unreg_login(phba, phba->pport->vpi,
2539 phba->sli4_hba.rpi_ids[rpi], mbox);
2540
James Smart3b5dd522010-01-26 23:10:15 -05002541 status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
2542
2543 if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) {
2544 if (status != MBX_TIMEOUT)
2545 mempool_free(mbox, phba->mbox_mem_pool);
James Smartd439d282010-09-29 11:18:45 -04002546 return -EIO;
James Smart3b5dd522010-01-26 23:10:15 -05002547 }
James Smart3b5dd522010-01-26 23:10:15 -05002548 mempool_free(mbox, phba->mbox_mem_pool);
James Smart40426292010-12-15 17:58:10 -05002549 if (phba->sli_rev == LPFC_SLI_REV4)
2550 lpfc_sli4_free_rpi(phba, rpi);
James Smart3b5dd522010-01-26 23:10:15 -05002551 return 0;
2552}
2553
2554/**
2555 * lpfcdiag_loop_get_xri - obtains the transmit and receive ids
2556 * @phba: Pointer to HBA context object
2557 * @rpi: Remote port login id
2558 * @txxri: Pointer to transmit exchange id
2559 * @rxxri: Pointer to response exchabge id
2560 *
2561 * This function obtains the transmit and receive ids required to send
2562 * an unsolicited ct command with a payload. A special lpfc FsType and CmdRsp
2563 * flags are used to the unsolicted response handler is able to process
2564 * the ct command sent on the same port.
2565 **/
2566static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
2567 uint16_t *txxri, uint16_t * rxxri)
2568{
2569 struct lpfc_bsg_event *evt;
2570 struct lpfc_iocbq *cmdiocbq, *rspiocbq;
2571 IOCB_t *cmd, *rsp;
2572 struct lpfc_dmabuf *dmabuf;
2573 struct ulp_bde64 *bpl = NULL;
2574 struct lpfc_sli_ct_request *ctreq = NULL;
2575 int ret_val = 0;
James Smartd439d282010-09-29 11:18:45 -04002576 int time_left;
James Smart5a0916b2013-07-15 18:31:42 -04002577 int iocb_stat = IOCB_SUCCESS;
James Smart3b5dd522010-01-26 23:10:15 -05002578 unsigned long flags;
2579
2580 *txxri = 0;
2581 *rxxri = 0;
2582 evt = lpfc_bsg_event_new(FC_REG_CT_EVENT, current->pid,
2583 SLI_CT_ELX_LOOPBACK);
2584 if (!evt)
James Smartd439d282010-09-29 11:18:45 -04002585 return -ENOMEM;
James Smart3b5dd522010-01-26 23:10:15 -05002586
2587 spin_lock_irqsave(&phba->ct_ev_lock, flags);
2588 list_add(&evt->node, &phba->ct_ev_waiters);
2589 lpfc_bsg_event_ref(evt);
2590 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
2591
2592 cmdiocbq = lpfc_sli_get_iocbq(phba);
2593 rspiocbq = lpfc_sli_get_iocbq(phba);
2594
2595 dmabuf = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
2596 if (dmabuf) {
2597 dmabuf->virt = lpfc_mbuf_alloc(phba, 0, &dmabuf->phys);
James Smartc7495932010-04-06 15:05:28 -04002598 if (dmabuf->virt) {
2599 INIT_LIST_HEAD(&dmabuf->list);
2600 bpl = (struct ulp_bde64 *) dmabuf->virt;
2601 memset(bpl, 0, sizeof(*bpl));
2602 ctreq = (struct lpfc_sli_ct_request *)(bpl + 1);
2603 bpl->addrHigh =
2604 le32_to_cpu(putPaddrHigh(dmabuf->phys +
2605 sizeof(*bpl)));
2606 bpl->addrLow =
2607 le32_to_cpu(putPaddrLow(dmabuf->phys +
2608 sizeof(*bpl)));
2609 bpl->tus.f.bdeFlags = 0;
2610 bpl->tus.f.bdeSize = ELX_LOOPBACK_HEADER_SZ;
2611 bpl->tus.w = le32_to_cpu(bpl->tus.w);
2612 }
James Smart3b5dd522010-01-26 23:10:15 -05002613 }
2614
2615 if (cmdiocbq == NULL || rspiocbq == NULL ||
James Smartc7495932010-04-06 15:05:28 -04002616 dmabuf == NULL || bpl == NULL || ctreq == NULL ||
2617 dmabuf->virt == NULL) {
James Smartd439d282010-09-29 11:18:45 -04002618 ret_val = -ENOMEM;
James Smart3b5dd522010-01-26 23:10:15 -05002619 goto err_get_xri_exit;
2620 }
2621
2622 cmd = &cmdiocbq->iocb;
2623 rsp = &rspiocbq->iocb;
2624
2625 memset(ctreq, 0, ELX_LOOPBACK_HEADER_SZ);
2626
2627 ctreq->RevisionId.bits.Revision = SLI_CT_REVISION;
2628 ctreq->RevisionId.bits.InId = 0;
2629 ctreq->FsType = SLI_CT_ELX_LOOPBACK;
2630 ctreq->FsSubType = 0;
2631 ctreq->CommandResponse.bits.CmdRsp = ELX_LOOPBACK_XRI_SETUP;
2632 ctreq->CommandResponse.bits.Size = 0;
2633
2634
2635 cmd->un.xseq64.bdl.addrHigh = putPaddrHigh(dmabuf->phys);
2636 cmd->un.xseq64.bdl.addrLow = putPaddrLow(dmabuf->phys);
2637 cmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
2638 cmd->un.xseq64.bdl.bdeSize = sizeof(*bpl);
2639
2640 cmd->un.xseq64.w5.hcsw.Fctl = LA;
2641 cmd->un.xseq64.w5.hcsw.Dfctl = 0;
2642 cmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL;
2643 cmd->un.xseq64.w5.hcsw.Type = FC_TYPE_CT;
2644
2645 cmd->ulpCommand = CMD_XMIT_SEQUENCE64_CR;
2646 cmd->ulpBdeCount = 1;
2647 cmd->ulpLe = 1;
2648 cmd->ulpClass = CLASS3;
2649 cmd->ulpContext = rpi;
2650
2651 cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
2652 cmdiocbq->vport = phba->pport;
James Smart5a0916b2013-07-15 18:31:42 -04002653 cmdiocbq->iocb_cmpl = NULL;
James Smart3b5dd522010-01-26 23:10:15 -05002654
James Smartd439d282010-09-29 11:18:45 -04002655 iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
James Smart3b5dd522010-01-26 23:10:15 -05002656 rspiocbq,
2657 (phba->fc_ratov * 2)
2658 + LPFC_DRVR_TIMEOUT);
James Smart53151bb2013-10-10 12:24:07 -04002659 if ((iocb_stat != IOCB_SUCCESS) || (rsp->ulpStatus != IOSTAT_SUCCESS)) {
James Smartd439d282010-09-29 11:18:45 -04002660 ret_val = -EIO;
James Smart3b5dd522010-01-26 23:10:15 -05002661 goto err_get_xri_exit;
James Smartd439d282010-09-29 11:18:45 -04002662 }
James Smart3b5dd522010-01-26 23:10:15 -05002663 *txxri = rsp->ulpContext;
2664
2665 evt->waiting = 1;
2666 evt->wait_time_stamp = jiffies;
James Smartd439d282010-09-29 11:18:45 -04002667 time_left = wait_event_interruptible_timeout(
James Smart3b5dd522010-01-26 23:10:15 -05002668 evt->wq, !list_empty(&evt->events_to_see),
James Smart256ec0d2013-04-17 20:14:58 -04002669 msecs_to_jiffies(1000 *
2670 ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT)));
James Smart3b5dd522010-01-26 23:10:15 -05002671 if (list_empty(&evt->events_to_see))
James Smartd439d282010-09-29 11:18:45 -04002672 ret_val = (time_left) ? -EINTR : -ETIMEDOUT;
James Smart3b5dd522010-01-26 23:10:15 -05002673 else {
James Smart3b5dd522010-01-26 23:10:15 -05002674 spin_lock_irqsave(&phba->ct_ev_lock, flags);
2675 list_move(evt->events_to_see.prev, &evt->events_to_get);
2676 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
2677 *rxxri = (list_entry(evt->events_to_get.prev,
2678 typeof(struct event_data),
2679 node))->immed_dat;
2680 }
2681 evt->waiting = 0;
2682
2683err_get_xri_exit:
2684 spin_lock_irqsave(&phba->ct_ev_lock, flags);
2685 lpfc_bsg_event_unref(evt); /* release ref */
2686 lpfc_bsg_event_unref(evt); /* delete */
2687 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
2688
2689 if (dmabuf) {
2690 if (dmabuf->virt)
2691 lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys);
2692 kfree(dmabuf);
2693 }
2694
James Smartd439d282010-09-29 11:18:45 -04002695 if (cmdiocbq && (iocb_stat != IOCB_TIMEDOUT))
James Smart3b5dd522010-01-26 23:10:15 -05002696 lpfc_sli_release_iocbq(phba, cmdiocbq);
2697 if (rspiocbq)
2698 lpfc_sli_release_iocbq(phba, rspiocbq);
2699 return ret_val;
2700}
2701
2702/**
James Smart7ad20aa2011-05-24 11:44:28 -04002703 * lpfc_bsg_dma_page_alloc - allocate a bsg mbox page sized dma buffers
2704 * @phba: Pointer to HBA context object
2705 *
James Smart2ea259e2017-02-12 13:52:27 -08002706 * This function allocates BSG_MBOX_SIZE (4KB) page size dma buffer and
Joe Perches9e03aa22013-09-03 13:45:58 -07002707 * returns the pointer to the buffer.
James Smart7ad20aa2011-05-24 11:44:28 -04002708 **/
2709static struct lpfc_dmabuf *
2710lpfc_bsg_dma_page_alloc(struct lpfc_hba *phba)
2711{
2712 struct lpfc_dmabuf *dmabuf;
2713 struct pci_dev *pcidev = phba->pcidev;
2714
2715 /* allocate dma buffer struct */
2716 dmabuf = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
2717 if (!dmabuf)
2718 return NULL;
2719
2720 INIT_LIST_HEAD(&dmabuf->list);
2721
2722 /* now, allocate dma buffer */
Joe Perches1aee3832014-09-03 12:56:12 -04002723 dmabuf->virt = dma_zalloc_coherent(&pcidev->dev, BSG_MBOX_SIZE,
2724 &(dmabuf->phys), GFP_KERNEL);
James Smart7ad20aa2011-05-24 11:44:28 -04002725
2726 if (!dmabuf->virt) {
2727 kfree(dmabuf);
2728 return NULL;
2729 }
James Smart7ad20aa2011-05-24 11:44:28 -04002730
2731 return dmabuf;
2732}
2733
2734/**
2735 * lpfc_bsg_dma_page_free - free a bsg mbox page sized dma buffer
2736 * @phba: Pointer to HBA context object.
2737 * @dmabuf: Pointer to the bsg mbox page sized dma buffer descriptor.
2738 *
2739 * This routine just simply frees a dma buffer and its associated buffer
2740 * descriptor referred by @dmabuf.
2741 **/
2742static void
2743lpfc_bsg_dma_page_free(struct lpfc_hba *phba, struct lpfc_dmabuf *dmabuf)
2744{
2745 struct pci_dev *pcidev = phba->pcidev;
2746
2747 if (!dmabuf)
2748 return;
2749
2750 if (dmabuf->virt)
2751 dma_free_coherent(&pcidev->dev, BSG_MBOX_SIZE,
2752 dmabuf->virt, dmabuf->phys);
2753 kfree(dmabuf);
2754 return;
2755}
2756
2757/**
2758 * lpfc_bsg_dma_page_list_free - free a list of bsg mbox page sized dma buffers
2759 * @phba: Pointer to HBA context object.
2760 * @dmabuf_list: Pointer to a list of bsg mbox page sized dma buffer descs.
2761 *
2762 * This routine just simply frees all dma buffers and their associated buffer
2763 * descriptors referred by @dmabuf_list.
2764 **/
2765static void
2766lpfc_bsg_dma_page_list_free(struct lpfc_hba *phba,
2767 struct list_head *dmabuf_list)
2768{
2769 struct lpfc_dmabuf *dmabuf, *next_dmabuf;
2770
2771 if (list_empty(dmabuf_list))
2772 return;
2773
2774 list_for_each_entry_safe(dmabuf, next_dmabuf, dmabuf_list, list) {
2775 list_del_init(&dmabuf->list);
2776 lpfc_bsg_dma_page_free(phba, dmabuf);
2777 }
2778 return;
2779}
2780
2781/**
James Smart3b5dd522010-01-26 23:10:15 -05002782 * diag_cmd_data_alloc - fills in a bde struct with dma buffers
2783 * @phba: Pointer to HBA context object
2784 * @bpl: Pointer to 64 bit bde structure
2785 * @size: Number of bytes to process
2786 * @nocopydata: Flag to copy user data into the allocated buffer
2787 *
2788 * This function allocates page size buffers and populates an lpfc_dmabufext.
2789 * If allowed the user data pointed to with indataptr is copied into the kernel
2790 * memory. The chained list of page size buffers is returned.
2791 **/
2792static struct lpfc_dmabufext *
2793diag_cmd_data_alloc(struct lpfc_hba *phba,
2794 struct ulp_bde64 *bpl, uint32_t size,
2795 int nocopydata)
2796{
2797 struct lpfc_dmabufext *mlist = NULL;
2798 struct lpfc_dmabufext *dmp;
2799 int cnt, offset = 0, i = 0;
2800 struct pci_dev *pcidev;
2801
2802 pcidev = phba->pcidev;
2803
2804 while (size) {
2805 /* We get chunks of 4K */
2806 if (size > BUF_SZ_4K)
2807 cnt = BUF_SZ_4K;
2808 else
2809 cnt = size;
2810
2811 /* allocate struct lpfc_dmabufext buffer header */
2812 dmp = kmalloc(sizeof(struct lpfc_dmabufext), GFP_KERNEL);
2813 if (!dmp)
2814 goto out;
2815
2816 INIT_LIST_HEAD(&dmp->dma.list);
2817
2818 /* Queue it to a linked list */
2819 if (mlist)
2820 list_add_tail(&dmp->dma.list, &mlist->dma.list);
2821 else
2822 mlist = dmp;
2823
2824 /* allocate buffer */
2825 dmp->dma.virt = dma_alloc_coherent(&pcidev->dev,
2826 cnt,
2827 &(dmp->dma.phys),
2828 GFP_KERNEL);
2829
2830 if (!dmp->dma.virt)
2831 goto out;
2832
2833 dmp->size = cnt;
2834
2835 if (nocopydata) {
2836 bpl->tus.f.bdeFlags = 0;
2837 pci_dma_sync_single_for_device(phba->pcidev,
2838 dmp->dma.phys, LPFC_BPL_SIZE, PCI_DMA_TODEVICE);
2839
2840 } else {
2841 memset((uint8_t *)dmp->dma.virt, 0, cnt);
2842 bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;
2843 }
2844
2845 /* build buffer ptr list for IOCB */
2846 bpl->addrLow = le32_to_cpu(putPaddrLow(dmp->dma.phys));
2847 bpl->addrHigh = le32_to_cpu(putPaddrHigh(dmp->dma.phys));
2848 bpl->tus.f.bdeSize = (ushort) cnt;
2849 bpl->tus.w = le32_to_cpu(bpl->tus.w);
2850 bpl++;
2851
2852 i++;
2853 offset += cnt;
2854 size -= cnt;
2855 }
2856
James Smarta2fc4aef2014-09-03 12:57:55 -04002857 if (mlist) {
2858 mlist->flag = i;
2859 return mlist;
2860 }
James Smart3b5dd522010-01-26 23:10:15 -05002861out:
2862 diag_cmd_data_free(phba, mlist);
2863 return NULL;
2864}
2865
2866/**
2867 * lpfcdiag_loop_post_rxbufs - post the receive buffers for an unsol CT cmd
2868 * @phba: Pointer to HBA context object
2869 * @rxxri: Receive exchange id
2870 * @len: Number of data bytes
2871 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002872 * This function allocates and posts a data buffer of sufficient size to receive
James Smart3b5dd522010-01-26 23:10:15 -05002873 * an unsolicted CT command.
2874 **/
2875static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
2876 size_t len)
2877{
2878 struct lpfc_sli *psli = &phba->sli;
2879 struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
2880 struct lpfc_iocbq *cmdiocbq;
2881 IOCB_t *cmd = NULL;
2882 struct list_head head, *curr, *next;
2883 struct lpfc_dmabuf *rxbmp;
2884 struct lpfc_dmabuf *dmp;
2885 struct lpfc_dmabuf *mp[2] = {NULL, NULL};
2886 struct ulp_bde64 *rxbpl = NULL;
2887 uint32_t num_bde;
2888 struct lpfc_dmabufext *rxbuffer = NULL;
2889 int ret_val = 0;
James Smartd439d282010-09-29 11:18:45 -04002890 int iocb_stat;
James Smart3b5dd522010-01-26 23:10:15 -05002891 int i = 0;
2892
2893 cmdiocbq = lpfc_sli_get_iocbq(phba);
2894 rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
2895 if (rxbmp != NULL) {
2896 rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys);
James Smartc7495932010-04-06 15:05:28 -04002897 if (rxbmp->virt) {
2898 INIT_LIST_HEAD(&rxbmp->list);
2899 rxbpl = (struct ulp_bde64 *) rxbmp->virt;
2900 rxbuffer = diag_cmd_data_alloc(phba, rxbpl, len, 0);
2901 }
James Smart3b5dd522010-01-26 23:10:15 -05002902 }
2903
2904 if (!cmdiocbq || !rxbmp || !rxbpl || !rxbuffer) {
James Smartd439d282010-09-29 11:18:45 -04002905 ret_val = -ENOMEM;
James Smart3b5dd522010-01-26 23:10:15 -05002906 goto err_post_rxbufs_exit;
2907 }
2908
2909 /* Queue buffers for the receive exchange */
2910 num_bde = (uint32_t)rxbuffer->flag;
2911 dmp = &rxbuffer->dma;
2912
2913 cmd = &cmdiocbq->iocb;
2914 i = 0;
2915
2916 INIT_LIST_HEAD(&head);
2917 list_add_tail(&head, &dmp->list);
2918 list_for_each_safe(curr, next, &head) {
2919 mp[i] = list_entry(curr, struct lpfc_dmabuf, list);
2920 list_del(curr);
2921
2922 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
2923 mp[i]->buffer_tag = lpfc_sli_get_buffer_tag(phba);
2924 cmd->un.quexri64cx.buff.bde.addrHigh =
2925 putPaddrHigh(mp[i]->phys);
2926 cmd->un.quexri64cx.buff.bde.addrLow =
2927 putPaddrLow(mp[i]->phys);
2928 cmd->un.quexri64cx.buff.bde.tus.f.bdeSize =
2929 ((struct lpfc_dmabufext *)mp[i])->size;
2930 cmd->un.quexri64cx.buff.buffer_tag = mp[i]->buffer_tag;
2931 cmd->ulpCommand = CMD_QUE_XRI64_CX;
2932 cmd->ulpPU = 0;
2933 cmd->ulpLe = 1;
2934 cmd->ulpBdeCount = 1;
2935 cmd->unsli3.que_xri64cx_ext_words.ebde_count = 0;
2936
2937 } else {
2938 cmd->un.cont64[i].addrHigh = putPaddrHigh(mp[i]->phys);
2939 cmd->un.cont64[i].addrLow = putPaddrLow(mp[i]->phys);
2940 cmd->un.cont64[i].tus.f.bdeSize =
2941 ((struct lpfc_dmabufext *)mp[i])->size;
2942 cmd->ulpBdeCount = ++i;
2943
2944 if ((--num_bde > 0) && (i < 2))
2945 continue;
2946
2947 cmd->ulpCommand = CMD_QUE_XRI_BUF64_CX;
2948 cmd->ulpLe = 1;
2949 }
2950
2951 cmd->ulpClass = CLASS3;
2952 cmd->ulpContext = rxxri;
2953
James Smartd439d282010-09-29 11:18:45 -04002954 iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq,
2955 0);
2956 if (iocb_stat == IOCB_ERROR) {
James Smart3b5dd522010-01-26 23:10:15 -05002957 diag_cmd_data_free(phba,
2958 (struct lpfc_dmabufext *)mp[0]);
2959 if (mp[1])
2960 diag_cmd_data_free(phba,
2961 (struct lpfc_dmabufext *)mp[1]);
2962 dmp = list_entry(next, struct lpfc_dmabuf, list);
James Smartd439d282010-09-29 11:18:45 -04002963 ret_val = -EIO;
James Smart3b5dd522010-01-26 23:10:15 -05002964 goto err_post_rxbufs_exit;
2965 }
2966
2967 lpfc_sli_ringpostbuf_put(phba, pring, mp[0]);
2968 if (mp[1]) {
2969 lpfc_sli_ringpostbuf_put(phba, pring, mp[1]);
2970 mp[1] = NULL;
2971 }
2972
2973 /* The iocb was freed by lpfc_sli_issue_iocb */
2974 cmdiocbq = lpfc_sli_get_iocbq(phba);
2975 if (!cmdiocbq) {
2976 dmp = list_entry(next, struct lpfc_dmabuf, list);
James Smartd439d282010-09-29 11:18:45 -04002977 ret_val = -EIO;
James Smart3b5dd522010-01-26 23:10:15 -05002978 goto err_post_rxbufs_exit;
2979 }
2980
2981 cmd = &cmdiocbq->iocb;
2982 i = 0;
2983 }
2984 list_del(&head);
2985
2986err_post_rxbufs_exit:
2987
2988 if (rxbmp) {
2989 if (rxbmp->virt)
2990 lpfc_mbuf_free(phba, rxbmp->virt, rxbmp->phys);
2991 kfree(rxbmp);
2992 }
2993
2994 if (cmdiocbq)
2995 lpfc_sli_release_iocbq(phba, cmdiocbq);
2996 return ret_val;
2997}
2998
2999/**
James Smart7ad20aa2011-05-24 11:44:28 -04003000 * lpfc_bsg_diag_loopback_run - run loopback on a port by issue ct cmd to itself
James Smart3b5dd522010-01-26 23:10:15 -05003001 * @job: LPFC_BSG_VENDOR_DIAG_TEST fc_bsg_job
3002 *
3003 * This function receives a user data buffer to be transmitted and received on
3004 * the same port, the link must be up and in loopback mode prior
3005 * to being called.
3006 * 1. A kernel buffer is allocated to copy the user data into.
3007 * 2. The port registers with "itself".
3008 * 3. The transmit and receive exchange ids are obtained.
3009 * 4. The receive exchange id is posted.
3010 * 5. A new els loopback event is created.
3011 * 6. The command and response iocbs are allocated.
3012 * 7. The cmd iocb FsType is set to elx loopback and the CmdRsp to looppback.
3013 *
3014 * This function is meant to be called n times while the port is in loopback
3015 * so it is the apps responsibility to issue a reset to take the port out
3016 * of loopback mode.
3017 **/
3018static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01003019lpfc_bsg_diag_loopback_run(struct bsg_job *job)
James Smart3b5dd522010-01-26 23:10:15 -05003020{
Johannes Thumshirncd21c602016-11-17 10:31:14 +01003021 struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003022 struct fc_bsg_reply *bsg_reply = job->reply;
James Smart3b5dd522010-01-26 23:10:15 -05003023 struct lpfc_hba *phba = vport->phba;
James Smart3b5dd522010-01-26 23:10:15 -05003024 struct lpfc_bsg_event *evt;
3025 struct event_data *evdat;
3026 struct lpfc_sli *psli = &phba->sli;
3027 uint32_t size;
3028 uint32_t full_size;
3029 size_t segment_len = 0, segment_offset = 0, current_offset = 0;
James Smart40426292010-12-15 17:58:10 -05003030 uint16_t rpi = 0;
James Smart1b511972011-12-13 13:23:09 -05003031 struct lpfc_iocbq *cmdiocbq, *rspiocbq = NULL;
3032 IOCB_t *cmd, *rsp = NULL;
James Smart3b5dd522010-01-26 23:10:15 -05003033 struct lpfc_sli_ct_request *ctreq;
3034 struct lpfc_dmabuf *txbmp;
3035 struct ulp_bde64 *txbpl = NULL;
3036 struct lpfc_dmabufext *txbuffer = NULL;
3037 struct list_head head;
3038 struct lpfc_dmabuf *curr;
James Smart1b511972011-12-13 13:23:09 -05003039 uint16_t txxri = 0, rxxri;
James Smart3b5dd522010-01-26 23:10:15 -05003040 uint32_t num_bde;
3041 uint8_t *ptr = NULL, *rx_databuf = NULL;
3042 int rc = 0;
James Smartd439d282010-09-29 11:18:45 -04003043 int time_left;
James Smart5a0916b2013-07-15 18:31:42 -04003044 int iocb_stat = IOCB_SUCCESS;
James Smart3b5dd522010-01-26 23:10:15 -05003045 unsigned long flags;
3046 void *dataout = NULL;
3047 uint32_t total_mem;
3048
3049 /* in case no data is returned return just the return code */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003050 bsg_reply->reply_payload_rcv_len = 0;
James Smart3b5dd522010-01-26 23:10:15 -05003051
3052 if (job->request_len <
3053 sizeof(struct fc_bsg_request) + sizeof(struct diag_mode_test)) {
3054 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
3055 "2739 Received DIAG TEST request below minimum "
3056 "size\n");
3057 rc = -EINVAL;
3058 goto loopback_test_exit;
3059 }
3060
3061 if (job->request_payload.payload_len !=
3062 job->reply_payload.payload_len) {
3063 rc = -EINVAL;
3064 goto loopback_test_exit;
3065 }
James Smart3b5dd522010-01-26 23:10:15 -05003066
3067 if ((phba->link_state == LPFC_HBA_ERROR) ||
3068 (psli->sli_flag & LPFC_BLOCK_MGMT_IO) ||
3069 (!(psli->sli_flag & LPFC_SLI_ACTIVE))) {
3070 rc = -EACCES;
3071 goto loopback_test_exit;
3072 }
3073
3074 if (!lpfc_is_link_up(phba) || !(phba->link_flag & LS_LOOPBACK_MODE)) {
3075 rc = -EACCES;
3076 goto loopback_test_exit;
3077 }
3078
3079 size = job->request_payload.payload_len;
3080 full_size = size + ELX_LOOPBACK_HEADER_SZ; /* plus the header */
3081
3082 if ((size == 0) || (size > 80 * BUF_SZ_4K)) {
3083 rc = -ERANGE;
3084 goto loopback_test_exit;
3085 }
3086
James Smart63e801c2010-11-20 23:14:19 -05003087 if (full_size >= BUF_SZ_4K) {
James Smart3b5dd522010-01-26 23:10:15 -05003088 /*
3089 * Allocate memory for ioctl data. If buffer is bigger than 64k,
3090 * then we allocate 64k and re-use that buffer over and over to
3091 * xfer the whole block. This is because Linux kernel has a
3092 * problem allocating more than 120k of kernel space memory. Saw
3093 * problem with GET_FCPTARGETMAPPING...
3094 */
3095 if (size <= (64 * 1024))
James Smart63e801c2010-11-20 23:14:19 -05003096 total_mem = full_size;
James Smart3b5dd522010-01-26 23:10:15 -05003097 else
3098 total_mem = 64 * 1024;
3099 } else
3100 /* Allocate memory for ioctl data */
3101 total_mem = BUF_SZ_4K;
3102
3103 dataout = kmalloc(total_mem, GFP_KERNEL);
3104 if (dataout == NULL) {
3105 rc = -ENOMEM;
3106 goto loopback_test_exit;
3107 }
3108
3109 ptr = dataout;
3110 ptr += ELX_LOOPBACK_HEADER_SZ;
3111 sg_copy_to_buffer(job->request_payload.sg_list,
3112 job->request_payload.sg_cnt,
3113 ptr, size);
James Smart3b5dd522010-01-26 23:10:15 -05003114 rc = lpfcdiag_loop_self_reg(phba, &rpi);
James Smartd439d282010-09-29 11:18:45 -04003115 if (rc)
James Smart3b5dd522010-01-26 23:10:15 -05003116 goto loopback_test_exit;
James Smart3b5dd522010-01-26 23:10:15 -05003117
James Smart1b511972011-12-13 13:23:09 -05003118 if (phba->sli_rev < LPFC_SLI_REV4) {
3119 rc = lpfcdiag_loop_get_xri(phba, rpi, &txxri, &rxxri);
3120 if (rc) {
3121 lpfcdiag_loop_self_unreg(phba, rpi);
3122 goto loopback_test_exit;
3123 }
James Smart3b5dd522010-01-26 23:10:15 -05003124
James Smart1b511972011-12-13 13:23:09 -05003125 rc = lpfcdiag_loop_post_rxbufs(phba, rxxri, full_size);
3126 if (rc) {
3127 lpfcdiag_loop_self_unreg(phba, rpi);
3128 goto loopback_test_exit;
3129 }
James Smart3b5dd522010-01-26 23:10:15 -05003130 }
James Smart3b5dd522010-01-26 23:10:15 -05003131 evt = lpfc_bsg_event_new(FC_REG_CT_EVENT, current->pid,
3132 SLI_CT_ELX_LOOPBACK);
3133 if (!evt) {
3134 lpfcdiag_loop_self_unreg(phba, rpi);
3135 rc = -ENOMEM;
3136 goto loopback_test_exit;
3137 }
3138
3139 spin_lock_irqsave(&phba->ct_ev_lock, flags);
3140 list_add(&evt->node, &phba->ct_ev_waiters);
3141 lpfc_bsg_event_ref(evt);
3142 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
3143
3144 cmdiocbq = lpfc_sli_get_iocbq(phba);
James Smart1b511972011-12-13 13:23:09 -05003145 if (phba->sli_rev < LPFC_SLI_REV4)
3146 rspiocbq = lpfc_sli_get_iocbq(phba);
James Smart3b5dd522010-01-26 23:10:15 -05003147 txbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
3148
3149 if (txbmp) {
3150 txbmp->virt = lpfc_mbuf_alloc(phba, 0, &txbmp->phys);
James Smartc7495932010-04-06 15:05:28 -04003151 if (txbmp->virt) {
3152 INIT_LIST_HEAD(&txbmp->list);
3153 txbpl = (struct ulp_bde64 *) txbmp->virt;
James Smart3b5dd522010-01-26 23:10:15 -05003154 txbuffer = diag_cmd_data_alloc(phba,
3155 txbpl, full_size, 0);
James Smartc7495932010-04-06 15:05:28 -04003156 }
James Smart3b5dd522010-01-26 23:10:15 -05003157 }
3158
James Smart1b511972011-12-13 13:23:09 -05003159 if (!cmdiocbq || !txbmp || !txbpl || !txbuffer || !txbmp->virt) {
3160 rc = -ENOMEM;
3161 goto err_loopback_test_exit;
3162 }
3163 if ((phba->sli_rev < LPFC_SLI_REV4) && !rspiocbq) {
James Smart3b5dd522010-01-26 23:10:15 -05003164 rc = -ENOMEM;
3165 goto err_loopback_test_exit;
3166 }
3167
3168 cmd = &cmdiocbq->iocb;
James Smart1b511972011-12-13 13:23:09 -05003169 if (phba->sli_rev < LPFC_SLI_REV4)
3170 rsp = &rspiocbq->iocb;
James Smart3b5dd522010-01-26 23:10:15 -05003171
3172 INIT_LIST_HEAD(&head);
3173 list_add_tail(&head, &txbuffer->dma.list);
3174 list_for_each_entry(curr, &head, list) {
3175 segment_len = ((struct lpfc_dmabufext *)curr)->size;
3176 if (current_offset == 0) {
3177 ctreq = curr->virt;
3178 memset(ctreq, 0, ELX_LOOPBACK_HEADER_SZ);
3179 ctreq->RevisionId.bits.Revision = SLI_CT_REVISION;
3180 ctreq->RevisionId.bits.InId = 0;
3181 ctreq->FsType = SLI_CT_ELX_LOOPBACK;
3182 ctreq->FsSubType = 0;
3183 ctreq->CommandResponse.bits.CmdRsp = ELX_LOOPBACK_DATA;
3184 ctreq->CommandResponse.bits.Size = size;
3185 segment_offset = ELX_LOOPBACK_HEADER_SZ;
3186 } else
3187 segment_offset = 0;
3188
3189 BUG_ON(segment_offset >= segment_len);
3190 memcpy(curr->virt + segment_offset,
3191 ptr + current_offset,
3192 segment_len - segment_offset);
3193
3194 current_offset += segment_len - segment_offset;
3195 BUG_ON(current_offset > size);
3196 }
3197 list_del(&head);
3198
3199 /* Build the XMIT_SEQUENCE iocb */
James Smart3b5dd522010-01-26 23:10:15 -05003200 num_bde = (uint32_t)txbuffer->flag;
3201
3202 cmd->un.xseq64.bdl.addrHigh = putPaddrHigh(txbmp->phys);
3203 cmd->un.xseq64.bdl.addrLow = putPaddrLow(txbmp->phys);
3204 cmd->un.xseq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
3205 cmd->un.xseq64.bdl.bdeSize = (num_bde * sizeof(struct ulp_bde64));
3206
3207 cmd->un.xseq64.w5.hcsw.Fctl = (LS | LA);
3208 cmd->un.xseq64.w5.hcsw.Dfctl = 0;
3209 cmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL;
3210 cmd->un.xseq64.w5.hcsw.Type = FC_TYPE_CT;
3211
3212 cmd->ulpCommand = CMD_XMIT_SEQUENCE64_CX;
3213 cmd->ulpBdeCount = 1;
3214 cmd->ulpLe = 1;
3215 cmd->ulpClass = CLASS3;
James Smart3b5dd522010-01-26 23:10:15 -05003216
James Smart1b511972011-12-13 13:23:09 -05003217 if (phba->sli_rev < LPFC_SLI_REV4) {
3218 cmd->ulpContext = txxri;
3219 } else {
3220 cmd->un.xseq64.bdl.ulpIoTag32 = 0;
3221 cmd->un.ulpWord[3] = phba->sli4_hba.rpi_ids[rpi];
3222 cmdiocbq->context3 = txbmp;
3223 cmdiocbq->sli4_xritag = NO_XRI;
3224 cmd->unsli3.rcvsli3.ox_id = 0xffff;
3225 }
James Smart3b5dd522010-01-26 23:10:15 -05003226 cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
James Smart6c7cf482015-04-07 15:07:25 -04003227 cmdiocbq->iocb_flag |= LPFC_IO_LOOPBACK;
James Smart3b5dd522010-01-26 23:10:15 -05003228 cmdiocbq->vport = phba->pport;
James Smart5a0916b2013-07-15 18:31:42 -04003229 cmdiocbq->iocb_cmpl = NULL;
James Smartd439d282010-09-29 11:18:45 -04003230 iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
3231 rspiocbq, (phba->fc_ratov * 2) +
3232 LPFC_DRVR_TIMEOUT);
James Smart3b5dd522010-01-26 23:10:15 -05003233
James Smart53151bb2013-10-10 12:24:07 -04003234 if ((iocb_stat != IOCB_SUCCESS) ||
3235 ((phba->sli_rev < LPFC_SLI_REV4) &&
3236 (rsp->ulpStatus != IOSTAT_SUCCESS))) {
James Smart1b511972011-12-13 13:23:09 -05003237 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3238 "3126 Failed loopback test issue iocb: "
3239 "iocb_stat:x%x\n", iocb_stat);
James Smart3b5dd522010-01-26 23:10:15 -05003240 rc = -EIO;
3241 goto err_loopback_test_exit;
3242 }
3243
3244 evt->waiting = 1;
James Smartd439d282010-09-29 11:18:45 -04003245 time_left = wait_event_interruptible_timeout(
James Smart3b5dd522010-01-26 23:10:15 -05003246 evt->wq, !list_empty(&evt->events_to_see),
James Smart256ec0d2013-04-17 20:14:58 -04003247 msecs_to_jiffies(1000 *
3248 ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT)));
James Smart3b5dd522010-01-26 23:10:15 -05003249 evt->waiting = 0;
James Smart1b511972011-12-13 13:23:09 -05003250 if (list_empty(&evt->events_to_see)) {
James Smartd439d282010-09-29 11:18:45 -04003251 rc = (time_left) ? -EINTR : -ETIMEDOUT;
James Smart1b511972011-12-13 13:23:09 -05003252 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3253 "3125 Not receiving unsolicited event, "
3254 "rc:x%x\n", rc);
3255 } else {
James Smart3b5dd522010-01-26 23:10:15 -05003256 spin_lock_irqsave(&phba->ct_ev_lock, flags);
3257 list_move(evt->events_to_see.prev, &evt->events_to_get);
3258 evdat = list_entry(evt->events_to_get.prev,
3259 typeof(*evdat), node);
3260 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
3261 rx_databuf = evdat->data;
3262 if (evdat->len != full_size) {
3263 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3264 "1603 Loopback test did not receive expected "
3265 "data length. actual length 0x%x expected "
3266 "length 0x%x\n",
3267 evdat->len, full_size);
3268 rc = -EIO;
3269 } else if (rx_databuf == NULL)
3270 rc = -EIO;
3271 else {
3272 rc = IOCB_SUCCESS;
3273 /* skip over elx loopback header */
3274 rx_databuf += ELX_LOOPBACK_HEADER_SZ;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003275 bsg_reply->reply_payload_rcv_len =
James Smart3b5dd522010-01-26 23:10:15 -05003276 sg_copy_from_buffer(job->reply_payload.sg_list,
3277 job->reply_payload.sg_cnt,
3278 rx_databuf, size);
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003279 bsg_reply->reply_payload_rcv_len = size;
James Smart3b5dd522010-01-26 23:10:15 -05003280 }
3281 }
3282
3283err_loopback_test_exit:
3284 lpfcdiag_loop_self_unreg(phba, rpi);
3285
3286 spin_lock_irqsave(&phba->ct_ev_lock, flags);
3287 lpfc_bsg_event_unref(evt); /* release ref */
3288 lpfc_bsg_event_unref(evt); /* delete */
3289 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
3290
James Smart5a0916b2013-07-15 18:31:42 -04003291 if ((cmdiocbq != NULL) && (iocb_stat != IOCB_TIMEDOUT))
James Smart3b5dd522010-01-26 23:10:15 -05003292 lpfc_sli_release_iocbq(phba, cmdiocbq);
3293
3294 if (rspiocbq != NULL)
3295 lpfc_sli_release_iocbq(phba, rspiocbq);
3296
3297 if (txbmp != NULL) {
3298 if (txbpl != NULL) {
3299 if (txbuffer != NULL)
3300 diag_cmd_data_free(phba, txbuffer);
3301 lpfc_mbuf_free(phba, txbmp->virt, txbmp->phys);
3302 }
3303 kfree(txbmp);
3304 }
3305
3306loopback_test_exit:
3307 kfree(dataout);
3308 /* make error code available to userspace */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003309 bsg_reply->result = rc;
James Smart3b5dd522010-01-26 23:10:15 -05003310 job->dd_data = NULL;
3311 /* complete the job back to userspace if no error */
James Smart1b511972011-12-13 13:23:09 -05003312 if (rc == IOCB_SUCCESS)
Johannes Thumshirn06548162016-11-17 10:31:22 +01003313 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01003314 bsg_reply->reply_payload_rcv_len);
James Smart3b5dd522010-01-26 23:10:15 -05003315 return rc;
3316}
3317
3318/**
3319 * lpfc_bsg_get_dfc_rev - process a GET_DFC_REV bsg vendor command
3320 * @job: GET_DFC_REV fc_bsg_job
3321 **/
3322static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01003323lpfc_bsg_get_dfc_rev(struct bsg_job *job)
James Smart3b5dd522010-01-26 23:10:15 -05003324{
Johannes Thumshirncd21c602016-11-17 10:31:14 +01003325 struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003326 struct fc_bsg_reply *bsg_reply = job->reply;
James Smart3b5dd522010-01-26 23:10:15 -05003327 struct lpfc_hba *phba = vport->phba;
James Smart3b5dd522010-01-26 23:10:15 -05003328 struct get_mgmt_rev_reply *event_reply;
3329 int rc = 0;
3330
3331 if (job->request_len <
3332 sizeof(struct fc_bsg_request) + sizeof(struct get_mgmt_rev)) {
3333 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
3334 "2740 Received GET_DFC_REV request below "
3335 "minimum size\n");
3336 rc = -EINVAL;
3337 goto job_error;
3338 }
3339
James Smart3b5dd522010-01-26 23:10:15 -05003340 event_reply = (struct get_mgmt_rev_reply *)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003341 bsg_reply->reply_data.vendor_reply.vendor_rsp;
James Smart3b5dd522010-01-26 23:10:15 -05003342
3343 if (job->reply_len <
3344 sizeof(struct fc_bsg_request) + sizeof(struct get_mgmt_rev_reply)) {
3345 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
3346 "2741 Received GET_DFC_REV reply below "
3347 "minimum size\n");
3348 rc = -EINVAL;
3349 goto job_error;
3350 }
3351
3352 event_reply->info.a_Major = MANAGEMENT_MAJOR_REV;
3353 event_reply->info.a_Minor = MANAGEMENT_MINOR_REV;
3354job_error:
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003355 bsg_reply->result = rc;
James Smart3b5dd522010-01-26 23:10:15 -05003356 if (rc == 0)
Johannes Thumshirn06548162016-11-17 10:31:22 +01003357 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01003358 bsg_reply->reply_payload_rcv_len);
James Smart3b5dd522010-01-26 23:10:15 -05003359 return rc;
3360}
3361
3362/**
James Smart7ad20aa2011-05-24 11:44:28 -04003363 * lpfc_bsg_issue_mbox_cmpl - lpfc_bsg_issue_mbox mbox completion handler
James Smart3b5dd522010-01-26 23:10:15 -05003364 * @phba: Pointer to HBA context object.
3365 * @pmboxq: Pointer to mailbox command.
3366 *
3367 * This is completion handler function for mailbox commands issued from
3368 * lpfc_bsg_issue_mbox function. This function is called by the
3369 * mailbox event handler function with no lock held. This function
3370 * will wake up thread waiting on the wait queue pointed by context1
3371 * of the mailbox.
3372 **/
Rashika Kheria9ab9b132014-09-03 12:55:46 -04003373static void
James Smart7ad20aa2011-05-24 11:44:28 -04003374lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
James Smart3b5dd522010-01-26 23:10:15 -05003375{
3376 struct bsg_job_data *dd_data;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003377 struct fc_bsg_reply *bsg_reply;
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01003378 struct bsg_job *job;
James Smart3b5dd522010-01-26 23:10:15 -05003379 uint32_t size;
3380 unsigned long flags;
James Smart7ad20aa2011-05-24 11:44:28 -04003381 uint8_t *pmb, *pmb_buf;
James Smart3b5dd522010-01-26 23:10:15 -05003382
James Smart3b5dd522010-01-26 23:10:15 -05003383 dd_data = pmboxq->context1;
James Smart3b5dd522010-01-26 23:10:15 -05003384
James Smart7ad20aa2011-05-24 11:44:28 -04003385 /*
3386 * The outgoing buffer is readily referred from the dma buffer,
3387 * just need to get header part from mailboxq structure.
James Smart7a470272010-03-15 11:25:20 -04003388 */
James Smart7ad20aa2011-05-24 11:44:28 -04003389 pmb = (uint8_t *)&pmboxq->u.mb;
3390 pmb_buf = (uint8_t *)dd_data->context_un.mbox.mb;
3391 memcpy(pmb_buf, pmb, sizeof(MAILBOX_t));
James Smart515e0aa2010-09-29 11:19:00 -04003392
James Smarta33c4f72013-03-01 16:36:00 -05003393 /* Determine if job has been aborted */
3394
3395 spin_lock_irqsave(&phba->ct_ev_lock, flags);
3396 job = dd_data->set_job;
3397 if (job) {
3398 /* Prevent timeout handling from trying to abort job */
3399 job->dd_data = NULL;
3400 }
3401 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
3402
3403 /* Copy the mailbox data to the job if it is still active */
3404
James Smart5a6f1332011-03-11 16:05:35 -05003405 if (job) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003406 bsg_reply = job->reply;
James Smart5a6f1332011-03-11 16:05:35 -05003407 size = job->reply_payload.payload_len;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003408 bsg_reply->reply_payload_rcv_len =
James Smart5a6f1332011-03-11 16:05:35 -05003409 sg_copy_from_buffer(job->reply_payload.sg_list,
James Smart7ad20aa2011-05-24 11:44:28 -04003410 job->reply_payload.sg_cnt,
3411 pmb_buf, size);
James Smart5a6f1332011-03-11 16:05:35 -05003412 }
James Smart7a470272010-03-15 11:25:20 -04003413
James Smarta33c4f72013-03-01 16:36:00 -05003414 dd_data->set_job = NULL;
James Smart3b5dd522010-01-26 23:10:15 -05003415 mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool);
James Smart7ad20aa2011-05-24 11:44:28 -04003416 lpfc_bsg_dma_page_free(phba, dd_data->context_un.mbox.dmabuffers);
James Smart3b5dd522010-01-26 23:10:15 -05003417 kfree(dd_data);
James Smart7ad20aa2011-05-24 11:44:28 -04003418
James Smarta33c4f72013-03-01 16:36:00 -05003419 /* Complete the job if the job is still active */
3420
James Smart7ad20aa2011-05-24 11:44:28 -04003421 if (job) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003422 bsg_reply->result = 0;
Johannes Thumshirn06548162016-11-17 10:31:22 +01003423 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01003424 bsg_reply->reply_payload_rcv_len);
James Smart7ad20aa2011-05-24 11:44:28 -04003425 }
James Smart3b5dd522010-01-26 23:10:15 -05003426 return;
3427}
3428
3429/**
3430 * lpfc_bsg_check_cmd_access - test for a supported mailbox command
3431 * @phba: Pointer to HBA context object.
3432 * @mb: Pointer to a mailbox object.
3433 * @vport: Pointer to a vport object.
3434 *
3435 * Some commands require the port to be offline, some may not be called from
3436 * the application.
3437 **/
3438static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba,
3439 MAILBOX_t *mb, struct lpfc_vport *vport)
3440{
3441 /* return negative error values for bsg job */
3442 switch (mb->mbxCommand) {
3443 /* Offline only */
3444 case MBX_INIT_LINK:
3445 case MBX_DOWN_LINK:
3446 case MBX_CONFIG_LINK:
3447 case MBX_CONFIG_RING:
3448 case MBX_RESET_RING:
3449 case MBX_UNREG_LOGIN:
3450 case MBX_CLEAR_LA:
3451 case MBX_DUMP_CONTEXT:
3452 case MBX_RUN_DIAGS:
3453 case MBX_RESTART:
3454 case MBX_SET_MASK:
3455 if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
3456 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
3457 "2743 Command 0x%x is illegal in on-line "
3458 "state\n",
3459 mb->mbxCommand);
3460 return -EPERM;
3461 }
3462 case MBX_WRITE_NV:
3463 case MBX_WRITE_VPARMS:
3464 case MBX_LOAD_SM:
3465 case MBX_READ_NV:
3466 case MBX_READ_CONFIG:
3467 case MBX_READ_RCONFIG:
3468 case MBX_READ_STATUS:
3469 case MBX_READ_XRI:
3470 case MBX_READ_REV:
3471 case MBX_READ_LNK_STAT:
3472 case MBX_DUMP_MEMORY:
3473 case MBX_DOWN_LOAD:
3474 case MBX_UPDATE_CFG:
3475 case MBX_KILL_BOARD:
James Smart06f35552013-05-31 17:04:50 -04003476 case MBX_READ_TOPOLOGY:
James Smart3b5dd522010-01-26 23:10:15 -05003477 case MBX_LOAD_AREA:
3478 case MBX_LOAD_EXP_ROM:
3479 case MBX_BEACON:
3480 case MBX_DEL_LD_ENTRY:
3481 case MBX_SET_DEBUG:
3482 case MBX_WRITE_WWN:
3483 case MBX_SLI4_CONFIG:
James Smartc7495932010-04-06 15:05:28 -04003484 case MBX_READ_EVENT_LOG:
James Smart3b5dd522010-01-26 23:10:15 -05003485 case MBX_READ_EVENT_LOG_STATUS:
3486 case MBX_WRITE_EVENT_LOG:
3487 case MBX_PORT_CAPABILITIES:
3488 case MBX_PORT_IOV_CONTROL:
James Smart7a470272010-03-15 11:25:20 -04003489 case MBX_RUN_BIU_DIAG64:
James Smart3b5dd522010-01-26 23:10:15 -05003490 break;
3491 case MBX_SET_VARIABLE:
James Smarte2aed292010-02-26 14:15:00 -05003492 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
3493 "1226 mbox: set_variable 0x%x, 0x%x\n",
3494 mb->un.varWords[0],
3495 mb->un.varWords[1]);
3496 if ((mb->un.varWords[0] == SETVAR_MLOMNT)
3497 && (mb->un.varWords[1] == 1)) {
3498 phba->wait_4_mlo_maint_flg = 1;
3499 } else if (mb->un.varWords[0] == SETVAR_MLORST) {
James Smart1b511972011-12-13 13:23:09 -05003500 spin_lock_irq(&phba->hbalock);
James Smarte2aed292010-02-26 14:15:00 -05003501 phba->link_flag &= ~LS_LOOPBACK_MODE;
James Smart1b511972011-12-13 13:23:09 -05003502 spin_unlock_irq(&phba->hbalock);
James Smart76a95d72010-11-20 23:11:48 -05003503 phba->fc_topology = LPFC_TOPOLOGY_PT_PT;
James Smarte2aed292010-02-26 14:15:00 -05003504 }
3505 break;
James Smart3b5dd522010-01-26 23:10:15 -05003506 case MBX_READ_SPARM64:
James Smart3b5dd522010-01-26 23:10:15 -05003507 case MBX_REG_LOGIN:
3508 case MBX_REG_LOGIN64:
3509 case MBX_CONFIG_PORT:
3510 case MBX_RUN_BIU_DIAG:
3511 default:
3512 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
3513 "2742 Unknown Command 0x%x\n",
3514 mb->mbxCommand);
3515 return -EPERM;
3516 }
3517
3518 return 0; /* ok */
3519}
3520
3521/**
James Smart7ad20aa2011-05-24 11:44:28 -04003522 * lpfc_bsg_mbox_ext_cleanup - clean up context of multi-buffer mbox session
3523 * @phba: Pointer to HBA context object.
3524 *
3525 * This is routine clean up and reset BSG handling of multi-buffer mbox
3526 * command session.
3527 **/
3528static void
3529lpfc_bsg_mbox_ext_session_reset(struct lpfc_hba *phba)
3530{
3531 if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_IDLE)
3532 return;
3533
3534 /* free all memory, including dma buffers */
3535 lpfc_bsg_dma_page_list_free(phba,
3536 &phba->mbox_ext_buf_ctx.ext_dmabuf_list);
3537 lpfc_bsg_dma_page_free(phba, phba->mbox_ext_buf_ctx.mbx_dmabuf);
3538 /* multi-buffer write mailbox command pass-through complete */
3539 memset((char *)&phba->mbox_ext_buf_ctx, 0,
3540 sizeof(struct lpfc_mbox_ext_buf_ctx));
3541 INIT_LIST_HEAD(&phba->mbox_ext_buf_ctx.ext_dmabuf_list);
3542
3543 return;
3544}
3545
3546/**
3547 * lpfc_bsg_issue_mbox_ext_handle_job - job handler for multi-buffer mbox cmpl
3548 * @phba: Pointer to HBA context object.
3549 * @pmboxq: Pointer to mailbox command.
3550 *
3551 * This is routine handles BSG job for mailbox commands completions with
3552 * multiple external buffers.
3553 **/
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01003554static struct bsg_job *
James Smart7ad20aa2011-05-24 11:44:28 -04003555lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
3556{
3557 struct bsg_job_data *dd_data;
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01003558 struct bsg_job *job;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003559 struct fc_bsg_reply *bsg_reply;
James Smart7ad20aa2011-05-24 11:44:28 -04003560 uint8_t *pmb, *pmb_buf;
3561 unsigned long flags;
3562 uint32_t size;
3563 int rc = 0;
James Smart026abb82011-12-13 13:20:45 -05003564 struct lpfc_dmabuf *dmabuf;
3565 struct lpfc_sli_config_mbox *sli_cfg_mbx;
3566 uint8_t *pmbx;
James Smart7ad20aa2011-05-24 11:44:28 -04003567
James Smart7ad20aa2011-05-24 11:44:28 -04003568 dd_data = pmboxq->context1;
James Smarta33c4f72013-03-01 16:36:00 -05003569
3570 /* Determine if job has been aborted */
3571 spin_lock_irqsave(&phba->ct_ev_lock, flags);
3572 job = dd_data->set_job;
3573 if (job) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003574 bsg_reply = job->reply;
James Smarta33c4f72013-03-01 16:36:00 -05003575 /* Prevent timeout handling from trying to abort job */
3576 job->dd_data = NULL;
James Smart7ad20aa2011-05-24 11:44:28 -04003577 }
James Smarta33c4f72013-03-01 16:36:00 -05003578 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
James Smart7ad20aa2011-05-24 11:44:28 -04003579
3580 /*
3581 * The outgoing buffer is readily referred from the dma buffer,
3582 * just need to get header part from mailboxq structure.
3583 */
James Smarta33c4f72013-03-01 16:36:00 -05003584
James Smart7ad20aa2011-05-24 11:44:28 -04003585 pmb = (uint8_t *)&pmboxq->u.mb;
3586 pmb_buf = (uint8_t *)dd_data->context_un.mbox.mb;
James Smart026abb82011-12-13 13:20:45 -05003587 /* Copy the byte swapped response mailbox back to the user */
James Smart7ad20aa2011-05-24 11:44:28 -04003588 memcpy(pmb_buf, pmb, sizeof(MAILBOX_t));
James Smart026abb82011-12-13 13:20:45 -05003589 /* if there is any non-embedded extended data copy that too */
3590 dmabuf = phba->mbox_ext_buf_ctx.mbx_dmabuf;
3591 sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;
3592 if (!bsg_bf_get(lpfc_mbox_hdr_emb,
3593 &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr)) {
3594 pmbx = (uint8_t *)dmabuf->virt;
3595 /* byte swap the extended data following the mailbox command */
3596 lpfc_sli_pcimem_bcopy(&pmbx[sizeof(MAILBOX_t)],
3597 &pmbx[sizeof(MAILBOX_t)],
3598 sli_cfg_mbx->un.sli_config_emb0_subsys.mse[0].buf_len);
3599 }
James Smart7ad20aa2011-05-24 11:44:28 -04003600
James Smarta33c4f72013-03-01 16:36:00 -05003601 /* Complete the job if the job is still active */
3602
James Smart7ad20aa2011-05-24 11:44:28 -04003603 if (job) {
3604 size = job->reply_payload.payload_len;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003605 bsg_reply->reply_payload_rcv_len =
James Smart7ad20aa2011-05-24 11:44:28 -04003606 sg_copy_from_buffer(job->reply_payload.sg_list,
3607 job->reply_payload.sg_cnt,
3608 pmb_buf, size);
James Smarta33c4f72013-03-01 16:36:00 -05003609
James Smart7ad20aa2011-05-24 11:44:28 -04003610 /* result for successful */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003611 bsg_reply->result = 0;
James Smarta33c4f72013-03-01 16:36:00 -05003612
James Smart7ad20aa2011-05-24 11:44:28 -04003613 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3614 "2937 SLI_CONFIG ext-buffer maibox command "
3615 "(x%x/x%x) complete bsg job done, bsize:%d\n",
3616 phba->mbox_ext_buf_ctx.nembType,
3617 phba->mbox_ext_buf_ctx.mboxType, size);
James Smartb76f2dc2011-07-22 18:37:42 -04003618 lpfc_idiag_mbxacc_dump_bsg_mbox(phba,
3619 phba->mbox_ext_buf_ctx.nembType,
3620 phba->mbox_ext_buf_ctx.mboxType,
3621 dma_ebuf, sta_pos_addr,
3622 phba->mbox_ext_buf_ctx.mbx_dmabuf, 0);
James Smarta33c4f72013-03-01 16:36:00 -05003623 } else {
James Smart7ad20aa2011-05-24 11:44:28 -04003624 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3625 "2938 SLI_CONFIG ext-buffer maibox "
3626 "command (x%x/x%x) failure, rc:x%x\n",
3627 phba->mbox_ext_buf_ctx.nembType,
3628 phba->mbox_ext_buf_ctx.mboxType, rc);
James Smarta33c4f72013-03-01 16:36:00 -05003629 }
3630
3631
James Smart7ad20aa2011-05-24 11:44:28 -04003632 /* state change */
3633 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_DONE;
3634 kfree(dd_data);
James Smart7ad20aa2011-05-24 11:44:28 -04003635 return job;
3636}
3637
3638/**
3639 * lpfc_bsg_issue_read_mbox_ext_cmpl - compl handler for multi-buffer read mbox
3640 * @phba: Pointer to HBA context object.
3641 * @pmboxq: Pointer to mailbox command.
3642 *
3643 * This is completion handler function for mailbox read commands with multiple
3644 * external buffers.
3645 **/
3646static void
3647lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
3648{
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01003649 struct bsg_job *job;
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01003650 struct fc_bsg_reply *bsg_reply;
James Smart7ad20aa2011-05-24 11:44:28 -04003651
James Smarta33c4f72013-03-01 16:36:00 -05003652 job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq);
3653
James Smart7ad20aa2011-05-24 11:44:28 -04003654 /* handle the BSG job with mailbox command */
James Smarta33c4f72013-03-01 16:36:00 -05003655 if (!job)
James Smart7ad20aa2011-05-24 11:44:28 -04003656 pmboxq->u.mb.mbxStatus = MBXERR_ERROR;
3657
3658 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3659 "2939 SLI_CONFIG ext-buffer rd maibox command "
3660 "complete, ctxState:x%x, mbxStatus:x%x\n",
3661 phba->mbox_ext_buf_ctx.state, pmboxq->u.mb.mbxStatus);
3662
James Smart7ad20aa2011-05-24 11:44:28 -04003663 if (pmboxq->u.mb.mbxStatus || phba->mbox_ext_buf_ctx.numBuf == 1)
3664 lpfc_bsg_mbox_ext_session_reset(phba);
3665
3666 /* free base driver mailbox structure memory */
3667 mempool_free(pmboxq, phba->mbox_mem_pool);
3668
James Smarta33c4f72013-03-01 16:36:00 -05003669 /* if the job is still active, call job done */
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01003670 if (job) {
3671 bsg_reply = job->reply;
Johannes Thumshirn06548162016-11-17 10:31:22 +01003672 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01003673 bsg_reply->reply_payload_rcv_len);
3674 }
James Smart7ad20aa2011-05-24 11:44:28 -04003675 return;
3676}
3677
3678/**
3679 * lpfc_bsg_issue_write_mbox_ext_cmpl - cmpl handler for multi-buffer write mbox
3680 * @phba: Pointer to HBA context object.
3681 * @pmboxq: Pointer to mailbox command.
3682 *
3683 * This is completion handler function for mailbox write commands with multiple
3684 * external buffers.
3685 **/
3686static void
3687lpfc_bsg_issue_write_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
3688{
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01003689 struct bsg_job *job;
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01003690 struct fc_bsg_reply *bsg_reply;
James Smart7ad20aa2011-05-24 11:44:28 -04003691
James Smarta33c4f72013-03-01 16:36:00 -05003692 job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq);
3693
James Smart7ad20aa2011-05-24 11:44:28 -04003694 /* handle the BSG job with the mailbox command */
James Smarta33c4f72013-03-01 16:36:00 -05003695 if (!job)
James Smart7ad20aa2011-05-24 11:44:28 -04003696 pmboxq->u.mb.mbxStatus = MBXERR_ERROR;
3697
3698 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3699 "2940 SLI_CONFIG ext-buffer wr maibox command "
3700 "complete, ctxState:x%x, mbxStatus:x%x\n",
3701 phba->mbox_ext_buf_ctx.state, pmboxq->u.mb.mbxStatus);
3702
James Smart7ad20aa2011-05-24 11:44:28 -04003703 /* free all memory, including dma buffers */
3704 mempool_free(pmboxq, phba->mbox_mem_pool);
3705 lpfc_bsg_mbox_ext_session_reset(phba);
3706
James Smarta33c4f72013-03-01 16:36:00 -05003707 /* if the job is still active, call job done */
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01003708 if (job) {
3709 bsg_reply = job->reply;
Johannes Thumshirn06548162016-11-17 10:31:22 +01003710 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01003711 bsg_reply->reply_payload_rcv_len);
3712 }
James Smart7ad20aa2011-05-24 11:44:28 -04003713
3714 return;
3715}
3716
3717static void
3718lpfc_bsg_sli_cfg_dma_desc_setup(struct lpfc_hba *phba, enum nemb_type nemb_tp,
3719 uint32_t index, struct lpfc_dmabuf *mbx_dmabuf,
3720 struct lpfc_dmabuf *ext_dmabuf)
3721{
3722 struct lpfc_sli_config_mbox *sli_cfg_mbx;
3723
3724 /* pointer to the start of mailbox command */
3725 sli_cfg_mbx = (struct lpfc_sli_config_mbox *)mbx_dmabuf->virt;
3726
3727 if (nemb_tp == nemb_mse) {
3728 if (index == 0) {
3729 sli_cfg_mbx->un.sli_config_emb0_subsys.
3730 mse[index].pa_hi =
3731 putPaddrHigh(mbx_dmabuf->phys +
3732 sizeof(MAILBOX_t));
3733 sli_cfg_mbx->un.sli_config_emb0_subsys.
3734 mse[index].pa_lo =
3735 putPaddrLow(mbx_dmabuf->phys +
3736 sizeof(MAILBOX_t));
3737 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3738 "2943 SLI_CONFIG(mse)[%d], "
3739 "bufLen:%d, addrHi:x%x, addrLo:x%x\n",
3740 index,
3741 sli_cfg_mbx->un.sli_config_emb0_subsys.
3742 mse[index].buf_len,
3743 sli_cfg_mbx->un.sli_config_emb0_subsys.
3744 mse[index].pa_hi,
3745 sli_cfg_mbx->un.sli_config_emb0_subsys.
3746 mse[index].pa_lo);
3747 } else {
3748 sli_cfg_mbx->un.sli_config_emb0_subsys.
3749 mse[index].pa_hi =
3750 putPaddrHigh(ext_dmabuf->phys);
3751 sli_cfg_mbx->un.sli_config_emb0_subsys.
3752 mse[index].pa_lo =
3753 putPaddrLow(ext_dmabuf->phys);
3754 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3755 "2944 SLI_CONFIG(mse)[%d], "
3756 "bufLen:%d, addrHi:x%x, addrLo:x%x\n",
3757 index,
3758 sli_cfg_mbx->un.sli_config_emb0_subsys.
3759 mse[index].buf_len,
3760 sli_cfg_mbx->un.sli_config_emb0_subsys.
3761 mse[index].pa_hi,
3762 sli_cfg_mbx->un.sli_config_emb0_subsys.
3763 mse[index].pa_lo);
3764 }
3765 } else {
3766 if (index == 0) {
3767 sli_cfg_mbx->un.sli_config_emb1_subsys.
3768 hbd[index].pa_hi =
3769 putPaddrHigh(mbx_dmabuf->phys +
3770 sizeof(MAILBOX_t));
3771 sli_cfg_mbx->un.sli_config_emb1_subsys.
3772 hbd[index].pa_lo =
3773 putPaddrLow(mbx_dmabuf->phys +
3774 sizeof(MAILBOX_t));
3775 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3776 "3007 SLI_CONFIG(hbd)[%d], "
3777 "bufLen:%d, addrHi:x%x, addrLo:x%x\n",
3778 index,
3779 bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len,
3780 &sli_cfg_mbx->un.
3781 sli_config_emb1_subsys.hbd[index]),
3782 sli_cfg_mbx->un.sli_config_emb1_subsys.
3783 hbd[index].pa_hi,
3784 sli_cfg_mbx->un.sli_config_emb1_subsys.
3785 hbd[index].pa_lo);
3786
3787 } else {
3788 sli_cfg_mbx->un.sli_config_emb1_subsys.
3789 hbd[index].pa_hi =
3790 putPaddrHigh(ext_dmabuf->phys);
3791 sli_cfg_mbx->un.sli_config_emb1_subsys.
3792 hbd[index].pa_lo =
3793 putPaddrLow(ext_dmabuf->phys);
3794 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3795 "3008 SLI_CONFIG(hbd)[%d], "
3796 "bufLen:%d, addrHi:x%x, addrLo:x%x\n",
3797 index,
3798 bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len,
3799 &sli_cfg_mbx->un.
3800 sli_config_emb1_subsys.hbd[index]),
3801 sli_cfg_mbx->un.sli_config_emb1_subsys.
3802 hbd[index].pa_hi,
3803 sli_cfg_mbx->un.sli_config_emb1_subsys.
3804 hbd[index].pa_lo);
3805 }
3806 }
3807 return;
3808}
3809
3810/**
3811 * lpfc_bsg_sli_cfg_mse_read_cmd_ext - sli_config non-embedded mailbox cmd read
3812 * @phba: Pointer to HBA context object.
3813 * @mb: Pointer to a BSG mailbox object.
3814 * @nemb_tp: Enumerate of non-embedded mailbox command type.
3815 * @dmabuff: Pointer to a DMA buffer descriptor.
3816 *
3817 * This routine performs SLI_CONFIG (0x9B) read mailbox command operation with
3818 * non-embedded external bufffers.
3819 **/
3820static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01003821lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job,
James Smart7ad20aa2011-05-24 11:44:28 -04003822 enum nemb_type nemb_tp,
3823 struct lpfc_dmabuf *dmabuf)
3824{
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003825 struct fc_bsg_request *bsg_request = job->request;
James Smart7ad20aa2011-05-24 11:44:28 -04003826 struct lpfc_sli_config_mbox *sli_cfg_mbx;
3827 struct dfc_mbox_req *mbox_req;
3828 struct lpfc_dmabuf *curr_dmabuf, *next_dmabuf;
3829 uint32_t ext_buf_cnt, ext_buf_index;
3830 struct lpfc_dmabuf *ext_dmabuf = NULL;
3831 struct bsg_job_data *dd_data = NULL;
3832 LPFC_MBOXQ_t *pmboxq = NULL;
3833 MAILBOX_t *pmb;
3834 uint8_t *pmbx;
3835 int rc, i;
3836
3837 mbox_req =
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01003838 (struct dfc_mbox_req *)bsg_request->rqst_data.h_vendor.vendor_cmd;
James Smart7ad20aa2011-05-24 11:44:28 -04003839
3840 /* pointer to the start of mailbox command */
3841 sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;
3842
3843 if (nemb_tp == nemb_mse) {
3844 ext_buf_cnt = bsg_bf_get(lpfc_mbox_hdr_mse_cnt,
3845 &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr);
3846 if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_MSE) {
3847 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3848 "2945 Handled SLI_CONFIG(mse) rd, "
3849 "ext_buf_cnt(%d) out of range(%d)\n",
3850 ext_buf_cnt,
3851 LPFC_MBX_SLI_CONFIG_MAX_MSE);
3852 rc = -ERANGE;
3853 goto job_error;
3854 }
3855 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3856 "2941 Handled SLI_CONFIG(mse) rd, "
3857 "ext_buf_cnt:%d\n", ext_buf_cnt);
3858 } else {
3859 /* sanity check on interface type for support */
3860 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
3861 LPFC_SLI_INTF_IF_TYPE_2) {
3862 rc = -ENODEV;
3863 goto job_error;
3864 }
3865 /* nemb_tp == nemb_hbd */
3866 ext_buf_cnt = sli_cfg_mbx->un.sli_config_emb1_subsys.hbd_count;
3867 if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_HBD) {
3868 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3869 "2946 Handled SLI_CONFIG(hbd) rd, "
3870 "ext_buf_cnt(%d) out of range(%d)\n",
3871 ext_buf_cnt,
3872 LPFC_MBX_SLI_CONFIG_MAX_HBD);
3873 rc = -ERANGE;
3874 goto job_error;
3875 }
3876 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3877 "2942 Handled SLI_CONFIG(hbd) rd, "
3878 "ext_buf_cnt:%d\n", ext_buf_cnt);
3879 }
3880
James Smartb76f2dc2011-07-22 18:37:42 -04003881 /* before dma descriptor setup */
3882 lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_rd, dma_mbox,
3883 sta_pre_addr, dmabuf, ext_buf_cnt);
3884
James Smart7ad20aa2011-05-24 11:44:28 -04003885 /* reject non-embedded mailbox command with none external buffer */
3886 if (ext_buf_cnt == 0) {
3887 rc = -EPERM;
3888 goto job_error;
3889 } else if (ext_buf_cnt > 1) {
3890 /* additional external read buffers */
3891 for (i = 1; i < ext_buf_cnt; i++) {
3892 ext_dmabuf = lpfc_bsg_dma_page_alloc(phba);
3893 if (!ext_dmabuf) {
3894 rc = -ENOMEM;
3895 goto job_error;
3896 }
3897 list_add_tail(&ext_dmabuf->list,
3898 &phba->mbox_ext_buf_ctx.ext_dmabuf_list);
3899 }
3900 }
3901
3902 /* bsg tracking structure */
3903 dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
3904 if (!dd_data) {
3905 rc = -ENOMEM;
3906 goto job_error;
3907 }
3908
3909 /* mailbox command structure for base driver */
3910 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
3911 if (!pmboxq) {
3912 rc = -ENOMEM;
3913 goto job_error;
3914 }
3915 memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
3916
3917 /* for the first external buffer */
3918 lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf);
3919
3920 /* for the rest of external buffer descriptors if any */
3921 if (ext_buf_cnt > 1) {
3922 ext_buf_index = 1;
3923 list_for_each_entry_safe(curr_dmabuf, next_dmabuf,
3924 &phba->mbox_ext_buf_ctx.ext_dmabuf_list, list) {
3925 lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp,
3926 ext_buf_index, dmabuf,
3927 curr_dmabuf);
3928 ext_buf_index++;
3929 }
3930 }
3931
James Smartb76f2dc2011-07-22 18:37:42 -04003932 /* after dma descriptor setup */
3933 lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_rd, dma_mbox,
3934 sta_pos_addr, dmabuf, ext_buf_cnt);
3935
James Smart7ad20aa2011-05-24 11:44:28 -04003936 /* construct base driver mbox command */
3937 pmb = &pmboxq->u.mb;
3938 pmbx = (uint8_t *)dmabuf->virt;
3939 memcpy(pmb, pmbx, sizeof(*pmb));
3940 pmb->mbxOwner = OWN_HOST;
3941 pmboxq->vport = phba->pport;
3942
3943 /* multi-buffer handling context */
3944 phba->mbox_ext_buf_ctx.nembType = nemb_tp;
3945 phba->mbox_ext_buf_ctx.mboxType = mbox_rd;
3946 phba->mbox_ext_buf_ctx.numBuf = ext_buf_cnt;
3947 phba->mbox_ext_buf_ctx.mbxTag = mbox_req->extMboxTag;
3948 phba->mbox_ext_buf_ctx.seqNum = mbox_req->extSeqNum;
3949 phba->mbox_ext_buf_ctx.mbx_dmabuf = dmabuf;
3950
3951 /* callback for multi-buffer read mailbox command */
3952 pmboxq->mbox_cmpl = lpfc_bsg_issue_read_mbox_ext_cmpl;
3953
3954 /* context fields to callback function */
3955 pmboxq->context1 = dd_data;
3956 dd_data->type = TYPE_MBOX;
James Smarta33c4f72013-03-01 16:36:00 -05003957 dd_data->set_job = job;
James Smart7ad20aa2011-05-24 11:44:28 -04003958 dd_data->context_un.mbox.pmboxq = pmboxq;
3959 dd_data->context_un.mbox.mb = (MAILBOX_t *)pmbx;
James Smart7ad20aa2011-05-24 11:44:28 -04003960 job->dd_data = dd_data;
3961
3962 /* state change */
3963 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT;
3964
James Smart026abb82011-12-13 13:20:45 -05003965 /*
3966 * Non-embedded mailbox subcommand data gets byte swapped here because
3967 * the lower level driver code only does the first 64 mailbox words.
3968 */
3969 if ((!bsg_bf_get(lpfc_mbox_hdr_emb,
3970 &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr)) &&
3971 (nemb_tp == nemb_mse))
3972 lpfc_sli_pcimem_bcopy(&pmbx[sizeof(MAILBOX_t)],
3973 &pmbx[sizeof(MAILBOX_t)],
3974 sli_cfg_mbx->un.sli_config_emb0_subsys.
3975 mse[0].buf_len);
3976
James Smart7ad20aa2011-05-24 11:44:28 -04003977 rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
3978 if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) {
3979 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
3980 "2947 Issued SLI_CONFIG ext-buffer "
3981 "maibox command, rc:x%x\n", rc);
James Smart88a2cfb2011-07-22 18:36:33 -04003982 return SLI_CONFIG_HANDLED;
James Smart7ad20aa2011-05-24 11:44:28 -04003983 }
3984 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
3985 "2948 Failed to issue SLI_CONFIG ext-buffer "
3986 "maibox command, rc:x%x\n", rc);
3987 rc = -EPIPE;
3988
3989job_error:
3990 if (pmboxq)
3991 mempool_free(pmboxq, phba->mbox_mem_pool);
3992 lpfc_bsg_dma_page_list_free(phba,
3993 &phba->mbox_ext_buf_ctx.ext_dmabuf_list);
3994 kfree(dd_data);
3995 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_IDLE;
3996 return rc;
3997}
3998
3999/**
4000 * lpfc_bsg_sli_cfg_write_cmd_ext - sli_config non-embedded mailbox cmd write
4001 * @phba: Pointer to HBA context object.
4002 * @mb: Pointer to a BSG mailbox object.
4003 * @dmabuff: Pointer to a DMA buffer descriptor.
4004 *
4005 * This routine performs SLI_CONFIG (0x9B) write mailbox command operation with
4006 * non-embedded external bufffers.
4007 **/
4008static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01004009lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job,
James Smart7ad20aa2011-05-24 11:44:28 -04004010 enum nemb_type nemb_tp,
4011 struct lpfc_dmabuf *dmabuf)
4012{
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004013 struct fc_bsg_request *bsg_request = job->request;
4014 struct fc_bsg_reply *bsg_reply = job->reply;
James Smart7ad20aa2011-05-24 11:44:28 -04004015 struct dfc_mbox_req *mbox_req;
4016 struct lpfc_sli_config_mbox *sli_cfg_mbx;
4017 uint32_t ext_buf_cnt;
4018 struct bsg_job_data *dd_data = NULL;
4019 LPFC_MBOXQ_t *pmboxq = NULL;
4020 MAILBOX_t *pmb;
4021 uint8_t *mbx;
James Smart88a2cfb2011-07-22 18:36:33 -04004022 int rc = SLI_CONFIG_NOT_HANDLED, i;
James Smart7ad20aa2011-05-24 11:44:28 -04004023
4024 mbox_req =
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004025 (struct dfc_mbox_req *)bsg_request->rqst_data.h_vendor.vendor_cmd;
James Smart7ad20aa2011-05-24 11:44:28 -04004026
4027 /* pointer to the start of mailbox command */
4028 sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;
4029
4030 if (nemb_tp == nemb_mse) {
4031 ext_buf_cnt = bsg_bf_get(lpfc_mbox_hdr_mse_cnt,
4032 &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr);
4033 if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_MSE) {
4034 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
James Smart026abb82011-12-13 13:20:45 -05004035 "2953 Failed SLI_CONFIG(mse) wr, "
James Smart7ad20aa2011-05-24 11:44:28 -04004036 "ext_buf_cnt(%d) out of range(%d)\n",
4037 ext_buf_cnt,
4038 LPFC_MBX_SLI_CONFIG_MAX_MSE);
4039 return -ERANGE;
4040 }
4041 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4042 "2949 Handled SLI_CONFIG(mse) wr, "
4043 "ext_buf_cnt:%d\n", ext_buf_cnt);
4044 } else {
4045 /* sanity check on interface type for support */
4046 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
4047 LPFC_SLI_INTF_IF_TYPE_2)
4048 return -ENODEV;
4049 /* nemb_tp == nemb_hbd */
4050 ext_buf_cnt = sli_cfg_mbx->un.sli_config_emb1_subsys.hbd_count;
4051 if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_HBD) {
4052 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
James Smart026abb82011-12-13 13:20:45 -05004053 "2954 Failed SLI_CONFIG(hbd) wr, "
James Smart7ad20aa2011-05-24 11:44:28 -04004054 "ext_buf_cnt(%d) out of range(%d)\n",
4055 ext_buf_cnt,
4056 LPFC_MBX_SLI_CONFIG_MAX_HBD);
4057 return -ERANGE;
4058 }
4059 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4060 "2950 Handled SLI_CONFIG(hbd) wr, "
4061 "ext_buf_cnt:%d\n", ext_buf_cnt);
4062 }
4063
James Smartb76f2dc2011-07-22 18:37:42 -04004064 /* before dma buffer descriptor setup */
4065 lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_wr, dma_mbox,
4066 sta_pre_addr, dmabuf, ext_buf_cnt);
4067
James Smart7ad20aa2011-05-24 11:44:28 -04004068 if (ext_buf_cnt == 0)
4069 return -EPERM;
4070
4071 /* for the first external buffer */
4072 lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf);
4073
James Smartb76f2dc2011-07-22 18:37:42 -04004074 /* after dma descriptor setup */
4075 lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_wr, dma_mbox,
4076 sta_pos_addr, dmabuf, ext_buf_cnt);
4077
James Smart7ad20aa2011-05-24 11:44:28 -04004078 /* log for looking forward */
4079 for (i = 1; i < ext_buf_cnt; i++) {
4080 if (nemb_tp == nemb_mse)
4081 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4082 "2951 SLI_CONFIG(mse), buf[%d]-length:%d\n",
4083 i, sli_cfg_mbx->un.sli_config_emb0_subsys.
4084 mse[i].buf_len);
4085 else
4086 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4087 "2952 SLI_CONFIG(hbd), buf[%d]-length:%d\n",
4088 i, bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len,
4089 &sli_cfg_mbx->un.sli_config_emb1_subsys.
4090 hbd[i]));
4091 }
4092
4093 /* multi-buffer handling context */
4094 phba->mbox_ext_buf_ctx.nembType = nemb_tp;
4095 phba->mbox_ext_buf_ctx.mboxType = mbox_wr;
4096 phba->mbox_ext_buf_ctx.numBuf = ext_buf_cnt;
4097 phba->mbox_ext_buf_ctx.mbxTag = mbox_req->extMboxTag;
4098 phba->mbox_ext_buf_ctx.seqNum = mbox_req->extSeqNum;
4099 phba->mbox_ext_buf_ctx.mbx_dmabuf = dmabuf;
4100
4101 if (ext_buf_cnt == 1) {
4102 /* bsg tracking structure */
4103 dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
4104 if (!dd_data) {
4105 rc = -ENOMEM;
4106 goto job_error;
4107 }
4108
4109 /* mailbox command structure for base driver */
4110 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
4111 if (!pmboxq) {
4112 rc = -ENOMEM;
4113 goto job_error;
4114 }
4115 memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
4116 pmb = &pmboxq->u.mb;
4117 mbx = (uint8_t *)dmabuf->virt;
4118 memcpy(pmb, mbx, sizeof(*pmb));
4119 pmb->mbxOwner = OWN_HOST;
4120 pmboxq->vport = phba->pport;
4121
4122 /* callback for multi-buffer read mailbox command */
4123 pmboxq->mbox_cmpl = lpfc_bsg_issue_write_mbox_ext_cmpl;
4124
4125 /* context fields to callback function */
4126 pmboxq->context1 = dd_data;
4127 dd_data->type = TYPE_MBOX;
James Smarta33c4f72013-03-01 16:36:00 -05004128 dd_data->set_job = job;
James Smart7ad20aa2011-05-24 11:44:28 -04004129 dd_data->context_un.mbox.pmboxq = pmboxq;
4130 dd_data->context_un.mbox.mb = (MAILBOX_t *)mbx;
James Smart7ad20aa2011-05-24 11:44:28 -04004131 job->dd_data = dd_data;
4132
4133 /* state change */
James Smart7ad20aa2011-05-24 11:44:28 -04004134
James Smarta33c4f72013-03-01 16:36:00 -05004135 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT;
James Smart7ad20aa2011-05-24 11:44:28 -04004136 rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
4137 if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) {
4138 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4139 "2955 Issued SLI_CONFIG ext-buffer "
4140 "maibox command, rc:x%x\n", rc);
James Smart88a2cfb2011-07-22 18:36:33 -04004141 return SLI_CONFIG_HANDLED;
James Smart7ad20aa2011-05-24 11:44:28 -04004142 }
4143 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
4144 "2956 Failed to issue SLI_CONFIG ext-buffer "
4145 "maibox command, rc:x%x\n", rc);
4146 rc = -EPIPE;
James Smart026abb82011-12-13 13:20:45 -05004147 goto job_error;
James Smart7ad20aa2011-05-24 11:44:28 -04004148 }
4149
James Smart88a2cfb2011-07-22 18:36:33 -04004150 /* wait for additoinal external buffers */
James Smarta33c4f72013-03-01 16:36:00 -05004151
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004152 bsg_reply->result = 0;
Johannes Thumshirn06548162016-11-17 10:31:22 +01004153 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01004154 bsg_reply->reply_payload_rcv_len);
James Smart88a2cfb2011-07-22 18:36:33 -04004155 return SLI_CONFIG_HANDLED;
4156
James Smart7ad20aa2011-05-24 11:44:28 -04004157job_error:
4158 if (pmboxq)
4159 mempool_free(pmboxq, phba->mbox_mem_pool);
4160 kfree(dd_data);
4161
4162 return rc;
4163}
4164
4165/**
4166 * lpfc_bsg_handle_sli_cfg_mbox - handle sli-cfg mailbox cmd with ext buffer
4167 * @phba: Pointer to HBA context object.
4168 * @mb: Pointer to a BSG mailbox object.
4169 * @dmabuff: Pointer to a DMA buffer descriptor.
4170 *
4171 * This routine handles SLI_CONFIG (0x9B) mailbox command with non-embedded
4172 * external bufffers, including both 0x9B with non-embedded MSEs and 0x9B
4173 * with embedded sussystem 0x1 and opcodes with external HBDs.
4174 **/
4175static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01004176lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct bsg_job *job,
James Smart7ad20aa2011-05-24 11:44:28 -04004177 struct lpfc_dmabuf *dmabuf)
4178{
4179 struct lpfc_sli_config_mbox *sli_cfg_mbx;
4180 uint32_t subsys;
4181 uint32_t opcode;
4182 int rc = SLI_CONFIG_NOT_HANDLED;
4183
James Smart026abb82011-12-13 13:20:45 -05004184 /* state change on new multi-buffer pass-through mailbox command */
James Smart7ad20aa2011-05-24 11:44:28 -04004185 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_HOST;
4186
4187 sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;
4188
4189 if (!bsg_bf_get(lpfc_mbox_hdr_emb,
4190 &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr)) {
4191 subsys = bsg_bf_get(lpfc_emb0_subcmnd_subsys,
4192 &sli_cfg_mbx->un.sli_config_emb0_subsys);
4193 opcode = bsg_bf_get(lpfc_emb0_subcmnd_opcode,
4194 &sli_cfg_mbx->un.sli_config_emb0_subsys);
4195 if (subsys == SLI_CONFIG_SUBSYS_FCOE) {
4196 switch (opcode) {
4197 case FCOE_OPCODE_READ_FCF:
James Smart2a2719d2014-02-20 09:56:28 -05004198 case FCOE_OPCODE_GET_DPORT_RESULTS:
James Smart7ad20aa2011-05-24 11:44:28 -04004199 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4200 "2957 Handled SLI_CONFIG "
4201 "subsys_fcoe, opcode:x%x\n",
4202 opcode);
4203 rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job,
4204 nemb_mse, dmabuf);
4205 break;
4206 case FCOE_OPCODE_ADD_FCF:
James Smart2a2719d2014-02-20 09:56:28 -05004207 case FCOE_OPCODE_SET_DPORT_MODE:
4208 case LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE:
James Smart7ad20aa2011-05-24 11:44:28 -04004209 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4210 "2958 Handled SLI_CONFIG "
4211 "subsys_fcoe, opcode:x%x\n",
4212 opcode);
4213 rc = lpfc_bsg_sli_cfg_write_cmd_ext(phba, job,
4214 nemb_mse, dmabuf);
4215 break;
4216 default:
4217 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
James Smart026abb82011-12-13 13:20:45 -05004218 "2959 Reject SLI_CONFIG "
James Smart7ad20aa2011-05-24 11:44:28 -04004219 "subsys_fcoe, opcode:x%x\n",
4220 opcode);
James Smart026abb82011-12-13 13:20:45 -05004221 rc = -EPERM;
4222 break;
4223 }
4224 } else if (subsys == SLI_CONFIG_SUBSYS_COMN) {
4225 switch (opcode) {
4226 case COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES:
James Smartb99570d2012-05-09 21:16:24 -04004227 case COMN_OPCODE_GET_CNTL_ATTRIBUTES:
James Smartc6377972015-04-07 15:07:10 -04004228 case COMN_OPCODE_GET_PROFILE_CONFIG:
James Smart026abb82011-12-13 13:20:45 -05004229 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4230 "3106 Handled SLI_CONFIG "
James Smart6b5151f2012-01-18 16:24:06 -05004231 "subsys_comn, opcode:x%x\n",
James Smart026abb82011-12-13 13:20:45 -05004232 opcode);
4233 rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job,
4234 nemb_mse, dmabuf);
4235 break;
4236 default:
4237 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4238 "3107 Reject SLI_CONFIG "
James Smart6b5151f2012-01-18 16:24:06 -05004239 "subsys_comn, opcode:x%x\n",
James Smart026abb82011-12-13 13:20:45 -05004240 opcode);
4241 rc = -EPERM;
James Smart7ad20aa2011-05-24 11:44:28 -04004242 break;
4243 }
4244 } else {
4245 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
James Smart026abb82011-12-13 13:20:45 -05004246 "2977 Reject SLI_CONFIG "
James Smart7ad20aa2011-05-24 11:44:28 -04004247 "subsys:x%d, opcode:x%x\n",
4248 subsys, opcode);
James Smart026abb82011-12-13 13:20:45 -05004249 rc = -EPERM;
James Smart7ad20aa2011-05-24 11:44:28 -04004250 }
4251 } else {
4252 subsys = bsg_bf_get(lpfc_emb1_subcmnd_subsys,
4253 &sli_cfg_mbx->un.sli_config_emb1_subsys);
4254 opcode = bsg_bf_get(lpfc_emb1_subcmnd_opcode,
4255 &sli_cfg_mbx->un.sli_config_emb1_subsys);
4256 if (subsys == SLI_CONFIG_SUBSYS_COMN) {
4257 switch (opcode) {
4258 case COMN_OPCODE_READ_OBJECT:
4259 case COMN_OPCODE_READ_OBJECT_LIST:
4260 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4261 "2960 Handled SLI_CONFIG "
4262 "subsys_comn, opcode:x%x\n",
4263 opcode);
4264 rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job,
4265 nemb_hbd, dmabuf);
4266 break;
4267 case COMN_OPCODE_WRITE_OBJECT:
4268 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4269 "2961 Handled SLI_CONFIG "
4270 "subsys_comn, opcode:x%x\n",
4271 opcode);
4272 rc = lpfc_bsg_sli_cfg_write_cmd_ext(phba, job,
4273 nemb_hbd, dmabuf);
4274 break;
4275 default:
4276 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4277 "2962 Not handled SLI_CONFIG "
4278 "subsys_comn, opcode:x%x\n",
4279 opcode);
4280 rc = SLI_CONFIG_NOT_HANDLED;
4281 break;
4282 }
4283 } else {
4284 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
James Smart026abb82011-12-13 13:20:45 -05004285 "2978 Not handled SLI_CONFIG "
James Smart7ad20aa2011-05-24 11:44:28 -04004286 "subsys:x%d, opcode:x%x\n",
4287 subsys, opcode);
4288 rc = SLI_CONFIG_NOT_HANDLED;
4289 }
4290 }
James Smart026abb82011-12-13 13:20:45 -05004291
4292 /* state reset on not handled new multi-buffer mailbox command */
4293 if (rc != SLI_CONFIG_HANDLED)
4294 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_IDLE;
4295
James Smart7ad20aa2011-05-24 11:44:28 -04004296 return rc;
4297}
4298
4299/**
4300 * lpfc_bsg_mbox_ext_abort_req - request to abort mbox command with ext buffers
4301 * @phba: Pointer to HBA context object.
4302 *
4303 * This routine is for requesting to abort a pass-through mailbox command with
4304 * multiple external buffers due to error condition.
4305 **/
4306static void
4307lpfc_bsg_mbox_ext_abort(struct lpfc_hba *phba)
4308{
4309 if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_PORT)
4310 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_ABTS;
4311 else
4312 lpfc_bsg_mbox_ext_session_reset(phba);
4313 return;
4314}
4315
4316/**
4317 * lpfc_bsg_read_ebuf_get - get the next mailbox read external buffer
4318 * @phba: Pointer to HBA context object.
4319 * @dmabuf: Pointer to a DMA buffer descriptor.
4320 *
4321 * This routine extracts the next mailbox read external buffer back to
4322 * user space through BSG.
4323 **/
4324static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01004325lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct bsg_job *job)
James Smart7ad20aa2011-05-24 11:44:28 -04004326{
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004327 struct fc_bsg_reply *bsg_reply = job->reply;
James Smart7ad20aa2011-05-24 11:44:28 -04004328 struct lpfc_sli_config_mbox *sli_cfg_mbx;
4329 struct lpfc_dmabuf *dmabuf;
4330 uint8_t *pbuf;
4331 uint32_t size;
4332 uint32_t index;
4333
4334 index = phba->mbox_ext_buf_ctx.seqNum;
4335 phba->mbox_ext_buf_ctx.seqNum++;
4336
4337 sli_cfg_mbx = (struct lpfc_sli_config_mbox *)
4338 phba->mbox_ext_buf_ctx.mbx_dmabuf->virt;
4339
4340 if (phba->mbox_ext_buf_ctx.nembType == nemb_mse) {
4341 size = bsg_bf_get(lpfc_mbox_sli_config_mse_len,
4342 &sli_cfg_mbx->un.sli_config_emb0_subsys.mse[index]);
4343 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4344 "2963 SLI_CONFIG (mse) ext-buffer rd get "
4345 "buffer[%d], size:%d\n", index, size);
4346 } else {
4347 size = bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len,
4348 &sli_cfg_mbx->un.sli_config_emb1_subsys.hbd[index]);
4349 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4350 "2964 SLI_CONFIG (hbd) ext-buffer rd get "
4351 "buffer[%d], size:%d\n", index, size);
4352 }
4353 if (list_empty(&phba->mbox_ext_buf_ctx.ext_dmabuf_list))
4354 return -EPIPE;
4355 dmabuf = list_first_entry(&phba->mbox_ext_buf_ctx.ext_dmabuf_list,
4356 struct lpfc_dmabuf, list);
4357 list_del_init(&dmabuf->list);
James Smartb76f2dc2011-07-22 18:37:42 -04004358
4359 /* after dma buffer descriptor setup */
4360 lpfc_idiag_mbxacc_dump_bsg_mbox(phba, phba->mbox_ext_buf_ctx.nembType,
4361 mbox_rd, dma_ebuf, sta_pos_addr,
4362 dmabuf, index);
4363
James Smart7ad20aa2011-05-24 11:44:28 -04004364 pbuf = (uint8_t *)dmabuf->virt;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004365 bsg_reply->reply_payload_rcv_len =
James Smart7ad20aa2011-05-24 11:44:28 -04004366 sg_copy_from_buffer(job->reply_payload.sg_list,
4367 job->reply_payload.sg_cnt,
4368 pbuf, size);
4369
4370 lpfc_bsg_dma_page_free(phba, dmabuf);
4371
4372 if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) {
4373 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4374 "2965 SLI_CONFIG (hbd) ext-buffer rd mbox "
4375 "command session done\n");
4376 lpfc_bsg_mbox_ext_session_reset(phba);
4377 }
4378
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004379 bsg_reply->result = 0;
Johannes Thumshirn06548162016-11-17 10:31:22 +01004380 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01004381 bsg_reply->reply_payload_rcv_len);
James Smart7ad20aa2011-05-24 11:44:28 -04004382
4383 return SLI_CONFIG_HANDLED;
4384}
4385
4386/**
4387 * lpfc_bsg_write_ebuf_set - set the next mailbox write external buffer
4388 * @phba: Pointer to HBA context object.
4389 * @dmabuf: Pointer to a DMA buffer descriptor.
4390 *
4391 * This routine sets up the next mailbox read external buffer obtained
4392 * from user space through BSG.
4393 **/
4394static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01004395lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct bsg_job *job,
James Smart7ad20aa2011-05-24 11:44:28 -04004396 struct lpfc_dmabuf *dmabuf)
4397{
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004398 struct fc_bsg_reply *bsg_reply = job->reply;
James Smart7ad20aa2011-05-24 11:44:28 -04004399 struct bsg_job_data *dd_data = NULL;
4400 LPFC_MBOXQ_t *pmboxq = NULL;
4401 MAILBOX_t *pmb;
4402 enum nemb_type nemb_tp;
4403 uint8_t *pbuf;
4404 uint32_t size;
4405 uint32_t index;
4406 int rc;
4407
4408 index = phba->mbox_ext_buf_ctx.seqNum;
4409 phba->mbox_ext_buf_ctx.seqNum++;
4410 nemb_tp = phba->mbox_ext_buf_ctx.nembType;
4411
James Smart7ad20aa2011-05-24 11:44:28 -04004412 dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
4413 if (!dd_data) {
4414 rc = -ENOMEM;
4415 goto job_error;
4416 }
4417
4418 pbuf = (uint8_t *)dmabuf->virt;
4419 size = job->request_payload.payload_len;
4420 sg_copy_to_buffer(job->request_payload.sg_list,
4421 job->request_payload.sg_cnt,
4422 pbuf, size);
4423
4424 if (phba->mbox_ext_buf_ctx.nembType == nemb_mse) {
4425 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4426 "2966 SLI_CONFIG (mse) ext-buffer wr set "
4427 "buffer[%d], size:%d\n",
4428 phba->mbox_ext_buf_ctx.seqNum, size);
4429
4430 } else {
4431 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4432 "2967 SLI_CONFIG (hbd) ext-buffer wr set "
4433 "buffer[%d], size:%d\n",
4434 phba->mbox_ext_buf_ctx.seqNum, size);
4435
4436 }
4437
4438 /* set up external buffer descriptor and add to external buffer list */
4439 lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, index,
4440 phba->mbox_ext_buf_ctx.mbx_dmabuf,
4441 dmabuf);
4442 list_add_tail(&dmabuf->list, &phba->mbox_ext_buf_ctx.ext_dmabuf_list);
4443
James Smartb76f2dc2011-07-22 18:37:42 -04004444 /* after write dma buffer */
4445 lpfc_idiag_mbxacc_dump_bsg_mbox(phba, phba->mbox_ext_buf_ctx.nembType,
4446 mbox_wr, dma_ebuf, sta_pos_addr,
4447 dmabuf, index);
4448
James Smart7ad20aa2011-05-24 11:44:28 -04004449 if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) {
4450 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4451 "2968 SLI_CONFIG ext-buffer wr all %d "
4452 "ebuffers received\n",
4453 phba->mbox_ext_buf_ctx.numBuf);
4454 /* mailbox command structure for base driver */
4455 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
4456 if (!pmboxq) {
4457 rc = -ENOMEM;
4458 goto job_error;
4459 }
4460 memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
4461 pbuf = (uint8_t *)phba->mbox_ext_buf_ctx.mbx_dmabuf->virt;
4462 pmb = &pmboxq->u.mb;
4463 memcpy(pmb, pbuf, sizeof(*pmb));
4464 pmb->mbxOwner = OWN_HOST;
4465 pmboxq->vport = phba->pport;
4466
4467 /* callback for multi-buffer write mailbox command */
4468 pmboxq->mbox_cmpl = lpfc_bsg_issue_write_mbox_ext_cmpl;
4469
4470 /* context fields to callback function */
4471 pmboxq->context1 = dd_data;
4472 dd_data->type = TYPE_MBOX;
James Smarta33c4f72013-03-01 16:36:00 -05004473 dd_data->set_job = job;
James Smart7ad20aa2011-05-24 11:44:28 -04004474 dd_data->context_un.mbox.pmboxq = pmboxq;
4475 dd_data->context_un.mbox.mb = (MAILBOX_t *)pbuf;
James Smart7ad20aa2011-05-24 11:44:28 -04004476 job->dd_data = dd_data;
4477
4478 /* state change */
4479 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT;
4480
4481 rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
4482 if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) {
4483 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4484 "2969 Issued SLI_CONFIG ext-buffer "
4485 "maibox command, rc:x%x\n", rc);
James Smart88a2cfb2011-07-22 18:36:33 -04004486 return SLI_CONFIG_HANDLED;
James Smart7ad20aa2011-05-24 11:44:28 -04004487 }
4488 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
4489 "2970 Failed to issue SLI_CONFIG ext-buffer "
4490 "maibox command, rc:x%x\n", rc);
4491 rc = -EPIPE;
4492 goto job_error;
4493 }
4494
4495 /* wait for additoinal external buffers */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004496 bsg_reply->result = 0;
Johannes Thumshirn06548162016-11-17 10:31:22 +01004497 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01004498 bsg_reply->reply_payload_rcv_len);
James Smart7ad20aa2011-05-24 11:44:28 -04004499 return SLI_CONFIG_HANDLED;
4500
4501job_error:
4502 lpfc_bsg_dma_page_free(phba, dmabuf);
4503 kfree(dd_data);
4504
4505 return rc;
4506}
4507
4508/**
4509 * lpfc_bsg_handle_sli_cfg_ebuf - handle ext buffer with sli-cfg mailbox cmd
4510 * @phba: Pointer to HBA context object.
4511 * @mb: Pointer to a BSG mailbox object.
4512 * @dmabuff: Pointer to a DMA buffer descriptor.
4513 *
4514 * This routine handles the external buffer with SLI_CONFIG (0x9B) mailbox
4515 * command with multiple non-embedded external buffers.
4516 **/
4517static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01004518lpfc_bsg_handle_sli_cfg_ebuf(struct lpfc_hba *phba, struct bsg_job *job,
James Smart7ad20aa2011-05-24 11:44:28 -04004519 struct lpfc_dmabuf *dmabuf)
4520{
4521 int rc;
4522
4523 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4524 "2971 SLI_CONFIG buffer (type:x%x)\n",
4525 phba->mbox_ext_buf_ctx.mboxType);
4526
4527 if (phba->mbox_ext_buf_ctx.mboxType == mbox_rd) {
4528 if (phba->mbox_ext_buf_ctx.state != LPFC_BSG_MBOX_DONE) {
4529 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
4530 "2972 SLI_CONFIG rd buffer state "
4531 "mismatch:x%x\n",
4532 phba->mbox_ext_buf_ctx.state);
4533 lpfc_bsg_mbox_ext_abort(phba);
4534 return -EPIPE;
4535 }
4536 rc = lpfc_bsg_read_ebuf_get(phba, job);
4537 if (rc == SLI_CONFIG_HANDLED)
4538 lpfc_bsg_dma_page_free(phba, dmabuf);
4539 } else { /* phba->mbox_ext_buf_ctx.mboxType == mbox_wr */
4540 if (phba->mbox_ext_buf_ctx.state != LPFC_BSG_MBOX_HOST) {
4541 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
4542 "2973 SLI_CONFIG wr buffer state "
4543 "mismatch:x%x\n",
4544 phba->mbox_ext_buf_ctx.state);
4545 lpfc_bsg_mbox_ext_abort(phba);
4546 return -EPIPE;
4547 }
4548 rc = lpfc_bsg_write_ebuf_set(phba, job, dmabuf);
4549 }
4550 return rc;
4551}
4552
4553/**
4554 * lpfc_bsg_handle_sli_cfg_ext - handle sli-cfg mailbox with external buffer
4555 * @phba: Pointer to HBA context object.
4556 * @mb: Pointer to a BSG mailbox object.
4557 * @dmabuff: Pointer to a DMA buffer descriptor.
4558 *
4559 * This routine checkes and handles non-embedded multi-buffer SLI_CONFIG
4560 * (0x9B) mailbox commands and external buffers.
4561 **/
4562static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01004563lpfc_bsg_handle_sli_cfg_ext(struct lpfc_hba *phba, struct bsg_job *job,
James Smart7ad20aa2011-05-24 11:44:28 -04004564 struct lpfc_dmabuf *dmabuf)
4565{
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004566 struct fc_bsg_request *bsg_request = job->request;
James Smart7ad20aa2011-05-24 11:44:28 -04004567 struct dfc_mbox_req *mbox_req;
James Smart88a2cfb2011-07-22 18:36:33 -04004568 int rc = SLI_CONFIG_NOT_HANDLED;
James Smart7ad20aa2011-05-24 11:44:28 -04004569
4570 mbox_req =
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004571 (struct dfc_mbox_req *)bsg_request->rqst_data.h_vendor.vendor_cmd;
James Smart7ad20aa2011-05-24 11:44:28 -04004572
4573 /* mbox command with/without single external buffer */
4574 if (mbox_req->extMboxTag == 0 && mbox_req->extSeqNum == 0)
James Smart88a2cfb2011-07-22 18:36:33 -04004575 return rc;
James Smart7ad20aa2011-05-24 11:44:28 -04004576
4577 /* mbox command and first external buffer */
4578 if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_IDLE) {
4579 if (mbox_req->extSeqNum == 1) {
4580 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4581 "2974 SLI_CONFIG mailbox: tag:%d, "
4582 "seq:%d\n", mbox_req->extMboxTag,
4583 mbox_req->extSeqNum);
4584 rc = lpfc_bsg_handle_sli_cfg_mbox(phba, job, dmabuf);
4585 return rc;
4586 } else
4587 goto sli_cfg_ext_error;
4588 }
4589
4590 /*
4591 * handle additional external buffers
4592 */
4593
4594 /* check broken pipe conditions */
4595 if (mbox_req->extMboxTag != phba->mbox_ext_buf_ctx.mbxTag)
4596 goto sli_cfg_ext_error;
4597 if (mbox_req->extSeqNum > phba->mbox_ext_buf_ctx.numBuf)
4598 goto sli_cfg_ext_error;
4599 if (mbox_req->extSeqNum != phba->mbox_ext_buf_ctx.seqNum + 1)
4600 goto sli_cfg_ext_error;
4601
4602 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
4603 "2975 SLI_CONFIG mailbox external buffer: "
4604 "extSta:x%x, tag:%d, seq:%d\n",
4605 phba->mbox_ext_buf_ctx.state, mbox_req->extMboxTag,
4606 mbox_req->extSeqNum);
4607 rc = lpfc_bsg_handle_sli_cfg_ebuf(phba, job, dmabuf);
4608 return rc;
4609
4610sli_cfg_ext_error:
4611 /* all other cases, broken pipe */
4612 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
4613 "2976 SLI_CONFIG mailbox broken pipe: "
4614 "ctxSta:x%x, ctxNumBuf:%d "
4615 "ctxTag:%d, ctxSeq:%d, tag:%d, seq:%d\n",
4616 phba->mbox_ext_buf_ctx.state,
4617 phba->mbox_ext_buf_ctx.numBuf,
4618 phba->mbox_ext_buf_ctx.mbxTag,
4619 phba->mbox_ext_buf_ctx.seqNum,
4620 mbox_req->extMboxTag, mbox_req->extSeqNum);
4621
4622 lpfc_bsg_mbox_ext_session_reset(phba);
4623
4624 return -EPIPE;
4625}
4626
4627/**
James Smart3b5dd522010-01-26 23:10:15 -05004628 * lpfc_bsg_issue_mbox - issues a mailbox command on behalf of an app
4629 * @phba: Pointer to HBA context object.
4630 * @mb: Pointer to a mailbox object.
4631 * @vport: Pointer to a vport object.
4632 *
4633 * Allocate a tracking object, mailbox command memory, get a mailbox
4634 * from the mailbox pool, copy the caller mailbox command.
4635 *
4636 * If offline and the sli is active we need to poll for the command (port is
4637 * being reset) and com-plete the job, otherwise issue the mailbox command and
4638 * let our completion handler finish the command.
4639 **/
James Smarta2fc4aef2014-09-03 12:57:55 -04004640static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01004641lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct bsg_job *job,
James Smart3b5dd522010-01-26 23:10:15 -05004642 struct lpfc_vport *vport)
4643{
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004644 struct fc_bsg_request *bsg_request = job->request;
4645 struct fc_bsg_reply *bsg_reply = job->reply;
James Smart7a470272010-03-15 11:25:20 -04004646 LPFC_MBOXQ_t *pmboxq = NULL; /* internal mailbox queue */
4647 MAILBOX_t *pmb; /* shortcut to the pmboxq mailbox */
4648 /* a 4k buffer to hold the mb and extended data from/to the bsg */
James Smart7ad20aa2011-05-24 11:44:28 -04004649 uint8_t *pmbx = NULL;
James Smart7a470272010-03-15 11:25:20 -04004650 struct bsg_job_data *dd_data = NULL; /* bsg data tracking structure */
James Smart7ad20aa2011-05-24 11:44:28 -04004651 struct lpfc_dmabuf *dmabuf = NULL;
4652 struct dfc_mbox_req *mbox_req;
James Smartb6e3b9c2011-04-16 11:03:43 -04004653 struct READ_EVENT_LOG_VAR *rdEventLog;
4654 uint32_t transmit_length, receive_length, mode;
James Smart7ad20aa2011-05-24 11:44:28 -04004655 struct lpfc_mbx_sli4_config *sli4_config;
James Smartb6e3b9c2011-04-16 11:03:43 -04004656 struct lpfc_mbx_nembed_cmd *nembed_sge;
James Smartb6e3b9c2011-04-16 11:03:43 -04004657 struct ulp_bde64 *bde;
James Smart7a470272010-03-15 11:25:20 -04004658 uint8_t *ext = NULL;
James Smart3b5dd522010-01-26 23:10:15 -05004659 int rc = 0;
James Smart7a470272010-03-15 11:25:20 -04004660 uint8_t *from;
James Smart7ad20aa2011-05-24 11:44:28 -04004661 uint32_t size;
4662
James Smart7a470272010-03-15 11:25:20 -04004663 /* in case no data is transferred */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004664 bsg_reply->reply_payload_rcv_len = 0;
James Smart7a470272010-03-15 11:25:20 -04004665
James Smartb6e3b9c2011-04-16 11:03:43 -04004666 /* sanity check to protect driver */
4667 if (job->reply_payload.payload_len > BSG_MBOX_SIZE ||
4668 job->request_payload.payload_len > BSG_MBOX_SIZE) {
4669 rc = -ERANGE;
4670 goto job_done;
4671 }
4672
James Smart7ad20aa2011-05-24 11:44:28 -04004673 /*
4674 * Don't allow mailbox commands to be sent when blocked or when in
4675 * the middle of discovery
4676 */
4677 if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
4678 rc = -EAGAIN;
4679 goto job_done;
4680 }
4681
4682 mbox_req =
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004683 (struct dfc_mbox_req *)bsg_request->rqst_data.h_vendor.vendor_cmd;
James Smart7ad20aa2011-05-24 11:44:28 -04004684
James Smart7a470272010-03-15 11:25:20 -04004685 /* check if requested extended data lengths are valid */
James Smartb6e3b9c2011-04-16 11:03:43 -04004686 if ((mbox_req->inExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t)) ||
4687 (mbox_req->outExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t))) {
James Smart7a470272010-03-15 11:25:20 -04004688 rc = -ERANGE;
4689 goto job_done;
4690 }
James Smart3b5dd522010-01-26 23:10:15 -05004691
James Smart7ad20aa2011-05-24 11:44:28 -04004692 dmabuf = lpfc_bsg_dma_page_alloc(phba);
4693 if (!dmabuf || !dmabuf->virt) {
4694 rc = -ENOMEM;
4695 goto job_done;
4696 }
4697
4698 /* Get the mailbox command or external buffer from BSG */
4699 pmbx = (uint8_t *)dmabuf->virt;
4700 size = job->request_payload.payload_len;
4701 sg_copy_to_buffer(job->request_payload.sg_list,
4702 job->request_payload.sg_cnt, pmbx, size);
4703
4704 /* Handle possible SLI_CONFIG with non-embedded payloads */
4705 if (phba->sli_rev == LPFC_SLI_REV4) {
4706 rc = lpfc_bsg_handle_sli_cfg_ext(phba, job, dmabuf);
4707 if (rc == SLI_CONFIG_HANDLED)
4708 goto job_cont;
4709 if (rc)
4710 goto job_done;
4711 /* SLI_CONFIG_NOT_HANDLED for other mailbox commands */
4712 }
4713
4714 rc = lpfc_bsg_check_cmd_access(phba, (MAILBOX_t *)pmbx, vport);
4715 if (rc != 0)
4716 goto job_done; /* must be negative */
4717
James Smart3b5dd522010-01-26 23:10:15 -05004718 /* allocate our bsg tracking structure */
4719 dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
4720 if (!dd_data) {
4721 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
4722 "2727 Failed allocation of dd_data\n");
James Smart7a470272010-03-15 11:25:20 -04004723 rc = -ENOMEM;
4724 goto job_done;
James Smart3b5dd522010-01-26 23:10:15 -05004725 }
4726
James Smart3b5dd522010-01-26 23:10:15 -05004727 pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
4728 if (!pmboxq) {
James Smart7a470272010-03-15 11:25:20 -04004729 rc = -ENOMEM;
4730 goto job_done;
James Smart3b5dd522010-01-26 23:10:15 -05004731 }
James Smart7a470272010-03-15 11:25:20 -04004732 memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
James Smart3b5dd522010-01-26 23:10:15 -05004733
James Smart3b5dd522010-01-26 23:10:15 -05004734 pmb = &pmboxq->u.mb;
James Smart7ad20aa2011-05-24 11:44:28 -04004735 memcpy(pmb, pmbx, sizeof(*pmb));
James Smart3b5dd522010-01-26 23:10:15 -05004736 pmb->mbxOwner = OWN_HOST;
James Smart3b5dd522010-01-26 23:10:15 -05004737 pmboxq->vport = vport;
4738
James Smartc7495932010-04-06 15:05:28 -04004739 /* If HBA encountered an error attention, allow only DUMP
4740 * or RESTART mailbox commands until the HBA is restarted.
4741 */
4742 if (phba->pport->stopped &&
4743 pmb->mbxCommand != MBX_DUMP_MEMORY &&
4744 pmb->mbxCommand != MBX_RESTART &&
4745 pmb->mbxCommand != MBX_WRITE_VPARMS &&
4746 pmb->mbxCommand != MBX_WRITE_WWN)
4747 lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
4748 "2797 mbox: Issued mailbox cmd "
4749 "0x%x while in stopped state.\n",
4750 pmb->mbxCommand);
4751
James Smart7a470272010-03-15 11:25:20 -04004752 /* extended mailbox commands will need an extended buffer */
James Smartc7495932010-04-06 15:05:28 -04004753 if (mbox_req->inExtWLen || mbox_req->outExtWLen) {
James Smart026abb82011-12-13 13:20:45 -05004754 from = pmbx;
4755 ext = from + sizeof(MAILBOX_t);
James Smart7a470272010-03-15 11:25:20 -04004756 pmboxq->context2 = ext;
4757 pmboxq->in_ext_byte_len =
James Smart7a470272010-03-15 11:25:20 -04004758 mbox_req->inExtWLen * sizeof(uint32_t);
4759 pmboxq->out_ext_byte_len =
James Smartc7495932010-04-06 15:05:28 -04004760 mbox_req->outExtWLen * sizeof(uint32_t);
James Smart7a470272010-03-15 11:25:20 -04004761 pmboxq->mbox_offset_word = mbox_req->mbOffset;
4762 }
4763
4764 /* biu diag will need a kernel buffer to transfer the data
4765 * allocate our own buffer and setup the mailbox command to
4766 * use ours
4767 */
4768 if (pmb->mbxCommand == MBX_RUN_BIU_DIAG64) {
James Smartb6e3b9c2011-04-16 11:03:43 -04004769 transmit_length = pmb->un.varWords[1];
4770 receive_length = pmb->un.varWords[4];
James Smartc7495932010-04-06 15:05:28 -04004771 /* transmit length cannot be greater than receive length or
4772 * mailbox extension size
4773 */
4774 if ((transmit_length > receive_length) ||
James Smart88a2cfb2011-07-22 18:36:33 -04004775 (transmit_length > BSG_MBOX_SIZE - sizeof(MAILBOX_t))) {
James Smartc7495932010-04-06 15:05:28 -04004776 rc = -ERANGE;
4777 goto job_done;
4778 }
James Smart7a470272010-03-15 11:25:20 -04004779 pmb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh =
James Smart7ad20aa2011-05-24 11:44:28 -04004780 putPaddrHigh(dmabuf->phys + sizeof(MAILBOX_t));
James Smart7a470272010-03-15 11:25:20 -04004781 pmb->un.varBIUdiag.un.s2.xmit_bde64.addrLow =
James Smart7ad20aa2011-05-24 11:44:28 -04004782 putPaddrLow(dmabuf->phys + sizeof(MAILBOX_t));
James Smart7a470272010-03-15 11:25:20 -04004783
4784 pmb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh =
James Smart7ad20aa2011-05-24 11:44:28 -04004785 putPaddrHigh(dmabuf->phys + sizeof(MAILBOX_t)
4786 + pmb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize);
James Smart7a470272010-03-15 11:25:20 -04004787 pmb->un.varBIUdiag.un.s2.rcv_bde64.addrLow =
James Smart7ad20aa2011-05-24 11:44:28 -04004788 putPaddrLow(dmabuf->phys + sizeof(MAILBOX_t)
4789 + pmb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize);
James Smartc7495932010-04-06 15:05:28 -04004790 } else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) {
James Smartb6e3b9c2011-04-16 11:03:43 -04004791 rdEventLog = &pmb->un.varRdEventLog;
4792 receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize;
4793 mode = bf_get(lpfc_event_log, rdEventLog);
James Smartc7495932010-04-06 15:05:28 -04004794
4795 /* receive length cannot be greater than mailbox
4796 * extension size
4797 */
James Smart88a2cfb2011-07-22 18:36:33 -04004798 if (receive_length > BSG_MBOX_SIZE - sizeof(MAILBOX_t)) {
James Smartc7495932010-04-06 15:05:28 -04004799 rc = -ERANGE;
4800 goto job_done;
4801 }
4802
4803 /* mode zero uses a bde like biu diags command */
4804 if (mode == 0) {
James Smart7ad20aa2011-05-24 11:44:28 -04004805 pmb->un.varWords[3] = putPaddrLow(dmabuf->phys
4806 + sizeof(MAILBOX_t));
4807 pmb->un.varWords[4] = putPaddrHigh(dmabuf->phys
4808 + sizeof(MAILBOX_t));
James Smartc7495932010-04-06 15:05:28 -04004809 }
4810 } else if (phba->sli_rev == LPFC_SLI_REV4) {
James Smart3ef6d242012-01-18 16:23:48 -05004811 /* Let type 4 (well known data) through because the data is
4812 * returned in varwords[4-8]
4813 * otherwise check the recieve length and fetch the buffer addr
4814 */
4815 if ((pmb->mbxCommand == MBX_DUMP_MEMORY) &&
4816 (pmb->un.varDmp.type != DMP_WELL_KNOWN)) {
James Smartc7495932010-04-06 15:05:28 -04004817 /* rebuild the command for sli4 using our own buffers
4818 * like we do for biu diags
4819 */
James Smartb6e3b9c2011-04-16 11:03:43 -04004820 receive_length = pmb->un.varWords[2];
James Smartc7495932010-04-06 15:05:28 -04004821 /* receive length cannot be greater than mailbox
4822 * extension size
4823 */
James Smart7ad20aa2011-05-24 11:44:28 -04004824 if (receive_length == 0) {
James Smartc7495932010-04-06 15:05:28 -04004825 rc = -ERANGE;
4826 goto job_done;
4827 }
James Smart7ad20aa2011-05-24 11:44:28 -04004828 pmb->un.varWords[3] = putPaddrLow(dmabuf->phys
4829 + sizeof(MAILBOX_t));
4830 pmb->un.varWords[4] = putPaddrHigh(dmabuf->phys
4831 + sizeof(MAILBOX_t));
James Smartc7495932010-04-06 15:05:28 -04004832 } else if ((pmb->mbxCommand == MBX_UPDATE_CFG) &&
4833 pmb->un.varUpdateCfg.co) {
James Smartb6e3b9c2011-04-16 11:03:43 -04004834 bde = (struct ulp_bde64 *)&pmb->un.varWords[4];
James Smartc7495932010-04-06 15:05:28 -04004835
4836 /* bde size cannot be greater than mailbox ext size */
James Smart88a2cfb2011-07-22 18:36:33 -04004837 if (bde->tus.f.bdeSize >
4838 BSG_MBOX_SIZE - sizeof(MAILBOX_t)) {
James Smartc7495932010-04-06 15:05:28 -04004839 rc = -ERANGE;
4840 goto job_done;
4841 }
James Smart7ad20aa2011-05-24 11:44:28 -04004842 bde->addrHigh = putPaddrHigh(dmabuf->phys
4843 + sizeof(MAILBOX_t));
4844 bde->addrLow = putPaddrLow(dmabuf->phys
4845 + sizeof(MAILBOX_t));
James Smart515e0aa2010-09-29 11:19:00 -04004846 } else if (pmb->mbxCommand == MBX_SLI4_CONFIG) {
James Smart7ad20aa2011-05-24 11:44:28 -04004847 /* Handling non-embedded SLI_CONFIG mailbox command */
4848 sli4_config = &pmboxq->u.mqe.un.sli4_config;
4849 if (!bf_get(lpfc_mbox_hdr_emb,
4850 &sli4_config->header.cfg_mhdr)) {
4851 /* rebuild the command for sli4 using our
4852 * own buffers like we do for biu diags
4853 */
James Smart7ad20aa2011-05-24 11:44:28 -04004854 nembed_sge = (struct lpfc_mbx_nembed_cmd *)
4855 &pmb->un.varWords[0];
4856 receive_length = nembed_sge->sge[0].length;
James Smart515e0aa2010-09-29 11:19:00 -04004857
James Smart7ad20aa2011-05-24 11:44:28 -04004858 /* receive length cannot be greater than
4859 * mailbox extension size
4860 */
4861 if ((receive_length == 0) ||
James Smart88a2cfb2011-07-22 18:36:33 -04004862 (receive_length >
4863 BSG_MBOX_SIZE - sizeof(MAILBOX_t))) {
James Smart7ad20aa2011-05-24 11:44:28 -04004864 rc = -ERANGE;
4865 goto job_done;
4866 }
4867
4868 nembed_sge->sge[0].pa_hi =
4869 putPaddrHigh(dmabuf->phys
4870 + sizeof(MAILBOX_t));
4871 nembed_sge->sge[0].pa_lo =
4872 putPaddrLow(dmabuf->phys
4873 + sizeof(MAILBOX_t));
James Smart515e0aa2010-09-29 11:19:00 -04004874 }
James Smartc7495932010-04-06 15:05:28 -04004875 }
James Smart3b5dd522010-01-26 23:10:15 -05004876 }
4877
James Smart7ad20aa2011-05-24 11:44:28 -04004878 dd_data->context_un.mbox.dmabuffers = dmabuf;
James Smartc7495932010-04-06 15:05:28 -04004879
James Smart3b5dd522010-01-26 23:10:15 -05004880 /* setup wake call as IOCB callback */
James Smart7ad20aa2011-05-24 11:44:28 -04004881 pmboxq->mbox_cmpl = lpfc_bsg_issue_mbox_cmpl;
James Smart7a470272010-03-15 11:25:20 -04004882
James Smart3b5dd522010-01-26 23:10:15 -05004883 /* setup context field to pass wait_queue pointer to wake function */
4884 pmboxq->context1 = dd_data;
4885 dd_data->type = TYPE_MBOX;
James Smarta33c4f72013-03-01 16:36:00 -05004886 dd_data->set_job = job;
James Smart3b5dd522010-01-26 23:10:15 -05004887 dd_data->context_un.mbox.pmboxq = pmboxq;
James Smart7ad20aa2011-05-24 11:44:28 -04004888 dd_data->context_un.mbox.mb = (MAILBOX_t *)pmbx;
James Smart7a470272010-03-15 11:25:20 -04004889 dd_data->context_un.mbox.ext = ext;
4890 dd_data->context_un.mbox.mbOffset = mbox_req->mbOffset;
4891 dd_data->context_un.mbox.inExtWLen = mbox_req->inExtWLen;
James Smartc7495932010-04-06 15:05:28 -04004892 dd_data->context_un.mbox.outExtWLen = mbox_req->outExtWLen;
James Smart3b5dd522010-01-26 23:10:15 -05004893 job->dd_data = dd_data;
James Smart7a470272010-03-15 11:25:20 -04004894
4895 if ((vport->fc_flag & FC_OFFLINE_MODE) ||
4896 (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE))) {
4897 rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
4898 if (rc != MBX_SUCCESS) {
4899 rc = (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;
4900 goto job_done;
4901 }
4902
4903 /* job finished, copy the data */
James Smart7ad20aa2011-05-24 11:44:28 -04004904 memcpy(pmbx, pmb, sizeof(*pmb));
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004905 bsg_reply->reply_payload_rcv_len =
James Smart7a470272010-03-15 11:25:20 -04004906 sg_copy_from_buffer(job->reply_payload.sg_list,
James Smart7ad20aa2011-05-24 11:44:28 -04004907 job->reply_payload.sg_cnt,
4908 pmbx, size);
James Smart7a470272010-03-15 11:25:20 -04004909 /* not waiting mbox already done */
4910 rc = 0;
4911 goto job_done;
James Smart3b5dd522010-01-26 23:10:15 -05004912 }
4913
James Smart7a470272010-03-15 11:25:20 -04004914 rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
4915 if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY))
4916 return 1; /* job started */
4917
4918job_done:
4919 /* common exit for error or job completed inline */
James Smart7a470272010-03-15 11:25:20 -04004920 if (pmboxq)
4921 mempool_free(pmboxq, phba->mbox_mem_pool);
James Smart7ad20aa2011-05-24 11:44:28 -04004922 lpfc_bsg_dma_page_free(phba, dmabuf);
James Smart7a470272010-03-15 11:25:20 -04004923 kfree(dd_data);
4924
James Smart7ad20aa2011-05-24 11:44:28 -04004925job_cont:
James Smart7a470272010-03-15 11:25:20 -04004926 return rc;
James Smart3b5dd522010-01-26 23:10:15 -05004927}
4928
4929/**
4930 * lpfc_bsg_mbox_cmd - process an fc bsg LPFC_BSG_VENDOR_MBOX command
4931 * @job: MBOX fc_bsg_job for LPFC_BSG_VENDOR_MBOX.
4932 **/
4933static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01004934lpfc_bsg_mbox_cmd(struct bsg_job *job)
James Smart3b5dd522010-01-26 23:10:15 -05004935{
Johannes Thumshirncd21c602016-11-17 10:31:14 +01004936 struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004937 struct fc_bsg_request *bsg_request = job->request;
4938 struct fc_bsg_reply *bsg_reply = job->reply;
James Smart3b5dd522010-01-26 23:10:15 -05004939 struct lpfc_hba *phba = vport->phba;
James Smart7ad20aa2011-05-24 11:44:28 -04004940 struct dfc_mbox_req *mbox_req;
James Smart3b5dd522010-01-26 23:10:15 -05004941 int rc = 0;
4942
James Smart7ad20aa2011-05-24 11:44:28 -04004943 /* mix-and-match backward compatibility */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004944 bsg_reply->reply_payload_rcv_len = 0;
James Smart3b5dd522010-01-26 23:10:15 -05004945 if (job->request_len <
4946 sizeof(struct fc_bsg_request) + sizeof(struct dfc_mbox_req)) {
James Smart7ad20aa2011-05-24 11:44:28 -04004947 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
Masanari Iida1051e9b2013-03-31 01:23:50 +09004948 "2737 Mix-and-match backward compatibility "
James Smart7ad20aa2011-05-24 11:44:28 -04004949 "between MBOX_REQ old size:%d and "
4950 "new request size:%d\n",
4951 (int)(job->request_len -
4952 sizeof(struct fc_bsg_request)),
4953 (int)sizeof(struct dfc_mbox_req));
4954 mbox_req = (struct dfc_mbox_req *)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004955 bsg_request->rqst_data.h_vendor.vendor_cmd;
James Smart7ad20aa2011-05-24 11:44:28 -04004956 mbox_req->extMboxTag = 0;
4957 mbox_req->extSeqNum = 0;
James Smart3b5dd522010-01-26 23:10:15 -05004958 }
4959
4960 rc = lpfc_bsg_issue_mbox(phba, job, vport);
4961
James Smart3b5dd522010-01-26 23:10:15 -05004962 if (rc == 0) {
4963 /* job done */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004964 bsg_reply->result = 0;
James Smart3b5dd522010-01-26 23:10:15 -05004965 job->dd_data = NULL;
Johannes Thumshirn06548162016-11-17 10:31:22 +01004966 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01004967 bsg_reply->reply_payload_rcv_len);
James Smart3b5dd522010-01-26 23:10:15 -05004968 } else if (rc == 1)
4969 /* job submitted, will complete later*/
4970 rc = 0; /* return zero, no error */
4971 else {
4972 /* some error occurred */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01004973 bsg_reply->result = rc;
James Smart3b5dd522010-01-26 23:10:15 -05004974 job->dd_data = NULL;
4975 }
4976
4977 return rc;
4978}
4979
4980/**
James Smarte2aed292010-02-26 14:15:00 -05004981 * lpfc_bsg_menlo_cmd_cmp - lpfc_menlo_cmd completion handler
4982 * @phba: Pointer to HBA context object.
4983 * @cmdiocbq: Pointer to command iocb.
4984 * @rspiocbq: Pointer to response iocb.
4985 *
4986 * This function is the completion handler for iocbs issued using
4987 * lpfc_menlo_cmd function. This function is called by the
4988 * ring event handler function without any lock held. This function
4989 * can be called from both worker thread context and interrupt
4990 * context. This function also can be called from another thread which
4991 * cleans up the SLI layer objects.
4992 * This function copies the contents of the response iocb to the
4993 * response iocb memory object provided by the caller of
4994 * lpfc_sli_issue_iocb_wait and then wakes up the thread which
4995 * sleeps for the iocb completion.
4996 **/
4997static void
4998lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba,
4999 struct lpfc_iocbq *cmdiocbq,
5000 struct lpfc_iocbq *rspiocbq)
5001{
5002 struct bsg_job_data *dd_data;
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01005003 struct bsg_job *job;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005004 struct fc_bsg_reply *bsg_reply;
James Smarte2aed292010-02-26 14:15:00 -05005005 IOCB_t *rsp;
James Smarta33c4f72013-03-01 16:36:00 -05005006 struct lpfc_dmabuf *bmp, *cmp, *rmp;
James Smarte2aed292010-02-26 14:15:00 -05005007 struct lpfc_bsg_menlo *menlo;
5008 unsigned long flags;
5009 struct menlo_response *menlo_resp;
James Smarta33c4f72013-03-01 16:36:00 -05005010 unsigned int rsp_size;
James Smarte2aed292010-02-26 14:15:00 -05005011 int rc = 0;
5012
James Smarte2aed292010-02-26 14:15:00 -05005013 dd_data = cmdiocbq->context1;
James Smarta33c4f72013-03-01 16:36:00 -05005014 cmp = cmdiocbq->context2;
5015 bmp = cmdiocbq->context3;
James Smarte2aed292010-02-26 14:15:00 -05005016 menlo = &dd_data->context_un.menlo;
James Smarta33c4f72013-03-01 16:36:00 -05005017 rmp = menlo->rmp;
James Smarte2aed292010-02-26 14:15:00 -05005018 rsp = &rspiocbq->iocb;
5019
James Smarta33c4f72013-03-01 16:36:00 -05005020 /* Determine if job has been aborted */
5021 spin_lock_irqsave(&phba->ct_ev_lock, flags);
5022 job = dd_data->set_job;
5023 if (job) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005024 bsg_reply = job->reply;
James Smarta33c4f72013-03-01 16:36:00 -05005025 /* Prevent timeout handling from trying to abort job */
5026 job->dd_data = NULL;
5027 }
5028 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
James Smarte2aed292010-02-26 14:15:00 -05005029
James Smarta33c4f72013-03-01 16:36:00 -05005030 /* Copy the job data or set the failing status for the job */
5031
5032 if (job) {
5033 /* always return the xri, this would be used in the case
5034 * of a menlo download to allow the data to be sent as a
5035 * continuation of the exchange.
5036 */
5037
5038 menlo_resp = (struct menlo_response *)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005039 bsg_reply->reply_data.vendor_reply.vendor_rsp;
James Smarta33c4f72013-03-01 16:36:00 -05005040 menlo_resp->xri = rsp->ulpContext;
5041 if (rsp->ulpStatus) {
5042 if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
5043 switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) {
5044 case IOERR_SEQUENCE_TIMEOUT:
5045 rc = -ETIMEDOUT;
5046 break;
5047 case IOERR_INVALID_RPI:
5048 rc = -EFAULT;
5049 break;
5050 default:
5051 rc = -EACCES;
5052 break;
5053 }
5054 } else {
James Smarte2aed292010-02-26 14:15:00 -05005055 rc = -EACCES;
James Smarte2aed292010-02-26 14:15:00 -05005056 }
James Smarta33c4f72013-03-01 16:36:00 -05005057 } else {
5058 rsp_size = rsp->un.genreq64.bdl.bdeSize;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005059 bsg_reply->reply_payload_rcv_len =
James Smarta33c4f72013-03-01 16:36:00 -05005060 lpfc_bsg_copy_data(rmp, &job->reply_payload,
5061 rsp_size, 0);
5062 }
James Smarte2aed292010-02-26 14:15:00 -05005063
James Smarta33c4f72013-03-01 16:36:00 -05005064 }
5065
James Smarte2aed292010-02-26 14:15:00 -05005066 lpfc_sli_release_iocbq(phba, cmdiocbq);
James Smarta33c4f72013-03-01 16:36:00 -05005067 lpfc_free_bsg_buffers(phba, cmp);
5068 lpfc_free_bsg_buffers(phba, rmp);
5069 lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
James Smarte2aed292010-02-26 14:15:00 -05005070 kfree(bmp);
5071 kfree(dd_data);
James Smarta33c4f72013-03-01 16:36:00 -05005072
5073 /* Complete the job if active */
5074
5075 if (job) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005076 bsg_reply->result = rc;
Johannes Thumshirn06548162016-11-17 10:31:22 +01005077 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01005078 bsg_reply->reply_payload_rcv_len);
James Smarta33c4f72013-03-01 16:36:00 -05005079 }
5080
James Smarte2aed292010-02-26 14:15:00 -05005081 return;
5082}
5083
5084/**
5085 * lpfc_menlo_cmd - send an ioctl for menlo hardware
5086 * @job: fc_bsg_job to handle
5087 *
5088 * This function issues a gen request 64 CR ioctl for all menlo cmd requests,
5089 * all the command completions will return the xri for the command.
5090 * For menlo data requests a gen request 64 CX is used to continue the exchange
5091 * supplied in the menlo request header xri field.
5092 **/
5093static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01005094lpfc_menlo_cmd(struct bsg_job *job)
James Smarte2aed292010-02-26 14:15:00 -05005095{
Johannes Thumshirncd21c602016-11-17 10:31:14 +01005096 struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005097 struct fc_bsg_request *bsg_request = job->request;
5098 struct fc_bsg_reply *bsg_reply = job->reply;
James Smarte2aed292010-02-26 14:15:00 -05005099 struct lpfc_hba *phba = vport->phba;
James Smarta33c4f72013-03-01 16:36:00 -05005100 struct lpfc_iocbq *cmdiocbq;
5101 IOCB_t *cmd;
James Smarte2aed292010-02-26 14:15:00 -05005102 int rc = 0;
5103 struct menlo_command *menlo_cmd;
James Smarta33c4f72013-03-01 16:36:00 -05005104 struct lpfc_dmabuf *bmp = NULL, *cmp = NULL, *rmp = NULL;
James Smarte2aed292010-02-26 14:15:00 -05005105 int request_nseg;
5106 int reply_nseg;
James Smarte2aed292010-02-26 14:15:00 -05005107 struct bsg_job_data *dd_data;
5108 struct ulp_bde64 *bpl = NULL;
5109
5110 /* in case no data is returned return just the return code */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005111 bsg_reply->reply_payload_rcv_len = 0;
James Smarte2aed292010-02-26 14:15:00 -05005112
5113 if (job->request_len <
5114 sizeof(struct fc_bsg_request) +
5115 sizeof(struct menlo_command)) {
5116 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
5117 "2784 Received MENLO_CMD request below "
5118 "minimum size\n");
5119 rc = -ERANGE;
5120 goto no_dd_data;
5121 }
5122
5123 if (job->reply_len <
5124 sizeof(struct fc_bsg_request) + sizeof(struct menlo_response)) {
5125 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
5126 "2785 Received MENLO_CMD reply below "
5127 "minimum size\n");
5128 rc = -ERANGE;
5129 goto no_dd_data;
5130 }
5131
5132 if (!(phba->menlo_flag & HBA_MENLO_SUPPORT)) {
5133 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
5134 "2786 Adapter does not support menlo "
5135 "commands\n");
5136 rc = -EPERM;
5137 goto no_dd_data;
5138 }
5139
5140 menlo_cmd = (struct menlo_command *)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005141 bsg_request->rqst_data.h_vendor.vendor_cmd;
James Smarte2aed292010-02-26 14:15:00 -05005142
James Smarte2aed292010-02-26 14:15:00 -05005143 /* allocate our bsg tracking structure */
5144 dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
5145 if (!dd_data) {
5146 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
5147 "2787 Failed allocation of dd_data\n");
5148 rc = -ENOMEM;
5149 goto no_dd_data;
5150 }
5151
5152 bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
5153 if (!bmp) {
5154 rc = -ENOMEM;
5155 goto free_dd;
5156 }
5157
James Smarta33c4f72013-03-01 16:36:00 -05005158 bmp->virt = lpfc_mbuf_alloc(phba, 0, &bmp->phys);
5159 if (!bmp->virt) {
James Smarte2aed292010-02-26 14:15:00 -05005160 rc = -ENOMEM;
5161 goto free_bmp;
5162 }
5163
James Smarte2aed292010-02-26 14:15:00 -05005164 INIT_LIST_HEAD(&bmp->list);
James Smarta33c4f72013-03-01 16:36:00 -05005165
5166 bpl = (struct ulp_bde64 *)bmp->virt;
5167 request_nseg = LPFC_BPL_SIZE/sizeof(struct ulp_bde64);
5168 cmp = lpfc_alloc_bsg_buffers(phba, job->request_payload.payload_len,
5169 1, bpl, &request_nseg);
5170 if (!cmp) {
5171 rc = -ENOMEM;
5172 goto free_bmp;
5173 }
5174 lpfc_bsg_copy_data(cmp, &job->request_payload,
5175 job->request_payload.payload_len, 1);
5176
5177 bpl += request_nseg;
5178 reply_nseg = LPFC_BPL_SIZE/sizeof(struct ulp_bde64) - request_nseg;
5179 rmp = lpfc_alloc_bsg_buffers(phba, job->reply_payload.payload_len, 0,
5180 bpl, &reply_nseg);
5181 if (!rmp) {
5182 rc = -ENOMEM;
5183 goto free_cmp;
James Smarte2aed292010-02-26 14:15:00 -05005184 }
5185
James Smarta33c4f72013-03-01 16:36:00 -05005186 cmdiocbq = lpfc_sli_get_iocbq(phba);
5187 if (!cmdiocbq) {
5188 rc = -ENOMEM;
5189 goto free_rmp;
James Smarte2aed292010-02-26 14:15:00 -05005190 }
5191
5192 cmd = &cmdiocbq->iocb;
5193 cmd->un.genreq64.bdl.ulpIoTag32 = 0;
5194 cmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
5195 cmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys);
5196 cmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
5197 cmd->un.genreq64.bdl.bdeSize =
5198 (request_nseg + reply_nseg) * sizeof(struct ulp_bde64);
5199 cmd->un.genreq64.w5.hcsw.Fctl = (SI | LA);
5200 cmd->un.genreq64.w5.hcsw.Dfctl = 0;
5201 cmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CMD;
5202 cmd->un.genreq64.w5.hcsw.Type = MENLO_TRANSPORT_TYPE; /* 0xfe */
5203 cmd->ulpBdeCount = 1;
5204 cmd->ulpClass = CLASS3;
5205 cmd->ulpOwner = OWN_CHIP;
5206 cmd->ulpLe = 1; /* Limited Edition */
5207 cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
5208 cmdiocbq->vport = phba->pport;
5209 /* We want the firmware to timeout before we do */
5210 cmd->ulpTimeout = MENLO_TIMEOUT - 5;
James Smarte2aed292010-02-26 14:15:00 -05005211 cmdiocbq->iocb_cmpl = lpfc_bsg_menlo_cmd_cmp;
5212 cmdiocbq->context1 = dd_data;
James Smarta33c4f72013-03-01 16:36:00 -05005213 cmdiocbq->context2 = cmp;
5214 cmdiocbq->context3 = bmp;
James Smarte2aed292010-02-26 14:15:00 -05005215 if (menlo_cmd->cmd == LPFC_BSG_VENDOR_MENLO_CMD) {
5216 cmd->ulpCommand = CMD_GEN_REQUEST64_CR;
5217 cmd->ulpPU = MENLO_PU; /* 3 */
5218 cmd->un.ulpWord[4] = MENLO_DID; /* 0x0000FC0E */
5219 cmd->ulpContext = MENLO_CONTEXT; /* 0 */
5220 } else {
5221 cmd->ulpCommand = CMD_GEN_REQUEST64_CX;
5222 cmd->ulpPU = 1;
5223 cmd->un.ulpWord[4] = 0;
5224 cmd->ulpContext = menlo_cmd->xri;
5225 }
5226
5227 dd_data->type = TYPE_MENLO;
James Smarta33c4f72013-03-01 16:36:00 -05005228 dd_data->set_job = job;
James Smarte2aed292010-02-26 14:15:00 -05005229 dd_data->context_un.menlo.cmdiocbq = cmdiocbq;
James Smarta33c4f72013-03-01 16:36:00 -05005230 dd_data->context_un.menlo.rmp = rmp;
5231 job->dd_data = dd_data;
James Smarte2aed292010-02-26 14:15:00 -05005232
5233 rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq,
5234 MENLO_TIMEOUT - 5);
5235 if (rc == IOCB_SUCCESS)
5236 return 0; /* done for now */
5237
James Smarte2aed292010-02-26 14:15:00 -05005238 lpfc_sli_release_iocbq(phba, cmdiocbq);
James Smarta33c4f72013-03-01 16:36:00 -05005239
5240free_rmp:
5241 lpfc_free_bsg_buffers(phba, rmp);
5242free_cmp:
5243 lpfc_free_bsg_buffers(phba, cmp);
James Smarte2aed292010-02-26 14:15:00 -05005244free_bmp:
James Smarta33c4f72013-03-01 16:36:00 -05005245 if (bmp->virt)
5246 lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
James Smarte2aed292010-02-26 14:15:00 -05005247 kfree(bmp);
5248free_dd:
5249 kfree(dd_data);
5250no_dd_data:
5251 /* make error code available to userspace */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005252 bsg_reply->result = rc;
James Smarte2aed292010-02-26 14:15:00 -05005253 job->dd_data = NULL;
5254 return rc;
5255}
James Smartb6e3b9c2011-04-16 11:03:43 -04005256
James Smartc6918162016-10-13 15:06:16 -07005257static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01005258lpfc_forced_link_speed(struct bsg_job *job)
James Smartc6918162016-10-13 15:06:16 -07005259{
Johannes Thumshirncd21c602016-11-17 10:31:14 +01005260 struct Scsi_Host *shost = fc_bsg_to_shost(job);
James Smartc6918162016-10-13 15:06:16 -07005261 struct lpfc_vport *vport = shost_priv(shost);
5262 struct lpfc_hba *phba = vport->phba;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005263 struct fc_bsg_reply *bsg_reply = job->reply;
James Smartc6918162016-10-13 15:06:16 -07005264 struct forced_link_speed_support_reply *forced_reply;
5265 int rc = 0;
5266
5267 if (job->request_len <
5268 sizeof(struct fc_bsg_request) +
5269 sizeof(struct get_forced_link_speed_support)) {
5270 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
5271 "0048 Received FORCED_LINK_SPEED request "
5272 "below minimum size\n");
5273 rc = -EINVAL;
5274 goto job_error;
5275 }
5276
5277 forced_reply = (struct forced_link_speed_support_reply *)
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005278 bsg_reply->reply_data.vendor_reply.vendor_rsp;
James Smartc6918162016-10-13 15:06:16 -07005279
5280 if (job->reply_len <
5281 sizeof(struct fc_bsg_request) +
5282 sizeof(struct forced_link_speed_support_reply)) {
5283 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
5284 "0049 Received FORCED_LINK_SPEED reply below "
5285 "minimum size\n");
5286 rc = -EINVAL;
5287 goto job_error;
5288 }
5289
5290 forced_reply->supported = (phba->hba_flag & HBA_FORCED_LINK_SPEED)
5291 ? LPFC_FORCED_LINK_SPEED_SUPPORTED
5292 : LPFC_FORCED_LINK_SPEED_NOT_SUPPORTED;
5293job_error:
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005294 bsg_reply->result = rc;
James Smartc6918162016-10-13 15:06:16 -07005295 if (rc == 0)
Johannes Thumshirn06548162016-11-17 10:31:22 +01005296 bsg_job_done(job, bsg_reply->result,
Johannes Thumshirn1abaede2016-11-17 10:31:13 +01005297 bsg_reply->reply_payload_rcv_len);
James Smartc6918162016-10-13 15:06:16 -07005298 return rc;
5299}
5300
James Smarte2aed292010-02-26 14:15:00 -05005301/**
James Smartf1c3b0f2009-07-19 10:01:32 -04005302 * lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job
5303 * @job: fc_bsg_job to handle
James Smart3b5dd522010-01-26 23:10:15 -05005304 **/
James Smartf1c3b0f2009-07-19 10:01:32 -04005305static int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01005306lpfc_bsg_hst_vendor(struct bsg_job *job)
James Smartf1c3b0f2009-07-19 10:01:32 -04005307{
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005308 struct fc_bsg_request *bsg_request = job->request;
5309 struct fc_bsg_reply *bsg_reply = job->reply;
5310 int command = bsg_request->rqst_data.h_vendor.vendor_cmd[0];
James Smart4cc0e562010-01-26 23:09:48 -05005311 int rc;
James Smartf1c3b0f2009-07-19 10:01:32 -04005312
5313 switch (command) {
5314 case LPFC_BSG_VENDOR_SET_CT_EVENT:
James Smart4cc0e562010-01-26 23:09:48 -05005315 rc = lpfc_bsg_hba_set_event(job);
James Smartf1c3b0f2009-07-19 10:01:32 -04005316 break;
James Smartf1c3b0f2009-07-19 10:01:32 -04005317 case LPFC_BSG_VENDOR_GET_CT_EVENT:
James Smart4cc0e562010-01-26 23:09:48 -05005318 rc = lpfc_bsg_hba_get_event(job);
James Smartf1c3b0f2009-07-19 10:01:32 -04005319 break;
James Smart3b5dd522010-01-26 23:10:15 -05005320 case LPFC_BSG_VENDOR_SEND_MGMT_RESP:
5321 rc = lpfc_bsg_send_mgmt_rsp(job);
5322 break;
5323 case LPFC_BSG_VENDOR_DIAG_MODE:
James Smart7ad20aa2011-05-24 11:44:28 -04005324 rc = lpfc_bsg_diag_loopback_mode(job);
James Smart3b5dd522010-01-26 23:10:15 -05005325 break;
James Smart7ad20aa2011-05-24 11:44:28 -04005326 case LPFC_BSG_VENDOR_DIAG_MODE_END:
5327 rc = lpfc_sli4_bsg_diag_mode_end(job);
5328 break;
5329 case LPFC_BSG_VENDOR_DIAG_RUN_LOOPBACK:
5330 rc = lpfc_bsg_diag_loopback_run(job);
5331 break;
5332 case LPFC_BSG_VENDOR_LINK_DIAG_TEST:
5333 rc = lpfc_sli4_bsg_link_diag_test(job);
James Smart3b5dd522010-01-26 23:10:15 -05005334 break;
5335 case LPFC_BSG_VENDOR_GET_MGMT_REV:
5336 rc = lpfc_bsg_get_dfc_rev(job);
5337 break;
5338 case LPFC_BSG_VENDOR_MBOX:
5339 rc = lpfc_bsg_mbox_cmd(job);
5340 break;
James Smarte2aed292010-02-26 14:15:00 -05005341 case LPFC_BSG_VENDOR_MENLO_CMD:
5342 case LPFC_BSG_VENDOR_MENLO_DATA:
5343 rc = lpfc_menlo_cmd(job);
5344 break;
James Smartc6918162016-10-13 15:06:16 -07005345 case LPFC_BSG_VENDOR_FORCED_LINK_SPEED:
5346 rc = lpfc_forced_link_speed(job);
5347 break;
James Smartf1c3b0f2009-07-19 10:01:32 -04005348 default:
James Smart4cc0e562010-01-26 23:09:48 -05005349 rc = -EINVAL;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005350 bsg_reply->reply_payload_rcv_len = 0;
James Smart4cc0e562010-01-26 23:09:48 -05005351 /* make error code available to userspace */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005352 bsg_reply->result = rc;
James Smart4cc0e562010-01-26 23:09:48 -05005353 break;
James Smartf1c3b0f2009-07-19 10:01:32 -04005354 }
James Smart4cc0e562010-01-26 23:09:48 -05005355
5356 return rc;
James Smartf1c3b0f2009-07-19 10:01:32 -04005357}
5358
5359/**
5360 * lpfc_bsg_request - handle a bsg request from the FC transport
5361 * @job: fc_bsg_job to handle
James Smart3b5dd522010-01-26 23:10:15 -05005362 **/
James Smartf1c3b0f2009-07-19 10:01:32 -04005363int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01005364lpfc_bsg_request(struct bsg_job *job)
James Smartf1c3b0f2009-07-19 10:01:32 -04005365{
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005366 struct fc_bsg_request *bsg_request = job->request;
5367 struct fc_bsg_reply *bsg_reply = job->reply;
James Smartf1c3b0f2009-07-19 10:01:32 -04005368 uint32_t msgcode;
James Smart4cc0e562010-01-26 23:09:48 -05005369 int rc;
James Smartf1c3b0f2009-07-19 10:01:32 -04005370
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005371 msgcode = bsg_request->msgcode;
James Smartf1c3b0f2009-07-19 10:01:32 -04005372 switch (msgcode) {
5373 case FC_BSG_HST_VENDOR:
5374 rc = lpfc_bsg_hst_vendor(job);
5375 break;
5376 case FC_BSG_RPT_ELS:
5377 rc = lpfc_bsg_rport_els(job);
5378 break;
5379 case FC_BSG_RPT_CT:
James Smart4cc0e562010-01-26 23:09:48 -05005380 rc = lpfc_bsg_send_mgmt_cmd(job);
James Smartf1c3b0f2009-07-19 10:01:32 -04005381 break;
5382 default:
James Smart4cc0e562010-01-26 23:09:48 -05005383 rc = -EINVAL;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005384 bsg_reply->reply_payload_rcv_len = 0;
James Smart4cc0e562010-01-26 23:09:48 -05005385 /* make error code available to userspace */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01005386 bsg_reply->result = rc;
James Smartf1c3b0f2009-07-19 10:01:32 -04005387 break;
5388 }
5389
5390 return rc;
5391}
5392
5393/**
5394 * lpfc_bsg_timeout - handle timeout of a bsg request from the FC transport
5395 * @job: fc_bsg_job that has timed out
5396 *
5397 * This function just aborts the job's IOCB. The aborted IOCB will return to
5398 * the waiting function which will handle passing the error back to userspace
James Smart3b5dd522010-01-26 23:10:15 -05005399 **/
James Smartf1c3b0f2009-07-19 10:01:32 -04005400int
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01005401lpfc_bsg_timeout(struct bsg_job *job)
James Smartf1c3b0f2009-07-19 10:01:32 -04005402{
Johannes Thumshirncd21c602016-11-17 10:31:14 +01005403 struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
James Smartf1c3b0f2009-07-19 10:01:32 -04005404 struct lpfc_hba *phba = vport->phba;
James Smart4cc0e562010-01-26 23:09:48 -05005405 struct lpfc_iocbq *cmdiocb;
James Smartf1c3b0f2009-07-19 10:01:32 -04005406 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
James Smart4cc0e562010-01-26 23:09:48 -05005407 struct bsg_job_data *dd_data;
5408 unsigned long flags;
James Smarta33c4f72013-03-01 16:36:00 -05005409 int rc = 0;
5410 LIST_HEAD(completions);
5411 struct lpfc_iocbq *check_iocb, *next_iocb;
5412
5413 /* if job's driver data is NULL, the command completed or is in the
5414 * the process of completing. In this case, return status to request
5415 * so the timeout is retried. This avoids double completion issues
5416 * and the request will be pulled off the timer queue when the
5417 * command's completion handler executes. Otherwise, prevent the
5418 * command's completion handler from executing the job done callback
5419 * and continue processing to abort the outstanding the command.
5420 */
James Smartf1c3b0f2009-07-19 10:01:32 -04005421
James Smart4cc0e562010-01-26 23:09:48 -05005422 spin_lock_irqsave(&phba->ct_ev_lock, flags);
5423 dd_data = (struct bsg_job_data *)job->dd_data;
James Smarta33c4f72013-03-01 16:36:00 -05005424 if (dd_data) {
5425 dd_data->set_job = NULL;
5426 job->dd_data = NULL;
5427 } else {
James Smart4cc0e562010-01-26 23:09:48 -05005428 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
James Smarta33c4f72013-03-01 16:36:00 -05005429 return -EAGAIN;
James Smart4cc0e562010-01-26 23:09:48 -05005430 }
5431
5432 switch (dd_data->type) {
5433 case TYPE_IOCB:
James Smarta33c4f72013-03-01 16:36:00 -05005434 /* Check to see if IOCB was issued to the port or not. If not,
5435 * remove it from the txq queue and call cancel iocbs.
5436 * Otherwise, call abort iotag
James Smart4cc0e562010-01-26 23:09:48 -05005437 */
James Smarta33c4f72013-03-01 16:36:00 -05005438 cmdiocb = dd_data->context_un.iocb.cmdiocbq;
James Smartb5a9b2d2013-09-06 12:19:45 -04005439 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
5440
5441 spin_lock_irqsave(&phba->hbalock, flags);
5442 /* make sure the I/O abort window is still open */
James Smart1b8d11a2013-09-06 12:20:51 -04005443 if (!(cmdiocb->iocb_flag & LPFC_IO_CMD_OUTSTANDING)) {
James Smartb5a9b2d2013-09-06 12:19:45 -04005444 spin_unlock_irqrestore(&phba->hbalock, flags);
5445 return -EAGAIN;
5446 }
James Smarta33c4f72013-03-01 16:36:00 -05005447 list_for_each_entry_safe(check_iocb, next_iocb, &pring->txq,
5448 list) {
5449 if (check_iocb == cmdiocb) {
5450 list_move_tail(&check_iocb->list, &completions);
5451 break;
5452 }
5453 }
5454 if (list_empty(&completions))
5455 lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb);
James Smartb5a9b2d2013-09-06 12:19:45 -04005456 spin_unlock_irqrestore(&phba->hbalock, flags);
James Smarta33c4f72013-03-01 16:36:00 -05005457 if (!list_empty(&completions)) {
5458 lpfc_sli_cancel_iocbs(phba, &completions,
5459 IOSTAT_LOCAL_REJECT,
5460 IOERR_SLI_ABORTED);
5461 }
James Smart4cc0e562010-01-26 23:09:48 -05005462 break;
James Smarta33c4f72013-03-01 16:36:00 -05005463
5464 case TYPE_EVT:
James Smart3b5dd522010-01-26 23:10:15 -05005465 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
James Smarta33c4f72013-03-01 16:36:00 -05005466 break;
5467
5468 case TYPE_MBOX:
5469 /* Update the ext buf ctx state if needed */
5470
James Smart7ad20aa2011-05-24 11:44:28 -04005471 if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_PORT)
5472 phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_ABTS;
James Smarta33c4f72013-03-01 16:36:00 -05005473 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
James Smart3b5dd522010-01-26 23:10:15 -05005474 break;
James Smarte2aed292010-02-26 14:15:00 -05005475 case TYPE_MENLO:
James Smarta33c4f72013-03-01 16:36:00 -05005476 /* Check to see if IOCB was issued to the port or not. If not,
5477 * remove it from the txq queue and call cancel iocbs.
5478 * Otherwise, call abort iotag.
5479 */
James Smarta33c4f72013-03-01 16:36:00 -05005480 cmdiocb = dd_data->context_un.menlo.cmdiocbq;
James Smartb5a9b2d2013-09-06 12:19:45 -04005481 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
5482
5483 spin_lock_irqsave(&phba->hbalock, flags);
James Smarta33c4f72013-03-01 16:36:00 -05005484 list_for_each_entry_safe(check_iocb, next_iocb, &pring->txq,
5485 list) {
5486 if (check_iocb == cmdiocb) {
5487 list_move_tail(&check_iocb->list, &completions);
5488 break;
5489 }
5490 }
5491 if (list_empty(&completions))
5492 lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb);
James Smartb5a9b2d2013-09-06 12:19:45 -04005493 spin_unlock_irqrestore(&phba->hbalock, flags);
James Smarta33c4f72013-03-01 16:36:00 -05005494 if (!list_empty(&completions)) {
5495 lpfc_sli_cancel_iocbs(phba, &completions,
5496 IOSTAT_LOCAL_REJECT,
5497 IOERR_SLI_ABORTED);
5498 }
James Smarte2aed292010-02-26 14:15:00 -05005499 break;
James Smart4cc0e562010-01-26 23:09:48 -05005500 default:
5501 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
5502 break;
5503 }
James Smartf1c3b0f2009-07-19 10:01:32 -04005504
James Smart4cc0e562010-01-26 23:09:48 -05005505 /* scsi transport fc fc_bsg_job_timeout expects a zero return code,
5506 * otherwise an error message will be displayed on the console
5507 * so always return success (zero)
5508 */
James Smarta33c4f72013-03-01 16:36:00 -05005509 return rc;
James Smartf1c3b0f2009-07-19 10:01:32 -04005510}