1 diff -Nurp linux-2.6.22-810/drivers/scsi/megaraid/megaraid_sas.c linux-2.6.22-820/drivers/scsi/megaraid/megaraid_sas.c
2 --- linux-2.6.22-810/drivers/scsi/megaraid/megaraid_sas.c 2007-07-08 19:32:17.000000000 -0400
3 +++ linux-2.6.22-820/drivers/scsi/megaraid/megaraid_sas.c 2010-12-08 15:32:31.000000000 -0500
6 * Linux MegaRAID driver for SAS based RAID controllers
8 - * Copyright (c) 2003-2005 LSI Logic Corporation.
9 + * Copyright (c) 2009 LSI Corporation.
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 - * as published by the Free Software Foundation; either version
14 - * 2 of the License, or (at your option) any later version.
15 + *as published by the Free Software Foundation; either version 2
16 + *of the License, or (at your option) any later version.
18 - * FILE : megaraid_sas.c
19 - * Version : v00.00.03.10-rc5
20 + *This program is distributed in the hope that it will be useful,
21 + *but WITHOUT ANY WARRANTY; without even the implied warranty of
22 + *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 + *GNU General Public License for more details.
26 - * (email-id : megaraidlinux@lsi.com)
27 - * Sreenivas Bagalkote
30 + *You should have received a copy of the GNU General Public License
31 + *along with this program; if not, write to the Free Software
32 + *Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
34 - * List of supported controllers
36 - * OEM Product Name VID DID SSVID SSID
37 - * --- ------------ --- --- ---- ----
38 + * Send feedback to <Bo.Yang@lsi.com>
41 #include <linux/kernel.h>
43 #include <linux/spinlock.h>
44 #include <linux/interrupt.h>
45 #include <linux/delay.h>
46 +#include <linux/smp_lock.h>
47 #include <linux/uio.h>
48 #include <asm/uaccess.h>
50 #include <linux/compat.h>
51 #include <linux/blkdev.h>
52 #include <linux/mutex.h>
53 +#include <linux/poll.h>
55 #include <scsi/scsi.h>
56 #include <scsi/scsi_cmnd.h>
58 #include <scsi/scsi_host.h>
59 #include "megaraid_sas.h"
62 + * poll_mode_io:1- schedule complete completion from q cmd
64 +static unsigned int poll_mode_io;
65 +module_param_named(poll_mode_io, poll_mode_io, int, 0);
66 +MODULE_PARM_DESC(poll_mode_io,
67 + "Complete cmds from IO path, (default=0)");
70 + * Number of sectors per IO command
71 + * Will be set in megasas_init_mfi if user does not provide
73 +static unsigned int max_sectors;
74 +module_param_named(max_sectors, max_sectors, int, 0);
75 +MODULE_PARM_DESC(max_sectors,
76 + "Maximum number of sectors per IO command");
78 MODULE_LICENSE("GPL");
79 MODULE_VERSION(MEGASAS_VERSION);
80 MODULE_AUTHOR("megaraidlinux@lsi.com");
81 -MODULE_DESCRIPTION("LSI Logic MegaRAID SAS Driver");
82 +MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
85 * PCI ID table for all supported controllers
86 @@ -60,6 +76,16 @@ static struct pci_device_id megasas_pci_
88 {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)},
90 + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)},
92 + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078GEN2)},
94 + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)},
96 + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0073SKINNY)},
98 + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0071SKINNY)},
100 {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)},
101 /* xscale IOP, vega */
102 {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
103 @@ -73,9 +99,35 @@ static int megasas_mgmt_majorno;
104 static struct megasas_mgmt_info megasas_mgmt_info;
105 static struct fasync_struct *megasas_async_queue;
106 static DEFINE_MUTEX(megasas_async_queue_mutex);
107 +static DEFINE_MUTEX(megasas_poll_wait_mutex);
110 +static int megasas_poll_wait_aen;
111 +static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait);
112 +static u32 support_poll_for_event;
113 +static u32 support_device_change;
115 +/* define lock for aen poll */
116 +spinlock_t poll_aen_lock;
118 static u32 megasas_dbg_lvl;
121 +megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
124 +static int megasas_transition_to_ready(struct megasas_instance* instance);
125 +static int megasas_get_pd_list(struct megasas_instance *instance);
126 +static int megasas_issue_init_mfi(struct megasas_instance *instance);
127 +static int megasas_register_aen(struct megasas_instance *instance, u32 seq_num, u32 class_locale_word);
128 +static int megasas_check_cpx_support( struct megasas_instance *instance);
129 +static u32 megasas_remove_cpx( struct megasas_instance *instance);
130 +static int megasas_send_cpx_queue_data( struct megasas_instance *instance );
131 +static int megasas_handle_cpx_requests( struct megasas_instance *instance);
132 +static u32 megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem * regs);
133 +static int megasas_adp_reset_gen2(struct megasas_instance *instance, struct megasas_register_set __iomem * reg_set);
137 * megasas_get_cmd - Get a command from the free pool
138 * @instance: Adapter soft state
139 @@ -133,7 +185,7 @@ megasas_return_cmd(struct megasas_instan
141 megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
143 - writel(1, &(regs)->outbound_intr_mask);
144 + writel(0, &(regs)->outbound_intr_mask);
146 /* Dummy readl to force pci flush */
147 readl(®s->outbound_intr_mask);
148 @@ -169,21 +221,27 @@ static int
149 megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
154 * Check if it is our interrupt
156 status = readl(®s->outbound_intr_status);
158 - if (!(status & MFI_OB_INTR_STATUS_MASK)) {
161 + if (status & MFI_OB_INTR_STATUS_MASK)
162 + mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
163 + if (status & MFI_XSCALE_OMR0_CHANGE_INTERRUPT)
164 + mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
167 * Clear the interrupt by writing back the same value
170 writel(status, ®s->outbound_intr_status);
173 + /* Dummy readl to force pci flush */
174 + readl(®s->outbound_intr_status);
180 @@ -193,10 +251,69 @@ megasas_clear_intr_xscale(struct megasas
181 * @regs : MFI register set
184 -megasas_fire_cmd_xscale(dma_addr_t frame_phys_addr,u32 frame_count, struct megasas_register_set __iomem *regs)
185 +megasas_fire_cmd_xscale(struct megasas_instance *instance,
186 + dma_addr_t frame_phys_addr,
188 + struct megasas_register_set __iomem *regs)
190 + unsigned long flags;
191 + spin_lock_irqsave(&instance->hba_lock, flags);
192 writel((frame_phys_addr >> 3)|(frame_count),
193 &(regs)->inbound_queue_port);
194 + spin_unlock_irqrestore(&instance->hba_lock, flags);
198 + * megasas_adp_reset_xscale - For controller reset
199 + * @regs: MFI register set
202 +megasas_adp_reset_xscale(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
206 + writel(MFI_ADP_RESET, ®s->inbound_doorbell);
208 + for (i=0; i < 3; i++)
209 + msleep(1000); /* sleep for 3 secs */
211 + pci_read_config_dword(instance->pdev, MFI_1068_PCSR_OFFSET, &pcidata);
212 + printk("pcidata = %x\n", pcidata);
213 + if (pcidata & 0x2) {
214 + printk("mfi 1068 offset read=%x\n", pcidata);
216 + pci_write_config_dword(instance->pdev, MFI_1068_PCSR_OFFSET, pcidata);
218 + for (i=0; i<2; i++)
219 + msleep(1000); /* need to wait 2 secs again */
222 + pci_read_config_dword(instance->pdev, MFI_1068_FW_HANDSHAKE_OFFSET, &pcidata);
223 + printk("mfi 1068 offset handshake read=%x\n", pcidata);
224 + if ((pcidata & 0xffff0000) == MFI_1068_FW_READY) {
225 + printk("mfi 1068 offset handshake=%x\n", pcidata);
227 + pci_write_config_dword(instance->pdev, MFI_1068_FW_HANDSHAKE_OFFSET, pcidata);
234 + * megasas_check_reset_xscale - For controller reset check
235 + * @regs: MFI register set
238 +megasas_check_reset_xscale(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
241 + consumer = *instance->consumer;
243 + if ((instance->adprecovery != MEGASAS_HBA_OPERATIONAL) && (*instance->consumer == MEGASAS_ADPRESET_INPROG_SIGN)) {
250 static struct megasas_instance_template megasas_instance_template_xscale = {
251 @@ -206,6 +323,8 @@ static struct megasas_instance_template
252 .disable_intr = megasas_disable_intr_xscale,
253 .clear_intr = megasas_clear_intr_xscale,
254 .read_fw_status_reg = megasas_read_fw_status_reg_xscale,
255 + .adp_reset = megasas_adp_reset_xscale,
256 + .check_reset = megasas_check_reset_xscale,
260 @@ -227,7 +346,7 @@ megasas_enable_intr_ppc(struct megasas_r
262 writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
264 - writel(~0x80000004, &(regs)->outbound_intr_mask);
265 + writel(~0x80000000, &(regs)->outbound_intr_mask);
267 /* Dummy readl to force pci flush */
268 readl(®s->outbound_intr_mask);
269 @@ -270,7 +389,7 @@ megasas_clear_intr_ppc(struct megasas_re
270 status = readl(®s->outbound_intr_status);
272 if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
278 @@ -278,7 +397,10 @@ megasas_clear_intr_ppc(struct megasas_re
280 writel(status, ®s->outbound_doorbell_clear);
283 + /* Dummy readl to force pci flush */
284 + readl(®s->outbound_doorbell_clear);
289 * megasas_fire_cmd_ppc - Sends command to the FW
290 @@ -287,10 +409,36 @@ megasas_clear_intr_ppc(struct megasas_re
291 * @regs : MFI register set
294 -megasas_fire_cmd_ppc(dma_addr_t frame_phys_addr, u32 frame_count, struct megasas_register_set __iomem *regs)
295 +megasas_fire_cmd_ppc(struct megasas_instance *instance,
296 + dma_addr_t frame_phys_addr,
298 + struct megasas_register_set __iomem *regs)
300 + unsigned long flags;
301 + spin_lock_irqsave(&instance->hba_lock, flags);
302 writel((frame_phys_addr | (frame_count<<1))|1,
303 &(regs)->inbound_queue_port);
304 + spin_unlock_irqrestore(&instance->hba_lock, flags);
308 + * megasas_adp_reset_ppc - For controller reset
309 + * @regs: MFI register set
312 +megasas_adp_reset_ppc(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
318 + * megasas_check_reset_ppc - For controller reset check
319 + * @regs: MFI register set
322 +megasas_check_reset_ppc(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
327 static struct megasas_instance_template megasas_instance_template_ppc = {
328 @@ -300,11 +448,321 @@ static struct megasas_instance_template
329 .disable_intr = megasas_disable_intr_ppc,
330 .clear_intr = megasas_clear_intr_ppc,
331 .read_fw_status_reg = megasas_read_fw_status_reg_ppc,
332 + .adp_reset = megasas_adp_reset_ppc,
333 + .check_reset = megasas_check_reset_ppc,
337 + * megasas_enable_intr_skinny - Enables interrupts
338 + * @regs: MFI register set
341 +megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs)
343 + writel(0xFFFFFFFF, &(regs)->outbound_intr_mask);
345 + /* write ~0x00000005 (4 & 1) to the intr mask*/
346 + writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
348 + /* Dummy readl to force pci flush */
349 + readl(®s->outbound_intr_mask);
353 + * megasas_disable_intr_skinny - Disables interrupt
354 + * @regs: MFI register set
357 +megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs)
359 + u32 mask = 0xFFFFFFFF;
360 + writel(mask, ®s->outbound_intr_mask);
361 + /* Dummy readl to force pci flush */
362 + readl(®s->outbound_intr_mask);
366 + * megasas_read_fw_status_reg_skinny - returns the current FW status value
367 + * @regs: MFI register set
370 +megasas_read_fw_status_reg_skinny(struct megasas_register_set __iomem *regs)
372 + return readl(&(regs)->outbound_scratch_pad);
376 + * megasas_clear_interrupt_skinny - Check & clear interrupt
377 + * @regs: MFI register set
380 +megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
386 + * Check if it is our interrupt
388 + status = readl(®s->outbound_intr_status);
390 + if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) {
396 + * Check if it is our interrupt
398 + if ((megasas_read_fw_status_reg_gen2( regs) & MFI_STATE_MASK ) == MFI_STATE_FAULT ){
399 + mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
401 + mfiStatus |= MFI_INTR_FLAG_REPLY_MESSAGE;
404 + * Clear the interrupt by writing back the same value
406 + writel(status, ®s->outbound_intr_status);
409 + * dummy read to flush PCI
411 + readl(®s->outbound_intr_status);
417 + * megasas_fire_cmd_skinny - Sends command to the FW
418 + * @frame_phys_addr : Physical address of cmd
419 + * @frame_count : Number of frames for the command
420 + * @regs : MFI register set
423 +megasas_fire_cmd_skinny(struct megasas_instance *instance,
424 + dma_addr_t frame_phys_addr,
426 + struct megasas_register_set __iomem *regs)
428 + unsigned long flags;
429 + spin_lock_irqsave(&instance->hba_lock, flags);
430 + writel(0, &(regs)->inbound_high_queue_port);
431 + writel((frame_phys_addr | (frame_count<<1))|1,
432 + &(regs)->inbound_low_queue_port);
433 + spin_unlock_irqrestore(&instance->hba_lock, flags);
438 + * megasas_check_reset_skinny - For controller reset check
439 + * @regs: MFI register set
442 +megasas_check_reset_skinny(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
447 +static struct megasas_instance_template megasas_instance_template_skinny = {
449 + .fire_cmd = megasas_fire_cmd_skinny,
450 + .enable_intr = megasas_enable_intr_skinny,
451 + .disable_intr = megasas_disable_intr_skinny,
452 + .clear_intr = megasas_clear_intr_skinny,
453 + .read_fw_status_reg = megasas_read_fw_status_reg_skinny,
454 + .adp_reset = megasas_adp_reset_gen2,
455 + .check_reset = megasas_check_reset_skinny,
460 +* The following functions are defined for gen2 (deviceid : 0x78 0x79)
465 + * megasas_enable_intr_gen2 - Enables interrupts
466 + * @regs: MFI register set
469 +megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs)
471 + writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
473 + /* write ~0x00000005 (4 & 1) to the intr mask*/
474 + writel(~MFI_GEN2_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
476 + /* Dummy readl to force pci flush */
477 + readl(®s->outbound_intr_mask);
481 + * megasas_disable_intr_gen2 - Disables interrupt
482 + * @regs: MFI register set
485 +megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs)
487 + u32 mask = 0xFFFFFFFF;
488 + writel(mask, ®s->outbound_intr_mask);
489 + /* Dummy readl to force pci flush */
490 + readl(®s->outbound_intr_mask);
494 + * megasas_read_fw_status_reg_gen2 - returns the current FW status value
495 + * @regs: MFI register set
498 +megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs)
500 + return readl(&(regs)->outbound_scratch_pad);
504 + * megasas_clear_interrupt_gen2 - Check & clear interrupt
505 + * @regs: MFI register set
508 +megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs)
513 + * Check if it is our interrupt
515 + status = readl(®s->outbound_intr_status);
517 + if (status & MFI_GEN2_ENABLE_INTERRUPT_MASK)
519 + mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
521 + if (status & MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT)
523 + mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
527 + * Clear the interrupt by writing back the same value
530 + writel(status, ®s->outbound_doorbell_clear);
532 + /* Dummy readl to force pci flush */
533 + readl(®s->outbound_intr_status);
539 + * megasas_fire_cmd_gen2 - Sends command to the FW
540 + * @frame_phys_addr : Physical address of cmd
541 + * @frame_count : Number of frames for the command
542 + * @regs : MFI register set
545 +megasas_fire_cmd_gen2(struct megasas_instance *instance,
546 + dma_addr_t frame_phys_addr,
548 + struct megasas_register_set __iomem *regs)
550 + unsigned long flags;
551 + spin_lock_irqsave(&instance->hba_lock, flags);
552 + writel((frame_phys_addr | (frame_count<<1))|1,
553 + &(regs)->inbound_queue_port);
554 + spin_unlock_irqrestore(&instance->hba_lock, flags);
558 + * megasas_adp_reset_gen2 - For controller reset
559 + * @regs: MFI register set
562 +megasas_adp_reset_gen2(struct megasas_instance *instance, struct megasas_register_set __iomem * reg_set)
564 + u32 retry = 0, delay = 0;
566 + u32 *seq_offset = ®_set->seq_offset;
567 + u32 *hostdiag_offset = ®_set->host_diag;
569 + if ( instance->instancet == &megasas_instance_template_skinny ){
570 + seq_offset = ®_set->fusion_seq_offset;
571 + hostdiag_offset = ®_set->fusion_host_diag;
574 + writel(0, seq_offset);
575 + writel(4, seq_offset);
576 + writel(0xb, seq_offset);
577 + writel(2, seq_offset);
578 + writel(7, seq_offset);
579 + writel(0xd, seq_offset);
583 + HostDiag = (u32)readl(hostdiag_offset);
585 + while ( !( HostDiag & DIAG_WRITE_ENABLE) )
588 + HostDiag = (u32)readl(hostdiag_offset);
589 + printk("ADP_RESET_GEN2: retry time=%x, hostdiag=%x\n", retry, HostDiag);
591 + if (retry++ >= 100)
596 + printk("ADP_RESET_GEN2: HostDiag=%x\n", HostDiag);
598 + writel((HostDiag | DIAG_RESET_ADAPTER), hostdiag_offset);
600 + for (delay=0; delay<10; delay++)
605 + HostDiag = (u32)readl(hostdiag_offset);
606 + while ( ( HostDiag & DIAG_RESET_ADAPTER) )
609 + HostDiag = (u32)readl(hostdiag_offset);
610 + printk("ADP_RESET_GEN2: retry time=%x, hostdiag=%x\n", retry, HostDiag);
612 + if (retry++ >= 1000)
620 + * megasas_check_reset_gen2 - For controller reset check
621 + * @regs: MFI register set
624 +megasas_check_reset_gen2(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
626 + if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
633 +static struct megasas_instance_template megasas_instance_template_gen2 = {
635 + .fire_cmd = megasas_fire_cmd_gen2,
636 + .enable_intr = megasas_enable_intr_gen2,
637 + .disable_intr = megasas_disable_intr_gen2,
638 + .clear_intr = megasas_clear_intr_gen2,
639 + .read_fw_status_reg = megasas_read_fw_status_reg_gen2,
640 + .adp_reset = megasas_adp_reset_gen2,
641 + .check_reset = megasas_check_reset_gen2,
645 * This is the end of set of functions & definitions
646 -* specific to ppc (deviceid : 0x60) controllers
647 + * specific to gen2 (deviceid : 0x78, 0x79) controllers
651 @@ -328,13 +786,17 @@ megasas_issue_polled(struct megasas_inst
653 * Issue the frame using inbound queue port
655 - instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set);
656 + instance->instancet->fire_cmd(instance,
657 + cmd->frame_phys_addr, 0, instance->reg_set);
660 * Wait for cmd_status to change
662 for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i++) {
664 + //FW using xor/copy as soon as we enable cpx
665 + if ( instance->cpx_supported )
666 + megasas_handle_cpx_requests( instance);
670 @@ -359,10 +821,10 @@ megasas_issue_blocked_cmd(struct megasas
672 cmd->cmd_status = ENODATA;
674 - instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set);
675 + instance->instancet->fire_cmd(instance,
676 + cmd->frame_phys_addr, 0, instance->reg_set);
678 - wait_event_timeout(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA),
679 - MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ);
680 + wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA);
684 @@ -404,13 +866,15 @@ megasas_issue_blocked_abort_cmd(struct m
686 cmd->cmd_status = 0xFF;
688 - instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set);
689 + instance->instancet->fire_cmd(instance,
690 + cmd->frame_phys_addr, 0, instance->reg_set);
693 * Wait for this cmd to complete
695 - wait_event_timeout(instance->abort_cmd_wait_q, (cmd->cmd_status != 0xFF),
696 - MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ);
697 + wait_event(instance->abort_cmd_wait_q, cmd->cmd_status != 0xFF);
701 megasas_return_cmd(instance, cmd);
703 @@ -513,14 +977,66 @@ megasas_make_sgl64(struct megasas_instan
708 - * megasas_get_frame_count - Computes the number of frames
709 - * @sge_count : number of sg elements
711 + * megasas_make_sgl_skinny - Prepares IEEE SGL
712 + * @instance: Adapter soft state
713 + * @scp: SCSI command from the mid-layer
714 + * @mfi_sgl: SGL to be filled in
716 + * If successful, this function returns the number of SG elements. Otherwise,
720 +megasas_make_sgl_skinny(struct megasas_instance *instance,
721 + struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl)
725 + struct scatterlist *os_sgl;
728 + * Return 0 if there is no data transfer
730 + if (!scp->request_buffer || !scp->request_bufflen)
733 + if (!scp->use_sg) {
734 + mfi_sgl->sge_skinny[0].phys_addr = pci_map_single(instance->pdev,
740 + sc_data_direction);
742 + mfi_sgl->sge_skinny[0].length = scp->request_bufflen;
747 + os_sgl = (struct scatterlist *)scp->request_buffer;
748 + sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg,
749 + scp->sc_data_direction);
751 + for (i = 0; i < sge_count; i++, os_sgl++) {
752 + mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl);
753 + mfi_sgl->sge_skinny[i].phys_addr = sg_dma_address(os_sgl);
754 + mfi_sgl->sge_skinny[i].flag = 0;
761 + * megasas_get_frame_count - Computes the number of frames
762 + * @frame_type : type of frame- io or pthru frame
763 + * @sge_count : number of sg elements
765 * Returns the number of frames required for numnber of sge's (sge_count)
768 -static u32 megasas_get_frame_count(u8 sge_count)
769 +static u32 megasas_get_frame_count(struct megasas_instance *instance,
770 + u8 sge_count, u8 frame_type)
774 @@ -530,14 +1046,31 @@ static u32 megasas_get_frame_count(u8 sg
775 sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
776 sizeof(struct megasas_sge32);
778 + if (instance->flag_ieee) {
779 + sge_sz = sizeof(struct megasas_sge_skinny);
783 - * Main frame can contain 2 SGEs for 64-bit SGLs and
784 - * 3 SGEs for 32-bit SGLs
787 - num_cnt = sge_count - 2;
789 - num_cnt = sge_count - 3;
790 + * Main frame can contain 2 SGEs for 64-bit SGLs and
791 + * 3 SGEs for 32-bit SGLs for ldio &
792 + * 1 SGEs for 64-bit SGLs and
793 + * 2 SGEs for 32-bit SGLs for pthru frame
795 + if (unlikely(frame_type == PTHRU_FRAME)) {
796 + if (instance->flag_ieee == 1) {
797 + num_cnt = sge_count - 1;
798 + } else if (IS_DMA64)
799 + num_cnt = sge_count - 1;
801 + num_cnt = sge_count - 2;
803 + if (instance->flag_ieee == 1) {
804 + num_cnt = sge_count - 1;
805 + } else if (IS_DMA64)
806 + num_cnt = sge_count - 2;
808 + num_cnt = sge_count - 3;
812 sge_bytes = sge_sz * num_cnt;
813 @@ -582,6 +1115,10 @@ megasas_build_dcdb(struct megasas_instan
814 else if (scp->sc_data_direction == PCI_DMA_NONE)
815 flags = MFI_FRAME_DIR_NONE;
817 + if (instance->flag_ieee == 1) {
818 + flags |= MFI_FRAME_IEEE;
822 * Prepare the DCDB frame
824 @@ -592,15 +1129,31 @@ megasas_build_dcdb(struct megasas_instan
825 pthru->lun = scp->device->lun;
826 pthru->cdb_len = scp->cmd_len;
829 pthru->flags = flags;
830 pthru->data_xfer_len = scp->request_bufflen;
832 memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
835 + * If the command is for the tape device, set the
836 + * pthru timeout to the os layer timeout value.
838 + if (scp->device->type == TYPE_TAPE) {
839 + if ((scp->request->timeout / HZ) > 0xFFFF)
840 + pthru->timeout = 0xFFFF;
842 + pthru->timeout = scp->request->timeout / HZ;
849 + if (instance->flag_ieee == 1) {
850 + pthru->flags |= MFI_FRAME_SGL64;
851 + pthru->sge_count = megasas_make_sgl_skinny(instance, scp,
853 + } else if (IS_DMA64) {
854 pthru->flags |= MFI_FRAME_SGL64;
855 pthru->sge_count = megasas_make_sgl64(instance, scp,
857 @@ -608,6 +1161,10 @@ megasas_build_dcdb(struct megasas_instan
858 pthru->sge_count = megasas_make_sgl32(instance, scp,
861 + if (pthru->sge_count > instance->max_num_sge) {
862 + printk("megasas: build_dcdb error, two many SGE\n");
866 * Sense info specific
868 @@ -619,7 +1176,8 @@ megasas_build_dcdb(struct megasas_instan
869 * Compute the total number of frames this command consumes. FW uses
870 * this number to pull sufficient number of frames from host memory.
872 - cmd->frame_count = megasas_get_frame_count(pthru->sge_count);
873 + cmd->frame_count = megasas_get_frame_count(instance, pthru->sge_count,
876 return cmd->frame_count;
878 @@ -628,7 +1186,7 @@ megasas_build_dcdb(struct megasas_instan
879 * megasas_build_ldio - Prepares IOs to logical devices
880 * @instance: Adapter soft state
882 - * @cmd: Command to to be prepared
883 + * @cmd: Command to be prepared
885 * Frames (and accompanying SGLs) for regular SCSI IOs use this function.
887 @@ -649,6 +1207,10 @@ megasas_build_ldio(struct megasas_instan
888 else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
889 flags = MFI_FRAME_DIR_READ;
891 + if (instance->flag_ieee == 1) {
892 + flags |= MFI_FRAME_IEEE;
896 * Prepare the Logical IO frame: 2nd bit is zero for all read cmds
898 @@ -719,12 +1281,20 @@ megasas_build_ldio(struct megasas_instan
903 + if (instance->flag_ieee) {
904 + ldio->flags |= MFI_FRAME_SGL64;
905 + ldio->sge_count = megasas_make_sgl_skinny(instance, scp,
907 + } else if (IS_DMA64) {
908 ldio->flags |= MFI_FRAME_SGL64;
909 ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl);
911 ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl);
913 + if (ldio->sge_count > instance->max_num_sge) {
914 + printk("megasas: build_ld_io error, sge_count = %x\n", ldio->sge_count);
918 * Sense info specific
920 @@ -736,7 +1306,8 @@ megasas_build_ldio(struct megasas_instan
921 * Compute the total number of frames this command consumes. FW uses
922 * this number to pull sufficient number of frames from host memory.
924 - cmd->frame_count = megasas_get_frame_count(ldio->sge_count);
925 + cmd->frame_count = megasas_get_frame_count(instance,
926 + ldio->sge_count, IO_FRAME);
928 return cmd->frame_count;
930 @@ -841,14 +1412,25 @@ megasas_queue_command(struct scsi_cmnd *
932 struct megasas_cmd *cmd;
933 struct megasas_instance *instance;
934 + unsigned long flags;
936 instance = (struct megasas_instance *)
937 scmd->device->host->hostdata;
939 - /* Don't process if we have already declared adapter dead */
940 - if (instance->hw_crit_error)
941 + if (instance->issuepend_done == 0)
942 return SCSI_MLQUEUE_HOST_BUSY;
944 + spin_lock_irqsave(&instance->hba_lock, flags);
945 + //Don't process if we have already declared adapter dead
946 + // If we are in middle of bringing up the HBA, send the busy status to mid-layer
947 + // till the process is complete
948 + if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
949 + spin_unlock_irqrestore(&instance->hba_lock, flags);
950 + return SCSI_MLQUEUE_HOST_BUSY;
953 + spin_unlock_irqrestore(&instance->hba_lock, flags);
955 scmd->scsi_done = done;
958 @@ -893,7 +1475,14 @@ megasas_queue_command(struct scsi_cmnd *
960 atomic_inc(&instance->fw_outstanding);
962 - instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set);
963 + instance->instancet->fire_cmd(instance, cmd->frame_phys_addr,
964 + cmd->frame_count-1, instance->reg_set);
966 + * Check if we have pend cmds to be completed
968 + if (poll_mode_io && atomic_read(&instance->fw_outstanding))
969 + tasklet_schedule(&instance->isr_tasklet);
974 @@ -904,211 +1493,1527 @@ megasas_queue_command(struct scsi_cmnd *
978 +static struct megasas_instance *megasas_lookup_instance(u16 host_no)
982 + for (i = 0; i < megasas_mgmt_info.max_index; i++) {
984 + if ((megasas_mgmt_info.instance[i]) &&
985 + (megasas_mgmt_info.instance[i]->host->host_no == host_no))
986 + return megasas_mgmt_info.instance[i];
992 static int megasas_slave_configure(struct scsi_device *sdev)
995 + struct megasas_instance *instance ;
997 + instance = megasas_lookup_instance(sdev->host->host_no);
1000 - * Don't export physical disk devices to the disk driver.
1002 - * FIXME: Currently we don't export them to the midlayer at all.
1003 - * That will be fixed once LSI engineers have audited the
1004 - * firmware for possible issues.
1006 - if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK)
1007 + * Don't export physical disk devices to the disk driver.
1009 + * FIXME: Currently we don't export them to the midlayer at all.
1010 + * That will be fixed once LSI engineers have audited the
1011 + * firmware for possible issues.
1013 + if (sdev->channel < MEGASAS_MAX_PD_CHANNELS) {
1014 + if (sdev->type == TYPE_TAPE) {
1015 + sdev->timeout = MEGASAS_DEFAULT_CMD_TIMEOUT * HZ;
1017 + } else if (sdev->type == TYPE_DISK) {
1019 + pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id;
1021 + if ((instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) &&
1022 + (instance->pd_list[pd_index].driveType == TYPE_DISK)) {
1023 + sdev->timeout = MEGASAS_DEFAULT_CMD_TIMEOUT * HZ;
1031 - * The RAID firmware may require extended timeouts.
1033 - if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS)
1034 - sdev->timeout = MEGASAS_DEFAULT_CMD_TIMEOUT * HZ;
1035 + * The RAID firmware may require extended timeouts.
1037 + sdev->timeout = MEGASAS_DEFAULT_CMD_TIMEOUT * HZ;
1042 - * megasas_wait_for_outstanding - Wait for all outstanding cmds
1043 - * @instance: Adapter soft state
1045 - * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to
1046 - * complete all its outstanding commands. Returns error if one or more IOs
1047 - * are pending after this time period. It also marks the controller dead.
1049 -static int megasas_wait_for_outstanding(struct megasas_instance *instance)
1050 +static void megaraid_sas_kill_hba(struct megasas_instance *instance)
1053 - u32 wait_time = MEGASAS_RESET_WAIT_TIME;
1054 + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
1055 + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY))
1057 + writel(MFI_STOP_ADP,
1058 + &instance->reg_set->reserved_0);
1060 + writel(MFI_STOP_ADP,
1061 + &instance->reg_set->inbound_doorbell);
1065 - for (i = 0; i < wait_time; i++) {
1067 - int outstanding = atomic_read(&instance->fw_outstanding);
1072 - if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
1073 - printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
1074 - "commands to complete\n",i,outstanding);
1076 +void xor_gen_15x1(u32 *buff_ptrs[16], u32 bytes)
1079 + u32 *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12, *s13, *s14, *s15;
1084 + s1 = buff_ptrs[1];
1085 + s2 = buff_ptrs[2];
1086 + s3 = buff_ptrs[3];
1087 + s4 = buff_ptrs[4];
1088 + s5 = buff_ptrs[5];
1089 + s6 = buff_ptrs[6];
1090 + s7 = buff_ptrs[7];
1091 + s8 = buff_ptrs[8];
1092 + s9 = buff_ptrs[9];
1093 + s10 = buff_ptrs[10];
1094 + s11 = buff_ptrs[11];
1095 + s12 = buff_ptrs[12];
1096 + s13 = buff_ptrs[13];
1097 + s14 = buff_ptrs[14];
1098 + s15 = buff_ptrs[15];
1100 - if (atomic_read(&instance->fw_outstanding)) {
1102 - * Send signal to FW to stop processing any pending cmds.
1103 - * The controller will be taken offline by the OS now.
1105 - writel(MFI_STOP_ADP,
1106 - &instance->reg_set->inbound_doorbell);
1107 - megasas_dump_pending_frames(instance);
1108 - instance->hw_crit_error = 1;
1111 + for (words = bytes/4, off=0; words>0; words--, off++)
1112 + d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1113 + s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off] ^ s13[off] ^ s14[off] ^ s15[off];
1119 - * megasas_generic_reset - Generic reset routine
1120 - * @scmd: Mid-layer SCSI command
1122 - * This routine implements a generic reset handler for device, bus and host
1123 - * reset requests. Device, bus and host specific reset handlers can use this
1124 - * function after they do their specific tasks.
1126 -static int megasas_generic_reset(struct scsi_cmnd *scmd)
1128 +void xor_gen_14x1(u32 *buff_ptrs[15], u32 bytes)
1131 - struct megasas_instance *instance;
1133 + u32 *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12, *s13, *s14;
1135 - instance = (struct megasas_instance *)scmd->device->host->hostdata;
1137 + s1 = buff_ptrs[1];
1138 + s2 = buff_ptrs[2];
1139 + s3 = buff_ptrs[3];
1140 + s4 = buff_ptrs[4];
1141 + s5 = buff_ptrs[5];
1142 + s6 = buff_ptrs[6];
1143 + s7 = buff_ptrs[7];
1144 + s8 = buff_ptrs[8];
1145 + s9 = buff_ptrs[9];
1146 + s10 = buff_ptrs[10];
1147 + s11 = buff_ptrs[11];
1148 + s12 = buff_ptrs[12];
1149 + s13 = buff_ptrs[13];
1150 + s14 = buff_ptrs[14];
1152 - scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
1153 - scmd->serial_number, scmd->cmnd[0], scmd->retries);
1154 + for (words = bytes/4, off=0; words>0; words--, off++)
1155 + d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1156 + s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off] ^ s13[off] ^ s14[off];
1158 - if (instance->hw_crit_error) {
1159 - printk(KERN_ERR "megasas: cannot recover from previous reset "
1165 - ret_val = megasas_wait_for_outstanding(instance);
1166 - if (ret_val == SUCCESS)
1167 - printk(KERN_NOTICE "megasas: reset successful \n");
1169 - printk(KERN_ERR "megasas: failed to do reset\n");
1172 +void xor_gen_13x1(u32 *buff_ptrs[14], u32 bytes)
1175 + u32 *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12, *s13;
1178 + s1 = buff_ptrs[1];
1179 + s2 = buff_ptrs[2];
1180 + s3 = buff_ptrs[3];
1181 + s4 = buff_ptrs[4];
1182 + s5 = buff_ptrs[5];
1183 + s6 = buff_ptrs[6];
1184 + s7 = buff_ptrs[7];
1185 + s8 = buff_ptrs[8];
1186 + s9 = buff_ptrs[9];
1187 + s10 = buff_ptrs[10];
1188 + s11 = buff_ptrs[11];
1189 + s12 = buff_ptrs[12];
1190 + s13 = buff_ptrs[13];
1192 + for (words = bytes/4, off=0; words>0; words--, off++)
1193 + d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1194 + s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off] ^ s13[off];
1199 - * megasas_reset_timer - quiesce the adapter if required
1200 - * @scmd: scsi cmnd
1202 - * Sets the FW busy flag and reduces the host->can_queue if the
1203 - * cmd has not been completed within the timeout period.
1206 -scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
1208 - struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
1209 - struct megasas_instance *instance;
1210 - unsigned long flags;
1212 - if (time_after(jiffies, scmd->jiffies_at_alloc +
1213 - (MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) {
1214 - return EH_NOT_HANDLED;
1216 +void xor_gen_12x1(u32 *buff_ptrs[13], u32 bytes)
1219 + u32 *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12;
1221 - instance = cmd->instance;
1222 - if (!(instance->flag & MEGASAS_FW_BUSY)) {
1223 - /* FW is busy, throttle IO */
1224 - spin_lock_irqsave(instance->host->host_lock, flags);
1226 + s1 = buff_ptrs[1];
1227 + s2 = buff_ptrs[2];
1228 + s3 = buff_ptrs[3];
1229 + s4 = buff_ptrs[4];
1230 + s5 = buff_ptrs[5];
1231 + s6 = buff_ptrs[6];
1232 + s7 = buff_ptrs[7];
1233 + s8 = buff_ptrs[8];
1234 + s9 = buff_ptrs[9];
1235 + s10 = buff_ptrs[10];
1236 + s11 = buff_ptrs[11];
1237 + s12 = buff_ptrs[12];
1239 - instance->host->can_queue = 16;
1240 - instance->last_time = jiffies;
1241 - instance->flag |= MEGASAS_FW_BUSY;
1242 + for (words = bytes/4, off=0; words>0; words--, off++)
1243 + d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1244 + s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off];
1246 - spin_unlock_irqrestore(instance->host->host_lock, flags);
1248 - return EH_RESET_TIMER;
1252 - * megasas_reset_device - Device reset handler entry point
1254 -static int megasas_reset_device(struct scsi_cmnd *scmd)
1256 +void xor_gen_11x1(u32 *buff_ptrs[12], u32 bytes)
1260 + u32 *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11;
1263 - * First wait for all commands to complete
1265 - ret = megasas_generic_reset(scmd);
1267 + s1 = buff_ptrs[1];
1268 + s2 = buff_ptrs[2];
1269 + s3 = buff_ptrs[3];
1270 + s4 = buff_ptrs[4];
1271 + s5 = buff_ptrs[5];
1272 + s6 = buff_ptrs[6];
1273 + s7 = buff_ptrs[7];
1274 + s8 = buff_ptrs[8];
1275 + s9 = buff_ptrs[9];
1276 + s10 = buff_ptrs[10];
1277 + s11 = buff_ptrs[11];
1279 + for (words = bytes/4, off=0; words>0; words--, off++)
1280 + d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1281 + s8[off] ^ s9[off] ^ s10[off] ^ s11[off];
1287 - * megasas_reset_bus_host - Bus & host reset handler entry point
1289 -static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
1291 +void xor_gen_10x1(u32 *buff_ptrs[11], u32 bytes)
1295 + u32 *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10;
1298 - * First wait for all commands to complete
1300 - ret = megasas_generic_reset(scmd);
1302 + s1 = buff_ptrs[1];
1303 + s2 = buff_ptrs[2];
1304 + s3 = buff_ptrs[3];
1305 + s4 = buff_ptrs[4];
1306 + s5 = buff_ptrs[5];
1307 + s6 = buff_ptrs[6];
1308 + s7 = buff_ptrs[7];
1309 + s8 = buff_ptrs[8];
1310 + s9 = buff_ptrs[9];
1311 + s10 = buff_ptrs[10];
1313 + for (words = bytes/4, off=0; words>0; words--, off++)
1314 + d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1315 + s8[off] ^ s9[off] ^ s10[off];
1321 - * megasas_bios_param - Returns disk geometry for a disk
1322 - * @sdev: device handle
1323 - * @bdev: block device
1324 - * @capacity: drive capacity
1325 - * @geom: geometry parameters
1328 -megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
1329 - sector_t capacity, int geom[])
1331 +void xor_gen_9x1(u32 *buff_ptrs[10], u32 bytes)
1335 - sector_t cylinders;
1336 - unsigned long tmp;
1337 - /* Default heads (64) & sectors (32) */
1341 + u32 *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
1343 - tmp = heads * sectors;
1344 - cylinders = capacity;
1346 + s1 = buff_ptrs[1];
1347 + s2 = buff_ptrs[2];
1348 + s3 = buff_ptrs[3];
1349 + s4 = buff_ptrs[4];
1350 + s5 = buff_ptrs[5];
1351 + s6 = buff_ptrs[6];
1352 + s7 = buff_ptrs[7];
1353 + s8 = buff_ptrs[8];
1354 + s9 = buff_ptrs[9];
1356 - sector_div(cylinders, tmp);
1357 + for (words = bytes/4, off=0; words>0; words--, off++)
1358 + d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1359 + s8[off] ^ s9[off];
1362 - * Handle extended translation size for logical drives > 1Gb
1366 - if (capacity >= 0x200000) {
1369 - tmp = heads*sectors;
1370 - cylinders = capacity;
1371 - sector_div(cylinders, tmp);
1375 - geom[1] = sectors;
1376 - geom[2] = cylinders;
1377 +void xor_gen_8x1(u32 *buff_ptrs[9], u32 bytes)
1380 + u32 *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8;
1383 + s1 = buff_ptrs[1];
1384 + s2 = buff_ptrs[2];
1385 + s3 = buff_ptrs[3];
1386 + s4 = buff_ptrs[4];
1387 + s5 = buff_ptrs[5];
1388 + s6 = buff_ptrs[6];
1389 + s7 = buff_ptrs[7];
1390 + s8 = buff_ptrs[8];
1392 + for (words = bytes/4, off=0; words>0; words--, off++)
1393 + d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^ s8[off];
1399 - * megasas_service_aen - Processes an event notification
1400 - * @instance: Adapter soft state
1402 +void xor_gen_7x1(u32 *buff_ptrs[8], u32 bytes)
1405 + u32 *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7;
1408 + s1 = buff_ptrs[1];
1409 + s2 = buff_ptrs[2];
1410 + s3 = buff_ptrs[3];
1411 + s4 = buff_ptrs[4];
1412 + s5 = buff_ptrs[5];
1413 + s6 = buff_ptrs[6];
1414 + s7 = buff_ptrs[7];
1416 + for (words = bytes/4, off=0; words>0; words--, off++)
1417 + d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off];
1422 +void xor_gen_6x1(u32 *buff_ptrs[7], u32 bytes)
1425 + u32 *d, *s1, *s2, *s3, *s4, *s5, *s6;
1428 + s1 = buff_ptrs[1];
1429 + s2 = buff_ptrs[2];
1430 + s3 = buff_ptrs[3];
1431 + s4 = buff_ptrs[4];
1432 + s5 = buff_ptrs[5];
1433 + s6 = buff_ptrs[6];
1435 + for (words = bytes/4, off=0; words>0; words--, off++)
1436 + d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off];
1441 +void xor_gen_5x1(u32 *buff_ptrs[6], u32 bytes)
1444 + u32 *d, *s1, *s2, *s3, *s4, *s5;
1447 + s1 = buff_ptrs[1];
1448 + s2 = buff_ptrs[2];
1449 + s3 = buff_ptrs[3];
1450 + s4 = buff_ptrs[4];
1451 + s5 = buff_ptrs[5];
1453 + for (words = bytes/4, off=0; words>0; words--, off++)
1454 + d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off];
1459 +void xor_gen_4x1(u32 *buff_ptrs[5], u32 bytes)
1462 + u32 *d, *s1, *s2, *s3, *s4;
1465 + s1 = buff_ptrs[1];
1466 + s2 = buff_ptrs[2];
1467 + s3 = buff_ptrs[3];
1468 + s4 = buff_ptrs[4];
1470 + for (words = bytes/4, off=0; words>0; words--, off++)
1471 + d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off];
1476 +void xor_gen_3x1(u32 *buff_ptrs[4], u32 bytes)
1479 + u32 *d, *s1, *s2, *s3;
1482 + s1 = buff_ptrs[1];
1483 + s2 = buff_ptrs[2];
1484 + s3 = buff_ptrs[3];
1486 + for (words = bytes/4, off=0; words>0; words--, off++)
1487 + d[off] = s1[off] ^ s2[off] ^ s3[off];
1492 +void xor_gen_2x1(u32 *buff_ptrs[3], u32 bytes)
1498 + s1 = buff_ptrs[1];
1499 + s2 = buff_ptrs[2];
1501 + for (words = bytes/4, off=0; words>0; words--, off++)
1502 + d[off] = s1[off] ^ s2[off];
1507 +void xor_gen_1x1(u32 *buff_ptrs[2], u32 bytes)
1513 + s1 = buff_ptrs[1];
1515 + for (words = bytes/4, off=0; words>0; words--, off++)
1521 +u8 xor_chk_15x1(u32 *buff_ptrs[16], u32 bytes)
1524 + u32 r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12, *s13, *s14, *s15;
1525 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1528 + s1 = buff_ptrs[1];
1529 + s2 = buff_ptrs[2];
1530 + s3 = buff_ptrs[3];
1531 + s4 = buff_ptrs[4];
1532 + s5 = buff_ptrs[5];
1533 + s6 = buff_ptrs[6];
1534 + s7 = buff_ptrs[7];
1535 + s8 = buff_ptrs[8];
1536 + s9 = buff_ptrs[9];
1537 + s10 = buff_ptrs[10];
1538 + s11 = buff_ptrs[11];
1539 + s12 = buff_ptrs[12];
1540 + s13 = buff_ptrs[13];
1541 + s14 = buff_ptrs[14];
1542 + s15 = buff_ptrs[15];
1545 + for (words = bytes/4, off=0; words>0; words--, off++) {
1546 + r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1547 + s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off] ^ s13[off] ^ s14[off] ^ s15[off];
1549 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1553 + return xor_result;
1557 +u8 xor_chk_14x1(u32 *buff_ptrs[15], u32 bytes)
1560 + u32 r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12, *s13, *s14;
1561 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1564 + s1 = buff_ptrs[1];
1565 + s2 = buff_ptrs[2];
1566 + s3 = buff_ptrs[3];
1567 + s4 = buff_ptrs[4];
1568 + s5 = buff_ptrs[5];
1569 + s6 = buff_ptrs[6];
1570 + s7 = buff_ptrs[7];
1571 + s8 = buff_ptrs[8];
1572 + s9 = buff_ptrs[9];
1573 + s10 = buff_ptrs[10];
1574 + s11 = buff_ptrs[11];
1575 + s12 = buff_ptrs[12];
1576 + s13 = buff_ptrs[13];
1577 + s14 = buff_ptrs[14];
1579 + for (words = bytes/4, off=0; words>0; words--, off++) {
1580 + r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1581 + s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off] ^ s13[off] ^ s14[off];
1583 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1587 + return xor_result;
1592 +u8 xor_chk_13x1(u32 *buff_ptrs[14], u32 bytes)
1595 + u32 r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12, *s13;
1596 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1599 + s1 = buff_ptrs[1];
1600 + s2 = buff_ptrs[2];
1601 + s3 = buff_ptrs[3];
1602 + s4 = buff_ptrs[4];
1603 + s5 = buff_ptrs[5];
1604 + s6 = buff_ptrs[6];
1605 + s7 = buff_ptrs[7];
1606 + s8 = buff_ptrs[8];
1607 + s9 = buff_ptrs[9];
1608 + s10 = buff_ptrs[10];
1609 + s11 = buff_ptrs[11];
1610 + s12 = buff_ptrs[12];
1611 + s13 = buff_ptrs[13];
1613 + for (words = bytes/4, off=0; words>0; words--, off++) {
1614 + r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1615 + s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off] ^ s13[off];
1617 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1621 + return xor_result;
1626 +u8 xor_chk_12x1(u32 *buff_ptrs[13], u32 bytes)
1629 + u32 r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12;
1630 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1633 + s1 = buff_ptrs[1];
1634 + s2 = buff_ptrs[2];
1635 + s3 = buff_ptrs[3];
1636 + s4 = buff_ptrs[4];
1637 + s5 = buff_ptrs[5];
1638 + s6 = buff_ptrs[6];
1639 + s7 = buff_ptrs[7];
1640 + s8 = buff_ptrs[8];
1641 + s9 = buff_ptrs[9];
1642 + s10 = buff_ptrs[10];
1643 + s11 = buff_ptrs[11];
1644 + s12 = buff_ptrs[12];
1646 + for (words = bytes/4, off=0; words>0; words--, off++) {
1647 + r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1648 + s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off];
1650 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1654 + return xor_result;
1659 +u8 xor_chk_11x1(u32 *buff_ptrs[12], u32 bytes)
1662 + u32 r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11;
1663 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1666 + s1 = buff_ptrs[1];
1667 + s2 = buff_ptrs[2];
1668 + s3 = buff_ptrs[3];
1669 + s4 = buff_ptrs[4];
1670 + s5 = buff_ptrs[5];
1671 + s6 = buff_ptrs[6];
1672 + s7 = buff_ptrs[7];
1673 + s8 = buff_ptrs[8];
1674 + s9 = buff_ptrs[9];
1675 + s10 = buff_ptrs[10];
1676 + s11 = buff_ptrs[11];
1678 + for (words = bytes/4, off=0; words>0; words--, off++) {
1679 + r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1680 + s8[off] ^ s9[off] ^ s10[off] ^ s11[off];
1682 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1686 + return xor_result;
1691 +u8 xor_chk_10x1(u32 *buff_ptrs[11], u32 bytes)
1694 + u32 r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10;
1695 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1698 + s1 = buff_ptrs[1];
1699 + s2 = buff_ptrs[2];
1700 + s3 = buff_ptrs[3];
1701 + s4 = buff_ptrs[4];
1702 + s5 = buff_ptrs[5];
1703 + s6 = buff_ptrs[6];
1704 + s7 = buff_ptrs[7];
1705 + s8 = buff_ptrs[8];
1706 + s9 = buff_ptrs[9];
1707 + s10 = buff_ptrs[10];
1709 + for (words = bytes/4, off=0; words>0; words--, off++) {
1710 + r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1711 + s8[off] ^ s9[off] ^ s10[off];
1713 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1717 + return xor_result;
1721 +u8 xor_chk_9x1(u32 *buff_ptrs[10], u32 bytes)
1724 + u32 r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
1725 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1728 + s1 = buff_ptrs[1];
1729 + s2 = buff_ptrs[2];
1730 + s3 = buff_ptrs[3];
1731 + s4 = buff_ptrs[4];
1732 + s5 = buff_ptrs[5];
1733 + s6 = buff_ptrs[6];
1734 + s7 = buff_ptrs[7];
1735 + s8 = buff_ptrs[8];
1736 + s9 = buff_ptrs[9];
1738 + for (words = bytes/4, off=0; words>0; words--, off++) {
1739 + r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1740 + s8[off] ^ s9[off];
1742 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1746 + return xor_result;
1750 +u8 xor_chk_8x1(u32 *buff_ptrs[9], u32 bytes)
1753 + u32 r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8;
1754 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1757 + s1 = buff_ptrs[1];
1758 + s2 = buff_ptrs[2];
1759 + s3 = buff_ptrs[3];
1760 + s4 = buff_ptrs[4];
1761 + s5 = buff_ptrs[5];
1762 + s6 = buff_ptrs[6];
1763 + s7 = buff_ptrs[7];
1764 + s8 = buff_ptrs[8];
1766 + for (words = bytes/4, off=0; words>0; words--, off++) {
1767 + r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^ s8[off];
1769 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1773 + return xor_result;
1777 +u8 xor_chk_7x1(u32 *buff_ptrs[8], u32 bytes)
1780 + u32 r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7;
1781 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1784 + s1 = buff_ptrs[1];
1785 + s2 = buff_ptrs[2];
1786 + s3 = buff_ptrs[3];
1787 + s4 = buff_ptrs[4];
1788 + s5 = buff_ptrs[5];
1789 + s6 = buff_ptrs[6];
1790 + s7 = buff_ptrs[7];
1792 + for (words = bytes/4, off=0; words>0; words--, off++) {
1793 + r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off];
1795 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1799 + return xor_result;
1804 +u8 xor_chk_6x1(u32 *buff_ptrs[7], u32 bytes)
1807 + u32 r, *d, *s1, *s2, *s3, *s4, *s5, *s6;
1808 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1811 + s1 = buff_ptrs[1];
1812 + s2 = buff_ptrs[2];
1813 + s3 = buff_ptrs[3];
1814 + s4 = buff_ptrs[4];
1815 + s5 = buff_ptrs[5];
1816 + s6 = buff_ptrs[6];
1818 + for (words = bytes/4, off=0; words>0; words--, off++) {
1819 + r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off];
1821 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1825 + return xor_result;
1829 +u8 xor_chk_5x1(u32 *buff_ptrs[6], u32 bytes)
1832 + u32 r, *d, *s1, *s2, *s3, *s4, *s5;
1833 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1836 + s1 = buff_ptrs[1];
1837 + s2 = buff_ptrs[2];
1838 + s3 = buff_ptrs[3];
1839 + s4 = buff_ptrs[4];
1840 + s5 = buff_ptrs[5];
1842 + for (words = bytes/4, off=0; words>0; words--, off++) {
1843 + r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off];
1845 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1849 + return xor_result;
1853 +u8 xor_chk_4x1(u32 *buff_ptrs[5], u32 bytes)
1856 + u32 r, *d, *s1, *s2, *s3, *s4;
1857 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1860 + s1 = buff_ptrs[1];
1861 + s2 = buff_ptrs[2];
1862 + s3 = buff_ptrs[3];
1863 + s4 = buff_ptrs[4];
1865 + for (words = bytes/4, off=0; words>0; words--, off++) {
1866 + r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off];
1868 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1872 + return xor_result;
1876 +u8 xor_chk_3x1(u32 *buff_ptrs[4], u32 bytes)
1879 + u32 r, *d, *s1, *s2, *s3;
1880 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1883 + s1 = buff_ptrs[1];
1884 + s2 = buff_ptrs[2];
1885 + s3 = buff_ptrs[3];
1887 + for (words = bytes/4, off=0; words>0; words--, off++) {
1888 + r = d[off] ^ s1[off] ^ s2[off] ^ s3[off];
1890 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1894 + return xor_result;
1898 +u8 xor_chk_2x1(u32 *buff_ptrs[3], u32 bytes)
1901 + u32 r, *d, *s1, *s2;
1902 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1905 + s1 = buff_ptrs[1];
1906 + s2 = buff_ptrs[2];
1908 + for (words = bytes/4, off=0; words>0; words--, off++) {
1909 + r = d[off] ^ s1[off] ^ s2[off];
1911 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1915 + return xor_result;
1919 +u8 xor_chk_1x1(u32 *buff_ptrs[2], u32 bytes)
1923 + u8 xor_result = MR_CPX_STATUS_SUCCESS;
1926 + s1 = buff_ptrs[1];
1928 + for (words = bytes/4, off=0; words>0; words--, off++) {
1929 + if (d[off] != s1[off]) {
1930 + xor_result = MR_CPX_STATUS_INCONSISTENT;
1934 + return xor_result;
1938 +XOR_LOW_LEVEL_GEN_FUNC xor_gen_funcs[MAX_MR_ROW_SIZE] = {
1956 +XOR_LOW_LEVEL_CHECK_FUNC xor_check_funcs[MAX_MR_ROW_SIZE] = {
1974 +inline static u8 megasas_scan_set_bit(u32 bitmap)
1990 + * megasas_do_cpx_xor - completes the xor operation
1991 + * @xor_des : soruce and dest buffers details.
1992 + * @host_mem : previously mapped memory for fw
1993 + * @host_mem_len : mapped memory length in bytes.
1995 + * @return 0 on success != 0 on failure
1998 +static u8 megasas_do_cpx_xor( struct mr_cpx_xor_descriptor *xor_des, const u8 *host_mem, const u32 host_mem_len)
2001 + u32 buff_valid_bit_map = xor_des->buff_valid_bitmap;
2002 + u32 *buf_ptr_list[MAX_MR_ROW_SIZE];
2003 + u32 tx_count = xor_des->size;
2004 + u8 dest_idx, buf_idx, bit;
2005 + u8 is_op_gen; // means is XOR generation (TRUE) or check (FALSE)
2006 + u8 status = MR_CPX_STATUS_SUCCESS;
2009 + //make the first buffer ptr as the destination.
2010 + if( xor_des->op == MR_CPX_XOR_OP_GEN_P || xor_des->op == MR_CPX_XOR_OP_CHECK_P )
2011 + dest_idx = xor_des->p_idx;
2013 + dest_idx = xor_des->q_idx;
2015 + buf_ptr_list[0] = (u32 *)(host_mem + xor_des->buff_list[dest_idx]);
2017 + is_op_gen = MR_CPX_XOR_OP_IS_GEN(xor_des->op);
2019 + if ( xor_des->buff_list[dest_idx]+tx_count > host_mem_len){
2020 + printk("Error: 1st host memory over flow detected.\n");
2021 + return MR_CPX_STATUS_FAILURE;
2025 + * For XOR_OP_CHECK_P, our check routine expects bufPtrs[0] to be both parity
2026 + * source and parity destination; clear out the P-index from our working bitmap
2027 + * so that the source-buffer scan loop below doesn't include P as one of the
2028 + * explicit source buffers in bufPtrs[].
2031 + buff_valid_bit_map &= ~(1<<xor_des->p_idx);
2033 + //populate buf_ptr_list with valid buffer pointers.
2034 + for ( buf_idx =1 ; buff_valid_bit_map != 0 ; buf_idx++ ){
2035 + bit = megasas_scan_set_bit( buff_valid_bit_map);
2036 + buf_ptr_list[buf_idx] = (u32 *)(host_mem + (u32)xor_des->buff_list[bit]);
2037 + if ( xor_des->buff_list[bit]+tx_count > host_mem_len) {
2038 + printk("Error: host memory over flow detected.\n");
2039 + return MR_CPX_STATUS_FAILURE;;
2041 + buff_valid_bit_map &= ~(1 <<bit);
2043 + //call the xor gen fuctions.
2045 + (*xor_gen_funcs[buf_idx-2])(buf_ptr_list, tx_count);
2047 + status = (*xor_check_funcs[buf_idx-2])(buf_ptr_list, tx_count);
2052 +static u8 megasas_copy( struct page *page, u32 page_offset, u32 sge_offset, u8 *host_ptr, u32 len, u8 dir)
2060 + off = page_offset+sge_offset;
2062 + //kmap_atomic maps single page size but os sg element can have size
2063 + //more than page size, handle it.
2064 + while( remaining > 0 ){
2066 + bytes_copied = min((size_t)remaining, (size_t)(PAGE_SIZE - (off & ~PAGE_MASK)));
2068 + page_addr = kmap_atomic(page+ (off >> PAGE_SHIFT), KM_SOFTIRQ0);
2069 + if ( page_addr == NULL ){
2070 + printk("kmap_atomic is failed.\n");
2071 + return MR_CPX_STATUS_FAILURE;;
2073 + if ( dir == MR_CPX_DIR_WRITE )
2074 + memcpy( host_ptr, page_addr+(off & ~PAGE_MASK), bytes_copied );
2076 + memcpy( page_addr+(off & ~PAGE_MASK), host_ptr, bytes_copied );
2078 + kunmap_atomic ( page_addr, KM_SOFTIRQ0 );
2080 + host_ptr += bytes_copied;
2081 + remaining -= bytes_copied;
2082 + off += bytes_copied;
2085 + return MR_CPX_STATUS_SUCCESS;
2088 + * megasas_do_cpx_copy - Completes the copy opreation
2089 + * @instance : Driver soft state.
2090 + * @cpy_des : input for copying the data.
2092 + * @return 0 on success != 0 on failure
2095 +static u8 megasas_do_cpx_copy( struct megasas_instance *instance, struct mr_cpx_copy_descriptor *cpy_des)
2097 + u8 status = MR_CPX_STATUS_SUCCESS ;
2098 + u32 total_remaining_len = cpy_des->total_byte_count;
2099 + u32 row_remaining_length;
2100 + u32 os_sge_sz = 0, os_sge_offset = 0, os_sge_idx =0, os_sge_len;
2101 + u8 sge_cnt, row_idx, *fw_ptr,host_skip_count_handled;
2102 + struct scsi_cmnd *os_cmd;
2103 + struct scatterlist *os_sgl;
2104 + struct megasas_cmd *mega_cmd;
2105 + struct megasas_io_frame *ldio;
2107 + if ( cpy_des->mfi_cmd_cxt >= instance->max_fw_cmds ){
2108 + printk("megasas: invalid context - 0x%x shoul be < 0x%x \n", cpy_des->mfi_cmd_cxt ,instance->max_fw_cmds );
2109 + return MR_CPX_STATUS_FAILURE;
2112 + mega_cmd = ( struct megasas_cmd *) instance->cmd_list[cpy_des->mfi_cmd_cxt];
2113 + os_cmd = mega_cmd->scmd;
2114 + ldio = (struct megasas_io_frame *)mega_cmd->frame;
2115 + sge_cnt = ldio->sge_count;
2117 + host_skip_count_handled = 0;
2120 + row_remaining_length =0;
2121 + os_sgl = (struct scatterlist *)os_cmd->request_buffer;
2123 + for ( os_sge_idx=0; os_sge_idx < sge_cnt; os_sge_idx++, os_sgl++ ){
2125 + os_sge_len = sg_dma_len(os_sgl);
2127 + if ( !host_skip_count_handled && cpy_des->host_skip_count < ( os_sge_sz += os_sge_len ) ){
2128 + os_sge_offset = cpy_des->host_skip_count - ( os_sge_sz -os_sge_len );
2129 + os_sge_len -= os_sge_offset;
2130 + host_skip_count_handled = 1;
2131 + } else if ( !host_skip_count_handled && cpy_des->host_skip_count == os_sge_sz ){
2132 + os_sge_offset = 0;
2133 + host_skip_count_handled = 1;
2137 + if ( !host_skip_count_handled )
2140 + for( ;total_remaining_len && row_idx < MAX_MR_ROW_SIZE ; row_idx++ ){
2142 + if ( ! row_remaining_length ){
2143 + fw_ptr = (u8 *)(instance->host_mem_virt+cpy_des->copy_buf[row_idx].buf);
2144 + row_remaining_length = cpy_des->copy_buf[row_idx].size;
2147 + if ( (status = megasas_copy( os_sgl->page, os_sgl->offset, os_sge_offset, fw_ptr,
2148 + MIN(os_sge_len, row_remaining_length), cpy_des->dir) ) )
2151 + total_remaining_len -= MIN(os_sge_len, row_remaining_length);
2153 + if ( os_sge_len <= row_remaining_length ){
2154 + fw_ptr += os_sge_len;
2155 + if ( !(row_remaining_length -= os_sge_len) ) row_idx++;
2156 + os_sge_offset = 0;
2159 + os_sge_len -= row_remaining_length;
2160 + os_sge_offset += row_remaining_length;
2161 + row_remaining_length =0;
2165 + if ( row_idx >= MAX_MR_ROW_SIZE && total_remaining_len )
2166 + printk("megasas: Reached end of fw sglist while pending data transfer,row_idx = 0x%x, total_remaining_len = 0x%x \n",
2167 + row_idx, total_remaining_len);
2169 + if( total_remaining_len == 0 || status == MR_CPX_STATUS_FAILURE )
2173 + if ( os_sge_idx >= sge_cnt && total_remaining_len )
2174 + printk("megasas: Reached end of os sglist while pending data transfer, os_sge_idx = 0x%x, total_remaining_len = 0x%x \n",
2175 + os_sge_idx, total_remaining_len);
2181 + * megasas_handle_cpx_requests - Manages the fw queues
2182 + * @instance : Driver soft state.
2184 + * @return 0 on success != 0 on failure
2187 +static int megasas_handle_cpx_requests( struct megasas_instance *instance)
2189 + struct mr_cpx_request_queue *req_q = instance->cpx_request_queue;
2190 + u32 producer_idx, consumer_idx;
2192 + unsigned long flags;
2194 + producer_idx = req_q->producer_idx;
2195 + consumer_idx = req_q->consumer_idx;
2197 + while (producer_idx != consumer_idx ){
2198 + union mr_cpx_descriptor *cpx_des = &instance->cpx_dscrptr[consumer_idx];
2199 + union mr_cpx_response_data rsp_data;
2201 + if ( cpx_des->cpx_copy_desc.hdr.type == MR_CPX_DESCRIPTOR_TYPE_COPY )
2202 + retval = megasas_do_cpx_copy( instance, ( struct mr_cpx_copy_descriptor *)cpx_des );
2204 + else if (cpx_des->cpx_copy_desc.hdr.type == MR_CPX_DESCRIPTOR_TYPE_XOR )
2205 + retval = megasas_do_cpx_xor( ( struct mr_cpx_xor_descriptor *)cpx_des,
2206 + (u8 *)instance->host_mem_virt, instance->host_mem_len );
2208 + printk("Fatal Error : Got invalid descriptor type...\n");
2209 + retval = MR_CPX_STATUS_FAILURE;
2213 + rsp_data.r.status = retval;
2214 + rsp_data.r.context = cpx_des->cpx_copy_desc.hdr.context;
2215 + rsp_data.r.type = cpx_des->cpx_copy_desc.hdr.type;
2218 + spin_lock_irqsave(&instance->hba_lock, flags);
2219 + writel( ~0, &instance->reg_set->inbound_high_queue_port);
2220 + writel( rsp_data.w, &instance->reg_set->inbound_low_queue_port);
2221 + spin_unlock_irqrestore(&instance->hba_lock, flags);
2223 + //take care of wrap around case.
2225 + if ( consumer_idx == instance->cpx_dscrptr_cnt )
2229 + req_q->consumer_idx = producer_idx;
2235 + * megasas_complete_cmd_dpc - Returns FW's controller structure
2236 + * @instance_addr: Address of adapter soft state
2238 + * Tasklet to complete cmds
2240 +static void megasas_complete_cmd_dpc(unsigned long instance_addr)
2245 + struct megasas_cmd *cmd;
2246 + struct megasas_instance *instance =
2247 + (struct megasas_instance *)instance_addr;
2248 + unsigned long flags;
2250 + /* If we have already declared adapter dead, donot complete cmds */
2251 + spin_lock_irqsave(&instance->hba_lock, flags);
2252 + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR ) {
2253 + spin_unlock_irqrestore(&instance->hba_lock, flags);
2256 + spin_unlock_irqrestore(&instance->hba_lock, flags);
2258 + spin_lock_irqsave(&instance->completion_lock, flags);
2260 + producer = *instance->producer;
2261 + consumer = *instance->consumer;
2263 + while (consumer != producer) {
2264 + context = instance->reply_queue[consumer];
2265 + if (context >= instance->max_fw_cmds) {
2266 + printk("ERROR ERROR: unexpected context value %x\n", context);
2270 + cmd = instance->cmd_list[context];
2272 + megasas_complete_cmd(instance, cmd, DID_OK);
2275 + if (consumer == (instance->max_fw_cmds + 1)) {
2280 + *instance->consumer = producer;
2282 + spin_unlock_irqrestore(&instance->completion_lock, flags);
2286 + if ( instance->cpx_supported )
2287 + megasas_handle_cpx_requests( instance);
2290 + * Check if we can restore can_queue
2292 + if (instance->flag & MEGASAS_FW_BUSY
2293 + && time_after(jiffies, instance->last_time + 5 * HZ)
2294 + && atomic_read(&instance->fw_outstanding) < 17) {
2296 + spin_lock_irqsave(instance->host->host_lock, flags);
2297 + instance->flag &= ~MEGASAS_FW_BUSY;
2298 + if ((instance->pdev->device ==
2299 + PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
2300 + (instance->pdev->device ==
2301 + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
2302 + instance->host->can_queue =
2303 + instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
2305 + instance->host->can_queue =
2306 + instance->max_fw_cmds - MEGASAS_INT_CMDS;
2308 + spin_unlock_irqrestore(instance->host->host_lock, flags);
2312 +static void megasas_internal_reset_defer_cmds(struct megasas_instance *instance);
2313 +static void process_fw_state_change_wq(struct work_struct *work);
2315 +void megasas_do_ocr(struct megasas_instance *instance)
2317 + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
2318 + (instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
2319 + (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR))
2321 + *instance->consumer = MEGASAS_ADPRESET_INPROG_SIGN;
2324 + instance->instancet->disable_intr(instance->reg_set);
2325 + instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
2326 + instance->issuepend_done = 0;
2328 + atomic_set(&instance->fw_outstanding, 0);
2329 + megasas_internal_reset_defer_cmds(instance);
2330 + process_fw_state_change_wq(&instance->work_init);
2335 + * megasas_wait_for_outstanding - Wait for all outstanding cmds
2336 + * @instance: Adapter soft state
2338 + * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to
2339 + * complete all its outstanding commands. Returns error if one or more IOs
2340 + * are pending after this time period. It also marks the controller dead.
2342 +static int megasas_wait_for_outstanding(struct megasas_instance *instance)
2346 + u32 wait_time = MEGASAS_RESET_WAIT_TIME;
2348 + unsigned long flags;
2349 + struct list_head clist_local;
2350 + struct megasas_cmd *reset_cmd;
2352 + u8 kill_adapter_flag;
2355 + // If we are in-process if internal reset, we should wait for that process to
2357 + spin_lock_irqsave(&instance->hba_lock, flags);
2358 + adprecovery = instance->adprecovery;
2359 + spin_unlock_irqrestore(&instance->hba_lock, flags);
2361 + if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
2363 + // We take the ownership of all the pending commands. These would be failed to the OS
2364 + // after a successful recovery from adapter internal reset condition.
2365 + INIT_LIST_HEAD(&clist_local);
2366 + spin_lock_irqsave(&instance->hba_lock, flags);
2367 + list_splice_init(&instance->internal_reset_pending_q, &clist_local);
2368 + spin_unlock_irqrestore(&instance->hba_lock, flags);
2370 + printk("megasas: HBA reset handler invoked while adapter internal reset in progress, wait till that's over...\n");
2371 + for (i = 0; i < wait_time; i++) {
2373 + // Are we there yet?
2374 + spin_lock_irqsave(&instance->hba_lock, flags);
2375 + adprecovery = instance->adprecovery;
2376 + spin_unlock_irqrestore(&instance->hba_lock, flags);
2377 + if (adprecovery == MEGASAS_HBA_OPERATIONAL)
2381 + // Are we out of reset yet? If not, HBA is toasted :-(
2382 + if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
2383 + printk("megasas: HBA reset handler timedout for internal reset. Stopping the HBA.\n");
2384 + spin_lock_irqsave(&instance->hba_lock, flags);
2385 + instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
2386 + spin_unlock_irqrestore(&instance->hba_lock, flags);
2390 + printk("megasas: HBA internal reset condition discovered to be cleared.\n");
2392 + // Send the pending commands back to the OS with reset condition
2394 + while (!list_empty(&clist_local)) {
2395 + reset_cmd = list_entry((&clist_local)->next, struct megasas_cmd, list);
2396 + list_del_init(&reset_cmd->list);
2397 + if (reset_cmd->scmd) {
2398 + reset_cmd->scmd->result = DID_RESET << 16;
2399 + printk("megasas: %d:%p reset scsi command [%02x], %#lx\n",
2400 + reset_index, reset_cmd, reset_cmd->scmd->cmnd[0], reset_cmd->scmd->serial_number);
2401 + reset_cmd->scmd->scsi_done(reset_cmd->scmd);
2402 + megasas_return_cmd(instance, reset_cmd);
2404 + else if (reset_cmd->sync_cmd) {
2405 + // Such commands have no timeout, we re-issue this guy again.
2406 + printk("megasas: %p synchronous command detected on the internal reset queue, re-issuing it.\n", reset_cmd);
2407 + reset_cmd->cmd_status = ENODATA;
2408 + instance->instancet->fire_cmd(instance, reset_cmd->frame_phys_addr ,0,instance->reg_set);
2411 + printk("megasas: %p unexpected command on the internal reset defer list.\n", reset_cmd);
2416 + printk("megaraid_sas: All pending commands have been cleared for reset condition.\n");
2421 + // Kernel reset without internal reset in progress.
2422 + printk("megaraid_sas: HBA reset handler invoked without an internal reset condition.\n");
2423 + for (i = 0; i < wait_time; i++) {
2424 + int outstanding = atomic_read(&instance->fw_outstanding);
2429 + if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
2430 + printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
2431 + "commands to complete\n",i,outstanding);
2433 + * Call cmd completion routine. Cmd to be
2434 + * be completed directly without depending on isr.
2436 + megasas_complete_cmd_dpc((unsigned long)instance);
2443 + kill_adapter_flag = 0;
2445 + fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
2446 + if ((fw_state == MFI_STATE_FAULT) && (instance->disableOnlineCtrlReset == 0)) {
2447 + printk("megasas: waiting_for_outstanding: before issue OCR. FW state = %x\n", fw_state);
2449 + kill_adapter_flag = 2;
2452 + megasas_do_ocr(instance);
2453 + kill_adapter_flag = 1;
2454 + printk("megasas: waiting_for_outstanding: after issue OCR. \n");
2456 + /* wait for 5 secs to let the FW finish all the pending cmds*/
2457 + for (sl=0; sl<10; sl++)
2463 + if (atomic_read(&instance->fw_outstanding) && !kill_adapter_flag) {
2464 + if (instance->disableOnlineCtrlReset == 0) {
2465 + printk("megasas: waiting_for_outstanding: before issue OCR. FW state = %x\n", fw_state);
2466 + megasas_do_ocr(instance);
2467 + printk("megasas: waiting_for_outstanding: after issue OCR. \n");
2469 + /* wait for 5 secs to let the FW finish all the pending cmds*/
2470 + for (i = 0; i < wait_time; i++) {
2471 + int outstanding = atomic_read(&instance->fw_outstanding);
2480 + if (atomic_read(&instance->fw_outstanding) || (kill_adapter_flag == 2)) {
2481 + printk("megaraid_sas: pending commands remain even after reset handling.\n");
2483 + * Send signal to FW to stop processing any pending cmds.
2484 + * The controller will be taken offline by the OS now.
2486 + if ((instance->pdev->device ==
2487 + PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
2488 + (instance->pdev->device ==
2489 + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
2490 + writel(MFI_STOP_ADP,
2491 + &instance->reg_set->reserved_0);
2493 + writel(MFI_STOP_ADP,
2494 + &instance->reg_set->inbound_doorbell);
2496 + megasas_dump_pending_frames(instance);
2497 + spin_lock_irqsave(&instance->hba_lock, flags);
2498 + instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
2499 + spin_unlock_irqrestore(&instance->hba_lock, flags);
2503 + printk("megaraid_sas: no more pending commands remain after reset handling.\n");
2509 + * megasas_generic_reset - Generic reset routine
2510 + * @scmd: Mid-layer SCSI command
2512 + * This routine implements a generic reset handler for device, bus and host
2513 + * reset requests. Device, bus and host specific reset handlers can use this
2514 + * function after they do their specific tasks.
2516 +static int megasas_generic_reset(struct scsi_cmnd *scmd)
2519 + struct megasas_instance *instance;
2521 + instance = (struct megasas_instance *)scmd->device->host->hostdata;
2523 + scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
2524 + scmd->serial_number, scmd->cmnd[0], scmd->retries);
2526 + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
2527 + printk(KERN_ERR "megasas: cannot recover from previous reset "
2532 + ret_val = megasas_wait_for_outstanding(instance);
2533 + if (ret_val == SUCCESS)
2534 + printk(KERN_NOTICE "megasas: reset successful \n");
2536 + printk(KERN_ERR "megasas: failed to do reset\n");
2542 + * megasas_reset_timer - quiesce the adapter if required
2543 + * @scmd: scsi cmnd
2545 + * Sets the FW busy flag and reduces the host->can_queue if the
2546 + * cmd has not been completed within the timeout period.
2549 +scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
2551 + struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
2552 + struct megasas_instance *instance;
2553 + unsigned long flags;
2555 + if (time_after(jiffies, scmd->jiffies_at_alloc +
2556 + (MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) {
2557 + return EH_NOT_HANDLED;
2560 + instance = cmd->instance;
2561 + if (!(instance->flag & MEGASAS_FW_BUSY)) {
2562 + /* FW is busy, throttle IO */
2563 + spin_lock_irqsave(instance->host->host_lock, flags);
2565 + instance->host->can_queue = 16;
2566 + instance->last_time = jiffies;
2567 + instance->flag |= MEGASAS_FW_BUSY;
2569 + spin_unlock_irqrestore(instance->host->host_lock, flags);
2571 + return EH_RESET_TIMER;
2575 + * megasas_reset_device - Device reset handler entry point
2577 +static int megasas_reset_device(struct scsi_cmnd *scmd)
2582 + * First wait for all commands to complete
2584 + ret = megasas_generic_reset(scmd);
2590 + * megasas_reset_bus_host - Bus & host reset handler entry point
2592 +static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
2597 + * First wait for all commands to complete
2599 + ret = megasas_generic_reset(scmd);
2605 + * megasas_bios_param - Returns disk geometry for a disk
2606 + * @sdev: device handle
2607 + * @bdev: block device
2608 + * @capacity: drive capacity
2609 + * @geom: geometry parameters
2612 +megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
2613 + sector_t capacity, int geom[])
2617 + sector_t cylinders;
2618 + unsigned long tmp;
2619 + /* Default heads (64) & sectors (32) */
2623 + tmp = heads * sectors;
2624 + cylinders = capacity;
2626 + sector_div(cylinders, tmp);
2629 + * Handle extended translation size for logical drives > 1Gb
2632 + if (capacity >= 0x200000) {
2635 + tmp = heads*sectors;
2636 + cylinders = capacity;
2637 + sector_div(cylinders, tmp);
2641 + geom[1] = sectors;
2642 + geom[2] = cylinders;
2647 +static void megasas_aen_polling(struct work_struct *work);
2650 + * megasas_service_aen - Processes an event notification
2651 + * @instance: Adapter soft state
2652 * @cmd: AEN command completed by the ISR
2654 * For AEN, driver sends a command down to FW that is held by the FW till an
2655 @@ -1121,27 +3026,74 @@ megasas_bios_param(struct scsi_device *s
2657 megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
2659 + unsigned long flags;
2661 * Don't signal app if it is just an aborted previously registered aen
2663 - if (!cmd->abort_aen)
2664 + if ((!cmd->abort_aen) && (instance->unload == 0)) {
2665 + spin_lock_irqsave(&poll_aen_lock, flags);
2666 + megasas_poll_wait_aen = 1;
2667 + spin_unlock_irqrestore(&poll_aen_lock, flags);
2668 + wake_up(&megasas_poll_wait);
2669 kill_fasync(&megasas_async_queue, SIGIO, POLL_IN);
2674 instance->aen_cmd = NULL;
2675 megasas_return_cmd(instance, cmd);
2677 + if ((instance->unload == 0) && ((instance->issuepend_done == 1))) {
2678 + struct megasas_aen_event *ev;
2679 + ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
2681 + printk(KERN_ERR "megasas_service_aen: out of memory\n");
2683 + ev->instance = instance;
2684 + instance->ev = ev;
2685 + INIT_WORK(&ev->hotplug_work, megasas_aen_polling);
2686 + schedule_delayed_work(
2687 + (struct delayed_work *)&ev->hotplug_work, 0);
2692 +static int megasas_slave_alloc(struct scsi_device *sdev)
2695 + struct megasas_instance *instance ;
2696 + instance = megasas_lookup_instance(sdev->host->host_no);
2698 + if ((sdev->channel < MEGASAS_MAX_PD_CHANNELS) &&
2699 + (sdev->type == TYPE_DISK)) {
2701 + * Open the OS scan to the SYSTEM PD
2704 + (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id;
2705 + if ((instance->pd_list[pd_index].driveState ==
2706 + MR_PD_STATE_SYSTEM) &&
2707 + (instance->pd_list[pd_index].driveType ==
2719 * Scsi host template for megaraid_sas driver
2721 static struct scsi_host_template megasas_template = {
2723 .module = THIS_MODULE,
2724 - .name = "LSI Logic SAS based MegaRAID driver",
2725 + .name = "LSI SAS based MegaRAID driver",
2726 .proc_name = "megaraid_sas",
2727 .slave_configure = megasas_slave_configure,
2728 + .slave_alloc = megasas_slave_alloc,
2729 .queuecommand = megasas_queue_command,
2730 .eh_device_reset_handler = megasas_reset_device,
2731 .eh_bus_reset_handler = megasas_reset_bus_host,
2732 @@ -1193,7 +3145,6 @@ megasas_complete_abort(struct megasas_in
2738 * megasas_unmap_sgbuf - Unmap SG buffers
2739 * @instance: Adapter soft state
2740 @@ -1217,12 +3168,18 @@ megasas_unmap_sgbuf(struct megasas_insta
2741 opcode = cmd->frame->hdr.cmd;
2743 if ((opcode == MFI_CMD_LD_READ) || (opcode == MFI_CMD_LD_WRITE)) {
2745 + if (instance->flag_ieee) {
2746 + buf_h = cmd->frame->io.sgl.sge_skinny[0].phys_addr;
2748 + } else if (IS_DMA64)
2749 buf_h = cmd->frame->io.sgl.sge64[0].phys_addr;
2751 buf_h = cmd->frame->io.sgl.sge32[0].phys_addr;
2754 + if (instance->flag_ieee) {
2755 + buf_h = cmd->frame->pthru.sgl.sge_skinny[0].phys_addr;
2757 + } else if (IS_DMA64)
2758 buf_h = cmd->frame->pthru.sgl.sge64[0].phys_addr;
2760 buf_h = cmd->frame->pthru.sgl.sge32[0].phys_addr;
2761 @@ -1233,6 +3190,7 @@ megasas_unmap_sgbuf(struct megasas_insta
2767 * megasas_complete_cmd - Completes a command
2768 * @instance: Adapter soft state
2769 @@ -1247,9 +3205,14 @@ static void
2770 megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
2773 + unsigned long flags;
2775 struct megasas_header *hdr = &cmd->frame->hdr;
2777 + // If the commands complete successfully, the retry counter should also be reset
2778 + // for future re-tries.
2779 + cmd->retry_for_fw_reset = 0;
2782 cmd->scmd->SCp.ptr = NULL;
2784 @@ -1338,6 +3301,12 @@ megasas_complete_cmd(struct megasas_inst
2788 + if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO ||
2789 + cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) {
2790 + spin_lock_irqsave(&poll_aen_lock, flags);
2791 + megasas_poll_wait_aen = 0;
2792 + spin_unlock_irqrestore(&poll_aen_lock, flags);
2796 * See if got an event notification
2797 @@ -1364,39 +3333,286 @@ megasas_complete_cmd(struct megasas_inst
2801 + * megasas_issue_pending_cmds_again - issue all pending cmds
2802 + * in FW again because of the fw reset
2803 + * @instance: Adapter soft state
2806 +megasas_issue_pending_cmds_again(struct megasas_instance *instance)
2808 + struct megasas_cmd *cmd;
2809 + struct list_head clist_local;
2810 + union megasas_evt_class_locale class_locale;
2811 + unsigned long flags;
2814 + INIT_LIST_HEAD(&clist_local);
2815 + spin_lock_irqsave(&instance->hba_lock, flags);
2816 + list_splice_init(&instance->internal_reset_pending_q, &clist_local);
2817 + spin_unlock_irqrestore(&instance->hba_lock, flags);
2819 + while (!list_empty(&clist_local)) {
2820 + cmd = list_entry((&clist_local)->next, struct megasas_cmd, list);
2821 + list_del_init(&cmd->list);
2823 + if (cmd->sync_cmd || cmd->scmd) {
2824 + printk("megaraid_sas: command %p, %p:%d detected to be pending while HBA reset.\n", cmd, cmd->scmd, cmd->sync_cmd);
2826 + cmd->retry_for_fw_reset++;
2828 + // If a command has continuously been tried multiple times and causing
2829 + // a FW reset condition, no further recoveries should be performed on
2831 + if (cmd->retry_for_fw_reset == 3) {
2832 + printk("megaraid_sas: command %p, %p:%d was tried multiple times during adapter reset. Shutting down the HBA\n", cmd, cmd->scmd, cmd->sync_cmd);
2833 + megaraid_sas_kill_hba(instance);
2835 + instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
2840 + if (cmd->sync_cmd == 1) {
2842 + printk("megaraid_sas: unexpected SCSI command attached to internal command!\n");
2844 + printk("megasas: %p synchronous command detected on the internal reset queue, issue it again.\n", cmd);
2845 + cmd->cmd_status = ENODATA;
2846 + instance->instancet->fire_cmd(instance,cmd->frame_phys_addr ,0,instance->reg_set);
2847 + } else if (cmd->scmd) {
2848 + printk("megasas: %p scsi command [%02x], %#lx detected on the internal reset queue, issue it again.\n", cmd, cmd->scmd->cmnd[0], cmd->scmd->serial_number);
2849 + atomic_inc(&instance->fw_outstanding);
2850 + instance->instancet->fire_cmd(instance, cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set);
2853 + printk("megasas: %p unexpected command on the internal reset defer list while re-issue!!\n", cmd);
2857 + // Re-register AEN
2858 + if (instance->aen_cmd) {
2859 + printk("megaraid_sas: existing aen_cmd discovered in deferred processing, freeing...\n");
2860 + megasas_return_cmd(instance, instance->aen_cmd);
2861 + instance->aen_cmd = NULL;
2865 + * Initiate AEN (Asynchronous Event Notification)
2867 + seq_num = instance->last_seq_num;
2868 + class_locale.members.reserved = 0;
2869 + class_locale.members.locale = MR_EVT_LOCALE_ALL;
2870 + class_locale.members.class = MR_EVT_CLASS_DEBUG;
2872 + megasas_register_aen(instance, seq_num, class_locale.word);
2878 + * Move the internal reset pending commands to a deferred queue.
2880 + * We move the commands pending at internal reset time to a pending queue. This queue would
2881 + * be flushed after successful completion of the internal reset sequence.
2882 + * if the internal reset did not complete in time, the kernel reset handler would flush these
2885 +static void megasas_internal_reset_defer_cmds(struct megasas_instance *instance)
2887 + struct megasas_cmd *cmd;
2889 + u32 max_cmd = instance->max_fw_cmds;
2891 + unsigned long flags;
2894 + spin_lock_irqsave(&instance->cmd_pool_lock, flags);
2895 + for (i = 0; i < max_cmd; i++) {
2896 + cmd = instance->cmd_list[i];
2897 + if (cmd->sync_cmd == 1 || cmd->scmd) {
2898 + printk("megasas: moving cmd[%d]:%p:%d:%p on the defer queue as internal reset in progress.\n",
2899 + defer_index, cmd, cmd->sync_cmd, cmd->scmd);
2900 + if (!list_empty(&cmd->list)) {
2901 + printk("megaraid_sas: ERROR while moving this cmd:%p, %d %p, it was discovered on some list?\n", cmd, cmd->sync_cmd, cmd->scmd);
2902 + list_del_init(&cmd->list);
2905 + list_add_tail(&cmd->list, &instance->internal_reset_pending_q);
2908 + spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
2913 +process_fw_state_change_wq(struct work_struct *work)
2915 + struct megasas_instance *instance =
2916 + container_of(work, struct megasas_instance, work_init);
2918 + unsigned long flags;
2920 + if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) {
2921 + printk("megaraid_sas: error, unexpected adapter recovery state %x in %s\n", instance->adprecovery, __FUNCTION__);
2925 + if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) {
2926 + printk("megaraid_sas: FW detected to be in fault state, restarting it...\n");
2928 + instance->instancet->disable_intr(instance->reg_set);
2929 + atomic_set(&instance->fw_outstanding, 0);
2931 + atomic_set(&instance->fw_reset_no_pci_access, 1);
2932 + instance->instancet->adp_reset(instance, instance->reg_set);
2933 + atomic_set(&instance->fw_reset_no_pci_access, 0 );
2935 + printk("megaraid_sas: FW was restarted successfully, initiating next stage...\n");
2937 + printk("megaraid_sas: HBA recovery state machine, state 2 starting...\n");
2939 + /*waitting for about 20 second before start the second init*/
2940 + for(wait = 0; wait < 30; wait++)
2943 + if (megasas_transition_to_ready(instance))
2945 + printk("megaraid_sas: out: controller is not in ready state\n");
2947 + megaraid_sas_kill_hba(instance);
2948 + instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
2952 + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
2953 + (instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
2954 + (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR))
2956 + *instance->consumer = *instance->producer;
2958 + *instance->consumer = 0;
2959 + *instance->producer = 0;
2962 + if ( megasas_check_cpx_support( instance ) == 0 ){
2963 + if ( megasas_send_cpx_queue_data( instance ) ){
2964 + printk("megasas: Sending cpx queue data to FW failed.\n");
2965 + megasas_remove_cpx(instance);
2969 + // Transition the FW to operational state
2970 + megasas_issue_init_mfi(instance);
2972 + // Setting the adapter to OPERATIONAL at this point is very important. This would
2973 + // prevent other subsystems (reset, aen, and ioctls) to block till the recovery
2974 + // logic has run it's course.
2975 + spin_lock_irqsave(&instance->hba_lock, flags);
2976 + instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
2977 + spin_unlock_irqrestore(&instance->hba_lock, flags);
2978 + instance->instancet->enable_intr(instance->reg_set);
2980 + printk("megaraid_sas: second stage of reset complete, FW is ready now.\n");
2982 + megasas_issue_pending_cmds_again(instance);
2983 + instance->issuepend_done = 1;
2991 * megasas_deplete_reply_queue - Processes all completed commands
2992 * @instance: Adapter soft state
2993 * @alt_status: Alternate status to be returned to
2994 * SCSI mid-layer instead of the status
2995 * returned by the FW
2996 + * Note: this must be called with hba lock held
2999 megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
3002 - * Check if it is our interrupt
3003 - * Clear the interrupt
3005 - if(instance->instancet->clear_intr(instance->reg_set))
3009 + // If the adapter is under a reset recovery, all interrupts coming from it must be acknowledged
3010 + // if the consumer pointer value indicates so.
3011 + if((mfiStatus = instance->instancet->check_reset(instance, instance->reg_set)) == 1) {
3012 + return IRQ_HANDLED;
3015 + // Clear the interrupt on the HBA
3016 + if((mfiStatus = instance->instancet->clear_intr(instance->reg_set)) == 0) {
3020 - if (instance->hw_crit_error)
3023 - * Schedule the tasklet for cmd completion
3025 + instance->mfiStatus = mfiStatus;
3027 + // If the current soft state indicates an OPERATIONAL state _and_ now we have
3028 + // detected state change, this should be FW FAULT case.
3029 + if ((mfiStatus & MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE)) {
3030 + fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
3032 + if (fw_state != MFI_STATE_FAULT) {
3033 + printk("megaraid_sas: fw state while internal state change operational, state:%x\n", fw_state);
3036 + if ((fw_state == MFI_STATE_FAULT) && (instance->disableOnlineCtrlReset == 0)){
3037 + printk("megaraid_sas: adapter reset condition is detected, waiting for it to restart...\n");
3039 + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
3040 + (instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
3041 + (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR))
3043 + *instance->consumer = MEGASAS_ADPRESET_INPROG_SIGN;
3047 + instance->instancet->disable_intr(instance->reg_set);
3048 + instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; // indicates adapter restart stage 1 is in progress
3049 + instance->issuepend_done = 0;
3051 + // The pending commands are moved to a deferred list. We would pick commands up and
3052 + // re-issue once the reset processing is over.
3053 + atomic_set(&instance->fw_outstanding, 0);
3054 + megasas_internal_reset_defer_cmds(instance);
3056 + // Schedule a low-priorty thread to perform the function for current stage of
3057 + // adapter reset state machine.
3058 + printk("megaraid_sas: FW state detected, current:%x, reset stage:%d\n", fw_state, instance->adprecovery);
3059 + schedule_work(&instance->work_init);
3060 + return IRQ_HANDLED;
3063 + printk("megaraid_sas: fw state while internal state changes, state:%x, disableOCR=%x\n",
3064 + fw_state, instance->disableOnlineCtrlReset);
3068 + // Schedule the tasklet for cmd completion
3069 tasklet_schedule(&instance->isr_tasklet);
3075 * megasas_isr - isr entry point
3077 static irqreturn_t megasas_isr(int irq, void *devp)
3079 - return megasas_deplete_reply_queue((struct megasas_instance *)devp,
3081 + struct megasas_instance *instance;
3082 + unsigned long flags;
3085 + if ( atomic_read( &(( (struct megasas_instance *)devp)->fw_reset_no_pci_access )) )
3086 + return IRQ_HANDLED;
3088 + instance = (struct megasas_instance *)devp;
3090 + spin_lock_irqsave(&instance->hba_lock, flags);
3091 + rc = megasas_deplete_reply_queue(instance, DID_OK);
3092 + spin_unlock_irqrestore(&instance->hba_lock, flags);
3098 @@ -1415,6 +3631,7 @@ megasas_transition_to_ready(struct megas
3102 + u32 abs_state, curr_abs_state;
3104 fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
3106 @@ -1424,6 +3641,8 @@ megasas_transition_to_ready(struct megas
3108 while (fw_state != MFI_STATE_READY) {
3110 + abs_state = instance->instancet->read_fw_status_reg(instance->reg_set);
3114 case MFI_STATE_FAULT:
3115 @@ -1435,18 +3654,36 @@ megasas_transition_to_ready(struct megas
3117 * Set the CLR bit in inbound doorbell
3119 - writel(MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
3120 - &instance->reg_set->inbound_doorbell);
3121 + if ((instance->pdev->device ==
3122 + PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
3123 + (instance->pdev->device ==
3124 + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
3127 + MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
3128 + &instance->reg_set->reserved_0);
3131 + MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
3132 + &instance->reg_set->inbound_doorbell);
3136 + max_wait = MEGASAS_RESET_WAIT_TIME;
3137 cur_state = MFI_STATE_WAIT_HANDSHAKE;
3140 case MFI_STATE_BOOT_MESSAGE_PENDING:
3141 - writel(MFI_INIT_HOTPLUG,
3142 - &instance->reg_set->inbound_doorbell);
3143 + if ((instance->pdev->device ==
3144 + PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
3145 + (instance->pdev->device ==
3146 + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
3147 + writel(MFI_INIT_HOTPLUG,
3148 + &instance->reg_set->reserved_0);
3150 + writel(MFI_INIT_HOTPLUG,
3151 + &instance->reg_set->inbound_doorbell);
3154 + max_wait = MEGASAS_RESET_WAIT_TIME;
3155 cur_state = MFI_STATE_BOOT_MESSAGE_PENDING;
3158 @@ -1455,9 +3692,17 @@ megasas_transition_to_ready(struct megas
3159 * Bring it to READY state; assuming max wait 10 secs
3161 instance->instancet->disable_intr(instance->reg_set);
3162 - writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell);
3163 + if ((instance->pdev->device ==
3164 + PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
3165 + (instance->pdev->device ==
3166 + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
3167 + writel(MFI_RESET_FLAGS,
3168 + &instance->reg_set->reserved_0);
3170 + writel(MFI_RESET_FLAGS,
3171 + &instance->reg_set->inbound_doorbell);
3174 + max_wait = MEGASAS_RESET_WAIT_TIME;
3175 cur_state = MFI_STATE_OPERATIONAL;
3178 @@ -1465,32 +3710,32 @@ megasas_transition_to_ready(struct megas
3180 * This state should not last for more than 2 seconds
3183 + max_wait = MEGASAS_RESET_WAIT_TIME;
3184 cur_state = MFI_STATE_UNDEFINED;
3187 case MFI_STATE_BB_INIT:
3189 + max_wait = MEGASAS_RESET_WAIT_TIME;
3190 cur_state = MFI_STATE_BB_INIT;
3193 case MFI_STATE_FW_INIT:
3195 + max_wait = MEGASAS_RESET_WAIT_TIME;
3196 cur_state = MFI_STATE_FW_INIT;
3199 case MFI_STATE_FW_INIT_2:
3201 + max_wait = MEGASAS_RESET_WAIT_TIME;
3202 cur_state = MFI_STATE_FW_INIT_2;
3205 case MFI_STATE_DEVICE_SCAN:
3207 + max_wait = MEGASAS_RESET_WAIT_TIME;
3208 cur_state = MFI_STATE_DEVICE_SCAN;
3211 case MFI_STATE_FLUSH_CACHE:
3213 + max_wait = MEGASAS_RESET_WAIT_TIME;
3214 cur_state = MFI_STATE_FLUSH_CACHE;
3217 @@ -1506,8 +3751,10 @@ megasas_transition_to_ready(struct megas
3218 for (i = 0; i < (max_wait * 1000); i++) {
3219 fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) &
3222 + instance->instancet->read_fw_status_reg(instance->reg_set);
3224 - if (fw_state == cur_state) {
3225 + if (abs_state == curr_abs_state) {
3229 @@ -1516,12 +3763,12 @@ megasas_transition_to_ready(struct megas
3231 * Return error if fw_state hasn't changed after max_wait
3233 - if (fw_state == cur_state) {
3234 + if (curr_abs_state == abs_state) {
3235 printk(KERN_DEBUG "FW state [%d] hasn't changed "
3236 "in %d secs\n", fw_state, max_wait);
3241 printk(KERN_INFO "megasas: FW now in Ready state\n");
3244 @@ -1594,11 +3841,16 @@ static int megasas_create_frame_pool(str
3245 sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
3246 sizeof(struct megasas_sge32);
3248 + if (instance->flag_ieee) {
3249 + sge_sz = sizeof(struct megasas_sge_skinny);
3253 * Calculated the number of 64byte frames required for SGL
3255 sgl_sz = sge_sz * instance->max_num_sge;
3256 frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE;
3260 * We need one extra frame for the MFI command
3261 @@ -1655,7 +3907,15 @@ static int megasas_create_frame_pool(str
3265 + memset(cmd->frame, 0, total_sz);
3267 cmd->frame->io.context = cmd->index;
3270 + * Initialize pad_0 to 0, otherwise it could corrupt
3271 + * the value of context and cause FW crash
3273 + cmd->frame->io.pad_0 = 0;
3277 @@ -1714,8 +3974,7 @@ static int megasas_alloc_cmds(struct meg
3278 * Allocate the dynamic array first and then allocate individual
3281 - instance->cmd_list = kmalloc(sizeof(struct megasas_cmd *) * max_cmd,
3283 + instance->cmd_list = kcalloc(max_cmd, sizeof(struct megasas_cmd*), GFP_KERNEL);
3285 if (!instance->cmd_list) {
3286 printk(KERN_DEBUG "megasas: out of memory\n");
3287 @@ -1747,6 +4006,7 @@ static int megasas_alloc_cmds(struct meg
3288 cmd = instance->cmd_list[i];
3289 memset(cmd, 0, sizeof(struct megasas_cmd));
3292 cmd->instance = instance;
3294 list_add_tail(&cmd->list, &instance->cmd_pool);
3295 @@ -1763,6 +4023,181 @@ static int megasas_alloc_cmds(struct meg
3300 + * megasas_get_pd_list_info - Returns FW's pd_list structure
3301 + * @instance: Adapter soft state
3302 + * @pd_list: pd_list structure
3304 + * Issues an internal command (DCMD) to get the FW's controller PD
3305 + * list structure. This information is mainly used to find out SYSTEM
3306 + * supported by the FW.
3309 +megasas_get_pd_list(struct megasas_instance *instance)
3311 + int ret = 0, pd_index = 0;
3312 + struct megasas_cmd *cmd;
3313 + struct megasas_dcmd_frame *dcmd;
3314 + struct MR_PD_LIST *ci;
3315 + struct MR_PD_ADDRESS *pd_addr;
3316 + dma_addr_t ci_h = 0;
3318 + cmd = megasas_get_cmd(instance);
3321 + printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n");
3325 + dcmd = &cmd->frame->dcmd;
3327 + ci = pci_alloc_consistent(instance->pdev,
3328 + MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h);
3331 + printk(KERN_DEBUG "Failed to alloc mem for pd_list\n");
3332 + megasas_return_cmd(instance, cmd);
3336 + memset(ci, 0, sizeof(*ci));
3337 + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
3339 + dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST;
3340 + dcmd->mbox.b[1] = 0;
3341 + dcmd->cmd = MFI_CMD_DCMD;
3342 + dcmd->cmd_status = 0xFF;
3343 + dcmd->sge_count = 1;
3344 + dcmd->flags = MFI_FRAME_DIR_READ;
3345 + dcmd->timeout = 0;
3347 + dcmd->data_xfer_len = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
3348 + dcmd->opcode = MR_DCMD_PD_LIST_QUERY;
3349 + dcmd->sgl.sge32[0].phys_addr = ci_h;
3350 + dcmd->sgl.sge32[0].length = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
3352 + if (!megasas_issue_polled(instance, cmd)) {
3359 + * the following function will get the instance PD LIST.
3362 + pd_addr = ci->addr;
3366 + (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) {
3368 + memset(instance->pd_list, 0,
3369 + MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
3371 + for (pd_index = 0; pd_index < ci->count; pd_index++) {
3373 + instance->pd_list[pd_addr->deviceId].tid =
3374 + pd_addr->deviceId;
3375 + instance->pd_list[pd_addr->deviceId].driveType =
3376 + pd_addr->scsiDevType;
3377 + instance->pd_list[pd_addr->deviceId].driveState =
3378 + MR_PD_STATE_SYSTEM;
3383 + pci_free_consistent(instance->pdev,
3384 + MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST),
3388 + megasas_return_cmd(instance, cmd);
3393 + * megasas_get_ld_list_info - Returns FW's ld_list structure
3394 + * @instance: Adapter soft state
3395 + * @ld_list: ld_list structure
3397 + * Issues an internal command (DCMD) to get the FW's controller PD
3398 + * list structure. This information is mainly used to find out SYSTEM
3399 + * supported by the FW.
3402 +megasas_get_ld_list(struct megasas_instance *instance)
3404 + int ret = 0, ld_index = 0, ids = 0;
3405 + struct megasas_cmd *cmd;
3406 + struct megasas_dcmd_frame *dcmd;
3407 + struct MR_LD_LIST *ci;
3408 + dma_addr_t ci_h = 0;
3410 + cmd = megasas_get_cmd(instance);
3413 + printk(KERN_DEBUG "megasas (megasas_get_ld_list): Failed to get cmd\n");
3417 + dcmd = &cmd->frame->dcmd;
3419 + ci = pci_alloc_consistent(instance->pdev, sizeof(struct MR_LD_LIST), &ci_h);
3422 + printk(KERN_DEBUG "Failed to alloc mem for megasas_get_ld_list\n");
3423 + megasas_return_cmd(instance, cmd);
3427 + memset(ci, 0, sizeof(*ci));
3428 + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
3430 + dcmd->cmd = MFI_CMD_DCMD;
3431 + dcmd->cmd_status = 0xFF;
3432 + dcmd->sge_count = 1;
3433 + dcmd->flags = MFI_FRAME_DIR_READ;
3434 + dcmd->timeout = 0;
3435 + dcmd->data_xfer_len = sizeof(struct MR_LD_LIST);
3436 + dcmd->opcode = MR_DCMD_LD_GET_LIST;
3437 + dcmd->sgl.sge32[0].phys_addr = ci_h;
3438 + dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST);
3441 + if (!megasas_issue_polled(instance, cmd)) {
3449 + * the following function will get the instance PD LIST.
3452 + if ( (ret == 0) && (ci->ldCount <= (MAX_LOGICAL_DRIVES))){
3454 + memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
3456 + for (ld_index = 0; ld_index < ci->ldCount; ld_index++) {
3457 + if (ci->ldList[ld_index].state != 0) {
3458 + ids = ci->ldList[ld_index].ref.targetId;
3459 + instance->ld_ids[ids] = ci->ldList[ld_index].ref.targetId;
3466 + pci_free_consistent(instance->pdev, sizeof(struct MR_LD_LIST), ci, ci_h);
3469 + megasas_return_cmd(instance, cmd);
3475 * megasas_get_controller_info - Returns FW's controller structure
3476 * @instance: Adapter soft state
3477 @@ -1808,6 +4243,7 @@ megasas_get_ctrl_info(struct megasas_ins
3478 dcmd->sge_count = 1;
3479 dcmd->flags = MFI_FRAME_DIR_READ;
3482 dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info);
3483 dcmd->opcode = MR_DCMD_CTRL_GET_INFO;
3484 dcmd->sgl.sge32[0].phys_addr = ci_h;
3485 @@ -1827,58 +4263,276 @@ megasas_get_ctrl_info(struct megasas_ins
3491 - * megasas_complete_cmd_dpc - Returns FW's controller structure
3492 - * @instance_addr: Address of adapter soft state
3493 + * megasas_check_cpx_support : Tries to get the host memory address if fails then cpx
3494 + not supported else cpx supported.
3495 + * @instance: Adapter soft state
3497 - * Tasklet to complete cmds
3498 + * @return 0 on success non-zero on failure.
3500 -static void megasas_complete_cmd_dpc(unsigned long instance_addr)
3501 +static int megasas_check_cpx_support( struct megasas_instance *instance)
3503 + struct megasas_cmd *cmd;
3504 + struct megasas_dcmd_frame *dcmd;
3505 + struct mr_cpx_init_data *cpx_init_data;
3506 + dma_addr_t cpx_init_data_h;
3509 + cmd = megasas_get_cmd(instance);
3511 + printk(KERN_DEBUG "megasas (get_host_mem_addr): Failed to get cmd\n");
3515 + cpx_init_data = pci_alloc_consistent(instance->pdev, sizeof( struct mr_cpx_init_data), &cpx_init_data_h);
3516 + if (cpx_init_data == NULL) {
3517 + printk(KERN_DEBUG "Failed to alloc mem for cpx_init_data. \n");
3518 + megasas_return_cmd(instance, cmd);
3522 + dcmd = &cmd->frame->dcmd;
3524 + dcmd->opcode = MR_DCMD_CTRL_MISC_CPX_INIT_DATA_GET;
3525 + dcmd->data_xfer_len = sizeof(struct mr_cpx_init_data );
3526 + dcmd->cmd = MFI_CMD_DCMD;
3527 + dcmd->cmd_status = 0xff;
3528 + dcmd->sge_count = 1;
3529 + dcmd->sgl.sge32[0].phys_addr = cpx_init_data_h;
3530 + dcmd->sgl.sge32[0].length = sizeof(struct mr_cpx_init_data);
3532 + retval = megasas_issue_polled ( instance, cmd );
3534 + if ( retval == 0 && cmd->frame->hdr.cmd_status == 0 ){
3535 + instance->host_mem_phys = cpx_init_data->phys_addr_cache_buf;
3536 + instance->host_mem_len = cpx_init_data->size;
3537 + instance->cpx_dscrptr_cnt = cpx_init_data->cpx_desc_count;
3538 + if ( instance->host_mem_len == 0 || instance->host_mem_phys == 0 || ! instance->cpx_dscrptr_cnt ){
3539 + printk("Got host_mem_len = 0 OR host_mem_phys as NULL OR cpx_descriptor count = 0 \n");
3543 + printk("megasas: cpx is not supported.\n");
3548 + pci_free_consistent(instance->pdev, sizeof(struct mr_cpx_init_data), cpx_init_data, cpx_init_data_h);
3549 + megasas_return_cmd(instance, cmd);
3555 + * megasas_send_cpx_queue_data : Sends the queue setup info to fw.
3556 + * @instance: Adapter soft state
3558 + * @return 0 on success non-zero on failure.
3561 +static int megasas_send_cpx_queue_data( struct megasas_instance *instance )
3564 + struct megasas_cmd *cmd;
3565 + struct megasas_dcmd_frame *dcmd;
3568 + cmd = megasas_get_cmd(instance);
3570 + printk(KERN_DEBUG "megasas (get_host_mem_addr): Failed to get cmd\n");
3574 + //initialize dcmd data
3575 + dcmd = &cmd->frame->dcmd;
3577 + dcmd->opcode = MR_DCMD_CTRL_MISC_CPX_QUEUE_DATA;
3578 + dcmd->data_xfer_len = sizeof( struct mr_cpx_queue_data );
3579 + dcmd->cmd = MFI_CMD_DCMD;
3580 + dcmd->cmd_status = 0xff;
3581 + dcmd->sge_count = 1;
3582 + dcmd->mbox.w[0] = instance->cpx_request_queue_h;
3583 + dcmd->mbox.w[1] = 0;
3584 + dcmd->mbox.w[2] = instance->cpx_dscrptr_cnt;
3586 + retval = megasas_issue_polled ( instance, cmd );
3588 + megasas_return_cmd( instance, cmd);
3590 + if ( retval == 0 ){
3591 + instance->cpx_request_queue->consumer_idx = instance->cpx_request_queue->producer_idx = 0;
3592 + instance->cpx_supported = 1;
3598 +static u32 megasas_get_cpx_mem_len( u16 max_fw_cmds )
3600 + return (sizeof( struct mr_cpx_request_queue ) + sizeof( union mr_cpx_descriptor ) * ( max_fw_cmds) );
3603 +static u32 megasas_remove_cpx( struct megasas_instance *instance)
3605 + if ( instance->host_mem_virt )
3606 + iounmap(instance->host_mem_virt);
3607 + if ( instance->cpx_request_queue )
3608 + pci_free_consistent(instance->pdev, megasas_get_cpx_mem_len( instance->cpx_dscrptr_cnt),
3609 + instance->cpx_request_queue,instance->cpx_request_queue_h );
3610 + instance->cpx_supported = 0;
3615 +/* should have host_mem_phys intialized before calling this function.*/
3616 +static int megasas_init_cpx( struct megasas_instance *instance)
3620 + instance->host_mem_virt = ioremap(instance->host_mem_phys, instance->host_mem_len);
3621 + if ( instance->host_mem_virt == NULL ){
3622 + printk("megasas: Failed to ioremap host memory.\n");
3623 + goto error_unload;
3626 + //allocate memory for indices and descriptors for reply and response array's
3627 + instance->cpx_request_queue = pci_alloc_consistent( instance->pdev, megasas_get_cpx_mem_len (instance->cpx_dscrptr_cnt), &instance->cpx_request_queue_h );
3628 + if ( instance->cpx_request_queue == NULL ){
3629 + printk(KERN_ERR "megasas: Out of DMA memory for cpx operations.\n");
3630 + goto error_unload;
3633 + //initialize queues
3634 + instance->cpx_dscrptr = (union mr_cpx_descriptor *)((u8*)instance->cpx_request_queue + ( sizeof(instance->cpx_request_queue->consumer_idx)*2 ));
3636 + //send data to fw.
3637 + if ( megasas_send_cpx_queue_data( instance ) ){
3638 + printk("megasas: Sending cpx queue data to FW failed.\n");
3639 + goto error_unload;
3645 + megasas_remove_cpx( instance );
3650 + * megasas_issue_init_mfi - Initializes the FW
3651 + * @instance: Adapter soft state
3653 + * Issues the INIT MFI cmd
3656 +megasas_issue_init_mfi(struct megasas_instance *instance)
3662 struct megasas_cmd *cmd;
3663 - struct megasas_instance *instance = (struct megasas_instance *)instance_addr;
3664 - unsigned long flags;
3666 - /* If we have already declared adapter dead, donot complete cmds */
3667 - if (instance->hw_crit_error)
3669 + struct megasas_init_frame *init_frame;
3670 + struct megasas_init_queue_info *initq_info;
3671 + dma_addr_t init_frame_h;
3672 + dma_addr_t initq_info_h;
3674 - producer = *instance->producer;
3675 - consumer = *instance->consumer;
3677 + * Prepare a init frame. Note the init frame points to queue info
3678 + * structure. Each frame has SGL allocated after first 64 bytes. For
3679 + * this frame - since we don't need any SGL - we use SGL's space as
3680 + * queue info structure
3682 + * We will not get a NULL command below. We just created the pool.
3684 + cmd = megasas_get_cmd(instance);
3686 - while (consumer != producer) {
3687 - context = instance->reply_queue[consumer];
3688 + init_frame = (struct megasas_init_frame *)cmd->frame;
3689 + initq_info = (struct megasas_init_queue_info *)
3690 + ((unsigned long)init_frame + 64);
3692 - cmd = instance->cmd_list[context];
3693 + init_frame_h = cmd->frame_phys_addr;
3694 + initq_info_h = init_frame_h + 64;
3696 + context = init_frame->context;
3697 + memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
3698 + memset(initq_info, 0, sizeof(struct megasas_init_queue_info));
3699 + init_frame->context = context;
3701 + initq_info->reply_queue_entries = instance->max_fw_cmds + 1;
3702 + initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h;
3704 + initq_info->producer_index_phys_addr_lo = instance->producer_h;
3705 + initq_info->consumer_index_phys_addr_lo = instance->consumer_h;
3707 + init_frame->cmd = MFI_CMD_INIT;
3708 + init_frame->cmd_status = 0xFF;
3709 + init_frame->queue_info_new_phys_addr_lo = initq_info_h;
3711 + init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info);
3714 + * disable the intr before firing the init frame to FW
3716 + instance->instancet->disable_intr(instance->reg_set);
3719 + * Issue the init frame in polled mode
3722 + if (megasas_issue_polled(instance, cmd)) {
3723 + printk(KERN_ERR "megasas: Failed to init firmware\n");
3724 + megasas_return_cmd(instance, cmd);
3725 + goto fail_fw_init;
3728 - megasas_complete_cmd(instance, cmd, DID_OK);
3729 + megasas_return_cmd(instance, cmd);
3732 - if (consumer == (instance->max_fw_cmds + 1)) {
3738 - *instance->consumer = producer;
3744 - * Check if we can restore can_queue
3746 - if (instance->flag & MEGASAS_FW_BUSY
3747 - && time_after(jiffies, instance->last_time + 5 * HZ)
3748 - && atomic_read(&instance->fw_outstanding) < 17) {
3750 + * megasas_start_timer - Initializes a timer object
3751 + * @instance: Adapter soft state
3752 + * @timer: timer object to be initialized
3753 + * @fn: timer function
3754 + * @interval: time interval between timer function call
3757 +megasas_start_timer(struct megasas_instance *instance,
3758 + struct timer_list *timer,
3759 + void *fn, unsigned long interval)
3761 + init_timer(timer);
3762 + timer->expires = jiffies + interval;
3763 + timer->data = (unsigned long)instance;
3764 + timer->function = fn;
3768 - spin_lock_irqsave(instance->host->host_lock, flags);
3769 - instance->flag &= ~MEGASAS_FW_BUSY;
3770 - instance->host->can_queue =
3771 - instance->max_fw_cmds - MEGASAS_INT_CMDS;
3773 + * megasas_io_completion_timer - Timer fn
3774 + * @instance_addr: Address of adapter soft state
3776 + * Schedules tasklet for cmd completion
3777 + * if poll_mode_io is set
3780 +megasas_io_completion_timer(unsigned long instance_addr)
3782 + struct megasas_instance *instance =
3783 + (struct megasas_instance *)instance_addr;
3785 - spin_unlock_irqrestore(instance->host->host_lock, flags);
3787 + if (atomic_read(&instance->fw_outstanding))
3788 + tasklet_schedule(&instance->isr_tasklet);
3790 + /* Restart timer */
3792 + mod_timer(&instance->io_completion_timer,
3793 + jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
3797 @@ -1893,22 +4547,24 @@ static int megasas_init_mfi(struct megas
3802 struct megasas_register_set __iomem *reg_set;
3804 - struct megasas_cmd *cmd;
3805 struct megasas_ctrl_info *ctrl_info;
3807 - struct megasas_init_frame *init_frame;
3808 - struct megasas_init_queue_info *initq_info;
3809 - dma_addr_t init_frame_h;
3810 - dma_addr_t initq_info_h;
3813 * Map the message registers
3815 - instance->base_addr = pci_resource_start(instance->pdev, 0);
3816 + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
3817 + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
3818 + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
3819 + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) {
3820 + instance->base_addr = pci_resource_start(instance->pdev, 1);
3822 + instance->base_addr = pci_resource_start(instance->pdev, 0);
3825 - if (pci_request_regions(instance->pdev, "megasas: LSI Logic")) {
3826 + if (pci_request_selected_regions(instance->pdev,
3827 + pci_select_bars(instance->pdev, IORESOURCE_MEM),
3828 + "megasas: LSI")) {
3829 printk(KERN_DEBUG "megasas: IO memory region busy!\n");
3832 @@ -1924,9 +4580,18 @@ static int megasas_init_mfi(struct megas
3834 switch(instance->pdev->device)
3836 - case PCI_DEVICE_ID_LSI_SAS1078R:
3837 + case PCI_DEVICE_ID_LSI_SAS1078R:
3838 + case PCI_DEVICE_ID_LSI_SAS1078DE:
3839 instance->instancet = &megasas_instance_template_ppc;
3841 + case PCI_DEVICE_ID_LSI_SAS1078GEN2:
3842 + case PCI_DEVICE_ID_LSI_SAS0079GEN2:
3843 + instance->instancet = &megasas_instance_template_gen2;
3845 + case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
3846 + case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
3847 + instance->instancet = &megasas_instance_template_skinny;
3849 case PCI_DEVICE_ID_LSI_SAS1064R:
3850 case PCI_DEVICE_ID_DELL_PERC5:
3852 @@ -1979,52 +4644,29 @@ static int megasas_init_mfi(struct megas
3853 goto fail_reply_queue;
3857 - * Prepare a init frame. Note the init frame points to queue info
3858 - * structure. Each frame has SGL allocated after first 64 bytes. For
3859 - * this frame - since we don't need any SGL - we use SGL's space as
3860 - * queue info structure
3862 - * We will not get a NULL command below. We just created the pool.
3864 - cmd = megasas_get_cmd(instance);
3866 - init_frame = (struct megasas_init_frame *)cmd->frame;
3867 - initq_info = (struct megasas_init_queue_info *)
3868 - ((unsigned long)init_frame + 64);
3870 - init_frame_h = cmd->frame_phys_addr;
3871 - initq_info_h = init_frame_h + 64;
3873 - memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
3874 - memset(initq_info, 0, sizeof(struct megasas_init_queue_info));
3876 - initq_info->reply_queue_entries = instance->max_fw_cmds + 1;
3877 - initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h;
3879 - initq_info->producer_index_phys_addr_lo = instance->producer_h;
3880 - initq_info->consumer_index_phys_addr_lo = instance->consumer_h;
3881 + if ( megasas_check_cpx_support( instance ) == 0 )
3882 + if ( megasas_init_cpx( instance ) )
3883 + printk("Error in initilizing cpx.\n");
3885 - init_frame->cmd = MFI_CMD_INIT;
3886 - init_frame->cmd_status = 0xFF;
3887 - init_frame->queue_info_new_phys_addr_lo = initq_info_h;
3888 + if (megasas_issue_init_mfi(instance))
3889 + goto fail_fw_init;
3891 - init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info);
3892 + instance->fw_support_ieee = 0;
3893 + instance->fw_support_ieee = (instance->instancet->read_fw_status_reg(reg_set) & 0x04000000);
3896 - * disable the intr before firing the init frame to FW
3898 - instance->instancet->disable_intr(instance->reg_set);
3899 + printk("megasas_init_mfi: fw_support_ieee=%d", instance->fw_support_ieee);
3900 + if (instance->fw_support_ieee)
3901 + instance->flag_ieee = 1;
3903 + /** for passthrough
3904 + * the following function will get the PD LIST.
3908 - * Issue the init frame in polled mode
3910 - if (megasas_issue_polled(instance, cmd)) {
3911 - printk(KERN_DEBUG "megasas: Failed to init firmware\n");
3912 - goto fail_fw_init;
3914 + memset(instance->pd_list, 0, MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
3915 + megasas_get_pd_list(instance);
3917 - megasas_return_cmd(instance, cmd);
3918 + memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
3919 + megasas_get_ld_list(instance);
3921 ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
3923 @@ -2037,17 +4679,21 @@ static int megasas_init_mfi(struct megas
3924 * Note that older firmwares ( < FW ver 30) didn't report information
3925 * to calculate max_sectors_1. So the number ended up as zero always.
3928 if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) {
3930 max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) *
3931 ctrl_info->max_strips_per_io;
3932 max_sectors_2 = ctrl_info->max_request_size;
3934 - instance->max_sectors_per_req = (max_sectors_1 < max_sectors_2)
3935 - ? max_sectors_1 : max_sectors_2;
3937 - instance->max_sectors_per_req = instance->max_num_sge *
3939 + tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2);
3940 + instance->disableOnlineCtrlReset = ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
3943 + instance->max_sectors_per_req = instance->max_num_sge *
3945 + if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
3946 + instance->max_sectors_per_req = tmp_sectors;
3950 @@ -2055,12 +4701,17 @@ static int megasas_init_mfi(struct megas
3951 * Setup tasklet for cmd completion
3954 - tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
3955 - (unsigned long)instance);
3956 + tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
3957 + (unsigned long)instance);
3959 + /* Initialize the cmd completion timer */
3961 + megasas_start_timer(instance, &instance->io_completion_timer,
3962 + megasas_io_completion_timer,
3963 + MEGASAS_COMPLETION_TIMER_INTERVAL);
3967 - megasas_return_cmd(instance, cmd);
3969 pci_free_consistent(instance->pdev, reply_q_sz,
3970 instance->reply_queue, instance->reply_queue_h);
3971 @@ -2072,7 +4723,8 @@ static int megasas_init_mfi(struct megas
3972 iounmap(instance->reg_set);
3975 - pci_release_regions(instance->pdev);
3976 + pci_release_selected_regions(instance->pdev,
3977 + pci_select_bars(instance->pdev, IORESOURCE_MEM));
3981 @@ -2092,7 +4744,10 @@ static void megasas_release_mfi(struct m
3983 iounmap(instance->reg_set);
3985 - pci_release_regions(instance->pdev);
3986 + megasas_remove_cpx( instance );
3988 + pci_release_selected_regions(instance->pdev,
3989 + pci_select_bars(instance->pdev, IORESOURCE_MEM));
3993 @@ -2140,6 +4795,7 @@ megasas_get_seq_num(struct megasas_insta
3994 dcmd->sge_count = 1;
3995 dcmd->flags = MFI_FRAME_DIR_READ;
3998 dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info);
3999 dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO;
4000 dcmd->sgl.sge32[0].phys_addr = el_info_h;
4001 @@ -2215,6 +4871,8 @@ megasas_register_aen(struct megasas_inst
4002 * Previously issued event registration includes
4003 * current request. Nothing to do.
4005 + printk(KERN_INFO "%s[%d]: already registered\n",
4006 + __FUNCTION__, instance->host->host_no);
4009 curr_aen.members.locale |= prev_aen.members.locale;
4010 @@ -2254,13 +4912,20 @@ megasas_register_aen(struct megasas_inst
4011 dcmd->sge_count = 1;
4012 dcmd->flags = MFI_FRAME_DIR_READ;
4015 dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
4016 dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
4017 dcmd->mbox.w[0] = seq_num;
4018 + instance->last_seq_num = seq_num;
4019 dcmd->mbox.w[1] = curr_aen.word;
4020 dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h;
4021 dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail);
4023 + if (instance->aen_cmd != NULL) {
4024 + megasas_return_cmd(instance, cmd);
4029 * Store reference to the cmd used to register for AEN. When an
4030 * application wants us to register for AEN, we have to abort this
4031 @@ -2271,7 +4936,8 @@ megasas_register_aen(struct megasas_inst
4033 * Issue the aen registration frame
4035 - instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set);
4036 + instance->instancet->fire_cmd(instance,
4037 + cmd->frame_phys_addr, 0, instance->reg_set);
4041 @@ -2304,6 +4970,30 @@ static int megasas_start_aen(struct mega
4046 +sysfs_max_sectors_read(struct kobject *kobj, struct bin_attribute *bin_attr,
4047 + char *buf, loff_t off, size_t count)
4049 + struct Scsi_Host *host = class_to_shost(container_of(kobj,
4050 + struct class_device, kobj));
4051 + struct megasas_instance *instance =
4052 + (struct megasas_instance *)host->hostdata;
4054 + count = sprintf(buf,"%u\n", instance->max_sectors_per_req);
4059 +static struct bin_attribute sysfs_max_sectors_attr = {
4061 + .name = "max_sectors",
4062 + .mode = S_IRUSR|S_IRGRP|S_IROTH,
4063 + .owner = THIS_MODULE,
4066 + .read = sysfs_max_sectors_read,
4070 * megasas_io_attach - Attaches this driver to SCSI mid-layer
4071 * @instance: Adapter soft state
4072 @@ -2311,17 +5001,48 @@ static int megasas_start_aen(struct mega
4073 static int megasas_io_attach(struct megasas_instance *instance)
4075 struct Scsi_Host *host = instance->host;
4079 * Export parameters required by SCSI mid-layer
4081 host->irq = instance->pdev->irq;
4082 host->unique_id = instance->unique_id;
4083 - host->can_queue = instance->max_fw_cmds - MEGASAS_INT_CMDS;
4084 + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
4085 + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
4087 + instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
4090 + instance->max_fw_cmds - MEGASAS_INT_CMDS;
4091 host->this_id = instance->init_id;
4092 host->sg_tablesize = instance->max_num_sge;
4094 + if (instance->fw_support_ieee)
4095 + instance->max_sectors_per_req = MEGASAS_MAX_SECTORS_IEEE;
4097 + * Check if the module parameter value for max_sectors can be used
4099 + if (max_sectors && max_sectors < instance->max_sectors_per_req)
4100 + instance->max_sectors_per_req = max_sectors;
4102 + if (max_sectors) {
4103 + if (((instance->pdev->device ==
4104 + PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
4105 + (instance->pdev->device ==
4106 + PCI_DEVICE_ID_LSI_SAS0079GEN2)) &&
4107 + (max_sectors <= MEGASAS_MAX_SECTORS)) {
4108 + instance->max_sectors_per_req = max_sectors;
4110 + printk(KERN_INFO "megasas: max_sectors should be > 0 and"
4111 + "<= %d (or < 1MB for GEN2 controller)\n",
4112 + instance->max_sectors_per_req);
4117 host->max_sectors = instance->max_sectors_per_req;
4118 - host->cmd_per_lun = 128;
4119 + host->cmd_per_lun = MEGASAS_DEFAULT_CMD_PER_LUN;
4120 host->max_channel = MEGASAS_MAX_CHANNELS - 1;
4121 host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL;
4122 host->max_lun = MEGASAS_MAX_LUN;
4123 @@ -2335,11 +5056,48 @@ static int megasas_io_attach(struct mega
4128 + * Create sysfs entries for module paramaters
4130 + error = sysfs_create_bin_file(&instance->host->shost_classdev.kobj,
4131 + &sysfs_max_sectors_attr);
4133 + printk(KERN_INFO "megasas: Error in creating the sysfs entry max_sectors.\n");
4134 + goto out_remove_host;
4138 * Trigger SCSI to scan our drives
4140 scsi_scan_host(host);
4144 + scsi_remove_host(host);
4150 +megasas_set_dma_mask(struct pci_dev *pdev)
4153 + * All our contollers are capable of performing 64-bit DMA
4156 + if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) != 0) {
4158 + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0)
4159 + goto fail_set_dma_mask;
4162 + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0)
4163 + goto fail_set_dma_mask;
4172 @@ -2375,19 +5133,8 @@ megasas_probe_one(struct pci_dev *pdev,
4174 pci_set_master(pdev);
4177 - * All our contollers are capable of performing 64-bit DMA
4180 - if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) != 0) {
4182 - if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0)
4183 - goto fail_set_dma_mask;
4186 - if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0)
4187 - goto fail_set_dma_mask;
4189 + if (megasas_set_dma_mask(pdev))
4190 + goto fail_set_dma_mask;
4192 host = scsi_host_alloc(&megasas_template,
4193 sizeof(struct megasas_instance));
4194 @@ -2399,6 +5146,7 @@ megasas_probe_one(struct pci_dev *pdev,
4196 instance = (struct megasas_instance *)host->hostdata;
4197 memset(instance, 0, sizeof(*instance));
4198 + atomic_set( &instance->fw_reset_no_pci_access, 0 );
4200 instance->producer = pci_alloc_consistent(pdev, sizeof(u32),
4201 &instance->producer_h);
4202 @@ -2413,6 +5161,11 @@ megasas_probe_one(struct pci_dev *pdev,
4204 *instance->producer = 0;
4205 *instance->consumer = 0;
4206 + instance->flag_ieee = 0;
4207 + instance->ev = NULL;
4208 + instance->issuepend_done = 1;
4209 + instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
4210 + megasas_poll_wait_aen = 0;
4212 instance->evt_detail = pci_alloc_consistent(pdev,
4214 @@ -2429,6 +5182,7 @@ megasas_probe_one(struct pci_dev *pdev,
4215 * Initialize locks and queues
4217 INIT_LIST_HEAD(&instance->cmd_pool);
4218 + INIT_LIST_HEAD(&instance->internal_reset_pending_q);
4220 atomic_set(&instance->fw_outstanding,0);
4222 @@ -2436,9 +5190,12 @@ megasas_probe_one(struct pci_dev *pdev,
4223 init_waitqueue_head(&instance->abort_cmd_wait_q);
4225 spin_lock_init(&instance->cmd_pool_lock);
4226 + spin_lock_init(&instance->hba_lock);
4228 + spin_lock_init(&instance->completion_lock);
4229 + spin_lock_init(&poll_aen_lock);
4231 - sema_init(&instance->aen_mutex, 1);
4232 - sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
4233 + mutex_init(&instance->aen_mutex);
4236 * Initialize PCI related and misc parameters
4237 @@ -2448,9 +5205,20 @@ megasas_probe_one(struct pci_dev *pdev,
4238 instance->unique_id = pdev->bus->number << 8 | pdev->devfn;
4239 instance->init_id = MEGASAS_DEFAULT_INIT_ID;
4241 + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
4242 + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
4243 + instance->flag_ieee = 1;
4244 + sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS);
4246 + sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
4248 megasas_dbg_lvl = 0;
4250 + instance->unload = 1;
4251 instance->last_time = 0;
4252 + instance->disableOnlineCtrlReset = 1;
4254 + INIT_WORK(&instance->work_init, process_fw_state_change_wq);
4257 * Initialize MFI Firmware
4258 @@ -2495,6 +5263,7 @@ megasas_probe_one(struct pci_dev *pdev,
4259 if (megasas_io_attach(instance))
4260 goto fail_io_attach;
4262 + instance->unload = 0;
4266 @@ -2541,83 +5310,266 @@ static void megasas_flush_cache(struct m
4267 struct megasas_cmd *cmd;
4268 struct megasas_dcmd_frame *dcmd;
4270 - cmd = megasas_get_cmd(instance);
4271 + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
4274 + cmd = megasas_get_cmd(instance);
4279 + dcmd = &cmd->frame->dcmd;
4281 + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
4283 + dcmd->cmd = MFI_CMD_DCMD;
4284 + dcmd->cmd_status = 0x0;
4285 + dcmd->sge_count = 0;
4286 + dcmd->flags = MFI_FRAME_DIR_NONE;
4287 + dcmd->timeout = 0;
4289 + dcmd->data_xfer_len = 0;
4290 + dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH;
4291 + dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
4293 + megasas_issue_blocked_cmd(instance, cmd);
4295 + megasas_return_cmd(instance, cmd);
4301 + * megasas_shutdown_controller - Instructs FW to shutdown the controller
4302 + * @instance: Adapter soft state
4303 + * @opcode: Shutdown/Hibernate
4305 +static void megasas_shutdown_controller(struct megasas_instance *instance,
4308 + struct megasas_cmd *cmd;
4309 + struct megasas_dcmd_frame *dcmd;
4311 + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
4314 + cmd = megasas_get_cmd(instance);
4319 + if (instance->aen_cmd)
4320 + megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd);
4322 + dcmd = &cmd->frame->dcmd;
4324 + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
4326 + dcmd->cmd = MFI_CMD_DCMD;
4327 + dcmd->cmd_status = 0x0;
4328 + dcmd->sge_count = 0;
4329 + dcmd->flags = MFI_FRAME_DIR_NONE;
4330 + dcmd->timeout = 0;
4332 + dcmd->data_xfer_len = 0;
4333 + dcmd->opcode = opcode;
4335 + megasas_issue_blocked_cmd(instance, cmd);
4337 + megasas_return_cmd(instance, cmd);
4344 + * megasas_suspend - driver suspend entry point
4345 + * @pdev: PCI device structure
4346 + * @state: PCI power state to suspend routine
4349 +megasas_suspend(struct pci_dev *pdev, pm_message_t state)
4351 + struct Scsi_Host *host;
4352 + struct megasas_instance *instance;
4354 + instance = pci_get_drvdata(pdev);
4355 + host = instance->host;
4356 + instance->unload = 1;
4359 + del_timer_sync(&instance->io_completion_timer);
4361 + megasas_flush_cache(instance);
4362 + megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN);
4364 + /* cancel the delayed work if this work still in queue */
4365 + if (instance->ev != NULL) {
4366 + struct megasas_aen_event *ev = instance->ev;
4367 + cancel_delayed_work(
4368 + (struct delayed_work *)&ev->hotplug_work);
4369 + flush_scheduled_work();
4370 + instance->ev = NULL;
4373 + tasklet_kill(&instance->isr_tasklet);
4375 + pci_set_drvdata(instance->pdev, instance);
4376 + instance->instancet->disable_intr(instance->reg_set);
4377 + free_irq(instance->pdev->irq, instance);
4379 + pci_save_state(pdev);
4380 + pci_disable_device(pdev);
4382 + pci_set_power_state(pdev, pci_choose_state(pdev, state));
4388 + * megasas_resume- driver resume entry point
4389 + * @pdev: PCI device structure
4392 +megasas_resume(struct pci_dev *pdev)
4395 + struct Scsi_Host *host;
4396 + struct megasas_instance *instance;
4398 + instance = pci_get_drvdata(pdev);
4399 + host = instance->host;
4400 + pci_set_power_state(pdev, PCI_D0);
4401 + pci_enable_wake(pdev, PCI_D0, 0);
4402 + pci_restore_state(pdev);
4405 + * PCI prepping: enable device set bus mastering and dma mask
4407 + rval = pci_enable_device(pdev);
4410 + printk(KERN_ERR "megasas: Enable device failed\n");
4414 + pci_set_master(pdev);
4416 + if (megasas_set_dma_mask(pdev))
4417 + goto fail_set_dma_mask;
4422 + * Initialize MFI Firmware
4425 - dcmd = &cmd->frame->dcmd;
4426 + *instance->producer = 0;
4427 + *instance->consumer = 0;
4429 - memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
4430 + atomic_set(&instance->fw_outstanding, 0);
4432 - dcmd->cmd = MFI_CMD_DCMD;
4433 - dcmd->cmd_status = 0x0;
4434 - dcmd->sge_count = 0;
4435 - dcmd->flags = MFI_FRAME_DIR_NONE;
4436 - dcmd->timeout = 0;
4437 - dcmd->data_xfer_len = 0;
4438 - dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH;
4439 - dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
4441 + * We expect the FW state to be READY
4443 + if (megasas_transition_to_ready(instance))
4444 + goto fail_ready_state;
4446 - megasas_issue_blocked_cmd(instance, cmd);
4447 + if ( megasas_check_cpx_support( instance ) == 0 ){
4448 + if ( megasas_send_cpx_queue_data( instance ) ){
4449 + printk("megasas: Sending cpx queue data to FW failed.\n");
4450 + megasas_remove_cpx(instance);
4452 + instance->cpx_request_queue->consumer_idx = instance->cpx_request_queue->producer_idx = 0;
4455 - megasas_return_cmd(instance, cmd);
4456 + if (megasas_issue_init_mfi(instance))
4457 + goto fail_init_mfi;
4461 + tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
4462 + (unsigned long)instance);
4465 - * megasas_shutdown_controller - Instructs FW to shutdown the controller
4466 - * @instance: Adapter soft state
4468 -static void megasas_shutdown_controller(struct megasas_instance *instance)
4470 - struct megasas_cmd *cmd;
4471 - struct megasas_dcmd_frame *dcmd;
4475 + if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED,
4476 + "megasas", instance)) {
4477 + printk(KERN_ERR "megasas: Failed to register IRQ\n");
4481 - cmd = megasas_get_cmd(instance);
4482 + instance->instancet->enable_intr(instance->reg_set);
4487 + * Initiate AEN (Asynchronous Event Notification)
4489 + if (megasas_start_aen(instance))
4490 + printk(KERN_ERR "megasas: Start AEN failed\n");
4492 - if (instance->aen_cmd)
4493 - megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd);
4494 + /* Initialize the cmd completion timer */
4496 + megasas_start_timer(instance, &instance->io_completion_timer,
4497 + megasas_io_completion_timer,
4498 + MEGASAS_COMPLETION_TIMER_INTERVAL);
4499 + instance->unload = 0;
4501 - dcmd = &cmd->frame->dcmd;
4504 - memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
4507 + if (instance->evt_detail)
4508 + pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
4509 + instance->evt_detail,
4510 + instance->evt_detail_h);
4512 - dcmd->cmd = MFI_CMD_DCMD;
4513 - dcmd->cmd_status = 0x0;
4514 - dcmd->sge_count = 0;
4515 - dcmd->flags = MFI_FRAME_DIR_NONE;
4516 - dcmd->timeout = 0;
4517 - dcmd->data_xfer_len = 0;
4518 - dcmd->opcode = MR_DCMD_CTRL_SHUTDOWN;
4519 + if (instance->producer)
4520 + pci_free_consistent(pdev, sizeof(u32), instance->producer,
4521 + instance->producer_h);
4522 + if (instance->consumer)
4523 + pci_free_consistent(pdev, sizeof(u32), instance->consumer,
4524 + instance->consumer_h);
4525 + scsi_host_put(host);
4527 - megasas_issue_blocked_cmd(instance, cmd);
4531 - megasas_return_cmd(instance, cmd);
4532 + pci_disable_device(pdev);
4538 +#define megasas_suspend NULL
4539 +#define megasas_resume NULL
4543 * megasas_detach_one - PCI hot"un"plug entry point
4544 * @pdev: PCI device structure
4546 -static void megasas_detach_one(struct pci_dev *pdev)
4547 +static void __devexit megasas_detach_one(struct pci_dev *pdev)
4550 struct Scsi_Host *host;
4551 struct megasas_instance *instance;
4553 instance = pci_get_drvdata(pdev);
4554 + instance->unload = 1;
4555 host = instance->host;
4558 + del_timer_sync(&instance->io_completion_timer);
4560 scsi_remove_host(instance->host);
4561 megasas_flush_cache(instance);
4562 - megasas_shutdown_controller(instance);
4563 + megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
4565 + /* cancel the delayed work if this work still in queue*/
4566 + if (instance->ev != NULL) {
4567 + struct megasas_aen_event *ev = instance->ev;
4568 + cancel_delayed_work(
4569 + (struct delayed_work *)&ev->hotplug_work);
4570 + flush_scheduled_work();
4571 + instance->ev = NULL;
4574 tasklet_kill(&instance->isr_tasklet);
4577 @@ -2666,7 +5618,9 @@ static void megasas_detach_one(struct pc
4578 static void megasas_shutdown(struct pci_dev *pdev)
4580 struct megasas_instance *instance = pci_get_drvdata(pdev);
4581 + instance->unload = 1;
4582 megasas_flush_cache(instance);
4583 + megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
4587 @@ -2722,6 +5676,23 @@ static int megasas_mgmt_fasync(int fd, s
4591 + * megasas_mgmt_poll - char node "poll" entry point
4593 +static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait)
4595 + unsigned int mask;
4596 + unsigned long flags;
4597 + poll_wait(file, &megasas_poll_wait, wait);
4598 + spin_lock_irqsave(&poll_aen_lock, flags);
4599 + if (megasas_poll_wait_aen)
4600 + mask = (POLLIN | POLLRDNORM);
4603 + spin_unlock_irqrestore(&poll_aen_lock, flags);
4608 * megasas_mgmt_fw_ioctl - Issues management ioctls to FW
4609 * @instance: Adapter soft state
4610 * @argp: User's ioctl packet
4611 @@ -2738,7 +5709,7 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
4614 dma_addr_t sense_handle;
4616 + unsigned long *sense_ptr;
4618 memset(kbuff_arr, 0, sizeof(kbuff_arr));
4620 @@ -2762,6 +5733,7 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
4622 memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
4623 cmd->frame->hdr.context = cmd->index;
4624 + cmd->frame->hdr.pad_0 = 0;
4627 * The management interface between applications and the fw uses
4628 @@ -2815,7 +5787,7 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
4632 - (u32 *) ((unsigned long)cmd->frame + ioc->sense_off);
4633 + (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off);
4634 *sense_ptr = sense_handle;
4637 @@ -2843,14 +5815,16 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
4639 if (ioc->sense_len) {
4641 - * sense_ptr points to the location that has the user
4642 + * sense_buff points to the location that has the user
4643 * sense buffer address
4645 - sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw +
4647 + sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw +
4650 if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)),
4651 sense, ioc->sense_len)) {
4652 + printk(KERN_ERR "megasas: Failed to copy out to user "
4657 @@ -2881,20 +5855,6 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
4661 -static struct megasas_instance *megasas_lookup_instance(u16 host_no)
4665 - for (i = 0; i < megasas_mgmt_info.max_index; i++) {
4667 - if ((megasas_mgmt_info.instance[i]) &&
4668 - (megasas_mgmt_info.instance[i]->host->host_no == host_no))
4669 - return megasas_mgmt_info.instance[i];
4675 static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
4677 struct megasas_iocpacket __user *user_ioc =
4678 @@ -2902,6 +5862,9 @@ static int megasas_mgmt_ioctl_fw(struct
4679 struct megasas_iocpacket *ioc;
4680 struct megasas_instance *instance;
4683 + unsigned long flags;
4684 + u32 wait_time = MEGASAS_RESET_WAIT_TIME;
4686 ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
4688 @@ -2918,6 +5881,17 @@ static int megasas_mgmt_ioctl_fw(struct
4692 + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
4693 + printk("Controller in crit error\n");
4695 + goto out_kfree_ioc;
4698 + if (instance->unload == 1) {
4700 + goto out_kfree_ioc;
4704 * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds
4706 @@ -2925,6 +5899,35 @@ static int megasas_mgmt_ioctl_fw(struct
4707 error = -ERESTARTSYS;
4711 + // If HBA is undergoing a reset recovery, wait for that to complete
4712 + // before issuing this command
4714 + for (i = 0; i < wait_time; i++) {
4716 + spin_lock_irqsave(&instance->hba_lock, flags);
4717 + if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
4718 + spin_unlock_irqrestore(&instance->hba_lock, flags);
4721 + spin_unlock_irqrestore(&instance->hba_lock, flags);
4723 + if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
4724 + printk(KERN_NOTICE "megasas: waiting for controller reset to finish\n");
4730 + spin_lock_irqsave(&instance->hba_lock, flags);
4731 + if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
4732 + spin_unlock_irqrestore(&instance->hba_lock, flags);
4733 + printk("megaraid_sas: %s timed out while waiting for HBA to recover.\n", __FUNCTION__);
4735 + goto out_kfree_ioc;
4737 + spin_unlock_irqrestore(&instance->hba_lock, flags);
4739 error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc);
4740 up(&instance->ioctl_sem);
4742 @@ -2938,6 +5941,9 @@ static int megasas_mgmt_ioctl_aen(struct
4743 struct megasas_instance *instance;
4744 struct megasas_aen aen;
4747 + unsigned long flags;
4748 + u32 wait_time = MEGASAS_RESET_WAIT_TIME;
4750 if (file->private_data != file) {
4751 printk(KERN_DEBUG "megasas: fasync_helper was not "
4752 @@ -2953,10 +5959,41 @@ static int megasas_mgmt_ioctl_aen(struct
4756 - down(&instance->aen_mutex);
4757 + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
4761 + if (instance->unload == 1) {
4764 + for (i = 0; i < wait_time; i++) {
4766 + spin_lock_irqsave(&instance->hba_lock, flags);
4767 + if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
4768 + spin_unlock_irqrestore(&instance->hba_lock, flags);
4771 + spin_unlock_irqrestore(&instance->hba_lock, flags);
4773 + if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
4774 + printk(KERN_NOTICE "megasas: waiting for controller reset to finish\n");
4780 + spin_lock_irqsave(&instance->hba_lock, flags);
4781 + if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
4782 + spin_unlock_irqrestore(&instance->hba_lock, flags);
4783 + printk("megaraid_sas: %s timed out while waiting for HBA to recover.\n", __FUNCTION__);
4786 + spin_unlock_irqrestore(&instance->hba_lock, flags);
4788 + mutex_lock(&instance->aen_mutex);
4789 error = megasas_register_aen(instance, aen.seq_num,
4790 aen.class_locale_word);
4791 - up(&instance->aen_mutex);
4792 + mutex_unlock(&instance->aen_mutex);
4796 @@ -2986,6 +6023,8 @@ static int megasas_mgmt_compat_ioctl_fw(
4797 compat_alloc_user_space(sizeof(struct megasas_iocpacket));
4800 + compat_uptr_t ptr;
4803 if (clear_user(ioc, sizeof(*ioc)))
4805 @@ -2998,9 +6037,14 @@ static int megasas_mgmt_compat_ioctl_fw(
4806 copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32)))
4809 - for (i = 0; i < MAX_IOCTL_SGE; i++) {
4810 - compat_uptr_t ptr;
4811 + if (ioc->sense_len) {
4812 + raw_ptr = ioc->frame.raw + ioc->sense_off;
4813 + if (get_user(ptr, (compat_uptr_t *)raw_ptr) ||
4814 + put_user(ptr, (unsigned long *)raw_ptr))
4818 + for (i = 0; i < MAX_IOCTL_SGE; i++) {
4819 if (get_user(ptr, &cioc->sgl[i].iov_base) ||
4820 put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) ||
4821 copy_in_user(&ioc->sgl[i].iov_len,
4822 @@ -3042,6 +6086,7 @@ static const struct file_operations mega
4823 .release = megasas_mgmt_release,
4824 .fasync = megasas_mgmt_fasync,
4825 .unlocked_ioctl = megasas_mgmt_ioctl,
4826 + .poll = megasas_mgmt_poll,
4827 #ifdef CONFIG_COMPAT
4828 .compat_ioctl = megasas_mgmt_compat_ioctl,
4830 @@ -3056,6 +6101,8 @@ static struct pci_driver megasas_pci_dri
4831 .id_table = megasas_pci_table,
4832 .probe = megasas_probe_one,
4833 .remove = __devexit_p(megasas_detach_one),
4834 + .suspend = megasas_suspend,
4835 + .resume = megasas_resume,
4836 .shutdown = megasas_shutdown,
4839 @@ -3081,9 +6128,27 @@ static DRIVER_ATTR(release_date, S_IRUGO
4843 +megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf)
4845 + return sprintf(buf, "%u\n", support_poll_for_event);
4848 +static DRIVER_ATTR(support_poll_for_event, S_IRUGO,
4849 + megasas_sysfs_show_support_poll_for_event, NULL);
4852 +megasas_sysfs_show_support_device_change(struct device_driver *dd, char *buf)
4854 + return sprintf(buf, "%u\n", support_device_change);
4857 +static DRIVER_ATTR(support_device_change, S_IRUGO,
4858 + megasas_sysfs_show_support_device_change, NULL);
4861 megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf)
4863 - return sprintf(buf,"%u",megasas_dbg_lvl);
4864 + return sprintf(buf, "%u\n", megasas_dbg_lvl);
4868 @@ -3097,8 +6162,262 @@ megasas_sysfs_set_dbg_lvl(struct device_
4872 -static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl,
4873 - megasas_sysfs_set_dbg_lvl);
4874 +static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl,
4875 + megasas_sysfs_set_dbg_lvl);
4878 +megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf)
4880 + return sprintf(buf, "%u\n", poll_mode_io);
4884 +megasas_sysfs_set_poll_mode_io(struct device_driver *dd,
4885 + const char *buf, size_t count)
4887 + int retval = count;
4888 + int tmp = poll_mode_io;
4890 + struct megasas_instance *instance;
4892 + if (sscanf(buf, "%u", &poll_mode_io) < 1) {
4893 + printk(KERN_ERR "megasas: could not set poll_mode_io\n");
4898 + * Check if poll_mode_io is already set or is same as previous value
4900 + if ((tmp && poll_mode_io) || (tmp == poll_mode_io))
4903 + if (poll_mode_io) {
4905 + * Start timers for all adapters
4907 + for (i = 0; i < megasas_mgmt_info.max_index; i++) {
4908 + instance = megasas_mgmt_info.instance[i];
4910 + megasas_start_timer(instance,
4911 + &instance->io_completion_timer,
4912 + megasas_io_completion_timer,
4913 + MEGASAS_COMPLETION_TIMER_INTERVAL);
4918 + * Delete timers for all adapters
4920 + for (i = 0; i < megasas_mgmt_info.max_index; i++) {
4921 + instance = megasas_mgmt_info.instance[i];
4923 + del_timer_sync(&instance->io_completion_timer);
4932 +megasas_aen_polling(struct work_struct *work)
4934 + struct Scsi_Host *host;
4935 + struct scsi_device *sdev1;
4939 + struct megasas_aen_event *ev =
4940 + container_of(work, struct megasas_aen_event, hotplug_work);
4941 + struct megasas_instance *instance = ev->instance;
4942 + union megasas_evt_class_locale class_locale;
4943 + int i, j, doscan = 0;
4948 + printk(KERN_ERR "invalid instance!\n");
4952 + instance->ev = NULL;
4953 + host = instance->host;
4954 + if (instance->evt_detail) {
4956 + switch (instance->evt_detail->code) {
4957 + case MR_EVT_PD_INSERTED:
4958 + if(megasas_get_pd_list(instance) == 0) {
4960 + for (i=0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
4961 + for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
4962 + pd_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
4963 + sdev1 = scsi_device_lookup(host, i, j, 0);
4964 + if (instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
4966 + scsi_add_device(host, i, j, 0);
4970 + scsi_device_put(sdev1);
4979 + case MR_EVT_PD_REMOVED:
4980 + if(megasas_get_pd_list(instance) == 0) {
4981 + megasas_get_pd_list(instance);
4982 + for (i=0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
4983 + for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
4984 + pd_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
4985 + sdev1 = scsi_device_lookup(host, i, j, 0);
4986 + if (instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
4988 + scsi_device_put(sdev1);
4992 + scsi_remove_device(sdev1);
4993 + scsi_device_put(sdev1);
5003 + case MR_EVT_LD_OFFLINE:
5004 + case MR_EVT_CFG_CLEARED:
5005 + case MR_EVT_LD_DELETED:
5006 + megasas_get_ld_list(instance);
5007 + for (i=0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
5008 + for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
5009 + ld_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
5010 + sdev1 = scsi_device_lookup(host, i+MEGASAS_MAX_LD_CHANNELS, j, 0);
5011 + if (instance->ld_ids[ld_index] != 0xff) {
5013 + scsi_device_put(sdev1);
5018 + scsi_remove_device(sdev1);
5019 + scsi_device_put(sdev1);
5026 + case MR_EVT_LD_CREATED:
5027 + megasas_get_ld_list(instance);
5028 + for (i=0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
5029 + for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
5030 + ld_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
5031 + sdev1 = scsi_device_lookup(host, i+MEGASAS_MAX_LD_CHANNELS, j, 0);
5032 + if (instance->ld_ids[ld_index] != 0xff) {
5034 + scsi_add_device(host, i+2, j, 0);
5038 + scsi_device_put(sdev1);
5044 + case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
5045 + case MR_EVT_FOREIGN_CFG_IMPORTED:
5046 + case MR_EVT_LD_STATE_CHANGE:
5054 + printk(KERN_ERR "invalid evt_detail!\n");
5060 + printk(KERN_INFO "scanning ...\n");
5061 + megasas_get_pd_list(instance);
5062 + for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
5063 + for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
5064 + pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j;
5065 + sdev1 = scsi_device_lookup(host, i, j, 0);
5066 + if (instance->pd_list[pd_index].driveState ==
5067 + MR_PD_STATE_SYSTEM) {
5069 + scsi_add_device(host, i, j, 0);
5071 + scsi_device_put(sdev1);
5075 + scsi_remove_device(sdev1);
5076 + scsi_device_put(sdev1);
5082 + megasas_get_ld_list(instance);
5083 + for (i=0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
5084 + for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
5085 + ld_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
5086 + sdev1 = scsi_device_lookup(host, i+MEGASAS_MAX_LD_CHANNELS, j, 0);
5087 + if (instance->ld_ids[ld_index] != 0xff) {
5089 + scsi_add_device(host, i+2, j, 0);
5091 + scsi_device_put(sdev1);
5095 + scsi_remove_device(sdev1);
5096 + scsi_device_put(sdev1);
5103 + seq_num = instance->evt_detail->seq_num + 1;
5105 + /* Register AEN with FW for latest sequence number plus 1 */
5106 + class_locale.members.reserved = 0;
5107 + class_locale.members.locale = MR_EVT_LOCALE_ALL;
5108 + class_locale.members.class = MR_EVT_CLASS_DEBUG;
5110 + if ( instance->aen_cmd != NULL ) {
5115 + mutex_lock(&instance->aen_mutex);
5116 + error = megasas_register_aen(instance, seq_num,
5117 + class_locale.word);
5118 + mutex_unlock(&instance->aen_mutex);
5121 + printk(KERN_ERR "register aen failed error %x\n", error);
5127 +static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR,
5128 + megasas_sysfs_show_poll_mode_io,
5129 + megasas_sysfs_set_poll_mode_io);
5132 * megasas_init - Driver load entry point
5133 @@ -3113,6 +6432,9 @@ static int __init megasas_init(void)
5134 printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
5135 MEGASAS_EXT_VERSION);
5137 + support_poll_for_event = 2;
5138 + support_device_change = 1;
5140 memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info));
5143 @@ -3145,15 +6467,41 @@ static int __init megasas_init(void)
5144 &driver_attr_release_date);
5146 goto err_dcf_rel_date;
5148 + rval = driver_create_file(&megasas_pci_driver.driver,
5149 + &driver_attr_support_poll_for_event);
5151 + goto err_dcf_support_poll_for_event;
5153 rval = driver_create_file(&megasas_pci_driver.driver,
5154 &driver_attr_dbg_lvl);
5156 goto err_dcf_dbg_lvl;
5157 + rval = driver_create_file(&megasas_pci_driver.driver,
5158 + &driver_attr_poll_mode_io);
5160 + goto err_dcf_poll_mode_io;
5161 + rval = driver_create_file(&megasas_pci_driver.driver,
5162 + &driver_attr_support_device_change);
5164 + goto err_dcf_support_device_change;
5167 +err_dcf_support_device_change:
5168 + driver_remove_file(&megasas_pci_driver.driver,
5169 + &driver_attr_poll_mode_io);
5171 +err_dcf_poll_mode_io:
5172 + driver_remove_file(&megasas_pci_driver.driver,
5173 + &driver_attr_dbg_lvl);
5175 driver_remove_file(&megasas_pci_driver.driver,
5176 + &driver_attr_support_poll_for_event);
5178 +err_dcf_support_poll_for_event:
5179 + driver_remove_file(&megasas_pci_driver.driver,
5180 &driver_attr_release_date);
5183 driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
5185 @@ -3169,8 +6517,14 @@ err_pcidrv:
5186 static void __exit megasas_exit(void)
5188 driver_remove_file(&megasas_pci_driver.driver,
5189 + &driver_attr_poll_mode_io);
5190 + driver_remove_file(&megasas_pci_driver.driver,
5191 &driver_attr_dbg_lvl);
5192 driver_remove_file(&megasas_pci_driver.driver,
5193 + &driver_attr_support_poll_for_event);
5194 + driver_remove_file(&megasas_pci_driver.driver,
5195 + &driver_attr_support_device_change);
5196 + driver_remove_file(&megasas_pci_driver.driver,
5197 &driver_attr_release_date);
5198 driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
5200 diff -Nurp linux-2.6.22-810/drivers/scsi/megaraid/megaraid_sas.h linux-2.6.22-820/drivers/scsi/megaraid/megaraid_sas.h
5201 --- linux-2.6.22-810/drivers/scsi/megaraid/megaraid_sas.h 2007-07-08 19:32:17.000000000 -0400
5202 +++ linux-2.6.22-820/drivers/scsi/megaraid/megaraid_sas.h 2010-12-03 10:42:20.000000000 -0500
5205 * MegaRAID SAS Driver meta data
5207 -#define MEGASAS_VERSION "00.00.03.10-rc5"
5208 -#define MEGASAS_RELDATE "May 17, 2007"
5209 -#define MEGASAS_EXT_VERSION "Thu May 17 10:09:32 PDT 2007"
5210 +#define MEGASAS_VERSION "00.00.04.33"
5211 +#define MEGASAS_RELDATE "July 20, 2010"
5212 +#define MEGASAS_EXT_VERSION "Tue Jul 20 12:24:32 EDT 2010"
5218 #define PCI_DEVICE_ID_LSI_SAS1078R 0x0060
5219 +#define PCI_DEVICE_ID_LSI_SAS1078DE 0x007C
5220 #define PCI_DEVICE_ID_LSI_VERDE_ZCR 0x0413
5221 +#define PCI_DEVICE_ID_LSI_SAS1078GEN2 0x0078
5222 +#define PCI_DEVICE_ID_LSI_SAS0079GEN2 0x0079
5223 +#define PCI_DEVICE_ID_LSI_SAS0073SKINNY 0x0073
5224 +#define PCI_DEVICE_ID_LSI_SAS0071SKINNY 0x0071
5227 * =====================================
5229 #define MFI_STATE_READY 0xB0000000
5230 #define MFI_STATE_OPERATIONAL 0xC0000000
5231 #define MFI_STATE_FAULT 0xF0000000
5232 +#define MFI_RESET_REQUIRED 0x00000001
5234 #define MEGAMFI_FRAME_SIZE 64
5237 * HOTPLUG : Resume from Hotplug
5238 * MFI_STOP_ADP : Send signal to FW to stop processing
5241 +#define WRITE_SEQUENCE_OFFSET (0x0000000FC) // I20
5242 +#define HOST_DIAGNOSTIC_OFFSET (0x000000F8) // I20
5243 +#define DIAG_WRITE_ENABLE (0x00000080)
5244 +#define DIAG_RESET_ADAPTER (0x00000004)
5246 +#define MFI_ADP_RESET 0x00000040
5247 #define MFI_INIT_ABORT 0x00000001
5248 #define MFI_INIT_READY 0x00000002
5249 #define MFI_INIT_MFIMODE 0x00000004
5251 #define MFI_FRAME_DIR_WRITE 0x0008
5252 #define MFI_FRAME_DIR_READ 0x0010
5253 #define MFI_FRAME_DIR_BOTH 0x0018
5254 +#define MFI_FRAME_IEEE 0x0020
5257 * Definition for cmd_status
5258 @@ -111,12 +126,14 @@
5259 #define MFI_CMD_STP 0x08
5261 #define MR_DCMD_CTRL_GET_INFO 0x01010000
5262 +#define MR_DCMD_LD_GET_LIST 0x03010000
5264 #define MR_DCMD_CTRL_CACHE_FLUSH 0x01101000
5265 #define MR_FLUSH_CTRL_CACHE 0x01
5266 #define MR_FLUSH_DISK_CACHE 0x02
5268 #define MR_DCMD_CTRL_SHUTDOWN 0x01050000
5269 +#define MR_DCMD_HIBERNATE_SHUTDOWN 0x01060000
5270 #define MR_ENABLE_DRIVE_SPINDOWN 0x01
5272 #define MR_DCMD_CTRL_EVENT_GET_INFO 0x01040100
5273 @@ -127,6 +144,29 @@
5274 #define MR_DCMD_CLUSTER 0x08000000
5275 #define MR_DCMD_CLUSTER_RESET_ALL 0x08010100
5276 #define MR_DCMD_CLUSTER_RESET_LD 0x08010200
5277 +#define MR_DCMD_PD_LIST_QUERY 0x02010100
5279 +#define MR_DCMD_CTRL_MISC_CPX 0x0100e200
5280 +#define MR_DCMD_CTRL_MISC_CPX_INIT_DATA_GET 0x0100e201
5281 +#define MR_DCMD_CTRL_MISC_CPX_QUEUE_DATA 0x0100e202
5282 +#define MR_DCMD_CTRL_MISC_CPX_UNREGISTER 0x0100e203
5283 +#define MAX_MR_ROW_SIZE 32
5284 +#define MR_CPX_DIR_WRITE 1
5285 +#define MR_CPX_DIR_READ 0
5286 +#define MR_CPX_VERSION 1
5288 +#define MR_EVT_CFG_CLEARED 0x0004
5290 +#define MR_EVT_LD_STATE_CHANGE 0x0051
5291 +#define MR_EVT_PD_INSERTED 0x005b
5292 +#define MR_EVT_PD_REMOVED 0x0070
5293 +#define MR_EVT_LD_CREATED 0x008a
5294 +#define MR_EVT_LD_DELETED 0x008b
5295 +#define MR_EVT_FOREIGN_CFG_IMPORTED 0x00db
5296 +#define MR_EVT_LD_OFFLINE 0x00fc
5297 +#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152
5298 +#define MAX_LOGICAL_DRIVES 64
5302 * MFI command completion codes
5303 @@ -247,8 +287,128 @@ enum MR_EVT_ARGS {
5307 + MR_EVT_ARGS_LD_PROP,
5308 + MR_EVT_ARGS_PD_SPARE,
5309 + MR_EVT_ARGS_PD_INDEX,
5310 + MR_EVT_ARGS_DIAG_PASS,
5311 + MR_EVT_ARGS_DIAG_FAIL,
5312 + MR_EVT_ARGS_PD_LBA_LBA,
5313 + MR_EVT_ARGS_PORT_PHY,
5314 + MR_EVT_ARGS_PD_MISSING,
5315 + MR_EVT_ARGS_PD_ADDRESS,
5316 + MR_EVT_ARGS_BITMAP,
5317 + MR_EVT_ARGS_CONNECTOR,
5318 + MR_EVT_ARGS_PD_PD,
5319 + MR_EVT_ARGS_PD_FRU,
5320 + MR_EVT_ARGS_PD_PATHINFO,
5321 + MR_EVT_ARGS_PD_POWER_STATE,
5322 + MR_EVT_ARGS_GENERIC,
5327 + * define constants for device list query options
5329 +enum MR_PD_QUERY_TYPE {
5330 + MR_PD_QUERY_TYPE_ALL = 0,
5331 + MR_PD_QUERY_TYPE_STATE = 1,
5332 + MR_PD_QUERY_TYPE_POWER_STATE = 2,
5333 + MR_PD_QUERY_TYPE_MEDIA_TYPE = 3,
5334 + MR_PD_QUERY_TYPE_SPEED = 4,
5335 + MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5,
5336 +} __attribute__ ((packed));
5338 +#define MR_EVT_CFG_CLEARED 0x0004
5339 +#define MR_EVT_LD_STATE_CHANGE 0x0051
5340 +#define MR_EVT_PD_INSERTED 0x005b
5341 +#define MR_EVT_PD_REMOVED 0x0070
5342 +#define MR_EVT_LD_CREATED 0x008a
5343 +#define MR_EVT_LD_DELETED 0x008b
5344 +#define MR_EVT_FOREIGN_CFG_IMPORTED 0x00db
5345 +#define MR_EVT_LD_OFFLINE 0x00fc
5346 +#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152
5349 + MR_PD_STATE_UNCONFIGURED_GOOD = 0x00,
5350 + MR_PD_STATE_UNCONFIGURED_BAD = 0x01,
5351 + MR_PD_STATE_HOT_SPARE = 0x02,
5352 + MR_PD_STATE_OFFLINE = 0x10,
5353 + MR_PD_STATE_FAILED = 0x11,
5354 + MR_PD_STATE_REBUILD = 0x14,
5355 + MR_PD_STATE_ONLINE = 0x18,
5356 + MR_PD_STATE_COPYBACK = 0x20,
5357 + MR_PD_STATE_SYSTEM = 0x40,
5361 + * defines the physical drive address structure
5363 +struct MR_PD_ADDRESS {
5375 + u8 enclConnectorIndex;
5380 + u8 connectedPortBitmap;
5381 + u8 connectedPortNumbers;
5385 +} __attribute__ ((packed));
5388 + * defines the physical drive list structure
5390 +struct MR_PD_LIST {
5393 + struct MR_PD_ADDRESS addr[1];
5394 +} __attribute__ ((packed));
5397 +struct megasas_pd_list {
5401 +} __attribute__ ((packed));
5404 + * defines the logical drive reference structure
5406 +typedef union _MR_LD_REF { // LD reference structure
5408 + u8 targetId; // LD target id (0 to MAX_TARGET_ID)
5409 + u8 reserved; // reserved to make in line with MR_PD_REF
5410 + u16 seqNum; // Sequence Number
5412 + u32 ref; // shorthand reference to full 32-bits
5413 +} MR_LD_REF; // 4 bytes
5417 + * defines the logical drive list structure
5419 +struct MR_LD_LIST {
5420 + u32 ldCount; // number of LDs
5421 + u32 reserved; // pad to 8-byte boundary
5423 + MR_LD_REF ref; // LD reference
5424 + u8 state; // current LD state (MR_LD_STATE)
5425 + u8 reserved[3]; // pad to 8-byte boundary
5426 + u64 size; // LD size
5427 + } ldList[MAX_LOGICAL_DRIVES];
5428 +} __attribute__ ((packed));
5431 * SAS controller properties
5432 @@ -276,7 +436,45 @@ struct megasas_ctrl_prop {
5433 u16 ecc_bucket_leak_rate;
5434 u8 restore_hotspare_on_insertion;
5435 u8 expose_encl_devices;
5437 + u8 maintainPdFailHistory;
5438 + u8 disallowHostRequestReordering;
5439 + u8 abortCCOnError; // set TRUE to abort CC on detecting an inconsistency
5440 + u8 loadBalanceMode; // load balance mode (MR_LOAD_BALANCE_MODE)
5441 + u8 disableAutoDetectBackplane; // 0 - use auto detect logic of backplanes like SGPIO, i2c SEP using h/w mechansim like GPIO pins
5442 + // 1 - disable auto detect SGPIO,
5443 + // 2 - disable i2c SEP auto detect
5444 + // 3 - disable both auto detect
5445 + u8 snapVDSpace; // % of source LD to be reserved for a VDs snapshot in snapshot repository, for metadata and user data
5446 + // 1=5%, 2=10%, 3=15% and so on
5449 + * Add properties that can be controlled by a bit in the following structure.
5452 + u32 copyBackDisabled : 1; // set TRUE to disable copyBack (0=copback enabled)
5453 + u32 SMARTerEnabled : 1;
5454 + u32 prCorrectUnconfiguredAreas : 1;
5455 + u32 useFdeOnly : 1;
5456 + u32 disableNCQ : 1;
5457 + u32 SSDSMARTerEnabled : 1;
5458 + u32 SSDPatrolReadEnabled : 1;
5459 + u32 enableSpinDownUnconfigured : 1;
5460 + u32 autoEnhancedImport : 1;
5461 + u32 enableSecretKeyControl : 1;
5462 + u32 disableOnlineCtrlReset : 1;
5463 + u32 allowBootWithPinnedCache : 1;
5464 + u32 disableSpinDownHS : 1;
5465 + u32 enableJBOD : 1;
5467 + } OnOffProperties;
5468 + u8 autoSnapVDSpace; // % of source LD to be reserved for auto snapshot in snapshot repository, for metadata and user data
5469 + // 1=5%, 2=10%, 3=15% and so on
5470 + u8 viewSpace; // snapshot writeable VIEWs capacity as a % of source LD capacity. 0=READ only
5471 + // 1=5%, 2=10%, 3=15% and so on
5473 + u16 spinDownTime; // # of idle minutes before device is spun down (0=use FW defaults)
5477 } __attribute__ ((packed));
5479 @@ -536,10 +734,20 @@ struct megasas_ctrl_info {
5480 #define MEGASAS_DEFAULT_INIT_ID -1
5481 #define MEGASAS_MAX_LUN 8
5482 #define MEGASAS_MAX_LD 64
5483 +#define MEGASAS_DEFAULT_CMD_PER_LUN 128
5484 +#define MEGASAS_MAX_PD (MEGASAS_MAX_PD_CHANNELS * \
5485 + MEGASAS_MAX_DEV_PER_CHANNEL)
5486 +#define MEGASAS_MAX_LD_IDS (MEGASAS_MAX_LD_CHANNELS * \
5487 + MEGASAS_MAX_DEV_PER_CHANNEL)
5489 -#define MEGASAS_DBG_LVL 1
5491 +#define MEGASAS_MAX_SECTORS (2*1024)
5492 +#define MEGASAS_MAX_SECTORS_IEEE (2*128)
5493 +#define MEGASAS_DBG_LVL 1
5494 #define MEGASAS_FW_BUSY 1
5497 +#define PTHRU_FRAME 1
5500 * When SCSI mid-layer calls driver's reset routine, driver waits for
5501 @@ -551,6 +759,7 @@ struct megasas_ctrl_info {
5502 #define MEGASAS_RESET_WAIT_TIME 180
5503 #define MEGASAS_INTERNAL_CMD_WAIT_TIME 180
5504 #define MEGASAS_RESET_NOTICE_INTERVAL 5
5506 #define MEGASAS_IOCTL_CMD 0
5507 #define MEGASAS_DEFAULT_CMD_TIMEOUT 90
5509 @@ -562,6 +771,7 @@ struct megasas_ctrl_info {
5512 #define MEGASAS_INT_CMDS 32
5513 +#define MEGASAS_SKINNY_INT_CMDS 5
5516 * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit
5517 @@ -569,10 +779,25 @@ struct megasas_ctrl_info {
5519 #define IS_DMA64 (sizeof(dma_addr_t) == 8)
5521 +#define MFI_XSCALE_OMR0_CHANGE_INTERRUPT 0x00000001 /* MFI state change interrupt */
5523 +#define MFI_INTR_FLAG_REPLY_MESSAGE 0x00000001
5524 +#define MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE 0x00000002
5525 +#define MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT 0x00000004 /* MFI state change interrrupt */
5527 #define MFI_OB_INTR_STATUS_MASK 0x00000002
5528 -#define MFI_POLL_TIMEOUT_SECS 10
5529 +#define MFI_POLL_TIMEOUT_SECS 60
5530 +#define MEGASAS_COMPLETION_TIMER_INTERVAL (HZ/10)
5532 #define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000
5533 +#define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001
5534 +#define MFI_GEN2_ENABLE_INTERRUPT_MASK 0x00000001
5535 +#define MFI_REPLY_SKINNY_MESSAGE_INTERRUPT 0x40000000
5536 +#define MFI_SKINNY_ENABLE_INTERRUPT_MASK (0x00000001)
5537 +#define MFI_1068_PCSR_OFFSET 0x84
5538 +#define MFI_1068_FW_HANDSHAKE_OFFSET 0x64
5539 +#define MFI_1068_FW_READY 0xDDDD0000
5543 * register set for both 1068 and 1078 controllers
5544 @@ -580,7 +805,11 @@ struct megasas_ctrl_info {
5547 struct megasas_register_set {
5548 - u32 reserved_0[4]; /*0000h*/
5549 + u32 reserved_0; /*0000h*/
5550 + u32 fusion_seq_offset; /*0008h*/
5551 + u32 fusion_host_diag; /*0004h*/
5552 + u32 reserved_01; /*000Ch*/
5555 u32 inbound_msg_0; /*0010h*/
5556 u32 inbound_msg_1; /*0014h*/
5557 @@ -615,7 +844,10 @@ struct megasas_register_set {
5558 u32 inbound_high_queue_port ; /*00C4h*/
5560 u32 reserved_5; /*00C8h*/
5561 - u32 index_registers[820]; /*00CCh*/
5562 + u32 res_6[11]; /*CCh*/
5565 + u32 index_registers[807]; /*00CCh*/
5567 } __attribute__ ((packed));
5569 @@ -632,11 +864,20 @@ struct megasas_sge64 {
5572 } __attribute__ ((packed));
5574 +struct megasas_sge_skinny {
5580 +} __attribute__ ((packed));
5584 struct megasas_sge32 sge32[1];
5585 struct megasas_sge64 sge64[1];
5586 + struct megasas_sge_skinny sge_skinny[1];
5588 } __attribute__ ((packed));
5590 @@ -1050,16 +1291,177 @@ struct megasas_evt_detail {
5592 } __attribute__ ((packed));
5594 - struct megasas_instance_template {
5595 - void (*fire_cmd)(dma_addr_t ,u32 ,struct megasas_register_set __iomem *);
5596 +#define MIN(a,b) ((a)<(b) ? (a):(b))
5597 +typedef void (*XOR_LOW_LEVEL_GEN_FUNC)(u32 **, u32);
5598 +typedef u8 (*XOR_LOW_LEVEL_CHECK_FUNC)(u32 **, u32);
5600 + * enumerates type of descriptor
5602 +typedef enum _MR_CPX_DESCRIPTOR_TYPE {
5603 + MR_CPX_DESCRIPTOR_TYPE_COPY = 1,
5604 + MR_CPX_DESCRIPTOR_TYPE_XOR = 2
5605 +} MR_CPX_DESCRIPTOR_TYPE;
5607 - void (*enable_intr)(struct megasas_register_set __iomem *) ;
5608 - void (*disable_intr)(struct megasas_register_set __iomem *);
5610 + * status information of copy or xor operation
5612 +typedef enum _MR_CPX_STATUS {
5613 + MR_CPX_STATUS_SUCCESS = 0,
5614 + MR_CPX_STATUS_INCONSISTENT = 1,
5615 + MR_CPX_STATUS_FAILURE = 2,
5618 - int (*clear_intr)(struct megasas_register_set __iomem *);
5620 + * define the XOR opcodes
5622 +typedef enum _mr_cpx_xor_op {
5623 + MR_CPX_XOR_OP_GEN_P = 0x01, // generate P buffer
5624 + MR_CPX_XOR_OP_GEN_Q = 0x02, // generate Q buffer
5625 + MR_CPX_XOR_OP_GEN_PQ = 0x03, // generate P+Q buffers
5626 + MR_CPX_XOR_OP_CHECK_P = 0x11, // check P buffer (and generate if bad)
5627 + MR_CPX_XOR_OP_CHECK_Q = 0x12, // check Q buffer (and generate if bad)
5628 + MR_CPX_XOR_OP_CHECK_PQ = 0x13, // check P+Q buffers (and generate if bad)
5631 +#define MR_CPX_XOR_OP_IS_CHECK(xorOp) ((xorOp & 0x10)!=0) // TRUE if operation is a CHECK operation
5632 +#define MR_CPX_XOR_OP_IS_GEN(xorOp) (!MR_CPX_XOR_OP_IS_CHECK(xorOp)) // TRUE if operation is a GEN operation
5633 +#define MR_CPX_XOR_OP_IS_P(xorOp) ((xorOp & 0x01)!=0) // TRUE if operation is for P or P/Q
5634 +#define MR_CPX_XOR_OP_IS_Q(xorOp) ((xorOp & 0x02)!=0) // TRUE if operation is for Q or P/Q
5635 +#define MR_CPX_XOR_OP_IS_PQ(xorOp) ((xorOp & 0x03)==3) // TRUE if operation is for P/Q
5637 - u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *);
5641 + * this data is passed to driver during driver init.
5643 +struct mr_cpx_init_data {
5644 + u32 cpx_desc_count; // Number of cpx desc required by fw.
5645 + u32 size; // size of the buffer
5646 + u64 phys_addr_cache_buf; // physical address of cache buffer allocated by pre-boot
5648 +} __attribute__ ((packed));
5651 + * header passed with each descriptor
5653 +struct mr_cpx_header {
5654 + u32 context : 24; // context information passed by firmware, to be passed back in response data
5655 + u32 type : 4; // type of descriptor
5657 +} __attribute__ ((packed));
5660 + * xor descriptor data
5662 +struct mr_cpx_xor_descriptor {
5663 + struct mr_cpx_header hdr;
5664 + MR_CPX_XOR_OP op; // xor operation for gen/check of p/q/p+q
5665 + u32 size; // number of bytes to gen/check for this operation
5666 + u32 buff_valid_bitmap; // bitmap of valid buffers for input
5667 + u8 p_idx; // index of p buffer within list (for p/pq gen/check functions)
5668 + u8 q_idx; // index of q buffer within list (for q/pq gen/check functions)
5670 + u32 buff_list[MAX_MR_ROW_SIZE]; // list of buffers for this xor operation (32 bit offset)
5671 + u32 mult_list[MAX_MR_ROW_SIZE]; // list of coefficient multipliers for q operations
5672 +} __attribute__ ((packed));
5676 + * copy buffer for each transfer. each such tranfer between
5677 + * user spare host address and firmware allocated cache data.
5679 +struct mr_cpx_copy_mr_buffer {
5680 + u32 buf; // buffer address/offset
5681 + u32 size; // size of copy
5682 +} __attribute__ ((packed));
5685 + * copy descriptor data
5687 +struct mr_cpx_copy_descriptor {
5688 + struct mr_cpx_header hdr;
5689 + u32 mfi_cmd_cxt; // mfi context
5690 + u32 total_byte_count; // total byte count for this transfer
5691 + u32 host_skip_count; // skip count from starting address of host buffer
5692 + u8 dir; // direction of transfer
5694 + struct mr_cpx_copy_mr_buffer copy_buf[MAX_MR_ROW_SIZE];
5695 +} __attribute__ ((packed)) ;
5698 + * users of this interface must allocate memory for the size of
5699 + * this structure while allocating memory for descriptors
5701 +union mr_cpx_descriptor {
5702 + struct mr_cpx_xor_descriptor cpx_xor_desc;
5703 + struct mr_cpx_copy_descriptor cpx_copy_desc;
5705 +} __attribute__ ((packed));
5710 + * firmware manages producerindex, driver manages consumerindex.
5711 + * number of decriptors is kept as variable. driver must use
5712 + * max host commands supported for allocation.
5714 +struct mr_cpx_request_queue {
5717 + union mr_cpx_descriptor cpxdescriptor[1]; // use max host commands
5718 +} __attribute__ ((packed));
5722 + * response data. this data will be posted by driver after copy/xor
5723 + * operation is compete.
5725 +union mr_cpx_response_data {
5727 + u32 context : 24; // context
5728 + u32 status : 4; // status in the form of cpx_status
5732 +} __attribute__ ((packed));
5737 + * driver manages producerindex, firmware manages consumerindex.
5738 + * number of decriptors is kept as variable. driver must use
5739 + * max host commands supported for allocation.
5741 +struct mr_cpx_response_queue {
5744 + union mr_cpx_response_data cpx_resp_data[1]; // use max host commands
5745 +} __attribute__ ((packed));
5749 + * the size of each of the structure within this is determined at run time.
5750 + * this structure is for document purpose and shows that the structures
5751 + * lay as shown below in memory
5753 +struct mr_cpx_queues {
5754 + struct mr_cpx_request_queue requestqueue;
5755 + struct mr_cpx_response_queue responsequeue;
5756 +} __attribute__ ((packed));
5759 + * driver sends this queue data during mfi init. firmware
5760 + * will not use the interface if the versions do not match.
5762 +struct mr_cpx_queue_data {
5764 + u32 count_queue_entries;
5765 + u64 phys_addr_cpx_queues;
5766 +} __attribute__ ((packed));
5768 +struct megasas_aen_event {
5769 + struct work_struct hotplug_work;
5770 + struct megasas_instance *instance;
5773 struct megasas_instance {
5775 @@ -1074,22 +1476,30 @@ struct megasas_instance {
5776 unsigned long base_addr;
5777 struct megasas_register_set __iomem *reg_set;
5779 + struct megasas_pd_list pd_list[MEGASAS_MAX_PD];
5780 + u8 ld_ids[MEGASAS_MAX_LD_IDS];
5786 u32 max_sectors_per_req;
5789 struct megasas_cmd **cmd_list;
5790 struct list_head cmd_pool;
5791 spinlock_t cmd_pool_lock;
5792 + struct megasas_aen_event *ev;
5793 + spinlock_t hba_lock;
5794 + /* used to synch producer, consumer ptrs in dpc */
5795 + spinlock_t completion_lock;
5796 struct dma_pool *frame_dma_pool;
5797 struct dma_pool *sense_dma_pool;
5799 struct megasas_evt_detail *evt_detail;
5800 dma_addr_t evt_detail_h;
5801 struct megasas_cmd *aen_cmd;
5802 - struct semaphore aen_mutex;
5803 + struct mutex aen_mutex;
5804 struct semaphore ioctl_sem;
5806 struct Scsi_Host *host;
5807 @@ -1099,17 +1509,62 @@ struct megasas_instance {
5809 struct pci_dev *pdev;
5811 + u32 fw_support_ieee;
5813 atomic_t fw_outstanding;
5814 - u32 hw_crit_error;
5815 + atomic_t fw_reset_no_pci_access;
5817 struct megasas_instance_template *instancet;
5818 struct tasklet_struct isr_tasklet;
5819 + struct work_struct work_init;
5824 + u8 issuepend_done;
5825 + u8 disableOnlineCtrlReset;
5827 unsigned long last_time;
5831 + struct timer_list io_completion_timer;
5832 + struct list_head internal_reset_pending_q;
5834 + u32 cpx_supported;
5835 + struct mr_cpx_request_queue *cpx_request_queue;
5836 + dma_addr_t cpx_request_queue_h;
5837 + union mr_cpx_descriptor *cpx_dscrptr;
5838 + u32 cpx_dscrptr_cnt;
5839 + u64 host_mem_phys;
5841 + u8 *host_mem_virt;
5846 + MEGASAS_HBA_OPERATIONAL = 0,
5847 + MEGASAS_ADPRESET_SM_INFAULT = 1,
5848 + MEGASAS_ADPRESET_SM_FW_RESET_SUCCESS = 2,
5849 + MEGASAS_ADPRESET_SM_OPERATIONAL = 3,
5850 + MEGASAS_HW_CRITICAL_ERROR = 4,
5851 + MEGASAS_ADPRESET_INPROG_SIGN = 0xDEADDEAD,
5855 + struct megasas_instance_template {
5856 + void (*fire_cmd)(struct megasas_instance *, dma_addr_t ,u32 ,struct megasas_register_set __iomem *);
5858 + void (*enable_intr)(struct megasas_register_set __iomem *) ;
5859 + void (*disable_intr)(struct megasas_register_set __iomem *);
5861 + int (*clear_intr)(struct megasas_register_set __iomem *);
5863 + u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *);
5864 + int (*adp_reset)(struct megasas_instance *, struct megasas_register_set __iomem *);
5865 + int (*check_reset)(struct megasas_instance *, struct megasas_register_set __iomem *);
5868 #define MEGASAS_IS_LOGICAL(scp) \
5869 (scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1
5871 @@ -1127,7 +1582,9 @@ struct megasas_cmd {
5877 + u8 retry_for_fw_reset;
5880 struct list_head list;
5881 struct scsi_cmnd *scmd;