blob: d9d0029fb1b0e09a101057ff9ac04498f0fb99e1 [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;
Sumit Saxenae3d178c2016-01-28 21:04:34 +053094extern unsigned int resetwaittime;
Sumit Saxena308ec452016-01-28 21:04:30 +053095extern unsigned int dual_qdepth_disable;
Sumit Saxena179ac142016-01-28 21:04:28 +053096static void megasas_free_rdpq_fusion(struct megasas_instance *instance);
97static void megasas_free_reply_fusion(struct megasas_instance *instance);
adam radford9c915a82010-12-21 13:34:31 -080098
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +053099
100
adam radford9c915a82010-12-21 13:34:31 -0800101/**
102 * megasas_enable_intr_fusion - Enables interrupts
103 * @regs: MFI register set
104 */
105void
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530106megasas_enable_intr_fusion(struct megasas_instance *instance)
adam radford9c915a82010-12-21 13:34:31 -0800107{
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530108 struct megasas_register_set __iomem *regs;
109 regs = instance->reg_set;
Sumit.Saxena@avagotech.comc2ced172015-01-05 20:06:13 +0530110
111 instance->mask_interrupts = 0;
adam radford6497b242011-10-08 18:14:50 -0700112 /* For Thunderbolt/Invader also clear intr on enable */
113 writel(~0, &regs->outbound_intr_status);
114 readl(&regs->outbound_intr_status);
115
adam radford9c915a82010-12-21 13:34:31 -0800116 writel(~MFI_FUSION_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
117
118 /* Dummy readl to force pci flush */
119 readl(&regs->outbound_intr_mask);
120}
121
122/**
123 * megasas_disable_intr_fusion - Disables interrupt
124 * @regs: MFI register set
125 */
126void
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530127megasas_disable_intr_fusion(struct megasas_instance *instance)
adam radford9c915a82010-12-21 13:34:31 -0800128{
129 u32 mask = 0xFFFFFFFF;
130 u32 status;
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530131 struct megasas_register_set __iomem *regs;
132 regs = instance->reg_set;
133 instance->mask_interrupts = 1;
adam radford9c915a82010-12-21 13:34:31 -0800134
135 writel(mask, &regs->outbound_intr_mask);
136 /* Dummy readl to force pci flush */
137 status = readl(&regs->outbound_intr_mask);
138}
139
140int
141megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs)
142{
143 u32 status;
144 /*
145 * Check if it is our interrupt
146 */
147 status = readl(&regs->outbound_intr_status);
148
149 if (status & 1) {
150 writel(status, &regs->outbound_intr_status);
151 readl(&regs->outbound_intr_status);
152 return 1;
153 }
154 if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK))
155 return 0;
156
adam radford9c915a82010-12-21 13:34:31 -0800157 return 1;
158}
159
160/**
161 * megasas_get_cmd_fusion - Get a command from the free pool
162 * @instance: Adapter soft state
163 *
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530164 * Returns a blk_tag indexed mpt frame
adam radford9c915a82010-12-21 13:34:31 -0800165 */
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530166inline struct megasas_cmd_fusion *megasas_get_cmd_fusion(struct megasas_instance
167 *instance, u32 blk_tag)
adam radford9c915a82010-12-21 13:34:31 -0800168{
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530169 struct fusion_context *fusion;
adam radford9c915a82010-12-21 13:34:31 -0800170
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530171 fusion = instance->ctrl_context;
172 return fusion->cmd_list[blk_tag];
adam radford9c915a82010-12-21 13:34:31 -0800173}
174
175/**
176 * megasas_return_cmd_fusion - Return a cmd to free command pool
177 * @instance: Adapter soft state
178 * @cmd: Command packet to be returned to free command pool
179 */
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530180inline void megasas_return_cmd_fusion(struct megasas_instance *instance,
181 struct megasas_cmd_fusion *cmd)
adam radford9c915a82010-12-21 13:34:31 -0800182{
adam radford9c915a82010-12-21 13:34:31 -0800183 cmd->scmd = NULL;
Sumit.Saxena@avagotech.com7497cde2015-01-05 20:06:03 +0530184 memset(cmd->io_request, 0, sizeof(struct MPI2_RAID_SCSI_IO_REQUEST));
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530185}
186
187/**
Christoph Hellwig01d7f032015-04-23 16:34:09 +0530188 * megasas_fire_cmd_fusion - Sends command to the FW
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530189 */
Christoph Hellwig01d7f032015-04-23 16:34:09 +0530190static void
191megasas_fire_cmd_fusion(struct megasas_instance *instance,
192 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc)
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530193{
Christoph Hellwig01d7f032015-04-23 16:34:09 +0530194#if defined(writeq) && defined(CONFIG_64BIT)
195 u64 req_data = (((u64)le32_to_cpu(req_desc->u.high) << 32) |
196 le32_to_cpu(req_desc->u.low));
197
198 writeq(req_data, &instance->reg_set->inbound_low_queue_port);
199#else
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530200 unsigned long flags;
201
Christoph Hellwig01d7f032015-04-23 16:34:09 +0530202 spin_lock_irqsave(&instance->hba_lock, flags);
203 writel(le32_to_cpu(req_desc->u.low),
204 &instance->reg_set->inbound_low_queue_port);
205 writel(le32_to_cpu(req_desc->u.high),
206 &instance->reg_set->inbound_high_queue_port);
207 spin_unlock_irqrestore(&instance->hba_lock, flags);
208#endif
adam radford9c915a82010-12-21 13:34:31 -0800209}
210
adam radford9c915a82010-12-21 13:34:31 -0800211/**
Sumit Saxena308ec452016-01-28 21:04:30 +0530212 * megasas_fusion_update_can_queue - Do all Adapter Queue depth related calculations here
213 * @instance: Adapter soft state
214 * fw_boot_context: Whether this function called during probe or after OCR
215 *
216 * This function is only for fusion controllers.
217 * Update host can queue, if firmware downgrade max supported firmware commands.
218 * Firmware upgrade case will be skiped because underlying firmware has
219 * more resource than exposed to the OS.
220 *
221 */
222static void
223megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_context)
224{
225 u16 cur_max_fw_cmds = 0;
226 u16 ldio_threshold = 0;
227 struct megasas_register_set __iomem *reg_set;
228
229 reg_set = instance->reg_set;
230
231 cur_max_fw_cmds = readl(&instance->reg_set->outbound_scratch_pad_3) & 0x00FFFF;
232
233 if (dual_qdepth_disable || !cur_max_fw_cmds)
234 cur_max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF;
235 else
236 ldio_threshold =
237 (instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF) - MEGASAS_FUSION_IOCTL_CMDS;
238
239 dev_info(&instance->pdev->dev,
240 "Current firmware maximum commands: %d\t LDIO threshold: %d\n",
241 cur_max_fw_cmds, ldio_threshold);
242
243 if (fw_boot_context == OCR_CONTEXT) {
244 cur_max_fw_cmds = cur_max_fw_cmds - 1;
245 if (cur_max_fw_cmds <= instance->max_fw_cmds) {
246 instance->cur_can_queue =
247 cur_max_fw_cmds - (MEGASAS_FUSION_INTERNAL_CMDS +
248 MEGASAS_FUSION_IOCTL_CMDS);
249 instance->host->can_queue = instance->cur_can_queue;
250 instance->ldio_threshold = ldio_threshold;
251 }
252 } else {
253 instance->max_fw_cmds = cur_max_fw_cmds;
254 instance->ldio_threshold = ldio_threshold;
255
256 if (!instance->is_rdpq)
257 instance->max_fw_cmds = min_t(u16, instance->max_fw_cmds, 1024);
258
259 /*
260 * Reduce the max supported cmds by 1. This is to ensure that the
261 * reply_q_sz (1 more than the max cmd that driver may send)
262 * does not exceed max cmds that the FW can support
263 */
264 instance->max_fw_cmds = instance->max_fw_cmds-1;
265
266 instance->max_scsi_cmds = instance->max_fw_cmds -
267 (MEGASAS_FUSION_INTERNAL_CMDS +
268 MEGASAS_FUSION_IOCTL_CMDS);
269 instance->cur_can_queue = instance->max_scsi_cmds;
270 }
271}
272/**
adam radford9c915a82010-12-21 13:34:31 -0800273 * megasas_free_cmds_fusion - Free all the cmds in the free cmd pool
274 * @instance: Adapter soft state
275 */
276void
277megasas_free_cmds_fusion(struct megasas_instance *instance)
278{
279 int i;
280 struct fusion_context *fusion = instance->ctrl_context;
Sumit Saxena179ac142016-01-28 21:04:28 +0530281 struct megasas_cmd_fusion *cmd;
adam radford9c915a82010-12-21 13:34:31 -0800282
Sumit Saxena179ac142016-01-28 21:04:28 +0530283 /* SG, Sense */
284 for (i = 0; i < instance->max_fw_cmds; i++) {
285 cmd = fusion->cmd_list[i];
286 if (cmd) {
287 if (cmd->sg_frame)
288 pci_pool_free(fusion->sg_dma_pool, cmd->sg_frame,
289 cmd->sg_frame_phys_addr);
290 if (cmd->sense)
291 pci_pool_free(fusion->sense_dma_pool, cmd->sense,
292 cmd->sense_phys_addr);
293 }
294 }
295
296 if (fusion->sg_dma_pool) {
297 pci_pool_destroy(fusion->sg_dma_pool);
298 fusion->sg_dma_pool = NULL;
299 }
300 if (fusion->sense_dma_pool) {
301 pci_pool_destroy(fusion->sense_dma_pool);
302 fusion->sense_dma_pool = NULL;
303 }
adam radford9c915a82010-12-21 13:34:31 -0800304
305
Sumit Saxena179ac142016-01-28 21:04:28 +0530306 /* Reply Frame, Desc*/
307 if (instance->is_rdpq)
308 megasas_free_rdpq_fusion(instance);
309 else
310 megasas_free_reply_fusion(instance);
adam radford9c915a82010-12-21 13:34:31 -0800311
Sumit Saxena179ac142016-01-28 21:04:28 +0530312 /* Request Frame, Desc*/
adam radford9c915a82010-12-21 13:34:31 -0800313 if (fusion->req_frames_desc)
Sumit Saxena179ac142016-01-28 21:04:28 +0530314 dma_free_coherent(&instance->pdev->dev,
315 fusion->request_alloc_sz, fusion->req_frames_desc,
316 fusion->req_frames_desc_phys);
317 if (fusion->io_request_frames)
adam radford9c915a82010-12-21 13:34:31 -0800318 pci_pool_free(fusion->io_request_frames_pool,
Sumit Saxena179ac142016-01-28 21:04:28 +0530319 fusion->io_request_frames,
320 fusion->io_request_frames_phys);
321 if (fusion->io_request_frames_pool) {
adam radford9c915a82010-12-21 13:34:31 -0800322 pci_pool_destroy(fusion->io_request_frames_pool);
Sumit Saxena179ac142016-01-28 21:04:28 +0530323 fusion->io_request_frames_pool = NULL;
adam radford9c915a82010-12-21 13:34:31 -0800324 }
325
adam radford9c915a82010-12-21 13:34:31 -0800326
Sumit Saxena179ac142016-01-28 21:04:28 +0530327 /* cmd_list */
328 for (i = 0; i < instance->max_fw_cmds; i++)
adam radford9c915a82010-12-21 13:34:31 -0800329 kfree(fusion->cmd_list[i]);
330
adam radford9c915a82010-12-21 13:34:31 -0800331 kfree(fusion->cmd_list);
adam radford9c915a82010-12-21 13:34:31 -0800332}
333
334/**
Sumit Saxena179ac142016-01-28 21:04:28 +0530335 * megasas_create_sg_sense_fusion - Creates DMA pool for cmd frames
adam radford9c915a82010-12-21 13:34:31 -0800336 * @instance: Adapter soft state
337 *
338 */
Sumit Saxena179ac142016-01-28 21:04:28 +0530339static int megasas_create_sg_sense_fusion(struct megasas_instance *instance)
adam radford9c915a82010-12-21 13:34:31 -0800340{
341 int i;
342 u32 max_cmd;
343 struct fusion_context *fusion;
344 struct megasas_cmd_fusion *cmd;
adam radford9c915a82010-12-21 13:34:31 -0800345
346 fusion = instance->ctrl_context;
347 max_cmd = instance->max_fw_cmds;
348
adam radford9c915a82010-12-21 13:34:31 -0800349
Sumit Saxena179ac142016-01-28 21:04:28 +0530350 fusion->sg_dma_pool =
351 pci_pool_create("mr_sg", instance->pdev,
352 instance->max_chain_frame_sz, 4, 0);
353 /* SCSI_SENSE_BUFFERSIZE = 96 bytes */
354 fusion->sense_dma_pool =
355 pci_pool_create("mr_sense", instance->pdev,
356 SCSI_SENSE_BUFFERSIZE, 64, 0);
adam radford9c915a82010-12-21 13:34:31 -0800357
Sumit Saxena179ac142016-01-28 21:04:28 +0530358 if (!fusion->sense_dma_pool || !fusion->sg_dma_pool) {
359 dev_err(&instance->pdev->dev,
360 "Failed from %s %d\n", __func__, __LINE__);
adam radford9c915a82010-12-21 13:34:31 -0800361 return -ENOMEM;
362 }
363
364 /*
365 * Allocate and attach a frame to each of the commands in cmd_list
366 */
367 for (i = 0; i < max_cmd; i++) {
adam radford9c915a82010-12-21 13:34:31 -0800368 cmd = fusion->cmd_list[i];
adam radford9c915a82010-12-21 13:34:31 -0800369 cmd->sg_frame = pci_pool_alloc(fusion->sg_dma_pool,
Sumit Saxena179ac142016-01-28 21:04:28 +0530370 GFP_KERNEL, &cmd->sg_frame_phys_addr);
adam radford9c915a82010-12-21 13:34:31 -0800371
372 cmd->sense = pci_pool_alloc(fusion->sense_dma_pool,
Sumit Saxena179ac142016-01-28 21:04:28 +0530373 GFP_KERNEL, &cmd->sense_phys_addr);
adam radford9c915a82010-12-21 13:34:31 -0800374 if (!cmd->sg_frame || !cmd->sense) {
Sumit Saxena179ac142016-01-28 21:04:28 +0530375 dev_err(&instance->pdev->dev,
376 "Failed from %s %d\n", __func__, __LINE__);
adam radford9c915a82010-12-21 13:34:31 -0800377 return -ENOMEM;
378 }
379 }
380 return 0;
381}
382
Sumit Saxena179ac142016-01-28 21:04:28 +0530383int
384megasas_alloc_cmdlist_fusion(struct megasas_instance *instance)
385{
386 u32 max_cmd, i;
387 struct fusion_context *fusion;
388
389 fusion = instance->ctrl_context;
390
391 max_cmd = instance->max_fw_cmds;
392
393 /*
394 * fusion->cmd_list is an array of struct megasas_cmd_fusion pointers.
395 * Allocate the dynamic array first and then allocate individual
396 * commands.
397 */
398 fusion->cmd_list = kzalloc(sizeof(struct megasas_cmd_fusion *) * max_cmd,
399 GFP_KERNEL);
400 if (!fusion->cmd_list) {
401 dev_err(&instance->pdev->dev,
402 "Failed from %s %d\n", __func__, __LINE__);
403 return -ENOMEM;
404 }
405
406 for (i = 0; i < max_cmd; i++) {
407 fusion->cmd_list[i] = kzalloc(sizeof(struct megasas_cmd_fusion),
408 GFP_KERNEL);
409 if (!fusion->cmd_list[i]) {
410 dev_err(&instance->pdev->dev,
411 "Failed from %s %d\n", __func__, __LINE__);
412 return -ENOMEM;
413 }
414 }
415 return 0;
416}
417int
418megasas_alloc_request_fusion(struct megasas_instance *instance)
419{
420 struct fusion_context *fusion;
421
422 fusion = instance->ctrl_context;
423
424 fusion->req_frames_desc =
425 dma_alloc_coherent(&instance->pdev->dev,
426 fusion->request_alloc_sz,
427 &fusion->req_frames_desc_phys, GFP_KERNEL);
428 if (!fusion->req_frames_desc) {
429 dev_err(&instance->pdev->dev,
430 "Failed from %s %d\n", __func__, __LINE__);
431 return -ENOMEM;
432 }
433
434 fusion->io_request_frames_pool =
435 pci_pool_create("mr_ioreq", instance->pdev,
436 fusion->io_frames_alloc_sz, 16, 0);
437
438 if (!fusion->io_request_frames_pool) {
439 dev_err(&instance->pdev->dev,
440 "Failed from %s %d\n", __func__, __LINE__);
441 return -ENOMEM;
442 }
443
444 fusion->io_request_frames =
445 pci_pool_alloc(fusion->io_request_frames_pool,
446 GFP_KERNEL, &fusion->io_request_frames_phys);
447 if (!fusion->io_request_frames) {
448 dev_err(&instance->pdev->dev,
449 "Failed from %s %d\n", __func__, __LINE__);
450 return -ENOMEM;
451 }
452 return 0;
453}
454
455int
456megasas_alloc_reply_fusion(struct megasas_instance *instance)
457{
458 int i, count;
459 struct fusion_context *fusion;
460 union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
461 fusion = instance->ctrl_context;
462
463 count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
464 fusion->reply_frames_desc_pool =
465 pci_pool_create("mr_reply", instance->pdev,
466 fusion->reply_alloc_sz * count, 16, 0);
467
468 if (!fusion->reply_frames_desc_pool) {
469 dev_err(&instance->pdev->dev,
470 "Failed from %s %d\n", __func__, __LINE__);
471 return -ENOMEM;
472 }
473
474 fusion->reply_frames_desc[0] =
475 pci_pool_alloc(fusion->reply_frames_desc_pool,
476 GFP_KERNEL, &fusion->reply_frames_desc_phys[0]);
477 if (!fusion->reply_frames_desc[0]) {
478 dev_err(&instance->pdev->dev,
479 "Failed from %s %d\n", __func__, __LINE__);
480 return -ENOMEM;
481 }
482 reply_desc = fusion->reply_frames_desc[0];
483 for (i = 0; i < fusion->reply_q_depth * count; i++, reply_desc++)
484 reply_desc->Words = cpu_to_le64(ULLONG_MAX);
485
486 /* This is not a rdpq mode, but driver still populate
487 * reply_frame_desc array to use same msix index in ISR path.
488 */
489 for (i = 0; i < (count - 1); i++)
490 fusion->reply_frames_desc[i + 1] =
491 fusion->reply_frames_desc[i] +
492 (fusion->reply_alloc_sz)/sizeof(union MPI2_REPLY_DESCRIPTORS_UNION);
493
494 return 0;
495}
496
497int
498megasas_alloc_rdpq_fusion(struct megasas_instance *instance)
499{
500 int i, j, count;
501 struct fusion_context *fusion;
502 union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
503
504 fusion = instance->ctrl_context;
505
506 fusion->rdpq_virt = pci_alloc_consistent(instance->pdev,
507 sizeof(struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) * MAX_MSIX_QUEUES_FUSION,
508 &fusion->rdpq_phys);
509 if (!fusion->rdpq_virt) {
510 dev_err(&instance->pdev->dev,
511 "Failed from %s %d\n", __func__, __LINE__);
512 return -ENOMEM;
513 }
514
515 memset(fusion->rdpq_virt, 0,
516 sizeof(struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) * MAX_MSIX_QUEUES_FUSION);
517 count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
518 fusion->reply_frames_desc_pool = pci_pool_create("mr_rdpq",
519 instance->pdev, fusion->reply_alloc_sz, 16, 0);
520
521 if (!fusion->reply_frames_desc_pool) {
522 dev_err(&instance->pdev->dev,
523 "Failed from %s %d\n", __func__, __LINE__);
524 return -ENOMEM;
525 }
526
527 for (i = 0; i < count; i++) {
528 fusion->reply_frames_desc[i] =
529 pci_pool_alloc(fusion->reply_frames_desc_pool,
530 GFP_KERNEL, &fusion->reply_frames_desc_phys[i]);
531 if (!fusion->reply_frames_desc[i]) {
532 dev_err(&instance->pdev->dev,
533 "Failed from %s %d\n", __func__, __LINE__);
534 return -ENOMEM;
535 }
536
537 fusion->rdpq_virt[i].RDPQBaseAddress =
538 fusion->reply_frames_desc_phys[i];
539
540 reply_desc = fusion->reply_frames_desc[i];
541 for (j = 0; j < fusion->reply_q_depth; j++, reply_desc++)
542 reply_desc->Words = cpu_to_le64(ULLONG_MAX);
543 }
544 return 0;
545}
546
547static void
548megasas_free_rdpq_fusion(struct megasas_instance *instance) {
549
550 int i;
551 struct fusion_context *fusion;
552
553 fusion = instance->ctrl_context;
554
555 for (i = 0; i < MAX_MSIX_QUEUES_FUSION; i++) {
556 if (fusion->reply_frames_desc[i])
557 pci_pool_free(fusion->reply_frames_desc_pool,
558 fusion->reply_frames_desc[i],
559 fusion->reply_frames_desc_phys[i]);
560 }
561
562 if (fusion->reply_frames_desc_pool)
563 pci_pool_destroy(fusion->reply_frames_desc_pool);
564
565 if (fusion->rdpq_virt)
566 pci_free_consistent(instance->pdev,
567 sizeof(struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) * MAX_MSIX_QUEUES_FUSION,
568 fusion->rdpq_virt, fusion->rdpq_phys);
569}
570
571static void
572megasas_free_reply_fusion(struct megasas_instance *instance) {
573
574 struct fusion_context *fusion;
575
576 fusion = instance->ctrl_context;
577
578 if (fusion->reply_frames_desc[0])
579 pci_pool_free(fusion->reply_frames_desc_pool,
580 fusion->reply_frames_desc[0],
581 fusion->reply_frames_desc_phys[0]);
582
583 if (fusion->reply_frames_desc_pool)
584 pci_pool_destroy(fusion->reply_frames_desc_pool);
585
586}
587
588
adam radford9c915a82010-12-21 13:34:31 -0800589/**
590 * megasas_alloc_cmds_fusion - Allocates the command packets
591 * @instance: Adapter soft state
592 *
593 *
594 * Each frame has a 32-bit field called context. This context is used to get
595 * back the megasas_cmd_fusion from the frame when a frame gets completed
596 * In this driver, the 32 bit values are the indices into an array cmd_list.
597 * This array is used only to look up the megasas_cmd_fusion given the context.
598 * The free commands themselves are maintained in a linked list called cmd_pool.
599 *
600 * cmds are formed in the io_request and sg_frame members of the
601 * megasas_cmd_fusion. The context field is used to get a request descriptor
602 * and is used as SMID of the cmd.
603 * SMID value range is from 1 to max_fw_cmds.
604 */
605int
606megasas_alloc_cmds_fusion(struct megasas_instance *instance)
607{
Sumit Saxena179ac142016-01-28 21:04:28 +0530608 int i;
adam radford9c915a82010-12-21 13:34:31 -0800609 struct fusion_context *fusion;
610 struct megasas_cmd_fusion *cmd;
adam radford9c915a82010-12-21 13:34:31 -0800611 u32 offset;
612 dma_addr_t io_req_base_phys;
613 u8 *io_req_base;
614
Sumit Saxena179ac142016-01-28 21:04:28 +0530615
adam radford9c915a82010-12-21 13:34:31 -0800616 fusion = instance->ctrl_context;
617
Sumit Saxena179ac142016-01-28 21:04:28 +0530618 if (megasas_alloc_cmdlist_fusion(instance))
619 goto fail_exit;
adam radford9c915a82010-12-21 13:34:31 -0800620
Sumit Saxena179ac142016-01-28 21:04:28 +0530621 if (megasas_alloc_request_fusion(instance))
622 goto fail_exit;
adam radford9c915a82010-12-21 13:34:31 -0800623
Sumit Saxena179ac142016-01-28 21:04:28 +0530624 if (instance->is_rdpq) {
625 if (megasas_alloc_rdpq_fusion(instance))
626 goto fail_exit;
627 } else
628 if (megasas_alloc_reply_fusion(instance))
629 goto fail_exit;
adam radford9c915a82010-12-21 13:34:31 -0800630
adam radford9c915a82010-12-21 13:34:31 -0800631
Sumit Saxena179ac142016-01-28 21:04:28 +0530632 /* The first 256 bytes (SMID 0) is not used. Don't add to the cmd list */
633 io_req_base = fusion->io_request_frames + MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
634 io_req_base_phys = fusion->io_request_frames_phys + MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
adam radford9c915a82010-12-21 13:34:31 -0800635
636 /*
637 * Add all the commands to command pool (fusion->cmd_pool)
638 */
639
640 /* SMID 0 is reserved. Set SMID/index from 1 */
Sumit Saxena179ac142016-01-28 21:04:28 +0530641 for (i = 0; i < instance->max_fw_cmds; i++) {
adam radford9c915a82010-12-21 13:34:31 -0800642 cmd = fusion->cmd_list[i];
643 offset = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * i;
644 memset(cmd, 0, sizeof(struct megasas_cmd_fusion));
645 cmd->index = i + 1;
646 cmd->scmd = NULL;
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530647 cmd->sync_cmd_idx = (i >= instance->max_scsi_cmds) ?
648 (i - instance->max_scsi_cmds) :
649 (u32)ULONG_MAX; /* Set to Invalid */
adam radford9c915a82010-12-21 13:34:31 -0800650 cmd->instance = instance;
651 cmd->io_request =
652 (struct MPI2_RAID_SCSI_IO_REQUEST *)
653 (io_req_base + offset);
654 memset(cmd->io_request, 0,
655 sizeof(struct MPI2_RAID_SCSI_IO_REQUEST));
656 cmd->io_request_phys_addr = io_req_base_phys + offset;
adam radford9c915a82010-12-21 13:34:31 -0800657 }
658
Sumit Saxena179ac142016-01-28 21:04:28 +0530659 if (megasas_create_sg_sense_fusion(instance))
660 goto fail_exit;
adam radford9c915a82010-12-21 13:34:31 -0800661
662 return 0;
663
Sumit Saxena179ac142016-01-28 21:04:28 +0530664fail_exit:
665 megasas_free_cmds_fusion(instance);
adam radford9c915a82010-12-21 13:34:31 -0800666 return -ENOMEM;
667}
668
669/**
670 * wait_and_poll - Issues a polling command
671 * @instance: Adapter soft state
672 * @cmd: Command packet to be issued
673 *
674 * For polling, MFI requires the cmd_status to be set to 0xFF before posting.
675 */
676int
adam radford229fe472014-03-10 02:51:56 -0700677wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd,
678 int seconds)
adam radford9c915a82010-12-21 13:34:31 -0800679{
680 int i;
681 struct megasas_header *frame_hdr = &cmd->frame->hdr;
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530682 struct fusion_context *fusion;
adam radford9c915a82010-12-21 13:34:31 -0800683
adam radford229fe472014-03-10 02:51:56 -0700684 u32 msecs = seconds * 1000;
adam radford9c915a82010-12-21 13:34:31 -0800685
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530686 fusion = instance->ctrl_context;
adam radford9c915a82010-12-21 13:34:31 -0800687 /*
688 * Wait for cmd_status to change
689 */
690 for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i += 20) {
691 rmb();
692 msleep(20);
693 }
694
Sumit Saxena6d40afb2016-01-28 21:04:23 +0530695 if (frame_hdr->cmd_status == MFI_STAT_INVALID_STATUS)
696 return DCMD_TIMEOUT;
697 else if (frame_hdr->cmd_status == MFI_STAT_OK)
698 return DCMD_SUCCESS;
699 else
700 return DCMD_FAILED;
adam radford9c915a82010-12-21 13:34:31 -0800701}
702
703/**
704 * megasas_ioc_init_fusion - Initializes the FW
705 * @instance: Adapter soft state
706 *
707 * Issues the IOC Init cmd
708 */
709int
710megasas_ioc_init_fusion(struct megasas_instance *instance)
711{
712 struct megasas_init_frame *init_frame;
Sumit Saxena179ac142016-01-28 21:04:28 +0530713 struct MPI2_IOC_INIT_REQUEST *IOCInitMessage = NULL;
adam radford9c915a82010-12-21 13:34:31 -0800714 dma_addr_t ioc_init_handle;
adam radford9c915a82010-12-21 13:34:31 -0800715 struct megasas_cmd *cmd;
Sumit Saxena179ac142016-01-28 21:04:28 +0530716 u8 ret, cur_rdpq_mode;
adam radford9c915a82010-12-21 13:34:31 -0800717 struct fusion_context *fusion;
adam radfordc77a9bd2014-03-10 02:51:36 -0700718 union MEGASAS_REQUEST_DESCRIPTOR_UNION req_desc;
adam radford9c915a82010-12-21 13:34:31 -0800719 int i;
720 struct megasas_header *frame_hdr;
Sumit.Saxena@avagotech.com5765c5b2015-04-23 16:32:09 +0530721 const char *sys_info;
sumit.saxena@avagotech.com4dbbe3c2015-08-31 17:23:21 +0530722 MFI_CAPABILITIES *drv_ops;
Sumit Saxena179ac142016-01-28 21:04:28 +0530723 u32 scratch_pad_2;
adam radford9c915a82010-12-21 13:34:31 -0800724
725 fusion = instance->ctrl_context;
726
727 cmd = megasas_get_cmd(instance);
728
729 if (!cmd) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -0500730 dev_err(&instance->pdev->dev, "Could not allocate cmd for INIT Frame\n");
adam radford9c915a82010-12-21 13:34:31 -0800731 ret = 1;
732 goto fail_get_cmd;
733 }
734
Sumit Saxena179ac142016-01-28 21:04:28 +0530735 scratch_pad_2 = readl
736 (&instance->reg_set->outbound_scratch_pad_2);
737
738 cur_rdpq_mode = (scratch_pad_2 & MR_RDPQ_MODE_OFFSET) ? 1 : 0;
739
740 if (instance->is_rdpq && !cur_rdpq_mode) {
741 dev_err(&instance->pdev->dev, "Firmware downgrade *NOT SUPPORTED*"
742 " from RDPQ mode to non RDPQ mode\n");
743 ret = 1;
744 goto fail_fw_init;
745 }
746
adam radford9c915a82010-12-21 13:34:31 -0800747 IOCInitMessage =
748 dma_alloc_coherent(&instance->pdev->dev,
749 sizeof(struct MPI2_IOC_INIT_REQUEST),
750 &ioc_init_handle, GFP_KERNEL);
751
752 if (!IOCInitMessage) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -0500753 dev_err(&instance->pdev->dev, "Could not allocate memory for "
adam radford9c915a82010-12-21 13:34:31 -0800754 "IOCInitMessage\n");
755 ret = 1;
756 goto fail_fw_init;
757 }
758
759 memset(IOCInitMessage, 0, sizeof(struct MPI2_IOC_INIT_REQUEST));
760
761 IOCInitMessage->Function = MPI2_FUNCTION_IOC_INIT;
762 IOCInitMessage->WhoInit = MPI2_WHOINIT_HOST_DRIVER;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530763 IOCInitMessage->MsgVersion = cpu_to_le16(MPI2_VERSION);
764 IOCInitMessage->HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
765 IOCInitMessage->SystemRequestFrameSize = cpu_to_le16(MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE / 4);
adam radford9c915a82010-12-21 13:34:31 -0800766
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530767 IOCInitMessage->ReplyDescriptorPostQueueDepth = cpu_to_le16(fusion->reply_q_depth);
Sumit Saxena179ac142016-01-28 21:04:28 +0530768 IOCInitMessage->ReplyDescriptorPostQueueAddress = instance->is_rdpq ?
769 cpu_to_le64(fusion->rdpq_phys) :
770 cpu_to_le64(fusion->reply_frames_desc_phys[0]);
771 IOCInitMessage->MsgFlags = instance->is_rdpq ?
772 MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE : 0;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530773 IOCInitMessage->SystemRequestFrameBaseAddress = cpu_to_le64(fusion->io_request_frames_phys);
adam radford5738f992012-03-19 19:49:53 -0700774 IOCInitMessage->HostMSIxVectors = instance->msix_vectors;
adam radford9c915a82010-12-21 13:34:31 -0800775 init_frame = (struct megasas_init_frame *)cmd->frame;
776 memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
777
778 frame_hdr = &cmd->frame->hdr;
adam radford9c915a82010-12-21 13:34:31 -0800779 frame_hdr->cmd_status = 0xFF;
Christoph Hellwig48433bd2015-04-23 16:33:39 +0530780 frame_hdr->flags = cpu_to_le16(
781 le16_to_cpu(frame_hdr->flags) |
782 MFI_FRAME_DONT_POST_IN_REPLY_QUEUE);
adam radford9c915a82010-12-21 13:34:31 -0800783
784 init_frame->cmd = MFI_CMD_INIT;
785 init_frame->cmd_status = 0xFF;
786
sumit.saxena@avagotech.com4dbbe3c2015-08-31 17:23:21 +0530787 drv_ops = (MFI_CAPABILITIES *) &(init_frame->driver_operations);
788
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530789 /* driver support Extended MSIX */
sumit.saxena@avagotech.com5a8cb852015-10-15 13:39:34 +0530790 if (fusion->adapter_type == INVADER_SERIES)
sumit.saxena@avagotech.com4dbbe3c2015-08-31 17:23:21 +0530791 drv_ops->mfi_capabilities.support_additional_msix = 1;
adam radford21c9e162013-09-06 15:27:14 -0700792 /* driver supports HA / Remote LUN over Fast Path interface */
sumit.saxena@avagotech.com4dbbe3c2015-08-31 17:23:21 +0530793 drv_ops->mfi_capabilities.support_fp_remote_lun = 1;
794
795 drv_ops->mfi_capabilities.support_max_255lds = 1;
796 drv_ops->mfi_capabilities.support_ndrive_r1_lb = 1;
797 drv_ops->mfi_capabilities.security_protocol_cmds_fw = 1;
798
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +0530799 if (instance->max_chain_frame_sz > MEGASAS_CHAIN_FRAME_SZ_MIN)
800 drv_ops->mfi_capabilities.support_ext_io_size = 1;
801
Sumit Saxena8f050242016-01-28 21:04:27 +0530802 drv_ops->mfi_capabilities.support_fp_rlbypass = 1;
Sumit Saxena308ec452016-01-28 21:04:30 +0530803 if (!dual_qdepth_disable)
804 drv_ops->mfi_capabilities.support_ext_queue_depth = 1;
Sumit Saxena8f050242016-01-28 21:04:27 +0530805
Sumit Saxena52b62ac2016-01-28 21:04:31 +0530806 drv_ops->mfi_capabilities.support_qd_throttling = 1;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530807 /* Convert capability to LE32 */
808 cpu_to_le32s((u32 *)&init_frame->driver_operations.mfi_capabilities);
adam radford21c9e162013-09-06 15:27:14 -0700809
Sumit.Saxena@avagotech.com5765c5b2015-04-23 16:32:09 +0530810 sys_info = dmi_get_system_info(DMI_PRODUCT_UUID);
811 if (instance->system_info_buf && sys_info) {
812 memcpy(instance->system_info_buf->systemId, sys_info,
813 strlen(sys_info) > 64 ? 64 : strlen(sys_info));
814 instance->system_info_buf->systemIdLength =
815 strlen(sys_info) > 64 ? 64 : strlen(sys_info);
816 init_frame->system_info_lo = instance->system_info_h;
817 init_frame->system_info_hi = 0;
818 }
819
Hannes Reineckefdc5a972014-01-16 11:25:33 +0100820 init_frame->queue_info_new_phys_addr_hi =
821 cpu_to_le32(upper_32_bits(ioc_init_handle));
822 init_frame->queue_info_new_phys_addr_lo =
823 cpu_to_le32(lower_32_bits(ioc_init_handle));
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +0530824 init_frame->data_xfer_len = cpu_to_le32(sizeof(struct MPI2_IOC_INIT_REQUEST));
adam radford9c915a82010-12-21 13:34:31 -0800825
Sumit.Saxena@avagotech.com200aed52015-01-05 20:05:58 +0530826 req_desc.u.low = cpu_to_le32(lower_32_bits(cmd->frame_phys_addr));
827 req_desc.u.high = cpu_to_le32(upper_32_bits(cmd->frame_phys_addr));
adam radfordc77a9bd2014-03-10 02:51:36 -0700828 req_desc.MFAIo.RequestFlags =
adam radford9c915a82010-12-21 13:34:31 -0800829 (MEGASAS_REQ_DESCRIPT_FLAGS_MFA <<
Sumit.Saxena@avagotech.com200aed52015-01-05 20:05:58 +0530830 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
adam radford9c915a82010-12-21 13:34:31 -0800831
832 /*
833 * disable the intr before firing the init frame
834 */
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530835 instance->instancet->disable_intr(instance);
adam radford9c915a82010-12-21 13:34:31 -0800836
837 for (i = 0; i < (10 * 1000); i += 20) {
838 if (readl(&instance->reg_set->doorbell) & 1)
839 msleep(20);
840 else
841 break;
842 }
843
Christoph Hellwig01d7f032015-04-23 16:34:09 +0530844 megasas_fire_cmd_fusion(instance, &req_desc);
adam radford9c915a82010-12-21 13:34:31 -0800845
adam radford229fe472014-03-10 02:51:56 -0700846 wait_and_poll(instance, cmd, MFI_POLL_TIMEOUT_SECS);
adam radford9c915a82010-12-21 13:34:31 -0800847
848 frame_hdr = &cmd->frame->hdr;
849 if (frame_hdr->cmd_status != 0) {
850 ret = 1;
851 goto fail_fw_init;
852 }
Bjorn Helgaas1be18252015-07-07 15:52:34 -0500853 dev_err(&instance->pdev->dev, "Init cmd success\n");
adam radford9c915a82010-12-21 13:34:31 -0800854
855 ret = 0;
856
857fail_fw_init:
858 megasas_return_cmd(instance, cmd);
859 if (IOCInitMessage)
860 dma_free_coherent(&instance->pdev->dev,
861 sizeof(struct MPI2_IOC_INIT_REQUEST),
862 IOCInitMessage, ioc_init_handle);
863fail_get_cmd:
864 return ret;
865}
866
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +0530867/**
868 * megasas_sync_pd_seq_num - JBOD SEQ MAP
869 * @instance: Adapter soft state
870 * @pend: set to 1, if it is pended jbod map.
871 *
872 * Issue Jbod map to the firmware. If it is pended command,
873 * issue command and return. If it is first instance of jbod map
874 * issue and receive command.
875 */
876int
877megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend) {
878 int ret = 0;
879 u32 pd_seq_map_sz;
880 struct megasas_cmd *cmd;
881 struct megasas_dcmd_frame *dcmd;
882 struct fusion_context *fusion = instance->ctrl_context;
883 struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync;
884 dma_addr_t pd_seq_h;
885
886 pd_sync = (void *)fusion->pd_seq_sync[(instance->pd_seq_map_id & 1)];
887 pd_seq_h = fusion->pd_seq_phys[(instance->pd_seq_map_id & 1)];
888 pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) +
889 (sizeof(struct MR_PD_CFG_SEQ) *
890 (MAX_PHYSICAL_DEVICES - 1));
891
892 cmd = megasas_get_cmd(instance);
893 if (!cmd) {
894 dev_err(&instance->pdev->dev,
895 "Could not get mfi cmd. Fail from %s %d\n",
896 __func__, __LINE__);
897 return -ENOMEM;
898 }
899
900 dcmd = &cmd->frame->dcmd;
901
902 memset(pd_sync, 0, pd_seq_map_sz);
903 memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
904 dcmd->cmd = MFI_CMD_DCMD;
905 dcmd->cmd_status = 0xFF;
906 dcmd->sge_count = 1;
907 dcmd->timeout = 0;
908 dcmd->pad_0 = 0;
909 dcmd->data_xfer_len = cpu_to_le32(pd_seq_map_sz);
910 dcmd->opcode = cpu_to_le32(MR_DCMD_SYSTEM_PD_MAP_GET_INFO);
911 dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(pd_seq_h);
912 dcmd->sgl.sge32[0].length = cpu_to_le32(pd_seq_map_sz);
913
914 if (pend) {
915 dcmd->mbox.b[0] = MEGASAS_DCMD_MBOX_PEND_FLAG;
916 dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_WRITE);
917 instance->jbod_seq_cmd = cmd;
918 instance->instancet->issue_dcmd(instance, cmd);
919 return 0;
920 }
921
922 dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ);
923
924 /* Below code is only for non pended DCMD */
925 if (instance->ctrl_context && !instance->mask_interrupts)
Sumit Saxena6d40afb2016-01-28 21:04:23 +0530926 ret = megasas_issue_blocked_cmd(instance, cmd,
927 MFI_IO_TIMEOUT_SECS);
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +0530928 else
929 ret = megasas_issue_polled(instance, cmd);
930
931 if (le32_to_cpu(pd_sync->count) > MAX_PHYSICAL_DEVICES) {
932 dev_warn(&instance->pdev->dev,
933 "driver supports max %d JBOD, but FW reports %d\n",
934 MAX_PHYSICAL_DEVICES, le32_to_cpu(pd_sync->count));
935 ret = -EINVAL;
936 }
937
Sumit Saxena6d40afb2016-01-28 21:04:23 +0530938 if (ret == DCMD_TIMEOUT && instance->ctrl_context)
939 megaraid_sas_kill_hba(instance);
940
941 if (ret == DCMD_SUCCESS)
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +0530942 instance->pd_seq_map_id++;
943
944 megasas_return_cmd(instance, cmd);
945 return ret;
946}
947
adam radford9c915a82010-12-21 13:34:31 -0800948/*
adam radford9c915a82010-12-21 13:34:31 -0800949 * megasas_get_ld_map_info - Returns FW's ld_map structure
950 * @instance: Adapter soft state
951 * @pend: Pend the command or not
952 * Issues an internal command (DCMD) to get the FW's controller PD
953 * list structure. This information is mainly used to find out SYSTEM
954 * supported by the FW.
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530955 * dcmd.mbox value setting for MR_DCMD_LD_MAP_GET_INFO
956 * dcmd.mbox.b[0] - number of LDs being sync'd
957 * dcmd.mbox.b[1] - 0 - complete command immediately.
958 * - 1 - pend till config change
959 * dcmd.mbox.b[2] - 0 - supports max 64 lds and uses legacy MR_FW_RAID_MAP
960 * - 1 - supports max MAX_LOGICAL_DRIVES_EXT lds and
961 * uses extended struct MR_FW_RAID_MAP_EXT
adam radford9c915a82010-12-21 13:34:31 -0800962 */
963static int
964megasas_get_ld_map_info(struct megasas_instance *instance)
965{
966 int ret = 0;
967 struct megasas_cmd *cmd;
968 struct megasas_dcmd_frame *dcmd;
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530969 void *ci;
adam radford9c915a82010-12-21 13:34:31 -0800970 dma_addr_t ci_h = 0;
971 u32 size_map_info;
972 struct fusion_context *fusion;
973
974 cmd = megasas_get_cmd(instance);
975
976 if (!cmd) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -0500977 dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to get cmd for map info\n");
adam radford9c915a82010-12-21 13:34:31 -0800978 return -ENOMEM;
979 }
980
981 fusion = instance->ctrl_context;
982
983 if (!fusion) {
984 megasas_return_cmd(instance, cmd);
Hannes Reinecke2f8bdfa2014-01-16 11:25:35 +0100985 return -ENXIO;
adam radford9c915a82010-12-21 13:34:31 -0800986 }
987
988 dcmd = &cmd->frame->dcmd;
989
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530990 size_map_info = fusion->current_map_sz;
adam radford9c915a82010-12-21 13:34:31 -0800991
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +0530992 ci = (void *) fusion->ld_map[(instance->map_id & 1)];
adam radford9c915a82010-12-21 13:34:31 -0800993 ci_h = fusion->ld_map_phys[(instance->map_id & 1)];
994
995 if (!ci) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -0500996 dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to alloc mem for ld_map_info\n");
adam radford9c915a82010-12-21 13:34:31 -0800997 megasas_return_cmd(instance, cmd);
998 return -ENOMEM;
999 }
1000
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301001 memset(ci, 0, fusion->max_map_sz);
adam radford9c915a82010-12-21 13:34:31 -08001002 memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301003#if VD_EXT_DEBUG
1004 dev_dbg(&instance->pdev->dev,
1005 "%s sending MR_DCMD_LD_MAP_GET_INFO with size %d\n",
1006 __func__, cpu_to_le32(size_map_info));
1007#endif
adam radford9c915a82010-12-21 13:34:31 -08001008 dcmd->cmd = MFI_CMD_DCMD;
1009 dcmd->cmd_status = 0xFF;
1010 dcmd->sge_count = 1;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301011 dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ);
adam radford9c915a82010-12-21 13:34:31 -08001012 dcmd->timeout = 0;
1013 dcmd->pad_0 = 0;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301014 dcmd->data_xfer_len = cpu_to_le32(size_map_info);
1015 dcmd->opcode = cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO);
1016 dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(ci_h);
1017 dcmd->sgl.sge32[0].length = cpu_to_le32(size_map_info);
adam radford9c915a82010-12-21 13:34:31 -08001018
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +05301019 if (instance->ctrl_context && !instance->mask_interrupts)
1020 ret = megasas_issue_blocked_cmd(instance, cmd,
Sumit Saxena6d40afb2016-01-28 21:04:23 +05301021 MFI_IO_TIMEOUT_SECS);
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +05301022 else
1023 ret = megasas_issue_polled(instance, cmd);
adam radford9c915a82010-12-21 13:34:31 -08001024
Sumit Saxena6d40afb2016-01-28 21:04:23 +05301025 if (ret == DCMD_TIMEOUT && instance->ctrl_context)
1026 megaraid_sas_kill_hba(instance);
1027
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05301028 megasas_return_cmd(instance, cmd);
adam radford9c915a82010-12-21 13:34:31 -08001029
1030 return ret;
1031}
1032
1033u8
1034megasas_get_map_info(struct megasas_instance *instance)
1035{
1036 struct fusion_context *fusion = instance->ctrl_context;
1037
1038 fusion->fast_path_io = 0;
1039 if (!megasas_get_ld_map_info(instance)) {
Sumit.Saxena@lsi.combc93d422013-05-22 12:35:04 +05301040 if (MR_ValidateMapInfo(instance)) {
adam radford9c915a82010-12-21 13:34:31 -08001041 fusion->fast_path_io = 1;
1042 return 0;
1043 }
1044 }
1045 return 1;
1046}
1047
1048/*
1049 * megasas_sync_map_info - Returns FW's ld_map structure
1050 * @instance: Adapter soft state
1051 *
1052 * Issues an internal command (DCMD) to get the FW's controller PD
1053 * list structure. This information is mainly used to find out SYSTEM
1054 * supported by the FW.
1055 */
1056int
1057megasas_sync_map_info(struct megasas_instance *instance)
1058{
1059 int ret = 0, i;
1060 struct megasas_cmd *cmd;
1061 struct megasas_dcmd_frame *dcmd;
1062 u32 size_sync_info, num_lds;
1063 struct fusion_context *fusion;
1064 struct MR_LD_TARGET_SYNC *ci = NULL;
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301065 struct MR_DRV_RAID_MAP_ALL *map;
adam radford9c915a82010-12-21 13:34:31 -08001066 struct MR_LD_RAID *raid;
1067 struct MR_LD_TARGET_SYNC *ld_sync;
1068 dma_addr_t ci_h = 0;
1069 u32 size_map_info;
1070
1071 cmd = megasas_get_cmd(instance);
1072
1073 if (!cmd) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05001074 dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to get cmd for sync info\n");
adam radford9c915a82010-12-21 13:34:31 -08001075 return -ENOMEM;
1076 }
1077
1078 fusion = instance->ctrl_context;
1079
1080 if (!fusion) {
1081 megasas_return_cmd(instance, cmd);
1082 return 1;
1083 }
1084
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301085 map = fusion->ld_drv_map[instance->map_id & 1];
adam radford9c915a82010-12-21 13:34:31 -08001086
Sumit.Saxena@avagotech.com6e755dd2014-11-17 15:24:28 +05301087 num_lds = le16_to_cpu(map->raidMap.ldCount);
adam radford9c915a82010-12-21 13:34:31 -08001088
1089 dcmd = &cmd->frame->dcmd;
1090
1091 size_sync_info = sizeof(struct MR_LD_TARGET_SYNC) *num_lds;
1092
1093 memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
1094
1095 ci = (struct MR_LD_TARGET_SYNC *)
1096 fusion->ld_map[(instance->map_id - 1) & 1];
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301097 memset(ci, 0, fusion->max_map_sz);
adam radford9c915a82010-12-21 13:34:31 -08001098
1099 ci_h = fusion->ld_map_phys[(instance->map_id - 1) & 1];
1100
1101 ld_sync = (struct MR_LD_TARGET_SYNC *)ci;
1102
1103 for (i = 0; i < num_lds; i++, ld_sync++) {
1104 raid = MR_LdRaidGet(i, map);
1105 ld_sync->targetId = MR_GetLDTgtId(i, map);
1106 ld_sync->seqNum = raid->seqNum;
1107 }
1108
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301109 size_map_info = fusion->current_map_sz;
adam radford9c915a82010-12-21 13:34:31 -08001110
1111 dcmd->cmd = MFI_CMD_DCMD;
1112 dcmd->cmd_status = 0xFF;
1113 dcmd->sge_count = 1;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301114 dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_WRITE);
adam radford9c915a82010-12-21 13:34:31 -08001115 dcmd->timeout = 0;
1116 dcmd->pad_0 = 0;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301117 dcmd->data_xfer_len = cpu_to_le32(size_map_info);
adam radford9c915a82010-12-21 13:34:31 -08001118 dcmd->mbox.b[0] = num_lds;
1119 dcmd->mbox.b[1] = MEGASAS_DCMD_MBOX_PEND_FLAG;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301120 dcmd->opcode = cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO);
1121 dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(ci_h);
1122 dcmd->sgl.sge32[0].length = cpu_to_le32(size_map_info);
adam radford9c915a82010-12-21 13:34:31 -08001123
1124 instance->map_update_cmd = cmd;
1125
1126 instance->instancet->issue_dcmd(instance, cmd);
1127
1128 return ret;
1129}
1130
Sumit.Saxena@lsi.com39b72c32013-05-22 12:32:43 +05301131/*
1132 * meagasas_display_intel_branding - Display branding string
1133 * @instance: per adapter object
1134 *
1135 * Return nothing.
1136 */
1137static void
1138megasas_display_intel_branding(struct megasas_instance *instance)
1139{
1140 if (instance->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL)
1141 return;
1142
1143 switch (instance->pdev->device) {
1144 case PCI_DEVICE_ID_LSI_INVADER:
1145 switch (instance->pdev->subsystem_device) {
1146 case MEGARAID_INTEL_RS3DC080_SSDID:
1147 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
1148 instance->host->host_no,
1149 MEGARAID_INTEL_RS3DC080_BRANDING);
1150 break;
1151 case MEGARAID_INTEL_RS3DC040_SSDID:
1152 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
1153 instance->host->host_no,
1154 MEGARAID_INTEL_RS3DC040_BRANDING);
1155 break;
1156 case MEGARAID_INTEL_RS3SC008_SSDID:
1157 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
1158 instance->host->host_no,
1159 MEGARAID_INTEL_RS3SC008_BRANDING);
1160 break;
1161 case MEGARAID_INTEL_RS3MC044_SSDID:
1162 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
1163 instance->host->host_no,
1164 MEGARAID_INTEL_RS3MC044_BRANDING);
1165 break;
1166 default:
1167 break;
1168 }
1169 break;
1170 case PCI_DEVICE_ID_LSI_FURY:
1171 switch (instance->pdev->subsystem_device) {
1172 case MEGARAID_INTEL_RS3WC080_SSDID:
1173 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
1174 instance->host->host_no,
1175 MEGARAID_INTEL_RS3WC080_BRANDING);
1176 break;
1177 case MEGARAID_INTEL_RS3WC040_SSDID:
1178 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
1179 instance->host->host_no,
1180 MEGARAID_INTEL_RS3WC040_BRANDING);
1181 break;
1182 default:
1183 break;
1184 }
1185 break;
sumit.saxena@avagotech.com7364d342015-10-15 13:39:54 +05301186 case PCI_DEVICE_ID_LSI_CUTLASS_52:
1187 case PCI_DEVICE_ID_LSI_CUTLASS_53:
1188 switch (instance->pdev->subsystem_device) {
1189 case MEGARAID_INTEL_RMS3BC160_SSDID:
1190 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
1191 instance->host->host_no,
1192 MEGARAID_INTEL_RMS3BC160_BRANDING);
1193 break;
1194 default:
1195 break;
1196 }
1197 break;
Sumit.Saxena@lsi.com39b72c32013-05-22 12:32:43 +05301198 default:
1199 break;
1200 }
1201}
1202
adam radford9c915a82010-12-21 13:34:31 -08001203/**
1204 * megasas_init_adapter_fusion - Initializes the FW
1205 * @instance: Adapter soft state
1206 *
1207 * This is the main function for initializing firmware.
1208 */
1209u32
1210megasas_init_adapter_fusion(struct megasas_instance *instance)
1211{
1212 struct megasas_register_set __iomem *reg_set;
1213 struct fusion_context *fusion;
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05301214 u32 max_cmd, scratch_pad_2;
adam radfordc8e858f2011-10-08 18:15:13 -07001215 int i = 0, count;
adam radford9c915a82010-12-21 13:34:31 -08001216
1217 fusion = instance->ctrl_context;
1218
1219 reg_set = instance->reg_set;
1220
Sumit Saxena308ec452016-01-28 21:04:30 +05301221 megasas_fusion_update_can_queue(instance, PROBE_CONTEXT);
adam radford9c915a82010-12-21 13:34:31 -08001222
1223 /*
1224 * Reduce the max supported cmds by 1. This is to ensure that the
1225 * reply_q_sz (1 more than the max cmd that driver may send)
1226 * does not exceed max cmds that the FW can support
1227 */
1228 instance->max_fw_cmds = instance->max_fw_cmds-1;
Sumit.Saxena@avagotech.comae09a6c2015-01-05 20:06:23 +05301229
1230 /*
1231 * Only Driver's internal DCMDs and IOCTL DCMDs needs to have MFI frames
1232 */
1233 instance->max_mfi_cmds =
1234 MEGASAS_FUSION_INTERNAL_CMDS + MEGASAS_FUSION_IOCTL_CMDS;
adam radford9c915a82010-12-21 13:34:31 -08001235
1236 max_cmd = instance->max_fw_cmds;
1237
Sumit.Saxena@avagotech.comdb4fc862014-09-12 18:57:23 +05301238 fusion->reply_q_depth = 2 * (((max_cmd + 1 + 15)/16)*16);
adam radford9c915a82010-12-21 13:34:31 -08001239
1240 fusion->request_alloc_sz =
1241 sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *max_cmd;
1242 fusion->reply_alloc_sz = sizeof(union MPI2_REPLY_DESCRIPTORS_UNION)
1243 *(fusion->reply_q_depth);
1244 fusion->io_frames_alloc_sz = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE +
1245 (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE *
1246 (max_cmd + 1)); /* Extra 1 for SMID 0 */
1247
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05301248 scratch_pad_2 = readl(&instance->reg_set->outbound_scratch_pad_2);
1249 /* If scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK is set,
1250 * Firmware support extended IO chain frame which is 4 times more than
1251 * legacy Firmware.
1252 * Legacy Firmware - Frame size is (8 * 128) = 1K
1253 * 1M IO Firmware - Frame size is (8 * 128 * 4) = 4K
1254 */
1255 if (scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK)
1256 instance->max_chain_frame_sz =
1257 ((scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_MASK) >>
1258 MEGASAS_MAX_CHAIN_SHIFT) * MEGASAS_1MB_IO;
1259 else
1260 instance->max_chain_frame_sz =
1261 ((scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_MASK) >>
1262 MEGASAS_MAX_CHAIN_SHIFT) * MEGASAS_256K_IO;
1263
1264 if (instance->max_chain_frame_sz < MEGASAS_CHAIN_FRAME_SZ_MIN) {
1265 dev_warn(&instance->pdev->dev, "frame size %d invalid, fall back to legacy max frame size %d\n",
1266 instance->max_chain_frame_sz,
1267 MEGASAS_CHAIN_FRAME_SZ_MIN);
1268 instance->max_chain_frame_sz = MEGASAS_CHAIN_FRAME_SZ_MIN;
1269 }
1270
adam radford9c915a82010-12-21 13:34:31 -08001271 fusion->max_sge_in_main_msg =
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05301272 (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE
1273 - offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL))/16;
adam radford9c915a82010-12-21 13:34:31 -08001274
1275 fusion->max_sge_in_chain =
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05301276 instance->max_chain_frame_sz
1277 / sizeof(union MPI2_SGE_IO_UNION);
adam radford9c915a82010-12-21 13:34:31 -08001278
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05301279 instance->max_num_sge =
1280 rounddown_pow_of_two(fusion->max_sge_in_main_msg
1281 + fusion->max_sge_in_chain - 2);
adam radford9c915a82010-12-21 13:34:31 -08001282
1283 /* Used for pass thru MFI frame (DCMD) */
1284 fusion->chain_offset_mfi_pthru =
1285 offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL)/16;
1286
1287 fusion->chain_offset_io_request =
1288 (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
1289 sizeof(union MPI2_SGE_IO_UNION))/16;
1290
adam radfordc8e858f2011-10-08 18:15:13 -07001291 count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
1292 for (i = 0 ; i < count; i++)
1293 fusion->last_reply_idx[i] = 0;
adam radford9c915a82010-12-21 13:34:31 -08001294
1295 /*
Sumit.Saxena@avagotech.comf26ac3a2015-04-23 16:30:54 +05301296 * For fusion adapters, 3 commands for IOCTL and 5 commands
1297 * for driver's internal DCMDs.
1298 */
1299 instance->max_scsi_cmds = instance->max_fw_cmds -
1300 (MEGASAS_FUSION_INTERNAL_CMDS +
1301 MEGASAS_FUSION_IOCTL_CMDS);
1302 sema_init(&instance->ioctl_sem, MEGASAS_FUSION_IOCTL_CMDS);
1303
1304 /*
adam radford9c915a82010-12-21 13:34:31 -08001305 * Allocate memory for descriptors
1306 * Create a pool of commands
1307 */
1308 if (megasas_alloc_cmds(instance))
1309 goto fail_alloc_mfi_cmds;
1310 if (megasas_alloc_cmds_fusion(instance))
1311 goto fail_alloc_cmds;
1312
1313 if (megasas_ioc_init_fusion(instance))
1314 goto fail_ioc_init;
1315
Sumit.Saxena@lsi.com39b72c32013-05-22 12:32:43 +05301316 megasas_display_intel_branding(instance);
Sumit.Saxena@avagotech.comd009b572014-11-17 15:24:13 +05301317 if (megasas_get_ctrl_info(instance)) {
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301318 dev_err(&instance->pdev->dev,
1319 "Could not get controller info. Fail from %s %d\n",
1320 __func__, __LINE__);
1321 goto fail_ioc_init;
1322 }
1323
adam radford9c915a82010-12-21 13:34:31 -08001324 instance->flag_ieee = 1;
adam radford9c915a82010-12-21 13:34:31 -08001325 fusion->fast_path_io = 0;
1326
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301327 fusion->drv_map_pages = get_order(fusion->drv_map_sz);
1328 for (i = 0; i < 2; i++) {
1329 fusion->ld_map[i] = NULL;
1330 fusion->ld_drv_map[i] = (void *)__get_free_pages(GFP_KERNEL,
1331 fusion->drv_map_pages);
1332 if (!fusion->ld_drv_map[i]) {
1333 dev_err(&instance->pdev->dev, "Could not allocate "
1334 "memory for local map info for %d pages\n",
1335 fusion->drv_map_pages);
1336 if (i == 1)
1337 free_pages((ulong)fusion->ld_drv_map[0],
1338 fusion->drv_map_pages);
1339 goto fail_ioc_init;
1340 }
Sumit.Saxena@avagotech.comd009b572014-11-17 15:24:13 +05301341 memset(fusion->ld_drv_map[i], 0,
1342 ((1 << PAGE_SHIFT) << fusion->drv_map_pages));
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301343 }
1344
adam radford9c915a82010-12-21 13:34:31 -08001345 for (i = 0; i < 2; i++) {
1346 fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301347 fusion->max_map_sz,
adam radford9c915a82010-12-21 13:34:31 -08001348 &fusion->ld_map_phys[i],
1349 GFP_KERNEL);
1350 if (!fusion->ld_map[i]) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05001351 dev_err(&instance->pdev->dev, "Could not allocate memory "
adam radford9c915a82010-12-21 13:34:31 -08001352 "for map info\n");
1353 goto fail_map_info;
1354 }
1355 }
1356
1357 if (!megasas_get_map_info(instance))
1358 megasas_sync_map_info(instance);
1359
1360 return 0;
1361
adam radford9c915a82010-12-21 13:34:31 -08001362fail_map_info:
1363 if (i == 1)
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301364 dma_free_coherent(&instance->pdev->dev, fusion->max_map_sz,
adam radford9c915a82010-12-21 13:34:31 -08001365 fusion->ld_map[0], fusion->ld_map_phys[0]);
1366fail_ioc_init:
adam radfordeb1b1232011-02-24 20:55:56 -08001367 megasas_free_cmds_fusion(instance);
1368fail_alloc_cmds:
1369 megasas_free_cmds(instance);
1370fail_alloc_mfi_cmds:
adam radford9c915a82010-12-21 13:34:31 -08001371 return 1;
1372}
1373
1374/**
adam radford9c915a82010-12-21 13:34:31 -08001375 * map_cmd_status - Maps FW cmd status to OS cmd status
1376 * @cmd : Pointer to cmd
1377 * @status : status of cmd returned by FW
1378 * @ext_status : ext status of cmd returned by FW
1379 */
1380
1381void
1382map_cmd_status(struct megasas_cmd_fusion *cmd, u8 status, u8 ext_status)
1383{
1384
1385 switch (status) {
1386
1387 case MFI_STAT_OK:
1388 cmd->scmd->result = DID_OK << 16;
1389 break;
1390
1391 case MFI_STAT_SCSI_IO_FAILED:
1392 case MFI_STAT_LD_INIT_IN_PROGRESS:
1393 cmd->scmd->result = (DID_ERROR << 16) | ext_status;
1394 break;
1395
1396 case MFI_STAT_SCSI_DONE_WITH_ERROR:
1397
1398 cmd->scmd->result = (DID_OK << 16) | ext_status;
1399 if (ext_status == SAM_STAT_CHECK_CONDITION) {
1400 memset(cmd->scmd->sense_buffer, 0,
1401 SCSI_SENSE_BUFFERSIZE);
1402 memcpy(cmd->scmd->sense_buffer, cmd->sense,
1403 SCSI_SENSE_BUFFERSIZE);
1404 cmd->scmd->result |= DRIVER_SENSE << 24;
1405 }
1406 break;
1407
1408 case MFI_STAT_LD_OFFLINE:
1409 case MFI_STAT_DEVICE_NOT_FOUND:
1410 cmd->scmd->result = DID_BAD_TARGET << 16;
1411 break;
adam radford36807e62011-10-08 18:15:06 -07001412 case MFI_STAT_CONFIG_SEQ_MISMATCH:
1413 cmd->scmd->result = DID_IMM_RETRY << 16;
1414 break;
adam radford9c915a82010-12-21 13:34:31 -08001415 default:
Bjorn Helgaas1be18252015-07-07 15:52:34 -05001416 dev_printk(KERN_DEBUG, &cmd->instance->pdev->dev, "FW status %#x\n", status);
adam radford9c915a82010-12-21 13:34:31 -08001417 cmd->scmd->result = DID_ERROR << 16;
1418 break;
1419 }
1420}
1421
1422/**
1423 * megasas_make_sgl_fusion - Prepares 32-bit SGL
1424 * @instance: Adapter soft state
1425 * @scp: SCSI command from the mid-layer
1426 * @sgl_ptr: SGL to be filled in
1427 * @cmd: cmd we are working on
1428 *
1429 * If successful, this function returns the number of SG elements.
1430 */
1431static int
1432megasas_make_sgl_fusion(struct megasas_instance *instance,
1433 struct scsi_cmnd *scp,
1434 struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr,
1435 struct megasas_cmd_fusion *cmd)
1436{
adam radford36807e62011-10-08 18:15:06 -07001437 int i, sg_processed, sge_count;
adam radford9c915a82010-12-21 13:34:31 -08001438 struct scatterlist *os_sgl;
1439 struct fusion_context *fusion;
1440
1441 fusion = instance->ctrl_context;
1442
sumit.saxena@avagotech.com5a8cb852015-10-15 13:39:34 +05301443 if (fusion->adapter_type == INVADER_SERIES) {
adam radford36807e62011-10-08 18:15:06 -07001444 struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = sgl_ptr;
1445 sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
1446 sgl_ptr_end->Flags = 0;
1447 }
adam radford9c915a82010-12-21 13:34:31 -08001448
1449 sge_count = scsi_dma_map(scp);
1450
1451 BUG_ON(sge_count < 0);
1452
1453 if (sge_count > instance->max_num_sge || !sge_count)
1454 return sge_count;
1455
adam radford9c915a82010-12-21 13:34:31 -08001456 scsi_for_each_sg(scp, os_sgl, sge_count, i) {
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301457 sgl_ptr->Length = cpu_to_le32(sg_dma_len(os_sgl));
1458 sgl_ptr->Address = cpu_to_le64(sg_dma_address(os_sgl));
adam radford9c915a82010-12-21 13:34:31 -08001459 sgl_ptr->Flags = 0;
sumit.saxena@avagotech.com5a8cb852015-10-15 13:39:34 +05301460 if (fusion->adapter_type == INVADER_SERIES)
adam radford36807e62011-10-08 18:15:06 -07001461 if (i == sge_count - 1)
1462 sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST;
adam radford9c915a82010-12-21 13:34:31 -08001463 sgl_ptr++;
1464
1465 sg_processed = i + 1;
1466
1467 if ((sg_processed == (fusion->max_sge_in_main_msg - 1)) &&
1468 (sge_count > fusion->max_sge_in_main_msg)) {
1469
1470 struct MPI25_IEEE_SGE_CHAIN64 *sg_chain;
sumit.saxena@avagotech.com5a8cb852015-10-15 13:39:34 +05301471 if (fusion->adapter_type == INVADER_SERIES) {
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301472 if ((le16_to_cpu(cmd->io_request->IoFlags) &
1473 MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) !=
1474 MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)
adam radford36807e62011-10-08 18:15:06 -07001475 cmd->io_request->ChainOffset =
1476 fusion->
1477 chain_offset_io_request;
1478 else
1479 cmd->io_request->ChainOffset = 0;
1480 } else
1481 cmd->io_request->ChainOffset =
1482 fusion->chain_offset_io_request;
1483
adam radford9c915a82010-12-21 13:34:31 -08001484 sg_chain = sgl_ptr;
1485 /* Prepare chain element */
1486 sg_chain->NextChainOffset = 0;
sumit.saxena@avagotech.com5a8cb852015-10-15 13:39:34 +05301487 if (fusion->adapter_type == INVADER_SERIES)
adam radford36807e62011-10-08 18:15:06 -07001488 sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT;
1489 else
1490 sg_chain->Flags =
1491 (IEEE_SGE_FLAGS_CHAIN_ELEMENT |
1492 MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301493 sg_chain->Length = cpu_to_le32((sizeof(union MPI2_SGE_IO_UNION) * (sge_count - sg_processed)));
1494 sg_chain->Address = cpu_to_le64(cmd->sg_frame_phys_addr);
adam radford9c915a82010-12-21 13:34:31 -08001495
1496 sgl_ptr =
1497 (struct MPI25_IEEE_SGE_CHAIN64 *)cmd->sg_frame;
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05301498 memset(sgl_ptr, 0, instance->max_chain_frame_sz);
adam radford9c915a82010-12-21 13:34:31 -08001499 }
1500 }
1501
1502 return sge_count;
1503}
1504
1505/**
1506 * megasas_set_pd_lba - Sets PD LBA
1507 * @cdb: CDB
1508 * @cdb_len: cdb length
1509 * @start_blk: Start block of IO
1510 *
1511 * Used to set the PD LBA in CDB for FP IOs
1512 */
1513void
1514megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
1515 struct IO_REQUEST_INFO *io_info, struct scsi_cmnd *scp,
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301516 struct MR_DRV_RAID_MAP_ALL *local_map_ptr, u32 ref_tag)
adam radford9c915a82010-12-21 13:34:31 -08001517{
1518 struct MR_LD_RAID *raid;
1519 u32 ld;
1520 u64 start_blk = io_info->pdBlock;
1521 u8 *cdb = io_request->CDB.CDB32;
1522 u32 num_blocks = io_info->numBlocks;
adam radford495c5602011-05-11 18:34:40 -07001523 u8 opcode = 0, flagvals = 0, groupnum = 0, control = 0;
adam radford9c915a82010-12-21 13:34:31 -08001524
1525 /* Check if T10 PI (DIF) is enabled for this LD */
1526 ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr);
1527 raid = MR_LdRaidGet(ld, local_map_ptr);
1528 if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) {
1529 memset(cdb, 0, sizeof(io_request->CDB.CDB32));
1530 cdb[0] = MEGASAS_SCSI_VARIABLE_LENGTH_CMD;
1531 cdb[7] = MEGASAS_SCSI_ADDL_CDB_LEN;
1532
1533 if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
1534 cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_READ32;
1535 else
1536 cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_WRITE32;
1537 cdb[10] = MEGASAS_RD_WR_PROTECT_CHECK_ALL;
1538
1539 /* LBA */
1540 cdb[12] = (u8)((start_blk >> 56) & 0xff);
1541 cdb[13] = (u8)((start_blk >> 48) & 0xff);
1542 cdb[14] = (u8)((start_blk >> 40) & 0xff);
1543 cdb[15] = (u8)((start_blk >> 32) & 0xff);
1544 cdb[16] = (u8)((start_blk >> 24) & 0xff);
1545 cdb[17] = (u8)((start_blk >> 16) & 0xff);
1546 cdb[18] = (u8)((start_blk >> 8) & 0xff);
1547 cdb[19] = (u8)(start_blk & 0xff);
1548
1549 /* Logical block reference tag */
1550 io_request->CDB.EEDP32.PrimaryReferenceTag =
1551 cpu_to_be32(ref_tag);
Sumit.Saxena@avagotech.com6e755dd2014-11-17 15:24:28 +05301552 io_request->CDB.EEDP32.PrimaryApplicationTagMask = cpu_to_be16(0xffff);
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301553 io_request->IoFlags = cpu_to_le16(32); /* Specify 32-byte cdb */
adam radford9c915a82010-12-21 13:34:31 -08001554
1555 /* Transfer length */
1556 cdb[28] = (u8)((num_blocks >> 24) & 0xff);
1557 cdb[29] = (u8)((num_blocks >> 16) & 0xff);
1558 cdb[30] = (u8)((num_blocks >> 8) & 0xff);
1559 cdb[31] = (u8)(num_blocks & 0xff);
1560
1561 /* set SCSI IO EEDPFlags */
1562 if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) {
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301563 io_request->EEDPFlags = cpu_to_le16(
adam radford9c915a82010-12-21 13:34:31 -08001564 MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
1565 MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
1566 MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP |
1567 MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG |
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301568 MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD);
adam radford9c915a82010-12-21 13:34:31 -08001569 } else {
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301570 io_request->EEDPFlags = cpu_to_le16(
adam radford9c915a82010-12-21 13:34:31 -08001571 MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301572 MPI2_SCSIIO_EEDPFLAGS_INSERT_OP);
adam radford9c915a82010-12-21 13:34:31 -08001573 }
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301574 io_request->Control |= cpu_to_le32((0x4 << 26));
1575 io_request->EEDPBlockSize = cpu_to_le32(scp->device->sector_size);
adam radford9c915a82010-12-21 13:34:31 -08001576 } else {
1577 /* Some drives don't support 16/12 byte CDB's, convert to 10 */
1578 if (((cdb_len == 12) || (cdb_len == 16)) &&
1579 (start_blk <= 0xffffffff)) {
1580 if (cdb_len == 16) {
1581 opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10;
1582 flagvals = cdb[1];
1583 groupnum = cdb[14];
1584 control = cdb[15];
1585 } else {
1586 opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10;
1587 flagvals = cdb[1];
1588 groupnum = cdb[10];
1589 control = cdb[11];
1590 }
1591
1592 memset(cdb, 0, sizeof(io_request->CDB.CDB32));
1593
1594 cdb[0] = opcode;
1595 cdb[1] = flagvals;
1596 cdb[6] = groupnum;
1597 cdb[9] = control;
1598
1599 /* Transfer length */
1600 cdb[8] = (u8)(num_blocks & 0xff);
1601 cdb[7] = (u8)((num_blocks >> 8) & 0xff);
1602
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301603 io_request->IoFlags = cpu_to_le16(10); /* Specify 10-byte cdb */
adam radford9c915a82010-12-21 13:34:31 -08001604 cdb_len = 10;
adam radford495c5602011-05-11 18:34:40 -07001605 } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) {
1606 /* Convert to 16 byte CDB for large LBA's */
1607 switch (cdb_len) {
1608 case 6:
1609 opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16;
1610 control = cdb[5];
1611 break;
1612 case 10:
1613 opcode =
1614 cdb[0] == READ_10 ? READ_16 : WRITE_16;
1615 flagvals = cdb[1];
1616 groupnum = cdb[6];
1617 control = cdb[9];
1618 break;
1619 case 12:
1620 opcode =
1621 cdb[0] == READ_12 ? READ_16 : WRITE_16;
1622 flagvals = cdb[1];
1623 groupnum = cdb[10];
1624 control = cdb[11];
1625 break;
1626 }
1627
1628 memset(cdb, 0, sizeof(io_request->CDB.CDB32));
1629
1630 cdb[0] = opcode;
1631 cdb[1] = flagvals;
1632 cdb[14] = groupnum;
1633 cdb[15] = control;
1634
1635 /* Transfer length */
1636 cdb[13] = (u8)(num_blocks & 0xff);
1637 cdb[12] = (u8)((num_blocks >> 8) & 0xff);
1638 cdb[11] = (u8)((num_blocks >> 16) & 0xff);
1639 cdb[10] = (u8)((num_blocks >> 24) & 0xff);
1640
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301641 io_request->IoFlags = cpu_to_le16(16); /* Specify 16-byte cdb */
adam radford495c5602011-05-11 18:34:40 -07001642 cdb_len = 16;
adam radford9c915a82010-12-21 13:34:31 -08001643 }
1644
1645 /* Normal case, just load LBA here */
1646 switch (cdb_len) {
1647 case 6:
1648 {
1649 u8 val = cdb[1] & 0xE0;
1650 cdb[3] = (u8)(start_blk & 0xff);
1651 cdb[2] = (u8)((start_blk >> 8) & 0xff);
1652 cdb[1] = val | ((u8)(start_blk >> 16) & 0x1f);
1653 break;
1654 }
1655 case 10:
1656 cdb[5] = (u8)(start_blk & 0xff);
1657 cdb[4] = (u8)((start_blk >> 8) & 0xff);
1658 cdb[3] = (u8)((start_blk >> 16) & 0xff);
1659 cdb[2] = (u8)((start_blk >> 24) & 0xff);
1660 break;
1661 case 12:
1662 cdb[5] = (u8)(start_blk & 0xff);
1663 cdb[4] = (u8)((start_blk >> 8) & 0xff);
1664 cdb[3] = (u8)((start_blk >> 16) & 0xff);
1665 cdb[2] = (u8)((start_blk >> 24) & 0xff);
1666 break;
1667 case 16:
1668 cdb[9] = (u8)(start_blk & 0xff);
1669 cdb[8] = (u8)((start_blk >> 8) & 0xff);
1670 cdb[7] = (u8)((start_blk >> 16) & 0xff);
1671 cdb[6] = (u8)((start_blk >> 24) & 0xff);
1672 cdb[5] = (u8)((start_blk >> 32) & 0xff);
1673 cdb[4] = (u8)((start_blk >> 40) & 0xff);
1674 cdb[3] = (u8)((start_blk >> 48) & 0xff);
1675 cdb[2] = (u8)((start_blk >> 56) & 0xff);
1676 break;
1677 }
1678 }
1679}
1680
1681/**
1682 * megasas_build_ldio_fusion - Prepares IOs to devices
1683 * @instance: Adapter soft state
1684 * @scp: SCSI command
1685 * @cmd: Command to be prepared
1686 *
1687 * Prepares the io_request and chain elements (sg_frame) for IO
1688 * The IO can be for PD (Fast Path) or LD
1689 */
1690void
1691megasas_build_ldio_fusion(struct megasas_instance *instance,
1692 struct scsi_cmnd *scp,
1693 struct megasas_cmd_fusion *cmd)
1694{
1695 u8 fp_possible;
adam radfordf9eff812012-10-01 19:27:07 -07001696 u32 start_lba_lo, start_lba_hi, device_id, datalength = 0;
adam radford9c915a82010-12-21 13:34:31 -08001697 struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
1698 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
1699 struct IO_REQUEST_INFO io_info;
1700 struct fusion_context *fusion;
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301701 struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
adam radford21c9e162013-09-06 15:27:14 -07001702 u8 *raidLUN;
adam radford9c915a82010-12-21 13:34:31 -08001703
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301704 device_id = MEGASAS_DEV_INDEX(scp);
adam radford9c915a82010-12-21 13:34:31 -08001705
1706 fusion = instance->ctrl_context;
1707
1708 io_request = cmd->io_request;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301709 io_request->RaidContext.VirtualDiskTgtId = cpu_to_le16(device_id);
adam radford9c915a82010-12-21 13:34:31 -08001710 io_request->RaidContext.status = 0;
1711 io_request->RaidContext.exStatus = 0;
1712
1713 req_desc = (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)cmd->request_desc;
1714
1715 start_lba_lo = 0;
1716 start_lba_hi = 0;
1717 fp_possible = 0;
1718
1719 /*
1720 * 6-byte READ(0x08) or WRITE(0x0A) cdb
1721 */
1722 if (scp->cmd_len == 6) {
adam radfordf9eff812012-10-01 19:27:07 -07001723 datalength = (u32) scp->cmnd[4];
adam radford9c915a82010-12-21 13:34:31 -08001724 start_lba_lo = ((u32) scp->cmnd[1] << 16) |
1725 ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3];
1726
1727 start_lba_lo &= 0x1FFFFF;
1728 }
1729
1730 /*
1731 * 10-byte READ(0x28) or WRITE(0x2A) cdb
1732 */
1733 else if (scp->cmd_len == 10) {
adam radfordf9eff812012-10-01 19:27:07 -07001734 datalength = (u32) scp->cmnd[8] |
adam radford9c915a82010-12-21 13:34:31 -08001735 ((u32) scp->cmnd[7] << 8);
1736 start_lba_lo = ((u32) scp->cmnd[2] << 24) |
1737 ((u32) scp->cmnd[3] << 16) |
1738 ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
1739 }
1740
1741 /*
1742 * 12-byte READ(0xA8) or WRITE(0xAA) cdb
1743 */
1744 else if (scp->cmd_len == 12) {
adam radfordf9eff812012-10-01 19:27:07 -07001745 datalength = ((u32) scp->cmnd[6] << 24) |
adam radford9c915a82010-12-21 13:34:31 -08001746 ((u32) scp->cmnd[7] << 16) |
1747 ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
1748 start_lba_lo = ((u32) scp->cmnd[2] << 24) |
1749 ((u32) scp->cmnd[3] << 16) |
1750 ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
1751 }
1752
1753 /*
1754 * 16-byte READ(0x88) or WRITE(0x8A) cdb
1755 */
1756 else if (scp->cmd_len == 16) {
adam radfordf9eff812012-10-01 19:27:07 -07001757 datalength = ((u32) scp->cmnd[10] << 24) |
adam radford9c915a82010-12-21 13:34:31 -08001758 ((u32) scp->cmnd[11] << 16) |
1759 ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13];
1760 start_lba_lo = ((u32) scp->cmnd[6] << 24) |
1761 ((u32) scp->cmnd[7] << 16) |
1762 ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
1763
1764 start_lba_hi = ((u32) scp->cmnd[2] << 24) |
1765 ((u32) scp->cmnd[3] << 16) |
1766 ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
1767 }
1768
1769 memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO));
1770 io_info.ldStartBlock = ((u64)start_lba_hi << 32) | start_lba_lo;
adam radfordf9eff812012-10-01 19:27:07 -07001771 io_info.numBlocks = datalength;
adam radford9c915a82010-12-21 13:34:31 -08001772 io_info.ldTgtId = device_id;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301773 io_request->DataLength = cpu_to_le32(scsi_bufflen(scp));
adam radford9c915a82010-12-21 13:34:31 -08001774
1775 if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
1776 io_info.isRead = 1;
1777
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301778 local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
adam radford9c915a82010-12-21 13:34:31 -08001779
1780 if ((MR_TargetIdToLdGet(device_id, local_map_ptr) >=
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301781 instance->fw_supported_vd_count) || (!fusion->fast_path_io)) {
adam radford9c915a82010-12-21 13:34:31 -08001782 io_request->RaidContext.regLockFlags = 0;
1783 fp_possible = 0;
1784 } else {
adam radford36807e62011-10-08 18:15:06 -07001785 if (MR_BuildRaidContext(instance, &io_info,
1786 &io_request->RaidContext,
adam radford21c9e162013-09-06 15:27:14 -07001787 local_map_ptr, &raidLUN))
adam radford9c915a82010-12-21 13:34:31 -08001788 fp_possible = io_info.fpOkForIo;
1789 }
1790
Christoph Hellwig16b85282015-04-15 09:44:37 -07001791 /* Use raw_smp_processor_id() for now until cmd->request->cpu is CPU
adam radfordc8e858f2011-10-08 18:15:13 -07001792 id by default, not CPU group id, otherwise all MSI-X queues won't
1793 be utilized */
1794 cmd->request_desc->SCSIIO.MSIxIndex = instance->msix_vectors ?
Christoph Hellwig16b85282015-04-15 09:44:37 -07001795 raw_smp_processor_id() % instance->msix_vectors : 0;
adam radfordc8e858f2011-10-08 18:15:13 -07001796
adam radford9c915a82010-12-21 13:34:31 -08001797 if (fp_possible) {
1798 megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp,
1799 local_map_ptr, start_lba_lo);
adam radford9c915a82010-12-21 13:34:31 -08001800 io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
1801 cmd->request_desc->SCSIIO.RequestFlags =
Sumit Saxena2c048352016-01-28 21:04:24 +05301802 (MPI2_REQ_DESCRIPT_FLAGS_FP_IO
adam radford9c915a82010-12-21 13:34:31 -08001803 << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
sumit.saxena@avagotech.com5a8cb852015-10-15 13:39:34 +05301804 if (fusion->adapter_type == INVADER_SERIES) {
adam radford36807e62011-10-08 18:15:06 -07001805 if (io_request->RaidContext.regLockFlags ==
1806 REGION_TYPE_UNUSED)
1807 cmd->request_desc->SCSIIO.RequestFlags =
1808 (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
1809 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
1810 io_request->RaidContext.Type = MPI2_TYPE_CUDA;
1811 io_request->RaidContext.nseg = 0x1;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301812 io_request->IoFlags |= cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH);
adam radford36807e62011-10-08 18:15:06 -07001813 io_request->RaidContext.regLockFlags |=
1814 (MR_RL_FLAGS_GRANT_DESTINATION_CUDA |
1815 MR_RL_FLAGS_SEQ_NUM_ENABLE);
1816 }
adam radford9c915a82010-12-21 13:34:31 -08001817 if ((fusion->load_balance_info[device_id].loadBalanceFlag) &&
1818 (io_info.isRead)) {
1819 io_info.devHandle =
Sumit.Saxena@avagotech.comd2552eb2014-09-12 18:57:53 +05301820 get_updated_dev_handle(instance,
adam radford9c915a82010-12-21 13:34:31 -08001821 &fusion->load_balance_info[device_id],
1822 &io_info);
1823 scp->SCp.Status |= MEGASAS_LOAD_BALANCE_FLAG;
Sumit.Saxena@avagotech.comd2552eb2014-09-12 18:57:53 +05301824 cmd->pd_r1_lb = io_info.pd_after_lb;
adam radford9c915a82010-12-21 13:34:31 -08001825 } else
1826 scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG;
Sumit.Saxena@avagotech.com5765c5b2015-04-23 16:32:09 +05301827
1828 if ((raidLUN[0] == 1) &&
sumit.saxena@avagotech.com75b96061e2015-08-31 17:24:01 +05301829 (local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].validHandles > 1)) {
Sumit.Saxena@avagotech.com5765c5b2015-04-23 16:32:09 +05301830 instance->dev_handle = !(instance->dev_handle);
1831 io_info.devHandle =
1832 local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].devHandle[instance->dev_handle];
1833 }
1834
adam radford9c915a82010-12-21 13:34:31 -08001835 cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle;
1836 io_request->DevHandle = io_info.devHandle;
adam radford21c9e162013-09-06 15:27:14 -07001837 /* populate the LUN field */
1838 memcpy(io_request->LUN, raidLUN, 8);
adam radford9c915a82010-12-21 13:34:31 -08001839 } else {
1840 io_request->RaidContext.timeoutValue =
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301841 cpu_to_le16(local_map_ptr->raidMap.fpPdIoTimeoutSec);
adam radford9c915a82010-12-21 13:34:31 -08001842 cmd->request_desc->SCSIIO.RequestFlags =
1843 (MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO
1844 << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
sumit.saxena@avagotech.com5a8cb852015-10-15 13:39:34 +05301845 if (fusion->adapter_type == INVADER_SERIES) {
Sumit Saxena8f050242016-01-28 21:04:27 +05301846 if (io_info.do_fp_rlbypass ||
1847 (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED))
adam radford36807e62011-10-08 18:15:06 -07001848 cmd->request_desc->SCSIIO.RequestFlags =
1849 (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
1850 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
1851 io_request->RaidContext.Type = MPI2_TYPE_CUDA;
1852 io_request->RaidContext.regLockFlags |=
1853 (MR_RL_FLAGS_GRANT_DESTINATION_CPU0 |
1854 MR_RL_FLAGS_SEQ_NUM_ENABLE);
1855 io_request->RaidContext.nseg = 0x1;
1856 }
1857 io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301858 io_request->DevHandle = cpu_to_le16(device_id);
adam radford9c915a82010-12-21 13:34:31 -08001859 } /* Not FP */
1860}
1861
1862/**
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301863 * megasas_build_ld_nonrw_fusion - prepares non rw ios for virtual disk
adam radford9c915a82010-12-21 13:34:31 -08001864 * @instance: Adapter soft state
1865 * @scp: SCSI command
1866 * @cmd: Command to be prepared
1867 *
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301868 * Prepares the io_request frame for non-rw io cmds for vd.
adam radford9c915a82010-12-21 13:34:31 -08001869 */
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301870static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance,
1871 struct scsi_cmnd *scmd, struct megasas_cmd_fusion *cmd)
adam radford9c915a82010-12-21 13:34:31 -08001872{
1873 u32 device_id;
1874 struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
1875 u16 pd_index = 0;
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301876 struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
adam radford9c915a82010-12-21 13:34:31 -08001877 struct fusion_context *fusion = instance->ctrl_context;
adam radford21c9e162013-09-06 15:27:14 -07001878 u8 span, physArm;
Christoph Hellwig9ab9ed382015-04-23 16:32:54 +05301879 __le16 devHandle;
adam radford21c9e162013-09-06 15:27:14 -07001880 u32 ld, arRef, pd;
1881 struct MR_LD_RAID *raid;
1882 struct RAID_CONTEXT *pRAID_Context;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301883 u8 fp_possible = 1;
adam radford9c915a82010-12-21 13:34:31 -08001884
1885 io_request = cmd->io_request;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301886 device_id = MEGASAS_DEV_INDEX(scmd);
1887 pd_index = MEGASAS_PD_INDEX(scmd);
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301888 local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301889 io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301890 /* get RAID_Context pointer */
1891 pRAID_Context = &io_request->RaidContext;
1892 /* Check with FW team */
1893 pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
1894 pRAID_Context->regLockRowLBA = 0;
1895 pRAID_Context->regLockLength = 0;
adam radford21c9e162013-09-06 15:27:14 -07001896
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301897 if (fusion->fast_path_io && (
1898 device_id < instance->fw_supported_vd_count)) {
Sumit.Saxena@avagotech.comab2f0602015-01-05 20:06:08 +05301899
adam radford21c9e162013-09-06 15:27:14 -07001900 ld = MR_TargetIdToLdGet(device_id, local_map_ptr);
Sumit.Saxena@avagotech.comab2f0602015-01-05 20:06:08 +05301901 if (ld >= instance->fw_supported_vd_count)
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301902 fp_possible = 0;
adam radford21c9e162013-09-06 15:27:14 -07001903
1904 raid = MR_LdRaidGet(ld, local_map_ptr);
adam radford21c9e162013-09-06 15:27:14 -07001905 if (!(raid->capability.fpNonRWCapable))
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301906 fp_possible = 0;
1907 } else
1908 fp_possible = 0;
adam radford21c9e162013-09-06 15:27:14 -07001909
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301910 if (!fp_possible) {
1911 io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
1912 io_request->DevHandle = cpu_to_le16(device_id);
1913 io_request->LUN[1] = scmd->device->lun;
1914 pRAID_Context->timeoutValue =
1915 cpu_to_le16 (scmd->request->timeout / HZ);
1916 cmd->request_desc->SCSIIO.RequestFlags =
1917 (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
1918 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
1919 } else {
adam radford21c9e162013-09-06 15:27:14 -07001920
1921 /* set RAID context values */
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301922 pRAID_Context->configSeqNum = raid->seqNum;
1923 pRAID_Context->regLockFlags = REGION_TYPE_SHARED_READ;
1924 pRAID_Context->timeoutValue = cpu_to_le16(raid->fpIoTimeoutForLd);
adam radford21c9e162013-09-06 15:27:14 -07001925
1926 /* get the DevHandle for the PD (since this is
1927 fpNonRWCapable, this is a single disk RAID0) */
1928 span = physArm = 0;
1929 arRef = MR_LdSpanArrayGet(ld, span, local_map_ptr);
1930 pd = MR_ArPdGet(arRef, physArm, local_map_ptr);
1931 devHandle = MR_PdDevHandleGet(pd, local_map_ptr);
1932
1933 /* build request descriptor */
1934 cmd->request_desc->SCSIIO.RequestFlags =
Sumit Saxena2c048352016-01-28 21:04:24 +05301935 (MPI2_REQ_DESCRIPT_FLAGS_FP_IO <<
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301936 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
adam radford21c9e162013-09-06 15:27:14 -07001937 cmd->request_desc->SCSIIO.DevHandle = devHandle;
1938
1939 /* populate the LUN field */
1940 memcpy(io_request->LUN, raid->LUN, 8);
1941
1942 /* build the raidScsiIO structure */
1943 io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
1944 io_request->DevHandle = devHandle;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301945 }
1946}
adam radford21c9e162013-09-06 15:27:14 -07001947
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301948/**
1949 * megasas_build_syspd_fusion - prepares rw/non-rw ios for syspd
1950 * @instance: Adapter soft state
1951 * @scp: SCSI command
1952 * @cmd: Command to be prepared
1953 * @fp_possible: parameter to detect fast path or firmware path io.
1954 *
1955 * Prepares the io_request frame for rw/non-rw io cmds for syspds
1956 */
1957static void
1958megasas_build_syspd_fusion(struct megasas_instance *instance,
1959 struct scsi_cmnd *scmd, struct megasas_cmd_fusion *cmd, u8 fp_possible)
1960{
1961 u32 device_id;
1962 struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
1963 u16 pd_index = 0;
1964 u16 os_timeout_value;
1965 u16 timeout_limit;
1966 struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
1967 struct RAID_CONTEXT *pRAID_Context;
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05301968 struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301969 struct fusion_context *fusion = instance->ctrl_context;
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05301970 pd_sync = (void *)fusion->pd_seq_sync[(instance->pd_seq_map_id - 1) & 1];
adam radford21c9e162013-09-06 15:27:14 -07001971
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301972 device_id = MEGASAS_DEV_INDEX(scmd);
1973 pd_index = MEGASAS_PD_INDEX(scmd);
1974 os_timeout_value = scmd->request->timeout / HZ;
1975
1976 io_request = cmd->io_request;
1977 /* get RAID_Context pointer */
1978 pRAID_Context = &io_request->RaidContext;
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05301979 pRAID_Context->regLockFlags = 0;
1980 pRAID_Context->regLockRowLBA = 0;
1981 pRAID_Context->regLockLength = 0;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05301982 io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
1983 io_request->LUN[1] = scmd->device->lun;
1984 pRAID_Context->RAIDFlags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD
1985 << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT;
1986
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05301987 /* If FW supports PD sequence number */
1988 if (instance->use_seqnum_jbod_fp &&
1989 instance->pd_list[pd_index].driveType == TYPE_DISK) {
1990 /* TgtId must be incremented by 255 as jbod seq number is index
1991 * below raid map
1992 */
1993 pRAID_Context->VirtualDiskTgtId =
1994 cpu_to_le16(device_id + (MAX_PHYSICAL_DEVICES - 1));
1995 pRAID_Context->configSeqNum = pd_sync->seq[pd_index].seqNum;
1996 io_request->DevHandle = pd_sync->seq[pd_index].devHandle;
1997 pRAID_Context->regLockFlags |=
1998 (MR_RL_FLAGS_SEQ_NUM_ENABLE|MR_RL_FLAGS_GRANT_DESTINATION_CUDA);
1999 } else if (fusion->fast_path_io) {
2000 pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
2001 pRAID_Context->configSeqNum = 0;
2002 local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
2003 io_request->DevHandle =
2004 local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
2005 } else {
2006 /* Want to send all IO via FW path */
2007 pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
2008 pRAID_Context->configSeqNum = 0;
Sumit Saxena9fb74c42015-11-05 21:17:38 +05302009 io_request->DevHandle = cpu_to_le16(0xFFFF);
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05302010 }
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302011
2012 cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle;
2013 cmd->request_desc->SCSIIO.MSIxIndex =
2014 instance->msix_vectors ?
2015 (raw_smp_processor_id() % instance->msix_vectors) : 0;
2016
2017
2018 if (!fp_possible) {
2019 /* system pd firmware path */
adam radford9c915a82010-12-21 13:34:31 -08002020 io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
adam radford9c915a82010-12-21 13:34:31 -08002021 cmd->request_desc->SCSIIO.RequestFlags =
2022 (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302023 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
2024 pRAID_Context->timeoutValue = cpu_to_le16(os_timeout_value);
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05302025 pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302026 } else {
2027 /* system pd Fast Path */
2028 io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302029 timeout_limit = (scmd->device->type == TYPE_DISK) ?
2030 255 : 0xFFFF;
2031 pRAID_Context->timeoutValue =
2032 cpu_to_le16((os_timeout_value > timeout_limit) ?
2033 timeout_limit : os_timeout_value);
sumit.saxena@avagotech.com5a8cb852015-10-15 13:39:34 +05302034 if (fusion->adapter_type == INVADER_SERIES) {
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302035 pRAID_Context->Type = MPI2_TYPE_CUDA;
2036 pRAID_Context->nseg = 0x1;
2037 io_request->IoFlags |=
2038 cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH);
2039 }
2040 cmd->request_desc->SCSIIO.RequestFlags =
Sumit Saxena2c048352016-01-28 21:04:24 +05302041 (MPI2_REQ_DESCRIPT_FLAGS_FP_IO <<
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302042 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
adam radford9c915a82010-12-21 13:34:31 -08002043 }
adam radford9c915a82010-12-21 13:34:31 -08002044}
2045
2046/**
2047 * megasas_build_io_fusion - Prepares IOs to devices
2048 * @instance: Adapter soft state
2049 * @scp: SCSI command
2050 * @cmd: Command to be prepared
2051 *
2052 * Invokes helper functions to prepare request frames
2053 * and sets flags appropriate for IO/Non-IO cmd
2054 */
2055int
2056megasas_build_io_fusion(struct megasas_instance *instance,
2057 struct scsi_cmnd *scp,
2058 struct megasas_cmd_fusion *cmd)
2059{
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05302060 u16 sge_count;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302061 u8 cmd_type;
adam radford9c915a82010-12-21 13:34:31 -08002062 struct MPI2_RAID_SCSI_IO_REQUEST *io_request = cmd->io_request;
2063
adam radford9c915a82010-12-21 13:34:31 -08002064 /* Zero out some fields so they don't get reused */
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002065 memset(io_request->LUN, 0x0, 8);
adam radford9c915a82010-12-21 13:34:31 -08002066 io_request->CDB.EEDP32.PrimaryReferenceTag = 0;
2067 io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0;
2068 io_request->EEDPFlags = 0;
2069 io_request->Control = 0;
2070 io_request->EEDPBlockSize = 0;
adam radford36807e62011-10-08 18:15:06 -07002071 io_request->ChainOffset = 0;
adam radford9c915a82010-12-21 13:34:31 -08002072 io_request->RaidContext.RAIDFlags = 0;
adam radford36807e62011-10-08 18:15:06 -07002073 io_request->RaidContext.Type = 0;
2074 io_request->RaidContext.nseg = 0;
adam radford9c915a82010-12-21 13:34:31 -08002075
2076 memcpy(io_request->CDB.CDB32, scp->cmnd, scp->cmd_len);
2077 /*
2078 * Just the CDB length,rest of the Flags are zero
2079 * This will be modified for FP in build_ldio_fusion
2080 */
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302081 io_request->IoFlags = cpu_to_le16(scp->cmd_len);
adam radford9c915a82010-12-21 13:34:31 -08002082
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302083 switch (cmd_type = megasas_cmd_type(scp)) {
2084 case READ_WRITE_LDIO:
adam radford9c915a82010-12-21 13:34:31 -08002085 megasas_build_ldio_fusion(instance, scp, cmd);
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302086 break;
2087 case NON_READ_WRITE_LDIO:
2088 megasas_build_ld_nonrw_fusion(instance, scp, cmd);
2089 break;
2090 case READ_WRITE_SYSPDIO:
2091 case NON_READ_WRITE_SYSPDIO:
2092 if (instance->secure_jbod_support &&
2093 (cmd_type == NON_READ_WRITE_SYSPDIO))
2094 megasas_build_syspd_fusion(instance, scp, cmd, 0);
2095 else
2096 megasas_build_syspd_fusion(instance, scp, cmd, 1);
2097 break;
2098 default:
2099 break;
2100 }
adam radford9c915a82010-12-21 13:34:31 -08002101
2102 /*
2103 * Construct SGL
2104 */
2105
2106 sge_count =
2107 megasas_make_sgl_fusion(instance, scp,
2108 (struct MPI25_IEEE_SGE_CHAIN64 *)
2109 &io_request->SGL, cmd);
2110
2111 if (sge_count > instance->max_num_sge) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05002112 dev_err(&instance->pdev->dev, "Error. sge_count (0x%x) exceeds "
adam radford9c915a82010-12-21 13:34:31 -08002113 "max (0x%x) allowed\n", sge_count,
2114 instance->max_num_sge);
2115 return 1;
2116 }
2117
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05302118 /* numSGE store lower 8 bit of sge_count.
2119 * numSGEExt store higher 8 bit of sge_count
2120 */
adam radford9c915a82010-12-21 13:34:31 -08002121 io_request->RaidContext.numSGE = sge_count;
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05302122 io_request->RaidContext.numSGEExt = (u8)(sge_count >> 8);
adam radford9c915a82010-12-21 13:34:31 -08002123
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302124 io_request->SGLFlags = cpu_to_le16(MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
adam radford9c915a82010-12-21 13:34:31 -08002125
2126 if (scp->sc_data_direction == PCI_DMA_TODEVICE)
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302127 io_request->Control |= cpu_to_le32(MPI2_SCSIIO_CONTROL_WRITE);
adam radford9c915a82010-12-21 13:34:31 -08002128 else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302129 io_request->Control |= cpu_to_le32(MPI2_SCSIIO_CONTROL_READ);
adam radford9c915a82010-12-21 13:34:31 -08002130
2131 io_request->SGLOffset0 =
2132 offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL) / 4;
2133
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302134 io_request->SenseBufferLowAddress = cpu_to_le32(cmd->sense_phys_addr);
adam radford9c915a82010-12-21 13:34:31 -08002135 io_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
2136
2137 cmd->scmd = scp;
2138 scp->SCp.ptr = (char *)cmd;
2139
2140 return 0;
2141}
2142
2143union MEGASAS_REQUEST_DESCRIPTOR_UNION *
2144megasas_get_request_descriptor(struct megasas_instance *instance, u16 index)
2145{
2146 u8 *p;
2147 struct fusion_context *fusion;
2148
2149 if (index >= instance->max_fw_cmds) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05002150 dev_err(&instance->pdev->dev, "Invalid SMID (0x%x)request for "
adam radford229fe472014-03-10 02:51:56 -07002151 "descriptor for scsi%d\n", index,
2152 instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002153 return NULL;
2154 }
2155 fusion = instance->ctrl_context;
2156 p = fusion->req_frames_desc
2157 +sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *index;
2158
2159 return (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)p;
2160}
2161
2162/**
2163 * megasas_build_and_issue_cmd_fusion -Main routine for building and
2164 * issuing non IOCTL cmd
2165 * @instance: Adapter soft state
2166 * @scmd: pointer to scsi cmd from OS
2167 */
2168static u32
2169megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
2170 struct scsi_cmnd *scmd)
2171{
2172 struct megasas_cmd_fusion *cmd;
2173 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
2174 u32 index;
2175 struct fusion_context *fusion;
2176
2177 fusion = instance->ctrl_context;
2178
Sumit Saxena308ec452016-01-28 21:04:30 +05302179 if ((megasas_cmd_type(scmd) == READ_WRITE_LDIO) &&
2180 instance->ldio_threshold &&
2181 (atomic_inc_return(&instance->ldio_outstanding) >
2182 instance->ldio_threshold)) {
2183 atomic_dec(&instance->ldio_outstanding);
2184 return SCSI_MLQUEUE_DEVICE_BUSY;
2185 }
2186
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302187 cmd = megasas_get_cmd_fusion(instance, scmd->request->tag);
adam radford9c915a82010-12-21 13:34:31 -08002188
2189 index = cmd->index;
2190
2191 req_desc = megasas_get_request_descriptor(instance, index-1);
2192 if (!req_desc)
Sumit Saxenaf9a9dee2016-01-28 21:04:29 +05302193 return SCSI_MLQUEUE_HOST_BUSY;
adam radford9c915a82010-12-21 13:34:31 -08002194
2195 req_desc->Words = 0;
2196 cmd->request_desc = req_desc;
adam radford9c915a82010-12-21 13:34:31 -08002197
2198 if (megasas_build_io_fusion(instance, scmd, cmd)) {
2199 megasas_return_cmd_fusion(instance, cmd);
Bjorn Helgaas1be18252015-07-07 15:52:34 -05002200 dev_err(&instance->pdev->dev, "Error building command\n");
adam radford9c915a82010-12-21 13:34:31 -08002201 cmd->request_desc = NULL;
Sumit Saxenaf9a9dee2016-01-28 21:04:29 +05302202 return SCSI_MLQUEUE_HOST_BUSY;
adam radford9c915a82010-12-21 13:34:31 -08002203 }
2204
2205 req_desc = cmd->request_desc;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302206 req_desc->SCSIIO.SMID = cpu_to_le16(index);
adam radford9c915a82010-12-21 13:34:31 -08002207
2208 if (cmd->io_request->ChainOffset != 0 &&
2209 cmd->io_request->ChainOffset != 0xF)
Bjorn Helgaas1be18252015-07-07 15:52:34 -05002210 dev_err(&instance->pdev->dev, "The chain offset value is not "
adam radford9c915a82010-12-21 13:34:31 -08002211 "correct : %x\n", cmd->io_request->ChainOffset);
2212
2213 /*
2214 * Issue the command to the FW
2215 */
2216 atomic_inc(&instance->fw_outstanding);
2217
Christoph Hellwig01d7f032015-04-23 16:34:09 +05302218 megasas_fire_cmd_fusion(instance, req_desc);
adam radford9c915a82010-12-21 13:34:31 -08002219
2220 return 0;
2221}
2222
2223/**
2224 * complete_cmd_fusion - Completes command
2225 * @instance: Adapter soft state
2226 * Completes all commands that is in reply descriptor queue
2227 */
2228int
adam radfordc8e858f2011-10-08 18:15:13 -07002229complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
adam radford9c915a82010-12-21 13:34:31 -08002230{
2231 union MPI2_REPLY_DESCRIPTORS_UNION *desc;
2232 struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
2233 struct MPI2_RAID_SCSI_IO_REQUEST *scsi_io_req;
2234 struct fusion_context *fusion;
2235 struct megasas_cmd *cmd_mfi;
2236 struct megasas_cmd_fusion *cmd_fusion;
2237 u16 smid, num_completed;
Sumit.Saxena@avagotech.comd2552eb2014-09-12 18:57:53 +05302238 u8 reply_descript_type;
adam radford9c915a82010-12-21 13:34:31 -08002239 u32 status, extStatus, device_id;
2240 union desc_value d_val;
2241 struct LD_LOAD_BALANCE_INFO *lbinfo;
Sumit.Saxena@avagotech.comdb4fc862014-09-12 18:57:23 +05302242 int threshold_reply_count = 0;
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302243 struct scsi_cmnd *scmd_local = NULL;
Sumit Saxena18365b12016-01-28 21:04:25 +05302244 struct MR_TASK_MANAGE_REQUEST *mr_tm_req;
2245 struct MPI2_SCSI_TASK_MANAGE_REQUEST *mpi_tm_req;
adam radford9c915a82010-12-21 13:34:31 -08002246
2247 fusion = instance->ctrl_context;
2248
Sumit Saxena8a01a412016-01-28 21:04:32 +05302249 if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR)
adam radford9c915a82010-12-21 13:34:31 -08002250 return IRQ_HANDLED;
2251
Sumit Saxena179ac142016-01-28 21:04:28 +05302252 desc = fusion->reply_frames_desc[MSIxIndex] +
2253 fusion->last_reply_idx[MSIxIndex];
adam radford9c915a82010-12-21 13:34:31 -08002254
2255 reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
2256
2257 d_val.word = desc->Words;
2258
2259 reply_descript_type = reply_desc->ReplyFlags &
2260 MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
2261
2262 if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
2263 return IRQ_NONE;
2264
adam radford9c915a82010-12-21 13:34:31 -08002265 num_completed = 0;
2266
Christoph Hellwigc6f5bf82015-04-23 16:33:09 +05302267 while (d_val.u.low != cpu_to_le32(UINT_MAX) &&
2268 d_val.u.high != cpu_to_le32(UINT_MAX)) {
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302269 smid = le16_to_cpu(reply_desc->SMID);
adam radford9c915a82010-12-21 13:34:31 -08002270
2271 cmd_fusion = fusion->cmd_list[smid - 1];
2272
2273 scsi_io_req =
2274 (struct MPI2_RAID_SCSI_IO_REQUEST *)
2275 cmd_fusion->io_request;
2276
2277 if (cmd_fusion->scmd)
2278 cmd_fusion->scmd->SCp.ptr = NULL;
2279
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302280 scmd_local = cmd_fusion->scmd;
adam radford9c915a82010-12-21 13:34:31 -08002281 status = scsi_io_req->RaidContext.status;
2282 extStatus = scsi_io_req->RaidContext.exStatus;
2283
2284 switch (scsi_io_req->Function) {
Sumit Saxena18365b12016-01-28 21:04:25 +05302285 case MPI2_FUNCTION_SCSI_TASK_MGMT:
2286 mr_tm_req = (struct MR_TASK_MANAGE_REQUEST *)
2287 cmd_fusion->io_request;
2288 mpi_tm_req = (struct MPI2_SCSI_TASK_MANAGE_REQUEST *)
2289 &mr_tm_req->TmRequest;
2290 dev_dbg(&instance->pdev->dev, "TM completion:"
2291 "type: 0x%x TaskMID: 0x%x\n",
2292 mpi_tm_req->TaskType, mpi_tm_req->TaskMID);
2293 complete(&cmd_fusion->done);
2294 break;
adam radford9c915a82010-12-21 13:34:31 -08002295 case MPI2_FUNCTION_SCSI_IO_REQUEST: /*Fast Path IO.*/
2296 /* Update load balancing info */
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302297 device_id = MEGASAS_DEV_INDEX(scmd_local);
adam radford9c915a82010-12-21 13:34:31 -08002298 lbinfo = &fusion->load_balance_info[device_id];
2299 if (cmd_fusion->scmd->SCp.Status &
2300 MEGASAS_LOAD_BALANCE_FLAG) {
Sumit.Saxena@avagotech.comd2552eb2014-09-12 18:57:53 +05302301 atomic_dec(&lbinfo->scsi_pending_cmds[cmd_fusion->pd_r1_lb]);
adam radford9c915a82010-12-21 13:34:31 -08002302 cmd_fusion->scmd->SCp.Status &=
2303 ~MEGASAS_LOAD_BALANCE_FLAG;
2304 }
2305 if (reply_descript_type ==
2306 MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
2307 if (megasas_dbg_lvl == 5)
Bjorn Helgaas1be18252015-07-07 15:52:34 -05002308 dev_err(&instance->pdev->dev, "\nFAST Path "
adam radford9c915a82010-12-21 13:34:31 -08002309 "IO Success\n");
2310 }
2311 /* Fall thru and complete IO */
2312 case MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST: /* LD-IO Path */
2313 /* Map the FW Cmd Status */
2314 map_cmd_status(cmd_fusion, status, extStatus);
adam radford9c915a82010-12-21 13:34:31 -08002315 scsi_io_req->RaidContext.status = 0;
2316 scsi_io_req->RaidContext.exStatus = 0;
Sumit Saxena308ec452016-01-28 21:04:30 +05302317 if (megasas_cmd_type(scmd_local) == READ_WRITE_LDIO)
2318 atomic_dec(&instance->ldio_outstanding);
adam radford9c915a82010-12-21 13:34:31 -08002319 megasas_return_cmd_fusion(instance, cmd_fusion);
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302320 scsi_dma_unmap(scmd_local);
2321 scmd_local->scsi_done(scmd_local);
adam radford9c915a82010-12-21 13:34:31 -08002322 atomic_dec(&instance->fw_outstanding);
2323
2324 break;
2325 case MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST: /*MFI command */
2326 cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +05302327
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302328 /* Poll mode. Dummy free.
2329 * In case of Interrupt mode, caller has reverse check.
2330 */
2331 if (cmd_mfi->flags & DRV_DCMD_POLLED_MODE) {
2332 cmd_mfi->flags &= ~DRV_DCMD_POLLED_MODE;
2333 megasas_return_cmd(instance, cmd_mfi);
2334 } else
2335 megasas_complete_cmd(instance, cmd_mfi, DID_OK);
adam radford9c915a82010-12-21 13:34:31 -08002336 break;
2337 }
2338
adam radfordc8e858f2011-10-08 18:15:13 -07002339 fusion->last_reply_idx[MSIxIndex]++;
2340 if (fusion->last_reply_idx[MSIxIndex] >=
2341 fusion->reply_q_depth)
2342 fusion->last_reply_idx[MSIxIndex] = 0;
adam radford9c915a82010-12-21 13:34:31 -08002343
Christoph Hellwigc6f5bf82015-04-23 16:33:09 +05302344 desc->Words = cpu_to_le64(ULLONG_MAX);
adam radford9c915a82010-12-21 13:34:31 -08002345 num_completed++;
Sumit.Saxena@avagotech.comdb4fc862014-09-12 18:57:23 +05302346 threshold_reply_count++;
adam radford9c915a82010-12-21 13:34:31 -08002347
2348 /* Get the next reply descriptor */
adam radfordc8e858f2011-10-08 18:15:13 -07002349 if (!fusion->last_reply_idx[MSIxIndex])
Sumit Saxena179ac142016-01-28 21:04:28 +05302350 desc = fusion->reply_frames_desc[MSIxIndex];
adam radford9c915a82010-12-21 13:34:31 -08002351 else
2352 desc++;
2353
2354 reply_desc =
2355 (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
2356
2357 d_val.word = desc->Words;
2358
2359 reply_descript_type = reply_desc->ReplyFlags &
2360 MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
2361
2362 if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
2363 break;
Sumit.Saxena@avagotech.comdb4fc862014-09-12 18:57:23 +05302364 /*
2365 * Write to reply post host index register after completing threshold
2366 * number of reply counts and still there are more replies in reply queue
2367 * pending to be completed
2368 */
2369 if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) {
sumit.saxena@avagotech.com5a8cb852015-10-15 13:39:34 +05302370 if (fusion->adapter_type == INVADER_SERIES)
Sumit.Saxena@avagotech.comdb4fc862014-09-12 18:57:23 +05302371 writel(((MSIxIndex & 0x7) << 24) |
2372 fusion->last_reply_idx[MSIxIndex],
2373 instance->reply_post_host_index_addr[MSIxIndex/8]);
2374 else
2375 writel((MSIxIndex << 24) |
2376 fusion->last_reply_idx[MSIxIndex],
2377 instance->reply_post_host_index_addr[0]);
2378 threshold_reply_count = 0;
2379 }
adam radford9c915a82010-12-21 13:34:31 -08002380 }
2381
2382 if (!num_completed)
2383 return IRQ_NONE;
2384
2385 wmb();
sumit.saxena@avagotech.com5a8cb852015-10-15 13:39:34 +05302386 if (fusion->adapter_type == INVADER_SERIES)
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +05302387 writel(((MSIxIndex & 0x7) << 24) |
2388 fusion->last_reply_idx[MSIxIndex],
2389 instance->reply_post_host_index_addr[MSIxIndex/8]);
2390 else
2391 writel((MSIxIndex << 24) |
2392 fusion->last_reply_idx[MSIxIndex],
2393 instance->reply_post_host_index_addr[0]);
adam radford53ef2bb2011-02-24 20:56:05 -08002394 megasas_check_and_restore_queue_depth(instance);
adam radford9c915a82010-12-21 13:34:31 -08002395 return IRQ_HANDLED;
2396}
2397
2398/**
2399 * megasas_complete_cmd_dpc_fusion - Completes command
2400 * @instance: Adapter soft state
2401 *
2402 * Tasklet to complete cmds
2403 */
2404void
2405megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
2406{
2407 struct megasas_instance *instance =
2408 (struct megasas_instance *)instance_addr;
2409 unsigned long flags;
adam radfordc8e858f2011-10-08 18:15:13 -07002410 u32 count, MSIxIndex;
2411
2412 count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
adam radford9c915a82010-12-21 13:34:31 -08002413
2414 /* If we have already declared adapter dead, donot complete cmds */
2415 spin_lock_irqsave(&instance->hba_lock, flags);
Sumit Saxena8a01a412016-01-28 21:04:32 +05302416 if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) {
adam radford9c915a82010-12-21 13:34:31 -08002417 spin_unlock_irqrestore(&instance->hba_lock, flags);
2418 return;
2419 }
2420 spin_unlock_irqrestore(&instance->hba_lock, flags);
2421
adam radfordc8e858f2011-10-08 18:15:13 -07002422 for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++)
2423 complete_cmd_fusion(instance, MSIxIndex);
adam radford9c915a82010-12-21 13:34:31 -08002424}
2425
2426/**
2427 * megasas_isr_fusion - isr entry point
2428 */
2429irqreturn_t megasas_isr_fusion(int irq, void *devp)
2430{
adam radfordc8e858f2011-10-08 18:15:13 -07002431 struct megasas_irq_context *irq_context = devp;
2432 struct megasas_instance *instance = irq_context->instance;
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05302433 u32 mfiStatus, fw_state, dma_state;
adam radford9c915a82010-12-21 13:34:31 -08002434
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +05302435 if (instance->mask_interrupts)
2436 return IRQ_NONE;
2437
adam radfordc8e858f2011-10-08 18:15:13 -07002438 if (!instance->msix_vectors) {
adam radford9c915a82010-12-21 13:34:31 -08002439 mfiStatus = instance->instancet->clear_intr(instance->reg_set);
2440 if (!mfiStatus)
2441 return IRQ_NONE;
2442 }
2443
2444 /* If we are resetting, bail */
adam radford6497b242011-10-08 18:14:50 -07002445 if (test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags)) {
2446 instance->instancet->clear_intr(instance->reg_set);
adam radford9c915a82010-12-21 13:34:31 -08002447 return IRQ_HANDLED;
adam radford6497b242011-10-08 18:14:50 -07002448 }
adam radford9c915a82010-12-21 13:34:31 -08002449
adam radfordc8e858f2011-10-08 18:15:13 -07002450 if (!complete_cmd_fusion(instance, irq_context->MSIxIndex)) {
adam radford6497b242011-10-08 18:14:50 -07002451 instance->instancet->clear_intr(instance->reg_set);
adam radford9c915a82010-12-21 13:34:31 -08002452 /* If we didn't complete any commands, check for FW fault */
2453 fw_state = instance->instancet->read_fw_status_reg(
2454 instance->reg_set) & MFI_STATE_MASK;
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05302455 dma_state = instance->instancet->read_fw_status_reg
2456 (instance->reg_set) & MFI_STATE_DMADONE;
2457 if (instance->crash_dump_drv_support &&
2458 instance->crash_dump_app_support) {
2459 /* Start collecting crash, if DMA bit is done */
2460 if ((fw_state == MFI_STATE_FAULT) && dma_state)
2461 schedule_work(&instance->crash_init);
2462 else if (fw_state == MFI_STATE_FAULT)
2463 schedule_work(&instance->work_init);
2464 } else if (fw_state == MFI_STATE_FAULT) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05002465 dev_warn(&instance->pdev->dev, "Iop2SysDoorbellInt"
adam radford229fe472014-03-10 02:51:56 -07002466 "for scsi%d\n", instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002467 schedule_work(&instance->work_init);
adam radford229fe472014-03-10 02:51:56 -07002468 }
adam radford9c915a82010-12-21 13:34:31 -08002469 }
2470
2471 return IRQ_HANDLED;
2472}
2473
2474/**
2475 * build_mpt_mfi_pass_thru - builds a cmd fo MFI Pass thru
2476 * @instance: Adapter soft state
2477 * mfi_cmd: megasas_cmd pointer
2478 *
2479 */
2480u8
2481build_mpt_mfi_pass_thru(struct megasas_instance *instance,
2482 struct megasas_cmd *mfi_cmd)
2483{
2484 struct MPI25_IEEE_SGE_CHAIN64 *mpi25_ieee_chain;
2485 struct MPI2_RAID_SCSI_IO_REQUEST *io_req;
2486 struct megasas_cmd_fusion *cmd;
2487 struct fusion_context *fusion;
2488 struct megasas_header *frame_hdr = &mfi_cmd->frame->hdr;
2489
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302490 fusion = instance->ctrl_context;
2491
2492 cmd = megasas_get_cmd_fusion(instance,
2493 instance->max_scsi_cmds + mfi_cmd->index);
adam radford9c915a82010-12-21 13:34:31 -08002494
2495 /* Save the smid. To be used for returning the cmd */
2496 mfi_cmd->context.smid = cmd->index;
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +05302497
adam radford9c915a82010-12-21 13:34:31 -08002498 /*
2499 * For cmds where the flag is set, store the flag and check
2500 * on completion. For cmds with this flag, don't call
2501 * megasas_complete_cmd
2502 */
2503
Sumit.Saxena@avagotech.com6e755dd2014-11-17 15:24:28 +05302504 if (frame_hdr->flags & cpu_to_le16(MFI_FRAME_DONT_POST_IN_REPLY_QUEUE))
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05302505 mfi_cmd->flags |= DRV_DCMD_POLLED_MODE;
adam radford9c915a82010-12-21 13:34:31 -08002506
adam radford9c915a82010-12-21 13:34:31 -08002507 io_req = cmd->io_request;
adam radford36807e62011-10-08 18:15:06 -07002508
sumit.saxena@avagotech.com5a8cb852015-10-15 13:39:34 +05302509 if (fusion->adapter_type == INVADER_SERIES) {
adam radford36807e62011-10-08 18:15:06 -07002510 struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end =
2511 (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL;
2512 sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
2513 sgl_ptr_end->Flags = 0;
2514 }
2515
adam radford9c915a82010-12-21 13:34:31 -08002516 mpi25_ieee_chain =
2517 (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain;
2518
2519 io_req->Function = MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST;
2520 io_req->SGLOffset0 = offsetof(struct MPI2_RAID_SCSI_IO_REQUEST,
2521 SGL) / 4;
2522 io_req->ChainOffset = fusion->chain_offset_mfi_pthru;
2523
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302524 mpi25_ieee_chain->Address = cpu_to_le64(mfi_cmd->frame_phys_addr);
adam radford9c915a82010-12-21 13:34:31 -08002525
2526 mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT |
2527 MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
2528
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05302529 mpi25_ieee_chain->Length = cpu_to_le32(instance->max_chain_frame_sz);
adam radford9c915a82010-12-21 13:34:31 -08002530
2531 return 0;
2532}
2533
2534/**
2535 * build_mpt_cmd - Calls helper function to build a cmd MFI Pass thru cmd
2536 * @instance: Adapter soft state
2537 * @cmd: mfi cmd to build
2538 *
2539 */
2540union MEGASAS_REQUEST_DESCRIPTOR_UNION *
2541build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
2542{
2543 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
2544 u16 index;
2545
2546 if (build_mpt_mfi_pass_thru(instance, cmd)) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05002547 dev_err(&instance->pdev->dev, "Couldn't build MFI pass thru cmd\n");
adam radford9c915a82010-12-21 13:34:31 -08002548 return NULL;
2549 }
2550
2551 index = cmd->context.smid;
2552
2553 req_desc = megasas_get_request_descriptor(instance, index - 1);
2554
2555 if (!req_desc)
2556 return NULL;
2557
2558 req_desc->Words = 0;
2559 req_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
2560 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
2561
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302562 req_desc->SCSIIO.SMID = cpu_to_le16(index);
adam radford9c915a82010-12-21 13:34:31 -08002563
2564 return req_desc;
2565}
2566
2567/**
2568 * megasas_issue_dcmd_fusion - Issues a MFI Pass thru cmd
2569 * @instance: Adapter soft state
2570 * @cmd: mfi cmd pointer
2571 *
2572 */
Sumit Saxena6d40afb2016-01-28 21:04:23 +05302573int
adam radford9c915a82010-12-21 13:34:31 -08002574megasas_issue_dcmd_fusion(struct megasas_instance *instance,
2575 struct megasas_cmd *cmd)
2576{
2577 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
adam radford9c915a82010-12-21 13:34:31 -08002578
2579 req_desc = build_mpt_cmd(instance, cmd);
2580 if (!req_desc) {
Sumit Saxena6d40afb2016-01-28 21:04:23 +05302581 dev_info(&instance->pdev->dev, "Failed from %s %d\n",
2582 __func__, __LINE__);
2583 return DCMD_NOT_FIRED;
adam radford9c915a82010-12-21 13:34:31 -08002584 }
Sumit Saxena6d40afb2016-01-28 21:04:23 +05302585
Christoph Hellwig01d7f032015-04-23 16:34:09 +05302586 megasas_fire_cmd_fusion(instance, req_desc);
Sumit Saxena6d40afb2016-01-28 21:04:23 +05302587 return DCMD_SUCCESS;
adam radford9c915a82010-12-21 13:34:31 -08002588}
2589
2590/**
2591 * megasas_release_fusion - Reverses the FW initialization
Geert Uytterhoeven4b63b282015-03-03 11:58:07 +01002592 * @instance: Adapter soft state
adam radford9c915a82010-12-21 13:34:31 -08002593 */
2594void
2595megasas_release_fusion(struct megasas_instance *instance)
2596{
2597 megasas_free_cmds(instance);
2598 megasas_free_cmds_fusion(instance);
2599
2600 iounmap(instance->reg_set);
2601
2602 pci_release_selected_regions(instance->pdev, instance->bar);
2603}
2604
2605/**
2606 * megasas_read_fw_status_reg_fusion - returns the current FW status value
2607 * @regs: MFI register set
2608 */
2609static u32
2610megasas_read_fw_status_reg_fusion(struct megasas_register_set __iomem *regs)
2611{
2612 return readl(&(regs)->outbound_scratch_pad);
2613}
2614
2615/**
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05302616 * megasas_alloc_host_crash_buffer - Host buffers for Crash dump collection from Firmware
2617 * @instance: Controller's soft instance
2618 * return: Number of allocated host crash buffers
2619 */
2620static void
2621megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
2622{
2623 unsigned int i;
2624
2625 instance->crash_buf_pages = get_order(CRASH_DMA_BUF_SIZE);
2626 for (i = 0; i < MAX_CRASH_DUMP_SIZE; i++) {
2627 instance->crash_buf[i] = (void *)__get_free_pages(GFP_KERNEL,
2628 instance->crash_buf_pages);
2629 if (!instance->crash_buf[i]) {
2630 dev_info(&instance->pdev->dev, "Firmware crash dump "
2631 "memory allocation failed at index %d\n", i);
2632 break;
2633 }
Sumit.Saxena@avagotech.comd009b572014-11-17 15:24:13 +05302634 memset(instance->crash_buf[i], 0,
2635 ((1 << PAGE_SHIFT) << instance->crash_buf_pages));
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05302636 }
2637 instance->drv_buf_alloc = i;
2638}
2639
2640/**
2641 * megasas_free_host_crash_buffer - Host buffers for Crash dump collection from Firmware
2642 * @instance: Controller's soft instance
2643 */
2644void
2645megasas_free_host_crash_buffer(struct megasas_instance *instance)
2646{
2647 unsigned int i
2648;
2649 for (i = 0; i < instance->drv_buf_alloc; i++) {
2650 if (instance->crash_buf[i])
2651 free_pages((ulong)instance->crash_buf[i],
2652 instance->crash_buf_pages);
2653 }
2654 instance->drv_buf_index = 0;
2655 instance->drv_buf_alloc = 0;
2656 instance->fw_crash_state = UNAVAILABLE;
2657 instance->fw_crash_buffer_size = 0;
2658}
2659
2660/**
adam radford9c915a82010-12-21 13:34:31 -08002661 * megasas_adp_reset_fusion - For controller reset
2662 * @regs: MFI register set
2663 */
2664static int
2665megasas_adp_reset_fusion(struct megasas_instance *instance,
2666 struct megasas_register_set __iomem *regs)
2667{
sumit.saxena@avagotech.com79b82c22015-08-31 17:23:41 +05302668 u32 host_diag, abs_state, retry;
2669
2670 /* Now try to reset the chip */
2671 writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
2672 writel(MPI2_WRSEQ_1ST_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
2673 writel(MPI2_WRSEQ_2ND_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
2674 writel(MPI2_WRSEQ_3RD_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
2675 writel(MPI2_WRSEQ_4TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
2676 writel(MPI2_WRSEQ_5TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
2677 writel(MPI2_WRSEQ_6TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
2678
2679 /* Check that the diag write enable (DRWE) bit is on */
2680 host_diag = readl(&instance->reg_set->fusion_host_diag);
2681 retry = 0;
2682 while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) {
2683 msleep(100);
2684 host_diag = readl(&instance->reg_set->fusion_host_diag);
2685 if (retry++ == 100) {
2686 dev_warn(&instance->pdev->dev,
2687 "Host diag unlock failed from %s %d\n",
2688 __func__, __LINE__);
2689 break;
2690 }
2691 }
2692 if (!(host_diag & HOST_DIAG_WRITE_ENABLE))
2693 return -1;
2694
2695 /* Send chip reset command */
2696 writel(host_diag | HOST_DIAG_RESET_ADAPTER,
2697 &instance->reg_set->fusion_host_diag);
2698 msleep(3000);
2699
2700 /* Make sure reset adapter bit is cleared */
2701 host_diag = readl(&instance->reg_set->fusion_host_diag);
2702 retry = 0;
2703 while (host_diag & HOST_DIAG_RESET_ADAPTER) {
2704 msleep(100);
2705 host_diag = readl(&instance->reg_set->fusion_host_diag);
2706 if (retry++ == 1000) {
2707 dev_warn(&instance->pdev->dev,
2708 "Diag reset adapter never cleared %s %d\n",
2709 __func__, __LINE__);
2710 break;
2711 }
2712 }
2713 if (host_diag & HOST_DIAG_RESET_ADAPTER)
2714 return -1;
2715
2716 abs_state = instance->instancet->read_fw_status_reg(instance->reg_set)
2717 & MFI_STATE_MASK;
2718 retry = 0;
2719
2720 while ((abs_state <= MFI_STATE_FW_INIT) && (retry++ < 1000)) {
2721 msleep(100);
2722 abs_state = instance->instancet->
2723 read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
2724 }
2725 if (abs_state <= MFI_STATE_FW_INIT) {
2726 dev_warn(&instance->pdev->dev,
2727 "fw state < MFI_STATE_FW_INIT, state = 0x%x %s %d\n",
2728 abs_state, __func__, __LINE__);
2729 return -1;
2730 }
2731
adam radford9c915a82010-12-21 13:34:31 -08002732 return 0;
2733}
2734
2735/**
2736 * megasas_check_reset_fusion - For controller reset check
2737 * @regs: MFI register set
2738 */
2739static int
2740megasas_check_reset_fusion(struct megasas_instance *instance,
2741 struct megasas_register_set __iomem *regs)
2742{
2743 return 0;
2744}
2745
2746/* This function waits for outstanding commands on fusion to complete */
adam radford229fe472014-03-10 02:51:56 -07002747int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance,
Sumit Saxena6d40afb2016-01-28 21:04:23 +05302748 int reason, int *convert)
adam radford9c915a82010-12-21 13:34:31 -08002749{
adam radford229fe472014-03-10 02:51:56 -07002750 int i, outstanding, retval = 0, hb_seconds_missed = 0;
adam radfordc007b8b2012-07-17 18:20:24 -07002751 u32 fw_state;
adam radford9c915a82010-12-21 13:34:31 -08002752
adam radfordc007b8b2012-07-17 18:20:24 -07002753 for (i = 0; i < resetwaittime; i++) {
adam radford9c915a82010-12-21 13:34:31 -08002754 /* Check if firmware is in fault state */
2755 fw_state = instance->instancet->read_fw_status_reg(
2756 instance->reg_set) & MFI_STATE_MASK;
2757 if (fw_state == MFI_STATE_FAULT) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05002758 dev_warn(&instance->pdev->dev, "Found FW in FAULT state,"
adam radford229fe472014-03-10 02:51:56 -07002759 " will reset adapter scsi%d.\n",
2760 instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002761 retval = 1;
2762 goto out;
2763 }
Sumit Saxena6d40afb2016-01-28 21:04:23 +05302764
2765 if (reason == MFI_IO_TIMEOUT_OCR) {
2766 dev_info(&instance->pdev->dev,
2767 "MFI IO is timed out, initiating OCR\n");
2768 retval = 1;
2769 goto out;
2770 }
2771
adam radford229fe472014-03-10 02:51:56 -07002772 /* If SR-IOV VF mode & heartbeat timeout, don't wait */
Sumit Saxena6d40afb2016-01-28 21:04:23 +05302773 if (instance->requestorId && !reason) {
adam radford229fe472014-03-10 02:51:56 -07002774 retval = 1;
2775 goto out;
2776 }
2777
2778 /* If SR-IOV VF mode & I/O timeout, check for HB timeout */
Sumit Saxena6d40afb2016-01-28 21:04:23 +05302779 if (instance->requestorId && reason) {
adam radford229fe472014-03-10 02:51:56 -07002780 if (instance->hb_host_mem->HB.fwCounter !=
2781 instance->hb_host_mem->HB.driverCounter) {
2782 instance->hb_host_mem->HB.driverCounter =
2783 instance->hb_host_mem->HB.fwCounter;
2784 hb_seconds_missed = 0;
2785 } else {
2786 hb_seconds_missed++;
2787 if (hb_seconds_missed ==
2788 (MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF/HZ)) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05002789 dev_warn(&instance->pdev->dev, "SR-IOV:"
adam radford229fe472014-03-10 02:51:56 -07002790 " Heartbeat never completed "
2791 " while polling during I/O "
2792 " timeout handling for "
2793 "scsi%d.\n",
2794 instance->host->host_no);
2795 *convert = 1;
2796 retval = 1;
2797 goto out;
2798 }
2799 }
2800 }
adam radford9c915a82010-12-21 13:34:31 -08002801
2802 outstanding = atomic_read(&instance->fw_outstanding);
2803 if (!outstanding)
2804 goto out;
2805
2806 if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05002807 dev_notice(&instance->pdev->dev, "[%2d]waiting for %d "
adam radford229fe472014-03-10 02:51:56 -07002808 "commands to complete for scsi%d\n", i,
2809 outstanding, instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002810 megasas_complete_cmd_dpc_fusion(
2811 (unsigned long)instance);
2812 }
2813 msleep(1000);
2814 }
2815
2816 if (atomic_read(&instance->fw_outstanding)) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05002817 dev_err(&instance->pdev->dev, "pending commands remain after waiting, "
adam radford229fe472014-03-10 02:51:56 -07002818 "will reset adapter scsi%d.\n",
2819 instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08002820 retval = 1;
2821 }
2822out:
2823 return retval;
2824}
2825
2826void megasas_reset_reply_desc(struct megasas_instance *instance)
2827{
Sumit Saxena179ac142016-01-28 21:04:28 +05302828 int i, j, count;
adam radford9c915a82010-12-21 13:34:31 -08002829 struct fusion_context *fusion;
2830 union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
2831
2832 fusion = instance->ctrl_context;
adam radfordc8e858f2011-10-08 18:15:13 -07002833 count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
Sumit Saxena179ac142016-01-28 21:04:28 +05302834 for (i = 0 ; i < count ; i++) {
adam radfordc8e858f2011-10-08 18:15:13 -07002835 fusion->last_reply_idx[i] = 0;
Sumit Saxena179ac142016-01-28 21:04:28 +05302836 reply_desc = fusion->reply_frames_desc[i];
2837 for (j = 0 ; j < fusion->reply_q_depth; j++, reply_desc++)
2838 reply_desc->Words = cpu_to_le64(ULLONG_MAX);
2839 }
adam radford9c915a82010-12-21 13:34:31 -08002840}
2841
Sumit.Saxena@avagotech.com9b828182015-04-23 16:30:24 +05302842/*
2843 * megasas_refire_mgmt_cmd : Re-fire management commands
2844 * @instance: Controller's soft instance
2845*/
2846void megasas_refire_mgmt_cmd(struct megasas_instance *instance)
2847{
2848 int j;
2849 struct megasas_cmd_fusion *cmd_fusion;
2850 struct fusion_context *fusion;
2851 struct megasas_cmd *cmd_mfi;
2852 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
2853 u16 smid;
Sumit Saxena6d40afb2016-01-28 21:04:23 +05302854 bool refire_cmd = 0;
Sumit.Saxena@avagotech.com9b828182015-04-23 16:30:24 +05302855
2856 fusion = instance->ctrl_context;
2857
2858 /* Re-fire management commands.
2859 * Do not traverse complet MPT frame pool. Start from max_scsi_cmds.
2860 */
2861 for (j = instance->max_scsi_cmds ; j < instance->max_fw_cmds; j++) {
2862 cmd_fusion = fusion->cmd_list[j];
2863 cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
2864 smid = le16_to_cpu(cmd_mfi->context.smid);
2865
2866 if (!smid)
2867 continue;
2868 req_desc = megasas_get_request_descriptor
2869 (instance, smid - 1);
Sumit Saxena6d40afb2016-01-28 21:04:23 +05302870 refire_cmd = req_desc && ((cmd_mfi->frame->dcmd.opcode !=
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05302871 cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO)) &&
2872 (cmd_mfi->frame->dcmd.opcode !=
Sumit Saxena6d40afb2016-01-28 21:04:23 +05302873 cpu_to_le32(MR_DCMD_SYSTEM_PD_MAP_GET_INFO)))
2874 && !(cmd_mfi->flags & DRV_DCMD_SKIP_REFIRE);
2875 if (refire_cmd)
Christoph Hellwig01d7f032015-04-23 16:34:09 +05302876 megasas_fire_cmd_fusion(instance, req_desc);
2877 else
Sumit.Saxena@avagotech.com9b828182015-04-23 16:30:24 +05302878 megasas_return_cmd(instance, cmd_mfi);
2879 }
adam radford9c915a82010-12-21 13:34:31 -08002880}
2881
Sumit Saxena18365b12016-01-28 21:04:25 +05302882/*
2883 * megasas_track_scsiio : Track SCSI IOs outstanding to a SCSI device
2884 * @instance: per adapter struct
2885 * @channel: the channel assigned by the OS
2886 * @id: the id assigned by the OS
2887 *
2888 * Returns SUCCESS if no IOs pending to SCSI device, else return FAILED
2889 */
2890
2891static int megasas_track_scsiio(struct megasas_instance *instance,
2892 int id, int channel)
2893{
2894 int i, found = 0;
2895 struct megasas_cmd_fusion *cmd_fusion;
2896 struct fusion_context *fusion;
2897 fusion = instance->ctrl_context;
2898
2899 for (i = 0 ; i < instance->max_scsi_cmds; i++) {
2900 cmd_fusion = fusion->cmd_list[i];
2901 if (cmd_fusion->scmd &&
2902 (cmd_fusion->scmd->device->id == id &&
2903 cmd_fusion->scmd->device->channel == channel)) {
2904 dev_info(&instance->pdev->dev,
2905 "SCSI commands pending to target"
2906 "channel %d id %d \tSMID: 0x%x\n",
2907 channel, id, cmd_fusion->index);
2908 scsi_print_command(cmd_fusion->scmd);
2909 found = 1;
2910 break;
2911 }
2912 }
2913
2914 return found ? FAILED : SUCCESS;
2915}
2916
2917/**
2918 * megasas_tm_response_code - translation of device response code
2919 * @ioc: per adapter object
2920 * @mpi_reply: MPI reply returned by firmware
2921 *
2922 * Return nothing.
2923 */
2924static void
2925megasas_tm_response_code(struct megasas_instance *instance,
2926 struct MPI2_SCSI_TASK_MANAGE_REPLY *mpi_reply)
2927{
2928 char *desc;
2929
2930 switch (mpi_reply->ResponseCode) {
2931 case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
2932 desc = "task management request completed";
2933 break;
2934 case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
2935 desc = "invalid frame";
2936 break;
2937 case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2938 desc = "task management request not supported";
2939 break;
2940 case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
2941 desc = "task management request failed";
2942 break;
2943 case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2944 desc = "task management request succeeded";
2945 break;
2946 case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2947 desc = "invalid lun";
2948 break;
2949 case 0xA:
2950 desc = "overlapped tag attempted";
2951 break;
2952 case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2953 desc = "task queued, however not sent to target";
2954 break;
2955 default:
2956 desc = "unknown";
2957 break;
2958 }
2959 dev_dbg(&instance->pdev->dev, "response_code(%01x): %s\n",
2960 mpi_reply->ResponseCode, desc);
2961 dev_dbg(&instance->pdev->dev,
2962 "TerminationCount/DevHandle/Function/TaskType/IOCStat/IOCLoginfo"
2963 " 0x%x/0x%x/0x%x/0x%x/0x%x/0x%x\n",
2964 mpi_reply->TerminationCount, mpi_reply->DevHandle,
2965 mpi_reply->Function, mpi_reply->TaskType,
2966 mpi_reply->IOCStatus, mpi_reply->IOCLogInfo);
2967}
2968
2969/**
2970 * megasas_issue_tm - main routine for sending tm requests
2971 * @instance: per adapter struct
2972 * @device_handle: device handle
2973 * @channel: the channel assigned by the OS
2974 * @id: the id assigned by the OS
2975 * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in megaraid_sas_fusion.c)
2976 * @smid_task: smid assigned to the task
2977 * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
2978 * Context: user
2979 *
2980 * MegaRaid use MPT interface for Task Magement request.
2981 * A generic API for sending task management requests to firmware.
2982 *
2983 * Return SUCCESS or FAILED.
2984 */
2985static int
2986megasas_issue_tm(struct megasas_instance *instance, u16 device_handle,
2987 uint channel, uint id, u16 smid_task, u8 type)
2988{
2989 struct MR_TASK_MANAGE_REQUEST *mr_request;
2990 struct MPI2_SCSI_TASK_MANAGE_REQUEST *mpi_request;
2991 unsigned long timeleft;
2992 struct megasas_cmd_fusion *cmd_fusion;
2993 struct megasas_cmd *cmd_mfi;
2994 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
2995 struct fusion_context *fusion;
2996 struct megasas_cmd_fusion *scsi_lookup;
2997 int rc;
2998 struct MPI2_SCSI_TASK_MANAGE_REPLY *mpi_reply;
2999
3000 fusion = instance->ctrl_context;
3001
3002 cmd_mfi = megasas_get_cmd(instance);
3003
3004 if (!cmd_mfi) {
3005 dev_err(&instance->pdev->dev, "Failed from %s %d\n",
3006 __func__, __LINE__);
3007 return -ENOMEM;
3008 }
3009
3010 cmd_fusion = megasas_get_cmd_fusion(instance,
3011 instance->max_scsi_cmds + cmd_mfi->index);
3012
3013 /* Save the smid. To be used for returning the cmd */
3014 cmd_mfi->context.smid = cmd_fusion->index;
3015
3016 req_desc = megasas_get_request_descriptor(instance,
3017 (cmd_fusion->index - 1));
3018 if (!req_desc) {
3019 dev_err(&instance->pdev->dev, "Failed from %s %d\n",
3020 __func__, __LINE__);
3021 megasas_return_cmd(instance, cmd_mfi);
3022 return -ENOMEM;
3023 }
3024
3025 cmd_fusion->request_desc = req_desc;
3026 req_desc->Words = 0;
3027
3028 scsi_lookup = fusion->cmd_list[smid_task - 1];
3029
3030 mr_request = (struct MR_TASK_MANAGE_REQUEST *) cmd_fusion->io_request;
3031 memset(mr_request, 0, sizeof(struct MR_TASK_MANAGE_REQUEST));
3032 mpi_request = (struct MPI2_SCSI_TASK_MANAGE_REQUEST *) &mr_request->TmRequest;
3033 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
3034 mpi_request->DevHandle = cpu_to_le16(device_handle);
3035 mpi_request->TaskType = type;
3036 mpi_request->TaskMID = cpu_to_le16(smid_task);
3037 mpi_request->LUN[1] = 0;
3038
3039
3040 req_desc = cmd_fusion->request_desc;
3041 req_desc->HighPriority.SMID = cpu_to_le16(cmd_fusion->index);
3042 req_desc->HighPriority.RequestFlags =
3043 (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
3044 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
3045 req_desc->HighPriority.MSIxIndex = 0;
3046 req_desc->HighPriority.LMID = 0;
3047 req_desc->HighPriority.Reserved1 = 0;
3048
3049 if (channel < MEGASAS_MAX_PD_CHANNELS)
3050 mr_request->tmReqFlags.isTMForPD = 1;
3051 else
3052 mr_request->tmReqFlags.isTMForLD = 1;
3053
3054 init_completion(&cmd_fusion->done);
3055 megasas_fire_cmd_fusion(instance, req_desc);
3056
3057 timeleft = wait_for_completion_timeout(&cmd_fusion->done, 50 * HZ);
3058
3059 if (!timeleft) {
3060 dev_err(&instance->pdev->dev,
3061 "task mgmt type 0x%x timed out\n", type);
3062 cmd_mfi->flags |= DRV_DCMD_SKIP_REFIRE;
3063 mutex_unlock(&instance->reset_mutex);
3064 rc = megasas_reset_fusion(instance->host, MFI_IO_TIMEOUT_OCR);
3065 mutex_lock(&instance->reset_mutex);
3066 return rc;
3067 }
3068
3069 mpi_reply = (struct MPI2_SCSI_TASK_MANAGE_REPLY *) &mr_request->TMReply;
3070 megasas_tm_response_code(instance, mpi_reply);
3071
3072 megasas_return_cmd(instance, cmd_mfi);
3073 rc = SUCCESS;
3074 switch (type) {
3075 case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
3076 if (scsi_lookup->scmd == NULL)
3077 break;
3078 else {
3079 instance->instancet->disable_intr(instance);
3080 msleep(1000);
3081 megasas_complete_cmd_dpc_fusion
3082 ((unsigned long)instance);
3083 instance->instancet->enable_intr(instance);
3084 if (scsi_lookup->scmd == NULL)
3085 break;
3086 }
3087 rc = FAILED;
3088 break;
3089
3090 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
3091 if ((channel == 0xFFFFFFFF) && (id == 0xFFFFFFFF))
3092 break;
3093 instance->instancet->disable_intr(instance);
3094 msleep(1000);
3095 megasas_complete_cmd_dpc_fusion
3096 ((unsigned long)instance);
3097 rc = megasas_track_scsiio(instance, id, channel);
3098 instance->instancet->enable_intr(instance);
3099
3100 break;
3101 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
3102 case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
3103 break;
3104 default:
3105 rc = FAILED;
3106 break;
3107 }
3108
3109 return rc;
3110
3111}
3112
3113/*
3114 * megasas_fusion_smid_lookup : Look for fusion command correpspodning to SCSI
3115 * @instance: per adapter struct
3116 *
3117 * Return Non Zero index, if SMID found in outstanding commands
3118 */
3119static u16 megasas_fusion_smid_lookup(struct scsi_cmnd *scmd)
3120{
3121 int i, ret = 0;
3122 struct megasas_instance *instance;
3123 struct megasas_cmd_fusion *cmd_fusion;
3124 struct fusion_context *fusion;
3125
3126 instance = (struct megasas_instance *)scmd->device->host->hostdata;
3127
3128 fusion = instance->ctrl_context;
3129
3130 for (i = 0; i < instance->max_scsi_cmds; i++) {
3131 cmd_fusion = fusion->cmd_list[i];
3132 if (cmd_fusion->scmd && (cmd_fusion->scmd == scmd)) {
3133 scmd_printk(KERN_NOTICE, scmd, "Abort request is for"
3134 " SMID: %d\n", cmd_fusion->index);
3135 ret = cmd_fusion->index;
3136 break;
3137 }
3138 }
3139
3140 return ret;
3141}
3142
3143/*
3144* megasas_get_tm_devhandle - Get devhandle for TM request
3145* @sdev- OS provided scsi device
3146*
3147* Returns- devhandle/targetID of SCSI device
3148*/
3149static u16 megasas_get_tm_devhandle(struct scsi_device *sdev)
3150{
3151 u16 pd_index = 0;
3152 u32 device_id;
3153 struct megasas_instance *instance;
3154 struct fusion_context *fusion;
3155 struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync;
3156 u16 devhandle = (u16)ULONG_MAX;
3157
3158 instance = (struct megasas_instance *)sdev->host->hostdata;
3159 fusion = instance->ctrl_context;
3160
3161 if (sdev->channel < MEGASAS_MAX_PD_CHANNELS) {
3162 if (instance->use_seqnum_jbod_fp) {
3163 pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
3164 sdev->id;
3165 pd_sync = (void *)fusion->pd_seq_sync
3166 [(instance->pd_seq_map_id - 1) & 1];
3167 devhandle = pd_sync->seq[pd_index].devHandle;
3168 } else
3169 sdev_printk(KERN_ERR, sdev, "Firmware expose tmCapable"
3170 " without JBOD MAP support from %s %d\n", __func__, __LINE__);
3171 } else {
3172 device_id = ((sdev->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL)
3173 + sdev->id;
3174 devhandle = device_id;
3175 }
3176
3177 return devhandle;
3178}
3179
3180/*
3181 * megasas_task_abort_fusion : SCSI task abort function for fusion adapters
3182 * @scmd : pointer to scsi command object
3183 *
3184 * Return SUCCESS, if command aborted else FAILED
3185 */
3186
3187int megasas_task_abort_fusion(struct scsi_cmnd *scmd)
3188{
3189 struct megasas_instance *instance;
3190 u16 smid, devhandle;
3191 struct fusion_context *fusion;
3192 int ret;
3193 struct MR_PRIV_DEVICE *mr_device_priv_data;
3194 mr_device_priv_data = scmd->device->hostdata;
3195
3196
3197 instance = (struct megasas_instance *)scmd->device->host->hostdata;
3198 fusion = instance->ctrl_context;
3199
Sumit Saxena8a01a412016-01-28 21:04:32 +05303200 if (atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) {
Sumit Saxena18365b12016-01-28 21:04:25 +05303201 dev_err(&instance->pdev->dev, "Controller is not OPERATIONAL,"
3202 "SCSI host:%d\n", instance->host->host_no);
3203 ret = FAILED;
3204 return ret;
3205 }
3206
3207 if (!mr_device_priv_data) {
3208 sdev_printk(KERN_INFO, scmd->device, "device been deleted! "
3209 "scmd(%p)\n", scmd);
3210 scmd->result = DID_NO_CONNECT << 16;
3211 ret = SUCCESS;
3212 goto out;
3213 }
3214
3215
3216 if (!mr_device_priv_data->is_tm_capable) {
3217 ret = FAILED;
3218 goto out;
3219 }
3220
3221 mutex_lock(&instance->reset_mutex);
3222
3223 smid = megasas_fusion_smid_lookup(scmd);
3224
3225 if (!smid) {
3226 ret = SUCCESS;
3227 scmd_printk(KERN_NOTICE, scmd, "Command for which abort is"
3228 " issued is not found in oustanding commands\n");
3229 mutex_unlock(&instance->reset_mutex);
3230 goto out;
3231 }
3232
3233 devhandle = megasas_get_tm_devhandle(scmd->device);
3234
3235 if (devhandle == (u16)ULONG_MAX) {
3236 ret = SUCCESS;
3237 sdev_printk(KERN_INFO, scmd->device,
3238 "task abort issued for invalid devhandle\n");
3239 mutex_unlock(&instance->reset_mutex);
3240 goto out;
3241 }
3242 sdev_printk(KERN_INFO, scmd->device,
3243 "attempting task abort! scmd(%p) tm_dev_handle 0x%x\n",
3244 scmd, devhandle);
3245
3246 mr_device_priv_data->tm_busy = 1;
3247 ret = megasas_issue_tm(instance, devhandle,
3248 scmd->device->channel, scmd->device->id, smid,
3249 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK);
3250 mr_device_priv_data->tm_busy = 0;
3251
3252 mutex_unlock(&instance->reset_mutex);
3253out:
3254 sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
3255 ((ret == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
3256
3257 return ret;
3258}
3259
3260/*
3261 * megasas_reset_target_fusion : target reset function for fusion adapters
3262 * scmd: SCSI command pointer
3263 *
3264 * Returns SUCCESS if all commands associated with target aborted else FAILED
3265 */
3266
3267int megasas_reset_target_fusion(struct scsi_cmnd *scmd)
3268{
3269
3270 struct megasas_instance *instance;
3271 int ret = FAILED;
3272 u16 devhandle;
3273 struct fusion_context *fusion;
3274 struct MR_PRIV_DEVICE *mr_device_priv_data;
3275 mr_device_priv_data = scmd->device->hostdata;
3276
3277 instance = (struct megasas_instance *)scmd->device->host->hostdata;
3278 fusion = instance->ctrl_context;
3279
Sumit Saxena8a01a412016-01-28 21:04:32 +05303280 if (atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) {
Sumit Saxena18365b12016-01-28 21:04:25 +05303281 dev_err(&instance->pdev->dev, "Controller is not OPERATIONAL,"
3282 "SCSI host:%d\n", instance->host->host_no);
3283 ret = FAILED;
3284 return ret;
3285 }
3286
3287 if (!mr_device_priv_data) {
3288 sdev_printk(KERN_INFO, scmd->device, "device been deleted! "
3289 "scmd(%p)\n", scmd);
3290 scmd->result = DID_NO_CONNECT << 16;
3291 ret = SUCCESS;
3292 goto out;
3293 }
3294
3295
3296 if (!mr_device_priv_data->is_tm_capable) {
3297 ret = FAILED;
3298 goto out;
3299 }
3300
3301 mutex_lock(&instance->reset_mutex);
3302 devhandle = megasas_get_tm_devhandle(scmd->device);
3303
3304 if (devhandle == (u16)ULONG_MAX) {
3305 ret = SUCCESS;
3306 sdev_printk(KERN_INFO, scmd->device,
3307 "target reset issued for invalid devhandle\n");
3308 mutex_unlock(&instance->reset_mutex);
3309 goto out;
3310 }
3311
3312 sdev_printk(KERN_INFO, scmd->device,
3313 "attempting target reset! scmd(%p) tm_dev_handle 0x%x\n",
3314 scmd, devhandle);
3315 mr_device_priv_data->tm_busy = 1;
3316 ret = megasas_issue_tm(instance, devhandle,
3317 scmd->device->channel, scmd->device->id, 0,
3318 MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET);
3319 mr_device_priv_data->tm_busy = 0;
3320 mutex_unlock(&instance->reset_mutex);
3321out:
3322 scmd_printk(KERN_NOTICE, scmd, "megasas: target reset %s!!\n",
3323 (ret == SUCCESS) ? "SUCCESS" : "FAILED");
3324
3325 return ret;
3326}
3327
Sumit Saxena8f67c8c2016-01-28 21:14:25 +05303328/*SRIOV get other instance in cluster if any*/
3329struct megasas_instance *megasas_get_peer_instance(struct megasas_instance *instance)
3330{
3331 int i;
3332
3333 for (i = 0; i < MAX_MGMT_ADAPTERS; i++) {
3334 if (megasas_mgmt_info.instance[i] &&
3335 (megasas_mgmt_info.instance[i] != instance) &&
3336 megasas_mgmt_info.instance[i]->requestorId &&
3337 megasas_mgmt_info.instance[i]->peerIsPresent &&
3338 (memcmp((megasas_mgmt_info.instance[i]->clusterId),
3339 instance->clusterId, MEGASAS_CLUSTER_ID_SIZE) == 0))
3340 return megasas_mgmt_info.instance[i];
3341 }
3342 return NULL;
3343}
3344
adam radford229fe472014-03-10 02:51:56 -07003345/* Check for a second path that is currently UP */
3346int megasas_check_mpio_paths(struct megasas_instance *instance,
3347 struct scsi_cmnd *scmd)
adam radford9c915a82010-12-21 13:34:31 -08003348{
Sumit Saxena8f67c8c2016-01-28 21:14:25 +05303349 struct megasas_instance *peer_instance = NULL;
3350 int retval = (DID_RESET << 16);
adam radford229fe472014-03-10 02:51:56 -07003351
Sumit Saxena8f67c8c2016-01-28 21:14:25 +05303352 if (instance->peerIsPresent) {
3353 peer_instance = megasas_get_peer_instance(instance);
3354 if ((peer_instance) &&
3355 (atomic_read(&peer_instance->adprecovery) ==
3356 MEGASAS_HBA_OPERATIONAL))
3357 retval = (DID_NO_CONNECT << 16);
adam radford229fe472014-03-10 02:51:56 -07003358 }
adam radford229fe472014-03-10 02:51:56 -07003359 return retval;
3360}
3361
3362/* Core fusion reset function */
Sumit Saxena18365b12016-01-28 21:04:25 +05303363int megasas_reset_fusion(struct Scsi_Host *shost, int reason)
adam radford229fe472014-03-10 02:51:56 -07003364{
sumit.saxena@avagotech.com79b82c22015-08-31 17:23:41 +05303365 int retval = SUCCESS, i, convert = 0;
adam radford9c915a82010-12-21 13:34:31 -08003366 struct megasas_instance *instance;
3367 struct megasas_cmd_fusion *cmd_fusion;
3368 struct fusion_context *fusion;
sumit.saxena@avagotech.com79b82c22015-08-31 17:23:41 +05303369 u32 abs_state, status_reg, reset_adapter;
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05303370 u32 io_timeout_in_crash_mode = 0;
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05303371 struct scsi_cmnd *scmd_local = NULL;
Sumit Saxena18365b12016-01-28 21:04:25 +05303372 struct scsi_device *sdev;
adam radford9c915a82010-12-21 13:34:31 -08003373
3374 instance = (struct megasas_instance *)shost->hostdata;
3375 fusion = instance->ctrl_context;
3376
adam radford229fe472014-03-10 02:51:56 -07003377 mutex_lock(&instance->reset_mutex);
3378
Sumit Saxena8a01a412016-01-28 21:04:32 +05303379 if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05003380 dev_warn(&instance->pdev->dev, "Hardware critical error, "
adam radford229fe472014-03-10 02:51:56 -07003381 "returning FAILED for scsi%d.\n",
3382 instance->host->host_no);
Adam Radforda2fbcbc2014-07-09 15:17:54 -07003383 mutex_unlock(&instance->reset_mutex);
adam radfordd4a759a2011-10-08 18:14:39 -07003384 return FAILED;
adam radford9c915a82010-12-21 13:34:31 -08003385 }
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05303386 status_reg = instance->instancet->read_fw_status_reg(instance->reg_set);
3387 abs_state = status_reg & MFI_STATE_MASK;
3388
3389 /* IO timeout detected, forcibly put FW in FAULT state */
3390 if (abs_state != MFI_STATE_FAULT && instance->crash_dump_buf &&
Sumit Saxena18365b12016-01-28 21:04:25 +05303391 instance->crash_dump_app_support && reason) {
3392 dev_info(&instance->pdev->dev, "IO/DCMD timeout is detected, "
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05303393 "forcibly FAULT Firmware\n");
Sumit Saxena8a01a412016-01-28 21:04:32 +05303394 atomic_set(&instance->adprecovery, MEGASAS_ADPRESET_SM_INFAULT);
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05303395 status_reg = readl(&instance->reg_set->doorbell);
3396 writel(status_reg | MFI_STATE_FORCE_OCR,
3397 &instance->reg_set->doorbell);
3398 readl(&instance->reg_set->doorbell);
3399 mutex_unlock(&instance->reset_mutex);
3400 do {
3401 ssleep(3);
3402 io_timeout_in_crash_mode++;
3403 dev_dbg(&instance->pdev->dev, "waiting for [%d] "
3404 "seconds for crash dump collection and OCR "
3405 "to be done\n", (io_timeout_in_crash_mode * 3));
Sumit Saxena8a01a412016-01-28 21:04:32 +05303406 } while ((atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) &&
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05303407 (io_timeout_in_crash_mode < 80));
3408
Sumit Saxena8a01a412016-01-28 21:04:32 +05303409 if (atomic_read(&instance->adprecovery) == MEGASAS_HBA_OPERATIONAL) {
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05303410 dev_info(&instance->pdev->dev, "OCR done for IO "
3411 "timeout case\n");
3412 retval = SUCCESS;
3413 } else {
3414 dev_info(&instance->pdev->dev, "Controller is not "
3415 "operational after 240 seconds wait for IO "
3416 "timeout case in FW crash dump mode\n do "
3417 "OCR/kill adapter\n");
3418 retval = megasas_reset_fusion(shost, 0);
3419 }
3420 return retval;
3421 }
adam radford9c915a82010-12-21 13:34:31 -08003422
adam radford229fe472014-03-10 02:51:56 -07003423 if (instance->requestorId && !instance->skip_heartbeat_timer_del)
3424 del_timer_sync(&instance->sriov_heartbeat_timer);
adam radford7e70e732011-05-11 18:34:08 -07003425 set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
Sumit Saxena8a01a412016-01-28 21:04:32 +05303426 atomic_set(&instance->adprecovery, MEGASAS_ADPRESET_SM_POLLING);
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +05303427 instance->instancet->disable_intr(instance);
adam radford7e70e732011-05-11 18:34:08 -07003428 msleep(1000);
3429
adam radford9c915a82010-12-21 13:34:31 -08003430 /* First try waiting for commands to complete */
Sumit Saxena18365b12016-01-28 21:04:25 +05303431 if (megasas_wait_for_outstanding_fusion(instance, reason,
adam radford229fe472014-03-10 02:51:56 -07003432 &convert)) {
Sumit Saxena8a01a412016-01-28 21:04:32 +05303433 atomic_set(&instance->adprecovery, MEGASAS_ADPRESET_SM_INFAULT);
Bjorn Helgaas1be18252015-07-07 15:52:34 -05003434 dev_warn(&instance->pdev->dev, "resetting fusion "
adam radford229fe472014-03-10 02:51:56 -07003435 "adapter scsi%d.\n", instance->host->host_no);
3436 if (convert)
Sumit Saxena18365b12016-01-28 21:04:25 +05303437 reason = 0;
adam radford229fe472014-03-10 02:51:56 -07003438
adam radford9c915a82010-12-21 13:34:31 -08003439 /* Now return commands back to the OS */
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05303440 for (i = 0 ; i < instance->max_scsi_cmds; i++) {
adam radford9c915a82010-12-21 13:34:31 -08003441 cmd_fusion = fusion->cmd_list[i];
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05303442 scmd_local = cmd_fusion->scmd;
adam radford9c915a82010-12-21 13:34:31 -08003443 if (cmd_fusion->scmd) {
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05303444 scmd_local->result =
adam radford229fe472014-03-10 02:51:56 -07003445 megasas_check_mpio_paths(instance,
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05303446 scmd_local);
Sumit Saxena308ec452016-01-28 21:04:30 +05303447 if (megasas_cmd_type(scmd_local) == READ_WRITE_LDIO)
3448 atomic_dec(&instance->ldio_outstanding);
adam radford9c915a82010-12-21 13:34:31 -08003449 megasas_return_cmd_fusion(instance, cmd_fusion);
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05303450 scsi_dma_unmap(scmd_local);
3451 scmd_local->scsi_done(scmd_local);
adam radford9c915a82010-12-21 13:34:31 -08003452 atomic_dec(&instance->fw_outstanding);
3453 }
3454 }
3455
adam radford7e70e732011-05-11 18:34:08 -07003456 status_reg = instance->instancet->read_fw_status_reg(
3457 instance->reg_set);
3458 abs_state = status_reg & MFI_STATE_MASK;
3459 reset_adapter = status_reg & MFI_RESET_ADAPTER;
3460 if (instance->disableOnlineCtrlReset ||
3461 (abs_state == MFI_STATE_FAULT && !reset_adapter)) {
adam radford9c915a82010-12-21 13:34:31 -08003462 /* Reset not supported, kill adapter */
Bjorn Helgaas1be18252015-07-07 15:52:34 -05003463 dev_warn(&instance->pdev->dev, "Reset not supported"
adam radford229fe472014-03-10 02:51:56 -07003464 ", killing adapter scsi%d.\n",
3465 instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08003466 megaraid_sas_kill_hba(instance);
adam radford229fe472014-03-10 02:51:56 -07003467 instance->skip_heartbeat_timer_del = 1;
adam radford9c915a82010-12-21 13:34:31 -08003468 retval = FAILED;
3469 goto out;
3470 }
3471
adam radford229fe472014-03-10 02:51:56 -07003472 /* Let SR-IOV VF & PF sync up if there was a HB failure */
Sumit Saxena18365b12016-01-28 21:04:25 +05303473 if (instance->requestorId && !reason) {
adam radford229fe472014-03-10 02:51:56 -07003474 msleep(MEGASAS_OCR_SETTLE_TIME_VF);
Sumit Saxena3885c262016-01-28 21:04:35 +05303475 goto transition_to_ready;
adam radford229fe472014-03-10 02:51:56 -07003476 }
3477
adam radford9c915a82010-12-21 13:34:31 -08003478 /* Now try to reset the chip */
3479 for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) {
adam radford9c915a82010-12-21 13:34:31 -08003480
sumit.saxena@avagotech.com79b82c22015-08-31 17:23:41 +05303481 if (instance->instancet->adp_reset
3482 (instance, instance->reg_set))
adam radford9c915a82010-12-21 13:34:31 -08003483 continue;
Sumit Saxena3885c262016-01-28 21:04:35 +05303484transition_to_ready:
adam radford9c915a82010-12-21 13:34:31 -08003485 /* Wait for FW to become ready */
adam radford058a8fa2011-10-08 18:14:27 -07003486 if (megasas_transition_to_ready(instance, 1)) {
Sumit Saxena3885c262016-01-28 21:04:35 +05303487 dev_warn(&instance->pdev->dev,
3488 "Failed to transition controller to ready for "
3489 "scsi%d.\n", instance->host->host_no);
3490 if (instance->requestorId && !reason)
3491 goto fail_kill_adapter;
3492 else
3493 continue;
adam radford9c915a82010-12-21 13:34:31 -08003494 }
adam radford9c915a82010-12-21 13:34:31 -08003495 megasas_reset_reply_desc(instance);
Sumit Saxena308ec452016-01-28 21:04:30 +05303496 megasas_fusion_update_can_queue(instance, OCR_CONTEXT);
3497
adam radford9c915a82010-12-21 13:34:31 -08003498 if (megasas_ioc_init_fusion(instance)) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05003499 dev_warn(&instance->pdev->dev,
Sumit Saxena3885c262016-01-28 21:04:35 +05303500 "megasas_ioc_init_fusion() failed! for "
3501 "scsi%d\n", instance->host->host_no);
3502 if (instance->requestorId && !reason)
3503 goto fail_kill_adapter;
3504 else
3505 continue;
adam radford9c915a82010-12-21 13:34:31 -08003506 }
3507
Sumit.Saxena@avagotech.com9b828182015-04-23 16:30:24 +05303508 megasas_refire_mgmt_cmd(instance);
adam radford9c915a82010-12-21 13:34:31 -08003509
Sumit.Saxena@avagotech.comd009b572014-11-17 15:24:13 +05303510 if (megasas_get_ctrl_info(instance)) {
3511 dev_info(&instance->pdev->dev,
3512 "Failed from %s %d\n",
3513 __func__, __LINE__);
Sumit.Saxena@avagotech.comd009b572014-11-17 15:24:13 +05303514 megaraid_sas_kill_hba(instance);
3515 retval = FAILED;
3516 }
adam radford9c915a82010-12-21 13:34:31 -08003517 /* Reset load balance info */
3518 memset(fusion->load_balance_info, 0,
3519 sizeof(struct LD_LOAD_BALANCE_INFO)
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05303520 *MAX_LOGICAL_DRIVES_EXT);
adam radford9c915a82010-12-21 13:34:31 -08003521
3522 if (!megasas_get_map_info(instance))
3523 megasas_sync_map_info(instance);
3524
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05303525 megasas_setup_jbod_map(instance);
3526
Sumit Saxena18365b12016-01-28 21:04:25 +05303527 shost_for_each_device(sdev, shost)
3528 megasas_update_sdev_properties(sdev);
3529
Sumit.Saxena@avagotech.comac340c52014-11-17 15:24:18 +05303530 clear_bit(MEGASAS_FUSION_IN_RESET,
3531 &instance->reset_flags);
3532 instance->instancet->enable_intr(instance);
Sumit Saxena8a01a412016-01-28 21:04:32 +05303533 atomic_set(&instance->adprecovery, MEGASAS_HBA_OPERATIONAL);
Sumit.Saxena@avagotech.comac340c52014-11-17 15:24:18 +05303534
adam radford229fe472014-03-10 02:51:56 -07003535 /* Restart SR-IOV heartbeat */
3536 if (instance->requestorId) {
3537 if (!megasas_sriov_start_heartbeat(instance, 0))
3538 megasas_start_timer(instance,
3539 &instance->sriov_heartbeat_timer,
3540 megasas_sriov_heartbeat_handler,
3541 MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF);
3542 else
3543 instance->skip_heartbeat_timer_del = 1;
3544 }
3545
adam radford9c915a82010-12-21 13:34:31 -08003546 /* Adapter reset completed successfully */
Bjorn Helgaas1be18252015-07-07 15:52:34 -05003547 dev_warn(&instance->pdev->dev, "Reset "
adam radford229fe472014-03-10 02:51:56 -07003548 "successful for scsi%d.\n",
3549 instance->host->host_no);
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05303550
Sumit.Saxena@avagotech.comac340c52014-11-17 15:24:18 +05303551 if (instance->crash_dump_drv_support &&
3552 instance->crash_dump_app_support)
3553 megasas_set_crash_dump_params(instance,
3554 MR_CRASH_BUF_TURN_ON);
3555 else
3556 megasas_set_crash_dump_params(instance,
3557 MR_CRASH_BUF_TURN_OFF);
3558
adam radford9c915a82010-12-21 13:34:31 -08003559 retval = SUCCESS;
3560 goto out;
3561 }
Sumit Saxena3885c262016-01-28 21:04:35 +05303562fail_kill_adapter:
adam radford9c915a82010-12-21 13:34:31 -08003563 /* Reset failed, kill the adapter */
Bjorn Helgaas1be18252015-07-07 15:52:34 -05003564 dev_warn(&instance->pdev->dev, "Reset failed, killing "
adam radford229fe472014-03-10 02:51:56 -07003565 "adapter scsi%d.\n", instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08003566 megaraid_sas_kill_hba(instance);
adam radford229fe472014-03-10 02:51:56 -07003567 instance->skip_heartbeat_timer_del = 1;
adam radford9c915a82010-12-21 13:34:31 -08003568 retval = FAILED;
3569 } else {
adam radford229fe472014-03-10 02:51:56 -07003570 /* For VF: Restart HB timer if we didn't OCR */
3571 if (instance->requestorId) {
3572 megasas_start_timer(instance,
3573 &instance->sriov_heartbeat_timer,
3574 megasas_sriov_heartbeat_handler,
3575 MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF);
3576 }
adam radford3f0e58bc2011-10-08 18:14:59 -07003577 clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +05303578 instance->instancet->enable_intr(instance);
Sumit Saxena8a01a412016-01-28 21:04:32 +05303579 atomic_set(&instance->adprecovery, MEGASAS_HBA_OPERATIONAL);
adam radford9c915a82010-12-21 13:34:31 -08003580 }
3581out:
3582 clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
3583 mutex_unlock(&instance->reset_mutex);
3584 return retval;
3585}
3586
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05303587/* Fusion Crash dump collection work queue */
3588void megasas_fusion_crash_dump_wq(struct work_struct *work)
3589{
3590 struct megasas_instance *instance =
3591 container_of(work, struct megasas_instance, crash_init);
3592 u32 status_reg;
3593 u8 partial_copy = 0;
3594
3595
3596 status_reg = instance->instancet->read_fw_status_reg(instance->reg_set);
3597
3598 /*
3599 * Allocate host crash buffers to copy data from 1 MB DMA crash buffer
3600 * to host crash buffers
3601 */
3602 if (instance->drv_buf_index == 0) {
3603 /* Buffer is already allocated for old Crash dump.
3604 * Do OCR and do not wait for crash dump collection
3605 */
3606 if (instance->drv_buf_alloc) {
3607 dev_info(&instance->pdev->dev, "earlier crash dump is "
3608 "not yet copied by application, ignoring this "
3609 "crash dump and initiating OCR\n");
3610 status_reg |= MFI_STATE_CRASH_DUMP_DONE;
3611 writel(status_reg,
3612 &instance->reg_set->outbound_scratch_pad);
3613 readl(&instance->reg_set->outbound_scratch_pad);
3614 return;
3615 }
3616 megasas_alloc_host_crash_buffer(instance);
3617 dev_info(&instance->pdev->dev, "Number of host crash buffers "
3618 "allocated: %d\n", instance->drv_buf_alloc);
3619 }
3620
3621 /*
3622 * Driver has allocated max buffers, which can be allocated
3623 * and FW has more crash dump data, then driver will
3624 * ignore the data.
3625 */
3626 if (instance->drv_buf_index >= (instance->drv_buf_alloc)) {
3627 dev_info(&instance->pdev->dev, "Driver is done copying "
3628 "the buffer: %d\n", instance->drv_buf_alloc);
3629 status_reg |= MFI_STATE_CRASH_DUMP_DONE;
3630 partial_copy = 1;
3631 } else {
3632 memcpy(instance->crash_buf[instance->drv_buf_index],
3633 instance->crash_dump_buf, CRASH_DMA_BUF_SIZE);
3634 instance->drv_buf_index++;
3635 status_reg &= ~MFI_STATE_DMADONE;
3636 }
3637
3638 if (status_reg & MFI_STATE_CRASH_DUMP_DONE) {
3639 dev_info(&instance->pdev->dev, "Crash Dump is available,number "
3640 "of copied buffers: %d\n", instance->drv_buf_index);
3641 instance->fw_crash_buffer_size = instance->drv_buf_index;
3642 instance->fw_crash_state = AVAILABLE;
3643 instance->drv_buf_index = 0;
3644 writel(status_reg, &instance->reg_set->outbound_scratch_pad);
3645 readl(&instance->reg_set->outbound_scratch_pad);
3646 if (!partial_copy)
3647 megasas_reset_fusion(instance->host, 0);
3648 } else {
3649 writel(status_reg, &instance->reg_set->outbound_scratch_pad);
3650 readl(&instance->reg_set->outbound_scratch_pad);
3651 }
3652}
3653
3654
adam radford9c915a82010-12-21 13:34:31 -08003655/* Fusion OCR work queue */
3656void megasas_fusion_ocr_wq(struct work_struct *work)
3657{
3658 struct megasas_instance *instance =
3659 container_of(work, struct megasas_instance, work_init);
3660
adam radford229fe472014-03-10 02:51:56 -07003661 megasas_reset_fusion(instance->host, 0);
adam radford9c915a82010-12-21 13:34:31 -08003662}
3663
3664struct megasas_instance_template megasas_instance_template_fusion = {
adam radford9c915a82010-12-21 13:34:31 -08003665 .enable_intr = megasas_enable_intr_fusion,
3666 .disable_intr = megasas_disable_intr_fusion,
3667 .clear_intr = megasas_clear_intr_fusion,
3668 .read_fw_status_reg = megasas_read_fw_status_reg_fusion,
3669 .adp_reset = megasas_adp_reset_fusion,
3670 .check_reset = megasas_check_reset_fusion,
3671 .service_isr = megasas_isr_fusion,
3672 .tasklet = megasas_complete_cmd_dpc_fusion,
3673 .init_adapter = megasas_init_adapter_fusion,
3674 .build_and_issue_cmd = megasas_build_and_issue_cmd_fusion,
3675 .issue_dcmd = megasas_issue_dcmd_fusion,
3676};