blob: 765633cd182cb94b375445ebf323e02c620d1ecf [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
Shivasharan S365597c2018-10-16 23:37:43 -07005 * Copyright (c) 2013-2016 Avago Technologies
6 * Copyright (c) 2016-2018 Broadcom Inc.
adam radford9c915a82010-12-21 13:34:31 -08007 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
Sumit.Saxena@avagotech.come3990652014-11-17 15:24:03 +053019 * along with this program. If not, see <http://www.gnu.org/licenses/>.
adam radford9c915a82010-12-21 13:34:31 -080020 *
21 * FILE: megaraid_sas_fusion.c
22 *
Shivasharan S365597c2018-10-16 23:37:43 -070023 * Authors: Broadcom Inc.
adam radford9c915a82010-12-21 13:34:31 -080024 * Sumant Patro
Sumit.Saxena@avagotech.come3990652014-11-17 15:24:03 +053025 * Adam Radford
Shivasharan S365597c2018-10-16 23:37:43 -070026 * Kashyap Desai <kashyap.desai@broadcom.com>
27 * Sumit Saxena <sumit.saxena@broadcom.com>
adam radford9c915a82010-12-21 13:34:31 -080028 *
Shivasharan S365597c2018-10-16 23:37:43 -070029 * Send feedback to: megaraidlinux.pdl@broadcom.com
adam radford9c915a82010-12-21 13:34:31 -080030 */
31
32#include <linux/kernel.h>
33#include <linux/types.h>
34#include <linux/pci.h>
35#include <linux/list.h>
36#include <linux/moduleparam.h>
37#include <linux/module.h>
38#include <linux/spinlock.h>
39#include <linux/interrupt.h>
40#include <linux/delay.h>
adam radford9c915a82010-12-21 13:34:31 -080041#include <linux/uio.h>
42#include <linux/uaccess.h>
43#include <linux/fs.h>
44#include <linux/compat.h>
45#include <linux/blkdev.h>
46#include <linux/mutex.h>
47#include <linux/poll.h>
Shivasharan S5fc499b2017-02-10 00:59:17 -080048#include <linux/vmalloc.h>
Shivasharan S3f6194a2018-10-16 23:37:39 -070049#include <linux/workqueue.h>
adam radford9c915a82010-12-21 13:34:31 -080050
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 -070087int megasas_sriov_start_heartbeat(struct megasas_instance *instance,
88 int initial);
Kees Cookc251a7b2017-10-22 15:30:04 -070089void megasas_start_timer(struct megasas_instance *instance);
adam radford229fe472014-03-10 02:51:56 -070090extern struct megasas_mgmt_info megasas_mgmt_info;
Sumit Saxenae3d178c2016-01-28 21:04:34 +053091extern unsigned int resetwaittime;
Sumit Saxena308ec452016-01-28 21:04:30 +053092extern unsigned int dual_qdepth_disable;
Sumit Saxena179ac142016-01-28 21:04:28 +053093static void megasas_free_rdpq_fusion(struct megasas_instance *instance);
94static void megasas_free_reply_fusion(struct megasas_instance *instance);
Shivasharan Se97e6732017-10-19 02:49:03 -070095static inline
96void megasas_configure_queue_sizes(struct megasas_instance *instance);
Shivasharan S3f6194a2018-10-16 23:37:39 -070097static void megasas_fusion_crash_dump(struct megasas_instance *instance);
adam radford9c915a82010-12-21 13:34:31 -080098
Shivasharan S107a60d2017-10-19 02:49:05 -070099/**
100 * megasas_check_same_4gb_region - check if allocation
101 * crosses same 4GB boundary or not
102 * @instance - adapter's soft instance
103 * start_addr - start address of DMA allocation
104 * size - size of allocation in bytes
105 * return - true : allocation does not cross same
106 * 4GB boundary
107 * false: allocation crosses same
108 * 4GB boundary
109 */
110static inline bool megasas_check_same_4gb_region
111 (struct megasas_instance *instance, dma_addr_t start_addr, size_t size)
112{
113 dma_addr_t end_addr;
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +0530114
Shivasharan S107a60d2017-10-19 02:49:05 -0700115 end_addr = start_addr + size;
116
117 if (upper_32_bits(start_addr) != upper_32_bits(end_addr)) {
118 dev_err(&instance->pdev->dev,
119 "Failed to get same 4GB boundary: start_addr: 0x%llx end_addr: 0x%llx\n",
120 (unsigned long long)start_addr,
121 (unsigned long long)end_addr);
122 return false;
123 }
124
125 return true;
126}
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +0530127
adam radford9c915a82010-12-21 13:34:31 -0800128/**
129 * megasas_enable_intr_fusion - Enables interrupts
130 * @regs: MFI register set
131 */
132void
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530133megasas_enable_intr_fusion(struct megasas_instance *instance)
adam radford9c915a82010-12-21 13:34:31 -0800134{
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530135 struct megasas_register_set __iomem *regs;
136 regs = instance->reg_set;
Sumit.Saxena@avagotech.comc2ced172015-01-05 20:06:13 +0530137
138 instance->mask_interrupts = 0;
adam radford6497b242011-10-08 18:14:50 -0700139 /* For Thunderbolt/Invader also clear intr on enable */
140 writel(~0, &regs->outbound_intr_status);
141 readl(&regs->outbound_intr_status);
142
adam radford9c915a82010-12-21 13:34:31 -0800143 writel(~MFI_FUSION_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
144
145 /* Dummy readl to force pci flush */
146 readl(&regs->outbound_intr_mask);
147}
148
149/**
150 * megasas_disable_intr_fusion - Disables interrupt
151 * @regs: MFI register set
152 */
153void
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530154megasas_disable_intr_fusion(struct megasas_instance *instance)
adam radford9c915a82010-12-21 13:34:31 -0800155{
156 u32 mask = 0xFFFFFFFF;
157 u32 status;
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +0530158 struct megasas_register_set __iomem *regs;
159 regs = instance->reg_set;
160 instance->mask_interrupts = 1;
adam radford9c915a82010-12-21 13:34:31 -0800161
162 writel(mask, &regs->outbound_intr_mask);
163 /* Dummy readl to force pci flush */
164 status = readl(&regs->outbound_intr_mask);
165}
166
167int
168megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs)
169{
170 u32 status;
171 /*
172 * Check if it is our interrupt
173 */
174 status = readl(&regs->outbound_intr_status);
175
176 if (status & 1) {
177 writel(status, &regs->outbound_intr_status);
178 readl(&regs->outbound_intr_status);
179 return 1;
180 }
181 if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK))
182 return 0;
183
adam radford9c915a82010-12-21 13:34:31 -0800184 return 1;
185}
186
187/**
188 * megasas_get_cmd_fusion - Get a command from the free pool
189 * @instance: Adapter soft state
190 *
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530191 * Returns a blk_tag indexed mpt frame
adam radford9c915a82010-12-21 13:34:31 -0800192 */
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530193inline struct megasas_cmd_fusion *megasas_get_cmd_fusion(struct megasas_instance
194 *instance, u32 blk_tag)
adam radford9c915a82010-12-21 13:34:31 -0800195{
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530196 struct fusion_context *fusion;
adam radford9c915a82010-12-21 13:34:31 -0800197
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530198 fusion = instance->ctrl_context;
199 return fusion->cmd_list[blk_tag];
adam radford9c915a82010-12-21 13:34:31 -0800200}
201
202/**
203 * megasas_return_cmd_fusion - Return a cmd to free command pool
204 * @instance: Adapter soft state
205 * @cmd: Command packet to be returned to free command pool
206 */
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530207inline void megasas_return_cmd_fusion(struct megasas_instance *instance,
208 struct megasas_cmd_fusion *cmd)
adam radford9c915a82010-12-21 13:34:31 -0800209{
adam radford9c915a82010-12-21 13:34:31 -0800210 cmd->scmd = NULL;
Shivasharan S8bf7c652017-02-10 00:59:03 -0800211 memset(cmd->io_request, 0, MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE);
212 cmd->r1_alt_dev_handle = MR_DEVHANDLE_INVALID;
213 cmd->cmd_completed = false;
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530214}
215
216/**
Christoph Hellwig01d7f03b2015-04-23 16:34:09 +0530217 * megasas_fire_cmd_fusion - Sends command to the FW
Shivasharan S45b8a352017-02-10 00:59:04 -0800218 * @instance: Adapter soft state
Shivasharan S9ff97fa2018-02-14 00:10:52 -0800219 * @req_desc: 64bit Request descriptor
Shivasharan S45b8a352017-02-10 00:59:04 -0800220 *
Shivasharan S9ff97fa2018-02-14 00:10:52 -0800221 * Perform PCI Write.
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530222 */
Shivasharan S45b8a352017-02-10 00:59:04 -0800223
Christoph Hellwig01d7f03b2015-04-23 16:34:09 +0530224static void
225megasas_fire_cmd_fusion(struct megasas_instance *instance,
Shivasharan S45b8a352017-02-10 00:59:04 -0800226 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc)
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530227{
Shivasharan S45b8a352017-02-10 00:59:04 -0800228#if defined(writeq) && defined(CONFIG_64BIT)
Shivasharan S9ff97fa2018-02-14 00:10:52 -0800229 u64 req_data = (((u64)le32_to_cpu(req_desc->u.high) << 32) |
230 le32_to_cpu(req_desc->u.low));
Shivasharan S45b8a352017-02-10 00:59:04 -0800231
Shivasharan S9ff97fa2018-02-14 00:10:52 -0800232 writeq(req_data, &instance->reg_set->inbound_low_queue_port);
Shivasharan S45b8a352017-02-10 00:59:04 -0800233#else
Shivasharan S9ff97fa2018-02-14 00:10:52 -0800234 unsigned long flags;
235 spin_lock_irqsave(&instance->hba_lock, flags);
236 writel(le32_to_cpu(req_desc->u.low),
237 &instance->reg_set->inbound_low_queue_port);
238 writel(le32_to_cpu(req_desc->u.high),
239 &instance->reg_set->inbound_high_queue_port);
240 mmiowb();
241 spin_unlock_irqrestore(&instance->hba_lock, flags);
Christoph Hellwig01d7f03b2015-04-23 16:34:09 +0530242#endif
adam radford9c915a82010-12-21 13:34:31 -0800243}
244
adam radford9c915a82010-12-21 13:34:31 -0800245/**
Sumit Saxena308ec452016-01-28 21:04:30 +0530246 * megasas_fusion_update_can_queue - Do all Adapter Queue depth related calculations here
247 * @instance: Adapter soft state
248 * fw_boot_context: Whether this function called during probe or after OCR
249 *
250 * This function is only for fusion controllers.
251 * Update host can queue, if firmware downgrade max supported firmware commands.
252 * Firmware upgrade case will be skiped because underlying firmware has
253 * more resource than exposed to the OS.
254 *
255 */
256static void
257megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_context)
258{
259 u16 cur_max_fw_cmds = 0;
260 u16 ldio_threshold = 0;
261 struct megasas_register_set __iomem *reg_set;
262
263 reg_set = instance->reg_set;
264
Shivasharan S81b76452018-10-16 23:37:51 -0700265 /* ventura FW does not fill outbound_scratch_pad_2 with queue depth */
Shivasharan Sf369a312017-10-19 02:48:52 -0700266 if (instance->adapter_type < VENTURA_SERIES)
Sasikumar Chandrasekaran9581ebe2017-01-10 18:20:49 -0500267 cur_max_fw_cmds =
Shivasharan S81b76452018-10-16 23:37:51 -0700268 readl(&instance->reg_set->outbound_scratch_pad_2) & 0x00FFFF;
Sumit Saxena308ec452016-01-28 21:04:30 +0530269
270 if (dual_qdepth_disable || !cur_max_fw_cmds)
271 cur_max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF;
272 else
273 ldio_threshold =
274 (instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF) - MEGASAS_FUSION_IOCTL_CMDS;
275
276 dev_info(&instance->pdev->dev,
Colin Ian Kingb5c5d0a2017-11-02 10:18:10 +0000277 "Current firmware supports maximum commands: %d\t LDIO threshold: %d\n",
Shivasharan Se97e6732017-10-19 02:49:03 -0700278 cur_max_fw_cmds, ldio_threshold);
Sumit Saxena308ec452016-01-28 21:04:30 +0530279
280 if (fw_boot_context == OCR_CONTEXT) {
281 cur_max_fw_cmds = cur_max_fw_cmds - 1;
Shivasharan S013aec62017-02-10 00:59:26 -0800282 if (cur_max_fw_cmds < instance->max_fw_cmds) {
Sumit Saxena308ec452016-01-28 21:04:30 +0530283 instance->cur_can_queue =
284 cur_max_fw_cmds - (MEGASAS_FUSION_INTERNAL_CMDS +
285 MEGASAS_FUSION_IOCTL_CMDS);
286 instance->host->can_queue = instance->cur_can_queue;
287 instance->ldio_threshold = ldio_threshold;
288 }
289 } else {
290 instance->max_fw_cmds = cur_max_fw_cmds;
291 instance->ldio_threshold = ldio_threshold;
292
Sumit Saxenac3e385a2016-04-15 00:23:30 -0700293 if (reset_devices)
294 instance->max_fw_cmds = min(instance->max_fw_cmds,
295 (u16)MEGASAS_KDUMP_QUEUE_DEPTH);
Sumit Saxena308ec452016-01-28 21:04:30 +0530296 /*
297 * Reduce the max supported cmds by 1. This is to ensure that the
298 * reply_q_sz (1 more than the max cmd that driver may send)
299 * does not exceed max cmds that the FW can support
300 */
301 instance->max_fw_cmds = instance->max_fw_cmds-1;
Sumit Saxena308ec452016-01-28 21:04:30 +0530302 }
303}
304/**
adam radford9c915a82010-12-21 13:34:31 -0800305 * megasas_free_cmds_fusion - Free all the cmds in the free cmd pool
306 * @instance: Adapter soft state
307 */
308void
309megasas_free_cmds_fusion(struct megasas_instance *instance)
310{
311 int i;
312 struct fusion_context *fusion = instance->ctrl_context;
Sumit Saxena179ac142016-01-28 21:04:28 +0530313 struct megasas_cmd_fusion *cmd;
adam radford9c915a82010-12-21 13:34:31 -0800314
Shivasharan S107a60d2017-10-19 02:49:05 -0700315 if (fusion->sense)
316 dma_pool_free(fusion->sense_dma_pool, fusion->sense,
317 fusion->sense_phys_addr);
318
319 /* SG */
320 if (fusion->cmd_list) {
321 for (i = 0; i < instance->max_mpt_cmds; i++) {
322 cmd = fusion->cmd_list[i];
323 if (cmd) {
324 if (cmd->sg_frame)
325 dma_pool_free(fusion->sg_dma_pool,
326 cmd->sg_frame,
327 cmd->sg_frame_phys_addr);
328 }
329 kfree(cmd);
Sumit Saxena179ac142016-01-28 21:04:28 +0530330 }
Shivasharan S107a60d2017-10-19 02:49:05 -0700331 kfree(fusion->cmd_list);
Sumit Saxena179ac142016-01-28 21:04:28 +0530332 }
333
334 if (fusion->sg_dma_pool) {
Romain Perierfc69d862017-07-06 10:13:06 +0200335 dma_pool_destroy(fusion->sg_dma_pool);
Sumit Saxena179ac142016-01-28 21:04:28 +0530336 fusion->sg_dma_pool = NULL;
337 }
338 if (fusion->sense_dma_pool) {
Romain Perierfc69d862017-07-06 10:13:06 +0200339 dma_pool_destroy(fusion->sense_dma_pool);
Sumit Saxena179ac142016-01-28 21:04:28 +0530340 fusion->sense_dma_pool = NULL;
341 }
adam radford9c915a82010-12-21 13:34:31 -0800342
343
Sumit Saxena179ac142016-01-28 21:04:28 +0530344 /* Reply Frame, Desc*/
345 if (instance->is_rdpq)
346 megasas_free_rdpq_fusion(instance);
347 else
348 megasas_free_reply_fusion(instance);
adam radford9c915a82010-12-21 13:34:31 -0800349
Sumit Saxena179ac142016-01-28 21:04:28 +0530350 /* Request Frame, Desc*/
adam radford9c915a82010-12-21 13:34:31 -0800351 if (fusion->req_frames_desc)
Sumit Saxena179ac142016-01-28 21:04:28 +0530352 dma_free_coherent(&instance->pdev->dev,
353 fusion->request_alloc_sz, fusion->req_frames_desc,
354 fusion->req_frames_desc_phys);
355 if (fusion->io_request_frames)
Romain Perierfc69d862017-07-06 10:13:06 +0200356 dma_pool_free(fusion->io_request_frames_pool,
Sumit Saxena179ac142016-01-28 21:04:28 +0530357 fusion->io_request_frames,
358 fusion->io_request_frames_phys);
359 if (fusion->io_request_frames_pool) {
Romain Perierfc69d862017-07-06 10:13:06 +0200360 dma_pool_destroy(fusion->io_request_frames_pool);
Sumit Saxena179ac142016-01-28 21:04:28 +0530361 fusion->io_request_frames_pool = NULL;
adam radford9c915a82010-12-21 13:34:31 -0800362 }
adam radford9c915a82010-12-21 13:34:31 -0800363}
364
365/**
Sumit Saxena179ac142016-01-28 21:04:28 +0530366 * megasas_create_sg_sense_fusion - Creates DMA pool for cmd frames
adam radford9c915a82010-12-21 13:34:31 -0800367 * @instance: Adapter soft state
368 *
369 */
Sumit Saxena179ac142016-01-28 21:04:28 +0530370static int megasas_create_sg_sense_fusion(struct megasas_instance *instance)
adam radford9c915a82010-12-21 13:34:31 -0800371{
372 int i;
Shivasharan S50b7f5a2017-02-10 00:59:25 -0800373 u16 max_cmd;
adam radford9c915a82010-12-21 13:34:31 -0800374 struct fusion_context *fusion;
375 struct megasas_cmd_fusion *cmd;
Shivasharan S107a60d2017-10-19 02:49:05 -0700376 int sense_sz;
377 u32 offset;
adam radford9c915a82010-12-21 13:34:31 -0800378
379 fusion = instance->ctrl_context;
380 max_cmd = instance->max_fw_cmds;
Shivasharan S107a60d2017-10-19 02:49:05 -0700381 sense_sz = instance->max_mpt_cmds * SCSI_SENSE_BUFFERSIZE;
adam radford9c915a82010-12-21 13:34:31 -0800382
Sumit Saxena179ac142016-01-28 21:04:28 +0530383 fusion->sg_dma_pool =
Romain Perierfc69d862017-07-06 10:13:06 +0200384 dma_pool_create("mr_sg", &instance->pdev->dev,
Shivasharan S15dd0382017-02-10 00:59:10 -0800385 instance->max_chain_frame_sz,
386 MR_DEFAULT_NVME_PAGE_SIZE, 0);
Sumit Saxena179ac142016-01-28 21:04:28 +0530387 /* SCSI_SENSE_BUFFERSIZE = 96 bytes */
388 fusion->sense_dma_pool =
Romain Perierfc69d862017-07-06 10:13:06 +0200389 dma_pool_create("mr_sense", &instance->pdev->dev,
Shivasharan S107a60d2017-10-19 02:49:05 -0700390 sense_sz, 64, 0);
adam radford9c915a82010-12-21 13:34:31 -0800391
Sumit Saxena179ac142016-01-28 21:04:28 +0530392 if (!fusion->sense_dma_pool || !fusion->sg_dma_pool) {
393 dev_err(&instance->pdev->dev,
394 "Failed from %s %d\n", __func__, __LINE__);
adam radford9c915a82010-12-21 13:34:31 -0800395 return -ENOMEM;
396 }
397
Shivasharan S107a60d2017-10-19 02:49:05 -0700398 fusion->sense = dma_pool_alloc(fusion->sense_dma_pool,
399 GFP_KERNEL, &fusion->sense_phys_addr);
400 if (!fusion->sense) {
401 dev_err(&instance->pdev->dev,
402 "failed from %s %d\n", __func__, __LINE__);
403 return -ENOMEM;
404 }
405
406 /* sense buffer, request frame and reply desc pool requires to be in
407 * same 4 gb region. Below function will check this.
408 * In case of failure, new pci pool will be created with updated
409 * alignment.
410 * Older allocation and pool will be destroyed.
411 * Alignment will be used such a way that next allocation if success,
412 * will always meet same 4gb region requirement.
413 * Actual requirement is not alignment, but we need start and end of
414 * DMA address must have same upper 32 bit address.
415 */
416
417 if (!megasas_check_same_4gb_region(instance, fusion->sense_phys_addr,
418 sense_sz)) {
419 dma_pool_free(fusion->sense_dma_pool, fusion->sense,
420 fusion->sense_phys_addr);
421 fusion->sense = NULL;
422 dma_pool_destroy(fusion->sense_dma_pool);
423
424 fusion->sense_dma_pool =
425 dma_pool_create("mr_sense_align", &instance->pdev->dev,
426 sense_sz, roundup_pow_of_two(sense_sz),
427 0);
428 if (!fusion->sense_dma_pool) {
429 dev_err(&instance->pdev->dev,
430 "Failed from %s %d\n", __func__, __LINE__);
431 return -ENOMEM;
432 }
433 fusion->sense = dma_pool_alloc(fusion->sense_dma_pool,
434 GFP_KERNEL,
435 &fusion->sense_phys_addr);
436 if (!fusion->sense) {
437 dev_err(&instance->pdev->dev,
438 "failed from %s %d\n", __func__, __LINE__);
439 return -ENOMEM;
440 }
441 }
442
adam radford9c915a82010-12-21 13:34:31 -0800443 /*
444 * Allocate and attach a frame to each of the commands in cmd_list
445 */
446 for (i = 0; i < max_cmd; i++) {
adam radford9c915a82010-12-21 13:34:31 -0800447 cmd = fusion->cmd_list[i];
Romain Perierfc69d862017-07-06 10:13:06 +0200448 cmd->sg_frame = dma_pool_alloc(fusion->sg_dma_pool,
Sumit Saxena179ac142016-01-28 21:04:28 +0530449 GFP_KERNEL, &cmd->sg_frame_phys_addr);
adam radford9c915a82010-12-21 13:34:31 -0800450
Shivasharan S107a60d2017-10-19 02:49:05 -0700451 offset = SCSI_SENSE_BUFFERSIZE * i;
452 cmd->sense = (u8 *)fusion->sense + offset;
453 cmd->sense_phys_addr = fusion->sense_phys_addr + offset;
454
455 if (!cmd->sg_frame) {
Sumit Saxena179ac142016-01-28 21:04:28 +0530456 dev_err(&instance->pdev->dev,
457 "Failed from %s %d\n", __func__, __LINE__);
adam radford9c915a82010-12-21 13:34:31 -0800458 return -ENOMEM;
459 }
460 }
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -0500461
462 /* create sense buffer for the raid 1/10 fp */
463 for (i = max_cmd; i < instance->max_mpt_cmds; i++) {
464 cmd = fusion->cmd_list[i];
Shivasharan S107a60d2017-10-19 02:49:05 -0700465 offset = SCSI_SENSE_BUFFERSIZE * i;
466 cmd->sense = (u8 *)fusion->sense + offset;
467 cmd->sense_phys_addr = fusion->sense_phys_addr + offset;
468
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -0500469 }
470
adam radford9c915a82010-12-21 13:34:31 -0800471 return 0;
472}
473
Sumit Saxena179ac142016-01-28 21:04:28 +0530474int
475megasas_alloc_cmdlist_fusion(struct megasas_instance *instance)
476{
Shu Wang70c54e22017-07-21 18:54:09 +0800477 u32 max_mpt_cmd, i, j;
Sumit Saxena179ac142016-01-28 21:04:28 +0530478 struct fusion_context *fusion;
479
480 fusion = instance->ctrl_context;
481
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -0500482 max_mpt_cmd = instance->max_mpt_cmds;
Sumit Saxena179ac142016-01-28 21:04:28 +0530483
484 /*
485 * fusion->cmd_list is an array of struct megasas_cmd_fusion pointers.
486 * Allocate the dynamic array first and then allocate individual
487 * commands.
488 */
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -0500489 fusion->cmd_list =
Kees Cook6396bb22018-06-12 14:03:40 -0700490 kcalloc(max_mpt_cmd, sizeof(struct megasas_cmd_fusion *),
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -0500491 GFP_KERNEL);
Sumit Saxena179ac142016-01-28 21:04:28 +0530492 if (!fusion->cmd_list) {
493 dev_err(&instance->pdev->dev,
494 "Failed from %s %d\n", __func__, __LINE__);
495 return -ENOMEM;
496 }
497
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -0500498 for (i = 0; i < max_mpt_cmd; i++) {
Sumit Saxena179ac142016-01-28 21:04:28 +0530499 fusion->cmd_list[i] = kzalloc(sizeof(struct megasas_cmd_fusion),
500 GFP_KERNEL);
501 if (!fusion->cmd_list[i]) {
Shu Wang70c54e22017-07-21 18:54:09 +0800502 for (j = 0; j < i; j++)
503 kfree(fusion->cmd_list[j]);
504 kfree(fusion->cmd_list);
Sumit Saxena179ac142016-01-28 21:04:28 +0530505 dev_err(&instance->pdev->dev,
506 "Failed from %s %d\n", __func__, __LINE__);
507 return -ENOMEM;
508 }
509 }
Shu Wang70c54e22017-07-21 18:54:09 +0800510
Sumit Saxena179ac142016-01-28 21:04:28 +0530511 return 0;
512}
513int
514megasas_alloc_request_fusion(struct megasas_instance *instance)
515{
516 struct fusion_context *fusion;
517
518 fusion = instance->ctrl_context;
519
Shivasharan Se97e6732017-10-19 02:49:03 -0700520retry_alloc:
Sumit Saxena179ac142016-01-28 21:04:28 +0530521 fusion->io_request_frames_pool =
Romain Perierfc69d862017-07-06 10:13:06 +0200522 dma_pool_create("mr_ioreq", &instance->pdev->dev,
Sumit Saxena179ac142016-01-28 21:04:28 +0530523 fusion->io_frames_alloc_sz, 16, 0);
524
525 if (!fusion->io_request_frames_pool) {
526 dev_err(&instance->pdev->dev,
527 "Failed from %s %d\n", __func__, __LINE__);
528 return -ENOMEM;
529 }
530
531 fusion->io_request_frames =
Romain Perierfc69d862017-07-06 10:13:06 +0200532 dma_pool_alloc(fusion->io_request_frames_pool,
Sumit Saxena179ac142016-01-28 21:04:28 +0530533 GFP_KERNEL, &fusion->io_request_frames_phys);
534 if (!fusion->io_request_frames) {
Shivasharan Se97e6732017-10-19 02:49:03 -0700535 if (instance->max_fw_cmds >= (MEGASAS_REDUCE_QD_COUNT * 2)) {
536 instance->max_fw_cmds -= MEGASAS_REDUCE_QD_COUNT;
537 dma_pool_destroy(fusion->io_request_frames_pool);
538 megasas_configure_queue_sizes(instance);
539 goto retry_alloc;
540 } else {
541 dev_err(&instance->pdev->dev,
542 "Failed from %s %d\n", __func__, __LINE__);
543 return -ENOMEM;
544 }
545 }
546
Shivasharan S107a60d2017-10-19 02:49:05 -0700547 if (!megasas_check_same_4gb_region(instance,
548 fusion->io_request_frames_phys,
549 fusion->io_frames_alloc_sz)) {
550 dma_pool_free(fusion->io_request_frames_pool,
551 fusion->io_request_frames,
552 fusion->io_request_frames_phys);
553 fusion->io_request_frames = NULL;
554 dma_pool_destroy(fusion->io_request_frames_pool);
555
556 fusion->io_request_frames_pool =
557 dma_pool_create("mr_ioreq_align",
558 &instance->pdev->dev,
559 fusion->io_frames_alloc_sz,
560 roundup_pow_of_two(fusion->io_frames_alloc_sz),
561 0);
562
563 if (!fusion->io_request_frames_pool) {
564 dev_err(&instance->pdev->dev,
565 "Failed from %s %d\n", __func__, __LINE__);
566 return -ENOMEM;
567 }
568
569 fusion->io_request_frames =
570 dma_pool_alloc(fusion->io_request_frames_pool,
571 GFP_KERNEL,
572 &fusion->io_request_frames_phys);
573
574 if (!fusion->io_request_frames) {
575 dev_err(&instance->pdev->dev,
576 "Failed from %s %d\n", __func__, __LINE__);
577 return -ENOMEM;
578 }
579 }
580
Shivasharan Se97e6732017-10-19 02:49:03 -0700581 fusion->req_frames_desc =
582 dma_alloc_coherent(&instance->pdev->dev,
583 fusion->request_alloc_sz,
584 &fusion->req_frames_desc_phys, GFP_KERNEL);
585 if (!fusion->req_frames_desc) {
Sumit Saxena179ac142016-01-28 21:04:28 +0530586 dev_err(&instance->pdev->dev,
587 "Failed from %s %d\n", __func__, __LINE__);
588 return -ENOMEM;
589 }
Shivasharan Se97e6732017-10-19 02:49:03 -0700590
Sumit Saxena179ac142016-01-28 21:04:28 +0530591 return 0;
592}
593
594int
595megasas_alloc_reply_fusion(struct megasas_instance *instance)
596{
597 int i, count;
598 struct fusion_context *fusion;
599 union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
600 fusion = instance->ctrl_context;
601
602 count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
603 fusion->reply_frames_desc_pool =
Romain Perierfc69d862017-07-06 10:13:06 +0200604 dma_pool_create("mr_reply", &instance->pdev->dev,
Sumit Saxena179ac142016-01-28 21:04:28 +0530605 fusion->reply_alloc_sz * count, 16, 0);
606
607 if (!fusion->reply_frames_desc_pool) {
608 dev_err(&instance->pdev->dev,
609 "Failed from %s %d\n", __func__, __LINE__);
610 return -ENOMEM;
611 }
612
613 fusion->reply_frames_desc[0] =
Romain Perierfc69d862017-07-06 10:13:06 +0200614 dma_pool_alloc(fusion->reply_frames_desc_pool,
Sumit Saxena179ac142016-01-28 21:04:28 +0530615 GFP_KERNEL, &fusion->reply_frames_desc_phys[0]);
616 if (!fusion->reply_frames_desc[0]) {
617 dev_err(&instance->pdev->dev,
618 "Failed from %s %d\n", __func__, __LINE__);
619 return -ENOMEM;
620 }
Shivasharan S107a60d2017-10-19 02:49:05 -0700621
622 if (!megasas_check_same_4gb_region(instance,
623 fusion->reply_frames_desc_phys[0],
624 (fusion->reply_alloc_sz * count))) {
625 dma_pool_free(fusion->reply_frames_desc_pool,
626 fusion->reply_frames_desc[0],
627 fusion->reply_frames_desc_phys[0]);
628 fusion->reply_frames_desc[0] = NULL;
629 dma_pool_destroy(fusion->reply_frames_desc_pool);
630
631 fusion->reply_frames_desc_pool =
632 dma_pool_create("mr_reply_align",
633 &instance->pdev->dev,
634 fusion->reply_alloc_sz * count,
635 roundup_pow_of_two(fusion->reply_alloc_sz * count),
636 0);
637
638 if (!fusion->reply_frames_desc_pool) {
639 dev_err(&instance->pdev->dev,
640 "Failed from %s %d\n", __func__, __LINE__);
641 return -ENOMEM;
642 }
643
644 fusion->reply_frames_desc[0] =
645 dma_pool_alloc(fusion->reply_frames_desc_pool,
646 GFP_KERNEL,
647 &fusion->reply_frames_desc_phys[0]);
648
649 if (!fusion->reply_frames_desc[0]) {
650 dev_err(&instance->pdev->dev,
651 "Failed from %s %d\n", __func__, __LINE__);
652 return -ENOMEM;
653 }
654 }
655
Sumit Saxena179ac142016-01-28 21:04:28 +0530656 reply_desc = fusion->reply_frames_desc[0];
657 for (i = 0; i < fusion->reply_q_depth * count; i++, reply_desc++)
658 reply_desc->Words = cpu_to_le64(ULLONG_MAX);
659
660 /* This is not a rdpq mode, but driver still populate
661 * reply_frame_desc array to use same msix index in ISR path.
662 */
663 for (i = 0; i < (count - 1); i++)
664 fusion->reply_frames_desc[i + 1] =
665 fusion->reply_frames_desc[i] +
666 (fusion->reply_alloc_sz)/sizeof(union MPI2_REPLY_DESCRIPTORS_UNION);
667
668 return 0;
669}
670
671int
672megasas_alloc_rdpq_fusion(struct megasas_instance *instance)
673{
Shivasharan S107a60d2017-10-19 02:49:05 -0700674 int i, j, k, msix_count;
Sumit Saxena179ac142016-01-28 21:04:28 +0530675 struct fusion_context *fusion;
676 union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
Shivasharan S107a60d2017-10-19 02:49:05 -0700677 union MPI2_REPLY_DESCRIPTORS_UNION *rdpq_chunk_virt[RDPQ_MAX_CHUNK_COUNT];
678 dma_addr_t rdpq_chunk_phys[RDPQ_MAX_CHUNK_COUNT];
679 u8 dma_alloc_count, abs_index;
680 u32 chunk_size, array_size, offset;
Sumit Saxena179ac142016-01-28 21:04:28 +0530681
682 fusion = instance->ctrl_context;
Shivasharan S107a60d2017-10-19 02:49:05 -0700683 chunk_size = fusion->reply_alloc_sz * RDPQ_MAX_INDEX_IN_ONE_CHUNK;
684 array_size = sizeof(struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) *
685 MAX_MSIX_QUEUES_FUSION;
Sumit Saxena179ac142016-01-28 21:04:28 +0530686
Christoph Hellwig60ee6522018-10-10 19:31:25 +0200687 fusion->rdpq_virt = dma_zalloc_coherent(&instance->pdev->dev,
688 array_size, &fusion->rdpq_phys, GFP_KERNEL);
Sumit Saxena179ac142016-01-28 21:04:28 +0530689 if (!fusion->rdpq_virt) {
690 dev_err(&instance->pdev->dev,
691 "Failed from %s %d\n", __func__, __LINE__);
692 return -ENOMEM;
693 }
694
Shivasharan S107a60d2017-10-19 02:49:05 -0700695 msix_count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
696
Romain Perierfc69d862017-07-06 10:13:06 +0200697 fusion->reply_frames_desc_pool = dma_pool_create("mr_rdpq",
698 &instance->pdev->dev,
Shivasharan S107a60d2017-10-19 02:49:05 -0700699 chunk_size, 16, 0);
700 fusion->reply_frames_desc_pool_align =
701 dma_pool_create("mr_rdpq_align",
702 &instance->pdev->dev,
703 chunk_size,
704 roundup_pow_of_two(chunk_size),
705 0);
Sumit Saxena179ac142016-01-28 21:04:28 +0530706
Shivasharan S107a60d2017-10-19 02:49:05 -0700707 if (!fusion->reply_frames_desc_pool ||
708 !fusion->reply_frames_desc_pool_align) {
Sumit Saxena179ac142016-01-28 21:04:28 +0530709 dev_err(&instance->pdev->dev,
710 "Failed from %s %d\n", __func__, __LINE__);
711 return -ENOMEM;
712 }
713
Shivasharan S107a60d2017-10-19 02:49:05 -0700714/*
715 * For INVADER_SERIES each set of 8 reply queues(0-7, 8-15, ..) and
716 * VENTURA_SERIES each set of 16 reply queues(0-15, 16-31, ..) should be
717 * within 4GB boundary and also reply queues in a set must have same
718 * upper 32-bits in their memory address. so here driver is allocating the
719 * DMA'able memory for reply queues according. Driver uses limitation of
720 * VENTURA_SERIES to manage INVADER_SERIES as well.
721 */
722 dma_alloc_count = DIV_ROUND_UP(msix_count, RDPQ_MAX_INDEX_IN_ONE_CHUNK);
723
724 for (i = 0; i < dma_alloc_count; i++) {
725 rdpq_chunk_virt[i] =
726 dma_pool_alloc(fusion->reply_frames_desc_pool,
727 GFP_KERNEL, &rdpq_chunk_phys[i]);
728 if (!rdpq_chunk_virt[i]) {
Sumit Saxena179ac142016-01-28 21:04:28 +0530729 dev_err(&instance->pdev->dev,
730 "Failed from %s %d\n", __func__, __LINE__);
731 return -ENOMEM;
732 }
Shivasharan S107a60d2017-10-19 02:49:05 -0700733 /* reply desc pool requires to be in same 4 gb region.
734 * Below function will check this.
735 * In case of failure, new pci pool will be created with updated
736 * alignment.
737 * For RDPQ buffers, driver always allocate two separate pci pool.
738 * Alignment will be used such a way that next allocation if
739 * success, will always meet same 4gb region requirement.
740 * rdpq_tracker keep track of each buffer's physical,
741 * virtual address and pci pool descriptor. It will help driver
742 * while freeing the resources.
743 *
744 */
745 if (!megasas_check_same_4gb_region(instance, rdpq_chunk_phys[i],
746 chunk_size)) {
747 dma_pool_free(fusion->reply_frames_desc_pool,
748 rdpq_chunk_virt[i],
749 rdpq_chunk_phys[i]);
Sumit Saxena179ac142016-01-28 21:04:28 +0530750
Shivasharan S107a60d2017-10-19 02:49:05 -0700751 rdpq_chunk_virt[i] =
752 dma_pool_alloc(fusion->reply_frames_desc_pool_align,
753 GFP_KERNEL, &rdpq_chunk_phys[i]);
754 if (!rdpq_chunk_virt[i]) {
755 dev_err(&instance->pdev->dev,
756 "Failed from %s %d\n",
757 __func__, __LINE__);
758 return -ENOMEM;
759 }
760 fusion->rdpq_tracker[i].dma_pool_ptr =
761 fusion->reply_frames_desc_pool_align;
762 } else {
763 fusion->rdpq_tracker[i].dma_pool_ptr =
764 fusion->reply_frames_desc_pool;
765 }
Sumit Saxena179ac142016-01-28 21:04:28 +0530766
Shivasharan S107a60d2017-10-19 02:49:05 -0700767 fusion->rdpq_tracker[i].pool_entry_phys = rdpq_chunk_phys[i];
768 fusion->rdpq_tracker[i].pool_entry_virt = rdpq_chunk_virt[i];
Sumit Saxena179ac142016-01-28 21:04:28 +0530769 }
Shivasharan S107a60d2017-10-19 02:49:05 -0700770
771 for (k = 0; k < dma_alloc_count; k++) {
772 for (i = 0; i < RDPQ_MAX_INDEX_IN_ONE_CHUNK; i++) {
773 abs_index = (k * RDPQ_MAX_INDEX_IN_ONE_CHUNK) + i;
774
775 if (abs_index == msix_count)
776 break;
777 offset = fusion->reply_alloc_sz * i;
778 fusion->rdpq_virt[abs_index].RDPQBaseAddress =
779 cpu_to_le64(rdpq_chunk_phys[k] + offset);
780 fusion->reply_frames_desc_phys[abs_index] =
781 rdpq_chunk_phys[k] + offset;
782 fusion->reply_frames_desc[abs_index] =
783 (union MPI2_REPLY_DESCRIPTORS_UNION *)((u8 *)rdpq_chunk_virt[k] + offset);
784
785 reply_desc = fusion->reply_frames_desc[abs_index];
786 for (j = 0; j < fusion->reply_q_depth; j++, reply_desc++)
787 reply_desc->Words = ULLONG_MAX;
788 }
789 }
790
Sumit Saxena179ac142016-01-28 21:04:28 +0530791 return 0;
792}
793
794static void
795megasas_free_rdpq_fusion(struct megasas_instance *instance) {
796
797 int i;
798 struct fusion_context *fusion;
799
800 fusion = instance->ctrl_context;
801
Shivasharan S107a60d2017-10-19 02:49:05 -0700802 for (i = 0; i < RDPQ_MAX_CHUNK_COUNT; i++) {
803 if (fusion->rdpq_tracker[i].pool_entry_virt)
804 dma_pool_free(fusion->rdpq_tracker[i].dma_pool_ptr,
805 fusion->rdpq_tracker[i].pool_entry_virt,
806 fusion->rdpq_tracker[i].pool_entry_phys);
807
Sumit Saxena179ac142016-01-28 21:04:28 +0530808 }
809
Thomas Meyer19c05072018-12-02 21:52:11 +0100810 dma_pool_destroy(fusion->reply_frames_desc_pool);
811 dma_pool_destroy(fusion->reply_frames_desc_pool_align);
Sumit Saxena179ac142016-01-28 21:04:28 +0530812
813 if (fusion->rdpq_virt)
Christoph Hellwig60ee6522018-10-10 19:31:25 +0200814 dma_free_coherent(&instance->pdev->dev,
Sumit Saxena179ac142016-01-28 21:04:28 +0530815 sizeof(struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) * MAX_MSIX_QUEUES_FUSION,
816 fusion->rdpq_virt, fusion->rdpq_phys);
817}
818
819static void
820megasas_free_reply_fusion(struct megasas_instance *instance) {
821
822 struct fusion_context *fusion;
823
824 fusion = instance->ctrl_context;
825
826 if (fusion->reply_frames_desc[0])
Romain Perierfc69d862017-07-06 10:13:06 +0200827 dma_pool_free(fusion->reply_frames_desc_pool,
Sumit Saxena179ac142016-01-28 21:04:28 +0530828 fusion->reply_frames_desc[0],
829 fusion->reply_frames_desc_phys[0]);
830
Thomas Meyer19c05072018-12-02 21:52:11 +0100831 dma_pool_destroy(fusion->reply_frames_desc_pool);
Sumit Saxena179ac142016-01-28 21:04:28 +0530832
833}
834
835
adam radford9c915a82010-12-21 13:34:31 -0800836/**
837 * megasas_alloc_cmds_fusion - Allocates the command packets
838 * @instance: Adapter soft state
839 *
840 *
841 * Each frame has a 32-bit field called context. This context is used to get
842 * back the megasas_cmd_fusion from the frame when a frame gets completed
843 * In this driver, the 32 bit values are the indices into an array cmd_list.
844 * This array is used only to look up the megasas_cmd_fusion given the context.
845 * The free commands themselves are maintained in a linked list called cmd_pool.
846 *
847 * cmds are formed in the io_request and sg_frame members of the
848 * megasas_cmd_fusion. The context field is used to get a request descriptor
849 * and is used as SMID of the cmd.
850 * SMID value range is from 1 to max_fw_cmds.
851 */
852int
853megasas_alloc_cmds_fusion(struct megasas_instance *instance)
854{
Sumit Saxena179ac142016-01-28 21:04:28 +0530855 int i;
adam radford9c915a82010-12-21 13:34:31 -0800856 struct fusion_context *fusion;
857 struct megasas_cmd_fusion *cmd;
adam radford9c915a82010-12-21 13:34:31 -0800858 u32 offset;
859 dma_addr_t io_req_base_phys;
860 u8 *io_req_base;
861
Sumit Saxena179ac142016-01-28 21:04:28 +0530862
adam radford9c915a82010-12-21 13:34:31 -0800863 fusion = instance->ctrl_context;
864
Sumit Saxena179ac142016-01-28 21:04:28 +0530865 if (megasas_alloc_request_fusion(instance))
866 goto fail_exit;
adam radford9c915a82010-12-21 13:34:31 -0800867
Sumit Saxena179ac142016-01-28 21:04:28 +0530868 if (instance->is_rdpq) {
869 if (megasas_alloc_rdpq_fusion(instance))
870 goto fail_exit;
871 } else
872 if (megasas_alloc_reply_fusion(instance))
873 goto fail_exit;
adam radford9c915a82010-12-21 13:34:31 -0800874
Shivasharan Se97e6732017-10-19 02:49:03 -0700875 if (megasas_alloc_cmdlist_fusion(instance))
876 goto fail_exit;
877
878 dev_info(&instance->pdev->dev, "Configured max firmware commands: %d\n",
879 instance->max_fw_cmds);
adam radford9c915a82010-12-21 13:34:31 -0800880
Sumit Saxena179ac142016-01-28 21:04:28 +0530881 /* The first 256 bytes (SMID 0) is not used. Don't add to the cmd list */
882 io_req_base = fusion->io_request_frames + MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
883 io_req_base_phys = fusion->io_request_frames_phys + MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
adam radford9c915a82010-12-21 13:34:31 -0800884
885 /*
886 * Add all the commands to command pool (fusion->cmd_pool)
887 */
888
889 /* SMID 0 is reserved. Set SMID/index from 1 */
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -0500890 for (i = 0; i < instance->max_mpt_cmds; i++) {
adam radford9c915a82010-12-21 13:34:31 -0800891 cmd = fusion->cmd_list[i];
892 offset = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * i;
893 memset(cmd, 0, sizeof(struct megasas_cmd_fusion));
894 cmd->index = i + 1;
895 cmd->scmd = NULL;
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -0500896 cmd->sync_cmd_idx =
897 (i >= instance->max_scsi_cmds && i < instance->max_fw_cmds) ?
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +0530898 (i - instance->max_scsi_cmds) :
899 (u32)ULONG_MAX; /* Set to Invalid */
adam radford9c915a82010-12-21 13:34:31 -0800900 cmd->instance = instance;
901 cmd->io_request =
902 (struct MPI2_RAID_SCSI_IO_REQUEST *)
903 (io_req_base + offset);
904 memset(cmd->io_request, 0,
905 sizeof(struct MPI2_RAID_SCSI_IO_REQUEST));
906 cmd->io_request_phys_addr = io_req_base_phys + offset;
Shivasharan S8bf7c652017-02-10 00:59:03 -0800907 cmd->r1_alt_dev_handle = MR_DEVHANDLE_INVALID;
adam radford9c915a82010-12-21 13:34:31 -0800908 }
909
Sumit Saxena179ac142016-01-28 21:04:28 +0530910 if (megasas_create_sg_sense_fusion(instance))
911 goto fail_exit;
adam radford9c915a82010-12-21 13:34:31 -0800912
913 return 0;
914
Sumit Saxena179ac142016-01-28 21:04:28 +0530915fail_exit:
916 megasas_free_cmds_fusion(instance);
adam radford9c915a82010-12-21 13:34:31 -0800917 return -ENOMEM;
918}
919
920/**
921 * wait_and_poll - Issues a polling command
922 * @instance: Adapter soft state
923 * @cmd: Command packet to be issued
924 *
925 * For polling, MFI requires the cmd_status to be set to 0xFF before posting.
926 */
927int
adam radford229fe472014-03-10 02:51:56 -0700928wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd,
929 int seconds)
adam radford9c915a82010-12-21 13:34:31 -0800930{
931 int i;
932 struct megasas_header *frame_hdr = &cmd->frame->hdr;
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530933 struct fusion_context *fusion;
adam radford9c915a82010-12-21 13:34:31 -0800934
adam radford229fe472014-03-10 02:51:56 -0700935 u32 msecs = seconds * 1000;
adam radford9c915a82010-12-21 13:34:31 -0800936
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +0530937 fusion = instance->ctrl_context;
adam radford9c915a82010-12-21 13:34:31 -0800938 /*
939 * Wait for cmd_status to change
940 */
941 for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i += 20) {
942 rmb();
943 msleep(20);
944 }
945
Sumit Saxena6d40afb2016-01-28 21:04:23 +0530946 if (frame_hdr->cmd_status == MFI_STAT_INVALID_STATUS)
947 return DCMD_TIMEOUT;
948 else if (frame_hdr->cmd_status == MFI_STAT_OK)
949 return DCMD_SUCCESS;
950 else
951 return DCMD_FAILED;
adam radford9c915a82010-12-21 13:34:31 -0800952}
953
954/**
955 * megasas_ioc_init_fusion - Initializes the FW
956 * @instance: Adapter soft state
957 *
958 * Issues the IOC Init cmd
959 */
960int
961megasas_ioc_init_fusion(struct megasas_instance *instance)
962{
963 struct megasas_init_frame *init_frame;
Sumit Saxena179ac142016-01-28 21:04:28 +0530964 struct MPI2_IOC_INIT_REQUEST *IOCInitMessage = NULL;
adam radford9c915a82010-12-21 13:34:31 -0800965 dma_addr_t ioc_init_handle;
adam radford9c915a82010-12-21 13:34:31 -0800966 struct megasas_cmd *cmd;
Sumit Saxena179ac142016-01-28 21:04:28 +0530967 u8 ret, cur_rdpq_mode;
adam radford9c915a82010-12-21 13:34:31 -0800968 struct fusion_context *fusion;
adam radfordc77a9bd2014-03-10 02:51:36 -0700969 union MEGASAS_REQUEST_DESCRIPTOR_UNION req_desc;
adam radford9c915a82010-12-21 13:34:31 -0800970 int i;
971 struct megasas_header *frame_hdr;
Sumit.Saxena@avagotech.com5765c5b2015-04-23 16:32:09 +0530972 const char *sys_info;
sumit.saxena@avagotech.com4dbbe3c2015-08-31 17:23:21 +0530973 MFI_CAPABILITIES *drv_ops;
Shivasharan S81b76452018-10-16 23:37:51 -0700974 u32 scratch_pad_1;
Arnd Bergmannb45093d2018-01-17 15:48:51 +0100975 ktime_t time;
Shivasharan S107a60d2017-10-19 02:49:05 -0700976 bool cur_fw_64bit_dma_capable;
adam radford9c915a82010-12-21 13:34:31 -0800977
978 fusion = instance->ctrl_context;
979
Shivasharan S9b3d0282017-10-19 02:48:56 -0700980 ioc_init_handle = fusion->ioc_init_request_phys;
981 IOCInitMessage = fusion->ioc_init_request;
adam radford9c915a82010-12-21 13:34:31 -0800982
Shivasharan Sb9637d12017-10-19 02:49:01 -0700983 cmd = fusion->ioc_init_cmd;
adam radford9c915a82010-12-21 13:34:31 -0800984
Shivasharan S81b76452018-10-16 23:37:51 -0700985 scratch_pad_1 = readl
986 (&instance->reg_set->outbound_scratch_pad_1);
Sumit Saxena179ac142016-01-28 21:04:28 +0530987
Shivasharan S81b76452018-10-16 23:37:51 -0700988 cur_rdpq_mode = (scratch_pad_1 & MR_RDPQ_MODE_OFFSET) ? 1 : 0;
Sumit Saxena179ac142016-01-28 21:04:28 +0530989
Shivasharan S107a60d2017-10-19 02:49:05 -0700990 if (instance->adapter_type == INVADER_SERIES) {
991 cur_fw_64bit_dma_capable =
Shivasharan S81b76452018-10-16 23:37:51 -0700992 (scratch_pad_1 & MR_CAN_HANDLE_64_BIT_DMA_OFFSET) ? true : false;
Shivasharan S107a60d2017-10-19 02:49:05 -0700993
994 if (instance->consistent_mask_64bit && !cur_fw_64bit_dma_capable) {
995 dev_err(&instance->pdev->dev, "Driver was operating on 64bit "
996 "DMA mask, but upcoming FW does not support 64bit DMA mask\n");
997 megaraid_sas_kill_hba(instance);
998 ret = 1;
999 goto fail_fw_init;
1000 }
1001 }
1002
Sumit Saxena179ac142016-01-28 21:04:28 +05301003 if (instance->is_rdpq && !cur_rdpq_mode) {
1004 dev_err(&instance->pdev->dev, "Firmware downgrade *NOT SUPPORTED*"
1005 " from RDPQ mode to non RDPQ mode\n");
1006 ret = 1;
1007 goto fail_fw_init;
1008 }
1009
Shivasharan S81b76452018-10-16 23:37:51 -07001010 instance->fw_sync_cache_support = (scratch_pad_1 &
Kashyap Desaid0fc91d2016-10-21 06:33:33 -07001011 MR_CAN_HANDLE_SYNC_CACHE_OFFSET) ? 1 : 0;
1012 dev_info(&instance->pdev->dev, "FW supports sync cache\t: %s\n",
1013 instance->fw_sync_cache_support ? "Yes" : "No");
1014
adam radford9c915a82010-12-21 13:34:31 -08001015 memset(IOCInitMessage, 0, sizeof(struct MPI2_IOC_INIT_REQUEST));
1016
1017 IOCInitMessage->Function = MPI2_FUNCTION_IOC_INIT;
1018 IOCInitMessage->WhoInit = MPI2_WHOINIT_HOST_DRIVER;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301019 IOCInitMessage->MsgVersion = cpu_to_le16(MPI2_VERSION);
1020 IOCInitMessage->HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
1021 IOCInitMessage->SystemRequestFrameSize = cpu_to_le16(MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE / 4);
adam radford9c915a82010-12-21 13:34:31 -08001022
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301023 IOCInitMessage->ReplyDescriptorPostQueueDepth = cpu_to_le16(fusion->reply_q_depth);
Sumit Saxena179ac142016-01-28 21:04:28 +05301024 IOCInitMessage->ReplyDescriptorPostQueueAddress = instance->is_rdpq ?
1025 cpu_to_le64(fusion->rdpq_phys) :
1026 cpu_to_le64(fusion->reply_frames_desc_phys[0]);
1027 IOCInitMessage->MsgFlags = instance->is_rdpq ?
1028 MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE : 0;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301029 IOCInitMessage->SystemRequestFrameBaseAddress = cpu_to_le64(fusion->io_request_frames_phys);
Shivasharan S107a60d2017-10-19 02:49:05 -07001030 IOCInitMessage->SenseBufferAddressHigh = cpu_to_le32(upper_32_bits(fusion->sense_phys_addr));
adam radford5738f992012-03-19 19:49:53 -07001031 IOCInitMessage->HostMSIxVectors = instance->msix_vectors;
Shivasharan S15dd0382017-02-10 00:59:10 -08001032 IOCInitMessage->HostPageSize = MR_DEFAULT_NVME_PAGE_SHIFT;
Shivasharan Sb99fc2022017-10-19 02:49:00 -07001033
Arnd Bergmannb45093d2018-01-17 15:48:51 +01001034 time = ktime_get_real();
Shivasharan Sb99fc2022017-10-19 02:49:00 -07001035 /* Convert to milliseconds as per FW requirement */
Arnd Bergmannb45093d2018-01-17 15:48:51 +01001036 IOCInitMessage->TimeStamp = cpu_to_le64(ktime_to_ms(time));
Shivasharan Sb99fc2022017-10-19 02:49:00 -07001037
adam radford9c915a82010-12-21 13:34:31 -08001038 init_frame = (struct megasas_init_frame *)cmd->frame;
Shivasharan Scb51efe2018-01-05 05:27:37 -08001039 memset(init_frame, 0, IOC_INIT_FRAME_SIZE);
adam radford9c915a82010-12-21 13:34:31 -08001040
1041 frame_hdr = &cmd->frame->hdr;
adam radford9c915a82010-12-21 13:34:31 -08001042 frame_hdr->cmd_status = 0xFF;
Shivasharan Sb52fd072018-10-16 23:37:53 -07001043 frame_hdr->flags |= cpu_to_le16(MFI_FRAME_DONT_POST_IN_REPLY_QUEUE);
adam radford9c915a82010-12-21 13:34:31 -08001044
1045 init_frame->cmd = MFI_CMD_INIT;
1046 init_frame->cmd_status = 0xFF;
1047
sumit.saxena@avagotech.com4dbbe3c2015-08-31 17:23:21 +05301048 drv_ops = (MFI_CAPABILITIES *) &(init_frame->driver_operations);
1049
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +05301050 /* driver support Extended MSIX */
Shivasharan Sc3651782017-10-19 02:48:48 -07001051 if (instance->adapter_type >= INVADER_SERIES)
sumit.saxena@avagotech.com4dbbe3c2015-08-31 17:23:21 +05301052 drv_ops->mfi_capabilities.support_additional_msix = 1;
adam radford21c9e162013-09-06 15:27:14 -07001053 /* driver supports HA / Remote LUN over Fast Path interface */
sumit.saxena@avagotech.com4dbbe3c2015-08-31 17:23:21 +05301054 drv_ops->mfi_capabilities.support_fp_remote_lun = 1;
1055
1056 drv_ops->mfi_capabilities.support_max_255lds = 1;
1057 drv_ops->mfi_capabilities.support_ndrive_r1_lb = 1;
1058 drv_ops->mfi_capabilities.security_protocol_cmds_fw = 1;
1059
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05301060 if (instance->max_chain_frame_sz > MEGASAS_CHAIN_FRAME_SZ_MIN)
1061 drv_ops->mfi_capabilities.support_ext_io_size = 1;
1062
Sumit Saxena8f050242016-01-28 21:04:27 +05301063 drv_ops->mfi_capabilities.support_fp_rlbypass = 1;
Sumit Saxena308ec452016-01-28 21:04:30 +05301064 if (!dual_qdepth_disable)
1065 drv_ops->mfi_capabilities.support_ext_queue_depth = 1;
Sumit Saxena8f050242016-01-28 21:04:27 +05301066
Sumit Saxena52b62ac2016-01-28 21:04:31 +05301067 drv_ops->mfi_capabilities.support_qd_throttling = 1;
Sasikumar Chandrasekaranede7c3c2017-01-10 18:20:52 -05001068 drv_ops->mfi_capabilities.support_pd_map_target_id = 1;
Shivasharan Sf870bcb2018-01-05 05:33:04 -08001069 drv_ops->mfi_capabilities.support_nvme_passthru = 1;
Shivasharan S107a60d2017-10-19 02:49:05 -07001070
1071 if (instance->consistent_mask_64bit)
1072 drv_ops->mfi_capabilities.support_64bit_mode = 1;
1073
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301074 /* Convert capability to LE32 */
1075 cpu_to_le32s((u32 *)&init_frame->driver_operations.mfi_capabilities);
adam radford21c9e162013-09-06 15:27:14 -07001076
Sumit.Saxena@avagotech.com5765c5b2015-04-23 16:32:09 +05301077 sys_info = dmi_get_system_info(DMI_PRODUCT_UUID);
1078 if (instance->system_info_buf && sys_info) {
1079 memcpy(instance->system_info_buf->systemId, sys_info,
1080 strlen(sys_info) > 64 ? 64 : strlen(sys_info));
1081 instance->system_info_buf->systemIdLength =
1082 strlen(sys_info) > 64 ? 64 : strlen(sys_info);
Shivasharan S107a60d2017-10-19 02:49:05 -07001083 init_frame->system_info_lo = cpu_to_le32(lower_32_bits(instance->system_info_h));
1084 init_frame->system_info_hi = cpu_to_le32(upper_32_bits(instance->system_info_h));
Sumit.Saxena@avagotech.com5765c5b2015-04-23 16:32:09 +05301085 }
1086
Hannes Reineckefdc5a972014-01-16 11:25:33 +01001087 init_frame->queue_info_new_phys_addr_hi =
1088 cpu_to_le32(upper_32_bits(ioc_init_handle));
1089 init_frame->queue_info_new_phys_addr_lo =
1090 cpu_to_le32(lower_32_bits(ioc_init_handle));
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301091 init_frame->data_xfer_len = cpu_to_le32(sizeof(struct MPI2_IOC_INIT_REQUEST));
adam radford9c915a82010-12-21 13:34:31 -08001092
Sumit.Saxena@avagotech.com200aed52015-01-05 20:05:58 +05301093 req_desc.u.low = cpu_to_le32(lower_32_bits(cmd->frame_phys_addr));
1094 req_desc.u.high = cpu_to_le32(upper_32_bits(cmd->frame_phys_addr));
adam radfordc77a9bd2014-03-10 02:51:36 -07001095 req_desc.MFAIo.RequestFlags =
adam radford9c915a82010-12-21 13:34:31 -08001096 (MEGASAS_REQ_DESCRIPT_FLAGS_MFA <<
Sumit.Saxena@avagotech.com200aed52015-01-05 20:05:58 +05301097 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
adam radford9c915a82010-12-21 13:34:31 -08001098
1099 /*
1100 * disable the intr before firing the init frame
1101 */
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +05301102 instance->instancet->disable_intr(instance);
adam radford9c915a82010-12-21 13:34:31 -08001103
1104 for (i = 0; i < (10 * 1000); i += 20) {
1105 if (readl(&instance->reg_set->doorbell) & 1)
1106 msleep(20);
1107 else
1108 break;
1109 }
1110
Shivasharan S9ff97fa2018-02-14 00:10:52 -08001111 megasas_fire_cmd_fusion(instance, &req_desc);
adam radford9c915a82010-12-21 13:34:31 -08001112
Shivasharan S1b60d4e2018-10-16 23:37:54 -07001113 wait_and_poll(instance, cmd, MFI_IO_TIMEOUT_SECS);
adam radford9c915a82010-12-21 13:34:31 -08001114
1115 frame_hdr = &cmd->frame->hdr;
1116 if (frame_hdr->cmd_status != 0) {
1117 ret = 1;
1118 goto fail_fw_init;
1119 }
adam radford9c915a82010-12-21 13:34:31 -08001120
Vinson Leefb1633d2018-03-21 21:04:12 +00001121 return 0;
adam radford9c915a82010-12-21 13:34:31 -08001122
1123fail_fw_init:
Shivasharan S2d2c2332017-08-23 04:47:06 -07001124 dev_err(&instance->pdev->dev,
Vinson Leefb1633d2018-03-21 21:04:12 +00001125 "Init cmd return status FAILED for SCSI host %d\n",
1126 instance->host->host_no);
Shivasharan S2d2c2332017-08-23 04:47:06 -07001127
adam radford9c915a82010-12-21 13:34:31 -08001128 return ret;
1129}
1130
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05301131/**
1132 * megasas_sync_pd_seq_num - JBOD SEQ MAP
1133 * @instance: Adapter soft state
1134 * @pend: set to 1, if it is pended jbod map.
1135 *
1136 * Issue Jbod map to the firmware. If it is pended command,
1137 * issue command and return. If it is first instance of jbod map
1138 * issue and receive command.
1139 */
1140int
1141megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend) {
1142 int ret = 0;
1143 u32 pd_seq_map_sz;
1144 struct megasas_cmd *cmd;
1145 struct megasas_dcmd_frame *dcmd;
1146 struct fusion_context *fusion = instance->ctrl_context;
1147 struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync;
1148 dma_addr_t pd_seq_h;
1149
1150 pd_sync = (void *)fusion->pd_seq_sync[(instance->pd_seq_map_id & 1)];
1151 pd_seq_h = fusion->pd_seq_phys[(instance->pd_seq_map_id & 1)];
1152 pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) +
1153 (sizeof(struct MR_PD_CFG_SEQ) *
1154 (MAX_PHYSICAL_DEVICES - 1));
1155
1156 cmd = megasas_get_cmd(instance);
1157 if (!cmd) {
1158 dev_err(&instance->pdev->dev,
1159 "Could not get mfi cmd. Fail from %s %d\n",
1160 __func__, __LINE__);
1161 return -ENOMEM;
1162 }
1163
1164 dcmd = &cmd->frame->dcmd;
1165
1166 memset(pd_sync, 0, pd_seq_map_sz);
1167 memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
Shivasharan S107a60d2017-10-19 02:49:05 -07001168
1169 if (pend) {
1170 dcmd->mbox.b[0] = MEGASAS_DCMD_MBOX_PEND_FLAG;
1171 dcmd->flags = MFI_FRAME_DIR_WRITE;
1172 instance->jbod_seq_cmd = cmd;
1173 } else {
1174 dcmd->flags = MFI_FRAME_DIR_READ;
1175 }
1176
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05301177 dcmd->cmd = MFI_CMD_DCMD;
1178 dcmd->cmd_status = 0xFF;
1179 dcmd->sge_count = 1;
1180 dcmd->timeout = 0;
1181 dcmd->pad_0 = 0;
1182 dcmd->data_xfer_len = cpu_to_le32(pd_seq_map_sz);
1183 dcmd->opcode = cpu_to_le32(MR_DCMD_SYSTEM_PD_MAP_GET_INFO);
Shivasharan S107a60d2017-10-19 02:49:05 -07001184
1185 megasas_set_dma_settings(instance, dcmd, pd_seq_h, pd_seq_map_sz);
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05301186
1187 if (pend) {
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05301188 instance->instancet->issue_dcmd(instance, cmd);
1189 return 0;
1190 }
1191
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05301192 /* Below code is only for non pended DCMD */
Shivasharan S55fecae2017-10-19 02:48:51 -07001193 if (!instance->mask_interrupts)
Sumit Saxena6d40afb2016-01-28 21:04:23 +05301194 ret = megasas_issue_blocked_cmd(instance, cmd,
1195 MFI_IO_TIMEOUT_SECS);
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05301196 else
1197 ret = megasas_issue_polled(instance, cmd);
1198
1199 if (le32_to_cpu(pd_sync->count) > MAX_PHYSICAL_DEVICES) {
1200 dev_warn(&instance->pdev->dev,
1201 "driver supports max %d JBOD, but FW reports %d\n",
1202 MAX_PHYSICAL_DEVICES, le32_to_cpu(pd_sync->count));
1203 ret = -EINVAL;
1204 }
1205
Shivasharan S55fecae2017-10-19 02:48:51 -07001206 if (ret == DCMD_TIMEOUT)
Sumit Saxena6d40afb2016-01-28 21:04:23 +05301207 megaraid_sas_kill_hba(instance);
1208
1209 if (ret == DCMD_SUCCESS)
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05301210 instance->pd_seq_map_id++;
1211
1212 megasas_return_cmd(instance, cmd);
1213 return ret;
1214}
1215
adam radford9c915a82010-12-21 13:34:31 -08001216/*
adam radford9c915a82010-12-21 13:34:31 -08001217 * megasas_get_ld_map_info - Returns FW's ld_map structure
1218 * @instance: Adapter soft state
1219 * @pend: Pend the command or not
1220 * Issues an internal command (DCMD) to get the FW's controller PD
1221 * list structure. This information is mainly used to find out SYSTEM
1222 * supported by the FW.
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301223 * dcmd.mbox value setting for MR_DCMD_LD_MAP_GET_INFO
1224 * dcmd.mbox.b[0] - number of LDs being sync'd
1225 * dcmd.mbox.b[1] - 0 - complete command immediately.
1226 * - 1 - pend till config change
1227 * dcmd.mbox.b[2] - 0 - supports max 64 lds and uses legacy MR_FW_RAID_MAP
1228 * - 1 - supports max MAX_LOGICAL_DRIVES_EXT lds and
1229 * uses extended struct MR_FW_RAID_MAP_EXT
adam radford9c915a82010-12-21 13:34:31 -08001230 */
1231static int
1232megasas_get_ld_map_info(struct megasas_instance *instance)
1233{
1234 int ret = 0;
1235 struct megasas_cmd *cmd;
1236 struct megasas_dcmd_frame *dcmd;
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301237 void *ci;
adam radford9c915a82010-12-21 13:34:31 -08001238 dma_addr_t ci_h = 0;
1239 u32 size_map_info;
1240 struct fusion_context *fusion;
1241
1242 cmd = megasas_get_cmd(instance);
1243
1244 if (!cmd) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05001245 dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to get cmd for map info\n");
adam radford9c915a82010-12-21 13:34:31 -08001246 return -ENOMEM;
1247 }
1248
1249 fusion = instance->ctrl_context;
1250
1251 if (!fusion) {
1252 megasas_return_cmd(instance, cmd);
Hannes Reinecke2f8bdfa2014-01-16 11:25:35 +01001253 return -ENXIO;
adam radford9c915a82010-12-21 13:34:31 -08001254 }
1255
1256 dcmd = &cmd->frame->dcmd;
1257
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301258 size_map_info = fusion->current_map_sz;
adam radford9c915a82010-12-21 13:34:31 -08001259
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301260 ci = (void *) fusion->ld_map[(instance->map_id & 1)];
adam radford9c915a82010-12-21 13:34:31 -08001261 ci_h = fusion->ld_map_phys[(instance->map_id & 1)];
1262
1263 if (!ci) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05001264 dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to alloc mem for ld_map_info\n");
adam radford9c915a82010-12-21 13:34:31 -08001265 megasas_return_cmd(instance, cmd);
1266 return -ENOMEM;
1267 }
1268
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301269 memset(ci, 0, fusion->max_map_sz);
adam radford9c915a82010-12-21 13:34:31 -08001270 memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
adam radford9c915a82010-12-21 13:34:31 -08001271 dcmd->cmd = MFI_CMD_DCMD;
1272 dcmd->cmd_status = 0xFF;
1273 dcmd->sge_count = 1;
Shivasharan S107a60d2017-10-19 02:49:05 -07001274 dcmd->flags = MFI_FRAME_DIR_READ;
adam radford9c915a82010-12-21 13:34:31 -08001275 dcmd->timeout = 0;
1276 dcmd->pad_0 = 0;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301277 dcmd->data_xfer_len = cpu_to_le32(size_map_info);
1278 dcmd->opcode = cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO);
adam radford9c915a82010-12-21 13:34:31 -08001279
Shivasharan S107a60d2017-10-19 02:49:05 -07001280 megasas_set_dma_settings(instance, dcmd, ci_h, size_map_info);
adam radford9c915a82010-12-21 13:34:31 -08001281
Shivasharan S55fecae2017-10-19 02:48:51 -07001282 if (!instance->mask_interrupts)
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +05301283 ret = megasas_issue_blocked_cmd(instance, cmd,
Sumit Saxena6d40afb2016-01-28 21:04:23 +05301284 MFI_IO_TIMEOUT_SECS);
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +05301285 else
1286 ret = megasas_issue_polled(instance, cmd);
adam radford9c915a82010-12-21 13:34:31 -08001287
Shivasharan S55fecae2017-10-19 02:48:51 -07001288 if (ret == DCMD_TIMEOUT)
Sumit Saxena6d40afb2016-01-28 21:04:23 +05301289 megaraid_sas_kill_hba(instance);
1290
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05301291 megasas_return_cmd(instance, cmd);
adam radford9c915a82010-12-21 13:34:31 -08001292
1293 return ret;
1294}
1295
1296u8
1297megasas_get_map_info(struct megasas_instance *instance)
1298{
1299 struct fusion_context *fusion = instance->ctrl_context;
1300
1301 fusion->fast_path_io = 0;
1302 if (!megasas_get_ld_map_info(instance)) {
Shivasharan S5f19f7c2018-01-05 05:27:44 -08001303 if (MR_ValidateMapInfo(instance, instance->map_id)) {
adam radford9c915a82010-12-21 13:34:31 -08001304 fusion->fast_path_io = 1;
1305 return 0;
1306 }
1307 }
1308 return 1;
1309}
1310
1311/*
1312 * megasas_sync_map_info - Returns FW's ld_map structure
1313 * @instance: Adapter soft state
1314 *
1315 * Issues an internal command (DCMD) to get the FW's controller PD
1316 * list structure. This information is mainly used to find out SYSTEM
1317 * supported by the FW.
1318 */
1319int
1320megasas_sync_map_info(struct megasas_instance *instance)
1321{
Shivasharan Sf4fc2092017-02-10 00:59:09 -08001322 int i;
adam radford9c915a82010-12-21 13:34:31 -08001323 struct megasas_cmd *cmd;
1324 struct megasas_dcmd_frame *dcmd;
Shivasharan Sd2d03582017-02-10 00:59:19 -08001325 u16 num_lds;
1326 u32 size_sync_info;
adam radford9c915a82010-12-21 13:34:31 -08001327 struct fusion_context *fusion;
1328 struct MR_LD_TARGET_SYNC *ci = NULL;
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301329 struct MR_DRV_RAID_MAP_ALL *map;
adam radford9c915a82010-12-21 13:34:31 -08001330 struct MR_LD_RAID *raid;
1331 struct MR_LD_TARGET_SYNC *ld_sync;
1332 dma_addr_t ci_h = 0;
1333 u32 size_map_info;
1334
1335 cmd = megasas_get_cmd(instance);
1336
1337 if (!cmd) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05001338 dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to get cmd for sync info\n");
adam radford9c915a82010-12-21 13:34:31 -08001339 return -ENOMEM;
1340 }
1341
1342 fusion = instance->ctrl_context;
1343
1344 if (!fusion) {
1345 megasas_return_cmd(instance, cmd);
1346 return 1;
1347 }
1348
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301349 map = fusion->ld_drv_map[instance->map_id & 1];
adam radford9c915a82010-12-21 13:34:31 -08001350
Sumit.Saxena@avagotech.com6e755dd2014-11-17 15:24:28 +05301351 num_lds = le16_to_cpu(map->raidMap.ldCount);
adam radford9c915a82010-12-21 13:34:31 -08001352
1353 dcmd = &cmd->frame->dcmd;
1354
1355 size_sync_info = sizeof(struct MR_LD_TARGET_SYNC) *num_lds;
1356
1357 memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
1358
1359 ci = (struct MR_LD_TARGET_SYNC *)
1360 fusion->ld_map[(instance->map_id - 1) & 1];
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301361 memset(ci, 0, fusion->max_map_sz);
adam radford9c915a82010-12-21 13:34:31 -08001362
1363 ci_h = fusion->ld_map_phys[(instance->map_id - 1) & 1];
1364
1365 ld_sync = (struct MR_LD_TARGET_SYNC *)ci;
1366
1367 for (i = 0; i < num_lds; i++, ld_sync++) {
1368 raid = MR_LdRaidGet(i, map);
1369 ld_sync->targetId = MR_GetLDTgtId(i, map);
1370 ld_sync->seqNum = raid->seqNum;
1371 }
1372
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301373 size_map_info = fusion->current_map_sz;
adam radford9c915a82010-12-21 13:34:31 -08001374
1375 dcmd->cmd = MFI_CMD_DCMD;
1376 dcmd->cmd_status = 0xFF;
1377 dcmd->sge_count = 1;
Shivasharan S107a60d2017-10-19 02:49:05 -07001378 dcmd->flags = MFI_FRAME_DIR_WRITE;
adam radford9c915a82010-12-21 13:34:31 -08001379 dcmd->timeout = 0;
1380 dcmd->pad_0 = 0;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301381 dcmd->data_xfer_len = cpu_to_le32(size_map_info);
adam radford9c915a82010-12-21 13:34:31 -08001382 dcmd->mbox.b[0] = num_lds;
1383 dcmd->mbox.b[1] = MEGASAS_DCMD_MBOX_PEND_FLAG;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05301384 dcmd->opcode = cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO);
Shivasharan S107a60d2017-10-19 02:49:05 -07001385
1386 megasas_set_dma_settings(instance, dcmd, ci_h, size_map_info);
adam radford9c915a82010-12-21 13:34:31 -08001387
1388 instance->map_update_cmd = cmd;
1389
1390 instance->instancet->issue_dcmd(instance, cmd);
1391
Shivasharan Sf4fc2092017-02-10 00:59:09 -08001392 return 0;
adam radford9c915a82010-12-21 13:34:31 -08001393}
1394
Sumit.Saxena@lsi.com39b72c32013-05-22 12:32:43 +05301395/*
1396 * meagasas_display_intel_branding - Display branding string
1397 * @instance: per adapter object
1398 *
1399 * Return nothing.
1400 */
1401static void
1402megasas_display_intel_branding(struct megasas_instance *instance)
1403{
1404 if (instance->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL)
1405 return;
1406
1407 switch (instance->pdev->device) {
1408 case PCI_DEVICE_ID_LSI_INVADER:
1409 switch (instance->pdev->subsystem_device) {
1410 case MEGARAID_INTEL_RS3DC080_SSDID:
1411 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
1412 instance->host->host_no,
1413 MEGARAID_INTEL_RS3DC080_BRANDING);
1414 break;
1415 case MEGARAID_INTEL_RS3DC040_SSDID:
1416 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
1417 instance->host->host_no,
1418 MEGARAID_INTEL_RS3DC040_BRANDING);
1419 break;
1420 case MEGARAID_INTEL_RS3SC008_SSDID:
1421 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
1422 instance->host->host_no,
1423 MEGARAID_INTEL_RS3SC008_BRANDING);
1424 break;
1425 case MEGARAID_INTEL_RS3MC044_SSDID:
1426 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
1427 instance->host->host_no,
1428 MEGARAID_INTEL_RS3MC044_BRANDING);
1429 break;
1430 default:
1431 break;
1432 }
1433 break;
1434 case PCI_DEVICE_ID_LSI_FURY:
1435 switch (instance->pdev->subsystem_device) {
1436 case MEGARAID_INTEL_RS3WC080_SSDID:
1437 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
1438 instance->host->host_no,
1439 MEGARAID_INTEL_RS3WC080_BRANDING);
1440 break;
1441 case MEGARAID_INTEL_RS3WC040_SSDID:
1442 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
1443 instance->host->host_no,
1444 MEGARAID_INTEL_RS3WC040_BRANDING);
1445 break;
1446 default:
1447 break;
1448 }
1449 break;
sumit.saxena@avagotech.com7364d342015-10-15 13:39:54 +05301450 case PCI_DEVICE_ID_LSI_CUTLASS_52:
1451 case PCI_DEVICE_ID_LSI_CUTLASS_53:
1452 switch (instance->pdev->subsystem_device) {
1453 case MEGARAID_INTEL_RMS3BC160_SSDID:
1454 dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
1455 instance->host->host_no,
1456 MEGARAID_INTEL_RMS3BC160_BRANDING);
1457 break;
1458 default:
1459 break;
1460 }
1461 break;
Sumit.Saxena@lsi.com39b72c32013-05-22 12:32:43 +05301462 default:
1463 break;
1464 }
1465}
1466
adam radford9c915a82010-12-21 13:34:31 -08001467/**
Shivasharan Sdef3e8d2017-08-23 04:47:03 -07001468 * megasas_allocate_raid_maps - Allocate memory for RAID maps
1469 * @instance: Adapter soft state
1470 *
1471 * return: if success: return 0
1472 * failed: return -ENOMEM
1473 */
1474static inline int megasas_allocate_raid_maps(struct megasas_instance *instance)
1475{
1476 struct fusion_context *fusion;
1477 int i = 0;
1478
1479 fusion = instance->ctrl_context;
1480
1481 fusion->drv_map_pages = get_order(fusion->drv_map_sz);
1482
1483 for (i = 0; i < 2; i++) {
1484 fusion->ld_map[i] = NULL;
1485
1486 fusion->ld_drv_map[i] = (void *)
1487 __get_free_pages(__GFP_ZERO | GFP_KERNEL,
1488 fusion->drv_map_pages);
1489
1490 if (!fusion->ld_drv_map[i]) {
1491 fusion->ld_drv_map[i] = vzalloc(fusion->drv_map_sz);
1492
1493 if (!fusion->ld_drv_map[i]) {
1494 dev_err(&instance->pdev->dev,
1495 "Could not allocate memory for local map"
1496 " size requested: %d\n",
1497 fusion->drv_map_sz);
1498 goto ld_drv_map_alloc_fail;
1499 }
1500 }
1501 }
1502
1503 for (i = 0; i < 2; i++) {
1504 fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
1505 fusion->max_map_sz,
1506 &fusion->ld_map_phys[i],
1507 GFP_KERNEL);
1508 if (!fusion->ld_map[i]) {
1509 dev_err(&instance->pdev->dev,
1510 "Could not allocate memory for map info %s:%d\n",
1511 __func__, __LINE__);
1512 goto ld_map_alloc_fail;
1513 }
1514 }
1515
1516 return 0;
1517
1518ld_map_alloc_fail:
1519 for (i = 0; i < 2; i++) {
1520 if (fusion->ld_map[i])
1521 dma_free_coherent(&instance->pdev->dev,
1522 fusion->max_map_sz,
1523 fusion->ld_map[i],
1524 fusion->ld_map_phys[i]);
1525 }
1526
1527ld_drv_map_alloc_fail:
1528 for (i = 0; i < 2; i++) {
1529 if (fusion->ld_drv_map[i]) {
1530 if (is_vmalloc_addr(fusion->ld_drv_map[i]))
1531 vfree(fusion->ld_drv_map[i]);
1532 else
1533 free_pages((ulong)fusion->ld_drv_map[i],
1534 fusion->drv_map_pages);
1535 }
1536 }
1537
1538 return -ENOMEM;
1539}
1540
1541/**
Shivasharan Se97e6732017-10-19 02:49:03 -07001542 * megasas_configure_queue_sizes - Calculate size of request desc queue,
1543 * reply desc queue,
1544 * IO request frame queue, set can_queue.
1545 * @instance: Adapter soft state
1546 * @return: void
1547 */
1548static inline
1549void megasas_configure_queue_sizes(struct megasas_instance *instance)
1550{
1551 struct fusion_context *fusion;
1552 u16 max_cmd;
1553
1554 fusion = instance->ctrl_context;
1555 max_cmd = instance->max_fw_cmds;
1556
Shivasharan S630d42b2018-12-17 00:47:37 -08001557 if (instance->adapter_type >= VENTURA_SERIES)
Shivasharan Se97e6732017-10-19 02:49:03 -07001558 instance->max_mpt_cmds = instance->max_fw_cmds * RAID_1_PEER_CMDS;
1559 else
1560 instance->max_mpt_cmds = instance->max_fw_cmds;
1561
Shivasharan S9fb98562018-10-16 23:37:52 -07001562 instance->max_scsi_cmds = instance->max_fw_cmds - instance->max_mfi_cmds;
Shivasharan Se97e6732017-10-19 02:49:03 -07001563 instance->cur_can_queue = instance->max_scsi_cmds;
1564 instance->host->can_queue = instance->cur_can_queue;
1565
1566 fusion->reply_q_depth = 2 * ((max_cmd + 1 + 15) / 16) * 16;
1567
1568 fusion->request_alloc_sz = sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *
1569 instance->max_mpt_cmds;
1570 fusion->reply_alloc_sz = sizeof(union MPI2_REPLY_DESCRIPTORS_UNION) *
1571 (fusion->reply_q_depth);
1572 fusion->io_frames_alloc_sz = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE +
1573 (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE
1574 * (instance->max_mpt_cmds + 1)); /* Extra 1 for SMID 0 */
1575}
1576
Shivasharan Sb9637d12017-10-19 02:49:01 -07001577static int megasas_alloc_ioc_init_frame(struct megasas_instance *instance)
1578{
1579 struct fusion_context *fusion;
1580 struct megasas_cmd *cmd;
1581
1582 fusion = instance->ctrl_context;
1583
Shivasharan Se05ee4e2018-01-05 05:27:36 -08001584 cmd = kzalloc(sizeof(struct megasas_cmd), GFP_KERNEL);
Shivasharan Sb9637d12017-10-19 02:49:01 -07001585
1586 if (!cmd) {
1587 dev_err(&instance->pdev->dev, "Failed from func: %s line: %d\n",
1588 __func__, __LINE__);
1589 return -ENOMEM;
1590 }
1591
1592 cmd->frame = dma_alloc_coherent(&instance->pdev->dev,
1593 IOC_INIT_FRAME_SIZE,
1594 &cmd->frame_phys_addr, GFP_KERNEL);
1595
1596 if (!cmd->frame) {
1597 dev_err(&instance->pdev->dev, "Failed from func: %s line: %d\n",
1598 __func__, __LINE__);
1599 kfree(cmd);
1600 return -ENOMEM;
1601 }
1602
1603 fusion->ioc_init_cmd = cmd;
1604 return 0;
1605}
1606
1607/**
1608 * megasas_free_ioc_init_cmd - Free IOC INIT command frame
1609 * @instance: Adapter soft state
1610 */
1611static inline void megasas_free_ioc_init_cmd(struct megasas_instance *instance)
1612{
1613 struct fusion_context *fusion;
1614
1615 fusion = instance->ctrl_context;
1616
1617 if (fusion->ioc_init_cmd && fusion->ioc_init_cmd->frame)
1618 dma_free_coherent(&instance->pdev->dev,
1619 IOC_INIT_FRAME_SIZE,
1620 fusion->ioc_init_cmd->frame,
1621 fusion->ioc_init_cmd->frame_phys_addr);
1622
Thomas Meyer19c05072018-12-02 21:52:11 +01001623 kfree(fusion->ioc_init_cmd);
Shivasharan Sb9637d12017-10-19 02:49:01 -07001624}
1625
adam radford9c915a82010-12-21 13:34:31 -08001626/**
1627 * megasas_init_adapter_fusion - Initializes the FW
1628 * @instance: Adapter soft state
1629 *
1630 * This is the main function for initializing firmware.
1631 */
1632u32
1633megasas_init_adapter_fusion(struct megasas_instance *instance)
1634{
1635 struct megasas_register_set __iomem *reg_set;
1636 struct fusion_context *fusion;
Shivasharan S81b76452018-10-16 23:37:51 -07001637 u32 scratch_pad_1;
adam radfordc8e858f2011-10-08 18:15:13 -07001638 int i = 0, count;
adam radford9c915a82010-12-21 13:34:31 -08001639
1640 fusion = instance->ctrl_context;
1641
1642 reg_set = instance->reg_set;
1643
Sumit Saxena308ec452016-01-28 21:04:30 +05301644 megasas_fusion_update_can_queue(instance, PROBE_CONTEXT);
adam radford9c915a82010-12-21 13:34:31 -08001645
1646 /*
Sumit.Saxena@avagotech.comae09a6c2015-01-05 20:06:23 +05301647 * Only Driver's internal DCMDs and IOCTL DCMDs needs to have MFI frames
1648 */
1649 instance->max_mfi_cmds =
1650 MEGASAS_FUSION_INTERNAL_CMDS + MEGASAS_FUSION_IOCTL_CMDS;
adam radford9c915a82010-12-21 13:34:31 -08001651
Shivasharan Se97e6732017-10-19 02:49:03 -07001652 megasas_configure_queue_sizes(instance);
adam radford9c915a82010-12-21 13:34:31 -08001653
Shivasharan S81b76452018-10-16 23:37:51 -07001654 scratch_pad_1 = readl(&instance->reg_set->outbound_scratch_pad_1);
1655 /* If scratch_pad_1 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK is set,
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05301656 * Firmware support extended IO chain frame which is 4 times more than
1657 * legacy Firmware.
1658 * Legacy Firmware - Frame size is (8 * 128) = 1K
1659 * 1M IO Firmware - Frame size is (8 * 128 * 4) = 4K
1660 */
Shivasharan S81b76452018-10-16 23:37:51 -07001661 if (scratch_pad_1 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK)
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05301662 instance->max_chain_frame_sz =
Shivasharan S81b76452018-10-16 23:37:51 -07001663 ((scratch_pad_1 & MEGASAS_MAX_CHAIN_SIZE_MASK) >>
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05301664 MEGASAS_MAX_CHAIN_SHIFT) * MEGASAS_1MB_IO;
1665 else
1666 instance->max_chain_frame_sz =
Shivasharan S81b76452018-10-16 23:37:51 -07001667 ((scratch_pad_1 & MEGASAS_MAX_CHAIN_SIZE_MASK) >>
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05301668 MEGASAS_MAX_CHAIN_SHIFT) * MEGASAS_256K_IO;
1669
1670 if (instance->max_chain_frame_sz < MEGASAS_CHAIN_FRAME_SZ_MIN) {
1671 dev_warn(&instance->pdev->dev, "frame size %d invalid, fall back to legacy max frame size %d\n",
1672 instance->max_chain_frame_sz,
1673 MEGASAS_CHAIN_FRAME_SZ_MIN);
1674 instance->max_chain_frame_sz = MEGASAS_CHAIN_FRAME_SZ_MIN;
1675 }
1676
adam radford9c915a82010-12-21 13:34:31 -08001677 fusion->max_sge_in_main_msg =
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05301678 (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE
1679 - offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL))/16;
adam radford9c915a82010-12-21 13:34:31 -08001680
1681 fusion->max_sge_in_chain =
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05301682 instance->max_chain_frame_sz
1683 / sizeof(union MPI2_SGE_IO_UNION);
adam radford9c915a82010-12-21 13:34:31 -08001684
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05301685 instance->max_num_sge =
1686 rounddown_pow_of_two(fusion->max_sge_in_main_msg
1687 + fusion->max_sge_in_chain - 2);
adam radford9c915a82010-12-21 13:34:31 -08001688
1689 /* Used for pass thru MFI frame (DCMD) */
1690 fusion->chain_offset_mfi_pthru =
1691 offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL)/16;
1692
1693 fusion->chain_offset_io_request =
1694 (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
1695 sizeof(union MPI2_SGE_IO_UNION))/16;
1696
adam radfordc8e858f2011-10-08 18:15:13 -07001697 count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
1698 for (i = 0 ; i < count; i++)
1699 fusion->last_reply_idx[i] = 0;
adam radford9c915a82010-12-21 13:34:31 -08001700
1701 /*
Shivasharan Sec779592017-02-10 00:59:35 -08001702 * For fusion adapters, 3 commands for IOCTL and 8 commands
Sumit.Saxena@avagotech.comf26ac3a2015-04-23 16:30:54 +05301703 * for driver's internal DCMDs.
1704 */
1705 instance->max_scsi_cmds = instance->max_fw_cmds -
1706 (MEGASAS_FUSION_INTERNAL_CMDS +
1707 MEGASAS_FUSION_IOCTL_CMDS);
1708 sema_init(&instance->ioctl_sem, MEGASAS_FUSION_IOCTL_CMDS);
1709
Shivasharan Sb9637d12017-10-19 02:49:01 -07001710 if (megasas_alloc_ioc_init_frame(instance))
1711 return 1;
1712
Sumit.Saxena@avagotech.comf26ac3a2015-04-23 16:30:54 +05301713 /*
adam radford9c915a82010-12-21 13:34:31 -08001714 * Allocate memory for descriptors
1715 * Create a pool of commands
1716 */
1717 if (megasas_alloc_cmds(instance))
1718 goto fail_alloc_mfi_cmds;
1719 if (megasas_alloc_cmds_fusion(instance))
1720 goto fail_alloc_cmds;
1721
1722 if (megasas_ioc_init_fusion(instance))
1723 goto fail_ioc_init;
1724
Sumit.Saxena@lsi.com39b72c32013-05-22 12:32:43 +05301725 megasas_display_intel_branding(instance);
Sumit.Saxena@avagotech.comd009b572014-11-17 15:24:13 +05301726 if (megasas_get_ctrl_info(instance)) {
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05301727 dev_err(&instance->pdev->dev,
1728 "Could not get controller info. Fail from %s %d\n",
1729 __func__, __LINE__);
1730 goto fail_ioc_init;
1731 }
1732
adam radford9c915a82010-12-21 13:34:31 -08001733 instance->flag_ieee = 1;
Shivasharan Sa48ba0e2017-02-10 00:59:13 -08001734 instance->r1_ldio_hint_default = MR_R1_LDIO_PIGGYBACK_DEFAULT;
adam radford9c915a82010-12-21 13:34:31 -08001735 fusion->fast_path_io = 0;
1736
Shivasharan Sdef3e8d2017-08-23 04:47:03 -07001737 if (megasas_allocate_raid_maps(instance))
1738 goto fail_ioc_init;
adam radford9c915a82010-12-21 13:34:31 -08001739
1740 if (!megasas_get_map_info(instance))
1741 megasas_sync_map_info(instance);
1742
1743 return 0;
1744
adam radford9c915a82010-12-21 13:34:31 -08001745fail_ioc_init:
adam radfordeb1b1232011-02-24 20:55:56 -08001746 megasas_free_cmds_fusion(instance);
1747fail_alloc_cmds:
1748 megasas_free_cmds(instance);
1749fail_alloc_mfi_cmds:
Shivasharan Sb9637d12017-10-19 02:49:01 -07001750 megasas_free_ioc_init_cmd(instance);
adam radford9c915a82010-12-21 13:34:31 -08001751 return 1;
1752}
1753
1754/**
Shivasharan S3f6194a2018-10-16 23:37:39 -07001755 * megasas_fault_detect_work - Worker function of
1756 * FW fault handling workqueue.
1757 */
1758static void
1759megasas_fault_detect_work(struct work_struct *work)
1760{
1761 struct megasas_instance *instance =
1762 container_of(work, struct megasas_instance,
1763 fw_fault_work.work);
1764 u32 fw_state, dma_state, status;
1765
1766 /* Check the fw state */
1767 fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) &
1768 MFI_STATE_MASK;
1769
1770 if (fw_state == MFI_STATE_FAULT) {
1771 dma_state = instance->instancet->read_fw_status_reg(
1772 instance->reg_set) & MFI_STATE_DMADONE;
1773 /* Start collecting crash, if DMA bit is done */
1774 if (instance->crash_dump_drv_support &&
1775 instance->crash_dump_app_support && dma_state) {
1776 megasas_fusion_crash_dump(instance);
1777 } else {
1778 if (instance->unload == 0) {
1779 status = megasas_reset_fusion(instance->host, 0);
1780 if (status != SUCCESS) {
1781 dev_err(&instance->pdev->dev,
1782 "Failed from %s %d, do not re-arm timer\n",
1783 __func__, __LINE__);
1784 return;
1785 }
1786 }
1787 }
1788 }
1789
1790 if (instance->fw_fault_work_q)
1791 queue_delayed_work(instance->fw_fault_work_q,
1792 &instance->fw_fault_work,
1793 msecs_to_jiffies(MEGASAS_WATCHDOG_THREAD_INTERVAL));
1794}
1795
1796int
1797megasas_fusion_start_watchdog(struct megasas_instance *instance)
1798{
1799 /* Check if the Fault WQ is already started */
1800 if (instance->fw_fault_work_q)
1801 return SUCCESS;
1802
1803 INIT_DELAYED_WORK(&instance->fw_fault_work, megasas_fault_detect_work);
1804
1805 snprintf(instance->fault_handler_work_q_name,
1806 sizeof(instance->fault_handler_work_q_name),
1807 "poll_megasas%d_status", instance->host->host_no);
1808
1809 instance->fw_fault_work_q =
1810 create_singlethread_workqueue(instance->fault_handler_work_q_name);
1811 if (!instance->fw_fault_work_q) {
1812 dev_err(&instance->pdev->dev, "Failed from %s %d\n",
1813 __func__, __LINE__);
1814 return FAILED;
1815 }
1816
1817 queue_delayed_work(instance->fw_fault_work_q,
1818 &instance->fw_fault_work,
1819 msecs_to_jiffies(MEGASAS_WATCHDOG_THREAD_INTERVAL));
1820
1821 return SUCCESS;
1822}
1823
1824void
1825megasas_fusion_stop_watchdog(struct megasas_instance *instance)
1826{
1827 struct workqueue_struct *wq;
1828
1829 if (instance->fw_fault_work_q) {
1830 wq = instance->fw_fault_work_q;
1831 instance->fw_fault_work_q = NULL;
1832 if (!cancel_delayed_work_sync(&instance->fw_fault_work))
1833 flush_workqueue(wq);
1834 destroy_workqueue(wq);
1835 }
1836}
1837
1838/**
adam radford9c915a82010-12-21 13:34:31 -08001839 * map_cmd_status - Maps FW cmd status to OS cmd status
1840 * @cmd : Pointer to cmd
1841 * @status : status of cmd returned by FW
1842 * @ext_status : ext status of cmd returned by FW
1843 */
1844
1845void
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05001846map_cmd_status(struct fusion_context *fusion,
Shivasharan S41064f12017-02-10 00:59:37 -08001847 struct scsi_cmnd *scmd, u8 status, u8 ext_status,
1848 u32 data_length, u8 *sense)
adam radford9c915a82010-12-21 13:34:31 -08001849{
Shivasharan Sdef0eab2017-02-10 00:59:15 -08001850 u8 cmd_type;
Shivasharan S31d9a572017-02-10 00:59:14 -08001851 int resid;
adam radford9c915a82010-12-21 13:34:31 -08001852
Shivasharan Sdef0eab2017-02-10 00:59:15 -08001853 cmd_type = megasas_cmd_type(scmd);
adam radford9c915a82010-12-21 13:34:31 -08001854 switch (status) {
1855
1856 case MFI_STAT_OK:
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05001857 scmd->result = DID_OK << 16;
adam radford9c915a82010-12-21 13:34:31 -08001858 break;
1859
1860 case MFI_STAT_SCSI_IO_FAILED:
1861 case MFI_STAT_LD_INIT_IN_PROGRESS:
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05001862 scmd->result = (DID_ERROR << 16) | ext_status;
adam radford9c915a82010-12-21 13:34:31 -08001863 break;
1864
1865 case MFI_STAT_SCSI_DONE_WITH_ERROR:
1866
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05001867 scmd->result = (DID_OK << 16) | ext_status;
adam radford9c915a82010-12-21 13:34:31 -08001868 if (ext_status == SAM_STAT_CHECK_CONDITION) {
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05001869 memset(scmd->sense_buffer, 0,
adam radford9c915a82010-12-21 13:34:31 -08001870 SCSI_SENSE_BUFFERSIZE);
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05001871 memcpy(scmd->sense_buffer, sense,
adam radford9c915a82010-12-21 13:34:31 -08001872 SCSI_SENSE_BUFFERSIZE);
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05001873 scmd->result |= DRIVER_SENSE << 24;
adam radford9c915a82010-12-21 13:34:31 -08001874 }
Shivasharan S31d9a572017-02-10 00:59:14 -08001875
1876 /*
1877 * If the IO request is partially completed, then MR FW will
1878 * update "io_request->DataLength" field with actual number of
1879 * bytes transferred.Driver will set residual bytes count in
1880 * SCSI command structure.
1881 */
1882 resid = (scsi_bufflen(scmd) - data_length);
1883 scsi_set_resid(scmd, resid);
Shivasharan Sdef0eab2017-02-10 00:59:15 -08001884
1885 if (resid &&
1886 ((cmd_type == READ_WRITE_LDIO) ||
1887 (cmd_type == READ_WRITE_SYSPDIO)))
1888 scmd_printk(KERN_INFO, scmd, "BRCM Debug mfi stat 0x%x, data len"
1889 " requested/completed 0x%x/0x%x\n",
1890 status, scsi_bufflen(scmd), data_length);
adam radford9c915a82010-12-21 13:34:31 -08001891 break;
1892
1893 case MFI_STAT_LD_OFFLINE:
1894 case MFI_STAT_DEVICE_NOT_FOUND:
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05001895 scmd->result = DID_BAD_TARGET << 16;
adam radford9c915a82010-12-21 13:34:31 -08001896 break;
adam radford36807e62011-10-08 18:15:06 -07001897 case MFI_STAT_CONFIG_SEQ_MISMATCH:
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05001898 scmd->result = DID_IMM_RETRY << 16;
adam radford36807e62011-10-08 18:15:06 -07001899 break;
adam radford9c915a82010-12-21 13:34:31 -08001900 default:
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05001901 scmd->result = DID_ERROR << 16;
adam radford9c915a82010-12-21 13:34:31 -08001902 break;
1903 }
1904}
1905
1906/**
Shivasharan S33203bc2017-02-10 00:59:12 -08001907 * megasas_is_prp_possible -
1908 * Checks if native NVMe PRPs can be built for the IO
1909 *
1910 * @instance: Adapter soft state
1911 * @scmd: SCSI command from the mid-layer
1912 * @sge_count: scatter gather element count.
1913 *
1914 * Returns: true: PRPs can be built
1915 * false: IEEE SGLs needs to be built
1916 */
1917static bool
1918megasas_is_prp_possible(struct megasas_instance *instance,
1919 struct scsi_cmnd *scmd, int sge_count)
1920{
1921 struct fusion_context *fusion;
1922 int i;
1923 u32 data_length = 0;
1924 struct scatterlist *sg_scmd;
1925 bool build_prp = false;
1926 u32 mr_nvme_pg_size;
1927
1928 mr_nvme_pg_size = max_t(u32, instance->nvme_page_size,
1929 MR_DEFAULT_NVME_PAGE_SIZE);
1930 fusion = instance->ctrl_context;
1931 data_length = scsi_bufflen(scmd);
1932 sg_scmd = scsi_sglist(scmd);
1933
1934 /*
1935 * NVMe uses one PRP for each page (or part of a page)
1936 * look at the data length - if 4 pages or less then IEEE is OK
1937 * if > 5 pages then we need to build a native SGL
1938 * if > 4 and <= 5 pages, then check physical address of 1st SG entry
1939 * if this first size in the page is >= the residual beyond 4 pages
1940 * then use IEEE, otherwise use native SGL
1941 */
1942
1943 if (data_length > (mr_nvme_pg_size * 5)) {
1944 build_prp = true;
1945 } else if ((data_length > (mr_nvme_pg_size * 4)) &&
1946 (data_length <= (mr_nvme_pg_size * 5))) {
1947 /* check if 1st SG entry size is < residual beyond 4 pages */
1948 if (sg_dma_len(sg_scmd) < (data_length - (mr_nvme_pg_size * 4)))
1949 build_prp = true;
1950 }
1951
1952/*
1953 * Below code detects gaps/holes in IO data buffers.
1954 * What does holes/gaps mean?
1955 * Any SGE except first one in a SGL starts at non NVME page size
1956 * aligned address OR Any SGE except last one in a SGL ends at
1957 * non NVME page size boundary.
1958 *
1959 * Driver has already informed block layer by setting boundary rules for
1960 * bio merging done at NVME page size boundary calling kernel API
1961 * blk_queue_virt_boundary inside slave_config.
1962 * Still there is possibility of IO coming with holes to driver because of
1963 * IO merging done by IO scheduler.
1964 *
1965 * With SCSI BLK MQ enabled, there will be no IO with holes as there is no
1966 * IO scheduling so no IO merging.
1967 *
1968 * With SCSI BLK MQ disabled, IO scheduler may attempt to merge IOs and
1969 * then sending IOs with holes.
1970 *
1971 * Though driver can request block layer to disable IO merging by calling-
Bart Van Assche8b904b52018-03-07 17:10:10 -08001972 * blk_queue_flag_set(QUEUE_FLAG_NOMERGES, sdev->request_queue) but
Shivasharan S33203bc2017-02-10 00:59:12 -08001973 * user may tune sysfs parameter- nomerges again to 0 or 1.
1974 *
1975 * If in future IO scheduling is enabled with SCSI BLK MQ,
1976 * this algorithm to detect holes will be required in driver
1977 * for SCSI BLK MQ enabled case as well.
1978 *
1979 *
1980 */
1981 scsi_for_each_sg(scmd, sg_scmd, sge_count, i) {
1982 if ((i != 0) && (i != (sge_count - 1))) {
1983 if (mega_mod64(sg_dma_len(sg_scmd), mr_nvme_pg_size) ||
1984 mega_mod64(sg_dma_address(sg_scmd),
1985 mr_nvme_pg_size)) {
1986 build_prp = false;
1987 atomic_inc(&instance->sge_holes_type1);
1988 break;
1989 }
1990 }
1991
1992 if ((sge_count > 1) && (i == 0)) {
1993 if ((mega_mod64((sg_dma_address(sg_scmd) +
1994 sg_dma_len(sg_scmd)),
1995 mr_nvme_pg_size))) {
1996 build_prp = false;
1997 atomic_inc(&instance->sge_holes_type2);
1998 break;
1999 }
2000 }
2001
2002 if ((sge_count > 1) && (i == (sge_count - 1))) {
2003 if (mega_mod64(sg_dma_address(sg_scmd),
2004 mr_nvme_pg_size)) {
2005 build_prp = false;
2006 atomic_inc(&instance->sge_holes_type3);
2007 break;
2008 }
2009 }
2010 }
2011
2012 return build_prp;
2013}
2014
2015/**
2016 * megasas_make_prp_nvme -
2017 * Prepare PRPs(Physical Region Page)- SGLs specific to NVMe drives only
2018 *
2019 * @instance: Adapter soft state
2020 * @scmd: SCSI command from the mid-layer
2021 * @sgl_ptr: SGL to be filled in
2022 * @cmd: Fusion command frame
2023 * @sge_count: scatter gather element count.
2024 *
2025 * Returns: true: PRPs are built
2026 * false: IEEE SGLs needs to be built
2027 */
2028static bool
2029megasas_make_prp_nvme(struct megasas_instance *instance, struct scsi_cmnd *scmd,
2030 struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr,
2031 struct megasas_cmd_fusion *cmd, int sge_count)
2032{
2033 int sge_len, offset, num_prp_in_chain = 0;
2034 struct MPI25_IEEE_SGE_CHAIN64 *main_chain_element, *ptr_first_sgl;
Arnd Bergmannd1da5222017-02-14 22:21:51 +01002035 u64 *ptr_sgl;
2036 dma_addr_t ptr_sgl_phys;
Shivasharan S33203bc2017-02-10 00:59:12 -08002037 u64 sge_addr;
2038 u32 page_mask, page_mask_result;
2039 struct scatterlist *sg_scmd;
2040 u32 first_prp_len;
2041 bool build_prp = false;
2042 int data_len = scsi_bufflen(scmd);
2043 struct fusion_context *fusion;
2044 u32 mr_nvme_pg_size = max_t(u32, instance->nvme_page_size,
2045 MR_DEFAULT_NVME_PAGE_SIZE);
2046
2047 fusion = instance->ctrl_context;
2048
2049 build_prp = megasas_is_prp_possible(instance, scmd, sge_count);
2050
2051 if (!build_prp)
2052 return false;
2053
2054 /*
2055 * Nvme has a very convoluted prp format. One prp is required
2056 * for each page or partial page. Driver need to split up OS sg_list
2057 * entries if it is longer than one page or cross a page
2058 * boundary. Driver also have to insert a PRP list pointer entry as
2059 * the last entry in each physical page of the PRP list.
2060 *
2061 * NOTE: The first PRP "entry" is actually placed in the first
2062 * SGL entry in the main message as IEEE 64 format. The 2nd
2063 * entry in the main message is the chain element, and the rest
2064 * of the PRP entries are built in the contiguous pcie buffer.
2065 */
2066 page_mask = mr_nvme_pg_size - 1;
2067 ptr_sgl = (u64 *)cmd->sg_frame;
Arnd Bergmannd1da5222017-02-14 22:21:51 +01002068 ptr_sgl_phys = cmd->sg_frame_phys_addr;
Shivasharan S33203bc2017-02-10 00:59:12 -08002069 memset(ptr_sgl, 0, instance->max_chain_frame_sz);
2070
2071 /* Build chain frame element which holds all prps except first*/
2072 main_chain_element = (struct MPI25_IEEE_SGE_CHAIN64 *)
2073 ((u8 *)sgl_ptr + sizeof(struct MPI25_IEEE_SGE_CHAIN64));
2074
Arnd Bergmannd1da5222017-02-14 22:21:51 +01002075 main_chain_element->Address = cpu_to_le64(ptr_sgl_phys);
Shivasharan S33203bc2017-02-10 00:59:12 -08002076 main_chain_element->NextChainOffset = 0;
2077 main_chain_element->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT |
2078 IEEE_SGE_FLAGS_SYSTEM_ADDR |
2079 MPI26_IEEE_SGE_FLAGS_NSF_NVME_PRP;
2080
2081 /* Build first prp, sge need not to be page aligned*/
2082 ptr_first_sgl = sgl_ptr;
2083 sg_scmd = scsi_sglist(scmd);
2084 sge_addr = sg_dma_address(sg_scmd);
2085 sge_len = sg_dma_len(sg_scmd);
2086
2087 offset = (u32)(sge_addr & page_mask);
2088 first_prp_len = mr_nvme_pg_size - offset;
2089
2090 ptr_first_sgl->Address = cpu_to_le64(sge_addr);
2091 ptr_first_sgl->Length = cpu_to_le32(first_prp_len);
2092
2093 data_len -= first_prp_len;
2094
2095 if (sge_len > first_prp_len) {
2096 sge_addr += first_prp_len;
2097 sge_len -= first_prp_len;
2098 } else if (sge_len == first_prp_len) {
2099 sg_scmd = sg_next(sg_scmd);
2100 sge_addr = sg_dma_address(sg_scmd);
2101 sge_len = sg_dma_len(sg_scmd);
2102 }
2103
2104 for (;;) {
2105 offset = (u32)(sge_addr & page_mask);
2106
2107 /* Put PRP pointer due to page boundary*/
2108 page_mask_result = (uintptr_t)(ptr_sgl + 1) & page_mask;
2109 if (unlikely(!page_mask_result)) {
2110 scmd_printk(KERN_NOTICE,
2111 scmd, "page boundary ptr_sgl: 0x%p\n",
2112 ptr_sgl);
Arnd Bergmannd1da5222017-02-14 22:21:51 +01002113 ptr_sgl_phys += 8;
2114 *ptr_sgl = cpu_to_le64(ptr_sgl_phys);
Shivasharan S33203bc2017-02-10 00:59:12 -08002115 ptr_sgl++;
2116 num_prp_in_chain++;
2117 }
2118
2119 *ptr_sgl = cpu_to_le64(sge_addr);
2120 ptr_sgl++;
Arnd Bergmannd1da5222017-02-14 22:21:51 +01002121 ptr_sgl_phys += 8;
Shivasharan S33203bc2017-02-10 00:59:12 -08002122 num_prp_in_chain++;
2123
2124 sge_addr += mr_nvme_pg_size;
2125 sge_len -= mr_nvme_pg_size;
2126 data_len -= mr_nvme_pg_size;
2127
2128 if (data_len <= 0)
2129 break;
2130
2131 if (sge_len > 0)
2132 continue;
2133
2134 sg_scmd = sg_next(sg_scmd);
2135 sge_addr = sg_dma_address(sg_scmd);
2136 sge_len = sg_dma_len(sg_scmd);
2137 }
2138
2139 main_chain_element->Length =
2140 cpu_to_le32(num_prp_in_chain * sizeof(u64));
2141
2142 atomic_inc(&instance->prp_sgl);
2143 return build_prp;
2144}
2145
2146/**
adam radford9c915a82010-12-21 13:34:31 -08002147 * megasas_make_sgl_fusion - Prepares 32-bit SGL
2148 * @instance: Adapter soft state
2149 * @scp: SCSI command from the mid-layer
2150 * @sgl_ptr: SGL to be filled in
2151 * @cmd: cmd we are working on
Shivasharan S33203bc2017-02-10 00:59:12 -08002152 * @sge_count sge count
adam radford9c915a82010-12-21 13:34:31 -08002153 *
adam radford9c915a82010-12-21 13:34:31 -08002154 */
Shivasharan S33203bc2017-02-10 00:59:12 -08002155static void
adam radford9c915a82010-12-21 13:34:31 -08002156megasas_make_sgl_fusion(struct megasas_instance *instance,
2157 struct scsi_cmnd *scp,
2158 struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr,
Shivasharan S33203bc2017-02-10 00:59:12 -08002159 struct megasas_cmd_fusion *cmd, int sge_count)
adam radford9c915a82010-12-21 13:34:31 -08002160{
Shivasharan S33203bc2017-02-10 00:59:12 -08002161 int i, sg_processed;
adam radford9c915a82010-12-21 13:34:31 -08002162 struct scatterlist *os_sgl;
2163 struct fusion_context *fusion;
2164
2165 fusion = instance->ctrl_context;
2166
Shivasharan Sc3651782017-10-19 02:48:48 -07002167 if (instance->adapter_type >= INVADER_SERIES) {
adam radford36807e62011-10-08 18:15:06 -07002168 struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = sgl_ptr;
2169 sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
2170 sgl_ptr_end->Flags = 0;
2171 }
adam radford9c915a82010-12-21 13:34:31 -08002172
adam radford9c915a82010-12-21 13:34:31 -08002173 scsi_for_each_sg(scp, os_sgl, sge_count, i) {
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302174 sgl_ptr->Length = cpu_to_le32(sg_dma_len(os_sgl));
2175 sgl_ptr->Address = cpu_to_le64(sg_dma_address(os_sgl));
adam radford9c915a82010-12-21 13:34:31 -08002176 sgl_ptr->Flags = 0;
Shivasharan Sc3651782017-10-19 02:48:48 -07002177 if (instance->adapter_type >= INVADER_SERIES)
adam radford36807e62011-10-08 18:15:06 -07002178 if (i == sge_count - 1)
2179 sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST;
adam radford9c915a82010-12-21 13:34:31 -08002180 sgl_ptr++;
adam radford9c915a82010-12-21 13:34:31 -08002181 sg_processed = i + 1;
2182
2183 if ((sg_processed == (fusion->max_sge_in_main_msg - 1)) &&
2184 (sge_count > fusion->max_sge_in_main_msg)) {
2185
2186 struct MPI25_IEEE_SGE_CHAIN64 *sg_chain;
Shivasharan Sc3651782017-10-19 02:48:48 -07002187 if (instance->adapter_type >= INVADER_SERIES) {
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302188 if ((le16_to_cpu(cmd->io_request->IoFlags) &
2189 MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) !=
2190 MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)
adam radford36807e62011-10-08 18:15:06 -07002191 cmd->io_request->ChainOffset =
2192 fusion->
2193 chain_offset_io_request;
2194 else
2195 cmd->io_request->ChainOffset = 0;
2196 } else
2197 cmd->io_request->ChainOffset =
2198 fusion->chain_offset_io_request;
2199
adam radford9c915a82010-12-21 13:34:31 -08002200 sg_chain = sgl_ptr;
2201 /* Prepare chain element */
2202 sg_chain->NextChainOffset = 0;
Shivasharan Sc3651782017-10-19 02:48:48 -07002203 if (instance->adapter_type >= INVADER_SERIES)
adam radford36807e62011-10-08 18:15:06 -07002204 sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT;
2205 else
2206 sg_chain->Flags =
2207 (IEEE_SGE_FLAGS_CHAIN_ELEMENT |
2208 MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302209 sg_chain->Length = cpu_to_le32((sizeof(union MPI2_SGE_IO_UNION) * (sge_count - sg_processed)));
2210 sg_chain->Address = cpu_to_le64(cmd->sg_frame_phys_addr);
adam radford9c915a82010-12-21 13:34:31 -08002211
2212 sgl_ptr =
2213 (struct MPI25_IEEE_SGE_CHAIN64 *)cmd->sg_frame;
sumit.saxena@avagotech.combd5f9482015-08-31 17:23:31 +05302214 memset(sgl_ptr, 0, instance->max_chain_frame_sz);
adam radford9c915a82010-12-21 13:34:31 -08002215 }
2216 }
Shivasharan S33203bc2017-02-10 00:59:12 -08002217 atomic_inc(&instance->ieee_sgl);
2218}
2219
2220/**
2221 * megasas_make_sgl - Build Scatter Gather List(SGLs)
2222 * @scp: SCSI command pointer
2223 * @instance: Soft instance of controller
2224 * @cmd: Fusion command pointer
2225 *
2226 * This function will build sgls based on device type.
2227 * For nvme drives, there is different way of building sgls in nvme native
2228 * format- PRPs(Physical Region Page).
2229 *
2230 * Returns the number of sg lists actually used, zero if the sg lists
2231 * is NULL, or -ENOMEM if the mapping failed
2232 */
2233static
2234int megasas_make_sgl(struct megasas_instance *instance, struct scsi_cmnd *scp,
2235 struct megasas_cmd_fusion *cmd)
2236{
2237 int sge_count;
2238 bool build_prp = false;
2239 struct MPI25_IEEE_SGE_CHAIN64 *sgl_chain64;
2240
2241 sge_count = scsi_dma_map(scp);
2242
2243 if ((sge_count > instance->max_num_sge) || (sge_count <= 0))
2244 return sge_count;
2245
2246 sgl_chain64 = (struct MPI25_IEEE_SGE_CHAIN64 *)&cmd->io_request->SGL;
2247 if ((le16_to_cpu(cmd->io_request->IoFlags) &
2248 MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) &&
2249 (cmd->pd_interface == NVME_PD))
2250 build_prp = megasas_make_prp_nvme(instance, scp, sgl_chain64,
2251 cmd, sge_count);
2252
2253 if (!build_prp)
2254 megasas_make_sgl_fusion(instance, scp, sgl_chain64,
2255 cmd, sge_count);
adam radford9c915a82010-12-21 13:34:31 -08002256
2257 return sge_count;
2258}
2259
2260/**
2261 * megasas_set_pd_lba - Sets PD LBA
2262 * @cdb: CDB
2263 * @cdb_len: cdb length
2264 * @start_blk: Start block of IO
2265 *
2266 * Used to set the PD LBA in CDB for FP IOs
2267 */
2268void
2269megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
2270 struct IO_REQUEST_INFO *io_info, struct scsi_cmnd *scp,
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05302271 struct MR_DRV_RAID_MAP_ALL *local_map_ptr, u32 ref_tag)
adam radford9c915a82010-12-21 13:34:31 -08002272{
2273 struct MR_LD_RAID *raid;
Shivasharan Sd2d03582017-02-10 00:59:19 -08002274 u16 ld;
adam radford9c915a82010-12-21 13:34:31 -08002275 u64 start_blk = io_info->pdBlock;
2276 u8 *cdb = io_request->CDB.CDB32;
2277 u32 num_blocks = io_info->numBlocks;
adam radford495c5602011-05-11 18:34:40 -07002278 u8 opcode = 0, flagvals = 0, groupnum = 0, control = 0;
adam radford9c915a82010-12-21 13:34:31 -08002279
2280 /* Check if T10 PI (DIF) is enabled for this LD */
2281 ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr);
2282 raid = MR_LdRaidGet(ld, local_map_ptr);
2283 if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) {
2284 memset(cdb, 0, sizeof(io_request->CDB.CDB32));
2285 cdb[0] = MEGASAS_SCSI_VARIABLE_LENGTH_CMD;
2286 cdb[7] = MEGASAS_SCSI_ADDL_CDB_LEN;
2287
Christoph Hellwig60ee6522018-10-10 19:31:25 +02002288 if (scp->sc_data_direction == DMA_FROM_DEVICE)
adam radford9c915a82010-12-21 13:34:31 -08002289 cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_READ32;
2290 else
2291 cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_WRITE32;
2292 cdb[10] = MEGASAS_RD_WR_PROTECT_CHECK_ALL;
2293
2294 /* LBA */
2295 cdb[12] = (u8)((start_blk >> 56) & 0xff);
2296 cdb[13] = (u8)((start_blk >> 48) & 0xff);
2297 cdb[14] = (u8)((start_blk >> 40) & 0xff);
2298 cdb[15] = (u8)((start_blk >> 32) & 0xff);
2299 cdb[16] = (u8)((start_blk >> 24) & 0xff);
2300 cdb[17] = (u8)((start_blk >> 16) & 0xff);
2301 cdb[18] = (u8)((start_blk >> 8) & 0xff);
2302 cdb[19] = (u8)(start_blk & 0xff);
2303
2304 /* Logical block reference tag */
2305 io_request->CDB.EEDP32.PrimaryReferenceTag =
2306 cpu_to_be32(ref_tag);
Sumit.Saxena@avagotech.com6e755dd2014-11-17 15:24:28 +05302307 io_request->CDB.EEDP32.PrimaryApplicationTagMask = cpu_to_be16(0xffff);
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302308 io_request->IoFlags = cpu_to_le16(32); /* Specify 32-byte cdb */
adam radford9c915a82010-12-21 13:34:31 -08002309
2310 /* Transfer length */
2311 cdb[28] = (u8)((num_blocks >> 24) & 0xff);
2312 cdb[29] = (u8)((num_blocks >> 16) & 0xff);
2313 cdb[30] = (u8)((num_blocks >> 8) & 0xff);
2314 cdb[31] = (u8)(num_blocks & 0xff);
2315
2316 /* set SCSI IO EEDPFlags */
Christoph Hellwig60ee6522018-10-10 19:31:25 +02002317 if (scp->sc_data_direction == DMA_FROM_DEVICE) {
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302318 io_request->EEDPFlags = cpu_to_le16(
adam radford9c915a82010-12-21 13:34:31 -08002319 MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
2320 MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
2321 MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP |
2322 MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG |
Sasikumar Chandrasekaran45d44602017-01-10 18:20:45 -05002323 MPI25_SCSIIO_EEDPFLAGS_DO_NOT_DISABLE_MODE |
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302324 MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD);
adam radford9c915a82010-12-21 13:34:31 -08002325 } else {
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302326 io_request->EEDPFlags = cpu_to_le16(
adam radford9c915a82010-12-21 13:34:31 -08002327 MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302328 MPI2_SCSIIO_EEDPFLAGS_INSERT_OP);
adam radford9c915a82010-12-21 13:34:31 -08002329 }
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302330 io_request->Control |= cpu_to_le32((0x4 << 26));
2331 io_request->EEDPBlockSize = cpu_to_le32(scp->device->sector_size);
adam radford9c915a82010-12-21 13:34:31 -08002332 } else {
2333 /* Some drives don't support 16/12 byte CDB's, convert to 10 */
2334 if (((cdb_len == 12) || (cdb_len == 16)) &&
2335 (start_blk <= 0xffffffff)) {
2336 if (cdb_len == 16) {
2337 opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10;
2338 flagvals = cdb[1];
2339 groupnum = cdb[14];
2340 control = cdb[15];
2341 } else {
2342 opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10;
2343 flagvals = cdb[1];
2344 groupnum = cdb[10];
2345 control = cdb[11];
2346 }
2347
2348 memset(cdb, 0, sizeof(io_request->CDB.CDB32));
2349
2350 cdb[0] = opcode;
2351 cdb[1] = flagvals;
2352 cdb[6] = groupnum;
2353 cdb[9] = control;
2354
2355 /* Transfer length */
2356 cdb[8] = (u8)(num_blocks & 0xff);
2357 cdb[7] = (u8)((num_blocks >> 8) & 0xff);
2358
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302359 io_request->IoFlags = cpu_to_le16(10); /* Specify 10-byte cdb */
adam radford9c915a82010-12-21 13:34:31 -08002360 cdb_len = 10;
adam radford495c5602011-05-11 18:34:40 -07002361 } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) {
2362 /* Convert to 16 byte CDB for large LBA's */
2363 switch (cdb_len) {
2364 case 6:
2365 opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16;
2366 control = cdb[5];
2367 break;
2368 case 10:
2369 opcode =
2370 cdb[0] == READ_10 ? READ_16 : WRITE_16;
2371 flagvals = cdb[1];
2372 groupnum = cdb[6];
2373 control = cdb[9];
2374 break;
2375 case 12:
2376 opcode =
2377 cdb[0] == READ_12 ? READ_16 : WRITE_16;
2378 flagvals = cdb[1];
2379 groupnum = cdb[10];
2380 control = cdb[11];
2381 break;
2382 }
2383
2384 memset(cdb, 0, sizeof(io_request->CDB.CDB32));
2385
2386 cdb[0] = opcode;
2387 cdb[1] = flagvals;
2388 cdb[14] = groupnum;
2389 cdb[15] = control;
2390
2391 /* Transfer length */
2392 cdb[13] = (u8)(num_blocks & 0xff);
2393 cdb[12] = (u8)((num_blocks >> 8) & 0xff);
2394 cdb[11] = (u8)((num_blocks >> 16) & 0xff);
2395 cdb[10] = (u8)((num_blocks >> 24) & 0xff);
2396
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302397 io_request->IoFlags = cpu_to_le16(16); /* Specify 16-byte cdb */
adam radford495c5602011-05-11 18:34:40 -07002398 cdb_len = 16;
adam radford9c915a82010-12-21 13:34:31 -08002399 }
2400
2401 /* Normal case, just load LBA here */
2402 switch (cdb_len) {
2403 case 6:
2404 {
2405 u8 val = cdb[1] & 0xE0;
2406 cdb[3] = (u8)(start_blk & 0xff);
2407 cdb[2] = (u8)((start_blk >> 8) & 0xff);
2408 cdb[1] = val | ((u8)(start_blk >> 16) & 0x1f);
2409 break;
2410 }
2411 case 10:
2412 cdb[5] = (u8)(start_blk & 0xff);
2413 cdb[4] = (u8)((start_blk >> 8) & 0xff);
2414 cdb[3] = (u8)((start_blk >> 16) & 0xff);
2415 cdb[2] = (u8)((start_blk >> 24) & 0xff);
2416 break;
2417 case 12:
2418 cdb[5] = (u8)(start_blk & 0xff);
2419 cdb[4] = (u8)((start_blk >> 8) & 0xff);
2420 cdb[3] = (u8)((start_blk >> 16) & 0xff);
2421 cdb[2] = (u8)((start_blk >> 24) & 0xff);
2422 break;
2423 case 16:
2424 cdb[9] = (u8)(start_blk & 0xff);
2425 cdb[8] = (u8)((start_blk >> 8) & 0xff);
2426 cdb[7] = (u8)((start_blk >> 16) & 0xff);
2427 cdb[6] = (u8)((start_blk >> 24) & 0xff);
2428 cdb[5] = (u8)((start_blk >> 32) & 0xff);
2429 cdb[4] = (u8)((start_blk >> 40) & 0xff);
2430 cdb[3] = (u8)((start_blk >> 48) & 0xff);
2431 cdb[2] = (u8)((start_blk >> 56) & 0xff);
2432 break;
2433 }
2434 }
2435}
2436
2437/**
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05002438 * megasas_stream_detect - stream detection on read and and write IOs
2439 * @instance: Adapter soft state
2440 * @cmd: Command to be prepared
2441 * @io_info: IO Request info
2442 *
2443 */
2444
2445/** stream detection on read and and write IOs */
2446static void megasas_stream_detect(struct megasas_instance *instance,
Shivasharan S41064f12017-02-10 00:59:37 -08002447 struct megasas_cmd_fusion *cmd,
2448 struct IO_REQUEST_INFO *io_info)
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05002449{
2450 struct fusion_context *fusion = instance->ctrl_context;
2451 u32 device_id = io_info->ldTgtId;
2452 struct LD_STREAM_DETECT *current_ld_sd
2453 = fusion->stream_detect_by_ld[device_id];
2454 u32 *track_stream = &current_ld_sd->mru_bit_map, stream_num;
2455 u32 shifted_values, unshifted_values;
2456 u32 index_value_mask, shifted_values_mask;
2457 int i;
2458 bool is_read_ahead = false;
2459 struct STREAM_DETECT *current_sd;
2460 /* find possible stream */
2461 for (i = 0; i < MAX_STREAMS_TRACKED; ++i) {
Shivasharan S41064f12017-02-10 00:59:37 -08002462 stream_num = (*track_stream >>
2463 (i * BITS_PER_INDEX_STREAM)) &
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05002464 STREAM_MASK;
2465 current_sd = &current_ld_sd->stream_track[stream_num];
Shivasharan S41064f12017-02-10 00:59:37 -08002466 /* if we found a stream, update the raid
2467 * context and also update the mruBitMap
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05002468 */
Shivasharan S41064f12017-02-10 00:59:37 -08002469 /* boundary condition */
2470 if ((current_sd->next_seq_lba) &&
2471 (io_info->ldStartBlock >= current_sd->next_seq_lba) &&
2472 (io_info->ldStartBlock <= (current_sd->next_seq_lba + 32)) &&
2473 (current_sd->is_read == io_info->isRead)) {
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05002474
Shivasharan S41064f12017-02-10 00:59:37 -08002475 if ((io_info->ldStartBlock != current_sd->next_seq_lba) &&
2476 ((!io_info->isRead) || (!is_read_ahead)))
2477 /*
2478 * Once the API availible we need to change this.
2479 * At this point we are not allowing any gap
2480 */
2481 continue;
2482
2483 SET_STREAM_DETECTED(cmd->io_request->RaidContext.raid_context_g35);
2484 current_sd->next_seq_lba =
2485 io_info->ldStartBlock + io_info->numBlocks;
2486 /*
2487 * update the mruBitMap LRU
2488 */
2489 shifted_values_mask =
2490 (1 << i * BITS_PER_INDEX_STREAM) - 1;
2491 shifted_values = ((*track_stream & shifted_values_mask)
2492 << BITS_PER_INDEX_STREAM);
2493 index_value_mask =
2494 STREAM_MASK << i * BITS_PER_INDEX_STREAM;
2495 unshifted_values =
2496 *track_stream & ~(shifted_values_mask |
2497 index_value_mask);
2498 *track_stream =
2499 unshifted_values | shifted_values | stream_num;
2500 return;
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05002501 }
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05002502 }
2503 /*
2504 * if we did not find any stream, create a new one
2505 * from the least recently used
2506 */
Shivasharan S41064f12017-02-10 00:59:37 -08002507 stream_num = (*track_stream >>
2508 ((MAX_STREAMS_TRACKED - 1) * BITS_PER_INDEX_STREAM)) &
2509 STREAM_MASK;
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05002510 current_sd = &current_ld_sd->stream_track[stream_num];
2511 current_sd->is_read = io_info->isRead;
2512 current_sd->next_seq_lba = io_info->ldStartBlock + io_info->numBlocks;
Shivasharan S41064f12017-02-10 00:59:37 -08002513 *track_stream = (((*track_stream & ZERO_LAST_STREAM) << 4) | stream_num);
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05002514 return;
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05002515}
2516
2517/**
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002518 * megasas_set_raidflag_cpu_affinity - This function sets the cpu
2519 * affinity (cpu of the controller) and raid_flags in the raid context
2520 * based on IO type.
2521 *
2522 * @praid_context: IO RAID context
2523 * @raid: LD raid map
2524 * @fp_possible: Is fast path possible?
2525 * @is_read: Is read IO?
2526 *
2527 */
2528static void
2529megasas_set_raidflag_cpu_affinity(union RAID_CONTEXT_UNION *praid_context,
2530 struct MR_LD_RAID *raid, bool fp_possible,
Shivasharan Sa48ba0e2017-02-10 00:59:13 -08002531 u8 is_read, u32 scsi_buff_len)
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002532{
2533 u8 cpu_sel = MR_RAID_CTX_CPUSEL_0;
2534 struct RAID_CONTEXT_G35 *rctx_g35;
2535
2536 rctx_g35 = &praid_context->raid_context_g35;
2537 if (fp_possible) {
2538 if (is_read) {
2539 if ((raid->cpuAffinity.pdRead.cpu0) &&
2540 (raid->cpuAffinity.pdRead.cpu1))
2541 cpu_sel = MR_RAID_CTX_CPUSEL_FCFS;
2542 else if (raid->cpuAffinity.pdRead.cpu1)
2543 cpu_sel = MR_RAID_CTX_CPUSEL_1;
2544 } else {
2545 if ((raid->cpuAffinity.pdWrite.cpu0) &&
2546 (raid->cpuAffinity.pdWrite.cpu1))
2547 cpu_sel = MR_RAID_CTX_CPUSEL_FCFS;
2548 else if (raid->cpuAffinity.pdWrite.cpu1)
2549 cpu_sel = MR_RAID_CTX_CPUSEL_1;
2550 /* Fast path cache by pass capable R0/R1 VD */
2551 if ((raid->level <= 1) &&
2552 (raid->capability.fp_cache_bypass_capable)) {
Shivasharan Sa174118b2017-02-10 00:59:21 -08002553 rctx_g35->routing_flags |=
2554 (1 << MR_RAID_CTX_ROUTINGFLAGS_SLD_SHIFT);
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002555 rctx_g35->raid_flags =
2556 (MR_RAID_FLAGS_IO_SUB_TYPE_CACHE_BYPASS
2557 << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT);
2558 }
2559 }
2560 } else {
2561 if (is_read) {
2562 if ((raid->cpuAffinity.ldRead.cpu0) &&
2563 (raid->cpuAffinity.ldRead.cpu1))
2564 cpu_sel = MR_RAID_CTX_CPUSEL_FCFS;
2565 else if (raid->cpuAffinity.ldRead.cpu1)
2566 cpu_sel = MR_RAID_CTX_CPUSEL_1;
2567 } else {
2568 if ((raid->cpuAffinity.ldWrite.cpu0) &&
2569 (raid->cpuAffinity.ldWrite.cpu1))
2570 cpu_sel = MR_RAID_CTX_CPUSEL_FCFS;
2571 else if (raid->cpuAffinity.ldWrite.cpu1)
2572 cpu_sel = MR_RAID_CTX_CPUSEL_1;
2573
Shivasharan Sa174118b2017-02-10 00:59:21 -08002574 if (is_stream_detected(rctx_g35) &&
Shivasharan S874d0252017-03-10 03:22:14 -08002575 ((raid->level == 5) || (raid->level == 6)) &&
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002576 (raid->writeMode == MR_RL_WRITE_THROUGH_MODE) &&
2577 (cpu_sel == MR_RAID_CTX_CPUSEL_FCFS))
2578 cpu_sel = MR_RAID_CTX_CPUSEL_0;
2579 }
2580 }
2581
Shivasharan Sa174118b2017-02-10 00:59:21 -08002582 rctx_g35->routing_flags |=
2583 (cpu_sel << MR_RAID_CTX_ROUTINGFLAGS_CPUSEL_SHIFT);
Shivasharan Sa48ba0e2017-02-10 00:59:13 -08002584
2585 /* Always give priority to MR_RAID_FLAGS_IO_SUB_TYPE_LDIO_BW_LIMIT
2586 * vs MR_RAID_FLAGS_IO_SUB_TYPE_CACHE_BYPASS.
2587 * IO Subtype is not bitmap.
2588 */
2589 if ((raid->level == 1) && (!is_read)) {
2590 if (scsi_buff_len > MR_LARGE_IO_MIN_SIZE)
2591 praid_context->raid_context_g35.raid_flags =
2592 (MR_RAID_FLAGS_IO_SUB_TYPE_LDIO_BW_LIMIT
2593 << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT);
2594 }
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002595}
2596
2597/**
adam radford9c915a82010-12-21 13:34:31 -08002598 * megasas_build_ldio_fusion - Prepares IOs to devices
2599 * @instance: Adapter soft state
2600 * @scp: SCSI command
2601 * @cmd: Command to be prepared
2602 *
2603 * Prepares the io_request and chain elements (sg_frame) for IO
2604 * The IO can be for PD (Fast Path) or LD
2605 */
2606void
2607megasas_build_ldio_fusion(struct megasas_instance *instance,
2608 struct scsi_cmnd *scp,
2609 struct megasas_cmd_fusion *cmd)
2610{
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002611 bool fp_possible;
2612 u16 ld;
2613 u32 start_lba_lo, start_lba_hi, device_id, datalength = 0;
2614 u32 scsi_buff_len;
adam radford9c915a82010-12-21 13:34:31 -08002615 struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
2616 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
2617 struct IO_REQUEST_INFO io_info;
2618 struct fusion_context *fusion;
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05302619 struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
adam radford21c9e162013-09-06 15:27:14 -07002620 u8 *raidLUN;
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05002621 unsigned long spinlock_flags;
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002622 struct MR_LD_RAID *raid = NULL;
2623 struct MR_PRIV_DEVICE *mrdev_priv;
Shivasharan S9e770182018-10-16 23:37:49 -07002624 struct RAID_CONTEXT *rctx;
2625 struct RAID_CONTEXT_G35 *rctx_g35;
adam radford9c915a82010-12-21 13:34:31 -08002626
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302627 device_id = MEGASAS_DEV_INDEX(scp);
adam radford9c915a82010-12-21 13:34:31 -08002628
2629 fusion = instance->ctrl_context;
2630
2631 io_request = cmd->io_request;
Shivasharan S9e770182018-10-16 23:37:49 -07002632 rctx = &io_request->RaidContext.raid_context;
2633 rctx_g35 = &io_request->RaidContext.raid_context_g35;
2634
2635 rctx->virtual_disk_tgt_id = cpu_to_le16(device_id);
2636 rctx->status = 0;
2637 rctx->ex_status = 0;
adam radford9c915a82010-12-21 13:34:31 -08002638
2639 req_desc = (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)cmd->request_desc;
2640
2641 start_lba_lo = 0;
2642 start_lba_hi = 0;
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002643 fp_possible = false;
adam radford9c915a82010-12-21 13:34:31 -08002644
2645 /*
2646 * 6-byte READ(0x08) or WRITE(0x0A) cdb
2647 */
2648 if (scp->cmd_len == 6) {
adam radfordf9eff812012-10-01 19:27:07 -07002649 datalength = (u32) scp->cmnd[4];
adam radford9c915a82010-12-21 13:34:31 -08002650 start_lba_lo = ((u32) scp->cmnd[1] << 16) |
2651 ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3];
2652
2653 start_lba_lo &= 0x1FFFFF;
2654 }
2655
2656 /*
2657 * 10-byte READ(0x28) or WRITE(0x2A) cdb
2658 */
2659 else if (scp->cmd_len == 10) {
adam radfordf9eff812012-10-01 19:27:07 -07002660 datalength = (u32) scp->cmnd[8] |
adam radford9c915a82010-12-21 13:34:31 -08002661 ((u32) scp->cmnd[7] << 8);
2662 start_lba_lo = ((u32) scp->cmnd[2] << 24) |
2663 ((u32) scp->cmnd[3] << 16) |
2664 ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
2665 }
2666
2667 /*
2668 * 12-byte READ(0xA8) or WRITE(0xAA) cdb
2669 */
2670 else if (scp->cmd_len == 12) {
adam radfordf9eff812012-10-01 19:27:07 -07002671 datalength = ((u32) scp->cmnd[6] << 24) |
adam radford9c915a82010-12-21 13:34:31 -08002672 ((u32) scp->cmnd[7] << 16) |
2673 ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
2674 start_lba_lo = ((u32) scp->cmnd[2] << 24) |
2675 ((u32) scp->cmnd[3] << 16) |
2676 ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
2677 }
2678
2679 /*
2680 * 16-byte READ(0x88) or WRITE(0x8A) cdb
2681 */
2682 else if (scp->cmd_len == 16) {
adam radfordf9eff812012-10-01 19:27:07 -07002683 datalength = ((u32) scp->cmnd[10] << 24) |
adam radford9c915a82010-12-21 13:34:31 -08002684 ((u32) scp->cmnd[11] << 16) |
2685 ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13];
2686 start_lba_lo = ((u32) scp->cmnd[6] << 24) |
2687 ((u32) scp->cmnd[7] << 16) |
2688 ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
2689
2690 start_lba_hi = ((u32) scp->cmnd[2] << 24) |
2691 ((u32) scp->cmnd[3] << 16) |
2692 ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
2693 }
2694
2695 memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO));
2696 io_info.ldStartBlock = ((u64)start_lba_hi << 32) | start_lba_lo;
adam radfordf9eff812012-10-01 19:27:07 -07002697 io_info.numBlocks = datalength;
adam radford9c915a82010-12-21 13:34:31 -08002698 io_info.ldTgtId = device_id;
Shivasharan S8bf7c652017-02-10 00:59:03 -08002699 io_info.r1_alt_dev_handle = MR_DEVHANDLE_INVALID;
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002700 scsi_buff_len = scsi_bufflen(scp);
2701 io_request->DataLength = cpu_to_le32(scsi_buff_len);
adam radford9c915a82010-12-21 13:34:31 -08002702
Christoph Hellwig60ee6522018-10-10 19:31:25 +02002703 if (scp->sc_data_direction == DMA_FROM_DEVICE)
adam radford9c915a82010-12-21 13:34:31 -08002704 io_info.isRead = 1;
2705
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05302706 local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05002707 ld = MR_TargetIdToLdGet(device_id, local_map_ptr);
adam radford9c915a82010-12-21 13:34:31 -08002708
Shivasharan Sd2d03582017-02-10 00:59:19 -08002709 if (ld < instance->fw_supported_vd_count)
2710 raid = MR_LdRaidGet(ld, local_map_ptr);
2711
2712 if (!raid || (!fusion->fast_path_io)) {
Shivasharan S9e770182018-10-16 23:37:49 -07002713 rctx->reg_lock_flags = 0;
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002714 fp_possible = false;
adam radford9c915a82010-12-21 13:34:31 -08002715 } else {
Shivasharan S9e770182018-10-16 23:37:49 -07002716 if (MR_BuildRaidContext(instance, &io_info, rctx,
adam radford21c9e162013-09-06 15:27:14 -07002717 local_map_ptr, &raidLUN))
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002718 fp_possible = (io_info.fpOkForIo > 0) ? true : false;
adam radford9c915a82010-12-21 13:34:31 -08002719 }
2720
Ming Leiadbe5522018-03-13 17:42:40 +08002721 cmd->request_desc->SCSIIO.MSIxIndex =
2722 instance->reply_map[raw_smp_processor_id()];
adam radfordc8e858f2011-10-08 18:15:13 -07002723
Shivasharan S630d42b2018-12-17 00:47:37 -08002724 if (instance->adapter_type >= VENTURA_SERIES) {
Shivasharan Sa48ba0e2017-02-10 00:59:13 -08002725 /* FP for Optimal raid level 1.
2726 * All large RAID-1 writes (> 32 KiB, both WT and WB modes)
2727 * are built by the driver as LD I/Os.
2728 * All small RAID-1 WT writes (<= 32 KiB) are built as FP I/Os
2729 * (there is never a reason to process these as buffered writes)
2730 * All small RAID-1 WB writes (<= 32 KiB) are built as FP I/Os
2731 * with the SLD bit asserted.
2732 */
Shivasharan S8bf7c652017-02-10 00:59:03 -08002733 if (io_info.r1_alt_dev_handle != MR_DEVHANDLE_INVALID) {
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002734 mrdev_priv = scp->device->hostdata;
2735
2736 if (atomic_inc_return(&instance->fw_outstanding) >
2737 (instance->host->can_queue)) {
2738 fp_possible = false;
2739 atomic_dec(&instance->fw_outstanding);
Shivasharan Sa48ba0e2017-02-10 00:59:13 -08002740 } else if ((scsi_buff_len > MR_LARGE_IO_MIN_SIZE) ||
Shivasharan S49524b32017-03-10 03:22:13 -08002741 (atomic_dec_if_positive(&mrdev_priv->r1_ldio_hint) > 0)) {
Shivasharan Sa48ba0e2017-02-10 00:59:13 -08002742 fp_possible = false;
2743 atomic_dec(&instance->fw_outstanding);
2744 if (scsi_buff_len > MR_LARGE_IO_MIN_SIZE)
2745 atomic_set(&mrdev_priv->r1_ldio_hint,
2746 instance->r1_ldio_hint_default);
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002747 }
2748 }
2749
Shivasharan S4959e612018-01-05 05:27:45 -08002750 if (!fp_possible ||
2751 (io_info.isRead && io_info.ra_capable)) {
2752 spin_lock_irqsave(&instance->stream_lock,
2753 spinlock_flags);
2754 megasas_stream_detect(instance, cmd, &io_info);
2755 spin_unlock_irqrestore(&instance->stream_lock,
2756 spinlock_flags);
2757 /* In ventura if stream detected for a read and it is
2758 * read ahead capable make this IO as LDIO
2759 */
Shivasharan S9e770182018-10-16 23:37:49 -07002760 if (is_stream_detected(rctx_g35))
Shivasharan S4959e612018-01-05 05:27:45 -08002761 fp_possible = false;
2762 }
2763
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002764 /* If raid is NULL, set CPU affinity to default CPU0 */
2765 if (raid)
Shivasharan S9e770182018-10-16 23:37:49 -07002766 megasas_set_raidflag_cpu_affinity(&io_request->RaidContext,
Shivasharan Sa48ba0e2017-02-10 00:59:13 -08002767 raid, fp_possible, io_info.isRead,
2768 scsi_buff_len);
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002769 else
Shivasharan S9e770182018-10-16 23:37:49 -07002770 rctx_g35->routing_flags |=
Shivasharan Sa174118b2017-02-10 00:59:21 -08002771 (MR_RAID_CTX_CPUSEL_0 << MR_RAID_CTX_ROUTINGFLAGS_CPUSEL_SHIFT);
Shivasharan Sf6c0d552017-02-10 00:59:02 -08002772 }
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05002773
adam radford9c915a82010-12-21 13:34:31 -08002774 if (fp_possible) {
2775 megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp,
2776 local_map_ptr, start_lba_lo);
adam radford9c915a82010-12-21 13:34:31 -08002777 io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
2778 cmd->request_desc->SCSIIO.RequestFlags =
Sumit Saxena2c048352016-01-28 21:04:24 +05302779 (MPI2_REQ_DESCRIPT_FLAGS_FP_IO
adam radford9c915a82010-12-21 13:34:31 -08002780 << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
Shivasharan Sc3651782017-10-19 02:48:48 -07002781 if (instance->adapter_type == INVADER_SERIES) {
Shivasharan S9e770182018-10-16 23:37:49 -07002782 if (rctx->reg_lock_flags == REGION_TYPE_UNUSED)
adam radford36807e62011-10-08 18:15:06 -07002783 cmd->request_desc->SCSIIO.RequestFlags =
2784 (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
2785 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
Shivasharan S9e770182018-10-16 23:37:49 -07002786 rctx->type = MPI2_TYPE_CUDA;
2787 rctx->nseg = 0x1;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302788 io_request->IoFlags |= cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH);
Shivasharan S9e770182018-10-16 23:37:49 -07002789 rctx->reg_lock_flags |=
adam radford36807e62011-10-08 18:15:06 -07002790 (MR_RL_FLAGS_GRANT_DESTINATION_CUDA |
2791 MR_RL_FLAGS_SEQ_NUM_ENABLE);
Shivasharan S630d42b2018-12-17 00:47:37 -08002792 } else if (instance->adapter_type >= VENTURA_SERIES) {
Shivasharan S9e770182018-10-16 23:37:49 -07002793 rctx_g35->nseg_type |= (1 << RAID_CONTEXT_NSEG_SHIFT);
2794 rctx_g35->nseg_type |= (MPI2_TYPE_CUDA << RAID_CONTEXT_TYPE_SHIFT);
2795 rctx_g35->routing_flags |= (1 << MR_RAID_CTX_ROUTINGFLAGS_SQN_SHIFT);
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05002796 io_request->IoFlags |=
Shivasharan Sa174118b2017-02-10 00:59:21 -08002797 cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH);
adam radford36807e62011-10-08 18:15:06 -07002798 }
Shivasharan S5fc499b2017-02-10 00:59:17 -08002799 if (fusion->load_balance_info &&
2800 (fusion->load_balance_info[device_id].loadBalanceFlag) &&
2801 (io_info.isRead)) {
adam radford9c915a82010-12-21 13:34:31 -08002802 io_info.devHandle =
Sumit.Saxena@avagotech.comd2552eb2014-09-12 18:57:53 +05302803 get_updated_dev_handle(instance,
adam radford9c915a82010-12-21 13:34:31 -08002804 &fusion->load_balance_info[device_id],
Shivasharan S33203bc2017-02-10 00:59:12 -08002805 &io_info, local_map_ptr);
adam radford9c915a82010-12-21 13:34:31 -08002806 scp->SCp.Status |= MEGASAS_LOAD_BALANCE_FLAG;
Sumit.Saxena@avagotech.comd2552eb2014-09-12 18:57:53 +05302807 cmd->pd_r1_lb = io_info.pd_after_lb;
Shivasharan S630d42b2018-12-17 00:47:37 -08002808 if (instance->adapter_type >= VENTURA_SERIES)
Shivasharan S9e770182018-10-16 23:37:49 -07002809 rctx_g35->span_arm = io_info.span_arm;
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05002810 else
Shivasharan S9e770182018-10-16 23:37:49 -07002811 rctx->span_arm = io_info.span_arm;
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05002812
adam radford9c915a82010-12-21 13:34:31 -08002813 } else
2814 scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG;
Sumit.Saxena@avagotech.com5765c5b2015-04-23 16:32:09 +05302815
Shivasharan S630d42b2018-12-17 00:47:37 -08002816 if (instance->adapter_type >= VENTURA_SERIES)
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05002817 cmd->r1_alt_dev_handle = io_info.r1_alt_dev_handle;
Shivasharan S8bf7c652017-02-10 00:59:03 -08002818 else
2819 cmd->r1_alt_dev_handle = MR_DEVHANDLE_INVALID;
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05002820
Sumit.Saxena@avagotech.com5765c5b2015-04-23 16:32:09 +05302821 if ((raidLUN[0] == 1) &&
sumit.saxena@avagotech.com75b96061e2015-08-31 17:24:01 +05302822 (local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].validHandles > 1)) {
Sumit.Saxena@avagotech.com5765c5b2015-04-23 16:32:09 +05302823 instance->dev_handle = !(instance->dev_handle);
2824 io_info.devHandle =
2825 local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].devHandle[instance->dev_handle];
2826 }
2827
adam radford9c915a82010-12-21 13:34:31 -08002828 cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle;
2829 io_request->DevHandle = io_info.devHandle;
Shivasharan S33203bc2017-02-10 00:59:12 -08002830 cmd->pd_interface = io_info.pd_interface;
adam radford21c9e162013-09-06 15:27:14 -07002831 /* populate the LUN field */
2832 memcpy(io_request->LUN, raidLUN, 8);
adam radford9c915a82010-12-21 13:34:31 -08002833 } else {
Shivasharan S9e770182018-10-16 23:37:49 -07002834 rctx->timeout_value =
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302835 cpu_to_le16(local_map_ptr->raidMap.fpPdIoTimeoutSec);
adam radford9c915a82010-12-21 13:34:31 -08002836 cmd->request_desc->SCSIIO.RequestFlags =
2837 (MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO
2838 << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
Shivasharan Sc3651782017-10-19 02:48:48 -07002839 if (instance->adapter_type == INVADER_SERIES) {
Sumit Saxena8f050242016-01-28 21:04:27 +05302840 if (io_info.do_fp_rlbypass ||
Shivasharan S9e770182018-10-16 23:37:49 -07002841 (rctx->reg_lock_flags == REGION_TYPE_UNUSED))
adam radford36807e62011-10-08 18:15:06 -07002842 cmd->request_desc->SCSIIO.RequestFlags =
2843 (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
2844 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
Shivasharan S9e770182018-10-16 23:37:49 -07002845 rctx->type = MPI2_TYPE_CUDA;
2846 rctx->reg_lock_flags |=
adam radford36807e62011-10-08 18:15:06 -07002847 (MR_RL_FLAGS_GRANT_DESTINATION_CPU0 |
Shivasharan S9e770182018-10-16 23:37:49 -07002848 MR_RL_FLAGS_SEQ_NUM_ENABLE);
2849 rctx->nseg = 0x1;
Shivasharan S630d42b2018-12-17 00:47:37 -08002850 } else if (instance->adapter_type >= VENTURA_SERIES) {
Shivasharan S9e770182018-10-16 23:37:49 -07002851 rctx_g35->routing_flags |= (1 << MR_RAID_CTX_ROUTINGFLAGS_SQN_SHIFT);
2852 rctx_g35->nseg_type |= (1 << RAID_CONTEXT_NSEG_SHIFT);
2853 rctx_g35->nseg_type |= (MPI2_TYPE_CUDA << RAID_CONTEXT_TYPE_SHIFT);
adam radford36807e62011-10-08 18:15:06 -07002854 }
2855 io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302856 io_request->DevHandle = cpu_to_le16(device_id);
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05002857
adam radford9c915a82010-12-21 13:34:31 -08002858 } /* Not FP */
2859}
2860
2861/**
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302862 * megasas_build_ld_nonrw_fusion - prepares non rw ios for virtual disk
adam radford9c915a82010-12-21 13:34:31 -08002863 * @instance: Adapter soft state
2864 * @scp: SCSI command
2865 * @cmd: Command to be prepared
2866 *
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302867 * Prepares the io_request frame for non-rw io cmds for vd.
adam radford9c915a82010-12-21 13:34:31 -08002868 */
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302869static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance,
2870 struct scsi_cmnd *scmd, struct megasas_cmd_fusion *cmd)
adam radford9c915a82010-12-21 13:34:31 -08002871{
2872 u32 device_id;
2873 struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
Shivasharan S25fb13d2017-02-10 00:59:29 -08002874 u16 ld;
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05302875 struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
adam radford9c915a82010-12-21 13:34:31 -08002876 struct fusion_context *fusion = instance->ctrl_context;
adam radford21c9e162013-09-06 15:27:14 -07002877 u8 span, physArm;
Christoph Hellwig9ab9ed382015-04-23 16:32:54 +05302878 __le16 devHandle;
Shivasharan Sd2d03582017-02-10 00:59:19 -08002879 u32 arRef, pd;
adam radford21c9e162013-09-06 15:27:14 -07002880 struct MR_LD_RAID *raid;
2881 struct RAID_CONTEXT *pRAID_Context;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302882 u8 fp_possible = 1;
adam radford9c915a82010-12-21 13:34:31 -08002883
2884 io_request = cmd->io_request;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302885 device_id = MEGASAS_DEV_INDEX(scmd);
Sumit.Saxena@avagotech.com51087a82014-09-12 18:57:33 +05302886 local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05302887 io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302888 /* get RAID_Context pointer */
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05002889 pRAID_Context = &io_request->RaidContext.raid_context;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302890 /* Check with FW team */
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05002891 pRAID_Context->virtual_disk_tgt_id = cpu_to_le16(device_id);
2892 pRAID_Context->reg_lock_row_lba = 0;
2893 pRAID_Context->reg_lock_length = 0;
adam radford21c9e162013-09-06 15:27:14 -07002894
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302895 if (fusion->fast_path_io && (
2896 device_id < instance->fw_supported_vd_count)) {
Sumit.Saxena@avagotech.comab2f0602015-01-05 20:06:08 +05302897
adam radford21c9e162013-09-06 15:27:14 -07002898 ld = MR_TargetIdToLdGet(device_id, local_map_ptr);
Sumit.Saxena@avagotech.comab2f0602015-01-05 20:06:08 +05302899 if (ld >= instance->fw_supported_vd_count)
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302900 fp_possible = 0;
Shivasharan Sd2d03582017-02-10 00:59:19 -08002901 else {
2902 raid = MR_LdRaidGet(ld, local_map_ptr);
2903 if (!(raid->capability.fpNonRWCapable))
2904 fp_possible = 0;
2905 }
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302906 } else
2907 fp_possible = 0;
adam radford21c9e162013-09-06 15:27:14 -07002908
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302909 if (!fp_possible) {
2910 io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
2911 io_request->DevHandle = cpu_to_le16(device_id);
2912 io_request->LUN[1] = scmd->device->lun;
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05002913 pRAID_Context->timeout_value =
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302914 cpu_to_le16 (scmd->request->timeout / HZ);
2915 cmd->request_desc->SCSIIO.RequestFlags =
2916 (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
2917 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
2918 } else {
adam radford21c9e162013-09-06 15:27:14 -07002919
2920 /* set RAID context values */
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05002921 pRAID_Context->config_seq_num = raid->seqNum;
Shivasharan S630d42b2018-12-17 00:47:37 -08002922 if (instance->adapter_type < VENTURA_SERIES)
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05002923 pRAID_Context->reg_lock_flags = REGION_TYPE_SHARED_READ;
2924 pRAID_Context->timeout_value =
2925 cpu_to_le16(raid->fpIoTimeoutForLd);
adam radford21c9e162013-09-06 15:27:14 -07002926
2927 /* get the DevHandle for the PD (since this is
2928 fpNonRWCapable, this is a single disk RAID0) */
2929 span = physArm = 0;
2930 arRef = MR_LdSpanArrayGet(ld, span, local_map_ptr);
2931 pd = MR_ArPdGet(arRef, physArm, local_map_ptr);
2932 devHandle = MR_PdDevHandleGet(pd, local_map_ptr);
2933
2934 /* build request descriptor */
2935 cmd->request_desc->SCSIIO.RequestFlags =
Sumit Saxena2c048352016-01-28 21:04:24 +05302936 (MPI2_REQ_DESCRIPT_FLAGS_FP_IO <<
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302937 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
adam radford21c9e162013-09-06 15:27:14 -07002938 cmd->request_desc->SCSIIO.DevHandle = devHandle;
2939
2940 /* populate the LUN field */
2941 memcpy(io_request->LUN, raid->LUN, 8);
2942
2943 /* build the raidScsiIO structure */
2944 io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
2945 io_request->DevHandle = devHandle;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302946 }
2947}
adam radford21c9e162013-09-06 15:27:14 -07002948
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302949/**
2950 * megasas_build_syspd_fusion - prepares rw/non-rw ios for syspd
2951 * @instance: Adapter soft state
2952 * @scp: SCSI command
2953 * @cmd: Command to be prepared
2954 * @fp_possible: parameter to detect fast path or firmware path io.
2955 *
2956 * Prepares the io_request frame for rw/non-rw io cmds for syspds
2957 */
2958static void
2959megasas_build_syspd_fusion(struct megasas_instance *instance,
Shivasharan S1d6dbd12017-02-10 00:59:30 -08002960 struct scsi_cmnd *scmd, struct megasas_cmd_fusion *cmd,
2961 bool fp_possible)
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302962{
2963 u32 device_id;
2964 struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
2965 u16 pd_index = 0;
2966 u16 os_timeout_value;
2967 u16 timeout_limit;
2968 struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
2969 struct RAID_CONTEXT *pRAID_Context;
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05302970 struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync;
Shivasharan S33203bc2017-02-10 00:59:12 -08002971 struct MR_PRIV_DEVICE *mr_device_priv_data;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302972 struct fusion_context *fusion = instance->ctrl_context;
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05302973 pd_sync = (void *)fusion->pd_seq_sync[(instance->pd_seq_map_id - 1) & 1];
adam radford21c9e162013-09-06 15:27:14 -07002974
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302975 device_id = MEGASAS_DEV_INDEX(scmd);
2976 pd_index = MEGASAS_PD_INDEX(scmd);
2977 os_timeout_value = scmd->request->timeout / HZ;
Shivasharan S33203bc2017-02-10 00:59:12 -08002978 mr_device_priv_data = scmd->device->hostdata;
2979 cmd->pd_interface = mr_device_priv_data->interface_type;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302980
2981 io_request = cmd->io_request;
2982 /* get RAID_Context pointer */
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05002983 pRAID_Context = &io_request->RaidContext.raid_context;
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05002984 pRAID_Context->reg_lock_flags = 0;
2985 pRAID_Context->reg_lock_row_lba = 0;
2986 pRAID_Context->reg_lock_length = 0;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302987 io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
2988 io_request->LUN[1] = scmd->device->lun;
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05002989 pRAID_Context->raid_flags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05302990 << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT;
2991
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05302992 /* If FW supports PD sequence number */
2993 if (instance->use_seqnum_jbod_fp &&
2994 instance->pd_list[pd_index].driveType == TYPE_DISK) {
2995 /* TgtId must be incremented by 255 as jbod seq number is index
2996 * below raid map
2997 */
Sasikumar Chandrasekaranede7c3c2017-01-10 18:20:52 -05002998 /* More than 256 PD/JBOD support for Ventura */
2999 if (instance->support_morethan256jbod)
3000 pRAID_Context->virtual_disk_tgt_id =
3001 pd_sync->seq[pd_index].pd_target_id;
3002 else
Shivasharan Sa174118b2017-02-10 00:59:21 -08003003 pRAID_Context->virtual_disk_tgt_id =
3004 cpu_to_le16(device_id + (MAX_PHYSICAL_DEVICES - 1));
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05003005 pRAID_Context->config_seq_num = pd_sync->seq[pd_index].seqNum;
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05303006 io_request->DevHandle = pd_sync->seq[pd_index].devHandle;
Shivasharan S630d42b2018-12-17 00:47:37 -08003007 if (instance->adapter_type >= VENTURA_SERIES) {
Shivasharan Sa174118b2017-02-10 00:59:21 -08003008 io_request->RaidContext.raid_context_g35.routing_flags |=
3009 (1 << MR_RAID_CTX_ROUTINGFLAGS_SQN_SHIFT);
3010 io_request->RaidContext.raid_context_g35.nseg_type |=
3011 (1 << RAID_CONTEXT_NSEG_SHIFT);
3012 io_request->RaidContext.raid_context_g35.nseg_type |=
3013 (MPI2_TYPE_CUDA << RAID_CONTEXT_TYPE_SHIFT);
3014 } else {
3015 pRAID_Context->type = MPI2_TYPE_CUDA;
3016 pRAID_Context->nseg = 0x1;
3017 pRAID_Context->reg_lock_flags |=
3018 (MR_RL_FLAGS_SEQ_NUM_ENABLE|MR_RL_FLAGS_GRANT_DESTINATION_CUDA);
3019 }
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05303020 } else if (fusion->fast_path_io) {
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05003021 pRAID_Context->virtual_disk_tgt_id = cpu_to_le16(device_id);
3022 pRAID_Context->config_seq_num = 0;
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05303023 local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
3024 io_request->DevHandle =
3025 local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
3026 } else {
3027 /* Want to send all IO via FW path */
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05003028 pRAID_Context->virtual_disk_tgt_id = cpu_to_le16(device_id);
3029 pRAID_Context->config_seq_num = 0;
Sumit Saxena9fb74c42015-11-05 21:17:38 +05303030 io_request->DevHandle = cpu_to_le16(0xFFFF);
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05303031 }
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303032
3033 cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303034
Ming Leiadbe5522018-03-13 17:42:40 +08003035 cmd->request_desc->SCSIIO.MSIxIndex =
3036 instance->reply_map[raw_smp_processor_id()];
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303037
3038 if (!fp_possible) {
3039 /* system pd firmware path */
adam radford9c915a82010-12-21 13:34:31 -08003040 io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
adam radford9c915a82010-12-21 13:34:31 -08003041 cmd->request_desc->SCSIIO.RequestFlags =
3042 (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303043 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05003044 pRAID_Context->timeout_value = cpu_to_le16(os_timeout_value);
3045 pRAID_Context->virtual_disk_tgt_id = cpu_to_le16(device_id);
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303046 } else {
Shivasharan S3239b8c2018-04-06 02:02:11 -07003047 if (os_timeout_value)
3048 os_timeout_value++;
3049
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303050 /* system pd Fast Path */
3051 io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303052 timeout_limit = (scmd->device->type == TYPE_DISK) ?
3053 255 : 0xFFFF;
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05003054 pRAID_Context->timeout_value =
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303055 cpu_to_le16((os_timeout_value > timeout_limit) ?
3056 timeout_limit : os_timeout_value);
Shivasharan Sc3651782017-10-19 02:48:48 -07003057 if (instance->adapter_type >= INVADER_SERIES)
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303058 io_request->IoFlags |=
3059 cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH);
Kashyap Desaid5573582016-10-21 06:33:35 -07003060
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303061 cmd->request_desc->SCSIIO.RequestFlags =
Sumit Saxena2c048352016-01-28 21:04:24 +05303062 (MPI2_REQ_DESCRIPT_FLAGS_FP_IO <<
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303063 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
adam radford9c915a82010-12-21 13:34:31 -08003064 }
adam radford9c915a82010-12-21 13:34:31 -08003065}
3066
3067/**
3068 * megasas_build_io_fusion - Prepares IOs to devices
3069 * @instance: Adapter soft state
3070 * @scp: SCSI command
3071 * @cmd: Command to be prepared
3072 *
3073 * Invokes helper functions to prepare request frames
3074 * and sets flags appropriate for IO/Non-IO cmd
3075 */
3076int
3077megasas_build_io_fusion(struct megasas_instance *instance,
3078 struct scsi_cmnd *scp,
3079 struct megasas_cmd_fusion *cmd)
3080{
Shivasharan S33203bc2017-02-10 00:59:12 -08003081 int sge_count;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303082 u8 cmd_type;
adam radford9c915a82010-12-21 13:34:31 -08003083 struct MPI2_RAID_SCSI_IO_REQUEST *io_request = cmd->io_request;
Shivasharan S1d6dbd12017-02-10 00:59:30 -08003084 struct MR_PRIV_DEVICE *mr_device_priv_data;
3085 mr_device_priv_data = scp->device->hostdata;
adam radford9c915a82010-12-21 13:34:31 -08003086
adam radford9c915a82010-12-21 13:34:31 -08003087 /* Zero out some fields so they don't get reused */
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02003088 memset(io_request->LUN, 0x0, 8);
adam radford9c915a82010-12-21 13:34:31 -08003089 io_request->CDB.EEDP32.PrimaryReferenceTag = 0;
3090 io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0;
3091 io_request->EEDPFlags = 0;
3092 io_request->Control = 0;
3093 io_request->EEDPBlockSize = 0;
adam radford36807e62011-10-08 18:15:06 -07003094 io_request->ChainOffset = 0;
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05003095 io_request->RaidContext.raid_context.raid_flags = 0;
3096 io_request->RaidContext.raid_context.type = 0;
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05003097 io_request->RaidContext.raid_context.nseg = 0;
adam radford9c915a82010-12-21 13:34:31 -08003098
3099 memcpy(io_request->CDB.CDB32, scp->cmnd, scp->cmd_len);
3100 /*
3101 * Just the CDB length,rest of the Flags are zero
3102 * This will be modified for FP in build_ldio_fusion
3103 */
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05303104 io_request->IoFlags = cpu_to_le16(scp->cmd_len);
adam radford9c915a82010-12-21 13:34:31 -08003105
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303106 switch (cmd_type = megasas_cmd_type(scp)) {
3107 case READ_WRITE_LDIO:
adam radford9c915a82010-12-21 13:34:31 -08003108 megasas_build_ldio_fusion(instance, scp, cmd);
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303109 break;
3110 case NON_READ_WRITE_LDIO:
3111 megasas_build_ld_nonrw_fusion(instance, scp, cmd);
3112 break;
3113 case READ_WRITE_SYSPDIO:
Shivasharan S1d6dbd12017-02-10 00:59:30 -08003114 megasas_build_syspd_fusion(instance, scp, cmd, true);
3115 break;
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303116 case NON_READ_WRITE_SYSPDIO:
Shivasharan S1d6dbd12017-02-10 00:59:30 -08003117 if (instance->secure_jbod_support ||
3118 mr_device_priv_data->is_tm_capable)
3119 megasas_build_syspd_fusion(instance, scp, cmd, false);
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303120 else
Shivasharan S1d6dbd12017-02-10 00:59:30 -08003121 megasas_build_syspd_fusion(instance, scp, cmd, true);
Sumit.Saxena@avagotech.com4a5c8142015-04-23 16:30:39 +05303122 break;
3123 default:
3124 break;
3125 }
adam radford9c915a82010-12-21 13:34:31 -08003126
3127 /*
3128 * Construct SGL
3129 */
3130
Shivasharan S33203bc2017-02-10 00:59:12 -08003131 sge_count = megasas_make_sgl(instance, scp, cmd);
adam radford9c915a82010-12-21 13:34:31 -08003132
Shivasharan S33203bc2017-02-10 00:59:12 -08003133 if (sge_count > instance->max_num_sge || (sge_count < 0)) {
3134 dev_err(&instance->pdev->dev,
3135 "%s %d sge_count (%d) is out of range. Range is: 0-%d\n",
3136 __func__, __LINE__, sge_count, instance->max_num_sge);
adam radford9c915a82010-12-21 13:34:31 -08003137 return 1;
3138 }
3139
Shivasharan S630d42b2018-12-17 00:47:37 -08003140 if (instance->adapter_type >= VENTURA_SERIES) {
Shivasharan Sa174118b2017-02-10 00:59:21 -08003141 set_num_sge(&io_request->RaidContext.raid_context_g35, sge_count);
3142 cpu_to_le16s(&io_request->RaidContext.raid_context_g35.routing_flags);
3143 cpu_to_le16s(&io_request->RaidContext.raid_context_g35.nseg_type);
3144 } else {
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05003145 /* numSGE store lower 8 bit of sge_count.
3146 * numSGEExt store higher 8 bit of sge_count
3147 */
3148 io_request->RaidContext.raid_context.num_sge = sge_count;
3149 io_request->RaidContext.raid_context.num_sge_ext =
3150 (u8)(sge_count >> 8);
3151 }
adam radford9c915a82010-12-21 13:34:31 -08003152
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05303153 io_request->SGLFlags = cpu_to_le16(MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
adam radford9c915a82010-12-21 13:34:31 -08003154
Christoph Hellwig60ee6522018-10-10 19:31:25 +02003155 if (scp->sc_data_direction == DMA_TO_DEVICE)
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05303156 io_request->Control |= cpu_to_le32(MPI2_SCSIIO_CONTROL_WRITE);
Christoph Hellwig60ee6522018-10-10 19:31:25 +02003157 else if (scp->sc_data_direction == DMA_FROM_DEVICE)
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05303158 io_request->Control |= cpu_to_le32(MPI2_SCSIIO_CONTROL_READ);
adam radford9c915a82010-12-21 13:34:31 -08003159
3160 io_request->SGLOffset0 =
3161 offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL) / 4;
3162
Shivasharan S107a60d2017-10-19 02:49:05 -07003163 io_request->SenseBufferLowAddress =
3164 cpu_to_le32(lower_32_bits(cmd->sense_phys_addr));
adam radford9c915a82010-12-21 13:34:31 -08003165 io_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
3166
3167 cmd->scmd = scp;
3168 scp->SCp.ptr = (char *)cmd;
3169
3170 return 0;
3171}
3172
Shivasharan S52205ac2017-02-10 00:59:08 -08003173static union MEGASAS_REQUEST_DESCRIPTOR_UNION *
adam radford9c915a82010-12-21 13:34:31 -08003174megasas_get_request_descriptor(struct megasas_instance *instance, u16 index)
3175{
3176 u8 *p;
3177 struct fusion_context *fusion;
3178
adam radford9c915a82010-12-21 13:34:31 -08003179 fusion = instance->ctrl_context;
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003180 p = fusion->req_frames_desc +
3181 sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) * index;
adam radford9c915a82010-12-21 13:34:31 -08003182
3183 return (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)p;
3184}
3185
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003186
3187/* megasas_prepate_secondRaid1_IO
3188 * It prepares the raid 1 second IO
3189 */
3190void megasas_prepare_secondRaid1_IO(struct megasas_instance *instance,
3191 struct megasas_cmd_fusion *cmd,
3192 struct megasas_cmd_fusion *r1_cmd)
3193{
3194 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc, *req_desc2 = NULL;
3195 struct fusion_context *fusion;
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003196 fusion = instance->ctrl_context;
3197 req_desc = cmd->request_desc;
Shivasharan S8bf7c652017-02-10 00:59:03 -08003198 /* copy the io request frame as well as 8 SGEs data for r1 command*/
3199 memcpy(r1_cmd->io_request, cmd->io_request,
3200 (sizeof(struct MPI2_RAID_SCSI_IO_REQUEST)));
3201 memcpy(&r1_cmd->io_request->SGL, &cmd->io_request->SGL,
3202 (fusion->max_sge_in_main_msg * sizeof(union MPI2_SGE_IO_UNION)));
3203 /*sense buffer is different for r1 command*/
3204 r1_cmd->io_request->SenseBufferLowAddress =
Shivasharan S107a60d2017-10-19 02:49:05 -07003205 cpu_to_le32(lower_32_bits(r1_cmd->sense_phys_addr));
Shivasharan S8bf7c652017-02-10 00:59:03 -08003206 r1_cmd->scmd = cmd->scmd;
3207 req_desc2 = megasas_get_request_descriptor(instance,
3208 (r1_cmd->index - 1));
3209 req_desc2->Words = 0;
3210 r1_cmd->request_desc = req_desc2;
3211 req_desc2->SCSIIO.SMID = cpu_to_le16(r1_cmd->index);
3212 req_desc2->SCSIIO.RequestFlags = req_desc->SCSIIO.RequestFlags;
3213 r1_cmd->request_desc->SCSIIO.DevHandle = cmd->r1_alt_dev_handle;
3214 r1_cmd->io_request->DevHandle = cmd->r1_alt_dev_handle;
3215 r1_cmd->r1_alt_dev_handle = cmd->io_request->DevHandle;
3216 cmd->io_request->RaidContext.raid_context_g35.smid.peer_smid =
3217 cpu_to_le16(r1_cmd->index);
3218 r1_cmd->io_request->RaidContext.raid_context_g35.smid.peer_smid =
3219 cpu_to_le16(cmd->index);
3220 /*MSIxIndex of both commands request descriptors should be same*/
3221 r1_cmd->request_desc->SCSIIO.MSIxIndex =
3222 cmd->request_desc->SCSIIO.MSIxIndex;
3223 /*span arm is different for r1 cmd*/
3224 r1_cmd->io_request->RaidContext.raid_context_g35.span_arm =
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003225 cmd->io_request->RaidContext.raid_context_g35.span_arm + 1;
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003226}
3227
adam radford9c915a82010-12-21 13:34:31 -08003228/**
3229 * megasas_build_and_issue_cmd_fusion -Main routine for building and
3230 * issuing non IOCTL cmd
3231 * @instance: Adapter soft state
3232 * @scmd: pointer to scsi cmd from OS
3233 */
3234static u32
3235megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
3236 struct scsi_cmnd *scmd)
3237{
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003238 struct megasas_cmd_fusion *cmd, *r1_cmd = NULL;
adam radford9c915a82010-12-21 13:34:31 -08003239 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
3240 u32 index;
3241 struct fusion_context *fusion;
3242
3243 fusion = instance->ctrl_context;
3244
Sumit Saxena308ec452016-01-28 21:04:30 +05303245 if ((megasas_cmd_type(scmd) == READ_WRITE_LDIO) &&
3246 instance->ldio_threshold &&
3247 (atomic_inc_return(&instance->ldio_outstanding) >
3248 instance->ldio_threshold)) {
3249 atomic_dec(&instance->ldio_outstanding);
3250 return SCSI_MLQUEUE_DEVICE_BUSY;
3251 }
3252
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003253 if (atomic_inc_return(&instance->fw_outstanding) >
3254 instance->host->can_queue) {
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003255 atomic_dec(&instance->fw_outstanding);
3256 return SCSI_MLQUEUE_HOST_BUSY;
3257 }
3258
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05303259 cmd = megasas_get_cmd_fusion(instance, scmd->request->tag);
adam radford9c915a82010-12-21 13:34:31 -08003260
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003261 if (!cmd) {
3262 atomic_dec(&instance->fw_outstanding);
3263 return SCSI_MLQUEUE_HOST_BUSY;
3264 }
3265
adam radford9c915a82010-12-21 13:34:31 -08003266 index = cmd->index;
3267
3268 req_desc = megasas_get_request_descriptor(instance, index-1);
adam radford9c915a82010-12-21 13:34:31 -08003269
3270 req_desc->Words = 0;
3271 cmd->request_desc = req_desc;
adam radford9c915a82010-12-21 13:34:31 -08003272
3273 if (megasas_build_io_fusion(instance, scmd, cmd)) {
3274 megasas_return_cmd_fusion(instance, cmd);
Bjorn Helgaas1be18252015-07-07 15:52:34 -05003275 dev_err(&instance->pdev->dev, "Error building command\n");
adam radford9c915a82010-12-21 13:34:31 -08003276 cmd->request_desc = NULL;
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003277 atomic_dec(&instance->fw_outstanding);
Sumit Saxenaf9a9dee2016-01-28 21:04:29 +05303278 return SCSI_MLQUEUE_HOST_BUSY;
adam radford9c915a82010-12-21 13:34:31 -08003279 }
3280
3281 req_desc = cmd->request_desc;
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05303282 req_desc->SCSIIO.SMID = cpu_to_le16(index);
adam radford9c915a82010-12-21 13:34:31 -08003283
3284 if (cmd->io_request->ChainOffset != 0 &&
3285 cmd->io_request->ChainOffset != 0xF)
Bjorn Helgaas1be18252015-07-07 15:52:34 -05003286 dev_err(&instance->pdev->dev, "The chain offset value is not "
adam radford9c915a82010-12-21 13:34:31 -08003287 "correct : %x\n", cmd->io_request->ChainOffset);
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003288 /*
3289 * if it is raid 1/10 fp write capable.
3290 * try to get second command from pool and construct it.
3291 * From FW, it has confirmed that lba values of two PDs
3292 * corresponds to single R1/10 LD are always same
3293 *
3294 */
3295 /* driver side count always should be less than max_fw_cmds
3296 * to get new command
3297 */
Shivasharan S8bf7c652017-02-10 00:59:03 -08003298 if (cmd->r1_alt_dev_handle != MR_DEVHANDLE_INVALID) {
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003299 r1_cmd = megasas_get_cmd_fusion(instance,
3300 (scmd->request->tag + instance->max_fw_cmds));
3301 megasas_prepare_secondRaid1_IO(instance, cmd, r1_cmd);
3302 }
3303
Shivasharan S18bbcab2017-02-10 00:59:01 -08003304
adam radford9c915a82010-12-21 13:34:31 -08003305 /*
3306 * Issue the command to the FW
3307 */
adam radford9c915a82010-12-21 13:34:31 -08003308
Shivasharan S45b8a352017-02-10 00:59:04 -08003309 megasas_fire_cmd_fusion(instance, req_desc);
adam radford9c915a82010-12-21 13:34:31 -08003310
Shivasharan S18bbcab2017-02-10 00:59:01 -08003311 if (r1_cmd)
Shivasharan S45b8a352017-02-10 00:59:04 -08003312 megasas_fire_cmd_fusion(instance, r1_cmd->request_desc);
Shivasharan S18bbcab2017-02-10 00:59:01 -08003313
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003314
adam radford9c915a82010-12-21 13:34:31 -08003315 return 0;
3316}
3317
3318/**
Shivasharan S8bf7c652017-02-10 00:59:03 -08003319 * megasas_complete_r1_command -
3320 * completes R1 FP write commands which has valid peer smid
3321 * @instance: Adapter soft state
3322 * @cmd_fusion: MPT command frame
3323 *
3324 */
3325static inline void
3326megasas_complete_r1_command(struct megasas_instance *instance,
3327 struct megasas_cmd_fusion *cmd)
3328{
3329 u8 *sense, status, ex_status;
3330 u32 data_length;
3331 u16 peer_smid;
3332 struct fusion_context *fusion;
3333 struct megasas_cmd_fusion *r1_cmd = NULL;
3334 struct scsi_cmnd *scmd_local = NULL;
3335 struct RAID_CONTEXT_G35 *rctx_g35;
3336
3337 rctx_g35 = &cmd->io_request->RaidContext.raid_context_g35;
3338 fusion = instance->ctrl_context;
3339 peer_smid = le16_to_cpu(rctx_g35->smid.peer_smid);
3340
3341 r1_cmd = fusion->cmd_list[peer_smid - 1];
3342 scmd_local = cmd->scmd;
3343 status = rctx_g35->status;
3344 ex_status = rctx_g35->ex_status;
3345 data_length = cmd->io_request->DataLength;
3346 sense = cmd->sense;
3347
3348 cmd->cmd_completed = true;
3349
3350 /* Check if peer command is completed or not*/
3351 if (r1_cmd->cmd_completed) {
3352 rctx_g35 = &r1_cmd->io_request->RaidContext.raid_context_g35;
3353 if (rctx_g35->status != MFI_STAT_OK) {
3354 status = rctx_g35->status;
3355 ex_status = rctx_g35->ex_status;
3356 data_length = r1_cmd->io_request->DataLength;
3357 sense = r1_cmd->sense;
3358 }
3359
3360 megasas_return_cmd_fusion(instance, r1_cmd);
3361 map_cmd_status(fusion, scmd_local, status, ex_status,
3362 le32_to_cpu(data_length), sense);
3363 if (instance->ldio_threshold &&
3364 megasas_cmd_type(scmd_local) == READ_WRITE_LDIO)
3365 atomic_dec(&instance->ldio_outstanding);
3366 scmd_local->SCp.ptr = NULL;
3367 megasas_return_cmd_fusion(instance, cmd);
3368 scsi_dma_unmap(scmd_local);
3369 scmd_local->scsi_done(scmd_local);
3370 }
3371}
3372
3373/**
adam radford9c915a82010-12-21 13:34:31 -08003374 * complete_cmd_fusion - Completes command
3375 * @instance: Adapter soft state
3376 * Completes all commands that is in reply descriptor queue
3377 */
3378int
adam radfordc8e858f2011-10-08 18:15:13 -07003379complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
adam radford9c915a82010-12-21 13:34:31 -08003380{
3381 union MPI2_REPLY_DESCRIPTORS_UNION *desc;
3382 struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
3383 struct MPI2_RAID_SCSI_IO_REQUEST *scsi_io_req;
3384 struct fusion_context *fusion;
3385 struct megasas_cmd *cmd_mfi;
Shivasharan S8bf7c652017-02-10 00:59:03 -08003386 struct megasas_cmd_fusion *cmd_fusion;
adam radford9c915a82010-12-21 13:34:31 -08003387 u16 smid, num_completed;
Shivasharan S8bf7c652017-02-10 00:59:03 -08003388 u8 reply_descript_type, *sense, status, extStatus;
3389 u32 device_id, data_length;
adam radford9c915a82010-12-21 13:34:31 -08003390 union desc_value d_val;
3391 struct LD_LOAD_BALANCE_INFO *lbinfo;
Sumit.Saxena@avagotech.comdb4fc862014-09-12 18:57:23 +05303392 int threshold_reply_count = 0;
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05303393 struct scsi_cmnd *scmd_local = NULL;
Sumit Saxena18365b12016-01-28 21:04:25 +05303394 struct MR_TASK_MANAGE_REQUEST *mr_tm_req;
3395 struct MPI2_SCSI_TASK_MANAGE_REQUEST *mpi_tm_req;
adam radford9c915a82010-12-21 13:34:31 -08003396
3397 fusion = instance->ctrl_context;
3398
Sumit Saxena8a01a412016-01-28 21:04:32 +05303399 if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR)
adam radford9c915a82010-12-21 13:34:31 -08003400 return IRQ_HANDLED;
3401
Sumit Saxena179ac142016-01-28 21:04:28 +05303402 desc = fusion->reply_frames_desc[MSIxIndex] +
3403 fusion->last_reply_idx[MSIxIndex];
adam radford9c915a82010-12-21 13:34:31 -08003404
3405 reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
3406
3407 d_val.word = desc->Words;
3408
3409 reply_descript_type = reply_desc->ReplyFlags &
3410 MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
3411
3412 if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
3413 return IRQ_NONE;
3414
adam radford9c915a82010-12-21 13:34:31 -08003415 num_completed = 0;
3416
Christoph Hellwigc6f5bf82015-04-23 16:33:09 +05303417 while (d_val.u.low != cpu_to_le32(UINT_MAX) &&
3418 d_val.u.high != cpu_to_le32(UINT_MAX)) {
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003419
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05303420 smid = le16_to_cpu(reply_desc->SMID);
adam radford9c915a82010-12-21 13:34:31 -08003421 cmd_fusion = fusion->cmd_list[smid - 1];
Shivasharan S8bf7c652017-02-10 00:59:03 -08003422 scsi_io_req = (struct MPI2_RAID_SCSI_IO_REQUEST *)
3423 cmd_fusion->io_request;
adam radford9c915a82010-12-21 13:34:31 -08003424
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05303425 scmd_local = cmd_fusion->scmd;
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05003426 status = scsi_io_req->RaidContext.raid_context.status;
Sasikumar Chandrasekarand8893442017-01-10 18:20:48 -05003427 extStatus = scsi_io_req->RaidContext.raid_context.ex_status;
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003428 sense = cmd_fusion->sense;
3429 data_length = scsi_io_req->DataLength;
adam radford9c915a82010-12-21 13:34:31 -08003430
3431 switch (scsi_io_req->Function) {
Sumit Saxena18365b12016-01-28 21:04:25 +05303432 case MPI2_FUNCTION_SCSI_TASK_MGMT:
3433 mr_tm_req = (struct MR_TASK_MANAGE_REQUEST *)
3434 cmd_fusion->io_request;
3435 mpi_tm_req = (struct MPI2_SCSI_TASK_MANAGE_REQUEST *)
3436 &mr_tm_req->TmRequest;
3437 dev_dbg(&instance->pdev->dev, "TM completion:"
3438 "type: 0x%x TaskMID: 0x%x\n",
3439 mpi_tm_req->TaskType, mpi_tm_req->TaskMID);
3440 complete(&cmd_fusion->done);
3441 break;
adam radford9c915a82010-12-21 13:34:31 -08003442 case MPI2_FUNCTION_SCSI_IO_REQUEST: /*Fast Path IO.*/
3443 /* Update load balancing info */
Shivasharan S8bf7c652017-02-10 00:59:03 -08003444 if (fusion->load_balance_info &&
3445 (cmd_fusion->scmd->SCp.Status &
3446 MEGASAS_LOAD_BALANCE_FLAG)) {
3447 device_id = MEGASAS_DEV_INDEX(scmd_local);
3448 lbinfo = &fusion->load_balance_info[device_id];
Sumit.Saxena@avagotech.comd2552eb2014-09-12 18:57:53 +05303449 atomic_dec(&lbinfo->scsi_pending_cmds[cmd_fusion->pd_r1_lb]);
Shivasharan S8bf7c652017-02-10 00:59:03 -08003450 cmd_fusion->scmd->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG;
adam radford9c915a82010-12-21 13:34:31 -08003451 }
Gustavo A. R. Silva74e716f2018-11-27 22:32:34 -06003452 /* Fall through - and complete IO */
adam radford9c915a82010-12-21 13:34:31 -08003453 case MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST: /* LD-IO Path */
Shivasharan S8bf7c652017-02-10 00:59:03 -08003454 atomic_dec(&instance->fw_outstanding);
3455 if (cmd_fusion->r1_alt_dev_handle == MR_DEVHANDLE_INVALID) {
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003456 map_cmd_status(fusion, scmd_local, status,
Shivasharan S8bf7c652017-02-10 00:59:03 -08003457 extStatus, le32_to_cpu(data_length),
3458 sense);
3459 if (instance->ldio_threshold &&
3460 (megasas_cmd_type(scmd_local) == READ_WRITE_LDIO))
Sasikumar Chandrasekaranb71b49c2017-01-10 18:20:51 -05003461 atomic_dec(&instance->ldio_outstanding);
Shivasharan S8bf7c652017-02-10 00:59:03 -08003462 scmd_local->SCp.ptr = NULL;
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05003463 megasas_return_cmd_fusion(instance, cmd_fusion);
3464 scsi_dma_unmap(scmd_local);
3465 scmd_local->scsi_done(scmd_local);
Shivasharan S8bf7c652017-02-10 00:59:03 -08003466 } else /* Optimal VD - R1 FP command completion. */
3467 megasas_complete_r1_command(instance, cmd_fusion);
adam radford9c915a82010-12-21 13:34:31 -08003468 break;
3469 case MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST: /*MFI command */
3470 cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05303471 /* Poll mode. Dummy free.
3472 * In case of Interrupt mode, caller has reverse check.
3473 */
3474 if (cmd_mfi->flags & DRV_DCMD_POLLED_MODE) {
3475 cmd_mfi->flags &= ~DRV_DCMD_POLLED_MODE;
3476 megasas_return_cmd(instance, cmd_mfi);
3477 } else
3478 megasas_complete_cmd(instance, cmd_mfi, DID_OK);
adam radford9c915a82010-12-21 13:34:31 -08003479 break;
3480 }
3481
adam radfordc8e858f2011-10-08 18:15:13 -07003482 fusion->last_reply_idx[MSIxIndex]++;
3483 if (fusion->last_reply_idx[MSIxIndex] >=
3484 fusion->reply_q_depth)
3485 fusion->last_reply_idx[MSIxIndex] = 0;
adam radford9c915a82010-12-21 13:34:31 -08003486
Christoph Hellwigc6f5bf82015-04-23 16:33:09 +05303487 desc->Words = cpu_to_le64(ULLONG_MAX);
adam radford9c915a82010-12-21 13:34:31 -08003488 num_completed++;
Sumit.Saxena@avagotech.comdb4fc862014-09-12 18:57:23 +05303489 threshold_reply_count++;
adam radford9c915a82010-12-21 13:34:31 -08003490
3491 /* Get the next reply descriptor */
adam radfordc8e858f2011-10-08 18:15:13 -07003492 if (!fusion->last_reply_idx[MSIxIndex])
Sumit Saxena179ac142016-01-28 21:04:28 +05303493 desc = fusion->reply_frames_desc[MSIxIndex];
adam radford9c915a82010-12-21 13:34:31 -08003494 else
3495 desc++;
3496
3497 reply_desc =
3498 (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
3499
3500 d_val.word = desc->Words;
3501
3502 reply_descript_type = reply_desc->ReplyFlags &
3503 MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
3504
3505 if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
3506 break;
Sumit.Saxena@avagotech.comdb4fc862014-09-12 18:57:23 +05303507 /*
3508 * Write to reply post host index register after completing threshold
3509 * number of reply counts and still there are more replies in reply queue
3510 * pending to be completed
3511 */
3512 if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) {
Sasikumar Chandrasekaran2493c672017-01-10 18:20:44 -05003513 if (instance->msix_combined)
Sumit.Saxena@avagotech.comdb4fc862014-09-12 18:57:23 +05303514 writel(((MSIxIndex & 0x7) << 24) |
3515 fusion->last_reply_idx[MSIxIndex],
3516 instance->reply_post_host_index_addr[MSIxIndex/8]);
3517 else
3518 writel((MSIxIndex << 24) |
3519 fusion->last_reply_idx[MSIxIndex],
3520 instance->reply_post_host_index_addr[0]);
3521 threshold_reply_count = 0;
3522 }
adam radford9c915a82010-12-21 13:34:31 -08003523 }
3524
3525 if (!num_completed)
3526 return IRQ_NONE;
3527
3528 wmb();
Sasikumar Chandrasekaran2493c672017-01-10 18:20:44 -05003529 if (instance->msix_combined)
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +05303530 writel(((MSIxIndex & 0x7) << 24) |
3531 fusion->last_reply_idx[MSIxIndex],
3532 instance->reply_post_host_index_addr[MSIxIndex/8]);
3533 else
3534 writel((MSIxIndex << 24) |
3535 fusion->last_reply_idx[MSIxIndex],
3536 instance->reply_post_host_index_addr[0]);
adam radford53ef2bb2011-02-24 20:56:05 -08003537 megasas_check_and_restore_queue_depth(instance);
adam radford9c915a82010-12-21 13:34:31 -08003538 return IRQ_HANDLED;
3539}
3540
3541/**
Shivasharan S29206da2017-02-10 00:59:34 -08003542 * megasas_sync_irqs - Synchronizes all IRQs owned by adapter
3543 * @instance: Adapter soft state
3544 */
3545void megasas_sync_irqs(unsigned long instance_addr)
3546{
3547 u32 count, i;
3548 struct megasas_instance *instance =
3549 (struct megasas_instance *)instance_addr;
3550
3551 count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
3552
3553 for (i = 0; i < count; i++)
3554 synchronize_irq(pci_irq_vector(instance->pdev, i));
3555}
3556
3557/**
adam radford9c915a82010-12-21 13:34:31 -08003558 * megasas_complete_cmd_dpc_fusion - Completes command
3559 * @instance: Adapter soft state
3560 *
3561 * Tasklet to complete cmds
3562 */
3563void
3564megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
3565{
3566 struct megasas_instance *instance =
3567 (struct megasas_instance *)instance_addr;
adam radfordc8e858f2011-10-08 18:15:13 -07003568 u32 count, MSIxIndex;
3569
3570 count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
adam radford9c915a82010-12-21 13:34:31 -08003571
3572 /* If we have already declared adapter dead, donot complete cmds */
Shivasharan S34bd9f22018-10-16 23:37:50 -07003573 if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR)
adam radford9c915a82010-12-21 13:34:31 -08003574 return;
adam radford9c915a82010-12-21 13:34:31 -08003575
adam radfordc8e858f2011-10-08 18:15:13 -07003576 for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++)
3577 complete_cmd_fusion(instance, MSIxIndex);
adam radford9c915a82010-12-21 13:34:31 -08003578}
3579
3580/**
3581 * megasas_isr_fusion - isr entry point
3582 */
3583irqreturn_t megasas_isr_fusion(int irq, void *devp)
3584{
adam radfordc8e858f2011-10-08 18:15:13 -07003585 struct megasas_irq_context *irq_context = devp;
3586 struct megasas_instance *instance = irq_context->instance;
Shivasharan S3f6194a2018-10-16 23:37:39 -07003587 u32 mfiStatus;
adam radford9c915a82010-12-21 13:34:31 -08003588
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +05303589 if (instance->mask_interrupts)
3590 return IRQ_NONE;
3591
adam radfordc8e858f2011-10-08 18:15:13 -07003592 if (!instance->msix_vectors) {
adam radford9c915a82010-12-21 13:34:31 -08003593 mfiStatus = instance->instancet->clear_intr(instance->reg_set);
3594 if (!mfiStatus)
3595 return IRQ_NONE;
3596 }
3597
3598 /* If we are resetting, bail */
adam radford6497b242011-10-08 18:14:50 -07003599 if (test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags)) {
3600 instance->instancet->clear_intr(instance->reg_set);
adam radford9c915a82010-12-21 13:34:31 -08003601 return IRQ_HANDLED;
adam radford6497b242011-10-08 18:14:50 -07003602 }
adam radford9c915a82010-12-21 13:34:31 -08003603
Shivasharan S3f6194a2018-10-16 23:37:39 -07003604 return complete_cmd_fusion(instance, irq_context->MSIxIndex);
adam radford9c915a82010-12-21 13:34:31 -08003605}
3606
3607/**
3608 * build_mpt_mfi_pass_thru - builds a cmd fo MFI Pass thru
3609 * @instance: Adapter soft state
3610 * mfi_cmd: megasas_cmd pointer
3611 *
3612 */
Shivasharan S7a7ae4f2017-02-10 00:59:32 -08003613void
adam radford9c915a82010-12-21 13:34:31 -08003614build_mpt_mfi_pass_thru(struct megasas_instance *instance,
3615 struct megasas_cmd *mfi_cmd)
3616{
3617 struct MPI25_IEEE_SGE_CHAIN64 *mpi25_ieee_chain;
3618 struct MPI2_RAID_SCSI_IO_REQUEST *io_req;
3619 struct megasas_cmd_fusion *cmd;
3620 struct fusion_context *fusion;
3621 struct megasas_header *frame_hdr = &mfi_cmd->frame->hdr;
3622
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05303623 fusion = instance->ctrl_context;
3624
3625 cmd = megasas_get_cmd_fusion(instance,
3626 instance->max_scsi_cmds + mfi_cmd->index);
adam radford9c915a82010-12-21 13:34:31 -08003627
3628 /* Save the smid. To be used for returning the cmd */
3629 mfi_cmd->context.smid = cmd->index;
Sumit.Saxena@avagotech.com90dc9d92014-09-12 18:57:58 +05303630
adam radford9c915a82010-12-21 13:34:31 -08003631 /*
3632 * For cmds where the flag is set, store the flag and check
3633 * on completion. For cmds with this flag, don't call
3634 * megasas_complete_cmd
3635 */
3636
Sumit.Saxena@avagotech.com6e755dd2014-11-17 15:24:28 +05303637 if (frame_hdr->flags & cpu_to_le16(MFI_FRAME_DONT_POST_IN_REPLY_QUEUE))
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05303638 mfi_cmd->flags |= DRV_DCMD_POLLED_MODE;
adam radford9c915a82010-12-21 13:34:31 -08003639
adam radford9c915a82010-12-21 13:34:31 -08003640 io_req = cmd->io_request;
adam radford36807e62011-10-08 18:15:06 -07003641
Shivasharan Sc3651782017-10-19 02:48:48 -07003642 if (instance->adapter_type >= INVADER_SERIES) {
adam radford36807e62011-10-08 18:15:06 -07003643 struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end =
3644 (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL;
3645 sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
3646 sgl_ptr_end->Flags = 0;
3647 }
3648
adam radford9c915a82010-12-21 13:34:31 -08003649 mpi25_ieee_chain =
3650 (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain;
3651
3652 io_req->Function = MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST;
3653 io_req->SGLOffset0 = offsetof(struct MPI2_RAID_SCSI_IO_REQUEST,
3654 SGL) / 4;
3655 io_req->ChainOffset = fusion->chain_offset_mfi_pthru;
3656
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05303657 mpi25_ieee_chain->Address = cpu_to_le64(mfi_cmd->frame_phys_addr);
adam radford9c915a82010-12-21 13:34:31 -08003658
3659 mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT |
3660 MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
3661
Shivasharan Sed2983f2017-08-23 04:46:55 -07003662 mpi25_ieee_chain->Length = cpu_to_le32(instance->mfi_frame_size);
adam radford9c915a82010-12-21 13:34:31 -08003663}
3664
3665/**
3666 * build_mpt_cmd - Calls helper function to build a cmd MFI Pass thru cmd
3667 * @instance: Adapter soft state
3668 * @cmd: mfi cmd to build
3669 *
3670 */
3671union MEGASAS_REQUEST_DESCRIPTOR_UNION *
3672build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
3673{
Shivasharan S52205ac2017-02-10 00:59:08 -08003674 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc = NULL;
adam radford9c915a82010-12-21 13:34:31 -08003675 u16 index;
3676
Shivasharan S7a7ae4f2017-02-10 00:59:32 -08003677 build_mpt_mfi_pass_thru(instance, cmd);
adam radford9c915a82010-12-21 13:34:31 -08003678 index = cmd->context.smid;
3679
3680 req_desc = megasas_get_request_descriptor(instance, index - 1);
3681
adam radford9c915a82010-12-21 13:34:31 -08003682 req_desc->Words = 0;
3683 req_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
3684 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
3685
Sumit.Saxena@lsi.com94cd65d2013-09-06 15:50:52 +05303686 req_desc->SCSIIO.SMID = cpu_to_le16(index);
adam radford9c915a82010-12-21 13:34:31 -08003687
3688 return req_desc;
3689}
3690
3691/**
3692 * megasas_issue_dcmd_fusion - Issues a MFI Pass thru cmd
3693 * @instance: Adapter soft state
3694 * @cmd: mfi cmd pointer
3695 *
3696 */
Shivasharan Sf4fc2092017-02-10 00:59:09 -08003697void
adam radford9c915a82010-12-21 13:34:31 -08003698megasas_issue_dcmd_fusion(struct megasas_instance *instance,
3699 struct megasas_cmd *cmd)
3700{
3701 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
adam radford9c915a82010-12-21 13:34:31 -08003702
3703 req_desc = build_mpt_cmd(instance, cmd);
Sumit Saxena6d40afb2016-01-28 21:04:23 +05303704
Shivasharan S45b8a352017-02-10 00:59:04 -08003705 megasas_fire_cmd_fusion(instance, req_desc);
Shivasharan Sf4fc2092017-02-10 00:59:09 -08003706 return;
adam radford9c915a82010-12-21 13:34:31 -08003707}
3708
3709/**
3710 * megasas_release_fusion - Reverses the FW initialization
Geert Uytterhoeven4b63b282015-03-03 11:58:07 +01003711 * @instance: Adapter soft state
adam radford9c915a82010-12-21 13:34:31 -08003712 */
3713void
3714megasas_release_fusion(struct megasas_instance *instance)
3715{
Shivasharan Sb9637d12017-10-19 02:49:01 -07003716 megasas_free_ioc_init_cmd(instance);
adam radford9c915a82010-12-21 13:34:31 -08003717 megasas_free_cmds(instance);
3718 megasas_free_cmds_fusion(instance);
3719
3720 iounmap(instance->reg_set);
3721
Yinghai Lue7f85162016-08-05 23:37:34 -07003722 pci_release_selected_regions(instance->pdev, 1<<instance->bar);
adam radford9c915a82010-12-21 13:34:31 -08003723}
3724
3725/**
3726 * megasas_read_fw_status_reg_fusion - returns the current FW status value
3727 * @regs: MFI register set
3728 */
3729static u32
3730megasas_read_fw_status_reg_fusion(struct megasas_register_set __iomem *regs)
3731{
Shivasharan S81b76452018-10-16 23:37:51 -07003732 return readl(&(regs)->outbound_scratch_pad_0);
adam radford9c915a82010-12-21 13:34:31 -08003733}
3734
3735/**
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05303736 * megasas_alloc_host_crash_buffer - Host buffers for Crash dump collection from Firmware
3737 * @instance: Controller's soft instance
3738 * return: Number of allocated host crash buffers
3739 */
3740static void
3741megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
3742{
3743 unsigned int i;
3744
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05303745 for (i = 0; i < MAX_CRASH_DUMP_SIZE; i++) {
Shivasharan Sdef3e8d2017-08-23 04:47:03 -07003746 instance->crash_buf[i] = vzalloc(CRASH_DMA_BUF_SIZE);
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05303747 if (!instance->crash_buf[i]) {
3748 dev_info(&instance->pdev->dev, "Firmware crash dump "
3749 "memory allocation failed at index %d\n", i);
3750 break;
3751 }
3752 }
3753 instance->drv_buf_alloc = i;
3754}
3755
3756/**
3757 * megasas_free_host_crash_buffer - Host buffers for Crash dump collection from Firmware
3758 * @instance: Controller's soft instance
3759 */
3760void
3761megasas_free_host_crash_buffer(struct megasas_instance *instance)
3762{
Shivasharan Sdef3e8d2017-08-23 04:47:03 -07003763 unsigned int i;
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05303764 for (i = 0; i < instance->drv_buf_alloc; i++) {
3765 if (instance->crash_buf[i])
Shivasharan Sdef3e8d2017-08-23 04:47:03 -07003766 vfree(instance->crash_buf[i]);
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05303767 }
3768 instance->drv_buf_index = 0;
3769 instance->drv_buf_alloc = 0;
3770 instance->fw_crash_state = UNAVAILABLE;
3771 instance->fw_crash_buffer_size = 0;
3772}
3773
3774/**
adam radford9c915a82010-12-21 13:34:31 -08003775 * megasas_adp_reset_fusion - For controller reset
3776 * @regs: MFI register set
3777 */
3778static int
3779megasas_adp_reset_fusion(struct megasas_instance *instance,
3780 struct megasas_register_set __iomem *regs)
3781{
sumit.saxena@avagotech.com79b82c22015-08-31 17:23:41 +05303782 u32 host_diag, abs_state, retry;
3783
3784 /* Now try to reset the chip */
3785 writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
3786 writel(MPI2_WRSEQ_1ST_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
3787 writel(MPI2_WRSEQ_2ND_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
3788 writel(MPI2_WRSEQ_3RD_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
3789 writel(MPI2_WRSEQ_4TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
3790 writel(MPI2_WRSEQ_5TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
3791 writel(MPI2_WRSEQ_6TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
3792
3793 /* Check that the diag write enable (DRWE) bit is on */
3794 host_diag = readl(&instance->reg_set->fusion_host_diag);
3795 retry = 0;
3796 while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) {
3797 msleep(100);
3798 host_diag = readl(&instance->reg_set->fusion_host_diag);
3799 if (retry++ == 100) {
3800 dev_warn(&instance->pdev->dev,
3801 "Host diag unlock failed from %s %d\n",
3802 __func__, __LINE__);
3803 break;
3804 }
3805 }
3806 if (!(host_diag & HOST_DIAG_WRITE_ENABLE))
3807 return -1;
3808
3809 /* Send chip reset command */
3810 writel(host_diag | HOST_DIAG_RESET_ADAPTER,
3811 &instance->reg_set->fusion_host_diag);
3812 msleep(3000);
3813
3814 /* Make sure reset adapter bit is cleared */
3815 host_diag = readl(&instance->reg_set->fusion_host_diag);
3816 retry = 0;
3817 while (host_diag & HOST_DIAG_RESET_ADAPTER) {
3818 msleep(100);
3819 host_diag = readl(&instance->reg_set->fusion_host_diag);
3820 if (retry++ == 1000) {
3821 dev_warn(&instance->pdev->dev,
3822 "Diag reset adapter never cleared %s %d\n",
3823 __func__, __LINE__);
3824 break;
3825 }
3826 }
3827 if (host_diag & HOST_DIAG_RESET_ADAPTER)
3828 return -1;
3829
3830 abs_state = instance->instancet->read_fw_status_reg(instance->reg_set)
3831 & MFI_STATE_MASK;
3832 retry = 0;
3833
3834 while ((abs_state <= MFI_STATE_FW_INIT) && (retry++ < 1000)) {
3835 msleep(100);
3836 abs_state = instance->instancet->
3837 read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
3838 }
3839 if (abs_state <= MFI_STATE_FW_INIT) {
3840 dev_warn(&instance->pdev->dev,
3841 "fw state < MFI_STATE_FW_INIT, state = 0x%x %s %d\n",
3842 abs_state, __func__, __LINE__);
3843 return -1;
3844 }
3845
adam radford9c915a82010-12-21 13:34:31 -08003846 return 0;
3847}
3848
3849/**
3850 * megasas_check_reset_fusion - For controller reset check
3851 * @regs: MFI register set
3852 */
3853static int
3854megasas_check_reset_fusion(struct megasas_instance *instance,
3855 struct megasas_register_set __iomem *regs)
3856{
3857 return 0;
3858}
3859
Shivasharan Sf0c21df2018-10-16 23:37:40 -07003860/**
3861 * megasas_trigger_snap_dump - Trigger snap dump in FW
3862 * @instance: Soft instance of adapter
3863 */
3864static inline void megasas_trigger_snap_dump(struct megasas_instance *instance)
3865{
3866 int j;
3867 u32 fw_state;
3868
3869 if (!instance->disableOnlineCtrlReset) {
3870 dev_info(&instance->pdev->dev, "Trigger snap dump\n");
3871 writel(MFI_ADP_TRIGGER_SNAP_DUMP,
3872 &instance->reg_set->doorbell);
3873 readl(&instance->reg_set->doorbell);
3874 }
3875
3876 for (j = 0; j < instance->snapdump_wait_time; j++) {
3877 fw_state = instance->instancet->read_fw_status_reg(
3878 instance->reg_set) & MFI_STATE_MASK;
3879 if (fw_state == MFI_STATE_FAULT) {
3880 dev_err(&instance->pdev->dev,
3881 "Found FW in FAULT state, after snap dump trigger\n");
3882 return;
3883 }
3884 msleep(1000);
3885 }
3886}
3887
adam radford9c915a82010-12-21 13:34:31 -08003888/* This function waits for outstanding commands on fusion to complete */
adam radford229fe472014-03-10 02:51:56 -07003889int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance,
Sumit Saxena6d40afb2016-01-28 21:04:23 +05303890 int reason, int *convert)
adam radford9c915a82010-12-21 13:34:31 -08003891{
adam radford229fe472014-03-10 02:51:56 -07003892 int i, outstanding, retval = 0, hb_seconds_missed = 0;
adam radfordc007b8b2012-07-17 18:20:24 -07003893 u32 fw_state;
Shivasharan Sf0c21df2018-10-16 23:37:40 -07003894 u32 waittime_for_io_completion;
adam radford9c915a82010-12-21 13:34:31 -08003895
Shivasharan Sf0c21df2018-10-16 23:37:40 -07003896 waittime_for_io_completion =
3897 min_t(u32, resetwaittime,
3898 (resetwaittime - instance->snapdump_wait_time));
3899
3900 if (reason == MFI_IO_TIMEOUT_OCR) {
3901 dev_info(&instance->pdev->dev,
3902 "MFI command is timed out\n");
3903 megasas_complete_cmd_dpc_fusion((unsigned long)instance);
3904 if (instance->snapdump_wait_time)
3905 megasas_trigger_snap_dump(instance);
3906 retval = 1;
3907 goto out;
3908 }
3909
3910 for (i = 0; i < waittime_for_io_completion; i++) {
adam radford9c915a82010-12-21 13:34:31 -08003911 /* Check if firmware is in fault state */
3912 fw_state = instance->instancet->read_fw_status_reg(
3913 instance->reg_set) & MFI_STATE_MASK;
3914 if (fw_state == MFI_STATE_FAULT) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05003915 dev_warn(&instance->pdev->dev, "Found FW in FAULT state,"
adam radford229fe472014-03-10 02:51:56 -07003916 " will reset adapter scsi%d.\n",
3917 instance->host->host_no);
Sumit Saxena64d0b8e2016-04-15 00:23:31 -07003918 megasas_complete_cmd_dpc_fusion((unsigned long)instance);
Shivasharan Sdef0eab2017-02-10 00:59:15 -08003919 if (instance->requestorId && reason) {
3920 dev_warn(&instance->pdev->dev, "SR-IOV Found FW in FAULT"
3921 " state while polling during"
3922 " I/O timeout handling for %d\n",
3923 instance->host->host_no);
3924 *convert = 1;
3925 }
3926
adam radford9c915a82010-12-21 13:34:31 -08003927 retval = 1;
3928 goto out;
3929 }
Sumit Saxena6d40afb2016-01-28 21:04:23 +05303930
Sumit Saxena6d40afb2016-01-28 21:04:23 +05303931
adam radford229fe472014-03-10 02:51:56 -07003932 /* If SR-IOV VF mode & heartbeat timeout, don't wait */
Sumit Saxena6d40afb2016-01-28 21:04:23 +05303933 if (instance->requestorId && !reason) {
adam radford229fe472014-03-10 02:51:56 -07003934 retval = 1;
3935 goto out;
3936 }
3937
3938 /* If SR-IOV VF mode & I/O timeout, check for HB timeout */
Shivasharan Sdef0eab2017-02-10 00:59:15 -08003939 if (instance->requestorId && (reason == SCSIIO_TIMEOUT_OCR)) {
adam radford229fe472014-03-10 02:51:56 -07003940 if (instance->hb_host_mem->HB.fwCounter !=
3941 instance->hb_host_mem->HB.driverCounter) {
3942 instance->hb_host_mem->HB.driverCounter =
3943 instance->hb_host_mem->HB.fwCounter;
3944 hb_seconds_missed = 0;
3945 } else {
3946 hb_seconds_missed++;
3947 if (hb_seconds_missed ==
3948 (MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF/HZ)) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05003949 dev_warn(&instance->pdev->dev, "SR-IOV:"
adam radford229fe472014-03-10 02:51:56 -07003950 " Heartbeat never completed "
3951 " while polling during I/O "
3952 " timeout handling for "
3953 "scsi%d.\n",
3954 instance->host->host_no);
3955 *convert = 1;
3956 retval = 1;
3957 goto out;
3958 }
3959 }
3960 }
adam radford9c915a82010-12-21 13:34:31 -08003961
Shivasharan S14298cf2017-08-23 04:46:58 -07003962 megasas_complete_cmd_dpc_fusion((unsigned long)instance);
adam radford9c915a82010-12-21 13:34:31 -08003963 outstanding = atomic_read(&instance->fw_outstanding);
3964 if (!outstanding)
3965 goto out;
3966
3967 if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05003968 dev_notice(&instance->pdev->dev, "[%2d]waiting for %d "
adam radford229fe472014-03-10 02:51:56 -07003969 "commands to complete for scsi%d\n", i,
3970 outstanding, instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08003971 }
3972 msleep(1000);
3973 }
3974
Shivasharan Sf0c21df2018-10-16 23:37:40 -07003975 if (instance->snapdump_wait_time) {
3976 megasas_trigger_snap_dump(instance);
3977 retval = 1;
3978 goto out;
3979 }
3980
adam radford9c915a82010-12-21 13:34:31 -08003981 if (atomic_read(&instance->fw_outstanding)) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05003982 dev_err(&instance->pdev->dev, "pending commands remain after waiting, "
adam radford229fe472014-03-10 02:51:56 -07003983 "will reset adapter scsi%d.\n",
3984 instance->host->host_no);
Kashyap Desai18e1c7f2016-10-21 06:33:29 -07003985 *convert = 1;
adam radford9c915a82010-12-21 13:34:31 -08003986 retval = 1;
3987 }
Shivasharan Sf0c21df2018-10-16 23:37:40 -07003988
adam radford9c915a82010-12-21 13:34:31 -08003989out:
3990 return retval;
3991}
3992
3993void megasas_reset_reply_desc(struct megasas_instance *instance)
3994{
Sumit Saxena179ac142016-01-28 21:04:28 +05303995 int i, j, count;
adam radford9c915a82010-12-21 13:34:31 -08003996 struct fusion_context *fusion;
3997 union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
3998
3999 fusion = instance->ctrl_context;
adam radfordc8e858f2011-10-08 18:15:13 -07004000 count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
Sumit Saxena179ac142016-01-28 21:04:28 +05304001 for (i = 0 ; i < count ; i++) {
adam radfordc8e858f2011-10-08 18:15:13 -07004002 fusion->last_reply_idx[i] = 0;
Sumit Saxena179ac142016-01-28 21:04:28 +05304003 reply_desc = fusion->reply_frames_desc[i];
4004 for (j = 0 ; j < fusion->reply_q_depth; j++, reply_desc++)
4005 reply_desc->Words = cpu_to_le64(ULLONG_MAX);
4006 }
adam radford9c915a82010-12-21 13:34:31 -08004007}
4008
Sumit.Saxena@avagotech.com9b828182015-04-23 16:30:24 +05304009/*
4010 * megasas_refire_mgmt_cmd : Re-fire management commands
4011 * @instance: Controller's soft instance
4012*/
4013void megasas_refire_mgmt_cmd(struct megasas_instance *instance)
4014{
4015 int j;
4016 struct megasas_cmd_fusion *cmd_fusion;
4017 struct fusion_context *fusion;
4018 struct megasas_cmd *cmd_mfi;
4019 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
4020 u16 smid;
Sumit Saxena6d40afb2016-01-28 21:04:23 +05304021 bool refire_cmd = 0;
Shivasharan S54b28042018-01-05 05:27:47 -08004022 u8 result;
4023 u32 opcode = 0;
Sumit.Saxena@avagotech.com9b828182015-04-23 16:30:24 +05304024
4025 fusion = instance->ctrl_context;
4026
4027 /* Re-fire management commands.
4028 * Do not traverse complet MPT frame pool. Start from max_scsi_cmds.
4029 */
4030 for (j = instance->max_scsi_cmds ; j < instance->max_fw_cmds; j++) {
4031 cmd_fusion = fusion->cmd_list[j];
4032 cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
4033 smid = le16_to_cpu(cmd_mfi->context.smid);
Shivasharan S54b28042018-01-05 05:27:47 -08004034 result = REFIRE_CMD;
Sumit.Saxena@avagotech.com9b828182015-04-23 16:30:24 +05304035
4036 if (!smid)
4037 continue;
Shivasharan S690e9c32017-08-23 04:46:59 -07004038
Shivasharan S54b28042018-01-05 05:27:47 -08004039 req_desc = megasas_get_request_descriptor(instance, smid - 1);
4040
4041 switch (cmd_mfi->frame->hdr.cmd) {
4042 case MFI_CMD_DCMD:
4043 opcode = le32_to_cpu(cmd_mfi->frame->dcmd.opcode);
4044 /* Do not refire shutdown command */
4045 if (opcode == MR_DCMD_CTRL_SHUTDOWN) {
4046 cmd_mfi->frame->dcmd.cmd_status = MFI_STAT_OK;
4047 result = COMPLETE_CMD;
4048 break;
4049 }
4050
4051 refire_cmd = ((opcode != MR_DCMD_LD_MAP_GET_INFO)) &&
4052 (opcode != MR_DCMD_SYSTEM_PD_MAP_GET_INFO) &&
4053 !(cmd_mfi->flags & DRV_DCMD_SKIP_REFIRE);
4054
4055 if (!refire_cmd)
4056 result = RETURN_CMD;
4057
4058 break;
Shivasharan Sf870bcb2018-01-05 05:33:04 -08004059 case MFI_CMD_NVME:
4060 if (!instance->support_nvme_passthru) {
4061 cmd_mfi->frame->hdr.cmd_status = MFI_STAT_INVALID_CMD;
4062 result = COMPLETE_CMD;
4063 }
Shivasharan S54b28042018-01-05 05:27:47 -08004064
Shivasharan Sf870bcb2018-01-05 05:33:04 -08004065 break;
Shivasharan S54b28042018-01-05 05:27:47 -08004066 default:
4067 break;
Shivasharan S690e9c32017-08-23 04:46:59 -07004068 }
4069
Shivasharan S54b28042018-01-05 05:27:47 -08004070 switch (result) {
4071 case REFIRE_CMD:
Shivasharan S45b8a352017-02-10 00:59:04 -08004072 megasas_fire_cmd_fusion(instance, req_desc);
Shivasharan S54b28042018-01-05 05:27:47 -08004073 break;
4074 case RETURN_CMD:
Sumit.Saxena@avagotech.com9b828182015-04-23 16:30:24 +05304075 megasas_return_cmd(instance, cmd_mfi);
Shivasharan S54b28042018-01-05 05:27:47 -08004076 break;
4077 case COMPLETE_CMD:
4078 megasas_complete_cmd(instance, cmd_mfi, DID_OK);
4079 break;
4080 }
Sumit.Saxena@avagotech.com9b828182015-04-23 16:30:24 +05304081 }
adam radford9c915a82010-12-21 13:34:31 -08004082}
4083
Sumit Saxena18365b12016-01-28 21:04:25 +05304084/*
4085 * megasas_track_scsiio : Track SCSI IOs outstanding to a SCSI device
4086 * @instance: per adapter struct
4087 * @channel: the channel assigned by the OS
4088 * @id: the id assigned by the OS
4089 *
4090 * Returns SUCCESS if no IOs pending to SCSI device, else return FAILED
4091 */
4092
4093static int megasas_track_scsiio(struct megasas_instance *instance,
4094 int id, int channel)
4095{
4096 int i, found = 0;
4097 struct megasas_cmd_fusion *cmd_fusion;
4098 struct fusion_context *fusion;
4099 fusion = instance->ctrl_context;
4100
4101 for (i = 0 ; i < instance->max_scsi_cmds; i++) {
4102 cmd_fusion = fusion->cmd_list[i];
4103 if (cmd_fusion->scmd &&
4104 (cmd_fusion->scmd->device->id == id &&
4105 cmd_fusion->scmd->device->channel == channel)) {
4106 dev_info(&instance->pdev->dev,
4107 "SCSI commands pending to target"
4108 "channel %d id %d \tSMID: 0x%x\n",
4109 channel, id, cmd_fusion->index);
4110 scsi_print_command(cmd_fusion->scmd);
4111 found = 1;
4112 break;
4113 }
4114 }
4115
4116 return found ? FAILED : SUCCESS;
4117}
4118
4119/**
4120 * megasas_tm_response_code - translation of device response code
4121 * @ioc: per adapter object
4122 * @mpi_reply: MPI reply returned by firmware
4123 *
4124 * Return nothing.
4125 */
4126static void
4127megasas_tm_response_code(struct megasas_instance *instance,
4128 struct MPI2_SCSI_TASK_MANAGE_REPLY *mpi_reply)
4129{
4130 char *desc;
4131
4132 switch (mpi_reply->ResponseCode) {
4133 case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
4134 desc = "task management request completed";
4135 break;
4136 case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
4137 desc = "invalid frame";
4138 break;
4139 case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
4140 desc = "task management request not supported";
4141 break;
4142 case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
4143 desc = "task management request failed";
4144 break;
4145 case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
4146 desc = "task management request succeeded";
4147 break;
4148 case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
4149 desc = "invalid lun";
4150 break;
4151 case 0xA:
4152 desc = "overlapped tag attempted";
4153 break;
4154 case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
4155 desc = "task queued, however not sent to target";
4156 break;
4157 default:
4158 desc = "unknown";
4159 break;
4160 }
4161 dev_dbg(&instance->pdev->dev, "response_code(%01x): %s\n",
4162 mpi_reply->ResponseCode, desc);
4163 dev_dbg(&instance->pdev->dev,
4164 "TerminationCount/DevHandle/Function/TaskType/IOCStat/IOCLoginfo"
4165 " 0x%x/0x%x/0x%x/0x%x/0x%x/0x%x\n",
4166 mpi_reply->TerminationCount, mpi_reply->DevHandle,
4167 mpi_reply->Function, mpi_reply->TaskType,
4168 mpi_reply->IOCStatus, mpi_reply->IOCLogInfo);
4169}
4170
4171/**
4172 * megasas_issue_tm - main routine for sending tm requests
4173 * @instance: per adapter struct
4174 * @device_handle: device handle
4175 * @channel: the channel assigned by the OS
4176 * @id: the id assigned by the OS
4177 * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in megaraid_sas_fusion.c)
4178 * @smid_task: smid assigned to the task
4179 * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
4180 * Context: user
4181 *
4182 * MegaRaid use MPT interface for Task Magement request.
4183 * A generic API for sending task management requests to firmware.
4184 *
4185 * Return SUCCESS or FAILED.
4186 */
4187static int
4188megasas_issue_tm(struct megasas_instance *instance, u16 device_handle,
Shivasharan Se9495e22018-06-04 03:45:12 -07004189 uint channel, uint id, u16 smid_task, u8 type,
4190 struct MR_PRIV_DEVICE *mr_device_priv_data)
Sumit Saxena18365b12016-01-28 21:04:25 +05304191{
4192 struct MR_TASK_MANAGE_REQUEST *mr_request;
4193 struct MPI2_SCSI_TASK_MANAGE_REQUEST *mpi_request;
4194 unsigned long timeleft;
4195 struct megasas_cmd_fusion *cmd_fusion;
4196 struct megasas_cmd *cmd_mfi;
4197 union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
Shivasharan S28661c82017-08-23 04:47:02 -07004198 struct fusion_context *fusion = NULL;
Sumit Saxena18365b12016-01-28 21:04:25 +05304199 struct megasas_cmd_fusion *scsi_lookup;
4200 int rc;
Shivasharan Se9495e22018-06-04 03:45:12 -07004201 int timeout = MEGASAS_DEFAULT_TM_TIMEOUT;
Sumit Saxena18365b12016-01-28 21:04:25 +05304202 struct MPI2_SCSI_TASK_MANAGE_REPLY *mpi_reply;
4203
4204 fusion = instance->ctrl_context;
4205
4206 cmd_mfi = megasas_get_cmd(instance);
4207
4208 if (!cmd_mfi) {
4209 dev_err(&instance->pdev->dev, "Failed from %s %d\n",
4210 __func__, __LINE__);
4211 return -ENOMEM;
4212 }
4213
4214 cmd_fusion = megasas_get_cmd_fusion(instance,
4215 instance->max_scsi_cmds + cmd_mfi->index);
4216
4217 /* Save the smid. To be used for returning the cmd */
4218 cmd_mfi->context.smid = cmd_fusion->index;
4219
4220 req_desc = megasas_get_request_descriptor(instance,
4221 (cmd_fusion->index - 1));
Sumit Saxena18365b12016-01-28 21:04:25 +05304222
4223 cmd_fusion->request_desc = req_desc;
4224 req_desc->Words = 0;
4225
Sumit Saxena18365b12016-01-28 21:04:25 +05304226 mr_request = (struct MR_TASK_MANAGE_REQUEST *) cmd_fusion->io_request;
4227 memset(mr_request, 0, sizeof(struct MR_TASK_MANAGE_REQUEST));
4228 mpi_request = (struct MPI2_SCSI_TASK_MANAGE_REQUEST *) &mr_request->TmRequest;
4229 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
4230 mpi_request->DevHandle = cpu_to_le16(device_handle);
4231 mpi_request->TaskType = type;
4232 mpi_request->TaskMID = cpu_to_le16(smid_task);
4233 mpi_request->LUN[1] = 0;
4234
4235
4236 req_desc = cmd_fusion->request_desc;
4237 req_desc->HighPriority.SMID = cpu_to_le16(cmd_fusion->index);
4238 req_desc->HighPriority.RequestFlags =
4239 (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
4240 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
4241 req_desc->HighPriority.MSIxIndex = 0;
4242 req_desc->HighPriority.LMID = 0;
4243 req_desc->HighPriority.Reserved1 = 0;
4244
4245 if (channel < MEGASAS_MAX_PD_CHANNELS)
4246 mr_request->tmReqFlags.isTMForPD = 1;
4247 else
4248 mr_request->tmReqFlags.isTMForLD = 1;
4249
4250 init_completion(&cmd_fusion->done);
Shivasharan S45b8a352017-02-10 00:59:04 -08004251 megasas_fire_cmd_fusion(instance, req_desc);
Sumit Saxena18365b12016-01-28 21:04:25 +05304252
Shivasharan Se9495e22018-06-04 03:45:12 -07004253 switch (type) {
4254 case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
4255 timeout = mr_device_priv_data->task_abort_tmo;
4256 break;
4257 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
4258 timeout = mr_device_priv_data->target_reset_tmo;
4259 break;
4260 }
4261
4262 timeleft = wait_for_completion_timeout(&cmd_fusion->done, timeout * HZ);
Sumit Saxena18365b12016-01-28 21:04:25 +05304263
4264 if (!timeleft) {
4265 dev_err(&instance->pdev->dev,
4266 "task mgmt type 0x%x timed out\n", type);
4267 cmd_mfi->flags |= DRV_DCMD_SKIP_REFIRE;
4268 mutex_unlock(&instance->reset_mutex);
4269 rc = megasas_reset_fusion(instance->host, MFI_IO_TIMEOUT_OCR);
4270 mutex_lock(&instance->reset_mutex);
4271 return rc;
4272 }
4273
4274 mpi_reply = (struct MPI2_SCSI_TASK_MANAGE_REPLY *) &mr_request->TMReply;
4275 megasas_tm_response_code(instance, mpi_reply);
4276
4277 megasas_return_cmd(instance, cmd_mfi);
4278 rc = SUCCESS;
4279 switch (type) {
4280 case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
Shivasharan S28661c82017-08-23 04:47:02 -07004281 scsi_lookup = fusion->cmd_list[smid_task - 1];
4282
Sumit Saxena18365b12016-01-28 21:04:25 +05304283 if (scsi_lookup->scmd == NULL)
4284 break;
4285 else {
4286 instance->instancet->disable_intr(instance);
Shivasharan S29206da2017-02-10 00:59:34 -08004287 megasas_sync_irqs((unsigned long)instance);
Sumit Saxena18365b12016-01-28 21:04:25 +05304288 instance->instancet->enable_intr(instance);
4289 if (scsi_lookup->scmd == NULL)
4290 break;
4291 }
4292 rc = FAILED;
4293 break;
4294
4295 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
4296 if ((channel == 0xFFFFFFFF) && (id == 0xFFFFFFFF))
4297 break;
4298 instance->instancet->disable_intr(instance);
Shivasharan Sbdb5c552017-08-23 04:46:57 -07004299 megasas_sync_irqs((unsigned long)instance);
Sumit Saxena18365b12016-01-28 21:04:25 +05304300 rc = megasas_track_scsiio(instance, id, channel);
4301 instance->instancet->enable_intr(instance);
4302
4303 break;
4304 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
4305 case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
4306 break;
4307 default:
4308 rc = FAILED;
4309 break;
4310 }
4311
4312 return rc;
4313
4314}
4315
4316/*
4317 * megasas_fusion_smid_lookup : Look for fusion command correpspodning to SCSI
4318 * @instance: per adapter struct
4319 *
4320 * Return Non Zero index, if SMID found in outstanding commands
4321 */
4322static u16 megasas_fusion_smid_lookup(struct scsi_cmnd *scmd)
4323{
4324 int i, ret = 0;
4325 struct megasas_instance *instance;
4326 struct megasas_cmd_fusion *cmd_fusion;
4327 struct fusion_context *fusion;
4328
4329 instance = (struct megasas_instance *)scmd->device->host->hostdata;
4330
4331 fusion = instance->ctrl_context;
4332
4333 for (i = 0; i < instance->max_scsi_cmds; i++) {
4334 cmd_fusion = fusion->cmd_list[i];
4335 if (cmd_fusion->scmd && (cmd_fusion->scmd == scmd)) {
4336 scmd_printk(KERN_NOTICE, scmd, "Abort request is for"
4337 " SMID: %d\n", cmd_fusion->index);
4338 ret = cmd_fusion->index;
4339 break;
4340 }
4341 }
4342
4343 return ret;
4344}
4345
4346/*
4347* megasas_get_tm_devhandle - Get devhandle for TM request
4348* @sdev- OS provided scsi device
4349*
4350* Returns- devhandle/targetID of SCSI device
4351*/
4352static u16 megasas_get_tm_devhandle(struct scsi_device *sdev)
4353{
4354 u16 pd_index = 0;
4355 u32 device_id;
4356 struct megasas_instance *instance;
4357 struct fusion_context *fusion;
4358 struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync;
4359 u16 devhandle = (u16)ULONG_MAX;
4360
4361 instance = (struct megasas_instance *)sdev->host->hostdata;
4362 fusion = instance->ctrl_context;
4363
Shivasharan S3cabd162017-02-10 00:59:05 -08004364 if (!MEGASAS_IS_LOGICAL(sdev)) {
Sumit Saxena18365b12016-01-28 21:04:25 +05304365 if (instance->use_seqnum_jbod_fp) {
Shivasharan S3cabd162017-02-10 00:59:05 -08004366 pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL)
4367 + sdev->id;
4368 pd_sync = (void *)fusion->pd_seq_sync
4369 [(instance->pd_seq_map_id - 1) & 1];
4370 devhandle = pd_sync->seq[pd_index].devHandle;
Sumit Saxena18365b12016-01-28 21:04:25 +05304371 } else
4372 sdev_printk(KERN_ERR, sdev, "Firmware expose tmCapable"
4373 " without JBOD MAP support from %s %d\n", __func__, __LINE__);
4374 } else {
4375 device_id = ((sdev->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL)
4376 + sdev->id;
4377 devhandle = device_id;
4378 }
4379
4380 return devhandle;
4381}
4382
4383/*
4384 * megasas_task_abort_fusion : SCSI task abort function for fusion adapters
4385 * @scmd : pointer to scsi command object
4386 *
4387 * Return SUCCESS, if command aborted else FAILED
4388 */
4389
4390int megasas_task_abort_fusion(struct scsi_cmnd *scmd)
4391{
4392 struct megasas_instance *instance;
4393 u16 smid, devhandle;
4394 struct fusion_context *fusion;
4395 int ret;
4396 struct MR_PRIV_DEVICE *mr_device_priv_data;
4397 mr_device_priv_data = scmd->device->hostdata;
4398
4399
4400 instance = (struct megasas_instance *)scmd->device->host->hostdata;
4401 fusion = instance->ctrl_context;
4402
Shivasharan Sdef0eab2017-02-10 00:59:15 -08004403 scmd_printk(KERN_INFO, scmd, "task abort called for scmd(%p)\n", scmd);
4404 scsi_print_command(scmd);
4405
Sumit Saxena8a01a412016-01-28 21:04:32 +05304406 if (atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) {
Sumit Saxena18365b12016-01-28 21:04:25 +05304407 dev_err(&instance->pdev->dev, "Controller is not OPERATIONAL,"
4408 "SCSI host:%d\n", instance->host->host_no);
4409 ret = FAILED;
4410 return ret;
4411 }
4412
4413 if (!mr_device_priv_data) {
4414 sdev_printk(KERN_INFO, scmd->device, "device been deleted! "
4415 "scmd(%p)\n", scmd);
4416 scmd->result = DID_NO_CONNECT << 16;
4417 ret = SUCCESS;
4418 goto out;
4419 }
4420
4421
4422 if (!mr_device_priv_data->is_tm_capable) {
4423 ret = FAILED;
4424 goto out;
4425 }
4426
4427 mutex_lock(&instance->reset_mutex);
4428
4429 smid = megasas_fusion_smid_lookup(scmd);
4430
4431 if (!smid) {
4432 ret = SUCCESS;
4433 scmd_printk(KERN_NOTICE, scmd, "Command for which abort is"
4434 " issued is not found in oustanding commands\n");
4435 mutex_unlock(&instance->reset_mutex);
4436 goto out;
4437 }
4438
4439 devhandle = megasas_get_tm_devhandle(scmd->device);
4440
4441 if (devhandle == (u16)ULONG_MAX) {
4442 ret = SUCCESS;
4443 sdev_printk(KERN_INFO, scmd->device,
4444 "task abort issued for invalid devhandle\n");
4445 mutex_unlock(&instance->reset_mutex);
4446 goto out;
4447 }
4448 sdev_printk(KERN_INFO, scmd->device,
4449 "attempting task abort! scmd(%p) tm_dev_handle 0x%x\n",
4450 scmd, devhandle);
4451
4452 mr_device_priv_data->tm_busy = 1;
4453 ret = megasas_issue_tm(instance, devhandle,
4454 scmd->device->channel, scmd->device->id, smid,
Shivasharan Se9495e22018-06-04 03:45:12 -07004455 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
4456 mr_device_priv_data);
Sumit Saxena18365b12016-01-28 21:04:25 +05304457 mr_device_priv_data->tm_busy = 0;
4458
4459 mutex_unlock(&instance->reset_mutex);
4460out:
4461 sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
4462 ((ret == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
4463
4464 return ret;
4465}
4466
4467/*
4468 * megasas_reset_target_fusion : target reset function for fusion adapters
4469 * scmd: SCSI command pointer
4470 *
4471 * Returns SUCCESS if all commands associated with target aborted else FAILED
4472 */
4473
4474int megasas_reset_target_fusion(struct scsi_cmnd *scmd)
4475{
4476
4477 struct megasas_instance *instance;
4478 int ret = FAILED;
4479 u16 devhandle;
4480 struct fusion_context *fusion;
4481 struct MR_PRIV_DEVICE *mr_device_priv_data;
4482 mr_device_priv_data = scmd->device->hostdata;
4483
4484 instance = (struct megasas_instance *)scmd->device->host->hostdata;
4485 fusion = instance->ctrl_context;
4486
Shivasharan Sdef0eab2017-02-10 00:59:15 -08004487 sdev_printk(KERN_INFO, scmd->device,
4488 "target reset called for scmd(%p)\n", scmd);
4489
Sumit Saxena8a01a412016-01-28 21:04:32 +05304490 if (atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) {
Sumit Saxena18365b12016-01-28 21:04:25 +05304491 dev_err(&instance->pdev->dev, "Controller is not OPERATIONAL,"
4492 "SCSI host:%d\n", instance->host->host_no);
4493 ret = FAILED;
4494 return ret;
4495 }
4496
4497 if (!mr_device_priv_data) {
4498 sdev_printk(KERN_INFO, scmd->device, "device been deleted! "
4499 "scmd(%p)\n", scmd);
4500 scmd->result = DID_NO_CONNECT << 16;
4501 ret = SUCCESS;
4502 goto out;
4503 }
4504
4505
4506 if (!mr_device_priv_data->is_tm_capable) {
4507 ret = FAILED;
4508 goto out;
4509 }
4510
4511 mutex_lock(&instance->reset_mutex);
4512 devhandle = megasas_get_tm_devhandle(scmd->device);
4513
4514 if (devhandle == (u16)ULONG_MAX) {
4515 ret = SUCCESS;
4516 sdev_printk(KERN_INFO, scmd->device,
4517 "target reset issued for invalid devhandle\n");
4518 mutex_unlock(&instance->reset_mutex);
4519 goto out;
4520 }
4521
4522 sdev_printk(KERN_INFO, scmd->device,
4523 "attempting target reset! scmd(%p) tm_dev_handle 0x%x\n",
4524 scmd, devhandle);
4525 mr_device_priv_data->tm_busy = 1;
4526 ret = megasas_issue_tm(instance, devhandle,
4527 scmd->device->channel, scmd->device->id, 0,
Shivasharan Se9495e22018-06-04 03:45:12 -07004528 MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
4529 mr_device_priv_data);
Sumit Saxena18365b12016-01-28 21:04:25 +05304530 mr_device_priv_data->tm_busy = 0;
4531 mutex_unlock(&instance->reset_mutex);
4532out:
4533 scmd_printk(KERN_NOTICE, scmd, "megasas: target reset %s!!\n",
4534 (ret == SUCCESS) ? "SUCCESS" : "FAILED");
4535
4536 return ret;
4537}
4538
Sumit Saxena8f67c8c2016-01-28 21:14:25 +05304539/*SRIOV get other instance in cluster if any*/
4540struct megasas_instance *megasas_get_peer_instance(struct megasas_instance *instance)
4541{
4542 int i;
4543
4544 for (i = 0; i < MAX_MGMT_ADAPTERS; i++) {
4545 if (megasas_mgmt_info.instance[i] &&
4546 (megasas_mgmt_info.instance[i] != instance) &&
4547 megasas_mgmt_info.instance[i]->requestorId &&
4548 megasas_mgmt_info.instance[i]->peerIsPresent &&
4549 (memcmp((megasas_mgmt_info.instance[i]->clusterId),
4550 instance->clusterId, MEGASAS_CLUSTER_ID_SIZE) == 0))
4551 return megasas_mgmt_info.instance[i];
4552 }
4553 return NULL;
4554}
4555
adam radford229fe472014-03-10 02:51:56 -07004556/* Check for a second path that is currently UP */
4557int megasas_check_mpio_paths(struct megasas_instance *instance,
4558 struct scsi_cmnd *scmd)
adam radford9c915a82010-12-21 13:34:31 -08004559{
Sumit Saxena8f67c8c2016-01-28 21:14:25 +05304560 struct megasas_instance *peer_instance = NULL;
Shivasharan Sf55cf472017-02-10 00:59:07 -08004561 int retval = (DID_REQUEUE << 16);
adam radford229fe472014-03-10 02:51:56 -07004562
Sumit Saxena8f67c8c2016-01-28 21:14:25 +05304563 if (instance->peerIsPresent) {
4564 peer_instance = megasas_get_peer_instance(instance);
4565 if ((peer_instance) &&
4566 (atomic_read(&peer_instance->adprecovery) ==
4567 MEGASAS_HBA_OPERATIONAL))
4568 retval = (DID_NO_CONNECT << 16);
adam radford229fe472014-03-10 02:51:56 -07004569 }
adam radford229fe472014-03-10 02:51:56 -07004570 return retval;
4571}
4572
4573/* Core fusion reset function */
Sumit Saxena18365b12016-01-28 21:04:25 +05304574int megasas_reset_fusion(struct Scsi_Host *shost, int reason)
adam radford229fe472014-03-10 02:51:56 -07004575{
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05004576 int retval = SUCCESS, i, j, convert = 0;
adam radford9c915a82010-12-21 13:34:31 -08004577 struct megasas_instance *instance;
Shivasharan S8bf7c652017-02-10 00:59:03 -08004578 struct megasas_cmd_fusion *cmd_fusion, *r1_cmd;
adam radford9c915a82010-12-21 13:34:31 -08004579 struct fusion_context *fusion;
sumit.saxena@avagotech.com79b82c22015-08-31 17:23:41 +05304580 u32 abs_state, status_reg, reset_adapter;
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05304581 u32 io_timeout_in_crash_mode = 0;
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05304582 struct scsi_cmnd *scmd_local = NULL;
Sumit Saxena18365b12016-01-28 21:04:25 +05304583 struct scsi_device *sdev;
Shivasharan Se9495e22018-06-04 03:45:12 -07004584 int ret_target_prop = DCMD_FAILED;
4585 bool is_target_prop = false;
adam radford9c915a82010-12-21 13:34:31 -08004586
4587 instance = (struct megasas_instance *)shost->hostdata;
4588 fusion = instance->ctrl_context;
4589
adam radford229fe472014-03-10 02:51:56 -07004590 mutex_lock(&instance->reset_mutex);
4591
Sumit Saxena8a01a412016-01-28 21:04:32 +05304592 if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) {
Bjorn Helgaas1be18252015-07-07 15:52:34 -05004593 dev_warn(&instance->pdev->dev, "Hardware critical error, "
adam radford229fe472014-03-10 02:51:56 -07004594 "returning FAILED for scsi%d.\n",
4595 instance->host->host_no);
Adam Radforda2fbcbc2014-07-09 15:17:54 -07004596 mutex_unlock(&instance->reset_mutex);
adam radfordd4a759a2011-10-08 18:14:39 -07004597 return FAILED;
adam radford9c915a82010-12-21 13:34:31 -08004598 }
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05304599 status_reg = instance->instancet->read_fw_status_reg(instance->reg_set);
4600 abs_state = status_reg & MFI_STATE_MASK;
4601
4602 /* IO timeout detected, forcibly put FW in FAULT state */
4603 if (abs_state != MFI_STATE_FAULT && instance->crash_dump_buf &&
Sumit Saxena18365b12016-01-28 21:04:25 +05304604 instance->crash_dump_app_support && reason) {
4605 dev_info(&instance->pdev->dev, "IO/DCMD timeout is detected, "
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05304606 "forcibly FAULT Firmware\n");
Sumit Saxena8a01a412016-01-28 21:04:32 +05304607 atomic_set(&instance->adprecovery, MEGASAS_ADPRESET_SM_INFAULT);
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05304608 status_reg = readl(&instance->reg_set->doorbell);
4609 writel(status_reg | MFI_STATE_FORCE_OCR,
4610 &instance->reg_set->doorbell);
4611 readl(&instance->reg_set->doorbell);
4612 mutex_unlock(&instance->reset_mutex);
4613 do {
4614 ssleep(3);
4615 io_timeout_in_crash_mode++;
4616 dev_dbg(&instance->pdev->dev, "waiting for [%d] "
4617 "seconds for crash dump collection and OCR "
4618 "to be done\n", (io_timeout_in_crash_mode * 3));
Sumit Saxena8a01a412016-01-28 21:04:32 +05304619 } while ((atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) &&
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05304620 (io_timeout_in_crash_mode < 80));
4621
Sumit Saxena8a01a412016-01-28 21:04:32 +05304622 if (atomic_read(&instance->adprecovery) == MEGASAS_HBA_OPERATIONAL) {
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05304623 dev_info(&instance->pdev->dev, "OCR done for IO "
4624 "timeout case\n");
4625 retval = SUCCESS;
4626 } else {
4627 dev_info(&instance->pdev->dev, "Controller is not "
4628 "operational after 240 seconds wait for IO "
4629 "timeout case in FW crash dump mode\n do "
4630 "OCR/kill adapter\n");
4631 retval = megasas_reset_fusion(shost, 0);
4632 }
4633 return retval;
4634 }
adam radford9c915a82010-12-21 13:34:31 -08004635
adam radford229fe472014-03-10 02:51:56 -07004636 if (instance->requestorId && !instance->skip_heartbeat_timer_del)
4637 del_timer_sync(&instance->sriov_heartbeat_timer);
adam radford7e70e732011-05-11 18:34:08 -07004638 set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
Sumit Saxena8a01a412016-01-28 21:04:32 +05304639 atomic_set(&instance->adprecovery, MEGASAS_ADPRESET_SM_POLLING);
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +05304640 instance->instancet->disable_intr(instance);
Shivasharan S29206da2017-02-10 00:59:34 -08004641 megasas_sync_irqs((unsigned long)instance);
adam radford7e70e732011-05-11 18:34:08 -07004642
adam radford9c915a82010-12-21 13:34:31 -08004643 /* First try waiting for commands to complete */
Sumit Saxena18365b12016-01-28 21:04:25 +05304644 if (megasas_wait_for_outstanding_fusion(instance, reason,
adam radford229fe472014-03-10 02:51:56 -07004645 &convert)) {
Sumit Saxena8a01a412016-01-28 21:04:32 +05304646 atomic_set(&instance->adprecovery, MEGASAS_ADPRESET_SM_INFAULT);
Bjorn Helgaas1be18252015-07-07 15:52:34 -05004647 dev_warn(&instance->pdev->dev, "resetting fusion "
adam radford229fe472014-03-10 02:51:56 -07004648 "adapter scsi%d.\n", instance->host->host_no);
4649 if (convert)
Sumit Saxena18365b12016-01-28 21:04:25 +05304650 reason = 0;
adam radford229fe472014-03-10 02:51:56 -07004651
Shivasharan Sdef0eab2017-02-10 00:59:15 -08004652 if (megasas_dbg_lvl & OCR_LOGS)
4653 dev_info(&instance->pdev->dev, "\nPending SCSI commands:\n");
4654
adam radford9c915a82010-12-21 13:34:31 -08004655 /* Now return commands back to the OS */
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05304656 for (i = 0 ; i < instance->max_scsi_cmds; i++) {
adam radford9c915a82010-12-21 13:34:31 -08004657 cmd_fusion = fusion->cmd_list[i];
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05004658 /*check for extra commands issued by driver*/
Shivasharan S630d42b2018-12-17 00:47:37 -08004659 if (instance->adapter_type >= VENTURA_SERIES) {
Shivasharan S8bf7c652017-02-10 00:59:03 -08004660 r1_cmd = fusion->cmd_list[i + instance->max_fw_cmds];
4661 megasas_return_cmd_fusion(instance, r1_cmd);
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05004662 }
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05304663 scmd_local = cmd_fusion->scmd;
adam radford9c915a82010-12-21 13:34:31 -08004664 if (cmd_fusion->scmd) {
Shivasharan Sdef0eab2017-02-10 00:59:15 -08004665 if (megasas_dbg_lvl & OCR_LOGS) {
4666 sdev_printk(KERN_INFO,
4667 cmd_fusion->scmd->device, "SMID: 0x%x\n",
4668 cmd_fusion->index);
4669 scsi_print_command(cmd_fusion->scmd);
4670 }
4671
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05304672 scmd_local->result =
adam radford229fe472014-03-10 02:51:56 -07004673 megasas_check_mpio_paths(instance,
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05304674 scmd_local);
Sasikumar Chandrasekaranb71b49c2017-01-10 18:20:51 -05004675 if (instance->ldio_threshold &&
4676 megasas_cmd_type(scmd_local) == READ_WRITE_LDIO)
Sumit Saxena308ec452016-01-28 21:04:30 +05304677 atomic_dec(&instance->ldio_outstanding);
adam radford9c915a82010-12-21 13:34:31 -08004678 megasas_return_cmd_fusion(instance, cmd_fusion);
Sumit.Saxena@avagotech.com4026e9a2015-04-23 16:31:24 +05304679 scsi_dma_unmap(scmd_local);
4680 scmd_local->scsi_done(scmd_local);
adam radford9c915a82010-12-21 13:34:31 -08004681 }
4682 }
4683
Sasikumar Chandrasekaran69c337c2017-01-10 18:20:47 -05004684 atomic_set(&instance->fw_outstanding, 0);
4685
adam radford7e70e732011-05-11 18:34:08 -07004686 status_reg = instance->instancet->read_fw_status_reg(
4687 instance->reg_set);
4688 abs_state = status_reg & MFI_STATE_MASK;
4689 reset_adapter = status_reg & MFI_RESET_ADAPTER;
4690 if (instance->disableOnlineCtrlReset ||
4691 (abs_state == MFI_STATE_FAULT && !reset_adapter)) {
adam radford9c915a82010-12-21 13:34:31 -08004692 /* Reset not supported, kill adapter */
Bjorn Helgaas1be18252015-07-07 15:52:34 -05004693 dev_warn(&instance->pdev->dev, "Reset not supported"
adam radford229fe472014-03-10 02:51:56 -07004694 ", killing adapter scsi%d.\n",
4695 instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08004696 megaraid_sas_kill_hba(instance);
adam radford229fe472014-03-10 02:51:56 -07004697 instance->skip_heartbeat_timer_del = 1;
adam radford9c915a82010-12-21 13:34:31 -08004698 retval = FAILED;
4699 goto out;
4700 }
4701
adam radford229fe472014-03-10 02:51:56 -07004702 /* Let SR-IOV VF & PF sync up if there was a HB failure */
Sumit Saxena18365b12016-01-28 21:04:25 +05304703 if (instance->requestorId && !reason) {
adam radford229fe472014-03-10 02:51:56 -07004704 msleep(MEGASAS_OCR_SETTLE_TIME_VF);
Sumit Saxena3885c262016-01-28 21:04:35 +05304705 goto transition_to_ready;
adam radford229fe472014-03-10 02:51:56 -07004706 }
4707
adam radford9c915a82010-12-21 13:34:31 -08004708 /* Now try to reset the chip */
4709 for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) {
adam radford9c915a82010-12-21 13:34:31 -08004710
sumit.saxena@avagotech.com79b82c22015-08-31 17:23:41 +05304711 if (instance->instancet->adp_reset
4712 (instance, instance->reg_set))
adam radford9c915a82010-12-21 13:34:31 -08004713 continue;
Sumit Saxena3885c262016-01-28 21:04:35 +05304714transition_to_ready:
adam radford9c915a82010-12-21 13:34:31 -08004715 /* Wait for FW to become ready */
adam radford058a8fa2011-10-08 18:14:27 -07004716 if (megasas_transition_to_ready(instance, 1)) {
Sumit Saxena3885c262016-01-28 21:04:35 +05304717 dev_warn(&instance->pdev->dev,
4718 "Failed to transition controller to ready for "
4719 "scsi%d.\n", instance->host->host_no);
4720 if (instance->requestorId && !reason)
4721 goto fail_kill_adapter;
4722 else
4723 continue;
adam radford9c915a82010-12-21 13:34:31 -08004724 }
adam radford9c915a82010-12-21 13:34:31 -08004725 megasas_reset_reply_desc(instance);
Sumit Saxena308ec452016-01-28 21:04:30 +05304726 megasas_fusion_update_can_queue(instance, OCR_CONTEXT);
4727
adam radford9c915a82010-12-21 13:34:31 -08004728 if (megasas_ioc_init_fusion(instance)) {
Sumit Saxena3885c262016-01-28 21:04:35 +05304729 if (instance->requestorId && !reason)
4730 goto fail_kill_adapter;
4731 else
4732 continue;
adam radford9c915a82010-12-21 13:34:31 -08004733 }
4734
Sumit.Saxena@avagotech.comd009b572014-11-17 15:24:13 +05304735 if (megasas_get_ctrl_info(instance)) {
4736 dev_info(&instance->pdev->dev,
4737 "Failed from %s %d\n",
4738 __func__, __LINE__);
Sumit.Saxena@avagotech.comd009b572014-11-17 15:24:13 +05304739 megaraid_sas_kill_hba(instance);
4740 retval = FAILED;
Shivasharan Sa6821ca2017-02-10 00:59:31 -08004741 goto out;
Sumit.Saxena@avagotech.comd009b572014-11-17 15:24:13 +05304742 }
Shivasharan S54b28042018-01-05 05:27:47 -08004743
4744 megasas_refire_mgmt_cmd(instance);
4745
adam radford9c915a82010-12-21 13:34:31 -08004746 /* Reset load balance info */
Shivasharan S5fc499b2017-02-10 00:59:17 -08004747 if (fusion->load_balance_info)
4748 memset(fusion->load_balance_info, 0,
4749 (sizeof(struct LD_LOAD_BALANCE_INFO) *
4750 MAX_LOGICAL_DRIVES_EXT));
adam radford9c915a82010-12-21 13:34:31 -08004751
4752 if (!megasas_get_map_info(instance))
4753 megasas_sync_map_info(instance);
4754
sumit.saxena@avagotech.com3761cb42015-08-31 17:23:11 +05304755 megasas_setup_jbod_map(instance);
4756
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05004757 /* reset stream detection array */
Shivasharan S630d42b2018-12-17 00:47:37 -08004758 if (instance->adapter_type >= VENTURA_SERIES) {
Sasikumar Chandrasekaranfdd84e22017-01-10 18:20:46 -05004759 for (j = 0; j < MAX_LOGICAL_DRIVES_EXT; ++j) {
4760 memset(fusion->stream_detect_by_ld[j],
4761 0, sizeof(struct LD_STREAM_DETECT));
4762 fusion->stream_detect_by_ld[j]->mru_bit_map
4763 = MR_STREAM_BITMAP;
4764 }
4765 }
4766
Sumit.Saxena@avagotech.comac340c52014-11-17 15:24:18 +05304767 clear_bit(MEGASAS_FUSION_IN_RESET,
4768 &instance->reset_flags);
4769 instance->instancet->enable_intr(instance);
Shivasharan Se9495e22018-06-04 03:45:12 -07004770
4771 shost_for_each_device(sdev, shost) {
4772 if ((instance->tgt_prop) &&
4773 (instance->nvme_page_size))
4774 ret_target_prop = megasas_get_target_prop(instance, sdev);
4775
4776 is_target_prop = (ret_target_prop == DCMD_SUCCESS) ? true : false;
4777 megasas_set_dynamic_target_properties(sdev, is_target_prop);
4778 }
4779
Sumit Saxena8a01a412016-01-28 21:04:32 +05304780 atomic_set(&instance->adprecovery, MEGASAS_HBA_OPERATIONAL);
Sumit.Saxena@avagotech.comac340c52014-11-17 15:24:18 +05304781
Shivasharan S2d2c2332017-08-23 04:47:06 -07004782 dev_info(&instance->pdev->dev, "Interrupts are enabled and"
4783 " controller is OPERATIONAL for scsi:%d\n",
4784 instance->host->host_no);
4785
adam radford229fe472014-03-10 02:51:56 -07004786 /* Restart SR-IOV heartbeat */
4787 if (instance->requestorId) {
4788 if (!megasas_sriov_start_heartbeat(instance, 0))
Kees Cookc251a7b2017-10-22 15:30:04 -07004789 megasas_start_timer(instance);
adam radford229fe472014-03-10 02:51:56 -07004790 else
4791 instance->skip_heartbeat_timer_del = 1;
4792 }
4793
Sumit.Saxena@avagotech.comac340c52014-11-17 15:24:18 +05304794 if (instance->crash_dump_drv_support &&
4795 instance->crash_dump_app_support)
4796 megasas_set_crash_dump_params(instance,
4797 MR_CRASH_BUF_TURN_ON);
4798 else
4799 megasas_set_crash_dump_params(instance,
4800 MR_CRASH_BUF_TURN_OFF);
4801
Shivasharan Sf0c21df2018-10-16 23:37:40 -07004802 if (instance->snapdump_wait_time) {
4803 megasas_get_snapdump_properties(instance);
4804 dev_info(&instance->pdev->dev,
4805 "Snap dump wait time\t: %d\n",
4806 instance->snapdump_wait_time);
4807 }
4808
adam radford9c915a82010-12-21 13:34:31 -08004809 retval = SUCCESS;
Shivasharan S2d2c2332017-08-23 04:47:06 -07004810
4811 /* Adapter reset completed successfully */
4812 dev_warn(&instance->pdev->dev,
4813 "Reset successful for scsi%d.\n",
4814 instance->host->host_no);
4815
adam radford9c915a82010-12-21 13:34:31 -08004816 goto out;
4817 }
Sumit Saxena3885c262016-01-28 21:04:35 +05304818fail_kill_adapter:
adam radford9c915a82010-12-21 13:34:31 -08004819 /* Reset failed, kill the adapter */
Bjorn Helgaas1be18252015-07-07 15:52:34 -05004820 dev_warn(&instance->pdev->dev, "Reset failed, killing "
adam radford229fe472014-03-10 02:51:56 -07004821 "adapter scsi%d.\n", instance->host->host_no);
adam radford9c915a82010-12-21 13:34:31 -08004822 megaraid_sas_kill_hba(instance);
adam radford229fe472014-03-10 02:51:56 -07004823 instance->skip_heartbeat_timer_del = 1;
adam radford9c915a82010-12-21 13:34:31 -08004824 retval = FAILED;
4825 } else {
adam radford229fe472014-03-10 02:51:56 -07004826 /* For VF: Restart HB timer if we didn't OCR */
4827 if (instance->requestorId) {
Kees Cookc251a7b2017-10-22 15:30:04 -07004828 megasas_start_timer(instance);
adam radford229fe472014-03-10 02:51:56 -07004829 }
adam radford3f0e58bc2011-10-08 18:14:59 -07004830 clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
Sumit.Saxena@lsi.comd46a3ad2013-05-22 12:34:14 +05304831 instance->instancet->enable_intr(instance);
Sumit Saxena8a01a412016-01-28 21:04:32 +05304832 atomic_set(&instance->adprecovery, MEGASAS_HBA_OPERATIONAL);
adam radford9c915a82010-12-21 13:34:31 -08004833 }
4834out:
4835 clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
4836 mutex_unlock(&instance->reset_mutex);
4837 return retval;
4838}
4839
Shivasharan S3f6194a2018-10-16 23:37:39 -07004840/* Fusion Crash dump collection */
4841void megasas_fusion_crash_dump(struct megasas_instance *instance)
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05304842{
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05304843 u32 status_reg;
4844 u8 partial_copy = 0;
Shivasharan S3f6194a2018-10-16 23:37:39 -07004845 int wait = 0;
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05304846
4847
4848 status_reg = instance->instancet->read_fw_status_reg(instance->reg_set);
4849
4850 /*
4851 * Allocate host crash buffers to copy data from 1 MB DMA crash buffer
4852 * to host crash buffers
4853 */
4854 if (instance->drv_buf_index == 0) {
4855 /* Buffer is already allocated for old Crash dump.
4856 * Do OCR and do not wait for crash dump collection
4857 */
4858 if (instance->drv_buf_alloc) {
4859 dev_info(&instance->pdev->dev, "earlier crash dump is "
4860 "not yet copied by application, ignoring this "
4861 "crash dump and initiating OCR\n");
4862 status_reg |= MFI_STATE_CRASH_DUMP_DONE;
4863 writel(status_reg,
Shivasharan S81b76452018-10-16 23:37:51 -07004864 &instance->reg_set->outbound_scratch_pad_0);
4865 readl(&instance->reg_set->outbound_scratch_pad_0);
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05304866 return;
4867 }
4868 megasas_alloc_host_crash_buffer(instance);
4869 dev_info(&instance->pdev->dev, "Number of host crash buffers "
4870 "allocated: %d\n", instance->drv_buf_alloc);
4871 }
4872
Shivasharan S3f6194a2018-10-16 23:37:39 -07004873 while (!(status_reg & MFI_STATE_CRASH_DUMP_DONE) &&
4874 (wait < MEGASAS_WATCHDOG_WAIT_COUNT)) {
4875 if (!(status_reg & MFI_STATE_DMADONE)) {
4876 /*
4877 * Next crash dump buffer is not yet DMA'd by FW
4878 * Check after 10ms. Wait for 1 second for FW to
4879 * post the next buffer. If not bail out.
4880 */
4881 wait++;
4882 msleep(MEGASAS_WAIT_FOR_NEXT_DMA_MSECS);
4883 status_reg = instance->instancet->read_fw_status_reg(
4884 instance->reg_set);
4885 continue;
4886 }
4887
4888 wait = 0;
4889 if (instance->drv_buf_index >= instance->drv_buf_alloc) {
4890 dev_info(&instance->pdev->dev,
4891 "Driver is done copying the buffer: %d\n",
4892 instance->drv_buf_alloc);
4893 status_reg |= MFI_STATE_CRASH_DUMP_DONE;
4894 partial_copy = 1;
4895 break;
4896 } else {
4897 memcpy(instance->crash_buf[instance->drv_buf_index],
4898 instance->crash_dump_buf, CRASH_DMA_BUF_SIZE);
4899 instance->drv_buf_index++;
4900 status_reg &= ~MFI_STATE_DMADONE;
4901 }
4902
Shivasharan S81b76452018-10-16 23:37:51 -07004903 writel(status_reg, &instance->reg_set->outbound_scratch_pad_0);
4904 readl(&instance->reg_set->outbound_scratch_pad_0);
Shivasharan S3f6194a2018-10-16 23:37:39 -07004905
4906 msleep(MEGASAS_WAIT_FOR_NEXT_DMA_MSECS);
4907 status_reg = instance->instancet->read_fw_status_reg(
4908 instance->reg_set);
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05304909 }
4910
4911 if (status_reg & MFI_STATE_CRASH_DUMP_DONE) {
4912 dev_info(&instance->pdev->dev, "Crash Dump is available,number "
4913 "of copied buffers: %d\n", instance->drv_buf_index);
4914 instance->fw_crash_buffer_size = instance->drv_buf_index;
4915 instance->fw_crash_state = AVAILABLE;
4916 instance->drv_buf_index = 0;
Shivasharan S81b76452018-10-16 23:37:51 -07004917 writel(status_reg, &instance->reg_set->outbound_scratch_pad_0);
4918 readl(&instance->reg_set->outbound_scratch_pad_0);
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05304919 if (!partial_copy)
4920 megasas_reset_fusion(instance->host, 0);
Sumit.Saxena@avagotech.comfc62b3f2014-09-12 18:57:28 +05304921 }
4922}
4923
4924
adam radford9c915a82010-12-21 13:34:31 -08004925/* Fusion OCR work queue */
4926void megasas_fusion_ocr_wq(struct work_struct *work)
4927{
4928 struct megasas_instance *instance =
4929 container_of(work, struct megasas_instance, work_init);
4930
adam radford229fe472014-03-10 02:51:56 -07004931 megasas_reset_fusion(instance->host, 0);
adam radford9c915a82010-12-21 13:34:31 -08004932}
4933
Shivasharan S5fc499b2017-02-10 00:59:17 -08004934/* Allocate fusion context */
4935int
4936megasas_alloc_fusion_context(struct megasas_instance *instance)
4937{
4938 struct fusion_context *fusion;
4939
Shivasharan S2dd689c2017-10-19 02:48:53 -07004940 instance->ctrl_context = kzalloc(sizeof(struct fusion_context),
4941 GFP_KERNEL);
Shivasharan S5fc499b2017-02-10 00:59:17 -08004942 if (!instance->ctrl_context) {
Shivasharan S2dd689c2017-10-19 02:48:53 -07004943 dev_err(&instance->pdev->dev, "Failed from %s %d\n",
4944 __func__, __LINE__);
4945 return -ENOMEM;
Shivasharan S5fc499b2017-02-10 00:59:17 -08004946 }
4947
4948 fusion = instance->ctrl_context;
4949
Shivasharan S2dd689c2017-10-19 02:48:53 -07004950 fusion->log_to_span_pages = get_order(MAX_LOGICAL_DRIVES_EXT *
4951 sizeof(LD_SPAN_INFO));
4952 fusion->log_to_span =
4953 (PLD_SPAN_INFO)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
4954 fusion->log_to_span_pages);
4955 if (!fusion->log_to_span) {
Kees Cookfad953c2018-06-12 14:27:37 -07004956 fusion->log_to_span =
4957 vzalloc(array_size(MAX_LOGICAL_DRIVES_EXT,
4958 sizeof(LD_SPAN_INFO)));
Shivasharan S2dd689c2017-10-19 02:48:53 -07004959 if (!fusion->log_to_span) {
4960 dev_err(&instance->pdev->dev, "Failed from %s %d\n",
4961 __func__, __LINE__);
4962 return -ENOMEM;
4963 }
4964 }
4965
Shivasharan S5fc499b2017-02-10 00:59:17 -08004966 fusion->load_balance_info_pages = get_order(MAX_LOGICAL_DRIVES_EXT *
4967 sizeof(struct LD_LOAD_BALANCE_INFO));
4968 fusion->load_balance_info =
4969 (struct LD_LOAD_BALANCE_INFO *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
4970 fusion->load_balance_info_pages);
4971 if (!fusion->load_balance_info) {
Kees Cookfad953c2018-06-12 14:27:37 -07004972 fusion->load_balance_info =
4973 vzalloc(array_size(MAX_LOGICAL_DRIVES_EXT,
4974 sizeof(struct LD_LOAD_BALANCE_INFO)));
Shivasharan S5fc499b2017-02-10 00:59:17 -08004975 if (!fusion->load_balance_info)
4976 dev_err(&instance->pdev->dev, "Failed to allocate load_balance_info, "
4977 "continuing without Load Balance support\n");
4978 }
4979
4980 return 0;
4981}
4982
4983void
4984megasas_free_fusion_context(struct megasas_instance *instance)
4985{
4986 struct fusion_context *fusion = instance->ctrl_context;
4987
4988 if (fusion) {
4989 if (fusion->load_balance_info) {
4990 if (is_vmalloc_addr(fusion->load_balance_info))
4991 vfree(fusion->load_balance_info);
4992 else
4993 free_pages((ulong)fusion->load_balance_info,
4994 fusion->load_balance_info_pages);
4995 }
4996
Shivasharan S2dd689c2017-10-19 02:48:53 -07004997 if (fusion->log_to_span) {
4998 if (is_vmalloc_addr(fusion->log_to_span))
4999 vfree(fusion->log_to_span);
5000 else
5001 free_pages((ulong)fusion->log_to_span,
5002 fusion->log_to_span_pages);
5003 }
5004
5005 kfree(fusion);
Shivasharan S5fc499b2017-02-10 00:59:17 -08005006 }
5007}
5008
adam radford9c915a82010-12-21 13:34:31 -08005009struct megasas_instance_template megasas_instance_template_fusion = {
adam radford9c915a82010-12-21 13:34:31 -08005010 .enable_intr = megasas_enable_intr_fusion,
5011 .disable_intr = megasas_disable_intr_fusion,
5012 .clear_intr = megasas_clear_intr_fusion,
5013 .read_fw_status_reg = megasas_read_fw_status_reg_fusion,
5014 .adp_reset = megasas_adp_reset_fusion,
5015 .check_reset = megasas_check_reset_fusion,
5016 .service_isr = megasas_isr_fusion,
5017 .tasklet = megasas_complete_cmd_dpc_fusion,
5018 .init_adapter = megasas_init_adapter_fusion,
5019 .build_and_issue_cmd = megasas_build_and_issue_cmd_fusion,
5020 .issue_dcmd = megasas_issue_dcmd_fusion,
5021};