blob: 6825772cfd6a16199ff8b8ab1f53e85ada6b62cb [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
Eric Moore635374e2009-03-09 01:21:12 -060045#include <linux/kernel.h>
46#include <linux/module.h>
47#include <linux/errno.h>
48#include <linux/init.h>
49#include <linux/slab.h>
50#include <linux/types.h>
51#include <linux/pci.h>
52#include <linux/kdev_t.h>
53#include <linux/blkdev.h>
54#include <linux/delay.h>
55#include <linux/interrupt.h>
56#include <linux/dma-mapping.h>
57#include <linux/sort.h>
58#include <linux/io.h>
Kashyap, Desaia8ebd762009-09-23 17:29:29 +053059#include <linux/time.h>
Kashyap, Desaief7c80c2010-04-05 14:20:07 +053060#include <linux/aer.h>
Eric Moore635374e2009-03-09 01:21:12 -060061
62#include "mpt2sas_base.h"
63
64static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS];
65
66#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
Eric Moore635374e2009-03-09 01:21:12 -060067
68static int max_queue_depth = -1;
69module_param(max_queue_depth, int, 0);
70MODULE_PARM_DESC(max_queue_depth, " max controller queue depth ");
71
72static int max_sgl_entries = -1;
73module_param(max_sgl_entries, int, 0);
74MODULE_PARM_DESC(max_sgl_entries, " max sg entries ");
75
76static int msix_disable = -1;
77module_param(msix_disable, int, 0);
78MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
79
Kashyap, Desai6cb8ef52010-11-13 04:32:18 +053080static int missing_delay[2] = {-1, -1};
81module_param_array(missing_delay, int, NULL, 0);
82MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
83
Kashyap, Desai32e0eb52009-09-23 17:28:09 +053084/* diag_buffer_enable is bitwise
Kashyap, Desai1b01fe32009-09-23 17:28:59 +053085 * bit 0 set = TRACE
86 * bit 1 set = SNAPSHOT
87 * bit 2 set = EXTENDED
Kashyap, Desai32e0eb52009-09-23 17:28:09 +053088 *
89 * Either bit can be set, or both
90 */
91static int diag_buffer_enable;
92module_param(diag_buffer_enable, int, 0);
Kashyap, Desai1b01fe32009-09-23 17:28:59 +053093MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
94 "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
Kashyap, Desai32e0eb52009-09-23 17:28:09 +053095
Kashyap, Desaic97951e2011-06-14 10:54:56 +053096static int mpt2sas_fwfault_debug;
Kashyap, Desaifa7f3162009-09-23 17:26:58 +053097MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
98 "and halt firmware - (default=0)");
99
Kashyap, Desaidd5fd332010-06-17 13:31:17 +0530100static int disable_discovery = -1;
101module_param(disable_discovery, int, 0);
102MODULE_PARM_DESC(disable_discovery, " disable discovery ");
103
Kashyap, Desaifa7f3162009-09-23 17:26:58 +0530104/**
105 * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.
106 *
107 */
108static int
109_scsih_set_fwfault_debug(const char *val, struct kernel_param *kp)
110{
111 int ret = param_set_int(val, kp);
112 struct MPT2SAS_ADAPTER *ioc;
113
114 if (ret)
115 return ret;
116
Kashyap, Desaie75b9b62009-12-16 18:52:39 +0530117 printk(KERN_INFO "setting fwfault_debug(%d)\n", mpt2sas_fwfault_debug);
Kashyap, Desaifa7f3162009-09-23 17:26:58 +0530118 list_for_each_entry(ioc, &mpt2sas_ioc_list, list)
119 ioc->fwfault_debug = mpt2sas_fwfault_debug;
120 return 0;
121}
122module_param_call(mpt2sas_fwfault_debug, _scsih_set_fwfault_debug,
123 param_get_int, &mpt2sas_fwfault_debug, 0644);
124
Eric Moore635374e2009-03-09 01:21:12 -0600125/**
126 * _base_fault_reset_work - workq handling ioc fault conditions
127 * @work: input argument, used to derive ioc
128 * Context: sleep.
129 *
130 * Return nothing.
131 */
132static void
133_base_fault_reset_work(struct work_struct *work)
134{
135 struct MPT2SAS_ADAPTER *ioc =
136 container_of(work, struct MPT2SAS_ADAPTER, fault_reset_work.work);
137 unsigned long flags;
138 u32 doorbell;
139 int rc;
140
141 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
Kashyap, Desai155dd4c2009-08-20 13:22:00 +0530142 if (ioc->shost_recovery)
Eric Moore635374e2009-03-09 01:21:12 -0600143 goto rearm_timer;
144 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
145
146 doorbell = mpt2sas_base_get_iocstate(ioc, 0);
147 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
148 rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
149 FORCE_BIG_HAMMER);
150 printk(MPT2SAS_WARN_FMT "%s: hard reset: %s\n", ioc->name,
151 __func__, (rc == 0) ? "success" : "failed");
152 doorbell = mpt2sas_base_get_iocstate(ioc, 0);
153 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
154 mpt2sas_base_fault_info(ioc, doorbell &
155 MPI2_DOORBELL_DATA_MASK);
156 }
157
158 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
159 rearm_timer:
160 if (ioc->fault_reset_work_q)
161 queue_delayed_work(ioc->fault_reset_work_q,
162 &ioc->fault_reset_work,
163 msecs_to_jiffies(FAULT_POLLING_INTERVAL));
164 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
165}
166
Kashyap, Desaie4750c92009-08-07 19:37:59 +0530167/**
168 * mpt2sas_base_start_watchdog - start the fault_reset_work_q
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530169 * @ioc: per adapter object
Kashyap, Desaie4750c92009-08-07 19:37:59 +0530170 * Context: sleep.
171 *
172 * Return nothing.
173 */
174void
175mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc)
176{
177 unsigned long flags;
178
179 if (ioc->fault_reset_work_q)
180 return;
181
182 /* initialize fault polling */
183 INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
184 snprintf(ioc->fault_reset_work_q_name,
185 sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
186 ioc->fault_reset_work_q =
187 create_singlethread_workqueue(ioc->fault_reset_work_q_name);
188 if (!ioc->fault_reset_work_q) {
189 printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n",
190 ioc->name, __func__, __LINE__);
191 return;
192 }
193 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
194 if (ioc->fault_reset_work_q)
195 queue_delayed_work(ioc->fault_reset_work_q,
196 &ioc->fault_reset_work,
197 msecs_to_jiffies(FAULT_POLLING_INTERVAL));
198 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
199}
200
201/**
202 * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530203 * @ioc: per adapter object
Kashyap, Desaie4750c92009-08-07 19:37:59 +0530204 * Context: sleep.
205 *
206 * Return nothing.
207 */
208void
209mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc)
210{
211 unsigned long flags;
212 struct workqueue_struct *wq;
213
214 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
215 wq = ioc->fault_reset_work_q;
216 ioc->fault_reset_work_q = NULL;
217 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
218 if (wq) {
219 if (!cancel_delayed_work(&ioc->fault_reset_work))
220 flush_workqueue(wq);
221 destroy_workqueue(wq);
222 }
223}
224
Kashyap, Desaifa7f3162009-09-23 17:26:58 +0530225/**
226 * mpt2sas_base_fault_info - verbose translation of firmware FAULT code
227 * @ioc: per adapter object
228 * @fault_code: fault code
229 *
230 * Return nothing.
231 */
232void
233mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code)
234{
235 printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n",
236 ioc->name, fault_code);
237}
238
239/**
240 * mpt2sas_halt_firmware - halt's mpt controller firmware
241 * @ioc: per adapter object
242 *
243 * For debugging timeout related issues. Writing 0xCOFFEE00
244 * to the doorbell register will halt controller firmware. With
245 * the purpose to stop both driver and firmware, the enduser can
246 * obtain a ring buffer from controller UART.
247 */
248void
249mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc)
250{
251 u32 doorbell;
252
253 if (!ioc->fwfault_debug)
254 return;
255
256 dump_stack();
257
258 doorbell = readl(&ioc->chip->Doorbell);
259 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
260 mpt2sas_base_fault_info(ioc , doorbell);
261 else {
262 writel(0xC0FFEE00, &ioc->chip->Doorbell);
263 printk(MPT2SAS_ERR_FMT "Firmware is halted due to command "
264 "timeout\n", ioc->name);
265 }
266
267 panic("panic in %s\n", __func__);
268}
269
Eric Moore635374e2009-03-09 01:21:12 -0600270#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
271/**
272 * _base_sas_ioc_info - verbose translation of the ioc status
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530273 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -0600274 * @mpi_reply: reply mf payload returned from firmware
275 * @request_hdr: request mf
276 *
277 * Return nothing.
278 */
279static void
280_base_sas_ioc_info(struct MPT2SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
281 MPI2RequestHeader_t *request_hdr)
282{
283 u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
284 MPI2_IOCSTATUS_MASK;
285 char *desc = NULL;
286 u16 frame_sz;
287 char *func_str = NULL;
288
289 /* SCSI_IO, RAID_PASS are handled from _scsih_scsi_ioc_info */
290 if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
291 request_hdr->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
292 request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION)
293 return;
294
Kashyap, Desaie94f6742010-03-17 16:24:52 +0530295 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
296 return;
297
Eric Moore635374e2009-03-09 01:21:12 -0600298 switch (ioc_status) {
299
300/****************************************************************************
301* Common IOCStatus values for all replies
302****************************************************************************/
303
304 case MPI2_IOCSTATUS_INVALID_FUNCTION:
305 desc = "invalid function";
306 break;
307 case MPI2_IOCSTATUS_BUSY:
308 desc = "busy";
309 break;
310 case MPI2_IOCSTATUS_INVALID_SGL:
311 desc = "invalid sgl";
312 break;
313 case MPI2_IOCSTATUS_INTERNAL_ERROR:
314 desc = "internal error";
315 break;
316 case MPI2_IOCSTATUS_INVALID_VPID:
317 desc = "invalid vpid";
318 break;
319 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
320 desc = "insufficient resources";
321 break;
322 case MPI2_IOCSTATUS_INVALID_FIELD:
323 desc = "invalid field";
324 break;
325 case MPI2_IOCSTATUS_INVALID_STATE:
326 desc = "invalid state";
327 break;
328 case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
329 desc = "op state not supported";
330 break;
331
332/****************************************************************************
333* Config IOCStatus values
334****************************************************************************/
335
336 case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
337 desc = "config invalid action";
338 break;
339 case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
340 desc = "config invalid type";
341 break;
342 case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
343 desc = "config invalid page";
344 break;
345 case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
346 desc = "config invalid data";
347 break;
348 case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
349 desc = "config no defaults";
350 break;
351 case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
352 desc = "config cant commit";
353 break;
354
355/****************************************************************************
356* SCSI IO Reply
357****************************************************************************/
358
359 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
360 case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
361 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
362 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
363 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
364 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
365 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
366 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
367 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
368 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
369 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
370 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
371 break;
372
373/****************************************************************************
374* For use by SCSI Initiator and SCSI Target end-to-end data protection
375****************************************************************************/
376
377 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
378 desc = "eedp guard error";
379 break;
380 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
381 desc = "eedp ref tag error";
382 break;
383 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
384 desc = "eedp app tag error";
385 break;
386
387/****************************************************************************
388* SCSI Target values
389****************************************************************************/
390
391 case MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX:
392 desc = "target invalid io index";
393 break;
394 case MPI2_IOCSTATUS_TARGET_ABORTED:
395 desc = "target aborted";
396 break;
397 case MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE:
398 desc = "target no conn retryable";
399 break;
400 case MPI2_IOCSTATUS_TARGET_NO_CONNECTION:
401 desc = "target no connection";
402 break;
403 case MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH:
404 desc = "target xfer count mismatch";
405 break;
406 case MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR:
407 desc = "target data offset error";
408 break;
409 case MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA:
410 desc = "target too much write data";
411 break;
412 case MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT:
413 desc = "target iu too short";
414 break;
415 case MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT:
416 desc = "target ack nak timeout";
417 break;
418 case MPI2_IOCSTATUS_TARGET_NAK_RECEIVED:
419 desc = "target nak received";
420 break;
421
422/****************************************************************************
423* Serial Attached SCSI values
424****************************************************************************/
425
426 case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
427 desc = "smp request failed";
428 break;
429 case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
430 desc = "smp data overrun";
431 break;
432
433/****************************************************************************
434* Diagnostic Buffer Post / Diagnostic Release values
435****************************************************************************/
436
437 case MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED:
438 desc = "diagnostic released";
439 break;
440 default:
441 break;
442 }
443
444 if (!desc)
445 return;
446
447 switch (request_hdr->Function) {
448 case MPI2_FUNCTION_CONFIG:
449 frame_sz = sizeof(Mpi2ConfigRequest_t) + ioc->sge_size;
450 func_str = "config_page";
451 break;
452 case MPI2_FUNCTION_SCSI_TASK_MGMT:
453 frame_sz = sizeof(Mpi2SCSITaskManagementRequest_t);
454 func_str = "task_mgmt";
455 break;
456 case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
457 frame_sz = sizeof(Mpi2SasIoUnitControlRequest_t);
458 func_str = "sas_iounit_ctl";
459 break;
460 case MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
461 frame_sz = sizeof(Mpi2SepRequest_t);
462 func_str = "enclosure";
463 break;
464 case MPI2_FUNCTION_IOC_INIT:
465 frame_sz = sizeof(Mpi2IOCInitRequest_t);
466 func_str = "ioc_init";
467 break;
468 case MPI2_FUNCTION_PORT_ENABLE:
469 frame_sz = sizeof(Mpi2PortEnableRequest_t);
470 func_str = "port_enable";
471 break;
472 case MPI2_FUNCTION_SMP_PASSTHROUGH:
473 frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size;
474 func_str = "smp_passthru";
475 break;
476 default:
477 frame_sz = 32;
478 func_str = "unknown";
479 break;
480 }
481
482 printk(MPT2SAS_WARN_FMT "ioc_status: %s(0x%04x), request(0x%p),"
483 " (%s)\n", ioc->name, desc, ioc_status, request_hdr, func_str);
484
485 _debug_dump_mf(request_hdr, frame_sz/4);
486}
487
488/**
489 * _base_display_event_data - verbose translation of firmware asyn events
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530490 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -0600491 * @mpi_reply: reply mf payload returned from firmware
492 *
493 * Return nothing.
494 */
495static void
496_base_display_event_data(struct MPT2SAS_ADAPTER *ioc,
497 Mpi2EventNotificationReply_t *mpi_reply)
498{
499 char *desc = NULL;
500 u16 event;
501
502 if (!(ioc->logging_level & MPT_DEBUG_EVENTS))
503 return;
504
505 event = le16_to_cpu(mpi_reply->Event);
506
507 switch (event) {
508 case MPI2_EVENT_LOG_DATA:
509 desc = "Log Data";
510 break;
511 case MPI2_EVENT_STATE_CHANGE:
512 desc = "Status Change";
513 break;
514 case MPI2_EVENT_HARD_RESET_RECEIVED:
515 desc = "Hard Reset Received";
516 break;
517 case MPI2_EVENT_EVENT_CHANGE:
518 desc = "Event Change";
519 break;
Eric Moore635374e2009-03-09 01:21:12 -0600520 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
521 desc = "Device Status Change";
522 break;
523 case MPI2_EVENT_IR_OPERATION_STATUS:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +0530524 if (!ioc->hide_ir_msg)
525 desc = "IR Operation Status";
Eric Moore635374e2009-03-09 01:21:12 -0600526 break;
527 case MPI2_EVENT_SAS_DISCOVERY:
Kashyap, Desaie94f6742010-03-17 16:24:52 +0530528 {
529 Mpi2EventDataSasDiscovery_t *event_data =
530 (Mpi2EventDataSasDiscovery_t *)mpi_reply->EventData;
531 printk(MPT2SAS_INFO_FMT "Discovery: (%s)", ioc->name,
532 (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
533 "start" : "stop");
534 if (event_data->DiscoveryStatus)
535 printk("discovery_status(0x%08x)",
536 le32_to_cpu(event_data->DiscoveryStatus));
Julia Lawall7968f192010-08-05 22:19:36 +0200537 printk("\n");
Kashyap, Desaie94f6742010-03-17 16:24:52 +0530538 return;
539 }
Eric Moore635374e2009-03-09 01:21:12 -0600540 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
541 desc = "SAS Broadcast Primitive";
542 break;
543 case MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
544 desc = "SAS Init Device Status Change";
545 break;
546 case MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW:
547 desc = "SAS Init Table Overflow";
548 break;
549 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
550 desc = "SAS Topology Change List";
551 break;
552 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
553 desc = "SAS Enclosure Device Status Change";
554 break;
555 case MPI2_EVENT_IR_VOLUME:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +0530556 if (!ioc->hide_ir_msg)
557 desc = "IR Volume";
Eric Moore635374e2009-03-09 01:21:12 -0600558 break;
559 case MPI2_EVENT_IR_PHYSICAL_DISK:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +0530560 if (!ioc->hide_ir_msg)
561 desc = "IR Physical Disk";
Eric Moore635374e2009-03-09 01:21:12 -0600562 break;
563 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +0530564 if (!ioc->hide_ir_msg)
565 desc = "IR Configuration Change List";
Eric Moore635374e2009-03-09 01:21:12 -0600566 break;
567 case MPI2_EVENT_LOG_ENTRY_ADDED:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +0530568 if (!ioc->hide_ir_msg)
569 desc = "Log Entry Added";
Eric Moore635374e2009-03-09 01:21:12 -0600570 break;
571 }
572
573 if (!desc)
574 return;
575
576 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, desc);
577}
578#endif
579
580/**
581 * _base_sas_log_info - verbose translation of firmware log info
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530582 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -0600583 * @log_info: log info
584 *
585 * Return nothing.
586 */
587static void
588_base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info)
589{
590 union loginfo_type {
591 u32 loginfo;
592 struct {
593 u32 subcode:16;
594 u32 code:8;
595 u32 originator:4;
596 u32 bus_type:4;
597 } dw;
598 };
599 union loginfo_type sas_loginfo;
600 char *originator_str = NULL;
601
602 sas_loginfo.loginfo = log_info;
603 if (sas_loginfo.dw.bus_type != 3 /*SAS*/)
604 return;
605
Kashyap, Desaibe9e8cd72009-08-07 19:36:43 +0530606 /* each nexus loss loginfo */
607 if (log_info == 0x31170000)
608 return;
609
Eric Moore635374e2009-03-09 01:21:12 -0600610 /* eat the loginfos associated with task aborts */
611 if (ioc->ignore_loginfos && (log_info == 30050000 || log_info ==
612 0x31140000 || log_info == 0x31130000))
613 return;
614
615 switch (sas_loginfo.dw.originator) {
616 case 0:
617 originator_str = "IOP";
618 break;
619 case 1:
620 originator_str = "PL";
621 break;
622 case 2:
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +0530623 if (!ioc->hide_ir_msg)
624 originator_str = "IR";
625 else
626 originator_str = "WarpDrive";
Eric Moore635374e2009-03-09 01:21:12 -0600627 break;
628 }
629
630 printk(MPT2SAS_WARN_FMT "log_info(0x%08x): originator(%s), "
631 "code(0x%02x), sub_code(0x%04x)\n", ioc->name, log_info,
632 originator_str, sas_loginfo.dw.code,
633 sas_loginfo.dw.subcode);
634}
635
636/**
Eric Moore635374e2009-03-09 01:21:12 -0600637 * _base_display_reply_info -
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530638 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -0600639 * @smid: system request message index
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530640 * @msix_index: MSIX table index supplied by the OS
Eric Moore635374e2009-03-09 01:21:12 -0600641 * @reply: reply message frame(lower 32bit addr)
642 *
643 * Return nothing.
644 */
645static void
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530646_base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
Eric Moore635374e2009-03-09 01:21:12 -0600647 u32 reply)
648{
649 MPI2DefaultReply_t *mpi_reply;
650 u16 ioc_status;
651
652 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
653 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
654#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
655 if ((ioc_status & MPI2_IOCSTATUS_MASK) &&
656 (ioc->logging_level & MPT_DEBUG_REPLY)) {
657 _base_sas_ioc_info(ioc , mpi_reply,
658 mpt2sas_base_get_msg_frame(ioc, smid));
659 }
660#endif
661 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
662 _base_sas_log_info(ioc, le32_to_cpu(mpi_reply->IOCLogInfo));
663}
664
665/**
666 * mpt2sas_base_done - base internal command completion routine
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530667 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -0600668 * @smid: system request message index
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530669 * @msix_index: MSIX table index supplied by the OS
Eric Moore635374e2009-03-09 01:21:12 -0600670 * @reply: reply message frame(lower 32bit addr)
671 *
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530672 * Return 1 meaning mf should be freed from _base_interrupt
673 * 0 means the mf is freed from this function.
Eric Moore635374e2009-03-09 01:21:12 -0600674 */
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530675u8
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530676mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
677 u32 reply)
Eric Moore635374e2009-03-09 01:21:12 -0600678{
679 MPI2DefaultReply_t *mpi_reply;
680
681 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
682 if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530683 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600684
685 if (ioc->base_cmds.status == MPT2_CMD_NOT_USED)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530686 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600687
688 ioc->base_cmds.status |= MPT2_CMD_COMPLETE;
689 if (mpi_reply) {
690 ioc->base_cmds.status |= MPT2_CMD_REPLY_VALID;
691 memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
692 }
693 ioc->base_cmds.status &= ~MPT2_CMD_PENDING;
694 complete(&ioc->base_cmds.done);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530695 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600696}
697
698/**
699 * _base_async_event - main callback handler for firmware asyn events
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530700 * @ioc: per adapter object
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530701 * @msix_index: MSIX table index supplied by the OS
Eric Moore635374e2009-03-09 01:21:12 -0600702 * @reply: reply message frame(lower 32bit addr)
703 *
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530704 * Return 1 meaning mf should be freed from _base_interrupt
705 * 0 means the mf is freed from this function.
Eric Moore635374e2009-03-09 01:21:12 -0600706 */
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530707static u8
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530708_base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply)
Eric Moore635374e2009-03-09 01:21:12 -0600709{
710 Mpi2EventNotificationReply_t *mpi_reply;
711 Mpi2EventAckRequest_t *ack_request;
712 u16 smid;
713
714 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
715 if (!mpi_reply)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530716 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600717 if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION)
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530718 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600719#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
720 _base_display_event_data(ioc, mpi_reply);
721#endif
722 if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED))
723 goto out;
724 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
725 if (!smid) {
726 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
727 ioc->name, __func__);
728 goto out;
729 }
730
731 ack_request = mpt2sas_base_get_msg_frame(ioc, smid);
732 memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t));
733 ack_request->Function = MPI2_FUNCTION_EVENT_ACK;
734 ack_request->Event = mpi_reply->Event;
735 ack_request->EventContext = mpi_reply->EventContext;
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530736 ack_request->VF_ID = 0; /* TODO */
737 ack_request->VP_ID = 0;
738 mpt2sas_base_put_smid_default(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -0600739
740 out:
741
742 /* scsih callback handler */
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530743 mpt2sas_scsih_event_callback(ioc, msix_index, reply);
Eric Moore635374e2009-03-09 01:21:12 -0600744
745 /* ctl callback handler */
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530746 mpt2sas_ctl_event_callback(ioc, msix_index, reply);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530747
748 return 1;
Eric Moore635374e2009-03-09 01:21:12 -0600749}
750
751/**
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530752 * _base_get_cb_idx - obtain the callback index
753 * @ioc: per adapter object
754 * @smid: system request message index
755 *
756 * Return callback index.
757 */
758static u8
759_base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid)
760{
761 int i;
Kashyap, Desaid5bd3492011-01-04 11:39:20 +0530762 u8 cb_idx;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530763
Kashyap, Desaid5bd3492011-01-04 11:39:20 +0530764 if (smid < ioc->hi_priority_smid) {
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530765 i = smid - 1;
766 cb_idx = ioc->scsi_lookup[i].cb_idx;
Kashyap, Desaid5bd3492011-01-04 11:39:20 +0530767 } else if (smid < ioc->internal_smid) {
768 i = smid - ioc->hi_priority_smid;
769 cb_idx = ioc->hpr_lookup[i].cb_idx;
770 } else if (smid <= ioc->hba_queue_depth) {
771 i = smid - ioc->internal_smid;
772 cb_idx = ioc->internal_lookup[i].cb_idx;
773 } else
774 cb_idx = 0xFF;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530775 return cb_idx;
776}
777
778/**
Eric Moore635374e2009-03-09 01:21:12 -0600779 * _base_mask_interrupts - disable interrupts
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530780 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -0600781 *
782 * Disabling ResetIRQ, Reply and Doorbell Interrupts
783 *
784 * Return nothing.
785 */
786static void
787_base_mask_interrupts(struct MPT2SAS_ADAPTER *ioc)
788{
789 u32 him_register;
790
791 ioc->mask_interrupts = 1;
792 him_register = readl(&ioc->chip->HostInterruptMask);
793 him_register |= MPI2_HIM_DIM + MPI2_HIM_RIM + MPI2_HIM_RESET_IRQ_MASK;
794 writel(him_register, &ioc->chip->HostInterruptMask);
795 readl(&ioc->chip->HostInterruptMask);
796}
797
798/**
799 * _base_unmask_interrupts - enable interrupts
Kashyap, Desaicef7a122009-09-23 17:27:41 +0530800 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -0600801 *
802 * Enabling only Reply Interrupts
803 *
804 * Return nothing.
805 */
806static void
807_base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc)
808{
809 u32 him_register;
810
Eric Moore635374e2009-03-09 01:21:12 -0600811 him_register = readl(&ioc->chip->HostInterruptMask);
812 him_register &= ~MPI2_HIM_RIM;
813 writel(him_register, &ioc->chip->HostInterruptMask);
814 ioc->mask_interrupts = 0;
815}
816
Kashyap, Desai5b768582009-08-20 13:24:31 +0530817union reply_descriptor {
818 u64 word;
819 struct {
820 u32 low;
821 u32 high;
822 } u;
823};
824
Eric Moore635374e2009-03-09 01:21:12 -0600825/**
826 * _base_interrupt - MPT adapter (IOC) specific interrupt handler.
827 * @irq: irq number (not used)
828 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
829 * @r: pt_regs pointer (not used)
830 *
831 * Return IRQ_HANDLE if processed, else IRQ_NONE.
832 */
833static irqreturn_t
834_base_interrupt(int irq, void *bus_id)
835{
Eric Moore03ea1112009-04-21 15:37:57 -0600836 union reply_descriptor rd;
Kashyap, Desai5b768582009-08-20 13:24:31 +0530837 u32 completed_cmds;
Eric Moore635374e2009-03-09 01:21:12 -0600838 u8 request_desript_type;
839 u16 smid;
840 u8 cb_idx;
841 u32 reply;
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530842 u8 msix_index;
Eric Moore635374e2009-03-09 01:21:12 -0600843 struct MPT2SAS_ADAPTER *ioc = bus_id;
Kashyap, Desai5b768582009-08-20 13:24:31 +0530844 Mpi2ReplyDescriptorsUnion_t *rpf;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530845 u8 rc;
Eric Moore635374e2009-03-09 01:21:12 -0600846
847 if (ioc->mask_interrupts)
848 return IRQ_NONE;
849
Kashyap, Desai5b768582009-08-20 13:24:31 +0530850 rpf = &ioc->reply_post_free[ioc->reply_post_host_index];
851 request_desript_type = rpf->Default.ReplyFlags
852 & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
Eric Moore635374e2009-03-09 01:21:12 -0600853 if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
854 return IRQ_NONE;
855
856 completed_cmds = 0;
Kashyap, Desaidd3741d2010-11-13 04:31:14 +0530857 cb_idx = 0xFF;
Eric Moore635374e2009-03-09 01:21:12 -0600858 do {
Kashyap, Desaic97951e2011-06-14 10:54:56 +0530859 rd.word = le64_to_cpu(rpf->Words);
Eric Moore03ea1112009-04-21 15:37:57 -0600860 if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
Eric Moore635374e2009-03-09 01:21:12 -0600861 goto out;
862 reply = 0;
863 cb_idx = 0xFF;
Kashyap, Desai5b768582009-08-20 13:24:31 +0530864 smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1);
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530865 msix_index = rpf->Default.MSIxIndex;
Eric Moore635374e2009-03-09 01:21:12 -0600866 if (request_desript_type ==
867 MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
Kashyap, Desai5b768582009-08-20 13:24:31 +0530868 reply = le32_to_cpu
869 (rpf->AddressReply.ReplyFrameAddress);
Kashyap, Desaidd3741d2010-11-13 04:31:14 +0530870 if (reply > ioc->reply_dma_max_address ||
871 reply < ioc->reply_dma_min_address)
872 reply = 0;
Eric Moore635374e2009-03-09 01:21:12 -0600873 } else if (request_desript_type ==
874 MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER)
875 goto next;
876 else if (request_desript_type ==
877 MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS)
878 goto next;
879 if (smid)
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530880 cb_idx = _base_get_cb_idx(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -0600881 if (smid && cb_idx != 0xFF) {
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530882 rc = mpt_callbacks[cb_idx](ioc, smid, msix_index,
Kashyap, Desai595bb0b2009-09-14 11:02:48 +0530883 reply);
Eric Moore635374e2009-03-09 01:21:12 -0600884 if (reply)
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530885 _base_display_reply_info(ioc, smid, msix_index,
Eric Moore635374e2009-03-09 01:21:12 -0600886 reply);
Kashyap, Desai77e63ed2009-09-14 11:04:23 +0530887 if (rc)
888 mpt2sas_base_free_smid(ioc, smid);
Eric Moore635374e2009-03-09 01:21:12 -0600889 }
890 if (!smid)
Kashyap, Desai7b936b02009-09-25 11:44:41 +0530891 _base_async_event(ioc, msix_index, reply);
Eric Moore635374e2009-03-09 01:21:12 -0600892
893 /* reply free queue handling */
894 if (reply) {
895 ioc->reply_free_host_index =
896 (ioc->reply_free_host_index ==
897 (ioc->reply_free_queue_depth - 1)) ?
898 0 : ioc->reply_free_host_index + 1;
899 ioc->reply_free[ioc->reply_free_host_index] =
900 cpu_to_le32(reply);
Kashyap, Desai5b768582009-08-20 13:24:31 +0530901 wmb();
Eric Moore635374e2009-03-09 01:21:12 -0600902 writel(ioc->reply_free_host_index,
903 &ioc->chip->ReplyFreeHostIndex);
Eric Moore635374e2009-03-09 01:21:12 -0600904 }
905
906 next:
Kashyap, Desai5b768582009-08-20 13:24:31 +0530907
Kashyap, Desaic97951e2011-06-14 10:54:56 +0530908 rpf->Words = cpu_to_le64(ULLONG_MAX);
Kashyap, Desai5b768582009-08-20 13:24:31 +0530909 ioc->reply_post_host_index = (ioc->reply_post_host_index ==
910 (ioc->reply_post_queue_depth - 1)) ? 0 :
911 ioc->reply_post_host_index + 1;
Eric Moore635374e2009-03-09 01:21:12 -0600912 request_desript_type =
Kashyap, Desai5b768582009-08-20 13:24:31 +0530913 ioc->reply_post_free[ioc->reply_post_host_index].Default.
914 ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
Eric Moore635374e2009-03-09 01:21:12 -0600915 completed_cmds++;
916 if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
917 goto out;
Kashyap, Desai5b768582009-08-20 13:24:31 +0530918 if (!ioc->reply_post_host_index)
919 rpf = ioc->reply_post_free;
920 else
921 rpf++;
Eric Moore635374e2009-03-09 01:21:12 -0600922 } while (1);
923
924 out:
925
926 if (!completed_cmds)
927 return IRQ_NONE;
928
Eric Moore635374e2009-03-09 01:21:12 -0600929 wmb();
Kashyap, Desai5b768582009-08-20 13:24:31 +0530930 writel(ioc->reply_post_host_index, &ioc->chip->ReplyPostHostIndex);
Eric Moore635374e2009-03-09 01:21:12 -0600931 return IRQ_HANDLED;
932}
933
934/**
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300935 * mpt2sas_base_release_callback_handler - clear interrupt callback handler
Eric Moore635374e2009-03-09 01:21:12 -0600936 * @cb_idx: callback index
937 *
938 * Return nothing.
939 */
940void
941mpt2sas_base_release_callback_handler(u8 cb_idx)
942{
943 mpt_callbacks[cb_idx] = NULL;
944}
945
946/**
947 * mpt2sas_base_register_callback_handler - obtain index for the interrupt callback handler
948 * @cb_func: callback function
949 *
950 * Returns cb_func.
951 */
952u8
953mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func)
954{
955 u8 cb_idx;
956
957 for (cb_idx = MPT_MAX_CALLBACKS-1; cb_idx; cb_idx--)
958 if (mpt_callbacks[cb_idx] == NULL)
959 break;
960
961 mpt_callbacks[cb_idx] = cb_func;
962 return cb_idx;
963}
964
965/**
966 * mpt2sas_base_initialize_callback_handler - initialize the interrupt callback handler
967 *
968 * Return nothing.
969 */
970void
971mpt2sas_base_initialize_callback_handler(void)
972{
973 u8 cb_idx;
974
975 for (cb_idx = 0; cb_idx < MPT_MAX_CALLBACKS; cb_idx++)
976 mpt2sas_base_release_callback_handler(cb_idx);
977}
978
979/**
980 * mpt2sas_base_build_zero_len_sge - build zero length sg entry
981 * @ioc: per adapter object
982 * @paddr: virtual address for SGE
983 *
984 * Create a zero length scatter gather entry to insure the IOCs hardware has
985 * something to use if the target device goes brain dead and tries
986 * to send data even when none is asked for.
987 *
988 * Return nothing.
989 */
990void
991mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr)
992{
993 u32 flags_length = (u32)((MPI2_SGE_FLAGS_LAST_ELEMENT |
994 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST |
995 MPI2_SGE_FLAGS_SIMPLE_ELEMENT) <<
996 MPI2_SGE_FLAGS_SHIFT);
997 ioc->base_add_sg_single(paddr, flags_length, -1);
998}
999
1000/**
1001 * _base_add_sg_single_32 - Place a simple 32 bit SGE at address pAddr.
1002 * @paddr: virtual address for SGE
1003 * @flags_length: SGE flags and data transfer length
1004 * @dma_addr: Physical address
1005 *
1006 * Return nothing.
1007 */
1008static void
1009_base_add_sg_single_32(void *paddr, u32 flags_length, dma_addr_t dma_addr)
1010{
1011 Mpi2SGESimple32_t *sgel = paddr;
1012
1013 flags_length |= (MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
1014 MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
1015 sgel->FlagsLength = cpu_to_le32(flags_length);
1016 sgel->Address = cpu_to_le32(dma_addr);
1017}
1018
1019
1020/**
1021 * _base_add_sg_single_64 - Place a simple 64 bit SGE at address pAddr.
1022 * @paddr: virtual address for SGE
1023 * @flags_length: SGE flags and data transfer length
1024 * @dma_addr: Physical address
1025 *
1026 * Return nothing.
1027 */
1028static void
1029_base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr)
1030{
1031 Mpi2SGESimple64_t *sgel = paddr;
1032
1033 flags_length |= (MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
1034 MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
1035 sgel->FlagsLength = cpu_to_le32(flags_length);
1036 sgel->Address = cpu_to_le64(dma_addr);
1037}
1038
1039#define convert_to_kb(x) ((x) << (PAGE_SHIFT - 10))
1040
1041/**
1042 * _base_config_dma_addressing - set dma addressing
1043 * @ioc: per adapter object
1044 * @pdev: PCI device struct
1045 *
1046 * Returns 0 for success, non-zero for failure.
1047 */
1048static int
1049_base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev)
1050{
1051 struct sysinfo s;
1052 char *desc = NULL;
1053
1054 if (sizeof(dma_addr_t) > 4) {
1055 const uint64_t required_mask =
1056 dma_get_required_mask(&pdev->dev);
Yang Hongyange9304382009-04-13 14:40:14 -07001057 if ((required_mask > DMA_BIT_MASK(32)) && !pci_set_dma_mask(pdev,
1058 DMA_BIT_MASK(64)) && !pci_set_consistent_dma_mask(pdev,
1059 DMA_BIT_MASK(64))) {
Eric Moore635374e2009-03-09 01:21:12 -06001060 ioc->base_add_sg_single = &_base_add_sg_single_64;
1061 ioc->sge_size = sizeof(Mpi2SGESimple64_t);
1062 desc = "64";
1063 goto out;
1064 }
1065 }
1066
Yang Hongyange9304382009-04-13 14:40:14 -07001067 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
1068 && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
Eric Moore635374e2009-03-09 01:21:12 -06001069 ioc->base_add_sg_single = &_base_add_sg_single_32;
1070 ioc->sge_size = sizeof(Mpi2SGESimple32_t);
1071 desc = "32";
1072 } else
1073 return -ENODEV;
1074
1075 out:
1076 si_meminfo(&s);
1077 printk(MPT2SAS_INFO_FMT "%s BIT PCI BUS DMA ADDRESSING SUPPORTED, "
1078 "total mem (%ld kB)\n", ioc->name, desc, convert_to_kb(s.totalram));
1079
1080 return 0;
1081}
1082
1083/**
1084 * _base_save_msix_table - backup msix vector table
1085 * @ioc: per adapter object
1086 *
1087 * This address an errata where diag reset clears out the table
1088 */
1089static void
1090_base_save_msix_table(struct MPT2SAS_ADAPTER *ioc)
1091{
1092 int i;
1093
1094 if (!ioc->msix_enable || ioc->msix_table_backup == NULL)
1095 return;
1096
1097 for (i = 0; i < ioc->msix_vector_count; i++)
1098 ioc->msix_table_backup[i] = ioc->msix_table[i];
1099}
1100
1101/**
1102 * _base_restore_msix_table - this restores the msix vector table
1103 * @ioc: per adapter object
1104 *
1105 */
1106static void
1107_base_restore_msix_table(struct MPT2SAS_ADAPTER *ioc)
1108{
1109 int i;
1110
1111 if (!ioc->msix_enable || ioc->msix_table_backup == NULL)
1112 return;
1113
1114 for (i = 0; i < ioc->msix_vector_count; i++)
1115 ioc->msix_table[i] = ioc->msix_table_backup[i];
1116}
1117
1118/**
1119 * _base_check_enable_msix - checks MSIX capabable.
1120 * @ioc: per adapter object
1121 *
1122 * Check to see if card is capable of MSIX, and set number
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001123 * of available msix vectors
Eric Moore635374e2009-03-09 01:21:12 -06001124 */
1125static int
1126_base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
1127{
1128 int base;
1129 u16 message_control;
1130 u32 msix_table_offset;
1131
1132 base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
1133 if (!base) {
1134 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not "
1135 "supported\n", ioc->name));
1136 return -EINVAL;
1137 }
1138
1139 /* get msix vector count */
1140 pci_read_config_word(ioc->pdev, base + 2, &message_control);
1141 ioc->msix_vector_count = (message_control & 0x3FF) + 1;
1142
1143 /* get msix table */
1144 pci_read_config_dword(ioc->pdev, base + 4, &msix_table_offset);
1145 msix_table_offset &= 0xFFFFFFF8;
1146 ioc->msix_table = (u32 *)((void *)ioc->chip + msix_table_offset);
1147
1148 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, "
1149 "vector_count(%d), table_offset(0x%08x), table(%p)\n", ioc->name,
1150 ioc->msix_vector_count, msix_table_offset, ioc->msix_table));
1151 return 0;
1152}
1153
1154/**
1155 * _base_disable_msix - disables msix
1156 * @ioc: per adapter object
1157 *
1158 */
1159static void
1160_base_disable_msix(struct MPT2SAS_ADAPTER *ioc)
1161{
1162 if (ioc->msix_enable) {
1163 pci_disable_msix(ioc->pdev);
1164 kfree(ioc->msix_table_backup);
1165 ioc->msix_table_backup = NULL;
1166 ioc->msix_enable = 0;
1167 }
1168}
1169
1170/**
1171 * _base_enable_msix - enables msix, failback to io_apic
1172 * @ioc: per adapter object
1173 *
1174 */
1175static int
1176_base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
1177{
1178 struct msix_entry entries;
1179 int r;
1180 u8 try_msix = 0;
1181
1182 if (msix_disable == -1 || msix_disable == 0)
1183 try_msix = 1;
1184
1185 if (!try_msix)
1186 goto try_ioapic;
1187
1188 if (_base_check_enable_msix(ioc) != 0)
1189 goto try_ioapic;
1190
1191 ioc->msix_table_backup = kcalloc(ioc->msix_vector_count,
1192 sizeof(u32), GFP_KERNEL);
1193 if (!ioc->msix_table_backup) {
1194 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation for "
1195 "msix_table_backup failed!!!\n", ioc->name));
1196 goto try_ioapic;
1197 }
1198
1199 memset(&entries, 0, sizeof(struct msix_entry));
1200 r = pci_enable_msix(ioc->pdev, &entries, 1);
1201 if (r) {
1202 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "pci_enable_msix "
1203 "failed (r=%d) !!!\n", ioc->name, r));
1204 goto try_ioapic;
1205 }
1206
1207 r = request_irq(entries.vector, _base_interrupt, IRQF_SHARED,
1208 ioc->name, ioc);
1209 if (r) {
1210 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "unable to allocate "
1211 "interrupt %d !!!\n", ioc->name, entries.vector));
1212 pci_disable_msix(ioc->pdev);
1213 goto try_ioapic;
1214 }
1215
1216 ioc->pci_irq = entries.vector;
1217 ioc->msix_enable = 1;
1218 return 0;
1219
1220/* failback to io_apic interrupt routing */
1221 try_ioapic:
1222
1223 r = request_irq(ioc->pdev->irq, _base_interrupt, IRQF_SHARED,
1224 ioc->name, ioc);
1225 if (r) {
1226 printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n",
1227 ioc->name, ioc->pdev->irq);
1228 r = -EBUSY;
1229 goto out_fail;
1230 }
1231
1232 ioc->pci_irq = ioc->pdev->irq;
1233 return 0;
1234
1235 out_fail:
1236 return r;
1237}
1238
1239/**
1240 * mpt2sas_base_map_resources - map in controller resources (io/irq/memap)
1241 * @ioc: per adapter object
1242 *
1243 * Returns 0 for success, non-zero for failure.
1244 */
1245int
1246mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
1247{
1248 struct pci_dev *pdev = ioc->pdev;
1249 u32 memap_sz;
1250 u32 pio_sz;
1251 int i, r = 0;
Kashyap, Desai6846e752009-12-16 18:51:45 +05301252 u64 pio_chip = 0;
1253 u64 chip_phys = 0;
Eric Moore635374e2009-03-09 01:21:12 -06001254
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05301255 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n",
Eric Moore635374e2009-03-09 01:21:12 -06001256 ioc->name, __func__));
1257
1258 ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
1259 if (pci_enable_device_mem(pdev)) {
1260 printk(MPT2SAS_WARN_FMT "pci_enable_device_mem: "
1261 "failed\n", ioc->name);
1262 return -ENODEV;
1263 }
1264
1265
1266 if (pci_request_selected_regions(pdev, ioc->bars,
1267 MPT2SAS_DRIVER_NAME)) {
1268 printk(MPT2SAS_WARN_FMT "pci_request_selected_regions: "
1269 "failed\n", ioc->name);
1270 r = -ENODEV;
1271 goto out_fail;
1272 }
1273
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05301274 /* AER (Advanced Error Reporting) hooks */
1275 pci_enable_pcie_error_reporting(pdev);
1276
Eric Moore635374e2009-03-09 01:21:12 -06001277 pci_set_master(pdev);
1278
1279 if (_base_config_dma_addressing(ioc, pdev) != 0) {
1280 printk(MPT2SAS_WARN_FMT "no suitable DMA mask for %s\n",
1281 ioc->name, pci_name(pdev));
1282 r = -ENODEV;
1283 goto out_fail;
1284 }
1285
1286 for (i = 0, memap_sz = 0, pio_sz = 0 ; i < DEVICE_COUNT_RESOURCE; i++) {
Richard A Laryfc193172010-03-12 15:27:06 -08001287 if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
Eric Moore635374e2009-03-09 01:21:12 -06001288 if (pio_sz)
1289 continue;
Kashyap, Desai6846e752009-12-16 18:51:45 +05301290 pio_chip = (u64)pci_resource_start(pdev, i);
Eric Moore635374e2009-03-09 01:21:12 -06001291 pio_sz = pci_resource_len(pdev, i);
1292 } else {
1293 if (memap_sz)
1294 continue;
Richard A Laryfc193172010-03-12 15:27:06 -08001295 /* verify memory resource is valid before using */
1296 if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
1297 ioc->chip_phys = pci_resource_start(pdev, i);
1298 chip_phys = (u64)ioc->chip_phys;
1299 memap_sz = pci_resource_len(pdev, i);
1300 ioc->chip = ioremap(ioc->chip_phys, memap_sz);
1301 if (ioc->chip == NULL) {
1302 printk(MPT2SAS_ERR_FMT "unable to map "
1303 "adapter memory!\n", ioc->name);
1304 r = -EINVAL;
1305 goto out_fail;
1306 }
Eric Moore635374e2009-03-09 01:21:12 -06001307 }
1308 }
1309 }
1310
Eric Moore635374e2009-03-09 01:21:12 -06001311 _base_mask_interrupts(ioc);
1312 r = _base_enable_msix(ioc);
1313 if (r)
1314 goto out_fail;
1315
1316 printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n",
1317 ioc->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
1318 "IO-APIC enabled"), ioc->pci_irq);
Kashyap, Desai6846e752009-12-16 18:51:45 +05301319 printk(MPT2SAS_INFO_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n",
1320 ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz);
1321 printk(MPT2SAS_INFO_FMT "ioport(0x%016llx), size(%d)\n",
1322 ioc->name, (unsigned long long)pio_chip, pio_sz);
Eric Moore635374e2009-03-09 01:21:12 -06001323
Eric Moore3cb54692010-07-08 14:44:34 -06001324 /* Save PCI configuration state for recovery from PCI AER/EEH errors */
1325 pci_save_state(pdev);
1326
Eric Moore635374e2009-03-09 01:21:12 -06001327 return 0;
1328
1329 out_fail:
1330 if (ioc->chip_phys)
1331 iounmap(ioc->chip);
1332 ioc->chip_phys = 0;
1333 ioc->pci_irq = -1;
1334 pci_release_selected_regions(ioc->pdev, ioc->bars);
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05301335 pci_disable_pcie_error_reporting(pdev);
Eric Moore635374e2009-03-09 01:21:12 -06001336 pci_disable_device(pdev);
Eric Moore635374e2009-03-09 01:21:12 -06001337 return r;
1338}
1339
1340/**
Eric Moore635374e2009-03-09 01:21:12 -06001341 * mpt2sas_base_get_msg_frame - obtain request mf pointer
1342 * @ioc: per adapter object
1343 * @smid: system request message index(smid zero is invalid)
1344 *
1345 * Returns virt pointer to message frame.
1346 */
1347void *
1348mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1349{
1350 return (void *)(ioc->request + (smid * ioc->request_sz));
1351}
1352
1353/**
1354 * mpt2sas_base_get_sense_buffer - obtain a sense buffer assigned to a mf request
1355 * @ioc: per adapter object
1356 * @smid: system request message index
1357 *
1358 * Returns virt pointer to sense buffer.
1359 */
1360void *
1361mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1362{
1363 return (void *)(ioc->sense + ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
1364}
1365
1366/**
1367 * mpt2sas_base_get_sense_buffer_dma - obtain a sense buffer assigned to a mf request
1368 * @ioc: per adapter object
1369 * @smid: system request message index
1370 *
Kashyap, Desaiec9472c2009-09-23 17:34:13 +05301371 * Returns phys pointer to the low 32bit address of the sense buffer.
Eric Moore635374e2009-03-09 01:21:12 -06001372 */
Kashyap, Desaiec9472c2009-09-23 17:34:13 +05301373__le32
Eric Moore635374e2009-03-09 01:21:12 -06001374mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1375{
Kashyap, Desaiec9472c2009-09-23 17:34:13 +05301376 return cpu_to_le32(ioc->sense_dma +
1377 ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
Eric Moore635374e2009-03-09 01:21:12 -06001378}
1379
1380/**
1381 * mpt2sas_base_get_reply_virt_addr - obtain reply frames virt address
1382 * @ioc: per adapter object
1383 * @phys_addr: lower 32 physical addr of the reply
1384 *
1385 * Converts 32bit lower physical addr into a virt address.
1386 */
1387void *
1388mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr)
1389{
1390 if (!phys_addr)
1391 return NULL;
1392 return ioc->reply + (phys_addr - (u32)ioc->reply_dma);
1393}
1394
1395/**
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301396 * mpt2sas_base_get_smid - obtain a free smid from internal queue
Eric Moore635374e2009-03-09 01:21:12 -06001397 * @ioc: per adapter object
1398 * @cb_idx: callback index
1399 *
1400 * Returns smid (zero is invalid)
1401 */
1402u16
1403mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx)
1404{
1405 unsigned long flags;
1406 struct request_tracker *request;
1407 u16 smid;
1408
1409 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301410 if (list_empty(&ioc->internal_free_list)) {
1411 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1412 printk(MPT2SAS_ERR_FMT "%s: smid not available\n",
1413 ioc->name, __func__);
1414 return 0;
1415 }
1416
1417 request = list_entry(ioc->internal_free_list.next,
1418 struct request_tracker, tracker_list);
1419 request->cb_idx = cb_idx;
1420 smid = request->smid;
1421 list_del(&request->tracker_list);
1422 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1423 return smid;
1424}
1425
1426/**
1427 * mpt2sas_base_get_smid_scsiio - obtain a free smid from scsiio queue
1428 * @ioc: per adapter object
1429 * @cb_idx: callback index
1430 * @scmd: pointer to scsi command object
1431 *
1432 * Returns smid (zero is invalid)
1433 */
1434u16
1435mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx,
1436 struct scsi_cmnd *scmd)
1437{
1438 unsigned long flags;
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05301439 struct scsiio_tracker *request;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301440 u16 smid;
1441
1442 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06001443 if (list_empty(&ioc->free_list)) {
1444 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1445 printk(MPT2SAS_ERR_FMT "%s: smid not available\n",
1446 ioc->name, __func__);
1447 return 0;
1448 }
1449
1450 request = list_entry(ioc->free_list.next,
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05301451 struct scsiio_tracker, tracker_list);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301452 request->scmd = scmd;
1453 request->cb_idx = cb_idx;
1454 smid = request->smid;
1455 list_del(&request->tracker_list);
1456 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1457 return smid;
1458}
1459
1460/**
1461 * mpt2sas_base_get_smid_hpr - obtain a free smid from hi-priority queue
1462 * @ioc: per adapter object
1463 * @cb_idx: callback index
1464 *
1465 * Returns smid (zero is invalid)
1466 */
1467u16
1468mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx)
1469{
1470 unsigned long flags;
1471 struct request_tracker *request;
1472 u16 smid;
1473
1474 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1475 if (list_empty(&ioc->hpr_free_list)) {
1476 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1477 return 0;
1478 }
1479
1480 request = list_entry(ioc->hpr_free_list.next,
1481 struct request_tracker, tracker_list);
Eric Moore635374e2009-03-09 01:21:12 -06001482 request->cb_idx = cb_idx;
1483 smid = request->smid;
1484 list_del(&request->tracker_list);
1485 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1486 return smid;
1487}
1488
1489
1490/**
1491 * mpt2sas_base_free_smid - put smid back on free_list
1492 * @ioc: per adapter object
1493 * @smid: system request message index
1494 *
1495 * Return nothing.
1496 */
1497void
1498mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1499{
1500 unsigned long flags;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301501 int i;
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301502 struct chain_tracker *chain_req, *next;
Eric Moore635374e2009-03-09 01:21:12 -06001503
1504 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05301505 if (smid < ioc->hi_priority_smid) {
1506 /* scsiio queue */
1507 i = smid - 1;
1508 if (!list_empty(&ioc->scsi_lookup[i].chain_list)) {
1509 list_for_each_entry_safe(chain_req, next,
1510 &ioc->scsi_lookup[i].chain_list, tracker_list) {
1511 list_del_init(&chain_req->tracker_list);
1512 list_add_tail(&chain_req->tracker_list,
1513 &ioc->free_chain_list);
1514 }
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301515 }
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05301516 ioc->scsi_lookup[i].cb_idx = 0xFF;
1517 ioc->scsi_lookup[i].scmd = NULL;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301518 ioc->scsi_lookup[i].direct_io = 0;
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05301519 list_add_tail(&ioc->scsi_lookup[i].tracker_list,
1520 &ioc->free_list);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301521 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05301522
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05301523 /*
1524 * See _wait_for_commands_to_complete() call with regards
1525 * to this code.
1526 */
1527 if (ioc->shost_recovery && ioc->pending_io_count) {
1528 if (ioc->pending_io_count == 1)
1529 wake_up(&ioc->reset_wq);
1530 ioc->pending_io_count--;
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301531 }
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05301532 return;
1533 } else if (smid < ioc->internal_smid) {
1534 /* hi-priority */
1535 i = smid - ioc->hi_priority_smid;
1536 ioc->hpr_lookup[i].cb_idx = 0xFF;
1537 list_add_tail(&ioc->hpr_lookup[i].tracker_list,
1538 &ioc->hpr_free_list);
1539 } else if (smid <= ioc->hba_queue_depth) {
1540 /* internal queue */
1541 i = smid - ioc->internal_smid;
1542 ioc->internal_lookup[i].cb_idx = 0xFF;
1543 list_add_tail(&ioc->internal_lookup[i].tracker_list,
1544 &ioc->internal_free_list);
Kashyap, Desai35f805b2010-11-13 04:34:06 +05301545 }
Eric Moore635374e2009-03-09 01:21:12 -06001546 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06001547}
1548
1549/**
1550 * _base_writeq - 64 bit write to MMIO
1551 * @ioc: per adapter object
1552 * @b: data payload
1553 * @addr: address in MMIO space
1554 * @writeq_lock: spin lock
1555 *
1556 * Glue for handling an atomic 64 bit word to MMIO. This special handling takes
1557 * care of 32 bit environment where its not quarenteed to send the entire word
1558 * in one transfer.
1559 */
1560#ifndef writeq
1561static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
1562 spinlock_t *writeq_lock)
1563{
1564 unsigned long flags;
1565 __u64 data_out = cpu_to_le64(b);
1566
1567 spin_lock_irqsave(writeq_lock, flags);
1568 writel((u32)(data_out), addr);
1569 writel((u32)(data_out >> 32), (addr + 4));
1570 spin_unlock_irqrestore(writeq_lock, flags);
1571}
1572#else
1573static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
1574 spinlock_t *writeq_lock)
1575{
1576 writeq(cpu_to_le64(b), addr);
1577}
1578#endif
1579
1580/**
1581 * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware
1582 * @ioc: per adapter object
1583 * @smid: system request message index
Eric Moore635374e2009-03-09 01:21:12 -06001584 * @handle: device handle
1585 *
1586 * Return nothing.
1587 */
1588void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301589mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u16 handle)
Eric Moore635374e2009-03-09 01:21:12 -06001590{
1591 Mpi2RequestDescriptorUnion_t descriptor;
1592 u64 *request = (u64 *)&descriptor;
1593
1594
1595 descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301596 descriptor.SCSIIO.MSIxIndex = 0; /* TODO */
Eric Moore635374e2009-03-09 01:21:12 -06001597 descriptor.SCSIIO.SMID = cpu_to_le16(smid);
1598 descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
1599 descriptor.SCSIIO.LMID = 0;
1600 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1601 &ioc->scsi_lookup_lock);
1602}
1603
1604
1605/**
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001606 * mpt2sas_base_put_smid_hi_priority - send Task Management request to firmware
Eric Moore635374e2009-03-09 01:21:12 -06001607 * @ioc: per adapter object
1608 * @smid: system request message index
Eric Moore635374e2009-03-09 01:21:12 -06001609 *
1610 * Return nothing.
1611 */
1612void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301613mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid)
Eric Moore635374e2009-03-09 01:21:12 -06001614{
1615 Mpi2RequestDescriptorUnion_t descriptor;
1616 u64 *request = (u64 *)&descriptor;
1617
1618 descriptor.HighPriority.RequestFlags =
1619 MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301620 descriptor.HighPriority.MSIxIndex = 0; /* TODO */
Eric Moore635374e2009-03-09 01:21:12 -06001621 descriptor.HighPriority.SMID = cpu_to_le16(smid);
1622 descriptor.HighPriority.LMID = 0;
1623 descriptor.HighPriority.Reserved1 = 0;
1624 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1625 &ioc->scsi_lookup_lock);
1626}
1627
1628/**
1629 * mpt2sas_base_put_smid_default - Default, primarily used for config pages
1630 * @ioc: per adapter object
1631 * @smid: system request message index
Eric Moore635374e2009-03-09 01:21:12 -06001632 *
1633 * Return nothing.
1634 */
1635void
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301636mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid)
Eric Moore635374e2009-03-09 01:21:12 -06001637{
1638 Mpi2RequestDescriptorUnion_t descriptor;
1639 u64 *request = (u64 *)&descriptor;
1640
1641 descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301642 descriptor.Default.MSIxIndex = 0; /* TODO */
Eric Moore635374e2009-03-09 01:21:12 -06001643 descriptor.Default.SMID = cpu_to_le16(smid);
1644 descriptor.Default.LMID = 0;
1645 descriptor.Default.DescriptorTypeDependent = 0;
1646 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1647 &ioc->scsi_lookup_lock);
1648}
1649
1650/**
1651 * mpt2sas_base_put_smid_target_assist - send Target Assist/Status to firmware
1652 * @ioc: per adapter object
1653 * @smid: system request message index
Eric Moore635374e2009-03-09 01:21:12 -06001654 * @io_index: value used to track the IO
1655 *
1656 * Return nothing.
1657 */
1658void
1659mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301660 u16 io_index)
Eric Moore635374e2009-03-09 01:21:12 -06001661{
1662 Mpi2RequestDescriptorUnion_t descriptor;
1663 u64 *request = (u64 *)&descriptor;
1664
1665 descriptor.SCSITarget.RequestFlags =
1666 MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05301667 descriptor.SCSITarget.MSIxIndex = 0; /* TODO */
Eric Moore635374e2009-03-09 01:21:12 -06001668 descriptor.SCSITarget.SMID = cpu_to_le16(smid);
1669 descriptor.SCSITarget.LMID = 0;
1670 descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index);
1671 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1672 &ioc->scsi_lookup_lock);
1673}
1674
1675/**
Eric Mooref0f9cc12009-04-21 15:40:48 -06001676 * _base_display_dell_branding - Disply branding string
1677 * @ioc: per adapter object
1678 *
1679 * Return nothing.
1680 */
1681static void
1682_base_display_dell_branding(struct MPT2SAS_ADAPTER *ioc)
1683{
1684 char dell_branding[MPT2SAS_DELL_BRANDING_SIZE];
1685
1686 if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_DELL)
1687 return;
1688
1689 memset(dell_branding, 0, MPT2SAS_DELL_BRANDING_SIZE);
1690 switch (ioc->pdev->subsystem_device) {
1691 case MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID:
1692 strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING,
1693 MPT2SAS_DELL_BRANDING_SIZE - 1);
1694 break;
1695 case MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID:
1696 strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING,
1697 MPT2SAS_DELL_BRANDING_SIZE - 1);
1698 break;
1699 case MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID:
1700 strncpy(dell_branding,
1701 MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING,
1702 MPT2SAS_DELL_BRANDING_SIZE - 1);
1703 break;
1704 case MPT2SAS_DELL_PERC_H200_MODULAR_SSDID:
1705 strncpy(dell_branding,
1706 MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING,
1707 MPT2SAS_DELL_BRANDING_SIZE - 1);
1708 break;
1709 case MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID:
1710 strncpy(dell_branding,
1711 MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING,
1712 MPT2SAS_DELL_BRANDING_SIZE - 1);
1713 break;
1714 case MPT2SAS_DELL_PERC_H200_SSDID:
1715 strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_BRANDING,
1716 MPT2SAS_DELL_BRANDING_SIZE - 1);
1717 break;
1718 case MPT2SAS_DELL_6GBPS_SAS_SSDID:
1719 strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_BRANDING,
1720 MPT2SAS_DELL_BRANDING_SIZE - 1);
1721 break;
1722 default:
1723 sprintf(dell_branding, "0x%4X", ioc->pdev->subsystem_device);
1724 break;
1725 }
1726
1727 printk(MPT2SAS_INFO_FMT "%s: Vendor(0x%04X), Device(0x%04X),"
1728 " SSVID(0x%04X), SSDID(0x%04X)\n", ioc->name, dell_branding,
1729 ioc->pdev->vendor, ioc->pdev->device, ioc->pdev->subsystem_vendor,
1730 ioc->pdev->subsystem_device);
1731}
1732
1733/**
Kashyap, Desaifb396be2011-01-04 11:36:37 +05301734 * _base_display_intel_branding - Display branding string
1735 * @ioc: per adapter object
1736 *
1737 * Return nothing.
1738 */
1739static void
1740_base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
1741{
Kashyap, Desaiab3e5f62011-06-14 10:57:31 +05301742 if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL)
1743 return;
Kashyap, Desaifb396be2011-01-04 11:36:37 +05301744
Kashyap, Desaiab3e5f62011-06-14 10:57:31 +05301745 switch (ioc->pdev->device) {
1746 case MPI2_MFGPAGE_DEVID_SAS2008:
Kashyap, Desaifb396be2011-01-04 11:36:37 +05301747 switch (ioc->pdev->subsystem_device) {
1748 case MPT2SAS_INTEL_RMS2LL080_SSDID:
1749 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1750 MPT2SAS_INTEL_RMS2LL080_BRANDING);
1751 break;
1752 case MPT2SAS_INTEL_RMS2LL040_SSDID:
1753 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1754 MPT2SAS_INTEL_RMS2LL040_BRANDING);
1755 break;
Kashyap, Desaiab3e5f62011-06-14 10:57:31 +05301756 default:
1757 break;
Kashyap, Desaifb396be2011-01-04 11:36:37 +05301758 }
Kashyap, Desaiab3e5f62011-06-14 10:57:31 +05301759 case MPI2_MFGPAGE_DEVID_SAS2308_2:
1760 switch (ioc->pdev->subsystem_device) {
1761 case MPT2SAS_INTEL_RS25GB008_SSDID:
1762 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1763 MPT2SAS_INTEL_RS25GB008_BRANDING);
1764 break;
1765 default:
1766 break;
1767 }
1768 default:
1769 break;
Kashyap, Desaifb396be2011-01-04 11:36:37 +05301770 }
1771}
1772
1773/**
Kashyap, Desai0a2385c2011-03-15 20:04:26 +05301774 * _base_display_hp_branding - Display branding string
1775 * @ioc: per adapter object
1776 *
1777 * Return nothing.
1778 */
1779static void
1780_base_display_hp_branding(struct MPT2SAS_ADAPTER *ioc)
1781{
1782 if (ioc->pdev->subsystem_vendor != MPT2SAS_HP_3PAR_SSVID)
1783 return;
1784
1785 switch (ioc->pdev->device) {
1786 case MPI2_MFGPAGE_DEVID_SAS2004:
1787 switch (ioc->pdev->subsystem_device) {
1788 case MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID:
1789 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1790 MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING);
1791 break;
1792 default:
1793 break;
1794 }
1795 case MPI2_MFGPAGE_DEVID_SAS2308_2:
1796 switch (ioc->pdev->subsystem_device) {
1797 case MPT2SAS_HP_2_4_INTERNAL_SSDID:
1798 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1799 MPT2SAS_HP_2_4_INTERNAL_BRANDING);
1800 break;
1801 case MPT2SAS_HP_2_4_EXTERNAL_SSDID:
1802 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1803 MPT2SAS_HP_2_4_EXTERNAL_BRANDING);
1804 break;
1805 case MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID:
1806 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1807 MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING);
1808 break;
1809 case MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID:
1810 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1811 MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING);
1812 break;
1813 default:
1814 break;
1815 }
1816 default:
1817 break;
1818 }
1819}
1820
1821/**
Eric Moore635374e2009-03-09 01:21:12 -06001822 * _base_display_ioc_capabilities - Disply IOC's capabilities.
1823 * @ioc: per adapter object
1824 *
1825 * Return nothing.
1826 */
1827static void
1828_base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
1829{
1830 int i = 0;
1831 char desc[16];
1832 u8 revision;
1833 u32 iounit_pg1_flags;
Kashyap, Desaic97951e2011-06-14 10:54:56 +05301834 u32 bios_version;
Eric Moore635374e2009-03-09 01:21:12 -06001835
Kashyap, Desaic97951e2011-06-14 10:54:56 +05301836 bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
Eric Moore635374e2009-03-09 01:21:12 -06001837 pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision);
1838 strncpy(desc, ioc->manu_pg0.ChipName, 16);
1839 printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "
1840 "ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n",
1841 ioc->name, desc,
1842 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
1843 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
1844 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
1845 ioc->facts.FWVersion.Word & 0x000000FF,
1846 revision,
Kashyap, Desaic97951e2011-06-14 10:54:56 +05301847 (bios_version & 0xFF000000) >> 24,
1848 (bios_version & 0x00FF0000) >> 16,
1849 (bios_version & 0x0000FF00) >> 8,
1850 bios_version & 0x000000FF);
Eric Moore635374e2009-03-09 01:21:12 -06001851
Kashyap, Desaied79f122009-08-20 13:23:49 +05301852 _base_display_dell_branding(ioc);
Kashyap, Desaifb396be2011-01-04 11:36:37 +05301853 _base_display_intel_branding(ioc);
Kashyap, Desai0a2385c2011-03-15 20:04:26 +05301854 _base_display_hp_branding(ioc);
Kashyap, Desaied79f122009-08-20 13:23:49 +05301855
Eric Moore635374e2009-03-09 01:21:12 -06001856 printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name);
1857
1858 if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) {
1859 printk("Initiator");
1860 i++;
1861 }
1862
1863 if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET) {
1864 printk("%sTarget", i ? "," : "");
1865 i++;
1866 }
1867
1868 i = 0;
1869 printk("), ");
1870 printk("Capabilities=(");
1871
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05301872 if (!ioc->hide_ir_msg) {
1873 if (ioc->facts.IOCCapabilities &
1874 MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
1875 printk("Raid");
1876 i++;
1877 }
Eric Moore635374e2009-03-09 01:21:12 -06001878 }
1879
1880 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) {
1881 printk("%sTLR", i ? "," : "");
1882 i++;
1883 }
1884
1885 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_MULTICAST) {
1886 printk("%sMulticast", i ? "," : "");
1887 i++;
1888 }
1889
1890 if (ioc->facts.IOCCapabilities &
1891 MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET) {
1892 printk("%sBIDI Target", i ? "," : "");
1893 i++;
1894 }
1895
1896 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) {
1897 printk("%sEEDP", i ? "," : "");
1898 i++;
1899 }
1900
1901 if (ioc->facts.IOCCapabilities &
1902 MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) {
1903 printk("%sSnapshot Buffer", i ? "," : "");
1904 i++;
1905 }
1906
1907 if (ioc->facts.IOCCapabilities &
1908 MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) {
1909 printk("%sDiag Trace Buffer", i ? "," : "");
1910 i++;
1911 }
1912
1913 if (ioc->facts.IOCCapabilities &
Kashyap, Desai1b01fe32009-09-23 17:28:59 +05301914 MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) {
1915 printk(KERN_INFO "%sDiag Extended Buffer", i ? "," : "");
1916 i++;
1917 }
1918
1919 if (ioc->facts.IOCCapabilities &
Eric Moore635374e2009-03-09 01:21:12 -06001920 MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) {
1921 printk("%sTask Set Full", i ? "," : "");
1922 i++;
1923 }
1924
1925 iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
1926 if (!(iounit_pg1_flags & MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE)) {
1927 printk("%sNCQ", i ? "," : "");
1928 i++;
1929 }
1930
1931 printk(")\n");
1932}
1933
1934/**
Kashyap, Desai6cb8ef52010-11-13 04:32:18 +05301935 * _base_update_missing_delay - change the missing delay timers
1936 * @ioc: per adapter object
1937 * @device_missing_delay: amount of time till device is reported missing
1938 * @io_missing_delay: interval IO is returned when there is a missing device
1939 *
1940 * Return nothing.
1941 *
1942 * Passed on the command line, this function will modify the device missing
1943 * delay, as well as the io missing delay. This should be called at driver
1944 * load time.
1945 */
1946static void
1947_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
1948 u16 device_missing_delay, u8 io_missing_delay)
1949{
1950 u16 dmd, dmd_new, dmd_orignal;
1951 u8 io_missing_delay_original;
1952 u16 sz;
1953 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1954 Mpi2ConfigReply_t mpi_reply;
1955 u8 num_phys = 0;
1956 u16 ioc_status;
1957
1958 mpt2sas_config_get_number_hba_phys(ioc, &num_phys);
1959 if (!num_phys)
1960 return;
1961
1962 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (num_phys *
1963 sizeof(Mpi2SasIOUnit1PhyData_t));
1964 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1965 if (!sas_iounit_pg1) {
1966 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1967 ioc->name, __FILE__, __LINE__, __func__);
1968 goto out;
1969 }
1970 if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1971 sas_iounit_pg1, sz))) {
1972 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1973 ioc->name, __FILE__, __LINE__, __func__);
1974 goto out;
1975 }
1976 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1977 MPI2_IOCSTATUS_MASK;
1978 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1979 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1980 ioc->name, __FILE__, __LINE__, __func__);
1981 goto out;
1982 }
1983
1984 /* device missing delay */
1985 dmd = sas_iounit_pg1->ReportDeviceMissingDelay;
1986 if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
1987 dmd = (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
1988 else
1989 dmd = dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
1990 dmd_orignal = dmd;
1991 if (device_missing_delay > 0x7F) {
1992 dmd = (device_missing_delay > 0x7F0) ? 0x7F0 :
1993 device_missing_delay;
1994 dmd = dmd / 16;
1995 dmd |= MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16;
1996 } else
1997 dmd = device_missing_delay;
1998 sas_iounit_pg1->ReportDeviceMissingDelay = dmd;
1999
2000 /* io missing delay */
2001 io_missing_delay_original = sas_iounit_pg1->IODeviceMissingDelay;
2002 sas_iounit_pg1->IODeviceMissingDelay = io_missing_delay;
2003
2004 if (!mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
2005 sz)) {
2006 if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
2007 dmd_new = (dmd &
2008 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
2009 else
2010 dmd_new =
2011 dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
2012 printk(MPT2SAS_INFO_FMT "device_missing_delay: old(%d), "
2013 "new(%d)\n", ioc->name, dmd_orignal, dmd_new);
2014 printk(MPT2SAS_INFO_FMT "ioc_missing_delay: old(%d), "
2015 "new(%d)\n", ioc->name, io_missing_delay_original,
2016 io_missing_delay);
2017 ioc->device_missing_delay = dmd_new;
2018 ioc->io_missing_delay = io_missing_delay;
2019 }
2020
2021out:
2022 kfree(sas_iounit_pg1);
2023}
2024
2025/**
Eric Moore635374e2009-03-09 01:21:12 -06002026 * _base_static_config_pages - static start of day config pages
2027 * @ioc: per adapter object
2028 *
2029 * Return nothing.
2030 */
2031static void
2032_base_static_config_pages(struct MPT2SAS_ADAPTER *ioc)
2033{
2034 Mpi2ConfigReply_t mpi_reply;
2035 u32 iounit_pg1_flags;
2036
2037 mpt2sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0);
Kashyap, Desaied79f122009-08-20 13:23:49 +05302038 if (ioc->ir_firmware)
2039 mpt2sas_config_get_manufacturing_pg10(ioc, &mpi_reply,
2040 &ioc->manu_pg10);
Eric Moore635374e2009-03-09 01:21:12 -06002041 mpt2sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
2042 mpt2sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
2043 mpt2sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8);
2044 mpt2sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0);
2045 mpt2sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
2046 _base_display_ioc_capabilities(ioc);
2047
2048 /*
2049 * Enable task_set_full handling in iounit_pg1 when the
2050 * facts capabilities indicate that its supported.
2051 */
2052 iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
2053 if ((ioc->facts.IOCCapabilities &
2054 MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING))
2055 iounit_pg1_flags &=
2056 ~MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
2057 else
2058 iounit_pg1_flags |=
2059 MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
2060 ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags);
Kashyap, Desai5b768582009-08-20 13:24:31 +05302061 mpt2sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
Kashyap, Desai6cb8ef52010-11-13 04:32:18 +05302062
Eric Moore635374e2009-03-09 01:21:12 -06002063}
2064
2065/**
2066 * _base_release_memory_pools - release memory
2067 * @ioc: per adapter object
2068 *
2069 * Free memory allocated from _base_allocate_memory_pools.
2070 *
2071 * Return nothing.
2072 */
2073static void
2074_base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
2075{
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302076 int i;
2077
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302078 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06002079 __func__));
2080
2081 if (ioc->request) {
2082 pci_free_consistent(ioc->pdev, ioc->request_dma_sz,
2083 ioc->request, ioc->request_dma);
2084 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "request_pool(0x%p)"
2085 ": free\n", ioc->name, ioc->request));
2086 ioc->request = NULL;
2087 }
2088
2089 if (ioc->sense) {
2090 pci_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma);
2091 if (ioc->sense_dma_pool)
2092 pci_pool_destroy(ioc->sense_dma_pool);
2093 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_pool(0x%p)"
2094 ": free\n", ioc->name, ioc->sense));
2095 ioc->sense = NULL;
2096 }
2097
2098 if (ioc->reply) {
2099 pci_pool_free(ioc->reply_dma_pool, ioc->reply, ioc->reply_dma);
2100 if (ioc->reply_dma_pool)
2101 pci_pool_destroy(ioc->reply_dma_pool);
2102 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_pool(0x%p)"
2103 ": free\n", ioc->name, ioc->reply));
2104 ioc->reply = NULL;
2105 }
2106
2107 if (ioc->reply_free) {
2108 pci_pool_free(ioc->reply_free_dma_pool, ioc->reply_free,
2109 ioc->reply_free_dma);
2110 if (ioc->reply_free_dma_pool)
2111 pci_pool_destroy(ioc->reply_free_dma_pool);
2112 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_pool"
2113 "(0x%p): free\n", ioc->name, ioc->reply_free));
2114 ioc->reply_free = NULL;
2115 }
2116
2117 if (ioc->reply_post_free) {
2118 pci_pool_free(ioc->reply_post_free_dma_pool,
2119 ioc->reply_post_free, ioc->reply_post_free_dma);
2120 if (ioc->reply_post_free_dma_pool)
2121 pci_pool_destroy(ioc->reply_post_free_dma_pool);
2122 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
2123 "reply_post_free_pool(0x%p): free\n", ioc->name,
2124 ioc->reply_post_free));
2125 ioc->reply_post_free = NULL;
2126 }
2127
2128 if (ioc->config_page) {
2129 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
2130 "config_page(0x%p): free\n", ioc->name,
2131 ioc->config_page));
2132 pci_free_consistent(ioc->pdev, ioc->config_page_sz,
2133 ioc->config_page, ioc->config_page_dma);
2134 }
2135
Kashyap, Desai66a67932010-04-05 14:21:07 +05302136 if (ioc->scsi_lookup) {
2137 free_pages((ulong)ioc->scsi_lookup, ioc->scsi_lookup_pages);
2138 ioc->scsi_lookup = NULL;
2139 }
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302140 kfree(ioc->hpr_lookup);
2141 kfree(ioc->internal_lookup);
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302142 if (ioc->chain_lookup) {
2143 for (i = 0; i < ioc->chain_depth; i++) {
2144 if (ioc->chain_lookup[i].chain_buffer)
2145 pci_pool_free(ioc->chain_dma_pool,
2146 ioc->chain_lookup[i].chain_buffer,
2147 ioc->chain_lookup[i].chain_buffer_dma);
2148 }
2149 if (ioc->chain_dma_pool)
2150 pci_pool_destroy(ioc->chain_dma_pool);
2151 }
2152 if (ioc->chain_lookup) {
2153 free_pages((ulong)ioc->chain_lookup, ioc->chain_pages);
2154 ioc->chain_lookup = NULL;
2155 }
Eric Moore635374e2009-03-09 01:21:12 -06002156}
2157
2158
2159/**
2160 * _base_allocate_memory_pools - allocate start of day memory pools
2161 * @ioc: per adapter object
2162 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2163 *
2164 * Returns 0 success, anything else error
2165 */
2166static int
2167_base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2168{
Kashyap, Desaic97951e2011-06-14 10:54:56 +05302169 struct mpt2sas_facts *facts;
Eric Moore635374e2009-03-09 01:21:12 -06002170 u32 queue_size, queue_diff;
2171 u16 max_sge_elements;
2172 u16 num_of_reply_frames;
2173 u16 chains_needed_per_io;
2174 u32 sz, total_sz;
Eric Moore635374e2009-03-09 01:21:12 -06002175 u32 retry_sz;
2176 u16 max_request_credit;
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302177 int i;
Eric Moore635374e2009-03-09 01:21:12 -06002178
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302179 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06002180 __func__));
2181
2182 retry_sz = 0;
2183 facts = &ioc->facts;
2184
2185 /* command line tunables for max sgl entries */
2186 if (max_sgl_entries != -1) {
2187 ioc->shost->sg_tablesize = (max_sgl_entries <
2188 MPT2SAS_SG_DEPTH) ? max_sgl_entries :
2189 MPT2SAS_SG_DEPTH;
2190 } else {
2191 ioc->shost->sg_tablesize = MPT2SAS_SG_DEPTH;
2192 }
2193
2194 /* command line tunables for max controller queue depth */
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302195 if (max_queue_depth != -1)
Eric Moore635374e2009-03-09 01:21:12 -06002196 max_request_credit = (max_queue_depth < facts->RequestCredit)
2197 ? max_queue_depth : facts->RequestCredit;
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302198 else
2199 max_request_credit = facts->RequestCredit;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302200
2201 ioc->hba_queue_depth = max_request_credit;
2202 ioc->hi_priority_depth = facts->HighPriorityCredit;
2203 ioc->internal_depth = ioc->hi_priority_depth + 5;
Eric Moore635374e2009-03-09 01:21:12 -06002204
2205 /* request frame size */
2206 ioc->request_sz = facts->IOCRequestFrameSize * 4;
2207
2208 /* reply frame size */
2209 ioc->reply_sz = facts->ReplyFrameSize * 4;
2210
2211 retry_allocation:
2212 total_sz = 0;
2213 /* calculate number of sg elements left over in the 1st frame */
2214 max_sge_elements = ioc->request_sz - ((sizeof(Mpi2SCSIIORequest_t) -
2215 sizeof(Mpi2SGEIOUnion_t)) + ioc->sge_size);
2216 ioc->max_sges_in_main_message = max_sge_elements/ioc->sge_size;
2217
2218 /* now do the same for a chain buffer */
2219 max_sge_elements = ioc->request_sz - ioc->sge_size;
2220 ioc->max_sges_in_chain_message = max_sge_elements/ioc->sge_size;
2221
2222 ioc->chain_offset_value_for_main_message =
2223 ((sizeof(Mpi2SCSIIORequest_t) - sizeof(Mpi2SGEIOUnion_t)) +
2224 (ioc->max_sges_in_chain_message * ioc->sge_size)) / 4;
2225
2226 /*
2227 * MPT2SAS_SG_DEPTH = CONFIG_FUSION_MAX_SGE
2228 */
2229 chains_needed_per_io = ((ioc->shost->sg_tablesize -
2230 ioc->max_sges_in_main_message)/ioc->max_sges_in_chain_message)
2231 + 1;
2232 if (chains_needed_per_io > facts->MaxChainDepth) {
2233 chains_needed_per_io = facts->MaxChainDepth;
2234 ioc->shost->sg_tablesize = min_t(u16,
2235 ioc->max_sges_in_main_message + (ioc->max_sges_in_chain_message
2236 * chains_needed_per_io), ioc->shost->sg_tablesize);
2237 }
2238 ioc->chains_needed_per_io = chains_needed_per_io;
2239
2240 /* reply free queue sizing - taking into account for events */
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302241 num_of_reply_frames = ioc->hba_queue_depth + 32;
Eric Moore635374e2009-03-09 01:21:12 -06002242
2243 /* number of replies frames can't be a multiple of 16 */
2244 /* decrease number of reply frames by 1 */
2245 if (!(num_of_reply_frames % 16))
2246 num_of_reply_frames--;
2247
2248 /* calculate number of reply free queue entries
2249 * (must be multiple of 16)
2250 */
2251
2252 /* (we know reply_free_queue_depth is not a multiple of 16) */
2253 queue_size = num_of_reply_frames;
2254 queue_size += 16 - (queue_size % 16);
2255 ioc->reply_free_queue_depth = queue_size;
2256
2257 /* reply descriptor post queue sizing */
2258 /* this size should be the number of request frames + number of reply
2259 * frames
2260 */
2261
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302262 queue_size = ioc->hba_queue_depth + num_of_reply_frames + 1;
Eric Moore635374e2009-03-09 01:21:12 -06002263 /* round up to 16 byte boundary */
2264 if (queue_size % 16)
2265 queue_size += 16 - (queue_size % 16);
2266
2267 /* check against IOC maximum reply post queue depth */
2268 if (queue_size > facts->MaxReplyDescriptorPostQueueDepth) {
2269 queue_diff = queue_size -
2270 facts->MaxReplyDescriptorPostQueueDepth;
2271
2272 /* round queue_diff up to multiple of 16 */
2273 if (queue_diff % 16)
2274 queue_diff += 16 - (queue_diff % 16);
2275
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302276 /* adjust hba_queue_depth, reply_free_queue_depth,
Eric Moore635374e2009-03-09 01:21:12 -06002277 * and queue_size
2278 */
Kashyap, Desai11e1b962011-01-04 11:34:57 +05302279 ioc->hba_queue_depth -= (queue_diff / 2);
2280 ioc->reply_free_queue_depth -= (queue_diff / 2);
2281 queue_size = facts->MaxReplyDescriptorPostQueueDepth;
Eric Moore635374e2009-03-09 01:21:12 -06002282 }
2283 ioc->reply_post_queue_depth = queue_size;
2284
Eric Moore635374e2009-03-09 01:21:12 -06002285 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: "
2286 "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), "
2287 "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message,
2288 ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize,
2289 ioc->chains_needed_per_io));
2290
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302291 ioc->scsiio_depth = ioc->hba_queue_depth -
2292 ioc->hi_priority_depth - ioc->internal_depth;
2293
2294 /* set the scsi host can_queue depth
2295 * with some internal commands that could be outstanding
2296 */
2297 ioc->shost->can_queue = ioc->scsiio_depth - (2);
2298 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: "
2299 "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue));
2300
Eric Moore635374e2009-03-09 01:21:12 -06002301 /* contiguous pool for request and chains, 16 byte align, one extra "
2302 * "frame for smid=0
2303 */
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302304 ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth;
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302305 sz = ((ioc->scsiio_depth + 1) * ioc->request_sz);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302306
2307 /* hi-priority queue */
2308 sz += (ioc->hi_priority_depth * ioc->request_sz);
2309
2310 /* internal queue */
2311 sz += (ioc->internal_depth * ioc->request_sz);
Eric Moore635374e2009-03-09 01:21:12 -06002312
2313 ioc->request_dma_sz = sz;
2314 ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma);
2315 if (!ioc->request) {
2316 printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent "
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302317 "failed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), "
2318 "total(%d kB)\n", ioc->name, ioc->hba_queue_depth,
Eric Moore635374e2009-03-09 01:21:12 -06002319 ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302320 if (ioc->scsiio_depth < MPT2SAS_SAS_QUEUE_DEPTH)
Eric Moore635374e2009-03-09 01:21:12 -06002321 goto out;
2322 retry_sz += 64;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302323 ioc->hba_queue_depth = max_request_credit - retry_sz;
Eric Moore635374e2009-03-09 01:21:12 -06002324 goto retry_allocation;
2325 }
2326
2327 if (retry_sz)
2328 printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent "
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302329 "succeed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), "
2330 "total(%d kb)\n", ioc->name, ioc->hba_queue_depth,
Eric Moore635374e2009-03-09 01:21:12 -06002331 ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
2332
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302333
2334 /* hi-priority queue */
2335 ioc->hi_priority = ioc->request + ((ioc->scsiio_depth + 1) *
Eric Moore635374e2009-03-09 01:21:12 -06002336 ioc->request_sz);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302337 ioc->hi_priority_dma = ioc->request_dma + ((ioc->scsiio_depth + 1) *
Eric Moore635374e2009-03-09 01:21:12 -06002338 ioc->request_sz);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302339
2340 /* internal queue */
2341 ioc->internal = ioc->hi_priority + (ioc->hi_priority_depth *
2342 ioc->request_sz);
2343 ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth *
2344 ioc->request_sz);
2345
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302346
Eric Moore635374e2009-03-09 01:21:12 -06002347 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): "
2348 "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302349 ioc->request, ioc->hba_queue_depth, ioc->request_sz,
2350 (ioc->hba_queue_depth * ioc->request_sz)/1024));
Eric Moore635374e2009-03-09 01:21:12 -06002351 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool: dma(0x%llx)\n",
2352 ioc->name, (unsigned long long) ioc->request_dma));
2353 total_sz += sz;
2354
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05302355 sz = ioc->scsiio_depth * sizeof(struct scsiio_tracker);
Kashyap, Desai89009fb2010-03-17 16:22:52 +05302356 ioc->scsi_lookup_pages = get_order(sz);
Kashyap, Desaid5bd3492011-01-04 11:39:20 +05302357 ioc->scsi_lookup = (struct scsiio_tracker *)__get_free_pages(
Kashyap, Desai89009fb2010-03-17 16:22:52 +05302358 GFP_KERNEL, ioc->scsi_lookup_pages);
Eric Moore635374e2009-03-09 01:21:12 -06002359 if (!ioc->scsi_lookup) {
Kashyap, Desai89009fb2010-03-17 16:22:52 +05302360 printk(MPT2SAS_ERR_FMT "scsi_lookup: get_free_pages failed, "
2361 "sz(%d)\n", ioc->name, (int)sz);
Eric Moore635374e2009-03-09 01:21:12 -06002362 goto out;
2363 }
2364
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302365 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsiio(0x%p): "
2366 "depth(%d)\n", ioc->name, ioc->request,
2367 ioc->scsiio_depth));
2368
Kashyap, Desai35f805b2010-11-13 04:34:06 +05302369 /* loop till the allocation succeeds */
2370 do {
2371 sz = ioc->chain_depth * sizeof(struct chain_tracker);
2372 ioc->chain_pages = get_order(sz);
2373 ioc->chain_lookup = (struct chain_tracker *)__get_free_pages(
2374 GFP_KERNEL, ioc->chain_pages);
2375 if (ioc->chain_lookup == NULL)
2376 ioc->chain_depth -= 100;
2377 } while (ioc->chain_lookup == NULL);
2378 ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev,
2379 ioc->request_sz, 16, 0);
2380 if (!ioc->chain_dma_pool) {
2381 printk(MPT2SAS_ERR_FMT "chain_dma_pool: pci_pool_create "
2382 "failed\n", ioc->name);
2383 goto out;
2384 }
2385 for (i = 0; i < ioc->chain_depth; i++) {
2386 ioc->chain_lookup[i].chain_buffer = pci_pool_alloc(
2387 ioc->chain_dma_pool , GFP_KERNEL,
2388 &ioc->chain_lookup[i].chain_buffer_dma);
2389 if (!ioc->chain_lookup[i].chain_buffer) {
2390 ioc->chain_depth = i;
2391 goto chain_done;
2392 }
2393 total_sz += ioc->request_sz;
2394 }
2395chain_done:
2396 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool depth"
2397 "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
2398 ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth *
2399 ioc->request_sz))/1024));
2400
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302401 /* initialize hi-priority queue smid's */
2402 ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth,
2403 sizeof(struct request_tracker), GFP_KERNEL);
2404 if (!ioc->hpr_lookup) {
2405 printk(MPT2SAS_ERR_FMT "hpr_lookup: kcalloc failed\n",
2406 ioc->name);
2407 goto out;
2408 }
2409 ioc->hi_priority_smid = ioc->scsiio_depth + 1;
2410 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hi_priority(0x%p): "
2411 "depth(%d), start smid(%d)\n", ioc->name, ioc->hi_priority,
2412 ioc->hi_priority_depth, ioc->hi_priority_smid));
2413
2414 /* initialize internal queue smid's */
2415 ioc->internal_lookup = kcalloc(ioc->internal_depth,
2416 sizeof(struct request_tracker), GFP_KERNEL);
2417 if (!ioc->internal_lookup) {
2418 printk(MPT2SAS_ERR_FMT "internal_lookup: kcalloc failed\n",
2419 ioc->name);
2420 goto out;
2421 }
2422 ioc->internal_smid = ioc->hi_priority_smid + ioc->hi_priority_depth;
2423 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "internal(0x%p): "
2424 "depth(%d), start smid(%d)\n", ioc->name, ioc->internal,
2425 ioc->internal_depth, ioc->internal_smid));
Eric Moore635374e2009-03-09 01:21:12 -06002426
2427 /* sense buffers, 4 byte align */
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302428 sz = ioc->scsiio_depth * SCSI_SENSE_BUFFERSIZE;
Eric Moore635374e2009-03-09 01:21:12 -06002429 ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4,
2430 0);
2431 if (!ioc->sense_dma_pool) {
2432 printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_create failed\n",
2433 ioc->name);
2434 goto out;
2435 }
2436 ioc->sense = pci_pool_alloc(ioc->sense_dma_pool , GFP_KERNEL,
2437 &ioc->sense_dma);
2438 if (!ioc->sense) {
2439 printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_alloc failed\n",
2440 ioc->name);
2441 goto out;
2442 }
2443 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
2444 "sense pool(0x%p): depth(%d), element_size(%d), pool_size"
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05302445 "(%d kB)\n", ioc->name, ioc->sense, ioc->scsiio_depth,
Eric Moore635374e2009-03-09 01:21:12 -06002446 SCSI_SENSE_BUFFERSIZE, sz/1024));
2447 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_dma(0x%llx)\n",
2448 ioc->name, (unsigned long long)ioc->sense_dma));
2449 total_sz += sz;
2450
2451 /* reply pool, 4 byte align */
2452 sz = ioc->reply_free_queue_depth * ioc->reply_sz;
2453 ioc->reply_dma_pool = pci_pool_create("reply pool", ioc->pdev, sz, 4,
2454 0);
2455 if (!ioc->reply_dma_pool) {
2456 printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_create failed\n",
2457 ioc->name);
2458 goto out;
2459 }
2460 ioc->reply = pci_pool_alloc(ioc->reply_dma_pool , GFP_KERNEL,
2461 &ioc->reply_dma);
2462 if (!ioc->reply) {
2463 printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_alloc failed\n",
2464 ioc->name);
2465 goto out;
2466 }
Kashyap, Desaidd3741d2010-11-13 04:31:14 +05302467 ioc->reply_dma_min_address = (u32)(ioc->reply_dma);
2468 ioc->reply_dma_max_address = (u32)(ioc->reply_dma) + sz;
Eric Moore635374e2009-03-09 01:21:12 -06002469 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply pool(0x%p): depth"
2470 "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->reply,
2471 ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024));
2472 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_dma(0x%llx)\n",
2473 ioc->name, (unsigned long long)ioc->reply_dma));
2474 total_sz += sz;
2475
2476 /* reply free queue, 16 byte align */
2477 sz = ioc->reply_free_queue_depth * 4;
2478 ioc->reply_free_dma_pool = pci_pool_create("reply_free pool",
2479 ioc->pdev, sz, 16, 0);
2480 if (!ioc->reply_free_dma_pool) {
2481 printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_create "
2482 "failed\n", ioc->name);
2483 goto out;
2484 }
2485 ioc->reply_free = pci_pool_alloc(ioc->reply_free_dma_pool , GFP_KERNEL,
2486 &ioc->reply_free_dma);
2487 if (!ioc->reply_free) {
2488 printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_alloc "
2489 "failed\n", ioc->name);
2490 goto out;
2491 }
2492 memset(ioc->reply_free, 0, sz);
2493 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free pool(0x%p): "
2494 "depth(%d), element_size(%d), pool_size(%d kB)\n", ioc->name,
2495 ioc->reply_free, ioc->reply_free_queue_depth, 4, sz/1024));
2496 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_dma"
2497 "(0x%llx)\n", ioc->name, (unsigned long long)ioc->reply_free_dma));
2498 total_sz += sz;
2499
2500 /* reply post queue, 16 byte align */
2501 sz = ioc->reply_post_queue_depth * sizeof(Mpi2DefaultReplyDescriptor_t);
2502 ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool",
2503 ioc->pdev, sz, 16, 0);
2504 if (!ioc->reply_post_free_dma_pool) {
2505 printk(MPT2SAS_ERR_FMT "reply_post_free pool: pci_pool_create "
2506 "failed\n", ioc->name);
2507 goto out;
2508 }
2509 ioc->reply_post_free = pci_pool_alloc(ioc->reply_post_free_dma_pool ,
2510 GFP_KERNEL, &ioc->reply_post_free_dma);
2511 if (!ioc->reply_post_free) {
2512 printk(MPT2SAS_ERR_FMT "reply_post_free pool: pci_pool_alloc "
2513 "failed\n", ioc->name);
2514 goto out;
2515 }
2516 memset(ioc->reply_post_free, 0, sz);
2517 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply post free pool"
2518 "(0x%p): depth(%d), element_size(%d), pool_size(%d kB)\n",
2519 ioc->name, ioc->reply_post_free, ioc->reply_post_queue_depth, 8,
2520 sz/1024));
2521 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_post_free_dma = "
2522 "(0x%llx)\n", ioc->name, (unsigned long long)
2523 ioc->reply_post_free_dma));
2524 total_sz += sz;
2525
2526 ioc->config_page_sz = 512;
2527 ioc->config_page = pci_alloc_consistent(ioc->pdev,
2528 ioc->config_page_sz, &ioc->config_page_dma);
2529 if (!ioc->config_page) {
2530 printk(MPT2SAS_ERR_FMT "config page: pci_pool_alloc "
2531 "failed\n", ioc->name);
2532 goto out;
2533 }
2534 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config page(0x%p): size"
2535 "(%d)\n", ioc->name, ioc->config_page, ioc->config_page_sz));
2536 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config_page_dma"
2537 "(0x%llx)\n", ioc->name, (unsigned long long)ioc->config_page_dma));
2538 total_sz += ioc->config_page_sz;
2539
2540 printk(MPT2SAS_INFO_FMT "Allocated physical memory: size(%d kB)\n",
2541 ioc->name, total_sz/1024);
2542 printk(MPT2SAS_INFO_FMT "Current Controller Queue Depth(%d), "
2543 "Max Controller Queue Depth(%d)\n",
2544 ioc->name, ioc->shost->can_queue, facts->RequestCredit);
2545 printk(MPT2SAS_INFO_FMT "Scatter Gather Elements per IO(%d)\n",
2546 ioc->name, ioc->shost->sg_tablesize);
2547 return 0;
2548
2549 out:
Eric Moore635374e2009-03-09 01:21:12 -06002550 return -ENOMEM;
2551}
2552
2553
2554/**
2555 * mpt2sas_base_get_iocstate - Get the current state of a MPT adapter.
2556 * @ioc: Pointer to MPT_ADAPTER structure
2557 * @cooked: Request raw or cooked IOC state
2558 *
2559 * Returns all IOC Doorbell register bits if cooked==0, else just the
2560 * Doorbell bits in MPI_IOC_STATE_MASK.
2561 */
2562u32
2563mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked)
2564{
2565 u32 s, sc;
2566
2567 s = readl(&ioc->chip->Doorbell);
2568 sc = s & MPI2_IOC_STATE_MASK;
2569 return cooked ? sc : s;
2570}
2571
2572/**
2573 * _base_wait_on_iocstate - waiting on a particular ioc state
2574 * @ioc_state: controller state { READY, OPERATIONAL, or RESET }
2575 * @timeout: timeout in second
2576 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2577 *
2578 * Returns 0 for success, non-zero for failure.
2579 */
2580static int
2581_base_wait_on_iocstate(struct MPT2SAS_ADAPTER *ioc, u32 ioc_state, int timeout,
2582 int sleep_flag)
2583{
2584 u32 count, cntdn;
2585 u32 current_state;
2586
2587 count = 0;
2588 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
2589 do {
2590 current_state = mpt2sas_base_get_iocstate(ioc, 1);
2591 if (current_state == ioc_state)
2592 return 0;
2593 if (count && current_state == MPI2_IOC_STATE_FAULT)
2594 break;
2595 if (sleep_flag == CAN_SLEEP)
2596 msleep(1);
2597 else
2598 udelay(500);
2599 count++;
2600 } while (--cntdn);
2601
2602 return current_state;
2603}
2604
2605/**
2606 * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by
2607 * a write to the doorbell)
2608 * @ioc: per adapter object
2609 * @timeout: timeout in second
2610 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2611 *
2612 * Returns 0 for success, non-zero for failure.
2613 *
2614 * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell.
2615 */
2616static int
2617_base_wait_for_doorbell_int(struct MPT2SAS_ADAPTER *ioc, int timeout,
2618 int sleep_flag)
2619{
2620 u32 cntdn, count;
2621 u32 int_status;
2622
2623 count = 0;
2624 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
2625 do {
2626 int_status = readl(&ioc->chip->HostInterruptStatus);
2627 if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302628 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002629 "successful count(%d), timeout(%d)\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06002630 __func__, count, timeout));
2631 return 0;
2632 }
2633 if (sleep_flag == CAN_SLEEP)
2634 msleep(1);
2635 else
2636 udelay(500);
2637 count++;
2638 } while (--cntdn);
2639
2640 printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
2641 "int_status(%x)!\n", ioc->name, __func__, count, int_status);
2642 return -EFAULT;
2643}
2644
2645/**
2646 * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell.
2647 * @ioc: per adapter object
2648 * @timeout: timeout in second
2649 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2650 *
2651 * Returns 0 for success, non-zero for failure.
2652 *
2653 * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to
2654 * doorbell.
2655 */
2656static int
2657_base_wait_for_doorbell_ack(struct MPT2SAS_ADAPTER *ioc, int timeout,
2658 int sleep_flag)
2659{
2660 u32 cntdn, count;
2661 u32 int_status;
2662 u32 doorbell;
2663
2664 count = 0;
2665 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
2666 do {
2667 int_status = readl(&ioc->chip->HostInterruptStatus);
2668 if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302669 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002670 "successful count(%d), timeout(%d)\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06002671 __func__, count, timeout));
2672 return 0;
2673 } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
2674 doorbell = readl(&ioc->chip->Doorbell);
2675 if ((doorbell & MPI2_IOC_STATE_MASK) ==
2676 MPI2_IOC_STATE_FAULT) {
2677 mpt2sas_base_fault_info(ioc , doorbell);
2678 return -EFAULT;
2679 }
2680 } else if (int_status == 0xFFFFFFFF)
2681 goto out;
2682
2683 if (sleep_flag == CAN_SLEEP)
2684 msleep(1);
2685 else
2686 udelay(500);
2687 count++;
2688 } while (--cntdn);
2689
2690 out:
2691 printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
2692 "int_status(%x)!\n", ioc->name, __func__, count, int_status);
2693 return -EFAULT;
2694}
2695
2696/**
2697 * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use
2698 * @ioc: per adapter object
2699 * @timeout: timeout in second
2700 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2701 *
2702 * Returns 0 for success, non-zero for failure.
2703 *
2704 */
2705static int
2706_base_wait_for_doorbell_not_used(struct MPT2SAS_ADAPTER *ioc, int timeout,
2707 int sleep_flag)
2708{
2709 u32 cntdn, count;
2710 u32 doorbell_reg;
2711
2712 count = 0;
2713 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
2714 do {
2715 doorbell_reg = readl(&ioc->chip->Doorbell);
2716 if (!(doorbell_reg & MPI2_DOORBELL_USED)) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302717 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002718 "successful count(%d), timeout(%d)\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06002719 __func__, count, timeout));
2720 return 0;
2721 }
2722 if (sleep_flag == CAN_SLEEP)
2723 msleep(1);
2724 else
2725 udelay(500);
2726 count++;
2727 } while (--cntdn);
2728
2729 printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
2730 "doorbell_reg(%x)!\n", ioc->name, __func__, count, doorbell_reg);
2731 return -EFAULT;
2732}
2733
2734/**
2735 * _base_send_ioc_reset - send doorbell reset
2736 * @ioc: per adapter object
2737 * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET
2738 * @timeout: timeout in second
2739 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2740 *
2741 * Returns 0 for success, non-zero for failure.
2742 */
2743static int
2744_base_send_ioc_reset(struct MPT2SAS_ADAPTER *ioc, u8 reset_type, int timeout,
2745 int sleep_flag)
2746{
2747 u32 ioc_state;
2748 int r = 0;
2749
2750 if (reset_type != MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET) {
2751 printk(MPT2SAS_ERR_FMT "%s: unknown reset_type\n",
2752 ioc->name, __func__);
2753 return -EFAULT;
2754 }
2755
2756 if (!(ioc->facts.IOCCapabilities &
2757 MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY))
2758 return -EFAULT;
2759
2760 printk(MPT2SAS_INFO_FMT "sending message unit reset !!\n", ioc->name);
2761
2762 writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT,
2763 &ioc->chip->Doorbell);
2764 if ((_base_wait_for_doorbell_ack(ioc, 15, sleep_flag))) {
2765 r = -EFAULT;
2766 goto out;
2767 }
2768 ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY,
2769 timeout, sleep_flag);
2770 if (ioc_state) {
2771 printk(MPT2SAS_ERR_FMT "%s: failed going to ready state "
2772 " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
2773 r = -EFAULT;
2774 goto out;
2775 }
2776 out:
2777 printk(MPT2SAS_INFO_FMT "message unit reset: %s\n",
2778 ioc->name, ((r == 0) ? "SUCCESS" : "FAILED"));
2779 return r;
2780}
2781
2782/**
2783 * _base_handshake_req_reply_wait - send request thru doorbell interface
2784 * @ioc: per adapter object
2785 * @request_bytes: request length
2786 * @request: pointer having request payload
2787 * @reply_bytes: reply length
2788 * @reply: pointer to reply payload
2789 * @timeout: timeout in second
2790 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2791 *
2792 * Returns 0 for success, non-zero for failure.
2793 */
2794static int
2795_base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
2796 u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag)
2797{
2798 MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply;
2799 int i;
2800 u8 failed;
2801 u16 dummy;
Kashyap, Desaic97951e2011-06-14 10:54:56 +05302802 __le32 *mfp;
Eric Moore635374e2009-03-09 01:21:12 -06002803
2804 /* make sure doorbell is not in use */
2805 if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
2806 printk(MPT2SAS_ERR_FMT "doorbell is in use "
2807 " (line=%d)\n", ioc->name, __LINE__);
2808 return -EFAULT;
2809 }
2810
2811 /* clear pending doorbell interrupts from previous state changes */
2812 if (readl(&ioc->chip->HostInterruptStatus) &
2813 MPI2_HIS_IOC2SYS_DB_STATUS)
2814 writel(0, &ioc->chip->HostInterruptStatus);
2815
2816 /* send message to ioc */
2817 writel(((MPI2_FUNCTION_HANDSHAKE<<MPI2_DOORBELL_FUNCTION_SHIFT) |
2818 ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)),
2819 &ioc->chip->Doorbell);
2820
Kashyap, Desai29786e12009-09-14 11:06:21 +05302821 if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) {
Eric Moore635374e2009-03-09 01:21:12 -06002822 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2823 "int failed (line=%d)\n", ioc->name, __LINE__);
2824 return -EFAULT;
2825 }
2826 writel(0, &ioc->chip->HostInterruptStatus);
2827
2828 if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) {
2829 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2830 "ack failed (line=%d)\n", ioc->name, __LINE__);
2831 return -EFAULT;
2832 }
2833
2834 /* send message 32-bits at a time */
2835 for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) {
2836 writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell);
2837 if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag)))
2838 failed = 1;
2839 }
2840
2841 if (failed) {
2842 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2843 "sending request failed (line=%d)\n", ioc->name, __LINE__);
2844 return -EFAULT;
2845 }
2846
2847 /* now wait for the reply */
2848 if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) {
2849 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2850 "int failed (line=%d)\n", ioc->name, __LINE__);
2851 return -EFAULT;
2852 }
2853
2854 /* read the first two 16-bits, it gives the total length of the reply */
2855 reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell)
2856 & MPI2_DOORBELL_DATA_MASK);
2857 writel(0, &ioc->chip->HostInterruptStatus);
2858 if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
2859 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2860 "int failed (line=%d)\n", ioc->name, __LINE__);
2861 return -EFAULT;
2862 }
2863 reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell)
2864 & MPI2_DOORBELL_DATA_MASK);
2865 writel(0, &ioc->chip->HostInterruptStatus);
2866
2867 for (i = 2; i < default_reply->MsgLength * 2; i++) {
2868 if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
2869 printk(MPT2SAS_ERR_FMT "doorbell "
2870 "handshake int failed (line=%d)\n", ioc->name,
2871 __LINE__);
2872 return -EFAULT;
2873 }
2874 if (i >= reply_bytes/2) /* overflow case */
2875 dummy = readl(&ioc->chip->Doorbell);
2876 else
2877 reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell)
2878 & MPI2_DOORBELL_DATA_MASK);
2879 writel(0, &ioc->chip->HostInterruptStatus);
2880 }
2881
2882 _base_wait_for_doorbell_int(ioc, 5, sleep_flag);
2883 if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) {
2884 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "doorbell is in use "
2885 " (line=%d)\n", ioc->name, __LINE__));
2886 }
2887 writel(0, &ioc->chip->HostInterruptStatus);
2888
2889 if (ioc->logging_level & MPT_DEBUG_INIT) {
Kashyap, Desaic97951e2011-06-14 10:54:56 +05302890 mfp = (__le32 *)reply;
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302891 printk(KERN_INFO "\toffset:data\n");
Eric Moore635374e2009-03-09 01:21:12 -06002892 for (i = 0; i < reply_bytes/4; i++)
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302893 printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
Eric Moore635374e2009-03-09 01:21:12 -06002894 le32_to_cpu(mfp[i]));
2895 }
2896 return 0;
2897}
2898
2899/**
2900 * mpt2sas_base_sas_iounit_control - send sas iounit control to FW
2901 * @ioc: per adapter object
2902 * @mpi_reply: the reply payload from FW
2903 * @mpi_request: the request payload sent to FW
2904 *
2905 * The SAS IO Unit Control Request message allows the host to perform low-level
2906 * operations, such as resets on the PHYs of the IO Unit, also allows the host
2907 * to obtain the IOC assigned device handles for a device if it has other
2908 * identifying information about the device, in addition allows the host to
2909 * remove IOC resources associated with the device.
2910 *
2911 * Returns 0 for success, non-zero for failure.
2912 */
2913int
2914mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc,
2915 Mpi2SasIoUnitControlReply_t *mpi_reply,
2916 Mpi2SasIoUnitControlRequest_t *mpi_request)
2917{
2918 u16 smid;
2919 u32 ioc_state;
2920 unsigned long timeleft;
2921 u8 issue_reset;
2922 int rc;
2923 void *request;
2924 u16 wait_state_count;
2925
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05302926 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06002927 __func__));
2928
2929 mutex_lock(&ioc->base_cmds.mutex);
2930
2931 if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) {
2932 printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n",
2933 ioc->name, __func__);
2934 rc = -EAGAIN;
2935 goto out;
2936 }
2937
2938 wait_state_count = 0;
2939 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
2940 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
2941 if (wait_state_count++ == 10) {
2942 printk(MPT2SAS_ERR_FMT
2943 "%s: failed due to ioc not operational\n",
2944 ioc->name, __func__);
2945 rc = -EFAULT;
2946 goto out;
2947 }
2948 ssleep(1);
2949 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
2950 printk(MPT2SAS_INFO_FMT "%s: waiting for "
2951 "operational state(count=%d)\n", ioc->name,
2952 __func__, wait_state_count);
2953 }
2954
2955 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
2956 if (!smid) {
2957 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
2958 ioc->name, __func__);
2959 rc = -EAGAIN;
2960 goto out;
2961 }
2962
2963 rc = 0;
2964 ioc->base_cmds.status = MPT2_CMD_PENDING;
2965 request = mpt2sas_base_get_msg_frame(ioc, smid);
2966 ioc->base_cmds.smid = smid;
2967 memcpy(request, mpi_request, sizeof(Mpi2SasIoUnitControlRequest_t));
2968 if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
2969 mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET)
2970 ioc->ioc_link_reset_in_progress = 1;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05302971 mpt2sas_base_put_smid_default(ioc, smid);
Kashyap, Desaibcfb6e62009-09-14 11:05:24 +05302972 init_completion(&ioc->base_cmds.done);
Eric Moore635374e2009-03-09 01:21:12 -06002973 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
2974 msecs_to_jiffies(10000));
2975 if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
2976 mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) &&
2977 ioc->ioc_link_reset_in_progress)
2978 ioc->ioc_link_reset_in_progress = 0;
2979 if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
2980 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
2981 ioc->name, __func__);
2982 _debug_dump_mf(mpi_request,
2983 sizeof(Mpi2SasIoUnitControlRequest_t)/4);
2984 if (!(ioc->base_cmds.status & MPT2_CMD_RESET))
2985 issue_reset = 1;
2986 goto issue_host_reset;
2987 }
2988 if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID)
2989 memcpy(mpi_reply, ioc->base_cmds.reply,
2990 sizeof(Mpi2SasIoUnitControlReply_t));
2991 else
2992 memset(mpi_reply, 0, sizeof(Mpi2SasIoUnitControlReply_t));
2993 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
2994 goto out;
2995
2996 issue_host_reset:
2997 if (issue_reset)
2998 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2999 FORCE_BIG_HAMMER);
3000 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
3001 rc = -EFAULT;
3002 out:
3003 mutex_unlock(&ioc->base_cmds.mutex);
3004 return rc;
3005}
3006
3007
3008/**
3009 * mpt2sas_base_scsi_enclosure_processor - sending request to sep device
3010 * @ioc: per adapter object
3011 * @mpi_reply: the reply payload from FW
3012 * @mpi_request: the request payload sent to FW
3013 *
3014 * The SCSI Enclosure Processor request message causes the IOC to
3015 * communicate with SES devices to control LED status signals.
3016 *
3017 * Returns 0 for success, non-zero for failure.
3018 */
3019int
3020mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc,
3021 Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request)
3022{
3023 u16 smid;
3024 u32 ioc_state;
3025 unsigned long timeleft;
3026 u8 issue_reset;
3027 int rc;
3028 void *request;
3029 u16 wait_state_count;
3030
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303031 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003032 __func__));
3033
3034 mutex_lock(&ioc->base_cmds.mutex);
3035
3036 if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) {
3037 printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n",
3038 ioc->name, __func__);
3039 rc = -EAGAIN;
3040 goto out;
3041 }
3042
3043 wait_state_count = 0;
3044 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
3045 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3046 if (wait_state_count++ == 10) {
3047 printk(MPT2SAS_ERR_FMT
3048 "%s: failed due to ioc not operational\n",
3049 ioc->name, __func__);
3050 rc = -EFAULT;
3051 goto out;
3052 }
3053 ssleep(1);
3054 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
3055 printk(MPT2SAS_INFO_FMT "%s: waiting for "
3056 "operational state(count=%d)\n", ioc->name,
3057 __func__, wait_state_count);
3058 }
3059
3060 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
3061 if (!smid) {
3062 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
3063 ioc->name, __func__);
3064 rc = -EAGAIN;
3065 goto out;
3066 }
3067
3068 rc = 0;
3069 ioc->base_cmds.status = MPT2_CMD_PENDING;
3070 request = mpt2sas_base_get_msg_frame(ioc, smid);
3071 ioc->base_cmds.smid = smid;
3072 memcpy(request, mpi_request, sizeof(Mpi2SepReply_t));
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303073 mpt2sas_base_put_smid_default(ioc, smid);
Kashyap, Desaibcfb6e62009-09-14 11:05:24 +05303074 init_completion(&ioc->base_cmds.done);
Eric Moore635374e2009-03-09 01:21:12 -06003075 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
3076 msecs_to_jiffies(10000));
3077 if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
3078 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
3079 ioc->name, __func__);
3080 _debug_dump_mf(mpi_request,
3081 sizeof(Mpi2SepRequest_t)/4);
3082 if (!(ioc->base_cmds.status & MPT2_CMD_RESET))
3083 issue_reset = 1;
3084 goto issue_host_reset;
3085 }
3086 if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID)
3087 memcpy(mpi_reply, ioc->base_cmds.reply,
3088 sizeof(Mpi2SepReply_t));
3089 else
3090 memset(mpi_reply, 0, sizeof(Mpi2SepReply_t));
3091 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
3092 goto out;
3093
3094 issue_host_reset:
3095 if (issue_reset)
3096 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
3097 FORCE_BIG_HAMMER);
3098 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
3099 rc = -EFAULT;
3100 out:
3101 mutex_unlock(&ioc->base_cmds.mutex);
3102 return rc;
3103}
3104
3105/**
3106 * _base_get_port_facts - obtain port facts reply and save in ioc
3107 * @ioc: per adapter object
3108 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3109 *
3110 * Returns 0 for success, non-zero for failure.
3111 */
3112static int
3113_base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)
3114{
3115 Mpi2PortFactsRequest_t mpi_request;
Kashyap, Desaic97951e2011-06-14 10:54:56 +05303116 Mpi2PortFactsReply_t mpi_reply;
3117 struct mpt2sas_port_facts *pfacts;
Eric Moore635374e2009-03-09 01:21:12 -06003118 int mpi_reply_sz, mpi_request_sz, r;
3119
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303120 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003121 __func__));
3122
3123 mpi_reply_sz = sizeof(Mpi2PortFactsReply_t);
3124 mpi_request_sz = sizeof(Mpi2PortFactsRequest_t);
3125 memset(&mpi_request, 0, mpi_request_sz);
3126 mpi_request.Function = MPI2_FUNCTION_PORT_FACTS;
3127 mpi_request.PortNumber = port;
3128 r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
3129 (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
3130
3131 if (r != 0) {
3132 printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
3133 ioc->name, __func__, r);
3134 return r;
3135 }
3136
3137 pfacts = &ioc->pfacts[port];
3138 memset(pfacts, 0, sizeof(Mpi2PortFactsReply_t));
3139 pfacts->PortNumber = mpi_reply.PortNumber;
3140 pfacts->VP_ID = mpi_reply.VP_ID;
3141 pfacts->VF_ID = mpi_reply.VF_ID;
3142 pfacts->MaxPostedCmdBuffers =
3143 le16_to_cpu(mpi_reply.MaxPostedCmdBuffers);
3144
3145 return 0;
3146}
3147
3148/**
3149 * _base_get_ioc_facts - obtain ioc facts reply and save in ioc
3150 * @ioc: per adapter object
3151 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3152 *
3153 * Returns 0 for success, non-zero for failure.
3154 */
3155static int
3156_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
3157{
3158 Mpi2IOCFactsRequest_t mpi_request;
Kashyap, Desaic97951e2011-06-14 10:54:56 +05303159 Mpi2IOCFactsReply_t mpi_reply;
3160 struct mpt2sas_facts *facts;
Eric Moore635374e2009-03-09 01:21:12 -06003161 int mpi_reply_sz, mpi_request_sz, r;
3162
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303163 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003164 __func__));
3165
3166 mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t);
3167 mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t);
3168 memset(&mpi_request, 0, mpi_request_sz);
3169 mpi_request.Function = MPI2_FUNCTION_IOC_FACTS;
3170 r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
3171 (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
3172
3173 if (r != 0) {
3174 printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
3175 ioc->name, __func__, r);
3176 return r;
3177 }
3178
3179 facts = &ioc->facts;
3180 memset(facts, 0, sizeof(Mpi2IOCFactsReply_t));
3181 facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion);
3182 facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion);
3183 facts->VP_ID = mpi_reply.VP_ID;
3184 facts->VF_ID = mpi_reply.VF_ID;
3185 facts->IOCExceptions = le16_to_cpu(mpi_reply.IOCExceptions);
3186 facts->MaxChainDepth = mpi_reply.MaxChainDepth;
3187 facts->WhoInit = mpi_reply.WhoInit;
3188 facts->NumberOfPorts = mpi_reply.NumberOfPorts;
3189 facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit);
3190 facts->MaxReplyDescriptorPostQueueDepth =
3191 le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth);
3192 facts->ProductID = le16_to_cpu(mpi_reply.ProductID);
3193 facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities);
3194 if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
3195 ioc->ir_firmware = 1;
3196 facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word);
3197 facts->IOCRequestFrameSize =
3198 le16_to_cpu(mpi_reply.IOCRequestFrameSize);
3199 facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators);
3200 facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets);
3201 ioc->shost->max_id = -1;
3202 facts->MaxSasExpanders = le16_to_cpu(mpi_reply.MaxSasExpanders);
3203 facts->MaxEnclosures = le16_to_cpu(mpi_reply.MaxEnclosures);
3204 facts->ProtocolFlags = le16_to_cpu(mpi_reply.ProtocolFlags);
3205 facts->HighPriorityCredit =
3206 le16_to_cpu(mpi_reply.HighPriorityCredit);
3207 facts->ReplyFrameSize = mpi_reply.ReplyFrameSize;
3208 facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle);
3209
3210 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hba queue depth(%d), "
3211 "max chains per io(%d)\n", ioc->name, facts->RequestCredit,
3212 facts->MaxChainDepth));
3213 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request frame size(%d), "
3214 "reply frame size(%d)\n", ioc->name,
3215 facts->IOCRequestFrameSize * 4, facts->ReplyFrameSize * 4));
3216 return 0;
3217}
3218
3219/**
3220 * _base_send_ioc_init - send ioc_init to firmware
3221 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -06003222 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3223 *
3224 * Returns 0 for success, non-zero for failure.
3225 */
3226static int
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303227_base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
Eric Moore635374e2009-03-09 01:21:12 -06003228{
3229 Mpi2IOCInitRequest_t mpi_request;
3230 Mpi2IOCInitReply_t mpi_reply;
3231 int r;
Kashyap, Desaia8ebd762009-09-23 17:29:29 +05303232 struct timeval current_time;
Kashyap, Desai463217b2009-10-05 15:53:06 +05303233 u16 ioc_status;
Eric Moore635374e2009-03-09 01:21:12 -06003234
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303235 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003236 __func__));
3237
3238 memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t));
3239 mpi_request.Function = MPI2_FUNCTION_IOC_INIT;
3240 mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303241 mpi_request.VF_ID = 0; /* TODO */
3242 mpi_request.VP_ID = 0;
Eric Moore635374e2009-03-09 01:21:12 -06003243 mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION);
3244 mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
3245
Eric Moore635374e2009-03-09 01:21:12 -06003246
3247 mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4);
3248 mpi_request.ReplyDescriptorPostQueueDepth =
3249 cpu_to_le16(ioc->reply_post_queue_depth);
3250 mpi_request.ReplyFreeQueueDepth =
3251 cpu_to_le16(ioc->reply_free_queue_depth);
3252
Eric Moore635374e2009-03-09 01:21:12 -06003253 mpi_request.SenseBufferAddressHigh =
Kashyap, Desaic97951e2011-06-14 10:54:56 +05303254 cpu_to_le32((u64)ioc->sense_dma >> 32);
Eric Moore635374e2009-03-09 01:21:12 -06003255 mpi_request.SystemReplyAddressHigh =
Kashyap, Desaic97951e2011-06-14 10:54:56 +05303256 cpu_to_le32((u64)ioc->reply_dma >> 32);
Eric Moore635374e2009-03-09 01:21:12 -06003257 mpi_request.SystemRequestFrameBaseAddress =
Kashyap, Desaic97951e2011-06-14 10:54:56 +05303258 cpu_to_le64((u64)ioc->request_dma);
Eric Moore635374e2009-03-09 01:21:12 -06003259 mpi_request.ReplyFreeQueueAddress =
Kashyap, Desaic97951e2011-06-14 10:54:56 +05303260 cpu_to_le64((u64)ioc->reply_free_dma);
Eric Moore635374e2009-03-09 01:21:12 -06003261 mpi_request.ReplyDescriptorPostQueueAddress =
Kashyap, Desaic97951e2011-06-14 10:54:56 +05303262 cpu_to_le64((u64)ioc->reply_post_free_dma);
3263
Eric Moore635374e2009-03-09 01:21:12 -06003264
Kashyap, Desaia8ebd762009-09-23 17:29:29 +05303265 /* This time stamp specifies number of milliseconds
3266 * since epoch ~ midnight January 1, 1970.
3267 */
3268 do_gettimeofday(&current_time);
Kashyap, Desai7921b352010-03-17 16:21:33 +05303269 mpi_request.TimeStamp = cpu_to_le64((u64)current_time.tv_sec * 1000 +
3270 (current_time.tv_usec / 1000));
Kashyap, Desaia8ebd762009-09-23 17:29:29 +05303271
Eric Moore635374e2009-03-09 01:21:12 -06003272 if (ioc->logging_level & MPT_DEBUG_INIT) {
Kashyap, Desaic97951e2011-06-14 10:54:56 +05303273 __le32 *mfp;
Eric Moore635374e2009-03-09 01:21:12 -06003274 int i;
3275
Kashyap, Desaic97951e2011-06-14 10:54:56 +05303276 mfp = (__le32 *)&mpi_request;
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303277 printk(KERN_INFO "\toffset:data\n");
Eric Moore635374e2009-03-09 01:21:12 -06003278 for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++)
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303279 printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
Eric Moore635374e2009-03-09 01:21:12 -06003280 le32_to_cpu(mfp[i]));
3281 }
3282
3283 r = _base_handshake_req_reply_wait(ioc,
3284 sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request,
3285 sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10,
3286 sleep_flag);
3287
3288 if (r != 0) {
3289 printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
3290 ioc->name, __func__, r);
3291 return r;
3292 }
3293
Kashyap, Desai463217b2009-10-05 15:53:06 +05303294 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
3295 if (ioc_status != MPI2_IOCSTATUS_SUCCESS ||
Eric Moore635374e2009-03-09 01:21:12 -06003296 mpi_reply.IOCLogInfo) {
3297 printk(MPT2SAS_ERR_FMT "%s: failed\n", ioc->name, __func__);
3298 r = -EIO;
3299 }
3300
3301 return 0;
3302}
3303
3304/**
3305 * _base_send_port_enable - send port_enable(discovery stuff) to firmware
3306 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -06003307 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3308 *
3309 * Returns 0 for success, non-zero for failure.
3310 */
3311static int
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303312_base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
Eric Moore635374e2009-03-09 01:21:12 -06003313{
3314 Mpi2PortEnableRequest_t *mpi_request;
3315 u32 ioc_state;
3316 unsigned long timeleft;
3317 int r = 0;
3318 u16 smid;
3319
3320 printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name);
3321
3322 if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
3323 printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
3324 ioc->name, __func__);
3325 return -EAGAIN;
3326 }
3327
3328 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
3329 if (!smid) {
3330 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
3331 ioc->name, __func__);
3332 return -EAGAIN;
3333 }
3334
3335 ioc->base_cmds.status = MPT2_CMD_PENDING;
3336 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
3337 ioc->base_cmds.smid = smid;
3338 memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
3339 mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303340 mpi_request->VF_ID = 0; /* TODO */
3341 mpi_request->VP_ID = 0;
Eric Moore635374e2009-03-09 01:21:12 -06003342
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303343 mpt2sas_base_put_smid_default(ioc, smid);
Kashyap, Desaibcfb6e62009-09-14 11:05:24 +05303344 init_completion(&ioc->base_cmds.done);
Eric Moore635374e2009-03-09 01:21:12 -06003345 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
3346 300*HZ);
3347 if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
3348 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
3349 ioc->name, __func__);
3350 _debug_dump_mf(mpi_request,
3351 sizeof(Mpi2PortEnableRequest_t)/4);
3352 if (ioc->base_cmds.status & MPT2_CMD_RESET)
3353 r = -EFAULT;
3354 else
3355 r = -ETIME;
3356 goto out;
3357 } else
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303358 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: complete\n",
Eric Moore635374e2009-03-09 01:21:12 -06003359 ioc->name, __func__));
3360
3361 ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_OPERATIONAL,
3362 60, sleep_flag);
3363 if (ioc_state) {
3364 printk(MPT2SAS_ERR_FMT "%s: failed going to operational state "
3365 " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
3366 r = -EFAULT;
3367 }
3368 out:
3369 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
3370 printk(MPT2SAS_INFO_FMT "port enable: %s\n",
3371 ioc->name, ((r == 0) ? "SUCCESS" : "FAILED"));
3372 return r;
3373}
3374
3375/**
3376 * _base_unmask_events - turn on notification for this event
3377 * @ioc: per adapter object
3378 * @event: firmware event
3379 *
3380 * The mask is stored in ioc->event_masks.
3381 */
3382static void
3383_base_unmask_events(struct MPT2SAS_ADAPTER *ioc, u16 event)
3384{
3385 u32 desired_event;
3386
3387 if (event >= 128)
3388 return;
3389
3390 desired_event = (1 << (event % 32));
3391
3392 if (event < 32)
3393 ioc->event_masks[0] &= ~desired_event;
3394 else if (event < 64)
3395 ioc->event_masks[1] &= ~desired_event;
3396 else if (event < 96)
3397 ioc->event_masks[2] &= ~desired_event;
3398 else if (event < 128)
3399 ioc->event_masks[3] &= ~desired_event;
3400}
3401
3402/**
3403 * _base_event_notification - send event notification
3404 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -06003405 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3406 *
3407 * Returns 0 for success, non-zero for failure.
3408 */
3409static int
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303410_base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
Eric Moore635374e2009-03-09 01:21:12 -06003411{
3412 Mpi2EventNotificationRequest_t *mpi_request;
3413 unsigned long timeleft;
3414 u16 smid;
3415 int r = 0;
3416 int i;
3417
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303418 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003419 __func__));
3420
3421 if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
3422 printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
3423 ioc->name, __func__);
3424 return -EAGAIN;
3425 }
3426
3427 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
3428 if (!smid) {
3429 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
3430 ioc->name, __func__);
3431 return -EAGAIN;
3432 }
3433 ioc->base_cmds.status = MPT2_CMD_PENDING;
3434 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
3435 ioc->base_cmds.smid = smid;
3436 memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t));
3437 mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303438 mpi_request->VF_ID = 0; /* TODO */
3439 mpi_request->VP_ID = 0;
Eric Moore635374e2009-03-09 01:21:12 -06003440 for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
3441 mpi_request->EventMasks[i] =
Kashyap, Desaie94f6742010-03-17 16:24:52 +05303442 cpu_to_le32(ioc->event_masks[i]);
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303443 mpt2sas_base_put_smid_default(ioc, smid);
Kashyap, Desaibcfb6e62009-09-14 11:05:24 +05303444 init_completion(&ioc->base_cmds.done);
Eric Moore635374e2009-03-09 01:21:12 -06003445 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ);
3446 if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
3447 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
3448 ioc->name, __func__);
3449 _debug_dump_mf(mpi_request,
3450 sizeof(Mpi2EventNotificationRequest_t)/4);
3451 if (ioc->base_cmds.status & MPT2_CMD_RESET)
3452 r = -EFAULT;
3453 else
3454 r = -ETIME;
3455 } else
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303456 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: complete\n",
Eric Moore635374e2009-03-09 01:21:12 -06003457 ioc->name, __func__));
3458 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
3459 return r;
3460}
3461
3462/**
3463 * mpt2sas_base_validate_event_type - validating event types
3464 * @ioc: per adapter object
3465 * @event: firmware event
3466 *
3467 * This will turn on firmware event notification when application
3468 * ask for that event. We don't mask events that are already enabled.
3469 */
3470void
3471mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type)
3472{
3473 int i, j;
3474 u32 event_mask, desired_event;
3475 u8 send_update_to_fw;
3476
3477 for (i = 0, send_update_to_fw = 0; i <
3478 MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) {
3479 event_mask = ~event_type[i];
3480 desired_event = 1;
3481 for (j = 0; j < 32; j++) {
3482 if (!(event_mask & desired_event) &&
3483 (ioc->event_masks[i] & desired_event)) {
3484 ioc->event_masks[i] &= ~desired_event;
3485 send_update_to_fw = 1;
3486 }
3487 desired_event = (desired_event << 1);
3488 }
3489 }
3490
3491 if (!send_update_to_fw)
3492 return;
3493
3494 mutex_lock(&ioc->base_cmds.mutex);
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303495 _base_event_notification(ioc, CAN_SLEEP);
Eric Moore635374e2009-03-09 01:21:12 -06003496 mutex_unlock(&ioc->base_cmds.mutex);
3497}
3498
3499/**
3500 * _base_diag_reset - the "big hammer" start of day reset
3501 * @ioc: per adapter object
3502 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3503 *
3504 * Returns 0 for success, non-zero for failure.
3505 */
3506static int
3507_base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
3508{
3509 u32 host_diagnostic;
3510 u32 ioc_state;
3511 u32 count;
3512 u32 hcb_size;
3513
3514 printk(MPT2SAS_INFO_FMT "sending diag reset !!\n", ioc->name);
3515
3516 _base_save_msix_table(ioc);
3517
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303518 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "clear interrupts\n",
Eric Moore635374e2009-03-09 01:21:12 -06003519 ioc->name));
Eric Moore635374e2009-03-09 01:21:12 -06003520
3521 count = 0;
3522 do {
3523 /* Write magic sequence to WriteSequence register
3524 * Loop until in diagnostic mode
3525 */
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303526 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "write magic "
Eric Moore635374e2009-03-09 01:21:12 -06003527 "sequence\n", ioc->name));
3528 writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
3529 writel(MPI2_WRSEQ_1ST_KEY_VALUE, &ioc->chip->WriteSequence);
3530 writel(MPI2_WRSEQ_2ND_KEY_VALUE, &ioc->chip->WriteSequence);
3531 writel(MPI2_WRSEQ_3RD_KEY_VALUE, &ioc->chip->WriteSequence);
3532 writel(MPI2_WRSEQ_4TH_KEY_VALUE, &ioc->chip->WriteSequence);
3533 writel(MPI2_WRSEQ_5TH_KEY_VALUE, &ioc->chip->WriteSequence);
3534 writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence);
3535
3536 /* wait 100 msec */
3537 if (sleep_flag == CAN_SLEEP)
3538 msleep(100);
3539 else
3540 mdelay(100);
3541
3542 if (count++ > 20)
3543 goto out;
3544
3545 host_diagnostic = readl(&ioc->chip->HostDiagnostic);
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303546 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "wrote magic "
Eric Moore635374e2009-03-09 01:21:12 -06003547 "sequence: count(%d), host_diagnostic(0x%08x)\n",
3548 ioc->name, count, host_diagnostic));
3549
3550 } while ((host_diagnostic & MPI2_DIAG_DIAG_WRITE_ENABLE) == 0);
3551
3552 hcb_size = readl(&ioc->chip->HCBSize);
3553
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303554 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "diag reset: issued\n",
Eric Moore635374e2009-03-09 01:21:12 -06003555 ioc->name));
3556 writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER,
3557 &ioc->chip->HostDiagnostic);
3558
3559 /* don't access any registers for 50 milliseconds */
3560 msleep(50);
3561
3562 /* 300 second max wait */
3563 for (count = 0; count < 3000000 ; count++) {
3564
3565 host_diagnostic = readl(&ioc->chip->HostDiagnostic);
3566
3567 if (host_diagnostic == 0xFFFFFFFF)
3568 goto out;
3569 if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER))
3570 break;
3571
3572 /* wait 100 msec */
3573 if (sleep_flag == CAN_SLEEP)
3574 msleep(1);
3575 else
3576 mdelay(1);
3577 }
3578
3579 if (host_diagnostic & MPI2_DIAG_HCB_MODE) {
3580
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303581 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "restart the adapter "
Eric Moore635374e2009-03-09 01:21:12 -06003582 "assuming the HCB Address points to good F/W\n",
3583 ioc->name));
3584 host_diagnostic &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK;
3585 host_diagnostic |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW;
3586 writel(host_diagnostic, &ioc->chip->HostDiagnostic);
3587
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303588 drsprintk(ioc, printk(MPT2SAS_INFO_FMT
Eric Moore635374e2009-03-09 01:21:12 -06003589 "re-enable the HCDW\n", ioc->name));
3590 writel(hcb_size | MPI2_HCB_SIZE_HCB_ENABLE,
3591 &ioc->chip->HCBSize);
3592 }
3593
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303594 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "restart the adapter\n",
Eric Moore635374e2009-03-09 01:21:12 -06003595 ioc->name));
3596 writel(host_diagnostic & ~MPI2_DIAG_HOLD_IOC_RESET,
3597 &ioc->chip->HostDiagnostic);
3598
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303599 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "disable writes to the "
Eric Moore635374e2009-03-09 01:21:12 -06003600 "diagnostic register\n", ioc->name));
3601 writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
3602
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303603 drsprintk(ioc, printk(MPT2SAS_INFO_FMT "Wait for FW to go to the "
Eric Moore635374e2009-03-09 01:21:12 -06003604 "READY state\n", ioc->name));
3605 ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20,
3606 sleep_flag);
3607 if (ioc_state) {
3608 printk(MPT2SAS_ERR_FMT "%s: failed going to ready state "
3609 " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
3610 goto out;
3611 }
3612
3613 _base_restore_msix_table(ioc);
3614 printk(MPT2SAS_INFO_FMT "diag reset: SUCCESS\n", ioc->name);
3615 return 0;
3616
3617 out:
3618 printk(MPT2SAS_ERR_FMT "diag reset: FAILED\n", ioc->name);
3619 return -EFAULT;
3620}
3621
3622/**
3623 * _base_make_ioc_ready - put controller in READY state
3624 * @ioc: per adapter object
3625 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3626 * @type: FORCE_BIG_HAMMER or SOFT_RESET
3627 *
3628 * Returns 0 for success, non-zero for failure.
3629 */
3630static int
3631_base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
3632 enum reset_type type)
3633{
3634 u32 ioc_state;
Kashyap, Desaid32a8c12010-06-17 13:36:53 +05303635 int rc;
Eric Moore635374e2009-03-09 01:21:12 -06003636
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303637 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003638 __func__));
3639
Eric Moore3cb54692010-07-08 14:44:34 -06003640 if (ioc->pci_error_recovery)
3641 return 0;
3642
Eric Moore635374e2009-03-09 01:21:12 -06003643 ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303644 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: ioc_state(0x%08x)\n",
Eric Moore635374e2009-03-09 01:21:12 -06003645 ioc->name, __func__, ioc_state));
3646
3647 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY)
3648 return 0;
3649
3650 if (ioc_state & MPI2_DOORBELL_USED) {
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303651 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "
Eric Moore635374e2009-03-09 01:21:12 -06003652 "active!\n", ioc->name));
3653 goto issue_diag_reset;
3654 }
3655
3656 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
3657 mpt2sas_base_fault_info(ioc, ioc_state &
3658 MPI2_DOORBELL_DATA_MASK);
3659 goto issue_diag_reset;
3660 }
3661
3662 if (type == FORCE_BIG_HAMMER)
3663 goto issue_diag_reset;
3664
3665 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL)
3666 if (!(_base_send_ioc_reset(ioc,
Kashyap, Desaid32a8c12010-06-17 13:36:53 +05303667 MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) {
3668 ioc->ioc_reset_count++;
Eric Moore635374e2009-03-09 01:21:12 -06003669 return 0;
Kashyap, Desaid32a8c12010-06-17 13:36:53 +05303670 }
Eric Moore635374e2009-03-09 01:21:12 -06003671
3672 issue_diag_reset:
Kashyap, Desaid32a8c12010-06-17 13:36:53 +05303673 rc = _base_diag_reset(ioc, CAN_SLEEP);
3674 ioc->ioc_reset_count++;
3675 return rc;
Eric Moore635374e2009-03-09 01:21:12 -06003676}
3677
3678/**
3679 * _base_make_ioc_operational - put controller in OPERATIONAL state
3680 * @ioc: per adapter object
Eric Moore635374e2009-03-09 01:21:12 -06003681 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3682 *
3683 * Returns 0 for success, non-zero for failure.
3684 */
3685static int
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303686_base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
Eric Moore635374e2009-03-09 01:21:12 -06003687{
3688 int r, i;
3689 unsigned long flags;
3690 u32 reply_address;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303691 u16 smid;
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303692 struct _tr_list *delayed_tr, *delayed_tr_next;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303693 u8 hide_flag;
Eric Moore635374e2009-03-09 01:21:12 -06003694
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303695 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003696 __func__));
3697
Kashyap, Desai77e63ed2009-09-14 11:04:23 +05303698 /* clean the delayed target reset list */
3699 list_for_each_entry_safe(delayed_tr, delayed_tr_next,
3700 &ioc->delayed_tr_list, list) {
3701 list_del(&delayed_tr->list);
3702 kfree(delayed_tr);
3703 }
3704
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303705 list_for_each_entry_safe(delayed_tr, delayed_tr_next,
3706 &ioc->delayed_tr_volume_list, list) {
3707 list_del(&delayed_tr->list);
3708 kfree(delayed_tr);
3709 }
3710
Eric Moore635374e2009-03-09 01:21:12 -06003711 /* initialize the scsi lookup free list */
3712 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
3713 INIT_LIST_HEAD(&ioc->free_list);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303714 smid = 1;
3715 for (i = 0; i < ioc->scsiio_depth; i++, smid++) {
Kashyap, Desai35f805b2010-11-13 04:34:06 +05303716 INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list);
Eric Moore635374e2009-03-09 01:21:12 -06003717 ioc->scsi_lookup[i].cb_idx = 0xFF;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303718 ioc->scsi_lookup[i].smid = smid;
3719 ioc->scsi_lookup[i].scmd = NULL;
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303720 ioc->scsi_lookup[i].direct_io = 0;
Eric Moore635374e2009-03-09 01:21:12 -06003721 list_add_tail(&ioc->scsi_lookup[i].tracker_list,
3722 &ioc->free_list);
3723 }
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303724
3725 /* hi-priority queue */
3726 INIT_LIST_HEAD(&ioc->hpr_free_list);
3727 smid = ioc->hi_priority_smid;
3728 for (i = 0; i < ioc->hi_priority_depth; i++, smid++) {
3729 ioc->hpr_lookup[i].cb_idx = 0xFF;
3730 ioc->hpr_lookup[i].smid = smid;
3731 list_add_tail(&ioc->hpr_lookup[i].tracker_list,
3732 &ioc->hpr_free_list);
3733 }
3734
3735 /* internal queue */
3736 INIT_LIST_HEAD(&ioc->internal_free_list);
3737 smid = ioc->internal_smid;
3738 for (i = 0; i < ioc->internal_depth; i++, smid++) {
3739 ioc->internal_lookup[i].cb_idx = 0xFF;
3740 ioc->internal_lookup[i].smid = smid;
3741 list_add_tail(&ioc->internal_lookup[i].tracker_list,
3742 &ioc->internal_free_list);
3743 }
Kashyap, Desai35f805b2010-11-13 04:34:06 +05303744
3745 /* chain pool */
3746 INIT_LIST_HEAD(&ioc->free_chain_list);
3747 for (i = 0; i < ioc->chain_depth; i++)
3748 list_add_tail(&ioc->chain_lookup[i].tracker_list,
3749 &ioc->free_chain_list);
3750
Eric Moore635374e2009-03-09 01:21:12 -06003751 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
3752
3753 /* initialize Reply Free Queue */
3754 for (i = 0, reply_address = (u32)ioc->reply_dma ;
3755 i < ioc->reply_free_queue_depth ; i++, reply_address +=
3756 ioc->reply_sz)
3757 ioc->reply_free[i] = cpu_to_le32(reply_address);
3758
3759 /* initialize Reply Post Free Queue */
3760 for (i = 0; i < ioc->reply_post_queue_depth; i++)
Kashyap, Desaic97951e2011-06-14 10:54:56 +05303761 ioc->reply_post_free[i].Words = cpu_to_le64(ULLONG_MAX);
Eric Moore635374e2009-03-09 01:21:12 -06003762
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303763 r = _base_send_ioc_init(ioc, sleep_flag);
Eric Moore635374e2009-03-09 01:21:12 -06003764 if (r)
3765 return r;
3766
3767 /* initialize the index's */
3768 ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1;
3769 ioc->reply_post_host_index = 0;
3770 writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex);
3771 writel(0, &ioc->chip->ReplyPostHostIndex);
3772
3773 _base_unmask_interrupts(ioc);
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303774 r = _base_event_notification(ioc, sleep_flag);
Eric Moore635374e2009-03-09 01:21:12 -06003775 if (r)
3776 return r;
3777
3778 if (sleep_flag == CAN_SLEEP)
3779 _base_static_config_pages(ioc);
3780
Kashyap, Desai0bdccdb2011-04-07 12:32:49 +05303781 if (ioc->wait_for_port_enable_to_complete && ioc->is_warpdrive) {
3782 if (ioc->manu_pg10.OEMIdentifier == 0x80) {
3783 hide_flag = (u8) (ioc->manu_pg10.OEMSpecificFlags0 &
3784 MFG_PAGE10_HIDE_SSDS_MASK);
3785 if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK)
3786 ioc->mfg_pg10_hide_flag = hide_flag;
3787 }
3788 }
3789
Kashyap, Desai570c67a2010-06-17 13:43:17 +05303790 if (ioc->wait_for_port_enable_to_complete) {
3791 if (diag_buffer_enable != 0)
3792 mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
3793 if (disable_discovery > 0)
3794 return r;
3795 }
Kashyap, Desaidd5fd332010-06-17 13:31:17 +05303796
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303797 r = _base_send_port_enable(ioc, sleep_flag);
Eric Moore635374e2009-03-09 01:21:12 -06003798 if (r)
3799 return r;
3800
3801 return r;
3802}
3803
3804/**
3805 * mpt2sas_base_free_resources - free resources controller resources (io/irq/memap)
3806 * @ioc: per adapter object
3807 *
3808 * Return nothing.
3809 */
3810void
3811mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc)
3812{
3813 struct pci_dev *pdev = ioc->pdev;
3814
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303815 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003816 __func__));
3817
3818 _base_mask_interrupts(ioc);
Kashyap, Desai6558bbb2010-03-17 16:23:36 +05303819 ioc->shost_recovery = 1;
Eric Moore635374e2009-03-09 01:21:12 -06003820 _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
Kashyap, Desai6558bbb2010-03-17 16:23:36 +05303821 ioc->shost_recovery = 0;
Eric Moore635374e2009-03-09 01:21:12 -06003822 if (ioc->pci_irq) {
3823 synchronize_irq(pdev->irq);
3824 free_irq(ioc->pci_irq, ioc);
3825 }
3826 _base_disable_msix(ioc);
3827 if (ioc->chip_phys)
3828 iounmap(ioc->chip);
3829 ioc->pci_irq = -1;
3830 ioc->chip_phys = 0;
3831 pci_release_selected_regions(ioc->pdev, ioc->bars);
Kashyap, Desaief7c80c2010-04-05 14:20:07 +05303832 pci_disable_pcie_error_reporting(pdev);
Eric Moore635374e2009-03-09 01:21:12 -06003833 pci_disable_device(pdev);
Eric Moore635374e2009-03-09 01:21:12 -06003834 return;
3835}
3836
3837/**
3838 * mpt2sas_base_attach - attach controller instance
3839 * @ioc: per adapter object
3840 *
3841 * Returns 0 for success, non-zero for failure.
3842 */
3843int
3844mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
3845{
3846 int r, i;
Eric Moore635374e2009-03-09 01:21:12 -06003847
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05303848 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06003849 __func__));
3850
3851 r = mpt2sas_base_map_resources(ioc);
3852 if (r)
3853 return r;
3854
Kashyap, Desaifcfe6392009-08-07 19:38:48 +05303855 pci_set_drvdata(ioc->pdev, ioc->shost);
Kashyap, Desai96b681c2009-09-23 17:32:06 +05303856 r = _base_get_ioc_facts(ioc, CAN_SLEEP);
Eric Moore635374e2009-03-09 01:21:12 -06003857 if (r)
3858 goto out_free_resources;
3859
Kashyap, Desai96b681c2009-09-23 17:32:06 +05303860 r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
Eric Moore635374e2009-03-09 01:21:12 -06003861 if (r)
3862 goto out_free_resources;
3863
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303864 ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts,
3865 sizeof(Mpi2PortFactsReply_t), GFP_KERNEL);
Kashyap, Desaif6aee7b2010-03-17 16:26:48 +05303866 if (!ioc->pfacts) {
3867 r = -ENOMEM;
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303868 goto out_free_resources;
Kashyap, Desaif6aee7b2010-03-17 16:26:48 +05303869 }
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05303870
3871 for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) {
3872 r = _base_get_port_facts(ioc, i, CAN_SLEEP);
3873 if (r)
3874 goto out_free_resources;
3875 }
3876
Eric Moore635374e2009-03-09 01:21:12 -06003877 r = _base_allocate_memory_pools(ioc, CAN_SLEEP);
3878 if (r)
3879 goto out_free_resources;
3880
3881 init_waitqueue_head(&ioc->reset_wq);
3882
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303883 /* allocate memory pd handle bitmask list */
3884 ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8);
3885 if (ioc->facts.MaxDevHandle % 8)
3886 ioc->pd_handles_sz++;
3887 ioc->pd_handles = kzalloc(ioc->pd_handles_sz,
3888 GFP_KERNEL);
Kashyap, Desai3e2e8332010-06-17 13:47:29 +05303889 if (!ioc->pd_handles) {
3890 r = -ENOMEM;
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303891 goto out_free_resources;
Kashyap, Desai3e2e8332010-06-17 13:47:29 +05303892 }
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303893
Kashyap, Desaie75b9b62009-12-16 18:52:39 +05303894 ioc->fwfault_debug = mpt2sas_fwfault_debug;
3895
Eric Moore635374e2009-03-09 01:21:12 -06003896 /* base internal command bits */
3897 mutex_init(&ioc->base_cmds.mutex);
Eric Moore635374e2009-03-09 01:21:12 -06003898 ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3899 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
3900
3901 /* transport internal command bits */
3902 ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3903 ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
3904 mutex_init(&ioc->transport_cmds.mutex);
Eric Moore635374e2009-03-09 01:21:12 -06003905
Kashyap, Desaid685c262009-11-17 13:16:37 +05303906 /* scsih internal command bits */
3907 ioc->scsih_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3908 ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
3909 mutex_init(&ioc->scsih_cmds.mutex);
3910
Eric Moore635374e2009-03-09 01:21:12 -06003911 /* task management internal command bits */
3912 ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3913 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
3914 mutex_init(&ioc->tm_cmds.mutex);
Eric Moore635374e2009-03-09 01:21:12 -06003915
3916 /* config page internal command bits */
3917 ioc->config_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3918 ioc->config_cmds.status = MPT2_CMD_NOT_USED;
3919 mutex_init(&ioc->config_cmds.mutex);
Eric Moore635374e2009-03-09 01:21:12 -06003920
3921 /* ctl module internal command bits */
3922 ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
Kashyap, Desai769578f2010-06-17 13:49:28 +05303923 ioc->ctl_cmds.sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
Eric Moore635374e2009-03-09 01:21:12 -06003924 ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
3925 mutex_init(&ioc->ctl_cmds.mutex);
Eric Moore635374e2009-03-09 01:21:12 -06003926
Kashyap, Desaif6aee7b2010-03-17 16:26:48 +05303927 if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply ||
3928 !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply ||
Kashyap, Desai769578f2010-06-17 13:49:28 +05303929 !ioc->config_cmds.reply || !ioc->ctl_cmds.reply ||
3930 !ioc->ctl_cmds.sense) {
Kashyap, Desaif6aee7b2010-03-17 16:26:48 +05303931 r = -ENOMEM;
3932 goto out_free_resources;
3933 }
3934
Kashyap, Desai3e2e8332010-06-17 13:47:29 +05303935 if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply ||
3936 !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply ||
3937 !ioc->config_cmds.reply || !ioc->ctl_cmds.reply) {
3938 r = -ENOMEM;
3939 goto out_free_resources;
3940 }
3941
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05303942 init_completion(&ioc->shost_recovery_done);
3943
Eric Moore635374e2009-03-09 01:21:12 -06003944 for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
3945 ioc->event_masks[i] = -1;
3946
3947 /* here we enable the events we care about */
3948 _base_unmask_events(ioc, MPI2_EVENT_SAS_DISCOVERY);
3949 _base_unmask_events(ioc, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE);
3950 _base_unmask_events(ioc, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
3951 _base_unmask_events(ioc, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
3952 _base_unmask_events(ioc, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE);
3953 _base_unmask_events(ioc, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST);
3954 _base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME);
3955 _base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK);
3956 _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS);
Eric Moore635374e2009-03-09 01:21:12 -06003957 _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED);
Kashyap, Desai7b936b02009-09-25 11:44:41 +05303958 r = _base_make_ioc_operational(ioc, CAN_SLEEP);
Eric Moore635374e2009-03-09 01:21:12 -06003959 if (r)
3960 goto out_free_resources;
3961
Kashyap, Desai6cb8ef52010-11-13 04:32:18 +05303962 if (missing_delay[0] != -1 && missing_delay[1] != -1)
3963 _base_update_missing_delay(ioc, missing_delay[0],
3964 missing_delay[1]);
3965
Kashyap, Desaie4750c92009-08-07 19:37:59 +05303966 mpt2sas_base_start_watchdog(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06003967 return 0;
3968
3969 out_free_resources:
3970
3971 ioc->remove_host = 1;
3972 mpt2sas_base_free_resources(ioc);
3973 _base_release_memory_pools(ioc);
Kashyap, Desaifcfe6392009-08-07 19:38:48 +05303974 pci_set_drvdata(ioc->pdev, NULL);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05303975 kfree(ioc->pd_handles);
Eric Moore635374e2009-03-09 01:21:12 -06003976 kfree(ioc->tm_cmds.reply);
3977 kfree(ioc->transport_cmds.reply);
Kashyap, Desaie94f6742010-03-17 16:24:52 +05303978 kfree(ioc->scsih_cmds.reply);
Eric Moore635374e2009-03-09 01:21:12 -06003979 kfree(ioc->config_cmds.reply);
3980 kfree(ioc->base_cmds.reply);
3981 kfree(ioc->ctl_cmds.reply);
Kashyap, Desai769578f2010-06-17 13:49:28 +05303982 kfree(ioc->ctl_cmds.sense);
Eric Moore635374e2009-03-09 01:21:12 -06003983 kfree(ioc->pfacts);
3984 ioc->ctl_cmds.reply = NULL;
3985 ioc->base_cmds.reply = NULL;
3986 ioc->tm_cmds.reply = NULL;
Kashyap, Desaie94f6742010-03-17 16:24:52 +05303987 ioc->scsih_cmds.reply = NULL;
Eric Moore635374e2009-03-09 01:21:12 -06003988 ioc->transport_cmds.reply = NULL;
3989 ioc->config_cmds.reply = NULL;
3990 ioc->pfacts = NULL;
3991 return r;
3992}
3993
3994
3995/**
3996 * mpt2sas_base_detach - remove controller instance
3997 * @ioc: per adapter object
3998 *
3999 * Return nothing.
4000 */
4001void
4002mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)
4003{
Eric Moore635374e2009-03-09 01:21:12 -06004004
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05304005 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06004006 __func__));
4007
Kashyap, Desaie4750c92009-08-07 19:37:59 +05304008 mpt2sas_base_stop_watchdog(ioc);
Eric Moore635374e2009-03-09 01:21:12 -06004009 mpt2sas_base_free_resources(ioc);
4010 _base_release_memory_pools(ioc);
Kashyap, Desaifcfe6392009-08-07 19:38:48 +05304011 pci_set_drvdata(ioc->pdev, NULL);
Kashyap, Desaif3eedd62010-06-17 13:46:13 +05304012 kfree(ioc->pd_handles);
Eric Moore635374e2009-03-09 01:21:12 -06004013 kfree(ioc->pfacts);
4014 kfree(ioc->ctl_cmds.reply);
Kashyap, Desai769578f2010-06-17 13:49:28 +05304015 kfree(ioc->ctl_cmds.sense);
Eric Moore635374e2009-03-09 01:21:12 -06004016 kfree(ioc->base_cmds.reply);
4017 kfree(ioc->tm_cmds.reply);
4018 kfree(ioc->transport_cmds.reply);
Kashyap, Desaie94f6742010-03-17 16:24:52 +05304019 kfree(ioc->scsih_cmds.reply);
Eric Moore635374e2009-03-09 01:21:12 -06004020 kfree(ioc->config_cmds.reply);
4021}
4022
4023/**
4024 * _base_reset_handler - reset callback handler (for base)
4025 * @ioc: per adapter object
4026 * @reset_phase: phase
4027 *
4028 * The handler for doing any required cleanup or initialization.
4029 *
4030 * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
4031 * MPT2_IOC_DONE_RESET
4032 *
4033 * Return nothing.
4034 */
4035static void
4036_base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
4037{
Kashyap, Desai42244892011-01-04 11:38:39 +05304038 mpt2sas_scsih_reset_handler(ioc, reset_phase);
4039 mpt2sas_ctl_reset_handler(ioc, reset_phase);
Eric Moore635374e2009-03-09 01:21:12 -06004040 switch (reset_phase) {
4041 case MPT2_IOC_PRE_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05304042 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Eric Moore635374e2009-03-09 01:21:12 -06004043 "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
4044 break;
4045 case MPT2_IOC_AFTER_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05304046 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Eric Moore635374e2009-03-09 01:21:12 -06004047 "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
4048 if (ioc->transport_cmds.status & MPT2_CMD_PENDING) {
4049 ioc->transport_cmds.status |= MPT2_CMD_RESET;
4050 mpt2sas_base_free_smid(ioc, ioc->transport_cmds.smid);
4051 complete(&ioc->transport_cmds.done);
4052 }
4053 if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
4054 ioc->base_cmds.status |= MPT2_CMD_RESET;
4055 mpt2sas_base_free_smid(ioc, ioc->base_cmds.smid);
4056 complete(&ioc->base_cmds.done);
4057 }
4058 if (ioc->config_cmds.status & MPT2_CMD_PENDING) {
4059 ioc->config_cmds.status |= MPT2_CMD_RESET;
4060 mpt2sas_base_free_smid(ioc, ioc->config_cmds.smid);
Alexey Dobriyan4be929b2010-05-24 14:33:03 -07004061 ioc->config_cmds.smid = USHRT_MAX;
Eric Moore635374e2009-03-09 01:21:12 -06004062 complete(&ioc->config_cmds.done);
4063 }
4064 break;
4065 case MPT2_IOC_DONE_RESET:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05304066 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
Eric Moore635374e2009-03-09 01:21:12 -06004067 "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
4068 break;
4069 }
Eric Moore635374e2009-03-09 01:21:12 -06004070}
4071
4072/**
4073 * _wait_for_commands_to_complete - reset controller
4074 * @ioc: Pointer to MPT_ADAPTER structure
4075 * @sleep_flag: CAN_SLEEP or NO_SLEEP
4076 *
4077 * This function waiting(3s) for all pending commands to complete
4078 * prior to putting controller in reset.
4079 */
4080static void
4081_wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
4082{
4083 u32 ioc_state;
4084 unsigned long flags;
4085 u16 i;
4086
4087 ioc->pending_io_count = 0;
4088 if (sleep_flag != CAN_SLEEP)
4089 return;
4090
4091 ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
4092 if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL)
4093 return;
4094
4095 /* pending command count */
4096 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
Kashyap, Desai595bb0b2009-09-14 11:02:48 +05304097 for (i = 0; i < ioc->scsiio_depth; i++)
Eric Moore635374e2009-03-09 01:21:12 -06004098 if (ioc->scsi_lookup[i].cb_idx != 0xFF)
4099 ioc->pending_io_count++;
4100 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
4101
4102 if (!ioc->pending_io_count)
4103 return;
4104
4105 /* wait for pending commands to complete */
Kashyap, Desaid2742132010-06-17 13:28:55 +05304106 wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ);
Eric Moore635374e2009-03-09 01:21:12 -06004107}
4108
4109/**
4110 * mpt2sas_base_hard_reset_handler - reset controller
4111 * @ioc: Pointer to MPT_ADAPTER structure
4112 * @sleep_flag: CAN_SLEEP or NO_SLEEP
4113 * @type: FORCE_BIG_HAMMER or SOFT_RESET
4114 *
4115 * Returns 0 for success, non-zero for failure.
4116 */
4117int
4118mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
4119 enum reset_type type)
4120{
Kashyap, Desai7b936b02009-09-25 11:44:41 +05304121 int r;
Eric Moore635374e2009-03-09 01:21:12 -06004122 unsigned long flags;
Kashyap, Desai42244892011-01-04 11:38:39 +05304123 u8 pe_complete = ioc->wait_for_port_enable_to_complete;
Eric Moore635374e2009-03-09 01:21:12 -06004124
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05304125 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
Eric Moore635374e2009-03-09 01:21:12 -06004126 __func__));
4127
Eric Moore3cb54692010-07-08 14:44:34 -06004128 if (ioc->pci_error_recovery) {
4129 printk(MPT2SAS_ERR_FMT "%s: pci error recovery reset\n",
4130 ioc->name, __func__);
4131 r = 0;
4132 goto out;
4133 }
4134
Kashyap, Desaifa7f3162009-09-23 17:26:58 +05304135 if (mpt2sas_fwfault_debug)
4136 mpt2sas_halt_firmware(ioc);
4137
Kashyap, Desaid2742132010-06-17 13:28:55 +05304138 /* TODO - What we really should be doing is pulling
4139 * out all the code associated with NO_SLEEP; its never used.
4140 * That is legacy code from mpt fusion driver, ported over.
4141 * I will leave this BUG_ON here for now till its been resolved.
4142 */
4143 BUG_ON(sleep_flag == NO_SLEEP);
4144
4145 /* wait for an active reset in progress to complete */
4146 if (!mutex_trylock(&ioc->reset_in_progress_mutex)) {
4147 do {
4148 ssleep(1);
4149 } while (ioc->shost_recovery == 1);
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05304150 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name,
Kashyap, Desaid2742132010-06-17 13:28:55 +05304151 __func__));
4152 return ioc->ioc_reset_in_progress_status;
Eric Moore635374e2009-03-09 01:21:12 -06004153 }
Kashyap, Desaid2742132010-06-17 13:28:55 +05304154
4155 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
Eric Moore635374e2009-03-09 01:21:12 -06004156 ioc->shost_recovery = 1;
Eric Moore635374e2009-03-09 01:21:12 -06004157 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
4158
4159 _base_reset_handler(ioc, MPT2_IOC_PRE_RESET);
4160 _wait_for_commands_to_complete(ioc, sleep_flag);
4161 _base_mask_interrupts(ioc);
4162 r = _base_make_ioc_ready(ioc, sleep_flag, type);
4163 if (r)
4164 goto out;
4165 _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET);
Kashyap, Desai42244892011-01-04 11:38:39 +05304166
4167 /* If this hard reset is called while port enable is active, then
4168 * there is no reason to call make_ioc_operational
4169 */
4170 if (pe_complete) {
4171 r = -EFAULT;
4172 goto out;
4173 }
Kashyap, Desai7b936b02009-09-25 11:44:41 +05304174 r = _base_make_ioc_operational(ioc, sleep_flag);
Eric Moore635374e2009-03-09 01:21:12 -06004175 if (!r)
4176 _base_reset_handler(ioc, MPT2_IOC_DONE_RESET);
4177 out:
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05304178 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %s\n",
Eric Moore635374e2009-03-09 01:21:12 -06004179 ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED")));
4180
4181 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
Kashyap, Desaid2742132010-06-17 13:28:55 +05304182 ioc->ioc_reset_in_progress_status = r;
Kashyap, Desai155dd4c2009-08-20 13:22:00 +05304183 ioc->shost_recovery = 0;
Kashyap, Desaif1c35e62010-03-09 16:31:43 +05304184 complete(&ioc->shost_recovery_done);
Eric Moore635374e2009-03-09 01:21:12 -06004185 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
Kashyap, Desaid2742132010-06-17 13:28:55 +05304186 mutex_unlock(&ioc->reset_in_progress_mutex);
Kashyap, Desaicd4e12e2009-08-20 13:20:54 +05304187
Kashyap, Desaieabb08a2010-06-17 13:43:57 +05304188 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name,
Kashyap, Desaid2742132010-06-17 13:28:55 +05304189 __func__));
Eric Moore635374e2009-03-09 01:21:12 -06004190 return r;
4191}