blob: a195caed8d9b6935d464d2364ed7b7b127c329bf [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);
Sreekanth Reddy782b2812019-09-13 09:04:40 -04001594 rc = -ENOMEM;
1595 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301596 }
1597 ioc->diag_buffer[buffer_type] = request_data;
1598 ioc->diag_buffer_sz[buffer_type] = request_data_sz;
1599 ioc->diag_buffer_dma[buffer_type] = request_data_dma;
1600 }
1601
1602 mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
1603 mpi_request->BufferType = diag_register->buffer_type;
1604 mpi_request->Flags = cpu_to_le32(diag_register->diagnostic_flags);
1605 mpi_request->BufferAddress = cpu_to_le64(request_data_dma);
1606 mpi_request->BufferLength = cpu_to_le32(request_data_sz);
1607 mpi_request->VF_ID = 0; /* TODO */
1608 mpi_request->VP_ID = 0;
1609
Joe Perches919d8a32018-09-17 08:01:09 -07001610 dctlprintk(ioc,
1611 ioc_info(ioc, "%s: diag_buffer(0x%p), dma(0x%llx), sz(%d)\n",
1612 __func__, request_data,
1613 (unsigned long long)request_data_dma,
1614 le32_to_cpu(mpi_request->BufferLength)));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301615
1616 for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++)
1617 mpi_request->ProductSpecific[i] =
1618 cpu_to_le32(ioc->product_specific[buffer_type][i]);
1619
1620 init_completion(&ioc->ctl_cmds.done);
Suganath Prabu S078a4cc2019-05-31 08:14:34 -04001621 ioc->put_smid_default(ioc, smid);
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07001622 wait_for_completion_timeout(&ioc->ctl_cmds.done,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301623 MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
1624
1625 if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
Chaitra P Bd37306c2018-05-31 06:34:50 -04001626 issue_reset =
1627 mpt3sas_base_check_cmd_timeout(ioc,
1628 ioc->ctl_cmds.status, mpi_request,
1629 sizeof(Mpi2DiagBufferPostRequest_t)/4);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301630 goto issue_host_reset;
1631 }
1632
1633 /* process the completed Reply Message Frame */
1634 if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07001635 ioc_err(ioc, "%s: no reply message\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301636 rc = -EFAULT;
1637 goto out;
1638 }
1639
1640 mpi_reply = ioc->ctl_cmds.reply;
1641 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1642
1643 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
1644 ioc->diag_buffer_status[buffer_type] |=
1645 MPT3_DIAG_BUFFER_IS_REGISTERED;
Joe Perches919d8a32018-09-17 08:01:09 -07001646 dctlprintk(ioc, ioc_info(ioc, "%s: success\n", __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301647 } else {
Joe Perches919d8a32018-09-17 08:01:09 -07001648 ioc_info(ioc, "%s: ioc_status(0x%04x) log_info(0x%08x)\n",
1649 __func__,
1650 ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301651 rc = -EFAULT;
1652 }
1653
1654 issue_host_reset:
1655 if (issue_reset)
Calvin Owens98c56ad2016-07-28 21:38:21 -07001656 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301657
1658 out:
1659
1660 if (rc && request_data)
Christoph Hellwig1c2048b2018-10-11 09:35:25 +02001661 dma_free_coherent(&ioc->pdev->dev, request_data_sz,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301662 request_data, request_data_dma);
1663
1664 ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
1665 return rc;
1666}
1667
1668/**
1669 * mpt3sas_enable_diag_buffer - enabling diag_buffers support driver load time
1670 * @ioc: per adapter object
1671 * @bits_to_register: bitwise field where trace is bit 0, and snapshot is bit 1
1672 *
1673 * This is called when command line option diag_buffer_enable is enabled
1674 * at driver load time.
1675 */
1676void
1677mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc, u8 bits_to_register)
1678{
1679 struct mpt3_diag_register diag_register;
Sreekanth Reddyd04a6ed2019-09-13 09:04:38 -04001680 u32 ret_val;
1681 u32 trace_buff_size = ioc->manu_pg11.HostTraceBufferMaxSizeKB<<10;
1682 u32 min_trace_buff_size = 0;
1683 u32 decr_trace_buff_size = 0;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301684
1685 memset(&diag_register, 0, sizeof(struct mpt3_diag_register));
1686
1687 if (bits_to_register & 1) {
Joe Perches919d8a32018-09-17 08:01:09 -07001688 ioc_info(ioc, "registering trace buffer support\n");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301689 ioc->diag_trigger_master.MasterData =
1690 (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET);
1691 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301692 diag_register.unique_id = 0x7075900;
Sreekanth Reddyd04a6ed2019-09-13 09:04:38 -04001693
1694 if (trace_buff_size != 0) {
1695 diag_register.requested_buffer_size = trace_buff_size;
1696 min_trace_buff_size =
1697 ioc->manu_pg11.HostTraceBufferMinSizeKB<<10;
1698 decr_trace_buff_size =
1699 ioc->manu_pg11.HostTraceBufferDecrementSizeKB<<10;
1700
1701 if (min_trace_buff_size > trace_buff_size) {
1702 /* The buff size is not set correctly */
1703 ioc_err(ioc,
1704 "Min Trace Buff size (%d KB) greater than Max Trace Buff size (%d KB)\n",
1705 min_trace_buff_size>>10,
1706 trace_buff_size>>10);
1707 ioc_err(ioc,
1708 "Using zero Min Trace Buff Size\n");
1709 min_trace_buff_size = 0;
1710 }
1711
1712 if (decr_trace_buff_size == 0) {
1713 /*
1714 * retry the min size if decrement
1715 * is not available.
1716 */
1717 decr_trace_buff_size =
1718 trace_buff_size - min_trace_buff_size;
1719 }
1720 } else {
1721 /* register for 2MB buffers */
1722 diag_register.requested_buffer_size = 2 * (1024 * 1024);
1723 }
1724
1725 do {
1726 ret_val = _ctl_diag_register_2(ioc, &diag_register);
1727
1728 if (ret_val == -ENOMEM && min_trace_buff_size &&
1729 (trace_buff_size - decr_trace_buff_size) >=
1730 min_trace_buff_size) {
1731 /* adjust the buffer size */
1732 trace_buff_size -= decr_trace_buff_size;
1733 diag_register.requested_buffer_size =
1734 trace_buff_size;
1735 } else
1736 break;
1737 } while (true);
1738
1739 if (ret_val == -ENOMEM)
1740 ioc_err(ioc,
1741 "Cannot allocate trace buffer memory. Last memory tried = %d KB\n",
1742 diag_register.requested_buffer_size>>10);
1743 else if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE]
1744 & MPT3_DIAG_BUFFER_IS_REGISTERED)
1745 ioc_err(ioc, "Trace buffer memory %d KB allocated\n",
1746 diag_register.requested_buffer_size>>10);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301747 }
1748
1749 if (bits_to_register & 2) {
Joe Perches919d8a32018-09-17 08:01:09 -07001750 ioc_info(ioc, "registering snapshot buffer support\n");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301751 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_SNAPSHOT;
1752 /* register for 2MB buffers */
1753 diag_register.requested_buffer_size = 2 * (1024 * 1024);
1754 diag_register.unique_id = 0x7075901;
1755 _ctl_diag_register_2(ioc, &diag_register);
1756 }
1757
1758 if (bits_to_register & 4) {
Joe Perches919d8a32018-09-17 08:01:09 -07001759 ioc_info(ioc, "registering extended buffer support\n");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301760 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_EXTENDED;
1761 /* register for 2MB buffers */
1762 diag_register.requested_buffer_size = 2 * (1024 * 1024);
1763 diag_register.unique_id = 0x7075901;
1764 _ctl_diag_register_2(ioc, &diag_register);
1765 }
1766}
1767
1768/**
1769 * _ctl_diag_register - application register with driver
1770 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07001771 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301772 *
1773 * This will allow the driver to setup any required buffers that will be
1774 * needed by firmware to communicate with the driver.
1775 */
1776static long
1777_ctl_diag_register(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1778{
1779 struct mpt3_diag_register karg;
1780 long rc;
1781
1782 if (copy_from_user(&karg, arg, sizeof(karg))) {
1783 pr_err("failure at %s:%d/%s()!\n",
1784 __FILE__, __LINE__, __func__);
1785 return -EFAULT;
1786 }
1787
1788 rc = _ctl_diag_register_2(ioc, &karg);
1789 return rc;
1790}
1791
1792/**
1793 * _ctl_diag_unregister - application unregister with driver
1794 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07001795 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301796 *
1797 * This will allow the driver to cleanup any memory allocated for diag
1798 * messages and to free up any resources.
1799 */
1800static long
1801_ctl_diag_unregister(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1802{
1803 struct mpt3_diag_unregister karg;
1804 void *request_data;
1805 dma_addr_t request_data_dma;
1806 u32 request_data_sz;
1807 u8 buffer_type;
1808
1809 if (copy_from_user(&karg, arg, sizeof(karg))) {
1810 pr_err("failure at %s:%d/%s()!\n",
1811 __FILE__, __LINE__, __func__);
1812 return -EFAULT;
1813 }
1814
Joe Perches919d8a32018-09-17 08:01:09 -07001815 dctlprintk(ioc, ioc_info(ioc, "%s\n",
1816 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301817
1818 buffer_type = karg.unique_id & 0x000000ff;
1819 if (!_ctl_diag_capability(ioc, buffer_type)) {
Joe Perches919d8a32018-09-17 08:01:09 -07001820 ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
1821 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301822 return -EPERM;
1823 }
1824
1825 if ((ioc->diag_buffer_status[buffer_type] &
1826 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07001827 ioc_err(ioc, "%s: buffer_type(0x%02x) is not registered\n",
1828 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301829 return -EINVAL;
1830 }
1831 if ((ioc->diag_buffer_status[buffer_type] &
1832 MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07001833 ioc_err(ioc, "%s: buffer_type(0x%02x) has not been released\n",
1834 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301835 return -EINVAL;
1836 }
1837
1838 if (karg.unique_id != ioc->unique_id[buffer_type]) {
Joe Perches919d8a32018-09-17 08:01:09 -07001839 ioc_err(ioc, "%s: unique_id(0x%08x) is not registered\n",
1840 __func__, karg.unique_id);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301841 return -EINVAL;
1842 }
1843
1844 request_data = ioc->diag_buffer[buffer_type];
1845 if (!request_data) {
Joe Perches919d8a32018-09-17 08:01:09 -07001846 ioc_err(ioc, "%s: doesn't have memory allocated for buffer_type(0x%02x)\n",
1847 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301848 return -ENOMEM;
1849 }
1850
1851 request_data_sz = ioc->diag_buffer_sz[buffer_type];
1852 request_data_dma = ioc->diag_buffer_dma[buffer_type];
Christoph Hellwig1c2048b2018-10-11 09:35:25 +02001853 dma_free_coherent(&ioc->pdev->dev, request_data_sz,
1854 request_data, request_data_dma);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301855 ioc->diag_buffer[buffer_type] = NULL;
1856 ioc->diag_buffer_status[buffer_type] = 0;
1857 return 0;
1858}
1859
1860/**
1861 * _ctl_diag_query - query relevant info associated with diag buffers
1862 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07001863 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301864 *
1865 * The application will send only buffer_type and unique_id. Driver will
1866 * inspect unique_id first, if valid, fill in all the info. If unique_id is
1867 * 0x00, the driver will return info specified by Buffer Type.
1868 */
1869static long
1870_ctl_diag_query(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1871{
1872 struct mpt3_diag_query karg;
1873 void *request_data;
1874 int i;
1875 u8 buffer_type;
1876
1877 if (copy_from_user(&karg, arg, sizeof(karg))) {
1878 pr_err("failure at %s:%d/%s()!\n",
1879 __FILE__, __LINE__, __func__);
1880 return -EFAULT;
1881 }
1882
Joe Perches919d8a32018-09-17 08:01:09 -07001883 dctlprintk(ioc, ioc_info(ioc, "%s\n",
1884 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301885
1886 karg.application_flags = 0;
1887 buffer_type = karg.buffer_type;
1888
1889 if (!_ctl_diag_capability(ioc, buffer_type)) {
Joe Perches919d8a32018-09-17 08:01:09 -07001890 ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
1891 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301892 return -EPERM;
1893 }
1894
1895 if ((ioc->diag_buffer_status[buffer_type] &
1896 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07001897 ioc_err(ioc, "%s: buffer_type(0x%02x) is not registered\n",
1898 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301899 return -EINVAL;
1900 }
1901
1902 if (karg.unique_id & 0xffffff00) {
1903 if (karg.unique_id != ioc->unique_id[buffer_type]) {
Joe Perches919d8a32018-09-17 08:01:09 -07001904 ioc_err(ioc, "%s: unique_id(0x%08x) is not registered\n",
1905 __func__, karg.unique_id);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301906 return -EINVAL;
1907 }
1908 }
1909
1910 request_data = ioc->diag_buffer[buffer_type];
1911 if (!request_data) {
Joe Perches919d8a32018-09-17 08:01:09 -07001912 ioc_err(ioc, "%s: doesn't have buffer for buffer_type(0x%02x)\n",
1913 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301914 return -ENOMEM;
1915 }
1916
1917 if (ioc->diag_buffer_status[buffer_type] & MPT3_DIAG_BUFFER_IS_RELEASED)
1918 karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED |
1919 MPT3_APP_FLAGS_BUFFER_VALID);
1920 else
1921 karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED |
1922 MPT3_APP_FLAGS_BUFFER_VALID |
1923 MPT3_APP_FLAGS_FW_BUFFER_ACCESS);
1924
1925 for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++)
1926 karg.product_specific[i] =
1927 ioc->product_specific[buffer_type][i];
1928
1929 karg.total_buffer_size = ioc->diag_buffer_sz[buffer_type];
1930 karg.driver_added_buffer_size = 0;
1931 karg.unique_id = ioc->unique_id[buffer_type];
1932 karg.diagnostic_flags = ioc->diagnostic_flags[buffer_type];
1933
1934 if (copy_to_user(arg, &karg, sizeof(struct mpt3_diag_query))) {
Joe Perches919d8a32018-09-17 08:01:09 -07001935 ioc_err(ioc, "%s: unable to write mpt3_diag_query data @ %p\n",
1936 __func__, arg);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301937 return -EFAULT;
1938 }
1939 return 0;
1940}
1941
1942/**
1943 * mpt3sas_send_diag_release - Diag Release Message
1944 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07001945 * @buffer_type: specifies either TRACE, SNAPSHOT, or EXTENDED
1946 * @issue_reset: specifies whether host reset is required.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301947 *
1948 */
1949int
1950mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
1951 u8 *issue_reset)
1952{
1953 Mpi2DiagReleaseRequest_t *mpi_request;
1954 Mpi2DiagReleaseReply_t *mpi_reply;
1955 u16 smid;
1956 u16 ioc_status;
1957 u32 ioc_state;
1958 int rc;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301959
Joe Perches919d8a32018-09-17 08:01:09 -07001960 dctlprintk(ioc, ioc_info(ioc, "%s\n",
1961 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301962
1963 rc = 0;
1964 *issue_reset = 0;
1965
1966 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1967 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1968 if (ioc->diag_buffer_status[buffer_type] &
1969 MPT3_DIAG_BUFFER_IS_REGISTERED)
1970 ioc->diag_buffer_status[buffer_type] |=
1971 MPT3_DIAG_BUFFER_IS_RELEASED;
Joe Perches919d8a32018-09-17 08:01:09 -07001972 dctlprintk(ioc,
1973 ioc_info(ioc, "%s: skipping due to FAULT state\n",
1974 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301975 rc = -EAGAIN;
1976 goto out;
1977 }
1978
1979 if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
Joe Perches919d8a32018-09-17 08:01:09 -07001980 ioc_err(ioc, "%s: ctl_cmd in use\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301981 rc = -EAGAIN;
1982 goto out;
1983 }
1984
1985 smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx);
1986 if (!smid) {
Joe Perches919d8a32018-09-17 08:01:09 -07001987 ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301988 rc = -EAGAIN;
1989 goto out;
1990 }
1991
1992 ioc->ctl_cmds.status = MPT3_CMD_PENDING;
1993 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
1994 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1995 ioc->ctl_cmds.smid = smid;
1996
1997 mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE;
1998 mpi_request->BufferType = buffer_type;
1999 mpi_request->VF_ID = 0; /* TODO */
2000 mpi_request->VP_ID = 0;
2001
2002 init_completion(&ioc->ctl_cmds.done);
Suganath Prabu S078a4cc2019-05-31 08:14:34 -04002003 ioc->put_smid_default(ioc, smid);
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002004 wait_for_completion_timeout(&ioc->ctl_cmds.done,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302005 MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
2006
2007 if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
Chaitra P Bd37306c2018-05-31 06:34:50 -04002008 *issue_reset = mpt3sas_base_check_cmd_timeout(ioc,
2009 ioc->ctl_cmds.status, mpi_request,
2010 sizeof(Mpi2DiagReleaseRequest_t)/4);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302011 rc = -EFAULT;
2012 goto out;
2013 }
2014
2015 /* process the completed Reply Message Frame */
2016 if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07002017 ioc_err(ioc, "%s: no reply message\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302018 rc = -EFAULT;
2019 goto out;
2020 }
2021
2022 mpi_reply = ioc->ctl_cmds.reply;
2023 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
2024
2025 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
2026 ioc->diag_buffer_status[buffer_type] |=
2027 MPT3_DIAG_BUFFER_IS_RELEASED;
Joe Perches919d8a32018-09-17 08:01:09 -07002028 dctlprintk(ioc, ioc_info(ioc, "%s: success\n", __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302029 } else {
Joe Perches919d8a32018-09-17 08:01:09 -07002030 ioc_info(ioc, "%s: ioc_status(0x%04x) log_info(0x%08x)\n",
2031 __func__,
2032 ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302033 rc = -EFAULT;
2034 }
2035
2036 out:
2037 ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
2038 return rc;
2039}
2040
2041/**
2042 * _ctl_diag_release - request to send Diag Release Message to firmware
Bart Van Assche4beb4862018-06-15 14:42:01 -07002043 * @ioc: ?
2044 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302045 *
2046 * This allows ownership of the specified buffer to returned to the driver,
2047 * allowing an application to read the buffer without fear that firmware is
Masahiro Yamada9a284e52017-02-27 14:29:48 -08002048 * overwriting information in the buffer.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302049 */
2050static long
2051_ctl_diag_release(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
2052{
2053 struct mpt3_diag_release karg;
2054 void *request_data;
2055 int rc;
2056 u8 buffer_type;
2057 u8 issue_reset = 0;
2058
2059 if (copy_from_user(&karg, arg, sizeof(karg))) {
2060 pr_err("failure at %s:%d/%s()!\n",
2061 __FILE__, __LINE__, __func__);
2062 return -EFAULT;
2063 }
2064
Joe Perches919d8a32018-09-17 08:01:09 -07002065 dctlprintk(ioc, ioc_info(ioc, "%s\n",
2066 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302067
2068 buffer_type = karg.unique_id & 0x000000ff;
2069 if (!_ctl_diag_capability(ioc, buffer_type)) {
Joe Perches919d8a32018-09-17 08:01:09 -07002070 ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
2071 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302072 return -EPERM;
2073 }
2074
2075 if ((ioc->diag_buffer_status[buffer_type] &
2076 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07002077 ioc_err(ioc, "%s: buffer_type(0x%02x) is not registered\n",
2078 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302079 return -EINVAL;
2080 }
2081
2082 if (karg.unique_id != ioc->unique_id[buffer_type]) {
Joe Perches919d8a32018-09-17 08:01:09 -07002083 ioc_err(ioc, "%s: unique_id(0x%08x) is not registered\n",
2084 __func__, karg.unique_id);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302085 return -EINVAL;
2086 }
2087
2088 if (ioc->diag_buffer_status[buffer_type] &
2089 MPT3_DIAG_BUFFER_IS_RELEASED) {
Joe Perches919d8a32018-09-17 08:01:09 -07002090 ioc_err(ioc, "%s: buffer_type(0x%02x) is already released\n",
2091 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302092 return 0;
2093 }
2094
2095 request_data = ioc->diag_buffer[buffer_type];
2096
2097 if (!request_data) {
Joe Perches919d8a32018-09-17 08:01:09 -07002098 ioc_err(ioc, "%s: doesn't have memory allocated for buffer_type(0x%02x)\n",
2099 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302100 return -ENOMEM;
2101 }
2102
2103 /* buffers were released by due to host reset */
2104 if ((ioc->diag_buffer_status[buffer_type] &
2105 MPT3_DIAG_BUFFER_IS_DIAG_RESET)) {
2106 ioc->diag_buffer_status[buffer_type] |=
2107 MPT3_DIAG_BUFFER_IS_RELEASED;
2108 ioc->diag_buffer_status[buffer_type] &=
2109 ~MPT3_DIAG_BUFFER_IS_DIAG_RESET;
Joe Perches919d8a32018-09-17 08:01:09 -07002110 ioc_err(ioc, "%s: buffer_type(0x%02x) was released due to host reset\n",
2111 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302112 return 0;
2113 }
2114
2115 rc = mpt3sas_send_diag_release(ioc, buffer_type, &issue_reset);
2116
2117 if (issue_reset)
Calvin Owens98c56ad2016-07-28 21:38:21 -07002118 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302119
2120 return rc;
2121}
2122
2123/**
2124 * _ctl_diag_read_buffer - request for copy of the diag buffer
2125 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07002126 * @arg: user space buffer containing ioctl content
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302127 */
2128static long
2129_ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
2130{
2131 struct mpt3_diag_read_buffer karg;
2132 struct mpt3_diag_read_buffer __user *uarg = arg;
2133 void *request_data, *diag_data;
2134 Mpi2DiagBufferPostRequest_t *mpi_request;
2135 Mpi2DiagBufferPostReply_t *mpi_reply;
2136 int rc, i;
2137 u8 buffer_type;
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002138 unsigned long request_size, copy_size;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302139 u16 smid;
2140 u16 ioc_status;
2141 u8 issue_reset = 0;
2142
2143 if (copy_from_user(&karg, arg, sizeof(karg))) {
2144 pr_err("failure at %s:%d/%s()!\n",
2145 __FILE__, __LINE__, __func__);
2146 return -EFAULT;
2147 }
2148
Joe Perches919d8a32018-09-17 08:01:09 -07002149 dctlprintk(ioc, ioc_info(ioc, "%s\n",
2150 __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302151
2152 buffer_type = karg.unique_id & 0x000000ff;
2153 if (!_ctl_diag_capability(ioc, buffer_type)) {
Joe Perches919d8a32018-09-17 08:01:09 -07002154 ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
2155 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302156 return -EPERM;
2157 }
2158
2159 if (karg.unique_id != ioc->unique_id[buffer_type]) {
Joe Perches919d8a32018-09-17 08:01:09 -07002160 ioc_err(ioc, "%s: unique_id(0x%08x) is not registered\n",
2161 __func__, karg.unique_id);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302162 return -EINVAL;
2163 }
2164
2165 request_data = ioc->diag_buffer[buffer_type];
2166 if (!request_data) {
Joe Perches919d8a32018-09-17 08:01:09 -07002167 ioc_err(ioc, "%s: doesn't have buffer for buffer_type(0x%02x)\n",
2168 __func__, buffer_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302169 return -ENOMEM;
2170 }
2171
2172 request_size = ioc->diag_buffer_sz[buffer_type];
2173
2174 if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) {
Joe Perches919d8a32018-09-17 08:01:09 -07002175 ioc_err(ioc, "%s: either the starting_offset or bytes_to_read are not 4 byte aligned\n",
2176 __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302177 return -EINVAL;
2178 }
2179
2180 if (karg.starting_offset > request_size)
2181 return -EINVAL;
2182
2183 diag_data = (void *)(request_data + karg.starting_offset);
Joe Perches919d8a32018-09-17 08:01:09 -07002184 dctlprintk(ioc,
2185 ioc_info(ioc, "%s: diag_buffer(%p), offset(%d), sz(%d)\n",
2186 __func__, diag_data, karg.starting_offset,
2187 karg.bytes_to_read));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302188
2189 /* Truncate data on requests that are too large */
2190 if ((diag_data + karg.bytes_to_read < diag_data) ||
2191 (diag_data + karg.bytes_to_read > request_data + request_size))
2192 copy_size = request_size - karg.starting_offset;
2193 else
2194 copy_size = karg.bytes_to_read;
2195
2196 if (copy_to_user((void __user *)uarg->diagnostic_data,
2197 diag_data, copy_size)) {
Joe Perches919d8a32018-09-17 08:01:09 -07002198 ioc_err(ioc, "%s: Unable to write mpt_diag_read_buffer_t data @ %p\n",
2199 __func__, diag_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302200 return -EFAULT;
2201 }
2202
2203 if ((karg.flags & MPT3_FLAGS_REREGISTER) == 0)
2204 return 0;
2205
Joe Perches919d8a32018-09-17 08:01:09 -07002206 dctlprintk(ioc,
2207 ioc_info(ioc, "%s: Reregister buffer_type(0x%02x)\n",
2208 __func__, buffer_type));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302209 if ((ioc->diag_buffer_status[buffer_type] &
2210 MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07002211 dctlprintk(ioc,
2212 ioc_info(ioc, "%s: buffer_type(0x%02x) is still registered\n",
2213 __func__, buffer_type));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302214 return 0;
2215 }
2216 /* Get a free request frame and save the message context.
2217 */
2218
2219 if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
Joe Perches919d8a32018-09-17 08:01:09 -07002220 ioc_err(ioc, "%s: ctl_cmd in use\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302221 rc = -EAGAIN;
2222 goto out;
2223 }
2224
2225 smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx);
2226 if (!smid) {
Joe Perches919d8a32018-09-17 08:01:09 -07002227 ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302228 rc = -EAGAIN;
2229 goto out;
2230 }
2231
2232 rc = 0;
2233 ioc->ctl_cmds.status = MPT3_CMD_PENDING;
2234 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
2235 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
2236 ioc->ctl_cmds.smid = smid;
2237
2238 mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
2239 mpi_request->BufferType = buffer_type;
2240 mpi_request->BufferLength =
2241 cpu_to_le32(ioc->diag_buffer_sz[buffer_type]);
2242 mpi_request->BufferAddress =
2243 cpu_to_le64(ioc->diag_buffer_dma[buffer_type]);
2244 for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++)
2245 mpi_request->ProductSpecific[i] =
2246 cpu_to_le32(ioc->product_specific[buffer_type][i]);
2247 mpi_request->VF_ID = 0; /* TODO */
2248 mpi_request->VP_ID = 0;
2249
2250 init_completion(&ioc->ctl_cmds.done);
Suganath Prabu S078a4cc2019-05-31 08:14:34 -04002251 ioc->put_smid_default(ioc, smid);
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002252 wait_for_completion_timeout(&ioc->ctl_cmds.done,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302253 MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
2254
2255 if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
Chaitra P Bd37306c2018-05-31 06:34:50 -04002256 issue_reset =
2257 mpt3sas_base_check_cmd_timeout(ioc,
2258 ioc->ctl_cmds.status, mpi_request,
2259 sizeof(Mpi2DiagBufferPostRequest_t)/4);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302260 goto issue_host_reset;
2261 }
2262
2263 /* process the completed Reply Message Frame */
2264 if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07002265 ioc_err(ioc, "%s: no reply message\n", __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302266 rc = -EFAULT;
2267 goto out;
2268 }
2269
2270 mpi_reply = ioc->ctl_cmds.reply;
2271 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
2272
2273 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
2274 ioc->diag_buffer_status[buffer_type] |=
2275 MPT3_DIAG_BUFFER_IS_REGISTERED;
Joe Perches919d8a32018-09-17 08:01:09 -07002276 dctlprintk(ioc, ioc_info(ioc, "%s: success\n", __func__));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302277 } else {
Joe Perches919d8a32018-09-17 08:01:09 -07002278 ioc_info(ioc, "%s: ioc_status(0x%04x) log_info(0x%08x)\n",
2279 __func__, ioc_status,
2280 le32_to_cpu(mpi_reply->IOCLogInfo));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302281 rc = -EFAULT;
2282 }
2283
2284 issue_host_reset:
2285 if (issue_reset)
Calvin Owens98c56ad2016-07-28 21:38:21 -07002286 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302287
2288 out:
2289
2290 ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
2291 return rc;
2292}
2293
2294
2295
2296#ifdef CONFIG_COMPAT
2297/**
2298 * _ctl_compat_mpt_command - convert 32bit pointers to 64bit.
2299 * @ioc: per adapter object
Bart Van Assche4beb4862018-06-15 14:42:01 -07002300 * @cmd: ioctl opcode
2301 * @arg: (struct mpt3_ioctl_command32)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302302 *
2303 * MPT3COMMAND32 - Handle 32bit applications running on 64bit os.
2304 */
2305static long
2306_ctl_compat_mpt_command(struct MPT3SAS_ADAPTER *ioc, unsigned cmd,
2307 void __user *arg)
2308{
2309 struct mpt3_ioctl_command32 karg32;
2310 struct mpt3_ioctl_command32 __user *uarg;
2311 struct mpt3_ioctl_command karg;
2312
2313 if (_IOC_SIZE(cmd) != sizeof(struct mpt3_ioctl_command32))
2314 return -EINVAL;
2315
2316 uarg = (struct mpt3_ioctl_command32 __user *) arg;
2317
2318 if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) {
2319 pr_err("failure at %s:%d/%s()!\n",
2320 __FILE__, __LINE__, __func__);
2321 return -EFAULT;
2322 }
2323
2324 memset(&karg, 0, sizeof(struct mpt3_ioctl_command));
2325 karg.hdr.ioc_number = karg32.hdr.ioc_number;
2326 karg.hdr.port_number = karg32.hdr.port_number;
2327 karg.hdr.max_data_size = karg32.hdr.max_data_size;
2328 karg.timeout = karg32.timeout;
2329 karg.max_reply_bytes = karg32.max_reply_bytes;
2330 karg.data_in_size = karg32.data_in_size;
2331 karg.data_out_size = karg32.data_out_size;
2332 karg.max_sense_bytes = karg32.max_sense_bytes;
2333 karg.data_sge_offset = karg32.data_sge_offset;
2334 karg.reply_frame_buf_ptr = compat_ptr(karg32.reply_frame_buf_ptr);
2335 karg.data_in_buf_ptr = compat_ptr(karg32.data_in_buf_ptr);
2336 karg.data_out_buf_ptr = compat_ptr(karg32.data_out_buf_ptr);
2337 karg.sense_data_ptr = compat_ptr(karg32.sense_data_ptr);
2338 return _ctl_do_mpt_command(ioc, karg, &uarg->mf);
2339}
2340#endif
2341
2342/**
2343 * _ctl_ioctl_main - main ioctl entry point
Bart Van Assche4beb4862018-06-15 14:42:01 -07002344 * @file: (struct file)
2345 * @cmd: ioctl opcode
2346 * @arg: user space data buffer
2347 * @compat: handles 32 bit applications in 64bit os
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302348 * @mpi_version: will be MPI2_VERSION for mpt2ctl ioctl device &
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05302349 * MPI25_VERSION | MPI26_VERSION for mpt3ctl ioctl device.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302350 */
2351static long
2352_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302353 u8 compat, u16 mpi_version)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302354{
2355 struct MPT3SAS_ADAPTER *ioc;
2356 struct mpt3_ioctl_header ioctl_header;
2357 enum block_state state;
2358 long ret = -EINVAL;
2359
2360 /* get IOCTL header */
2361 if (copy_from_user(&ioctl_header, (char __user *)arg,
2362 sizeof(struct mpt3_ioctl_header))) {
2363 pr_err("failure at %s:%d/%s()!\n",
2364 __FILE__, __LINE__, __func__);
2365 return -EFAULT;
2366 }
2367
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302368 if (_ctl_verify_adapter(ioctl_header.ioc_number,
2369 &ioc, mpi_version) == -1 || !ioc)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302370 return -ENODEV;
2371
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05302372 /* pci_access_mutex lock acquired by ioctl path */
2373 mutex_lock(&ioc->pci_access_mutex);
2374
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302375 if (ioc->shost_recovery || ioc->pci_error_recovery ||
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05302376 ioc->is_driver_loading || ioc->remove_host) {
2377 ret = -EAGAIN;
2378 goto out_unlock_pciaccess;
2379 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302380
2381 state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
2382 if (state == NON_BLOCKING) {
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05302383 if (!mutex_trylock(&ioc->ctl_cmds.mutex)) {
2384 ret = -EAGAIN;
2385 goto out_unlock_pciaccess;
2386 }
2387 } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) {
2388 ret = -ERESTARTSYS;
2389 goto out_unlock_pciaccess;
2390 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302391
2392
2393 switch (cmd) {
2394 case MPT3IOCINFO:
2395 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_iocinfo))
2396 ret = _ctl_getiocinfo(ioc, arg);
2397 break;
2398#ifdef CONFIG_COMPAT
2399 case MPT3COMMAND32:
2400#endif
2401 case MPT3COMMAND:
2402 {
2403 struct mpt3_ioctl_command __user *uarg;
2404 struct mpt3_ioctl_command karg;
2405
2406#ifdef CONFIG_COMPAT
2407 if (compat) {
2408 ret = _ctl_compat_mpt_command(ioc, cmd, arg);
2409 break;
2410 }
2411#endif
2412 if (copy_from_user(&karg, arg, sizeof(karg))) {
2413 pr_err("failure at %s:%d/%s()!\n",
2414 __FILE__, __LINE__, __func__);
2415 ret = -EFAULT;
2416 break;
2417 }
2418
Gen Zhangf9e3ebe2019-05-30 09:10:30 +08002419 if (karg.hdr.ioc_number != ioctl_header.ioc_number) {
2420 ret = -EINVAL;
2421 break;
2422 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302423 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_command)) {
2424 uarg = arg;
2425 ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf);
2426 }
2427 break;
2428 }
2429 case MPT3EVENTQUERY:
2430 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_eventquery))
2431 ret = _ctl_eventquery(ioc, arg);
2432 break;
2433 case MPT3EVENTENABLE:
2434 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_eventenable))
2435 ret = _ctl_eventenable(ioc, arg);
2436 break;
2437 case MPT3EVENTREPORT:
2438 ret = _ctl_eventreport(ioc, arg);
2439 break;
2440 case MPT3HARDRESET:
2441 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_diag_reset))
2442 ret = _ctl_do_reset(ioc, arg);
2443 break;
2444 case MPT3BTDHMAPPING:
2445 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_btdh_mapping))
2446 ret = _ctl_btdh_mapping(ioc, arg);
2447 break;
2448 case MPT3DIAGREGISTER:
2449 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_register))
2450 ret = _ctl_diag_register(ioc, arg);
2451 break;
2452 case MPT3DIAGUNREGISTER:
2453 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_unregister))
2454 ret = _ctl_diag_unregister(ioc, arg);
2455 break;
2456 case MPT3DIAGQUERY:
2457 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_query))
2458 ret = _ctl_diag_query(ioc, arg);
2459 break;
2460 case MPT3DIAGRELEASE:
2461 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_release))
2462 ret = _ctl_diag_release(ioc, arg);
2463 break;
2464 case MPT3DIAGREADBUFFER:
2465 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_read_buffer))
2466 ret = _ctl_diag_read_buffer(ioc, arg);
2467 break;
2468 default:
Joe Perches919d8a32018-09-17 08:01:09 -07002469 dctlprintk(ioc,
2470 ioc_info(ioc, "unsupported ioctl opcode(0x%08x)\n",
2471 cmd));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302472 break;
2473 }
2474
2475 mutex_unlock(&ioc->ctl_cmds.mutex);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05302476out_unlock_pciaccess:
2477 mutex_unlock(&ioc->pci_access_mutex);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302478 return ret;
2479}
2480
2481/**
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302482 * _ctl_ioctl - mpt3ctl main ioctl entry point (unlocked)
Bart Van Assche4beb4862018-06-15 14:42:01 -07002483 * @file: (struct file)
2484 * @cmd: ioctl opcode
2485 * @arg: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302486 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002487static long
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302488_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302489{
2490 long ret;
2491
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05302492 /* pass MPI25_VERSION | MPI26_VERSION value,
2493 * to indicate that this ioctl cmd
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302494 * came from mpt3ctl ioctl device.
2495 */
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05302496 ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0,
2497 MPI25_VERSION | MPI26_VERSION);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302498 return ret;
2499}
2500
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302501/**
2502 * _ctl_mpt2_ioctl - mpt2ctl main ioctl entry point (unlocked)
Bart Van Assche4beb4862018-06-15 14:42:01 -07002503 * @file: (struct file)
2504 * @cmd: ioctl opcode
2505 * @arg: ?
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302506 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002507static long
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302508_ctl_mpt2_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2509{
2510 long ret;
2511
2512 /* pass MPI2_VERSION value, to indicate that this ioctl cmd
2513 * came from mpt2ctl ioctl device.
2514 */
2515 ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0, MPI2_VERSION);
2516 return ret;
2517}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302518#ifdef CONFIG_COMPAT
2519/**
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302520 *_ ctl_ioctl_compat - main ioctl entry point (compat)
Bart Van Assche4beb4862018-06-15 14:42:01 -07002521 * @file: ?
2522 * @cmd: ?
2523 * @arg: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302524 *
2525 * This routine handles 32 bit applications in 64bit os.
2526 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002527static long
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302528_ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302529{
2530 long ret;
2531
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05302532 ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1,
2533 MPI25_VERSION | MPI26_VERSION);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302534 return ret;
2535}
2536
2537/**
2538 *_ ctl_mpt2_ioctl_compat - main ioctl entry point (compat)
Bart Van Assche4beb4862018-06-15 14:42:01 -07002539 * @file: ?
2540 * @cmd: ?
2541 * @arg: ?
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302542 *
2543 * This routine handles 32 bit applications in 64bit os.
2544 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002545static long
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05302546_ctl_mpt2_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
2547{
2548 long ret;
2549
2550 ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1, MPI2_VERSION);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302551 return ret;
2552}
2553#endif
2554
2555/* scsi host attributes */
2556/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002557 * version_fw_show - firmware version
Bart Van Assche4beb4862018-06-15 14:42:01 -07002558 * @cdev: pointer to embedded class device
2559 * @attr: ?
2560 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302561 *
2562 * A sysfs 'read-only' shost attribute.
2563 */
2564static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002565version_fw_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302566 char *buf)
2567{
2568 struct Scsi_Host *shost = class_to_shost(cdev);
2569 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2570
2571 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
2572 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
2573 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
2574 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
2575 ioc->facts.FWVersion.Word & 0x000000FF);
2576}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002577static DEVICE_ATTR_RO(version_fw);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302578
2579/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002580 * version_bios_show - bios version
Bart Van Assche4beb4862018-06-15 14:42:01 -07002581 * @cdev: pointer to embedded class device
2582 * @attr: ?
2583 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302584 *
2585 * A sysfs 'read-only' shost attribute.
2586 */
2587static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002588version_bios_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302589 char *buf)
2590{
2591 struct Scsi_Host *shost = class_to_shost(cdev);
2592 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2593
2594 u32 version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
2595
2596 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
2597 (version & 0xFF000000) >> 24,
2598 (version & 0x00FF0000) >> 16,
2599 (version & 0x0000FF00) >> 8,
2600 version & 0x000000FF);
2601}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002602static DEVICE_ATTR_RO(version_bios);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302603
2604/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002605 * version_mpi_show - MPI (message passing interface) version
Bart Van Assche4beb4862018-06-15 14:42:01 -07002606 * @cdev: pointer to embedded class device
2607 * @attr: ?
2608 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302609 *
2610 * A sysfs 'read-only' shost attribute.
2611 */
2612static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002613version_mpi_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302614 char *buf)
2615{
2616 struct Scsi_Host *shost = class_to_shost(cdev);
2617 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2618
2619 return snprintf(buf, PAGE_SIZE, "%03x.%02x\n",
2620 ioc->facts.MsgVersion, ioc->facts.HeaderVersion >> 8);
2621}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002622static DEVICE_ATTR_RO(version_mpi);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302623
2624/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002625 * version_product_show - product name
Bart Van Assche4beb4862018-06-15 14:42:01 -07002626 * @cdev: pointer to embedded class device
2627 * @attr: ?
2628 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302629 *
2630 * A sysfs 'read-only' shost attribute.
2631 */
2632static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002633version_product_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302634 char *buf)
2635{
2636 struct Scsi_Host *shost = class_to_shost(cdev);
2637 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2638
2639 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.ChipName);
2640}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002641static DEVICE_ATTR_RO(version_product);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302642
2643/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002644 * version_nvdata_persistent_show - ndvata persistent version
Bart Van Assche4beb4862018-06-15 14:42:01 -07002645 * @cdev: pointer to embedded class device
2646 * @attr: ?
2647 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302648 *
2649 * A sysfs 'read-only' shost attribute.
2650 */
2651static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002652version_nvdata_persistent_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302653 struct device_attribute *attr, char *buf)
2654{
2655 struct Scsi_Host *shost = class_to_shost(cdev);
2656 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2657
2658 return snprintf(buf, PAGE_SIZE, "%08xh\n",
2659 le32_to_cpu(ioc->iounit_pg0.NvdataVersionPersistent.Word));
2660}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002661static DEVICE_ATTR_RO(version_nvdata_persistent);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302662
2663/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002664 * version_nvdata_default_show - nvdata default version
Bart Van Assche4beb4862018-06-15 14:42:01 -07002665 * @cdev: pointer to embedded class device
2666 * @attr: ?
2667 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302668 *
2669 * A sysfs 'read-only' shost attribute.
2670 */
2671static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002672version_nvdata_default_show(struct device *cdev, struct device_attribute
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302673 *attr, char *buf)
2674{
2675 struct Scsi_Host *shost = class_to_shost(cdev);
2676 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2677
2678 return snprintf(buf, PAGE_SIZE, "%08xh\n",
2679 le32_to_cpu(ioc->iounit_pg0.NvdataVersionDefault.Word));
2680}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002681static DEVICE_ATTR_RO(version_nvdata_default);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302682
2683/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002684 * board_name_show - board name
Bart Van Assche4beb4862018-06-15 14:42:01 -07002685 * @cdev: pointer to embedded class device
2686 * @attr: ?
2687 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302688 *
2689 * A sysfs 'read-only' shost attribute.
2690 */
2691static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002692board_name_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302693 char *buf)
2694{
2695 struct Scsi_Host *shost = class_to_shost(cdev);
2696 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2697
2698 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardName);
2699}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002700static DEVICE_ATTR_RO(board_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302701
2702/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002703 * board_assembly_show - board assembly name
Bart Van Assche4beb4862018-06-15 14:42:01 -07002704 * @cdev: pointer to embedded class device
2705 * @attr: ?
2706 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302707 *
2708 * A sysfs 'read-only' shost attribute.
2709 */
2710static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002711board_assembly_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302712 char *buf)
2713{
2714 struct Scsi_Host *shost = class_to_shost(cdev);
2715 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2716
2717 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardAssembly);
2718}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002719static DEVICE_ATTR_RO(board_assembly);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302720
2721/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002722 * board_tracer_show - board tracer number
Bart Van Assche4beb4862018-06-15 14:42:01 -07002723 * @cdev: pointer to embedded class device
2724 * @attr: ?
2725 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302726 *
2727 * A sysfs 'read-only' shost attribute.
2728 */
2729static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002730board_tracer_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302731 char *buf)
2732{
2733 struct Scsi_Host *shost = class_to_shost(cdev);
2734 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2735
2736 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardTracerNumber);
2737}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002738static DEVICE_ATTR_RO(board_tracer);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302739
2740/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002741 * io_delay_show - io missing delay
Bart Van Assche4beb4862018-06-15 14:42:01 -07002742 * @cdev: pointer to embedded class device
2743 * @attr: ?
2744 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302745 *
2746 * This is for firmware implemention for deboucing device
2747 * removal events.
2748 *
2749 * A sysfs 'read-only' shost attribute.
2750 */
2751static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002752io_delay_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302753 char *buf)
2754{
2755 struct Scsi_Host *shost = class_to_shost(cdev);
2756 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2757
2758 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
2759}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002760static DEVICE_ATTR_RO(io_delay);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302761
2762/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002763 * device_delay_show - device missing delay
Bart Van Assche4beb4862018-06-15 14:42:01 -07002764 * @cdev: pointer to embedded class device
2765 * @attr: ?
2766 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302767 *
2768 * This is for firmware implemention for deboucing device
2769 * removal events.
2770 *
2771 * A sysfs 'read-only' shost attribute.
2772 */
2773static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002774device_delay_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302775 char *buf)
2776{
2777 struct Scsi_Host *shost = class_to_shost(cdev);
2778 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2779
2780 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
2781}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002782static DEVICE_ATTR_RO(device_delay);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302783
2784/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002785 * fw_queue_depth_show - global credits
Bart Van Assche4beb4862018-06-15 14:42:01 -07002786 * @cdev: pointer to embedded class device
2787 * @attr: ?
2788 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302789 *
2790 * This is firmware queue depth limit
2791 *
2792 * A sysfs 'read-only' shost attribute.
2793 */
2794static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002795fw_queue_depth_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302796 char *buf)
2797{
2798 struct Scsi_Host *shost = class_to_shost(cdev);
2799 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2800
2801 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->facts.RequestCredit);
2802}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002803static DEVICE_ATTR_RO(fw_queue_depth);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302804
2805/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002806 * sas_address_show - sas address
Bart Van Assche4beb4862018-06-15 14:42:01 -07002807 * @cdev: pointer to embedded class device
2808 * @attr: ?
2809 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302810 *
2811 * This is the controller sas address
2812 *
2813 * A sysfs 'read-only' shost attribute.
2814 */
2815static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002816host_sas_address_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302817 char *buf)
2818
2819{
2820 struct Scsi_Host *shost = class_to_shost(cdev);
2821 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2822
2823 return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
2824 (unsigned long long)ioc->sas_hba.sas_address);
2825}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002826static DEVICE_ATTR_RO(host_sas_address);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302827
2828/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002829 * logging_level_show - logging level
Bart Van Assche4beb4862018-06-15 14:42:01 -07002830 * @cdev: pointer to embedded class device
2831 * @attr: ?
2832 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302833 *
2834 * A sysfs 'read/write' shost attribute.
2835 */
2836static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002837logging_level_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302838 char *buf)
2839{
2840 struct Scsi_Host *shost = class_to_shost(cdev);
2841 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2842
2843 return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->logging_level);
2844}
2845static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002846logging_level_store(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302847 const char *buf, size_t count)
2848{
2849 struct Scsi_Host *shost = class_to_shost(cdev);
2850 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2851 int val = 0;
2852
2853 if (sscanf(buf, "%x", &val) != 1)
2854 return -EINVAL;
2855
2856 ioc->logging_level = val;
Joe Perches919d8a32018-09-17 08:01:09 -07002857 ioc_info(ioc, "logging_level=%08xh\n",
2858 ioc->logging_level);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302859 return strlen(buf);
2860}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002861static DEVICE_ATTR_RW(logging_level);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302862
2863/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002864 * fwfault_debug_show - show/store fwfault_debug
Bart Van Assche4beb4862018-06-15 14:42:01 -07002865 * @cdev: pointer to embedded class device
2866 * @attr: ?
2867 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302868 *
2869 * mpt3sas_fwfault_debug is command line option
2870 * A sysfs 'read/write' shost attribute.
2871 */
2872static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002873fwfault_debug_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302874 char *buf)
2875{
2876 struct Scsi_Host *shost = class_to_shost(cdev);
2877 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2878
2879 return snprintf(buf, PAGE_SIZE, "%d\n", ioc->fwfault_debug);
2880}
2881static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002882fwfault_debug_store(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302883 const char *buf, size_t count)
2884{
2885 struct Scsi_Host *shost = class_to_shost(cdev);
2886 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2887 int val = 0;
2888
2889 if (sscanf(buf, "%d", &val) != 1)
2890 return -EINVAL;
2891
2892 ioc->fwfault_debug = val;
Joe Perches919d8a32018-09-17 08:01:09 -07002893 ioc_info(ioc, "fwfault_debug=%d\n",
2894 ioc->fwfault_debug);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302895 return strlen(buf);
2896}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002897static DEVICE_ATTR_RW(fwfault_debug);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302898
2899/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002900 * ioc_reset_count_show - ioc reset count
Bart Van Assche4beb4862018-06-15 14:42:01 -07002901 * @cdev: pointer to embedded class device
2902 * @attr: ?
2903 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302904 *
2905 * This is firmware queue depth limit
2906 *
2907 * A sysfs 'read-only' shost attribute.
2908 */
2909static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002910ioc_reset_count_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302911 char *buf)
2912{
2913 struct Scsi_Host *shost = class_to_shost(cdev);
2914 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2915
2916 return snprintf(buf, PAGE_SIZE, "%d\n", ioc->ioc_reset_count);
2917}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002918static DEVICE_ATTR_RO(ioc_reset_count);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302919
2920/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002921 * reply_queue_count_show - number of reply queues
Bart Van Assche4beb4862018-06-15 14:42:01 -07002922 * @cdev: pointer to embedded class device
2923 * @attr: ?
2924 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302925 *
2926 * This is number of reply queues
2927 *
2928 * A sysfs 'read-only' shost attribute.
2929 */
2930static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002931reply_queue_count_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302932 struct device_attribute *attr, char *buf)
2933{
2934 u8 reply_queue_count;
2935 struct Scsi_Host *shost = class_to_shost(cdev);
2936 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2937
2938 if ((ioc->facts.IOCCapabilities &
2939 MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable)
2940 reply_queue_count = ioc->reply_queue_count;
2941 else
2942 reply_queue_count = 1;
2943
2944 return snprintf(buf, PAGE_SIZE, "%d\n", reply_queue_count);
2945}
Tomas Henzlc9df1442019-06-14 16:41:44 +02002946static DEVICE_ATTR_RO(reply_queue_count);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302947
Sreekanth Reddy42263092015-11-11 17:30:29 +05302948/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02002949 * BRM_status_show - Backup Rail Monitor Status
Bart Van Assche4beb4862018-06-15 14:42:01 -07002950 * @cdev: pointer to embedded class device
2951 * @attr: ?
2952 * @buf: the buffer returned
Sreekanth Reddy42263092015-11-11 17:30:29 +05302953 *
2954 * This is number of reply queues
2955 *
2956 * A sysfs 'read-only' shost attribute.
2957 */
2958static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02002959BRM_status_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddy42263092015-11-11 17:30:29 +05302960 char *buf)
2961{
2962 struct Scsi_Host *shost = class_to_shost(cdev);
2963 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2964 Mpi2IOUnitPage3_t *io_unit_pg3 = NULL;
2965 Mpi2ConfigReply_t mpi_reply;
2966 u16 backup_rail_monitor_status = 0;
2967 u16 ioc_status;
2968 int sz;
2969 ssize_t rc = 0;
2970
2971 if (!ioc->is_warpdrive) {
Joe Perches919d8a32018-09-17 08:01:09 -07002972 ioc_err(ioc, "%s: BRM attribute is only for warpdrive\n",
2973 __func__);
Sreekanth Reddy42263092015-11-11 17:30:29 +05302974 goto out;
2975 }
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05302976 /* pci_access_mutex lock acquired by sysfs show path */
2977 mutex_lock(&ioc->pci_access_mutex);
2978 if (ioc->pci_error_recovery || ioc->remove_host) {
2979 mutex_unlock(&ioc->pci_access_mutex);
2980 return 0;
2981 }
Sreekanth Reddy42263092015-11-11 17:30:29 +05302982
2983 /* allocate upto GPIOVal 36 entries */
2984 sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36);
2985 io_unit_pg3 = kzalloc(sz, GFP_KERNEL);
2986 if (!io_unit_pg3) {
Joe Perches919d8a32018-09-17 08:01:09 -07002987 ioc_err(ioc, "%s: failed allocating memory for iounit_pg3: (%d) bytes\n",
2988 __func__, sz);
Sreekanth Reddy42263092015-11-11 17:30:29 +05302989 goto out;
2990 }
2991
2992 if (mpt3sas_config_get_iounit_pg3(ioc, &mpi_reply, io_unit_pg3, sz) !=
2993 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07002994 ioc_err(ioc, "%s: failed reading iounit_pg3\n",
2995 __func__);
Sreekanth Reddy42263092015-11-11 17:30:29 +05302996 goto out;
2997 }
2998
2999 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
3000 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
Joe Perches919d8a32018-09-17 08:01:09 -07003001 ioc_err(ioc, "%s: iounit_pg3 failed with ioc_status(0x%04x)\n",
3002 __func__, ioc_status);
Sreekanth Reddy42263092015-11-11 17:30:29 +05303003 goto out;
3004 }
3005
3006 if (io_unit_pg3->GPIOCount < 25) {
Joe Perches919d8a32018-09-17 08:01:09 -07003007 ioc_err(ioc, "%s: iounit_pg3->GPIOCount less than 25 entries, detected (%d) entries\n",
3008 __func__, io_unit_pg3->GPIOCount);
Sreekanth Reddy42263092015-11-11 17:30:29 +05303009 goto out;
3010 }
3011
3012 /* BRM status is in bit zero of GPIOVal[24] */
3013 backup_rail_monitor_status = le16_to_cpu(io_unit_pg3->GPIOVal[24]);
3014 rc = snprintf(buf, PAGE_SIZE, "%d\n", (backup_rail_monitor_status & 1));
3015
3016 out:
3017 kfree(io_unit_pg3);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05303018 mutex_unlock(&ioc->pci_access_mutex);
Sreekanth Reddy42263092015-11-11 17:30:29 +05303019 return rc;
3020}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003021static DEVICE_ATTR_RO(BRM_status);
Sreekanth Reddy42263092015-11-11 17:30:29 +05303022
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303023struct DIAG_BUFFER_START {
3024 __le32 Size;
3025 __le32 DiagVersion;
3026 u8 BufferType;
3027 u8 Reserved[3];
3028 __le32 Reserved1;
3029 __le32 Reserved2;
3030 __le32 Reserved3;
3031};
3032
3033/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003034 * host_trace_buffer_size_show - host buffer size (trace only)
Bart Van Assche4beb4862018-06-15 14:42:01 -07003035 * @cdev: pointer to embedded class device
3036 * @attr: ?
3037 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303038 *
3039 * A sysfs 'read-only' shost attribute.
3040 */
3041static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003042host_trace_buffer_size_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303043 struct device_attribute *attr, char *buf)
3044{
3045 struct Scsi_Host *shost = class_to_shost(cdev);
3046 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3047 u32 size = 0;
3048 struct DIAG_BUFFER_START *request_data;
3049
3050 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
Joe Perches919d8a32018-09-17 08:01:09 -07003051 ioc_err(ioc, "%s: host_trace_buffer is not registered\n",
3052 __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303053 return 0;
3054 }
3055
3056 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3057 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07003058 ioc_err(ioc, "%s: host_trace_buffer is not registered\n",
3059 __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303060 return 0;
3061 }
3062
3063 request_data = (struct DIAG_BUFFER_START *)
3064 ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE];
3065 if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 ||
3066 le32_to_cpu(request_data->DiagVersion) == 0x01000000 ||
3067 le32_to_cpu(request_data->DiagVersion) == 0x01010000) &&
3068 le32_to_cpu(request_data->Reserved3) == 0x4742444c)
3069 size = le32_to_cpu(request_data->Size);
3070
3071 ioc->ring_buffer_sz = size;
3072 return snprintf(buf, PAGE_SIZE, "%d\n", size);
3073}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003074static DEVICE_ATTR_RO(host_trace_buffer_size);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303075
3076/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003077 * host_trace_buffer_show - firmware ring buffer (trace only)
Bart Van Assche4beb4862018-06-15 14:42:01 -07003078 * @cdev: pointer to embedded class device
3079 * @attr: ?
3080 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303081 *
3082 * A sysfs 'read/write' shost attribute.
3083 *
3084 * You will only be able to read 4k bytes of ring buffer at a time.
3085 * In order to read beyond 4k bytes, you will have to write out the
3086 * offset to the same attribute, it will move the pointer.
3087 */
3088static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003089host_trace_buffer_show(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303090 char *buf)
3091{
3092 struct Scsi_Host *shost = class_to_shost(cdev);
3093 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3094 void *request_data;
3095 u32 size;
3096
3097 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
Joe Perches919d8a32018-09-17 08:01:09 -07003098 ioc_err(ioc, "%s: host_trace_buffer is not registered\n",
3099 __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303100 return 0;
3101 }
3102
3103 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3104 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
Joe Perches919d8a32018-09-17 08:01:09 -07003105 ioc_err(ioc, "%s: host_trace_buffer is not registered\n",
3106 __func__);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303107 return 0;
3108 }
3109
3110 if (ioc->ring_buffer_offset > ioc->ring_buffer_sz)
3111 return 0;
3112
3113 size = ioc->ring_buffer_sz - ioc->ring_buffer_offset;
3114 size = (size >= PAGE_SIZE) ? (PAGE_SIZE - 1) : size;
3115 request_data = ioc->diag_buffer[0] + ioc->ring_buffer_offset;
3116 memcpy(buf, request_data, size);
3117 return size;
3118}
3119
3120static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003121host_trace_buffer_store(struct device *cdev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303122 const char *buf, size_t count)
3123{
3124 struct Scsi_Host *shost = class_to_shost(cdev);
3125 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3126 int val = 0;
3127
3128 if (sscanf(buf, "%d", &val) != 1)
3129 return -EINVAL;
3130
3131 ioc->ring_buffer_offset = val;
3132 return strlen(buf);
3133}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003134static DEVICE_ATTR_RW(host_trace_buffer);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303135
3136
3137/*****************************************/
3138
3139/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003140 * host_trace_buffer_enable_show - firmware ring buffer (trace only)
Bart Van Assche4beb4862018-06-15 14:42:01 -07003141 * @cdev: pointer to embedded class device
3142 * @attr: ?
3143 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303144 *
3145 * A sysfs 'read/write' shost attribute.
3146 *
3147 * This is a mechnism to post/release host_trace_buffers
3148 */
3149static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003150host_trace_buffer_enable_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303151 struct device_attribute *attr, char *buf)
3152{
3153 struct Scsi_Host *shost = class_to_shost(cdev);
3154 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3155
3156 if ((!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) ||
3157 ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3158 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0))
3159 return snprintf(buf, PAGE_SIZE, "off\n");
3160 else if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3161 MPT3_DIAG_BUFFER_IS_RELEASED))
3162 return snprintf(buf, PAGE_SIZE, "release\n");
3163 else
3164 return snprintf(buf, PAGE_SIZE, "post\n");
3165}
3166
3167static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003168host_trace_buffer_enable_store(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303169 struct device_attribute *attr, const char *buf, size_t count)
3170{
3171 struct Scsi_Host *shost = class_to_shost(cdev);
3172 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3173 char str[10] = "";
3174 struct mpt3_diag_register diag_register;
3175 u8 issue_reset = 0;
3176
3177 /* don't allow post/release occurr while recovery is active */
3178 if (ioc->shost_recovery || ioc->remove_host ||
3179 ioc->pci_error_recovery || ioc->is_driver_loading)
3180 return -EBUSY;
3181
3182 if (sscanf(buf, "%9s", str) != 1)
3183 return -EINVAL;
3184
3185 if (!strcmp(str, "post")) {
3186 /* exit out if host buffers are already posted */
3187 if ((ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) &&
3188 (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3189 MPT3_DIAG_BUFFER_IS_REGISTERED) &&
3190 ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3191 MPT3_DIAG_BUFFER_IS_RELEASED) == 0))
3192 goto out;
3193 memset(&diag_register, 0, sizeof(struct mpt3_diag_register));
Joe Perches919d8a32018-09-17 08:01:09 -07003194 ioc_info(ioc, "posting host trace buffers\n");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303195 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
Sreekanth Reddyd04a6ed2019-09-13 09:04:38 -04003196
3197 if (ioc->manu_pg11.HostTraceBufferMaxSizeKB != 0 &&
3198 ioc->diag_buffer_sz[MPI2_DIAG_BUF_TYPE_TRACE] != 0) {
3199 /* post the same buffer allocated previously */
3200 diag_register.requested_buffer_size =
3201 ioc->diag_buffer_sz[MPI2_DIAG_BUF_TYPE_TRACE];
3202 } else
3203 diag_register.requested_buffer_size = (1024 * 1024);
3204
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303205 diag_register.unique_id = 0x7075900;
3206 ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0;
3207 _ctl_diag_register_2(ioc, &diag_register);
3208 } else if (!strcmp(str, "release")) {
3209 /* exit out if host buffers are already released */
3210 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE])
3211 goto out;
3212 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3213 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0)
3214 goto out;
3215 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
3216 MPT3_DIAG_BUFFER_IS_RELEASED))
3217 goto out;
Joe Perches919d8a32018-09-17 08:01:09 -07003218 ioc_info(ioc, "releasing host trace buffer\n");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303219 mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE,
3220 &issue_reset);
3221 }
3222
3223 out:
3224 return strlen(buf);
3225}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003226static DEVICE_ATTR_RW(host_trace_buffer_enable);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303227
3228/*********** diagnostic trigger suppport *********************************/
3229
3230/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003231 * diag_trigger_master_show - show the diag_trigger_master attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003232 * @cdev: pointer to embedded class device
3233 * @attr: ?
3234 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303235 *
3236 * A sysfs 'read/write' shost attribute.
3237 */
3238static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003239diag_trigger_master_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303240 struct device_attribute *attr, char *buf)
3241
3242{
3243 struct Scsi_Host *shost = class_to_shost(cdev);
3244 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3245 unsigned long flags;
3246 ssize_t rc;
3247
3248 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3249 rc = sizeof(struct SL_WH_MASTER_TRIGGER_T);
3250 memcpy(buf, &ioc->diag_trigger_master, rc);
3251 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3252 return rc;
3253}
3254
3255/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003256 * diag_trigger_master_store - store the diag_trigger_master attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003257 * @cdev: pointer to embedded class device
3258 * @attr: ?
3259 * @buf: the buffer returned
3260 * @count: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303261 *
3262 * A sysfs 'read/write' shost attribute.
3263 */
3264static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003265diag_trigger_master_store(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303266 struct device_attribute *attr, const char *buf, size_t count)
3267
3268{
3269 struct Scsi_Host *shost = class_to_shost(cdev);
3270 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3271 unsigned long flags;
3272 ssize_t rc;
3273
3274 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3275 rc = min(sizeof(struct SL_WH_MASTER_TRIGGER_T), count);
3276 memset(&ioc->diag_trigger_master, 0,
3277 sizeof(struct SL_WH_MASTER_TRIGGER_T));
3278 memcpy(&ioc->diag_trigger_master, buf, rc);
3279 ioc->diag_trigger_master.MasterData |=
3280 (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET);
3281 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3282 return rc;
3283}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003284static DEVICE_ATTR_RW(diag_trigger_master);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303285
3286
3287/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003288 * diag_trigger_event_show - show the diag_trigger_event attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003289 * @cdev: pointer to embedded class device
3290 * @attr: ?
3291 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303292 *
3293 * A sysfs 'read/write' shost attribute.
3294 */
3295static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003296diag_trigger_event_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303297 struct device_attribute *attr, char *buf)
3298{
3299 struct Scsi_Host *shost = class_to_shost(cdev);
3300 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3301 unsigned long flags;
3302 ssize_t rc;
3303
3304 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3305 rc = sizeof(struct SL_WH_EVENT_TRIGGERS_T);
3306 memcpy(buf, &ioc->diag_trigger_event, rc);
3307 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3308 return rc;
3309}
3310
3311/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003312 * diag_trigger_event_store - store the diag_trigger_event attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003313 * @cdev: pointer to embedded class device
3314 * @attr: ?
3315 * @buf: the buffer returned
3316 * @count: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303317 *
3318 * A sysfs 'read/write' shost attribute.
3319 */
3320static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003321diag_trigger_event_store(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303322 struct device_attribute *attr, const char *buf, size_t count)
3323
3324{
3325 struct Scsi_Host *shost = class_to_shost(cdev);
3326 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3327 unsigned long flags;
3328 ssize_t sz;
3329
3330 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3331 sz = min(sizeof(struct SL_WH_EVENT_TRIGGERS_T), count);
3332 memset(&ioc->diag_trigger_event, 0,
3333 sizeof(struct SL_WH_EVENT_TRIGGERS_T));
3334 memcpy(&ioc->diag_trigger_event, buf, sz);
3335 if (ioc->diag_trigger_event.ValidEntries > NUM_VALID_ENTRIES)
3336 ioc->diag_trigger_event.ValidEntries = NUM_VALID_ENTRIES;
3337 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3338 return sz;
3339}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003340static DEVICE_ATTR_RW(diag_trigger_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303341
3342
3343/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003344 * diag_trigger_scsi_show - show the diag_trigger_scsi attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003345 * @cdev: pointer to embedded class device
3346 * @attr: ?
3347 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303348 *
3349 * A sysfs 'read/write' shost attribute.
3350 */
3351static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003352diag_trigger_scsi_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303353 struct device_attribute *attr, char *buf)
3354{
3355 struct Scsi_Host *shost = class_to_shost(cdev);
3356 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3357 unsigned long flags;
3358 ssize_t rc;
3359
3360 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3361 rc = sizeof(struct SL_WH_SCSI_TRIGGERS_T);
3362 memcpy(buf, &ioc->diag_trigger_scsi, rc);
3363 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3364 return rc;
3365}
3366
3367/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003368 * diag_trigger_scsi_store - store the diag_trigger_scsi attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003369 * @cdev: pointer to embedded class device
3370 * @attr: ?
3371 * @buf: the buffer returned
3372 * @count: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303373 *
3374 * A sysfs 'read/write' shost attribute.
3375 */
3376static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003377diag_trigger_scsi_store(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303378 struct device_attribute *attr, const char *buf, size_t count)
3379{
3380 struct Scsi_Host *shost = class_to_shost(cdev);
3381 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3382 unsigned long flags;
3383 ssize_t sz;
3384
3385 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
Dan Carpenter1de540a2019-07-26 09:52:05 +03003386 sz = min(sizeof(ioc->diag_trigger_scsi), count);
3387 memset(&ioc->diag_trigger_scsi, 0, sizeof(ioc->diag_trigger_scsi));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303388 memcpy(&ioc->diag_trigger_scsi, buf, sz);
3389 if (ioc->diag_trigger_scsi.ValidEntries > NUM_VALID_ENTRIES)
3390 ioc->diag_trigger_scsi.ValidEntries = NUM_VALID_ENTRIES;
3391 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3392 return sz;
3393}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003394static DEVICE_ATTR_RW(diag_trigger_scsi);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303395
3396
3397/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003398 * diag_trigger_scsi_show - show the diag_trigger_mpi attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003399 * @cdev: pointer to embedded class device
3400 * @attr: ?
3401 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303402 *
3403 * A sysfs 'read/write' shost attribute.
3404 */
3405static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003406diag_trigger_mpi_show(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303407 struct device_attribute *attr, char *buf)
3408{
3409 struct Scsi_Host *shost = class_to_shost(cdev);
3410 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3411 unsigned long flags;
3412 ssize_t rc;
3413
3414 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3415 rc = sizeof(struct SL_WH_MPI_TRIGGERS_T);
3416 memcpy(buf, &ioc->diag_trigger_mpi, rc);
3417 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3418 return rc;
3419}
3420
3421/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003422 * diag_trigger_mpi_store - store the diag_trigger_mpi attribute
Bart Van Assche4beb4862018-06-15 14:42:01 -07003423 * @cdev: pointer to embedded class device
3424 * @attr: ?
3425 * @buf: the buffer returned
3426 * @count: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303427 *
3428 * A sysfs 'read/write' shost attribute.
3429 */
3430static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003431diag_trigger_mpi_store(struct device *cdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303432 struct device_attribute *attr, const char *buf, size_t count)
3433{
3434 struct Scsi_Host *shost = class_to_shost(cdev);
3435 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3436 unsigned long flags;
3437 ssize_t sz;
3438
3439 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3440 sz = min(sizeof(struct SL_WH_MPI_TRIGGERS_T), count);
3441 memset(&ioc->diag_trigger_mpi, 0,
Dan Carpenter66331e82012-12-07 13:56:22 +03003442 sizeof(ioc->diag_trigger_mpi));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303443 memcpy(&ioc->diag_trigger_mpi, buf, sz);
3444 if (ioc->diag_trigger_mpi.ValidEntries > NUM_VALID_ENTRIES)
3445 ioc->diag_trigger_mpi.ValidEntries = NUM_VALID_ENTRIES;
3446 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3447 return sz;
3448}
3449
Tomas Henzlc9df1442019-06-14 16:41:44 +02003450static DEVICE_ATTR_RW(diag_trigger_mpi);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303451
3452/*********** diagnostic trigger suppport *** END ****************************/
3453
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303454/*****************************************/
3455
Suganath Prabu3ac8e472019-08-03 09:59:53 -04003456/**
3457 * drv_support_bitmap_show - driver supported feature bitmap
3458 * @cdev - pointer to embedded class device
3459 * @buf - the buffer returned
3460 *
3461 * A sysfs 'read-only' shost attribute.
3462 */
3463static ssize_t
3464drv_support_bitmap_show(struct device *cdev,
3465 struct device_attribute *attr, char *buf)
3466{
3467 struct Scsi_Host *shost = class_to_shost(cdev);
3468 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3469
3470 return snprintf(buf, PAGE_SIZE, "0x%08x\n", ioc->drv_support_bitmap);
3471}
3472static DEVICE_ATTR_RO(drv_support_bitmap);
3473
Sreekanth Reddy8dc8d292019-08-22 02:19:01 -04003474/**
3475 * enable_sdev_max_qd_show - display whether sdev max qd is enabled/disabled
3476 * @cdev - pointer to embedded class device
3477 * @buf - the buffer returned
3478 *
3479 * A sysfs read/write shost attribute. This attribute is used to set the
3480 * targets queue depth to HBA IO queue depth if this attribute is enabled.
3481 */
3482static ssize_t
3483enable_sdev_max_qd_show(struct device *cdev,
3484 struct device_attribute *attr, char *buf)
3485{
3486 struct Scsi_Host *shost = class_to_shost(cdev);
3487 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3488
3489 return snprintf(buf, PAGE_SIZE, "%d\n", ioc->enable_sdev_max_qd);
3490}
3491
3492/**
3493 * enable_sdev_max_qd_store - Enable/disable sdev max qd
3494 * @cdev - pointer to embedded class device
3495 * @buf - the buffer returned
3496 *
3497 * A sysfs read/write shost attribute. This attribute is used to set the
3498 * targets queue depth to HBA IO queue depth if this attribute is enabled.
3499 * If this attribute is disabled then targets will have corresponding default
3500 * queue depth.
3501 */
3502static ssize_t
3503enable_sdev_max_qd_store(struct device *cdev,
3504 struct device_attribute *attr, const char *buf, size_t count)
3505{
3506 struct Scsi_Host *shost = class_to_shost(cdev);
3507 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3508 struct MPT3SAS_DEVICE *sas_device_priv_data;
3509 struct MPT3SAS_TARGET *sas_target_priv_data;
3510 int val = 0;
3511 struct scsi_device *sdev;
3512 struct _raid_device *raid_device;
3513 int qdepth;
3514
3515 if (kstrtoint(buf, 0, &val) != 0)
3516 return -EINVAL;
3517
3518 switch (val) {
3519 case 0:
3520 ioc->enable_sdev_max_qd = 0;
3521 shost_for_each_device(sdev, ioc->shost) {
3522 sas_device_priv_data = sdev->hostdata;
3523 if (!sas_device_priv_data)
3524 continue;
3525 sas_target_priv_data = sas_device_priv_data->sas_target;
3526 if (!sas_target_priv_data)
3527 continue;
3528
3529 if (sas_target_priv_data->flags &
3530 MPT_TARGET_FLAGS_VOLUME) {
3531 raid_device =
3532 mpt3sas_raid_device_find_by_handle(ioc,
3533 sas_target_priv_data->handle);
3534
3535 switch (raid_device->volume_type) {
3536 case MPI2_RAID_VOL_TYPE_RAID0:
3537 if (raid_device->device_info &
3538 MPI2_SAS_DEVICE_INFO_SSP_TARGET)
3539 qdepth =
3540 MPT3SAS_SAS_QUEUE_DEPTH;
3541 else
3542 qdepth =
3543 MPT3SAS_SATA_QUEUE_DEPTH;
3544 break;
3545 case MPI2_RAID_VOL_TYPE_RAID1E:
3546 case MPI2_RAID_VOL_TYPE_RAID1:
3547 case MPI2_RAID_VOL_TYPE_RAID10:
3548 case MPI2_RAID_VOL_TYPE_UNKNOWN:
3549 default:
3550 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
3551 }
3552 } else if (sas_target_priv_data->flags &
3553 MPT_TARGET_FLAGS_PCIE_DEVICE)
3554 qdepth = MPT3SAS_NVME_QUEUE_DEPTH;
3555 else
3556 qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
3557
3558 mpt3sas_scsih_change_queue_depth(sdev, qdepth);
3559 }
3560 break;
3561 case 1:
3562 ioc->enable_sdev_max_qd = 1;
3563 shost_for_each_device(sdev, ioc->shost)
3564 mpt3sas_scsih_change_queue_depth(sdev,
3565 shost->can_queue);
3566 break;
3567 default:
3568 return -EINVAL;
3569 }
3570
3571 return strlen(buf);
3572}
3573static DEVICE_ATTR_RW(enable_sdev_max_qd);
3574
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303575struct device_attribute *mpt3sas_host_attrs[] = {
3576 &dev_attr_version_fw,
3577 &dev_attr_version_bios,
3578 &dev_attr_version_mpi,
3579 &dev_attr_version_product,
3580 &dev_attr_version_nvdata_persistent,
3581 &dev_attr_version_nvdata_default,
3582 &dev_attr_board_name,
3583 &dev_attr_board_assembly,
3584 &dev_attr_board_tracer,
3585 &dev_attr_io_delay,
3586 &dev_attr_device_delay,
3587 &dev_attr_logging_level,
3588 &dev_attr_fwfault_debug,
3589 &dev_attr_fw_queue_depth,
3590 &dev_attr_host_sas_address,
3591 &dev_attr_ioc_reset_count,
3592 &dev_attr_host_trace_buffer_size,
3593 &dev_attr_host_trace_buffer,
3594 &dev_attr_host_trace_buffer_enable,
3595 &dev_attr_reply_queue_count,
3596 &dev_attr_diag_trigger_master,
3597 &dev_attr_diag_trigger_event,
3598 &dev_attr_diag_trigger_scsi,
3599 &dev_attr_diag_trigger_mpi,
Suganath Prabu3ac8e472019-08-03 09:59:53 -04003600 &dev_attr_drv_support_bitmap,
Sreekanth Reddy42263092015-11-11 17:30:29 +05303601 &dev_attr_BRM_status,
Sreekanth Reddy8dc8d292019-08-22 02:19:01 -04003602 &dev_attr_enable_sdev_max_qd,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303603 NULL,
3604};
3605
3606/* device attributes */
3607
3608/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003609 * sas_address_show - sas address
Bart Van Assche4beb4862018-06-15 14:42:01 -07003610 * @dev: pointer to embedded class device
3611 * @attr: ?
3612 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303613 *
3614 * This is the sas address for the target
3615 *
3616 * A sysfs 'read-only' shost attribute.
3617 */
3618static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003619sas_address_show(struct device *dev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303620 char *buf)
3621{
3622 struct scsi_device *sdev = to_scsi_device(dev);
3623 struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
3624
3625 return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
3626 (unsigned long long)sas_device_priv_data->sas_target->sas_address);
3627}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003628static DEVICE_ATTR_RO(sas_address);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303629
3630/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003631 * sas_device_handle_show - device handle
Bart Van Assche4beb4862018-06-15 14:42:01 -07003632 * @dev: pointer to embedded class device
3633 * @attr: ?
3634 * @buf: the buffer returned
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303635 *
3636 * This is the firmware assigned device handle
3637 *
3638 * A sysfs 'read-only' shost attribute.
3639 */
3640static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003641sas_device_handle_show(struct device *dev, struct device_attribute *attr,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303642 char *buf)
3643{
3644 struct scsi_device *sdev = to_scsi_device(dev);
3645 struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
3646
3647 return snprintf(buf, PAGE_SIZE, "0x%04x\n",
3648 sas_device_priv_data->sas_target->handle);
3649}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003650static DEVICE_ATTR_RO(sas_device_handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303651
Adam Manzanares307d9072016-12-12 16:31:40 -08003652/**
Tomas Henzlc9df1442019-06-14 16:41:44 +02003653 * sas_ncq_io_prio_show - send prioritized io commands to device
Bart Van Assche4beb4862018-06-15 14:42:01 -07003654 * @dev: pointer to embedded device
3655 * @attr: ?
3656 * @buf: the buffer returned
Adam Manzanares307d9072016-12-12 16:31:40 -08003657 *
3658 * A sysfs 'read/write' sdev attribute, only works with SATA
3659 */
3660static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003661sas_ncq_prio_enable_show(struct device *dev,
Adam Manzanares307d9072016-12-12 16:31:40 -08003662 struct device_attribute *attr, char *buf)
3663{
3664 struct scsi_device *sdev = to_scsi_device(dev);
3665 struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
3666
3667 return snprintf(buf, PAGE_SIZE, "%d\n",
3668 sas_device_priv_data->ncq_prio_enable);
3669}
3670
3671static ssize_t
Tomas Henzlc9df1442019-06-14 16:41:44 +02003672sas_ncq_prio_enable_store(struct device *dev,
Adam Manzanares307d9072016-12-12 16:31:40 -08003673 struct device_attribute *attr,
3674 const char *buf, size_t count)
3675{
3676 struct scsi_device *sdev = to_scsi_device(dev);
3677 struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
3678 bool ncq_prio_enable = 0;
3679
3680 if (kstrtobool(buf, &ncq_prio_enable))
3681 return -EINVAL;
3682
3683 if (!scsih_ncq_prio_supp(sdev))
3684 return -EINVAL;
3685
3686 sas_device_priv_data->ncq_prio_enable = ncq_prio_enable;
3687 return strlen(buf);
3688}
Tomas Henzlc9df1442019-06-14 16:41:44 +02003689static DEVICE_ATTR_RW(sas_ncq_prio_enable);
Adam Manzanares307d9072016-12-12 16:31:40 -08003690
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303691struct device_attribute *mpt3sas_dev_attrs[] = {
3692 &dev_attr_sas_address,
3693 &dev_attr_sas_device_handle,
Adam Manzanares307d9072016-12-12 16:31:40 -08003694 &dev_attr_sas_ncq_prio_enable,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303695 NULL,
3696};
3697
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303698/* file operations table for mpt3ctl device */
3699static const struct file_operations ctl_fops = {
3700 .owner = THIS_MODULE,
3701 .unlocked_ioctl = _ctl_ioctl,
3702 .poll = _ctl_poll,
3703 .fasync = _ctl_fasync,
3704#ifdef CONFIG_COMPAT
3705 .compat_ioctl = _ctl_ioctl_compat,
3706#endif
3707};
3708
3709/* file operations table for mpt2ctl device */
3710static const struct file_operations ctl_gen2_fops = {
3711 .owner = THIS_MODULE,
3712 .unlocked_ioctl = _ctl_mpt2_ioctl,
3713 .poll = _ctl_poll,
3714 .fasync = _ctl_fasync,
3715#ifdef CONFIG_COMPAT
3716 .compat_ioctl = _ctl_mpt2_ioctl_compat,
3717#endif
3718};
3719
3720static struct miscdevice ctl_dev = {
3721 .minor = MPT3SAS_MINOR,
3722 .name = MPT3SAS_DEV_NAME,
3723 .fops = &ctl_fops,
3724};
3725
3726static struct miscdevice gen2_ctl_dev = {
3727 .minor = MPT2SAS_MINOR,
3728 .name = MPT2SAS_DEV_NAME,
3729 .fops = &ctl_gen2_fops,
3730};
3731
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303732/**
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303733 * mpt3sas_ctl_init - main entry point for ctl.
Bart Van Assche4beb4862018-06-15 14:42:01 -07003734 * @hbas_to_enumerate: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303735 */
3736void
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303737mpt3sas_ctl_init(ushort hbas_to_enumerate)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303738{
3739 async_queue = NULL;
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303740
3741 /* Don't register mpt3ctl ioctl device if
3742 * hbas_to_enumarate is one.
3743 */
3744 if (hbas_to_enumerate != 1)
3745 if (misc_register(&ctl_dev) < 0)
3746 pr_err("%s can't register misc device [minor=%d]\n",
3747 MPT3SAS_DRIVER_NAME, MPT3SAS_MINOR);
3748
3749 /* Don't register mpt3ctl ioctl device if
3750 * hbas_to_enumarate is two.
3751 */
3752 if (hbas_to_enumerate != 2)
3753 if (misc_register(&gen2_ctl_dev) < 0)
3754 pr_err("%s can't register misc device [minor=%d]\n",
3755 MPT2SAS_DRIVER_NAME, MPT2SAS_MINOR);
3756
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303757 init_waitqueue_head(&ctl_poll_wait);
3758}
3759
3760/**
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303761 * mpt3sas_ctl_exit - exit point for ctl
Bart Van Assche4beb4862018-06-15 14:42:01 -07003762 * @hbas_to_enumerate: ?
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303763 */
3764void
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303765mpt3sas_ctl_exit(ushort hbas_to_enumerate)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303766{
3767 struct MPT3SAS_ADAPTER *ioc;
3768 int i;
3769
3770 list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
3771
3772 /* free memory associated to diag buffers */
3773 for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
3774 if (!ioc->diag_buffer[i])
3775 continue;
3776 if (!(ioc->diag_buffer_status[i] &
3777 MPT3_DIAG_BUFFER_IS_REGISTERED))
3778 continue;
3779 if ((ioc->diag_buffer_status[i] &
3780 MPT3_DIAG_BUFFER_IS_RELEASED))
3781 continue;
Christoph Hellwig1c2048b2018-10-11 09:35:25 +02003782 dma_free_coherent(&ioc->pdev->dev,
3783 ioc->diag_buffer_sz[i],
3784 ioc->diag_buffer[i],
3785 ioc->diag_buffer_dma[i]);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303786 ioc->diag_buffer[i] = NULL;
3787 ioc->diag_buffer_status[i] = 0;
3788 }
3789
3790 kfree(ioc->event_log);
3791 }
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303792 if (hbas_to_enumerate != 1)
3793 misc_deregister(&ctl_dev);
3794 if (hbas_to_enumerate != 2)
3795 misc_deregister(&gen2_ctl_dev);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303796}