/drivers/scsi/mpt2sas/mpt2sas_base.c
C | 3819 lines | 2660 code | 437 blank | 722 comment | 369 complexity | d38806ed30cbbad5f34e536fb2833842 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, GPL-2.0, LGPL-2.0, AGPL-1.0
Large files files are truncated, but you can click here to view the full file
1/*
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
6 * Copyright (C) 2007-2009 LSI Corporation
7 * (mailto:DL-MPTFusionLinux@lsi.com)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * NO WARRANTY
20 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
21 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
22 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
23 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
24 * solely responsible for determining the appropriateness of using and
25 * distributing the Program and assumes all risks associated with its
26 * exercise of rights under this Agreement, including but not limited to
27 * the risks and costs of program errors, damage to or loss of data,
28 * programs or equipment, and unavailability or interruption of operations.
29
30 * DISCLAIMER OF LIABILITY
31 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
34 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
35 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
37 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
38
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
42 * USA.
43 */
44
45#include <linux/version.h>
46#include <linux/kernel.h>
47#include <linux/module.h>
48#include <linux/errno.h>
49#include <linux/init.h>
50#include <linux/slab.h>
51#include <linux/types.h>
52#include <linux/pci.h>
53#include <linux/kdev_t.h>
54#include <linux/blkdev.h>
55#include <linux/delay.h>
56#include <linux/interrupt.h>
57#include <linux/dma-mapping.h>
58#include <linux/sort.h>
59#include <linux/io.h>
60#include <linux/time.h>
61
62#include "mpt2sas_base.h"
63
64static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS];
65
66#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
67#define MPT2SAS_MAX_REQUEST_QUEUE 600 /* maximum controller queue depth */
68
69static int max_queue_depth = -1;
70module_param(max_queue_depth, int, 0);
71MODULE_PARM_DESC(max_queue_depth, " max controller queue depth ");
72
73static int max_sgl_entries = -1;
74module_param(max_sgl_entries, int, 0);
75MODULE_PARM_DESC(max_sgl_entries, " max sg entries ");
76
77static int msix_disable = -1;
78module_param(msix_disable, int, 0);
79MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
80
81/* diag_buffer_enable is bitwise
82 * bit 0 set = TRACE
83 * bit 1 set = SNAPSHOT
84 * bit 2 set = EXTENDED
85 *
86 * Either bit can be set, or both
87 */
88static int diag_buffer_enable;
89module_param(diag_buffer_enable, int, 0);
90MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
91 "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
92
93int mpt2sas_fwfault_debug;
94MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
95 "and halt firmware - (default=0)");
96
97/**
98 * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.
99 *
100 */
101static int
102_scsih_set_fwfault_debug(const char *val, struct kernel_param *kp)
103{
104 int ret = param_set_int(val, kp);
105 struct MPT2SAS_ADAPTER *ioc;
106
107 if (ret)
108 return ret;
109
110 printk(KERN_INFO "setting fwfault_debug(%d)\n", mpt2sas_fwfault_debug);
111 list_for_each_entry(ioc, &mpt2sas_ioc_list, list)
112 ioc->fwfault_debug = mpt2sas_fwfault_debug;
113 return 0;
114}
115module_param_call(mpt2sas_fwfault_debug, _scsih_set_fwfault_debug,
116 param_get_int, &mpt2sas_fwfault_debug, 0644);
117
118/**
119 * _base_fault_reset_work - workq handling ioc fault conditions
120 * @work: input argument, used to derive ioc
121 * Context: sleep.
122 *
123 * Return nothing.
124 */
125static void
126_base_fault_reset_work(struct work_struct *work)
127{
128 struct MPT2SAS_ADAPTER *ioc =
129 container_of(work, struct MPT2SAS_ADAPTER, fault_reset_work.work);
130 unsigned long flags;
131 u32 doorbell;
132 int rc;
133
134 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
135 if (ioc->shost_recovery)
136 goto rearm_timer;
137 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
138
139 doorbell = mpt2sas_base_get_iocstate(ioc, 0);
140 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
141 rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
142 FORCE_BIG_HAMMER);
143 printk(MPT2SAS_WARN_FMT "%s: hard reset: %s\n", ioc->name,
144 __func__, (rc == 0) ? "success" : "failed");
145 doorbell = mpt2sas_base_get_iocstate(ioc, 0);
146 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
147 mpt2sas_base_fault_info(ioc, doorbell &
148 MPI2_DOORBELL_DATA_MASK);
149 }
150
151 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
152 rearm_timer:
153 if (ioc->fault_reset_work_q)
154 queue_delayed_work(ioc->fault_reset_work_q,
155 &ioc->fault_reset_work,
156 msecs_to_jiffies(FAULT_POLLING_INTERVAL));
157 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
158}
159
160/**
161 * mpt2sas_base_start_watchdog - start the fault_reset_work_q
162 * @ioc: per adapter object
163 * Context: sleep.
164 *
165 * Return nothing.
166 */
167void
168mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc)
169{
170 unsigned long flags;
171
172 if (ioc->fault_reset_work_q)
173 return;
174
175 /* initialize fault polling */
176 INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
177 snprintf(ioc->fault_reset_work_q_name,
178 sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
179 ioc->fault_reset_work_q =
180 create_singlethread_workqueue(ioc->fault_reset_work_q_name);
181 if (!ioc->fault_reset_work_q) {
182 printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n",
183 ioc->name, __func__, __LINE__);
184 return;
185 }
186 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
187 if (ioc->fault_reset_work_q)
188 queue_delayed_work(ioc->fault_reset_work_q,
189 &ioc->fault_reset_work,
190 msecs_to_jiffies(FAULT_POLLING_INTERVAL));
191 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
192}
193
194/**
195 * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q
196 * @ioc: per adapter object
197 * Context: sleep.
198 *
199 * Return nothing.
200 */
201void
202mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc)
203{
204 unsigned long flags;
205 struct workqueue_struct *wq;
206
207 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
208 wq = ioc->fault_reset_work_q;
209 ioc->fault_reset_work_q = NULL;
210 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
211 if (wq) {
212 if (!cancel_delayed_work(&ioc->fault_reset_work))
213 flush_workqueue(wq);
214 destroy_workqueue(wq);
215 }
216}
217
218/**
219 * mpt2sas_base_fault_info - verbose translation of firmware FAULT code
220 * @ioc: per adapter object
221 * @fault_code: fault code
222 *
223 * Return nothing.
224 */
225void
226mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code)
227{
228 printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n",
229 ioc->name, fault_code);
230}
231
232/**
233 * mpt2sas_halt_firmware - halt's mpt controller firmware
234 * @ioc: per adapter object
235 *
236 * For debugging timeout related issues. Writing 0xCOFFEE00
237 * to the doorbell register will halt controller firmware. With
238 * the purpose to stop both driver and firmware, the enduser can
239 * obtain a ring buffer from controller UART.
240 */
241void
242mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc)
243{
244 u32 doorbell;
245
246 if (!ioc->fwfault_debug)
247 return;
248
249 dump_stack();
250
251 doorbell = readl(&ioc->chip->Doorbell);
252 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
253 mpt2sas_base_fault_info(ioc , doorbell);
254 else {
255 writel(0xC0FFEE00, &ioc->chip->Doorbell);
256 printk(MPT2SAS_ERR_FMT "Firmware is halted due to command "
257 "timeout\n", ioc->name);
258 }
259
260 panic("panic in %s\n", __func__);
261}
262
263#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
264/**
265 * _base_sas_ioc_info - verbose translation of the ioc status
266 * @ioc: per adapter object
267 * @mpi_reply: reply mf payload returned from firmware
268 * @request_hdr: request mf
269 *
270 * Return nothing.
271 */
272static void
273_base_sas_ioc_info(struct MPT2SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
274 MPI2RequestHeader_t *request_hdr)
275{
276 u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
277 MPI2_IOCSTATUS_MASK;
278 char *desc = NULL;
279 u16 frame_sz;
280 char *func_str = NULL;
281
282 /* SCSI_IO, RAID_PASS are handled from _scsih_scsi_ioc_info */
283 if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
284 request_hdr->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
285 request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION)
286 return;
287
288 switch (ioc_status) {
289
290/****************************************************************************
291* Common IOCStatus values for all replies
292****************************************************************************/
293
294 case MPI2_IOCSTATUS_INVALID_FUNCTION:
295 desc = "invalid function";
296 break;
297 case MPI2_IOCSTATUS_BUSY:
298 desc = "busy";
299 break;
300 case MPI2_IOCSTATUS_INVALID_SGL:
301 desc = "invalid sgl";
302 break;
303 case MPI2_IOCSTATUS_INTERNAL_ERROR:
304 desc = "internal error";
305 break;
306 case MPI2_IOCSTATUS_INVALID_VPID:
307 desc = "invalid vpid";
308 break;
309 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
310 desc = "insufficient resources";
311 break;
312 case MPI2_IOCSTATUS_INVALID_FIELD:
313 desc = "invalid field";
314 break;
315 case MPI2_IOCSTATUS_INVALID_STATE:
316 desc = "invalid state";
317 break;
318 case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
319 desc = "op state not supported";
320 break;
321
322/****************************************************************************
323* Config IOCStatus values
324****************************************************************************/
325
326 case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
327 desc = "config invalid action";
328 break;
329 case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
330 desc = "config invalid type";
331 break;
332 case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
333 desc = "config invalid page";
334 break;
335 case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
336 desc = "config invalid data";
337 break;
338 case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
339 desc = "config no defaults";
340 break;
341 case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
342 desc = "config cant commit";
343 break;
344
345/****************************************************************************
346* SCSI IO Reply
347****************************************************************************/
348
349 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
350 case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
351 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
352 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
353 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
354 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
355 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
356 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
357 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
358 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
359 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
360 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
361 break;
362
363/****************************************************************************
364* For use by SCSI Initiator and SCSI Target end-to-end data protection
365****************************************************************************/
366
367 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
368 desc = "eedp guard error";
369 break;
370 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
371 desc = "eedp ref tag error";
372 break;
373 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
374 desc = "eedp app tag error";
375 break;
376
377/****************************************************************************
378* SCSI Target values
379****************************************************************************/
380
381 case MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX:
382 desc = "target invalid io index";
383 break;
384 case MPI2_IOCSTATUS_TARGET_ABORTED:
385 desc = "target aborted";
386 break;
387 case MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE:
388 desc = "target no conn retryable";
389 break;
390 case MPI2_IOCSTATUS_TARGET_NO_CONNECTION:
391 desc = "target no connection";
392 break;
393 case MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH:
394 desc = "target xfer count mismatch";
395 break;
396 case MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR:
397 desc = "target data offset error";
398 break;
399 case MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA:
400 desc = "target too much write data";
401 break;
402 case MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT:
403 desc = "target iu too short";
404 break;
405 case MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT:
406 desc = "target ack nak timeout";
407 break;
408 case MPI2_IOCSTATUS_TARGET_NAK_RECEIVED:
409 desc = "target nak received";
410 break;
411
412/****************************************************************************
413* Serial Attached SCSI values
414****************************************************************************/
415
416 case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
417 desc = "smp request failed";
418 break;
419 case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
420 desc = "smp data overrun";
421 break;
422
423/****************************************************************************
424* Diagnostic Buffer Post / Diagnostic Release values
425****************************************************************************/
426
427 case MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED:
428 desc = "diagnostic released";
429 break;
430 default:
431 break;
432 }
433
434 if (!desc)
435 return;
436
437 switch (request_hdr->Function) {
438 case MPI2_FUNCTION_CONFIG:
439 frame_sz = sizeof(Mpi2ConfigRequest_t) + ioc->sge_size;
440 func_str = "config_page";
441 break;
442 case MPI2_FUNCTION_SCSI_TASK_MGMT:
443 frame_sz = sizeof(Mpi2SCSITaskManagementRequest_t);
444 func_str = "task_mgmt";
445 break;
446 case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
447 frame_sz = sizeof(Mpi2SasIoUnitControlRequest_t);
448 func_str = "sas_iounit_ctl";
449 break;
450 case MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
451 frame_sz = sizeof(Mpi2SepRequest_t);
452 func_str = "enclosure";
453 break;
454 case MPI2_FUNCTION_IOC_INIT:
455 frame_sz = sizeof(Mpi2IOCInitRequest_t);
456 func_str = "ioc_init";
457 break;
458 case MPI2_FUNCTION_PORT_ENABLE:
459 frame_sz = sizeof(Mpi2PortEnableRequest_t);
460 func_str = "port_enable";
461 break;
462 case MPI2_FUNCTION_SMP_PASSTHROUGH:
463 frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size;
464 func_str = "smp_passthru";
465 break;
466 default:
467 frame_sz = 32;
468 func_str = "unknown";
469 break;
470 }
471
472 printk(MPT2SAS_WARN_FMT "ioc_status: %s(0x%04x), request(0x%p),"
473 " (%s)\n", ioc->name, desc, ioc_status, request_hdr, func_str);
474
475 _debug_dump_mf(request_hdr, frame_sz/4);
476}
477
478/**
479 * _base_display_event_data - verbose translation of firmware asyn events
480 * @ioc: per adapter object
481 * @mpi_reply: reply mf payload returned from firmware
482 *
483 * Return nothing.
484 */
485static void
486_base_display_event_data(struct MPT2SAS_ADAPTER *ioc,
487 Mpi2EventNotificationReply_t *mpi_reply)
488{
489 char *desc = NULL;
490 u16 event;
491
492 if (!(ioc->logging_level & MPT_DEBUG_EVENTS))
493 return;
494
495 event = le16_to_cpu(mpi_reply->Event);
496
497 switch (event) {
498 case MPI2_EVENT_LOG_DATA:
499 desc = "Log Data";
500 break;
501 case MPI2_EVENT_STATE_CHANGE:
502 desc = "Status Change";
503 break;
504 case MPI2_EVENT_HARD_RESET_RECEIVED:
505 desc = "Hard Reset Received";
506 break;
507 case MPI2_EVENT_EVENT_CHANGE:
508 desc = "Event Change";
509 break;
510 case MPI2_EVENT_TASK_SET_FULL:
511 desc = "Task Set Full";
512 break;
513 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
514 desc = "Device Status Change";
515 break;
516 case MPI2_EVENT_IR_OPERATION_STATUS:
517 desc = "IR Operation Status";
518 break;
519 case MPI2_EVENT_SAS_DISCOVERY:
520 desc = "Discovery";
521 break;
522 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
523 desc = "SAS Broadcast Primitive";
524 break;
525 case MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
526 desc = "SAS Init Device Status Change";
527 break;
528 case MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW:
529 desc = "SAS Init Table Overflow";
530 break;
531 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
532 desc = "SAS Topology Change List";
533 break;
534 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
535 desc = "SAS Enclosure Device Status Change";
536 break;
537 case MPI2_EVENT_IR_VOLUME:
538 desc = "IR Volume";
539 break;
540 case MPI2_EVENT_IR_PHYSICAL_DISK:
541 desc = "IR Physical Disk";
542 break;
543 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
544 desc = "IR Configuration Change List";
545 break;
546 case MPI2_EVENT_LOG_ENTRY_ADDED:
547 desc = "Log Entry Added";
548 break;
549 }
550
551 if (!desc)
552 return;
553
554 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, desc);
555}
556#endif
557
558/**
559 * _base_sas_log_info - verbose translation of firmware log info
560 * @ioc: per adapter object
561 * @log_info: log info
562 *
563 * Return nothing.
564 */
565static void
566_base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info)
567{
568 union loginfo_type {
569 u32 loginfo;
570 struct {
571 u32 subcode:16;
572 u32 code:8;
573 u32 originator:4;
574 u32 bus_type:4;
575 } dw;
576 };
577 union loginfo_type sas_loginfo;
578 char *originator_str = NULL;
579
580 sas_loginfo.loginfo = log_info;
581 if (sas_loginfo.dw.bus_type != 3 /*SAS*/)
582 return;
583
584 /* each nexus loss loginfo */
585 if (log_info == 0x31170000)
586 return;
587
588 /* eat the loginfos associated with task aborts */
589 if (ioc->ignore_loginfos && (log_info == 30050000 || log_info ==
590 0x31140000 || log_info == 0x31130000))
591 return;
592
593 switch (sas_loginfo.dw.originator) {
594 case 0:
595 originator_str = "IOP";
596 break;
597 case 1:
598 originator_str = "PL";
599 break;
600 case 2:
601 originator_str = "IR";
602 break;
603 }
604
605 printk(MPT2SAS_WARN_FMT "log_info(0x%08x): originator(%s), "
606 "code(0x%02x), sub_code(0x%04x)\n", ioc->name, log_info,
607 originator_str, sas_loginfo.dw.code,
608 sas_loginfo.dw.subcode);
609}
610
611/**
612 * _base_display_reply_info -
613 * @ioc: per adapter object
614 * @smid: system request message index
615 * @msix_index: MSIX table index supplied by the OS
616 * @reply: reply message frame(lower 32bit addr)
617 *
618 * Return nothing.
619 */
620static void
621_base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
622 u32 reply)
623{
624 MPI2DefaultReply_t *mpi_reply;
625 u16 ioc_status;
626
627 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
628 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
629#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
630 if ((ioc_status & MPI2_IOCSTATUS_MASK) &&
631 (ioc->logging_level & MPT_DEBUG_REPLY)) {
632 _base_sas_ioc_info(ioc , mpi_reply,
633 mpt2sas_base_get_msg_frame(ioc, smid));
634 }
635#endif
636 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
637 _base_sas_log_info(ioc, le32_to_cpu(mpi_reply->IOCLogInfo));
638}
639
640/**
641 * mpt2sas_base_done - base internal command completion routine
642 * @ioc: per adapter object
643 * @smid: system request message index
644 * @msix_index: MSIX table index supplied by the OS
645 * @reply: reply message frame(lower 32bit addr)
646 *
647 * Return 1 meaning mf should be freed from _base_interrupt
648 * 0 means the mf is freed from this function.
649 */
650u8
651mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
652 u32 reply)
653{
654 MPI2DefaultReply_t *mpi_reply;
655
656 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
657 if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK)
658 return 1;
659
660 if (ioc->base_cmds.status == MPT2_CMD_NOT_USED)
661 return 1;
662
663 ioc->base_cmds.status |= MPT2_CMD_COMPLETE;
664 if (mpi_reply) {
665 ioc->base_cmds.status |= MPT2_CMD_REPLY_VALID;
666 memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
667 }
668 ioc->base_cmds.status &= ~MPT2_CMD_PENDING;
669 complete(&ioc->base_cmds.done);
670 return 1;
671}
672
673/**
674 * _base_async_event - main callback handler for firmware asyn events
675 * @ioc: per adapter object
676 * @msix_index: MSIX table index supplied by the OS
677 * @reply: reply message frame(lower 32bit addr)
678 *
679 * Return 1 meaning mf should be freed from _base_interrupt
680 * 0 means the mf is freed from this function.
681 */
682static u8
683_base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply)
684{
685 Mpi2EventNotificationReply_t *mpi_reply;
686 Mpi2EventAckRequest_t *ack_request;
687 u16 smid;
688
689 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
690 if (!mpi_reply)
691 return 1;
692 if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION)
693 return 1;
694#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
695 _base_display_event_data(ioc, mpi_reply);
696#endif
697 if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED))
698 goto out;
699 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
700 if (!smid) {
701 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
702 ioc->name, __func__);
703 goto out;
704 }
705
706 ack_request = mpt2sas_base_get_msg_frame(ioc, smid);
707 memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t));
708 ack_request->Function = MPI2_FUNCTION_EVENT_ACK;
709 ack_request->Event = mpi_reply->Event;
710 ack_request->EventContext = mpi_reply->EventContext;
711 ack_request->VF_ID = 0; /* TODO */
712 ack_request->VP_ID = 0;
713 mpt2sas_base_put_smid_default(ioc, smid);
714
715 out:
716
717 /* scsih callback handler */
718 mpt2sas_scsih_event_callback(ioc, msix_index, reply);
719
720 /* ctl callback handler */
721 mpt2sas_ctl_event_callback(ioc, msix_index, reply);
722
723 return 1;
724}
725
726/**
727 * _base_get_cb_idx - obtain the callback index
728 * @ioc: per adapter object
729 * @smid: system request message index
730 *
731 * Return callback index.
732 */
733static u8
734_base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid)
735{
736 int i;
737 u8 cb_idx = 0xFF;
738
739 if (smid >= ioc->hi_priority_smid) {
740 if (smid < ioc->internal_smid) {
741 i = smid - ioc->hi_priority_smid;
742 cb_idx = ioc->hpr_lookup[i].cb_idx;
743 } else {
744 i = smid - ioc->internal_smid;
745 cb_idx = ioc->internal_lookup[i].cb_idx;
746 }
747 } else {
748 i = smid - 1;
749 cb_idx = ioc->scsi_lookup[i].cb_idx;
750 }
751 return cb_idx;
752}
753
754/**
755 * _base_mask_interrupts - disable interrupts
756 * @ioc: per adapter object
757 *
758 * Disabling ResetIRQ, Reply and Doorbell Interrupts
759 *
760 * Return nothing.
761 */
762static void
763_base_mask_interrupts(struct MPT2SAS_ADAPTER *ioc)
764{
765 u32 him_register;
766
767 ioc->mask_interrupts = 1;
768 him_register = readl(&ioc->chip->HostInterruptMask);
769 him_register |= MPI2_HIM_DIM + MPI2_HIM_RIM + MPI2_HIM_RESET_IRQ_MASK;
770 writel(him_register, &ioc->chip->HostInterruptMask);
771 readl(&ioc->chip->HostInterruptMask);
772}
773
774/**
775 * _base_unmask_interrupts - enable interrupts
776 * @ioc: per adapter object
777 *
778 * Enabling only Reply Interrupts
779 *
780 * Return nothing.
781 */
782static void
783_base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc)
784{
785 u32 him_register;
786
787 him_register = readl(&ioc->chip->HostInterruptMask);
788 him_register &= ~MPI2_HIM_RIM;
789 writel(him_register, &ioc->chip->HostInterruptMask);
790 ioc->mask_interrupts = 0;
791}
792
793union reply_descriptor {
794 u64 word;
795 struct {
796 u32 low;
797 u32 high;
798 } u;
799};
800
801/**
802 * _base_interrupt - MPT adapter (IOC) specific interrupt handler.
803 * @irq: irq number (not used)
804 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
805 * @r: pt_regs pointer (not used)
806 *
807 * Return IRQ_HANDLE if processed, else IRQ_NONE.
808 */
809static irqreturn_t
810_base_interrupt(int irq, void *bus_id)
811{
812 union reply_descriptor rd;
813 u32 completed_cmds;
814 u8 request_desript_type;
815 u16 smid;
816 u8 cb_idx;
817 u32 reply;
818 u8 msix_index;
819 struct MPT2SAS_ADAPTER *ioc = bus_id;
820 Mpi2ReplyDescriptorsUnion_t *rpf;
821 u8 rc;
822
823 if (ioc->mask_interrupts)
824 return IRQ_NONE;
825
826 rpf = &ioc->reply_post_free[ioc->reply_post_host_index];
827 request_desript_type = rpf->Default.ReplyFlags
828 & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
829 if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
830 return IRQ_NONE;
831
832 completed_cmds = 0;
833 do {
834 rd.word = rpf->Words;
835 if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
836 goto out;
837 reply = 0;
838 cb_idx = 0xFF;
839 smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1);
840 msix_index = rpf->Default.MSIxIndex;
841 if (request_desript_type ==
842 MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
843 reply = le32_to_cpu
844 (rpf->AddressReply.ReplyFrameAddress);
845 } else if (request_desript_type ==
846 MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER)
847 goto next;
848 else if (request_desript_type ==
849 MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS)
850 goto next;
851 if (smid)
852 cb_idx = _base_get_cb_idx(ioc, smid);
853 if (smid && cb_idx != 0xFF) {
854 rc = mpt_callbacks[cb_idx](ioc, smid, msix_index,
855 reply);
856 if (reply)
857 _base_display_reply_info(ioc, smid, msix_index,
858 reply);
859 if (rc)
860 mpt2sas_base_free_smid(ioc, smid);
861 }
862 if (!smid)
863 _base_async_event(ioc, msix_index, reply);
864
865 /* reply free queue handling */
866 if (reply) {
867 ioc->reply_free_host_index =
868 (ioc->reply_free_host_index ==
869 (ioc->reply_free_queue_depth - 1)) ?
870 0 : ioc->reply_free_host_index + 1;
871 ioc->reply_free[ioc->reply_free_host_index] =
872 cpu_to_le32(reply);
873 wmb();
874 writel(ioc->reply_free_host_index,
875 &ioc->chip->ReplyFreeHostIndex);
876 }
877
878 next:
879
880 rpf->Words = ULLONG_MAX;
881 ioc->reply_post_host_index = (ioc->reply_post_host_index ==
882 (ioc->reply_post_queue_depth - 1)) ? 0 :
883 ioc->reply_post_host_index + 1;
884 request_desript_type =
885 ioc->reply_post_free[ioc->reply_post_host_index].Default.
886 ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
887 completed_cmds++;
888 if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
889 goto out;
890 if (!ioc->reply_post_host_index)
891 rpf = ioc->reply_post_free;
892 else
893 rpf++;
894 } while (1);
895
896 out:
897
898 if (!completed_cmds)
899 return IRQ_NONE;
900
901 wmb();
902 writel(ioc->reply_post_host_index, &ioc->chip->ReplyPostHostIndex);
903 return IRQ_HANDLED;
904}
905
906/**
907 * mpt2sas_base_release_callback_handler - clear interupt callback handler
908 * @cb_idx: callback index
909 *
910 * Return nothing.
911 */
912void
913mpt2sas_base_release_callback_handler(u8 cb_idx)
914{
915 mpt_callbacks[cb_idx] = NULL;
916}
917
918/**
919 * mpt2sas_base_register_callback_handler - obtain index for the interrupt callback handler
920 * @cb_func: callback function
921 *
922 * Returns cb_func.
923 */
924u8
925mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func)
926{
927 u8 cb_idx;
928
929 for (cb_idx = MPT_MAX_CALLBACKS-1; cb_idx; cb_idx--)
930 if (mpt_callbacks[cb_idx] == NULL)
931 break;
932
933 mpt_callbacks[cb_idx] = cb_func;
934 return cb_idx;
935}
936
937/**
938 * mpt2sas_base_initialize_callback_handler - initialize the interrupt callback handler
939 *
940 * Return nothing.
941 */
942void
943mpt2sas_base_initialize_callback_handler(void)
944{
945 u8 cb_idx;
946
947 for (cb_idx = 0; cb_idx < MPT_MAX_CALLBACKS; cb_idx++)
948 mpt2sas_base_release_callback_handler(cb_idx);
949}
950
951/**
952 * mpt2sas_base_build_zero_len_sge - build zero length sg entry
953 * @ioc: per adapter object
954 * @paddr: virtual address for SGE
955 *
956 * Create a zero length scatter gather entry to insure the IOCs hardware has
957 * something to use if the target device goes brain dead and tries
958 * to send data even when none is asked for.
959 *
960 * Return nothing.
961 */
962void
963mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr)
964{
965 u32 flags_length = (u32)((MPI2_SGE_FLAGS_LAST_ELEMENT |
966 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST |
967 MPI2_SGE_FLAGS_SIMPLE_ELEMENT) <<
968 MPI2_SGE_FLAGS_SHIFT);
969 ioc->base_add_sg_single(paddr, flags_length, -1);
970}
971
972/**
973 * _base_add_sg_single_32 - Place a simple 32 bit SGE at address pAddr.
974 * @paddr: virtual address for SGE
975 * @flags_length: SGE flags and data transfer length
976 * @dma_addr: Physical address
977 *
978 * Return nothing.
979 */
980static void
981_base_add_sg_single_32(void *paddr, u32 flags_length, dma_addr_t dma_addr)
982{
983 Mpi2SGESimple32_t *sgel = paddr;
984
985 flags_length |= (MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
986 MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
987 sgel->FlagsLength = cpu_to_le32(flags_length);
988 sgel->Address = cpu_to_le32(dma_addr);
989}
990
991
992/**
993 * _base_add_sg_single_64 - Place a simple 64 bit SGE at address pAddr.
994 * @paddr: virtual address for SGE
995 * @flags_length: SGE flags and data transfer length
996 * @dma_addr: Physical address
997 *
998 * Return nothing.
999 */
1000static void
1001_base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr)
1002{
1003 Mpi2SGESimple64_t *sgel = paddr;
1004
1005 flags_length |= (MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
1006 MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
1007 sgel->FlagsLength = cpu_to_le32(flags_length);
1008 sgel->Address = cpu_to_le64(dma_addr);
1009}
1010
1011#define convert_to_kb(x) ((x) << (PAGE_SHIFT - 10))
1012
1013/**
1014 * _base_config_dma_addressing - set dma addressing
1015 * @ioc: per adapter object
1016 * @pdev: PCI device struct
1017 *
1018 * Returns 0 for success, non-zero for failure.
1019 */
1020static int
1021_base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev)
1022{
1023 struct sysinfo s;
1024 char *desc = NULL;
1025
1026 if (sizeof(dma_addr_t) > 4) {
1027 const uint64_t required_mask =
1028 dma_get_required_mask(&pdev->dev);
1029 if ((required_mask > DMA_BIT_MASK(32)) && !pci_set_dma_mask(pdev,
1030 DMA_BIT_MASK(64)) && !pci_set_consistent_dma_mask(pdev,
1031 DMA_BIT_MASK(64))) {
1032 ioc->base_add_sg_single = &_base_add_sg_single_64;
1033 ioc->sge_size = sizeof(Mpi2SGESimple64_t);
1034 desc = "64";
1035 goto out;
1036 }
1037 }
1038
1039 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
1040 && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
1041 ioc->base_add_sg_single = &_base_add_sg_single_32;
1042 ioc->sge_size = sizeof(Mpi2SGESimple32_t);
1043 desc = "32";
1044 } else
1045 return -ENODEV;
1046
1047 out:
1048 si_meminfo(&s);
1049 printk(MPT2SAS_INFO_FMT "%s BIT PCI BUS DMA ADDRESSING SUPPORTED, "
1050 "total mem (%ld kB)\n", ioc->name, desc, convert_to_kb(s.totalram));
1051
1052 return 0;
1053}
1054
1055/**
1056 * _base_save_msix_table - backup msix vector table
1057 * @ioc: per adapter object
1058 *
1059 * This address an errata where diag reset clears out the table
1060 */
1061static void
1062_base_save_msix_table(struct MPT2SAS_ADAPTER *ioc)
1063{
1064 int i;
1065
1066 if (!ioc->msix_enable || ioc->msix_table_backup == NULL)
1067 return;
1068
1069 for (i = 0; i < ioc->msix_vector_count; i++)
1070 ioc->msix_table_backup[i] = ioc->msix_table[i];
1071}
1072
1073/**
1074 * _base_restore_msix_table - this restores the msix vector table
1075 * @ioc: per adapter object
1076 *
1077 */
1078static void
1079_base_restore_msix_table(struct MPT2SAS_ADAPTER *ioc)
1080{
1081 int i;
1082
1083 if (!ioc->msix_enable || ioc->msix_table_backup == NULL)
1084 return;
1085
1086 for (i = 0; i < ioc->msix_vector_count; i++)
1087 ioc->msix_table[i] = ioc->msix_table_backup[i];
1088}
1089
1090/**
1091 * _base_check_enable_msix - checks MSIX capabable.
1092 * @ioc: per adapter object
1093 *
1094 * Check to see if card is capable of MSIX, and set number
1095 * of avaliable msix vectors
1096 */
1097static int
1098_base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
1099{
1100 int base;
1101 u16 message_control;
1102 u32 msix_table_offset;
1103
1104 base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
1105 if (!base) {
1106 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not "
1107 "supported\n", ioc->name));
1108 return -EINVAL;
1109 }
1110
1111 /* get msix vector count */
1112 pci_read_config_word(ioc->pdev, base + 2, &message_control);
1113 ioc->msix_vector_count = (message_control & 0x3FF) + 1;
1114
1115 /* get msix table */
1116 pci_read_config_dword(ioc->pdev, base + 4, &msix_table_offset);
1117 msix_table_offset &= 0xFFFFFFF8;
1118 ioc->msix_table = (u32 *)((void *)ioc->chip + msix_table_offset);
1119
1120 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, "
1121 "vector_count(%d), table_offset(0x%08x), table(%p)\n", ioc->name,
1122 ioc->msix_vector_count, msix_table_offset, ioc->msix_table));
1123 return 0;
1124}
1125
1126/**
1127 * _base_disable_msix - disables msix
1128 * @ioc: per adapter object
1129 *
1130 */
1131static void
1132_base_disable_msix(struct MPT2SAS_ADAPTER *ioc)
1133{
1134 if (ioc->msix_enable) {
1135 pci_disable_msix(ioc->pdev);
1136 kfree(ioc->msix_table_backup);
1137 ioc->msix_table_backup = NULL;
1138 ioc->msix_enable = 0;
1139 }
1140}
1141
1142/**
1143 * _base_enable_msix - enables msix, failback to io_apic
1144 * @ioc: per adapter object
1145 *
1146 */
1147static int
1148_base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
1149{
1150 struct msix_entry entries;
1151 int r;
1152 u8 try_msix = 0;
1153
1154 if (msix_disable == -1 || msix_disable == 0)
1155 try_msix = 1;
1156
1157 if (!try_msix)
1158 goto try_ioapic;
1159
1160 if (_base_check_enable_msix(ioc) != 0)
1161 goto try_ioapic;
1162
1163 ioc->msix_table_backup = kcalloc(ioc->msix_vector_count,
1164 sizeof(u32), GFP_KERNEL);
1165 if (!ioc->msix_table_backup) {
1166 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation for "
1167 "msix_table_backup failed!!!\n", ioc->name));
1168 goto try_ioapic;
1169 }
1170
1171 memset(&entries, 0, sizeof(struct msix_entry));
1172 r = pci_enable_msix(ioc->pdev, &entries, 1);
1173 if (r) {
1174 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "pci_enable_msix "
1175 "failed (r=%d) !!!\n", ioc->name, r));
1176 goto try_ioapic;
1177 }
1178
1179 r = request_irq(entries.vector, _base_interrupt, IRQF_SHARED,
1180 ioc->name, ioc);
1181 if (r) {
1182 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "unable to allocate "
1183 "interrupt %d !!!\n", ioc->name, entries.vector));
1184 pci_disable_msix(ioc->pdev);
1185 goto try_ioapic;
1186 }
1187
1188 ioc->pci_irq = entries.vector;
1189 ioc->msix_enable = 1;
1190 return 0;
1191
1192/* failback to io_apic interrupt routing */
1193 try_ioapic:
1194
1195 r = request_irq(ioc->pdev->irq, _base_interrupt, IRQF_SHARED,
1196 ioc->name, ioc);
1197 if (r) {
1198 printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n",
1199 ioc->name, ioc->pdev->irq);
1200 r = -EBUSY;
1201 goto out_fail;
1202 }
1203
1204 ioc->pci_irq = ioc->pdev->irq;
1205 return 0;
1206
1207 out_fail:
1208 return r;
1209}
1210
1211/**
1212 * mpt2sas_base_map_resources - map in controller resources (io/irq/memap)
1213 * @ioc: per adapter object
1214 *
1215 * Returns 0 for success, non-zero for failure.
1216 */
1217int
1218mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
1219{
1220 struct pci_dev *pdev = ioc->pdev;
1221 u32 memap_sz;
1222 u32 pio_sz;
1223 int i, r = 0;
1224 u64 pio_chip = 0;
1225 u64 chip_phys = 0;
1226
1227 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n",
1228 ioc->name, __func__));
1229
1230 ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
1231 if (pci_enable_device_mem(pdev)) {
1232 printk(MPT2SAS_WARN_FMT "pci_enable_device_mem: "
1233 "failed\n", ioc->name);
1234 return -ENODEV;
1235 }
1236
1237
1238 if (pci_request_selected_regions(pdev, ioc->bars,
1239 MPT2SAS_DRIVER_NAME)) {
1240 printk(MPT2SAS_WARN_FMT "pci_request_selected_regions: "
1241 "failed\n", ioc->name);
1242 r = -ENODEV;
1243 goto out_fail;
1244 }
1245
1246 pci_set_master(pdev);
1247
1248 if (_base_config_dma_addressing(ioc, pdev) != 0) {
1249 printk(MPT2SAS_WARN_FMT "no suitable DMA mask for %s\n",
1250 ioc->name, pci_name(pdev));
1251 r = -ENODEV;
1252 goto out_fail;
1253 }
1254
1255 for (i = 0, memap_sz = 0, pio_sz = 0 ; i < DEVICE_COUNT_RESOURCE; i++) {
1256 if (pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE_IO) {
1257 if (pio_sz)
1258 continue;
1259 pio_chip = (u64)pci_resource_start(pdev, i);
1260 pio_sz = pci_resource_len(pdev, i);
1261 } else {
1262 if (memap_sz)
1263 continue;
1264 ioc->chip_phys = pci_resource_start(pdev, i);
1265 chip_phys = (u64)ioc->chip_phys;
1266 memap_sz = pci_resource_len(pdev, i);
1267 ioc->chip = ioremap(ioc->chip_phys, memap_sz);
1268 if (ioc->chip == NULL) {
1269 printk(MPT2SAS_ERR_FMT "unable to map adapter "
1270 "memory!\n", ioc->name);
1271 r = -EINVAL;
1272 goto out_fail;
1273 }
1274 }
1275 }
1276
1277 _base_mask_interrupts(ioc);
1278 r = _base_enable_msix(ioc);
1279 if (r)
1280 goto out_fail;
1281
1282 printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n",
1283 ioc->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
1284 "IO-APIC enabled"), ioc->pci_irq);
1285 printk(MPT2SAS_INFO_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n",
1286 ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz);
1287 printk(MPT2SAS_INFO_FMT "ioport(0x%016llx), size(%d)\n",
1288 ioc->name, (unsigned long long)pio_chip, pio_sz);
1289
1290 return 0;
1291
1292 out_fail:
1293 if (ioc->chip_phys)
1294 iounmap(ioc->chip);
1295 ioc->chip_phys = 0;
1296 ioc->pci_irq = -1;
1297 pci_release_selected_regions(ioc->pdev, ioc->bars);
1298 pci_disable_device(pdev);
1299 return r;
1300}
1301
1302/**
1303 * mpt2sas_base_get_msg_frame - obtain request mf pointer
1304 * @ioc: per adapter object
1305 * @smid: system request message index(smid zero is invalid)
1306 *
1307 * Returns virt pointer to message frame.
1308 */
1309void *
1310mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1311{
1312 return (void *)(ioc->request + (smid * ioc->request_sz));
1313}
1314
1315/**
1316 * mpt2sas_base_get_sense_buffer - obtain a sense buffer assigned to a mf request
1317 * @ioc: per adapter object
1318 * @smid: system request message index
1319 *
1320 * Returns virt pointer to sense buffer.
1321 */
1322void *
1323mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1324{
1325 return (void *)(ioc->sense + ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
1326}
1327
1328/**
1329 * mpt2sas_base_get_sense_buffer_dma - obtain a sense buffer assigned to a mf request
1330 * @ioc: per adapter object
1331 * @smid: system request message index
1332 *
1333 * Returns phys pointer to the low 32bit address of the sense buffer.
1334 */
1335__le32
1336mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1337{
1338 return cpu_to_le32(ioc->sense_dma +
1339 ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
1340}
1341
1342/**
1343 * mpt2sas_base_get_reply_virt_addr - obtain reply frames virt address
1344 * @ioc: per adapter object
1345 * @phys_addr: lower 32 physical addr of the reply
1346 *
1347 * Converts 32bit lower physical addr into a virt address.
1348 */
1349void *
1350mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr)
1351{
1352 if (!phys_addr)
1353 return NULL;
1354 return ioc->reply + (phys_addr - (u32)ioc->reply_dma);
1355}
1356
1357/**
1358 * mpt2sas_base_get_smid - obtain a free smid from internal queue
1359 * @ioc: per adapter object
1360 * @cb_idx: callback index
1361 *
1362 * Returns smid (zero is invalid)
1363 */
1364u16
1365mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx)
1366{
1367 unsigned long flags;
1368 struct request_tracker *request;
1369 u16 smid;
1370
1371 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1372 if (list_empty(&ioc->internal_free_list)) {
1373 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1374 printk(MPT2SAS_ERR_FMT "%s: smid not available\n",
1375 ioc->name, __func__);
1376 return 0;
1377 }
1378
1379 request = list_entry(ioc->internal_free_list.next,
1380 struct request_tracker, tracker_list);
1381 request->cb_idx = cb_idx;
1382 smid = request->smid;
1383 list_del(&request->tracker_list);
1384 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1385 return smid;
1386}
1387
1388/**
1389 * mpt2sas_base_get_smid_scsiio - obtain a free smid from scsiio queue
1390 * @ioc: per adapter object
1391 * @cb_idx: callback index
1392 * @scmd: pointer to scsi command object
1393 *
1394 * Returns smid (zero is invalid)
1395 */
1396u16
1397mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx,
1398 struct scsi_cmnd *scmd)
1399{
1400 unsigned long flags;
1401 struct request_tracker *request;
1402 u16 smid;
1403
1404 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1405 if (list_empty(&ioc->free_list)) {
1406 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1407 printk(MPT2SAS_ERR_FMT "%s: smid not available\n",
1408 ioc->name, __func__);
1409 return 0;
1410 }
1411
1412 request = list_entry(ioc->free_list.next,
1413 struct request_tracker, tracker_list);
1414 request->scmd = scmd;
1415 request->cb_idx = cb_idx;
1416 smid = request->smid;
1417 list_del(&request->tracker_list);
1418 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1419 return smid;
1420}
1421
1422/**
1423 * mpt2sas_base_get_smid_hpr - obtain a free smid from hi-priority queue
1424 * @ioc: per adapter object
1425 * @cb_idx: callback index
1426 *
1427 * Returns smid (zero is invalid)
1428 */
1429u16
1430mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx)
1431{
1432 unsigned long flags;
1433 struct request_tracker *request;
1434 u16 smid;
1435
1436 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1437 if (list_empty(&ioc->hpr_free_list)) {
1438 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1439 return 0;
1440 }
1441
1442 request = list_entry(ioc->hpr_free_list.next,
1443 struct request_tracker, tracker_list);
1444 request->cb_idx = cb_idx;
1445 smid = request->smid;
1446 list_del(&request->tracker_list);
1447 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1448 return smid;
1449}
1450
1451
1452/**
1453 * mpt2sas_base_free_smid - put smid back on free_list
1454 * @ioc: per adapter object
1455 * @smid: system request message index
1456 *
1457 * Return nothing.
1458 */
1459void
1460mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1461{
1462 unsigned long flags;
1463 int i;
1464
1465 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1466 if (smid >= ioc->hi_priority_smid) {
1467 if (smid < ioc->internal_smid) {
1468 /* hi-priority */
1469 i = smid - ioc->hi_priority_smid;
1470 ioc->hpr_lookup[i].cb_idx = 0xFF;
1471 list_add_tail(&ioc->hpr_lookup[i].tracker_list,
1472 &ioc->hpr_free_list);
1473 } else {
1474 /* internal queue */
1475 i = smid - ioc->internal_smid;
1476 ioc->internal_lookup[i].cb_idx = 0xFF;
1477 list_add_tail(&ioc->internal_lookup[i].tracker_list,
1478 &ioc->internal_free_list);
1479 }
1480 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1481 return;
1482 }
1483
1484 /* scsiio queue */
1485 i = smid - 1;
1486 ioc->scsi_lookup[i].cb_idx = 0xFF;
1487 ioc->scsi_lookup[i].scmd = NULL;
1488 list_add_tail(&ioc->scsi_lookup[i].tracker_list,
1489 &ioc->free_list);
1490 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1491
1492 /*
1493 * See _wait_for_commands_to_complete() call with regards to this code.
1494 */
1495 if (ioc->shost_recovery && ioc->pending_io_count) {
1496 if (ioc->pending_io_count == 1)
1497 wake_up(&ioc->reset_wq);
1498 ioc->pending_io_count--;
1499 }
1500}
1501
1502/**
1503 * _base_writeq - 64 bit write to MMIO
1504 * @ioc: per adapter object
1505 * @b: data payload
1506 * @addr: address in MMIO space
1507 * @writeq_lock: spin lock
1508 *
1509 * Glue for handling an atomic 64 bit word to MMIO. This special handling takes
1510 * care of 32 bit environment where its not quarenteed to send the entire word
1511 * in one transfer.
1512 */
1513#ifndef writeq
1514static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
1515 spinlock_t *writeq_lock)
1516{
1517 unsigned long flags;
1518 __u64 data_out = cpu_to_le64(b);
1519
1520 spin_lock_irqsave(writeq_lock, flags);
1521 writel((u32)(data_out), addr);
1522 writel((u32)(data_out >> 32), (addr + 4));
1523 spin_unlock_irqrestore(writeq_lock, flags);
1524}
1525#else
1526static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
1527 spinlock_t *writeq_lock)
1528{
1529 writeq(cpu_to_le64(b), addr);
1530}
1531#endif
1532
1533/**
1534 * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware
1535 * @ioc: per adapter object
1536 * @smid: system request message index
1537 * @handle: device handle
1538 *
1539 * Return nothing.
1540 */
1541void
1542mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u16 handle)
1543{
1544 Mpi2RequestDescriptorUnion_t descriptor;
1545 u64 *request = (u64 *)&descriptor;
1546
1547
1548 descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
1549 descriptor.SCSIIO.MSIxIndex = 0; /* TODO */
1550 descriptor.SCSIIO.SMID = cpu_to_le16(smid);
1551 descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
1552 descriptor.SCSIIO.LMID = 0;
1553 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1554 &ioc->scsi_lookup_lock);
1555}
1556
1557
1558/**
1559 * mpt2sas_base_put_smid_hi_priority - send Task Managment request to firmware
1560 * @ioc: per adapter object
1561 * @smid: system request message index
1562 *
1563 * Return nothing.
1564 */
1565void
1566mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1567{
1568 Mpi2RequestDescriptorUnion_t descriptor;
1569 u64 *request = (u64 *)&descriptor;
1570
1571 descriptor.HighPriority.RequestFlags =
1572 MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
1573 descriptor.HighPriority.MSIxIndex = 0; /* TODO */
1574 descriptor.HighPriority.SMID = cpu_to_le16(smid);
1575 descriptor.HighPriority.LMID = 0;
1576 descriptor.HighPriority.Reserved1 = 0;
1577 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1578 &ioc->scsi_lookup_lock);
1579}
1580
1581/**
1582 * mpt2sas_base_put_smid_default - Default, primarily used for config pages
1583 * @ioc: per adapter object
1584 * @smid: system request message index
1585 *
1586 * Return nothing.
1587 */
1588void
1589mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1590{
1591 Mpi2RequestDescriptorUnion_t descriptor;
1592 u64 *request = (u64 *)&descriptor;
1593
1594 descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1595 descriptor.Default.MSIxIndex = 0; /* TODO */
1596 descriptor.Default.SMID = cpu_to_le16(smid);
1597 descriptor.Default.LMID = 0;
1598 descriptor.Default.DescriptorTypeDependent = 0;
1599 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1600 &ioc->scsi_lookup_lock);
1601}
1602
1603/**
1604 * mpt2sas_base_put_smid_target_assist - send Target Assist/Status to firmware
1605 * @ioc: per adapter object
1606 * @smid: system request message index
1607 * @io_index: value used to track the IO
1608 *
1609 * Return nothing.
1610 */
1611void
1612mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
1613 u16 io_index)
1614{
1615 Mpi2RequestDescriptorUnion_t descriptor;
1616 u64 *request = (u64 *)&descriptor;
1617
1618 descriptor.SCSITarget.RequestFlags =
1619 MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET;
1620 descriptor.SCSITarget.MSIxIndex = 0; /* TODO */
1621 descriptor.SCSITarget.SMID = cpu_to_le16(smid);
1622 descriptor.SCSITarget.LMID = 0;
1623 descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index);
1624 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1625 &ioc->scsi_lookup_lock);
1626}
1627
1628/**
1629 * _base_display_dell_branding - Disply branding string
1630 * @ioc: per adapter object
1631 *
1632 * Return nothing.
1633 */
1634static void
1635_base_display_dell_branding(struct MPT2SAS_ADAPTER *ioc)
1636{
1637 char dell_branding[MPT2SAS_DELL_BRANDING_SIZE];
1638
1639 if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_DELL)
1640 return;
1641
1642 memset(dell_branding, 0, MPT2SAS_DELL_BRANDING_SIZE);
1643 switch (ioc->pdev->subsystem_device) {
1644 case MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID:
1645 strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING,
1646 MPT2SAS_DELL_BRANDING_SIZE - 1);
1647 break;
1648 case MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID:
1649 strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING,
1650 MPT2SAS_DELL_BRANDING_SIZE - 1);
1651 break;
1652 case MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID:
1653 strncpy(dell_branding,
1654 MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING,
1655 MPT2SAS_DELL_BRANDING_SIZE - 1);
1656 break;
1657 case MPT2SAS_DELL_PERC_H200_MODULAR_SSDID:
1658 strncpy(dell_branding,
1659 MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING,
1660 MPT2SAS_DELL_BRANDING_SIZE - 1);
1661 break;
1662 case MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID:
1663 strncpy(dell_branding,
1664 MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING,
1665 MPT2SAS_DELL_BRANDING_SIZE - 1);
1666 break;
1667 case MPT2SAS_DELL_PERC_H200_SSDID:
1668 strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_BRANDING,
1669 MPT2SAS_DELL_BRANDING_SIZE - 1);
1670 break;
1671 case MPT2SAS_DELL_6GBPS_SAS_SSDID:
1672 strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_BRANDING,
1673 MPT2SAS_DELL_BRANDING_SIZE - 1);
1674 break;
1675 default:
1676 sprintf(dell_branding, "0x%4X", ioc->pdev->subsystem_device);
1677 break;
1678 }
1679
1680 printk(MPT2SAS_INFO_FMT "%s: Vendor(0x%04X), Device(0x%04X),"
1681 " SSVID(0x%04X), SSDID(0x%04X)\n", ioc->name, dell_branding,
1682 ioc->pdev->vendor, ioc->pdev->device, ioc->pdev->subsystem_vendor,
1683 ioc->pdev->subsystem_device);
1684}
1685
1686/**
1687 * _base_display_ioc_capabilities - Disply IOC's capabilities.
1688 * @ioc: per adapter object
1689 *
1690 * Return nothing.
1691 */
1692static void
1693_base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
1694{
1695 int i = 0;
1696 char desc[16];
1697 u8 revision;
1698 u32 iounit_pg1_flags;
1699
1700 pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision);
1701 strncpy(desc, ioc->manu_pg0.ChipName, 16);
1702 printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "
1703 "ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n",
1704 ioc->name, desc,
1705 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
1706 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
1707 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
1708 ioc->facts.FWVersion.Word & 0x000000FF,
1709 revision,
1710 (ioc->bios_pg3.BiosVersion & 0xFF000000) >> 24,
1711 (ioc->bios_pg3.BiosVersion & 0x00FF0000) >> 16,
1712 (ioc->bios_pg3.BiosVersion & 0x0000FF00) >> 8,
1713 ioc->bios_pg3.BiosVersion & 0x000000FF);
1714
1715 _base_display_dell_branding(ioc);
1716
1717 printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name);
1718
1719 if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) {
1720 printk("Initiator");
1721 i++;
1722 }
1723
1724 if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET) {
1725 printk("%sTarget", i ? "," : "");
1726 i++;
1727 }
1728
1729 i = 0;
1730 printk("), ");
1731 printk("Capabilities=(");
1732
1733 if (ioc->facts.IOCCapabilities &
1734 MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
1735 printk("Raid");
1736 i++;
1737 }
1738
1739 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) {
1740 printk("%sTLR", i ? "," : "");
1741 i++;
1742 }
1743
1744 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_MULTICAST) {
1745 printk("%sMulticast", i ? "," : "");
1746 i++;
1747 }
1748
1749 if (ioc->facts.IOCCapabilities &
1750 MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET) {
1751 printk("%sBIDI Target", i ? "," : "");
1752 i++;
1753 }
1754
1755 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) {
1756 printk("%sEEDP", i ? "," : "");
1757 i++;
1758 }
1759
1760 if (ioc->facts.IOCCapabilities &
1761 MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) {
1762 printk("%sSnapshot Buffer", i ? "," : "");
1763 i++;
1764 }
1765
1766 if (ioc->facts.IOCCapabilities &
1767 MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) {
1768 printk("%sDiag Trace Buffer", i ? "," : "");
1769 i++;
1770 }
1771
1772 if (ioc->facts.IOCCapabilities &
1773 MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) {
1774 printk(KERN_INFO "%sDiag Extended Buffer", i ? "," : "");
1775 i++;
1776 }
1777
1778 if (ioc->facts.IOCCapabilities &
1779 MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) {
1780 printk("%sTask Set Full", i ? "," : "");
1781 i++;
1782 }
1783
1784 iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
1785 if (!(iounit_pg1_flags & MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE)) {
1786 printk("%sNCQ", i ? "," : "");
1787 i++;
1788 }
1789
1790 printk(")\n");
1791}
1792
1793/**
1794 * _base_static_config_pages - static start of day config pages
1795 * @ioc: per adapter object
1796 *
1797 * Return nothing.
1798 */
1799static void
1800_base_static_config_pages(struct MPT2SAS_ADAPTER *ioc)
1801{
1802 Mpi2ConfigReply_t mpi_reply;
1803 u32 iounit_pg1_flags;
1804
1805 mpt2sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0);
1806 if (ioc->ir_firmware)
1807 mpt2sas_config_get_manufacturing_pg10(ioc, &mpi_reply,
1808 &ioc->manu_pg10);
1809 mpt2sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
1810 mpt2sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
1811 mpt2sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8);
1812 mpt2sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0);
1813 mpt2sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
1814 _base_display_ioc_capabilities(ioc);
1815
1816 /*
1817 * Enable task_set_full handling in iounit_pg1 when the
1818 * facts capabilities indicate that its supported.
1819 */
1820 iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
1821 if ((ioc->facts.IOCCapabilities &
1822 MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING))
1823 iounit_pg1_flags &=
1824 ~MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
1825 else
1826 iounit_pg1_flags |=
1827 MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
1828 ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags);
1829 mpt2sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
1830}
1831
1832/**
1833 * _base_release_memory_pools - release memory
1834 * @ioc: per adapter object
1835 *
1836 * Free memory allocated from _base_allocate_memory_pools.
1837 *
1838 * Retur…
Large files files are truncated, but you can click here to view the full file