blob: 76ca416a3806c82d8ebe84bd3af97eecf8edb785 [file] [log] [blame]
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301/*
2 * Management Module Support for MPT (Message Passing Technology) based
3 * controllers
4 *
5 * This code is based on drivers/scsi/mpt3sas/mpt3sas_ctl.c
Sreekanth Reddya4ffce02014-09-12 15:35:29 +05306 * Copyright (C) 2012-2014 LSI Corporation
Sreekanth Reddya03bd152015-01-12 11:39:02 +05307 * Copyright (C) 2013-2014 Avago Technologies
8 * (mailto: MPT-FusionLinux.pdl@avagotech.com)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * NO WARRANTY
21 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
22 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
23 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
24 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
25 * solely responsible for determining the appropriateness of using and
26 * distributing the Program and assumes all risks associated with its
27 * exercise of rights under this Agreement, including but not limited to
28 * the risks and costs of program errors, damage to or loss of data,
29 * programs or equipment, and unavailability or interruption of operations.
30
31 * DISCLAIMER OF LIABILITY
32 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
33 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
35 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
38 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
39
40 * You should have received a copy of the GNU General Public License
41 * along with this program; if not, write to the Free Software
42 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
43 * USA.
44 */
45
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053046#include <linux/kernel.h>
47#include <linux/module.h>
48#include <linux/errno.h>
49#include <linux/init.h>
50#include <linux/slab.h>
51#include <linux/types.h>
52#include <linux/pci.h>
53#include <linux/delay.h>
54#include <linux/compat.h>
55#include <linux/poll.h>
56
57#include <linux/io.h>
58#include <linux/uaccess.h>
59
60#include "mpt3sas_base.h"
61#include "mpt3sas_ctl.h"
62
63
64static struct fasync_struct *async_queue;
65static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
66
67
68/**
69 * enum block_state - blocking state
70 * @NON_BLOCKING: non blocking
71 * @BLOCKING: blocking
72 *
73 * These states are for ioctls that need to wait for a response
74 * from firmware, so they probably require sleep.
75 */
76enum block_state {
77 NON_BLOCKING,
78 BLOCKING,
79};
80
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053081/**
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053082 * _ctl_display_some_debug - debug routine
83 * @ioc: per adapter object
84 * @smid: system request message index
85 * @calling_function_name: string pass from calling function
86 * @mpi_reply: reply message frame
87 * Context: none.
88 *
89 * Function for displaying debug info helpful when debugging issues
90 * in this module.
91 */
92static void
93_ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
94 char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
95{
96 Mpi2ConfigRequest_t *mpi_request;
97 char *desc = NULL;
98
99 if (!(ioc->logging_level & MPT_DEBUG_IOCTL))
100 return;
101
102 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
103 switch (mpi_request->Function) {
104 case MPI2_FUNCTION_SCSI_IO_REQUEST:
105 {
106 Mpi2SCSIIORequest_t *scsi_request =
107 (Mpi2SCSIIORequest_t *)mpi_request;
108
109 snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
110 "scsi_io, cmd(0x%02x), cdb_len(%d)",
111 scsi_request->CDB.CDB32[0],
112 le16_to_cpu(scsi_request->IoFlags) & 0xF);
113 desc = ioc->tmp_string;
114 break;
115 }
116 case MPI2_FUNCTION_SCSI_TASK_MGMT:
117 desc = "task_mgmt";
118 break;
119 case MPI2_FUNCTION_IOC_INIT:
120 desc = "ioc_init";
121 break;
122 case MPI2_FUNCTION_IOC_FACTS:
123 desc = "ioc_facts";
124 break;
125 case MPI2_FUNCTION_CONFIG:
126 {
127 Mpi2ConfigRequest_t *config_request =
128 (Mpi2ConfigRequest_t *)mpi_request;
129
130 snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
131 "config, type(0x%02x), ext_type(0x%02x), number(%d)",
132 (config_request->Header.PageType &
133 MPI2_CONFIG_PAGETYPE_MASK), config_request->ExtPageType,
134 config_request->Header.PageNumber);
135 desc = ioc->tmp_string;
136 break;
137 }
138 case MPI2_FUNCTION_PORT_FACTS:
139 desc = "port_facts";
140 break;
141 case MPI2_FUNCTION_PORT_ENABLE:
142 desc = "port_enable";
143 break;
144 case MPI2_FUNCTION_EVENT_NOTIFICATION:
145 desc = "event_notification";
146 break;
147 case MPI2_FUNCTION_FW_DOWNLOAD:
148 desc = "fw_download";
149 break;
150 case MPI2_FUNCTION_FW_UPLOAD:
151 desc = "fw_upload";
152 break;
153 case MPI2_FUNCTION_RAID_ACTION:
154 desc = "raid_action";
155 break;
156 case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
157 {
158 Mpi2SCSIIORequest_t *scsi_request =
159 (Mpi2SCSIIORequest_t *)mpi_request;
160
161 snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
162 "raid_pass, cmd(0x%02x), cdb_len(%d)",
163 scsi_request->CDB.CDB32[0],
164 le16_to_cpu(scsi_request->IoFlags) & 0xF);
165 desc = ioc->tmp_string;
166 break;
167 }
168 case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
169 desc = "sas_iounit_cntl";
170 break;
171 case MPI2_FUNCTION_SATA_PASSTHROUGH:
172 desc = "sata_pass";
173 break;
174 case MPI2_FUNCTION_DIAG_BUFFER_POST:
175 desc = "diag_buffer_post";
176 break;
177 case MPI2_FUNCTION_DIAG_RELEASE:
178 desc = "diag_release";
179 break;
180 case MPI2_FUNCTION_SMP_PASSTHROUGH:
181 desc = "smp_passthrough";
182 break;
183 }
184
185 if (!desc)
186 return;
187
Joe Perches919d8a32018-09-17 08:01:09 -0700188 ioc_info(ioc, "%s: %s, smid(%d)\n", calling_function_name, desc, smid);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530189
190 if (!mpi_reply)
191 return;
192
193 if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
Joe Perches919d8a32018-09-17 08:01:09 -0700194 ioc_info(ioc, "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
195 le16_to_cpu(mpi_reply->IOCStatus),
196 le32_to_cpu(mpi_reply->IOCLogInfo));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530197
198 if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
199 mpi_request->Function ==
200 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
201 Mpi2SCSIIOReply_t *scsi_reply =
202 (Mpi2SCSIIOReply_t *)mpi_reply;
203 struct _sas_device *sas_device = NULL;
Suganath Prabu Subramani45aa6a12017-10-31 18:02:36 +0530204 struct _pcie_device *pcie_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530205
Suganath Prabu Subramani45aa6a12017-10-31 18:02:36 +0530206 sas_device = mpt3sas_get_sdev_by_handle(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530207 le16_to_cpu(scsi_reply->DevHandle));
208 if (sas_device) {
Joe Perches919d8a32018-09-17 08:01:09 -0700209 ioc_warn(ioc, "\tsas_address(0x%016llx), phy(%d)\n",
210 (u64)sas_device->sas_address,
211 sas_device->phy);
212 ioc_warn(ioc, "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
213 (u64)sas_device->enclosure_logical_id,
214 sas_device->slot);
Suganath Prabu Subramani45aa6a12017-10-31 18:02:36 +0530215 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530216 }
Suganath Prabu Subramani45aa6a12017-10-31 18:02:36 +0530217 if (!sas_device) {
218 pcie_device = mpt3sas_get_pdev_by_handle(ioc,
219 le16_to_cpu(scsi_reply->DevHandle));
220 if (pcie_device) {
Joe Perches919d8a32018-09-17 08:01:09 -0700221 ioc_warn(ioc, "\tWWID(0x%016llx), port(%d)\n",
222 (unsigned long long)pcie_device->wwid,
223 pcie_device->port_num);
Suganath Prabu Subramani45aa6a12017-10-31 18:02:36 +0530224 if (pcie_device->enclosure_handle != 0)
Joe Perches919d8a32018-09-17 08:01:09 -0700225 ioc_warn(ioc, "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
226 (u64)pcie_device->enclosure_logical_id,
227 pcie_device->slot);
Suganath Prabu Subramani45aa6a12017-10-31 18:02:36 +0530228 pcie_device_put(pcie_device);
229 }
230 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530231 if (scsi_reply->SCSIState || scsi_reply->SCSIStatus)
Joe Perches919d8a32018-09-17 08:01:09 -0700232 ioc_info(ioc, "\tscsi_state(0x%02x), scsi_status(0x%02x)\n",
233 scsi_reply->SCSIState,
234 scsi_reply->SCSIStatus);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530235 }
236}
237
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530238/**
239 * mpt3sas_ctl_done - ctl module completion routine
240 * @ioc: per adapter object
241 * @smid: system request message index
242 * @msix_index: MSIX table index supplied by the OS
243 * @reply: reply message frame(lower 32bit addr)
244 * Context: none.
245 *
246 * The callback handler when using ioc->ctl_cb_idx.
247 *
Bart Van Assche4beb4862018-06-15 14:42:01 -0700248 * Return: 1 meaning mf should be freed from _base_interrupt
249 * 0 means the mf is freed from this function.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530250 */
251u8
252mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
253 u32 reply)
254{
255 MPI2DefaultReply_t *mpi_reply;
256 Mpi2SCSIIOReply_t *scsiio_reply;
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +0530257 Mpi26NVMeEncapsulatedErrorReply_t *nvme_error_reply;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530258 const void *sense_data;
259 u32 sz;
260
261 if (ioc->ctl_cmds.status == MPT3_CMD_NOT_USED)
262 return 1;
263 if (ioc->ctl_cmds.smid != smid)
264 return 1;
265 ioc->ctl_cmds.status |= MPT3_CMD_COMPLETE;
266 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
267 if (mpi_reply) {
268 memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
269 ioc->ctl_cmds.status |= MPT3_CMD_REPLY_VALID;
270 /* get sense data */
271 if (mpi_reply->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
272 mpi_reply->Function ==
273 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
274 scsiio_reply = (Mpi2SCSIIOReply_t *)mpi_reply;
275 if (scsiio_reply->SCSIState &
276 MPI2_SCSI_STATE_AUTOSENSE_VALID) {
277 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
278 le32_to_cpu(scsiio_reply->SenseCount));
279 sense_data = mpt3sas_base_get_sense_buffer(ioc,
280 smid);
281 memcpy(ioc->ctl_cmds.sense, sense_data, sz);
282 }
283 }
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +0530284 /*
285 * Get Error Response data for NVMe device. The ctl_cmds.sense
286 * buffer is used to store the Error Response data.
287 */
288 if (mpi_reply->Function == MPI2_FUNCTION_NVME_ENCAPSULATED) {
289 nvme_error_reply =
290 (Mpi26NVMeEncapsulatedErrorReply_t *)mpi_reply;
291 sz = min_t(u32, NVME_ERROR_RESPONSE_SIZE,
Chaitra P Bcf6bf972018-04-24 05:28:30 -0400292 le16_to_cpu(nvme_error_reply->ErrorResponseCount));
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +0530293 sense_data = mpt3sas_base_get_sense_buffer(ioc, smid);
294 memcpy(ioc->ctl_cmds.sense, sense_data, sz);
295 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530296 }
Suganath Prabu Subramani016d5c32017-10-31 18:02:28 +0530297
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530298 _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530299 ioc->ctl_cmds.status &= ~MPT3_CMD_PENDING;
300 complete(&ioc->ctl_cmds.done);
301 return 1;
302}
303
304/**
305 * _ctl_check_event_type - determines when an event needs logging
306 * @ioc: per adapter object
307 * @event: firmware event
308 *
309 * The bitmask in ioc->event_type[] indicates which events should be
310 * be saved in the driver event_log. This bitmask is set by application.
311 *
Bart Van Assche4beb4862018-06-15 14:42:01 -0700312 * Return: 1 when event should be captured, or zero means no match.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530313 */
314static int
315_ctl_check_event_type(struct MPT3SAS_ADAPTER *ioc, u16 event)
316{
317 u16 i;
318 u32 desired_event;
319
320 if (event >= 128 || !event || !ioc->event_log)
321 return 0;
322
323 desired_event = (1 << (event % 32));
324 if (!desired_event)
325 desired_event = 1;
326 i = event / 32;
327 return desired_event & ioc->event_type[i];
328}
329
330/**
331 * mpt3sas_ctl_add_to_event_log - add event
332 * @ioc: per adapter object
333 * @mpi_reply: reply message frame
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530334 */
335void
336mpt3sas_ctl_add_to_event_log(struct MPT3SAS_ADAPTER *ioc,
337 Mpi2EventNotificationReply_t *mpi_reply)
338{
339 struct MPT3_IOCTL_EVENTS *event_log;
340 u16 event;
341 int i;
342 u32 sz, event_data_sz;
343 u8 send_aen = 0;
344
345 if (!ioc->event_log)
346 return;
347
348 event = le16_to_cpu(mpi_reply->Event);
349
350 if (_ctl_check_event_type(ioc, event)) {
351
352 /* insert entry into circular event_log */
353 i = ioc->event_context % MPT3SAS_CTL_EVENT_LOG_SIZE;
354 event_log = ioc->event_log;
355 event_log[i].event = event;
356 event_log[i].context = ioc->event_context++;
357
358 event_data_sz = le16_to_cpu(mpi_reply->EventDataLength)*4;
359 sz = min_t(u32, event_data_sz, MPT3_EVENT_DATA_SIZE);
360 memset(event_log[i].data, 0, MPT3_EVENT_DATA_SIZE);
361 memcpy(event_log[i].data, mpi_reply->EventData, sz);
362 send_aen = 1;
363 }
364
365 /* This aen_event_read_flag flag is set until the
366 * application has read the event log.
367 * For MPI2_EVENT_LOG_ENTRY_ADDED, we always notify.
368 */
369 if (event == MPI2_EVENT_LOG_ENTRY_ADDED ||
370 (send_aen && !ioc->aen_event_read_flag)) {
371 ioc->aen_event_read_flag = 1;
372 wake_up_interruptible(&ctl_poll_wait);
373 if (async_queue)
374 kill_fasync(&async_queue, SIGIO, POLL_IN);
375 }
376}
377
378/**
379 * mpt3sas_ctl_event_callback - firmware event handler (called at ISR time)
380 * @ioc: per adapter object
381 * @msix_index: MSIX table index supplied by the OS
382 * @reply: reply message frame(lower 32bit addr)
383 * Context: interrupt.
384 *
385 * This function merely adds a new work task into ioc->firmware_event_thread.
386 * The tasks are worked from _firmware_event_work in user context.
387 *
Bart Van Assche4beb4862018-06-15 14:42:01 -0700388 * Return: 1 meaning mf should be freed from _base_interrupt
389 * 0 means the mf is freed from this function.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530390 */
391u8
392mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
393 u32 reply)
394{
395 Mpi2EventNotificationReply_t *mpi_reply;
396
397 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
Suganath prabu Subramani869817f2016-01-28 12:07:00 +0530398 if (mpi_reply)
399 mpt3sas_ctl_add_to_event_log(ioc, mpi_reply);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530400 return 1;
401}
402
403/**
404 * _ctl_verify_adapter - validates ioc_number passed from application
Bart Van Assche4beb4862018-06-15 14:42:01 -0700405 * @ioc_number: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530406 * @iocpp: The ioc pointer is returned in this.
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +0530407 * @mpi_version: will be MPI2_VERSION for mpt2ctl ioctl device &
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +0530408 * MPI25_VERSION | MPI26_VERSION for mpt3ctl ioctl device.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530409 *
Bart Van Assche4beb4862018-06-15 14:42:01 -0700410 * Return: (-1) means error, else ioc_number.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530411 */
412static int
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +0530413_ctl_verify_adapter(int ioc_number, struct MPT3SAS_ADAPTER **iocpp,
414 int mpi_version)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530415{
416 struct MPT3SAS_ADAPTER *ioc;
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +0530417 int version = 0;
Sreekanth Reddy08c4d552015-11-11 17:30:33 +0530418 /* global ioc lock to protect controller on list operations */
419 spin_lock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530420 list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
421 if (ioc->id != ioc_number)
422 continue;
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +0530423 /* Check whether this ioctl command is from right
424 * ioctl device or not, if not continue the search.
425 */
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +0530426 version = ioc->hba_mpi_version_belonged;
427 /* MPI25_VERSION and MPI26_VERSION uses same ioctl
428 * device.
429 */
430 if (mpi_version == (MPI25_VERSION | MPI26_VERSION)) {
431 if ((version == MPI25_VERSION) ||
432 (version == MPI26_VERSION))
433 goto out;
434 else
435 continue;
436 } else {
437 if (version != mpi_version)
438 continue;
439 }
440out:
Sreekanth Reddy08c4d552015-11-11 17:30:33 +0530441 spin_unlock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530442 *iocpp = ioc;
443 return ioc_number;
444 }
Sreekanth Reddy08c4d552015-11-11 17:30:33 +0530445 spin_unlock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530446 *iocpp = NULL;
447 return -1;
448}
449
450/**
451 * mpt3sas_ctl_reset_handler - reset callback handler (for ctl)
452 * @ioc: per adapter object
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530453 *
454 * The handler for doing any required cleanup or initialization.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530455 */
Bart Van Asschec7a35702018-06-15 14:42:00 -0700456void mpt3sas_ctl_pre_reset_handler(struct MPT3SAS_ADAPTER *ioc)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530457{
458 int i;
459 u8 issue_reset;
460
Joe Perches919d8a32018-09-17 08:01:09 -0700461 dtmprintk(ioc, ioc_info(ioc, "%s: MPT3_IOC_PRE_RESET\n", __func__));
Bart Van Asschec7a35702018-06-15 14:42:00 -0700462 for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
463 if (!(ioc->diag_buffer_status[i] &
464 MPT3_DIAG_BUFFER_IS_REGISTERED))
465 continue;
466 if ((ioc->diag_buffer_status[i] &
467 MPT3_DIAG_BUFFER_IS_RELEASED))
468 continue;
Sreekanth Reddy4bc50dc2019-09-13 09:04:39 -0400469
470 /*
471 * add a log message to indicate the release
472 */
473 ioc_info(ioc,
474 "%s: Releasing the trace buffer due to adapter reset.",
475 __func__);
Bart Van Asschec7a35702018-06-15 14:42:00 -0700476 mpt3sas_send_diag_release(ioc, i, &issue_reset);
477 }
478}
479
480/**
481 * mpt3sas_ctl_reset_handler - reset callback handler (for ctl)
482 * @ioc: per adapter object
483 *
484 * The handler for doing any required cleanup or initialization.
485 */
486void mpt3sas_ctl_after_reset_handler(struct MPT3SAS_ADAPTER *ioc)
487{
Joe Perches919d8a32018-09-17 08:01:09 -0700488 dtmprintk(ioc, ioc_info(ioc, "%s: MPT3_IOC_AFTER_RESET\n", __func__));
Bart Van Asschec7a35702018-06-15 14:42:00 -0700489 if (ioc->ctl_cmds.status & MPT3_CMD_PENDING) {
490 ioc->ctl_cmds.status |= MPT3_CMD_RESET;
491 mpt3sas_base_free_smid(ioc, ioc->ctl_cmds.smid);
492 complete(&ioc->ctl_cmds.done);
493 }
494}
495
496/**
497 * mpt3sas_ctl_reset_handler - reset callback handler (for ctl)
498 * @ioc: per adapter object
499 *
500 * The handler for doing any required cleanup or initialization.
501 */
502void mpt3sas_ctl_reset_done_handler(struct MPT3SAS_ADAPTER *ioc)
503{
504 int i;
505
Joe Perches919d8a32018-09-17 08:01:09 -0700506 dtmprintk(ioc, ioc_info(ioc, "%s: MPT3_IOC_DONE_RESET\n", __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530507
Bart Van Asschec7a35702018-06-15 14:42:00 -0700508 for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
509 if (!(ioc->diag_buffer_status[i] &
510 MPT3_DIAG_BUFFER_IS_REGISTERED))
511 continue;
512 if ((ioc->diag_buffer_status[i] &
513 MPT3_DIAG_BUFFER_IS_RELEASED))
514 continue;
515 ioc->diag_buffer_status[i] |=
516 MPT3_DIAG_BUFFER_IS_DIAG_RESET;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530517 }
518}
519
520/**
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +0530521 * _ctl_fasync -
Bart Van Assche4beb4862018-06-15 14:42:01 -0700522 * @fd: ?
523 * @filep: ?
524 * @mode: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530525 *
526 * Called when application request fasyn callback handler.
527 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -0700528static int
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +0530529_ctl_fasync(int fd, struct file *filep, int mode)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530530{
531 return fasync_helper(fd, filep, mode, &async_queue);
532}
533
534/**
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +0530535 * _ctl_poll -
Bart Van Assche4beb4862018-06-15 14:42:01 -0700536 * @filep: ?
537 * @wait: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530538 *
539 */
Al Viroafc9a422017-07-03 06:39:46 -0400540static __poll_t
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +0530541_ctl_poll(struct file *filep, poll_table *wait)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530542{
543 struct MPT3SAS_ADAPTER *ioc;
544
545 poll_wait(filep, &ctl_poll_wait, wait);
546
Sreekanth Reddy08c4d552015-11-11 17:30:33 +0530547 /* global ioc lock to protect controller on list operations */
548 spin_lock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530549 list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
Sreekanth Reddy08c4d552015-11-11 17:30:33 +0530550 if (ioc->aen_event_read_flag) {
551 spin_unlock(&gioc_lock);
Linus Torvaldsa9a08842018-02-11 14:34:03 -0800552 return EPOLLIN | EPOLLRDNORM;
Sreekanth Reddy08c4d552015-11-11 17:30:33 +0530553 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530554 }
Sreekanth Reddy08c4d552015-11-11 17:30:33 +0530555 spin_unlock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530556 return 0;
557}
558
559/**
560 * _ctl_set_task_mid - assign an active smid to tm request
561 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -0700562 * @karg: (struct mpt3_ioctl_command)
563 * @tm_request: pointer to mf from user space
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530564 *
Bart Van Assche4beb4862018-06-15 14:42:01 -0700565 * Return: 0 when an smid if found, else fail.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530566 * during failure, the reply frame is filled.
567 */
568static int
569_ctl_set_task_mid(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command *karg,
570 Mpi2SCSITaskManagementRequest_t *tm_request)
571{
572 u8 found = 0;
Suganath Prabu Subramanidbec4c902018-01-04 04:57:11 -0800573 u16 smid;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530574 u16 handle;
575 struct scsi_cmnd *scmd;
576 struct MPT3SAS_DEVICE *priv_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530577 Mpi2SCSITaskManagementReply_t *tm_reply;
578 u32 sz;
579 u32 lun;
580 char *desc = NULL;
581
582 if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
583 desc = "abort_task";
584 else if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK)
585 desc = "query_task";
586 else
587 return 0;
588
589 lun = scsilun_to_int((struct scsi_lun *)tm_request->LUN);
590
591 handle = le16_to_cpu(tm_request->DevHandle);
Suganath Prabu Subramanidbec4c902018-01-04 04:57:11 -0800592 for (smid = ioc->scsiio_depth; smid && !found; smid--) {
593 struct scsiio_tracker *st;
594
595 scmd = mpt3sas_scsih_scsi_lookup_get(ioc, smid);
596 if (!scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530597 continue;
598 if (lun != scmd->device->lun)
599 continue;
600 priv_data = scmd->device->hostdata;
601 if (priv_data->sas_target == NULL)
602 continue;
603 if (priv_data->sas_target->handle != handle)
604 continue;
Suganath Prabu Subramanidbec4c902018-01-04 04:57:11 -0800605 st = scsi_cmd_priv(scmd);
Minwoo Im8f55c302019-07-28 03:53:37 +0900606
607 /*
608 * If the given TaskMID from the user space is zero, then the
609 * first outstanding smid will be picked up. Otherwise,
610 * targeted smid will be the one.
611 */
612 if (!tm_request->TaskMID || tm_request->TaskMID == st->smid) {
613 tm_request->TaskMID = cpu_to_le16(st->smid);
614 found = 1;
615 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530616 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530617
618 if (!found) {
Joe Perches919d8a32018-09-17 08:01:09 -0700619 dctlprintk(ioc,
620 ioc_info(ioc, "%s: handle(0x%04x), lun(%d), no active mid!!\n",
621 desc, le16_to_cpu(tm_request->DevHandle),
622 lun));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530623 tm_reply = ioc->ctl_cmds.reply;
624 tm_reply->DevHandle = tm_request->DevHandle;
625 tm_reply->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
626 tm_reply->TaskType = tm_request->TaskType;
627 tm_reply->MsgLength = sizeof(Mpi2SCSITaskManagementReply_t)/4;
628 tm_reply->VP_ID = tm_request->VP_ID;
629 tm_reply->VF_ID = tm_request->VF_ID;
630 sz = min_t(u32, karg->max_reply_bytes, ioc->reply_sz);
631 if (copy_to_user(karg->reply_frame_buf_ptr, ioc->ctl_cmds.reply,
632 sz))
633 pr_err("failure at %s:%d/%s()!\n", __FILE__,
634 __LINE__, __func__);
635 return 1;
636 }
637
Joe Perches919d8a32018-09-17 08:01:09 -0700638 dctlprintk(ioc,
639 ioc_info(ioc, "%s: handle(0x%04x), lun(%d), task_mid(%d)\n",
640 desc, le16_to_cpu(tm_request->DevHandle), lun,
641 le16_to_cpu(tm_request->TaskMID)));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530642 return 0;
643}
644
645/**
646 * _ctl_do_mpt_command - main handler for MPT3COMMAND opcode
647 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -0700648 * @karg: (struct mpt3_ioctl_command)
649 * @mf: pointer to mf in user space
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530650 */
651static long
652_ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
653 void __user *mf)
654{
655 MPI2RequestHeader_t *mpi_request = NULL, *request;
656 MPI2DefaultReply_t *mpi_reply;
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +0530657 Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request = NULL;
Chaitra P Bc1a6c5a2018-04-24 05:28:41 -0400658 struct _pcie_device *pcie_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530659 u16 smid;
Chaitra P Bc1a6c5a2018-04-24 05:28:41 -0400660 u8 timeout;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530661 u8 issue_reset;
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +0530662 u32 sz, sz_arg;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530663 void *psge;
664 void *data_out = NULL;
665 dma_addr_t data_out_dma = 0;
666 size_t data_out_sz = 0;
667 void *data_in = NULL;
668 dma_addr_t data_in_dma = 0;
669 size_t data_in_sz = 0;
670 long ret;
Suganath Prabu Subramanic696f7b2016-10-26 13:34:34 +0530671 u16 device_handle = MPT3SAS_INVALID_DEVICE_HANDLE;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530672
673 issue_reset = 0;
674
675 if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
Joe Perches919d8a32018-09-17 08:01:09 -0700676 ioc_err(ioc, "%s: ctl_cmd in use\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530677 ret = -EAGAIN;
678 goto out;
679 }
680
Suganath Prabuf4305742018-10-31 18:53:33 +0530681 ret = mpt3sas_wait_for_ioc(ioc, IOC_OPERATIONAL_WAIT_COUNT);
682 if (ret)
683 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530684
685 mpi_request = kzalloc(ioc->request_sz, GFP_KERNEL);
686 if (!mpi_request) {
Joe Perches919d8a32018-09-17 08:01:09 -0700687 ioc_err(ioc, "%s: failed obtaining a memory for mpi_request\n",
688 __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530689 ret = -ENOMEM;
690 goto out;
691 }
692
693 /* Check for overflow and wraparound */
694 if (karg.data_sge_offset * 4 > ioc->request_sz ||
695 karg.data_sge_offset > (UINT_MAX / 4)) {
696 ret = -EINVAL;
697 goto out;
698 }
699
700 /* copy in request message frame from user */
701 if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) {
702 pr_err("failure at %s:%d/%s()!\n", __FILE__, __LINE__,
703 __func__);
704 ret = -EFAULT;
705 goto out;
706 }
707
708 if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
709 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->ctl_cb_idx);
710 if (!smid) {
Joe Perches919d8a32018-09-17 08:01:09 -0700711 ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530712 ret = -EAGAIN;
713 goto out;
714 }
715 } else {
Hannes Reineckeb0cd285e2018-01-04 04:57:07 -0800716 /* Use first reserved smid for passthrough ioctls */
717 smid = ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT + 1;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530718 }
719
720 ret = 0;
721 ioc->ctl_cmds.status = MPT3_CMD_PENDING;
722 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
723 request = mpt3sas_base_get_msg_frame(ioc, smid);
Suganath Prabue224e032019-08-03 09:59:47 -0400724 memset(request, 0, ioc->request_sz);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530725 memcpy(request, mpi_request, karg.data_sge_offset*4);
726 ioc->ctl_cmds.smid = smid;
727 data_out_sz = karg.data_out_size;
728 data_in_sz = karg.data_in_size;
729
730 if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
Suganath Prabu Subramanic696f7b2016-10-26 13:34:34 +0530731 mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
732 mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT ||
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +0530733 mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH ||
734 mpi_request->Function == MPI2_FUNCTION_NVME_ENCAPSULATED) {
Suganath Prabu Subramanic696f7b2016-10-26 13:34:34 +0530735
736 device_handle = le16_to_cpu(mpi_request->FunctionDependent1);
737 if (!device_handle || (device_handle >
738 ioc->facts.MaxDevHandle)) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530739 ret = -EINVAL;
740 mpt3sas_base_free_smid(ioc, smid);
741 goto out;
742 }
743 }
744
745 /* obtain dma-able memory for data transfer */
746 if (data_out_sz) /* WRITE */ {
Christoph Hellwig1c2048b2018-10-11 09:35:25 +0200747 data_out = dma_alloc_coherent(&ioc->pdev->dev, data_out_sz,
748 &data_out_dma, GFP_KERNEL);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530749 if (!data_out) {
750 pr_err("failure at %s:%d/%s()!\n", __FILE__,
751 __LINE__, __func__);
752 ret = -ENOMEM;
753 mpt3sas_base_free_smid(ioc, smid);
754 goto out;
755 }
756 if (copy_from_user(data_out, karg.data_out_buf_ptr,
757 data_out_sz)) {
758 pr_err("failure at %s:%d/%s()!\n", __FILE__,
759 __LINE__, __func__);
760 ret = -EFAULT;
761 mpt3sas_base_free_smid(ioc, smid);
762 goto out;
763 }
764 }
765
766 if (data_in_sz) /* READ */ {
Christoph Hellwig1c2048b2018-10-11 09:35:25 +0200767 data_in = dma_alloc_coherent(&ioc->pdev->dev, data_in_sz,
768 &data_in_dma, GFP_KERNEL);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530769 if (!data_in) {
770 pr_err("failure at %s:%d/%s()!\n", __FILE__,
771 __LINE__, __func__);
772 ret = -ENOMEM;
773 mpt3sas_base_free_smid(ioc, smid);
774 goto out;
775 }
776 }
777
778 psge = (void *)request + (karg.data_sge_offset*4);
779
780 /* send command to firmware */
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530781 _ctl_display_some_debug(ioc, smid, "ctl_request", NULL);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530782
783 init_completion(&ioc->ctl_cmds.done);
784 switch (mpi_request->Function) {
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +0530785 case MPI2_FUNCTION_NVME_ENCAPSULATED:
786 {
787 nvme_encap_request = (Mpi26NVMeEncapsulatedRequest_t *)request;
788 /*
789 * Get the Physical Address of the sense buffer.
790 * Use Error Response buffer address field to hold the sense
791 * buffer address.
792 * Clear the internal sense buffer, which will potentially hold
793 * the Completion Queue Entry on return, or 0 if no Entry.
794 * Build the PRPs and set direction bits.
795 * Send the request.
796 */
Chaitra P Bcf6bf972018-04-24 05:28:30 -0400797 nvme_encap_request->ErrorResponseBaseAddress =
798 cpu_to_le64(ioc->sense_dma & 0xFFFFFFFF00000000UL);
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +0530799 nvme_encap_request->ErrorResponseBaseAddress |=
Chaitra P Bcf6bf972018-04-24 05:28:30 -0400800 cpu_to_le64(le32_to_cpu(
801 mpt3sas_base_get_sense_buffer_dma(ioc, smid)));
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +0530802 nvme_encap_request->ErrorResponseAllocationLength =
Chaitra P Bcf6bf972018-04-24 05:28:30 -0400803 cpu_to_le16(NVME_ERROR_RESPONSE_SIZE);
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +0530804 memset(ioc->ctl_cmds.sense, 0, NVME_ERROR_RESPONSE_SIZE);
805 ioc->build_nvme_prp(ioc, smid, nvme_encap_request,
806 data_out_dma, data_out_sz, data_in_dma, data_in_sz);
807 if (test_bit(device_handle, ioc->device_remove_in_progress)) {
Joe Perches919d8a32018-09-17 08:01:09 -0700808 dtmprintk(ioc,
809 ioc_info(ioc, "handle(0x%04x): ioctl failed due to device removal in progress\n",
810 device_handle));
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +0530811 mpt3sas_base_free_smid(ioc, smid);
812 ret = -EINVAL;
813 goto out;
814 }
Suganath Prabu S40114bd2018-02-14 02:16:37 -0800815 mpt3sas_base_put_smid_nvme_encap(ioc, smid);
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +0530816 break;
817 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530818 case MPI2_FUNCTION_SCSI_IO_REQUEST:
819 case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
820 {
821 Mpi2SCSIIORequest_t *scsiio_request =
822 (Mpi2SCSIIORequest_t *)request;
823 scsiio_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
824 scsiio_request->SenseBufferLowAddress =
825 mpt3sas_base_get_sense_buffer_dma(ioc, smid);
826 memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE);
Suganath Prabu Subramanic696f7b2016-10-26 13:34:34 +0530827 if (test_bit(device_handle, ioc->device_remove_in_progress)) {
Joe Perches919d8a32018-09-17 08:01:09 -0700828 dtmprintk(ioc,
829 ioc_info(ioc, "handle(0x%04x) :ioctl failed due to device removal in progress\n",
830 device_handle));
Suganath Prabu Subramanic696f7b2016-10-26 13:34:34 +0530831 mpt3sas_base_free_smid(ioc, smid);
832 ret = -EINVAL;
833 goto out;
834 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530835 ioc->build_sg(ioc, psge, data_out_dma, data_out_sz,
836 data_in_dma, data_in_sz);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530837 if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)
Suganath Prabu Subramani81c16f82016-10-26 13:34:40 +0530838 ioc->put_smid_scsi_io(ioc, smid, device_handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530839 else
Suganath Prabu S078a4cc2019-05-31 08:14:34 -0400840 ioc->put_smid_default(ioc, smid);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530841 break;
842 }
843 case MPI2_FUNCTION_SCSI_TASK_MGMT:
844 {
845 Mpi2SCSITaskManagementRequest_t *tm_request =
846 (Mpi2SCSITaskManagementRequest_t *)request;
847
Joe Perches919d8a32018-09-17 08:01:09 -0700848 dtmprintk(ioc,
849 ioc_info(ioc, "TASK_MGMT: handle(0x%04x), task_type(0x%02x)\n",
850 le16_to_cpu(tm_request->DevHandle),
851 tm_request->TaskType));
Chaitra P B459325c2017-01-23 15:26:08 +0530852 ioc->got_task_abort_from_ioctl = 1;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530853 if (tm_request->TaskType ==
854 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK ||
855 tm_request->TaskType ==
856 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) {
857 if (_ctl_set_task_mid(ioc, &karg, tm_request)) {
858 mpt3sas_base_free_smid(ioc, smid);
Chaitra P B459325c2017-01-23 15:26:08 +0530859 ioc->got_task_abort_from_ioctl = 0;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530860 goto out;
861 }
862 }
Chaitra P B459325c2017-01-23 15:26:08 +0530863 ioc->got_task_abort_from_ioctl = 0;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530864
Suganath Prabu Subramanic696f7b2016-10-26 13:34:34 +0530865 if (test_bit(device_handle, ioc->device_remove_in_progress)) {
Joe Perches919d8a32018-09-17 08:01:09 -0700866 dtmprintk(ioc,
867 ioc_info(ioc, "handle(0x%04x) :ioctl failed due to device removal in progress\n",
868 device_handle));
Suganath Prabu Subramanic696f7b2016-10-26 13:34:34 +0530869 mpt3sas_base_free_smid(ioc, smid);
870 ret = -EINVAL;
871 goto out;
872 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530873 mpt3sas_scsih_set_tm_flag(ioc, le16_to_cpu(
874 tm_request->DevHandle));
875 ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
876 data_in_dma, data_in_sz);
Suganath Prabu S078a4cc2019-05-31 08:14:34 -0400877 ioc->put_smid_hi_priority(ioc, smid, 0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530878 break;
879 }
880 case MPI2_FUNCTION_SMP_PASSTHROUGH:
881 {
882 Mpi2SmpPassthroughRequest_t *smp_request =
883 (Mpi2SmpPassthroughRequest_t *)mpi_request;
884 u8 *data;
885
886 /* ioc determines which port to use */
887 smp_request->PhysicalPort = 0xFF;
888 if (smp_request->PassthroughFlags &
889 MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE)
890 data = (u8 *)&smp_request->SGL;
891 else {
892 if (unlikely(data_out == NULL)) {
893 pr_err("failure at %s:%d/%s()!\n",
894 __FILE__, __LINE__, __func__);
895 mpt3sas_base_free_smid(ioc, smid);
896 ret = -EINVAL;
897 goto out;
898 }
899 data = data_out;
900 }
901
902 if (data[1] == 0x91 && (data[10] == 1 || data[10] == 2)) {
903 ioc->ioc_link_reset_in_progress = 1;
904 ioc->ignore_loginfos = 1;
905 }
906 ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
907 data_in_sz);
Suganath Prabu S078a4cc2019-05-31 08:14:34 -0400908 ioc->put_smid_default(ioc, smid);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530909 break;
910 }
911 case MPI2_FUNCTION_SATA_PASSTHROUGH:
Suganath Prabu Subramanic696f7b2016-10-26 13:34:34 +0530912 {
913 if (test_bit(device_handle, ioc->device_remove_in_progress)) {
Joe Perches919d8a32018-09-17 08:01:09 -0700914 dtmprintk(ioc,
915 ioc_info(ioc, "handle(0x%04x) :ioctl failed due to device removal in progress\n",
916 device_handle));
Suganath Prabu Subramanic696f7b2016-10-26 13:34:34 +0530917 mpt3sas_base_free_smid(ioc, smid);
918 ret = -EINVAL;
919 goto out;
920 }
921 ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
922 data_in_sz);
Suganath Prabu S078a4cc2019-05-31 08:14:34 -0400923 ioc->put_smid_default(ioc, smid);
Suganath Prabu Subramanic696f7b2016-10-26 13:34:34 +0530924 break;
925 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530926 case MPI2_FUNCTION_FW_DOWNLOAD:
927 case MPI2_FUNCTION_FW_UPLOAD:
928 {
929 ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
930 data_in_sz);
Suganath Prabu S078a4cc2019-05-31 08:14:34 -0400931 ioc->put_smid_default(ioc, smid);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530932 break;
933 }
934 case MPI2_FUNCTION_TOOLBOX:
935 {
936 Mpi2ToolboxCleanRequest_t *toolbox_request =
937 (Mpi2ToolboxCleanRequest_t *)mpi_request;
938
Suganath Prabuf23ca2c2019-08-03 09:59:46 -0400939 if ((toolbox_request->Tool == MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL)
940 || (toolbox_request->Tool ==
941 MPI26_TOOLBOX_BACKEND_PCIE_LANE_MARGIN))
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530942 ioc->build_sg(ioc, psge, data_out_dma, data_out_sz,
943 data_in_dma, data_in_sz);
Suganath Prabuba630ea2019-08-03 09:59:52 -0400944 else if (toolbox_request->Tool ==
945 MPI2_TOOLBOX_MEMORY_MOVE_TOOL) {
946 Mpi2ToolboxMemMoveRequest_t *mem_move_request =
947 (Mpi2ToolboxMemMoveRequest_t *)request;
948 Mpi2SGESimple64_t tmp, *src = NULL, *dst = NULL;
949
950 ioc->build_sg_mpi(ioc, psge, data_out_dma,
951 data_out_sz, data_in_dma, data_in_sz);
952 if (data_out_sz && !data_in_sz) {
953 dst =
954 (Mpi2SGESimple64_t *)&mem_move_request->SGL;
955 src = (void *)dst + ioc->sge_size;
956
957 memcpy(&tmp, src, ioc->sge_size);
958 memcpy(src, dst, ioc->sge_size);
959 memcpy(dst, &tmp, ioc->sge_size);
960 }
961 if (ioc->logging_level & MPT_DEBUG_TM) {
962 ioc_info(ioc,
963 "Mpi2ToolboxMemMoveRequest_t request msg\n");
964 _debug_dump_mf(mem_move_request,
965 ioc->request_sz/4);
966 }
967 } else
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530968 ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
Suganath Prabuba630ea2019-08-03 09:59:52 -0400969 data_in_dma, data_in_sz);
Suganath Prabu S078a4cc2019-05-31 08:14:34 -0400970 ioc->put_smid_default(ioc, smid);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530971 break;
972 }
973 case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
974 {
975 Mpi2SasIoUnitControlRequest_t *sasiounit_request =
976 (Mpi2SasIoUnitControlRequest_t *)mpi_request;
977
978 if (sasiounit_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET
979 || sasiounit_request->Operation ==
980 MPI2_SAS_OP_PHY_LINK_RESET) {
981 ioc->ioc_link_reset_in_progress = 1;
982 ioc->ignore_loginfos = 1;
983 }
984 /* drop to default case for posting the request */
985 }
Bart Van Asscheeb0c7af2018-06-15 14:41:56 -0700986 /* fall through */
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530987 default:
988 ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
989 data_in_dma, data_in_sz);
Suganath Prabu S078a4cc2019-05-31 08:14:34 -0400990 ioc->put_smid_default(ioc, smid);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530991 break;
992 }
993
994 if (karg.timeout < MPT3_IOCTL_DEFAULT_TIMEOUT)
995 timeout = MPT3_IOCTL_DEFAULT_TIMEOUT;
996 else
997 timeout = karg.timeout;
Calvin Owens8bbb1cf2016-07-28 21:38:22 -0700998 wait_for_completion_timeout(&ioc->ctl_cmds.done, timeout*HZ);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530999 if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
1000 Mpi2SCSITaskManagementRequest_t *tm_request =
1001 (Mpi2SCSITaskManagementRequest_t *)mpi_request;
1002 mpt3sas_scsih_clear_tm_flag(ioc, le16_to_cpu(
1003 tm_request->DevHandle));
1004 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT);
1005 } else if ((mpi_request->Function == MPI2_FUNCTION_SMP_PASSTHROUGH ||
1006 mpi_request->Function == MPI2_FUNCTION_SAS_IO_UNIT_CONTROL) &&
1007 ioc->ioc_link_reset_in_progress) {
1008 ioc->ioc_link_reset_in_progress = 0;
1009 ioc->ignore_loginfos = 0;
1010 }
1011 if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
Chaitra P Bd37306c2018-05-31 06:34:50 -04001012 issue_reset =
1013 mpt3sas_base_check_cmd_timeout(ioc,
1014 ioc->ctl_cmds.status, mpi_request,
1015 karg.data_sge_offset);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301016 goto issue_host_reset;
1017 }
1018
1019 mpi_reply = ioc->ctl_cmds.reply;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301020
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301021 if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT &&
1022 (ioc->logging_level & MPT_DEBUG_TM)) {
1023 Mpi2SCSITaskManagementReply_t *tm_reply =
1024 (Mpi2SCSITaskManagementReply_t *)mpi_reply;
1025
Joe Perches919d8a32018-09-17 08:01:09 -07001026 ioc_info(ioc, "TASK_MGMT: IOCStatus(0x%04x), IOCLogInfo(0x%08x), TerminationCount(0x%08x)\n",
1027 le16_to_cpu(tm_reply->IOCStatus),
1028 le32_to_cpu(tm_reply->IOCLogInfo),
1029 le32_to_cpu(tm_reply->TerminationCount));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301030 }
Sreekanth Reddyaf009412015-11-11 17:30:23 +05301031
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301032 /* copy out xdata to user */
1033 if (data_in_sz) {
1034 if (copy_to_user(karg.data_in_buf_ptr, data_in,
1035 data_in_sz)) {
1036 pr_err("failure at %s:%d/%s()!\n", __FILE__,
1037 __LINE__, __func__);
1038 ret = -ENODATA;
1039 goto out;
1040 }
1041 }
1042
1043 /* copy out reply message frame to user */
1044 if (karg.max_reply_bytes) {
1045 sz = min_t(u32, karg.max_reply_bytes, ioc->reply_sz);
1046 if (copy_to_user(karg.reply_frame_buf_ptr, ioc->ctl_cmds.reply,
1047 sz)) {
1048 pr_err("failure at %s:%d/%s()!\n", __FILE__,
1049 __LINE__, __func__);
1050 ret = -ENODATA;
1051 goto out;
1052 }
1053 }
1054
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +05301055 /* copy out sense/NVMe Error Response to user */
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301056 if (karg.max_sense_bytes && (mpi_request->Function ==
1057 MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function ==
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +05301058 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || mpi_request->Function ==
1059 MPI2_FUNCTION_NVME_ENCAPSULATED)) {
1060 if (karg.sense_data_ptr == NULL) {
Joe Perches919d8a32018-09-17 08:01:09 -07001061 ioc_info(ioc, "Response buffer provided by application is NULL; Response data will not be returned\n");
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +05301062 goto out;
1063 }
1064 sz_arg = (mpi_request->Function ==
1065 MPI2_FUNCTION_NVME_ENCAPSULATED) ? NVME_ERROR_RESPONSE_SIZE :
1066 SCSI_SENSE_BUFFERSIZE;
1067 sz = min_t(u32, karg.max_sense_bytes, sz_arg);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301068 if (copy_to_user(karg.sense_data_ptr, ioc->ctl_cmds.sense,
1069 sz)) {
1070 pr_err("failure at %s:%d/%s()!\n", __FILE__,
Suganath Prabu Subramaniaff39e62017-10-31 18:02:29 +05301071 __LINE__, __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301072 ret = -ENODATA;
1073 goto out;
1074 }
1075 }
1076
1077 issue_host_reset:
1078 if (issue_reset) {
1079 ret = -ENODATA;
1080 if ((mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
1081 mpi_request->Function ==
1082 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
1083 mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH)) {
Joe Perches919d8a32018-09-17 08:01:09 -07001084 ioc_info(ioc, "issue target reset: handle = (0x%04x)\n",
1085 le16_to_cpu(mpi_request->FunctionDependent1));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301086 mpt3sas_halt_firmware(ioc);
Chaitra P Bc1a6c5a2018-04-24 05:28:41 -04001087 pcie_device = mpt3sas_get_pdev_by_handle(ioc,
1088 le16_to_cpu(mpi_request->FunctionDependent1));
Suganath Prabu5bb309d2019-08-03 09:59:50 -04001089 if (pcie_device && (!ioc->tm_custom_handling) &&
1090 (!(mpt3sas_scsih_is_pcie_scsi_device(
1091 pcie_device->device_info))))
Chaitra P Bc1a6c5a2018-04-24 05:28:41 -04001092 mpt3sas_scsih_issue_locked_tm(ioc,
1093 le16_to_cpu(mpi_request->FunctionDependent1),
1094 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
1095 0, pcie_device->reset_timeout,
Suganath Prabu5bb309d2019-08-03 09:59:50 -04001096 MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE);
Chaitra P Bc1a6c5a2018-04-24 05:28:41 -04001097 else
1098 mpt3sas_scsih_issue_locked_tm(ioc,
1099 le16_to_cpu(mpi_request->FunctionDependent1),
1100 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
1101 0, 30, MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301102 } else
Calvin Owens98c56ad2016-07-28 21:38:21 -07001103 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301104 }
1105
1106 out:
Chaitra P Bc1a6c5a2018-04-24 05:28:41 -04001107 if (pcie_device)
1108 pcie_device_put(pcie_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301109
1110 /* free memory associated with sg buffers */
1111 if (data_in)
Christoph Hellwig1c2048b2018-10-11 09:35:25 +02001112 dma_free_coherent(&ioc->pdev->dev, data_in_sz, data_in,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301113 data_in_dma);
1114
1115 if (data_out)
Christoph Hellwig1c2048b2018-10-11 09:35:25 +02001116 dma_free_coherent(&ioc->pdev->dev, data_out_sz, data_out,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301117 data_out_dma);
1118
1119 kfree(mpi_request);
1120 ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
1121 return ret;
1122}
1123
1124/**
1125 * _ctl_getiocinfo - main handler for MPT3IOCINFO opcode
1126 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07001127 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301128 */
1129static long
1130_ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1131{
1132 struct mpt3_ioctl_iocinfo karg;
1133
Joe Perches919d8a32018-09-17 08:01:09 -07001134 dctlprintk(ioc, ioc_info(ioc, "%s: enter\n",
1135 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301136
1137 memset(&karg, 0 , sizeof(karg));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301138 if (ioc->pfacts)
1139 karg.port_number = ioc->pfacts[0].PortNumber;
1140 karg.hw_rev = ioc->pdev->revision;
1141 karg.pci_id = ioc->pdev->device;
1142 karg.subsystem_device = ioc->pdev->subsystem_device;
1143 karg.subsystem_vendor = ioc->pdev->subsystem_vendor;
1144 karg.pci_information.u.bits.bus = ioc->pdev->bus->number;
1145 karg.pci_information.u.bits.device = PCI_SLOT(ioc->pdev->devfn);
1146 karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn);
1147 karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus);
1148 karg.firmware_version = ioc->facts.FWVersion.Word;
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05301149 strcpy(karg.driver_version, ioc->driver_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301150 strcat(karg.driver_version, "-");
Sreekanth Reddyd357e842015-11-11 17:30:22 +05301151 switch (ioc->hba_mpi_version_belonged) {
1152 case MPI2_VERSION:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301153 if (ioc->is_warpdrive)
1154 karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2_SSS6200;
1155 else
1156 karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2;
Sreekanth Reddyd357e842015-11-11 17:30:22 +05301157 strcat(karg.driver_version, MPT2SAS_DRIVER_VERSION);
1158 break;
1159 case MPI25_VERSION:
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05301160 case MPI26_VERSION:
Suganath Prabu Subramani998f26a2016-10-26 13:34:37 +05301161 if (ioc->is_gen35_ioc)
1162 karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS35;
1163 else
1164 karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS3;
Sreekanth Reddyd357e842015-11-11 17:30:22 +05301165 strcat(karg.driver_version, MPT3SAS_DRIVER_VERSION);
1166 break;
1167 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301168 karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
1169
1170 if (copy_to_user(arg, &karg, sizeof(karg))) {
1171 pr_err("failure at %s:%d/%s()!\n",
1172 __FILE__, __LINE__, __func__);
1173 return -EFAULT;
1174 }
1175 return 0;
1176}
1177
1178/**
1179 * _ctl_eventquery - main handler for MPT3EVENTQUERY opcode
1180 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07001181 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301182 */
1183static long
1184_ctl_eventquery(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1185{
1186 struct mpt3_ioctl_eventquery karg;
1187
1188 if (copy_from_user(&karg, arg, sizeof(karg))) {
1189 pr_err("failure at %s:%d/%s()!\n",
1190 __FILE__, __LINE__, __func__);
1191 return -EFAULT;
1192 }
1193
Joe Perches919d8a32018-09-17 08:01:09 -07001194 dctlprintk(ioc, ioc_info(ioc, "%s: enter\n",
1195 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301196
1197 karg.event_entries = MPT3SAS_CTL_EVENT_LOG_SIZE;
1198 memcpy(karg.event_types, ioc->event_type,
1199 MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
1200
1201 if (copy_to_user(arg, &karg, sizeof(karg))) {
1202 pr_err("failure at %s:%d/%s()!\n",
1203 __FILE__, __LINE__, __func__);
1204 return -EFAULT;
1205 }
1206 return 0;
1207}
1208
1209/**
1210 * _ctl_eventenable - main handler for MPT3EVENTENABLE opcode
1211 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07001212 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301213 */
1214static long
1215_ctl_eventenable(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1216{
1217 struct mpt3_ioctl_eventenable karg;
1218
1219 if (copy_from_user(&karg, arg, sizeof(karg))) {
1220 pr_err("failure at %s:%d/%s()!\n",
1221 __FILE__, __LINE__, __func__);
1222 return -EFAULT;
1223 }
1224
Joe Perches919d8a32018-09-17 08:01:09 -07001225 dctlprintk(ioc, ioc_info(ioc, "%s: enter\n",
1226 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301227
1228 memcpy(ioc->event_type, karg.event_types,
1229 MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
1230 mpt3sas_base_validate_event_type(ioc, ioc->event_type);
1231
1232 if (ioc->event_log)
1233 return 0;
1234 /* initialize event_log */
1235 ioc->event_context = 0;
1236 ioc->aen_event_read_flag = 0;
1237 ioc->event_log = kcalloc(MPT3SAS_CTL_EVENT_LOG_SIZE,
1238 sizeof(struct MPT3_IOCTL_EVENTS), GFP_KERNEL);
1239 if (!ioc->event_log) {
1240 pr_err("failure at %s:%d/%s()!\n",
1241 __FILE__, __LINE__, __func__);
1242 return -ENOMEM;
1243 }
1244 return 0;
1245}
1246
1247/**
1248 * _ctl_eventreport - main handler for MPT3EVENTREPORT opcode
1249 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07001250 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301251 */
1252static long
1253_ctl_eventreport(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1254{
1255 struct mpt3_ioctl_eventreport karg;
1256 u32 number_bytes, max_events, max;
1257 struct mpt3_ioctl_eventreport __user *uarg = arg;
1258
1259 if (copy_from_user(&karg, arg, sizeof(karg))) {
1260 pr_err("failure at %s:%d/%s()!\n",
1261 __FILE__, __LINE__, __func__);
1262 return -EFAULT;
1263 }
1264
Joe Perches919d8a32018-09-17 08:01:09 -07001265 dctlprintk(ioc, ioc_info(ioc, "%s: enter\n",
1266 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301267
1268 number_bytes = karg.hdr.max_data_size -
1269 sizeof(struct mpt3_ioctl_header);
1270 max_events = number_bytes/sizeof(struct MPT3_IOCTL_EVENTS);
1271 max = min_t(u32, MPT3SAS_CTL_EVENT_LOG_SIZE, max_events);
1272
1273 /* If fewer than 1 event is requested, there must have
1274 * been some type of error.
1275 */
1276 if (!max || !ioc->event_log)
1277 return -ENODATA;
1278
1279 number_bytes = max * sizeof(struct MPT3_IOCTL_EVENTS);
1280 if (copy_to_user(uarg->event_data, ioc->event_log, number_bytes)) {
1281 pr_err("failure at %s:%d/%s()!\n",
1282 __FILE__, __LINE__, __func__);
1283 return -EFAULT;
1284 }
1285
1286 /* reset flag so SIGIO can restart */
1287 ioc->aen_event_read_flag = 0;
1288 return 0;
1289}
1290
1291/**
1292 * _ctl_do_reset - main handler for MPT3HARDRESET opcode
1293 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07001294 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301295 */
1296static long
1297_ctl_do_reset(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1298{
1299 struct mpt3_ioctl_diag_reset karg;
1300 int retval;
1301
1302 if (copy_from_user(&karg, arg, sizeof(karg))) {
1303 pr_err("failure at %s:%d/%s()!\n",
1304 __FILE__, __LINE__, __func__);
1305 return -EFAULT;
1306 }
1307
1308 if (ioc->shost_recovery || ioc->pci_error_recovery ||
1309 ioc->is_driver_loading)
1310 return -EAGAIN;
1311
Joe Perches919d8a32018-09-17 08:01:09 -07001312 dctlprintk(ioc, ioc_info(ioc, "%s: enter\n",
1313 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301314
Calvin Owens98c56ad2016-07-28 21:38:21 -07001315 retval = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Joe Perches919d8a32018-09-17 08:01:09 -07001316 ioc_info(ioc, "host reset: %s\n", ((!retval) ? "SUCCESS" : "FAILED"));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301317 return 0;
1318}
1319
1320/**
1321 * _ctl_btdh_search_sas_device - searching for sas device
1322 * @ioc: per adapter object
1323 * @btdh: btdh ioctl payload
1324 */
1325static int
1326_ctl_btdh_search_sas_device(struct MPT3SAS_ADAPTER *ioc,
1327 struct mpt3_ioctl_btdh_mapping *btdh)
1328{
1329 struct _sas_device *sas_device;
1330 unsigned long flags;
1331 int rc = 0;
1332
1333 if (list_empty(&ioc->sas_device_list))
1334 return rc;
1335
1336 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1337 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
1338 if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
1339 btdh->handle == sas_device->handle) {
1340 btdh->bus = sas_device->channel;
1341 btdh->id = sas_device->id;
1342 rc = 1;
1343 goto out;
1344 } else if (btdh->bus == sas_device->channel && btdh->id ==
1345 sas_device->id && btdh->handle == 0xFFFF) {
1346 btdh->handle = sas_device->handle;
1347 rc = 1;
1348 goto out;
1349 }
1350 }
1351 out:
1352 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1353 return rc;
1354}
1355
1356/**
Suganath Prabu Subramani45aa6a12017-10-31 18:02:36 +05301357 * _ctl_btdh_search_pcie_device - searching for pcie device
1358 * @ioc: per adapter object
1359 * @btdh: btdh ioctl payload
1360 */
1361static int
1362_ctl_btdh_search_pcie_device(struct MPT3SAS_ADAPTER *ioc,
1363 struct mpt3_ioctl_btdh_mapping *btdh)
1364{
1365 struct _pcie_device *pcie_device;
1366 unsigned long flags;
1367 int rc = 0;
1368
1369 if (list_empty(&ioc->pcie_device_list))
1370 return rc;
1371
1372 spin_lock_irqsave(&ioc->pcie_device_lock, flags);
1373 list_for_each_entry(pcie_device, &ioc->pcie_device_list, list) {
1374 if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
1375 btdh->handle == pcie_device->handle) {
1376 btdh->bus = pcie_device->channel;
1377 btdh->id = pcie_device->id;
1378 rc = 1;
1379 goto out;
1380 } else if (btdh->bus == pcie_device->channel && btdh->id ==
1381 pcie_device->id && btdh->handle == 0xFFFF) {
1382 btdh->handle = pcie_device->handle;
1383 rc = 1;
1384 goto out;
1385 }
1386 }
1387 out:
1388 spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
1389 return rc;
1390}
1391
1392/**
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301393 * _ctl_btdh_search_raid_device - searching for raid device
1394 * @ioc: per adapter object
1395 * @btdh: btdh ioctl payload
1396 */
1397static int
1398_ctl_btdh_search_raid_device(struct MPT3SAS_ADAPTER *ioc,
1399 struct mpt3_ioctl_btdh_mapping *btdh)
1400{
1401 struct _raid_device *raid_device;
1402 unsigned long flags;
1403 int rc = 0;
1404
1405 if (list_empty(&ioc->raid_device_list))
1406 return rc;
1407
1408 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1409 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
1410 if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
1411 btdh->handle == raid_device->handle) {
1412 btdh->bus = raid_device->channel;
1413 btdh->id = raid_device->id;
1414 rc = 1;
1415 goto out;
1416 } else if (btdh->bus == raid_device->channel && btdh->id ==
1417 raid_device->id && btdh->handle == 0xFFFF) {
1418 btdh->handle = raid_device->handle;
1419 rc = 1;
1420 goto out;
1421 }
1422 }
1423 out:
1424 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1425 return rc;
1426}
1427
1428/**
1429 * _ctl_btdh_mapping - main handler for MPT3BTDHMAPPING opcode
1430 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07001431 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301432 */
1433static long
1434_ctl_btdh_mapping(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1435{
1436 struct mpt3_ioctl_btdh_mapping karg;
1437 int rc;
1438
1439 if (copy_from_user(&karg, arg, sizeof(karg))) {
1440 pr_err("failure at %s:%d/%s()!\n",
1441 __FILE__, __LINE__, __func__);
1442 return -EFAULT;
1443 }
1444
Joe Perches919d8a32018-09-17 08:01:09 -07001445 dctlprintk(ioc, ioc_info(ioc, "%s\n",
1446 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301447
1448 rc = _ctl_btdh_search_sas_device(ioc, &karg);
1449 if (!rc)
Suganath Prabu Subramani45aa6a12017-10-31 18:02:36 +05301450 rc = _ctl_btdh_search_pcie_device(ioc, &karg);
1451 if (!rc)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301452 _ctl_btdh_search_raid_device(ioc, &karg);
1453
1454 if (copy_to_user(arg, &karg, sizeof(karg))) {
1455 pr_err("failure at %s:%d/%s()!\n",
1456 __FILE__, __LINE__, __func__);
1457 return -EFAULT;
1458 }
1459 return 0;
1460}
1461
1462/**
1463 * _ctl_diag_capability - return diag buffer capability
1464 * @ioc: per adapter object
1465 * @buffer_type: specifies either TRACE, SNAPSHOT, or EXTENDED
1466 *
1467 * returns 1 when diag buffer support is enabled in firmware
1468 */
1469static u8
1470_ctl_diag_capability(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type)
1471{
1472 u8 rc = 0;
1473
1474 switch (buffer_type) {
1475 case MPI2_DIAG_BUF_TYPE_TRACE:
1476 if (ioc->facts.IOCCapabilities &
1477 MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER)
1478 rc = 1;
1479 break;
1480 case MPI2_DIAG_BUF_TYPE_SNAPSHOT:
1481 if (ioc->facts.IOCCapabilities &
1482 MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)
1483 rc = 1;
1484 break;
1485 case MPI2_DIAG_BUF_TYPE_EXTENDED:
1486 if (ioc->facts.IOCCapabilities &
1487 MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER)
1488 rc = 1;
1489 }
1490
1491 return rc;
1492}
1493
1494
1495/**
1496 * _ctl_diag_register_2 - wrapper for registering diag buffer support
1497 * @ioc: per adapter object
1498 * @diag_register: the diag_register struct passed in from user space
1499 *
1500 */
1501static long
1502_ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
1503 struct mpt3_diag_register *diag_register)
1504{
1505 int rc, i;
1506 void *request_data = NULL;
1507 dma_addr_t request_data_dma;
1508 u32 request_data_sz = 0;
1509 Mpi2DiagBufferPostRequest_t *mpi_request;
1510 Mpi2DiagBufferPostReply_t *mpi_reply;
1511 u8 buffer_type;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301512 u16 smid;
1513 u16 ioc_status;
1514 u32 ioc_state;
1515 u8 issue_reset = 0;
1516
Joe Perches919d8a32018-09-17 08:01:09 -07001517 dctlprintk(ioc, ioc_info(ioc, "%s\n",
1518 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301519
1520 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1521 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
Joe Perches919d8a32018-09-17 08:01:09 -07001522 ioc_err(ioc, "%s: failed due to ioc not operational\n",
1523 __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301524 rc = -EAGAIN;
1525 goto out;
1526 }
1527
1528 if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
Joe Perches919d8a32018-09-17 08:01:09 -07001529 ioc_err(ioc, "%s: ctl_cmd in use\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301530 rc = -EAGAIN;
1531 goto out;
1532 }
1533
1534 buffer_type = diag_register->buffer_type;
1535 if (!_ctl_diag_capability(ioc, buffer_type)) {
Joe Perches919d8a32018-09-17 08:01:09 -07001536 ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
1537 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301538 return -EPERM;
1539 }
1540
1541 if (ioc->diag_buffer_status[buffer_type] &
1542 MPT3_DIAG_BUFFER_IS_REGISTERED) {
Joe Perches919d8a32018-09-17 08:01:09 -07001543 ioc_err(ioc, "%s: already has a registered buffer for buffer_type(0x%02x)\n",
1544 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301545 return -EINVAL;
1546 }
1547
1548 if (diag_register->requested_buffer_size % 4) {
Joe Perches919d8a32018-09-17 08:01:09 -07001549 ioc_err(ioc, "%s: the requested_buffer_size is not 4 byte aligned\n",
1550 __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301551 return -EINVAL;
1552 }
1553
1554 smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx);
1555 if (!smid) {
Joe Perches919d8a32018-09-17 08:01:09 -07001556 ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301557 rc = -EAGAIN;
1558 goto out;
1559 }
1560
1561 rc = 0;
1562 ioc->ctl_cmds.status = MPT3_CMD_PENDING;
1563 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
1564 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1565 ioc->ctl_cmds.smid = smid;
1566
1567 request_data = ioc->diag_buffer[buffer_type];
1568 request_data_sz = diag_register->requested_buffer_size;
1569 ioc->unique_id[buffer_type] = diag_register->unique_id;
1570 ioc->diag_buffer_status[buffer_type] = 0;
1571 memcpy(ioc->product_specific[buffer_type],
1572 diag_register->product_specific, MPT3_PRODUCT_SPECIFIC_DWORDS);
1573 ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags;
1574
1575 if (request_data) {
1576 request_data_dma = ioc->diag_buffer_dma[buffer_type];
1577 if (request_data_sz != ioc->diag_buffer_sz[buffer_type]) {
Christoph Hellwig1c2048b2018-10-11 09:35:25 +02001578 dma_free_coherent(&ioc->pdev->dev,
1579 ioc->diag_buffer_sz[buffer_type],
1580 request_data, request_data_dma);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301581 request_data = NULL;
1582 }
1583 }
1584
1585 if (request_data == NULL) {
1586 ioc->diag_buffer_sz[buffer_type] = 0;
1587 ioc->diag_buffer_dma[buffer_type] = 0;
Christoph Hellwig1c2048b2018-10-11 09:35:25 +02001588 request_data = dma_alloc_coherent(&ioc->pdev->dev,
1589 request_data_sz, &request_data_dma, GFP_KERNEL);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301590 if (request_data == NULL) {
Joe Perches919d8a32018-09-17 08:01:09 -07001591 ioc_err(ioc, "%s: failed allocating memory for diag buffers, requested size(%d)\n",
1592 __func__, request_data_sz);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301593 mpt3sas_base_free_smid(ioc, smid);
1594 return -ENOMEM;
1595 }
1596 ioc->diag_buffer[buffer_type] = request_data;
1597 ioc->diag_buffer_sz[buffer_type] = request_data_sz;
1598 ioc->diag_buffer_dma[buffer_type] = request_data_dma;
1599 }
1600
1601 mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
1602 mpi_request->BufferType = diag_register->buffer_type;
1603 mpi_request->Flags = cpu_to_le32(diag_register->diagnostic_flags);
1604 mpi_request->BufferAddress = cpu_to_le64(request_data_dma);
1605 mpi_request->BufferLength = cpu_to_le32(request_data_sz);
1606 mpi_request->VF_ID = 0; /* TODO */
1607 mpi_request->VP_ID = 0;
1608
Joe Perches919d8a32018-09-17 08:01:09 -07001609 dctlprintk(ioc,
1610 ioc_info(ioc, "%s: diag_buffer(0x%p), dma(0x%llx), sz(%d)\n",
1611 __func__, request_data,
1612 (unsigned long long)request_data_dma,
1613 le32_to_cpu(mpi_request->BufferLength)));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301614
1615 for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++)
1616 mpi_request->ProductSpecific[i] =
1617 cpu_to_le32(ioc->product_specific[buffer_type][i]);
1618
1619 init_completion(&ioc->ctl_cmds.done);
Suganath Prabu S078a4cc2019-05-31 08:14:34 -04001620 ioc->put_smid_default(ioc, smid);
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07001621 wait_for_completion_timeout(&ioc->ctl_cmds.done,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301622 MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
1623
1624 if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
Chaitra P Bd37306c2018-05-31 06:34:50 -04001625 issue_reset =
1626 mpt3sas_base_check_cmd_timeout(ioc,
1627 ioc->ctl_cmds.status, mpi_request,
1628 sizeof(Mpi2DiagBufferPostRequest_t)/4);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301629 goto issue_host_reset;
1630 }
1631
1632 /* process the completed Reply Message Frame */
1633 if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07001634 ioc_err(ioc, "%s: no reply message\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301635 rc = -EFAULT;
1636 goto out;
1637 }
1638
1639 mpi_reply = ioc->ctl_cmds.reply;
1640 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1641
1642 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
1643 ioc->diag_buffer_status[buffer_type] |=
1644 MPT3_DIAG_BUFFER_IS_REGISTERED;
Joe Perches919d8a32018-09-17 08:01:09 -07001645 dctlprintk(ioc, ioc_info(ioc, "%s: success\n", __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301646 } else {
Joe Perches919d8a32018-09-17 08:01:09 -07001647 ioc_info(ioc, "%s: ioc_status(0x%04x) log_info(0x%08x)\n",
1648 __func__,
1649 ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301650 rc = -EFAULT;
1651 }
1652
1653 issue_host_reset:
1654 if (issue_reset)
Calvin Owens98c56ad2016-07-28 21:38:21 -07001655 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301656
1657 out:
1658
1659 if (rc && request_data)
Christoph Hellwig1c2048b2018-10-11 09:35:25 +02001660 dma_free_coherent(&ioc->pdev->dev, request_data_sz,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301661 request_data, request_data_dma);
1662
1663 ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
1664 return rc;
1665}
1666
1667/**
1668 * mpt3sas_enable_diag_buffer - enabling diag_buffers support driver load time
1669 * @ioc: per adapter object
1670 * @bits_to_register: bitwise field where trace is bit 0, and snapshot is bit 1
1671 *
1672 * This is called when command line option diag_buffer_enable is enabled
1673 * at driver load time.
1674 */
1675void
1676mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc, u8 bits_to_register)
1677{
1678 struct mpt3_diag_register diag_register;
Sreekanth Reddyd04a6ed2019-09-13 09:04:38 -04001679 u32 ret_val;
1680 u32 trace_buff_size = ioc->manu_pg11.HostTraceBufferMaxSizeKB<<10;
1681 u32 min_trace_buff_size = 0;
1682 u32 decr_trace_buff_size = 0;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301683
1684 memset(&diag_register, 0, sizeof(struct mpt3_diag_register));
1685
1686 if (bits_to_register & 1) {
Joe Perches919d8a32018-09-17 08:01:09 -07001687 ioc_info(ioc, "registering trace buffer support\n");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301688 ioc->diag_trigger_master.MasterData =
1689 (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET);
1690 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301691 diag_register.unique_id = 0x7075900;
Sreekanth Reddyd04a6ed2019-09-13 09:04:38 -04001692
1693 if (trace_buff_size != 0) {
1694 diag_register.requested_buffer_size = trace_buff_size;
1695 min_trace_buff_size =
1696 ioc->manu_pg11.HostTraceBufferMinSizeKB<<10;
1697 decr_trace_buff_size =
1698 ioc->manu_pg11.HostTraceBufferDecrementSizeKB<<10;
1699
1700 if (min_trace_buff_size > trace_buff_size) {
1701 /* The buff size is not set correctly */
1702 ioc_err(ioc,
1703 "Min Trace Buff size (%d KB) greater than Max Trace Buff size (%d KB)\n",
1704 min_trace_buff_size>>10,
1705 trace_buff_size>>10);
1706 ioc_err(ioc,
1707 "Using zero Min Trace Buff Size\n");
1708 min_trace_buff_size = 0;
1709 }
1710
1711 if (decr_trace_buff_size == 0) {
1712 /*
1713 * retry the min size if decrement
1714 * is not available.
1715 */
1716 decr_trace_buff_size =
1717 trace_buff_size - min_trace_buff_size;
1718 }
1719 } else {
1720 /* register for 2MB buffers */
1721 diag_register.requested_buffer_size = 2 * (1024 * 1024);
1722 }
1723
1724 do {
1725 ret_val = _ctl_diag_register_2(ioc, &diag_register);
1726
1727 if (ret_val == -ENOMEM && min_trace_buff_size &&
1728 (trace_buff_size - decr_trace_buff_size) >=
1729 min_trace_buff_size) {
1730 /* adjust the buffer size */
1731 trace_buff_size -= decr_trace_buff_size;
1732 diag_register.requested_buffer_size =
1733 trace_buff_size;
1734 } else
1735 break;
1736 } while (true);
1737
1738 if (ret_val == -ENOMEM)
1739 ioc_err(ioc,
1740 "Cannot allocate trace buffer memory. Last memory tried = %d KB\n",
1741 diag_register.requested_buffer_size>>10);
1742 else if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE]
1743 & MPT3_DIAG_BUFFER_IS_REGISTERED)
1744 ioc_err(ioc, "Trace buffer memory %d KB allocated\n",
1745 diag_register.requested_buffer_size>>10);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301746 }
1747
1748 if (bits_to_register & 2) {
Joe Perches919d8a32018-09-17 08:01:09 -07001749 ioc_info(ioc, "registering snapshot buffer support\n");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301750 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_SNAPSHOT;
1751 /* register for 2MB buffers */
1752 diag_register.requested_buffer_size = 2 * (1024 * 1024);
1753 diag_register.unique_id = 0x7075901;
1754 _ctl_diag_register_2(ioc, &diag_register);
1755 }
1756
1757 if (bits_to_register & 4) {
Joe Perches919d8a32018-09-17 08:01:09 -07001758 ioc_info(ioc, "registering extended buffer support\n");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301759 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_EXTENDED;
1760 /* register for 2MB buffers */
1761 diag_register.requested_buffer_size = 2 * (1024 * 1024);
1762 diag_register.unique_id = 0x7075901;
1763 _ctl_diag_register_2(ioc, &diag_register);
1764 }
1765}
1766
1767/**
1768 * _ctl_diag_register - application register with driver
1769 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07001770 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301771 *
1772 * This will allow the driver to setup any required buffers that will be
1773 * needed by firmware to communicate with the driver.
1774 */
1775static long
1776_ctl_diag_register(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1777{
1778 struct mpt3_diag_register karg;
1779 long rc;
1780
1781 if (copy_from_user(&karg, arg, sizeof(karg))) {
1782 pr_err("failure at %s:%d/%s()!\n",
1783 __FILE__, __LINE__, __func__);
1784 return -EFAULT;
1785 }
1786
1787 rc = _ctl_diag_register_2(ioc, &karg);
1788 return rc;
1789}
1790
1791/**
1792 * _ctl_diag_unregister - application unregister with driver
1793 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07001794 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301795 *
1796 * This will allow the driver to cleanup any memory allocated for diag
1797 * messages and to free up any resources.
1798 */
1799static long
1800_ctl_diag_unregister(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1801{
1802 struct mpt3_diag_unregister karg;
1803 void *request_data;
1804 dma_addr_t request_data_dma;
1805 u32 request_data_sz;
1806 u8 buffer_type;
1807
1808 if (copy_from_user(&karg, arg, sizeof(karg))) {
1809 pr_err("failure at %s:%d/%s()!\n",
1810 __FILE__, __LINE__, __func__);
1811 return -EFAULT;
1812 }
1813
Joe Perches919d8a32018-09-17 08:01:09 -07001814 dctlprintk(ioc, ioc_info(ioc, "%s\n",
1815 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301816
1817 buffer_type = karg.unique_id & 0x000000ff;
1818 if (!_ctl_diag_capability(ioc, buffer_type)) {
Joe Perches919d8a32018-09-17 08:01:09 -07001819 ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
1820 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301821 return -EPERM;
1822 }
1823
1824 if ((ioc->diag_buffer_status[buffer_type] &
1825 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07001826 ioc_err(ioc, "%s: buffer_type(0x%02x) is not registered\n",
1827 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301828 return -EINVAL;
1829 }
1830 if ((ioc->diag_buffer_status[buffer_type] &
1831 MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07001832 ioc_err(ioc, "%s: buffer_type(0x%02x) has not been released\n",
1833 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301834 return -EINVAL;
1835 }
1836
1837 if (karg.unique_id != ioc->unique_id[buffer_type]) {
Joe Perches919d8a32018-09-17 08:01:09 -07001838 ioc_err(ioc, "%s: unique_id(0x%08x) is not registered\n",
1839 __func__, karg.unique_id);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301840 return -EINVAL;
1841 }
1842
1843 request_data = ioc->diag_buffer[buffer_type];
1844 if (!request_data) {
Joe Perches919d8a32018-09-17 08:01:09 -07001845 ioc_err(ioc, "%s: doesn't have memory allocated for buffer_type(0x%02x)\n",
1846 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301847 return -ENOMEM;
1848 }
1849
1850 request_data_sz = ioc->diag_buffer_sz[buffer_type];
1851 request_data_dma = ioc->diag_buffer_dma[buffer_type];
Christoph Hellwig1c2048b2018-10-11 09:35:25 +02001852 dma_free_coherent(&ioc->pdev->dev, request_data_sz,
1853 request_data, request_data_dma);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301854 ioc->diag_buffer[buffer_type] = NULL;
1855 ioc->diag_buffer_status[buffer_type] = 0;
1856 return 0;
1857}
1858
1859/**
1860 * _ctl_diag_query - query relevant info associated with diag buffers
1861 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07001862 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301863 *
1864 * The application will send only buffer_type and unique_id. Driver will
1865 * inspect unique_id first, if valid, fill in all the info. If unique_id is
1866 * 0x00, the driver will return info specified by Buffer Type.
1867 */
1868static long
1869_ctl_diag_query(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1870{
1871 struct mpt3_diag_query karg;
1872 void *request_data;
1873 int i;
1874 u8 buffer_type;
1875
1876 if (copy_from_user(&karg, arg, sizeof(karg))) {
1877 pr_err("failure at %s:%d/%s()!\n",
1878 __FILE__, __LINE__, __func__);
1879 return -EFAULT;
1880 }
1881
Joe Perches919d8a32018-09-17 08:01:09 -07001882 dctlprintk(ioc, ioc_info(ioc, "%s\n",
1883 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301884
1885 karg.application_flags = 0;
1886 buffer_type = karg.buffer_type;
1887
1888 if (!_ctl_diag_capability(ioc, buffer_type)) {
Joe Perches919d8a32018-09-17 08:01:09 -07001889 ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
1890 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301891 return -EPERM;
1892 }
1893
1894 if ((ioc->diag_buffer_status[buffer_type] &
1895 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07001896 ioc_err(ioc, "%s: buffer_type(0x%02x) is not registered\n",
1897 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301898 return -EINVAL;
1899 }
1900
1901 if (karg.unique_id & 0xffffff00) {
1902 if (karg.unique_id != ioc->unique_id[buffer_type]) {
Joe Perches919d8a32018-09-17 08:01:09 -07001903 ioc_err(ioc, "%s: unique_id(0x%08x) is not registered\n",
1904 __func__, karg.unique_id);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301905 return -EINVAL;
1906 }
1907 }
1908
1909 request_data = ioc->diag_buffer[buffer_type];
1910 if (!request_data) {
Joe Perches919d8a32018-09-17 08:01:09 -07001911 ioc_err(ioc, "%s: doesn't have buffer for buffer_type(0x%02x)\n",
1912 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301913 return -ENOMEM;
1914 }
1915
1916 if (ioc->diag_buffer_status[buffer_type] & MPT3_DIAG_BUFFER_IS_RELEASED)
1917 karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED |
1918 MPT3_APP_FLAGS_BUFFER_VALID);
1919 else
1920 karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED |
1921 MPT3_APP_FLAGS_BUFFER_VALID |
1922 MPT3_APP_FLAGS_FW_BUFFER_ACCESS);
1923
1924 for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++)
1925 karg.product_specific[i] =
1926 ioc->product_specific[buffer_type][i];
1927
1928 karg.total_buffer_size = ioc->diag_buffer_sz[buffer_type];
1929 karg.driver_added_buffer_size = 0;
1930 karg.unique_id = ioc->unique_id[buffer_type];
1931 karg.diagnostic_flags = ioc->diagnostic_flags[buffer_type];
1932
1933 if (copy_to_user(arg, &karg, sizeof(struct mpt3_diag_query))) {
Joe Perches919d8a32018-09-17 08:01:09 -07001934 ioc_err(ioc, "%s: unable to write mpt3_diag_query data @ %p\n",
1935 __func__, arg);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301936 return -EFAULT;
1937 }
1938 return 0;
1939}
1940
1941/**
1942 * mpt3sas_send_diag_release - Diag Release Message
1943 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07001944 * @buffer_type: specifies either TRACE, SNAPSHOT, or EXTENDED
1945 * @issue_reset: specifies whether host reset is required.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301946 *
1947 */
1948int
1949mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
1950 u8 *issue_reset)
1951{
1952 Mpi2DiagReleaseRequest_t *mpi_request;
1953 Mpi2DiagReleaseReply_t *mpi_reply;
1954 u16 smid;
1955 u16 ioc_status;
1956 u32 ioc_state;
1957 int rc;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301958
Joe Perches919d8a32018-09-17 08:01:09 -07001959 dctlprintk(ioc, ioc_info(ioc, "%s\n",
1960 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301961
1962 rc = 0;
1963 *issue_reset = 0;
1964
1965 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1966 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1967 if (ioc->diag_buffer_status[buffer_type] &
1968 MPT3_DIAG_BUFFER_IS_REGISTERED)
1969 ioc->diag_buffer_status[buffer_type] |=
1970 MPT3_DIAG_BUFFER_IS_RELEASED;
Joe Perches919d8a32018-09-17 08:01:09 -07001971 dctlprintk(ioc,
1972 ioc_info(ioc, "%s: skipping due to FAULT state\n",
1973 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301974 rc = -EAGAIN;
1975 goto out;
1976 }
1977
1978 if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
Joe Perches919d8a32018-09-17 08:01:09 -07001979 ioc_err(ioc, "%s: ctl_cmd in use\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301980 rc = -EAGAIN;
1981 goto out;
1982 }
1983
1984 smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx);
1985 if (!smid) {
Joe Perches919d8a32018-09-17 08:01:09 -07001986 ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301987 rc = -EAGAIN;
1988 goto out;
1989 }
1990
1991 ioc->ctl_cmds.status = MPT3_CMD_PENDING;
1992 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
1993 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1994 ioc->ctl_cmds.smid = smid;
1995
1996 mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE;
1997 mpi_request->BufferType = buffer_type;
1998 mpi_request->VF_ID = 0; /* TODO */
1999 mpi_request->VP_ID = 0;
2000
2001 init_completion(&ioc->ctl_cmds.done);
Suganath Prabu S078a4cc2019-05-31 08:14:34 -04002002 ioc->put_smid_default(ioc, smid);
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002003 wait_for_completion_timeout(&ioc->ctl_cmds.done,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302004 MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
2005
2006 if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
Chaitra P Bd37306c2018-05-31 06:34:50 -04002007 *issue_reset = mpt3sas_base_check_cmd_timeout(ioc,
2008 ioc->ctl_cmds.status, mpi_request,
2009 sizeof(Mpi2DiagReleaseRequest_t)/4);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302010 rc = -EFAULT;
2011 goto out;
2012 }
2013
2014 /* process the completed Reply Message Frame */
2015 if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07002016 ioc_err(ioc, "%s: no reply message\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302017 rc = -EFAULT;
2018 goto out;
2019 }
2020
2021 mpi_reply = ioc->ctl_cmds.reply;
2022 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
2023
2024 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
2025 ioc->diag_buffer_status[buffer_type] |=
2026 MPT3_DIAG_BUFFER_IS_RELEASED;
Joe Perches919d8a32018-09-17 08:01:09 -07002027 dctlprintk(ioc, ioc_info(ioc, "%s: success\n", __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302028 } else {
Joe Perches919d8a32018-09-17 08:01:09 -07002029 ioc_info(ioc, "%s: ioc_status(0x%04x) log_info(0x%08x)\n",
2030 __func__,
2031 ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302032 rc = -EFAULT;
2033 }
2034
2035 out:
2036 ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
2037 return rc;
2038}
2039
2040/**
2041 * _ctl_diag_release - request to send Diag Release Message to firmware
Bart Van Assche4beb4862018-06-15 14:42:01 -07002042 * @ioc: ?
2043 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302044 *
2045 * This allows ownership of the specified buffer to returned to the driver,
2046 * allowing an application to read the buffer without fear that firmware is
Masahiro Yamada9a284e52017-02-27 14:29:48 -08002047 * overwriting information in the buffer.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302048 */
2049static long
2050_ctl_diag_release(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
2051{
2052 struct mpt3_diag_release karg;
2053 void *request_data;
2054 int rc;
2055 u8 buffer_type;
2056 u8 issue_reset = 0;
2057
2058 if (copy_from_user(&karg, arg, sizeof(karg))) {
2059 pr_err("failure at %s:%d/%s()!\n",
2060 __FILE__, __LINE__, __func__);
2061 return -EFAULT;
2062 }
2063
Joe Perches919d8a32018-09-17 08:01:09 -07002064 dctlprintk(ioc, ioc_info(ioc, "%s\n",
2065 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302066
2067 buffer_type = karg.unique_id & 0x000000ff;
2068 if (!_ctl_diag_capability(ioc, buffer_type)) {
Joe Perches919d8a32018-09-17 08:01:09 -07002069 ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
2070 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302071 return -EPERM;
2072 }
2073
2074 if ((ioc->diag_buffer_status[buffer_type] &
2075 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07002076 ioc_err(ioc, "%s: buffer_type(0x%02x) is not registered\n",
2077 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302078 return -EINVAL;
2079 }
2080
2081 if (karg.unique_id != ioc->unique_id[buffer_type]) {
Joe Perches919d8a32018-09-17 08:01:09 -07002082 ioc_err(ioc, "%s: unique_id(0x%08x) is not registered\n",
2083 __func__, karg.unique_id);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302084 return -EINVAL;
2085 }
2086
2087 if (ioc->diag_buffer_status[buffer_type] &
2088 MPT3_DIAG_BUFFER_IS_RELEASED) {
Joe Perches919d8a32018-09-17 08:01:09 -07002089 ioc_err(ioc, "%s: buffer_type(0x%02x) is already released\n",
2090 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302091 return 0;
2092 }
2093
2094 request_data = ioc->diag_buffer[buffer_type];
2095
2096 if (!request_data) {
Joe Perches919d8a32018-09-17 08:01:09 -07002097 ioc_err(ioc, "%s: doesn't have memory allocated for buffer_type(0x%02x)\n",
2098 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302099 return -ENOMEM;
2100 }
2101
2102 /* buffers were released by due to host reset */
2103 if ((ioc->diag_buffer_status[buffer_type] &
2104 MPT3_DIAG_BUFFER_IS_DIAG_RESET)) {
2105 ioc->diag_buffer_status[buffer_type] |=
2106 MPT3_DIAG_BUFFER_IS_RELEASED;
2107 ioc->diag_buffer_status[buffer_type] &=
2108 ~MPT3_DIAG_BUFFER_IS_DIAG_RESET;
Joe Perches919d8a32018-09-17 08:01:09 -07002109 ioc_err(ioc, "%s: buffer_type(0x%02x) was released due to host reset\n",
2110 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302111 return 0;
2112 }
2113
2114 rc = mpt3sas_send_diag_release(ioc, buffer_type, &issue_reset);
2115
2116 if (issue_reset)
Calvin Owens98c56ad2016-07-28 21:38:21 -07002117 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302118
2119 return rc;
2120}
2121
2122/**
2123 * _ctl_diag_read_buffer - request for copy of the diag buffer
2124 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07002125 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302126 */
2127static long
2128_ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
2129{
2130 struct mpt3_diag_read_buffer karg;
2131 struct mpt3_diag_read_buffer __user *uarg = arg;
2132 void *request_data, *diag_data;
2133 Mpi2DiagBufferPostRequest_t *mpi_request;
2134 Mpi2DiagBufferPostReply_t *mpi_reply;
2135 int rc, i;
2136 u8 buffer_type;
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002137 unsigned long request_size, copy_size;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302138 u16 smid;
2139 u16 ioc_status;
2140 u8 issue_reset = 0;
2141
2142 if (copy_from_user(&karg, arg, sizeof(karg))) {
2143 pr_err("failure at %s:%d/%s()!\n",
2144 __FILE__, __LINE__, __func__);
2145 return -EFAULT;
2146 }
2147
Joe Perches919d8a32018-09-17 08:01:09 -07002148 dctlprintk(ioc, ioc_info(ioc, "%s\n",
2149 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302150
2151 buffer_type = karg.unique_id & 0x000000ff;
2152 if (!_ctl_diag_capability(ioc, buffer_type)) {
Joe Perches919d8a32018-09-17 08:01:09 -07002153 ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
2154 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302155 return -EPERM;
2156 }
2157
2158 if (karg.unique_id != ioc->unique_id[buffer_type]) {
Joe Perches919d8a32018-09-17 08:01:09 -07002159 ioc_err(ioc, "%s: unique_id(0x%08x) is not registered\n",
2160 __func__, karg.unique_id);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302161 return -EINVAL;
2162 }
2163
2164 request_data = ioc->diag_buffer[buffer_type];
2165 if (!request_data) {
Joe Perches919d8a32018-09-17 08:01:09 -07002166 ioc_err(ioc, "%s: doesn't have buffer for buffer_type(0x%02x)\n",
2167 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302168 return -ENOMEM;
2169 }
2170
2171 request_size = ioc->diag_buffer_sz[buffer_type];
2172
2173 if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) {
Joe Perches919d8a32018-09-17 08:01:09 -07002174 ioc_err(ioc, "%s: either the starting_offset or bytes_to_read are not 4 byte aligned\n",
2175 __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302176 return -EINVAL;
2177 }
2178
2179 if (karg.starting_offset > request_size)
2180 return -EINVAL;
2181
2182 diag_data = (void *)(request_data + karg.starting_offset);
Joe Perches919d8a32018-09-17 08:01:09 -07002183 dctlprintk(ioc,
2184 ioc_info(ioc, "%s: diag_buffer(%p), offset(%d), sz(%d)\n",
2185 __func__, diag_data, karg.starting_offset,
2186 karg.bytes_to_read));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302187
2188 /* Truncate data on requests that are too large */
2189 if ((diag_data + karg.bytes_to_read < diag_data) ||
2190 (diag_data + karg.bytes_to_read > request_data + request_size))
2191 copy_size = request_size - karg.starting_offset;
2192 else
2193 copy_size = karg.bytes_to_read;
2194
2195 if (copy_to_user((void __user *)uarg->diagnostic_data,
2196 diag_data, copy_size)) {
Joe Perches919d8a32018-09-17 08:01:09 -07002197 ioc_err(ioc, "%s: Unable to write mpt_diag_read_buffer_t data @ %p\n",
2198 __func__, diag_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302199 return -EFAULT;
2200 }
2201
2202 if ((karg.flags & MPT3_FLAGS_REREGISTER) == 0)
2203 return 0;
2204
Joe Perches919d8a32018-09-17 08:01:09 -07002205 dctlprintk(ioc,
2206 ioc_info(ioc, "%s: Reregister buffer_type(0x%02x)\n",
2207 __func__, buffer_type));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302208 if ((ioc->diag_buffer_status[buffer_type] &
2209 MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07002210 dctlprintk(ioc,
2211 ioc_info(ioc, "%s: buffer_type(0x%02x) is still registered\n",
2212 __func__, buffer_type));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302213 return 0;
2214 }
2215 /* Get a free request frame and save the message context.
2216 */
2217
2218 if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
Joe Perches919d8a32018-09-17 08:01:09 -07002219 ioc_err(ioc, "%s: ctl_cmd in use\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302220 rc = -EAGAIN;
2221 goto out;
2222 }
2223
2224 smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx);
2225 if (!smid) {
Joe Perches919d8a32018-09-17 08:01:09 -07002226 ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302227 rc = -EAGAIN;
2228 goto out;
2229 }
2230
2231 rc = 0;
2232 ioc->ctl_cmds.status = MPT3_CMD_PENDING;
2233 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
2234 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
2235 ioc->ctl_cmds.smid = smid;
2236
2237 mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
2238 mpi_request->BufferType = buffer_type;
2239 mpi_request->BufferLength =
2240 cpu_to_le32(ioc->diag_buffer_sz[buffer_type]);
2241 mpi_request->BufferAddress =
2242 cpu_to_le64(ioc->diag_buffer_dma[buffer_type]);
2243 for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++)
2244 mpi_request->ProductSpecific[i] =
2245 cpu_to_le32(ioc->product_specific[buffer_type][i]);
2246 mpi_request->VF_ID = 0; /* TODO */
2247 mpi_request->VP_ID = 0;
2248
2249 init_completion(&ioc->ctl_cmds.done);
Suganath Prabu S078a4cc2019-05-31 08:14:34 -04002250 ioc->put_smid_default(ioc, smid);
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002251 wait_for_completion_timeout(&ioc->ctl_cmds.done,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302252 MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
2253
2254 if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
Chaitra P Bd37306c2018-05-31 06:34:50 -04002255 issue_reset =
2256 mpt3sas_base_check_cmd_timeout(ioc,
2257 ioc->ctl_cmds.status, mpi_request,
2258 sizeof(Mpi2DiagBufferPostRequest_t)/4);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302259 goto issue_host_reset;
2260 }
2261
2262 /* process the completed Reply Message Frame */
2263 if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07002264 ioc_err(ioc, "%s: no reply message\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302265 rc = -EFAULT;
2266 goto out;
2267 }
2268
2269 mpi_reply = ioc->ctl_cmds.reply;
2270 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
2271
2272 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
2273 ioc->diag_buffer_status[buffer_type] |=
2274 MPT3_DIAG_BUFFER_IS_REGISTERED;
Joe Perches919d8a32018-09-17 08:01:09 -07002275 dctlprintk(ioc, ioc_info(ioc, "%s: success\n", __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302276 } else {
Joe Perches919d8a32018-09-17 08:01:09 -07002277 ioc_info(ioc, "%s: ioc_status(0x%04x) log_info(0x%08x)\n",
2278 __func__, ioc_status,
2279 le32_to_cpu(mpi_reply->IOCLogInfo));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302280 rc = -EFAULT;
2281 }
2282
2283 issue_host_reset:
2284 if (issue_reset)
Calvin Owens98c56ad2016-07-28 21:38:21 -07002285 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302286
2287 out:
2288
2289 ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
2290 return rc;
2291}
2292
2293
2294
2295#ifdef CONFIG_COMPAT
2296/**
2297 * _ctl_compat_mpt_command - convert 32bit pointers to 64bit.
2298 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07002299 * @cmd: ioctl opcode
2300 * @arg: (struct mpt3_ioctl_command32)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302301 *
2302 * MPT3COMMAND32 - Handle 32bit applications running on 64bit os.
2303 */
2304static long
2305_ctl_compat_mpt_command(struct MPT3SAS_ADAPTER *ioc, unsigned cmd,
2306 void __user *arg)
2307{
2308 struct mpt3_ioctl_command32 karg32;
2309 struct mpt3_ioctl_command32 __user *uarg;
2310 struct mpt3_ioctl_command karg;
2311
2312 if (_IOC_SIZE(cmd) != sizeof(struct mpt3_ioctl_command32))
2313 return -EINVAL;
2314
2315 uarg = (struct mpt3_ioctl_command32 __user *) arg;
2316
2317 if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) {
2318 pr_err("failure at %s:%d/%s()!\n",
2319 __FILE__, __LINE__, __func__);
2320 return -EFAULT;
2321 }
2322
2323 memset(&karg, 0, sizeof(struct mpt3_ioctl_command));
2324 karg.hdr.ioc_number = karg32.hdr.ioc_number;
2325 karg.hdr.port_number = karg32.hdr.port_number;
2326 karg.hdr.max_data_size = karg32.hdr.max_data_size;
2327 karg.timeout = karg32.timeout;
2328 karg.max_reply_bytes = karg32.max_reply_bytes;
2329 karg.data_in_size = karg32.data_in_size;
2330 karg.data_out_size = karg32.data_out_size;
2331 karg.max_sense_bytes = karg32.max_sense_bytes;
2332 karg.data_sge_offset = karg32.data_sge_offset;
2333 karg.reply_frame_buf_ptr = compat_ptr(karg32.reply_frame_buf_ptr);
2334 karg.data_in_buf_ptr = compat_ptr(karg32.data_in_buf_ptr);
2335 karg.data_out_buf_ptr = compat_ptr(karg32.data_out_buf_ptr);
2336 karg.sense_data_ptr = compat_ptr(karg32.sense_data_ptr);
2337 return _ctl_do_mpt_command(ioc, karg, &uarg->mf);
2338}
2339#endif
2340
2341/**
2342 * _ctl_ioctl_main - main ioctl entry point
Bart Van Assche4beb4862018-06-15 14:42:01 -07002343 * @file: (struct file)
2344 * @cmd: ioctl opcode
2345 * @arg: user space data buffer
2346 * @compat: handles 32 bit applications in 64bit os
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302347 * @mpi_version: will be MPI2_VERSION for mpt2ctl ioctl device &
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05302348 * MPI25_VERSION | MPI26_VERSION for mpt3ctl ioctl device.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302349 */
2350static long
2351_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302352 u8 compat, u16 mpi_version)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302353{
2354 struct MPT3SAS_ADAPTER *ioc;
2355 struct mpt3_ioctl_header ioctl_header;
2356 enum block_state state;
2357 long ret = -EINVAL;
2358
2359 /* get IOCTL header */
2360 if (copy_from_user(&ioctl_header, (char __user *)arg,
2361 sizeof(struct mpt3_ioctl_header))) {
2362 pr_err("failure at %s:%d/%s()!\n",
2363 __FILE__, __LINE__, __func__);
2364 return -EFAULT;
2365 }
2366
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302367 if (_ctl_verify_adapter(ioctl_header.ioc_number,
2368 &ioc, mpi_version) == -1 || !ioc)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302369 return -ENODEV;
2370
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05302371 /* pci_access_mutex lock acquired by ioctl path */
2372 mutex_lock(&ioc->pci_access_mutex);
2373
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302374 if (ioc->shost_recovery || ioc->pci_error_recovery ||
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05302375 ioc->is_driver_loading || ioc->remove_host) {
2376 ret = -EAGAIN;
2377 goto out_unlock_pciaccess;
2378 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302379
2380 state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
2381 if (state == NON_BLOCKING) {
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05302382 if (!mutex_trylock(&ioc->ctl_cmds.mutex)) {
2383 ret = -EAGAIN;
2384 goto out_unlock_pciaccess;
2385 }
2386 } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) {
2387 ret = -ERESTARTSYS;
2388 goto out_unlock_pciaccess;
2389 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302390
2391
2392 switch (cmd) {
2393 case MPT3IOCINFO:
2394 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_iocinfo))
2395 ret = _ctl_getiocinfo(ioc, arg);
2396 break;
2397#ifdef CONFIG_COMPAT
2398 case MPT3COMMAND32:
2399#endif
2400 case MPT3COMMAND:
2401 {
2402 struct mpt3_ioctl_command __user *uarg;
2403 struct mpt3_ioctl_command karg;
2404
2405#ifdef CONFIG_COMPAT
2406 if (compat) {
2407 ret = _ctl_compat_mpt_command(ioc, cmd, arg);
2408 break;
2409 }
2410#endif
2411 if (copy_from_user(&karg, arg, sizeof(karg))) {
2412 pr_err("failure at %s:%d/%s()!\n",
2413 __FILE__, __LINE__, __func__);
2414 ret = -EFAULT;
2415 break;
2416 }
2417
Gen Zhangf9e3ebe2019-05-30 09:10:30 +08002418 if (karg.hdr.ioc_number != ioctl_header.ioc_number) {
2419 ret = -EINVAL;
2420 break;
2421 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302422 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_command)) {
2423 uarg = arg;
2424 ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf);
2425 }
2426 break;
2427 }
2428 case MPT3EVENTQUERY:
2429 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_eventquery))
2430 ret = _ctl_eventquery(ioc, arg);
2431 break;
2432 case MPT3EVENTENABLE:
2433 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_eventenable))
2434 ret = _ctl_eventenable(ioc, arg);
2435 break;
2436 case MPT3EVENTREPORT:
2437 ret = _ctl_eventreport(ioc, arg);
2438 break;
2439 case MPT3HARDRESET:
2440 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_diag_reset))
2441 ret = _ctl_do_reset(ioc, arg);
2442 break;
2443 case MPT3BTDHMAPPING:
2444 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_btdh_mapping))
2445 ret = _ctl_btdh_mapping(ioc, arg);
2446 break;
2447 case MPT3DIAGREGISTER:
2448 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_register))
2449 ret = _ctl_diag_register(ioc, arg);
2450 break;
2451 case MPT3DIAGUNREGISTER:
2452 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_unregister))
2453 ret = _ctl_diag_unregister(ioc, arg);
2454 break;
2455 case MPT3DIAGQUERY:
2456 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_query))
2457 ret = _ctl_diag_query(ioc, arg);
2458 break;
2459 case MPT3DIAGRELEASE:
2460 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_release))
2461 ret = _ctl_diag_release(ioc, arg);
2462 break;
2463 case MPT3DIAGREADBUFFER:
2464 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_read_buffer))
2465 ret = _ctl_diag_read_buffer(ioc, arg);
2466 break;
2467 default:
Joe Perches919d8a32018-09-17 08:01:09 -07002468 dctlprintk(ioc,
2469 ioc_info(ioc, "unsupported ioctl opcode(0x%08x)\n",
2470 cmd));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302471 break;
2472 }
2473
2474 mutex_unlock(&ioc->ctl_cmds.mutex);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05302475out_unlock_pciaccess:
2476 mutex_unlock(&ioc->pci_access_mutex);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302477 return ret;
2478}
2479
2480/**
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302481 * _ctl_ioctl - mpt3ctl main ioctl entry point (unlocked)
Bart Van Assche4beb4862018-06-15 14:42:01 -07002482 * @file: (struct file)
2483 * @cmd: ioctl opcode
2484 * @arg: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302485 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002486static long
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302487_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302488{
2489 long ret;
2490
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05302491 /* pass MPI25_VERSION | MPI26_VERSION value,
2492 * to indicate that this ioctl cmd
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302493 * came from mpt3ctl ioctl device.
2494 */
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05302495 ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0,
2496 MPI25_VERSION | MPI26_VERSION);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302497 return ret;
2498}
2499
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302500/**
2501 * _ctl_mpt2_ioctl - mpt2ctl main ioctl entry point (unlocked)
Bart Van Assche4beb4862018-06-15 14:42:01 -07002502 * @file: (struct file)
2503 * @cmd: ioctl opcode
2504 * @arg: ?
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302505 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002506static long
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302507_ctl_mpt2_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2508{
2509 long ret;
2510
2511 /* pass MPI2_VERSION value, to indicate that this ioctl cmd
2512 * came from mpt2ctl ioctl device.
2513 */
2514 ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0, MPI2_VERSION);
2515 return ret;
2516}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302517#ifdef CONFIG_COMPAT
2518/**
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302519 *_ ctl_ioctl_compat - main ioctl entry point (compat)
Bart Van Assche4beb4862018-06-15 14:42:01 -07002520 * @file: ?
2521 * @cmd: ?
2522 * @arg: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302523 *
2524 * This routine handles 32 bit applications in 64bit os.
2525 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002526static long
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302527_ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302528{
2529 long ret;
2530
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05302531 ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1,
2532 MPI25_VERSION | MPI26_VERSION);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302533 return ret;
2534}
2535
2536/**
2537 *_ ctl_mpt2_ioctl_compat - main ioctl entry point (compat)
Bart Van Assche4beb4862018-06-15 14:42:01 -07002538 * @file: ?
2539 * @cmd: ?
2540 * @arg: ?
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302541 *
2542 * This routine handles 32 bit applications in 64bit os.
2543 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002544static long
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302545_ctl_mpt2_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
2546{
2547 long ret;
2548
2549 ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1, MPI2_VERSION);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302550 return ret;
2551}
2552#endif
2553
2554/* scsi host attributes */
2555/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002556 * version_fw_show - firmware version
Bart Van Assche4beb4862018-06-15 14:42:01 -07002557 * @cdev: pointer to embedded class device
2558 * @attr: ?
2559 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302560 *
2561 * A sysfs 'read-only' shost attribute.
2562 */
2563static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002564version_fw_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302565 char *buf)
2566{
2567 struct Scsi_Host *shost = class_to_shost(cdev);
2568 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2569
2570 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
2571 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
2572 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
2573 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
2574 ioc->facts.FWVersion.Word & 0x000000FF);
2575}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002576static DEVICE_ATTR_RO(version_fw);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302577
2578/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002579 * version_bios_show - bios version
Bart Van Assche4beb4862018-06-15 14:42:01 -07002580 * @cdev: pointer to embedded class device
2581 * @attr: ?
2582 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302583 *
2584 * A sysfs 'read-only' shost attribute.
2585 */
2586static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002587version_bios_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302588 char *buf)
2589{
2590 struct Scsi_Host *shost = class_to_shost(cdev);
2591 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2592
2593 u32 version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
2594
2595 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
2596 (version & 0xFF000000) >> 24,
2597 (version & 0x00FF0000) >> 16,
2598 (version & 0x0000FF00) >> 8,
2599 version & 0x000000FF);
2600}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002601static DEVICE_ATTR_RO(version_bios);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302602
2603/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002604 * version_mpi_show - MPI (message passing interface) version
Bart Van Assche4beb4862018-06-15 14:42:01 -07002605 * @cdev: pointer to embedded class device
2606 * @attr: ?
2607 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302608 *
2609 * A sysfs 'read-only' shost attribute.
2610 */
2611static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002612version_mpi_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302613 char *buf)
2614{
2615 struct Scsi_Host *shost = class_to_shost(cdev);
2616 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2617
2618 return snprintf(buf, PAGE_SIZE, "%03x.%02x\n",
2619 ioc->facts.MsgVersion, ioc->facts.HeaderVersion >> 8);
2620}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002621static DEVICE_ATTR_RO(version_mpi);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302622
2623/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002624 * version_product_show - product name
Bart Van Assche4beb4862018-06-15 14:42:01 -07002625 * @cdev: pointer to embedded class device
2626 * @attr: ?
2627 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302628 *
2629 * A sysfs 'read-only' shost attribute.
2630 */
2631static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002632version_product_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302633 char *buf)
2634{
2635 struct Scsi_Host *shost = class_to_shost(cdev);
2636 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2637
2638 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.ChipName);
2639}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002640static DEVICE_ATTR_RO(version_product);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302641
2642/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002643 * version_nvdata_persistent_show - ndvata persistent version
Bart Van Assche4beb4862018-06-15 14:42:01 -07002644 * @cdev: pointer to embedded class device
2645 * @attr: ?
2646 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302647 *
2648 * A sysfs 'read-only' shost attribute.
2649 */
2650static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002651version_nvdata_persistent_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302652 struct device_attribute *attr, char *buf)
2653{
2654 struct Scsi_Host *shost = class_to_shost(cdev);
2655 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2656
2657 return snprintf(buf, PAGE_SIZE, "%08xh\n",
2658 le32_to_cpu(ioc->iounit_pg0.NvdataVersionPersistent.Word));
2659}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002660static DEVICE_ATTR_RO(version_nvdata_persistent);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302661
2662/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002663 * version_nvdata_default_show - nvdata default version
Bart Van Assche4beb4862018-06-15 14:42:01 -07002664 * @cdev: pointer to embedded class device
2665 * @attr: ?
2666 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302667 *
2668 * A sysfs 'read-only' shost attribute.
2669 */
2670static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002671version_nvdata_default_show(struct device *cdev, struct device_attribute
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302672 *attr, char *buf)
2673{
2674 struct Scsi_Host *shost = class_to_shost(cdev);
2675 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2676
2677 return snprintf(buf, PAGE_SIZE, "%08xh\n",
2678 le32_to_cpu(ioc->iounit_pg0.NvdataVersionDefault.Word));
2679}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002680static DEVICE_ATTR_RO(version_nvdata_default);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302681
2682/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002683 * board_name_show - board name
Bart Van Assche4beb4862018-06-15 14:42:01 -07002684 * @cdev: pointer to embedded class device
2685 * @attr: ?
2686 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302687 *
2688 * A sysfs 'read-only' shost attribute.
2689 */
2690static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002691board_name_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302692 char *buf)
2693{
2694 struct Scsi_Host *shost = class_to_shost(cdev);
2695 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2696
2697 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardName);
2698}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002699static DEVICE_ATTR_RO(board_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302700
2701/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002702 * board_assembly_show - board assembly name
Bart Van Assche4beb4862018-06-15 14:42:01 -07002703 * @cdev: pointer to embedded class device
2704 * @attr: ?
2705 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302706 *
2707 * A sysfs 'read-only' shost attribute.
2708 */
2709static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002710board_assembly_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302711 char *buf)
2712{
2713 struct Scsi_Host *shost = class_to_shost(cdev);
2714 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2715
2716 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardAssembly);
2717}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002718static DEVICE_ATTR_RO(board_assembly);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302719
2720/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002721 * board_tracer_show - board tracer number
Bart Van Assche4beb4862018-06-15 14:42:01 -07002722 * @cdev: pointer to embedded class device
2723 * @attr: ?
2724 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302725 *
2726 * A sysfs 'read-only' shost attribute.
2727 */
2728static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002729board_tracer_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302730 char *buf)
2731{
2732 struct Scsi_Host *shost = class_to_shost(cdev);
2733 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2734
2735 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardTracerNumber);
2736}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002737static DEVICE_ATTR_RO(board_tracer);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302738
2739/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002740 * io_delay_show - io missing delay
Bart Van Assche4beb4862018-06-15 14:42:01 -07002741 * @cdev: pointer to embedded class device
2742 * @attr: ?
2743 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302744 *
2745 * This is for firmware implemention for deboucing device
2746 * removal events.
2747 *
2748 * A sysfs 'read-only' shost attribute.
2749 */
2750static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002751io_delay_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302752 char *buf)
2753{
2754 struct Scsi_Host *shost = class_to_shost(cdev);
2755 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2756
2757 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
2758}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002759static DEVICE_ATTR_RO(io_delay);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302760
2761/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002762 * device_delay_show - device missing delay
Bart Van Assche4beb4862018-06-15 14:42:01 -07002763 * @cdev: pointer to embedded class device
2764 * @attr: ?
2765 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302766 *
2767 * This is for firmware implemention for deboucing device
2768 * removal events.
2769 *
2770 * A sysfs 'read-only' shost attribute.
2771 */
2772static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002773device_delay_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302774 char *buf)
2775{
2776 struct Scsi_Host *shost = class_to_shost(cdev);
2777 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2778
2779 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
2780}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002781static DEVICE_ATTR_RO(device_delay);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302782
2783/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002784 * fw_queue_depth_show - global credits
Bart Van Assche4beb4862018-06-15 14:42:01 -07002785 * @cdev: pointer to embedded class device
2786 * @attr: ?
2787 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302788 *
2789 * This is firmware queue depth limit
2790 *
2791 * A sysfs 'read-only' shost attribute.
2792 */
2793static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002794fw_queue_depth_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302795 char *buf)
2796{
2797 struct Scsi_Host *shost = class_to_shost(cdev);
2798 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2799
2800 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->facts.RequestCredit);
2801}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002802static DEVICE_ATTR_RO(fw_queue_depth);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302803
2804/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002805 * sas_address_show - sas address
Bart Van Assche4beb4862018-06-15 14:42:01 -07002806 * @cdev: pointer to embedded class device
2807 * @attr: ?
2808 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302809 *
2810 * This is the controller sas address
2811 *
2812 * A sysfs 'read-only' shost attribute.
2813 */
2814static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002815host_sas_address_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302816 char *buf)
2817
2818{
2819 struct Scsi_Host *shost = class_to_shost(cdev);
2820 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2821
2822 return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
2823 (unsigned long long)ioc->sas_hba.sas_address);
2824}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002825static DEVICE_ATTR_RO(host_sas_address);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302826
2827/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002828 * logging_level_show - logging level
Bart Van Assche4beb4862018-06-15 14:42:01 -07002829 * @cdev: pointer to embedded class device
2830 * @attr: ?
2831 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302832 *
2833 * A sysfs 'read/write' shost attribute.
2834 */
2835static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002836logging_level_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302837 char *buf)
2838{
2839 struct Scsi_Host *shost = class_to_shost(cdev);
2840 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2841
2842 return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->logging_level);
2843}
2844static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002845logging_level_store(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302846 const char *buf, size_t count)
2847{
2848 struct Scsi_Host *shost = class_to_shost(cdev);
2849 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2850 int val = 0;
2851
2852 if (sscanf(buf, "%x", &val) != 1)
2853 return -EINVAL;
2854
2855 ioc->logging_level = val;
Joe Perches919d8a32018-09-17 08:01:09 -07002856 ioc_info(ioc, "logging_level=%08xh\n",
2857 ioc->logging_level);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302858 return strlen(buf);
2859}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002860static DEVICE_ATTR_RW(logging_level);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302861
2862/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002863 * fwfault_debug_show - show/store fwfault_debug
Bart Van Assche4beb4862018-06-15 14:42:01 -07002864 * @cdev: pointer to embedded class device
2865 * @attr: ?
2866 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302867 *
2868 * mpt3sas_fwfault_debug is command line option
2869 * A sysfs 'read/write' shost attribute.
2870 */
2871static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002872fwfault_debug_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302873 char *buf)
2874{
2875 struct Scsi_Host *shost = class_to_shost(cdev);
2876 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2877
2878 return snprintf(buf, PAGE_SIZE, "%d\n", ioc->fwfault_debug);
2879}
2880static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002881fwfault_debug_store(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302882 const char *buf, size_t count)
2883{
2884 struct Scsi_Host *shost = class_to_shost(cdev);
2885 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2886 int val = 0;
2887
2888 if (sscanf(buf, "%d", &val) != 1)
2889 return -EINVAL;
2890
2891 ioc->fwfault_debug = val;
Joe Perches919d8a32018-09-17 08:01:09 -07002892 ioc_info(ioc, "fwfault_debug=%d\n",
2893 ioc->fwfault_debug);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302894 return strlen(buf);
2895}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002896static DEVICE_ATTR_RW(fwfault_debug);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302897
2898/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002899 * ioc_reset_count_show - ioc reset count
Bart Van Assche4beb4862018-06-15 14:42:01 -07002900 * @cdev: pointer to embedded class device
2901 * @attr: ?
2902 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302903 *
2904 * This is firmware queue depth limit
2905 *
2906 * A sysfs 'read-only' shost attribute.
2907 */
2908static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002909ioc_reset_count_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302910 char *buf)
2911{
2912 struct Scsi_Host *shost = class_to_shost(cdev);
2913 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2914
2915 return snprintf(buf, PAGE_SIZE, "%d\n", ioc->ioc_reset_count);
2916}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002917static DEVICE_ATTR_RO(ioc_reset_count);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302918
2919/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002920 * reply_queue_count_show - number of reply queues
Bart Van Assche4beb4862018-06-15 14:42:01 -07002921 * @cdev: pointer to embedded class device
2922 * @attr: ?
2923 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302924 *
2925 * This is number of reply queues
2926 *
2927 * A sysfs 'read-only' shost attribute.
2928 */
2929static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002930reply_queue_count_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302931 struct device_attribute *attr, char *buf)
2932{
2933 u8 reply_queue_count;
2934 struct Scsi_Host *shost = class_to_shost(cdev);
2935 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2936
2937 if ((ioc->facts.IOCCapabilities &
2938 MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable)
2939 reply_queue_count = ioc->reply_queue_count;
2940 else
2941 reply_queue_count = 1;
2942
2943 return snprintf(buf, PAGE_SIZE, "%d\n", reply_queue_count);
2944}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002945static DEVICE_ATTR_RO(reply_queue_count);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302946
Sreekanth Reddy42263092015-11-11 17:30:29 +05302947/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002948 * BRM_status_show - Backup Rail Monitor Status
Bart Van Assche4beb4862018-06-15 14:42:01 -07002949 * @cdev: pointer to embedded class device
2950 * @attr: ?
2951 * @buf: the buffer returned
Sreekanth Reddy42263092015-11-11 17:30:29 +05302952 *
2953 * This is number of reply queues
2954 *
2955 * A sysfs 'read-only' shost attribute.
2956 */
2957static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002958BRM_status_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddy42263092015-11-11 17:30:29 +05302959 char *buf)
2960{
2961 struct Scsi_Host *shost = class_to_shost(cdev);
2962 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2963 Mpi2IOUnitPage3_t *io_unit_pg3 = NULL;
2964 Mpi2ConfigReply_t mpi_reply;
2965 u16 backup_rail_monitor_status = 0;
2966 u16 ioc_status;
2967 int sz;
2968 ssize_t rc = 0;
2969
2970 if (!ioc->is_warpdrive) {
Joe Perches919d8a32018-09-17 08:01:09 -07002971 ioc_err(ioc, "%s: BRM attribute is only for warpdrive\n",
2972 __func__);
Sreekanth Reddy42263092015-11-11 17:30:29 +05302973 goto out;
2974 }
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05302975 /* pci_access_mutex lock acquired by sysfs show path */
2976 mutex_lock(&ioc->pci_access_mutex);
2977 if (ioc->pci_error_recovery || ioc->remove_host) {
2978 mutex_unlock(&ioc->pci_access_mutex);
2979 return 0;
2980 }
Sreekanth Reddy42263092015-11-11 17:30:29 +05302981
2982 /* allocate upto GPIOVal 36 entries */
2983 sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36);
2984 io_unit_pg3 = kzalloc(sz, GFP_KERNEL);
2985 if (!io_unit_pg3) {
Joe Perches919d8a32018-09-17 08:01:09 -07002986 ioc_err(ioc, "%s: failed allocating memory for iounit_pg3: (%d) bytes\n",
2987 __func__, sz);
Sreekanth Reddy42263092015-11-11 17:30:29 +05302988 goto out;
2989 }
2990
2991 if (mpt3sas_config_get_iounit_pg3(ioc, &mpi_reply, io_unit_pg3, sz) !=
2992 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07002993 ioc_err(ioc, "%s: failed reading iounit_pg3\n",
2994 __func__);
Sreekanth Reddy42263092015-11-11 17:30:29 +05302995 goto out;
2996 }
2997
2998 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
2999 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
Joe Perches919d8a32018-09-17 08:01:09 -07003000 ioc_err(ioc, "%s: iounit_pg3 failed with ioc_status(0x%04x)\n",
3001 __func__, ioc_status);
Sreekanth Reddy42263092015-11-11 17:30:29 +05303002 goto out;
3003 }
3004
3005 if (io_unit_pg3->GPIOCount < 25) {
Joe Perches919d8a32018-09-17 08:01:09 -07003006 ioc_err(ioc, "%s: iounit_pg3->GPIOCount less than 25 entries, detected (%d) entries\n",
3007 __func__, io_unit_pg3->GPIOCount);
Sreekanth Reddy42263092015-11-11 17:30:29 +05303008 goto out;
3009 }
3010
3011 /* BRM status is in bit zero of GPIOVal[24] */
3012 backup_rail_monitor_status = le16_to_cpu(io_unit_pg3->GPIOVal[24]);
3013 rc = snprintf(buf, PAGE_SIZE, "%d\n", (backup_rail_monitor_status & 1));
3014
3015 out:
3016 kfree(io_unit_pg3);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05303017 mutex_unlock(&ioc->pci_access_mutex);
Sreekanth Reddy42263092015-11-11 17:30:29 +05303018 return rc;
3019}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003020static DEVICE_ATTR_RO(BRM_status);
Sreekanth Reddy42263092015-11-11 17:30:29 +05303021
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303022struct DIAG_BUFFER_START {
3023 __le32 Size;
3024 __le32 DiagVersion;
3025 u8 BufferType;
3026 u8 Reserved[3];
3027 __le32 Reserved1;
3028 __le32 Reserved2;
3029 __le32 Reserved3;
3030};
3031
3032/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003033 * host_trace_buffer_size_show - host buffer size (trace only)
Bart Van Assche4beb4862018-06-15 14:42:01 -07003034 * @cdev: pointer to embedded class device
3035 * @attr: ?
3036 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303037 *
3038 * A sysfs 'read-only' shost attribute.
3039 */
3040static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003041host_trace_buffer_size_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303042 struct device_attribute *attr, char *buf)
3043{
3044 struct Scsi_Host *shost = class_to_shost(cdev);
3045 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3046 u32 size = 0;
3047 struct DIAG_BUFFER_START *request_data;
3048
3049 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
Joe Perches919d8a32018-09-17 08:01:09 -07003050 ioc_err(ioc, "%s: host_trace_buffer is not registered\n",
3051 __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303052 return 0;
3053 }
3054
3055 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3056 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07003057 ioc_err(ioc, "%s: host_trace_buffer is not registered\n",
3058 __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303059 return 0;
3060 }
3061
3062 request_data = (struct DIAG_BUFFER_START *)
3063 ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE];
3064 if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 ||
3065 le32_to_cpu(request_data->DiagVersion) == 0x01000000 ||
3066 le32_to_cpu(request_data->DiagVersion) == 0x01010000) &&
3067 le32_to_cpu(request_data->Reserved3) == 0x4742444c)
3068 size = le32_to_cpu(request_data->Size);
3069
3070 ioc->ring_buffer_sz = size;
3071 return snprintf(buf, PAGE_SIZE, "%d\n", size);
3072}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003073static DEVICE_ATTR_RO(host_trace_buffer_size);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303074
3075/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003076 * host_trace_buffer_show - firmware ring buffer (trace only)
Bart Van Assche4beb4862018-06-15 14:42:01 -07003077 * @cdev: pointer to embedded class device
3078 * @attr: ?
3079 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303080 *
3081 * A sysfs 'read/write' shost attribute.
3082 *
3083 * You will only be able to read 4k bytes of ring buffer at a time.
3084 * In order to read beyond 4k bytes, you will have to write out the
3085 * offset to the same attribute, it will move the pointer.
3086 */
3087static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003088host_trace_buffer_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303089 char *buf)
3090{
3091 struct Scsi_Host *shost = class_to_shost(cdev);
3092 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3093 void *request_data;
3094 u32 size;
3095
3096 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
Joe Perches919d8a32018-09-17 08:01:09 -07003097 ioc_err(ioc, "%s: host_trace_buffer is not registered\n",
3098 __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303099 return 0;
3100 }
3101
3102 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3103 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07003104 ioc_err(ioc, "%s: host_trace_buffer is not registered\n",
3105 __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303106 return 0;
3107 }
3108
3109 if (ioc->ring_buffer_offset > ioc->ring_buffer_sz)
3110 return 0;
3111
3112 size = ioc->ring_buffer_sz - ioc->ring_buffer_offset;
3113 size = (size >= PAGE_SIZE) ? (PAGE_SIZE - 1) : size;
3114 request_data = ioc->diag_buffer[0] + ioc->ring_buffer_offset;
3115 memcpy(buf, request_data, size);
3116 return size;
3117}
3118
3119static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003120host_trace_buffer_store(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303121 const char *buf, size_t count)
3122{
3123 struct Scsi_Host *shost = class_to_shost(cdev);
3124 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3125 int val = 0;
3126
3127 if (sscanf(buf, "%d", &val) != 1)
3128 return -EINVAL;
3129
3130 ioc->ring_buffer_offset = val;
3131 return strlen(buf);
3132}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003133static DEVICE_ATTR_RW(host_trace_buffer);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303134
3135
3136/*****************************************/
3137
3138/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003139 * host_trace_buffer_enable_show - firmware ring buffer (trace only)
Bart Van Assche4beb4862018-06-15 14:42:01 -07003140 * @cdev: pointer to embedded class device
3141 * @attr: ?
3142 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303143 *
3144 * A sysfs 'read/write' shost attribute.
3145 *
3146 * This is a mechnism to post/release host_trace_buffers
3147 */
3148static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003149host_trace_buffer_enable_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303150 struct device_attribute *attr, char *buf)
3151{
3152 struct Scsi_Host *shost = class_to_shost(cdev);
3153 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3154
3155 if ((!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) ||
3156 ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3157 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0))
3158 return snprintf(buf, PAGE_SIZE, "off\n");
3159 else if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3160 MPT3_DIAG_BUFFER_IS_RELEASED))
3161 return snprintf(buf, PAGE_SIZE, "release\n");
3162 else
3163 return snprintf(buf, PAGE_SIZE, "post\n");
3164}
3165
3166static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003167host_trace_buffer_enable_store(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303168 struct device_attribute *attr, const char *buf, size_t count)
3169{
3170 struct Scsi_Host *shost = class_to_shost(cdev);
3171 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3172 char str[10] = "";
3173 struct mpt3_diag_register diag_register;
3174 u8 issue_reset = 0;
3175
3176 /* don't allow post/release occurr while recovery is active */
3177 if (ioc->shost_recovery || ioc->remove_host ||
3178 ioc->pci_error_recovery || ioc->is_driver_loading)
3179 return -EBUSY;
3180
3181 if (sscanf(buf, "%9s", str) != 1)
3182 return -EINVAL;
3183
3184 if (!strcmp(str, "post")) {
3185 /* exit out if host buffers are already posted */
3186 if ((ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) &&
3187 (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3188 MPT3_DIAG_BUFFER_IS_REGISTERED) &&
3189 ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3190 MPT3_DIAG_BUFFER_IS_RELEASED) == 0))
3191 goto out;
3192 memset(&diag_register, 0, sizeof(struct mpt3_diag_register));
Joe Perches919d8a32018-09-17 08:01:09 -07003193 ioc_info(ioc, "posting host trace buffers\n");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303194 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
Sreekanth Reddyd04a6ed2019-09-13 09:04:38 -04003195
3196 if (ioc->manu_pg11.HostTraceBufferMaxSizeKB != 0 &&
3197 ioc->diag_buffer_sz[MPI2_DIAG_BUF_TYPE_TRACE] != 0) {
3198 /* post the same buffer allocated previously */
3199 diag_register.requested_buffer_size =
3200 ioc->diag_buffer_sz[MPI2_DIAG_BUF_TYPE_TRACE];
3201 } else
3202 diag_register.requested_buffer_size = (1024 * 1024);
3203
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303204 diag_register.unique_id = 0x7075900;
3205 ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0;
3206 _ctl_diag_register_2(ioc, &diag_register);
3207 } else if (!strcmp(str, "release")) {
3208 /* exit out if host buffers are already released */
3209 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE])
3210 goto out;
3211 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3212 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0)
3213 goto out;
3214 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3215 MPT3_DIAG_BUFFER_IS_RELEASED))
3216 goto out;
Joe Perches919d8a32018-09-17 08:01:09 -07003217 ioc_info(ioc, "releasing host trace buffer\n");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303218 mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE,
3219 &issue_reset);
3220 }
3221
3222 out:
3223 return strlen(buf);
3224}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003225static DEVICE_ATTR_RW(host_trace_buffer_enable);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303226
3227/*********** diagnostic trigger suppport *********************************/
3228
3229/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003230 * diag_trigger_master_show - show the diag_trigger_master attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003231 * @cdev: pointer to embedded class device
3232 * @attr: ?
3233 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303234 *
3235 * A sysfs 'read/write' shost attribute.
3236 */
3237static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003238diag_trigger_master_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303239 struct device_attribute *attr, char *buf)
3240
3241{
3242 struct Scsi_Host *shost = class_to_shost(cdev);
3243 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3244 unsigned long flags;
3245 ssize_t rc;
3246
3247 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3248 rc = sizeof(struct SL_WH_MASTER_TRIGGER_T);
3249 memcpy(buf, &ioc->diag_trigger_master, rc);
3250 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3251 return rc;
3252}
3253
3254/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003255 * diag_trigger_master_store - store the diag_trigger_master attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003256 * @cdev: pointer to embedded class device
3257 * @attr: ?
3258 * @buf: the buffer returned
3259 * @count: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303260 *
3261 * A sysfs 'read/write' shost attribute.
3262 */
3263static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003264diag_trigger_master_store(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303265 struct device_attribute *attr, const char *buf, size_t count)
3266
3267{
3268 struct Scsi_Host *shost = class_to_shost(cdev);
3269 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3270 unsigned long flags;
3271 ssize_t rc;
3272
3273 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3274 rc = min(sizeof(struct SL_WH_MASTER_TRIGGER_T), count);
3275 memset(&ioc->diag_trigger_master, 0,
3276 sizeof(struct SL_WH_MASTER_TRIGGER_T));
3277 memcpy(&ioc->diag_trigger_master, buf, rc);
3278 ioc->diag_trigger_master.MasterData |=
3279 (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET);
3280 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3281 return rc;
3282}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003283static DEVICE_ATTR_RW(diag_trigger_master);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303284
3285
3286/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003287 * diag_trigger_event_show - show the diag_trigger_event attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003288 * @cdev: pointer to embedded class device
3289 * @attr: ?
3290 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303291 *
3292 * A sysfs 'read/write' shost attribute.
3293 */
3294static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003295diag_trigger_event_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303296 struct device_attribute *attr, char *buf)
3297{
3298 struct Scsi_Host *shost = class_to_shost(cdev);
3299 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3300 unsigned long flags;
3301 ssize_t rc;
3302
3303 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3304 rc = sizeof(struct SL_WH_EVENT_TRIGGERS_T);
3305 memcpy(buf, &ioc->diag_trigger_event, rc);
3306 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3307 return rc;
3308}
3309
3310/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003311 * diag_trigger_event_store - store the diag_trigger_event attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003312 * @cdev: pointer to embedded class device
3313 * @attr: ?
3314 * @buf: the buffer returned
3315 * @count: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303316 *
3317 * A sysfs 'read/write' shost attribute.
3318 */
3319static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003320diag_trigger_event_store(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303321 struct device_attribute *attr, const char *buf, size_t count)
3322
3323{
3324 struct Scsi_Host *shost = class_to_shost(cdev);
3325 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3326 unsigned long flags;
3327 ssize_t sz;
3328
3329 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3330 sz = min(sizeof(struct SL_WH_EVENT_TRIGGERS_T), count);
3331 memset(&ioc->diag_trigger_event, 0,
3332 sizeof(struct SL_WH_EVENT_TRIGGERS_T));
3333 memcpy(&ioc->diag_trigger_event, buf, sz);
3334 if (ioc->diag_trigger_event.ValidEntries > NUM_VALID_ENTRIES)
3335 ioc->diag_trigger_event.ValidEntries = NUM_VALID_ENTRIES;
3336 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3337 return sz;
3338}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003339static DEVICE_ATTR_RW(diag_trigger_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303340
3341
3342/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003343 * diag_trigger_scsi_show - show the diag_trigger_scsi attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003344 * @cdev: pointer to embedded class device
3345 * @attr: ?
3346 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303347 *
3348 * A sysfs 'read/write' shost attribute.
3349 */
3350static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003351diag_trigger_scsi_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303352 struct device_attribute *attr, char *buf)
3353{
3354 struct Scsi_Host *shost = class_to_shost(cdev);
3355 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3356 unsigned long flags;
3357 ssize_t rc;
3358
3359 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3360 rc = sizeof(struct SL_WH_SCSI_TRIGGERS_T);
3361 memcpy(buf, &ioc->diag_trigger_scsi, rc);
3362 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3363 return rc;
3364}
3365
3366/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003367 * diag_trigger_scsi_store - store the diag_trigger_scsi attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003368 * @cdev: pointer to embedded class device
3369 * @attr: ?
3370 * @buf: the buffer returned
3371 * @count: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303372 *
3373 * A sysfs 'read/write' shost attribute.
3374 */
3375static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003376diag_trigger_scsi_store(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303377 struct device_attribute *attr, const char *buf, size_t count)
3378{
3379 struct Scsi_Host *shost = class_to_shost(cdev);
3380 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3381 unsigned long flags;
3382 ssize_t sz;
3383
3384 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
Dan Carpenter1de540a2019-07-26 09:52:05 +03003385 sz = min(sizeof(ioc->diag_trigger_scsi), count);
3386 memset(&ioc->diag_trigger_scsi, 0, sizeof(ioc->diag_trigger_scsi));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303387 memcpy(&ioc->diag_trigger_scsi, buf, sz);
3388 if (ioc->diag_trigger_scsi.ValidEntries > NUM_VALID_ENTRIES)
3389 ioc->diag_trigger_scsi.ValidEntries = NUM_VALID_ENTRIES;
3390 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3391 return sz;
3392}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003393static DEVICE_ATTR_RW(diag_trigger_scsi);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303394
3395
3396/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003397 * diag_trigger_scsi_show - show the diag_trigger_mpi attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003398 * @cdev: pointer to embedded class device
3399 * @attr: ?
3400 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303401 *
3402 * A sysfs 'read/write' shost attribute.
3403 */
3404static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003405diag_trigger_mpi_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303406 struct device_attribute *attr, char *buf)
3407{
3408 struct Scsi_Host *shost = class_to_shost(cdev);
3409 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3410 unsigned long flags;
3411 ssize_t rc;
3412
3413 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3414 rc = sizeof(struct SL_WH_MPI_TRIGGERS_T);
3415 memcpy(buf, &ioc->diag_trigger_mpi, rc);
3416 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3417 return rc;
3418}
3419
3420/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003421 * diag_trigger_mpi_store - store the diag_trigger_mpi attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003422 * @cdev: pointer to embedded class device
3423 * @attr: ?
3424 * @buf: the buffer returned
3425 * @count: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303426 *
3427 * A sysfs 'read/write' shost attribute.
3428 */
3429static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003430diag_trigger_mpi_store(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303431 struct device_attribute *attr, const char *buf, size_t count)
3432{
3433 struct Scsi_Host *shost = class_to_shost(cdev);
3434 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3435 unsigned long flags;
3436 ssize_t sz;
3437
3438 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3439 sz = min(sizeof(struct SL_WH_MPI_TRIGGERS_T), count);
3440 memset(&ioc->diag_trigger_mpi, 0,
Dan Carpenter66331e82012-12-07 13:56:22 +03003441 sizeof(ioc->diag_trigger_mpi));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303442 memcpy(&ioc->diag_trigger_mpi, buf, sz);
3443 if (ioc->diag_trigger_mpi.ValidEntries > NUM_VALID_ENTRIES)
3444 ioc->diag_trigger_mpi.ValidEntries = NUM_VALID_ENTRIES;
3445 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3446 return sz;
3447}
3448
Tomas Henzlc9df1442019-06-14 16:41:44 +02003449static DEVICE_ATTR_RW(diag_trigger_mpi);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303450
3451/*********** diagnostic trigger suppport *** END ****************************/
3452
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303453/*****************************************/
3454
Suganath Prabu3ac8e472019-08-03 09:59:53 -04003455/**
3456 * drv_support_bitmap_show - driver supported feature bitmap
3457 * @cdev - pointer to embedded class device
3458 * @buf - the buffer returned
3459 *
3460 * A sysfs 'read-only' shost attribute.
3461 */
3462static ssize_t
3463drv_support_bitmap_show(struct device *cdev,
3464 struct device_attribute *attr, char *buf)
3465{
3466 struct Scsi_Host *shost = class_to_shost(cdev);
3467 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3468
3469 return snprintf(buf, PAGE_SIZE, "0x%08x\n", ioc->drv_support_bitmap);
3470}
3471static DEVICE_ATTR_RO(drv_support_bitmap);
3472
Sreekanth Reddy8dc8d292019-08-22 02:19:01 -04003473/**
3474 * enable_sdev_max_qd_show - display whether sdev max qd is enabled/disabled
3475 * @cdev - pointer to embedded class device
3476 * @buf - the buffer returned
3477 *
3478 * A sysfs read/write shost attribute. This attribute is used to set the
3479 * targets queue depth to HBA IO queue depth if this attribute is enabled.
3480 */
3481static ssize_t
3482enable_sdev_max_qd_show(struct device *cdev,
3483 struct device_attribute *attr, char *buf)
3484{
3485 struct Scsi_Host *shost = class_to_shost(cdev);
3486 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3487
3488 return snprintf(buf, PAGE_SIZE, "%d\n", ioc->enable_sdev_max_qd);
3489}
3490
3491/**
3492 * enable_sdev_max_qd_store - Enable/disable sdev max qd
3493 * @cdev - pointer to embedded class device
3494 * @buf - the buffer returned
3495 *
3496 * A sysfs read/write shost attribute. This attribute is used to set the
3497 * targets queue depth to HBA IO queue depth if this attribute is enabled.
3498 * If this attribute is disabled then targets will have corresponding default
3499 * queue depth.
3500 */
3501static ssize_t
3502enable_sdev_max_qd_store(struct device *cdev,
3503 struct device_attribute *attr, const char *buf, size_t count)
3504{
3505 struct Scsi_Host *shost = class_to_shost(cdev);
3506 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3507 struct MPT3SAS_DEVICE *sas_device_priv_data;
3508 struct MPT3SAS_TARGET *sas_target_priv_data;
3509 int val = 0;
3510 struct scsi_device *sdev;
3511 struct _raid_device *raid_device;
3512 int qdepth;
3513
3514 if (kstrtoint(buf, 0, &val) != 0)
3515 return -EINVAL;
3516
3517 switch (val) {
3518 case 0:
3519 ioc->enable_sdev_max_qd = 0;
3520 shost_for_each_device(sdev, ioc->shost) {
3521 sas_device_priv_data = sdev->hostdata;
3522 if (!sas_device_priv_data)
3523 continue;
3524 sas_target_priv_data = sas_device_priv_data->sas_target;
3525 if (!sas_target_priv_data)
3526 continue;
3527
3528 if (sas_target_priv_data->flags &
3529 MPT_TARGET_FLAGS_VOLUME) {
3530 raid_device =
3531 mpt3sas_raid_device_find_by_handle(ioc,
3532 sas_target_priv_data->handle);
3533
3534 switch (raid_device->volume_type) {
3535 case MPI2_RAID_VOL_TYPE_RAID0:
3536 if (raid_device->device_info &
3537 MPI2_SAS_DEVICE_INFO_SSP_TARGET)
3538 qdepth =
3539 MPT3SAS_SAS_QUEUE_DEPTH;
3540 else
3541 qdepth =
3542 MPT3SAS_SATA_QUEUE_DEPTH;
3543 break;
3544 case MPI2_RAID_VOL_TYPE_RAID1E:
3545 case MPI2_RAID_VOL_TYPE_RAID1:
3546 case MPI2_RAID_VOL_TYPE_RAID10:
3547 case MPI2_RAID_VOL_TYPE_UNKNOWN:
3548 default:
3549 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
3550 }
3551 } else if (sas_target_priv_data->flags &
3552 MPT_TARGET_FLAGS_PCIE_DEVICE)
3553 qdepth = MPT3SAS_NVME_QUEUE_DEPTH;
3554 else
3555 qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
3556
3557 mpt3sas_scsih_change_queue_depth(sdev, qdepth);
3558 }
3559 break;
3560 case 1:
3561 ioc->enable_sdev_max_qd = 1;
3562 shost_for_each_device(sdev, ioc->shost)
3563 mpt3sas_scsih_change_queue_depth(sdev,
3564 shost->can_queue);
3565 break;
3566 default:
3567 return -EINVAL;
3568 }
3569
3570 return strlen(buf);
3571}
3572static DEVICE_ATTR_RW(enable_sdev_max_qd);
3573
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303574struct device_attribute *mpt3sas_host_attrs[] = {
3575 &dev_attr_version_fw,
3576 &dev_attr_version_bios,
3577 &dev_attr_version_mpi,
3578 &dev_attr_version_product,
3579 &dev_attr_version_nvdata_persistent,
3580 &dev_attr_version_nvdata_default,
3581 &dev_attr_board_name,
3582 &dev_attr_board_assembly,
3583 &dev_attr_board_tracer,
3584 &dev_attr_io_delay,
3585 &dev_attr_device_delay,
3586 &dev_attr_logging_level,
3587 &dev_attr_fwfault_debug,
3588 &dev_attr_fw_queue_depth,
3589 &dev_attr_host_sas_address,
3590 &dev_attr_ioc_reset_count,
3591 &dev_attr_host_trace_buffer_size,
3592 &dev_attr_host_trace_buffer,
3593 &dev_attr_host_trace_buffer_enable,
3594 &dev_attr_reply_queue_count,
3595 &dev_attr_diag_trigger_master,
3596 &dev_attr_diag_trigger_event,
3597 &dev_attr_diag_trigger_scsi,
3598 &dev_attr_diag_trigger_mpi,
Suganath Prabu3ac8e472019-08-03 09:59:53 -04003599 &dev_attr_drv_support_bitmap,
Sreekanth Reddy42263092015-11-11 17:30:29 +05303600 &dev_attr_BRM_status,
Sreekanth Reddy8dc8d292019-08-22 02:19:01 -04003601 &dev_attr_enable_sdev_max_qd,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303602 NULL,
3603};
3604
3605/* device attributes */
3606
3607/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003608 * sas_address_show - sas address
Bart Van Assche4beb4862018-06-15 14:42:01 -07003609 * @dev: pointer to embedded class device
3610 * @attr: ?
3611 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303612 *
3613 * This is the sas address for the target
3614 *
3615 * A sysfs 'read-only' shost attribute.
3616 */
3617static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003618sas_address_show(struct device *dev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303619 char *buf)
3620{
3621 struct scsi_device *sdev = to_scsi_device(dev);
3622 struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
3623
3624 return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
3625 (unsigned long long)sas_device_priv_data->sas_target->sas_address);
3626}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003627static DEVICE_ATTR_RO(sas_address);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303628
3629/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003630 * sas_device_handle_show - device handle
Bart Van Assche4beb4862018-06-15 14:42:01 -07003631 * @dev: pointer to embedded class device
3632 * @attr: ?
3633 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303634 *
3635 * This is the firmware assigned device handle
3636 *
3637 * A sysfs 'read-only' shost attribute.
3638 */
3639static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003640sas_device_handle_show(struct device *dev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303641 char *buf)
3642{
3643 struct scsi_device *sdev = to_scsi_device(dev);
3644 struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
3645
3646 return snprintf(buf, PAGE_SIZE, "0x%04x\n",
3647 sas_device_priv_data->sas_target->handle);
3648}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003649static DEVICE_ATTR_RO(sas_device_handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303650
Adam Manzanares307d9072016-12-12 16:31:40 -08003651/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003652 * sas_ncq_io_prio_show - send prioritized io commands to device
Bart Van Assche4beb4862018-06-15 14:42:01 -07003653 * @dev: pointer to embedded device
3654 * @attr: ?
3655 * @buf: the buffer returned
Adam Manzanares307d9072016-12-12 16:31:40 -08003656 *
3657 * A sysfs 'read/write' sdev attribute, only works with SATA
3658 */
3659static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003660sas_ncq_prio_enable_show(struct device *dev,
Adam Manzanares307d9072016-12-12 16:31:40 -08003661 struct device_attribute *attr, char *buf)
3662{
3663 struct scsi_device *sdev = to_scsi_device(dev);
3664 struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
3665
3666 return snprintf(buf, PAGE_SIZE, "%d\n",
3667 sas_device_priv_data->ncq_prio_enable);
3668}
3669
3670static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003671sas_ncq_prio_enable_store(struct device *dev,
Adam Manzanares307d9072016-12-12 16:31:40 -08003672 struct device_attribute *attr,
3673 const char *buf, size_t count)
3674{
3675 struct scsi_device *sdev = to_scsi_device(dev);
3676 struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
3677 bool ncq_prio_enable = 0;
3678
3679 if (kstrtobool(buf, &ncq_prio_enable))
3680 return -EINVAL;
3681
3682 if (!scsih_ncq_prio_supp(sdev))
3683 return -EINVAL;
3684
3685 sas_device_priv_data->ncq_prio_enable = ncq_prio_enable;
3686 return strlen(buf);
3687}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003688static DEVICE_ATTR_RW(sas_ncq_prio_enable);
Adam Manzanares307d9072016-12-12 16:31:40 -08003689
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303690struct device_attribute *mpt3sas_dev_attrs[] = {
3691 &dev_attr_sas_address,
3692 &dev_attr_sas_device_handle,
Adam Manzanares307d9072016-12-12 16:31:40 -08003693 &dev_attr_sas_ncq_prio_enable,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303694 NULL,
3695};
3696
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303697/* file operations table for mpt3ctl device */
3698static const struct file_operations ctl_fops = {
3699 .owner = THIS_MODULE,
3700 .unlocked_ioctl = _ctl_ioctl,
3701 .poll = _ctl_poll,
3702 .fasync = _ctl_fasync,
3703#ifdef CONFIG_COMPAT
3704 .compat_ioctl = _ctl_ioctl_compat,
3705#endif
3706};
3707
3708/* file operations table for mpt2ctl device */
3709static const struct file_operations ctl_gen2_fops = {
3710 .owner = THIS_MODULE,
3711 .unlocked_ioctl = _ctl_mpt2_ioctl,
3712 .poll = _ctl_poll,
3713 .fasync = _ctl_fasync,
3714#ifdef CONFIG_COMPAT
3715 .compat_ioctl = _ctl_mpt2_ioctl_compat,
3716#endif
3717};
3718
3719static struct miscdevice ctl_dev = {
3720 .minor = MPT3SAS_MINOR,
3721 .name = MPT3SAS_DEV_NAME,
3722 .fops = &ctl_fops,
3723};
3724
3725static struct miscdevice gen2_ctl_dev = {
3726 .minor = MPT2SAS_MINOR,
3727 .name = MPT2SAS_DEV_NAME,
3728 .fops = &ctl_gen2_fops,
3729};
3730
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303731/**
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303732 * mpt3sas_ctl_init - main entry point for ctl.
Bart Van Assche4beb4862018-06-15 14:42:01 -07003733 * @hbas_to_enumerate: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303734 */
3735void
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303736mpt3sas_ctl_init(ushort hbas_to_enumerate)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303737{
3738 async_queue = NULL;
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303739
3740 /* Don't register mpt3ctl ioctl device if
3741 * hbas_to_enumarate is one.
3742 */
3743 if (hbas_to_enumerate != 1)
3744 if (misc_register(&ctl_dev) < 0)
3745 pr_err("%s can't register misc device [minor=%d]\n",
3746 MPT3SAS_DRIVER_NAME, MPT3SAS_MINOR);
3747
3748 /* Don't register mpt3ctl ioctl device if
3749 * hbas_to_enumarate is two.
3750 */
3751 if (hbas_to_enumerate != 2)
3752 if (misc_register(&gen2_ctl_dev) < 0)
3753 pr_err("%s can't register misc device [minor=%d]\n",
3754 MPT2SAS_DRIVER_NAME, MPT2SAS_MINOR);
3755
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303756 init_waitqueue_head(&ctl_poll_wait);
3757}
3758
3759/**
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303760 * mpt3sas_ctl_exit - exit point for ctl
Bart Van Assche4beb4862018-06-15 14:42:01 -07003761 * @hbas_to_enumerate: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303762 */
3763void
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303764mpt3sas_ctl_exit(ushort hbas_to_enumerate)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303765{
3766 struct MPT3SAS_ADAPTER *ioc;
3767 int i;
3768
3769 list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
3770
3771 /* free memory associated to diag buffers */
3772 for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
3773 if (!ioc->diag_buffer[i])
3774 continue;
3775 if (!(ioc->diag_buffer_status[i] &
3776 MPT3_DIAG_BUFFER_IS_REGISTERED))
3777 continue;
3778 if ((ioc->diag_buffer_status[i] &
3779 MPT3_DIAG_BUFFER_IS_RELEASED))
3780 continue;
Christoph Hellwig1c2048b2018-10-11 09:35:25 +02003781 dma_free_coherent(&ioc->pdev->dev,
3782 ioc->diag_buffer_sz[i],
3783 ioc->diag_buffer[i],
3784 ioc->diag_buffer_dma[i]);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303785 ioc->diag_buffer[i] = NULL;
3786 ioc->diag_buffer_status[i] = 0;
3787 }
3788
3789 kfree(ioc->event_log);
3790 }
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303791 if (hbas_to_enumerate != 1)
3792 misc_deregister(&ctl_dev);
3793 if (hbas_to_enumerate != 2)
3794 misc_deregister(&gen2_ctl_dev);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303795}