blob: ce63a4a66706293f08932b379b05f14c0e50773c [file] [log] [blame]
Eric Moore635374e2009-03-09 01:21:12 -06001/*
2 * Management Module Support for MPT (Message Passing Technology) based
3 * controllers
4 *
5 * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.c
Kashyap, Desai31b7f2e2010-03-17 16:28:04 +05306 * Copyright (C) 2007-2010 LSI Corporation
Eric Moore635374e2009-03-09 01:21:12 -06007 * (mailto:DL-MPTFusionLinux@lsi.com)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * NO WARRANTY
20 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
21 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
22 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
23 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
24 * solely responsible for determining the appropriateness of using and
25 * distributing the Program and assumes all risks associated with its
26 * exercise of rights under this Agreement, including but not limited to
27 * the risks and costs of program errors, damage to or loss of data,
28 * programs or equipment, and unavailability or interruption of operations.
29
30 * DISCLAIMER OF LIABILITY
31 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
34 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
35 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
37 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
38
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
42 * USA.
43 */
44
45#include <linux/version.h>
46#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/smp_lock.h>
55#include <linux/compat.h>
56#include <linux/poll.h>
57
58#include <linux/io.h>
59#include <linux/uaccess.h>
60
61#include "mpt2sas_base.h"
62#include "mpt2sas_ctl.h"
63
64static struct fasync_struct *async_queue;
65static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
66
Eric Moore99bb2142009-04-21 15:42:13 -060067static int _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type,
68 u8 *issue_reset);
69
Eric Moore635374e2009-03-09 01:21:12 -060070/**
71 * enum block_state - blocking state
72 * @NON_BLOCKING: non blocking
73 * @BLOCKING: blocking
74 *
75 * These states are for ioctls that need to wait for a response
76 * from firmware, so they probably require sleep.
77 */
78enum block_state {
79 NON_BLOCKING,
80 BLOCKING,
81};
82
Kashyap, Desai7fbae672010-06-17 13:45:17 +053083/**
84 * _ctl_sas_device_find_by_handle - sas device search
85 * @ioc: per adapter object
86 * @handle: sas device handle (assigned by firmware)
87 * Context: Calling function should acquire ioc->sas_device_lock
88 *
89 * This searches for sas_device based on sas_address, then return sas_device
90 * object.
91 */
92static struct _sas_device *
93_ctl_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
94{
95 struct _sas_device *sas_device, *r;
96
97 r = NULL;
98 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
99 if (sas_device->handle != handle)
100 continue;
101 r = sas_device;
102 goto out;
103 }
104
105 out:
106 return r;
107}
108
Eric Moore635374e2009-03-09 01:21:12 -0600109#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
110/**
111 * _ctl_display_some_debug - debug routine
112 * @ioc: per adapter object
113 * @smid: system request message index
114 * @calling_function_name: string pass from calling function
115 * @mpi_reply: reply message frame
116 * Context: none.
117 *
118 * Function for displaying debug info helpfull when debugging issues
119 * in this module.
120 */
121static void
122_ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid,
123 char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
124{
125 Mpi2ConfigRequest_t *mpi_request;
126 char *desc = NULL;
127
128 if (!(ioc->logging_level & MPT_DEBUG_IOCTL))
129 return;
130
131 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
132 switch (mpi_request->Function) {
133 case MPI2_FUNCTION_SCSI_IO_REQUEST:
134 {
135 Mpi2SCSIIORequest_t *scsi_request =
136 (Mpi2SCSIIORequest_t *)mpi_request;
137
138 snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
139 "scsi_io, cmd(0x%02x), cdb_len(%d)",
140 scsi_request->CDB.CDB32[0],
141 le16_to_cpu(scsi_request->IoFlags) & 0xF);
142 desc = ioc->tmp_string;
143 break;
144 }
145 case MPI2_FUNCTION_SCSI_TASK_MGMT:
146 desc = "task_mgmt";
147 break;
148 case MPI2_FUNCTION_IOC_INIT:
149 desc = "ioc_init";
150 break;
151 case MPI2_FUNCTION_IOC_FACTS:
152 desc = "ioc_facts";
153 break;
154 case MPI2_FUNCTION_CONFIG:
155 {
156 Mpi2ConfigRequest_t *config_request =
157 (Mpi2ConfigRequest_t *)mpi_request;
158
159 snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
160 "config, type(0x%02x), ext_type(0x%02x), number(%d)",
161 (config_request->Header.PageType &
162 MPI2_CONFIG_PAGETYPE_MASK), config_request->ExtPageType,
163 config_request->Header.PageNumber);
164 desc = ioc->tmp_string;
165 break;
166 }
167 case MPI2_FUNCTION_PORT_FACTS:
168 desc = "port_facts";
169 break;
170 case MPI2_FUNCTION_PORT_ENABLE:
171 desc = "port_enable";
172 break;
173 case MPI2_FUNCTION_EVENT_NOTIFICATION:
174 desc = "event_notification";
175 break;
176 case MPI2_FUNCTION_FW_DOWNLOAD:
177 desc = "fw_download";
178 break;
179 case MPI2_FUNCTION_FW_UPLOAD:
180 desc = "fw_upload";
181 break;
182 case MPI2_FUNCTION_RAID_ACTION:
183 desc = "raid_action";
184 break;
185 case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
186 {
187 Mpi2SCSIIORequest_t *scsi_request =
188 (Mpi2SCSIIORequest_t *)mpi_request;
189
190 snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
191 "raid_pass, cmd(0x%02x), cdb_len(%d)",
192 scsi_request->CDB.CDB32[0],
193 le16_to_cpu(scsi_request->IoFlags) & 0xF);
194 desc = ioc->tmp_string;
195 break;
196 }
197 case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
198 desc = "sas_iounit_cntl";
199 break;
200 case MPI2_FUNCTION_SATA_PASSTHROUGH:
201 desc = "sata_pass";
202 break;
203 case MPI2_FUNCTION_DIAG_BUFFER_POST:
204 desc = "diag_buffer_post";
205 break;
206 case MPI2_FUNCTION_DIAG_RELEASE:
207 desc = "diag_release";
208 break;
209 case MPI2_FUNCTION_SMP_PASSTHROUGH:
210 desc = "smp_passthrough";
211 break;
212 }
213
214 if (!desc)
215 return;
216
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530217 printk(MPT2SAS_INFO_FMT "%s: %s, smid(%d)\n",
Eric Moore635374e2009-03-09 01:21:12 -0600218 ioc->name, calling_function_name, desc, smid);
219
220 if (!mpi_reply)
221 return;
222
223 if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530224 printk(MPT2SAS_INFO_FMT
Eric Moore635374e2009-03-09 01:21:12 -0600225 "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
226 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
227 le32_to_cpu(mpi_reply->IOCLogInfo));
228
229 if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
230 mpi_request->Function ==
231 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
232 Mpi2SCSIIOReply_t *scsi_reply =
233 (Mpi2SCSIIOReply_t *)mpi_reply;
Kashyap, Desai7fbae672010-06-17 13:45:17 +0530234 struct _sas_device *sas_device = NULL;
235 unsigned long flags;
236
237 spin_lock_irqsave(&ioc->sas_device_lock, flags);
238 sas_device = _ctl_sas_device_find_by_handle(ioc,
239 le16_to_cpu(scsi_reply->DevHandle));
240 if (sas_device) {
241 printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), "
242 "phy(%d)\n", ioc->name, (unsigned long long)
243 sas_device->sas_address, sas_device->phy);
244 printk(MPT2SAS_WARN_FMT
245 "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
246 ioc->name, sas_device->enclosure_logical_id,
247 sas_device->slot);
248 }
249 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -0600250 if (scsi_reply->SCSIState || scsi_reply->SCSIStatus)
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530251 printk(MPT2SAS_INFO_FMT
Eric Moore635374e2009-03-09 01:21:12 -0600252 "\tscsi_state(0x%02x), scsi_status"
253 "(0x%02x)\n", ioc->name,
254 scsi_reply->SCSIState,
255 scsi_reply->SCSIStatus);
256 }
257}
258#endif
259
260/**
261 * mpt2sas_ctl_done - ctl module completion routine
262 * @ioc: per adapter object
263 * @smid: system request message index
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530264 * @msix_index: MSIX table index supplied by the OS
Eric Moore635374e2009-03-09 01:21:12 -0600265 * @reply: reply message frame(lower 32bit addr)
266 * Context: none.
267 *
268 * The callback handler when using ioc->ctl_cb_idx.
269 *
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530270 * Return 1 meaning mf should be freed from _base_interrupt
271 * 0 means the mf is freed from this function.
Eric Moore635374e2009-03-09 01:21:12 -0600272 */
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530273u8
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530274mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
275 u32 reply)
Eric Moore635374e2009-03-09 01:21:12 -0600276{
277 MPI2DefaultReply_t *mpi_reply;
278
279 if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530280 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600281 if (ioc->ctl_cmds.smid != smid)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530282 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600283 ioc->ctl_cmds.status |= MPT2_CMD_COMPLETE;
284 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
285 if (mpi_reply) {
286 memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
287 ioc->ctl_cmds.status |= MPT2_CMD_REPLY_VALID;
288 }
289#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
290 _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply);
291#endif
292 ioc->ctl_cmds.status &= ~MPT2_CMD_PENDING;
293 complete(&ioc->ctl_cmds.done);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530294 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600295}
296
297/**
298 * _ctl_check_event_type - determines when an event needs logging
299 * @ioc: per adapter object
300 * @event: firmware event
301 *
302 * The bitmask in ioc->event_type[] indicates which events should be
303 * be saved in the driver event_log. This bitmask is set by application.
304 *
305 * Returns 1 when event should be captured, or zero means no match.
306 */
307static int
308_ctl_check_event_type(struct MPT2SAS_ADAPTER *ioc, u16 event)
309{
310 u16 i;
311 u32 desired_event;
312
313 if (event >= 128 || !event || !ioc->event_log)
314 return 0;
315
316 desired_event = (1 << (event % 32));
317 if (!desired_event)
318 desired_event = 1;
319 i = event / 32;
320 return desired_event & ioc->event_type[i];
321}
322
323/**
324 * mpt2sas_ctl_add_to_event_log - add event
325 * @ioc: per adapter object
326 * @mpi_reply: reply message frame
327 *
328 * Return nothing.
329 */
330void
331mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc,
332 Mpi2EventNotificationReply_t *mpi_reply)
333{
334 struct MPT2_IOCTL_EVENTS *event_log;
335 u16 event;
336 int i;
337 u32 sz, event_data_sz;
338 u8 send_aen = 0;
339
340 if (!ioc->event_log)
341 return;
342
343 event = le16_to_cpu(mpi_reply->Event);
344
345 if (_ctl_check_event_type(ioc, event)) {
346
347 /* insert entry into circular event_log */
348 i = ioc->event_context % MPT2SAS_CTL_EVENT_LOG_SIZE;
349 event_log = ioc->event_log;
350 event_log[i].event = event;
351 event_log[i].context = ioc->event_context++;
352
353 event_data_sz = le16_to_cpu(mpi_reply->EventDataLength)*4;
354 sz = min_t(u32, event_data_sz, MPT2_EVENT_DATA_SIZE);
355 memset(event_log[i].data, 0, MPT2_EVENT_DATA_SIZE);
356 memcpy(event_log[i].data, mpi_reply->EventData, sz);
357 send_aen = 1;
358 }
359
360 /* This aen_event_read_flag flag is set until the
361 * application has read the event log.
362 * For MPI2_EVENT_LOG_ENTRY_ADDED, we always notify.
363 */
364 if (event == MPI2_EVENT_LOG_ENTRY_ADDED ||
365 (send_aen && !ioc->aen_event_read_flag)) {
366 ioc->aen_event_read_flag = 1;
367 wake_up_interruptible(&ctl_poll_wait);
368 if (async_queue)
369 kill_fasync(&async_queue, SIGIO, POLL_IN);
370 }
371}
372
373/**
374 * mpt2sas_ctl_event_callback - firmware event handler (called at ISR time)
375 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530376 * @msix_index: MSIX table index supplied by the OS
Eric Moore635374e2009-03-09 01:21:12 -0600377 * @reply: reply message frame(lower 32bit addr)
378 * Context: interrupt.
379 *
380 * This function merely adds a new work task into ioc->firmware_event_thread.
381 * The tasks are worked from _firmware_event_work in user context.
382 *
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530383 * Return 1 meaning mf should be freed from _base_interrupt
384 * 0 means the mf is freed from this function.
Eric Moore635374e2009-03-09 01:21:12 -0600385 */
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530386u8
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530387mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
388 u32 reply)
Eric Moore635374e2009-03-09 01:21:12 -0600389{
390 Mpi2EventNotificationReply_t *mpi_reply;
391
392 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
393 mpt2sas_ctl_add_to_event_log(ioc, mpi_reply);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530394 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600395}
396
397/**
398 * _ctl_verify_adapter - validates ioc_number passed from application
399 * @ioc: per adapter object
400 * @iocpp: The ioc pointer is returned in this.
401 *
402 * Return (-1) means error, else ioc_number.
403 */
404static int
405_ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp)
406{
407 struct MPT2SAS_ADAPTER *ioc;
408
Eric Mooreba33fad2009-03-15 21:37:18 -0600409 list_for_each_entry(ioc, &mpt2sas_ioc_list, list) {
Eric Moore635374e2009-03-09 01:21:12 -0600410 if (ioc->id != ioc_number)
411 continue;
412 *iocpp = ioc;
413 return ioc_number;
414 }
415 *iocpp = NULL;
416 return -1;
417}
418
419/**
420 * mpt2sas_ctl_reset_handler - reset callback handler (for ctl)
421 * @ioc: per adapter object
422 * @reset_phase: phase
423 *
424 * The handler for doing any required cleanup or initialization.
425 *
426 * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
427 * MPT2_IOC_DONE_RESET
428 */
429void
430mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
431{
Eric Moore99bb2142009-04-21 15:42:13 -0600432 int i;
433 u8 issue_reset;
434
Eric Moore635374e2009-03-09 01:21:12 -0600435 switch (reset_phase) {
436 case MPT2_IOC_PRE_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530437 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Eric Moore635374e2009-03-09 01:21:12 -0600438 "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
Eric Moore99bb2142009-04-21 15:42:13 -0600439 for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
440 if (!(ioc->diag_buffer_status[i] &
441 MPT2_DIAG_BUFFER_IS_REGISTERED))
442 continue;
443 if ((ioc->diag_buffer_status[i] &
444 MPT2_DIAG_BUFFER_IS_RELEASED))
445 continue;
446 _ctl_send_release(ioc, i, &issue_reset);
447 }
Eric Moore635374e2009-03-09 01:21:12 -0600448 break;
449 case MPT2_IOC_AFTER_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530450 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Eric Moore635374e2009-03-09 01:21:12 -0600451 "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
452 if (ioc->ctl_cmds.status & MPT2_CMD_PENDING) {
453 ioc->ctl_cmds.status |= MPT2_CMD_RESET;
454 mpt2sas_base_free_smid(ioc, ioc->ctl_cmds.smid);
455 complete(&ioc->ctl_cmds.done);
456 }
457 break;
458 case MPT2_IOC_DONE_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530459 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Eric Moore635374e2009-03-09 01:21:12 -0600460 "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
Eric Moore99bb2142009-04-21 15:42:13 -0600461
462 for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
463 if (!(ioc->diag_buffer_status[i] &
464 MPT2_DIAG_BUFFER_IS_REGISTERED))
465 continue;
466 if ((ioc->diag_buffer_status[i] &
467 MPT2_DIAG_BUFFER_IS_RELEASED))
468 continue;
469 ioc->diag_buffer_status[i] |=
470 MPT2_DIAG_BUFFER_IS_DIAG_RESET;
471 }
Eric Moore635374e2009-03-09 01:21:12 -0600472 break;
473 }
474}
475
476/**
477 * _ctl_fasync -
478 * @fd -
479 * @filep -
480 * @mode -
481 *
482 * Called when application request fasyn callback handler.
483 */
484static int
485_ctl_fasync(int fd, struct file *filep, int mode)
486{
487 return fasync_helper(fd, filep, mode, &async_queue);
488}
489
490/**
491 * _ctl_release -
492 * @inode -
493 * @filep -
494 *
495 * Called when application releases the fasyn callback handler.
496 */
497static int
498_ctl_release(struct inode *inode, struct file *filep)
499{
500 return fasync_helper(-1, filep, 0, &async_queue);
501}
502
503/**
504 * _ctl_poll -
505 * @file -
506 * @wait -
507 *
508 */
509static unsigned int
510_ctl_poll(struct file *filep, poll_table *wait)
511{
512 struct MPT2SAS_ADAPTER *ioc;
513
514 poll_wait(filep, &ctl_poll_wait, wait);
515
Eric Mooreba33fad2009-03-15 21:37:18 -0600516 list_for_each_entry(ioc, &mpt2sas_ioc_list, list) {
Eric Moore635374e2009-03-09 01:21:12 -0600517 if (ioc->aen_event_read_flag)
518 return POLLIN | POLLRDNORM;
519 }
520 return 0;
521}
522
523/**
Eric Mooreddf59a32009-05-18 13:01:29 -0600524 * _ctl_set_task_mid - assign an active smid to tm request
Eric Moore635374e2009-03-09 01:21:12 -0600525 * @ioc: per adapter object
526 * @karg - (struct mpt2_ioctl_command)
527 * @tm_request - pointer to mf from user space
528 *
529 * Returns 0 when an smid if found, else fail.
530 * during failure, the reply frame is filled.
531 */
532static int
Eric Mooreddf59a32009-05-18 13:01:29 -0600533_ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg,
Eric Moore635374e2009-03-09 01:21:12 -0600534 Mpi2SCSITaskManagementRequest_t *tm_request)
535{
536 u8 found = 0;
537 u16 i;
538 u16 handle;
539 struct scsi_cmnd *scmd;
540 struct MPT2SAS_DEVICE *priv_data;
541 unsigned long flags;
542 Mpi2SCSITaskManagementReply_t *tm_reply;
543 u32 sz;
544 u32 lun;
Eric Mooreddf59a32009-05-18 13:01:29 -0600545 char *desc = NULL;
546
547 if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
548 desc = "abort_task";
549 else if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK)
550 desc = "query_task";
551 else
552 return 0;
Eric Moore635374e2009-03-09 01:21:12 -0600553
554 lun = scsilun_to_int((struct scsi_lun *)tm_request->LUN);
555
556 handle = le16_to_cpu(tm_request->DevHandle);
557 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530558 for (i = ioc->scsiio_depth; i && !found; i--) {
Eric Moore635374e2009-03-09 01:21:12 -0600559 scmd = ioc->scsi_lookup[i - 1].scmd;
560 if (scmd == NULL || scmd->device == NULL ||
561 scmd->device->hostdata == NULL)
562 continue;
563 if (lun != scmd->device->lun)
564 continue;
565 priv_data = scmd->device->hostdata;
566 if (priv_data->sas_target == NULL)
567 continue;
568 if (priv_data->sas_target->handle != handle)
569 continue;
570 tm_request->TaskMID = cpu_to_le16(ioc->scsi_lookup[i - 1].smid);
571 found = 1;
572 }
573 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
574
575 if (!found) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530576 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Eric Mooreddf59a32009-05-18 13:01:29 -0600577 "handle(0x%04x), lun(%d), no active mid!!\n", ioc->name,
Kashyap, Desaie94f6742010-03-17 16:24:52 +0530578 desc, le16_to_cpu(tm_request->DevHandle), lun));
Eric Moore635374e2009-03-09 01:21:12 -0600579 tm_reply = ioc->ctl_cmds.reply;
580 tm_reply->DevHandle = tm_request->DevHandle;
581 tm_reply->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
Eric Mooreddf59a32009-05-18 13:01:29 -0600582 tm_reply->TaskType = tm_request->TaskType;
Eric Moore635374e2009-03-09 01:21:12 -0600583 tm_reply->MsgLength = sizeof(Mpi2SCSITaskManagementReply_t)/4;
584 tm_reply->VP_ID = tm_request->VP_ID;
585 tm_reply->VF_ID = tm_request->VF_ID;
586 sz = min_t(u32, karg->max_reply_bytes, ioc->reply_sz);
587 if (copy_to_user(karg->reply_frame_buf_ptr, ioc->ctl_cmds.reply,
588 sz))
589 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
590 __LINE__, __func__);
591 return 1;
592 }
593
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530594 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Eric Mooreddf59a32009-05-18 13:01:29 -0600595 "handle(0x%04x), lun(%d), task_mid(%d)\n", ioc->name,
Kashyap, Desaie94f6742010-03-17 16:24:52 +0530596 desc, le16_to_cpu(tm_request->DevHandle), lun,
597 le16_to_cpu(tm_request->TaskMID)));
Eric Moore635374e2009-03-09 01:21:12 -0600598 return 0;
599}
600
601/**
602 * _ctl_do_mpt_command - main handler for MPT2COMMAND opcode
603 * @ioc: per adapter object
604 * @karg - (struct mpt2_ioctl_command)
605 * @mf - pointer to mf in user space
606 * @state - NON_BLOCKING or BLOCKING
607 */
608static long
609_ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
610 struct mpt2_ioctl_command karg, void __user *mf, enum block_state state)
611{
612 MPI2RequestHeader_t *mpi_request;
613 MPI2DefaultReply_t *mpi_reply;
614 u32 ioc_state;
615 u16 ioc_status;
616 u16 smid;
617 unsigned long timeout, timeleft;
618 u8 issue_reset;
619 u32 sz;
620 void *psge;
621 void *priv_sense = NULL;
622 void *data_out = NULL;
623 dma_addr_t data_out_dma;
624 size_t data_out_sz = 0;
625 void *data_in = NULL;
626 dma_addr_t data_in_dma;
627 size_t data_in_sz = 0;
628 u32 sgl_flags;
629 long ret;
630 u16 wait_state_count;
631
632 issue_reset = 0;
633
634 if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
635 return -EAGAIN;
636 else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
637 return -ERESTARTSYS;
638
639 if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
640 printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
641 ioc->name, __func__);
642 ret = -EAGAIN;
643 goto out;
644 }
645
646 wait_state_count = 0;
647 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
648 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
649 if (wait_state_count++ == 10) {
650 printk(MPT2SAS_ERR_FMT
651 "%s: failed due to ioc not operational\n",
652 ioc->name, __func__);
653 ret = -EFAULT;
654 goto out;
655 }
656 ssleep(1);
657 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
658 printk(MPT2SAS_INFO_FMT "%s: waiting for "
659 "operational state(count=%d)\n", ioc->name,
660 __func__, wait_state_count);
661 }
662 if (wait_state_count)
663 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
664 ioc->name, __func__);
665
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530666 smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL);
Eric Moore635374e2009-03-09 01:21:12 -0600667 if (!smid) {
668 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
669 ioc->name, __func__);
670 ret = -EAGAIN;
671 goto out;
672 }
673
674 ret = 0;
675 ioc->ctl_cmds.status = MPT2_CMD_PENDING;
676 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
677 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
678 ioc->ctl_cmds.smid = smid;
679 data_out_sz = karg.data_out_size;
680 data_in_sz = karg.data_in_size;
681
682 /* copy in request message frame from user */
683 if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) {
684 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__,
685 __func__);
686 ret = -EFAULT;
687 mpt2sas_base_free_smid(ioc, smid);
688 goto out;
689 }
690
691 if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
692 mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
Kashyap, Desaie94f6742010-03-17 16:24:52 +0530693 if (!le16_to_cpu(mpi_request->FunctionDependent1) ||
694 le16_to_cpu(mpi_request->FunctionDependent1) >
695 ioc->facts.MaxDevHandle) {
Eric Moore635374e2009-03-09 01:21:12 -0600696 ret = -EINVAL;
697 mpt2sas_base_free_smid(ioc, smid);
698 goto out;
699 }
700 }
701
702 /* obtain dma-able memory for data transfer */
703 if (data_out_sz) /* WRITE */ {
704 data_out = pci_alloc_consistent(ioc->pdev, data_out_sz,
705 &data_out_dma);
706 if (!data_out) {
707 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
708 __LINE__, __func__);
709 ret = -ENOMEM;
710 mpt2sas_base_free_smid(ioc, smid);
711 goto out;
712 }
713 if (copy_from_user(data_out, karg.data_out_buf_ptr,
714 data_out_sz)) {
715 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
716 __LINE__, __func__);
717 ret = -EFAULT;
718 mpt2sas_base_free_smid(ioc, smid);
719 goto out;
720 }
721 }
722
723 if (data_in_sz) /* READ */ {
724 data_in = pci_alloc_consistent(ioc->pdev, data_in_sz,
725 &data_in_dma);
726 if (!data_in) {
727 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
728 __LINE__, __func__);
729 ret = -ENOMEM;
730 mpt2sas_base_free_smid(ioc, smid);
731 goto out;
732 }
733 }
734
735 /* add scatter gather elements */
736 psge = (void *)mpi_request + (karg.data_sge_offset*4);
737
738 if (!data_out_sz && !data_in_sz) {
739 mpt2sas_base_build_zero_len_sge(ioc, psge);
740 } else if (data_out_sz && data_in_sz) {
741 /* WRITE sgel first */
742 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
743 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
744 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
745 ioc->base_add_sg_single(psge, sgl_flags |
746 data_out_sz, data_out_dma);
747
748 /* incr sgel */
749 psge += ioc->sge_size;
750
751 /* READ sgel last */
752 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
753 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
754 MPI2_SGE_FLAGS_END_OF_LIST);
755 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
756 ioc->base_add_sg_single(psge, sgl_flags |
757 data_in_sz, data_in_dma);
758 } else if (data_out_sz) /* WRITE */ {
759 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
760 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
761 MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC);
762 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
763 ioc->base_add_sg_single(psge, sgl_flags |
764 data_out_sz, data_out_dma);
765 } else if (data_in_sz) /* READ */ {
766 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
767 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
768 MPI2_SGE_FLAGS_END_OF_LIST);
769 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
770 ioc->base_add_sg_single(psge, sgl_flags |
771 data_in_sz, data_in_dma);
772 }
773
774 /* send command to firmware */
775#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
776 _ctl_display_some_debug(ioc, smid, "ctl_request", NULL);
777#endif
778
779 switch (mpi_request->Function) {
780 case MPI2_FUNCTION_SCSI_IO_REQUEST:
781 case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
782 {
783 Mpi2SCSIIORequest_t *scsiio_request =
784 (Mpi2SCSIIORequest_t *)mpi_request;
785 scsiio_request->SenseBufferLowAddress =
Kashyap, Desaiec9472c2009-09-23 17:34:13 +0530786 mpt2sas_base_get_sense_buffer_dma(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -0600787 priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid);
788 memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE);
Kashyap, Desaiebda4d32010-04-05 14:19:21 +0530789 if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)
790 mpt2sas_base_put_smid_scsi_io(ioc, smid,
791 le16_to_cpu(mpi_request->FunctionDependent1));
792 else
793 mpt2sas_base_put_smid_default(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -0600794 break;
795 }
796 case MPI2_FUNCTION_SCSI_TASK_MGMT:
797 {
798 Mpi2SCSITaskManagementRequest_t *tm_request =
799 (Mpi2SCSITaskManagementRequest_t *)mpi_request;
800
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530801 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "TASK_MGMT: "
Kashyap, Desai8ed9a032010-03-17 16:25:59 +0530802 "handle(0x%04x), task_type(0x%02x)\n", ioc->name,
803 le16_to_cpu(tm_request->DevHandle), tm_request->TaskType));
804
Eric Moore635374e2009-03-09 01:21:12 -0600805 if (tm_request->TaskType ==
Eric Mooreddf59a32009-05-18 13:01:29 -0600806 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK ||
807 tm_request->TaskType ==
808 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) {
809 if (_ctl_set_task_mid(ioc, &karg, tm_request)) {
Eric Moore77bdd9e2009-04-21 15:39:24 -0600810 mpt2sas_base_free_smid(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -0600811 goto out;
Eric Moore77bdd9e2009-04-21 15:39:24 -0600812 }
Eric Moore635374e2009-03-09 01:21:12 -0600813 }
814
Eric Moore635374e2009-03-09 01:21:12 -0600815 mpt2sas_scsih_set_tm_flag(ioc, le16_to_cpu(
816 tm_request->DevHandle));
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530817 mpt2sas_base_put_smid_hi_priority(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -0600818 break;
819 }
820 case MPI2_FUNCTION_SMP_PASSTHROUGH:
821 {
822 Mpi2SmpPassthroughRequest_t *smp_request =
823 (Mpi2SmpPassthroughRequest_t *)mpi_request;
824 u8 *data;
825
826 /* ioc determines which port to use */
827 smp_request->PhysicalPort = 0xFF;
828 if (smp_request->PassthroughFlags &
829 MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE)
830 data = (u8 *)&smp_request->SGL;
831 else
832 data = data_out;
833
834 if (data[1] == 0x91 && (data[10] == 1 || data[10] == 2)) {
835 ioc->ioc_link_reset_in_progress = 1;
836 ioc->ignore_loginfos = 1;
837 }
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530838 mpt2sas_base_put_smid_default(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -0600839 break;
840 }
841 case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
842 {
843 Mpi2SasIoUnitControlRequest_t *sasiounit_request =
844 (Mpi2SasIoUnitControlRequest_t *)mpi_request;
845
846 if (sasiounit_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET
847 || sasiounit_request->Operation ==
848 MPI2_SAS_OP_PHY_LINK_RESET) {
849 ioc->ioc_link_reset_in_progress = 1;
850 ioc->ignore_loginfos = 1;
851 }
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530852 mpt2sas_base_put_smid_default(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -0600853 break;
854 }
855 default:
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530856 mpt2sas_base_put_smid_default(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -0600857 break;
858 }
859
860 if (karg.timeout < MPT2_IOCTL_DEFAULT_TIMEOUT)
861 timeout = MPT2_IOCTL_DEFAULT_TIMEOUT;
862 else
863 timeout = karg.timeout;
Kashyap, Desaibcfb6e62009-09-14 11:05:24 +0530864 init_completion(&ioc->ctl_cmds.done);
Eric Moore635374e2009-03-09 01:21:12 -0600865 timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
866 timeout*HZ);
867 if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
868 Mpi2SCSITaskManagementRequest_t *tm_request =
869 (Mpi2SCSITaskManagementRequest_t *)mpi_request;
Eric Moore635374e2009-03-09 01:21:12 -0600870 mpt2sas_scsih_clear_tm_flag(ioc, le16_to_cpu(
871 tm_request->DevHandle));
872 } else if ((mpi_request->Function == MPI2_FUNCTION_SMP_PASSTHROUGH ||
873 mpi_request->Function == MPI2_FUNCTION_SAS_IO_UNIT_CONTROL) &&
874 ioc->ioc_link_reset_in_progress) {
875 ioc->ioc_link_reset_in_progress = 0;
876 ioc->ignore_loginfos = 0;
877 }
878 if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
879 printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
880 __func__);
881 _debug_dump_mf(mpi_request, karg.data_sge_offset);
882 if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
883 issue_reset = 1;
884 goto issue_host_reset;
885 }
886
887 mpi_reply = ioc->ctl_cmds.reply;
888 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
889
890#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
891 if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT &&
892 (ioc->logging_level & MPT_DEBUG_TM)) {
893 Mpi2SCSITaskManagementReply_t *tm_reply =
894 (Mpi2SCSITaskManagementReply_t *)mpi_reply;
895
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530896 printk(MPT2SAS_INFO_FMT "TASK_MGMT: "
Eric Moore635374e2009-03-09 01:21:12 -0600897 "IOCStatus(0x%04x), IOCLogInfo(0x%08x), "
898 "TerminationCount(0x%08x)\n", ioc->name,
Kashyap, Desai463217b2009-10-05 15:53:06 +0530899 le16_to_cpu(tm_reply->IOCStatus),
900 le32_to_cpu(tm_reply->IOCLogInfo),
901 le32_to_cpu(tm_reply->TerminationCount));
Eric Moore635374e2009-03-09 01:21:12 -0600902 }
903#endif
904 /* copy out xdata to user */
905 if (data_in_sz) {
906 if (copy_to_user(karg.data_in_buf_ptr, data_in,
907 data_in_sz)) {
908 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
909 __LINE__, __func__);
910 ret = -ENODATA;
911 goto out;
912 }
913 }
914
915 /* copy out reply message frame to user */
916 if (karg.max_reply_bytes) {
917 sz = min_t(u32, karg.max_reply_bytes, ioc->reply_sz);
918 if (copy_to_user(karg.reply_frame_buf_ptr, ioc->ctl_cmds.reply,
919 sz)) {
920 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
921 __LINE__, __func__);
922 ret = -ENODATA;
923 goto out;
924 }
925 }
926
927 /* copy out sense to user */
928 if (karg.max_sense_bytes && (mpi_request->Function ==
929 MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function ==
930 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
931 sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE);
932 if (copy_to_user(karg.sense_data_ptr, priv_sense, sz)) {
933 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
934 __LINE__, __func__);
935 ret = -ENODATA;
936 goto out;
937 }
938 }
939
940 issue_host_reset:
941 if (issue_reset) {
Kashyap, Desaib2ff36b2009-12-16 18:51:05 +0530942 ret = -ENODATA;
Eric Moore635374e2009-03-09 01:21:12 -0600943 if ((mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
944 mpi_request->Function ==
945 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
946 printk(MPT2SAS_INFO_FMT "issue target reset: handle "
947 "= (0x%04x)\n", ioc->name,
Kashyap, Desaie94f6742010-03-17 16:24:52 +0530948 le16_to_cpu(mpi_request->FunctionDependent1));
Kashyap, Desaifa7f3162009-09-23 17:26:58 +0530949 mpt2sas_halt_firmware(ioc);
Eric Moore635374e2009-03-09 01:21:12 -0600950 mpt2sas_scsih_issue_tm(ioc,
Kashyap, Desai8ed9a032010-03-17 16:25:59 +0530951 le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
952 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10,
953 NULL);
Eric Moore635374e2009-03-09 01:21:12 -0600954 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
Eric Moore635374e2009-03-09 01:21:12 -0600955 } else
956 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
957 FORCE_BIG_HAMMER);
958 }
959
960 out:
961
962 /* free memory associated with sg buffers */
963 if (data_in)
964 pci_free_consistent(ioc->pdev, data_in_sz, data_in,
965 data_in_dma);
966
967 if (data_out)
968 pci_free_consistent(ioc->pdev, data_out_sz, data_out,
969 data_out_dma);
970
971 ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
972 mutex_unlock(&ioc->ctl_cmds.mutex);
973 return ret;
974}
975
976/**
977 * _ctl_getiocinfo - main handler for MPT2IOCINFO opcode
978 * @arg - user space buffer containing ioctl content
979 */
980static long
981_ctl_getiocinfo(void __user *arg)
982{
983 struct mpt2_ioctl_iocinfo karg;
984 struct MPT2SAS_ADAPTER *ioc;
985 u8 revision;
986
987 if (copy_from_user(&karg, arg, sizeof(karg))) {
988 printk(KERN_ERR "failure at %s:%d/%s()!\n",
989 __FILE__, __LINE__, __func__);
990 return -EFAULT;
991 }
992 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
993 return -ENODEV;
994
Kashyap, Desaieabb08a2010-06-17 13:43:57 +0530995 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -0600996 __func__));
997
998 memset(&karg, 0 , sizeof(karg));
999 karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2;
1000 if (ioc->pfacts)
1001 karg.port_number = ioc->pfacts[0].PortNumber;
1002 pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision);
1003 karg.hw_rev = revision;
1004 karg.pci_id = ioc->pdev->device;
1005 karg.subsystem_device = ioc->pdev->subsystem_device;
1006 karg.subsystem_vendor = ioc->pdev->subsystem_vendor;
1007 karg.pci_information.u.bits.bus = ioc->pdev->bus->number;
1008 karg.pci_information.u.bits.device = PCI_SLOT(ioc->pdev->devfn);
1009 karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn);
1010 karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus);
1011 karg.firmware_version = ioc->facts.FWVersion.Word;
Eric Mooree5f9bb12009-04-21 15:40:01 -06001012 strcpy(karg.driver_version, MPT2SAS_DRIVER_NAME);
1013 strcat(karg.driver_version, "-");
1014 strcat(karg.driver_version, MPT2SAS_DRIVER_VERSION);
Eric Moore635374e2009-03-09 01:21:12 -06001015 karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
1016
1017 if (copy_to_user(arg, &karg, sizeof(karg))) {
1018 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1019 __FILE__, __LINE__, __func__);
1020 return -EFAULT;
1021 }
1022 return 0;
1023}
1024
1025/**
1026 * _ctl_eventquery - main handler for MPT2EVENTQUERY opcode
1027 * @arg - user space buffer containing ioctl content
1028 */
1029static long
1030_ctl_eventquery(void __user *arg)
1031{
1032 struct mpt2_ioctl_eventquery karg;
1033 struct MPT2SAS_ADAPTER *ioc;
1034
1035 if (copy_from_user(&karg, arg, sizeof(karg))) {
1036 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1037 __FILE__, __LINE__, __func__);
1038 return -EFAULT;
1039 }
1040 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1041 return -ENODEV;
1042
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301043 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06001044 __func__));
1045
1046 karg.event_entries = MPT2SAS_CTL_EVENT_LOG_SIZE;
1047 memcpy(karg.event_types, ioc->event_type,
1048 MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
1049
1050 if (copy_to_user(arg, &karg, sizeof(karg))) {
1051 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1052 __FILE__, __LINE__, __func__);
1053 return -EFAULT;
1054 }
1055 return 0;
1056}
1057
1058/**
1059 * _ctl_eventenable - main handler for MPT2EVENTENABLE opcode
1060 * @arg - user space buffer containing ioctl content
1061 */
1062static long
1063_ctl_eventenable(void __user *arg)
1064{
1065 struct mpt2_ioctl_eventenable karg;
1066 struct MPT2SAS_ADAPTER *ioc;
1067
1068 if (copy_from_user(&karg, arg, sizeof(karg))) {
1069 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1070 __FILE__, __LINE__, __func__);
1071 return -EFAULT;
1072 }
1073 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1074 return -ENODEV;
1075
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301076 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06001077 __func__));
1078
1079 if (ioc->event_log)
1080 return 0;
1081 memcpy(ioc->event_type, karg.event_types,
1082 MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
1083 mpt2sas_base_validate_event_type(ioc, ioc->event_type);
1084
1085 /* initialize event_log */
1086 ioc->event_context = 0;
1087 ioc->aen_event_read_flag = 0;
1088 ioc->event_log = kcalloc(MPT2SAS_CTL_EVENT_LOG_SIZE,
1089 sizeof(struct MPT2_IOCTL_EVENTS), GFP_KERNEL);
1090 if (!ioc->event_log) {
1091 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1092 __FILE__, __LINE__, __func__);
1093 return -ENOMEM;
1094 }
1095 return 0;
1096}
1097
1098/**
1099 * _ctl_eventreport - main handler for MPT2EVENTREPORT opcode
1100 * @arg - user space buffer containing ioctl content
1101 */
1102static long
1103_ctl_eventreport(void __user *arg)
1104{
1105 struct mpt2_ioctl_eventreport karg;
1106 struct MPT2SAS_ADAPTER *ioc;
1107 u32 number_bytes, max_events, max;
1108 struct mpt2_ioctl_eventreport __user *uarg = arg;
1109
1110 if (copy_from_user(&karg, arg, sizeof(karg))) {
1111 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1112 __FILE__, __LINE__, __func__);
1113 return -EFAULT;
1114 }
1115 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1116 return -ENODEV;
1117
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301118 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06001119 __func__));
1120
1121 number_bytes = karg.hdr.max_data_size -
1122 sizeof(struct mpt2_ioctl_header);
1123 max_events = number_bytes/sizeof(struct MPT2_IOCTL_EVENTS);
1124 max = min_t(u32, MPT2SAS_CTL_EVENT_LOG_SIZE, max_events);
1125
1126 /* If fewer than 1 event is requested, there must have
1127 * been some type of error.
1128 */
1129 if (!max || !ioc->event_log)
1130 return -ENODATA;
1131
1132 number_bytes = max * sizeof(struct MPT2_IOCTL_EVENTS);
1133 if (copy_to_user(uarg->event_data, ioc->event_log, number_bytes)) {
1134 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1135 __FILE__, __LINE__, __func__);
1136 return -EFAULT;
1137 }
1138
1139 /* reset flag so SIGIO can restart */
1140 ioc->aen_event_read_flag = 0;
1141 return 0;
1142}
1143
1144/**
1145 * _ctl_do_reset - main handler for MPT2HARDRESET opcode
1146 * @arg - user space buffer containing ioctl content
1147 */
1148static long
1149_ctl_do_reset(void __user *arg)
1150{
1151 struct mpt2_ioctl_diag_reset karg;
1152 struct MPT2SAS_ADAPTER *ioc;
1153 int retval;
1154
1155 if (copy_from_user(&karg, arg, sizeof(karg))) {
1156 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1157 __FILE__, __LINE__, __func__);
1158 return -EFAULT;
1159 }
1160 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1161 return -ENODEV;
1162
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301163 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06001164 __func__));
1165
1166 retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1167 FORCE_BIG_HAMMER);
1168 printk(MPT2SAS_INFO_FMT "host reset: %s\n",
1169 ioc->name, ((!retval) ? "SUCCESS" : "FAILED"));
1170 return 0;
1171}
1172
1173/**
1174 * _ctl_btdh_search_sas_device - searching for sas device
1175 * @ioc: per adapter object
1176 * @btdh: btdh ioctl payload
1177 */
1178static int
1179_ctl_btdh_search_sas_device(struct MPT2SAS_ADAPTER *ioc,
1180 struct mpt2_ioctl_btdh_mapping *btdh)
1181{
1182 struct _sas_device *sas_device;
1183 unsigned long flags;
1184 int rc = 0;
1185
1186 if (list_empty(&ioc->sas_device_list))
1187 return rc;
1188
1189 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1190 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
1191 if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
1192 btdh->handle == sas_device->handle) {
1193 btdh->bus = sas_device->channel;
1194 btdh->id = sas_device->id;
1195 rc = 1;
1196 goto out;
1197 } else if (btdh->bus == sas_device->channel && btdh->id ==
1198 sas_device->id && btdh->handle == 0xFFFF) {
1199 btdh->handle = sas_device->handle;
1200 rc = 1;
1201 goto out;
1202 }
1203 }
1204 out:
1205 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1206 return rc;
1207}
1208
1209/**
1210 * _ctl_btdh_search_raid_device - searching for raid device
1211 * @ioc: per adapter object
1212 * @btdh: btdh ioctl payload
1213 */
1214static int
1215_ctl_btdh_search_raid_device(struct MPT2SAS_ADAPTER *ioc,
1216 struct mpt2_ioctl_btdh_mapping *btdh)
1217{
1218 struct _raid_device *raid_device;
1219 unsigned long flags;
1220 int rc = 0;
1221
1222 if (list_empty(&ioc->raid_device_list))
1223 return rc;
1224
1225 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1226 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
1227 if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
1228 btdh->handle == raid_device->handle) {
1229 btdh->bus = raid_device->channel;
1230 btdh->id = raid_device->id;
1231 rc = 1;
1232 goto out;
1233 } else if (btdh->bus == raid_device->channel && btdh->id ==
1234 raid_device->id && btdh->handle == 0xFFFF) {
1235 btdh->handle = raid_device->handle;
1236 rc = 1;
1237 goto out;
1238 }
1239 }
1240 out:
1241 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1242 return rc;
1243}
1244
1245/**
1246 * _ctl_btdh_mapping - main handler for MPT2BTDHMAPPING opcode
1247 * @arg - user space buffer containing ioctl content
1248 */
1249static long
1250_ctl_btdh_mapping(void __user *arg)
1251{
1252 struct mpt2_ioctl_btdh_mapping karg;
1253 struct MPT2SAS_ADAPTER *ioc;
1254 int rc;
1255
1256 if (copy_from_user(&karg, arg, sizeof(karg))) {
1257 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1258 __FILE__, __LINE__, __func__);
1259 return -EFAULT;
1260 }
1261 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1262 return -ENODEV;
1263
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301264 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06001265 __func__));
1266
1267 rc = _ctl_btdh_search_sas_device(ioc, &karg);
1268 if (!rc)
1269 _ctl_btdh_search_raid_device(ioc, &karg);
1270
1271 if (copy_to_user(arg, &karg, sizeof(karg))) {
1272 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1273 __FILE__, __LINE__, __func__);
1274 return -EFAULT;
1275 }
1276 return 0;
1277}
1278
1279/**
1280 * _ctl_diag_capability - return diag buffer capability
1281 * @ioc: per adapter object
Kashyap, Desai1b01fe32009-09-23 17:28:59 +05301282 * @buffer_type: specifies either TRACE, SNAPSHOT, or EXTENDED
Eric Moore635374e2009-03-09 01:21:12 -06001283 *
1284 * returns 1 when diag buffer support is enabled in firmware
1285 */
1286static u8
1287_ctl_diag_capability(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type)
1288{
1289 u8 rc = 0;
1290
1291 switch (buffer_type) {
1292 case MPI2_DIAG_BUF_TYPE_TRACE:
1293 if (ioc->facts.IOCCapabilities &
1294 MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER)
1295 rc = 1;
1296 break;
1297 case MPI2_DIAG_BUF_TYPE_SNAPSHOT:
1298 if (ioc->facts.IOCCapabilities &
1299 MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)
1300 rc = 1;
1301 break;
Kashyap, Desai1b01fe32009-09-23 17:28:59 +05301302 case MPI2_DIAG_BUF_TYPE_EXTENDED:
1303 if (ioc->facts.IOCCapabilities &
1304 MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER)
1305 rc = 1;
Eric Moore635374e2009-03-09 01:21:12 -06001306 }
1307
1308 return rc;
1309}
1310
1311/**
Kashyap, Desai32e0eb52009-09-23 17:28:09 +05301312 * _ctl_diag_register_2 - wrapper for registering diag buffer support
1313 * @ioc: per adapter object
1314 * @diag_register: the diag_register struct passed in from user space
Eric Moore635374e2009-03-09 01:21:12 -06001315 *
Eric Moore635374e2009-03-09 01:21:12 -06001316 */
1317static long
Kashyap, Desai32e0eb52009-09-23 17:28:09 +05301318_ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc,
1319 struct mpt2_diag_register *diag_register)
Eric Moore635374e2009-03-09 01:21:12 -06001320{
Eric Moore635374e2009-03-09 01:21:12 -06001321 int rc, i;
1322 void *request_data = NULL;
1323 dma_addr_t request_data_dma;
1324 u32 request_data_sz = 0;
1325 Mpi2DiagBufferPostRequest_t *mpi_request;
1326 Mpi2DiagBufferPostReply_t *mpi_reply;
1327 u8 buffer_type;
1328 unsigned long timeleft;
1329 u16 smid;
1330 u16 ioc_status;
1331 u8 issue_reset = 0;
1332
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301333 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06001334 __func__));
1335
Kashyap, Desai32e0eb52009-09-23 17:28:09 +05301336 if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
1337 printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
1338 ioc->name, __func__);
1339 rc = -EAGAIN;
1340 goto out;
1341 }
1342
1343 buffer_type = diag_register->buffer_type;
Eric Moore635374e2009-03-09 01:21:12 -06001344 if (!_ctl_diag_capability(ioc, buffer_type)) {
1345 printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
1346 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1347 return -EPERM;
1348 }
1349
1350 if (ioc->diag_buffer_status[buffer_type] &
1351 MPT2_DIAG_BUFFER_IS_REGISTERED) {
1352 printk(MPT2SAS_ERR_FMT "%s: already has a registered "
1353 "buffer for buffer_type(0x%02x)\n", ioc->name, __func__,
1354 buffer_type);
1355 return -EINVAL;
1356 }
1357
Kashyap, Desai32e0eb52009-09-23 17:28:09 +05301358 if (diag_register->requested_buffer_size % 4) {
Eric Moore635374e2009-03-09 01:21:12 -06001359 printk(MPT2SAS_ERR_FMT "%s: the requested_buffer_size "
1360 "is not 4 byte aligned\n", ioc->name, __func__);
1361 return -EINVAL;
1362 }
1363
Eric Moore635374e2009-03-09 01:21:12 -06001364 smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
1365 if (!smid) {
1366 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1367 ioc->name, __func__);
1368 rc = -EAGAIN;
1369 goto out;
1370 }
1371
1372 rc = 0;
1373 ioc->ctl_cmds.status = MPT2_CMD_PENDING;
1374 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
1375 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1376 ioc->ctl_cmds.smid = smid;
1377
1378 request_data = ioc->diag_buffer[buffer_type];
Kashyap, Desai32e0eb52009-09-23 17:28:09 +05301379 request_data_sz = diag_register->requested_buffer_size;
1380 ioc->unique_id[buffer_type] = diag_register->unique_id;
Eric Moore635374e2009-03-09 01:21:12 -06001381 ioc->diag_buffer_status[buffer_type] = 0;
Kashyap, Desai32e0eb52009-09-23 17:28:09 +05301382 memcpy(ioc->product_specific[buffer_type],
1383 diag_register->product_specific, MPT2_PRODUCT_SPECIFIC_DWORDS);
1384 ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags;
Eric Moore635374e2009-03-09 01:21:12 -06001385
1386 if (request_data) {
1387 request_data_dma = ioc->diag_buffer_dma[buffer_type];
1388 if (request_data_sz != ioc->diag_buffer_sz[buffer_type]) {
1389 pci_free_consistent(ioc->pdev,
1390 ioc->diag_buffer_sz[buffer_type],
1391 request_data, request_data_dma);
1392 request_data = NULL;
1393 }
1394 }
1395
1396 if (request_data == NULL) {
1397 ioc->diag_buffer_sz[buffer_type] = 0;
1398 ioc->diag_buffer_dma[buffer_type] = 0;
1399 request_data = pci_alloc_consistent(
1400 ioc->pdev, request_data_sz, &request_data_dma);
1401 if (request_data == NULL) {
1402 printk(MPT2SAS_ERR_FMT "%s: failed allocating memory"
1403 " for diag buffers, requested size(%d)\n",
1404 ioc->name, __func__, request_data_sz);
1405 mpt2sas_base_free_smid(ioc, smid);
1406 return -ENOMEM;
1407 }
1408 ioc->diag_buffer[buffer_type] = request_data;
1409 ioc->diag_buffer_sz[buffer_type] = request_data_sz;
1410 ioc->diag_buffer_dma[buffer_type] = request_data_dma;
1411 }
1412
1413 mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
Kashyap, Desai32e0eb52009-09-23 17:28:09 +05301414 mpi_request->BufferType = diag_register->buffer_type;
1415 mpi_request->Flags = cpu_to_le32(diag_register->diagnostic_flags);
Eric Moore635374e2009-03-09 01:21:12 -06001416 mpi_request->BufferAddress = cpu_to_le64(request_data_dma);
1417 mpi_request->BufferLength = cpu_to_le32(request_data_sz);
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301418 mpi_request->VF_ID = 0; /* TODO */
1419 mpi_request->VP_ID = 0;
Eric Moore635374e2009-03-09 01:21:12 -06001420
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301421 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(0x%p), "
Eric Moore635374e2009-03-09 01:21:12 -06001422 "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data,
Kashyap, Desaie94f6742010-03-17 16:24:52 +05301423 (unsigned long long)request_data_dma,
1424 le32_to_cpu(mpi_request->BufferLength)));
Eric Moore635374e2009-03-09 01:21:12 -06001425
1426 for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
1427 mpi_request->ProductSpecific[i] =
1428 cpu_to_le32(ioc->product_specific[buffer_type][i]);
1429
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301430 mpt2sas_base_put_smid_default(ioc, smid);
Kashyap, Desaibcfb6e62009-09-14 11:05:24 +05301431 init_completion(&ioc->ctl_cmds.done);
Eric Moore635374e2009-03-09 01:21:12 -06001432 timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
1433 MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
1434
1435 if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
1436 printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
1437 __func__);
1438 _debug_dump_mf(mpi_request,
1439 sizeof(Mpi2DiagBufferPostRequest_t)/4);
1440 if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
1441 issue_reset = 1;
1442 goto issue_host_reset;
1443 }
1444
1445 /* process the completed Reply Message Frame */
1446 if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
1447 printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
1448 ioc->name, __func__);
1449 rc = -EFAULT;
1450 goto out;
1451 }
1452
1453 mpi_reply = ioc->ctl_cmds.reply;
1454 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1455
1456 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
1457 ioc->diag_buffer_status[buffer_type] |=
1458 MPT2_DIAG_BUFFER_IS_REGISTERED;
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301459 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n",
Eric Moore635374e2009-03-09 01:21:12 -06001460 ioc->name, __func__));
1461 } else {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301462 printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) "
Eric Moore635374e2009-03-09 01:21:12 -06001463 "log_info(0x%08x)\n", ioc->name, __func__,
Kashyap, Desai463217b2009-10-05 15:53:06 +05301464 ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
Eric Moore635374e2009-03-09 01:21:12 -06001465 rc = -EFAULT;
1466 }
1467
1468 issue_host_reset:
1469 if (issue_reset)
1470 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1471 FORCE_BIG_HAMMER);
1472
1473 out:
1474
1475 if (rc && request_data)
1476 pci_free_consistent(ioc->pdev, request_data_sz,
1477 request_data, request_data_dma);
1478
1479 ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
Kashyap, Desai32e0eb52009-09-23 17:28:09 +05301480 return rc;
1481}
1482
1483/**
1484 * mpt2sas_enable_diag_buffer - enabling diag_buffers support driver load time
1485 * @ioc: per adapter object
1486 * @bits_to_register: bitwise field where trace is bit 0, and snapshot is bit 1
1487 *
1488 * This is called when command line option diag_buffer_enable is enabled
1489 * at driver load time.
1490 */
1491void
1492mpt2sas_enable_diag_buffer(struct MPT2SAS_ADAPTER *ioc, u8 bits_to_register)
1493{
1494 struct mpt2_diag_register diag_register;
1495
1496 memset(&diag_register, 0, sizeof(struct mpt2_diag_register));
1497
1498 if (bits_to_register & 1) {
1499 printk(MPT2SAS_INFO_FMT "registering trace buffer support\n",
1500 ioc->name);
1501 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
1502 /* register for 1MB buffers */
1503 diag_register.requested_buffer_size = (1024 * 1024);
1504 diag_register.unique_id = 0x7075900;
1505 _ctl_diag_register_2(ioc, &diag_register);
1506 }
1507
1508 if (bits_to_register & 2) {
1509 printk(MPT2SAS_INFO_FMT "registering snapshot buffer support\n",
1510 ioc->name);
1511 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_SNAPSHOT;
1512 /* register for 2MB buffers */
1513 diag_register.requested_buffer_size = 2 * (1024 * 1024);
1514 diag_register.unique_id = 0x7075901;
1515 _ctl_diag_register_2(ioc, &diag_register);
1516 }
Kashyap, Desai1b01fe32009-09-23 17:28:59 +05301517
1518 if (bits_to_register & 4) {
1519 printk(MPT2SAS_INFO_FMT "registering extended buffer support\n",
1520 ioc->name);
1521 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_EXTENDED;
1522 /* register for 2MB buffers */
1523 diag_register.requested_buffer_size = 2 * (1024 * 1024);
1524 diag_register.unique_id = 0x7075901;
1525 _ctl_diag_register_2(ioc, &diag_register);
1526 }
Kashyap, Desai32e0eb52009-09-23 17:28:09 +05301527}
1528
1529/**
1530 * _ctl_diag_register - application register with driver
1531 * @arg - user space buffer containing ioctl content
1532 * @state - NON_BLOCKING or BLOCKING
1533 *
1534 * This will allow the driver to setup any required buffers that will be
1535 * needed by firmware to communicate with the driver.
1536 */
1537static long
1538_ctl_diag_register(void __user *arg, enum block_state state)
1539{
1540 struct mpt2_diag_register karg;
1541 struct MPT2SAS_ADAPTER *ioc;
1542 long rc;
1543
1544 if (copy_from_user(&karg, arg, sizeof(karg))) {
1545 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1546 __FILE__, __LINE__, __func__);
1547 return -EFAULT;
1548 }
1549 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1550 return -ENODEV;
1551
1552 if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
1553 return -EAGAIN;
1554 else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
1555 return -ERESTARTSYS;
1556 rc = _ctl_diag_register_2(ioc, &karg);
Eric Moore635374e2009-03-09 01:21:12 -06001557 mutex_unlock(&ioc->ctl_cmds.mutex);
1558 return rc;
1559}
1560
1561/**
1562 * _ctl_diag_unregister - application unregister with driver
1563 * @arg - user space buffer containing ioctl content
1564 *
1565 * This will allow the driver to cleanup any memory allocated for diag
1566 * messages and to free up any resources.
1567 */
1568static long
1569_ctl_diag_unregister(void __user *arg)
1570{
1571 struct mpt2_diag_unregister karg;
1572 struct MPT2SAS_ADAPTER *ioc;
1573 void *request_data;
1574 dma_addr_t request_data_dma;
1575 u32 request_data_sz;
1576 u8 buffer_type;
1577
1578 if (copy_from_user(&karg, arg, sizeof(karg))) {
1579 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1580 __FILE__, __LINE__, __func__);
1581 return -EFAULT;
1582 }
1583 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1584 return -ENODEV;
1585
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301586 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06001587 __func__));
1588
1589 buffer_type = karg.unique_id & 0x000000ff;
1590 if (!_ctl_diag_capability(ioc, buffer_type)) {
1591 printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
1592 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1593 return -EPERM;
1594 }
1595
1596 if ((ioc->diag_buffer_status[buffer_type] &
1597 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
1598 printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
1599 "registered\n", ioc->name, __func__, buffer_type);
1600 return -EINVAL;
1601 }
1602 if ((ioc->diag_buffer_status[buffer_type] &
1603 MPT2_DIAG_BUFFER_IS_RELEASED) == 0) {
1604 printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) has not been "
1605 "released\n", ioc->name, __func__, buffer_type);
1606 return -EINVAL;
1607 }
1608
1609 if (karg.unique_id != ioc->unique_id[buffer_type]) {
1610 printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
1611 "registered\n", ioc->name, __func__, karg.unique_id);
1612 return -EINVAL;
1613 }
1614
1615 request_data = ioc->diag_buffer[buffer_type];
1616 if (!request_data) {
1617 printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for "
1618 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1619 return -ENOMEM;
1620 }
1621
1622 request_data_sz = ioc->diag_buffer_sz[buffer_type];
1623 request_data_dma = ioc->diag_buffer_dma[buffer_type];
1624 pci_free_consistent(ioc->pdev, request_data_sz,
1625 request_data, request_data_dma);
1626 ioc->diag_buffer[buffer_type] = NULL;
1627 ioc->diag_buffer_status[buffer_type] = 0;
1628 return 0;
1629}
1630
1631/**
1632 * _ctl_diag_query - query relevant info associated with diag buffers
1633 * @arg - user space buffer containing ioctl content
1634 *
1635 * The application will send only buffer_type and unique_id. Driver will
1636 * inspect unique_id first, if valid, fill in all the info. If unique_id is
1637 * 0x00, the driver will return info specified by Buffer Type.
1638 */
1639static long
1640_ctl_diag_query(void __user *arg)
1641{
1642 struct mpt2_diag_query karg;
1643 struct MPT2SAS_ADAPTER *ioc;
1644 void *request_data;
1645 int i;
1646 u8 buffer_type;
1647
1648 if (copy_from_user(&karg, arg, sizeof(karg))) {
1649 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1650 __FILE__, __LINE__, __func__);
1651 return -EFAULT;
1652 }
1653 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1654 return -ENODEV;
1655
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301656 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06001657 __func__));
1658
1659 karg.application_flags = 0;
1660 buffer_type = karg.buffer_type;
1661
1662 if (!_ctl_diag_capability(ioc, buffer_type)) {
1663 printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
1664 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1665 return -EPERM;
1666 }
1667
1668 if ((ioc->diag_buffer_status[buffer_type] &
1669 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
1670 printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
1671 "registered\n", ioc->name, __func__, buffer_type);
1672 return -EINVAL;
1673 }
1674
1675 if (karg.unique_id & 0xffffff00) {
1676 if (karg.unique_id != ioc->unique_id[buffer_type]) {
1677 printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
1678 "registered\n", ioc->name, __func__,
1679 karg.unique_id);
1680 return -EINVAL;
1681 }
1682 }
1683
1684 request_data = ioc->diag_buffer[buffer_type];
1685 if (!request_data) {
1686 printk(MPT2SAS_ERR_FMT "%s: doesn't have buffer for "
1687 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1688 return -ENOMEM;
1689 }
1690
1691 if (ioc->diag_buffer_status[buffer_type] & MPT2_DIAG_BUFFER_IS_RELEASED)
1692 karg.application_flags = (MPT2_APP_FLAGS_APP_OWNED |
1693 MPT2_APP_FLAGS_BUFFER_VALID);
1694 else
1695 karg.application_flags = (MPT2_APP_FLAGS_APP_OWNED |
1696 MPT2_APP_FLAGS_BUFFER_VALID |
1697 MPT2_APP_FLAGS_FW_BUFFER_ACCESS);
1698
1699 for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
1700 karg.product_specific[i] =
1701 ioc->product_specific[buffer_type][i];
1702
1703 karg.total_buffer_size = ioc->diag_buffer_sz[buffer_type];
1704 karg.driver_added_buffer_size = 0;
1705 karg.unique_id = ioc->unique_id[buffer_type];
1706 karg.diagnostic_flags = ioc->diagnostic_flags[buffer_type];
1707
1708 if (copy_to_user(arg, &karg, sizeof(struct mpt2_diag_query))) {
1709 printk(MPT2SAS_ERR_FMT "%s: unable to write mpt2_diag_query "
1710 "data @ %p\n", ioc->name, __func__, arg);
1711 return -EFAULT;
1712 }
1713 return 0;
1714}
1715
1716/**
Eric Moore99bb2142009-04-21 15:42:13 -06001717 * _ctl_send_release - Diag Release Message
1718 * @ioc: per adapter object
Kashyap, Desai1b01fe32009-09-23 17:28:59 +05301719 * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED
Eric Moore99bb2142009-04-21 15:42:13 -06001720 * @issue_reset - specifies whether host reset is required.
1721 *
1722 */
1723static int
1724_ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset)
1725{
1726 Mpi2DiagReleaseRequest_t *mpi_request;
1727 Mpi2DiagReleaseReply_t *mpi_reply;
1728 u16 smid;
1729 u16 ioc_status;
1730 u32 ioc_state;
1731 int rc;
1732 unsigned long timeleft;
1733
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301734 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore99bb2142009-04-21 15:42:13 -06001735 __func__));
1736
1737 rc = 0;
1738 *issue_reset = 0;
1739
1740 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1741 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301742 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Eric Moore99bb2142009-04-21 15:42:13 -06001743 "skipping due to FAULT state\n", ioc->name,
1744 __func__));
1745 rc = -EAGAIN;
1746 goto out;
1747 }
1748
1749 if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
1750 printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
1751 ioc->name, __func__);
1752 rc = -EAGAIN;
1753 goto out;
1754 }
1755
1756 smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
1757 if (!smid) {
1758 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1759 ioc->name, __func__);
1760 rc = -EAGAIN;
1761 goto out;
1762 }
1763
1764 ioc->ctl_cmds.status = MPT2_CMD_PENDING;
1765 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
1766 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1767 ioc->ctl_cmds.smid = smid;
1768
1769 mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE;
1770 mpi_request->BufferType = buffer_type;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301771 mpi_request->VF_ID = 0; /* TODO */
1772 mpi_request->VP_ID = 0;
Eric Moore99bb2142009-04-21 15:42:13 -06001773
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301774 mpt2sas_base_put_smid_default(ioc, smid);
Kashyap, Desaibcfb6e62009-09-14 11:05:24 +05301775 init_completion(&ioc->ctl_cmds.done);
Eric Moore99bb2142009-04-21 15:42:13 -06001776 timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
1777 MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
1778
1779 if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
1780 printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
1781 __func__);
1782 _debug_dump_mf(mpi_request,
1783 sizeof(Mpi2DiagReleaseRequest_t)/4);
1784 if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
1785 *issue_reset = 1;
1786 rc = -EFAULT;
1787 goto out;
1788 }
1789
1790 /* process the completed Reply Message Frame */
1791 if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
1792 printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
1793 ioc->name, __func__);
1794 rc = -EFAULT;
1795 goto out;
1796 }
1797
1798 mpi_reply = ioc->ctl_cmds.reply;
1799 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1800
1801 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
1802 ioc->diag_buffer_status[buffer_type] |=
1803 MPT2_DIAG_BUFFER_IS_RELEASED;
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301804 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n",
Eric Moore99bb2142009-04-21 15:42:13 -06001805 ioc->name, __func__));
1806 } else {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301807 printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) "
Eric Moore99bb2142009-04-21 15:42:13 -06001808 "log_info(0x%08x)\n", ioc->name, __func__,
Kashyap, Desai463217b2009-10-05 15:53:06 +05301809 ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
Eric Moore99bb2142009-04-21 15:42:13 -06001810 rc = -EFAULT;
1811 }
1812
1813 out:
1814 ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
1815 return rc;
1816}
1817
1818/**
Eric Moore635374e2009-03-09 01:21:12 -06001819 * _ctl_diag_release - request to send Diag Release Message to firmware
1820 * @arg - user space buffer containing ioctl content
1821 * @state - NON_BLOCKING or BLOCKING
1822 *
1823 * This allows ownership of the specified buffer to returned to the driver,
1824 * allowing an application to read the buffer without fear that firmware is
1825 * overwritting information in the buffer.
1826 */
1827static long
1828_ctl_diag_release(void __user *arg, enum block_state state)
1829{
1830 struct mpt2_diag_release karg;
1831 struct MPT2SAS_ADAPTER *ioc;
1832 void *request_data;
1833 int rc;
Eric Moore635374e2009-03-09 01:21:12 -06001834 u8 buffer_type;
Eric Moore635374e2009-03-09 01:21:12 -06001835 u8 issue_reset = 0;
1836
1837 if (copy_from_user(&karg, arg, sizeof(karg))) {
1838 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1839 __FILE__, __LINE__, __func__);
1840 return -EFAULT;
1841 }
1842 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1843 return -ENODEV;
1844
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301845 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06001846 __func__));
1847
1848 buffer_type = karg.unique_id & 0x000000ff;
1849 if (!_ctl_diag_capability(ioc, buffer_type)) {
1850 printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
1851 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1852 return -EPERM;
1853 }
1854
1855 if ((ioc->diag_buffer_status[buffer_type] &
1856 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
1857 printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
1858 "registered\n", ioc->name, __func__, buffer_type);
1859 return -EINVAL;
1860 }
1861
1862 if (karg.unique_id != ioc->unique_id[buffer_type]) {
1863 printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
1864 "registered\n", ioc->name, __func__, karg.unique_id);
1865 return -EINVAL;
1866 }
1867
1868 if (ioc->diag_buffer_status[buffer_type] &
1869 MPT2_DIAG_BUFFER_IS_RELEASED) {
1870 printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
1871 "is already released\n", ioc->name, __func__,
1872 buffer_type);
1873 return 0;
1874 }
1875
1876 request_data = ioc->diag_buffer[buffer_type];
1877
1878 if (!request_data) {
1879 printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for "
1880 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1881 return -ENOMEM;
1882 }
1883
Eric Moore99bb2142009-04-21 15:42:13 -06001884 /* buffers were released by due to host reset */
1885 if ((ioc->diag_buffer_status[buffer_type] &
1886 MPT2_DIAG_BUFFER_IS_DIAG_RESET)) {
1887 ioc->diag_buffer_status[buffer_type] |=
1888 MPT2_DIAG_BUFFER_IS_RELEASED;
1889 ioc->diag_buffer_status[buffer_type] &=
1890 ~MPT2_DIAG_BUFFER_IS_DIAG_RESET;
1891 printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
1892 "was released due to host reset\n", ioc->name, __func__,
1893 buffer_type);
1894 return 0;
1895 }
1896
Eric Moore635374e2009-03-09 01:21:12 -06001897 if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
1898 return -EAGAIN;
1899 else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
1900 return -ERESTARTSYS;
1901
Eric Moore99bb2142009-04-21 15:42:13 -06001902 rc = _ctl_send_release(ioc, buffer_type, &issue_reset);
Eric Moore635374e2009-03-09 01:21:12 -06001903
Eric Moore635374e2009-03-09 01:21:12 -06001904 if (issue_reset)
1905 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1906 FORCE_BIG_HAMMER);
1907
Eric Moore635374e2009-03-09 01:21:12 -06001908 mutex_unlock(&ioc->ctl_cmds.mutex);
1909 return rc;
1910}
1911
1912/**
1913 * _ctl_diag_read_buffer - request for copy of the diag buffer
1914 * @arg - user space buffer containing ioctl content
1915 * @state - NON_BLOCKING or BLOCKING
1916 */
1917static long
1918_ctl_diag_read_buffer(void __user *arg, enum block_state state)
1919{
1920 struct mpt2_diag_read_buffer karg;
1921 struct mpt2_diag_read_buffer __user *uarg = arg;
1922 struct MPT2SAS_ADAPTER *ioc;
1923 void *request_data, *diag_data;
1924 Mpi2DiagBufferPostRequest_t *mpi_request;
1925 Mpi2DiagBufferPostReply_t *mpi_reply;
1926 int rc, i;
1927 u8 buffer_type;
1928 unsigned long timeleft;
1929 u16 smid;
1930 u16 ioc_status;
1931 u8 issue_reset = 0;
1932
1933 if (copy_from_user(&karg, arg, sizeof(karg))) {
1934 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1935 __FILE__, __LINE__, __func__);
1936 return -EFAULT;
1937 }
1938 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1939 return -ENODEV;
1940
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301941 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06001942 __func__));
1943
1944 buffer_type = karg.unique_id & 0x000000ff;
1945 if (!_ctl_diag_capability(ioc, buffer_type)) {
1946 printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
1947 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1948 return -EPERM;
1949 }
1950
1951 if (karg.unique_id != ioc->unique_id[buffer_type]) {
1952 printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
1953 "registered\n", ioc->name, __func__, karg.unique_id);
1954 return -EINVAL;
1955 }
1956
1957 request_data = ioc->diag_buffer[buffer_type];
1958 if (!request_data) {
1959 printk(MPT2SAS_ERR_FMT "%s: doesn't have buffer for "
1960 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1961 return -ENOMEM;
1962 }
1963
1964 if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) {
1965 printk(MPT2SAS_ERR_FMT "%s: either the starting_offset "
1966 "or bytes_to_read are not 4 byte aligned\n", ioc->name,
1967 __func__);
1968 return -EINVAL;
1969 }
1970
1971 diag_data = (void *)(request_data + karg.starting_offset);
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301972 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), "
Eric Moore635374e2009-03-09 01:21:12 -06001973 "offset(%d), sz(%d)\n", ioc->name, __func__,
1974 diag_data, karg.starting_offset, karg.bytes_to_read));
1975
1976 if (copy_to_user((void __user *)uarg->diagnostic_data,
1977 diag_data, karg.bytes_to_read)) {
1978 printk(MPT2SAS_ERR_FMT "%s: Unable to write "
1979 "mpt_diag_read_buffer_t data @ %p\n", ioc->name,
1980 __func__, diag_data);
1981 return -EFAULT;
1982 }
1983
1984 if ((karg.flags & MPT2_FLAGS_REREGISTER) == 0)
1985 return 0;
1986
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301987 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: Reregister "
Eric Moore635374e2009-03-09 01:21:12 -06001988 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type));
1989 if ((ioc->diag_buffer_status[buffer_type] &
1990 MPT2_DIAG_BUFFER_IS_RELEASED) == 0) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301991 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Eric Moore635374e2009-03-09 01:21:12 -06001992 "buffer_type(0x%02x) is still registered\n", ioc->name,
1993 __func__, buffer_type));
1994 return 0;
1995 }
1996 /* Get a free request frame and save the message context.
1997 */
1998 if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
1999 return -EAGAIN;
2000 else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
2001 return -ERESTARTSYS;
2002
2003 if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
2004 printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
2005 ioc->name, __func__);
2006 rc = -EAGAIN;
2007 goto out;
2008 }
2009
2010 smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
2011 if (!smid) {
2012 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
2013 ioc->name, __func__);
2014 rc = -EAGAIN;
2015 goto out;
2016 }
2017
2018 rc = 0;
2019 ioc->ctl_cmds.status = MPT2_CMD_PENDING;
2020 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
2021 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
2022 ioc->ctl_cmds.smid = smid;
2023
2024 mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
2025 mpi_request->BufferType = buffer_type;
2026 mpi_request->BufferLength =
2027 cpu_to_le32(ioc->diag_buffer_sz[buffer_type]);
2028 mpi_request->BufferAddress =
2029 cpu_to_le64(ioc->diag_buffer_dma[buffer_type]);
2030 for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
2031 mpi_request->ProductSpecific[i] =
2032 cpu_to_le32(ioc->product_specific[buffer_type][i]);
Kashyap, Desai7b936b02009-09-25 11:44:41 +05302033 mpi_request->VF_ID = 0; /* TODO */
2034 mpi_request->VP_ID = 0;
Eric Moore635374e2009-03-09 01:21:12 -06002035
Kashyap, Desai7b936b02009-09-25 11:44:41 +05302036 mpt2sas_base_put_smid_default(ioc, smid);
Kashyap, Desaibcfb6e62009-09-14 11:05:24 +05302037 init_completion(&ioc->ctl_cmds.done);
Eric Moore635374e2009-03-09 01:21:12 -06002038 timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
2039 MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
2040
2041 if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
2042 printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
2043 __func__);
2044 _debug_dump_mf(mpi_request,
2045 sizeof(Mpi2DiagBufferPostRequest_t)/4);
2046 if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
2047 issue_reset = 1;
2048 goto issue_host_reset;
2049 }
2050
2051 /* process the completed Reply Message Frame */
2052 if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
2053 printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
2054 ioc->name, __func__);
2055 rc = -EFAULT;
2056 goto out;
2057 }
2058
2059 mpi_reply = ioc->ctl_cmds.reply;
2060 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
2061
2062 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
2063 ioc->diag_buffer_status[buffer_type] |=
2064 MPT2_DIAG_BUFFER_IS_REGISTERED;
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302065 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n",
Eric Moore635374e2009-03-09 01:21:12 -06002066 ioc->name, __func__));
2067 } else {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302068 printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) "
Eric Moore635374e2009-03-09 01:21:12 -06002069 "log_info(0x%08x)\n", ioc->name, __func__,
Kashyap, Desai463217b2009-10-05 15:53:06 +05302070 ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
Eric Moore635374e2009-03-09 01:21:12 -06002071 rc = -EFAULT;
2072 }
2073
2074 issue_host_reset:
2075 if (issue_reset)
2076 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2077 FORCE_BIG_HAMMER);
2078
2079 out:
2080
2081 ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
2082 mutex_unlock(&ioc->ctl_cmds.mutex);
2083 return rc;
2084}
2085
2086/**
2087 * _ctl_ioctl_main - main ioctl entry point
2088 * @file - (struct file)
2089 * @cmd - ioctl opcode
2090 * @arg -
2091 */
2092static long
2093_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg)
2094{
2095 enum block_state state;
2096 long ret = -EINVAL;
Eric Moore635374e2009-03-09 01:21:12 -06002097
2098 state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING :
2099 BLOCKING;
2100
2101 switch (cmd) {
2102 case MPT2IOCINFO:
2103 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_iocinfo))
2104 ret = _ctl_getiocinfo(arg);
2105 break;
2106 case MPT2COMMAND:
2107 {
2108 struct mpt2_ioctl_command karg;
2109 struct mpt2_ioctl_command __user *uarg;
2110 struct MPT2SAS_ADAPTER *ioc;
2111
2112 if (copy_from_user(&karg, arg, sizeof(karg))) {
2113 printk(KERN_ERR "failure at %s:%d/%s()!\n",
2114 __FILE__, __LINE__, __func__);
2115 return -EFAULT;
2116 }
2117
2118 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 ||
2119 !ioc)
2120 return -ENODEV;
2121
Kashyap, Desai155dd4c2009-08-20 13:22:00 +05302122 if (ioc->shost_recovery)
Eric Moore635374e2009-03-09 01:21:12 -06002123 return -EAGAIN;
Eric Moore635374e2009-03-09 01:21:12 -06002124
2125 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) {
2126 uarg = arg;
2127 ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf, state);
2128 }
2129 break;
2130 }
2131 case MPT2EVENTQUERY:
2132 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventquery))
2133 ret = _ctl_eventquery(arg);
2134 break;
2135 case MPT2EVENTENABLE:
2136 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventenable))
2137 ret = _ctl_eventenable(arg);
2138 break;
2139 case MPT2EVENTREPORT:
2140 ret = _ctl_eventreport(arg);
2141 break;
2142 case MPT2HARDRESET:
2143 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_diag_reset))
2144 ret = _ctl_do_reset(arg);
2145 break;
2146 case MPT2BTDHMAPPING:
2147 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_btdh_mapping))
2148 ret = _ctl_btdh_mapping(arg);
2149 break;
2150 case MPT2DIAGREGISTER:
2151 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_register))
2152 ret = _ctl_diag_register(arg, state);
2153 break;
2154 case MPT2DIAGUNREGISTER:
2155 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_unregister))
2156 ret = _ctl_diag_unregister(arg);
2157 break;
2158 case MPT2DIAGQUERY:
2159 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_query))
2160 ret = _ctl_diag_query(arg);
2161 break;
2162 case MPT2DIAGRELEASE:
2163 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_release))
2164 ret = _ctl_diag_release(arg, state);
2165 break;
2166 case MPT2DIAGREADBUFFER:
2167 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_read_buffer))
2168 ret = _ctl_diag_read_buffer(arg, state);
2169 break;
2170 default:
2171 {
2172 struct mpt2_ioctl_command karg;
2173 struct MPT2SAS_ADAPTER *ioc;
2174
2175 if (copy_from_user(&karg, arg, sizeof(karg))) {
2176 printk(KERN_ERR "failure at %s:%d/%s()!\n",
2177 __FILE__, __LINE__, __func__);
2178 return -EFAULT;
2179 }
2180
2181 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 ||
2182 !ioc)
2183 return -ENODEV;
2184
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302185 dctlprintk(ioc, printk(MPT2SAS_INFO_FMT
Eric Moore635374e2009-03-09 01:21:12 -06002186 "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd));
2187 break;
2188 }
2189 }
2190 return ret;
2191}
2192
2193/**
2194 * _ctl_ioctl - main ioctl entry point (unlocked)
2195 * @file - (struct file)
2196 * @cmd - ioctl opcode
2197 * @arg -
2198 */
2199static long
2200_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2201{
2202 long ret;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05302203
Eric Moore635374e2009-03-09 01:21:12 -06002204 lock_kernel();
2205 ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
2206 unlock_kernel();
2207 return ret;
2208}
2209
2210#ifdef CONFIG_COMPAT
2211/**
2212 * _ctl_compat_mpt_command - convert 32bit pointers to 64bit.
2213 * @file - (struct file)
2214 * @cmd - ioctl opcode
2215 * @arg - (struct mpt2_ioctl_command32)
2216 *
2217 * MPT2COMMAND32 - Handle 32bit applications running on 64bit os.
2218 */
2219static long
2220_ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg)
2221{
2222 struct mpt2_ioctl_command32 karg32;
2223 struct mpt2_ioctl_command32 __user *uarg;
2224 struct mpt2_ioctl_command karg;
2225 struct MPT2SAS_ADAPTER *ioc;
2226 enum block_state state;
Eric Moore635374e2009-03-09 01:21:12 -06002227
2228 if (_IOC_SIZE(cmd) != sizeof(struct mpt2_ioctl_command32))
2229 return -EINVAL;
2230
2231 uarg = (struct mpt2_ioctl_command32 __user *) arg;
2232
2233 if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) {
2234 printk(KERN_ERR "failure at %s:%d/%s()!\n",
2235 __FILE__, __LINE__, __func__);
2236 return -EFAULT;
2237 }
2238 if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc)
2239 return -ENODEV;
2240
Kashyap, Desai155dd4c2009-08-20 13:22:00 +05302241 if (ioc->shost_recovery)
Eric Moore635374e2009-03-09 01:21:12 -06002242 return -EAGAIN;
Eric Moore635374e2009-03-09 01:21:12 -06002243
2244 memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
2245 karg.hdr.ioc_number = karg32.hdr.ioc_number;
2246 karg.hdr.port_number = karg32.hdr.port_number;
2247 karg.hdr.max_data_size = karg32.hdr.max_data_size;
2248 karg.timeout = karg32.timeout;
2249 karg.max_reply_bytes = karg32.max_reply_bytes;
2250 karg.data_in_size = karg32.data_in_size;
2251 karg.data_out_size = karg32.data_out_size;
2252 karg.max_sense_bytes = karg32.max_sense_bytes;
2253 karg.data_sge_offset = karg32.data_sge_offset;
Kashyap, Desai22c88422009-12-16 18:53:04 +05302254 karg.reply_frame_buf_ptr = compat_ptr(karg32.reply_frame_buf_ptr);
2255 karg.data_in_buf_ptr = compat_ptr(karg32.data_in_buf_ptr);
2256 karg.data_out_buf_ptr = compat_ptr(karg32.data_out_buf_ptr);
2257 karg.sense_data_ptr = compat_ptr(karg32.sense_data_ptr);
Eric Moore635374e2009-03-09 01:21:12 -06002258 state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
2259 return _ctl_do_mpt_command(ioc, karg, &uarg->mf, state);
2260}
2261
2262/**
2263 * _ctl_ioctl_compat - main ioctl entry point (compat)
2264 * @file -
2265 * @cmd -
2266 * @arg -
2267 *
2268 * This routine handles 32 bit applications in 64bit os.
2269 */
2270static long
2271_ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
2272{
2273 long ret;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05302274
Eric Moore635374e2009-03-09 01:21:12 -06002275 lock_kernel();
2276 if (cmd == MPT2COMMAND32)
2277 ret = _ctl_compat_mpt_command(file, cmd, arg);
2278 else
2279 ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
2280 unlock_kernel();
2281 return ret;
2282}
2283#endif
2284
2285/* scsi host attributes */
2286
2287/**
2288 * _ctl_version_fw_show - firmware version
2289 * @cdev - pointer to embedded class device
2290 * @buf - the buffer returned
2291 *
2292 * A sysfs 'read-only' shost attribute.
2293 */
2294static ssize_t
2295_ctl_version_fw_show(struct device *cdev, struct device_attribute *attr,
2296 char *buf)
2297{
2298 struct Scsi_Host *shost = class_to_shost(cdev);
2299 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2300
2301 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
2302 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
2303 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
2304 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
2305 ioc->facts.FWVersion.Word & 0x000000FF);
2306}
2307static DEVICE_ATTR(version_fw, S_IRUGO, _ctl_version_fw_show, NULL);
2308
2309/**
2310 * _ctl_version_bios_show - bios version
2311 * @cdev - pointer to embedded class device
2312 * @buf - the buffer returned
2313 *
2314 * A sysfs 'read-only' shost attribute.
2315 */
2316static ssize_t
2317_ctl_version_bios_show(struct device *cdev, struct device_attribute *attr,
2318 char *buf)
2319{
2320 struct Scsi_Host *shost = class_to_shost(cdev);
2321 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2322
2323 u32 version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
2324
2325 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
2326 (version & 0xFF000000) >> 24,
2327 (version & 0x00FF0000) >> 16,
2328 (version & 0x0000FF00) >> 8,
2329 version & 0x000000FF);
2330}
2331static DEVICE_ATTR(version_bios, S_IRUGO, _ctl_version_bios_show, NULL);
2332
2333/**
2334 * _ctl_version_mpi_show - MPI (message passing interface) version
2335 * @cdev - pointer to embedded class device
2336 * @buf - the buffer returned
2337 *
2338 * A sysfs 'read-only' shost attribute.
2339 */
2340static ssize_t
2341_ctl_version_mpi_show(struct device *cdev, struct device_attribute *attr,
2342 char *buf)
2343{
2344 struct Scsi_Host *shost = class_to_shost(cdev);
2345 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2346
2347 return snprintf(buf, PAGE_SIZE, "%03x.%02x\n",
2348 ioc->facts.MsgVersion, ioc->facts.HeaderVersion >> 8);
2349}
2350static DEVICE_ATTR(version_mpi, S_IRUGO, _ctl_version_mpi_show, NULL);
2351
2352/**
2353 * _ctl_version_product_show - product name
2354 * @cdev - pointer to embedded class device
2355 * @buf - the buffer returned
2356 *
2357 * A sysfs 'read-only' shost attribute.
2358 */
2359static ssize_t
2360_ctl_version_product_show(struct device *cdev, struct device_attribute *attr,
2361 char *buf)
2362{
2363 struct Scsi_Host *shost = class_to_shost(cdev);
2364 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2365
2366 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.ChipName);
2367}
2368static DEVICE_ATTR(version_product, S_IRUGO,
2369 _ctl_version_product_show, NULL);
2370
2371/**
2372 * _ctl_version_nvdata_persistent_show - ndvata persistent version
2373 * @cdev - pointer to embedded class device
2374 * @buf - the buffer returned
2375 *
2376 * A sysfs 'read-only' shost attribute.
2377 */
2378static ssize_t
2379_ctl_version_nvdata_persistent_show(struct device *cdev,
2380 struct device_attribute *attr, char *buf)
2381{
2382 struct Scsi_Host *shost = class_to_shost(cdev);
2383 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2384
Kashyap, Desaie94f6742010-03-17 16:24:52 +05302385 return snprintf(buf, PAGE_SIZE, "%08xh\n",
2386 le32_to_cpu(ioc->iounit_pg0.NvdataVersionPersistent.Word));
Eric Moore635374e2009-03-09 01:21:12 -06002387}
2388static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
2389 _ctl_version_nvdata_persistent_show, NULL);
2390
2391/**
2392 * _ctl_version_nvdata_default_show - nvdata default version
2393 * @cdev - pointer to embedded class device
2394 * @buf - the buffer returned
2395 *
2396 * A sysfs 'read-only' shost attribute.
2397 */
2398static ssize_t
2399_ctl_version_nvdata_default_show(struct device *cdev,
2400 struct device_attribute *attr, char *buf)
2401{
2402 struct Scsi_Host *shost = class_to_shost(cdev);
2403 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2404
Kashyap, Desaie94f6742010-03-17 16:24:52 +05302405 return snprintf(buf, PAGE_SIZE, "%08xh\n",
2406 le32_to_cpu(ioc->iounit_pg0.NvdataVersionDefault.Word));
Eric Moore635374e2009-03-09 01:21:12 -06002407}
2408static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
2409 _ctl_version_nvdata_default_show, NULL);
2410
2411/**
2412 * _ctl_board_name_show - board name
2413 * @cdev - pointer to embedded class device
2414 * @buf - the buffer returned
2415 *
2416 * A sysfs 'read-only' shost attribute.
2417 */
2418static ssize_t
2419_ctl_board_name_show(struct device *cdev, struct device_attribute *attr,
2420 char *buf)
2421{
2422 struct Scsi_Host *shost = class_to_shost(cdev);
2423 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2424
2425 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardName);
2426}
2427static DEVICE_ATTR(board_name, S_IRUGO, _ctl_board_name_show, NULL);
2428
2429/**
2430 * _ctl_board_assembly_show - board assembly name
2431 * @cdev - pointer to embedded class device
2432 * @buf - the buffer returned
2433 *
2434 * A sysfs 'read-only' shost attribute.
2435 */
2436static ssize_t
2437_ctl_board_assembly_show(struct device *cdev, struct device_attribute *attr,
2438 char *buf)
2439{
2440 struct Scsi_Host *shost = class_to_shost(cdev);
2441 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2442
2443 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardAssembly);
2444}
2445static DEVICE_ATTR(board_assembly, S_IRUGO,
2446 _ctl_board_assembly_show, NULL);
2447
2448/**
2449 * _ctl_board_tracer_show - board tracer number
2450 * @cdev - pointer to embedded class device
2451 * @buf - the buffer returned
2452 *
2453 * A sysfs 'read-only' shost attribute.
2454 */
2455static ssize_t
2456_ctl_board_tracer_show(struct device *cdev, struct device_attribute *attr,
2457 char *buf)
2458{
2459 struct Scsi_Host *shost = class_to_shost(cdev);
2460 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2461
2462 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardTracerNumber);
2463}
2464static DEVICE_ATTR(board_tracer, S_IRUGO,
2465 _ctl_board_tracer_show, NULL);
2466
2467/**
2468 * _ctl_io_delay_show - io missing delay
2469 * @cdev - pointer to embedded class device
2470 * @buf - the buffer returned
2471 *
2472 * This is for firmware implemention for deboucing device
2473 * removal events.
2474 *
2475 * A sysfs 'read-only' shost attribute.
2476 */
2477static ssize_t
2478_ctl_io_delay_show(struct device *cdev, struct device_attribute *attr,
2479 char *buf)
2480{
2481 struct Scsi_Host *shost = class_to_shost(cdev);
2482 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2483
2484 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
2485}
2486static DEVICE_ATTR(io_delay, S_IRUGO,
2487 _ctl_io_delay_show, NULL);
2488
2489/**
2490 * _ctl_device_delay_show - device missing delay
2491 * @cdev - pointer to embedded class device
2492 * @buf - the buffer returned
2493 *
2494 * This is for firmware implemention for deboucing device
2495 * removal events.
2496 *
2497 * A sysfs 'read-only' shost attribute.
2498 */
2499static ssize_t
2500_ctl_device_delay_show(struct device *cdev, struct device_attribute *attr,
2501 char *buf)
2502{
2503 struct Scsi_Host *shost = class_to_shost(cdev);
2504 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2505
2506 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
2507}
2508static DEVICE_ATTR(device_delay, S_IRUGO,
2509 _ctl_device_delay_show, NULL);
2510
2511/**
2512 * _ctl_fw_queue_depth_show - global credits
2513 * @cdev - pointer to embedded class device
2514 * @buf - the buffer returned
2515 *
2516 * This is firmware queue depth limit
2517 *
2518 * A sysfs 'read-only' shost attribute.
2519 */
2520static ssize_t
2521_ctl_fw_queue_depth_show(struct device *cdev, struct device_attribute *attr,
2522 char *buf)
2523{
2524 struct Scsi_Host *shost = class_to_shost(cdev);
2525 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2526
2527 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->facts.RequestCredit);
2528}
2529static DEVICE_ATTR(fw_queue_depth, S_IRUGO,
2530 _ctl_fw_queue_depth_show, NULL);
2531
2532/**
2533 * _ctl_sas_address_show - sas address
2534 * @cdev - pointer to embedded class device
2535 * @buf - the buffer returned
2536 *
2537 * This is the controller sas address
2538 *
2539 * A sysfs 'read-only' shost attribute.
2540 */
2541static ssize_t
2542_ctl_host_sas_address_show(struct device *cdev, struct device_attribute *attr,
2543 char *buf)
2544{
2545 struct Scsi_Host *shost = class_to_shost(cdev);
2546 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2547
2548 return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
2549 (unsigned long long)ioc->sas_hba.sas_address);
2550}
2551static DEVICE_ATTR(host_sas_address, S_IRUGO,
2552 _ctl_host_sas_address_show, NULL);
2553
2554/**
2555 * _ctl_logging_level_show - logging level
2556 * @cdev - pointer to embedded class device
2557 * @buf - the buffer returned
2558 *
2559 * A sysfs 'read/write' shost attribute.
2560 */
2561static ssize_t
2562_ctl_logging_level_show(struct device *cdev, struct device_attribute *attr,
2563 char *buf)
2564{
2565 struct Scsi_Host *shost = class_to_shost(cdev);
2566 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2567
2568 return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->logging_level);
2569}
2570static ssize_t
2571_ctl_logging_level_store(struct device *cdev, struct device_attribute *attr,
2572 const char *buf, size_t count)
2573{
2574 struct Scsi_Host *shost = class_to_shost(cdev);
2575 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2576 int val = 0;
2577
2578 if (sscanf(buf, "%x", &val) != 1)
2579 return -EINVAL;
2580
2581 ioc->logging_level = val;
2582 printk(MPT2SAS_INFO_FMT "logging_level=%08xh\n", ioc->name,
2583 ioc->logging_level);
2584 return strlen(buf);
2585}
2586static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR,
2587 _ctl_logging_level_show, _ctl_logging_level_store);
2588
Kashyap, Desaifa7f3162009-09-23 17:26:58 +05302589/* device attributes */
2590/*
2591 * _ctl_fwfault_debug_show - show/store fwfault_debug
2592 * @cdev - pointer to embedded class device
2593 * @buf - the buffer returned
2594 *
2595 * mpt2sas_fwfault_debug is command line option
2596 * A sysfs 'read/write' shost attribute.
2597 */
2598static ssize_t
2599_ctl_fwfault_debug_show(struct device *cdev,
2600 struct device_attribute *attr, char *buf)
2601{
2602 struct Scsi_Host *shost = class_to_shost(cdev);
2603 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2604
2605 return snprintf(buf, PAGE_SIZE, "%d\n", ioc->fwfault_debug);
2606}
2607static ssize_t
2608_ctl_fwfault_debug_store(struct device *cdev,
2609 struct device_attribute *attr, const char *buf, size_t count)
2610{
2611 struct Scsi_Host *shost = class_to_shost(cdev);
2612 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2613 int val = 0;
2614
2615 if (sscanf(buf, "%d", &val) != 1)
2616 return -EINVAL;
2617
2618 ioc->fwfault_debug = val;
2619 printk(MPT2SAS_INFO_FMT "fwfault_debug=%d\n", ioc->name,
2620 ioc->fwfault_debug);
2621 return strlen(buf);
2622}
2623static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR,
2624 _ctl_fwfault_debug_show, _ctl_fwfault_debug_store);
2625
Kashyap, Desaid32a8c12010-06-17 13:36:53 +05302626
2627/**
2628 * _ctl_ioc_reset_count_show - ioc reset count
2629 * @cdev - pointer to embedded class device
2630 * @buf - the buffer returned
2631 *
2632 * This is firmware queue depth limit
2633 *
2634 * A sysfs 'read-only' shost attribute.
2635 */
2636static ssize_t
2637_ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr,
2638 char *buf)
2639{
2640 struct Scsi_Host *shost = class_to_shost(cdev);
2641 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2642
2643 return snprintf(buf, PAGE_SIZE, "%08d\n", ioc->ioc_reset_count);
2644}
2645static DEVICE_ATTR(ioc_reset_count, S_IRUGO,
2646 _ctl_ioc_reset_count_show, NULL);
2647
Kashyap, Desai570c67a2010-06-17 13:43:17 +05302648struct DIAG_BUFFER_START {
2649 u32 Size;
2650 u32 DiagVersion;
2651 u8 BufferType;
2652 u8 Reserved[3];
2653 u32 Reserved1;
2654 u32 Reserved2;
2655 u32 Reserved3;
2656};
2657/**
2658 * _ctl_host_trace_buffer_size_show - host buffer size (trace only)
2659 * @cdev - pointer to embedded class device
2660 * @buf - the buffer returned
2661 *
2662 * A sysfs 'read-only' shost attribute.
2663 */
2664static ssize_t
2665_ctl_host_trace_buffer_size_show(struct device *cdev,
2666 struct device_attribute *attr, char *buf)
2667{
2668 struct Scsi_Host *shost = class_to_shost(cdev);
2669 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2670 u32 size = 0;
2671 struct DIAG_BUFFER_START *request_data;
2672
2673 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
2674 printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
2675 "registered\n", ioc->name, __func__);
2676 return 0;
2677 }
2678
2679 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2680 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
2681 printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
2682 "registered\n", ioc->name, __func__);
2683 return 0;
2684 }
2685
2686 request_data = (struct DIAG_BUFFER_START *)
2687 ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE];
2688 if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 ||
2689 le32_to_cpu(request_data->DiagVersion) == 0x01000000) &&
2690 le32_to_cpu(request_data->Reserved3) == 0x4742444c)
2691 size = le32_to_cpu(request_data->Size);
2692
2693 ioc->ring_buffer_sz = size;
2694 return snprintf(buf, PAGE_SIZE, "%d\n", size);
2695}
2696static DEVICE_ATTR(host_trace_buffer_size, S_IRUGO,
2697 _ctl_host_trace_buffer_size_show, NULL);
2698
2699/**
2700 * _ctl_host_trace_buffer_show - firmware ring buffer (trace only)
2701 * @cdev - pointer to embedded class device
2702 * @buf - the buffer returned
2703 *
2704 * A sysfs 'read/write' shost attribute.
2705 *
2706 * You will only be able to read 4k bytes of ring buffer at a time.
2707 * In order to read beyond 4k bytes, you will have to write out the
2708 * offset to the same attribute, it will move the pointer.
2709 */
2710static ssize_t
2711_ctl_host_trace_buffer_show(struct device *cdev, struct device_attribute *attr,
2712 char *buf)
2713{
2714 struct Scsi_Host *shost = class_to_shost(cdev);
2715 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2716 void *request_data;
2717 u32 size;
2718
2719 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
2720 printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
2721 "registered\n", ioc->name, __func__);
2722 return 0;
2723 }
2724
2725 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2726 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
2727 printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
2728 "registered\n", ioc->name, __func__);
2729 return 0;
2730 }
2731
2732 if (ioc->ring_buffer_offset > ioc->ring_buffer_sz)
2733 return 0;
2734
2735 size = ioc->ring_buffer_sz - ioc->ring_buffer_offset;
2736 size = (size > PAGE_SIZE) ? PAGE_SIZE : size;
2737 request_data = ioc->diag_buffer[0] + ioc->ring_buffer_offset;
2738 memcpy(buf, request_data, size);
2739 return size;
2740}
2741
2742static ssize_t
2743_ctl_host_trace_buffer_store(struct device *cdev, struct device_attribute *attr,
2744 const char *buf, size_t count)
2745{
2746 struct Scsi_Host *shost = class_to_shost(cdev);
2747 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2748 int val = 0;
2749
2750 if (sscanf(buf, "%d", &val) != 1)
2751 return -EINVAL;
2752
2753 ioc->ring_buffer_offset = val;
2754 return strlen(buf);
2755}
2756static DEVICE_ATTR(host_trace_buffer, S_IRUGO | S_IWUSR,
2757 _ctl_host_trace_buffer_show, _ctl_host_trace_buffer_store);
2758
2759/*****************************************/
2760
2761/**
2762 * _ctl_host_trace_buffer_enable_show - firmware ring buffer (trace only)
2763 * @cdev - pointer to embedded class device
2764 * @buf - the buffer returned
2765 *
2766 * A sysfs 'read/write' shost attribute.
2767 *
2768 * This is a mechnism to post/release host_trace_buffers
2769 */
2770static ssize_t
2771_ctl_host_trace_buffer_enable_show(struct device *cdev,
2772 struct device_attribute *attr, char *buf)
2773{
2774 struct Scsi_Host *shost = class_to_shost(cdev);
2775 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2776
2777 if ((!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) ||
2778 ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2779 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0))
2780 return snprintf(buf, PAGE_SIZE, "off\n");
2781 else if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2782 MPT2_DIAG_BUFFER_IS_RELEASED))
2783 return snprintf(buf, PAGE_SIZE, "release\n");
2784 else
2785 return snprintf(buf, PAGE_SIZE, "post\n");
2786}
2787
2788static ssize_t
2789_ctl_host_trace_buffer_enable_store(struct device *cdev,
2790 struct device_attribute *attr, const char *buf, size_t count)
2791{
2792 struct Scsi_Host *shost = class_to_shost(cdev);
2793 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2794 char str[10] = "";
2795 struct mpt2_diag_register diag_register;
2796 u8 issue_reset = 0;
2797
2798 if (sscanf(buf, "%s", str) != 1)
2799 return -EINVAL;
2800
2801 if (!strcmp(str, "post")) {
2802 /* exit out if host buffers are already posted */
2803 if ((ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) &&
2804 (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2805 MPT2_DIAG_BUFFER_IS_REGISTERED) &&
2806 ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2807 MPT2_DIAG_BUFFER_IS_RELEASED) == 0))
2808 goto out;
2809 memset(&diag_register, 0, sizeof(struct mpt2_diag_register));
2810 printk(MPT2SAS_INFO_FMT "posting host trace buffers\n",
2811 ioc->name);
2812 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
2813 diag_register.requested_buffer_size = (1024 * 1024);
2814 diag_register.unique_id = 0x7075900;
2815 ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0;
2816 _ctl_diag_register_2(ioc, &diag_register);
2817 } else if (!strcmp(str, "release")) {
2818 /* exit out if host buffers are already released */
2819 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE])
2820 goto out;
2821 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2822 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0)
2823 goto out;
2824 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2825 MPT2_DIAG_BUFFER_IS_RELEASED))
2826 goto out;
2827 printk(MPT2SAS_INFO_FMT "releasing host trace buffer\n",
2828 ioc->name);
2829 _ctl_send_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE, &issue_reset);
2830 }
2831
2832 out:
2833 return strlen(buf);
2834}
2835static DEVICE_ATTR(host_trace_buffer_enable, S_IRUGO | S_IWUSR,
2836 _ctl_host_trace_buffer_enable_show, _ctl_host_trace_buffer_enable_store);
Kashyap, Desaid32a8c12010-06-17 13:36:53 +05302837
Eric Moore635374e2009-03-09 01:21:12 -06002838struct device_attribute *mpt2sas_host_attrs[] = {
2839 &dev_attr_version_fw,
2840 &dev_attr_version_bios,
2841 &dev_attr_version_mpi,
2842 &dev_attr_version_product,
2843 &dev_attr_version_nvdata_persistent,
2844 &dev_attr_version_nvdata_default,
2845 &dev_attr_board_name,
2846 &dev_attr_board_assembly,
2847 &dev_attr_board_tracer,
2848 &dev_attr_io_delay,
2849 &dev_attr_device_delay,
2850 &dev_attr_logging_level,
Kashyap, Desaifa7f3162009-09-23 17:26:58 +05302851 &dev_attr_fwfault_debug,
Eric Moore635374e2009-03-09 01:21:12 -06002852 &dev_attr_fw_queue_depth,
2853 &dev_attr_host_sas_address,
Kashyap, Desaid32a8c12010-06-17 13:36:53 +05302854 &dev_attr_ioc_reset_count,
Kashyap, Desai570c67a2010-06-17 13:43:17 +05302855 &dev_attr_host_trace_buffer_size,
2856 &dev_attr_host_trace_buffer,
2857 &dev_attr_host_trace_buffer_enable,
Eric Moore635374e2009-03-09 01:21:12 -06002858 NULL,
2859};
2860
Eric Moore635374e2009-03-09 01:21:12 -06002861/**
2862 * _ctl_device_sas_address_show - sas address
2863 * @cdev - pointer to embedded class device
2864 * @buf - the buffer returned
2865 *
2866 * This is the sas address for the target
2867 *
2868 * A sysfs 'read-only' shost attribute.
2869 */
2870static ssize_t
2871_ctl_device_sas_address_show(struct device *dev, struct device_attribute *attr,
2872 char *buf)
2873{
2874 struct scsi_device *sdev = to_scsi_device(dev);
2875 struct MPT2SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
2876
2877 return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
2878 (unsigned long long)sas_device_priv_data->sas_target->sas_address);
2879}
2880static DEVICE_ATTR(sas_address, S_IRUGO, _ctl_device_sas_address_show, NULL);
2881
2882/**
2883 * _ctl_device_handle_show - device handle
2884 * @cdev - pointer to embedded class device
2885 * @buf - the buffer returned
2886 *
2887 * This is the firmware assigned device handle
2888 *
2889 * A sysfs 'read-only' shost attribute.
2890 */
2891static ssize_t
2892_ctl_device_handle_show(struct device *dev, struct device_attribute *attr,
2893 char *buf)
2894{
2895 struct scsi_device *sdev = to_scsi_device(dev);
2896 struct MPT2SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
2897
2898 return snprintf(buf, PAGE_SIZE, "0x%04x\n",
2899 sas_device_priv_data->sas_target->handle);
2900}
2901static DEVICE_ATTR(sas_device_handle, S_IRUGO, _ctl_device_handle_show, NULL);
2902
2903struct device_attribute *mpt2sas_dev_attrs[] = {
2904 &dev_attr_sas_address,
2905 &dev_attr_sas_device_handle,
2906 NULL,
2907};
2908
2909static const struct file_operations ctl_fops = {
2910 .owner = THIS_MODULE,
2911 .unlocked_ioctl = _ctl_ioctl,
2912 .release = _ctl_release,
2913 .poll = _ctl_poll,
2914 .fasync = _ctl_fasync,
2915#ifdef CONFIG_COMPAT
2916 .compat_ioctl = _ctl_ioctl_compat,
2917#endif
2918};
2919
2920static struct miscdevice ctl_dev = {
2921 .minor = MPT2SAS_MINOR,
2922 .name = MPT2SAS_DEV_NAME,
2923 .fops = &ctl_fops,
2924};
2925
2926/**
2927 * mpt2sas_ctl_init - main entry point for ctl.
2928 *
2929 */
2930void
2931mpt2sas_ctl_init(void)
2932{
2933 async_queue = NULL;
2934 if (misc_register(&ctl_dev) < 0)
2935 printk(KERN_ERR "%s can't register misc device [minor=%d]\n",
2936 MPT2SAS_DRIVER_NAME, MPT2SAS_MINOR);
2937
2938 init_waitqueue_head(&ctl_poll_wait);
2939}
2940
2941/**
2942 * mpt2sas_ctl_exit - exit point for ctl
2943 *
2944 */
2945void
2946mpt2sas_ctl_exit(void)
2947{
2948 struct MPT2SAS_ADAPTER *ioc;
2949 int i;
2950
Eric Mooreba33fad2009-03-15 21:37:18 -06002951 list_for_each_entry(ioc, &mpt2sas_ioc_list, list) {
Eric Moore635374e2009-03-09 01:21:12 -06002952
2953 /* free memory associated to diag buffers */
2954 for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
2955 if (!ioc->diag_buffer[i])
2956 continue;
2957 pci_free_consistent(ioc->pdev, ioc->diag_buffer_sz[i],
2958 ioc->diag_buffer[i], ioc->diag_buffer_dma[i]);
2959 ioc->diag_buffer[i] = NULL;
2960 ioc->diag_buffer_status[i] = 0;
2961 }
2962
2963 kfree(ioc->event_log);
2964 }
2965 misc_deregister(&ctl_dev);
2966}
2967