blob: 10f16a306e54ac153d434afb31f36f03ca1e6d16 [file] [log] [blame]
Eric Moore635374e2009-03-09 01:21:12 -06001/*
2 * This is the Fusion MPT base driver providing common API layer interface
3 * for access to MPT (Message Passing Technology) firmware.
4 *
5 * This code is based on drivers/scsi/mpt2sas/mpt2_base.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/kdev_t.h>
54#include <linux/blkdev.h>
55#include <linux/delay.h>
56#include <linux/interrupt.h>
57#include <linux/dma-mapping.h>
58#include <linux/sort.h>
59#include <linux/io.h>
Kashyap, Desaia8ebd762009-09-23 17:29:29 +053060#include <linux/time.h>
Kashyap, Desaief7c80c2010-04-05 14:20:07 +053061#include <linux/aer.h>
Eric Moore635374e2009-03-09 01:21:12 -060062
63#include "mpt2sas_base.h"
64
65static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS];
66
67#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
Eric Moore635374e2009-03-09 01:21:12 -060068
nagalakshmi.nandigama@lsi.com73669de2011-12-01 07:53:08 +053069#define MAX_HBA_QUEUE_DEPTH 30000
70#define MAX_CHAIN_DEPTH 100000
Eric Moore635374e2009-03-09 01:21:12 -060071static int max_queue_depth = -1;
72module_param(max_queue_depth, int, 0);
73MODULE_PARM_DESC(max_queue_depth, " max controller queue depth ");
74
75static int max_sgl_entries = -1;
76module_param(max_sgl_entries, int, 0);
77MODULE_PARM_DESC(max_sgl_entries, " max sg entries ");
78
79static int msix_disable = -1;
80module_param(msix_disable, int, 0);
81MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
82
Kashyap, Desai6cb8ef52010-11-13 04:32:18 +053083static int missing_delay[2] = {-1, -1};
84module_param_array(missing_delay, int, NULL, 0);
85MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
86
Kashyap, Desai32e0eb52009-09-23 17:28:09 +053087/* diag_buffer_enable is bitwise
Kashyap, Desai1b01fe32009-09-23 17:28:59 +053088 * bit 0 set = TRACE
89 * bit 1 set = SNAPSHOT
90 * bit 2 set = EXTENDED
Kashyap, Desai32e0eb52009-09-23 17:28:09 +053091 *
92 * Either bit can be set, or both
93 */
94static int diag_buffer_enable;
95module_param(diag_buffer_enable, int, 0);
Kashyap, Desai1b01fe32009-09-23 17:28:59 +053096MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
97 "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
Kashyap, Desai32e0eb52009-09-23 17:28:09 +053098
Kashyap, Desaifb07bb92011-06-14 10:54:56 +053099static int mpt2sas_fwfault_debug;
Kashyap, Desaifa7f3162009-09-23 17:26:58 +0530100MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
101 "and halt firmware - (default=0)");
102
Kashyap, Desaidd5fd332010-06-17 13:31:17 +0530103static int disable_discovery = -1;
104module_param(disable_discovery, int, 0);
105MODULE_PARM_DESC(disable_discovery, " disable discovery ");
106
Kashyap, Desaifa7f3162009-09-23 17:26:58 +0530107/**
108 * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.
109 *
110 */
111static int
112_scsih_set_fwfault_debug(const char *val, struct kernel_param *kp)
113{
114 int ret = param_set_int(val, kp);
115 struct MPT2SAS_ADAPTER *ioc;
116
117 if (ret)
118 return ret;
119
Kashyap, Desaie75b9b62009-12-16 18:52:39 +0530120 printk(KERN_INFO "setting fwfault_debug(%d)\n", mpt2sas_fwfault_debug);
Kashyap, Desaifa7f3162009-09-23 17:26:58 +0530121 list_for_each_entry(ioc, &mpt2sas_ioc_list, list)
122 ioc->fwfault_debug = mpt2sas_fwfault_debug;
123 return 0;
124}
125module_param_call(mpt2sas_fwfault_debug, _scsih_set_fwfault_debug,
126 param_get_int, &mpt2sas_fwfault_debug, 0644);
127
Eric Moore635374e2009-03-09 01:21:12 -0600128/**
129 * _base_fault_reset_work - workq handling ioc fault conditions
130 * @work: input argument, used to derive ioc
131 * Context: sleep.
132 *
133 * Return nothing.
134 */
135static void
136_base_fault_reset_work(struct work_struct *work)
137{
138 struct MPT2SAS_ADAPTER *ioc =
139 container_of(work, struct MPT2SAS_ADAPTER, fault_reset_work.work);
140 unsigned long flags;
141 u32 doorbell;
142 int rc;
143
144 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
Kashyap, Desai155dd4c2009-08-20 13:22:00 +0530145 if (ioc->shost_recovery)
Eric Moore635374e2009-03-09 01:21:12 -0600146 goto rearm_timer;
147 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
148
149 doorbell = mpt2sas_base_get_iocstate(ioc, 0);
150 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
151 rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
152 FORCE_BIG_HAMMER);
153 printk(MPT2SAS_WARN_FMT "%s: hard reset: %s\n", ioc->name,
154 __func__, (rc == 0) ? "success" : "failed");
155 doorbell = mpt2sas_base_get_iocstate(ioc, 0);
156 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
157 mpt2sas_base_fault_info(ioc, doorbell &
158 MPI2_DOORBELL_DATA_MASK);
159 }
160
161 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
162 rearm_timer:
163 if (ioc->fault_reset_work_q)
164 queue_delayed_work(ioc->fault_reset_work_q,
165 &ioc->fault_reset_work,
166 msecs_to_jiffies(FAULT_POLLING_INTERVAL));
167 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
168}
169
Kashyap, Desaie4750c92009-08-07 19:37:59 +0530170/**
171 * mpt2sas_base_start_watchdog - start the fault_reset_work_q
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530172 * @ioc: per adapter object
Kashyap, Desaie4750c92009-08-07 19:37:59 +0530173 * Context: sleep.
174 *
175 * Return nothing.
176 */
177void
178mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc)
179{
180 unsigned long flags;
181
182 if (ioc->fault_reset_work_q)
183 return;
184
185 /* initialize fault polling */
186 INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
187 snprintf(ioc->fault_reset_work_q_name,
188 sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
189 ioc->fault_reset_work_q =
190 create_singlethread_workqueue(ioc->fault_reset_work_q_name);
191 if (!ioc->fault_reset_work_q) {
192 printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n",
193 ioc->name, __func__, __LINE__);
194 return;
195 }
196 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
197 if (ioc->fault_reset_work_q)
198 queue_delayed_work(ioc->fault_reset_work_q,
199 &ioc->fault_reset_work,
200 msecs_to_jiffies(FAULT_POLLING_INTERVAL));
201 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
202}
203
204/**
205 * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530206 * @ioc: per adapter object
Kashyap, Desaie4750c92009-08-07 19:37:59 +0530207 * Context: sleep.
208 *
209 * Return nothing.
210 */
211void
212mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc)
213{
214 unsigned long flags;
215 struct workqueue_struct *wq;
216
217 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
218 wq = ioc->fault_reset_work_q;
219 ioc->fault_reset_work_q = NULL;
220 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
221 if (wq) {
222 if (!cancel_delayed_work(&ioc->fault_reset_work))
223 flush_workqueue(wq);
224 destroy_workqueue(wq);
225 }
226}
227
Kashyap, Desaifa7f3162009-09-23 17:26:58 +0530228/**
229 * mpt2sas_base_fault_info - verbose translation of firmware FAULT code
230 * @ioc: per adapter object
231 * @fault_code: fault code
232 *
233 * Return nothing.
234 */
235void
236mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code)
237{
238 printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n",
239 ioc->name, fault_code);
240}
241
242/**
243 * mpt2sas_halt_firmware - halt's mpt controller firmware
244 * @ioc: per adapter object
245 *
246 * For debugging timeout related issues. Writing 0xCOFFEE00
247 * to the doorbell register will halt controller firmware. With
248 * the purpose to stop both driver and firmware, the enduser can
249 * obtain a ring buffer from controller UART.
250 */
251void
252mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc)
253{
254 u32 doorbell;
255
256 if (!ioc->fwfault_debug)
257 return;
258
259 dump_stack();
260
261 doorbell = readl(&ioc->chip->Doorbell);
262 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
263 mpt2sas_base_fault_info(ioc , doorbell);
264 else {
265 writel(0xC0FFEE00, &ioc->chip->Doorbell);
266 printk(MPT2SAS_ERR_FMT "Firmware is halted due to command "
267 "timeout\n", ioc->name);
268 }
269
270 panic("panic in %s\n", __func__);
271}
272
Eric Moore635374e2009-03-09 01:21:12 -0600273#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
274/**
275 * _base_sas_ioc_info - verbose translation of the ioc status
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530276 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -0600277 * @mpi_reply: reply mf payload returned from firmware
278 * @request_hdr: request mf
279 *
280 * Return nothing.
281 */
282static void
283_base_sas_ioc_info(struct MPT2SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
284 MPI2RequestHeader_t *request_hdr)
285{
286 u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
287 MPI2_IOCSTATUS_MASK;
288 char *desc = NULL;
289 u16 frame_sz;
290 char *func_str = NULL;
291
292 /* SCSI_IO, RAID_PASS are handled from _scsih_scsi_ioc_info */
293 if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
294 request_hdr->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
295 request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION)
296 return;
297
Kashyap, Desaie94f6742010-03-17 16:24:52 +0530298 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
299 return;
300
Eric Moore635374e2009-03-09 01:21:12 -0600301 switch (ioc_status) {
302
303/****************************************************************************
304* Common IOCStatus values for all replies
305****************************************************************************/
306
307 case MPI2_IOCSTATUS_INVALID_FUNCTION:
308 desc = "invalid function";
309 break;
310 case MPI2_IOCSTATUS_BUSY:
311 desc = "busy";
312 break;
313 case MPI2_IOCSTATUS_INVALID_SGL:
314 desc = "invalid sgl";
315 break;
316 case MPI2_IOCSTATUS_INTERNAL_ERROR:
317 desc = "internal error";
318 break;
319 case MPI2_IOCSTATUS_INVALID_VPID:
320 desc = "invalid vpid";
321 break;
322 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
323 desc = "insufficient resources";
324 break;
325 case MPI2_IOCSTATUS_INVALID_FIELD:
326 desc = "invalid field";
327 break;
328 case MPI2_IOCSTATUS_INVALID_STATE:
329 desc = "invalid state";
330 break;
331 case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
332 desc = "op state not supported";
333 break;
334
335/****************************************************************************
336* Config IOCStatus values
337****************************************************************************/
338
339 case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
340 desc = "config invalid action";
341 break;
342 case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
343 desc = "config invalid type";
344 break;
345 case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
346 desc = "config invalid page";
347 break;
348 case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
349 desc = "config invalid data";
350 break;
351 case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
352 desc = "config no defaults";
353 break;
354 case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
355 desc = "config cant commit";
356 break;
357
358/****************************************************************************
359* SCSI IO Reply
360****************************************************************************/
361
362 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
363 case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
364 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
365 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
366 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
367 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
368 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
369 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
370 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
371 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
372 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
373 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
374 break;
375
376/****************************************************************************
377* For use by SCSI Initiator and SCSI Target end-to-end data protection
378****************************************************************************/
379
380 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
381 desc = "eedp guard error";
382 break;
383 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
384 desc = "eedp ref tag error";
385 break;
386 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
387 desc = "eedp app tag error";
388 break;
389
390/****************************************************************************
391* SCSI Target values
392****************************************************************************/
393
394 case MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX:
395 desc = "target invalid io index";
396 break;
397 case MPI2_IOCSTATUS_TARGET_ABORTED:
398 desc = "target aborted";
399 break;
400 case MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE:
401 desc = "target no conn retryable";
402 break;
403 case MPI2_IOCSTATUS_TARGET_NO_CONNECTION:
404 desc = "target no connection";
405 break;
406 case MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH:
407 desc = "target xfer count mismatch";
408 break;
409 case MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR:
410 desc = "target data offset error";
411 break;
412 case MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA:
413 desc = "target too much write data";
414 break;
415 case MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT:
416 desc = "target iu too short";
417 break;
418 case MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT:
419 desc = "target ack nak timeout";
420 break;
421 case MPI2_IOCSTATUS_TARGET_NAK_RECEIVED:
422 desc = "target nak received";
423 break;
424
425/****************************************************************************
426* Serial Attached SCSI values
427****************************************************************************/
428
429 case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
430 desc = "smp request failed";
431 break;
432 case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
433 desc = "smp data overrun";
434 break;
435
436/****************************************************************************
437* Diagnostic Buffer Post / Diagnostic Release values
438****************************************************************************/
439
440 case MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED:
441 desc = "diagnostic released";
442 break;
443 default:
444 break;
445 }
446
447 if (!desc)
448 return;
449
450 switch (request_hdr->Function) {
451 case MPI2_FUNCTION_CONFIG:
452 frame_sz = sizeof(Mpi2ConfigRequest_t) + ioc->sge_size;
453 func_str = "config_page";
454 break;
455 case MPI2_FUNCTION_SCSI_TASK_MGMT:
456 frame_sz = sizeof(Mpi2SCSITaskManagementRequest_t);
457 func_str = "task_mgmt";
458 break;
459 case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
460 frame_sz = sizeof(Mpi2SasIoUnitControlRequest_t);
461 func_str = "sas_iounit_ctl";
462 break;
463 case MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
464 frame_sz = sizeof(Mpi2SepRequest_t);
465 func_str = "enclosure";
466 break;
467 case MPI2_FUNCTION_IOC_INIT:
468 frame_sz = sizeof(Mpi2IOCInitRequest_t);
469 func_str = "ioc_init";
470 break;
471 case MPI2_FUNCTION_PORT_ENABLE:
472 frame_sz = sizeof(Mpi2PortEnableRequest_t);
473 func_str = "port_enable";
474 break;
475 case MPI2_FUNCTION_SMP_PASSTHROUGH:
476 frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size;
477 func_str = "smp_passthru";
478 break;
479 default:
480 frame_sz = 32;
481 func_str = "unknown";
482 break;
483 }
484
485 printk(MPT2SAS_WARN_FMT "ioc_status: %s(0x%04x), request(0x%p),"
486 " (%s)\n", ioc->name, desc, ioc_status, request_hdr, func_str);
487
488 _debug_dump_mf(request_hdr, frame_sz/4);
489}
490
491/**
492 * _base_display_event_data - verbose translation of firmware asyn events
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530493 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -0600494 * @mpi_reply: reply mf payload returned from firmware
495 *
496 * Return nothing.
497 */
498static void
499_base_display_event_data(struct MPT2SAS_ADAPTER *ioc,
500 Mpi2EventNotificationReply_t *mpi_reply)
501{
502 char *desc = NULL;
503 u16 event;
504
505 if (!(ioc->logging_level & MPT_DEBUG_EVENTS))
506 return;
507
508 event = le16_to_cpu(mpi_reply->Event);
509
510 switch (event) {
511 case MPI2_EVENT_LOG_DATA:
512 desc = "Log Data";
513 break;
514 case MPI2_EVENT_STATE_CHANGE:
515 desc = "Status Change";
516 break;
517 case MPI2_EVENT_HARD_RESET_RECEIVED:
518 desc = "Hard Reset Received";
519 break;
520 case MPI2_EVENT_EVENT_CHANGE:
521 desc = "Event Change";
522 break;
Eric Moore635374e2009-03-09 01:21:12 -0600523 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
524 desc = "Device Status Change";
525 break;
526 case MPI2_EVENT_IR_OPERATION_STATUS:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +0530527 if (!ioc->hide_ir_msg)
528 desc = "IR Operation Status";
Eric Moore635374e2009-03-09 01:21:12 -0600529 break;
530 case MPI2_EVENT_SAS_DISCOVERY:
Kashyap, Desaie94f6742010-03-17 16:24:52 +0530531 {
532 Mpi2EventDataSasDiscovery_t *event_data =
533 (Mpi2EventDataSasDiscovery_t *)mpi_reply->EventData;
534 printk(MPT2SAS_INFO_FMT "Discovery: (%s)", ioc->name,
535 (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
536 "start" : "stop");
537 if (event_data->DiscoveryStatus)
538 printk("discovery_status(0x%08x)",
539 le32_to_cpu(event_data->DiscoveryStatus));
Julia Lawall7968f192010-08-05 22:19:36 +0200540 printk("\n");
Kashyap, Desaie94f6742010-03-17 16:24:52 +0530541 return;
542 }
Eric Moore635374e2009-03-09 01:21:12 -0600543 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
544 desc = "SAS Broadcast Primitive";
545 break;
546 case MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
547 desc = "SAS Init Device Status Change";
548 break;
549 case MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW:
550 desc = "SAS Init Table Overflow";
551 break;
552 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
553 desc = "SAS Topology Change List";
554 break;
555 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
556 desc = "SAS Enclosure Device Status Change";
557 break;
558 case MPI2_EVENT_IR_VOLUME:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +0530559 if (!ioc->hide_ir_msg)
560 desc = "IR Volume";
Eric Moore635374e2009-03-09 01:21:12 -0600561 break;
562 case MPI2_EVENT_IR_PHYSICAL_DISK:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +0530563 if (!ioc->hide_ir_msg)
564 desc = "IR Physical Disk";
Eric Moore635374e2009-03-09 01:21:12 -0600565 break;
566 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +0530567 if (!ioc->hide_ir_msg)
568 desc = "IR Configuration Change List";
Eric Moore635374e2009-03-09 01:21:12 -0600569 break;
570 case MPI2_EVENT_LOG_ENTRY_ADDED:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +0530571 if (!ioc->hide_ir_msg)
572 desc = "Log Entry Added";
Eric Moore635374e2009-03-09 01:21:12 -0600573 break;
574 }
575
576 if (!desc)
577 return;
578
579 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, desc);
580}
581#endif
582
583/**
584 * _base_sas_log_info - verbose translation of firmware log info
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530585 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -0600586 * @log_info: log info
587 *
588 * Return nothing.
589 */
590static void
591_base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info)
592{
593 union loginfo_type {
594 u32 loginfo;
595 struct {
596 u32 subcode:16;
597 u32 code:8;
598 u32 originator:4;
599 u32 bus_type:4;
600 } dw;
601 };
602 union loginfo_type sas_loginfo;
603 char *originator_str = NULL;
604
605 sas_loginfo.loginfo = log_info;
606 if (sas_loginfo.dw.bus_type != 3 /*SAS*/)
607 return;
608
Kashyap, Desaibe9e8cd72009-08-07 19:36:43 +0530609 /* each nexus loss loginfo */
610 if (log_info == 0x31170000)
611 return;
612
Eric Moore635374e2009-03-09 01:21:12 -0600613 /* eat the loginfos associated with task aborts */
614 if (ioc->ignore_loginfos && (log_info == 30050000 || log_info ==
615 0x31140000 || log_info == 0x31130000))
616 return;
617
618 switch (sas_loginfo.dw.originator) {
619 case 0:
620 originator_str = "IOP";
621 break;
622 case 1:
623 originator_str = "PL";
624 break;
625 case 2:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +0530626 if (!ioc->hide_ir_msg)
627 originator_str = "IR";
628 else
629 originator_str = "WarpDrive";
Eric Moore635374e2009-03-09 01:21:12 -0600630 break;
631 }
632
633 printk(MPT2SAS_WARN_FMT "log_info(0x%08x): originator(%s), "
634 "code(0x%02x), sub_code(0x%04x)\n", ioc->name, log_info,
635 originator_str, sas_loginfo.dw.code,
636 sas_loginfo.dw.subcode);
637}
638
639/**
Eric Moore635374e2009-03-09 01:21:12 -0600640 * _base_display_reply_info -
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530641 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -0600642 * @smid: system request message index
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530643 * @msix_index: MSIX table index supplied by the OS
Eric Moore635374e2009-03-09 01:21:12 -0600644 * @reply: reply message frame(lower 32bit addr)
645 *
646 * Return nothing.
647 */
648static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530649_base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
Eric Moore635374e2009-03-09 01:21:12 -0600650 u32 reply)
651{
652 MPI2DefaultReply_t *mpi_reply;
653 u16 ioc_status;
654
655 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
656 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
657#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
658 if ((ioc_status & MPI2_IOCSTATUS_MASK) &&
659 (ioc->logging_level & MPT_DEBUG_REPLY)) {
660 _base_sas_ioc_info(ioc , mpi_reply,
661 mpt2sas_base_get_msg_frame(ioc, smid));
662 }
663#endif
664 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
665 _base_sas_log_info(ioc, le32_to_cpu(mpi_reply->IOCLogInfo));
666}
667
668/**
669 * mpt2sas_base_done - base internal command completion routine
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530670 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -0600671 * @smid: system request message index
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530672 * @msix_index: MSIX table index supplied by the OS
Eric Moore635374e2009-03-09 01:21:12 -0600673 * @reply: reply message frame(lower 32bit addr)
674 *
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530675 * Return 1 meaning mf should be freed from _base_interrupt
676 * 0 means the mf is freed from this function.
Eric Moore635374e2009-03-09 01:21:12 -0600677 */
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530678u8
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530679mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
680 u32 reply)
Eric Moore635374e2009-03-09 01:21:12 -0600681{
682 MPI2DefaultReply_t *mpi_reply;
683
684 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
685 if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530686 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600687
688 if (ioc->base_cmds.status == MPT2_CMD_NOT_USED)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530689 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600690
691 ioc->base_cmds.status |= MPT2_CMD_COMPLETE;
692 if (mpi_reply) {
693 ioc->base_cmds.status |= MPT2_CMD_REPLY_VALID;
694 memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
695 }
696 ioc->base_cmds.status &= ~MPT2_CMD_PENDING;
697 complete(&ioc->base_cmds.done);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530698 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600699}
700
701/**
702 * _base_async_event - main callback handler for firmware asyn events
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530703 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530704 * @msix_index: MSIX table index supplied by the OS
Eric Moore635374e2009-03-09 01:21:12 -0600705 * @reply: reply message frame(lower 32bit addr)
706 *
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530707 * Return 1 meaning mf should be freed from _base_interrupt
708 * 0 means the mf is freed from this function.
Eric Moore635374e2009-03-09 01:21:12 -0600709 */
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530710static u8
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530711_base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply)
Eric Moore635374e2009-03-09 01:21:12 -0600712{
713 Mpi2EventNotificationReply_t *mpi_reply;
714 Mpi2EventAckRequest_t *ack_request;
715 u16 smid;
716
717 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
718 if (!mpi_reply)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530719 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600720 if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530721 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600722#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
723 _base_display_event_data(ioc, mpi_reply);
724#endif
725 if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED))
726 goto out;
727 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
728 if (!smid) {
729 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
730 ioc->name, __func__);
731 goto out;
732 }
733
734 ack_request = mpt2sas_base_get_msg_frame(ioc, smid);
735 memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t));
736 ack_request->Function = MPI2_FUNCTION_EVENT_ACK;
737 ack_request->Event = mpi_reply->Event;
738 ack_request->EventContext = mpi_reply->EventContext;
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530739 ack_request->VF_ID = 0; /* TODO */
740 ack_request->VP_ID = 0;
741 mpt2sas_base_put_smid_default(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -0600742
743 out:
744
745 /* scsih callback handler */
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530746 mpt2sas_scsih_event_callback(ioc, msix_index, reply);
Eric Moore635374e2009-03-09 01:21:12 -0600747
748 /* ctl callback handler */
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530749 mpt2sas_ctl_event_callback(ioc, msix_index, reply);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530750
751 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600752}
753
754/**
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530755 * _base_get_cb_idx - obtain the callback index
756 * @ioc: per adapter object
757 * @smid: system request message index
758 *
759 * Return callback index.
760 */
761static u8
762_base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid)
763{
764 int i;
Kashyap, Desaid5bd3492011-01-04 11:39:20 +0530765 u8 cb_idx;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530766
Kashyap, Desaid5bd3492011-01-04 11:39:20 +0530767 if (smid < ioc->hi_priority_smid) {
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530768 i = smid - 1;
769 cb_idx = ioc->scsi_lookup[i].cb_idx;
Kashyap, Desaid5bd3492011-01-04 11:39:20 +0530770 } else if (smid < ioc->internal_smid) {
771 i = smid - ioc->hi_priority_smid;
772 cb_idx = ioc->hpr_lookup[i].cb_idx;
773 } else if (smid <= ioc->hba_queue_depth) {
774 i = smid - ioc->internal_smid;
775 cb_idx = ioc->internal_lookup[i].cb_idx;
776 } else
777 cb_idx = 0xFF;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530778 return cb_idx;
779}
780
781/**
Eric Moore635374e2009-03-09 01:21:12 -0600782 * _base_mask_interrupts - disable interrupts
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530783 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -0600784 *
785 * Disabling ResetIRQ, Reply and Doorbell Interrupts
786 *
787 * Return nothing.
788 */
789static void
790_base_mask_interrupts(struct MPT2SAS_ADAPTER *ioc)
791{
792 u32 him_register;
793
794 ioc->mask_interrupts = 1;
795 him_register = readl(&ioc->chip->HostInterruptMask);
796 him_register |= MPI2_HIM_DIM + MPI2_HIM_RIM + MPI2_HIM_RESET_IRQ_MASK;
797 writel(him_register, &ioc->chip->HostInterruptMask);
798 readl(&ioc->chip->HostInterruptMask);
799}
800
801/**
802 * _base_unmask_interrupts - enable interrupts
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530803 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -0600804 *
805 * Enabling only Reply Interrupts
806 *
807 * Return nothing.
808 */
809static void
810_base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc)
811{
812 u32 him_register;
813
Eric Moore635374e2009-03-09 01:21:12 -0600814 him_register = readl(&ioc->chip->HostInterruptMask);
815 him_register &= ~MPI2_HIM_RIM;
816 writel(him_register, &ioc->chip->HostInterruptMask);
817 ioc->mask_interrupts = 0;
818}
819
Kashyap, Desai5b768582009-08-20 13:24:31 +0530820union reply_descriptor {
821 u64 word;
822 struct {
823 u32 low;
824 u32 high;
825 } u;
826};
827
Eric Moore635374e2009-03-09 01:21:12 -0600828/**
829 * _base_interrupt - MPT adapter (IOC) specific interrupt handler.
830 * @irq: irq number (not used)
831 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
832 * @r: pt_regs pointer (not used)
833 *
834 * Return IRQ_HANDLE if processed, else IRQ_NONE.
835 */
836static irqreturn_t
837_base_interrupt(int irq, void *bus_id)
838{
Eric Moore03ea1112009-04-21 15:37:57 -0600839 union reply_descriptor rd;
Kashyap, Desai5b768582009-08-20 13:24:31 +0530840 u32 completed_cmds;
Eric Moore635374e2009-03-09 01:21:12 -0600841 u8 request_desript_type;
842 u16 smid;
843 u8 cb_idx;
844 u32 reply;
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530845 u8 msix_index;
Eric Moore635374e2009-03-09 01:21:12 -0600846 struct MPT2SAS_ADAPTER *ioc = bus_id;
Kashyap, Desai5b768582009-08-20 13:24:31 +0530847 Mpi2ReplyDescriptorsUnion_t *rpf;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530848 u8 rc;
Eric Moore635374e2009-03-09 01:21:12 -0600849
850 if (ioc->mask_interrupts)
851 return IRQ_NONE;
852
Kashyap, Desai5b768582009-08-20 13:24:31 +0530853 rpf = &ioc->reply_post_free[ioc->reply_post_host_index];
854 request_desript_type = rpf->Default.ReplyFlags
855 & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
Eric Moore635374e2009-03-09 01:21:12 -0600856 if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
857 return IRQ_NONE;
858
859 completed_cmds = 0;
Kashyap, Desaidd3741d2010-11-13 04:31:14 +0530860 cb_idx = 0xFF;
Eric Moore635374e2009-03-09 01:21:12 -0600861 do {
Kashyap, Desaifb07bb92011-06-14 10:54:56 +0530862 rd.word = le64_to_cpu(rpf->Words);
Eric Moore03ea1112009-04-21 15:37:57 -0600863 if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
Eric Moore635374e2009-03-09 01:21:12 -0600864 goto out;
865 reply = 0;
866 cb_idx = 0xFF;
Kashyap, Desai5b768582009-08-20 13:24:31 +0530867 smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1);
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530868 msix_index = rpf->Default.MSIxIndex;
Eric Moore635374e2009-03-09 01:21:12 -0600869 if (request_desript_type ==
870 MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
Kashyap, Desai5b768582009-08-20 13:24:31 +0530871 reply = le32_to_cpu
872 (rpf->AddressReply.ReplyFrameAddress);
Kashyap, Desaidd3741d2010-11-13 04:31:14 +0530873 if (reply > ioc->reply_dma_max_address ||
874 reply < ioc->reply_dma_min_address)
875 reply = 0;
Eric Moore635374e2009-03-09 01:21:12 -0600876 } else if (request_desript_type ==
877 MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER)
878 goto next;
879 else if (request_desript_type ==
880 MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS)
881 goto next;
882 if (smid)
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530883 cb_idx = _base_get_cb_idx(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -0600884 if (smid && cb_idx != 0xFF) {
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530885 rc = mpt_callbacks[cb_idx](ioc, smid, msix_index,
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530886 reply);
Eric Moore635374e2009-03-09 01:21:12 -0600887 if (reply)
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530888 _base_display_reply_info(ioc, smid, msix_index,
Eric Moore635374e2009-03-09 01:21:12 -0600889 reply);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530890 if (rc)
891 mpt2sas_base_free_smid(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -0600892 }
893 if (!smid)
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530894 _base_async_event(ioc, msix_index, reply);
Eric Moore635374e2009-03-09 01:21:12 -0600895
896 /* reply free queue handling */
897 if (reply) {
898 ioc->reply_free_host_index =
899 (ioc->reply_free_host_index ==
900 (ioc->reply_free_queue_depth - 1)) ?
901 0 : ioc->reply_free_host_index + 1;
902 ioc->reply_free[ioc->reply_free_host_index] =
903 cpu_to_le32(reply);
Kashyap, Desai5b768582009-08-20 13:24:31 +0530904 wmb();
Eric Moore635374e2009-03-09 01:21:12 -0600905 writel(ioc->reply_free_host_index,
906 &ioc->chip->ReplyFreeHostIndex);
Eric Moore635374e2009-03-09 01:21:12 -0600907 }
908
909 next:
Kashyap, Desai5b768582009-08-20 13:24:31 +0530910
Kashyap, Desaifb07bb92011-06-14 10:54:56 +0530911 rpf->Words = cpu_to_le64(ULLONG_MAX);
Kashyap, Desai5b768582009-08-20 13:24:31 +0530912 ioc->reply_post_host_index = (ioc->reply_post_host_index ==
913 (ioc->reply_post_queue_depth - 1)) ? 0 :
914 ioc->reply_post_host_index + 1;
Eric Moore635374e2009-03-09 01:21:12 -0600915 request_desript_type =
Kashyap, Desai5b768582009-08-20 13:24:31 +0530916 ioc->reply_post_free[ioc->reply_post_host_index].Default.
917 ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
Eric Moore635374e2009-03-09 01:21:12 -0600918 completed_cmds++;
919 if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
920 goto out;
Kashyap, Desai5b768582009-08-20 13:24:31 +0530921 if (!ioc->reply_post_host_index)
922 rpf = ioc->reply_post_free;
923 else
924 rpf++;
Eric Moore635374e2009-03-09 01:21:12 -0600925 } while (1);
926
927 out:
928
929 if (!completed_cmds)
930 return IRQ_NONE;
931
Eric Moore635374e2009-03-09 01:21:12 -0600932 wmb();
Kashyap, Desai5b768582009-08-20 13:24:31 +0530933 writel(ioc->reply_post_host_index, &ioc->chip->ReplyPostHostIndex);
Eric Moore635374e2009-03-09 01:21:12 -0600934 return IRQ_HANDLED;
935}
936
937/**
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300938 * mpt2sas_base_release_callback_handler - clear interrupt callback handler
Eric Moore635374e2009-03-09 01:21:12 -0600939 * @cb_idx: callback index
940 *
941 * Return nothing.
942 */
943void
944mpt2sas_base_release_callback_handler(u8 cb_idx)
945{
946 mpt_callbacks[cb_idx] = NULL;
947}
948
949/**
950 * mpt2sas_base_register_callback_handler - obtain index for the interrupt callback handler
951 * @cb_func: callback function
952 *
953 * Returns cb_func.
954 */
955u8
956mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func)
957{
958 u8 cb_idx;
959
960 for (cb_idx = MPT_MAX_CALLBACKS-1; cb_idx; cb_idx--)
961 if (mpt_callbacks[cb_idx] == NULL)
962 break;
963
964 mpt_callbacks[cb_idx] = cb_func;
965 return cb_idx;
966}
967
968/**
969 * mpt2sas_base_initialize_callback_handler - initialize the interrupt callback handler
970 *
971 * Return nothing.
972 */
973void
974mpt2sas_base_initialize_callback_handler(void)
975{
976 u8 cb_idx;
977
978 for (cb_idx = 0; cb_idx < MPT_MAX_CALLBACKS; cb_idx++)
979 mpt2sas_base_release_callback_handler(cb_idx);
980}
981
982/**
983 * mpt2sas_base_build_zero_len_sge - build zero length sg entry
984 * @ioc: per adapter object
985 * @paddr: virtual address for SGE
986 *
987 * Create a zero length scatter gather entry to insure the IOCs hardware has
988 * something to use if the target device goes brain dead and tries
989 * to send data even when none is asked for.
990 *
991 * Return nothing.
992 */
993void
994mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr)
995{
996 u32 flags_length = (u32)((MPI2_SGE_FLAGS_LAST_ELEMENT |
997 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST |
998 MPI2_SGE_FLAGS_SIMPLE_ELEMENT) <<
999 MPI2_SGE_FLAGS_SHIFT);
1000 ioc->base_add_sg_single(paddr, flags_length, -1);
1001}
1002
1003/**
1004 * _base_add_sg_single_32 - Place a simple 32 bit SGE at address pAddr.
1005 * @paddr: virtual address for SGE
1006 * @flags_length: SGE flags and data transfer length
1007 * @dma_addr: Physical address
1008 *
1009 * Return nothing.
1010 */
1011static void
1012_base_add_sg_single_32(void *paddr, u32 flags_length, dma_addr_t dma_addr)
1013{
1014 Mpi2SGESimple32_t *sgel = paddr;
1015
1016 flags_length |= (MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
1017 MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
1018 sgel->FlagsLength = cpu_to_le32(flags_length);
1019 sgel->Address = cpu_to_le32(dma_addr);
1020}
1021
1022
1023/**
1024 * _base_add_sg_single_64 - Place a simple 64 bit SGE at address pAddr.
1025 * @paddr: virtual address for SGE
1026 * @flags_length: SGE flags and data transfer length
1027 * @dma_addr: Physical address
1028 *
1029 * Return nothing.
1030 */
1031static void
1032_base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr)
1033{
1034 Mpi2SGESimple64_t *sgel = paddr;
1035
1036 flags_length |= (MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
1037 MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
1038 sgel->FlagsLength = cpu_to_le32(flags_length);
1039 sgel->Address = cpu_to_le64(dma_addr);
1040}
1041
1042#define convert_to_kb(x) ((x) << (PAGE_SHIFT - 10))
1043
1044/**
1045 * _base_config_dma_addressing - set dma addressing
1046 * @ioc: per adapter object
1047 * @pdev: PCI device struct
1048 *
1049 * Returns 0 for success, non-zero for failure.
1050 */
1051static int
1052_base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev)
1053{
1054 struct sysinfo s;
1055 char *desc = NULL;
1056
1057 if (sizeof(dma_addr_t) > 4) {
1058 const uint64_t required_mask =
1059 dma_get_required_mask(&pdev->dev);
Yang Hongyange9304382009-04-13 14:40:14 -07001060 if ((required_mask > DMA_BIT_MASK(32)) && !pci_set_dma_mask(pdev,
1061 DMA_BIT_MASK(64)) && !pci_set_consistent_dma_mask(pdev,
1062 DMA_BIT_MASK(64))) {
Eric Moore635374e2009-03-09 01:21:12 -06001063 ioc->base_add_sg_single = &_base_add_sg_single_64;
1064 ioc->sge_size = sizeof(Mpi2SGESimple64_t);
1065 desc = "64";
1066 goto out;
1067 }
1068 }
1069
Yang Hongyange9304382009-04-13 14:40:14 -07001070 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
1071 && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
Eric Moore635374e2009-03-09 01:21:12 -06001072 ioc->base_add_sg_single = &_base_add_sg_single_32;
1073 ioc->sge_size = sizeof(Mpi2SGESimple32_t);
1074 desc = "32";
1075 } else
1076 return -ENODEV;
1077
1078 out:
1079 si_meminfo(&s);
1080 printk(MPT2SAS_INFO_FMT "%s BIT PCI BUS DMA ADDRESSING SUPPORTED, "
1081 "total mem (%ld kB)\n", ioc->name, desc, convert_to_kb(s.totalram));
1082
1083 return 0;
1084}
1085
1086/**
Eric Moore635374e2009-03-09 01:21:12 -06001087 * _base_check_enable_msix - checks MSIX capabable.
1088 * @ioc: per adapter object
1089 *
1090 * Check to see if card is capable of MSIX, and set number
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001091 * of available msix vectors
Eric Moore635374e2009-03-09 01:21:12 -06001092 */
1093static int
1094_base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
1095{
1096 int base;
1097 u16 message_control;
Nagalakshmi Nandigamafca54d02012-01-04 09:25:13 -06001098
Eric Moore635374e2009-03-09 01:21:12 -06001099
1100 base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
1101 if (!base) {
1102 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not "
1103 "supported\n", ioc->name));
1104 return -EINVAL;
1105 }
1106
1107 /* get msix vector count */
1108 pci_read_config_word(ioc->pdev, base + 2, &message_control);
1109 ioc->msix_vector_count = (message_control & 0x3FF) + 1;
1110
Eric Moore635374e2009-03-09 01:21:12 -06001111 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, "
Nagalakshmi Nandigamafca54d02012-01-04 09:25:13 -06001112 "vector_count(%d)\n", ioc->name, ioc->msix_vector_count));
Eric Moore635374e2009-03-09 01:21:12 -06001113 return 0;
1114}
1115
1116/**
1117 * _base_disable_msix - disables msix
1118 * @ioc: per adapter object
1119 *
1120 */
1121static void
1122_base_disable_msix(struct MPT2SAS_ADAPTER *ioc)
1123{
1124 if (ioc->msix_enable) {
1125 pci_disable_msix(ioc->pdev);
Eric Moore635374e2009-03-09 01:21:12 -06001126 ioc->msix_enable = 0;
1127 }
1128}
1129
1130/**
1131 * _base_enable_msix - enables msix, failback to io_apic
1132 * @ioc: per adapter object
1133 *
1134 */
1135static int
1136_base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
1137{
1138 struct msix_entry entries;
1139 int r;
1140 u8 try_msix = 0;
1141
1142 if (msix_disable == -1 || msix_disable == 0)
1143 try_msix = 1;
1144
1145 if (!try_msix)
1146 goto try_ioapic;
1147
1148 if (_base_check_enable_msix(ioc) != 0)
1149 goto try_ioapic;
1150
Eric Moore635374e2009-03-09 01:21:12 -06001151 memset(&entries, 0, sizeof(struct msix_entry));
1152 r = pci_enable_msix(ioc->pdev, &entries, 1);
1153 if (r) {
1154 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "pci_enable_msix "
1155 "failed (r=%d) !!!\n", ioc->name, r));
1156 goto try_ioapic;
1157 }
1158
1159 r = request_irq(entries.vector, _base_interrupt, IRQF_SHARED,
1160 ioc->name, ioc);
1161 if (r) {
1162 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "unable to allocate "
1163 "interrupt %d !!!\n", ioc->name, entries.vector));
1164 pci_disable_msix(ioc->pdev);
1165 goto try_ioapic;
1166 }
1167
1168 ioc->pci_irq = entries.vector;
1169 ioc->msix_enable = 1;
1170 return 0;
1171
1172/* failback to io_apic interrupt routing */
1173 try_ioapic:
1174
1175 r = request_irq(ioc->pdev->irq, _base_interrupt, IRQF_SHARED,
1176 ioc->name, ioc);
1177 if (r) {
1178 printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n",
1179 ioc->name, ioc->pdev->irq);
1180 r = -EBUSY;
1181 goto out_fail;
1182 }
1183
1184 ioc->pci_irq = ioc->pdev->irq;
1185 return 0;
1186
1187 out_fail:
1188 return r;
1189}
1190
1191/**
1192 * mpt2sas_base_map_resources - map in controller resources (io/irq/memap)
1193 * @ioc: per adapter object
1194 *
1195 * Returns 0 for success, non-zero for failure.
1196 */
1197int
1198mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
1199{
1200 struct pci_dev *pdev = ioc->pdev;
1201 u32 memap_sz;
1202 u32 pio_sz;
1203 int i, r = 0;
Kashyap, Desai6846e752009-12-16 18:51:45 +05301204 u64 pio_chip = 0;
1205 u64 chip_phys = 0;
Eric Moore635374e2009-03-09 01:21:12 -06001206
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301207 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n",
Eric Moore635374e2009-03-09 01:21:12 -06001208 ioc->name, __func__));
1209
1210 ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
1211 if (pci_enable_device_mem(pdev)) {
1212 printk(MPT2SAS_WARN_FMT "pci_enable_device_mem: "
1213 "failed\n", ioc->name);
1214 return -ENODEV;
1215 }
1216
1217
1218 if (pci_request_selected_regions(pdev, ioc->bars,
1219 MPT2SAS_DRIVER_NAME)) {
1220 printk(MPT2SAS_WARN_FMT "pci_request_selected_regions: "
1221 "failed\n", ioc->name);
1222 r = -ENODEV;
1223 goto out_fail;
1224 }
1225
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05301226 /* AER (Advanced Error Reporting) hooks */
1227 pci_enable_pcie_error_reporting(pdev);
1228
Eric Moore635374e2009-03-09 01:21:12 -06001229 pci_set_master(pdev);
1230
1231 if (_base_config_dma_addressing(ioc, pdev) != 0) {
1232 printk(MPT2SAS_WARN_FMT "no suitable DMA mask for %s\n",
1233 ioc->name, pci_name(pdev));
1234 r = -ENODEV;
1235 goto out_fail;
1236 }
1237
1238 for (i = 0, memap_sz = 0, pio_sz = 0 ; i < DEVICE_COUNT_RESOURCE; i++) {
Richard A Laryfc193172010-03-12 15:27:06 -08001239 if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
Eric Moore635374e2009-03-09 01:21:12 -06001240 if (pio_sz)
1241 continue;
Kashyap, Desai6846e752009-12-16 18:51:45 +05301242 pio_chip = (u64)pci_resource_start(pdev, i);
Eric Moore635374e2009-03-09 01:21:12 -06001243 pio_sz = pci_resource_len(pdev, i);
1244 } else {
1245 if (memap_sz)
1246 continue;
Richard A Laryfc193172010-03-12 15:27:06 -08001247 /* verify memory resource is valid before using */
1248 if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
1249 ioc->chip_phys = pci_resource_start(pdev, i);
1250 chip_phys = (u64)ioc->chip_phys;
1251 memap_sz = pci_resource_len(pdev, i);
1252 ioc->chip = ioremap(ioc->chip_phys, memap_sz);
1253 if (ioc->chip == NULL) {
1254 printk(MPT2SAS_ERR_FMT "unable to map "
1255 "adapter memory!\n", ioc->name);
1256 r = -EINVAL;
1257 goto out_fail;
1258 }
Eric Moore635374e2009-03-09 01:21:12 -06001259 }
1260 }
1261 }
1262
Eric Moore635374e2009-03-09 01:21:12 -06001263 _base_mask_interrupts(ioc);
1264 r = _base_enable_msix(ioc);
1265 if (r)
1266 goto out_fail;
1267
1268 printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n",
1269 ioc->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
1270 "IO-APIC enabled"), ioc->pci_irq);
Kashyap, Desai6846e752009-12-16 18:51:45 +05301271 printk(MPT2SAS_INFO_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n",
1272 ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz);
1273 printk(MPT2SAS_INFO_FMT "ioport(0x%016llx), size(%d)\n",
1274 ioc->name, (unsigned long long)pio_chip, pio_sz);
Eric Moore635374e2009-03-09 01:21:12 -06001275
Eric Moore3cb54692010-07-08 14:44:34 -06001276 /* Save PCI configuration state for recovery from PCI AER/EEH errors */
1277 pci_save_state(pdev);
1278
Eric Moore635374e2009-03-09 01:21:12 -06001279 return 0;
1280
1281 out_fail:
1282 if (ioc->chip_phys)
1283 iounmap(ioc->chip);
1284 ioc->chip_phys = 0;
1285 ioc->pci_irq = -1;
1286 pci_release_selected_regions(ioc->pdev, ioc->bars);
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05301287 pci_disable_pcie_error_reporting(pdev);
Eric Moore635374e2009-03-09 01:21:12 -06001288 pci_disable_device(pdev);
Eric Moore635374e2009-03-09 01:21:12 -06001289 return r;
1290}
1291
1292/**
Eric Moore635374e2009-03-09 01:21:12 -06001293 * mpt2sas_base_get_msg_frame - obtain request mf pointer
1294 * @ioc: per adapter object
1295 * @smid: system request message index(smid zero is invalid)
1296 *
1297 * Returns virt pointer to message frame.
1298 */
1299void *
1300mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1301{
1302 return (void *)(ioc->request + (smid * ioc->request_sz));
1303}
1304
1305/**
1306 * mpt2sas_base_get_sense_buffer - obtain a sense buffer assigned to a mf request
1307 * @ioc: per adapter object
1308 * @smid: system request message index
1309 *
1310 * Returns virt pointer to sense buffer.
1311 */
1312void *
1313mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1314{
1315 return (void *)(ioc->sense + ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
1316}
1317
1318/**
1319 * mpt2sas_base_get_sense_buffer_dma - obtain a sense buffer assigned to a mf request
1320 * @ioc: per adapter object
1321 * @smid: system request message index
1322 *
Kashyap, Desaiec9472c2009-09-23 17:34:13 +05301323 * Returns phys pointer to the low 32bit address of the sense buffer.
Eric Moore635374e2009-03-09 01:21:12 -06001324 */
Kashyap, Desaiec9472c2009-09-23 17:34:13 +05301325__le32
Eric Moore635374e2009-03-09 01:21:12 -06001326mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1327{
Kashyap, Desaiec9472c2009-09-23 17:34:13 +05301328 return cpu_to_le32(ioc->sense_dma +
1329 ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
Eric Moore635374e2009-03-09 01:21:12 -06001330}
1331
1332/**
1333 * mpt2sas_base_get_reply_virt_addr - obtain reply frames virt address
1334 * @ioc: per adapter object
1335 * @phys_addr: lower 32 physical addr of the reply
1336 *
1337 * Converts 32bit lower physical addr into a virt address.
1338 */
1339void *
1340mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr)
1341{
1342 if (!phys_addr)
1343 return NULL;
1344 return ioc->reply + (phys_addr - (u32)ioc->reply_dma);
1345}
1346
1347/**
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301348 * mpt2sas_base_get_smid - obtain a free smid from internal queue
Eric Moore635374e2009-03-09 01:21:12 -06001349 * @ioc: per adapter object
1350 * @cb_idx: callback index
1351 *
1352 * Returns smid (zero is invalid)
1353 */
1354u16
1355mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx)
1356{
1357 unsigned long flags;
1358 struct request_tracker *request;
1359 u16 smid;
1360
1361 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301362 if (list_empty(&ioc->internal_free_list)) {
1363 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1364 printk(MPT2SAS_ERR_FMT "%s: smid not available\n",
1365 ioc->name, __func__);
1366 return 0;
1367 }
1368
1369 request = list_entry(ioc->internal_free_list.next,
1370 struct request_tracker, tracker_list);
1371 request->cb_idx = cb_idx;
1372 smid = request->smid;
1373 list_del(&request->tracker_list);
1374 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1375 return smid;
1376}
1377
1378/**
1379 * mpt2sas_base_get_smid_scsiio - obtain a free smid from scsiio queue
1380 * @ioc: per adapter object
1381 * @cb_idx: callback index
1382 * @scmd: pointer to scsi command object
1383 *
1384 * Returns smid (zero is invalid)
1385 */
1386u16
1387mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx,
1388 struct scsi_cmnd *scmd)
1389{
1390 unsigned long flags;
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05301391 struct scsiio_tracker *request;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301392 u16 smid;
1393
1394 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06001395 if (list_empty(&ioc->free_list)) {
1396 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1397 printk(MPT2SAS_ERR_FMT "%s: smid not available\n",
1398 ioc->name, __func__);
1399 return 0;
1400 }
1401
1402 request = list_entry(ioc->free_list.next,
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05301403 struct scsiio_tracker, tracker_list);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301404 request->scmd = scmd;
1405 request->cb_idx = cb_idx;
1406 smid = request->smid;
1407 list_del(&request->tracker_list);
1408 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1409 return smid;
1410}
1411
1412/**
1413 * mpt2sas_base_get_smid_hpr - obtain a free smid from hi-priority queue
1414 * @ioc: per adapter object
1415 * @cb_idx: callback index
1416 *
1417 * Returns smid (zero is invalid)
1418 */
1419u16
1420mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx)
1421{
1422 unsigned long flags;
1423 struct request_tracker *request;
1424 u16 smid;
1425
1426 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1427 if (list_empty(&ioc->hpr_free_list)) {
1428 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1429 return 0;
1430 }
1431
1432 request = list_entry(ioc->hpr_free_list.next,
1433 struct request_tracker, tracker_list);
Eric Moore635374e2009-03-09 01:21:12 -06001434 request->cb_idx = cb_idx;
1435 smid = request->smid;
1436 list_del(&request->tracker_list);
1437 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1438 return smid;
1439}
1440
1441
1442/**
1443 * mpt2sas_base_free_smid - put smid back on free_list
1444 * @ioc: per adapter object
1445 * @smid: system request message index
1446 *
1447 * Return nothing.
1448 */
1449void
1450mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1451{
1452 unsigned long flags;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301453 int i;
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301454 struct chain_tracker *chain_req, *next;
Eric Moore635374e2009-03-09 01:21:12 -06001455
1456 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05301457 if (smid < ioc->hi_priority_smid) {
1458 /* scsiio queue */
1459 i = smid - 1;
1460 if (!list_empty(&ioc->scsi_lookup[i].chain_list)) {
1461 list_for_each_entry_safe(chain_req, next,
1462 &ioc->scsi_lookup[i].chain_list, tracker_list) {
1463 list_del_init(&chain_req->tracker_list);
1464 list_add_tail(&chain_req->tracker_list,
1465 &ioc->free_chain_list);
1466 }
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301467 }
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05301468 ioc->scsi_lookup[i].cb_idx = 0xFF;
1469 ioc->scsi_lookup[i].scmd = NULL;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301470 ioc->scsi_lookup[i].direct_io = 0;
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05301471 list_add_tail(&ioc->scsi_lookup[i].tracker_list,
1472 &ioc->free_list);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301473 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301474
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05301475 /*
1476 * See _wait_for_commands_to_complete() call with regards
1477 * to this code.
1478 */
1479 if (ioc->shost_recovery && ioc->pending_io_count) {
1480 if (ioc->pending_io_count == 1)
1481 wake_up(&ioc->reset_wq);
1482 ioc->pending_io_count--;
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301483 }
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05301484 return;
1485 } else if (smid < ioc->internal_smid) {
1486 /* hi-priority */
1487 i = smid - ioc->hi_priority_smid;
1488 ioc->hpr_lookup[i].cb_idx = 0xFF;
1489 list_add_tail(&ioc->hpr_lookup[i].tracker_list,
1490 &ioc->hpr_free_list);
1491 } else if (smid <= ioc->hba_queue_depth) {
1492 /* internal queue */
1493 i = smid - ioc->internal_smid;
1494 ioc->internal_lookup[i].cb_idx = 0xFF;
1495 list_add_tail(&ioc->internal_lookup[i].tracker_list,
1496 &ioc->internal_free_list);
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301497 }
Eric Moore635374e2009-03-09 01:21:12 -06001498 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06001499}
1500
1501/**
1502 * _base_writeq - 64 bit write to MMIO
1503 * @ioc: per adapter object
1504 * @b: data payload
1505 * @addr: address in MMIO space
1506 * @writeq_lock: spin lock
1507 *
1508 * Glue for handling an atomic 64 bit word to MMIO. This special handling takes
1509 * care of 32 bit environment where its not quarenteed to send the entire word
1510 * in one transfer.
1511 */
1512#ifndef writeq
1513static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
1514 spinlock_t *writeq_lock)
1515{
1516 unsigned long flags;
1517 __u64 data_out = cpu_to_le64(b);
1518
1519 spin_lock_irqsave(writeq_lock, flags);
1520 writel((u32)(data_out), addr);
1521 writel((u32)(data_out >> 32), (addr + 4));
1522 spin_unlock_irqrestore(writeq_lock, flags);
1523}
1524#else
1525static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
1526 spinlock_t *writeq_lock)
1527{
1528 writeq(cpu_to_le64(b), addr);
1529}
1530#endif
1531
1532/**
1533 * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware
1534 * @ioc: per adapter object
1535 * @smid: system request message index
Eric Moore635374e2009-03-09 01:21:12 -06001536 * @handle: device handle
1537 *
1538 * Return nothing.
1539 */
1540void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301541mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u16 handle)
Eric Moore635374e2009-03-09 01:21:12 -06001542{
1543 Mpi2RequestDescriptorUnion_t descriptor;
1544 u64 *request = (u64 *)&descriptor;
1545
1546
1547 descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301548 descriptor.SCSIIO.MSIxIndex = 0; /* TODO */
Eric Moore635374e2009-03-09 01:21:12 -06001549 descriptor.SCSIIO.SMID = cpu_to_le16(smid);
1550 descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
1551 descriptor.SCSIIO.LMID = 0;
1552 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1553 &ioc->scsi_lookup_lock);
1554}
1555
1556
1557/**
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001558 * mpt2sas_base_put_smid_hi_priority - send Task Management request to firmware
Eric Moore635374e2009-03-09 01:21:12 -06001559 * @ioc: per adapter object
1560 * @smid: system request message index
Eric Moore635374e2009-03-09 01:21:12 -06001561 *
1562 * Return nothing.
1563 */
1564void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301565mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid)
Eric Moore635374e2009-03-09 01:21:12 -06001566{
1567 Mpi2RequestDescriptorUnion_t descriptor;
1568 u64 *request = (u64 *)&descriptor;
1569
1570 descriptor.HighPriority.RequestFlags =
1571 MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301572 descriptor.HighPriority.MSIxIndex = 0; /* TODO */
Eric Moore635374e2009-03-09 01:21:12 -06001573 descriptor.HighPriority.SMID = cpu_to_le16(smid);
1574 descriptor.HighPriority.LMID = 0;
1575 descriptor.HighPriority.Reserved1 = 0;
1576 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1577 &ioc->scsi_lookup_lock);
1578}
1579
1580/**
1581 * mpt2sas_base_put_smid_default - Default, primarily used for config pages
1582 * @ioc: per adapter object
1583 * @smid: system request message index
Eric Moore635374e2009-03-09 01:21:12 -06001584 *
1585 * Return nothing.
1586 */
1587void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301588mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid)
Eric Moore635374e2009-03-09 01:21:12 -06001589{
1590 Mpi2RequestDescriptorUnion_t descriptor;
1591 u64 *request = (u64 *)&descriptor;
1592
1593 descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301594 descriptor.Default.MSIxIndex = 0; /* TODO */
Eric Moore635374e2009-03-09 01:21:12 -06001595 descriptor.Default.SMID = cpu_to_le16(smid);
1596 descriptor.Default.LMID = 0;
1597 descriptor.Default.DescriptorTypeDependent = 0;
1598 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1599 &ioc->scsi_lookup_lock);
1600}
1601
1602/**
1603 * mpt2sas_base_put_smid_target_assist - send Target Assist/Status to firmware
1604 * @ioc: per adapter object
1605 * @smid: system request message index
Eric Moore635374e2009-03-09 01:21:12 -06001606 * @io_index: value used to track the IO
1607 *
1608 * Return nothing.
1609 */
1610void
1611mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301612 u16 io_index)
Eric Moore635374e2009-03-09 01:21:12 -06001613{
1614 Mpi2RequestDescriptorUnion_t descriptor;
1615 u64 *request = (u64 *)&descriptor;
1616
1617 descriptor.SCSITarget.RequestFlags =
1618 MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301619 descriptor.SCSITarget.MSIxIndex = 0; /* TODO */
Eric Moore635374e2009-03-09 01:21:12 -06001620 descriptor.SCSITarget.SMID = cpu_to_le16(smid);
1621 descriptor.SCSITarget.LMID = 0;
1622 descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index);
1623 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1624 &ioc->scsi_lookup_lock);
1625}
1626
1627/**
Eric Mooref0f9cc12009-04-21 15:40:48 -06001628 * _base_display_dell_branding - Disply branding string
1629 * @ioc: per adapter object
1630 *
1631 * Return nothing.
1632 */
1633static void
1634_base_display_dell_branding(struct MPT2SAS_ADAPTER *ioc)
1635{
1636 char dell_branding[MPT2SAS_DELL_BRANDING_SIZE];
1637
1638 if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_DELL)
1639 return;
1640
1641 memset(dell_branding, 0, MPT2SAS_DELL_BRANDING_SIZE);
1642 switch (ioc->pdev->subsystem_device) {
1643 case MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID:
1644 strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING,
1645 MPT2SAS_DELL_BRANDING_SIZE - 1);
1646 break;
1647 case MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID:
1648 strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING,
1649 MPT2SAS_DELL_BRANDING_SIZE - 1);
1650 break;
1651 case MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID:
1652 strncpy(dell_branding,
1653 MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING,
1654 MPT2SAS_DELL_BRANDING_SIZE - 1);
1655 break;
1656 case MPT2SAS_DELL_PERC_H200_MODULAR_SSDID:
1657 strncpy(dell_branding,
1658 MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING,
1659 MPT2SAS_DELL_BRANDING_SIZE - 1);
1660 break;
1661 case MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID:
1662 strncpy(dell_branding,
1663 MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING,
1664 MPT2SAS_DELL_BRANDING_SIZE - 1);
1665 break;
1666 case MPT2SAS_DELL_PERC_H200_SSDID:
1667 strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_BRANDING,
1668 MPT2SAS_DELL_BRANDING_SIZE - 1);
1669 break;
1670 case MPT2SAS_DELL_6GBPS_SAS_SSDID:
1671 strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_BRANDING,
1672 MPT2SAS_DELL_BRANDING_SIZE - 1);
1673 break;
1674 default:
1675 sprintf(dell_branding, "0x%4X", ioc->pdev->subsystem_device);
1676 break;
1677 }
1678
1679 printk(MPT2SAS_INFO_FMT "%s: Vendor(0x%04X), Device(0x%04X),"
1680 " SSVID(0x%04X), SSDID(0x%04X)\n", ioc->name, dell_branding,
1681 ioc->pdev->vendor, ioc->pdev->device, ioc->pdev->subsystem_vendor,
1682 ioc->pdev->subsystem_device);
1683}
1684
1685/**
Kashyap, Desaifb396be2011-01-04 11:36:37 +05301686 * _base_display_intel_branding - Display branding string
1687 * @ioc: per adapter object
1688 *
1689 * Return nothing.
1690 */
1691static void
1692_base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
1693{
Kashyap, Desaie670d472011-06-14 10:57:31 +05301694 if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL)
1695 return;
Kashyap, Desaifb396be2011-01-04 11:36:37 +05301696
Kashyap, Desaie670d472011-06-14 10:57:31 +05301697 switch (ioc->pdev->device) {
1698 case MPI2_MFGPAGE_DEVID_SAS2008:
Kashyap, Desaifb396be2011-01-04 11:36:37 +05301699 switch (ioc->pdev->subsystem_device) {
1700 case MPT2SAS_INTEL_RMS2LL080_SSDID:
1701 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1702 MPT2SAS_INTEL_RMS2LL080_BRANDING);
1703 break;
1704 case MPT2SAS_INTEL_RMS2LL040_SSDID:
1705 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1706 MPT2SAS_INTEL_RMS2LL040_BRANDING);
1707 break;
Kashyap, Desaie670d472011-06-14 10:57:31 +05301708 default:
1709 break;
Kashyap, Desaifb396be2011-01-04 11:36:37 +05301710 }
Kashyap, Desaie670d472011-06-14 10:57:31 +05301711 case MPI2_MFGPAGE_DEVID_SAS2308_2:
1712 switch (ioc->pdev->subsystem_device) {
1713 case MPT2SAS_INTEL_RS25GB008_SSDID:
1714 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1715 MPT2SAS_INTEL_RS25GB008_BRANDING);
1716 break;
1717 default:
1718 break;
1719 }
1720 default:
1721 break;
Kashyap, Desaifb396be2011-01-04 11:36:37 +05301722 }
1723}
1724
1725/**
Kashyap, Desai0a2385c2011-03-15 20:04:26 +05301726 * _base_display_hp_branding - Display branding string
1727 * @ioc: per adapter object
1728 *
1729 * Return nothing.
1730 */
1731static void
1732_base_display_hp_branding(struct MPT2SAS_ADAPTER *ioc)
1733{
1734 if (ioc->pdev->subsystem_vendor != MPT2SAS_HP_3PAR_SSVID)
1735 return;
1736
1737 switch (ioc->pdev->device) {
1738 case MPI2_MFGPAGE_DEVID_SAS2004:
1739 switch (ioc->pdev->subsystem_device) {
1740 case MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID:
1741 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1742 MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING);
1743 break;
1744 default:
1745 break;
1746 }
1747 case MPI2_MFGPAGE_DEVID_SAS2308_2:
1748 switch (ioc->pdev->subsystem_device) {
1749 case MPT2SAS_HP_2_4_INTERNAL_SSDID:
1750 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1751 MPT2SAS_HP_2_4_INTERNAL_BRANDING);
1752 break;
1753 case MPT2SAS_HP_2_4_EXTERNAL_SSDID:
1754 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1755 MPT2SAS_HP_2_4_EXTERNAL_BRANDING);
1756 break;
1757 case MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID:
1758 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1759 MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING);
1760 break;
1761 case MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID:
1762 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1763 MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING);
1764 break;
1765 default:
1766 break;
1767 }
1768 default:
1769 break;
1770 }
1771}
1772
1773/**
Eric Moore635374e2009-03-09 01:21:12 -06001774 * _base_display_ioc_capabilities - Disply IOC's capabilities.
1775 * @ioc: per adapter object
1776 *
1777 * Return nothing.
1778 */
1779static void
1780_base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
1781{
1782 int i = 0;
1783 char desc[16];
1784 u8 revision;
1785 u32 iounit_pg1_flags;
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05301786 u32 bios_version;
Eric Moore635374e2009-03-09 01:21:12 -06001787
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05301788 bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
Eric Moore635374e2009-03-09 01:21:12 -06001789 pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision);
1790 strncpy(desc, ioc->manu_pg0.ChipName, 16);
1791 printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "
1792 "ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n",
1793 ioc->name, desc,
1794 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
1795 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
1796 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
1797 ioc->facts.FWVersion.Word & 0x000000FF,
1798 revision,
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05301799 (bios_version & 0xFF000000) >> 24,
1800 (bios_version & 0x00FF0000) >> 16,
1801 (bios_version & 0x0000FF00) >> 8,
1802 bios_version & 0x000000FF);
Eric Moore635374e2009-03-09 01:21:12 -06001803
Kashyap, Desaied79f122009-08-20 13:23:49 +05301804 _base_display_dell_branding(ioc);
Kashyap, Desaifb396be2011-01-04 11:36:37 +05301805 _base_display_intel_branding(ioc);
Kashyap, Desai0a2385c2011-03-15 20:04:26 +05301806 _base_display_hp_branding(ioc);
Kashyap, Desaied79f122009-08-20 13:23:49 +05301807
Eric Moore635374e2009-03-09 01:21:12 -06001808 printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name);
1809
1810 if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) {
1811 printk("Initiator");
1812 i++;
1813 }
1814
1815 if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET) {
1816 printk("%sTarget", i ? "," : "");
1817 i++;
1818 }
1819
1820 i = 0;
1821 printk("), ");
1822 printk("Capabilities=(");
1823
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301824 if (!ioc->hide_ir_msg) {
1825 if (ioc->facts.IOCCapabilities &
1826 MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
1827 printk("Raid");
1828 i++;
1829 }
Eric Moore635374e2009-03-09 01:21:12 -06001830 }
1831
1832 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) {
1833 printk("%sTLR", i ? "," : "");
1834 i++;
1835 }
1836
1837 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_MULTICAST) {
1838 printk("%sMulticast", i ? "," : "");
1839 i++;
1840 }
1841
1842 if (ioc->facts.IOCCapabilities &
1843 MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET) {
1844 printk("%sBIDI Target", i ? "," : "");
1845 i++;
1846 }
1847
1848 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) {
1849 printk("%sEEDP", i ? "," : "");
1850 i++;
1851 }
1852
1853 if (ioc->facts.IOCCapabilities &
1854 MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) {
1855 printk("%sSnapshot Buffer", i ? "," : "");
1856 i++;
1857 }
1858
1859 if (ioc->facts.IOCCapabilities &
1860 MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) {
1861 printk("%sDiag Trace Buffer", i ? "," : "");
1862 i++;
1863 }
1864
1865 if (ioc->facts.IOCCapabilities &
Kashyap, Desai1b01fe32009-09-23 17:28:59 +05301866 MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) {
1867 printk(KERN_INFO "%sDiag Extended Buffer", i ? "," : "");
1868 i++;
1869 }
1870
1871 if (ioc->facts.IOCCapabilities &
Eric Moore635374e2009-03-09 01:21:12 -06001872 MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) {
1873 printk("%sTask Set Full", i ? "," : "");
1874 i++;
1875 }
1876
1877 iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
1878 if (!(iounit_pg1_flags & MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE)) {
1879 printk("%sNCQ", i ? "," : "");
1880 i++;
1881 }
1882
1883 printk(")\n");
1884}
1885
1886/**
Kashyap, Desai6cb8ef52010-11-13 04:32:18 +05301887 * _base_update_missing_delay - change the missing delay timers
1888 * @ioc: per adapter object
1889 * @device_missing_delay: amount of time till device is reported missing
1890 * @io_missing_delay: interval IO is returned when there is a missing device
1891 *
1892 * Return nothing.
1893 *
1894 * Passed on the command line, this function will modify the device missing
1895 * delay, as well as the io missing delay. This should be called at driver
1896 * load time.
1897 */
1898static void
1899_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
1900 u16 device_missing_delay, u8 io_missing_delay)
1901{
1902 u16 dmd, dmd_new, dmd_orignal;
1903 u8 io_missing_delay_original;
1904 u16 sz;
1905 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1906 Mpi2ConfigReply_t mpi_reply;
1907 u8 num_phys = 0;
1908 u16 ioc_status;
1909
1910 mpt2sas_config_get_number_hba_phys(ioc, &num_phys);
1911 if (!num_phys)
1912 return;
1913
1914 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (num_phys *
1915 sizeof(Mpi2SasIOUnit1PhyData_t));
1916 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1917 if (!sas_iounit_pg1) {
1918 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1919 ioc->name, __FILE__, __LINE__, __func__);
1920 goto out;
1921 }
1922 if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1923 sas_iounit_pg1, sz))) {
1924 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1925 ioc->name, __FILE__, __LINE__, __func__);
1926 goto out;
1927 }
1928 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1929 MPI2_IOCSTATUS_MASK;
1930 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1931 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1932 ioc->name, __FILE__, __LINE__, __func__);
1933 goto out;
1934 }
1935
1936 /* device missing delay */
1937 dmd = sas_iounit_pg1->ReportDeviceMissingDelay;
1938 if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
1939 dmd = (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
1940 else
1941 dmd = dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
1942 dmd_orignal = dmd;
1943 if (device_missing_delay > 0x7F) {
1944 dmd = (device_missing_delay > 0x7F0) ? 0x7F0 :
1945 device_missing_delay;
1946 dmd = dmd / 16;
1947 dmd |= MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16;
1948 } else
1949 dmd = device_missing_delay;
1950 sas_iounit_pg1->ReportDeviceMissingDelay = dmd;
1951
1952 /* io missing delay */
1953 io_missing_delay_original = sas_iounit_pg1->IODeviceMissingDelay;
1954 sas_iounit_pg1->IODeviceMissingDelay = io_missing_delay;
1955
1956 if (!mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
1957 sz)) {
1958 if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
1959 dmd_new = (dmd &
1960 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
1961 else
1962 dmd_new =
1963 dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
1964 printk(MPT2SAS_INFO_FMT "device_missing_delay: old(%d), "
1965 "new(%d)\n", ioc->name, dmd_orignal, dmd_new);
1966 printk(MPT2SAS_INFO_FMT "ioc_missing_delay: old(%d), "
1967 "new(%d)\n", ioc->name, io_missing_delay_original,
1968 io_missing_delay);
1969 ioc->device_missing_delay = dmd_new;
1970 ioc->io_missing_delay = io_missing_delay;
1971 }
1972
1973out:
1974 kfree(sas_iounit_pg1);
1975}
1976
1977/**
Eric Moore635374e2009-03-09 01:21:12 -06001978 * _base_static_config_pages - static start of day config pages
1979 * @ioc: per adapter object
1980 *
1981 * Return nothing.
1982 */
1983static void
1984_base_static_config_pages(struct MPT2SAS_ADAPTER *ioc)
1985{
1986 Mpi2ConfigReply_t mpi_reply;
1987 u32 iounit_pg1_flags;
1988
1989 mpt2sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0);
Kashyap, Desaied79f122009-08-20 13:23:49 +05301990 if (ioc->ir_firmware)
1991 mpt2sas_config_get_manufacturing_pg10(ioc, &mpi_reply,
1992 &ioc->manu_pg10);
Eric Moore635374e2009-03-09 01:21:12 -06001993 mpt2sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
1994 mpt2sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
1995 mpt2sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8);
1996 mpt2sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0);
1997 mpt2sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
1998 _base_display_ioc_capabilities(ioc);
1999
2000 /*
2001 * Enable task_set_full handling in iounit_pg1 when the
2002 * facts capabilities indicate that its supported.
2003 */
2004 iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
2005 if ((ioc->facts.IOCCapabilities &
2006 MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING))
2007 iounit_pg1_flags &=
2008 ~MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
2009 else
2010 iounit_pg1_flags |=
2011 MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
2012 ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags);
Kashyap, Desai5b768582009-08-20 13:24:31 +05302013 mpt2sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
Kashyap, Desai6cb8ef52010-11-13 04:32:18 +05302014
Eric Moore635374e2009-03-09 01:21:12 -06002015}
2016
2017/**
2018 * _base_release_memory_pools - release memory
2019 * @ioc: per adapter object
2020 *
2021 * Free memory allocated from _base_allocate_memory_pools.
2022 *
2023 * Return nothing.
2024 */
2025static void
2026_base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
2027{
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302028 int i;
2029
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302030 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06002031 __func__));
2032
2033 if (ioc->request) {
2034 pci_free_consistent(ioc->pdev, ioc->request_dma_sz,
2035 ioc->request, ioc->request_dma);
2036 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "request_pool(0x%p)"
2037 ": free\n", ioc->name, ioc->request));
2038 ioc->request = NULL;
2039 }
2040
2041 if (ioc->sense) {
2042 pci_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma);
2043 if (ioc->sense_dma_pool)
2044 pci_pool_destroy(ioc->sense_dma_pool);
2045 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_pool(0x%p)"
2046 ": free\n", ioc->name, ioc->sense));
2047 ioc->sense = NULL;
2048 }
2049
2050 if (ioc->reply) {
2051 pci_pool_free(ioc->reply_dma_pool, ioc->reply, ioc->reply_dma);
2052 if (ioc->reply_dma_pool)
2053 pci_pool_destroy(ioc->reply_dma_pool);
2054 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_pool(0x%p)"
2055 ": free\n", ioc->name, ioc->reply));
2056 ioc->reply = NULL;
2057 }
2058
2059 if (ioc->reply_free) {
2060 pci_pool_free(ioc->reply_free_dma_pool, ioc->reply_free,
2061 ioc->reply_free_dma);
2062 if (ioc->reply_free_dma_pool)
2063 pci_pool_destroy(ioc->reply_free_dma_pool);
2064 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_pool"
2065 "(0x%p): free\n", ioc->name, ioc->reply_free));
2066 ioc->reply_free = NULL;
2067 }
2068
2069 if (ioc->reply_post_free) {
2070 pci_pool_free(ioc->reply_post_free_dma_pool,
2071 ioc->reply_post_free, ioc->reply_post_free_dma);
2072 if (ioc->reply_post_free_dma_pool)
2073 pci_pool_destroy(ioc->reply_post_free_dma_pool);
2074 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
2075 "reply_post_free_pool(0x%p): free\n", ioc->name,
2076 ioc->reply_post_free));
2077 ioc->reply_post_free = NULL;
2078 }
2079
2080 if (ioc->config_page) {
2081 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
2082 "config_page(0x%p): free\n", ioc->name,
2083 ioc->config_page));
2084 pci_free_consistent(ioc->pdev, ioc->config_page_sz,
2085 ioc->config_page, ioc->config_page_dma);
2086 }
2087
Kashyap, Desai66a67932010-04-05 14:21:07 +05302088 if (ioc->scsi_lookup) {
2089 free_pages((ulong)ioc->scsi_lookup, ioc->scsi_lookup_pages);
2090 ioc->scsi_lookup = NULL;
2091 }
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302092 kfree(ioc->hpr_lookup);
2093 kfree(ioc->internal_lookup);
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302094 if (ioc->chain_lookup) {
2095 for (i = 0; i < ioc->chain_depth; i++) {
2096 if (ioc->chain_lookup[i].chain_buffer)
2097 pci_pool_free(ioc->chain_dma_pool,
2098 ioc->chain_lookup[i].chain_buffer,
2099 ioc->chain_lookup[i].chain_buffer_dma);
2100 }
2101 if (ioc->chain_dma_pool)
2102 pci_pool_destroy(ioc->chain_dma_pool);
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302103 free_pages((ulong)ioc->chain_lookup, ioc->chain_pages);
2104 ioc->chain_lookup = NULL;
2105 }
Eric Moore635374e2009-03-09 01:21:12 -06002106}
2107
2108
2109/**
2110 * _base_allocate_memory_pools - allocate start of day memory pools
2111 * @ioc: per adapter object
2112 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2113 *
2114 * Returns 0 success, anything else error
2115 */
2116static int
2117_base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2118{
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05302119 struct mpt2sas_facts *facts;
Eric Moore635374e2009-03-09 01:21:12 -06002120 u16 max_sge_elements;
Eric Moore635374e2009-03-09 01:21:12 -06002121 u16 chains_needed_per_io;
2122 u32 sz, total_sz;
Eric Moore635374e2009-03-09 01:21:12 -06002123 u32 retry_sz;
2124 u16 max_request_credit;
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302125 int i;
Eric Moore635374e2009-03-09 01:21:12 -06002126
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302127 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06002128 __func__));
2129
2130 retry_sz = 0;
2131 facts = &ioc->facts;
2132
2133 /* command line tunables for max sgl entries */
2134 if (max_sgl_entries != -1) {
2135 ioc->shost->sg_tablesize = (max_sgl_entries <
2136 MPT2SAS_SG_DEPTH) ? max_sgl_entries :
2137 MPT2SAS_SG_DEPTH;
2138 } else {
2139 ioc->shost->sg_tablesize = MPT2SAS_SG_DEPTH;
2140 }
2141
2142 /* command line tunables for max controller queue depth */
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302143 if (max_queue_depth != -1)
Eric Moore635374e2009-03-09 01:21:12 -06002144 max_request_credit = (max_queue_depth < facts->RequestCredit)
2145 ? max_queue_depth : facts->RequestCredit;
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302146 else
nagalakshmi.nandigama@lsi.com73669de2011-12-01 07:53:08 +05302147 max_request_credit = min_t(u16, facts->RequestCredit,
2148 MAX_HBA_QUEUE_DEPTH);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302149
2150 ioc->hba_queue_depth = max_request_credit;
2151 ioc->hi_priority_depth = facts->HighPriorityCredit;
2152 ioc->internal_depth = ioc->hi_priority_depth + 5;
Eric Moore635374e2009-03-09 01:21:12 -06002153
2154 /* request frame size */
2155 ioc->request_sz = facts->IOCRequestFrameSize * 4;
2156
2157 /* reply frame size */
2158 ioc->reply_sz = facts->ReplyFrameSize * 4;
2159
2160 retry_allocation:
2161 total_sz = 0;
2162 /* calculate number of sg elements left over in the 1st frame */
2163 max_sge_elements = ioc->request_sz - ((sizeof(Mpi2SCSIIORequest_t) -
2164 sizeof(Mpi2SGEIOUnion_t)) + ioc->sge_size);
2165 ioc->max_sges_in_main_message = max_sge_elements/ioc->sge_size;
2166
2167 /* now do the same for a chain buffer */
2168 max_sge_elements = ioc->request_sz - ioc->sge_size;
2169 ioc->max_sges_in_chain_message = max_sge_elements/ioc->sge_size;
2170
2171 ioc->chain_offset_value_for_main_message =
2172 ((sizeof(Mpi2SCSIIORequest_t) - sizeof(Mpi2SGEIOUnion_t)) +
2173 (ioc->max_sges_in_chain_message * ioc->sge_size)) / 4;
2174
2175 /*
2176 * MPT2SAS_SG_DEPTH = CONFIG_FUSION_MAX_SGE
2177 */
2178 chains_needed_per_io = ((ioc->shost->sg_tablesize -
2179 ioc->max_sges_in_main_message)/ioc->max_sges_in_chain_message)
2180 + 1;
2181 if (chains_needed_per_io > facts->MaxChainDepth) {
2182 chains_needed_per_io = facts->MaxChainDepth;
2183 ioc->shost->sg_tablesize = min_t(u16,
2184 ioc->max_sges_in_main_message + (ioc->max_sges_in_chain_message
2185 * chains_needed_per_io), ioc->shost->sg_tablesize);
2186 }
2187 ioc->chains_needed_per_io = chains_needed_per_io;
2188
nagalakshmi.nandigama@lsi.com73669de2011-12-01 07:53:08 +05302189 /* reply free queue sizing - taking into account for 64 FW events */
2190 ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
Eric Moore635374e2009-03-09 01:21:12 -06002191
nagalakshmi.nandigama@lsi.com73669de2011-12-01 07:53:08 +05302192 /* align the reply post queue on the next 16 count boundary */
2193 if (!ioc->reply_free_queue_depth % 16)
2194 ioc->reply_post_queue_depth = ioc->reply_free_queue_depth + 16;
2195 else
2196 ioc->reply_post_queue_depth = ioc->reply_free_queue_depth +
2197 32 - (ioc->reply_free_queue_depth % 16);
2198 if (ioc->reply_post_queue_depth >
2199 facts->MaxReplyDescriptorPostQueueDepth) {
2200 ioc->reply_post_queue_depth = min_t(u16,
2201 (facts->MaxReplyDescriptorPostQueueDepth -
2202 (facts->MaxReplyDescriptorPostQueueDepth % 16)),
2203 (ioc->hba_queue_depth - (ioc->hba_queue_depth % 16)));
2204 ioc->reply_free_queue_depth = ioc->reply_post_queue_depth - 16;
2205 ioc->hba_queue_depth = ioc->reply_free_queue_depth - 64;
Eric Moore635374e2009-03-09 01:21:12 -06002206 }
nagalakshmi.nandigama@lsi.com73669de2011-12-01 07:53:08 +05302207
Eric Moore635374e2009-03-09 01:21:12 -06002208
Eric Moore635374e2009-03-09 01:21:12 -06002209 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: "
2210 "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), "
2211 "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message,
2212 ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize,
2213 ioc->chains_needed_per_io));
2214
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302215 ioc->scsiio_depth = ioc->hba_queue_depth -
2216 ioc->hi_priority_depth - ioc->internal_depth;
2217
2218 /* set the scsi host can_queue depth
2219 * with some internal commands that could be outstanding
2220 */
2221 ioc->shost->can_queue = ioc->scsiio_depth - (2);
2222 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: "
2223 "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue));
2224
Eric Moore635374e2009-03-09 01:21:12 -06002225 /* contiguous pool for request and chains, 16 byte align, one extra "
2226 * "frame for smid=0
2227 */
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302228 ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth;
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302229 sz = ((ioc->scsiio_depth + 1) * ioc->request_sz);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302230
2231 /* hi-priority queue */
2232 sz += (ioc->hi_priority_depth * ioc->request_sz);
2233
2234 /* internal queue */
2235 sz += (ioc->internal_depth * ioc->request_sz);
Eric Moore635374e2009-03-09 01:21:12 -06002236
2237 ioc->request_dma_sz = sz;
2238 ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma);
2239 if (!ioc->request) {
2240 printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent "
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302241 "failed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), "
2242 "total(%d kB)\n", ioc->name, ioc->hba_queue_depth,
Eric Moore635374e2009-03-09 01:21:12 -06002243 ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302244 if (ioc->scsiio_depth < MPT2SAS_SAS_QUEUE_DEPTH)
Eric Moore635374e2009-03-09 01:21:12 -06002245 goto out;
2246 retry_sz += 64;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302247 ioc->hba_queue_depth = max_request_credit - retry_sz;
Eric Moore635374e2009-03-09 01:21:12 -06002248 goto retry_allocation;
2249 }
2250
2251 if (retry_sz)
2252 printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent "
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302253 "succeed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), "
2254 "total(%d kb)\n", ioc->name, ioc->hba_queue_depth,
Eric Moore635374e2009-03-09 01:21:12 -06002255 ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
2256
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302257
2258 /* hi-priority queue */
2259 ioc->hi_priority = ioc->request + ((ioc->scsiio_depth + 1) *
Eric Moore635374e2009-03-09 01:21:12 -06002260 ioc->request_sz);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302261 ioc->hi_priority_dma = ioc->request_dma + ((ioc->scsiio_depth + 1) *
Eric Moore635374e2009-03-09 01:21:12 -06002262 ioc->request_sz);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302263
2264 /* internal queue */
2265 ioc->internal = ioc->hi_priority + (ioc->hi_priority_depth *
2266 ioc->request_sz);
2267 ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth *
2268 ioc->request_sz);
2269
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302270
Eric Moore635374e2009-03-09 01:21:12 -06002271 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): "
2272 "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302273 ioc->request, ioc->hba_queue_depth, ioc->request_sz,
2274 (ioc->hba_queue_depth * ioc->request_sz)/1024));
Eric Moore635374e2009-03-09 01:21:12 -06002275 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool: dma(0x%llx)\n",
2276 ioc->name, (unsigned long long) ioc->request_dma));
2277 total_sz += sz;
2278
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05302279 sz = ioc->scsiio_depth * sizeof(struct scsiio_tracker);
Kashyap, Desai89009fb2010-03-17 16:22:52 +05302280 ioc->scsi_lookup_pages = get_order(sz);
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05302281 ioc->scsi_lookup = (struct scsiio_tracker *)__get_free_pages(
Kashyap, Desai89009fb2010-03-17 16:22:52 +05302282 GFP_KERNEL, ioc->scsi_lookup_pages);
Eric Moore635374e2009-03-09 01:21:12 -06002283 if (!ioc->scsi_lookup) {
Kashyap, Desai89009fb2010-03-17 16:22:52 +05302284 printk(MPT2SAS_ERR_FMT "scsi_lookup: get_free_pages failed, "
2285 "sz(%d)\n", ioc->name, (int)sz);
Eric Moore635374e2009-03-09 01:21:12 -06002286 goto out;
2287 }
2288
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302289 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsiio(0x%p): "
2290 "depth(%d)\n", ioc->name, ioc->request,
2291 ioc->scsiio_depth));
2292
nagalakshmi.nandigama@lsi.com73669de2011-12-01 07:53:08 +05302293 ioc->chain_depth = min_t(u32, ioc->chain_depth, MAX_CHAIN_DEPTH);
2294 sz = ioc->chain_depth * sizeof(struct chain_tracker);
2295 ioc->chain_pages = get_order(sz);
2296
2297 ioc->chain_lookup = (struct chain_tracker *)__get_free_pages(
2298 GFP_KERNEL, ioc->chain_pages);
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302299 ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev,
2300 ioc->request_sz, 16, 0);
2301 if (!ioc->chain_dma_pool) {
2302 printk(MPT2SAS_ERR_FMT "chain_dma_pool: pci_pool_create "
2303 "failed\n", ioc->name);
2304 goto out;
2305 }
2306 for (i = 0; i < ioc->chain_depth; i++) {
2307 ioc->chain_lookup[i].chain_buffer = pci_pool_alloc(
2308 ioc->chain_dma_pool , GFP_KERNEL,
2309 &ioc->chain_lookup[i].chain_buffer_dma);
2310 if (!ioc->chain_lookup[i].chain_buffer) {
2311 ioc->chain_depth = i;
2312 goto chain_done;
2313 }
2314 total_sz += ioc->request_sz;
2315 }
2316chain_done:
2317 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool depth"
2318 "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
2319 ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth *
2320 ioc->request_sz))/1024));
2321
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302322 /* initialize hi-priority queue smid's */
2323 ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth,
2324 sizeof(struct request_tracker), GFP_KERNEL);
2325 if (!ioc->hpr_lookup) {
2326 printk(MPT2SAS_ERR_FMT "hpr_lookup: kcalloc failed\n",
2327 ioc->name);
2328 goto out;
2329 }
2330 ioc->hi_priority_smid = ioc->scsiio_depth + 1;
2331 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hi_priority(0x%p): "
2332 "depth(%d), start smid(%d)\n", ioc->name, ioc->hi_priority,
2333 ioc->hi_priority_depth, ioc->hi_priority_smid));
2334
2335 /* initialize internal queue smid's */
2336 ioc->internal_lookup = kcalloc(ioc->internal_depth,
2337 sizeof(struct request_tracker), GFP_KERNEL);
2338 if (!ioc->internal_lookup) {
2339 printk(MPT2SAS_ERR_FMT "internal_lookup: kcalloc failed\n",
2340 ioc->name);
2341 goto out;
2342 }
2343 ioc->internal_smid = ioc->hi_priority_smid + ioc->hi_priority_depth;
2344 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "internal(0x%p): "
2345 "depth(%d), start smid(%d)\n", ioc->name, ioc->internal,
2346 ioc->internal_depth, ioc->internal_smid));
Eric Moore635374e2009-03-09 01:21:12 -06002347
2348 /* sense buffers, 4 byte align */
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302349 sz = ioc->scsiio_depth * SCSI_SENSE_BUFFERSIZE;
Eric Moore635374e2009-03-09 01:21:12 -06002350 ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4,
2351 0);
2352 if (!ioc->sense_dma_pool) {
2353 printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_create failed\n",
2354 ioc->name);
2355 goto out;
2356 }
2357 ioc->sense = pci_pool_alloc(ioc->sense_dma_pool , GFP_KERNEL,
2358 &ioc->sense_dma);
2359 if (!ioc->sense) {
2360 printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_alloc failed\n",
2361 ioc->name);
2362 goto out;
2363 }
2364 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
2365 "sense pool(0x%p): depth(%d), element_size(%d), pool_size"
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302366 "(%d kB)\n", ioc->name, ioc->sense, ioc->scsiio_depth,
Eric Moore635374e2009-03-09 01:21:12 -06002367 SCSI_SENSE_BUFFERSIZE, sz/1024));
2368 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_dma(0x%llx)\n",
2369 ioc->name, (unsigned long long)ioc->sense_dma));
2370 total_sz += sz;
2371
2372 /* reply pool, 4 byte align */
2373 sz = ioc->reply_free_queue_depth * ioc->reply_sz;
2374 ioc->reply_dma_pool = pci_pool_create("reply pool", ioc->pdev, sz, 4,
2375 0);
2376 if (!ioc->reply_dma_pool) {
2377 printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_create failed\n",
2378 ioc->name);
2379 goto out;
2380 }
2381 ioc->reply = pci_pool_alloc(ioc->reply_dma_pool , GFP_KERNEL,
2382 &ioc->reply_dma);
2383 if (!ioc->reply) {
2384 printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_alloc failed\n",
2385 ioc->name);
2386 goto out;
2387 }
Kashyap, Desaidd3741d2010-11-13 04:31:14 +05302388 ioc->reply_dma_min_address = (u32)(ioc->reply_dma);
2389 ioc->reply_dma_max_address = (u32)(ioc->reply_dma) + sz;
Eric Moore635374e2009-03-09 01:21:12 -06002390 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply pool(0x%p): depth"
2391 "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->reply,
2392 ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024));
2393 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_dma(0x%llx)\n",
2394 ioc->name, (unsigned long long)ioc->reply_dma));
2395 total_sz += sz;
2396
2397 /* reply free queue, 16 byte align */
2398 sz = ioc->reply_free_queue_depth * 4;
2399 ioc->reply_free_dma_pool = pci_pool_create("reply_free pool",
2400 ioc->pdev, sz, 16, 0);
2401 if (!ioc->reply_free_dma_pool) {
2402 printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_create "
2403 "failed\n", ioc->name);
2404 goto out;
2405 }
2406 ioc->reply_free = pci_pool_alloc(ioc->reply_free_dma_pool , GFP_KERNEL,
2407 &ioc->reply_free_dma);
2408 if (!ioc->reply_free) {
2409 printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_alloc "
2410 "failed\n", ioc->name);
2411 goto out;
2412 }
2413 memset(ioc->reply_free, 0, sz);
2414 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free pool(0x%p): "
2415 "depth(%d), element_size(%d), pool_size(%d kB)\n", ioc->name,
2416 ioc->reply_free, ioc->reply_free_queue_depth, 4, sz/1024));
2417 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_dma"
2418 "(0x%llx)\n", ioc->name, (unsigned long long)ioc->reply_free_dma));
2419 total_sz += sz;
2420
2421 /* reply post queue, 16 byte align */
2422 sz = ioc->reply_post_queue_depth * sizeof(Mpi2DefaultReplyDescriptor_t);
2423 ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool",
2424 ioc->pdev, sz, 16, 0);
2425 if (!ioc->reply_post_free_dma_pool) {
2426 printk(MPT2SAS_ERR_FMT "reply_post_free pool: pci_pool_create "
2427 "failed\n", ioc->name);
2428 goto out;
2429 }
2430 ioc->reply_post_free = pci_pool_alloc(ioc->reply_post_free_dma_pool ,
2431 GFP_KERNEL, &ioc->reply_post_free_dma);
2432 if (!ioc->reply_post_free) {
2433 printk(MPT2SAS_ERR_FMT "reply_post_free pool: pci_pool_alloc "
2434 "failed\n", ioc->name);
2435 goto out;
2436 }
2437 memset(ioc->reply_post_free, 0, sz);
2438 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply post free pool"
2439 "(0x%p): depth(%d), element_size(%d), pool_size(%d kB)\n",
2440 ioc->name, ioc->reply_post_free, ioc->reply_post_queue_depth, 8,
2441 sz/1024));
2442 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_post_free_dma = "
2443 "(0x%llx)\n", ioc->name, (unsigned long long)
2444 ioc->reply_post_free_dma));
2445 total_sz += sz;
2446
2447 ioc->config_page_sz = 512;
2448 ioc->config_page = pci_alloc_consistent(ioc->pdev,
2449 ioc->config_page_sz, &ioc->config_page_dma);
2450 if (!ioc->config_page) {
2451 printk(MPT2SAS_ERR_FMT "config page: pci_pool_alloc "
2452 "failed\n", ioc->name);
2453 goto out;
2454 }
2455 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config page(0x%p): size"
2456 "(%d)\n", ioc->name, ioc->config_page, ioc->config_page_sz));
2457 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config_page_dma"
2458 "(0x%llx)\n", ioc->name, (unsigned long long)ioc->config_page_dma));
2459 total_sz += ioc->config_page_sz;
2460
2461 printk(MPT2SAS_INFO_FMT "Allocated physical memory: size(%d kB)\n",
2462 ioc->name, total_sz/1024);
2463 printk(MPT2SAS_INFO_FMT "Current Controller Queue Depth(%d), "
2464 "Max Controller Queue Depth(%d)\n",
2465 ioc->name, ioc->shost->can_queue, facts->RequestCredit);
2466 printk(MPT2SAS_INFO_FMT "Scatter Gather Elements per IO(%d)\n",
2467 ioc->name, ioc->shost->sg_tablesize);
2468 return 0;
2469
2470 out:
Eric Moore635374e2009-03-09 01:21:12 -06002471 return -ENOMEM;
2472}
2473
2474
2475/**
2476 * mpt2sas_base_get_iocstate - Get the current state of a MPT adapter.
2477 * @ioc: Pointer to MPT_ADAPTER structure
2478 * @cooked: Request raw or cooked IOC state
2479 *
2480 * Returns all IOC Doorbell register bits if cooked==0, else just the
2481 * Doorbell bits in MPI_IOC_STATE_MASK.
2482 */
2483u32
2484mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked)
2485{
2486 u32 s, sc;
2487
2488 s = readl(&ioc->chip->Doorbell);
2489 sc = s & MPI2_IOC_STATE_MASK;
2490 return cooked ? sc : s;
2491}
2492
2493/**
2494 * _base_wait_on_iocstate - waiting on a particular ioc state
2495 * @ioc_state: controller state { READY, OPERATIONAL, or RESET }
2496 * @timeout: timeout in second
2497 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2498 *
2499 * Returns 0 for success, non-zero for failure.
2500 */
2501static int
2502_base_wait_on_iocstate(struct MPT2SAS_ADAPTER *ioc, u32 ioc_state, int timeout,
2503 int sleep_flag)
2504{
2505 u32 count, cntdn;
2506 u32 current_state;
2507
2508 count = 0;
2509 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
2510 do {
2511 current_state = mpt2sas_base_get_iocstate(ioc, 1);
2512 if (current_state == ioc_state)
2513 return 0;
2514 if (count && current_state == MPI2_IOC_STATE_FAULT)
2515 break;
2516 if (sleep_flag == CAN_SLEEP)
2517 msleep(1);
2518 else
2519 udelay(500);
2520 count++;
2521 } while (--cntdn);
2522
2523 return current_state;
2524}
2525
2526/**
2527 * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by
2528 * a write to the doorbell)
2529 * @ioc: per adapter object
2530 * @timeout: timeout in second
2531 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2532 *
2533 * Returns 0 for success, non-zero for failure.
2534 *
2535 * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell.
2536 */
2537static int
2538_base_wait_for_doorbell_int(struct MPT2SAS_ADAPTER *ioc, int timeout,
2539 int sleep_flag)
2540{
2541 u32 cntdn, count;
2542 u32 int_status;
2543
2544 count = 0;
2545 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
2546 do {
2547 int_status = readl(&ioc->chip->HostInterruptStatus);
2548 if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302549 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002550 "successful count(%d), timeout(%d)\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06002551 __func__, count, timeout));
2552 return 0;
2553 }
2554 if (sleep_flag == CAN_SLEEP)
2555 msleep(1);
2556 else
2557 udelay(500);
2558 count++;
2559 } while (--cntdn);
2560
2561 printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
2562 "int_status(%x)!\n", ioc->name, __func__, count, int_status);
2563 return -EFAULT;
2564}
2565
2566/**
2567 * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell.
2568 * @ioc: per adapter object
2569 * @timeout: timeout in second
2570 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2571 *
2572 * Returns 0 for success, non-zero for failure.
2573 *
2574 * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to
2575 * doorbell.
2576 */
2577static int
2578_base_wait_for_doorbell_ack(struct MPT2SAS_ADAPTER *ioc, int timeout,
2579 int sleep_flag)
2580{
2581 u32 cntdn, count;
2582 u32 int_status;
2583 u32 doorbell;
2584
2585 count = 0;
2586 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
2587 do {
2588 int_status = readl(&ioc->chip->HostInterruptStatus);
2589 if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302590 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002591 "successful count(%d), timeout(%d)\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06002592 __func__, count, timeout));
2593 return 0;
2594 } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
2595 doorbell = readl(&ioc->chip->Doorbell);
2596 if ((doorbell & MPI2_IOC_STATE_MASK) ==
2597 MPI2_IOC_STATE_FAULT) {
2598 mpt2sas_base_fault_info(ioc , doorbell);
2599 return -EFAULT;
2600 }
2601 } else if (int_status == 0xFFFFFFFF)
2602 goto out;
2603
2604 if (sleep_flag == CAN_SLEEP)
2605 msleep(1);
2606 else
2607 udelay(500);
2608 count++;
2609 } while (--cntdn);
2610
2611 out:
2612 printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
2613 "int_status(%x)!\n", ioc->name, __func__, count, int_status);
2614 return -EFAULT;
2615}
2616
2617/**
2618 * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use
2619 * @ioc: per adapter object
2620 * @timeout: timeout in second
2621 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2622 *
2623 * Returns 0 for success, non-zero for failure.
2624 *
2625 */
2626static int
2627_base_wait_for_doorbell_not_used(struct MPT2SAS_ADAPTER *ioc, int timeout,
2628 int sleep_flag)
2629{
2630 u32 cntdn, count;
2631 u32 doorbell_reg;
2632
2633 count = 0;
2634 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
2635 do {
2636 doorbell_reg = readl(&ioc->chip->Doorbell);
2637 if (!(doorbell_reg & MPI2_DOORBELL_USED)) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302638 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002639 "successful count(%d), timeout(%d)\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06002640 __func__, count, timeout));
2641 return 0;
2642 }
2643 if (sleep_flag == CAN_SLEEP)
2644 msleep(1);
2645 else
2646 udelay(500);
2647 count++;
2648 } while (--cntdn);
2649
2650 printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
2651 "doorbell_reg(%x)!\n", ioc->name, __func__, count, doorbell_reg);
2652 return -EFAULT;
2653}
2654
2655/**
2656 * _base_send_ioc_reset - send doorbell reset
2657 * @ioc: per adapter object
2658 * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET
2659 * @timeout: timeout in second
2660 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2661 *
2662 * Returns 0 for success, non-zero for failure.
2663 */
2664static int
2665_base_send_ioc_reset(struct MPT2SAS_ADAPTER *ioc, u8 reset_type, int timeout,
2666 int sleep_flag)
2667{
2668 u32 ioc_state;
2669 int r = 0;
2670
2671 if (reset_type != MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET) {
2672 printk(MPT2SAS_ERR_FMT "%s: unknown reset_type\n",
2673 ioc->name, __func__);
2674 return -EFAULT;
2675 }
2676
2677 if (!(ioc->facts.IOCCapabilities &
2678 MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY))
2679 return -EFAULT;
2680
2681 printk(MPT2SAS_INFO_FMT "sending message unit reset !!\n", ioc->name);
2682
2683 writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT,
2684 &ioc->chip->Doorbell);
2685 if ((_base_wait_for_doorbell_ack(ioc, 15, sleep_flag))) {
2686 r = -EFAULT;
2687 goto out;
2688 }
2689 ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY,
2690 timeout, sleep_flag);
2691 if (ioc_state) {
2692 printk(MPT2SAS_ERR_FMT "%s: failed going to ready state "
2693 " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
2694 r = -EFAULT;
2695 goto out;
2696 }
2697 out:
2698 printk(MPT2SAS_INFO_FMT "message unit reset: %s\n",
2699 ioc->name, ((r == 0) ? "SUCCESS" : "FAILED"));
2700 return r;
2701}
2702
2703/**
2704 * _base_handshake_req_reply_wait - send request thru doorbell interface
2705 * @ioc: per adapter object
2706 * @request_bytes: request length
2707 * @request: pointer having request payload
2708 * @reply_bytes: reply length
2709 * @reply: pointer to reply payload
2710 * @timeout: timeout in second
2711 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2712 *
2713 * Returns 0 for success, non-zero for failure.
2714 */
2715static int
2716_base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
2717 u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag)
2718{
2719 MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply;
2720 int i;
2721 u8 failed;
2722 u16 dummy;
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05302723 __le32 *mfp;
Eric Moore635374e2009-03-09 01:21:12 -06002724
2725 /* make sure doorbell is not in use */
2726 if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
2727 printk(MPT2SAS_ERR_FMT "doorbell is in use "
2728 " (line=%d)\n", ioc->name, __LINE__);
2729 return -EFAULT;
2730 }
2731
2732 /* clear pending doorbell interrupts from previous state changes */
2733 if (readl(&ioc->chip->HostInterruptStatus) &
2734 MPI2_HIS_IOC2SYS_DB_STATUS)
2735 writel(0, &ioc->chip->HostInterruptStatus);
2736
2737 /* send message to ioc */
2738 writel(((MPI2_FUNCTION_HANDSHAKE<<MPI2_DOORBELL_FUNCTION_SHIFT) |
2739 ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)),
2740 &ioc->chip->Doorbell);
2741
Kashyap, Desai29786e12009-09-14 11:06:21 +05302742 if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) {
Eric Moore635374e2009-03-09 01:21:12 -06002743 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2744 "int failed (line=%d)\n", ioc->name, __LINE__);
2745 return -EFAULT;
2746 }
2747 writel(0, &ioc->chip->HostInterruptStatus);
2748
2749 if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) {
2750 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2751 "ack failed (line=%d)\n", ioc->name, __LINE__);
2752 return -EFAULT;
2753 }
2754
2755 /* send message 32-bits at a time */
2756 for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) {
2757 writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell);
2758 if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag)))
2759 failed = 1;
2760 }
2761
2762 if (failed) {
2763 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2764 "sending request failed (line=%d)\n", ioc->name, __LINE__);
2765 return -EFAULT;
2766 }
2767
2768 /* now wait for the reply */
2769 if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) {
2770 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2771 "int failed (line=%d)\n", ioc->name, __LINE__);
2772 return -EFAULT;
2773 }
2774
2775 /* read the first two 16-bits, it gives the total length of the reply */
2776 reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell)
2777 & MPI2_DOORBELL_DATA_MASK);
2778 writel(0, &ioc->chip->HostInterruptStatus);
2779 if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
2780 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2781 "int failed (line=%d)\n", ioc->name, __LINE__);
2782 return -EFAULT;
2783 }
2784 reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell)
2785 & MPI2_DOORBELL_DATA_MASK);
2786 writel(0, &ioc->chip->HostInterruptStatus);
2787
2788 for (i = 2; i < default_reply->MsgLength * 2; i++) {
2789 if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
2790 printk(MPT2SAS_ERR_FMT "doorbell "
2791 "handshake int failed (line=%d)\n", ioc->name,
2792 __LINE__);
2793 return -EFAULT;
2794 }
2795 if (i >= reply_bytes/2) /* overflow case */
2796 dummy = readl(&ioc->chip->Doorbell);
2797 else
2798 reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell)
2799 & MPI2_DOORBELL_DATA_MASK);
2800 writel(0, &ioc->chip->HostInterruptStatus);
2801 }
2802
2803 _base_wait_for_doorbell_int(ioc, 5, sleep_flag);
2804 if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) {
2805 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "doorbell is in use "
2806 " (line=%d)\n", ioc->name, __LINE__));
2807 }
2808 writel(0, &ioc->chip->HostInterruptStatus);
2809
2810 if (ioc->logging_level & MPT_DEBUG_INIT) {
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05302811 mfp = (__le32 *)reply;
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302812 printk(KERN_INFO "\toffset:data\n");
Eric Moore635374e2009-03-09 01:21:12 -06002813 for (i = 0; i < reply_bytes/4; i++)
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302814 printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
Eric Moore635374e2009-03-09 01:21:12 -06002815 le32_to_cpu(mfp[i]));
2816 }
2817 return 0;
2818}
2819
2820/**
2821 * mpt2sas_base_sas_iounit_control - send sas iounit control to FW
2822 * @ioc: per adapter object
2823 * @mpi_reply: the reply payload from FW
2824 * @mpi_request: the request payload sent to FW
2825 *
2826 * The SAS IO Unit Control Request message allows the host to perform low-level
2827 * operations, such as resets on the PHYs of the IO Unit, also allows the host
2828 * to obtain the IOC assigned device handles for a device if it has other
2829 * identifying information about the device, in addition allows the host to
2830 * remove IOC resources associated with the device.
2831 *
2832 * Returns 0 for success, non-zero for failure.
2833 */
2834int
2835mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc,
2836 Mpi2SasIoUnitControlReply_t *mpi_reply,
2837 Mpi2SasIoUnitControlRequest_t *mpi_request)
2838{
2839 u16 smid;
2840 u32 ioc_state;
2841 unsigned long timeleft;
2842 u8 issue_reset;
2843 int rc;
2844 void *request;
2845 u16 wait_state_count;
2846
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302847 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06002848 __func__));
2849
2850 mutex_lock(&ioc->base_cmds.mutex);
2851
2852 if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) {
2853 printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n",
2854 ioc->name, __func__);
2855 rc = -EAGAIN;
2856 goto out;
2857 }
2858
2859 wait_state_count = 0;
2860 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
2861 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
2862 if (wait_state_count++ == 10) {
2863 printk(MPT2SAS_ERR_FMT
2864 "%s: failed due to ioc not operational\n",
2865 ioc->name, __func__);
2866 rc = -EFAULT;
2867 goto out;
2868 }
2869 ssleep(1);
2870 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
2871 printk(MPT2SAS_INFO_FMT "%s: waiting for "
2872 "operational state(count=%d)\n", ioc->name,
2873 __func__, wait_state_count);
2874 }
2875
2876 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
2877 if (!smid) {
2878 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
2879 ioc->name, __func__);
2880 rc = -EAGAIN;
2881 goto out;
2882 }
2883
2884 rc = 0;
2885 ioc->base_cmds.status = MPT2_CMD_PENDING;
2886 request = mpt2sas_base_get_msg_frame(ioc, smid);
2887 ioc->base_cmds.smid = smid;
2888 memcpy(request, mpi_request, sizeof(Mpi2SasIoUnitControlRequest_t));
2889 if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
2890 mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET)
2891 ioc->ioc_link_reset_in_progress = 1;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05302892 mpt2sas_base_put_smid_default(ioc, smid);
Kashyap, Desaibcfb6e62009-09-14 11:05:24 +05302893 init_completion(&ioc->base_cmds.done);
Eric Moore635374e2009-03-09 01:21:12 -06002894 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
2895 msecs_to_jiffies(10000));
2896 if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
2897 mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) &&
2898 ioc->ioc_link_reset_in_progress)
2899 ioc->ioc_link_reset_in_progress = 0;
2900 if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
2901 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
2902 ioc->name, __func__);
2903 _debug_dump_mf(mpi_request,
2904 sizeof(Mpi2SasIoUnitControlRequest_t)/4);
2905 if (!(ioc->base_cmds.status & MPT2_CMD_RESET))
2906 issue_reset = 1;
2907 goto issue_host_reset;
2908 }
2909 if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID)
2910 memcpy(mpi_reply, ioc->base_cmds.reply,
2911 sizeof(Mpi2SasIoUnitControlReply_t));
2912 else
2913 memset(mpi_reply, 0, sizeof(Mpi2SasIoUnitControlReply_t));
2914 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
2915 goto out;
2916
2917 issue_host_reset:
2918 if (issue_reset)
2919 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2920 FORCE_BIG_HAMMER);
2921 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
2922 rc = -EFAULT;
2923 out:
2924 mutex_unlock(&ioc->base_cmds.mutex);
2925 return rc;
2926}
2927
2928
2929/**
2930 * mpt2sas_base_scsi_enclosure_processor - sending request to sep device
2931 * @ioc: per adapter object
2932 * @mpi_reply: the reply payload from FW
2933 * @mpi_request: the request payload sent to FW
2934 *
2935 * The SCSI Enclosure Processor request message causes the IOC to
2936 * communicate with SES devices to control LED status signals.
2937 *
2938 * Returns 0 for success, non-zero for failure.
2939 */
2940int
2941mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc,
2942 Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request)
2943{
2944 u16 smid;
2945 u32 ioc_state;
2946 unsigned long timeleft;
2947 u8 issue_reset;
2948 int rc;
2949 void *request;
2950 u16 wait_state_count;
2951
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302952 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06002953 __func__));
2954
2955 mutex_lock(&ioc->base_cmds.mutex);
2956
2957 if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) {
2958 printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n",
2959 ioc->name, __func__);
2960 rc = -EAGAIN;
2961 goto out;
2962 }
2963
2964 wait_state_count = 0;
2965 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
2966 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
2967 if (wait_state_count++ == 10) {
2968 printk(MPT2SAS_ERR_FMT
2969 "%s: failed due to ioc not operational\n",
2970 ioc->name, __func__);
2971 rc = -EFAULT;
2972 goto out;
2973 }
2974 ssleep(1);
2975 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
2976 printk(MPT2SAS_INFO_FMT "%s: waiting for "
2977 "operational state(count=%d)\n", ioc->name,
2978 __func__, wait_state_count);
2979 }
2980
2981 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
2982 if (!smid) {
2983 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
2984 ioc->name, __func__);
2985 rc = -EAGAIN;
2986 goto out;
2987 }
2988
2989 rc = 0;
2990 ioc->base_cmds.status = MPT2_CMD_PENDING;
2991 request = mpt2sas_base_get_msg_frame(ioc, smid);
2992 ioc->base_cmds.smid = smid;
2993 memcpy(request, mpi_request, sizeof(Mpi2SepReply_t));
Kashyap, Desai7b936b02009-09-25 11:44:41 +05302994 mpt2sas_base_put_smid_default(ioc, smid);
Kashyap, Desaibcfb6e62009-09-14 11:05:24 +05302995 init_completion(&ioc->base_cmds.done);
Eric Moore635374e2009-03-09 01:21:12 -06002996 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
2997 msecs_to_jiffies(10000));
2998 if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
2999 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
3000 ioc->name, __func__);
3001 _debug_dump_mf(mpi_request,
3002 sizeof(Mpi2SepRequest_t)/4);
3003 if (!(ioc->base_cmds.status & MPT2_CMD_RESET))
3004 issue_reset = 1;
3005 goto issue_host_reset;
3006 }
3007 if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID)
3008 memcpy(mpi_reply, ioc->base_cmds.reply,
3009 sizeof(Mpi2SepReply_t));
3010 else
3011 memset(mpi_reply, 0, sizeof(Mpi2SepReply_t));
3012 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
3013 goto out;
3014
3015 issue_host_reset:
3016 if (issue_reset)
3017 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
3018 FORCE_BIG_HAMMER);
3019 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
3020 rc = -EFAULT;
3021 out:
3022 mutex_unlock(&ioc->base_cmds.mutex);
3023 return rc;
3024}
3025
3026/**
3027 * _base_get_port_facts - obtain port facts reply and save in ioc
3028 * @ioc: per adapter object
3029 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3030 *
3031 * Returns 0 for success, non-zero for failure.
3032 */
3033static int
3034_base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)
3035{
3036 Mpi2PortFactsRequest_t mpi_request;
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05303037 Mpi2PortFactsReply_t mpi_reply;
3038 struct mpt2sas_port_facts *pfacts;
Eric Moore635374e2009-03-09 01:21:12 -06003039 int mpi_reply_sz, mpi_request_sz, r;
3040
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303041 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003042 __func__));
3043
3044 mpi_reply_sz = sizeof(Mpi2PortFactsReply_t);
3045 mpi_request_sz = sizeof(Mpi2PortFactsRequest_t);
3046 memset(&mpi_request, 0, mpi_request_sz);
3047 mpi_request.Function = MPI2_FUNCTION_PORT_FACTS;
3048 mpi_request.PortNumber = port;
3049 r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
3050 (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
3051
3052 if (r != 0) {
3053 printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
3054 ioc->name, __func__, r);
3055 return r;
3056 }
3057
3058 pfacts = &ioc->pfacts[port];
3059 memset(pfacts, 0, sizeof(Mpi2PortFactsReply_t));
3060 pfacts->PortNumber = mpi_reply.PortNumber;
3061 pfacts->VP_ID = mpi_reply.VP_ID;
3062 pfacts->VF_ID = mpi_reply.VF_ID;
3063 pfacts->MaxPostedCmdBuffers =
3064 le16_to_cpu(mpi_reply.MaxPostedCmdBuffers);
3065
3066 return 0;
3067}
3068
3069/**
3070 * _base_get_ioc_facts - obtain ioc facts reply and save in ioc
3071 * @ioc: per adapter object
3072 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3073 *
3074 * Returns 0 for success, non-zero for failure.
3075 */
3076static int
3077_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
3078{
3079 Mpi2IOCFactsRequest_t mpi_request;
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05303080 Mpi2IOCFactsReply_t mpi_reply;
3081 struct mpt2sas_facts *facts;
Eric Moore635374e2009-03-09 01:21:12 -06003082 int mpi_reply_sz, mpi_request_sz, r;
3083
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303084 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003085 __func__));
3086
3087 mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t);
3088 mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t);
3089 memset(&mpi_request, 0, mpi_request_sz);
3090 mpi_request.Function = MPI2_FUNCTION_IOC_FACTS;
3091 r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
3092 (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
3093
3094 if (r != 0) {
3095 printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
3096 ioc->name, __func__, r);
3097 return r;
3098 }
3099
3100 facts = &ioc->facts;
3101 memset(facts, 0, sizeof(Mpi2IOCFactsReply_t));
3102 facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion);
3103 facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion);
3104 facts->VP_ID = mpi_reply.VP_ID;
3105 facts->VF_ID = mpi_reply.VF_ID;
3106 facts->IOCExceptions = le16_to_cpu(mpi_reply.IOCExceptions);
3107 facts->MaxChainDepth = mpi_reply.MaxChainDepth;
3108 facts->WhoInit = mpi_reply.WhoInit;
3109 facts->NumberOfPorts = mpi_reply.NumberOfPorts;
3110 facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit);
3111 facts->MaxReplyDescriptorPostQueueDepth =
3112 le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth);
3113 facts->ProductID = le16_to_cpu(mpi_reply.ProductID);
3114 facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities);
3115 if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
3116 ioc->ir_firmware = 1;
3117 facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word);
3118 facts->IOCRequestFrameSize =
3119 le16_to_cpu(mpi_reply.IOCRequestFrameSize);
3120 facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators);
3121 facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets);
3122 ioc->shost->max_id = -1;
3123 facts->MaxSasExpanders = le16_to_cpu(mpi_reply.MaxSasExpanders);
3124 facts->MaxEnclosures = le16_to_cpu(mpi_reply.MaxEnclosures);
3125 facts->ProtocolFlags = le16_to_cpu(mpi_reply.ProtocolFlags);
3126 facts->HighPriorityCredit =
3127 le16_to_cpu(mpi_reply.HighPriorityCredit);
3128 facts->ReplyFrameSize = mpi_reply.ReplyFrameSize;
3129 facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle);
3130
3131 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hba queue depth(%d), "
3132 "max chains per io(%d)\n", ioc->name, facts->RequestCredit,
3133 facts->MaxChainDepth));
3134 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request frame size(%d), "
3135 "reply frame size(%d)\n", ioc->name,
3136 facts->IOCRequestFrameSize * 4, facts->ReplyFrameSize * 4));
3137 return 0;
3138}
3139
3140/**
3141 * _base_send_ioc_init - send ioc_init to firmware
3142 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -06003143 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3144 *
3145 * Returns 0 for success, non-zero for failure.
3146 */
3147static int
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303148_base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
Eric Moore635374e2009-03-09 01:21:12 -06003149{
3150 Mpi2IOCInitRequest_t mpi_request;
3151 Mpi2IOCInitReply_t mpi_reply;
3152 int r;
Kashyap, Desaia8ebd762009-09-23 17:29:29 +05303153 struct timeval current_time;
Kashyap, Desai463217b2009-10-05 15:53:06 +05303154 u16 ioc_status;
Eric Moore635374e2009-03-09 01:21:12 -06003155
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303156 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003157 __func__));
3158
3159 memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t));
3160 mpi_request.Function = MPI2_FUNCTION_IOC_INIT;
3161 mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303162 mpi_request.VF_ID = 0; /* TODO */
3163 mpi_request.VP_ID = 0;
Eric Moore635374e2009-03-09 01:21:12 -06003164 mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION);
3165 mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
3166
Eric Moore635374e2009-03-09 01:21:12 -06003167
3168 mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4);
3169 mpi_request.ReplyDescriptorPostQueueDepth =
3170 cpu_to_le16(ioc->reply_post_queue_depth);
3171 mpi_request.ReplyFreeQueueDepth =
3172 cpu_to_le16(ioc->reply_free_queue_depth);
3173
Eric Moore635374e2009-03-09 01:21:12 -06003174 mpi_request.SenseBufferAddressHigh =
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05303175 cpu_to_le32((u64)ioc->sense_dma >> 32);
Eric Moore635374e2009-03-09 01:21:12 -06003176 mpi_request.SystemReplyAddressHigh =
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05303177 cpu_to_le32((u64)ioc->reply_dma >> 32);
Eric Moore635374e2009-03-09 01:21:12 -06003178 mpi_request.SystemRequestFrameBaseAddress =
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05303179 cpu_to_le64((u64)ioc->request_dma);
Eric Moore635374e2009-03-09 01:21:12 -06003180 mpi_request.ReplyFreeQueueAddress =
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05303181 cpu_to_le64((u64)ioc->reply_free_dma);
Eric Moore635374e2009-03-09 01:21:12 -06003182 mpi_request.ReplyDescriptorPostQueueAddress =
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05303183 cpu_to_le64((u64)ioc->reply_post_free_dma);
3184
Eric Moore635374e2009-03-09 01:21:12 -06003185
Kashyap, Desaia8ebd762009-09-23 17:29:29 +05303186 /* This time stamp specifies number of milliseconds
3187 * since epoch ~ midnight January 1, 1970.
3188 */
3189 do_gettimeofday(&current_time);
Kashyap, Desai7921b352010-03-17 16:21:33 +05303190 mpi_request.TimeStamp = cpu_to_le64((u64)current_time.tv_sec * 1000 +
3191 (current_time.tv_usec / 1000));
Kashyap, Desaia8ebd762009-09-23 17:29:29 +05303192
Eric Moore635374e2009-03-09 01:21:12 -06003193 if (ioc->logging_level & MPT_DEBUG_INIT) {
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05303194 __le32 *mfp;
Eric Moore635374e2009-03-09 01:21:12 -06003195 int i;
3196
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05303197 mfp = (__le32 *)&mpi_request;
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303198 printk(KERN_INFO "\toffset:data\n");
Eric Moore635374e2009-03-09 01:21:12 -06003199 for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++)
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303200 printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
Eric Moore635374e2009-03-09 01:21:12 -06003201 le32_to_cpu(mfp[i]));
3202 }
3203
3204 r = _base_handshake_req_reply_wait(ioc,
3205 sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request,
3206 sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10,
3207 sleep_flag);
3208
3209 if (r != 0) {
3210 printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
3211 ioc->name, __func__, r);
3212 return r;
3213 }
3214
Kashyap, Desai463217b2009-10-05 15:53:06 +05303215 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
3216 if (ioc_status != MPI2_IOCSTATUS_SUCCESS ||
Eric Moore635374e2009-03-09 01:21:12 -06003217 mpi_reply.IOCLogInfo) {
3218 printk(MPT2SAS_ERR_FMT "%s: failed\n", ioc->name, __func__);
3219 r = -EIO;
3220 }
3221
3222 return 0;
3223}
3224
3225/**
3226 * _base_send_port_enable - send port_enable(discovery stuff) to firmware
3227 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -06003228 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3229 *
3230 * Returns 0 for success, non-zero for failure.
3231 */
3232static int
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303233_base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
Eric Moore635374e2009-03-09 01:21:12 -06003234{
3235 Mpi2PortEnableRequest_t *mpi_request;
3236 u32 ioc_state;
3237 unsigned long timeleft;
3238 int r = 0;
3239 u16 smid;
3240
3241 printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name);
3242
3243 if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
3244 printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
3245 ioc->name, __func__);
3246 return -EAGAIN;
3247 }
3248
3249 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
3250 if (!smid) {
3251 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
3252 ioc->name, __func__);
3253 return -EAGAIN;
3254 }
3255
3256 ioc->base_cmds.status = MPT2_CMD_PENDING;
3257 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
3258 ioc->base_cmds.smid = smid;
3259 memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
3260 mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303261 mpi_request->VF_ID = 0; /* TODO */
3262 mpi_request->VP_ID = 0;
Eric Moore635374e2009-03-09 01:21:12 -06003263
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303264 mpt2sas_base_put_smid_default(ioc, smid);
Kashyap, Desaibcfb6e62009-09-14 11:05:24 +05303265 init_completion(&ioc->base_cmds.done);
Eric Moore635374e2009-03-09 01:21:12 -06003266 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
3267 300*HZ);
3268 if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
3269 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
3270 ioc->name, __func__);
3271 _debug_dump_mf(mpi_request,
3272 sizeof(Mpi2PortEnableRequest_t)/4);
3273 if (ioc->base_cmds.status & MPT2_CMD_RESET)
3274 r = -EFAULT;
3275 else
3276 r = -ETIME;
3277 goto out;
3278 } else
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303279 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: complete\n",
Eric Moore635374e2009-03-09 01:21:12 -06003280 ioc->name, __func__));
3281
3282 ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_OPERATIONAL,
3283 60, sleep_flag);
3284 if (ioc_state) {
3285 printk(MPT2SAS_ERR_FMT "%s: failed going to operational state "
3286 " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
3287 r = -EFAULT;
3288 }
3289 out:
3290 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
3291 printk(MPT2SAS_INFO_FMT "port enable: %s\n",
3292 ioc->name, ((r == 0) ? "SUCCESS" : "FAILED"));
3293 return r;
3294}
3295
3296/**
3297 * _base_unmask_events - turn on notification for this event
3298 * @ioc: per adapter object
3299 * @event: firmware event
3300 *
3301 * The mask is stored in ioc->event_masks.
3302 */
3303static void
3304_base_unmask_events(struct MPT2SAS_ADAPTER *ioc, u16 event)
3305{
3306 u32 desired_event;
3307
3308 if (event >= 128)
3309 return;
3310
3311 desired_event = (1 << (event % 32));
3312
3313 if (event < 32)
3314 ioc->event_masks[0] &= ~desired_event;
3315 else if (event < 64)
3316 ioc->event_masks[1] &= ~desired_event;
3317 else if (event < 96)
3318 ioc->event_masks[2] &= ~desired_event;
3319 else if (event < 128)
3320 ioc->event_masks[3] &= ~desired_event;
3321}
3322
3323/**
3324 * _base_event_notification - send event notification
3325 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -06003326 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3327 *
3328 * Returns 0 for success, non-zero for failure.
3329 */
3330static int
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303331_base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
Eric Moore635374e2009-03-09 01:21:12 -06003332{
3333 Mpi2EventNotificationRequest_t *mpi_request;
3334 unsigned long timeleft;
3335 u16 smid;
3336 int r = 0;
3337 int i;
3338
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303339 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003340 __func__));
3341
3342 if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
3343 printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
3344 ioc->name, __func__);
3345 return -EAGAIN;
3346 }
3347
3348 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
3349 if (!smid) {
3350 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
3351 ioc->name, __func__);
3352 return -EAGAIN;
3353 }
3354 ioc->base_cmds.status = MPT2_CMD_PENDING;
3355 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
3356 ioc->base_cmds.smid = smid;
3357 memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t));
3358 mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303359 mpi_request->VF_ID = 0; /* TODO */
3360 mpi_request->VP_ID = 0;
Eric Moore635374e2009-03-09 01:21:12 -06003361 for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
3362 mpi_request->EventMasks[i] =
Kashyap, Desaie94f6742010-03-17 16:24:52 +05303363 cpu_to_le32(ioc->event_masks[i]);
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303364 mpt2sas_base_put_smid_default(ioc, smid);
Kashyap, Desaibcfb6e62009-09-14 11:05:24 +05303365 init_completion(&ioc->base_cmds.done);
Eric Moore635374e2009-03-09 01:21:12 -06003366 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ);
3367 if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
3368 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
3369 ioc->name, __func__);
3370 _debug_dump_mf(mpi_request,
3371 sizeof(Mpi2EventNotificationRequest_t)/4);
3372 if (ioc->base_cmds.status & MPT2_CMD_RESET)
3373 r = -EFAULT;
3374 else
3375 r = -ETIME;
3376 } else
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303377 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: complete\n",
Eric Moore635374e2009-03-09 01:21:12 -06003378 ioc->name, __func__));
3379 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
3380 return r;
3381}
3382
3383/**
3384 * mpt2sas_base_validate_event_type - validating event types
3385 * @ioc: per adapter object
3386 * @event: firmware event
3387 *
3388 * This will turn on firmware event notification when application
3389 * ask for that event. We don't mask events that are already enabled.
3390 */
3391void
3392mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type)
3393{
3394 int i, j;
3395 u32 event_mask, desired_event;
3396 u8 send_update_to_fw;
3397
3398 for (i = 0, send_update_to_fw = 0; i <
3399 MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) {
3400 event_mask = ~event_type[i];
3401 desired_event = 1;
3402 for (j = 0; j < 32; j++) {
3403 if (!(event_mask & desired_event) &&
3404 (ioc->event_masks[i] & desired_event)) {
3405 ioc->event_masks[i] &= ~desired_event;
3406 send_update_to_fw = 1;
3407 }
3408 desired_event = (desired_event << 1);
3409 }
3410 }
3411
3412 if (!send_update_to_fw)
3413 return;
3414
3415 mutex_lock(&ioc->base_cmds.mutex);
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303416 _base_event_notification(ioc, CAN_SLEEP);
Eric Moore635374e2009-03-09 01:21:12 -06003417 mutex_unlock(&ioc->base_cmds.mutex);
3418}
3419
3420/**
3421 * _base_diag_reset - the "big hammer" start of day reset
3422 * @ioc: per adapter object
3423 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3424 *
3425 * Returns 0 for success, non-zero for failure.
3426 */
3427static int
3428_base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
3429{
3430 u32 host_diagnostic;
3431 u32 ioc_state;
3432 u32 count;
3433 u32 hcb_size;
3434
3435 printk(MPT2SAS_INFO_FMT "sending diag reset !!\n", ioc->name);
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303436 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "clear interrupts\n",
Eric Moore635374e2009-03-09 01:21:12 -06003437 ioc->name));
Eric Moore635374e2009-03-09 01:21:12 -06003438
3439 count = 0;
3440 do {
3441 /* Write magic sequence to WriteSequence register
3442 * Loop until in diagnostic mode
3443 */
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303444 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "write magic "
Eric Moore635374e2009-03-09 01:21:12 -06003445 "sequence\n", ioc->name));
3446 writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
3447 writel(MPI2_WRSEQ_1ST_KEY_VALUE, &ioc->chip->WriteSequence);
3448 writel(MPI2_WRSEQ_2ND_KEY_VALUE, &ioc->chip->WriteSequence);
3449 writel(MPI2_WRSEQ_3RD_KEY_VALUE, &ioc->chip->WriteSequence);
3450 writel(MPI2_WRSEQ_4TH_KEY_VALUE, &ioc->chip->WriteSequence);
3451 writel(MPI2_WRSEQ_5TH_KEY_VALUE, &ioc->chip->WriteSequence);
3452 writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence);
3453
3454 /* wait 100 msec */
3455 if (sleep_flag == CAN_SLEEP)
3456 msleep(100);
3457 else
3458 mdelay(100);
3459
3460 if (count++ > 20)
3461 goto out;
3462
3463 host_diagnostic = readl(&ioc->chip->HostDiagnostic);
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303464 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "wrote magic "
Eric Moore635374e2009-03-09 01:21:12 -06003465 "sequence: count(%d), host_diagnostic(0x%08x)\n",
3466 ioc->name, count, host_diagnostic));
3467
3468 } while ((host_diagnostic & MPI2_DIAG_DIAG_WRITE_ENABLE) == 0);
3469
3470 hcb_size = readl(&ioc->chip->HCBSize);
3471
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303472 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "diag reset: issued\n",
Eric Moore635374e2009-03-09 01:21:12 -06003473 ioc->name));
3474 writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER,
3475 &ioc->chip->HostDiagnostic);
3476
3477 /* don't access any registers for 50 milliseconds */
3478 msleep(50);
3479
3480 /* 300 second max wait */
3481 for (count = 0; count < 3000000 ; count++) {
3482
3483 host_diagnostic = readl(&ioc->chip->HostDiagnostic);
3484
3485 if (host_diagnostic == 0xFFFFFFFF)
3486 goto out;
3487 if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER))
3488 break;
3489
3490 /* wait 100 msec */
3491 if (sleep_flag == CAN_SLEEP)
3492 msleep(1);
3493 else
3494 mdelay(1);
3495 }
3496
3497 if (host_diagnostic & MPI2_DIAG_HCB_MODE) {
3498
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303499 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "restart the adapter "
Eric Moore635374e2009-03-09 01:21:12 -06003500 "assuming the HCB Address points to good F/W\n",
3501 ioc->name));
3502 host_diagnostic &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK;
3503 host_diagnostic |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW;
3504 writel(host_diagnostic, &ioc->chip->HostDiagnostic);
3505
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303506 drsprintk(ioc, printk(MPT2SAS_INFO_FMT
Eric Moore635374e2009-03-09 01:21:12 -06003507 "re-enable the HCDW\n", ioc->name));
3508 writel(hcb_size | MPI2_HCB_SIZE_HCB_ENABLE,
3509 &ioc->chip->HCBSize);
3510 }
3511
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303512 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "restart the adapter\n",
Eric Moore635374e2009-03-09 01:21:12 -06003513 ioc->name));
3514 writel(host_diagnostic & ~MPI2_DIAG_HOLD_IOC_RESET,
3515 &ioc->chip->HostDiagnostic);
3516
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303517 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "disable writes to the "
Eric Moore635374e2009-03-09 01:21:12 -06003518 "diagnostic register\n", ioc->name));
3519 writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
3520
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303521 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "Wait for FW to go to the "
Eric Moore635374e2009-03-09 01:21:12 -06003522 "READY state\n", ioc->name));
3523 ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20,
3524 sleep_flag);
3525 if (ioc_state) {
3526 printk(MPT2SAS_ERR_FMT "%s: failed going to ready state "
3527 " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
3528 goto out;
3529 }
3530
Eric Moore635374e2009-03-09 01:21:12 -06003531 printk(MPT2SAS_INFO_FMT "diag reset: SUCCESS\n", ioc->name);
3532 return 0;
3533
3534 out:
3535 printk(MPT2SAS_ERR_FMT "diag reset: FAILED\n", ioc->name);
3536 return -EFAULT;
3537}
3538
3539/**
3540 * _base_make_ioc_ready - put controller in READY state
3541 * @ioc: per adapter object
3542 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3543 * @type: FORCE_BIG_HAMMER or SOFT_RESET
3544 *
3545 * Returns 0 for success, non-zero for failure.
3546 */
3547static int
3548_base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
3549 enum reset_type type)
3550{
3551 u32 ioc_state;
Kashyap, Desaid32a8c12010-06-17 13:36:53 +05303552 int rc;
Eric Moore635374e2009-03-09 01:21:12 -06003553
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303554 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003555 __func__));
3556
Eric Moore3cb54692010-07-08 14:44:34 -06003557 if (ioc->pci_error_recovery)
3558 return 0;
3559
Eric Moore635374e2009-03-09 01:21:12 -06003560 ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303561 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: ioc_state(0x%08x)\n",
Eric Moore635374e2009-03-09 01:21:12 -06003562 ioc->name, __func__, ioc_state));
3563
3564 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY)
3565 return 0;
3566
3567 if (ioc_state & MPI2_DOORBELL_USED) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303568 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "
Eric Moore635374e2009-03-09 01:21:12 -06003569 "active!\n", ioc->name));
3570 goto issue_diag_reset;
3571 }
3572
3573 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
3574 mpt2sas_base_fault_info(ioc, ioc_state &
3575 MPI2_DOORBELL_DATA_MASK);
3576 goto issue_diag_reset;
3577 }
3578
3579 if (type == FORCE_BIG_HAMMER)
3580 goto issue_diag_reset;
3581
3582 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL)
3583 if (!(_base_send_ioc_reset(ioc,
Kashyap, Desaid32a8c12010-06-17 13:36:53 +05303584 MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) {
3585 ioc->ioc_reset_count++;
Eric Moore635374e2009-03-09 01:21:12 -06003586 return 0;
Kashyap, Desaid32a8c12010-06-17 13:36:53 +05303587 }
Eric Moore635374e2009-03-09 01:21:12 -06003588
3589 issue_diag_reset:
Kashyap, Desaid32a8c12010-06-17 13:36:53 +05303590 rc = _base_diag_reset(ioc, CAN_SLEEP);
3591 ioc->ioc_reset_count++;
3592 return rc;
Eric Moore635374e2009-03-09 01:21:12 -06003593}
3594
3595/**
3596 * _base_make_ioc_operational - put controller in OPERATIONAL state
3597 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -06003598 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3599 *
3600 * Returns 0 for success, non-zero for failure.
3601 */
3602static int
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303603_base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
Eric Moore635374e2009-03-09 01:21:12 -06003604{
3605 int r, i;
3606 unsigned long flags;
3607 u32 reply_address;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303608 u16 smid;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303609 struct _tr_list *delayed_tr, *delayed_tr_next;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303610 u8 hide_flag;
Eric Moore635374e2009-03-09 01:21:12 -06003611
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303612 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003613 __func__));
3614
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303615 /* clean the delayed target reset list */
3616 list_for_each_entry_safe(delayed_tr, delayed_tr_next,
3617 &ioc->delayed_tr_list, list) {
3618 list_del(&delayed_tr->list);
3619 kfree(delayed_tr);
3620 }
3621
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303622 list_for_each_entry_safe(delayed_tr, delayed_tr_next,
3623 &ioc->delayed_tr_volume_list, list) {
3624 list_del(&delayed_tr->list);
3625 kfree(delayed_tr);
3626 }
3627
Eric Moore635374e2009-03-09 01:21:12 -06003628 /* initialize the scsi lookup free list */
3629 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
3630 INIT_LIST_HEAD(&ioc->free_list);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303631 smid = 1;
3632 for (i = 0; i < ioc->scsiio_depth; i++, smid++) {
Kashyap, Desai35f805b2010-11-13 04:34:06 +05303633 INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list);
Eric Moore635374e2009-03-09 01:21:12 -06003634 ioc->scsi_lookup[i].cb_idx = 0xFF;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303635 ioc->scsi_lookup[i].smid = smid;
3636 ioc->scsi_lookup[i].scmd = NULL;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303637 ioc->scsi_lookup[i].direct_io = 0;
Eric Moore635374e2009-03-09 01:21:12 -06003638 list_add_tail(&ioc->scsi_lookup[i].tracker_list,
3639 &ioc->free_list);
3640 }
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303641
3642 /* hi-priority queue */
3643 INIT_LIST_HEAD(&ioc->hpr_free_list);
3644 smid = ioc->hi_priority_smid;
3645 for (i = 0; i < ioc->hi_priority_depth; i++, smid++) {
3646 ioc->hpr_lookup[i].cb_idx = 0xFF;
3647 ioc->hpr_lookup[i].smid = smid;
3648 list_add_tail(&ioc->hpr_lookup[i].tracker_list,
3649 &ioc->hpr_free_list);
3650 }
3651
3652 /* internal queue */
3653 INIT_LIST_HEAD(&ioc->internal_free_list);
3654 smid = ioc->internal_smid;
3655 for (i = 0; i < ioc->internal_depth; i++, smid++) {
3656 ioc->internal_lookup[i].cb_idx = 0xFF;
3657 ioc->internal_lookup[i].smid = smid;
3658 list_add_tail(&ioc->internal_lookup[i].tracker_list,
3659 &ioc->internal_free_list);
3660 }
Kashyap, Desai35f805b2010-11-13 04:34:06 +05303661
3662 /* chain pool */
3663 INIT_LIST_HEAD(&ioc->free_chain_list);
3664 for (i = 0; i < ioc->chain_depth; i++)
3665 list_add_tail(&ioc->chain_lookup[i].tracker_list,
3666 &ioc->free_chain_list);
3667
Eric Moore635374e2009-03-09 01:21:12 -06003668 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
3669
3670 /* initialize Reply Free Queue */
3671 for (i = 0, reply_address = (u32)ioc->reply_dma ;
3672 i < ioc->reply_free_queue_depth ; i++, reply_address +=
3673 ioc->reply_sz)
3674 ioc->reply_free[i] = cpu_to_le32(reply_address);
3675
3676 /* initialize Reply Post Free Queue */
3677 for (i = 0; i < ioc->reply_post_queue_depth; i++)
Kashyap, Desaifb07bb92011-06-14 10:54:56 +05303678 ioc->reply_post_free[i].Words = cpu_to_le64(ULLONG_MAX);
Eric Moore635374e2009-03-09 01:21:12 -06003679
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303680 r = _base_send_ioc_init(ioc, sleep_flag);
Eric Moore635374e2009-03-09 01:21:12 -06003681 if (r)
3682 return r;
3683
3684 /* initialize the index's */
3685 ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1;
3686 ioc->reply_post_host_index = 0;
3687 writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex);
3688 writel(0, &ioc->chip->ReplyPostHostIndex);
3689
3690 _base_unmask_interrupts(ioc);
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303691 r = _base_event_notification(ioc, sleep_flag);
Eric Moore635374e2009-03-09 01:21:12 -06003692 if (r)
3693 return r;
3694
3695 if (sleep_flag == CAN_SLEEP)
3696 _base_static_config_pages(ioc);
3697
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303698 if (ioc->wait_for_port_enable_to_complete && ioc->is_warpdrive) {
3699 if (ioc->manu_pg10.OEMIdentifier == 0x80) {
3700 hide_flag = (u8) (ioc->manu_pg10.OEMSpecificFlags0 &
3701 MFG_PAGE10_HIDE_SSDS_MASK);
3702 if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK)
3703 ioc->mfg_pg10_hide_flag = hide_flag;
3704 }
3705 }
3706
Kashyap, Desai570c67a2010-06-17 13:43:17 +05303707 if (ioc->wait_for_port_enable_to_complete) {
3708 if (diag_buffer_enable != 0)
3709 mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
3710 if (disable_discovery > 0)
3711 return r;
3712 }
Kashyap, Desaidd5fd332010-06-17 13:31:17 +05303713
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303714 r = _base_send_port_enable(ioc, sleep_flag);
Eric Moore635374e2009-03-09 01:21:12 -06003715 if (r)
3716 return r;
3717
3718 return r;
3719}
3720
3721/**
3722 * mpt2sas_base_free_resources - free resources controller resources (io/irq/memap)
3723 * @ioc: per adapter object
3724 *
3725 * Return nothing.
3726 */
3727void
3728mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc)
3729{
3730 struct pci_dev *pdev = ioc->pdev;
3731
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303732 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003733 __func__));
3734
3735 _base_mask_interrupts(ioc);
Kashyap, Desai6558bbb2010-03-17 16:23:36 +05303736 ioc->shost_recovery = 1;
Eric Moore635374e2009-03-09 01:21:12 -06003737 _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
Kashyap, Desai6558bbb2010-03-17 16:23:36 +05303738 ioc->shost_recovery = 0;
Eric Moore635374e2009-03-09 01:21:12 -06003739 if (ioc->pci_irq) {
3740 synchronize_irq(pdev->irq);
3741 free_irq(ioc->pci_irq, ioc);
3742 }
3743 _base_disable_msix(ioc);
3744 if (ioc->chip_phys)
3745 iounmap(ioc->chip);
3746 ioc->pci_irq = -1;
3747 ioc->chip_phys = 0;
3748 pci_release_selected_regions(ioc->pdev, ioc->bars);
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05303749 pci_disable_pcie_error_reporting(pdev);
Eric Moore635374e2009-03-09 01:21:12 -06003750 pci_disable_device(pdev);
Eric Moore635374e2009-03-09 01:21:12 -06003751 return;
3752}
3753
3754/**
3755 * mpt2sas_base_attach - attach controller instance
3756 * @ioc: per adapter object
3757 *
3758 * Returns 0 for success, non-zero for failure.
3759 */
3760int
3761mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
3762{
3763 int r, i;
Eric Moore635374e2009-03-09 01:21:12 -06003764
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303765 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003766 __func__));
3767
3768 r = mpt2sas_base_map_resources(ioc);
3769 if (r)
3770 return r;
3771
Kashyap, Desaifcfe6392009-08-07 19:38:48 +05303772 pci_set_drvdata(ioc->pdev, ioc->shost);
Kashyap, Desai96b681c2009-09-23 17:32:06 +05303773 r = _base_get_ioc_facts(ioc, CAN_SLEEP);
Eric Moore635374e2009-03-09 01:21:12 -06003774 if (r)
3775 goto out_free_resources;
3776
Kashyap, Desai96b681c2009-09-23 17:32:06 +05303777 r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
Eric Moore635374e2009-03-09 01:21:12 -06003778 if (r)
3779 goto out_free_resources;
3780
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303781 ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts,
3782 sizeof(Mpi2PortFactsReply_t), GFP_KERNEL);
Kashyap, Desaif6aee7b2010-03-17 16:26:48 +05303783 if (!ioc->pfacts) {
3784 r = -ENOMEM;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303785 goto out_free_resources;
Kashyap, Desaif6aee7b2010-03-17 16:26:48 +05303786 }
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303787
3788 for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) {
3789 r = _base_get_port_facts(ioc, i, CAN_SLEEP);
3790 if (r)
3791 goto out_free_resources;
3792 }
3793
Eric Moore635374e2009-03-09 01:21:12 -06003794 r = _base_allocate_memory_pools(ioc, CAN_SLEEP);
3795 if (r)
3796 goto out_free_resources;
3797
3798 init_waitqueue_head(&ioc->reset_wq);
3799
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303800 /* allocate memory pd handle bitmask list */
3801 ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8);
3802 if (ioc->facts.MaxDevHandle % 8)
3803 ioc->pd_handles_sz++;
3804 ioc->pd_handles = kzalloc(ioc->pd_handles_sz,
3805 GFP_KERNEL);
Kashyap, Desai3e2e8332010-06-17 13:47:29 +05303806 if (!ioc->pd_handles) {
3807 r = -ENOMEM;
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303808 goto out_free_resources;
Kashyap, Desai3e2e8332010-06-17 13:47:29 +05303809 }
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303810
Kashyap, Desaie75b9b62009-12-16 18:52:39 +05303811 ioc->fwfault_debug = mpt2sas_fwfault_debug;
3812
Eric Moore635374e2009-03-09 01:21:12 -06003813 /* base internal command bits */
3814 mutex_init(&ioc->base_cmds.mutex);
Eric Moore635374e2009-03-09 01:21:12 -06003815 ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3816 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
3817
3818 /* transport internal command bits */
3819 ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3820 ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
3821 mutex_init(&ioc->transport_cmds.mutex);
Eric Moore635374e2009-03-09 01:21:12 -06003822
Kashyap, Desaid685c262009-11-17 13:16:37 +05303823 /* scsih internal command bits */
3824 ioc->scsih_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3825 ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
3826 mutex_init(&ioc->scsih_cmds.mutex);
3827
Eric Moore635374e2009-03-09 01:21:12 -06003828 /* task management internal command bits */
3829 ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3830 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
3831 mutex_init(&ioc->tm_cmds.mutex);
Eric Moore635374e2009-03-09 01:21:12 -06003832
3833 /* config page internal command bits */
3834 ioc->config_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3835 ioc->config_cmds.status = MPT2_CMD_NOT_USED;
3836 mutex_init(&ioc->config_cmds.mutex);
Eric Moore635374e2009-03-09 01:21:12 -06003837
3838 /* ctl module internal command bits */
3839 ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
Kashyap, Desai769578f2010-06-17 13:49:28 +05303840 ioc->ctl_cmds.sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
Eric Moore635374e2009-03-09 01:21:12 -06003841 ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
3842 mutex_init(&ioc->ctl_cmds.mutex);
Eric Moore635374e2009-03-09 01:21:12 -06003843
Kashyap, Desaif6aee7b2010-03-17 16:26:48 +05303844 if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply ||
3845 !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply ||
Kashyap, Desai769578f2010-06-17 13:49:28 +05303846 !ioc->config_cmds.reply || !ioc->ctl_cmds.reply ||
3847 !ioc->ctl_cmds.sense) {
Kashyap, Desaif6aee7b2010-03-17 16:26:48 +05303848 r = -ENOMEM;
3849 goto out_free_resources;
3850 }
3851
Kashyap, Desai3e2e8332010-06-17 13:47:29 +05303852 if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply ||
3853 !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply ||
3854 !ioc->config_cmds.reply || !ioc->ctl_cmds.reply) {
3855 r = -ENOMEM;
3856 goto out_free_resources;
3857 }
3858
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05303859 init_completion(&ioc->shost_recovery_done);
3860
Eric Moore635374e2009-03-09 01:21:12 -06003861 for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
3862 ioc->event_masks[i] = -1;
3863
3864 /* here we enable the events we care about */
3865 _base_unmask_events(ioc, MPI2_EVENT_SAS_DISCOVERY);
3866 _base_unmask_events(ioc, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE);
3867 _base_unmask_events(ioc, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
3868 _base_unmask_events(ioc, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
3869 _base_unmask_events(ioc, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE);
3870 _base_unmask_events(ioc, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST);
3871 _base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME);
3872 _base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK);
3873 _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS);
Eric Moore635374e2009-03-09 01:21:12 -06003874 _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED);
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303875 r = _base_make_ioc_operational(ioc, CAN_SLEEP);
Eric Moore635374e2009-03-09 01:21:12 -06003876 if (r)
3877 goto out_free_resources;
3878
Kashyap, Desai6cb8ef52010-11-13 04:32:18 +05303879 if (missing_delay[0] != -1 && missing_delay[1] != -1)
3880 _base_update_missing_delay(ioc, missing_delay[0],
3881 missing_delay[1]);
3882
Kashyap, Desaie4750c92009-08-07 19:37:59 +05303883 mpt2sas_base_start_watchdog(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06003884 return 0;
3885
3886 out_free_resources:
3887
3888 ioc->remove_host = 1;
3889 mpt2sas_base_free_resources(ioc);
3890 _base_release_memory_pools(ioc);
Kashyap, Desaifcfe6392009-08-07 19:38:48 +05303891 pci_set_drvdata(ioc->pdev, NULL);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303892 kfree(ioc->pd_handles);
Eric Moore635374e2009-03-09 01:21:12 -06003893 kfree(ioc->tm_cmds.reply);
3894 kfree(ioc->transport_cmds.reply);
Kashyap, Desaie94f6742010-03-17 16:24:52 +05303895 kfree(ioc->scsih_cmds.reply);
Eric Moore635374e2009-03-09 01:21:12 -06003896 kfree(ioc->config_cmds.reply);
3897 kfree(ioc->base_cmds.reply);
3898 kfree(ioc->ctl_cmds.reply);
Kashyap, Desai769578f2010-06-17 13:49:28 +05303899 kfree(ioc->ctl_cmds.sense);
Eric Moore635374e2009-03-09 01:21:12 -06003900 kfree(ioc->pfacts);
3901 ioc->ctl_cmds.reply = NULL;
3902 ioc->base_cmds.reply = NULL;
3903 ioc->tm_cmds.reply = NULL;
Kashyap, Desaie94f6742010-03-17 16:24:52 +05303904 ioc->scsih_cmds.reply = NULL;
Eric Moore635374e2009-03-09 01:21:12 -06003905 ioc->transport_cmds.reply = NULL;
3906 ioc->config_cmds.reply = NULL;
3907 ioc->pfacts = NULL;
3908 return r;
3909}
3910
3911
3912/**
3913 * mpt2sas_base_detach - remove controller instance
3914 * @ioc: per adapter object
3915 *
3916 * Return nothing.
3917 */
3918void
3919mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)
3920{
Eric Moore635374e2009-03-09 01:21:12 -06003921
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303922 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003923 __func__));
3924
Kashyap, Desaie4750c92009-08-07 19:37:59 +05303925 mpt2sas_base_stop_watchdog(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06003926 mpt2sas_base_free_resources(ioc);
3927 _base_release_memory_pools(ioc);
Kashyap, Desaifcfe6392009-08-07 19:38:48 +05303928 pci_set_drvdata(ioc->pdev, NULL);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303929 kfree(ioc->pd_handles);
Eric Moore635374e2009-03-09 01:21:12 -06003930 kfree(ioc->pfacts);
3931 kfree(ioc->ctl_cmds.reply);
Kashyap, Desai769578f2010-06-17 13:49:28 +05303932 kfree(ioc->ctl_cmds.sense);
Eric Moore635374e2009-03-09 01:21:12 -06003933 kfree(ioc->base_cmds.reply);
3934 kfree(ioc->tm_cmds.reply);
3935 kfree(ioc->transport_cmds.reply);
Kashyap, Desaie94f6742010-03-17 16:24:52 +05303936 kfree(ioc->scsih_cmds.reply);
Eric Moore635374e2009-03-09 01:21:12 -06003937 kfree(ioc->config_cmds.reply);
3938}
3939
3940/**
3941 * _base_reset_handler - reset callback handler (for base)
3942 * @ioc: per adapter object
3943 * @reset_phase: phase
3944 *
3945 * The handler for doing any required cleanup or initialization.
3946 *
3947 * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
3948 * MPT2_IOC_DONE_RESET
3949 *
3950 * Return nothing.
3951 */
3952static void
3953_base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
3954{
Kashyap, Desai42244892011-01-04 11:38:39 +05303955 mpt2sas_scsih_reset_handler(ioc, reset_phase);
3956 mpt2sas_ctl_reset_handler(ioc, reset_phase);
Eric Moore635374e2009-03-09 01:21:12 -06003957 switch (reset_phase) {
3958 case MPT2_IOC_PRE_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303959 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Eric Moore635374e2009-03-09 01:21:12 -06003960 "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
3961 break;
3962 case MPT2_IOC_AFTER_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303963 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Eric Moore635374e2009-03-09 01:21:12 -06003964 "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
3965 if (ioc->transport_cmds.status & MPT2_CMD_PENDING) {
3966 ioc->transport_cmds.status |= MPT2_CMD_RESET;
3967 mpt2sas_base_free_smid(ioc, ioc->transport_cmds.smid);
3968 complete(&ioc->transport_cmds.done);
3969 }
3970 if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
3971 ioc->base_cmds.status |= MPT2_CMD_RESET;
3972 mpt2sas_base_free_smid(ioc, ioc->base_cmds.smid);
3973 complete(&ioc->base_cmds.done);
3974 }
3975 if (ioc->config_cmds.status & MPT2_CMD_PENDING) {
3976 ioc->config_cmds.status |= MPT2_CMD_RESET;
3977 mpt2sas_base_free_smid(ioc, ioc->config_cmds.smid);
Alexey Dobriyan4be929b2010-05-24 14:33:03 -07003978 ioc->config_cmds.smid = USHRT_MAX;
Eric Moore635374e2009-03-09 01:21:12 -06003979 complete(&ioc->config_cmds.done);
3980 }
3981 break;
3982 case MPT2_IOC_DONE_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303983 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Eric Moore635374e2009-03-09 01:21:12 -06003984 "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
3985 break;
3986 }
Eric Moore635374e2009-03-09 01:21:12 -06003987}
3988
3989/**
3990 * _wait_for_commands_to_complete - reset controller
3991 * @ioc: Pointer to MPT_ADAPTER structure
3992 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3993 *
3994 * This function waiting(3s) for all pending commands to complete
3995 * prior to putting controller in reset.
3996 */
3997static void
3998_wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
3999{
4000 u32 ioc_state;
4001 unsigned long flags;
4002 u16 i;
4003
4004 ioc->pending_io_count = 0;
4005 if (sleep_flag != CAN_SLEEP)
4006 return;
4007
4008 ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
4009 if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL)
4010 return;
4011
4012 /* pending command count */
4013 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05304014 for (i = 0; i < ioc->scsiio_depth; i++)
Eric Moore635374e2009-03-09 01:21:12 -06004015 if (ioc->scsi_lookup[i].cb_idx != 0xFF)
4016 ioc->pending_io_count++;
4017 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
4018
4019 if (!ioc->pending_io_count)
4020 return;
4021
4022 /* wait for pending commands to complete */
Kashyap, Desaid2742132010-06-17 13:28:55 +05304023 wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ);
Eric Moore635374e2009-03-09 01:21:12 -06004024}
4025
4026/**
4027 * mpt2sas_base_hard_reset_handler - reset controller
4028 * @ioc: Pointer to MPT_ADAPTER structure
4029 * @sleep_flag: CAN_SLEEP or NO_SLEEP
4030 * @type: FORCE_BIG_HAMMER or SOFT_RESET
4031 *
4032 * Returns 0 for success, non-zero for failure.
4033 */
4034int
4035mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
4036 enum reset_type type)
4037{
Kashyap, Desai7b936b02009-09-25 11:44:41 +05304038 int r;
Eric Moore635374e2009-03-09 01:21:12 -06004039 unsigned long flags;
Kashyap, Desai42244892011-01-04 11:38:39 +05304040 u8 pe_complete = ioc->wait_for_port_enable_to_complete;
Eric Moore635374e2009-03-09 01:21:12 -06004041
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05304042 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06004043 __func__));
4044
Eric Moore3cb54692010-07-08 14:44:34 -06004045 if (ioc->pci_error_recovery) {
4046 printk(MPT2SAS_ERR_FMT "%s: pci error recovery reset\n",
4047 ioc->name, __func__);
4048 r = 0;
4049 goto out;
4050 }
4051
Kashyap, Desaifa7f3162009-09-23 17:26:58 +05304052 if (mpt2sas_fwfault_debug)
4053 mpt2sas_halt_firmware(ioc);
4054
Kashyap, Desaid2742132010-06-17 13:28:55 +05304055 /* TODO - What we really should be doing is pulling
4056 * out all the code associated with NO_SLEEP; its never used.
4057 * That is legacy code from mpt fusion driver, ported over.
4058 * I will leave this BUG_ON here for now till its been resolved.
4059 */
4060 BUG_ON(sleep_flag == NO_SLEEP);
4061
4062 /* wait for an active reset in progress to complete */
4063 if (!mutex_trylock(&ioc->reset_in_progress_mutex)) {
4064 do {
4065 ssleep(1);
4066 } while (ioc->shost_recovery == 1);
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05304067 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name,
Kashyap, Desaid2742132010-06-17 13:28:55 +05304068 __func__));
4069 return ioc->ioc_reset_in_progress_status;
Eric Moore635374e2009-03-09 01:21:12 -06004070 }
Kashyap, Desaid2742132010-06-17 13:28:55 +05304071
4072 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06004073 ioc->shost_recovery = 1;
Eric Moore635374e2009-03-09 01:21:12 -06004074 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
4075
4076 _base_reset_handler(ioc, MPT2_IOC_PRE_RESET);
4077 _wait_for_commands_to_complete(ioc, sleep_flag);
4078 _base_mask_interrupts(ioc);
4079 r = _base_make_ioc_ready(ioc, sleep_flag, type);
4080 if (r)
4081 goto out;
4082 _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET);
Kashyap, Desai42244892011-01-04 11:38:39 +05304083
4084 /* If this hard reset is called while port enable is active, then
4085 * there is no reason to call make_ioc_operational
4086 */
4087 if (pe_complete) {
4088 r = -EFAULT;
4089 goto out;
4090 }
Kashyap, Desai7b936b02009-09-25 11:44:41 +05304091 r = _base_make_ioc_operational(ioc, sleep_flag);
Eric Moore635374e2009-03-09 01:21:12 -06004092 if (!r)
4093 _base_reset_handler(ioc, MPT2_IOC_DONE_RESET);
4094 out:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05304095 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %s\n",
Eric Moore635374e2009-03-09 01:21:12 -06004096 ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED")));
4097
4098 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
Kashyap, Desaid2742132010-06-17 13:28:55 +05304099 ioc->ioc_reset_in_progress_status = r;
Kashyap, Desai155dd4c2009-08-20 13:22:00 +05304100 ioc->shost_recovery = 0;
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05304101 complete(&ioc->shost_recovery_done);
Eric Moore635374e2009-03-09 01:21:12 -06004102 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
Kashyap, Desaid2742132010-06-17 13:28:55 +05304103 mutex_unlock(&ioc->reset_in_progress_mutex);
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05304104
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05304105 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name,
Kashyap, Desaid2742132010-06-17 13:28:55 +05304106 __func__));
Eric Moore635374e2009-03-09 01:21:12 -06004107 return r;
4108}