blob: b995774d601ecb0a3305a76dcd3fb878969095c5 [file] [log] [blame]
adam radford9c915a82010-12-21 13:34:31 -08001/*
2 * Linux MegaRAID driver for SAS based RAID controllers
3 *
Sumit.Saxena@avagotech.come3990652014-11-17 15:24:03 +05304 * Copyright (c) 2009-2013 LSI Corporation
5 * Copyright (c) 2013-2014 Avago Technologies
adam radford9c915a82010-12-21 13:34:31 -08006 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
Sumit.Saxena@avagotech.come3990652014-11-17 15:24:03 +053018 * along with this program. If not, see <http://www.gnu.org/licenses/>.
adam radford9c915a82010-12-21 13:34:31 -080019 *
20 * FILE: megaraid_sas_fusion.c
21 *
Sumit.Saxena@avagotech.come3990652014-11-17 15:24:03 +053022 * Authors: Avago Technologies
adam radford9c915a82010-12-21 13:34:31 -080023 * Sumant Patro
Sumit.Saxena@avagotech.come3990652014-11-17 15:24:03 +053024 * Adam Radford
25 * Kashyap Desai <kashyap.desai@avagotech.com>
26 * Sumit Saxena <sumit.saxena@avagotech.com>
adam radford9c915a82010-12-21 13:34:31 -080027 *
Sumit.Saxena@avagotech.come3990652014-11-17 15:24:03 +053028 * Send feedback to: megaraidlinux.pdl@avagotech.com
adam radford9c915a82010-12-21 13:34:31 -080029 *
Sumit.Saxena@avagotech.come3990652014-11-17 15:24:03 +053030 * Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
31 * San Jose, California 95131
adam radford9c915a82010-12-21 13:34:31 -080032 */
33
34#include <linux/kernel.h>
35#include <linux/types.h>
36#include <linux/pci.h>
37#include <linux/list.h>
38#include <linux/moduleparam.h>
39#include <linux/module.h>
40#include <linux/spinlock.h>
41#include <linux/interrupt.h>
42#include <linux/delay.h>
adam radford9c915a82010-12-21 13:34:31 -080043#include <linux/uio.h>
44#include <linux/uaccess.h>
45#include <linux/fs.h>
46#include <linux/compat.h>
47#include <linux/blkdev.h>
48#include <linux/mutex.h>
49#include <linux/poll.h>
50
51#include <scsi/scsi.h>
52#include <scsi/scsi_cmnd.h>
53#include <scsi/scsi_device.h>
54#include <scsi/scsi_host.h>
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +053055#include <scsi/scsi_dbg.h>
Sumit.Saxena@avagotech.com5765c5b2015-04-23 16:32:09 +053056#include <linux/dmi.h>
adam radford9c915a82010-12-21 13:34:31 -080057
58#include "megaraid_sas_fusion.h"
59#include "megaraid_sas.h"
60
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +053061
adam radford9c915a82010-12-21 13:34:31 -080062extern void megasas_free_cmds(struct megasas_instance *instance);
63extern struct megasas_cmd *megasas_get_cmd(struct megasas_instance
64 *instance);
65extern void
66megasas_complete_cmd(struct megasas_instance *instance,
67 struct megasas_cmd *cmd, u8 alt_status);
adam radford9c915a82010-12-21 13:34:31 -080068int
adam radford229fe472014-03-10 02:51:56 -070069wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd,
70 int seconds);
adam radford9c915a82010-12-21 13:34:31 -080071
72void
73megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd);
74int megasas_alloc_cmds(struct megasas_instance *instance);
75int
76megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs);
77int
78megasas_issue_polled(struct megasas_instance *instance,
79 struct megasas_cmd *cmd);
adam radford53ef2bb2011-02-24 20:56:05 -080080void
81megasas_check_and_restore_queue_depth(struct megasas_instance *instance);
82
adam radford058a8fa2011-10-08 18:14:27 -070083int megasas_transition_to_ready(struct megasas_instance *instance, int ocr);
adam radford9c915a82010-12-21 13:34:31 -080084void megaraid_sas_kill_hba(struct megasas_instance *instance);
85
86extern u32 megasas_dbg_lvl;
adam radford229fe472014-03-10 02:51:56 -070087void megasas_sriov_heartbeat_handler(unsigned long instance_addr);
88int megasas_sriov_start_heartbeat(struct megasas_instance *instance,
89 int initial);
90void megasas_start_timer(struct megasas_instance *instance,
91 struct timer_list *timer,
92 void *fn, unsigned long interval);
93extern struct megasas_mgmt_info megasas_mgmt_info;
adam radfordc007b8b2012-07-17 18:20:24 -070094extern int resetwaittime;
adam radford9c915a82010-12-21 13:34:31 -080095
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +053096
97
adam radford9c915a82010-12-21 13:34:31 -080098/**
99 * megasas_enable_intr_fusion - Enables interrupts
100 * @regs: MFI register set
101 */
102void
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530103megasas_enable_intr_fusion(struct megasas_instance *instance)
adam radford9c915a82010-12-21 13:34:31 -0800104{
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530105 struct megasas_register_set __iomem *regs;
106 regs = instance->reg_set;
Sumit.Saxena@avagotech.comc2ced172015-01-05 20:06:13 +0530107
108 instance->mask_interrupts = 0;
adam radford6497b242011-10-08 18:14:50 -0700109 /* For Thunderbolt/Invader also clear intr on enable */
110 writel(~0, &regs->outbound_intr_status);
111 readl(&regs->outbound_intr_status);
112
adam radford9c915a82010-12-21 13:34:31 -0800113 writel(~MFI_FUSION_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
114
115 /* Dummy readl to force pci flush */
116 readl(&regs->outbound_intr_mask);
117}
118
119/**
120 * megasas_disable_intr_fusion - Disables interrupt
121 * @regs: MFI register set
122 */
123void
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530124megasas_disable_intr_fusion(struct megasas_instance *instance)
adam radford9c915a82010-12-21 13:34:31 -0800125{
126 u32 mask = 0xFFFFFFFF;
127 u32 status;
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530128 struct megasas_register_set __iomem *regs;
129 regs = instance->reg_set;
130 instance->mask_interrupts = 1;
adam radford9c915a82010-12-21 13:34:31 -0800131
132 writel(mask, &regs->outbound_intr_mask);
133 /* Dummy readl to force pci flush */
134 status = readl(&regs->outbound_intr_mask);
135}
136
137int
138megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs)
139{
140 u32 status;
141 /*
142 * Check if it is our interrupt
143 */
144 status = readl(&regs->outbound_intr_status);
145
146 if (status & 1) {
147 writel(status, &regs->outbound_intr_status);
148 readl(&regs->outbound_intr_status);
149 return 1;
150 }
151 if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK))
152 return 0;
153
adam radford9c915a82010-12-21 13:34:31 -0800154 return 1;
155}
156
157/**
158 * megasas_get_cmd_fusion - Get a command from the free pool
159 * @instance: Adapter soft state
160 *
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530161 * Returns a blk_tag indexed mpt frame
adam radford9c915a82010-12-21 13:34:31 -0800162 */
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530163inline struct megasas_cmd_fusion *megasas_get_cmd_fusion(struct megasas_instance
164 *instance, u32 blk_tag)
adam radford9c915a82010-12-21 13:34:31 -0800165{
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530166 struct fusion_context *fusion;
adam radford9c915a82010-12-21 13:34:31 -0800167
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530168 fusion = instance->ctrl_context;
169 return fusion->cmd_list[blk_tag];
adam radford9c915a82010-12-21 13:34:31 -0800170}
171
172/**
173 * megasas_return_cmd_fusion - Return a cmd to free command pool
174 * @instance: Adapter soft state
175 * @cmd: Command packet to be returned to free command pool
176 */
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530177inline void megasas_return_cmd_fusion(struct megasas_instance *instance,
178 struct megasas_cmd_fusion *cmd)
adam radford9c915a82010-12-21 13:34:31 -0800179{
adam radford9c915a82010-12-21 13:34:31 -0800180 cmd->scmd = NULL;
Sumit.Saxena@avagotech.com7497cde2015-01-05 20:06:03 +0530181 memset(cmd->io_request, 0, sizeof(struct MPI2_RAID_SCSI_IO_REQUEST));
adam radford9c915a82010-12-21 13:34:31 -0800182}
183
184/**
185 * megasas_teardown_frame_pool_fusion - Destroy the cmd frame DMA pool
186 * @instance: Adapter soft state
187 */
188static void megasas_teardown_frame_pool_fusion(
189 struct megasas_instance *instance)
190{
191 int i;
192 struct fusion_context *fusion = instance->ctrl_context;
193
194 u16 max_cmd = instance->max_fw_cmds;
195
196 struct megasas_cmd_fusion *cmd;
197
198 if (!fusion->sg_dma_pool || !fusion->sense_dma_pool) {
199 printk(KERN_ERR "megasas: dma pool is null. SG Pool %p, "
200 "sense pool : %p\n", fusion->sg_dma_pool,
201 fusion->sense_dma_pool);
202 return;
203 }
204
205 /*
206 * Return all frames to pool
207 */
208 for (i = 0; i < max_cmd; i++) {
209
210 cmd = fusion->cmd_list[i];
211
212 if (cmd->sg_frame)
213 pci_pool_free(fusion->sg_dma_pool, cmd->sg_frame,
214 cmd->sg_frame_phys_addr);
215
216 if (cmd->sense)
217 pci_pool_free(fusion->sense_dma_pool, cmd->sense,
218 cmd->sense_phys_addr);
219 }
220
221 /*
222 * Now destroy the pool itself
223 */
224 pci_pool_destroy(fusion->sg_dma_pool);
225 pci_pool_destroy(fusion->sense_dma_pool);
226
227 fusion->sg_dma_pool = NULL;
228 fusion->sense_dma_pool = NULL;
229}
230
231/**
232 * megasas_free_cmds_fusion - Free all the cmds in the free cmd pool
233 * @instance: Adapter soft state
234 */
235void
236megasas_free_cmds_fusion(struct megasas_instance *instance)
237{
238 int i;
239 struct fusion_context *fusion = instance->ctrl_context;
240
241 u32 max_cmds, req_sz, reply_sz, io_frames_sz;
242
243
244 req_sz = fusion->request_alloc_sz;
245 reply_sz = fusion->reply_alloc_sz;
246 io_frames_sz = fusion->io_frames_alloc_sz;
247
248 max_cmds = instance->max_fw_cmds;
249
250 /* Free descriptors and request Frames memory */
251 if (fusion->req_frames_desc)
252 dma_free_coherent(&instance->pdev->dev, req_sz,
253 fusion->req_frames_desc,
254 fusion->req_frames_desc_phys);
255
256 if (fusion->reply_frames_desc) {
257 pci_pool_free(fusion->reply_frames_desc_pool,
258 fusion->reply_frames_desc,
259 fusion->reply_frames_desc_phys);
260 pci_pool_destroy(fusion->reply_frames_desc_pool);
261 }
262
263 if (fusion->io_request_frames) {
264 pci_pool_free(fusion->io_request_frames_pool,
265 fusion->io_request_frames,
266 fusion->io_request_frames_phys);
267 pci_pool_destroy(fusion->io_request_frames_pool);
268 }
269
270 /* Free the Fusion frame pool */
271 megasas_teardown_frame_pool_fusion(instance);
272
273 /* Free all the commands in the cmd_list */
274 for (i = 0; i < max_cmds; i++)
275 kfree(fusion->cmd_list[i]);
276
277 /* Free the cmd_list buffer itself */
278 kfree(fusion->cmd_list);
279 fusion->cmd_list = NULL;
280
adam radford9c915a82010-12-21 13:34:31 -0800281}
282
283/**
284 * megasas_create_frame_pool_fusion - Creates DMA pool for cmd frames
285 * @instance: Adapter soft state
286 *
287 */
288static int megasas_create_frame_pool_fusion(struct megasas_instance *instance)
289{
290 int i;
291 u32 max_cmd;
292 struct fusion_context *fusion;
293 struct megasas_cmd_fusion *cmd;
294 u32 total_sz_chain_frame;
295
296 fusion = instance->ctrl_context;
297 max_cmd = instance->max_fw_cmds;
298
299 total_sz_chain_frame = MEGASAS_MAX_SZ_CHAIN_FRAME;
300
301 /*
302 * Use DMA pool facility provided by PCI layer
303 */
304
305 fusion->sg_dma_pool = pci_pool_create("megasas sg pool fusion",
306 instance->pdev,
307 total_sz_chain_frame, 4,
308 0);
309 if (!fusion->sg_dma_pool) {
310 printk(KERN_DEBUG "megasas: failed to setup request pool "
311 "fusion\n");
312 return -ENOMEM;
313 }
314 fusion->sense_dma_pool = pci_pool_create("megasas sense pool fusion",
315 instance->pdev,
316 SCSI_SENSE_BUFFERSIZE, 64, 0);
317
318 if (!fusion->sense_dma_pool) {
319 printk(KERN_DEBUG "megasas: failed to setup sense pool "
320 "fusion\n");
321 pci_pool_destroy(fusion->sg_dma_pool);
322 fusion->sg_dma_pool = NULL;
323 return -ENOMEM;
324 }
325
326 /*
327 * Allocate and attach a frame to each of the commands in cmd_list
328 */
329 for (i = 0; i < max_cmd; i++) {
330
331 cmd = fusion->cmd_list[i];
332
333 cmd->sg_frame = pci_pool_alloc(fusion->sg_dma_pool,
334 GFP_KERNEL,
335 &cmd->sg_frame_phys_addr);
336
337 cmd->sense = pci_pool_alloc(fusion->sense_dma_pool,
338 GFP_KERNEL, &cmd->sense_phys_addr);
339 /*
340 * megasas_teardown_frame_pool_fusion() takes care of freeing
341 * whatever has been allocated
342 */
343 if (!cmd->sg_frame || !cmd->sense) {
344 printk(KERN_DEBUG "megasas: pci_pool_alloc failed\n");
345 megasas_teardown_frame_pool_fusion(instance);
346 return -ENOMEM;
347 }
348 }
349 return 0;
350}
351
352/**
353 * megasas_alloc_cmds_fusion - Allocates the command packets
354 * @instance: Adapter soft state
355 *
356 *
357 * Each frame has a 32-bit field called context. This context is used to get
358 * back the megasas_cmd_fusion from the frame when a frame gets completed
359 * In this driver, the 32 bit values are the indices into an array cmd_list.
360 * This array is used only to look up the megasas_cmd_fusion given the context.
361 * The free commands themselves are maintained in a linked list called cmd_pool.
362 *
363 * cmds are formed in the io_request and sg_frame members of the
364 * megasas_cmd_fusion. The context field is used to get a request descriptor
365 * and is used as SMID of the cmd.
366 * SMID value range is from 1 to max_fw_cmds.
367 */
368int
369megasas_alloc_cmds_fusion(struct megasas_instance *instance)
370{
adam radfordc8e858f2011-10-08 18:15:13 -0700371 int i, j, count;
adam radford9c915a82010-12-21 13:34:31 -0800372 u32 max_cmd, io_frames_sz;
373 struct fusion_context *fusion;
374 struct megasas_cmd_fusion *cmd;
375 union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
376 u32 offset;
377 dma_addr_t io_req_base_phys;
378 u8 *io_req_base;
379
380 fusion = instance->ctrl_context;
381
382 max_cmd = instance->max_fw_cmds;
383
384 fusion->req_frames_desc =
385 dma_alloc_coherent(&instance->pdev->dev,
386 fusion->request_alloc_sz,
387 &fusion->req_frames_desc_phys, GFP_KERNEL);
388
389 if (!fusion->req_frames_desc) {
390 printk(KERN_ERR "megasas; Could not allocate memory for "
391 "request_frames\n");
392 goto fail_req_desc;
393 }
394
adam radfordc8e858f2011-10-08 18:15:13 -0700395 count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
adam radford9c915a82010-12-21 13:34:31 -0800396 fusion->reply_frames_desc_pool =
397 pci_pool_create("reply_frames pool", instance->pdev,
adam radfordc8e858f2011-10-08 18:15:13 -0700398 fusion->reply_alloc_sz * count, 16, 0);
adam radford9c915a82010-12-21 13:34:31 -0800399
400 if (!fusion->reply_frames_desc_pool) {
401 printk(KERN_ERR "megasas; Could not allocate memory for "
402 "reply_frame pool\n");
403 goto fail_reply_desc;
404 }
405
406 fusion->reply_frames_desc =
407 pci_pool_alloc(fusion->reply_frames_desc_pool, GFP_KERNEL,
408 &fusion->reply_frames_desc_phys);
409 if (!fusion->reply_frames_desc) {
410 printk(KERN_ERR "megasas; Could not allocate memory for "
411 "reply_frame pool\n");
412 pci_pool_destroy(fusion->reply_frames_desc_pool);
413 goto fail_reply_desc;
414 }
415
416 reply_desc = fusion->reply_frames_desc;
adam radfordc8e858f2011-10-08 18:15:13 -0700417 for (i = 0; i < fusion->reply_q_depth * count; i++, reply_desc++)
Christoph Hellwigc6f5bf82015-04-23 16:33:09 +0530418 reply_desc->Words = cpu_to_le64(ULLONG_MAX);
adam radford9c915a82010-12-21 13:34:31 -0800419
420 io_frames_sz = fusion->io_frames_alloc_sz;
421
422 fusion->io_request_frames_pool =
423 pci_pool_create("io_request_frames pool", instance->pdev,
424 fusion->io_frames_alloc_sz, 16, 0);
425
426 if (!fusion->io_request_frames_pool) {
427 printk(KERN_ERR "megasas: Could not allocate memory for "
428 "io_request_frame pool\n");
429 goto fail_io_frames;
430 }
431
432 fusion->io_request_frames =
433 pci_pool_alloc(fusion->io_request_frames_pool, GFP_KERNEL,
434 &fusion->io_request_frames_phys);
435 if (!fusion->io_request_frames) {
436 printk(KERN_ERR "megasas: Could not allocate memory for "
437 "io_request_frames frames\n");
438 pci_pool_destroy(fusion->io_request_frames_pool);
439 goto fail_io_frames;
440 }
441
442 /*
443 * fusion->cmd_list is an array of struct megasas_cmd_fusion pointers.
444 * Allocate the dynamic array first and then allocate individual
445 * commands.
446 */
Fengguang Wu7731e6b2012-08-24 23:27:35 +0800447 fusion->cmd_list = kzalloc(sizeof(struct megasas_cmd_fusion *)
448 * max_cmd, GFP_KERNEL);
adam radford9c915a82010-12-21 13:34:31 -0800449
450 if (!fusion->cmd_list) {
451 printk(KERN_DEBUG "megasas: out of memory. Could not alloc "
452 "memory for cmd_list_fusion\n");
453 goto fail_cmd_list;
454 }
455
adam radford9c915a82010-12-21 13:34:31 -0800456 max_cmd = instance->max_fw_cmds;
457 for (i = 0; i < max_cmd; i++) {
458 fusion->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd_fusion),
459 GFP_KERNEL);
460 if (!fusion->cmd_list[i]) {
461 printk(KERN_ERR "Could not alloc cmd list fusion\n");
462
463 for (j = 0; j < i; j++)
464 kfree(fusion->cmd_list[j]);
465
466 kfree(fusion->cmd_list);
467 fusion->cmd_list = NULL;
468 goto fail_cmd_list;
469 }
470 }
471
472 /* The first 256 bytes (SMID 0) is not used. Don't add to cmd list */
473 io_req_base = fusion->io_request_frames +
474 MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
475 io_req_base_phys = fusion->io_request_frames_phys +
476 MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
477
478 /*
479 * Add all the commands to command pool (fusion->cmd_pool)
480 */
481
482 /* SMID 0 is reserved. Set SMID/index from 1 */
483 for (i = 0; i < max_cmd; i++) {
484 cmd = fusion->cmd_list[i];
485 offset = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * i;
486 memset(cmd, 0, sizeof(struct megasas_cmd_fusion));
487 cmd->index = i + 1;
488 cmd->scmd = NULL;
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530489 cmd->sync_cmd_idx = (i >= instance->max_scsi_cmds) ?
490 (i - instance->max_scsi_cmds) :
491 (u32)ULONG_MAX; /* Set to Invalid */
adam radford9c915a82010-12-21 13:34:31 -0800492 cmd->instance = instance;
493 cmd->io_request =
494 (struct MPI2_RAID_SCSI_IO_REQUEST *)
495 (io_req_base + offset);
496 memset(cmd->io_request, 0,
497 sizeof(struct MPI2_RAID_SCSI_IO_REQUEST));
498 cmd->io_request_phys_addr = io_req_base_phys + offset;
adam radford9c915a82010-12-21 13:34:31 -0800499 }
500
501 /*
502 * Create a frame pool and assign one frame to each cmd
503 */
504 if (megasas_create_frame_pool_fusion(instance)) {
505 printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n");
506 megasas_free_cmds_fusion(instance);
507 goto fail_req_desc;
508 }
509
510 return 0;
511
512fail_cmd_list:
513 pci_pool_free(fusion->io_request_frames_pool, fusion->io_request_frames,
514 fusion->io_request_frames_phys);
515 pci_pool_destroy(fusion->io_request_frames_pool);
516fail_io_frames:
517 dma_free_coherent(&instance->pdev->dev, fusion->request_alloc_sz,
518 fusion->reply_frames_desc,
519 fusion->reply_frames_desc_phys);
520 pci_pool_free(fusion->reply_frames_desc_pool,
521 fusion->reply_frames_desc,
522 fusion->reply_frames_desc_phys);
523 pci_pool_destroy(fusion->reply_frames_desc_pool);
524
525fail_reply_desc:
526 dma_free_coherent(&instance->pdev->dev, fusion->request_alloc_sz,
527 fusion->req_frames_desc,
528 fusion->req_frames_desc_phys);
529fail_req_desc:
530 return -ENOMEM;
531}
532
533/**
534 * wait_and_poll - Issues a polling command
535 * @instance: Adapter soft state
536 * @cmd: Command packet to be issued
537 *
538 * For polling, MFI requires the cmd_status to be set to 0xFF before posting.
539 */
540int
adam radford229fe472014-03-10 02:51:56 -0700541wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd,
542 int seconds)
adam radford9c915a82010-12-21 13:34:31 -0800543{
544 int i;
545 struct megasas_header *frame_hdr = &cmd->frame->hdr;
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530546 struct fusion_context *fusion;
adam radford9c915a82010-12-21 13:34:31 -0800547
adam radford229fe472014-03-10 02:51:56 -0700548 u32 msecs = seconds * 1000;
adam radford9c915a82010-12-21 13:34:31 -0800549
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530550 fusion = instance->ctrl_context;
adam radford9c915a82010-12-21 13:34:31 -0800551 /*
552 * Wait for cmd_status to change
553 */
554 for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i += 20) {
555 rmb();
556 msleep(20);
557 }
558
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530559 if (frame_hdr->cmd_status == 0xff)
adam radford9c915a82010-12-21 13:34:31 -0800560 return -ETIME;
561
562 return 0;
563}
564
565/**
566 * megasas_ioc_init_fusion - Initializes the FW
567 * @instance: Adapter soft state
568 *
569 * Issues the IOC Init cmd
570 */
571int
572megasas_ioc_init_fusion(struct megasas_instance *instance)
573{
574 struct megasas_init_frame *init_frame;
575 struct MPI2_IOC_INIT_REQUEST *IOCInitMessage;
576 dma_addr_t ioc_init_handle;
adam radford9c915a82010-12-21 13:34:31 -0800577 struct megasas_cmd *cmd;
578 u8 ret;
579 struct fusion_context *fusion;
adam radfordc77a9bd2014-03-10 02:51:36 -0700580 union MEGASAS_REQUEST_DESCRIPTOR_UNION req_desc;
adam radford9c915a82010-12-21 13:34:31 -0800581 int i;
582 struct megasas_header *frame_hdr;
Sumit.Saxena@avagotech.com5765c5b2015-04-23 16:32:09 +0530583 const char *sys_info;
adam radford9c915a82010-12-21 13:34:31 -0800584
585 fusion = instance->ctrl_context;
586
587 cmd = megasas_get_cmd(instance);
588
589 if (!cmd) {
590 printk(KERN_ERR "Could not allocate cmd for INIT Frame\n");
591 ret = 1;
592 goto fail_get_cmd;
593 }
594
595 IOCInitMessage =
596 dma_alloc_coherent(&instance->pdev->dev,
597 sizeof(struct MPI2_IOC_INIT_REQUEST),
598 &ioc_init_handle, GFP_KERNEL);
599
600 if (!IOCInitMessage) {
601 printk(KERN_ERR "Could not allocate memory for "
602 "IOCInitMessage\n");
603 ret = 1;
604 goto fail_fw_init;
605 }
606
607 memset(IOCInitMessage, 0, sizeof(struct MPI2_IOC_INIT_REQUEST));
608
609 IOCInitMessage->Function = MPI2_FUNCTION_IOC_INIT;
610 IOCInitMessage->WhoInit = MPI2_WHOINIT_HOST_DRIVER;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530611 IOCInitMessage->MsgVersion = cpu_to_le16(MPI2_VERSION);
612 IOCInitMessage->HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
613 IOCInitMessage->SystemRequestFrameSize = cpu_to_le16(MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE / 4);
adam radford9c915a82010-12-21 13:34:31 -0800614
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530615 IOCInitMessage->ReplyDescriptorPostQueueDepth = cpu_to_le16(fusion->reply_q_depth);
616 IOCInitMessage->ReplyDescriptorPostQueueAddress = cpu_to_le64(fusion->reply_frames_desc_phys);
617 IOCInitMessage->SystemRequestFrameBaseAddress = cpu_to_le64(fusion->io_request_frames_phys);
adam radford5738f992012-03-19 19:49:53 -0700618 IOCInitMessage->HostMSIxVectors = instance->msix_vectors;
adam radford9c915a82010-12-21 13:34:31 -0800619 init_frame = (struct megasas_init_frame *)cmd->frame;
620 memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
621
622 frame_hdr = &cmd->frame->hdr;
adam radford9c915a82010-12-21 13:34:31 -0800623 frame_hdr->cmd_status = 0xFF;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530624 frame_hdr->flags |= cpu_to_le16(MFI_FRAME_DONT_POST_IN_REPLY_QUEUE);
adam radford9c915a82010-12-21 13:34:31 -0800625
626 init_frame->cmd = MFI_CMD_INIT;
627 init_frame->cmd_status = 0xFF;
628
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530629 /* driver support Extended MSIX */
630 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
631 (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
632 init_frame->driver_operations.
633 mfi_capabilities.support_additional_msix = 1;
adam radford21c9e162013-09-06 15:27:14 -0700634 /* driver supports HA / Remote LUN over Fast Path interface */
635 init_frame->driver_operations.mfi_capabilities.support_fp_remote_lun
636 = 1;
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530637 init_frame->driver_operations.mfi_capabilities.support_max_255lds
638 = 1;
Sumit.Saxena@avagotech.comd2552eb2014-09-12 18:57:53 +0530639 init_frame->driver_operations.mfi_capabilities.support_ndrive_r1_lb
640 = 1;
Sumit.Saxena@avagotech.com7497cde2015-01-05 20:06:03 +0530641 init_frame->driver_operations.mfi_capabilities.security_protocol_cmds_fw
642 = 1;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530643 /* Convert capability to LE32 */
644 cpu_to_le32s((u32 *)&init_frame->driver_operations.mfi_capabilities);
adam radford21c9e162013-09-06 15:27:14 -0700645
Sumit.Saxena@avagotech.com5765c5b2015-04-23 16:32:09 +0530646 sys_info = dmi_get_system_info(DMI_PRODUCT_UUID);
647 if (instance->system_info_buf && sys_info) {
648 memcpy(instance->system_info_buf->systemId, sys_info,
649 strlen(sys_info) > 64 ? 64 : strlen(sys_info));
650 instance->system_info_buf->systemIdLength =
651 strlen(sys_info) > 64 ? 64 : strlen(sys_info);
652 init_frame->system_info_lo = instance->system_info_h;
653 init_frame->system_info_hi = 0;
654 }
655
Hannes Reineckefdc5a972014-01-16 11:25:33 +0100656 init_frame->queue_info_new_phys_addr_hi =
657 cpu_to_le32(upper_32_bits(ioc_init_handle));
658 init_frame->queue_info_new_phys_addr_lo =
659 cpu_to_le32(lower_32_bits(ioc_init_handle));
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530660 init_frame->data_xfer_len = cpu_to_le32(sizeof(struct MPI2_IOC_INIT_REQUEST));
adam radford9c915a82010-12-21 13:34:31 -0800661
Sumit.Saxena@avagotech.com200aed52015-01-05 20:05:58 +0530662 req_desc.u.low = cpu_to_le32(lower_32_bits(cmd->frame_phys_addr));
663 req_desc.u.high = cpu_to_le32(upper_32_bits(cmd->frame_phys_addr));
adam radfordc77a9bd2014-03-10 02:51:36 -0700664 req_desc.MFAIo.RequestFlags =
adam radford9c915a82010-12-21 13:34:31 -0800665 (MEGASAS_REQ_DESCRIPT_FLAGS_MFA <<
Sumit.Saxena@avagotech.com200aed52015-01-05 20:05:58 +0530666 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
adam radford9c915a82010-12-21 13:34:31 -0800667
668 /*
669 * disable the intr before firing the init frame
670 */
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530671 instance->instancet->disable_intr(instance);
adam radford9c915a82010-12-21 13:34:31 -0800672
673 for (i = 0; i < (10 * 1000); i += 20) {
674 if (readl(&instance->reg_set->doorbell) & 1)
675 msleep(20);
676 else
677 break;
678 }
679
adam radfordc77a9bd2014-03-10 02:51:36 -0700680 instance->instancet->fire_cmd(instance, req_desc.u.low,
681 req_desc.u.high, instance->reg_set);
adam radford9c915a82010-12-21 13:34:31 -0800682
adam radford229fe472014-03-10 02:51:56 -0700683 wait_and_poll(instance, cmd, MFI_POLL_TIMEOUT_SECS);
adam radford9c915a82010-12-21 13:34:31 -0800684
685 frame_hdr = &cmd->frame->hdr;
686 if (frame_hdr->cmd_status != 0) {
687 ret = 1;
688 goto fail_fw_init;
689 }
690 printk(KERN_ERR "megasas:IOC Init cmd success\n");
691
692 ret = 0;
693
694fail_fw_init:
695 megasas_return_cmd(instance, cmd);
696 if (IOCInitMessage)
697 dma_free_coherent(&instance->pdev->dev,
698 sizeof(struct MPI2_IOC_INIT_REQUEST),
699 IOCInitMessage, ioc_init_handle);
700fail_get_cmd:
701 return ret;
702}
703
704/*
adam radford9c915a82010-12-21 13:34:31 -0800705 * megasas_get_ld_map_info - Returns FW's ld_map structure
706 * @instance: Adapter soft state
707 * @pend: Pend the command or not
708 * Issues an internal command (DCMD) to get the FW's controller PD
709 * list structure. This information is mainly used to find out SYSTEM
710 * supported by the FW.
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530711 * dcmd.mbox value setting for MR_DCMD_LD_MAP_GET_INFO
712 * dcmd.mbox.b[0] - number of LDs being sync'd
713 * dcmd.mbox.b[1] - 0 - complete command immediately.
714 * - 1 - pend till config change
715 * dcmd.mbox.b[2] - 0 - supports max 64 lds and uses legacy MR_FW_RAID_MAP
716 * - 1 - supports max MAX_LOGICAL_DRIVES_EXT lds and
717 * uses extended struct MR_FW_RAID_MAP_EXT
adam radford9c915a82010-12-21 13:34:31 -0800718 */
719static int
720megasas_get_ld_map_info(struct megasas_instance *instance)
721{
722 int ret = 0;
723 struct megasas_cmd *cmd;
724 struct megasas_dcmd_frame *dcmd;
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530725 void *ci;
adam radford9c915a82010-12-21 13:34:31 -0800726 dma_addr_t ci_h = 0;
727 u32 size_map_info;
728 struct fusion_context *fusion;
729
730 cmd = megasas_get_cmd(instance);
731
732 if (!cmd) {
733 printk(KERN_DEBUG "megasas: Failed to get cmd for map info.\n");
734 return -ENOMEM;
735 }
736
737 fusion = instance->ctrl_context;
738
739 if (!fusion) {
740 megasas_return_cmd(instance, cmd);
Hannes Reinecke2f8bdfa2014-01-16 11:25:35 +0100741 return -ENXIO;
adam radford9c915a82010-12-21 13:34:31 -0800742 }
743
744 dcmd = &cmd->frame->dcmd;
745
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530746 size_map_info = fusion->current_map_sz;
adam radford9c915a82010-12-21 13:34:31 -0800747
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530748 ci = (void *) fusion->ld_map[(instance->map_id & 1)];
adam radford9c915a82010-12-21 13:34:31 -0800749 ci_h = fusion->ld_map_phys[(instance->map_id & 1)];
750
751 if (!ci) {
752 printk(KERN_DEBUG "Failed to alloc mem for ld_map_info\n");
753 megasas_return_cmd(instance, cmd);
754 return -ENOMEM;
755 }
756
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530757 memset(ci, 0, fusion->max_map_sz);
adam radford9c915a82010-12-21 13:34:31 -0800758 memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530759#if VD_EXT_DEBUG
760 dev_dbg(&instance->pdev->dev,
761 "%s sending MR_DCMD_LD_MAP_GET_INFO with size %d\n",
762 __func__, cpu_to_le32(size_map_info));
763#endif
adam radford9c915a82010-12-21 13:34:31 -0800764 dcmd->cmd = MFI_CMD_DCMD;
765 dcmd->cmd_status = 0xFF;
766 dcmd->sge_count = 1;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530767 dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ);
adam radford9c915a82010-12-21 13:34:31 -0800768 dcmd->timeout = 0;
769 dcmd->pad_0 = 0;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530770 dcmd->data_xfer_len = cpu_to_le32(size_map_info);
771 dcmd->opcode = cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO);
772 dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(ci_h);
773 dcmd->sgl.sge32[0].length = cpu_to_le32(size_map_info);
adam radford9c915a82010-12-21 13:34:31 -0800774
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530775 if (instance->ctrl_context && !instance->mask_interrupts)
776 ret = megasas_issue_blocked_cmd(instance, cmd,
777 MEGASAS_BLOCKED_CMD_TIMEOUT);
778 else
779 ret = megasas_issue_polled(instance, cmd);
adam radford9c915a82010-12-21 13:34:31 -0800780
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530781 megasas_return_cmd(instance, cmd);
adam radford9c915a82010-12-21 13:34:31 -0800782
783 return ret;
784}
785
786u8
787megasas_get_map_info(struct megasas_instance *instance)
788{
789 struct fusion_context *fusion = instance->ctrl_context;
790
791 fusion->fast_path_io = 0;
792 if (!megasas_get_ld_map_info(instance)) {
Sumit.Saxena@lsi.combc93d422013-05-22 12:35:04 +0530793 if (MR_ValidateMapInfo(instance)) {
adam radford9c915a82010-12-21 13:34:31 -0800794 fusion->fast_path_io = 1;
795 return 0;
796 }
797 }
798 return 1;
799}
800
801/*
802 * megasas_sync_map_info - Returns FW's ld_map structure
803 * @instance: Adapter soft state
804 *
805 * Issues an internal command (DCMD) to get the FW's controller PD
806 * list structure. This information is mainly used to find out SYSTEM
807 * supported by the FW.
808 */
809int
810megasas_sync_map_info(struct megasas_instance *instance)
811{
812 int ret = 0, i;
813 struct megasas_cmd *cmd;
814 struct megasas_dcmd_frame *dcmd;
815 u32 size_sync_info, num_lds;
816 struct fusion_context *fusion;
817 struct MR_LD_TARGET_SYNC *ci = NULL;
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530818 struct MR_DRV_RAID_MAP_ALL *map;
adam radford9c915a82010-12-21 13:34:31 -0800819 struct MR_LD_RAID *raid;
820 struct MR_LD_TARGET_SYNC *ld_sync;
821 dma_addr_t ci_h = 0;
822 u32 size_map_info;
823
824 cmd = megasas_get_cmd(instance);
825
826 if (!cmd) {
827 printk(KERN_DEBUG "megasas: Failed to get cmd for sync"
828 "info.\n");
829 return -ENOMEM;
830 }
831
832 fusion = instance->ctrl_context;
833
834 if (!fusion) {
835 megasas_return_cmd(instance, cmd);
836 return 1;
837 }
838
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530839 map = fusion->ld_drv_map[instance->map_id & 1];
adam radford9c915a82010-12-21 13:34:31 -0800840
Sumit.Saxena@avagotech.com6e755dd2014-11-17 15:24:28 +0530841 num_lds = le16_to_cpu(map->raidMap.ldCount);
adam radford9c915a82010-12-21 13:34:31 -0800842
843 dcmd = &cmd->frame->dcmd;
844
845 size_sync_info = sizeof(struct MR_LD_TARGET_SYNC) *num_lds;
846
847 memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
848
849 ci = (struct MR_LD_TARGET_SYNC *)
850 fusion->ld_map[(instance->map_id - 1) & 1];
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530851 memset(ci, 0, fusion->max_map_sz);
adam radford9c915a82010-12-21 13:34:31 -0800852
853 ci_h = fusion->ld_map_phys[(instance->map_id - 1) & 1];
854
855 ld_sync = (struct MR_LD_TARGET_SYNC *)ci;
856
857 for (i = 0; i < num_lds; i++, ld_sync++) {
858 raid = MR_LdRaidGet(i, map);
859 ld_sync->targetId = MR_GetLDTgtId(i, map);
860 ld_sync->seqNum = raid->seqNum;
861 }
862
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530863 size_map_info = fusion->current_map_sz;
adam radford9c915a82010-12-21 13:34:31 -0800864
865 dcmd->cmd = MFI_CMD_DCMD;
866 dcmd->cmd_status = 0xFF;
867 dcmd->sge_count = 1;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530868 dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_WRITE);
adam radford9c915a82010-12-21 13:34:31 -0800869 dcmd->timeout = 0;
870 dcmd->pad_0 = 0;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530871 dcmd->data_xfer_len = cpu_to_le32(size_map_info);
adam radford9c915a82010-12-21 13:34:31 -0800872 dcmd->mbox.b[0] = num_lds;
873 dcmd->mbox.b[1] = MEGASAS_DCMD_MBOX_PEND_FLAG;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530874 dcmd->opcode = cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO);
875 dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(ci_h);
876 dcmd->sgl.sge32[0].length = cpu_to_le32(size_map_info);
adam radford9c915a82010-12-21 13:34:31 -0800877
878 instance->map_update_cmd = cmd;
879
880 instance->instancet->issue_dcmd(instance, cmd);
881
882 return ret;
883}
884
Sumit.Saxena@lsi.com39b72c32013-05-22 12:32:43 +0530885/*
886 * meagasas_display_intel_branding - Display branding string
887 * @instance: per adapter object
888 *
889 * Return nothing.
890 */
891static void
892megasas_display_intel_branding(struct megasas_instance *instance)
893{
894 if (instance->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL)
895 return;
896
897 switch (instance->pdev->device) {
898 case PCI_DEVICE_ID_LSI_INVADER:
899 switch (instance->pdev->subsystem_device) {
900 case MEGARAID_INTEL_RS3DC080_SSDID:
901 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
902 instance->host->host_no,
903 MEGARAID_INTEL_RS3DC080_BRANDING);
904 break;
905 case MEGARAID_INTEL_RS3DC040_SSDID:
906 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
907 instance->host->host_no,
908 MEGARAID_INTEL_RS3DC040_BRANDING);
909 break;
910 case MEGARAID_INTEL_RS3SC008_SSDID:
911 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
912 instance->host->host_no,
913 MEGARAID_INTEL_RS3SC008_BRANDING);
914 break;
915 case MEGARAID_INTEL_RS3MC044_SSDID:
916 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
917 instance->host->host_no,
918 MEGARAID_INTEL_RS3MC044_BRANDING);
919 break;
920 default:
921 break;
922 }
923 break;
924 case PCI_DEVICE_ID_LSI_FURY:
925 switch (instance->pdev->subsystem_device) {
926 case MEGARAID_INTEL_RS3WC080_SSDID:
927 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
928 instance->host->host_no,
929 MEGARAID_INTEL_RS3WC080_BRANDING);
930 break;
931 case MEGARAID_INTEL_RS3WC040_SSDID:
932 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
933 instance->host->host_no,
934 MEGARAID_INTEL_RS3WC040_BRANDING);
935 break;
936 default:
937 break;
938 }
939 break;
940 default:
941 break;
942 }
943}
944
adam radford9c915a82010-12-21 13:34:31 -0800945/**
946 * megasas_init_adapter_fusion - Initializes the FW
947 * @instance: Adapter soft state
948 *
949 * This is the main function for initializing firmware.
950 */
951u32
952megasas_init_adapter_fusion(struct megasas_instance *instance)
953{
954 struct megasas_register_set __iomem *reg_set;
955 struct fusion_context *fusion;
956 u32 max_cmd;
adam radfordc8e858f2011-10-08 18:15:13 -0700957 int i = 0, count;
adam radford9c915a82010-12-21 13:34:31 -0800958
959 fusion = instance->ctrl_context;
960
961 reg_set = instance->reg_set;
962
963 /*
964 * Get various operational parameters from status register
965 */
966 instance->max_fw_cmds =
967 instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF;
968 instance->max_fw_cmds = min(instance->max_fw_cmds, (u16)1008);
969
970 /*
971 * Reduce the max supported cmds by 1. This is to ensure that the
972 * reply_q_sz (1 more than the max cmd that driver may send)
973 * does not exceed max cmds that the FW can support
974 */
975 instance->max_fw_cmds = instance->max_fw_cmds-1;
Sumit.Saxena@avagotech.comae09a6c2015-01-05 20:06:23 +0530976
977 /*
978 * Only Driver's internal DCMDs and IOCTL DCMDs needs to have MFI frames
979 */
980 instance->max_mfi_cmds =
981 MEGASAS_FUSION_INTERNAL_CMDS + MEGASAS_FUSION_IOCTL_CMDS;
adam radford9c915a82010-12-21 13:34:31 -0800982
983 max_cmd = instance->max_fw_cmds;
984
Sumit.Saxena@avagotech.comdb4fc862014-09-12 18:57:23 +0530985 fusion->reply_q_depth = 2 * (((max_cmd + 1 + 15)/16)*16);
adam radford9c915a82010-12-21 13:34:31 -0800986
987 fusion->request_alloc_sz =
988 sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *max_cmd;
989 fusion->reply_alloc_sz = sizeof(union MPI2_REPLY_DESCRIPTORS_UNION)
990 *(fusion->reply_q_depth);
991 fusion->io_frames_alloc_sz = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE +
992 (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE *
993 (max_cmd + 1)); /* Extra 1 for SMID 0 */
994
995 fusion->max_sge_in_main_msg =
996 (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
997 offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL))/16;
998
999 fusion->max_sge_in_chain =
1000 MEGASAS_MAX_SZ_CHAIN_FRAME / sizeof(union MPI2_SGE_IO_UNION);
1001
Sumit.Saxena@avagotech.coma5fd2852014-09-12 18:57:43 +05301002 instance->max_num_sge = rounddown_pow_of_two(
1003 fusion->max_sge_in_main_msg + fusion->max_sge_in_chain - 2);
adam radford9c915a82010-12-21 13:34:31 -08001004
1005 /* Used for pass thru MFI frame (DCMD) */
1006 fusion->chain_offset_mfi_pthru =
1007 offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL)/16;
1008
1009 fusion->chain_offset_io_request =
1010 (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
1011 sizeof(union MPI2_SGE_IO_UNION))/16;
1012
adam radfordc8e858f2011-10-08 18:15:13 -07001013 count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
1014 for (i = 0 ; i < count; i++)
1015 fusion->last_reply_idx[i] = 0;
adam radford9c915a82010-12-21 13:34:31 -08001016
1017 /*
Sumit.Saxena@avagotech.comf26ac3a2015-04-23 16:30:54 +05301018 * For fusion adapters, 3 commands for IOCTL and 5 commands
1019 * for driver's internal DCMDs.
1020 */
1021 instance->max_scsi_cmds = instance->max_fw_cmds -
1022 (MEGASAS_FUSION_INTERNAL_CMDS +
1023 MEGASAS_FUSION_IOCTL_CMDS);
1024 sema_init(&instance->ioctl_sem, MEGASAS_FUSION_IOCTL_CMDS);
1025
1026 /*
adam radford9c915a82010-12-21 13:34:31 -08001027 * Allocate memory for descriptors
1028 * Create a pool of commands
1029 */
1030 if (megasas_alloc_cmds(instance))
1031 goto fail_alloc_mfi_cmds;
1032 if (megasas_alloc_cmds_fusion(instance))
1033 goto fail_alloc_cmds;
1034
1035 if (megasas_ioc_init_fusion(instance))
1036 goto fail_ioc_init;
1037
Sumit.Saxena@lsi.com39b72c32013-05-22 12:32:43 +05301038 megasas_display_intel_branding(instance);
Sumit.Saxena@avagotech.comd009b572014-11-17 15:24:13 +05301039 if (megasas_get_ctrl_info(instance)) {
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301040 dev_err(&instance->pdev->dev,
1041 "Could not get controller info. Fail from %s %d\n",
1042 __func__, __LINE__);
1043 goto fail_ioc_init;
1044 }
1045
adam radford9c915a82010-12-21 13:34:31 -08001046 instance->flag_ieee = 1;
adam radford9c915a82010-12-21 13:34:31 -08001047 fusion->fast_path_io = 0;
1048
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301049 fusion->drv_map_pages = get_order(fusion->drv_map_sz);
1050 for (i = 0; i < 2; i++) {
1051 fusion->ld_map[i] = NULL;
1052 fusion->ld_drv_map[i] = (void *)__get_free_pages(GFP_KERNEL,
1053 fusion->drv_map_pages);
1054 if (!fusion->ld_drv_map[i]) {
1055 dev_err(&instance->pdev->dev, "Could not allocate "
1056 "memory for local map info for %d pages\n",
1057 fusion->drv_map_pages);
1058 if (i == 1)
1059 free_pages((ulong)fusion->ld_drv_map[0],
1060 fusion->drv_map_pages);
1061 goto fail_ioc_init;
1062 }
Sumit.Saxena@avagotech.comd009b572014-11-17 15:24:13 +05301063 memset(fusion->ld_drv_map[i], 0,
1064 ((1 << PAGE_SHIFT) << fusion->drv_map_pages));
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301065 }
1066
adam radford9c915a82010-12-21 13:34:31 -08001067 for (i = 0; i < 2; i++) {
1068 fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301069 fusion->max_map_sz,
adam radford9c915a82010-12-21 13:34:31 -08001070 &fusion->ld_map_phys[i],
1071 GFP_KERNEL);
1072 if (!fusion->ld_map[i]) {
1073 printk(KERN_ERR "megasas: Could not allocate memory "
1074 "for map info\n");
1075 goto fail_map_info;
1076 }
1077 }
1078
1079 if (!megasas_get_map_info(instance))
1080 megasas_sync_map_info(instance);
1081
1082 return 0;
1083
adam radford9c915a82010-12-21 13:34:31 -08001084fail_map_info:
1085 if (i == 1)
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301086 dma_free_coherent(&instance->pdev->dev, fusion->max_map_sz,
adam radford9c915a82010-12-21 13:34:31 -08001087 fusion->ld_map[0], fusion->ld_map_phys[0]);
1088fail_ioc_init:
adam radfordeb1b1232011-02-24 20:55:56 -08001089 megasas_free_cmds_fusion(instance);
1090fail_alloc_cmds:
1091 megasas_free_cmds(instance);
1092fail_alloc_mfi_cmds:
adam radford9c915a82010-12-21 13:34:31 -08001093 return 1;
1094}
1095
1096/**
1097 * megasas_fire_cmd_fusion - Sends command to the FW
1098 * @frame_phys_addr : Physical address of cmd
1099 * @frame_count : Number of frames for the command
1100 * @regs : MFI register set
1101 */
1102void
1103megasas_fire_cmd_fusion(struct megasas_instance *instance,
1104 dma_addr_t req_desc_lo,
1105 u32 req_desc_hi,
1106 struct megasas_register_set __iomem *regs)
1107{
Sumit.Saxena@avagotech.com07560402014-09-12 18:57:18 +05301108#if defined(writeq) && defined(CONFIG_64BIT)
Sumit.Saxena@avagotech.com6e755dd2014-11-17 15:24:28 +05301109 u64 req_data = (((u64)le32_to_cpu(req_desc_hi) << 32) |
1110 le32_to_cpu(req_desc_lo));
Sumit.Saxena@avagotech.com07560402014-09-12 18:57:18 +05301111
Sumit.Saxena@avagotech.com6e755dd2014-11-17 15:24:28 +05301112 writeq(req_data, &(regs)->inbound_low_queue_port);
Sumit.Saxena@avagotech.com07560402014-09-12 18:57:18 +05301113#else
adam radford9c915a82010-12-21 13:34:31 -08001114 unsigned long flags;
1115
1116 spin_lock_irqsave(&instance->hba_lock, flags);
1117
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301118 writel(le32_to_cpu(req_desc_lo), &(regs)->inbound_low_queue_port);
1119 writel(le32_to_cpu(req_desc_hi), &(regs)->inbound_high_queue_port);
adam radford9c915a82010-12-21 13:34:31 -08001120 spin_unlock_irqrestore(&instance->hba_lock, flags);
Sumit.Saxena@avagotech.com07560402014-09-12 18:57:18 +05301121#endif
adam radford9c915a82010-12-21 13:34:31 -08001122}
1123
1124/**
1125 * map_cmd_status - Maps FW cmd status to OS cmd status
1126 * @cmd : Pointer to cmd
1127 * @status : status of cmd returned by FW
1128 * @ext_status : ext status of cmd returned by FW
1129 */
1130
1131void
1132map_cmd_status(struct megasas_cmd_fusion *cmd, u8 status, u8 ext_status)
1133{
1134
1135 switch (status) {
1136
1137 case MFI_STAT_OK:
1138 cmd->scmd->result = DID_OK << 16;
1139 break;
1140
1141 case MFI_STAT_SCSI_IO_FAILED:
1142 case MFI_STAT_LD_INIT_IN_PROGRESS:
1143 cmd->scmd->result = (DID_ERROR << 16) | ext_status;
1144 break;
1145
1146 case MFI_STAT_SCSI_DONE_WITH_ERROR:
1147
1148 cmd->scmd->result = (DID_OK << 16) | ext_status;
1149 if (ext_status == SAM_STAT_CHECK_CONDITION) {
1150 memset(cmd->scmd->sense_buffer, 0,
1151 SCSI_SENSE_BUFFERSIZE);
1152 memcpy(cmd->scmd->sense_buffer, cmd->sense,
1153 SCSI_SENSE_BUFFERSIZE);
1154 cmd->scmd->result |= DRIVER_SENSE << 24;
1155 }
1156 break;
1157
1158 case MFI_STAT_LD_OFFLINE:
1159 case MFI_STAT_DEVICE_NOT_FOUND:
1160 cmd->scmd->result = DID_BAD_TARGET << 16;
1161 break;
adam radford36807e62011-10-08 18:15:06 -07001162 case MFI_STAT_CONFIG_SEQ_MISMATCH:
1163 cmd->scmd->result = DID_IMM_RETRY << 16;
1164 break;
adam radford9c915a82010-12-21 13:34:31 -08001165 default:
1166 printk(KERN_DEBUG "megasas: FW status %#x\n", status);
1167 cmd->scmd->result = DID_ERROR << 16;
1168 break;
1169 }
1170}
1171
1172/**
1173 * megasas_make_sgl_fusion - Prepares 32-bit SGL
1174 * @instance: Adapter soft state
1175 * @scp: SCSI command from the mid-layer
1176 * @sgl_ptr: SGL to be filled in
1177 * @cmd: cmd we are working on
1178 *
1179 * If successful, this function returns the number of SG elements.
1180 */
1181static int
1182megasas_make_sgl_fusion(struct megasas_instance *instance,
1183 struct scsi_cmnd *scp,
1184 struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr,
1185 struct megasas_cmd_fusion *cmd)
1186{
adam radford36807e62011-10-08 18:15:06 -07001187 int i, sg_processed, sge_count;
adam radford9c915a82010-12-21 13:34:31 -08001188 struct scatterlist *os_sgl;
1189 struct fusion_context *fusion;
1190
1191 fusion = instance->ctrl_context;
1192
Sumit.Saxena@lsi.com21d3c712013-05-22 12:31:43 +05301193 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
1194 (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
adam radford36807e62011-10-08 18:15:06 -07001195 struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = sgl_ptr;
1196 sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
1197 sgl_ptr_end->Flags = 0;
1198 }
adam radford9c915a82010-12-21 13:34:31 -08001199
1200 sge_count = scsi_dma_map(scp);
1201
1202 BUG_ON(sge_count < 0);
1203
1204 if (sge_count > instance->max_num_sge || !sge_count)
1205 return sge_count;
1206
adam radford9c915a82010-12-21 13:34:31 -08001207 scsi_for_each_sg(scp, os_sgl, sge_count, i) {
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301208 sgl_ptr->Length = cpu_to_le32(sg_dma_len(os_sgl));
1209 sgl_ptr->Address = cpu_to_le64(sg_dma_address(os_sgl));
adam radford9c915a82010-12-21 13:34:31 -08001210 sgl_ptr->Flags = 0;
Sumit.Saxena@lsi.com21d3c712013-05-22 12:31:43 +05301211 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
1212 (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
adam radford36807e62011-10-08 18:15:06 -07001213 if (i == sge_count - 1)
1214 sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST;
1215 }
adam radford9c915a82010-12-21 13:34:31 -08001216 sgl_ptr++;
1217
1218 sg_processed = i + 1;
1219
1220 if ((sg_processed == (fusion->max_sge_in_main_msg - 1)) &&
1221 (sge_count > fusion->max_sge_in_main_msg)) {
1222
1223 struct MPI25_IEEE_SGE_CHAIN64 *sg_chain;
Sumit.Saxena@lsi.com21d3c712013-05-22 12:31:43 +05301224 if ((instance->pdev->device ==
1225 PCI_DEVICE_ID_LSI_INVADER) ||
1226 (instance->pdev->device ==
1227 PCI_DEVICE_ID_LSI_FURY)) {
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301228 if ((le16_to_cpu(cmd->io_request->IoFlags) &
1229 MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) !=
1230 MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)
adam radford36807e62011-10-08 18:15:06 -07001231 cmd->io_request->ChainOffset =
1232 fusion->
1233 chain_offset_io_request;
1234 else
1235 cmd->io_request->ChainOffset = 0;
1236 } else
1237 cmd->io_request->ChainOffset =
1238 fusion->chain_offset_io_request;
1239
adam radford9c915a82010-12-21 13:34:31 -08001240 sg_chain = sgl_ptr;
1241 /* Prepare chain element */
1242 sg_chain->NextChainOffset = 0;
Sumit.Saxena@lsi.com21d3c712013-05-22 12:31:43 +05301243 if ((instance->pdev->device ==
1244 PCI_DEVICE_ID_LSI_INVADER) ||
1245 (instance->pdev->device ==
1246 PCI_DEVICE_ID_LSI_FURY))
adam radford36807e62011-10-08 18:15:06 -07001247 sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT;
1248 else
1249 sg_chain->Flags =
1250 (IEEE_SGE_FLAGS_CHAIN_ELEMENT |
1251 MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301252 sg_chain->Length = cpu_to_le32((sizeof(union MPI2_SGE_IO_UNION) * (sge_count - sg_processed)));
1253 sg_chain->Address = cpu_to_le64(cmd->sg_frame_phys_addr);
adam radford9c915a82010-12-21 13:34:31 -08001254
1255 sgl_ptr =
1256 (struct MPI25_IEEE_SGE_CHAIN64 *)cmd->sg_frame;
Sumit.Saxena@avagotech.com7497cde2015-01-05 20:06:03 +05301257 memset(sgl_ptr, 0, MEGASAS_MAX_SZ_CHAIN_FRAME);
adam radford9c915a82010-12-21 13:34:31 -08001258 }
1259 }
1260
1261 return sge_count;
1262}
1263
1264/**
1265 * megasas_set_pd_lba - Sets PD LBA
1266 * @cdb: CDB
1267 * @cdb_len: cdb length
1268 * @start_blk: Start block of IO
1269 *
1270 * Used to set the PD LBA in CDB for FP IOs
1271 */
1272void
1273megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
1274 struct IO_REQUEST_INFO *io_info, struct scsi_cmnd *scp,
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301275 struct MR_DRV_RAID_MAP_ALL *local_map_ptr, u32 ref_tag)
adam radford9c915a82010-12-21 13:34:31 -08001276{
1277 struct MR_LD_RAID *raid;
1278 u32 ld;
1279 u64 start_blk = io_info->pdBlock;
1280 u8 *cdb = io_request->CDB.CDB32;
1281 u32 num_blocks = io_info->numBlocks;
adam radford495c5602011-05-11 18:34:40 -07001282 u8 opcode = 0, flagvals = 0, groupnum = 0, control = 0;
adam radford9c915a82010-12-21 13:34:31 -08001283
1284 /* Check if T10 PI (DIF) is enabled for this LD */
1285 ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr);
1286 raid = MR_LdRaidGet(ld, local_map_ptr);
1287 if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) {
1288 memset(cdb, 0, sizeof(io_request->CDB.CDB32));
1289 cdb[0] = MEGASAS_SCSI_VARIABLE_LENGTH_CMD;
1290 cdb[7] = MEGASAS_SCSI_ADDL_CDB_LEN;
1291
1292 if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
1293 cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_READ32;
1294 else
1295 cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_WRITE32;
1296 cdb[10] = MEGASAS_RD_WR_PROTECT_CHECK_ALL;
1297
1298 /* LBA */
1299 cdb[12] = (u8)((start_blk >> 56) & 0xff);
1300 cdb[13] = (u8)((start_blk >> 48) & 0xff);
1301 cdb[14] = (u8)((start_blk >> 40) & 0xff);
1302 cdb[15] = (u8)((start_blk >> 32) & 0xff);
1303 cdb[16] = (u8)((start_blk >> 24) & 0xff);
1304 cdb[17] = (u8)((start_blk >> 16) & 0xff);
1305 cdb[18] = (u8)((start_blk >> 8) & 0xff);
1306 cdb[19] = (u8)(start_blk & 0xff);
1307
1308 /* Logical block reference tag */
1309 io_request->CDB.EEDP32.PrimaryReferenceTag =
1310 cpu_to_be32(ref_tag);
Sumit.Saxena@avagotech.com6e755dd2014-11-17 15:24:28 +05301311 io_request->CDB.EEDP32.PrimaryApplicationTagMask = cpu_to_be16(0xffff);
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301312 io_request->IoFlags = cpu_to_le16(32); /* Specify 32-byte cdb */
adam radford9c915a82010-12-21 13:34:31 -08001313
1314 /* Transfer length */
1315 cdb[28] = (u8)((num_blocks >> 24) & 0xff);
1316 cdb[29] = (u8)((num_blocks >> 16) & 0xff);
1317 cdb[30] = (u8)((num_blocks >> 8) & 0xff);
1318 cdb[31] = (u8)(num_blocks & 0xff);
1319
1320 /* set SCSI IO EEDPFlags */
1321 if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) {
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301322 io_request->EEDPFlags = cpu_to_le16(
adam radford9c915a82010-12-21 13:34:31 -08001323 MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
1324 MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
1325 MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP |
1326 MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG |
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301327 MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD);
adam radford9c915a82010-12-21 13:34:31 -08001328 } else {
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301329 io_request->EEDPFlags = cpu_to_le16(
adam radford9c915a82010-12-21 13:34:31 -08001330 MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301331 MPI2_SCSIIO_EEDPFLAGS_INSERT_OP);
adam radford9c915a82010-12-21 13:34:31 -08001332 }
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301333 io_request->Control |= cpu_to_le32((0x4 << 26));
1334 io_request->EEDPBlockSize = cpu_to_le32(scp->device->sector_size);
adam radford9c915a82010-12-21 13:34:31 -08001335 } else {
1336 /* Some drives don't support 16/12 byte CDB's, convert to 10 */
1337 if (((cdb_len == 12) || (cdb_len == 16)) &&
1338 (start_blk <= 0xffffffff)) {
1339 if (cdb_len == 16) {
1340 opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10;
1341 flagvals = cdb[1];
1342 groupnum = cdb[14];
1343 control = cdb[15];
1344 } else {
1345 opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10;
1346 flagvals = cdb[1];
1347 groupnum = cdb[10];
1348 control = cdb[11];
1349 }
1350
1351 memset(cdb, 0, sizeof(io_request->CDB.CDB32));
1352
1353 cdb[0] = opcode;
1354 cdb[1] = flagvals;
1355 cdb[6] = groupnum;
1356 cdb[9] = control;
1357
1358 /* Transfer length */
1359 cdb[8] = (u8)(num_blocks & 0xff);
1360 cdb[7] = (u8)((num_blocks >> 8) & 0xff);
1361
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301362 io_request->IoFlags = cpu_to_le16(10); /* Specify 10-byte cdb */
adam radford9c915a82010-12-21 13:34:31 -08001363 cdb_len = 10;
adam radford495c5602011-05-11 18:34:40 -07001364 } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) {
1365 /* Convert to 16 byte CDB for large LBA's */
1366 switch (cdb_len) {
1367 case 6:
1368 opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16;
1369 control = cdb[5];
1370 break;
1371 case 10:
1372 opcode =
1373 cdb[0] == READ_10 ? READ_16 : WRITE_16;
1374 flagvals = cdb[1];
1375 groupnum = cdb[6];
1376 control = cdb[9];
1377 break;
1378 case 12:
1379 opcode =
1380 cdb[0] == READ_12 ? READ_16 : WRITE_16;
1381 flagvals = cdb[1];
1382 groupnum = cdb[10];
1383 control = cdb[11];
1384 break;
1385 }
1386
1387 memset(cdb, 0, sizeof(io_request->CDB.CDB32));
1388
1389 cdb[0] = opcode;
1390 cdb[1] = flagvals;
1391 cdb[14] = groupnum;
1392 cdb[15] = control;
1393
1394 /* Transfer length */
1395 cdb[13] = (u8)(num_blocks & 0xff);
1396 cdb[12] = (u8)((num_blocks >> 8) & 0xff);
1397 cdb[11] = (u8)((num_blocks >> 16) & 0xff);
1398 cdb[10] = (u8)((num_blocks >> 24) & 0xff);
1399
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301400 io_request->IoFlags = cpu_to_le16(16); /* Specify 16-byte cdb */
adam radford495c5602011-05-11 18:34:40 -07001401 cdb_len = 16;
adam radford9c915a82010-12-21 13:34:31 -08001402 }
1403
1404 /* Normal case, just load LBA here */
1405 switch (cdb_len) {
1406 case 6:
1407 {
1408 u8 val = cdb[1] & 0xE0;
1409 cdb[3] = (u8)(start_blk & 0xff);
1410 cdb[2] = (u8)((start_blk >> 8) & 0xff);
1411 cdb[1] = val | ((u8)(start_blk >> 16) & 0x1f);
1412 break;
1413 }
1414 case 10:
1415 cdb[5] = (u8)(start_blk & 0xff);
1416 cdb[4] = (u8)((start_blk >> 8) & 0xff);
1417 cdb[3] = (u8)((start_blk >> 16) & 0xff);
1418 cdb[2] = (u8)((start_blk >> 24) & 0xff);
1419 break;
1420 case 12:
1421 cdb[5] = (u8)(start_blk & 0xff);
1422 cdb[4] = (u8)((start_blk >> 8) & 0xff);
1423 cdb[3] = (u8)((start_blk >> 16) & 0xff);
1424 cdb[2] = (u8)((start_blk >> 24) & 0xff);
1425 break;
1426 case 16:
1427 cdb[9] = (u8)(start_blk & 0xff);
1428 cdb[8] = (u8)((start_blk >> 8) & 0xff);
1429 cdb[7] = (u8)((start_blk >> 16) & 0xff);
1430 cdb[6] = (u8)((start_blk >> 24) & 0xff);
1431 cdb[5] = (u8)((start_blk >> 32) & 0xff);
1432 cdb[4] = (u8)((start_blk >> 40) & 0xff);
1433 cdb[3] = (u8)((start_blk >> 48) & 0xff);
1434 cdb[2] = (u8)((start_blk >> 56) & 0xff);
1435 break;
1436 }
1437 }
1438}
1439
1440/**
1441 * megasas_build_ldio_fusion - Prepares IOs to devices
1442 * @instance: Adapter soft state
1443 * @scp: SCSI command
1444 * @cmd: Command to be prepared
1445 *
1446 * Prepares the io_request and chain elements (sg_frame) for IO
1447 * The IO can be for PD (Fast Path) or LD
1448 */
1449void
1450megasas_build_ldio_fusion(struct megasas_instance *instance,
1451 struct scsi_cmnd *scp,
1452 struct megasas_cmd_fusion *cmd)
1453{
1454 u8 fp_possible;
adam radfordf9eff812012-10-01 19:27:07 -07001455 u32 start_lba_lo, start_lba_hi, device_id, datalength = 0;
adam radford9c915a82010-12-21 13:34:31 -08001456 struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
1457 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
1458 struct IO_REQUEST_INFO io_info;
1459 struct fusion_context *fusion;
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301460 struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
adam radford21c9e162013-09-06 15:27:14 -07001461 u8 *raidLUN;
adam radford9c915a82010-12-21 13:34:31 -08001462
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301463 device_id = MEGASAS_DEV_INDEX(scp);
adam radford9c915a82010-12-21 13:34:31 -08001464
1465 fusion = instance->ctrl_context;
1466
1467 io_request = cmd->io_request;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301468 io_request->RaidContext.VirtualDiskTgtId = cpu_to_le16(device_id);
adam radford9c915a82010-12-21 13:34:31 -08001469 io_request->RaidContext.status = 0;
1470 io_request->RaidContext.exStatus = 0;
1471
1472 req_desc = (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)cmd->request_desc;
1473
1474 start_lba_lo = 0;
1475 start_lba_hi = 0;
1476 fp_possible = 0;
1477
1478 /*
1479 * 6-byte READ(0x08) or WRITE(0x0A) cdb
1480 */
1481 if (scp->cmd_len == 6) {
adam radfordf9eff812012-10-01 19:27:07 -07001482 datalength = (u32) scp->cmnd[4];
adam radford9c915a82010-12-21 13:34:31 -08001483 start_lba_lo = ((u32) scp->cmnd[1] << 16) |
1484 ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3];
1485
1486 start_lba_lo &= 0x1FFFFF;
1487 }
1488
1489 /*
1490 * 10-byte READ(0x28) or WRITE(0x2A) cdb
1491 */
1492 else if (scp->cmd_len == 10) {
adam radfordf9eff812012-10-01 19:27:07 -07001493 datalength = (u32) scp->cmnd[8] |
adam radford9c915a82010-12-21 13:34:31 -08001494 ((u32) scp->cmnd[7] << 8);
1495 start_lba_lo = ((u32) scp->cmnd[2] << 24) |
1496 ((u32) scp->cmnd[3] << 16) |
1497 ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
1498 }
1499
1500 /*
1501 * 12-byte READ(0xA8) or WRITE(0xAA) cdb
1502 */
1503 else if (scp->cmd_len == 12) {
adam radfordf9eff812012-10-01 19:27:07 -07001504 datalength = ((u32) scp->cmnd[6] << 24) |
adam radford9c915a82010-12-21 13:34:31 -08001505 ((u32) scp->cmnd[7] << 16) |
1506 ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
1507 start_lba_lo = ((u32) scp->cmnd[2] << 24) |
1508 ((u32) scp->cmnd[3] << 16) |
1509 ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
1510 }
1511
1512 /*
1513 * 16-byte READ(0x88) or WRITE(0x8A) cdb
1514 */
1515 else if (scp->cmd_len == 16) {
adam radfordf9eff812012-10-01 19:27:07 -07001516 datalength = ((u32) scp->cmnd[10] << 24) |
adam radford9c915a82010-12-21 13:34:31 -08001517 ((u32) scp->cmnd[11] << 16) |
1518 ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13];
1519 start_lba_lo = ((u32) scp->cmnd[6] << 24) |
1520 ((u32) scp->cmnd[7] << 16) |
1521 ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
1522
1523 start_lba_hi = ((u32) scp->cmnd[2] << 24) |
1524 ((u32) scp->cmnd[3] << 16) |
1525 ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
1526 }
1527
1528 memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO));
1529 io_info.ldStartBlock = ((u64)start_lba_hi << 32) | start_lba_lo;
adam radfordf9eff812012-10-01 19:27:07 -07001530 io_info.numBlocks = datalength;
adam radford9c915a82010-12-21 13:34:31 -08001531 io_info.ldTgtId = device_id;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301532 io_request->DataLength = cpu_to_le32(scsi_bufflen(scp));
adam radford9c915a82010-12-21 13:34:31 -08001533
1534 if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
1535 io_info.isRead = 1;
1536
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301537 local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
adam radford9c915a82010-12-21 13:34:31 -08001538
1539 if ((MR_TargetIdToLdGet(device_id, local_map_ptr) >=
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301540 instance->fw_supported_vd_count) || (!fusion->fast_path_io)) {
adam radford9c915a82010-12-21 13:34:31 -08001541 io_request->RaidContext.regLockFlags = 0;
1542 fp_possible = 0;
1543 } else {
adam radford36807e62011-10-08 18:15:06 -07001544 if (MR_BuildRaidContext(instance, &io_info,
1545 &io_request->RaidContext,
adam radford21c9e162013-09-06 15:27:14 -07001546 local_map_ptr, &raidLUN))
adam radford9c915a82010-12-21 13:34:31 -08001547 fp_possible = io_info.fpOkForIo;
1548 }
1549
Christoph Hellwig16b85282015-04-15 09:44:37 -07001550 /* Use raw_smp_processor_id() for now until cmd->request->cpu is CPU
adam radfordc8e858f2011-10-08 18:15:13 -07001551 id by default, not CPU group id, otherwise all MSI-X queues won't
1552 be utilized */
1553 cmd->request_desc->SCSIIO.MSIxIndex = instance->msix_vectors ?
Christoph Hellwig16b85282015-04-15 09:44:37 -07001554 raw_smp_processor_id() % instance->msix_vectors : 0;
adam radfordc8e858f2011-10-08 18:15:13 -07001555
adam radford9c915a82010-12-21 13:34:31 -08001556 if (fp_possible) {
1557 megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp,
1558 local_map_ptr, start_lba_lo);
adam radford9c915a82010-12-21 13:34:31 -08001559 io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
1560 cmd->request_desc->SCSIIO.RequestFlags =
1561 (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY
1562 << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
Sumit.Saxena@lsi.com21d3c712013-05-22 12:31:43 +05301563 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
1564 (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
adam radford36807e62011-10-08 18:15:06 -07001565 if (io_request->RaidContext.regLockFlags ==
1566 REGION_TYPE_UNUSED)
1567 cmd->request_desc->SCSIIO.RequestFlags =
1568 (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
1569 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
1570 io_request->RaidContext.Type = MPI2_TYPE_CUDA;
1571 io_request->RaidContext.nseg = 0x1;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301572 io_request->IoFlags |= cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH);
adam radford36807e62011-10-08 18:15:06 -07001573 io_request->RaidContext.regLockFlags |=
1574 (MR_RL_FLAGS_GRANT_DESTINATION_CUDA |
1575 MR_RL_FLAGS_SEQ_NUM_ENABLE);
1576 }
adam radford9c915a82010-12-21 13:34:31 -08001577 if ((fusion->load_balance_info[device_id].loadBalanceFlag) &&
1578 (io_info.isRead)) {
1579 io_info.devHandle =
Sumit.Saxena@avagotech.comd2552eb2014-09-12 18:57:53 +05301580 get_updated_dev_handle(instance,
adam radford9c915a82010-12-21 13:34:31 -08001581 &fusion->load_balance_info[device_id],
1582 &io_info);
1583 scp->SCp.Status |= MEGASAS_LOAD_BALANCE_FLAG;
Sumit.Saxena@avagotech.comd2552eb2014-09-12 18:57:53 +05301584 cmd->pd_r1_lb = io_info.pd_after_lb;
adam radford9c915a82010-12-21 13:34:31 -08001585 } else
1586 scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG;
Sumit.Saxena@avagotech.com5765c5b2015-04-23 16:32:09 +05301587
1588 if ((raidLUN[0] == 1) &&
1589 (local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].validHandles > 2)) {
1590 instance->dev_handle = !(instance->dev_handle);
1591 io_info.devHandle =
1592 local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].devHandle[instance->dev_handle];
1593 }
1594
adam radford9c915a82010-12-21 13:34:31 -08001595 cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle;
1596 io_request->DevHandle = io_info.devHandle;
adam radford21c9e162013-09-06 15:27:14 -07001597 /* populate the LUN field */
1598 memcpy(io_request->LUN, raidLUN, 8);
adam radford9c915a82010-12-21 13:34:31 -08001599 } else {
1600 io_request->RaidContext.timeoutValue =
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301601 cpu_to_le16(local_map_ptr->raidMap.fpPdIoTimeoutSec);
adam radford9c915a82010-12-21 13:34:31 -08001602 cmd->request_desc->SCSIIO.RequestFlags =
1603 (MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO
1604 << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
Sumit.Saxena@lsi.com21d3c712013-05-22 12:31:43 +05301605 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
1606 (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
adam radford36807e62011-10-08 18:15:06 -07001607 if (io_request->RaidContext.regLockFlags ==
1608 REGION_TYPE_UNUSED)
1609 cmd->request_desc->SCSIIO.RequestFlags =
1610 (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
1611 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
1612 io_request->RaidContext.Type = MPI2_TYPE_CUDA;
1613 io_request->RaidContext.regLockFlags |=
1614 (MR_RL_FLAGS_GRANT_DESTINATION_CPU0 |
1615 MR_RL_FLAGS_SEQ_NUM_ENABLE);
1616 io_request->RaidContext.nseg = 0x1;
1617 }
1618 io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301619 io_request->DevHandle = cpu_to_le16(device_id);
adam radford9c915a82010-12-21 13:34:31 -08001620 } /* Not FP */
1621}
1622
1623/**
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301624 * megasas_build_ld_nonrw_fusion - prepares non rw ios for virtual disk
adam radford9c915a82010-12-21 13:34:31 -08001625 * @instance: Adapter soft state
1626 * @scp: SCSI command
1627 * @cmd: Command to be prepared
1628 *
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301629 * Prepares the io_request frame for non-rw io cmds for vd.
adam radford9c915a82010-12-21 13:34:31 -08001630 */
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301631static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance,
1632 struct scsi_cmnd *scmd, struct megasas_cmd_fusion *cmd)
adam radford9c915a82010-12-21 13:34:31 -08001633{
1634 u32 device_id;
1635 struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
1636 u16 pd_index = 0;
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301637 struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
adam radford9c915a82010-12-21 13:34:31 -08001638 struct fusion_context *fusion = instance->ctrl_context;
adam radford21c9e162013-09-06 15:27:14 -07001639 u8 span, physArm;
Christoph Hellwig9ab9ed382015-04-23 16:32:54 +05301640 __le16 devHandle;
adam radford21c9e162013-09-06 15:27:14 -07001641 u32 ld, arRef, pd;
1642 struct MR_LD_RAID *raid;
1643 struct RAID_CONTEXT *pRAID_Context;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301644 u8 fp_possible = 1;
adam radford9c915a82010-12-21 13:34:31 -08001645
1646 io_request = cmd->io_request;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301647 device_id = MEGASAS_DEV_INDEX(scmd);
1648 pd_index = MEGASAS_PD_INDEX(scmd);
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301649 local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301650 io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301651 /* get RAID_Context pointer */
1652 pRAID_Context = &io_request->RaidContext;
1653 /* Check with FW team */
1654 pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
1655 pRAID_Context->regLockRowLBA = 0;
1656 pRAID_Context->regLockLength = 0;
adam radford21c9e162013-09-06 15:27:14 -07001657
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301658 if (fusion->fast_path_io && (
1659 device_id < instance->fw_supported_vd_count)) {
Sumit.Saxena@avagotech.comab2f0602015-01-05 20:06:08 +05301660
adam radford21c9e162013-09-06 15:27:14 -07001661 ld = MR_TargetIdToLdGet(device_id, local_map_ptr);
Sumit.Saxena@avagotech.comab2f0602015-01-05 20:06:08 +05301662 if (ld >= instance->fw_supported_vd_count)
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301663 fp_possible = 0;
adam radford21c9e162013-09-06 15:27:14 -07001664
1665 raid = MR_LdRaidGet(ld, local_map_ptr);
adam radford21c9e162013-09-06 15:27:14 -07001666 if (!(raid->capability.fpNonRWCapable))
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301667 fp_possible = 0;
1668 } else
1669 fp_possible = 0;
adam radford21c9e162013-09-06 15:27:14 -07001670
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301671 if (!fp_possible) {
1672 io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
1673 io_request->DevHandle = cpu_to_le16(device_id);
1674 io_request->LUN[1] = scmd->device->lun;
1675 pRAID_Context->timeoutValue =
1676 cpu_to_le16 (scmd->request->timeout / HZ);
1677 cmd->request_desc->SCSIIO.RequestFlags =
1678 (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
1679 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
1680 } else {
adam radford21c9e162013-09-06 15:27:14 -07001681
1682 /* set RAID context values */
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301683 pRAID_Context->configSeqNum = raid->seqNum;
1684 pRAID_Context->regLockFlags = REGION_TYPE_SHARED_READ;
1685 pRAID_Context->timeoutValue = cpu_to_le16(raid->fpIoTimeoutForLd);
adam radford21c9e162013-09-06 15:27:14 -07001686
1687 /* get the DevHandle for the PD (since this is
1688 fpNonRWCapable, this is a single disk RAID0) */
1689 span = physArm = 0;
1690 arRef = MR_LdSpanArrayGet(ld, span, local_map_ptr);
1691 pd = MR_ArPdGet(arRef, physArm, local_map_ptr);
1692 devHandle = MR_PdDevHandleGet(pd, local_map_ptr);
1693
1694 /* build request descriptor */
1695 cmd->request_desc->SCSIIO.RequestFlags =
1696 (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301697 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
adam radford21c9e162013-09-06 15:27:14 -07001698 cmd->request_desc->SCSIIO.DevHandle = devHandle;
1699
1700 /* populate the LUN field */
1701 memcpy(io_request->LUN, raid->LUN, 8);
1702
1703 /* build the raidScsiIO structure */
1704 io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
1705 io_request->DevHandle = devHandle;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301706 }
1707}
adam radford21c9e162013-09-06 15:27:14 -07001708
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301709/**
1710 * megasas_build_syspd_fusion - prepares rw/non-rw ios for syspd
1711 * @instance: Adapter soft state
1712 * @scp: SCSI command
1713 * @cmd: Command to be prepared
1714 * @fp_possible: parameter to detect fast path or firmware path io.
1715 *
1716 * Prepares the io_request frame for rw/non-rw io cmds for syspds
1717 */
1718static void
1719megasas_build_syspd_fusion(struct megasas_instance *instance,
1720 struct scsi_cmnd *scmd, struct megasas_cmd_fusion *cmd, u8 fp_possible)
1721{
1722 u32 device_id;
1723 struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
1724 u16 pd_index = 0;
1725 u16 os_timeout_value;
1726 u16 timeout_limit;
1727 struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
1728 struct RAID_CONTEXT *pRAID_Context;
1729 struct fusion_context *fusion = instance->ctrl_context;
adam radford21c9e162013-09-06 15:27:14 -07001730
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301731 device_id = MEGASAS_DEV_INDEX(scmd);
1732 pd_index = MEGASAS_PD_INDEX(scmd);
1733 os_timeout_value = scmd->request->timeout / HZ;
1734
1735 io_request = cmd->io_request;
1736 /* get RAID_Context pointer */
1737 pRAID_Context = &io_request->RaidContext;
1738 io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
1739 io_request->LUN[1] = scmd->device->lun;
1740 pRAID_Context->RAIDFlags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD
1741 << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT;
1742
1743 pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
1744 pRAID_Context->configSeqNum = 0;
1745 local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
1746 io_request->DevHandle =
1747 local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
1748
1749 cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle;
1750 cmd->request_desc->SCSIIO.MSIxIndex =
1751 instance->msix_vectors ?
1752 (raw_smp_processor_id() % instance->msix_vectors) : 0;
1753
1754
1755 if (!fp_possible) {
1756 /* system pd firmware path */
adam radford9c915a82010-12-21 13:34:31 -08001757 io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
adam radford9c915a82010-12-21 13:34:31 -08001758 cmd->request_desc->SCSIIO.RequestFlags =
1759 (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301760 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
1761 pRAID_Context->timeoutValue = cpu_to_le16(os_timeout_value);
1762 } else {
1763 /* system pd Fast Path */
1764 io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
1765 pRAID_Context->regLockFlags = 0;
1766 pRAID_Context->regLockRowLBA = 0;
1767 pRAID_Context->regLockLength = 0;
1768 timeout_limit = (scmd->device->type == TYPE_DISK) ?
1769 255 : 0xFFFF;
1770 pRAID_Context->timeoutValue =
1771 cpu_to_le16((os_timeout_value > timeout_limit) ?
1772 timeout_limit : os_timeout_value);
1773 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
1774 (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
1775 cmd->request_desc->SCSIIO.RequestFlags |=
1776 (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
1777 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
1778 pRAID_Context->Type = MPI2_TYPE_CUDA;
1779 pRAID_Context->nseg = 0x1;
1780 io_request->IoFlags |=
1781 cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH);
1782 }
1783 cmd->request_desc->SCSIIO.RequestFlags =
1784 (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
1785 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
adam radford9c915a82010-12-21 13:34:31 -08001786 }
adam radford9c915a82010-12-21 13:34:31 -08001787}
1788
1789/**
1790 * megasas_build_io_fusion - Prepares IOs to devices
1791 * @instance: Adapter soft state
1792 * @scp: SCSI command
1793 * @cmd: Command to be prepared
1794 *
1795 * Invokes helper functions to prepare request frames
1796 * and sets flags appropriate for IO/Non-IO cmd
1797 */
1798int
1799megasas_build_io_fusion(struct megasas_instance *instance,
1800 struct scsi_cmnd *scp,
1801 struct megasas_cmd_fusion *cmd)
1802{
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301803 u32 sge_count;
1804 u8 cmd_type;
adam radford9c915a82010-12-21 13:34:31 -08001805 struct MPI2_RAID_SCSI_IO_REQUEST *io_request = cmd->io_request;
1806
adam radford9c915a82010-12-21 13:34:31 -08001807 /* Zero out some fields so they don't get reused */
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02001808 memset(io_request->LUN, 0x0, 8);
adam radford9c915a82010-12-21 13:34:31 -08001809 io_request->CDB.EEDP32.PrimaryReferenceTag = 0;
1810 io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0;
1811 io_request->EEDPFlags = 0;
1812 io_request->Control = 0;
1813 io_request->EEDPBlockSize = 0;
adam radford36807e62011-10-08 18:15:06 -07001814 io_request->ChainOffset = 0;
adam radford9c915a82010-12-21 13:34:31 -08001815 io_request->RaidContext.RAIDFlags = 0;
adam radford36807e62011-10-08 18:15:06 -07001816 io_request->RaidContext.Type = 0;
1817 io_request->RaidContext.nseg = 0;
adam radford9c915a82010-12-21 13:34:31 -08001818
1819 memcpy(io_request->CDB.CDB32, scp->cmnd, scp->cmd_len);
1820 /*
1821 * Just the CDB length,rest of the Flags are zero
1822 * This will be modified for FP in build_ldio_fusion
1823 */
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301824 io_request->IoFlags = cpu_to_le16(scp->cmd_len);
adam radford9c915a82010-12-21 13:34:31 -08001825
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301826 switch (cmd_type = megasas_cmd_type(scp)) {
1827 case READ_WRITE_LDIO:
adam radford9c915a82010-12-21 13:34:31 -08001828 megasas_build_ldio_fusion(instance, scp, cmd);
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301829 break;
1830 case NON_READ_WRITE_LDIO:
1831 megasas_build_ld_nonrw_fusion(instance, scp, cmd);
1832 break;
1833 case READ_WRITE_SYSPDIO:
1834 case NON_READ_WRITE_SYSPDIO:
1835 if (instance->secure_jbod_support &&
1836 (cmd_type == NON_READ_WRITE_SYSPDIO))
1837 megasas_build_syspd_fusion(instance, scp, cmd, 0);
1838 else
1839 megasas_build_syspd_fusion(instance, scp, cmd, 1);
1840 break;
1841 default:
1842 break;
1843 }
adam radford9c915a82010-12-21 13:34:31 -08001844
1845 /*
1846 * Construct SGL
1847 */
1848
1849 sge_count =
1850 megasas_make_sgl_fusion(instance, scp,
1851 (struct MPI25_IEEE_SGE_CHAIN64 *)
1852 &io_request->SGL, cmd);
1853
1854 if (sge_count > instance->max_num_sge) {
1855 printk(KERN_ERR "megasas: Error. sge_count (0x%x) exceeds "
1856 "max (0x%x) allowed\n", sge_count,
1857 instance->max_num_sge);
1858 return 1;
1859 }
1860
1861 io_request->RaidContext.numSGE = sge_count;
1862
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301863 io_request->SGLFlags = cpu_to_le16(MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
adam radford9c915a82010-12-21 13:34:31 -08001864
1865 if (scp->sc_data_direction == PCI_DMA_TODEVICE)
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301866 io_request->Control |= cpu_to_le32(MPI2_SCSIIO_CONTROL_WRITE);
adam radford9c915a82010-12-21 13:34:31 -08001867 else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301868 io_request->Control |= cpu_to_le32(MPI2_SCSIIO_CONTROL_READ);
adam radford9c915a82010-12-21 13:34:31 -08001869
1870 io_request->SGLOffset0 =
1871 offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL) / 4;
1872
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301873 io_request->SenseBufferLowAddress = cpu_to_le32(cmd->sense_phys_addr);
adam radford9c915a82010-12-21 13:34:31 -08001874 io_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
1875
1876 cmd->scmd = scp;
1877 scp->SCp.ptr = (char *)cmd;
1878
1879 return 0;
1880}
1881
1882union MEGASAS_REQUEST_DESCRIPTOR_UNION *
1883megasas_get_request_descriptor(struct megasas_instance *instance, u16 index)
1884{
1885 u8 *p;
1886 struct fusion_context *fusion;
1887
1888 if (index >= instance->max_fw_cmds) {
1889 printk(KERN_ERR "megasas: Invalid SMID (0x%x)request for "
adam radford229fe472014-03-10 02:51:56 -07001890 "descriptor for scsi%d\n", index,
1891 instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08001892 return NULL;
1893 }
1894 fusion = instance->ctrl_context;
1895 p = fusion->req_frames_desc
1896 +sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *index;
1897
1898 return (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)p;
1899}
1900
1901/**
1902 * megasas_build_and_issue_cmd_fusion -Main routine for building and
1903 * issuing non IOCTL cmd
1904 * @instance: Adapter soft state
1905 * @scmd: pointer to scsi cmd from OS
1906 */
1907static u32
1908megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
1909 struct scsi_cmnd *scmd)
1910{
1911 struct megasas_cmd_fusion *cmd;
1912 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
1913 u32 index;
1914 struct fusion_context *fusion;
1915
1916 fusion = instance->ctrl_context;
1917
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05301918 cmd = megasas_get_cmd_fusion(instance, scmd->request->tag);
adam radford9c915a82010-12-21 13:34:31 -08001919
1920 index = cmd->index;
1921
1922 req_desc = megasas_get_request_descriptor(instance, index-1);
1923 if (!req_desc)
1924 return 1;
1925
1926 req_desc->Words = 0;
1927 cmd->request_desc = req_desc;
adam radford9c915a82010-12-21 13:34:31 -08001928
1929 if (megasas_build_io_fusion(instance, scmd, cmd)) {
1930 megasas_return_cmd_fusion(instance, cmd);
1931 printk(KERN_ERR "megasas: Error building command.\n");
1932 cmd->request_desc = NULL;
1933 return 1;
1934 }
1935
1936 req_desc = cmd->request_desc;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301937 req_desc->SCSIIO.SMID = cpu_to_le16(index);
adam radford9c915a82010-12-21 13:34:31 -08001938
1939 if (cmd->io_request->ChainOffset != 0 &&
1940 cmd->io_request->ChainOffset != 0xF)
1941 printk(KERN_ERR "megasas: The chain offset value is not "
1942 "correct : %x\n", cmd->io_request->ChainOffset);
1943
1944 /*
1945 * Issue the command to the FW
1946 */
1947 atomic_inc(&instance->fw_outstanding);
1948
1949 instance->instancet->fire_cmd(instance,
1950 req_desc->u.low, req_desc->u.high,
1951 instance->reg_set);
1952
1953 return 0;
1954}
1955
1956/**
1957 * complete_cmd_fusion - Completes command
1958 * @instance: Adapter soft state
1959 * Completes all commands that is in reply descriptor queue
1960 */
1961int
adam radfordc8e858f2011-10-08 18:15:13 -07001962complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
adam radford9c915a82010-12-21 13:34:31 -08001963{
1964 union MPI2_REPLY_DESCRIPTORS_UNION *desc;
1965 struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
1966 struct MPI2_RAID_SCSI_IO_REQUEST *scsi_io_req;
1967 struct fusion_context *fusion;
1968 struct megasas_cmd *cmd_mfi;
1969 struct megasas_cmd_fusion *cmd_fusion;
1970 u16 smid, num_completed;
Sumit.Saxena@avagotech.comd2552eb2014-09-12 18:57:53 +05301971 u8 reply_descript_type;
adam radford9c915a82010-12-21 13:34:31 -08001972 u32 status, extStatus, device_id;
1973 union desc_value d_val;
1974 struct LD_LOAD_BALANCE_INFO *lbinfo;
Sumit.Saxena@avagotech.comdb4fc862014-09-12 18:57:23 +05301975 int threshold_reply_count = 0;
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05301976 struct scsi_cmnd *scmd_local = NULL;
adam radford9c915a82010-12-21 13:34:31 -08001977
1978 fusion = instance->ctrl_context;
1979
1980 if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
1981 return IRQ_HANDLED;
1982
1983 desc = fusion->reply_frames_desc;
adam radfordc8e858f2011-10-08 18:15:13 -07001984 desc += ((MSIxIndex * fusion->reply_alloc_sz)/
1985 sizeof(union MPI2_REPLY_DESCRIPTORS_UNION)) +
1986 fusion->last_reply_idx[MSIxIndex];
adam radford9c915a82010-12-21 13:34:31 -08001987
1988 reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
1989
1990 d_val.word = desc->Words;
1991
1992 reply_descript_type = reply_desc->ReplyFlags &
1993 MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
1994
1995 if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
1996 return IRQ_NONE;
1997
adam radford9c915a82010-12-21 13:34:31 -08001998 num_completed = 0;
1999
Christoph Hellwigc6f5bf82015-04-23 16:33:09 +05302000 while (d_val.u.low != cpu_to_le32(UINT_MAX) &&
2001 d_val.u.high != cpu_to_le32(UINT_MAX)) {
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302002 smid = le16_to_cpu(reply_desc->SMID);
adam radford9c915a82010-12-21 13:34:31 -08002003
2004 cmd_fusion = fusion->cmd_list[smid - 1];
2005
2006 scsi_io_req =
2007 (struct MPI2_RAID_SCSI_IO_REQUEST *)
2008 cmd_fusion->io_request;
2009
2010 if (cmd_fusion->scmd)
2011 cmd_fusion->scmd->SCp.ptr = NULL;
2012
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302013 scmd_local = cmd_fusion->scmd;
adam radford9c915a82010-12-21 13:34:31 -08002014 status = scsi_io_req->RaidContext.status;
2015 extStatus = scsi_io_req->RaidContext.exStatus;
2016
2017 switch (scsi_io_req->Function) {
2018 case MPI2_FUNCTION_SCSI_IO_REQUEST: /*Fast Path IO.*/
2019 /* Update load balancing info */
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302020 device_id = MEGASAS_DEV_INDEX(scmd_local);
adam radford9c915a82010-12-21 13:34:31 -08002021 lbinfo = &fusion->load_balance_info[device_id];
2022 if (cmd_fusion->scmd->SCp.Status &
2023 MEGASAS_LOAD_BALANCE_FLAG) {
Sumit.Saxena@avagotech.comd2552eb2014-09-12 18:57:53 +05302024 atomic_dec(&lbinfo->scsi_pending_cmds[cmd_fusion->pd_r1_lb]);
adam radford9c915a82010-12-21 13:34:31 -08002025 cmd_fusion->scmd->SCp.Status &=
2026 ~MEGASAS_LOAD_BALANCE_FLAG;
2027 }
2028 if (reply_descript_type ==
2029 MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
2030 if (megasas_dbg_lvl == 5)
2031 printk(KERN_ERR "\nmegasas: FAST Path "
2032 "IO Success\n");
2033 }
2034 /* Fall thru and complete IO */
2035 case MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST: /* LD-IO Path */
2036 /* Map the FW Cmd Status */
2037 map_cmd_status(cmd_fusion, status, extStatus);
adam radford9c915a82010-12-21 13:34:31 -08002038 scsi_io_req->RaidContext.status = 0;
2039 scsi_io_req->RaidContext.exStatus = 0;
2040 megasas_return_cmd_fusion(instance, cmd_fusion);
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302041 scsi_dma_unmap(scmd_local);
2042 scmd_local->scsi_done(scmd_local);
adam radford9c915a82010-12-21 13:34:31 -08002043 atomic_dec(&instance->fw_outstanding);
2044
2045 break;
2046 case MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST: /*MFI command */
2047 cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +05302048
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302049 /* Poll mode. Dummy free.
2050 * In case of Interrupt mode, caller has reverse check.
2051 */
2052 if (cmd_mfi->flags & DRV_DCMD_POLLED_MODE) {
2053 cmd_mfi->flags &= ~DRV_DCMD_POLLED_MODE;
2054 megasas_return_cmd(instance, cmd_mfi);
2055 } else
2056 megasas_complete_cmd(instance, cmd_mfi, DID_OK);
adam radford9c915a82010-12-21 13:34:31 -08002057 break;
2058 }
2059
adam radfordc8e858f2011-10-08 18:15:13 -07002060 fusion->last_reply_idx[MSIxIndex]++;
2061 if (fusion->last_reply_idx[MSIxIndex] >=
2062 fusion->reply_q_depth)
2063 fusion->last_reply_idx[MSIxIndex] = 0;
adam radford9c915a82010-12-21 13:34:31 -08002064
Christoph Hellwigc6f5bf82015-04-23 16:33:09 +05302065 desc->Words = cpu_to_le64(ULLONG_MAX);
adam radford9c915a82010-12-21 13:34:31 -08002066 num_completed++;
Sumit.Saxena@avagotech.comdb4fc862014-09-12 18:57:23 +05302067 threshold_reply_count++;
adam radford9c915a82010-12-21 13:34:31 -08002068
2069 /* Get the next reply descriptor */
adam radfordc8e858f2011-10-08 18:15:13 -07002070 if (!fusion->last_reply_idx[MSIxIndex])
2071 desc = fusion->reply_frames_desc +
2072 ((MSIxIndex * fusion->reply_alloc_sz)/
2073 sizeof(union MPI2_REPLY_DESCRIPTORS_UNION));
adam radford9c915a82010-12-21 13:34:31 -08002074 else
2075 desc++;
2076
2077 reply_desc =
2078 (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
2079
2080 d_val.word = desc->Words;
2081
2082 reply_descript_type = reply_desc->ReplyFlags &
2083 MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
2084
2085 if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
2086 break;
Sumit.Saxena@avagotech.comdb4fc862014-09-12 18:57:23 +05302087 /*
2088 * Write to reply post host index register after completing threshold
2089 * number of reply counts and still there are more replies in reply queue
2090 * pending to be completed
2091 */
2092 if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) {
2093 if ((instance->pdev->device ==
2094 PCI_DEVICE_ID_LSI_INVADER) ||
2095 (instance->pdev->device ==
2096 PCI_DEVICE_ID_LSI_FURY))
2097 writel(((MSIxIndex & 0x7) << 24) |
2098 fusion->last_reply_idx[MSIxIndex],
2099 instance->reply_post_host_index_addr[MSIxIndex/8]);
2100 else
2101 writel((MSIxIndex << 24) |
2102 fusion->last_reply_idx[MSIxIndex],
2103 instance->reply_post_host_index_addr[0]);
2104 threshold_reply_count = 0;
2105 }
adam radford9c915a82010-12-21 13:34:31 -08002106 }
2107
2108 if (!num_completed)
2109 return IRQ_NONE;
2110
2111 wmb();
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +05302112 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
2113 (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
2114 writel(((MSIxIndex & 0x7) << 24) |
2115 fusion->last_reply_idx[MSIxIndex],
2116 instance->reply_post_host_index_addr[MSIxIndex/8]);
2117 else
2118 writel((MSIxIndex << 24) |
2119 fusion->last_reply_idx[MSIxIndex],
2120 instance->reply_post_host_index_addr[0]);
adam radford53ef2bb2011-02-24 20:56:05 -08002121 megasas_check_and_restore_queue_depth(instance);
adam radford9c915a82010-12-21 13:34:31 -08002122 return IRQ_HANDLED;
2123}
2124
2125/**
2126 * megasas_complete_cmd_dpc_fusion - Completes command
2127 * @instance: Adapter soft state
2128 *
2129 * Tasklet to complete cmds
2130 */
2131void
2132megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
2133{
2134 struct megasas_instance *instance =
2135 (struct megasas_instance *)instance_addr;
2136 unsigned long flags;
adam radfordc8e858f2011-10-08 18:15:13 -07002137 u32 count, MSIxIndex;
2138
2139 count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
adam radford9c915a82010-12-21 13:34:31 -08002140
2141 /* If we have already declared adapter dead, donot complete cmds */
2142 spin_lock_irqsave(&instance->hba_lock, flags);
2143 if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
2144 spin_unlock_irqrestore(&instance->hba_lock, flags);
2145 return;
2146 }
2147 spin_unlock_irqrestore(&instance->hba_lock, flags);
2148
adam radfordc8e858f2011-10-08 18:15:13 -07002149 for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++)
2150 complete_cmd_fusion(instance, MSIxIndex);
adam radford9c915a82010-12-21 13:34:31 -08002151}
2152
2153/**
2154 * megasas_isr_fusion - isr entry point
2155 */
2156irqreturn_t megasas_isr_fusion(int irq, void *devp)
2157{
adam radfordc8e858f2011-10-08 18:15:13 -07002158 struct megasas_irq_context *irq_context = devp;
2159 struct megasas_instance *instance = irq_context->instance;
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05302160 u32 mfiStatus, fw_state, dma_state;
adam radford9c915a82010-12-21 13:34:31 -08002161
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +05302162 if (instance->mask_interrupts)
2163 return IRQ_NONE;
2164
adam radfordc8e858f2011-10-08 18:15:13 -07002165 if (!instance->msix_vectors) {
adam radford9c915a82010-12-21 13:34:31 -08002166 mfiStatus = instance->instancet->clear_intr(instance->reg_set);
2167 if (!mfiStatus)
2168 return IRQ_NONE;
2169 }
2170
2171 /* If we are resetting, bail */
adam radford6497b242011-10-08 18:14:50 -07002172 if (test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags)) {
2173 instance->instancet->clear_intr(instance->reg_set);
adam radford9c915a82010-12-21 13:34:31 -08002174 return IRQ_HANDLED;
adam radford6497b242011-10-08 18:14:50 -07002175 }
adam radford9c915a82010-12-21 13:34:31 -08002176
adam radfordc8e858f2011-10-08 18:15:13 -07002177 if (!complete_cmd_fusion(instance, irq_context->MSIxIndex)) {
adam radford6497b242011-10-08 18:14:50 -07002178 instance->instancet->clear_intr(instance->reg_set);
adam radford9c915a82010-12-21 13:34:31 -08002179 /* If we didn't complete any commands, check for FW fault */
2180 fw_state = instance->instancet->read_fw_status_reg(
2181 instance->reg_set) & MFI_STATE_MASK;
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05302182 dma_state = instance->instancet->read_fw_status_reg
2183 (instance->reg_set) & MFI_STATE_DMADONE;
2184 if (instance->crash_dump_drv_support &&
2185 instance->crash_dump_app_support) {
2186 /* Start collecting crash, if DMA bit is done */
2187 if ((fw_state == MFI_STATE_FAULT) && dma_state)
2188 schedule_work(&instance->crash_init);
2189 else if (fw_state == MFI_STATE_FAULT)
2190 schedule_work(&instance->work_init);
2191 } else if (fw_state == MFI_STATE_FAULT) {
adam radford229fe472014-03-10 02:51:56 -07002192 printk(KERN_WARNING "megaraid_sas: Iop2SysDoorbellInt"
2193 "for scsi%d\n", instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002194 schedule_work(&instance->work_init);
adam radford229fe472014-03-10 02:51:56 -07002195 }
adam radford9c915a82010-12-21 13:34:31 -08002196 }
2197
2198 return IRQ_HANDLED;
2199}
2200
2201/**
2202 * build_mpt_mfi_pass_thru - builds a cmd fo MFI Pass thru
2203 * @instance: Adapter soft state
2204 * mfi_cmd: megasas_cmd pointer
2205 *
2206 */
2207u8
2208build_mpt_mfi_pass_thru(struct megasas_instance *instance,
2209 struct megasas_cmd *mfi_cmd)
2210{
2211 struct MPI25_IEEE_SGE_CHAIN64 *mpi25_ieee_chain;
2212 struct MPI2_RAID_SCSI_IO_REQUEST *io_req;
2213 struct megasas_cmd_fusion *cmd;
2214 struct fusion_context *fusion;
2215 struct megasas_header *frame_hdr = &mfi_cmd->frame->hdr;
2216
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302217 fusion = instance->ctrl_context;
2218
2219 cmd = megasas_get_cmd_fusion(instance,
2220 instance->max_scsi_cmds + mfi_cmd->index);
adam radford9c915a82010-12-21 13:34:31 -08002221
2222 /* Save the smid. To be used for returning the cmd */
2223 mfi_cmd->context.smid = cmd->index;
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +05302224
adam radford9c915a82010-12-21 13:34:31 -08002225 /*
2226 * For cmds where the flag is set, store the flag and check
2227 * on completion. For cmds with this flag, don't call
2228 * megasas_complete_cmd
2229 */
2230
Sumit.Saxena@avagotech.com6e755dd2014-11-17 15:24:28 +05302231 if (frame_hdr->flags & cpu_to_le16(MFI_FRAME_DONT_POST_IN_REPLY_QUEUE))
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302232 mfi_cmd->flags |= DRV_DCMD_POLLED_MODE;
adam radford9c915a82010-12-21 13:34:31 -08002233
adam radford9c915a82010-12-21 13:34:31 -08002234 io_req = cmd->io_request;
adam radford36807e62011-10-08 18:15:06 -07002235
Sumit.Saxena@lsi.com21d3c712013-05-22 12:31:43 +05302236 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
2237 (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
adam radford36807e62011-10-08 18:15:06 -07002238 struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end =
2239 (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL;
2240 sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
2241 sgl_ptr_end->Flags = 0;
2242 }
2243
adam radford9c915a82010-12-21 13:34:31 -08002244 mpi25_ieee_chain =
2245 (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain;
2246
2247 io_req->Function = MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST;
2248 io_req->SGLOffset0 = offsetof(struct MPI2_RAID_SCSI_IO_REQUEST,
2249 SGL) / 4;
2250 io_req->ChainOffset = fusion->chain_offset_mfi_pthru;
2251
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302252 mpi25_ieee_chain->Address = cpu_to_le64(mfi_cmd->frame_phys_addr);
adam radford9c915a82010-12-21 13:34:31 -08002253
2254 mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT |
2255 MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
2256
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302257 mpi25_ieee_chain->Length = cpu_to_le32(MEGASAS_MAX_SZ_CHAIN_FRAME);
adam radford9c915a82010-12-21 13:34:31 -08002258
2259 return 0;
2260}
2261
2262/**
2263 * build_mpt_cmd - Calls helper function to build a cmd MFI Pass thru cmd
2264 * @instance: Adapter soft state
2265 * @cmd: mfi cmd to build
2266 *
2267 */
2268union MEGASAS_REQUEST_DESCRIPTOR_UNION *
2269build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
2270{
2271 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
2272 u16 index;
2273
2274 if (build_mpt_mfi_pass_thru(instance, cmd)) {
2275 printk(KERN_ERR "Couldn't build MFI pass thru cmd\n");
2276 return NULL;
2277 }
2278
2279 index = cmd->context.smid;
2280
2281 req_desc = megasas_get_request_descriptor(instance, index - 1);
2282
2283 if (!req_desc)
2284 return NULL;
2285
2286 req_desc->Words = 0;
2287 req_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
2288 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
2289
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302290 req_desc->SCSIIO.SMID = cpu_to_le16(index);
adam radford9c915a82010-12-21 13:34:31 -08002291
2292 return req_desc;
2293}
2294
2295/**
2296 * megasas_issue_dcmd_fusion - Issues a MFI Pass thru cmd
2297 * @instance: Adapter soft state
2298 * @cmd: mfi cmd pointer
2299 *
2300 */
2301void
2302megasas_issue_dcmd_fusion(struct megasas_instance *instance,
2303 struct megasas_cmd *cmd)
2304{
2305 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
adam radford9c915a82010-12-21 13:34:31 -08002306
2307 req_desc = build_mpt_cmd(instance, cmd);
2308 if (!req_desc) {
2309 printk(KERN_ERR "Couldn't issue MFI pass thru cmd\n");
2310 return;
2311 }
adam radford9c915a82010-12-21 13:34:31 -08002312 instance->instancet->fire_cmd(instance, req_desc->u.low,
2313 req_desc->u.high, instance->reg_set);
2314}
2315
2316/**
2317 * megasas_release_fusion - Reverses the FW initialization
2318 * @intance: Adapter soft state
2319 */
2320void
2321megasas_release_fusion(struct megasas_instance *instance)
2322{
2323 megasas_free_cmds(instance);
2324 megasas_free_cmds_fusion(instance);
2325
2326 iounmap(instance->reg_set);
2327
2328 pci_release_selected_regions(instance->pdev, instance->bar);
2329}
2330
2331/**
2332 * megasas_read_fw_status_reg_fusion - returns the current FW status value
2333 * @regs: MFI register set
2334 */
2335static u32
2336megasas_read_fw_status_reg_fusion(struct megasas_register_set __iomem *regs)
2337{
2338 return readl(&(regs)->outbound_scratch_pad);
2339}
2340
2341/**
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05302342 * megasas_alloc_host_crash_buffer - Host buffers for Crash dump collection from Firmware
2343 * @instance: Controller's soft instance
2344 * return: Number of allocated host crash buffers
2345 */
2346static void
2347megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
2348{
2349 unsigned int i;
2350
2351 instance->crash_buf_pages = get_order(CRASH_DMA_BUF_SIZE);
2352 for (i = 0; i < MAX_CRASH_DUMP_SIZE; i++) {
2353 instance->crash_buf[i] = (void *)__get_free_pages(GFP_KERNEL,
2354 instance->crash_buf_pages);
2355 if (!instance->crash_buf[i]) {
2356 dev_info(&instance->pdev->dev, "Firmware crash dump "
2357 "memory allocation failed at index %d\n", i);
2358 break;
2359 }
Sumit.Saxena@avagotech.comd009b572014-11-17 15:24:13 +05302360 memset(instance->crash_buf[i], 0,
2361 ((1 << PAGE_SHIFT) << instance->crash_buf_pages));
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05302362 }
2363 instance->drv_buf_alloc = i;
2364}
2365
2366/**
2367 * megasas_free_host_crash_buffer - Host buffers for Crash dump collection from Firmware
2368 * @instance: Controller's soft instance
2369 */
2370void
2371megasas_free_host_crash_buffer(struct megasas_instance *instance)
2372{
2373 unsigned int i
2374;
2375 for (i = 0; i < instance->drv_buf_alloc; i++) {
2376 if (instance->crash_buf[i])
2377 free_pages((ulong)instance->crash_buf[i],
2378 instance->crash_buf_pages);
2379 }
2380 instance->drv_buf_index = 0;
2381 instance->drv_buf_alloc = 0;
2382 instance->fw_crash_state = UNAVAILABLE;
2383 instance->fw_crash_buffer_size = 0;
2384}
2385
2386/**
adam radford9c915a82010-12-21 13:34:31 -08002387 * megasas_adp_reset_fusion - For controller reset
2388 * @regs: MFI register set
2389 */
2390static int
2391megasas_adp_reset_fusion(struct megasas_instance *instance,
2392 struct megasas_register_set __iomem *regs)
2393{
2394 return 0;
2395}
2396
2397/**
2398 * megasas_check_reset_fusion - For controller reset check
2399 * @regs: MFI register set
2400 */
2401static int
2402megasas_check_reset_fusion(struct megasas_instance *instance,
2403 struct megasas_register_set __iomem *regs)
2404{
2405 return 0;
2406}
2407
2408/* This function waits for outstanding commands on fusion to complete */
adam radford229fe472014-03-10 02:51:56 -07002409int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance,
2410 int iotimeout, int *convert)
adam radford9c915a82010-12-21 13:34:31 -08002411{
adam radford229fe472014-03-10 02:51:56 -07002412 int i, outstanding, retval = 0, hb_seconds_missed = 0;
adam radfordc007b8b2012-07-17 18:20:24 -07002413 u32 fw_state;
adam radford9c915a82010-12-21 13:34:31 -08002414
adam radfordc007b8b2012-07-17 18:20:24 -07002415 for (i = 0; i < resetwaittime; i++) {
adam radford9c915a82010-12-21 13:34:31 -08002416 /* Check if firmware is in fault state */
2417 fw_state = instance->instancet->read_fw_status_reg(
2418 instance->reg_set) & MFI_STATE_MASK;
2419 if (fw_state == MFI_STATE_FAULT) {
2420 printk(KERN_WARNING "megasas: Found FW in FAULT state,"
adam radford229fe472014-03-10 02:51:56 -07002421 " will reset adapter scsi%d.\n",
2422 instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002423 retval = 1;
2424 goto out;
2425 }
adam radford229fe472014-03-10 02:51:56 -07002426 /* If SR-IOV VF mode & heartbeat timeout, don't wait */
2427 if (instance->requestorId && !iotimeout) {
2428 retval = 1;
2429 goto out;
2430 }
2431
2432 /* If SR-IOV VF mode & I/O timeout, check for HB timeout */
2433 if (instance->requestorId && iotimeout) {
2434 if (instance->hb_host_mem->HB.fwCounter !=
2435 instance->hb_host_mem->HB.driverCounter) {
2436 instance->hb_host_mem->HB.driverCounter =
2437 instance->hb_host_mem->HB.fwCounter;
2438 hb_seconds_missed = 0;
2439 } else {
2440 hb_seconds_missed++;
2441 if (hb_seconds_missed ==
2442 (MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF/HZ)) {
2443 printk(KERN_WARNING "megasas: SR-IOV:"
2444 " Heartbeat never completed "
2445 " while polling during I/O "
2446 " timeout handling for "
2447 "scsi%d.\n",
2448 instance->host->host_no);
2449 *convert = 1;
2450 retval = 1;
2451 goto out;
2452 }
2453 }
2454 }
adam radford9c915a82010-12-21 13:34:31 -08002455
2456 outstanding = atomic_read(&instance->fw_outstanding);
2457 if (!outstanding)
2458 goto out;
2459
2460 if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
2461 printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
adam radford229fe472014-03-10 02:51:56 -07002462 "commands to complete for scsi%d\n", i,
2463 outstanding, instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002464 megasas_complete_cmd_dpc_fusion(
2465 (unsigned long)instance);
2466 }
2467 msleep(1000);
2468 }
2469
2470 if (atomic_read(&instance->fw_outstanding)) {
2471 printk("megaraid_sas: pending commands remain after waiting, "
adam radford229fe472014-03-10 02:51:56 -07002472 "will reset adapter scsi%d.\n",
2473 instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002474 retval = 1;
2475 }
2476out:
2477 return retval;
2478}
2479
2480void megasas_reset_reply_desc(struct megasas_instance *instance)
2481{
adam radfordc8e858f2011-10-08 18:15:13 -07002482 int i, count;
adam radford9c915a82010-12-21 13:34:31 -08002483 struct fusion_context *fusion;
2484 union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
2485
2486 fusion = instance->ctrl_context;
adam radfordc8e858f2011-10-08 18:15:13 -07002487 count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
2488 for (i = 0 ; i < count ; i++)
2489 fusion->last_reply_idx[i] = 0;
adam radford9c915a82010-12-21 13:34:31 -08002490 reply_desc = fusion->reply_frames_desc;
adam radfordc8e858f2011-10-08 18:15:13 -07002491 for (i = 0 ; i < fusion->reply_q_depth * count; i++, reply_desc++)
Christoph Hellwigc6f5bf82015-04-23 16:33:09 +05302492 reply_desc->Words = cpu_to_le64(ULLONG_MAX);
adam radford9c915a82010-12-21 13:34:31 -08002493}
2494
Sumit.Saxena@avagotech.com9b828182015-04-23 16:30:24 +05302495/*
2496 * megasas_refire_mgmt_cmd : Re-fire management commands
2497 * @instance: Controller's soft instance
2498*/
2499void megasas_refire_mgmt_cmd(struct megasas_instance *instance)
2500{
2501 int j;
2502 struct megasas_cmd_fusion *cmd_fusion;
2503 struct fusion_context *fusion;
2504 struct megasas_cmd *cmd_mfi;
2505 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
2506 u16 smid;
2507
2508 fusion = instance->ctrl_context;
2509
2510 /* Re-fire management commands.
2511 * Do not traverse complet MPT frame pool. Start from max_scsi_cmds.
2512 */
2513 for (j = instance->max_scsi_cmds ; j < instance->max_fw_cmds; j++) {
2514 cmd_fusion = fusion->cmd_list[j];
2515 cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
2516 smid = le16_to_cpu(cmd_mfi->context.smid);
2517
2518 if (!smid)
2519 continue;
2520 req_desc = megasas_get_request_descriptor
2521 (instance, smid - 1);
2522 if (req_desc && (cmd_mfi->frame->dcmd.opcode !=
2523 cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO))) {
2524 instance->instancet->fire_cmd(instance,
2525 req_desc->u.low, req_desc->u.high,
2526 instance->reg_set);
2527 } else
2528 megasas_return_cmd(instance, cmd_mfi);
2529 }
2530}
2531
adam radford229fe472014-03-10 02:51:56 -07002532/* Check for a second path that is currently UP */
2533int megasas_check_mpio_paths(struct megasas_instance *instance,
2534 struct scsi_cmnd *scmd)
adam radford9c915a82010-12-21 13:34:31 -08002535{
adam radford229fe472014-03-10 02:51:56 -07002536 int i, j, retval = (DID_RESET << 16);
2537
2538 if (instance->mpio && instance->requestorId) {
2539 for (i = 0 ; i < MAX_MGMT_ADAPTERS ; i++)
2540 for (j = 0 ; j < MAX_LOGICAL_DRIVES; j++)
2541 if (megasas_mgmt_info.instance[i] &&
2542 (megasas_mgmt_info.instance[i] != instance) &&
2543 megasas_mgmt_info.instance[i]->mpio &&
2544 megasas_mgmt_info.instance[i]->requestorId
2545 &&
2546 (megasas_mgmt_info.instance[i]->ld_ids[j]
2547 == scmd->device->id)) {
2548 retval = (DID_NO_CONNECT << 16);
2549 goto out;
2550 }
2551 }
2552out:
2553 return retval;
2554}
2555
2556/* Core fusion reset function */
2557int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
2558{
Sumit.Saxena@avagotech.com9b828182015-04-23 16:30:24 +05302559 int retval = SUCCESS, i, retry = 0, convert = 0;
adam radford9c915a82010-12-21 13:34:31 -08002560 struct megasas_instance *instance;
2561 struct megasas_cmd_fusion *cmd_fusion;
2562 struct fusion_context *fusion;
adam radford7e70e732011-05-11 18:34:08 -07002563 u32 host_diag, abs_state, status_reg, reset_adapter;
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05302564 u32 io_timeout_in_crash_mode = 0;
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302565 struct scsi_cmnd *scmd_local = NULL;
adam radford9c915a82010-12-21 13:34:31 -08002566
2567 instance = (struct megasas_instance *)shost->hostdata;
2568 fusion = instance->ctrl_context;
2569
adam radford229fe472014-03-10 02:51:56 -07002570 mutex_lock(&instance->reset_mutex);
2571
adam radford9c915a82010-12-21 13:34:31 -08002572 if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
2573 printk(KERN_WARNING "megaraid_sas: Hardware critical error, "
adam radford229fe472014-03-10 02:51:56 -07002574 "returning FAILED for scsi%d.\n",
2575 instance->host->host_no);
Adam Radforda2fbcbc2014-07-09 15:17:54 -07002576 mutex_unlock(&instance->reset_mutex);
adam radfordd4a759a2011-10-08 18:14:39 -07002577 return FAILED;
adam radford9c915a82010-12-21 13:34:31 -08002578 }
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05302579 status_reg = instance->instancet->read_fw_status_reg(instance->reg_set);
2580 abs_state = status_reg & MFI_STATE_MASK;
2581
2582 /* IO timeout detected, forcibly put FW in FAULT state */
2583 if (abs_state != MFI_STATE_FAULT && instance->crash_dump_buf &&
2584 instance->crash_dump_app_support && iotimeout) {
2585 dev_info(&instance->pdev->dev, "IO timeout is detected, "
2586 "forcibly FAULT Firmware\n");
2587 instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
2588 status_reg = readl(&instance->reg_set->doorbell);
2589 writel(status_reg | MFI_STATE_FORCE_OCR,
2590 &instance->reg_set->doorbell);
2591 readl(&instance->reg_set->doorbell);
2592 mutex_unlock(&instance->reset_mutex);
2593 do {
2594 ssleep(3);
2595 io_timeout_in_crash_mode++;
2596 dev_dbg(&instance->pdev->dev, "waiting for [%d] "
2597 "seconds for crash dump collection and OCR "
2598 "to be done\n", (io_timeout_in_crash_mode * 3));
2599 } while ((instance->adprecovery != MEGASAS_HBA_OPERATIONAL) &&
2600 (io_timeout_in_crash_mode < 80));
2601
2602 if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
2603 dev_info(&instance->pdev->dev, "OCR done for IO "
2604 "timeout case\n");
2605 retval = SUCCESS;
2606 } else {
2607 dev_info(&instance->pdev->dev, "Controller is not "
2608 "operational after 240 seconds wait for IO "
2609 "timeout case in FW crash dump mode\n do "
2610 "OCR/kill adapter\n");
2611 retval = megasas_reset_fusion(shost, 0);
2612 }
2613 return retval;
2614 }
adam radford9c915a82010-12-21 13:34:31 -08002615
adam radford229fe472014-03-10 02:51:56 -07002616 if (instance->requestorId && !instance->skip_heartbeat_timer_del)
2617 del_timer_sync(&instance->sriov_heartbeat_timer);
adam radford7e70e732011-05-11 18:34:08 -07002618 set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
adam radford229fe472014-03-10 02:51:56 -07002619 instance->adprecovery = MEGASAS_ADPRESET_SM_POLLING;
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +05302620 instance->instancet->disable_intr(instance);
adam radford7e70e732011-05-11 18:34:08 -07002621 msleep(1000);
2622
adam radford9c915a82010-12-21 13:34:31 -08002623 /* First try waiting for commands to complete */
adam radford229fe472014-03-10 02:51:56 -07002624 if (megasas_wait_for_outstanding_fusion(instance, iotimeout,
2625 &convert)) {
2626 instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
adam radford9c915a82010-12-21 13:34:31 -08002627 printk(KERN_WARNING "megaraid_sas: resetting fusion "
adam radford229fe472014-03-10 02:51:56 -07002628 "adapter scsi%d.\n", instance->host->host_no);
2629 if (convert)
2630 iotimeout = 0;
2631
adam radford9c915a82010-12-21 13:34:31 -08002632 /* Now return commands back to the OS */
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302633 for (i = 0 ; i < instance->max_scsi_cmds; i++) {
adam radford9c915a82010-12-21 13:34:31 -08002634 cmd_fusion = fusion->cmd_list[i];
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302635 scmd_local = cmd_fusion->scmd;
adam radford9c915a82010-12-21 13:34:31 -08002636 if (cmd_fusion->scmd) {
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302637 scmd_local->result =
adam radford229fe472014-03-10 02:51:56 -07002638 megasas_check_mpio_paths(instance,
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302639 scmd_local);
adam radford9c915a82010-12-21 13:34:31 -08002640 megasas_return_cmd_fusion(instance, cmd_fusion);
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302641 scsi_dma_unmap(scmd_local);
2642 scmd_local->scsi_done(scmd_local);
adam radford9c915a82010-12-21 13:34:31 -08002643 atomic_dec(&instance->fw_outstanding);
2644 }
2645 }
2646
adam radford7e70e732011-05-11 18:34:08 -07002647 status_reg = instance->instancet->read_fw_status_reg(
2648 instance->reg_set);
2649 abs_state = status_reg & MFI_STATE_MASK;
2650 reset_adapter = status_reg & MFI_RESET_ADAPTER;
2651 if (instance->disableOnlineCtrlReset ||
2652 (abs_state == MFI_STATE_FAULT && !reset_adapter)) {
adam radford9c915a82010-12-21 13:34:31 -08002653 /* Reset not supported, kill adapter */
2654 printk(KERN_WARNING "megaraid_sas: Reset not supported"
adam radford229fe472014-03-10 02:51:56 -07002655 ", killing adapter scsi%d.\n",
2656 instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002657 megaraid_sas_kill_hba(instance);
adam radford229fe472014-03-10 02:51:56 -07002658 instance->skip_heartbeat_timer_del = 1;
adam radford9c915a82010-12-21 13:34:31 -08002659 retval = FAILED;
2660 goto out;
2661 }
2662
adam radford229fe472014-03-10 02:51:56 -07002663 /* Let SR-IOV VF & PF sync up if there was a HB failure */
2664 if (instance->requestorId && !iotimeout) {
2665 msleep(MEGASAS_OCR_SETTLE_TIME_VF);
2666 /* Look for a late HB update after VF settle time */
2667 if (abs_state == MFI_STATE_OPERATIONAL &&
2668 (instance->hb_host_mem->HB.fwCounter !=
2669 instance->hb_host_mem->HB.driverCounter)) {
2670 instance->hb_host_mem->HB.driverCounter =
2671 instance->hb_host_mem->HB.fwCounter;
2672 printk(KERN_WARNING "megasas: SR-IOV:"
2673 "Late FW heartbeat update for "
2674 "scsi%d.\n",
2675 instance->host->host_no);
2676 } else {
2677 /* In VF mode, first poll for FW ready */
2678 for (i = 0;
2679 i < (MEGASAS_RESET_WAIT_TIME * 1000);
2680 i += 20) {
2681 status_reg =
2682 instance->instancet->
2683 read_fw_status_reg(
2684 instance->reg_set);
2685 abs_state = status_reg &
2686 MFI_STATE_MASK;
2687 if (abs_state == MFI_STATE_READY) {
2688 printk(KERN_WARNING "megasas"
2689 ": SR-IOV: FW was found"
2690 "to be in ready state "
2691 "for scsi%d.\n",
2692 instance->host->host_no);
2693 break;
2694 }
2695 msleep(20);
2696 }
2697 if (abs_state != MFI_STATE_READY) {
2698 printk(KERN_WARNING "megasas: SR-IOV: "
2699 "FW not in ready state after %d"
2700 " seconds for scsi%d, status_reg = "
2701 "0x%x.\n",
2702 MEGASAS_RESET_WAIT_TIME,
2703 instance->host->host_no,
2704 status_reg);
2705 megaraid_sas_kill_hba(instance);
2706 instance->skip_heartbeat_timer_del = 1;
2707 instance->adprecovery =
2708 MEGASAS_HW_CRITICAL_ERROR;
2709 retval = FAILED;
2710 goto out;
2711 }
2712 }
2713 }
2714
adam radford9c915a82010-12-21 13:34:31 -08002715 /* Now try to reset the chip */
2716 for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) {
2717 writel(MPI2_WRSEQ_FLUSH_KEY_VALUE,
2718 &instance->reg_set->fusion_seq_offset);
2719 writel(MPI2_WRSEQ_1ST_KEY_VALUE,
2720 &instance->reg_set->fusion_seq_offset);
2721 writel(MPI2_WRSEQ_2ND_KEY_VALUE,
2722 &instance->reg_set->fusion_seq_offset);
2723 writel(MPI2_WRSEQ_3RD_KEY_VALUE,
2724 &instance->reg_set->fusion_seq_offset);
2725 writel(MPI2_WRSEQ_4TH_KEY_VALUE,
2726 &instance->reg_set->fusion_seq_offset);
2727 writel(MPI2_WRSEQ_5TH_KEY_VALUE,
2728 &instance->reg_set->fusion_seq_offset);
2729 writel(MPI2_WRSEQ_6TH_KEY_VALUE,
2730 &instance->reg_set->fusion_seq_offset);
2731
2732 /* Check that the diag write enable (DRWE) bit is on */
2733 host_diag = readl(&instance->reg_set->fusion_host_diag);
adam radford7e70e732011-05-11 18:34:08 -07002734 retry = 0;
adam radford9c915a82010-12-21 13:34:31 -08002735 while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) {
2736 msleep(100);
2737 host_diag =
2738 readl(&instance->reg_set->fusion_host_diag);
2739 if (retry++ == 100) {
2740 printk(KERN_WARNING "megaraid_sas: "
adam radford229fe472014-03-10 02:51:56 -07002741 "Host diag unlock failed! "
2742 "for scsi%d\n",
2743 instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002744 break;
2745 }
2746 }
2747 if (!(host_diag & HOST_DIAG_WRITE_ENABLE))
2748 continue;
2749
2750 /* Send chip reset command */
2751 writel(host_diag | HOST_DIAG_RESET_ADAPTER,
2752 &instance->reg_set->fusion_host_diag);
2753 msleep(3000);
2754
2755 /* Make sure reset adapter bit is cleared */
2756 host_diag = readl(&instance->reg_set->fusion_host_diag);
2757 retry = 0;
2758 while (host_diag & HOST_DIAG_RESET_ADAPTER) {
2759 msleep(100);
2760 host_diag =
2761 readl(&instance->reg_set->fusion_host_diag);
2762 if (retry++ == 1000) {
2763 printk(KERN_WARNING "megaraid_sas: "
2764 "Diag reset adapter never "
adam radford229fe472014-03-10 02:51:56 -07002765 "cleared for scsi%d!\n",
2766 instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002767 break;
2768 }
2769 }
2770 if (host_diag & HOST_DIAG_RESET_ADAPTER)
2771 continue;
2772
2773 abs_state =
2774 instance->instancet->read_fw_status_reg(
adam radford7e70e732011-05-11 18:34:08 -07002775 instance->reg_set) & MFI_STATE_MASK;
adam radford9c915a82010-12-21 13:34:31 -08002776 retry = 0;
2777
2778 while ((abs_state <= MFI_STATE_FW_INIT) &&
2779 (retry++ < 1000)) {
2780 msleep(100);
2781 abs_state =
2782 instance->instancet->read_fw_status_reg(
adam radford7e70e732011-05-11 18:34:08 -07002783 instance->reg_set) & MFI_STATE_MASK;
adam radford9c915a82010-12-21 13:34:31 -08002784 }
2785 if (abs_state <= MFI_STATE_FW_INIT) {
2786 printk(KERN_WARNING "megaraid_sas: firmware "
2787 "state < MFI_STATE_FW_INIT, state = "
adam radford229fe472014-03-10 02:51:56 -07002788 "0x%x for scsi%d\n", abs_state,
2789 instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002790 continue;
2791 }
2792
2793 /* Wait for FW to become ready */
adam radford058a8fa2011-10-08 18:14:27 -07002794 if (megasas_transition_to_ready(instance, 1)) {
adam radford9c915a82010-12-21 13:34:31 -08002795 printk(KERN_WARNING "megaraid_sas: Failed to "
adam radford229fe472014-03-10 02:51:56 -07002796 "transition controller to ready "
2797 "for scsi%d.\n",
2798 instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002799 continue;
2800 }
2801
2802 megasas_reset_reply_desc(instance);
2803 if (megasas_ioc_init_fusion(instance)) {
2804 printk(KERN_WARNING "megaraid_sas: "
adam radford229fe472014-03-10 02:51:56 -07002805 "megasas_ioc_init_fusion() failed!"
2806 " for scsi%d\n",
2807 instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002808 continue;
2809 }
2810
Sumit.Saxena@avagotech.com9b828182015-04-23 16:30:24 +05302811 megasas_refire_mgmt_cmd(instance);
adam radford9c915a82010-12-21 13:34:31 -08002812
Sumit.Saxena@avagotech.comd009b572014-11-17 15:24:13 +05302813 if (megasas_get_ctrl_info(instance)) {
2814 dev_info(&instance->pdev->dev,
2815 "Failed from %s %d\n",
2816 __func__, __LINE__);
Sumit.Saxena@avagotech.comd009b572014-11-17 15:24:13 +05302817 megaraid_sas_kill_hba(instance);
2818 retval = FAILED;
2819 }
adam radford9c915a82010-12-21 13:34:31 -08002820 /* Reset load balance info */
2821 memset(fusion->load_balance_info, 0,
2822 sizeof(struct LD_LOAD_BALANCE_INFO)
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05302823 *MAX_LOGICAL_DRIVES_EXT);
adam radford9c915a82010-12-21 13:34:31 -08002824
2825 if (!megasas_get_map_info(instance))
2826 megasas_sync_map_info(instance);
2827
Sumit.Saxena@avagotech.comac340c52014-11-17 15:24:18 +05302828 clear_bit(MEGASAS_FUSION_IN_RESET,
2829 &instance->reset_flags);
2830 instance->instancet->enable_intr(instance);
2831 instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
2832
adam radford229fe472014-03-10 02:51:56 -07002833 /* Restart SR-IOV heartbeat */
2834 if (instance->requestorId) {
2835 if (!megasas_sriov_start_heartbeat(instance, 0))
2836 megasas_start_timer(instance,
2837 &instance->sriov_heartbeat_timer,
2838 megasas_sriov_heartbeat_handler,
2839 MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF);
2840 else
2841 instance->skip_heartbeat_timer_del = 1;
2842 }
2843
adam radford9c915a82010-12-21 13:34:31 -08002844 /* Adapter reset completed successfully */
2845 printk(KERN_WARNING "megaraid_sas: Reset "
adam radford229fe472014-03-10 02:51:56 -07002846 "successful for scsi%d.\n",
2847 instance->host->host_no);
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05302848
Sumit.Saxena@avagotech.comac340c52014-11-17 15:24:18 +05302849 if (instance->crash_dump_drv_support &&
2850 instance->crash_dump_app_support)
2851 megasas_set_crash_dump_params(instance,
2852 MR_CRASH_BUF_TURN_ON);
2853 else
2854 megasas_set_crash_dump_params(instance,
2855 MR_CRASH_BUF_TURN_OFF);
2856
adam radford9c915a82010-12-21 13:34:31 -08002857 retval = SUCCESS;
2858 goto out;
2859 }
2860 /* Reset failed, kill the adapter */
2861 printk(KERN_WARNING "megaraid_sas: Reset failed, killing "
adam radford229fe472014-03-10 02:51:56 -07002862 "adapter scsi%d.\n", instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002863 megaraid_sas_kill_hba(instance);
adam radford229fe472014-03-10 02:51:56 -07002864 instance->skip_heartbeat_timer_del = 1;
adam radford9c915a82010-12-21 13:34:31 -08002865 retval = FAILED;
2866 } else {
adam radford229fe472014-03-10 02:51:56 -07002867 /* For VF: Restart HB timer if we didn't OCR */
2868 if (instance->requestorId) {
2869 megasas_start_timer(instance,
2870 &instance->sriov_heartbeat_timer,
2871 megasas_sriov_heartbeat_handler,
2872 MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF);
2873 }
adam radford3f0e58bc2011-10-08 18:14:59 -07002874 clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +05302875 instance->instancet->enable_intr(instance);
adam radford9c915a82010-12-21 13:34:31 -08002876 instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
2877 }
2878out:
2879 clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
2880 mutex_unlock(&instance->reset_mutex);
2881 return retval;
2882}
2883
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05302884/* Fusion Crash dump collection work queue */
2885void megasas_fusion_crash_dump_wq(struct work_struct *work)
2886{
2887 struct megasas_instance *instance =
2888 container_of(work, struct megasas_instance, crash_init);
2889 u32 status_reg;
2890 u8 partial_copy = 0;
2891
2892
2893 status_reg = instance->instancet->read_fw_status_reg(instance->reg_set);
2894
2895 /*
2896 * Allocate host crash buffers to copy data from 1 MB DMA crash buffer
2897 * to host crash buffers
2898 */
2899 if (instance->drv_buf_index == 0) {
2900 /* Buffer is already allocated for old Crash dump.
2901 * Do OCR and do not wait for crash dump collection
2902 */
2903 if (instance->drv_buf_alloc) {
2904 dev_info(&instance->pdev->dev, "earlier crash dump is "
2905 "not yet copied by application, ignoring this "
2906 "crash dump and initiating OCR\n");
2907 status_reg |= MFI_STATE_CRASH_DUMP_DONE;
2908 writel(status_reg,
2909 &instance->reg_set->outbound_scratch_pad);
2910 readl(&instance->reg_set->outbound_scratch_pad);
2911 return;
2912 }
2913 megasas_alloc_host_crash_buffer(instance);
2914 dev_info(&instance->pdev->dev, "Number of host crash buffers "
2915 "allocated: %d\n", instance->drv_buf_alloc);
2916 }
2917
2918 /*
2919 * Driver has allocated max buffers, which can be allocated
2920 * and FW has more crash dump data, then driver will
2921 * ignore the data.
2922 */
2923 if (instance->drv_buf_index >= (instance->drv_buf_alloc)) {
2924 dev_info(&instance->pdev->dev, "Driver is done copying "
2925 "the buffer: %d\n", instance->drv_buf_alloc);
2926 status_reg |= MFI_STATE_CRASH_DUMP_DONE;
2927 partial_copy = 1;
2928 } else {
2929 memcpy(instance->crash_buf[instance->drv_buf_index],
2930 instance->crash_dump_buf, CRASH_DMA_BUF_SIZE);
2931 instance->drv_buf_index++;
2932 status_reg &= ~MFI_STATE_DMADONE;
2933 }
2934
2935 if (status_reg & MFI_STATE_CRASH_DUMP_DONE) {
2936 dev_info(&instance->pdev->dev, "Crash Dump is available,number "
2937 "of copied buffers: %d\n", instance->drv_buf_index);
2938 instance->fw_crash_buffer_size = instance->drv_buf_index;
2939 instance->fw_crash_state = AVAILABLE;
2940 instance->drv_buf_index = 0;
2941 writel(status_reg, &instance->reg_set->outbound_scratch_pad);
2942 readl(&instance->reg_set->outbound_scratch_pad);
2943 if (!partial_copy)
2944 megasas_reset_fusion(instance->host, 0);
2945 } else {
2946 writel(status_reg, &instance->reg_set->outbound_scratch_pad);
2947 readl(&instance->reg_set->outbound_scratch_pad);
2948 }
2949}
2950
2951
adam radford9c915a82010-12-21 13:34:31 -08002952/* Fusion OCR work queue */
2953void megasas_fusion_ocr_wq(struct work_struct *work)
2954{
2955 struct megasas_instance *instance =
2956 container_of(work, struct megasas_instance, work_init);
2957
adam radford229fe472014-03-10 02:51:56 -07002958 megasas_reset_fusion(instance->host, 0);
adam radford9c915a82010-12-21 13:34:31 -08002959}
2960
2961struct megasas_instance_template megasas_instance_template_fusion = {
2962 .fire_cmd = megasas_fire_cmd_fusion,
2963 .enable_intr = megasas_enable_intr_fusion,
2964 .disable_intr = megasas_disable_intr_fusion,
2965 .clear_intr = megasas_clear_intr_fusion,
2966 .read_fw_status_reg = megasas_read_fw_status_reg_fusion,
2967 .adp_reset = megasas_adp_reset_fusion,
2968 .check_reset = megasas_check_reset_fusion,
2969 .service_isr = megasas_isr_fusion,
2970 .tasklet = megasas_complete_cmd_dpc_fusion,
2971 .init_adapter = megasas_init_adapter_fusion,
2972 .build_and_issue_cmd = megasas_build_and_issue_cmd_fusion,
2973 .issue_dcmd = megasas_issue_dcmd_fusion,
2974};